mirror of
https://github.com/IllusionMan1212/C2048.git
synced 2026-10-24 02:12:31 +00:00
zephr/game: textures, icons, and buttons
- zephr: correctly set cursor when hovering button - zephr: added texture loading and displaying - zephr: added icon button - game: added help and settings icon buttons
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
BIN=c2048
|
BIN=c2048
|
||||||
CC=gcc
|
CC=gcc
|
||||||
CFLAGS=-Wall -Wextra -Werror -Wfloat-conversion -Wimplicit-fallthrough -pedantic -g `pkg-config --cflags freetype2` -I3rdparty/glad/include -I3rdparty/fmod/include -I3rdparty/stb/
|
CFLAGS=-Wall -Wextra -Werror -Wfloat-conversion -Wimplicit-fallthrough -pedantic -g `pkg-config --cflags freetype2` -I3rdparty/glad/include -I3rdparty/fmod/include -I3rdparty/stb/
|
||||||
OBJ=main.o game.o core.o shader.o text.o audio.o timer.o ui.o zephr.o zephr_math.o 3rdparty/glad/src/gl.o 3rdparty/glad/src/glx.o 3rdparty/stb/stb.o
|
OBJ=main.o game.o core.o shader.o text.o audio.o texture.o timer.o ui.o zephr.o zephr_math.o 3rdparty/glad/src/gl.o 3rdparty/glad/src/glx.o 3rdparty/stb/stb.o
|
||||||
LDFLAGS=`pkg-config --libs x11 freetype2` -lm -L3rdparty/fmod/lib -Wl,-rpath=3rdparty/fmod/lib -lfmod
|
LDFLAGS=`pkg-config --libs x11 freetype2` -lm -L3rdparty/fmod/lib -Wl,-rpath=3rdparty/fmod/lib -lfmod
|
||||||
DEPS=3rdparty/glad/include/glad/gl.h 3rdparty/glad/include/glad/glx.h 3rdparty/fmod/include/fmod.h 3rdparty/stb/stb_image.h
|
DEPS=3rdparty/glad/include/glad/gl.h 3rdparty/glad/include/glad/glx.h 3rdparty/fmod/include/fmod.h 3rdparty/stb/stb_image.h
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
@@ -122,7 +122,7 @@ u8 get_tile_font_size(Tile tile) {
|
|||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
void draw_board() {
|
void draw_bg() {
|
||||||
Size window_size = zephr_get_window_size();
|
Size window_size = zephr_get_window_size();
|
||||||
UIConstraints board_con = {0};
|
UIConstraints board_con = {0};
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ void draw_board() {
|
|||||||
// bg
|
// bg
|
||||||
draw_quad(&board_con, ColorRGBA(248, 250, 230, 255), 0, ALIGN_TOP_LEFT);
|
draw_quad(&board_con, ColorRGBA(248, 250, 230, 255), 0, ALIGN_TOP_LEFT);
|
||||||
|
|
||||||
// text
|
// 2048 text
|
||||||
UIConstraints text_con = {0};
|
UIConstraints text_con = {0};
|
||||||
|
|
||||||
set_y_constraint(&text_con, 0.05f, UI_CONSTRAINT_RELATIVE);
|
set_y_constraint(&text_con, 0.05f, UI_CONSTRAINT_RELATIVE);
|
||||||
@@ -140,7 +140,48 @@ void draw_board() {
|
|||||||
|
|
||||||
draw_text("2048", 100, text_con, ColorRGBA(34, 234, 82, 155), ALIGN_TOP_CENTER);
|
draw_text("2048", 100, text_con, ColorRGBA(34, 234, 82, 155), ALIGN_TOP_CENTER);
|
||||||
|
|
||||||
|
// score
|
||||||
|
char score[16];
|
||||||
|
sprintf(score, "%d", game.score);
|
||||||
|
|
||||||
|
set_parent_constraint(&text_con, NULL);
|
||||||
|
set_x_constraint(&text_con, 0.05f, UI_CONSTRAINT_RELATIVE);
|
||||||
|
set_y_constraint(&text_con, 0.8f, UI_CONSTRAINT_RELATIVE);
|
||||||
|
draw_text("Score", 40, text_con, COLOR_BLACK, ALIGN_TOP_LEFT);
|
||||||
|
|
||||||
|
set_x_constraint(&text_con, 0.15f, UI_CONSTRAINT_RELATIVE);
|
||||||
|
draw_text(score, 40, text_con, COLOR_BLACK, ALIGN_TOP_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_ui() {
|
||||||
|
UIConstraints btn_con = {0};
|
||||||
|
|
||||||
|
set_x_constraint(&btn_con, -8, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
|
set_y_constraint(&btn_con, 8, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
|
set_width_constraint(&btn_con, 100, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
|
set_height_constraint(&btn_con, 1, UI_CONSTRAINT_ASPECT_RATIO);
|
||||||
|
|
||||||
|
if (draw_icon_button(&btn_con, ColorRGBA(201, 146, 126, 255), game.icon_textures[HELP_ICON], btn_con.height * 0.25f, ALIGN_TOP_RIGHT)) {
|
||||||
|
printf("help\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
set_x_constraint(&btn_con, -8 - btn_con.width - 10, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
|
if (draw_icon_button(&btn_con, ColorRGBA(201, 146, 126, 255), game.icon_textures[SETTINGS_ICON], btn_con.height * 0.25f, ALIGN_TOP_RIGHT)) {
|
||||||
|
printf("settings\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
set_x_constraint(&btn_con, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
|
set_y_constraint(&btn_con, -0.05f, UI_CONSTRAINT_RELATIVE);
|
||||||
|
set_width_constraint(&btn_con, 200, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
|
set_height_constraint(&btn_con, 65, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
|
if (draw_button(&btn_con, ColorRGBA(201, 172, 126, 255), "New Game", btn_con.height * 0.25f, ALIGN_BOTTOM_CENTER)) {
|
||||||
|
printf("new game\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_board() {
|
||||||
// board
|
// board
|
||||||
|
UIConstraints board_con = {0};
|
||||||
set_y_constraint(&board_con, 0.05f, UI_CONSTRAINT_RELATIVE);
|
set_y_constraint(&board_con, 0.05f, UI_CONSTRAINT_RELATIVE);
|
||||||
set_height_constraint(&board_con, 0.6f, UI_CONSTRAINT_RELATIVE);
|
set_height_constraint(&board_con, 0.6f, UI_CONSTRAINT_RELATIVE);
|
||||||
set_width_constraint(&board_con, 1, UI_CONSTRAINT_ASPECT_RATIO);
|
set_width_constraint(&board_con, 1, UI_CONSTRAINT_ASPECT_RATIO);
|
||||||
@@ -166,6 +207,8 @@ void draw_board() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// filled tiles
|
// filled tiles
|
||||||
|
UIConstraints text_con = {0};
|
||||||
|
set_width_constraint(&text_con, 1.5, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
UIConstraints tile_con = {0};
|
UIConstraints tile_con = {0};
|
||||||
set_parent_constraint(&tile_con, &board_con);
|
set_parent_constraint(&tile_con, &board_con);
|
||||||
set_height_constraint(&tile_con, tile_height, UI_CONSTRAINT_FIXED);
|
set_height_constraint(&tile_con, tile_height, UI_CONSTRAINT_FIXED);
|
||||||
@@ -188,22 +231,10 @@ void draw_board() {
|
|||||||
set_x_constraint(&text_con, 0, UI_CONSTRAINT_FIXED);
|
set_x_constraint(&text_con, 0, UI_CONSTRAINT_FIXED);
|
||||||
set_y_constraint(&text_con, 0, UI_CONSTRAINT_FIXED);
|
set_y_constraint(&text_con, 0, UI_CONSTRAINT_FIXED);
|
||||||
|
|
||||||
draw_text(value, get_tile_font_size(*tile), text_con, mul_color(tile_color, 0.5), ALIGN_CENTER);
|
draw_text(value, get_tile_font_size(*tile), text_con, mult_color(tile_color, 0.5), ALIGN_CENTER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// score
|
|
||||||
char score[16];
|
|
||||||
sprintf(score, "%d", game.score);
|
|
||||||
|
|
||||||
set_parent_constraint(&text_con, NULL);
|
|
||||||
set_x_constraint(&text_con, 0.05f, UI_CONSTRAINT_RELATIVE);
|
|
||||||
set_y_constraint(&text_con, 0.8f, UI_CONSTRAINT_RELATIVE);
|
|
||||||
draw_text("Score", 40, text_con, COLOR_BLACK, ALIGN_TOP_LEFT);
|
|
||||||
|
|
||||||
set_x_constraint(&text_con, 0.15f, UI_CONSTRAINT_RELATIVE);
|
|
||||||
draw_text(score, 40, text_con, COLOR_BLACK, ALIGN_TOP_LEFT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
@@ -601,6 +632,9 @@ bool gameover() {
|
|||||||
void game_init(void) {
|
void game_init(void) {
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
|
game.icon_textures[HELP_ICON] = load_texture("assets/icons/help.png");
|
||||||
|
game.icon_textures[SETTINGS_ICON] = load_texture("assets/icons/settings.png");
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
spawn_random_tile();
|
spawn_random_tile();
|
||||||
}
|
}
|
||||||
@@ -661,6 +695,8 @@ void game_loop(void) {
|
|||||||
last_frame = now;
|
last_frame = now;
|
||||||
|
|
||||||
update_positions(delta_t);
|
update_positions(delta_t);
|
||||||
|
draw_bg();
|
||||||
|
draw_ui();
|
||||||
draw_board();
|
draw_board();
|
||||||
|
|
||||||
zephr_swap_buffers();
|
zephr_swap_buffers();
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ typedef enum MoveDir {
|
|||||||
MOVE_DIR_RIGHT,
|
MOVE_DIR_RIGHT,
|
||||||
} MoveDir;
|
} MoveDir;
|
||||||
|
|
||||||
|
typedef enum IconTexture {
|
||||||
|
HELP_ICON,
|
||||||
|
SETTINGS_ICON,
|
||||||
|
|
||||||
|
ICON_TEXTURE_COUNT,
|
||||||
|
} IconTexture;
|
||||||
|
|
||||||
typedef struct Tile {
|
typedef struct Tile {
|
||||||
u16 value;
|
u16 value;
|
||||||
u16 new_value;
|
u16 new_value;
|
||||||
@@ -27,6 +34,8 @@ typedef struct Game {
|
|||||||
bool spawning_new_tile;
|
bool spawning_new_tile;
|
||||||
bool game_over;
|
bool game_over;
|
||||||
u32 score;
|
u32 score;
|
||||||
|
|
||||||
|
TextureId icon_textures[ICON_TEXTURE_COUNT];
|
||||||
} Game;
|
} Game;
|
||||||
|
|
||||||
void draw_board(void);
|
void draw_board(void);
|
||||||
|
|||||||
@@ -90,6 +90,15 @@ void set_float(Shader shader, const char *name, float val) {
|
|||||||
glUniform1f(loc, val);
|
glUniform1f(loc, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_int(Shader shader, const char *name, int val) {
|
||||||
|
int loc = glGetUniformLocation(shader.program, name);
|
||||||
|
glUniform1i(loc, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_bool(Shader shader, const char *name, bool val) {
|
||||||
|
set_int(shader, name, val);
|
||||||
|
}
|
||||||
|
|
||||||
void set_vec2f(Shader shader, const char *name, float val1, float val2) {
|
void set_vec2f(Shader shader, const char *name, float val1, float val2) {
|
||||||
int loc = glGetUniformLocation(shader.program, name);
|
int loc = glGetUniformLocation(shader.program, name);
|
||||||
glUniform2f(loc, val1, val2);
|
glUniform2f(loc, val1, val2);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef struct Shader {
|
typedef struct Shader {
|
||||||
int program;
|
int program;
|
||||||
} Shader;
|
} Shader;
|
||||||
@@ -9,6 +11,8 @@ Shader create_shader(const char *vertex_path, const char *fragment_path);
|
|||||||
void use_shader(Shader shader);
|
void use_shader(Shader shader);
|
||||||
void set_mat4f(Shader shader, const char *name, float *mat);
|
void set_mat4f(Shader shader, const char *name, float *mat);
|
||||||
void set_float(Shader shader, const char *name, float val);
|
void set_float(Shader shader, const char *name, float val);
|
||||||
|
void set_int(Shader shader, const char *name, int val);
|
||||||
|
void set_bool(Shader shader, const char *name, bool val);
|
||||||
void set_vec2f(Shader shader, const char *name, float val1, float val2);
|
void set_vec2f(Shader shader, const char *name, float val1, float val2);
|
||||||
void set_vec3f(Shader shader, const char *name, float val1, float val2, float val3);
|
void set_vec3f(Shader shader, const char *name, float val1, float val2, float val3);
|
||||||
void set_vec4f(Shader shader, const char *name, float val1, float val2, float val3, float val4);
|
void set_vec4f(Shader shader, const char *name, float val1, float val2, float val3, float val4);
|
||||||
|
|||||||
+8
-1
@@ -7,6 +7,9 @@ uniform vec4 aColor;
|
|||||||
uniform float borderRadius;
|
uniform float borderRadius;
|
||||||
uniform float uiWidth;
|
uniform float uiWidth;
|
||||||
uniform float uiHeight;
|
uniform float uiHeight;
|
||||||
|
uniform bool hasTexture;
|
||||||
|
|
||||||
|
uniform sampler2D tex;
|
||||||
|
|
||||||
const float smoothness = 1.0;
|
const float smoothness = 1.0;
|
||||||
|
|
||||||
@@ -29,5 +32,9 @@ void main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FragColor = vec4(aColor.rgb, alpha);
|
if (hasTexture) {
|
||||||
|
FragColor = texture(tex, v_TexCoords) * vec4(aColor.rgb, alpha);
|
||||||
|
} else {
|
||||||
|
FragColor = vec4(aColor.rgb, alpha);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#include "glad/gl.h"
|
||||||
|
#include "stb_image.h"
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
#include "texture.h"
|
||||||
|
|
||||||
|
TextureId load_texture(const char *path) {
|
||||||
|
int width, height, nrChannels;
|
||||||
|
unsigned char *data = stbi_load(path, &width, &height, &nrChannels, STBI_rgb_alpha);
|
||||||
|
GLuint texture_id;
|
||||||
|
|
||||||
|
u32 format = GL_RGBA;
|
||||||
|
|
||||||
|
switch (nrChannels) {
|
||||||
|
case 1:
|
||||||
|
format = GL_RED;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
format = GL_RG;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
format = GL_RGB;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
format = GL_RGBA;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glGenTextures(1, &texture_id);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||||
|
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
stbi_image_free(data);
|
||||||
|
|
||||||
|
return texture_id;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "glad/gl.h"
|
||||||
|
|
||||||
|
typedef GLuint TextureId;
|
||||||
|
|
||||||
|
TextureId load_texture(const char *path);
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <glad/glx.h>
|
#include <glad/glx.h>
|
||||||
|
#include <stb_image.h>
|
||||||
|
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "zephr.h"
|
#include "zephr.h"
|
||||||
@@ -171,6 +172,14 @@ void apply_alignment(Alignment align, UIConstraints *constraints, Vec2f *pos, Si
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool inside_rect(Rect *rect, Vec2 *point) {
|
||||||
|
if (point->x >= rect->pos.x && point->x <= rect->pos.x + rect->size.width &&
|
||||||
|
point->y >= rect->pos.y && point->y <= rect->pos.y + rect->size.height) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void draw_quad(UIConstraints *constraints, const Color color, float border_radius, Alignment align) {
|
void draw_quad(UIConstraints *constraints, const Color color, float border_radius, Alignment align) {
|
||||||
use_shader(ui_shader);
|
use_shader(ui_shader);
|
||||||
|
|
||||||
@@ -245,6 +254,10 @@ void draw_triangle(UIConstraints *constraints, const Color color, Alignment alig
|
|||||||
apply_constraints(constraints, &pos, &size);
|
apply_constraints(constraints, &pos, &size);
|
||||||
apply_alignment(align, constraints, &pos, size);
|
apply_alignment(align, constraints, &pos, size);
|
||||||
|
|
||||||
|
// set the positions after applying alignment so children can use them
|
||||||
|
constraints->x = pos.x;
|
||||||
|
constraints->y = pos.y;
|
||||||
|
|
||||||
Matrix4x4 model = identity();
|
Matrix4x4 model = identity();
|
||||||
apply_translation(&model, (Vec2f){-size.width / 2.f, -size.height / 2.f});
|
apply_translation(&model, (Vec2f){-size.width / 2.f, -size.height / 2.f});
|
||||||
apply_rotation(&model, to_radians(constraints->rotation));
|
apply_rotation(&model, to_radians(constraints->rotation));
|
||||||
@@ -271,12 +284,61 @@ void draw_triangle(UIConstraints *constraints, const Color color, Alignment alig
|
|||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inside_rect(Rect *rect, Vec2 *point) {
|
void draw_texture(UIConstraints *constraints, const TextureId texture_id, const Color color, f32 radius, Alignment align) {
|
||||||
if (point->x >= rect->pos.x && point->x <= rect->pos.x + rect->size.width &&
|
use_shader(ui_shader);
|
||||||
point->y >= rect->pos.y && point->y <= rect->pos.y + rect->size.height) {
|
|
||||||
return true;
|
set_vec4f(ui_shader, "aColor", color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
|
||||||
}
|
set_float(ui_shader, "uiWidth", constraints->width);
|
||||||
return false;
|
set_float(ui_shader, "uiHeight", constraints->height);
|
||||||
|
set_float(ui_shader, "borderRadius", radius);
|
||||||
|
set_bool(ui_shader, "hasTexture", true);
|
||||||
|
|
||||||
|
set_mat4f(ui_shader, "projection", (float *)zephr_ctx->projection.m);
|
||||||
|
|
||||||
|
Vec2f pos = { 0.f, 0.f };
|
||||||
|
Sizef size = { 0.f, 0.f };
|
||||||
|
|
||||||
|
apply_constraints(constraints, &pos, &size);
|
||||||
|
apply_alignment(align, constraints, &pos, size);
|
||||||
|
|
||||||
|
// set the positions after applying alignment so children can use them
|
||||||
|
constraints->x = pos.x;
|
||||||
|
constraints->y = pos.y;
|
||||||
|
|
||||||
|
Matrix4x4 model = identity();
|
||||||
|
apply_translation(&model, (Vec2f){-size.width / 2.f, -size.height / 2.f});
|
||||||
|
apply_rotation(&model, to_radians(constraints->rotation));
|
||||||
|
apply_translation(&model, (Vec2f){size.width / 2.f, size.height / 2.f});
|
||||||
|
|
||||||
|
apply_translation(&model, pos);
|
||||||
|
|
||||||
|
set_mat4f(ui_shader, "model", (float *)model.m);
|
||||||
|
|
||||||
|
glBindVertexArray(ui_vao);
|
||||||
|
|
||||||
|
float vertices[6][4] = {
|
||||||
|
// bottom left tri
|
||||||
|
{0, 0 + size.height, 0.0, 1.0},
|
||||||
|
{0, 0, 0.0, 0.0},
|
||||||
|
{0 + size.width, 0, 1.0, 0.0},
|
||||||
|
|
||||||
|
// top right tri
|
||||||
|
{0, 0 + size.height, 0.0, 1.0},
|
||||||
|
{0 + size.width, 0, 1.0, 0.0},
|
||||||
|
{0 + size.width, 0 + size.height, 1.0, 1.0},
|
||||||
|
};
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, ui_vbo);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
set_bool(ui_shader, "hasTexture", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool draw_button(UIConstraints *constraints, const Color color, const char *text, f32 radius, Alignment align) {
|
bool draw_button(UIConstraints *constraints, const Color color, const char *text, f32 radius, Alignment align) {
|
||||||
@@ -285,10 +347,13 @@ bool draw_button(UIConstraints *constraints, const Color color, const char *text
|
|||||||
apply_constraints(constraints, &rect.pos, &rect.size);
|
apply_constraints(constraints, &rect.pos, &rect.size);
|
||||||
apply_alignment(align, constraints, &rect.pos, rect.size);
|
apply_alignment(align, constraints, &rect.pos, rect.size);
|
||||||
|
|
||||||
if (inside_rect(&rect, &zephr_ctx->mouse.pos)) {
|
bool is_hovered = inside_rect(&rect, &zephr_ctx->mouse.pos);
|
||||||
|
bool left_mouse_pressed = zephr_ctx->mouse.pressed && zephr_ctx->mouse.button == ZEPHR_MOUSE_BUTTON_LEFT;
|
||||||
|
|
||||||
|
if (is_hovered) {
|
||||||
zephr_set_cursor(ZEPHR_CURSOR_HAND);
|
zephr_set_cursor(ZEPHR_CURSOR_HAND);
|
||||||
|
|
||||||
if (zephr_ctx->mouse.pressed) {
|
if (left_mouse_pressed) {
|
||||||
Color new_color = mult_color(color, 0.8f);
|
Color new_color = mult_color(color, 0.8f);
|
||||||
draw_quad(constraints, new_color, radius, align);
|
draw_quad(constraints, new_color, radius, align);
|
||||||
} else {
|
} else {
|
||||||
@@ -296,7 +361,6 @@ bool draw_button(UIConstraints *constraints, const Color color, const char *text
|
|||||||
draw_quad(constraints, new_color, radius, align);
|
draw_quad(constraints, new_color, radius, align);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
zephr_set_cursor(ZEPHR_CURSOR_ARROW);
|
|
||||||
draw_quad(constraints, color, radius, align);
|
draw_quad(constraints, color, radius, align);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,22 +370,65 @@ bool draw_button(UIConstraints *constraints, const Color color, const char *text
|
|||||||
set_parent_constraint(&text_constraints, constraints);
|
set_parent_constraint(&text_constraints, constraints);
|
||||||
set_x_constraint(&text_constraints, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
|
set_x_constraint(&text_constraints, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
set_y_constraint(&text_constraints, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
|
set_y_constraint(&text_constraints, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
set_width_constraint(&text_constraints, 1.5, UI_CONSTRAINT_RELATIVE_PIXELS);
|
set_width_constraint(&text_constraints, 1.0, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
|
|
||||||
u8 font_size = (u8)(constraints->width * 0.2 / text_constraints.width * 0.2 * 100.f);
|
u8 font_size = (u8)((constraints->width) / (text_constraints.width * 0.1 * 65.f));
|
||||||
|
|
||||||
// TODO: need to adjust the font size based on the text height
|
// TODO: need to adjust the font size based on the text height
|
||||||
|
|
||||||
draw_text(text, font_size, text_constraints, COLOR_BLACK, ALIGN_CENTER);
|
draw_text(text, font_size, text_constraints, COLOR_BLACK, ALIGN_CENTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inside_rect(&rect, &zephr_ctx->mouse.pos) && zephr_ctx->mouse.released && zephr_ctx->mouse.button == ZEPHR_MOUSE_BUTTON_LEFT) {
|
if (is_hovered && zephr_ctx->mouse.released && zephr_ctx->mouse.button == ZEPHR_MOUSE_BUTTON_LEFT) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool draw_icon_button(UIConstraints *constraints, Color btn_color, const TextureId icon_tex_id, f32 radius, Alignment align) {
|
||||||
|
CORE_DEBUG_ASSERT(icon_tex_id, "draw_icon_button() requires that you provide an icon texture");
|
||||||
|
|
||||||
|
Rect rect = {0};
|
||||||
|
Color icon_color = COLOR_WHITE;
|
||||||
|
|
||||||
|
apply_constraints(constraints, &rect.pos, &rect.size);
|
||||||
|
apply_alignment(align, constraints, &rect.pos, rect.size);
|
||||||
|
|
||||||
|
bool is_hovered = inside_rect(&rect, &zephr_ctx->mouse.pos);
|
||||||
|
bool left_mouse_pressed = zephr_ctx->mouse.pressed && zephr_ctx->mouse.button == ZEPHR_MOUSE_BUTTON_LEFT;
|
||||||
|
|
||||||
|
if (is_hovered) {
|
||||||
|
zephr_set_cursor(ZEPHR_CURSOR_HAND);
|
||||||
|
|
||||||
|
if (left_mouse_pressed) {
|
||||||
|
btn_color = mult_color(btn_color, 0.8f);
|
||||||
|
icon_color = mult_color(icon_color, 0.8f);
|
||||||
|
} else {
|
||||||
|
btn_color = mult_color(btn_color, 0.9f);
|
||||||
|
icon_color = mult_color(icon_color, 0.9f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_quad(constraints, btn_color, radius, align);
|
||||||
|
|
||||||
|
UIConstraints icon_constraints = {0};
|
||||||
|
|
||||||
|
set_parent_constraint(&icon_constraints, constraints);
|
||||||
|
set_x_constraint(&icon_constraints, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
|
set_y_constraint(&icon_constraints, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
|
set_width_constraint(&icon_constraints, constraints->width * 0.8f, UI_CONSTRAINT_FIXED);
|
||||||
|
set_height_constraint(&icon_constraints, constraints->height * 0.8f, UI_CONSTRAINT_FIXED);
|
||||||
|
draw_texture(&icon_constraints, icon_tex_id, icon_color, 0, ALIGN_CENTER);
|
||||||
|
|
||||||
|
if (is_hovered && zephr_ctx->mouse.released && zephr_ctx->mouse.button == ZEPHR_MOUSE_BUTTON_LEFT) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* enum Element { */
|
/* enum Element { */
|
||||||
/* Rect, */
|
/* Rect, */
|
||||||
/* Circle, */
|
/* Circle, */
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "texture.h"
|
||||||
#include "zephr_math.h"
|
#include "zephr_math.h"
|
||||||
|
|
||||||
typedef struct Rect {
|
typedef struct Rect {
|
||||||
@@ -47,4 +48,5 @@ void apply_alignment(Alignment align, UIConstraints *constraints, Vec2f *pos, Si
|
|||||||
void draw_quad(UIConstraints *constraints, const Color color, float border_radius, Alignment align);
|
void draw_quad(UIConstraints *constraints, const Color color, float border_radius, Alignment align);
|
||||||
void draw_circle(UIConstraints *constraints, const Color color, Alignment align);
|
void draw_circle(UIConstraints *constraints, const Color color, Alignment align);
|
||||||
void draw_triangle(UIConstraints *constraints, const Color color, Alignment align);
|
void draw_triangle(UIConstraints *constraints, const Color color, Alignment align);
|
||||||
bool draw_button(UIConstraints *constraints, const Color color, const char *text, f32 radius, Alignment align);
|
bool draw_button(UIConstraints *constraints, Color color, const char *text, f32 radius, Alignment align);
|
||||||
|
bool draw_icon_button(UIConstraints *constraints, Color color, const TextureId icon_tex_id, f32 radius, Alignment align);
|
||||||
|
|||||||
@@ -529,6 +529,8 @@ void x11_toggle_fullscreen(bool fullscreen) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: currently the icon shows on gnome's sidebar correctly but not in gnome-system-monitor.
|
||||||
|
// investigate.
|
||||||
void x11_assign_window_icon(const char *icon_path) {
|
void x11_assign_window_icon(const char *icon_path) {
|
||||||
int icon_width, icon_height;
|
int icon_width, icon_height;
|
||||||
unsigned char *icon_data = stbi_load(icon_path, &icon_width, &icon_height, NULL, STBI_rgb_alpha);
|
unsigned char *icon_data = stbi_load(icon_path, &icon_width, &icon_height, NULL, STBI_rgb_alpha);
|
||||||
@@ -754,7 +756,7 @@ void x11_make_window_non_resizable(int width, int height) {
|
|||||||
|
|
||||||
|
|
||||||
void zephr_init(const char* font_path, const char* icon_path, const char* window_title, Size window_size) {
|
void zephr_init(const char* font_path, const char* icon_path, const char* window_title, Size window_size) {
|
||||||
zephr_ctx = malloc(sizeof(ZephrContext));
|
zephr_ctx = calloc(1, sizeof(ZephrContext));
|
||||||
|
|
||||||
// TODO: should I initalize the audio here or let the game handle that??
|
// TODO: should I initalize the audio here or let the game handle that??
|
||||||
int res = audio_init();
|
int res = audio_init();
|
||||||
@@ -790,6 +792,9 @@ bool zephr_should_quit(void) {
|
|||||||
glClearColor(0, 0, 0, 1);
|
glClearColor(0, 0, 0, 1);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
zephr_ctx->cursor = ZEPHR_CURSOR_ARROW;
|
||||||
|
zephr_ctx->mouse.released = false;
|
||||||
|
|
||||||
audio_update();
|
audio_update();
|
||||||
|
|
||||||
return zephr_ctx->should_quit;
|
return zephr_ctx->should_quit;
|
||||||
@@ -799,9 +804,8 @@ bool zephr_should_quit(void) {
|
|||||||
void zephr_swap_buffers(void) {
|
void zephr_swap_buffers(void) {
|
||||||
CORE_DEBUG_ASSERT(zephr_ctx, "Zephr context not initialized");
|
CORE_DEBUG_ASSERT(zephr_ctx, "Zephr context not initialized");
|
||||||
|
|
||||||
zephr_ctx->mouse.released = false;
|
|
||||||
|
|
||||||
glXSwapBuffers(x11_display, x11_window);
|
glXSwapBuffers(x11_display, x11_window);
|
||||||
|
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[zephr_ctx->cursor]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Size zephr_get_window_size(void) {
|
Size zephr_get_window_size(void) {
|
||||||
@@ -1042,30 +1046,6 @@ void zephr_set_cursor(ZephrCursor cursor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
zephr_ctx->cursor = cursor;
|
zephr_ctx->cursor = cursor;
|
||||||
|
|
||||||
switch (cursor) {
|
|
||||||
case ZEPHR_CURSOR_ARROW:
|
|
||||||
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[ZEPHR_CURSOR_ARROW]);
|
|
||||||
break;
|
|
||||||
case ZEPHR_CURSOR_IBEAM:
|
|
||||||
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[ZEPHR_CURSOR_IBEAM]);
|
|
||||||
break;
|
|
||||||
case ZEPHR_CURSOR_CROSSHAIR:
|
|
||||||
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[ZEPHR_CURSOR_CROSSHAIR]);
|
|
||||||
break;
|
|
||||||
case ZEPHR_CURSOR_HAND:
|
|
||||||
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[ZEPHR_CURSOR_HAND]);
|
|
||||||
break;
|
|
||||||
case ZEPHR_CURSOR_HRESIZE:
|
|
||||||
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[ZEPHR_CURSOR_HRESIZE]);
|
|
||||||
break;
|
|
||||||
case ZEPHR_CURSOR_VRESIZE:
|
|
||||||
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[ZEPHR_CURSOR_VRESIZE]);
|
|
||||||
break;
|
|
||||||
default :
|
|
||||||
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[ZEPHR_CURSOR_ARROW]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bool zephr_keyboard_scancode_is_pressed(ZephrScancode scancode) { */
|
/* bool zephr_keyboard_scancode_is_pressed(ZephrScancode scancode) { */
|
||||||
|
|||||||
Reference in New Issue
Block a user