summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortalha <sarcxd@gmail.com>2025-04-06 13:51:01 +0500
committertalha <sarcxd@gmail.com>2025-04-06 13:51:01 +0500
commitdef19703ae126fcc73f38abacc3cfd41a515302a (patch)
tree75a738503fa46d42f996a3f4f4e271aedcddb839
parent188ea2eb92bae770dcfbdef67984986cbaf2c9ea (diff)
Added dropdown button
-rwxr-xr-xsource/main.cpp330
-rw-r--r--source/renderer/renderer.cpp3
2 files changed, 235 insertions, 98 deletions
diff --git a/source/main.cpp b/source/main.cpp
index 2280e94..214ddff 100755
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -532,7 +532,7 @@ struct UiButton {
// @description: This is a very scrappy function that goes through the button render
// logic and pre-computes items like text dimensions
// It does not support, tabs and newlines
-Vec2 ui_button_get_text_dims(GLRenderer renderer, char *text, r32 font_size) {
+Vec2 ui_get_text_dims(GLRenderer renderer, char *text, r32 font_size) {
Vec2 max_dims = Vec2{0, 0};
u32 running_index = 0;
@@ -591,7 +591,7 @@ ButtonState ui_button(GameState state, UiButton button) {
if (!font_size) {
font_size = 0.6f * quad_size.y;
}
- Vec2 txt_dims = ui_button_get_text_dims(state.renderer,
+ Vec2 txt_dims = ui_get_text_dims(state.renderer,
button.text.buffer,
font_size);
r32 txt_base_offsety = -5.0f*state.render_scale.y;
@@ -650,6 +650,197 @@ ButtonState ui_button(GameState state, UiButton button) {
return btn_state;
}
+struct UiDropdownButton {
+ r32 font_size;
+ Vec3 position;
+ Vec2 size;
+ b8 is_toggled;
+ u32 selected_option_index;
+ u32 option_count;
+ Str256 *options;
+
+ Vec3 bgd_color_primary;
+ Vec3 bgd_color_secondary;
+ Vec3 bgd_color_hover;
+ Vec3 bgd_color_pressed;
+};
+
+Vec2 ui_center_text(
+ GameState state,
+ Str256 text,
+ r32 font_size,
+ Vec2 container_pos,
+ Vec2 container_size)
+{
+ // @step: ui position text
+ Vec2 text_dims = ui_get_text_dims(
+ state.renderer,
+ text.buffer,
+ font_size);
+
+ r32 txt_base_offsety = -5.0f*state.render_scale.y;
+ Vec2 txt_center_offset = Vec2{
+ (container_size.x - text_dims.x)/2.0f,
+ (container_size.y - text_dims.y)/2.0f + txt_base_offsety
+ };
+ Vec2 txt_pos = container_pos + txt_center_offset;
+
+ return txt_pos;
+}
+
+void ui_dropdown_button(GameState state, UiDropdownButton *dropdown) {
+ r32 font_size = dropdown->font_size * state.render_scale.y;
+
+ // @component: value_box
+ Vec3 value_pos = Vec3{
+ dropdown->position.x*state.render_scale.x,
+ dropdown->position.y*state.render_scale.y,
+ dropdown->position.z
+ };
+
+ Vec2 value_size = dropdown->size*state.render_scale;
+
+ Vec3 value_pos_adjusted = value_pos;
+ value_pos_adjusted.x += value_size.x/2.0f;
+ value_pos_adjusted.y += value_size.y/2.0f;
+
+ gl_draw_quad(
+ state.renderer.quad,
+ &state.renderer.ui_cam,
+ value_pos_adjusted,
+ value_size,
+ dropdown->bgd_color_primary
+ );
+
+ // @component: toggle_button
+ Vec3 toggle_pos = Vec3{
+ value_pos.x + value_size.x,
+ value_pos.y,
+ value_pos.z
+ };
+ Vec2 toggle_size = Vec2{40.0f*state.render_scale.x, value_size.y};
+ Vec3 toggle_pos_adjusted = toggle_pos;
+ toggle_pos_adjusted.x += toggle_size.x/2.0f;
+ toggle_pos_adjusted.y += toggle_size.y/2.0f;
+
+ // @step: check if mouse on button
+ b8 is_mouse_on_button = 0;
+ {
+ Rect btn_rect = rect(toggle_pos.v2(), toggle_size);
+ is_mouse_on_button = (
+ (state.mouse_position.x >= btn_rect.lb.x &&
+ state.mouse_position.y >= btn_rect.lb.y) &&
+ (state.mouse_position.x <= btn_rect.rt.x &&
+ state.mouse_position.y <= btn_rect.rt.y)
+ );
+ }
+ Vec3 toggle_color = dropdown->bgd_color_secondary;
+ if (is_mouse_on_button) {
+ if (state.mouse_down) {
+ toggle_color = dropdown->bgd_color_pressed;
+ } else if (state.mouse_up) {
+ dropdown->is_toggled = !dropdown->is_toggled;
+ } else {
+ toggle_color = dropdown->bgd_color_hover;
+ }
+ }
+
+ Str256 value_text = dropdown->options[dropdown->selected_option_index];
+ Vec2 value_text_pos = ui_center_text(
+ state,
+ value_text,
+ dropdown->font_size,
+ value_pos.v2(),
+ value_size);
+
+ gl_draw_quad(
+ state.renderer.quad,
+ &state.renderer.ui_cam,
+ toggle_pos_adjusted,
+ toggle_size,
+ toggle_color
+ );
+ gl_render_text(
+ &state.renderer,
+ value_text.buffer,
+ Vec3{
+ value_text_pos.x,
+ value_text_pos.y,
+ value_pos.z},
+ Vec3{0.0f, 0.0f, 0.0f},
+ dropdown->font_size);
+
+ // @component: dropdown_option
+ if (dropdown->is_toggled) {
+ Vec2 option_size = value_size;
+ for (int i = 0; i < dropdown->option_count; i++) {
+ Vec3 option_pos = Vec3{
+ value_pos.x,
+ value_pos.y - (option_size.y*(i+1)),
+ value_pos.z
+ };
+ Vec3 option_color = i%2 ?
+ Vec3{0.8f, 0.3f, 0.2f} :
+ Vec3{0.2f, 0.3f, 0.8f};
+
+ b8 is_mouse_on_option = 0;
+ {
+ Rect btn_rect = rect(option_pos.v2(), option_size);
+ is_mouse_on_option = (
+ (state.mouse_position.x >= btn_rect.lb.x &&
+ state.mouse_position.y >= btn_rect.lb.y) &&
+ (state.mouse_position.x <= btn_rect.rt.x &&
+ state.mouse_position.y <= btn_rect.rt.y));
+ }
+ b8 is_option_clicked = 0;
+ if (is_mouse_on_option) {
+ if (state.mouse_down) {
+ option_color = dropdown->bgd_color_pressed;
+ } else if (state.mouse_up) {
+ option_color = dropdown->bgd_color_pressed;
+ is_option_clicked = 1;
+ } else {
+ option_color = dropdown->bgd_color_hover;
+ }
+ }
+
+ if (is_option_clicked) {
+ dropdown->selected_option_index = i;
+ dropdown->is_toggled = 0;
+ }
+
+ Str256 dropdown_text = dropdown->options[i];
+ Vec2 txt_pos = ui_center_text(
+ state,
+ dropdown_text,
+ dropdown->font_size,
+ option_pos.v2(),
+ option_size);
+
+ gl_draw_quad(
+ state.renderer.quad,
+ &state.renderer.ui_cam,
+ Vec3{
+ option_pos.x + option_size.x/2.0f,
+ option_pos.y + option_size.y/2.0f,
+ option_pos.z},
+ option_size,
+ option_color
+ );
+
+ gl_render_text(
+ &state.renderer,
+ dropdown_text.buffer,
+ Vec3{
+ txt_pos.x,
+ txt_pos.y,
+ option_pos.z},
+ Vec3{0.0f, 0.0f, 0.0f},
+ dropdown->font_size);
+ }
+ }
+}
+
// @section: main
int main(int argc, char* argv[])
{
@@ -692,7 +883,7 @@ int main(int argc, char* argv[])
SDL_WINDOWPOS_UNDEFINED,
render_dims.x, render_dims.y,
SDL_WINDOW_OPENGL
- | SDL_WINDOW_FULLSCREEN_DESKTOP
+// | SDL_WINDOW_FULLSCREEN_DESKTOP
);
SDL_GLContext context = SDL_GL_CreateContext(window);
@@ -807,6 +998,27 @@ int main(int argc, char* argv[])
renderer->ui_cam.view = renderer->cam_view;
renderer->ui_cam.proj = renderer->cam_proj;
+ // ui stuff
+
+ UiDropdownButton resolution_select = {0};
+ resolution_select.font_size = 24.0f;
+ resolution_select.size = Vec2{120.0f, 40.0f};
+ resolution_select.bgd_color_primary = Vec3{1.0f, 1.0f, 1.0f};
+ resolution_select.bgd_color_secondary = Vec3{0.6f, 0.6f, 0.6f};
+ resolution_select.bgd_color_hover = Vec3{0.8f, 0.8f, 0.8f};
+ resolution_select.bgd_color_pressed = Vec3{0.4f, 0.4f, 0.4f};
+ resolution_select.option_count = 3;
+ // @todo: Remove this memory allocation method
+ // Use a lifetime tied arena
+ resolution_select.options = (Str256 *)malloc(
+ resolution_select.option_count *
+ sizeof(Str256)
+ );
+ resolution_select.selected_option_index = 1;
+ resolution_select.options[0] = str256("2560 x 1440");
+ resolution_select.options[1] = str256("1920 x 1080");
+ resolution_select.options[2] = str256("1280 x 720");
+
// @thinking: level object handling
// there should be a most smallest supported unit
// smallest_size: 16x16
@@ -959,6 +1171,7 @@ int main(int argc, char* argv[])
game_screen = PAUSE_MENU;
} else if (game_screen == SETTINGS_MENU) {
game_screen = PAUSE_MENU;
+ // clean_up_settings_menu
} else if (game_screen == PAUSE_MENU) {
game_screen = GAMEPLAY;
}
@@ -1686,105 +1899,28 @@ int main(int argc, char* argv[])
// settings menu
if (game_screen == SETTINGS_MENU) {
- UiButton back_button = button;
-
- back_button.text = str256("Apply");
- back_button.position = Vec3{30.0f, 40.0f, entity_z[TEXT]};
+ // resolution button
+ //
+ // @api:
+ // draw_ms_button(state)
+ // draw_ms_options(options)
+ //
+ // VS
+ //
+ // draw_ms_button(state, options)
+ u32 ms_font_size = 24.0f * state.render_scale.y;
gl_render_text(
renderer, "Resolution",
Vec3{800, 800, entity_z[TEXT]},
- Vec3{0.0f, 0.0f, 0.0f}, 24.0f*state.render_scale.y
+ Vec3{0.0f, 0.0f, 0.0f}, ms_font_size
);
- {
- // @params
- Vec3 ms_value_pos = Vec3{1000.0f, 800.0f, entity_z[TEXT]};
- Vec2 ms_value_size = Vec2{120.0f, 40.0f};
-
- Vec3 ms_value_pos_adjusted = ms_value_pos;
- ms_value_pos_adjusted.x += ms_value_size.x/2.0f;
- ms_value_pos_adjusted.y += ms_value_size.y/2.0f;
-
- // draw multi select value box
- gl_draw_quad(
- state.renderer.quad,
- &state.renderer.ui_cam,
- ms_value_pos_adjusted,
- ms_value_size,
- Vec3{1.0f, 1.0f, 1.0f}
- );
- static bool is_toggle_open = false;
- {
- Vec3 ms_toggle_pos = Vec3{
- ms_value_pos.x + ms_value_size.x,
- ms_value_pos.y,
- ms_value_pos.z
- };
- Vec2 ms_toggle_size = Vec2{40.0f, ms_value_size.y};
- Vec3 ms_toggle_pos_adjusted = ms_toggle_pos;
- ms_toggle_pos_adjusted.x += ms_toggle_size.x/2.0f;
- ms_toggle_pos_adjusted.y += ms_toggle_size.y/2.0f;
-
- b8 is_mouse_on_button = 0;
- {
- // check_if_mouse_on_button
- Rect btn_rect = rect(ms_toggle_pos.v2(), ms_toggle_size);
- is_mouse_on_button = (
- (state.mouse_position.x >= btn_rect.lb.x &&
- state.mouse_position.y >= btn_rect.lb.y) &&
- (state.mouse_position.x <= btn_rect.rt.x &&
- state.mouse_position.y <= btn_rect.rt.y)
- );
- }
- Vec3 ms_toggle_color = {0.8f, 0.8f, 0.8f};
- if (is_mouse_on_button) {
- if (state.mouse_down) {
- // pressed
- //btn_state = ButtonState::PRESSED;
- ms_toggle_color = {0.8f, 0.8f, 0.8f};
- } else if (state.mouse_up) {
- //btn_state = ButtonState::CLICK;
- is_toggle_open = !is_toggle_open;
- } else {
- // hover
- //btn_state = ButtonState::HOVER;
- ms_toggle_color = {0.6f, 0.6f, 0.6f};
- }
- }
- gl_draw_quad(
- state.renderer.quad,
- &state.renderer.ui_cam,
- ms_toggle_pos_adjusted,
- ms_toggle_size,
- ms_toggle_color
- );
- if (is_toggle_open) {
- {
- // draw toggle option
- Vec2 ms_option_size = Vec2{ms_value_size.x + ms_toggle_size.x, ms_value_size.y};
- Vec3 ms_option_pos = Vec3{ms_value_pos.x, ms_value_pos.y - ms_option_size.y, ms_value_pos.z};
-
- gl_draw_quad(
- state.renderer.quad,
- &state.renderer.ui_cam,
- Vec3{ms_option_pos.x + ms_option_size.x/2.0f,
- ms_option_pos.y + ms_option_size.y/2.0f,
- ms_option_pos.z},
- ms_option_size,
- Vec3{1.0f, 0.0f, 0.0f}
- );
- }
- }
- }
- // multi-select drop down
- Str256 dropdown_options[] = {
- str256("2560x1440"),
- str256("1920x1080"),
- str256("1280x720")
- };
-
-
- }
+ resolution_select.position = Vec3{
+ 1000.0f,
+ 800.0f,
+ entity_z[TEXT]
+ };
+ ui_dropdown_button(state, &resolution_select);
}
}
diff --git a/source/renderer/renderer.cpp b/source/renderer/renderer.cpp
index d61d85a..eabf57f 100644
--- a/source/renderer/renderer.cpp
+++ b/source/renderer/renderer.cpp
@@ -524,7 +524,8 @@ void gl_render_text(
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(renderer->ui_text.sp);
- if (renderer->ui_cam.update) {
+ if (renderer->ui_cam.update)
+ {
glUniformMatrix4fv(
glGetUniformLocation(