mirror of
https://github.com/IllusionMan1212/C2048.git
synced 2026-10-24 02:12:31 +00:00
WIP: settings, color picker and stuff
This commit is contained in:
@@ -64,29 +64,29 @@ void print_new_board() {
|
|||||||
Color get_tile_color(u16 value) {
|
Color get_tile_color(u16 value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case 2:
|
case 2:
|
||||||
return ColorRGBA(238, 228, 218, 255);
|
return game.palette.tile_colors[0];
|
||||||
case 4:
|
case 4:
|
||||||
return ColorRGBA(237, 224, 200, 255);
|
return game.palette.tile_colors[1];
|
||||||
case 8:
|
case 8:
|
||||||
return ColorRGBA(242, 177, 121, 255);
|
return game.palette.tile_colors[2];
|
||||||
case 16:
|
case 16:
|
||||||
return ColorRGBA(245, 149, 99, 255);
|
return game.palette.tile_colors[3];
|
||||||
case 32:
|
case 32:
|
||||||
return ColorRGBA(246, 124, 95, 255);
|
return game.palette.tile_colors[4];
|
||||||
case 64:
|
case 64:
|
||||||
return ColorRGBA(246, 94, 59, 255);
|
return game.palette.tile_colors[5];
|
||||||
case 128:
|
case 128:
|
||||||
return ColorRGBA(237, 207, 114, 255);
|
return game.palette.tile_colors[6];
|
||||||
case 256:
|
case 256:
|
||||||
return ColorRGBA(237, 204, 97, 255);
|
return game.palette.tile_colors[7];
|
||||||
case 512:
|
case 512:
|
||||||
return ColorRGBA(237, 200, 80, 255);
|
return game.palette.tile_colors[8];
|
||||||
case 1024:
|
case 1024:
|
||||||
return ColorRGBA(237, 197, 63, 255);
|
return game.palette.tile_colors[9];
|
||||||
case 2048:
|
case 2048:
|
||||||
return ColorRGBA(237, 194, 46, 255);
|
return game.palette.tile_colors[10];
|
||||||
default:
|
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.spawning_new_tile = false;
|
||||||
game.quit_dialog = false;
|
game.quit_dialog = false;
|
||||||
game.help_dialog = false;
|
game.help_dialog = false;
|
||||||
|
game.settings_dialog = false;
|
||||||
game.has_lost = false;
|
game.has_lost = false;
|
||||||
game.game_over_bg_opacity = 0;
|
game.game_over_bg_opacity = 0;
|
||||||
game.game_over_opacity = 0;
|
game.game_over_opacity = 0;
|
||||||
@@ -421,9 +422,29 @@ void reset_game(void) {
|
|||||||
|
|
||||||
void game_attempt_quit(void) {
|
void game_attempt_quit(void) {
|
||||||
game.help_dialog = false;
|
game.help_dialog = false;
|
||||||
|
game.settings_dialog = false;
|
||||||
game.quit_dialog = true;
|
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) {
|
void game_init(void) {
|
||||||
srand(time(NULL));
|
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[SETTINGS_ICON] = load_texture("assets/icons/settings.png");
|
||||||
game.icon_textures[CLOSE_ICON] = load_texture("assets/icons/close.png");
|
game.icon_textures[CLOSE_ICON] = load_texture("assets/icons/close.png");
|
||||||
|
|
||||||
|
reset_palette();
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
spawn_random_tile();
|
spawn_random_tile();
|
||||||
}
|
}
|
||||||
@@ -447,37 +470,39 @@ void game_init(void) {
|
|||||||
|
|
||||||
void draw_bg(void) {
|
void draw_bg(void) {
|
||||||
Size window_size = zephr_get_window_size();
|
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_width_constraint(&board_con, window_size.width, UI_CONSTRAINT_FIXED);
|
||||||
set_height_constraint(&board_con, window_size.height, UI_CONSTRAINT_FIXED);
|
set_height_constraint(&board_con, window_size.height, UI_CONSTRAINT_FIXED);
|
||||||
|
|
||||||
// bg
|
// 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
|
// 2048 text
|
||||||
UIConstraints text_con = {0};
|
UIConstraints text_con = default_constraints;
|
||||||
|
|
||||||
set_y_constraint(&text_con, 0.05f, UI_CONSTRAINT_RELATIVE);
|
set_y_constraint(&text_con, 0.05f, UI_CONSTRAINT_RELATIVE);
|
||||||
set_width_constraint(&text_con, 1.5, UI_CONSTRAINT_RELATIVE_PIXELS);
|
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
|
// score
|
||||||
char score[16];
|
char score[24];
|
||||||
sprintf(score, "%d", game.score);
|
sprintf(score, "Score %d", game.score);
|
||||||
|
|
||||||
set_parent_constraint(&text_con, NULL);
|
set_parent_constraint(&text_con, NULL);
|
||||||
set_x_constraint(&text_con, 0.05f, UI_CONSTRAINT_RELATIVE);
|
set_x_constraint(&text_con, 0.05f, UI_CONSTRAINT_RELATIVE);
|
||||||
set_y_constraint(&text_con, 0.8f, 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_batch(&batch);
|
||||||
draw_text(score, 40, text_con, COLOR_BLACK, ALIGN_TOP_LEFT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_quit_dialog(void) {
|
void draw_quit_dialog(void) {
|
||||||
UIConstraints dialog_con = {0};
|
UIConstraints dialog_con = default_constraints;
|
||||||
set_x_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED);
|
set_x_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED);
|
||||||
set_y_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);
|
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);
|
set_height_constraint(&dialog_con, 0.2f, UI_CONSTRAINT_RELATIVE);
|
||||||
draw_quad(&dialog_con, ColorRGBA(135, 124, 124, 255), 8, ALIGN_CENTER);
|
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_parent_constraint(&text_con, &dialog_con);
|
||||||
set_x_constraint(&text_con, 0, UI_CONSTRAINT_FIXED);
|
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);
|
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);
|
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_parent_constraint(&btn_con, &dialog_con);
|
||||||
set_width_constraint(&btn_con, 0.12f, UI_CONSTRAINT_RELATIVE);
|
set_width_constraint(&btn_con, 0.25f, UI_CONSTRAINT_RELATIVE);
|
||||||
set_height_constraint(&btn_con, 0.05f, UI_CONSTRAINT_RELATIVE);
|
set_height_constraint(&btn_con, 0.25f, UI_CONSTRAINT_RELATIVE);
|
||||||
set_y_constraint(&btn_con, -0.02f, UI_CONSTRAINT_RELATIVE);
|
set_y_constraint(&btn_con, -0.10f, UI_CONSTRAINT_RELATIVE);
|
||||||
set_x_constraint(&btn_con, -0.07f, 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)) {
|
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();
|
zephr_quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
set_y_constraint(&btn_con, -0.02f, UI_CONSTRAINT_RELATIVE);
|
set_y_constraint(&btn_con, -0.10f, UI_CONSTRAINT_RELATIVE);
|
||||||
set_x_constraint(&btn_con, 0.07f, 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)) {
|
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;
|
game.quit_dialog = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_help_dialog(void) {
|
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_width_constraint(&dialog_con, 1.f, UI_CONSTRAINT_RELATIVE);
|
||||||
set_height_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_x_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED);
|
||||||
set_y_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);
|
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_parent_constraint(&content_card_con, &dialog_con);
|
||||||
set_width_constraint(&content_card_con, 0.4f, UI_CONSTRAINT_RELATIVE);
|
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);
|
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_parent_constraint(&text_con, &content_card_con);
|
||||||
set_width_constraint(&text_con, 1, UI_CONSTRAINT_RELATIVE_PIXELS);
|
set_width_constraint(&text_con, 1, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
set_x_constraint(&text_con, 0, UI_CONSTRAINT_FIXED);
|
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"
|
"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);
|
"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_parent_constraint(&btn_con, &content_card_con);
|
||||||
set_width_constraint(&btn_con, 56, UI_CONSTRAINT_RELATIVE_PIXELS);
|
set_width_constraint(&btn_con, 56, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
set_height_constraint(&btn_con, 1, UI_CONSTRAINT_ASPECT_RATIO);
|
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) {
|
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_width_constraint(&dialog_con, 1.f, UI_CONSTRAINT_RELATIVE);
|
||||||
set_height_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_x_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED);
|
||||||
set_y_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);
|
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_parent_constraint(&content_card_con, &dialog_con);
|
||||||
set_width_constraint(&content_card_con, 0.3f, UI_CONSTRAINT_RELATIVE);
|
set_width_constraint(&content_card_con, 0.3f, UI_CONSTRAINT_RELATIVE);
|
||||||
set_height_constraint(&content_card_con, 0.2f, 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);
|
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_parent_constraint(&text_con, &content_card_con);
|
||||||
set_width_constraint(&text_con, 1, UI_CONSTRAINT_RELATIVE_PIXELS);
|
set_width_constraint(&text_con, 1, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
set_x_constraint(&text_con, 0, UI_CONSTRAINT_FIXED);
|
set_x_constraint(&text_con, 0, UI_CONSTRAINT_FIXED);
|
||||||
set_y_constraint(&text_con, 40, UI_CONSTRAINT_RELATIVE_PIXELS);
|
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);
|
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;
|
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_parent_constraint(&btn_con, &content_card_con);
|
||||||
set_x_constraint(&btn_con, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
|
set_x_constraint(&btn_con, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
set_y_constraint(&btn_con, -24, 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);
|
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)) {
|
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();
|
reset_game();
|
||||||
@@ -584,14 +700,14 @@ void draw_game_over(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void draw_ui(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_INACTIVE
|
||||||
: BUTTON_STATE_ACTIVE;
|
: BUTTON_STATE_ACTIVE;
|
||||||
const int icon_btn_width = 80;
|
const int icon_btn_width = 80;
|
||||||
const int icon_btn_offset = 8;
|
const int icon_btn_offset = 8;
|
||||||
const int icon_btns_padding = 10;
|
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_x_constraint(&btn_con, -icon_btn_offset, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
set_y_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);
|
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);
|
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)) {
|
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);
|
set_x_constraint(&btn_con, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
|
||||||
@@ -614,6 +730,10 @@ void draw_ui(void) {
|
|||||||
reset_game();
|
reset_game();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (game.settings_dialog) {
|
||||||
|
draw_settings_dialog();
|
||||||
|
}
|
||||||
|
|
||||||
if (game.help_dialog) {
|
if (game.help_dialog) {
|
||||||
draw_help_dialog();
|
draw_help_dialog();
|
||||||
}
|
}
|
||||||
@@ -629,19 +749,19 @@ void draw_ui(void) {
|
|||||||
|
|
||||||
void draw_board(void) {
|
void draw_board(void) {
|
||||||
// board
|
// board
|
||||||
UIConstraints board_con = {0};
|
UIConstraints board_con = default_constraints;
|
||||||
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);
|
||||||
const float board_border_radius = board_con.width * 0.02f;
|
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
|
// empty tiles
|
||||||
const float tile_padding = board_con.width * 0.02f;
|
const float tile_padding = board_con.width * 0.02f;
|
||||||
const float tile_height = board_con.height * 0.225f;
|
const float tile_height = board_con.height * 0.225f;
|
||||||
const float tile_board_radius = tile_height * 0.15f;
|
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_parent_constraint(&empty_tile_con, &board_con);
|
||||||
set_height_constraint(&empty_tile_con, tile_height, UI_CONSTRAINT_FIXED);
|
set_height_constraint(&empty_tile_con, tile_height, UI_CONSTRAINT_FIXED);
|
||||||
set_width_constraint(&empty_tile_con, 1, UI_CONSTRAINT_ASPECT_RATIO);
|
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);
|
set_y_constraint(&empty_tile_con, (tile_height + tile_padding) * i + tile_padding, UI_CONSTRAINT_FIXED);
|
||||||
for (int j = 0; j < 4; j++) {
|
for (int j = 0; j < 4; j++) {
|
||||||
set_x_constraint(&empty_tile_con, (tile_height + tile_padding) * j + tile_padding, UI_CONSTRAINT_FIXED);
|
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
|
// filled tiles
|
||||||
UIConstraints text_con = {0};
|
UIConstraints text_con = default_constraints;
|
||||||
set_width_constraint(&text_con, 1.5, UI_CONSTRAINT_RELATIVE_PIXELS);
|
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_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);
|
||||||
set_width_constraint(&tile_con, 1, UI_CONSTRAINT_ASPECT_RATIO);
|
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) {
|
} else if (e.key.code == ZEPHR_KEYCODE_ESCAPE) {
|
||||||
game.quit_dialog = false;
|
game.quit_dialog = false;
|
||||||
game.help_dialog = false;
|
game.help_dialog = false;
|
||||||
|
game.settings_dialog = false;
|
||||||
} else if (e.key.code == ZEPHR_KEYCODE_F11) {
|
} else if (e.key.code == ZEPHR_KEYCODE_F11) {
|
||||||
zephr_toggle_fullscreen();
|
zephr_toggle_fullscreen();
|
||||||
} else if (e.key.code == ZEPHR_KEYCODE_UP) {
|
} else if (e.key.code == ZEPHR_KEYCODE_UP) {
|
||||||
|
|||||||
@@ -18,6 +18,12 @@ typedef enum IconTexture {
|
|||||||
ICON_TEXTURE_COUNT,
|
ICON_TEXTURE_COUNT,
|
||||||
} IconTexture;
|
} IconTexture;
|
||||||
|
|
||||||
|
typedef struct ColorPalette {
|
||||||
|
Color bg_color;
|
||||||
|
Color board_bg_color;
|
||||||
|
Color tile_colors[11];
|
||||||
|
} ColorPalette;
|
||||||
|
|
||||||
typedef struct Tile {
|
typedef struct Tile {
|
||||||
u16 value;
|
u16 value;
|
||||||
u16 new_value;
|
u16 new_value;
|
||||||
@@ -41,9 +47,12 @@ typedef struct Game {
|
|||||||
Vec2 spawning_tile_coords;
|
Vec2 spawning_tile_coords;
|
||||||
u16 spawning_tile_value;
|
u16 spawning_tile_value;
|
||||||
|
|
||||||
TextureId icon_textures[ICON_TEXTURE_COUNT];
|
|
||||||
bool quit_dialog;
|
bool quit_dialog;
|
||||||
bool help_dialog;
|
bool help_dialog;
|
||||||
|
bool settings_dialog;
|
||||||
|
|
||||||
|
TextureId icon_textures[ICON_TEXTURE_COUNT];
|
||||||
|
ColorPalette palette;
|
||||||
} Game;
|
} Game;
|
||||||
|
|
||||||
void draw_board(void);
|
void draw_board(void);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
#include "text.h"
|
#include "text.h"
|
||||||
#include "zephr.h"
|
#include "zephr.h"
|
||||||
|
|
||||||
#define FONT_PIXEL_SIZE 128
|
#define FONT_PIXEL_SIZE 100
|
||||||
#define LINE_HEIGHT 2.0f
|
#define LINE_HEIGHT 2.0f
|
||||||
|
|
||||||
Shader font_shader;
|
Shader font_shader;
|
||||||
@@ -100,7 +100,7 @@ int init_freetype(const char* font_path) {
|
|||||||
tex_height = CORE_MAX(tex_height, face->glyph->bitmap.rows);
|
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++) {
|
for (u32 i = 32; i < 128; i++) {
|
||||||
/* while (glyph_idx) { */
|
/* while (glyph_idx) { */
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <glad/glx.h>
|
#include <glad/glx.h>
|
||||||
@@ -7,9 +8,14 @@
|
|||||||
#include "zephr.h"
|
#include "zephr.h"
|
||||||
|
|
||||||
Shader ui_shader;
|
Shader ui_shader;
|
||||||
|
Shader color_chooser_shader;
|
||||||
unsigned int ui_vao;
|
unsigned int ui_vao;
|
||||||
unsigned int ui_vbo;
|
unsigned int ui_vbo;
|
||||||
|
|
||||||
|
const UIConstraints default_constraints = {
|
||||||
|
.scale = {.height = 1, .width = 1},
|
||||||
|
};
|
||||||
|
|
||||||
int init_ui(const char* font_path) {
|
int init_ui(const char* font_path) {
|
||||||
int res = init_fonts(font_path);
|
int res = init_fonts(font_path);
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
@@ -21,6 +27,7 @@ int init_ui(const char* font_path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ui_shader = create_shader("shaders/ui.vert", "shaders/ui.frag");
|
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);
|
glGenVertexArrays(1, &ui_vao);
|
||||||
glGenBuffers(1, &ui_vbo);
|
glGenBuffers(1, &ui_vbo);
|
||||||
@@ -49,7 +56,11 @@ void set_x_constraint(UIConstraints *constraints, float value, UIConstraint type
|
|||||||
constraints->x = value;
|
constraints->x = value;
|
||||||
break;
|
break;
|
||||||
case UI_CONSTRAINT_RELATIVE:
|
case UI_CONSTRAINT_RELATIVE:
|
||||||
|
if (constraints->parent) {
|
||||||
|
constraints->x = (value * constraints->parent->width);
|
||||||
|
} else {
|
||||||
constraints->x = (value * zephr_ctx->window.size.width);
|
constraints->x = (value * zephr_ctx->window.size.width);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case UI_CONSTRAINT_RELATIVE_PIXELS:
|
case UI_CONSTRAINT_RELATIVE_PIXELS:
|
||||||
constraints->x = zephr_ctx->window.size.width / (float)zephr_ctx->screen_size.width * value;
|
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;
|
constraints->y = value;
|
||||||
break;
|
break;
|
||||||
case UI_CONSTRAINT_RELATIVE:
|
case UI_CONSTRAINT_RELATIVE:
|
||||||
|
if (constraints->parent) {
|
||||||
|
constraints->y = (value * constraints->parent->height);
|
||||||
|
} else {
|
||||||
constraints->y = (value * zephr_ctx->window.size.height);
|
constraints->y = (value * zephr_ctx->window.size.height);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case UI_CONSTRAINT_RELATIVE_PIXELS:
|
case UI_CONSTRAINT_RELATIVE_PIXELS:
|
||||||
constraints->y = zephr_ctx->window.size.height / (float)zephr_ctx->screen_size.height * value;
|
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;
|
constraints->width = value;
|
||||||
break;
|
break;
|
||||||
case UI_CONSTRAINT_RELATIVE:
|
case UI_CONSTRAINT_RELATIVE:
|
||||||
|
if (constraints->parent) {
|
||||||
|
constraints->width = (value * constraints->parent->width);
|
||||||
|
} else {
|
||||||
constraints->width = (value * zephr_ctx->window.size.width);
|
constraints->width = (value * zephr_ctx->window.size.width);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case UI_CONSTRAINT_RELATIVE_PIXELS:
|
case UI_CONSTRAINT_RELATIVE_PIXELS:
|
||||||
constraints->width = zephr_ctx->window.size.width / (float)zephr_ctx->screen_size.width * value;
|
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;
|
constraints->height = value;
|
||||||
break;
|
break;
|
||||||
case UI_CONSTRAINT_RELATIVE:
|
case UI_CONSTRAINT_RELATIVE:
|
||||||
|
if (constraints->parent) {
|
||||||
|
constraints->height = (value * constraints->parent->height);
|
||||||
|
} else {
|
||||||
constraints->height = (value * zephr_ctx->window.size.height);
|
constraints->height = (value * zephr_ctx->window.size.height);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case UI_CONSTRAINT_RELATIVE_PIXELS:
|
case UI_CONSTRAINT_RELATIVE_PIXELS:
|
||||||
constraints->height = zephr_ctx->window.size.height / (float)zephr_ctx->screen_size.height * value;
|
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) {
|
bool inside_rect(Rect *rect, Vec2 *point) {
|
||||||
if (point->x >= rect->pos.x && point->x <= rect->pos.x + rect->size.width &&
|
/* bool outside_popup = true; */
|
||||||
point->y >= rect->pos.y && point->y <= rect->pos.y + rect->size.height) {
|
/* 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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -204,6 +234,10 @@ void draw_quad(UIConstraints *constraints, const Color color, float border_radiu
|
|||||||
constraints->y = pos.y;
|
constraints->y = pos.y;
|
||||||
|
|
||||||
Matrix4x4 model = identity();
|
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_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));
|
||||||
apply_translation(&model, (Vec2f){size.width / 2.f, size.height / 2.f});
|
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);
|
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_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);
|
set_mat4f(ui_shader, "projection", (float *)zephr_ctx->projection.m);
|
||||||
|
|
||||||
Vec2f pos = { 0.f, 0.f };
|
Vec2f pos = { 0.f, 0.f };
|
||||||
@@ -263,6 +298,10 @@ void draw_triangle(UIConstraints *constraints, const Color color, Alignment alig
|
|||||||
constraints->y = pos.y;
|
constraints->y = pos.y;
|
||||||
|
|
||||||
Matrix4x4 model = identity();
|
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_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));
|
||||||
apply_translation(&model, (Vec2f){size.width / 2.f, size.height / 2.f});
|
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;
|
constraints->y = pos.y;
|
||||||
|
|
||||||
Matrix4x4 model = identity();
|
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_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));
|
||||||
apply_translation(&model, (Vec2f){size.width / 2.f, size.height / 2.f});
|
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) {
|
if (text) {
|
||||||
UIConstraints text_constraints = {0};
|
UIConstraints text_constraints = default_constraints;
|
||||||
|
|
||||||
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);
|
||||||
@@ -434,7 +477,7 @@ bool draw_icon_button(UIConstraints *constraints, Color btn_color, const Texture
|
|||||||
|
|
||||||
draw_quad(constraints, btn_color, radius, align);
|
draw_quad(constraints, btn_color, radius, align);
|
||||||
|
|
||||||
UIConstraints icon_constraints = {0};
|
UIConstraints icon_constraints = default_constraints;
|
||||||
|
|
||||||
set_parent_constraint(&icon_constraints, constraints);
|
set_parent_constraint(&icon_constraints, constraints);
|
||||||
set_x_constraint(&icon_constraints, 0, UI_CONSTRAINT_RELATIVE_PIXELS);
|
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;
|
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 { */
|
/* enum Element { */
|
||||||
/* Rect, */
|
/* Rect, */
|
||||||
|
|||||||
@@ -3,11 +3,6 @@
|
|||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
#include "zephr_math.h"
|
#include "zephr_math.h"
|
||||||
|
|
||||||
typedef struct Rect {
|
|
||||||
Vec2f pos;
|
|
||||||
Sizef size;
|
|
||||||
} Rect;
|
|
||||||
|
|
||||||
typedef enum Alignment {
|
typedef enum Alignment {
|
||||||
ALIGN_TOP_LEFT,
|
ALIGN_TOP_LEFT,
|
||||||
ALIGN_TOP_CENTER,
|
ALIGN_TOP_CENTER,
|
||||||
@@ -33,9 +28,24 @@ typedef struct UIConstraints {
|
|||||||
float width;
|
float width;
|
||||||
float height;
|
float height;
|
||||||
float rotation;
|
float rotation;
|
||||||
|
Sizef scale;
|
||||||
struct UIConstraints *parent;
|
struct UIConstraints *parent;
|
||||||
} UIConstraints;
|
} 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 {
|
typedef enum ButtonState {
|
||||||
BUTTON_STATE_ACTIVE,
|
BUTTON_STATE_ACTIVE,
|
||||||
BUTTON_STATE_INACTIVE,
|
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 set_rotation_constraint(UIConstraints *constraints, float angle_d);
|
||||||
void apply_constraints(UIConstraints *constraints, Vec2f *pos, Sizef *size);
|
void apply_constraints(UIConstraints *constraints, Vec2f *pos, Sizef *size);
|
||||||
void apply_alignment(Alignment align, 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_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, Color color, const char *text, f32 radius, Alignment align, ButtonState state);
|
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);
|
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);
|
||||||
|
|||||||
@@ -539,7 +539,7 @@ void x11_assign_window_icon(const char *icon_path) {
|
|||||||
|
|
||||||
u32 target_size = 2 + icon_width * icon_height;
|
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;
|
u64 *target = data;
|
||||||
|
|
||||||
// first two elements are width and height
|
// 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);
|
XChangeProperty(x11_display, x11_window, net_wm_icon, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)data, target_size);
|
||||||
|
|
||||||
free(data);
|
|
||||||
stbi_image_free(icon_data);
|
stbi_image_free(icon_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,6 +808,10 @@ 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");
|
||||||
|
|
||||||
|
if (zephr_ctx->ui.popup_open) {
|
||||||
|
draw_color_picker_popup(&zephr_ctx->ui.popup_parent_constraints);
|
||||||
|
}
|
||||||
|
|
||||||
glXSwapBuffers(x11_display, x11_window);
|
glXSwapBuffers(x11_display, x11_window);
|
||||||
XDefineCursor(x11_display, x11_window, zephr_ctx->cursors[zephr_ctx->cursor]);
|
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) {
|
switch (xev.xbutton.button) {
|
||||||
case Button1:
|
case Button1:
|
||||||
event_out->mouse.button = ZEPHR_MOUSE_BUTTON_LEFT;
|
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;
|
break;
|
||||||
case Button2:
|
case Button2:
|
||||||
event_out->mouse.button = ZEPHR_MOUSE_BUTTON_MIDDLE;
|
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;
|
break;
|
||||||
case Button3:
|
case Button3:
|
||||||
event_out->mouse.button = ZEPHR_MOUSE_BUTTON_RIGHT;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -380,6 +380,8 @@ typedef struct ZephrContext {
|
|||||||
ZephrMouse mouse;
|
ZephrMouse mouse;
|
||||||
ZephrCursor cursor;
|
ZephrCursor cursor;
|
||||||
ZephrCursor cursors[ZEPHR_CURSOR_COUNT];
|
ZephrCursor cursors[ZEPHR_CURSOR_COUNT];
|
||||||
|
UI ui;
|
||||||
|
|
||||||
/* ZephrKeyboard keyboard; */
|
/* ZephrKeyboard keyboard; */
|
||||||
/* XkbDescPtr xkb; */
|
/* XkbDescPtr xkb; */
|
||||||
/* XIM xim; */
|
/* XIM xim; */
|
||||||
|
|||||||
@@ -84,3 +84,26 @@ Color mult_color(Color color, float amount) {
|
|||||||
return result;
|
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};
|
||||||
|
}
|
||||||
|
|||||||
@@ -55,3 +55,4 @@ void apply_rotation(Matrix4x4 *model, float angle);
|
|||||||
void apply_translation(Matrix4x4 *matrix, Vec2f pos);
|
void apply_translation(Matrix4x4 *matrix, Vec2f pos);
|
||||||
Matrix4x4 orthographic_projection_2d(float left, float right, float bottom, float top);
|
Matrix4x4 orthographic_projection_2d(float left, float right, float bottom, float top);
|
||||||
Color mult_color(Color color, float amount);
|
Color mult_color(Color color, float amount);
|
||||||
|
Color hsv2rgb(float h, float s, float v);
|
||||||
|
|||||||
Reference in New Issue
Block a user