WIP: settings, color picker and stuff

This commit is contained in:
2024-01-05 22:19:31 +02:00
parent b8d11050f8
commit bba2f8a189
10 changed files with 561 additions and 68 deletions
+171 -50
View File
@@ -64,29 +64,29 @@ void print_new_board() {
Color get_tile_color(u16 value) {
switch (value) {
case 2:
return ColorRGBA(238, 228, 218, 255);
return game.palette.tile_colors[0];
case 4:
return ColorRGBA(237, 224, 200, 255);
return game.palette.tile_colors[1];
case 8:
return ColorRGBA(242, 177, 121, 255);
return game.palette.tile_colors[2];
case 16:
return ColorRGBA(245, 149, 99, 255);
return game.palette.tile_colors[3];
case 32:
return ColorRGBA(246, 124, 95, 255);
return game.palette.tile_colors[4];
case 64:
return ColorRGBA(246, 94, 59, 255);
return game.palette.tile_colors[5];
case 128:
return ColorRGBA(237, 207, 114, 255);
return game.palette.tile_colors[6];
case 256:
return ColorRGBA(237, 204, 97, 255);
return game.palette.tile_colors[7];
case 512:
return ColorRGBA(237, 200, 80, 255);
return game.palette.tile_colors[8];
case 1024:
return ColorRGBA(237, 197, 63, 255);
return game.palette.tile_colors[9];
case 2048:
return ColorRGBA(237, 194, 46, 255);
return game.palette.tile_colors[10];
default:
return ColorRGBA(237, 194, 46, 255);
return game.palette.tile_colors[10];
}
}
@@ -399,6 +399,7 @@ void reset_game(void) {
game.spawning_new_tile = false;
game.quit_dialog = false;
game.help_dialog = false;
game.settings_dialog = false;
game.has_lost = false;
game.game_over_bg_opacity = 0;
game.game_over_opacity = 0;
@@ -421,9 +422,29 @@ void reset_game(void) {
void game_attempt_quit(void) {
game.help_dialog = false;
game.settings_dialog = false;
game.quit_dialog = true;
}
void reset_palette(void) {
game.palette = (ColorPalette){
.bg_color = ColorRGBA(248, 250, 230, 255),
.board_bg_color = ColorRGBA(140, 154, 147, 255),
.tile_colors[0] = ColorRGBA(238, 228, 218, 255), // 2
.tile_colors[1] = ColorRGBA(237, 224, 200, 255), // 4
.tile_colors[2] = ColorRGBA(242, 177, 121, 255), // 8
.tile_colors[3] = ColorRGBA(245, 149, 99, 255), // 16
.tile_colors[4] = ColorRGBA(246, 124, 95, 255), // 32
.tile_colors[5] = ColorRGBA(246, 94, 59, 255), // 64
.tile_colors[6] = ColorRGBA(237, 207, 114, 255), // 128
.tile_colors[7] = ColorRGBA(237, 204, 97, 255), // 256
.tile_colors[8] = ColorRGBA(237, 200, 80, 255), // 512
.tile_colors[9] = ColorRGBA(237, 197, 63, 255), // 1024
.tile_colors[10] = ColorRGBA(237, 194, 46, 255), // 2048
};
}
void game_init(void) {
srand(time(NULL));
@@ -431,6 +452,8 @@ void game_init(void) {
game.icon_textures[SETTINGS_ICON] = load_texture("assets/icons/settings.png");
game.icon_textures[CLOSE_ICON] = load_texture("assets/icons/close.png");
reset_palette();
for (int i = 0; i < 2; i++) {
spawn_random_tile();
}
@@ -447,37 +470,39 @@ void game_init(void) {
void draw_bg(void) {
Size window_size = zephr_get_window_size();
UIConstraints board_con = {0};
UIConstraints board_con = default_constraints;
set_width_constraint(&board_con, window_size.width, UI_CONSTRAINT_FIXED);
set_height_constraint(&board_con, window_size.height, UI_CONSTRAINT_FIXED);
// bg
draw_quad(&board_con, ColorRGBA(248, 250, 230, 255), 0, ALIGN_TOP_LEFT);
draw_quad(&board_con, game.palette.bg_color, 0, ALIGN_TOP_LEFT);
GlyphInstanceList batch;
new_glyph_instance_list(&batch, 32);
// 2048 text
UIConstraints text_con = {0};
UIConstraints text_con = default_constraints;
set_y_constraint(&text_con, 0.05f, UI_CONSTRAINT_RELATIVE);
set_width_constraint(&text_con, 1.5, UI_CONSTRAINT_RELATIVE_PIXELS);
draw_text("2048", 100, text_con, ColorRGBA(34, 234, 82, 155), ALIGN_TOP_CENTER);
add_text_instance(&batch, "2048", 100, text_con, ColorRGBA(34, 234, 82, 155), ALIGN_TOP_CENTER);
// score
char score[16];
sprintf(score, "%d", game.score);
char score[24];
sprintf(score, "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);
add_text_instance(&batch, 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);
draw_text_batch(&batch);
}
void draw_quit_dialog(void) {
UIConstraints dialog_con = {0};
UIConstraints dialog_con = default_constraints;
set_x_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED);
set_y_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED);
set_width_constraint(&dialog_con, 1.f, UI_CONSTRAINT_RELATIVE);
@@ -488,45 +513,45 @@ void draw_quit_dialog(void) {
set_height_constraint(&dialog_con, 0.2f, UI_CONSTRAINT_RELATIVE);
draw_quad(&dialog_con, ColorRGBA(135, 124, 124, 255), 8, ALIGN_CENTER);
UIConstraints text_con = {0};
UIConstraints text_con = default_constraints;
set_parent_constraint(&text_con, &dialog_con);
set_x_constraint(&text_con, 0, UI_CONSTRAINT_FIXED);
set_y_constraint(&text_con, -0.04f, UI_CONSTRAINT_RELATIVE);
set_y_constraint(&text_con, -0.25f, UI_CONSTRAINT_RELATIVE);
set_width_constraint(&text_con, 1, UI_CONSTRAINT_RELATIVE_PIXELS);
draw_text("Are you sure you want to quit?", 36.f, text_con, COLOR_WHITE, ALIGN_CENTER);
UIConstraints btn_con = {0};
UIConstraints btn_con = default_constraints;
set_parent_constraint(&btn_con, &dialog_con);
set_width_constraint(&btn_con, 0.12f, UI_CONSTRAINT_RELATIVE);
set_height_constraint(&btn_con, 0.05f, UI_CONSTRAINT_RELATIVE);
set_y_constraint(&btn_con, -0.02f, UI_CONSTRAINT_RELATIVE);
set_x_constraint(&btn_con, -0.07f, UI_CONSTRAINT_RELATIVE);
set_width_constraint(&btn_con, 0.25f, UI_CONSTRAINT_RELATIVE);
set_height_constraint(&btn_con, 0.25f, UI_CONSTRAINT_RELATIVE);
set_y_constraint(&btn_con, -0.10f, UI_CONSTRAINT_RELATIVE);
set_x_constraint(&btn_con, -0.20f, UI_CONSTRAINT_RELATIVE);
if (draw_button(&btn_con, mult_color(COLOR_WHITE, 0.9f), "Yes", btn_con.height * 0.20f, ALIGN_BOTTOM_CENTER, BUTTON_STATE_ACTIVE)) {
zephr_quit();
}
set_y_constraint(&btn_con, -0.02f, UI_CONSTRAINT_RELATIVE);
set_x_constraint(&btn_con, 0.07f, UI_CONSTRAINT_RELATIVE);
set_y_constraint(&btn_con, -0.10f, UI_CONSTRAINT_RELATIVE);
set_x_constraint(&btn_con, 0.20f, UI_CONSTRAINT_RELATIVE);
if (draw_button(&btn_con, mult_color(COLOR_WHITE, 0.9f), "No", btn_con.height * 0.20f, ALIGN_BOTTOM_CENTER, BUTTON_STATE_ACTIVE)) {
game.quit_dialog = false;
}
}
void draw_help_dialog(void) {
UIConstraints dialog_con = {0};
UIConstraints dialog_con = default_constraints;
set_width_constraint(&dialog_con, 1.f, UI_CONSTRAINT_RELATIVE);
set_height_constraint(&dialog_con, 1.f, UI_CONSTRAINT_RELATIVE);
set_x_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED);
set_y_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED);
draw_quad(&dialog_con, ColorRGBA(0, 0, 0, 200), 0, ALIGN_CENTER);
UIConstraints content_card_con = {0};
UIConstraints content_card_con = default_constraints;
set_parent_constraint(&content_card_con, &dialog_con);
set_width_constraint(&content_card_con, 0.4f, UI_CONSTRAINT_RELATIVE);
set_height_constraint(&content_card_con, 0.3f, UI_CONSTRAINT_RELATIVE);
set_height_constraint(&content_card_con, 0.33f, UI_CONSTRAINT_RELATIVE);
draw_quad(&content_card_con, ColorRGBA(135, 124, 124, 255), 8, ALIGN_CENTER);
UIConstraints text_con = {0};
UIConstraints text_con = default_constraints;
set_parent_constraint(&text_con, &content_card_con);
set_width_constraint(&text_con, 1, UI_CONSTRAINT_RELATIVE_PIXELS);
set_x_constraint(&text_con, 0, UI_CONSTRAINT_FIXED);
@@ -539,7 +564,7 @@ void draw_help_dialog(void) {
"When two tiles with the same number touch, they\n"
"merge into one!\n\nYour goal is to reach 2048 without filling all the tiles", 30.f, text_con, COLOR_WHITE, ALIGN_CENTER);
UIConstraints btn_con = {0};
UIConstraints btn_con = default_constraints;
set_parent_constraint(&btn_con, &content_card_con);
set_width_constraint(&btn_con, 56, UI_CONSTRAINT_RELATIVE_PIXELS);
set_height_constraint(&btn_con, 1, UI_CONSTRAINT_ASPECT_RATIO);
@@ -550,33 +575,124 @@ void draw_help_dialog(void) {
}
}
void draw_settings_dialog(void) {
UIConstraints dialog_con = default_constraints;
set_width_constraint(&dialog_con, 1.f, UI_CONSTRAINT_RELATIVE);
set_height_constraint(&dialog_con, 1.f, UI_CONSTRAINT_RELATIVE);
set_x_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED);
set_y_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED);
draw_quad(&dialog_con, ColorRGBA(0, 0, 0, 200), 0, ALIGN_CENTER);
UIConstraints content_card_con = default_constraints;
set_parent_constraint(&content_card_con, &dialog_con);
set_width_constraint(&content_card_con, 0.55f, UI_CONSTRAINT_RELATIVE);
set_height_constraint(&content_card_con, 0.6f, UI_CONSTRAINT_RELATIVE);
draw_quad(&content_card_con, ColorRGBA(135, 124, 124, 255), 8, ALIGN_CENTER);
UIConstraints text_con = default_constraints;
set_parent_constraint(&text_con, &content_card_con);
set_width_constraint(&text_con, 1, UI_CONSTRAINT_RELATIVE_PIXELS);
set_x_constraint(&text_con, 0, UI_CONSTRAINT_FIXED);
set_y_constraint(&text_con, 40, UI_CONSTRAINT_RELATIVE_PIXELS);
draw_text("Settings", 64.f, text_con, COLOR_YELLOW, ALIGN_TOP_CENTER);
set_x_constraint(&text_con, 30, UI_CONSTRAINT_RELATIVE_PIXELS);
set_y_constraint(&text_con, 150, UI_CONSTRAINT_RELATIVE_PIXELS);
draw_text("Color Palette", 40.f, text_con, COLOR_WHITE, ALIGN_TOP_LEFT);
const char *bg_color_text = "Background: ";
const u8 font_size = 30.f;
set_x_constraint(&text_con, 30, UI_CONSTRAINT_RELATIVE_PIXELS);
set_y_constraint(&text_con, 220, UI_CONSTRAINT_RELATIVE_PIXELS);
set_height_constraint(&text_con, 0.9f, UI_CONSTRAINT_RELATIVE);
draw_text(bg_color_text, font_size, text_con, COLOR_WHITE, ALIGN_TOP_LEFT);
Sizef text_size = calculate_text_size(bg_color_text, font_size);
UIConstraints color_picker_con = default_constraints;
set_parent_constraint(&color_picker_con, &content_card_con);
set_x_constraint(&color_picker_con, 30 + text_size.width + 20, UI_CONSTRAINT_RELATIVE_PIXELS);
set_y_constraint(&color_picker_con, 220 - text_size.height / 2.f + 6, UI_CONSTRAINT_RELATIVE_PIXELS);
set_width_constraint(&color_picker_con, 100, UI_CONSTRAINT_RELATIVE_PIXELS);
set_height_constraint(&color_picker_con, 40, UI_CONSTRAINT_RELATIVE_PIXELS);
draw_color_picker(&color_picker_con, &game.palette.bg_color, ALIGN_TOP_LEFT, BUTTON_STATE_ACTIVE);
set_y_constraint(&text_con, 270, UI_CONSTRAINT_RELATIVE_PIXELS);
draw_text("Board: ", font_size, text_con, COLOR_WHITE, ALIGN_TOP_LEFT);
set_x_constraint(&color_picker_con, 30 + text_size.width + 20, UI_CONSTRAINT_RELATIVE_PIXELS);
set_y_constraint(&color_picker_con, 270 - text_size.height / 2.f + 6, UI_CONSTRAINT_RELATIVE_PIXELS);
set_width_constraint(&color_picker_con, 100, UI_CONSTRAINT_RELATIVE_PIXELS);
set_height_constraint(&color_picker_con, 40, UI_CONSTRAINT_RELATIVE_PIXELS);
draw_color_picker(&color_picker_con, &game.palette.board_bg_color, ALIGN_TOP_LEFT, BUTTON_STATE_ACTIVE);
set_y_constraint(&text_con, 320, UI_CONSTRAINT_RELATIVE_PIXELS);
draw_text("Tiles: ", font_size, text_con, COLOR_WHITE, ALIGN_TOP_LEFT);
const u8 tile_size = 60;
for (u8 i = 0; i < 11; i++) {
set_x_constraint(&color_picker_con, 30 + text_size.width + 20 + (i * (tile_size + 10)), UI_CONSTRAINT_RELATIVE_PIXELS);
set_y_constraint(&color_picker_con, 320 - text_size.height / 2.f + 6, UI_CONSTRAINT_RELATIVE_PIXELS);
set_width_constraint(&color_picker_con, tile_size, UI_CONSTRAINT_RELATIVE_PIXELS);
set_height_constraint(&color_picker_con, tile_size, UI_CONSTRAINT_RELATIVE_PIXELS);
draw_color_picker(&color_picker_con, &game.palette.tile_colors[i], ALIGN_TOP_LEFT, BUTTON_STATE_ACTIVE);
u16 tile_val = (u16)pow(2, i + 1);
char text[16];
sprintf(text, "%d", tile_val);
const f32 font_size = get_tile_font_size(tile_val) * 0.5f;
const Color tile_color = get_tile_color(tile_val);
set_parent_constraint(&text_con, &color_picker_con);
set_x_constraint(&text_con, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
set_y_constraint(&text_con, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
draw_text(text, (u8)font_size, text_con, mult_color(tile_color, 0.5f), ALIGN_CENTER);
}
UIConstraints btn_con = default_constraints;
set_parent_constraint(&btn_con, &content_card_con);
set_x_constraint(&btn_con, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
set_y_constraint(&btn_con, 400, UI_CONSTRAINT_RELATIVE_PIXELS);
set_width_constraint(&btn_con, 150, UI_CONSTRAINT_RELATIVE_PIXELS);
set_height_constraint(&btn_con, 0.35f, UI_CONSTRAINT_ASPECT_RATIO);
if (draw_button(&btn_con, ColorRGBA(201, 146, 126, 255), "Reset", 8.f, ALIGN_TOP_CENTER, BUTTON_STATE_ACTIVE)) {
reset_palette();
}
set_width_constraint(&btn_con, 56, UI_CONSTRAINT_RELATIVE_PIXELS);
set_height_constraint(&btn_con, 1, UI_CONSTRAINT_ASPECT_RATIO);
set_y_constraint(&btn_con, -24, UI_CONSTRAINT_RELATIVE_PIXELS);
set_x_constraint(&btn_con, 24, UI_CONSTRAINT_RELATIVE_PIXELS);
if (draw_icon_button(&btn_con, mult_color(COLOR_WHITE, 0.8f), game.icon_textures[CLOSE_ICON], btn_con.height * 0.20f, ALIGN_TOP_RIGHT, BUTTON_STATE_ACTIVE)) {
game.settings_dialog = false;
}
}
void draw_game_over(void) {
UIConstraints dialog_con = {0};
UIConstraints dialog_con = default_constraints;
set_width_constraint(&dialog_con, 1.f, UI_CONSTRAINT_RELATIVE);
set_height_constraint(&dialog_con, 1.f, UI_CONSTRAINT_RELATIVE);
set_x_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED);
set_y_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED);
draw_quad(&dialog_con, ColorRGBA(0, 0, 0, (u8)game.game_over_bg_opacity), 0, ALIGN_CENTER);
UIConstraints content_card_con = {0};
UIConstraints content_card_con = default_constraints;
set_parent_constraint(&content_card_con, &dialog_con);
set_width_constraint(&content_card_con, 0.3f, UI_CONSTRAINT_RELATIVE);
set_height_constraint(&content_card_con, 0.2f, UI_CONSTRAINT_RELATIVE);
draw_quad(&content_card_con, ColorRGBA(135, 124, 124, (u8)game.game_over_opacity), 8, ALIGN_CENTER);
UIConstraints text_con = {0};
UIConstraints text_con = default_constraints;
set_parent_constraint(&text_con, &content_card_con);
set_width_constraint(&text_con, 1, UI_CONSTRAINT_RELATIVE_PIXELS);
set_x_constraint(&text_con, 0, UI_CONSTRAINT_FIXED);
set_y_constraint(&text_con, 40, UI_CONSTRAINT_RELATIVE_PIXELS);
draw_text("Game Over!", 64.f, text_con, ColorRGBA(255, 255, 0, (u8)game.game_over_opacity), ALIGN_TOP_CENTER);
UIConstraints btn_con = {0};
UIConstraints btn_con = default_constraints;
const ButtonState btn_state = game.quit_dialog ? BUTTON_STATE_INACTIVE : game.game_over_opacity > 0 ? BUTTON_STATE_ACTIVE : BUTTON_STATE_INACTIVE;
set_parent_constraint(&btn_con, &content_card_con);
set_x_constraint(&btn_con, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
set_y_constraint(&btn_con, -24, UI_CONSTRAINT_RELATIVE_PIXELS);
set_width_constraint(&btn_con, 0.10f, UI_CONSTRAINT_RELATIVE);
set_width_constraint(&btn_con, 0.30f, UI_CONSTRAINT_RELATIVE);
set_height_constraint(&btn_con, 0.3f, UI_CONSTRAINT_ASPECT_RATIO);
if (draw_button(&btn_con, ColorRGBA(201, 146, 126, (u8)game.game_over_opacity), "Try Again", 8.f, ALIGN_BOTTOM_CENTER, btn_state)) {
reset_game();
@@ -584,14 +700,14 @@ void draw_game_over(void) {
}
void draw_ui(void) {
ButtonState bg_btns_state = game.quit_dialog || game.help_dialog || game.has_lost
ButtonState bg_btns_state = game.quit_dialog || game.help_dialog || game.settings_dialog || game.has_lost
? BUTTON_STATE_INACTIVE
: BUTTON_STATE_ACTIVE;
const int icon_btn_width = 80;
const int icon_btn_offset = 8;
const int icon_btns_padding = 10;
UIConstraints btn_con = {0};
UIConstraints btn_con = default_constraints;
set_x_constraint(&btn_con, -icon_btn_offset, UI_CONSTRAINT_RELATIVE_PIXELS);
set_y_constraint(&btn_con, icon_btn_offset, UI_CONSTRAINT_RELATIVE_PIXELS);
set_width_constraint(&btn_con, icon_btn_width, UI_CONSTRAINT_RELATIVE_PIXELS);
@@ -603,7 +719,7 @@ void draw_ui(void) {
set_x_constraint(&btn_con, -icon_btn_offset - icon_btn_width - icon_btns_padding, UI_CONSTRAINT_RELATIVE_PIXELS);
if (draw_icon_button(&btn_con, ColorRGBA(201, 146, 126, 255), game.icon_textures[SETTINGS_ICON], btn_con.height * 0.15f, ALIGN_TOP_RIGHT, bg_btns_state)) {
printf("TODO: settings\n");
game.settings_dialog = true;
}
set_x_constraint(&btn_con, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
@@ -614,6 +730,10 @@ void draw_ui(void) {
reset_game();
}
if (game.settings_dialog) {
draw_settings_dialog();
}
if (game.help_dialog) {
draw_help_dialog();
}
@@ -629,19 +749,19 @@ void draw_ui(void) {
void draw_board(void) {
// board
UIConstraints board_con = {0};
UIConstraints board_con = default_constraints;
set_y_constraint(&board_con, 0.05f, UI_CONSTRAINT_RELATIVE);
set_height_constraint(&board_con, 0.6f, UI_CONSTRAINT_RELATIVE);
set_width_constraint(&board_con, 1, UI_CONSTRAINT_ASPECT_RATIO);
const float board_border_radius = board_con.width * 0.02f;
draw_quad(&board_con, ColorRGBA(140, 154, 147, 255), board_border_radius, ALIGN_CENTER);
draw_quad(&board_con, game.palette.board_bg_color, board_border_radius, ALIGN_CENTER);
// empty tiles
const float tile_padding = board_con.width * 0.02f;
const float tile_height = board_con.height * 0.225f;
const float tile_board_radius = tile_height * 0.15f;
UIConstraints empty_tile_con = {0};
UIConstraints empty_tile_con = default_constraints;
set_parent_constraint(&empty_tile_con, &board_con);
set_height_constraint(&empty_tile_con, tile_height, UI_CONSTRAINT_FIXED);
set_width_constraint(&empty_tile_con, 1, UI_CONSTRAINT_ASPECT_RATIO);
@@ -650,14 +770,14 @@ void draw_board(void) {
set_y_constraint(&empty_tile_con, (tile_height + tile_padding) * i + tile_padding, UI_CONSTRAINT_FIXED);
for (int j = 0; j < 4; j++) {
set_x_constraint(&empty_tile_con, (tile_height + tile_padding) * j + tile_padding, UI_CONSTRAINT_FIXED);
draw_quad(&empty_tile_con, ColorRGBA(120, 133, 126, 255), tile_board_radius, ALIGN_TOP_LEFT);
draw_quad(&empty_tile_con, mult_color(game.palette.board_bg_color, 0.85f), tile_board_radius, ALIGN_TOP_LEFT);
}
}
// filled tiles
UIConstraints text_con = {0};
UIConstraints text_con = default_constraints;
set_width_constraint(&text_con, 1.5, UI_CONSTRAINT_RELATIVE_PIXELS);
UIConstraints tile_con = {0};
UIConstraints tile_con = default_constraints;
set_parent_constraint(&tile_con, &board_con);
set_height_constraint(&tile_con, tile_height, UI_CONSTRAINT_FIXED);
set_width_constraint(&tile_con, 1, UI_CONSTRAINT_ASPECT_RATIO);
@@ -863,6 +983,7 @@ void handle_keyboard_input(ZephrEvent e) {
} else if (e.key.code == ZEPHR_KEYCODE_ESCAPE) {
game.quit_dialog = false;
game.help_dialog = false;
game.settings_dialog = false;
} else if (e.key.code == ZEPHR_KEYCODE_F11) {
zephr_toggle_fullscreen();
} else if (e.key.code == ZEPHR_KEYCODE_UP) {
+10 -1
View File
@@ -18,6 +18,12 @@ typedef enum IconTexture {
ICON_TEXTURE_COUNT,
} IconTexture;
typedef struct ColorPalette {
Color bg_color;
Color board_bg_color;
Color tile_colors[11];
} ColorPalette;
typedef struct Tile {
u16 value;
u16 new_value;
@@ -41,9 +47,12 @@ typedef struct Game {
Vec2 spawning_tile_coords;
u16 spawning_tile_value;
TextureId icon_textures[ICON_TEXTURE_COUNT];
bool quit_dialog;
bool help_dialog;
bool settings_dialog;
TextureId icon_textures[ICON_TEXTURE_COUNT];
ColorPalette palette;
} Game;
void draw_board(void);
+32
View File
@@ -0,0 +1,32 @@
#version 330 core
in vec2 v_TexCoords;
out vec4 FragColor;
uniform bool isSlider;
uniform float sliderPercentage;
//vec3 rgb2hsv(vec3 c){
// vec4 K = vec4(0.0,-1.0 / 3.0,2.0 / 3.0,-1.0);
// vec4 p = mix(vec4(c.bg,K.wz),vec4(c.gb,K.xy),step(c.b,c.g));
// vec4 q = mix(vec4(p.xyw,c.r),vec4(c.r,p.yzx),step(p.x,c.r));
// float d = q.x - min(q.w,q.y);
// float e = 1.0e-10;
// return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)),d / (q.x + e),q.x);
//}
vec3 hsv2rgb(vec3 color){
vec3 rgb = clamp(abs(mod(color.r * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);
rgb = rgb * rgb * (3.0 - 2.0 * rgb);
return color.b * mix(vec3(1.0), rgb, color.g);
}
void main() {
if (isSlider) {
vec3 color = hsv2rgb(vec3(v_TexCoords.y, 1.0, 1.0));
FragColor = vec4(color, 1.0);
} else {
vec3 color = hsv2rgb(vec3(sliderPercentage, v_TexCoords.x, 1.0 - v_TexCoords.y));
FragColor = vec4(color, 1.0);
}
}
+2 -2
View File
@@ -10,7 +10,7 @@
#include "text.h"
#include "zephr.h"
#define FONT_PIXEL_SIZE 128
#define FONT_PIXEL_SIZE 100
#define LINE_HEIGHT 2.0f
Shader font_shader;
@@ -100,7 +100,7 @@ int init_freetype(const char* font_path) {
tex_height = CORE_MAX(tex_height, face->glyph->bitmap.rows);
}
char *pixels = (char *)calloc(tex_width * tex_height, 1);
char *pixels = (char *)malloc(tex_width * tex_height);
for (u32 i = 32; i < 128; i++) {
/* while (glyph_idx) { */
+288 -8
View File
@@ -1,3 +1,4 @@
#include <math.h>
#include <stdio.h>
#include <glad/glx.h>
@@ -7,9 +8,14 @@
#include "zephr.h"
Shader ui_shader;
Shader color_chooser_shader;
unsigned int ui_vao;
unsigned int ui_vbo;
const UIConstraints default_constraints = {
.scale = {.height = 1, .width = 1},
};
int init_ui(const char* font_path) {
int res = init_fonts(font_path);
if (res == -1) {
@@ -21,6 +27,7 @@ int init_ui(const char* font_path) {
}
ui_shader = create_shader("shaders/ui.vert", "shaders/ui.frag");
color_chooser_shader = create_shader("shaders/ui.vert", "shaders/color_chooser.frag");
glGenVertexArrays(1, &ui_vao);
glGenBuffers(1, &ui_vbo);
@@ -49,7 +56,11 @@ void set_x_constraint(UIConstraints *constraints, float value, UIConstraint type
constraints->x = value;
break;
case UI_CONSTRAINT_RELATIVE:
constraints->x = (value * zephr_ctx->window.size.width);
if (constraints->parent) {
constraints->x = (value * constraints->parent->width);
} else {
constraints->x = (value * zephr_ctx->window.size.width);
}
break;
case UI_CONSTRAINT_RELATIVE_PIXELS:
constraints->x = zephr_ctx->window.size.width / (float)zephr_ctx->screen_size.width * value;
@@ -69,7 +80,11 @@ void set_y_constraint(UIConstraints *constraints, float value, UIConstraint type
constraints->y = value;
break;
case UI_CONSTRAINT_RELATIVE:
constraints->y = (value * zephr_ctx->window.size.height);
if (constraints->parent) {
constraints->y = (value * constraints->parent->height);
} else {
constraints->y = (value * zephr_ctx->window.size.height);
}
break;
case UI_CONSTRAINT_RELATIVE_PIXELS:
constraints->y = zephr_ctx->window.size.height / (float)zephr_ctx->screen_size.height * value;
@@ -87,7 +102,11 @@ void set_width_constraint(UIConstraints *constraints, float value, UIConstraint
constraints->width = value;
break;
case UI_CONSTRAINT_RELATIVE:
constraints->width = (value * zephr_ctx->window.size.width);
if (constraints->parent) {
constraints->width = (value * constraints->parent->width);
} else {
constraints->width = (value * zephr_ctx->window.size.width);
}
break;
case UI_CONSTRAINT_RELATIVE_PIXELS:
constraints->width = zephr_ctx->window.size.width / (float)zephr_ctx->screen_size.width * value;
@@ -104,7 +123,11 @@ void set_height_constraint(UIConstraints *constraints, float value, UIConstraint
constraints->height = value;
break;
case UI_CONSTRAINT_RELATIVE:
constraints->height = (value * zephr_ctx->window.size.height);
if (constraints->parent) {
constraints->height = (value * constraints->parent->height);
} else {
constraints->height = (value * zephr_ctx->window.size.height);
}
break;
case UI_CONSTRAINT_RELATIVE_PIXELS:
constraints->height = zephr_ctx->window.size.height / (float)zephr_ctx->screen_size.height * value;
@@ -177,8 +200,15 @@ 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) {
/* bool outside_popup = true; */
/* if (rect != &zephr_ctx->ui.popup_rect) { */
/* outside_popup = !inside_rect(&zephr_ctx->ui.popup_rect, point); */
/* } else { */
/* outside_popup = false; */
/* } */
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;
@@ -204,6 +234,10 @@ void draw_quad(UIConstraints *constraints, const Color color, float border_radiu
constraints->y = pos.y;
Matrix4x4 model = identity();
apply_translation(&model, (Vec2f){-size.width / 2.f, -size.height / 2.f});
apply_scale(&model, constraints->scale);
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_translation(&model, (Vec2f){size.width / 2.f, size.height / 2.f});
@@ -250,6 +284,7 @@ void draw_triangle(UIConstraints *constraints, const Color color, Alignment alig
use_shader(ui_shader);
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, "borderRadius", 0.f);
set_mat4f(ui_shader, "projection", (float *)zephr_ctx->projection.m);
Vec2f pos = { 0.f, 0.f };
@@ -263,6 +298,10 @@ void draw_triangle(UIConstraints *constraints, const Color color, Alignment alig
constraints->y = pos.y;
Matrix4x4 model = identity();
apply_translation(&model, (Vec2f){-size.width / 2.f, -size.height / 2.f});
apply_scale(&model, constraints->scale);
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_translation(&model, (Vec2f){size.width / 2.f, size.height / 2.f});
@@ -310,6 +349,10 @@ void draw_texture(UIConstraints *constraints, const TextureId texture_id, const
constraints->y = pos.y;
Matrix4x4 model = identity();
apply_translation(&model, (Vec2f){-size.width / 2.f, -size.height / 2.f});
apply_scale(&model, constraints->scale);
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_translation(&model, (Vec2f){size.width / 2.f, size.height / 2.f});
@@ -380,7 +423,7 @@ bool draw_button(UIConstraints *constraints, const Color color, const char *text
}
if (text) {
UIConstraints text_constraints = {0};
UIConstraints text_constraints = default_constraints;
set_parent_constraint(&text_constraints, constraints);
set_x_constraint(&text_constraints, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
@@ -434,7 +477,7 @@ bool draw_icon_button(UIConstraints *constraints, Color btn_color, const Texture
draw_quad(constraints, btn_color, radius, align);
UIConstraints icon_constraints = {0};
UIConstraints icon_constraints = default_constraints;
set_parent_constraint(&icon_constraints, constraints);
set_x_constraint(&icon_constraints, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
@@ -450,6 +493,243 @@ bool draw_icon_button(UIConstraints *constraints, Color btn_color, const Texture
return false;
}
void draw_color_picker_slider(UIConstraints *constraints, Alignment align) {
use_shader(color_chooser_shader);
set_bool(color_chooser_shader, "isSlider", true);
set_mat4f(color_chooser_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, pos);
set_mat4f(color_chooser_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);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
set_bool(color_chooser_shader, "isSlider", false);
}
void draw_color_picker_canvas(UIConstraints *constraints, f32 slider_percentage, Alignment align) {
use_shader(color_chooser_shader);
set_bool(color_chooser_shader, "isSlider", false);
set_float(color_chooser_shader, "sliderPercentage", slider_percentage);
set_mat4f(color_chooser_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, pos);
set_mat4f(color_chooser_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);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
// TODO: consume mouse events on the popup
void draw_color_picker_popup(UIConstraints *picker_button_con) {
UIConstraints popup_con = default_constraints;
set_parent_constraint(&popup_con, picker_button_con);
set_x_constraint(&popup_con, 0, UI_CONSTRAINT_FIXED);
set_y_constraint(&popup_con, picker_button_con->height + 20, UI_CONSTRAINT_FIXED);
set_width_constraint(&popup_con, 450, UI_CONSTRAINT_RELATIVE_PIXELS);
set_height_constraint(&popup_con, 480, UI_CONSTRAINT_RELATIVE_PIXELS);
draw_quad(&popup_con, mult_color(COLOR_WHITE, 0.94f), 8, ALIGN_TOP_LEFT);
UIConstraints color_slider_con = default_constraints;
set_parent_constraint(&color_slider_con, &popup_con);
set_x_constraint(&color_slider_con, -0.04f, UI_CONSTRAINT_RELATIVE);
set_y_constraint(&color_slider_con, 0.05f, UI_CONSTRAINT_RELATIVE);
set_height_constraint(&color_slider_con, 400 * 0.9f, UI_CONSTRAINT_RELATIVE_PIXELS);
set_width_constraint(&color_slider_con, 0.1f, UI_CONSTRAINT_ASPECT_RATIO);
draw_color_picker_slider(&color_slider_con, ALIGN_TOP_RIGHT);
static f32 slider_selection = 0;
static Vec2f canvas_pos = {0};
if (inside_rect(&(Rect){{color_slider_con.x, color_slider_con.y}, {color_slider_con.width, color_slider_con.height}}, &zephr_ctx->mouse.pos) &&
zephr_ctx->mouse.pressed && zephr_ctx->mouse.button == ZEPHR_MOUSE_BUTTON_LEFT) {
slider_selection = (zephr_ctx->mouse.pos.y - color_slider_con.y) / color_slider_con.height;
}
UIConstraints triangle_con = default_constraints;
set_parent_constraint(&triangle_con, &color_slider_con);
set_x_constraint(&triangle_con, -11, UI_CONSTRAINT_RELATIVE_PIXELS);
set_y_constraint(&triangle_con, slider_selection, UI_CONSTRAINT_RELATIVE);
set_rotation_constraint(&triangle_con, -90);
set_width_constraint(&triangle_con, 14, UI_CONSTRAINT_RELATIVE_PIXELS);
set_height_constraint(&triangle_con, 0.5f, UI_CONSTRAINT_ASPECT_RATIO);
triangle_con.y += -(triangle_con.height / 2.f);
draw_triangle(&triangle_con, COLOR_BLACK, ALIGN_TOP_LEFT);
set_x_constraint(&triangle_con, 1, UI_CONSTRAINT_RELATIVE);
triangle_con.x -= triangle_con.height / 2;
set_rotation_constraint(&triangle_con, 90);
draw_triangle(&triangle_con, COLOR_BLACK, ALIGN_TOP_LEFT);
set_x_constraint(&color_slider_con, 0.04f, UI_CONSTRAINT_RELATIVE);
set_y_constraint(&color_slider_con, 0.05f, UI_CONSTRAINT_RELATIVE);
set_width_constraint(&color_slider_con, popup_con.width * 0.8f, UI_CONSTRAINT_FIXED);
draw_color_picker_canvas(&color_slider_con, slider_selection, ALIGN_TOP_LEFT);
if (inside_rect(&(Rect){{color_slider_con.x, color_slider_con.y}, {color_slider_con.width, color_slider_con.height}}, &zephr_ctx->mouse.pos) &&
zephr_ctx->mouse.pressed && zephr_ctx->mouse.button == ZEPHR_MOUSE_BUTTON_LEFT) {
f32 x = (zephr_ctx->mouse.pos.x - color_slider_con.x) / color_slider_con.width;
f32 y = (zephr_ctx->mouse.pos.y - color_slider_con.y) / color_slider_con.height;
canvas_pos.x = x;
canvas_pos.y = y;
}
set_parent_constraint(&triangle_con, &color_slider_con);
set_x_constraint(&triangle_con, canvas_pos.x, UI_CONSTRAINT_RELATIVE);
set_y_constraint(&triangle_con, canvas_pos.y, UI_CONSTRAINT_RELATIVE);
triangle_con.x -= triangle_con.height;
triangle_con.y -= triangle_con.height * 2;
set_rotation_constraint(&triangle_con, 0);
draw_triangle(&triangle_con, COLOR_WHITE, ALIGN_TOP_LEFT);
triangle_con.x += triangle_con.height * 2;
triangle_con.y += triangle_con.height * 2;
set_rotation_constraint(&triangle_con, 90);
draw_triangle(&triangle_con, COLOR_WHITE, ALIGN_TOP_LEFT);
triangle_con.x -= triangle_con.height * 2;
triangle_con.y += triangle_con.height * 2;
set_rotation_constraint(&triangle_con, 180);
draw_triangle(&triangle_con, COLOR_WHITE, ALIGN_TOP_LEFT);
triangle_con.x -= triangle_con.height * 2;
triangle_con.y -= triangle_con.height * 2;
set_rotation_constraint(&triangle_con, 270);
draw_triangle(&triangle_con, COLOR_WHITE, ALIGN_TOP_LEFT);
UIConstraints button_con = default_constraints;
set_parent_constraint(&button_con, &popup_con);
set_x_constraint(&button_con, 0.04f, UI_CONSTRAINT_RELATIVE);
set_y_constraint(&button_con, -0.05f, UI_CONSTRAINT_RELATIVE);
set_width_constraint(&button_con, 0.43f, UI_CONSTRAINT_RELATIVE);
set_height_constraint(&button_con, 0.3f, UI_CONSTRAINT_ASPECT_RATIO);
if (draw_button(&button_con, *zephr_ctx->ui.popup_revert_color, "Revert", 4, ALIGN_BOTTOM_LEFT, BUTTON_STATE_ACTIVE)) {
zephr_ctx->ui.popup_open = false;
}
Color selected_color = hsv2rgb(slider_selection * 360.f, canvas_pos.x, 1.0f - canvas_pos.y);
set_x_constraint(&button_con, -0.04f, UI_CONSTRAINT_RELATIVE);
set_y_constraint(&button_con, -0.05f, UI_CONSTRAINT_RELATIVE);
if (draw_button(&button_con, selected_color, "Apply", 4, ALIGN_BOTTOM_RIGHT, BUTTON_STATE_ACTIVE)) {
*zephr_ctx->ui.popup_revert_color = selected_color;
zephr_ctx->ui.popup_open = false;
}
zephr_ctx->ui.popup_rect = (Rect){{popup_con.x, popup_con.y}, {popup_con.width, popup_con.height}};
}
void draw_color_picker(UIConstraints *constraints, Color *color, Alignment align, ButtonState state) {
Rect rect = {0};
Color display_color = *color;
UIConstraints con = *constraints;
apply_constraints(&con, &rect.pos, &rect.size);
apply_alignment(align, &con, &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 && state == BUTTON_STATE_ACTIVE) {
zephr_set_cursor(ZEPHR_CURSOR_HAND);
con.scale.height *= 1.08f;
con.scale.width *= 1.08f;
if (left_mouse_pressed) {
display_color = mult_color(display_color, 0.8f);
} else {
display_color = mult_color(display_color, 0.9f);
}
} else if (state == BUTTON_STATE_DISABLED) {
if (is_hovered) {
zephr_set_cursor(ZEPHR_CURSOR_DISABLED);
}
display_color.a = 100;
}
draw_quad(&con, display_color, con.width * 0.08f, align);
if (is_hovered && state == BUTTON_STATE_ACTIVE && zephr_ctx->mouse.released && zephr_ctx->mouse.button == ZEPHR_MOUSE_BUTTON_LEFT) {
zephr_ctx->ui.popup_open = true;
zephr_ctx->ui.popup_parent_constraints = con;
zephr_ctx->ui.popup_revert_color = color;
/* zephr_ctx->ui.popup_rect = (Rect){rect.pos, rect.size}; */
/* draw_color_picker_overlay(constraints); */
}
/* if (is_hovered && state == BUTTON_STATE_ACTIVE && zephr_ctx->mouse.released && zephr_ctx->mouse.button == ZEPHR_MOUSE_BUTTON_LEFT) { */
/* return true; */
/* } */
/* return false; */
}
/* enum Element { */
/* Rect, */
+18 -5
View File
@@ -3,11 +3,6 @@
#include "texture.h"
#include "zephr_math.h"
typedef struct Rect {
Vec2f pos;
Sizef size;
} Rect;
typedef enum Alignment {
ALIGN_TOP_LEFT,
ALIGN_TOP_CENTER,
@@ -33,9 +28,24 @@ typedef struct UIConstraints {
float width;
float height;
float rotation;
Sizef scale;
struct UIConstraints *parent;
} UIConstraints;
extern const UIConstraints default_constraints;
typedef struct Rect {
Vec2f pos;
Sizef size;
} Rect;
typedef struct UI {
bool popup_open;
Rect popup_rect;
UIConstraints popup_parent_constraints;
Color *popup_revert_color;
} UI;
typedef enum ButtonState {
BUTTON_STATE_ACTIVE,
BUTTON_STATE_INACTIVE,
@@ -51,8 +61,11 @@ void set_height_constraint(UIConstraints *constraints, float value, UIConstraint
void set_rotation_constraint(UIConstraints *constraints, float angle_d);
void apply_constraints(UIConstraints *constraints, Vec2f *pos, Sizef *size);
void apply_alignment(Alignment align, UIConstraints *constraints, Vec2f *pos, Sizef size);
bool inside_rect(Rect *rect, Vec2 *point);
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_triangle(UIConstraints *constraints, const Color color, Alignment align);
bool draw_button(UIConstraints *constraints, Color color, const char *text, f32 radius, Alignment align, ButtonState state);
bool draw_icon_button(UIConstraints *constraints, Color color, const TextureId icon_tex_id, f32 radius, Alignment align, ButtonState state);
void draw_color_picker_popup(UIConstraints *picker_button_con);
void draw_color_picker(UIConstraints *constraints, Color *color, Alignment align, ButtonState state);
+14 -2
View File
@@ -539,7 +539,7 @@ void x11_assign_window_icon(const char *icon_path) {
u32 target_size = 2 + icon_width * icon_height;
u64 *data = malloc(target_size * sizeof(u64));
u64 *data = alloca(target_size * sizeof(u64));
u64 *target = data;
// first two elements are width and height
@@ -554,7 +554,6 @@ void x11_assign_window_icon(const char *icon_path) {
XChangeProperty(x11_display, x11_window, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)data, target_size);
free(data);
stbi_image_free(icon_data);
}
@@ -809,6 +808,10 @@ bool zephr_should_quit(void) {
void zephr_swap_buffers(void) {
CORE_DEBUG_ASSERT(zephr_ctx, "Zephr context not initialized");
if (zephr_ctx->ui.popup_open) {
draw_color_picker_popup(&zephr_ctx->ui.popup_parent_constraints);
}
glXSwapBuffers(x11_display, x11_window);
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[zephr_ctx->cursor]);
}
@@ -1016,12 +1019,21 @@ bool zephr_iter_events(ZephrEvent *event_out) {
switch (xev.xbutton.button) {
case Button1:
event_out->mouse.button = ZEPHR_MOUSE_BUTTON_LEFT;
if (!inside_rect(&zephr_ctx->ui.popup_rect, &event_out->mouse.position)) {
zephr_ctx->ui.popup_open = false;
}
break;
case Button2:
event_out->mouse.button = ZEPHR_MOUSE_BUTTON_MIDDLE;
if (!inside_rect(&zephr_ctx->ui.popup_rect, &event_out->mouse.position)) {
zephr_ctx->ui.popup_open = false;
}
break;
case Button3:
event_out->mouse.button = ZEPHR_MOUSE_BUTTON_RIGHT;
if (!inside_rect(&zephr_ctx->ui.popup_rect, &event_out->mouse.position)) {
zephr_ctx->ui.popup_open = false;
}
break;
}
+2
View File
@@ -380,6 +380,8 @@ typedef struct ZephrContext {
ZephrMouse mouse;
ZephrCursor cursor;
ZephrCursor cursors[ZEPHR_CURSOR_COUNT];
UI ui;
/* ZephrKeyboard keyboard; */
/* XkbDescPtr xkb; */
/* XIM xim; */
+23
View File
@@ -84,3 +84,26 @@ Color mult_color(Color color, float amount) {
return result;
}
Color hsv2rgb(float h, float s, float v) {
float c = v * s;
float x = (float)(c * (1 - fabs(fmod(h / 60.0, 2) - 1)));
float m = v - c;
float r, g, b;
if (h >= 0 && h < 60) {
r = c, g = x, b = 0;
} else if (h >= 60 && h < 120) {
r = x, g = c, b = 0;
} else if (h >= 120 && h < 180) {
r = 0, g = c, b = x;
} else if (h >= 180 && h < 240) {
r = 0, g = x, b = c;
} else if (h >= 240 && h < 300) {
r = x, g = 0, b = c;
} else {
r = c, g = 0, b = x;
}
return (Color){(u8)((r + m) * 255), (u8)((g + m) * 255), (u8)((b + m) * 255), 255};
}
+1
View File
@@ -55,3 +55,4 @@ void apply_rotation(Matrix4x4 *model, float angle);
void apply_translation(Matrix4x4 *matrix, Vec2f pos);
Matrix4x4 orthographic_projection_2d(float left, float right, float bottom, float top);
Color mult_color(Color color, float amount);
Color hsv2rgb(float h, float s, float v);