scroll bars
This commit is contained in:
parent
c9709a7eac
commit
0e7a1b5536
Binary file not shown.
|
@ -152,6 +152,8 @@ ed_frame_prepare(App_State* state)
|
||||||
ui_frame_prepare(&state->editor->ui, state->editor->window_dim);
|
ui_frame_prepare(&state->editor->ui, state->editor->window_dim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
global r32 p = 0.3f;
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
ed_frame(App_State* state)
|
ed_frame(App_State* state)
|
||||||
{
|
{
|
||||||
|
@ -160,14 +162,11 @@ ed_frame(App_State* state)
|
||||||
UI_Layout layout = {};
|
UI_Layout layout = {};
|
||||||
layout.bounds_min = v2{ 500, 200 };
|
layout.bounds_min = v2{ 500, 200 };
|
||||||
layout.bounds_max = v2{ 700, 500 };
|
layout.bounds_max = v2{ 700, 500 };
|
||||||
layout.row_height = ui->font_ascent + ui->font_descent + ui->font_line_gap + 15;
|
ui_layout_set_row_info(ui, &layout);
|
||||||
layout.row_gap = 2;
|
|
||||||
layout.col_gap = 2;
|
|
||||||
layout.at = layout.bounds_min;
|
layout.at = layout.bounds_min;
|
||||||
ui->layout = &layout;
|
ui_layout_push(ui, &layout);
|
||||||
|
|
||||||
|
ui_text_f(ui, "Hi there! %d", 1000);
|
||||||
ui_text(ui, lit_str("Hi there!"));
|
|
||||||
show = ui_toggle(ui, lit_str("my toggle"), show);
|
show = ui_toggle(ui, lit_str("my toggle"), show);
|
||||||
if (show)
|
if (show)
|
||||||
{
|
{
|
||||||
|
@ -178,9 +177,34 @@ ed_frame(App_State* state)
|
||||||
}
|
}
|
||||||
ui_layout_row_end(ui);
|
ui_layout_row_end(ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_button(ui, lit_str("Hi there my good sir"));
|
ui_button(ui, lit_str("Hi there my good sir"));
|
||||||
|
|
||||||
|
ui_scroll_view_begin(ui, lit_str("scroll area"), v2{800, 200}, v2{1000,500}, 8);
|
||||||
|
{
|
||||||
|
ui_button(ui, lit_str("Sup"));
|
||||||
|
ui_button(ui, lit_str("you there"));
|
||||||
|
ui_button(ui, lit_str("Sup"));
|
||||||
|
ui_button(ui, lit_str("you there"));
|
||||||
|
|
||||||
|
ui_button(ui, lit_str("Sup"));
|
||||||
|
ui_button(ui, lit_str("you there"));
|
||||||
|
ui_button(ui, lit_str("Sup"));
|
||||||
|
ui_button(ui, lit_str("you there"));
|
||||||
|
|
||||||
|
ui_button(ui, lit_str("Sup"));
|
||||||
|
ui_button(ui, lit_str("you there"));
|
||||||
|
ui_button(ui, lit_str("Sup"));
|
||||||
|
ui_button(ui, lit_str("you there"));
|
||||||
|
|
||||||
|
ui_button(ui, lit_str("Sup"));
|
||||||
|
ui_button(ui, lit_str("you there"));
|
||||||
|
ui_button(ui, lit_str("Sup"));
|
||||||
|
ui_button(ui, lit_str("I'm lastf;"));
|
||||||
|
}
|
||||||
|
ui_scroll_view_end(ui);
|
||||||
|
|
||||||
|
ui_layout_pop(ui);
|
||||||
|
|
||||||
edr_render_begin(state);
|
edr_render_begin(state);
|
||||||
ui_draw(&state->editor->ui);
|
ui_draw(&state->editor->ui);
|
||||||
edr_render(state);
|
edr_render(state);
|
||||||
|
|
|
@ -35,6 +35,9 @@ ui_create(u32 widget_pool_cap, u32 verts_cap, Input_State* input, Allocator* a)
|
||||||
// Widgets
|
// Widgets
|
||||||
result.widgets.free = allocator_alloc_array(a, UI_Widget, widget_pool_cap);
|
result.widgets.free = allocator_alloc_array(a, UI_Widget, widget_pool_cap);
|
||||||
result.widgets.free_cap = widget_pool_cap;
|
result.widgets.free_cap = widget_pool_cap;
|
||||||
|
result.widgets.states_cap = 3 * widget_pool_cap;
|
||||||
|
result.widgets.states = allocator_alloc_array(a, UI_Widget_State, result.widgets.states_cap);
|
||||||
|
result.widgets.states_hash = allocator_alloc_array(a, u32, result.widgets.states_cap);
|
||||||
|
|
||||||
// Per Frame Vertex Buffer
|
// Per Frame Vertex Buffer
|
||||||
result.verts_cap = verts_cap;
|
result.verts_cap = verts_cap;
|
||||||
|
@ -192,15 +195,12 @@ ui_frame_prepare(UI* ui, v2 window_dim)
|
||||||
if (ui->widget_next_hot.value != 0)
|
if (ui->widget_next_hot.value != 0)
|
||||||
{
|
{
|
||||||
ui->widget_next_hot_frames += 1;
|
ui->widget_next_hot_frames += 1;
|
||||||
if (ui->widget_hot_frames > 1)
|
if (ui->widget_next_hot_frames > 1) ui_widget_next_hot_set(ui, 0);
|
||||||
{
|
|
||||||
ui->widget_next_hot = UI_Widget_Id{0};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (ui->widget_hot.value != 0)
|
if (ui->widget_hot.value != 0)
|
||||||
{
|
{
|
||||||
ui->widget_hot_frames += 1;
|
ui->widget_hot_frames += 1;
|
||||||
if (ui->widget_hot_frames > 1) ui->widget_hot = UI_Widget_Id{0};
|
if (ui->widget_hot_frames > 1) ui_widget_hot_set(ui, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,6 +229,8 @@ ui_draw(UI* ui)
|
||||||
platform_texture_bind(ui->atlas_texture);
|
platform_texture_bind(ui->atlas_texture);
|
||||||
platform_geometry_bind(ui->per_frame_buffer);
|
platform_geometry_bind(ui->per_frame_buffer);
|
||||||
platform_geometry_draw(ui->per_frame_buffer, ui->indices_len);
|
platform_geometry_draw(ui->per_frame_buffer, ui->indices_len);
|
||||||
|
|
||||||
|
OutputDebugStringA("Frame\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
|
@ -244,6 +246,20 @@ ui_widget_id_create(String string, u32 index)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal UI_Widget_State*
|
||||||
|
ui_widget_state_get(UI_Widget_Pool* pool, UI_Widget_Id id)
|
||||||
|
{
|
||||||
|
u32 index = hash_table_find(pool->states_hash, pool->states_cap, id.value);
|
||||||
|
assert(index != pool->states_cap);
|
||||||
|
UI_Widget_State* result = pool->states + index;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
internal UI_Widget_State*
|
||||||
|
ui_widget_state_get(UI* ui, UI_Widget_Id id)
|
||||||
|
{
|
||||||
|
return ui_widget_state_get(&ui->widgets, id);
|
||||||
|
}
|
||||||
|
|
||||||
internal UI_Widget*
|
internal UI_Widget*
|
||||||
ui_widget_pool_push(UI_Widget_Pool* pool, String string)
|
ui_widget_pool_push(UI_Widget_Pool* pool, String string)
|
||||||
{
|
{
|
||||||
|
@ -256,6 +272,11 @@ ui_widget_pool_push(UI_Widget_Pool* pool, String string)
|
||||||
result->child_first = 0;
|
result->child_first = 0;
|
||||||
result->child_last = 0;
|
result->child_last = 0;
|
||||||
|
|
||||||
|
u32 index = hash_table_register(pool->states_hash, pool->states_cap, result->id.value);
|
||||||
|
assert(index != pool->states_cap);
|
||||||
|
UI_Widget_State* state = pool->states + index;
|
||||||
|
zero_struct(*state);
|
||||||
|
|
||||||
if (pool->active_parent)
|
if (pool->active_parent)
|
||||||
{
|
{
|
||||||
result->parent = pool->active_parent;
|
result->parent = pool->active_parent;
|
||||||
|
@ -293,14 +314,22 @@ ui_widget_id_is_valid(UI_Widget_Id h)
|
||||||
internal void
|
internal void
|
||||||
ui_widget_next_hot_set(UI* ui, UI_Widget* w)
|
ui_widget_next_hot_set(UI* ui, UI_Widget* w)
|
||||||
{
|
{
|
||||||
|
if (w) {
|
||||||
ui->widget_next_hot = w->id;
|
ui->widget_next_hot = w->id;
|
||||||
|
} else {
|
||||||
|
ui->widget_next_hot = UI_Widget_Id{0};
|
||||||
|
}
|
||||||
ui->widget_next_hot_frames = 0;
|
ui->widget_next_hot_frames = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
ui_widget_hot_set(UI* ui, UI_Widget* w)
|
ui_widget_hot_set(UI* ui, UI_Widget* w)
|
||||||
{
|
{
|
||||||
|
if (w) {
|
||||||
ui->widget_hot = w->id;
|
ui->widget_hot = w->id;
|
||||||
|
} else {
|
||||||
|
ui->widget_hot = UI_Widget_Id{0};
|
||||||
|
}
|
||||||
ui->widget_hot_frames = 0;
|
ui->widget_hot_frames = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,11 +337,26 @@ internal UI_Widget_Result
|
||||||
ui_widget_push(UI* ui, UI_Widget_Desc desc)
|
ui_widget_push(UI* ui, UI_Widget_Desc desc)
|
||||||
{
|
{
|
||||||
UI_Widget_Result result = {};
|
UI_Widget_Result result = {};
|
||||||
|
v2 dim = desc.p_max - desc.p_min;
|
||||||
|
if (dim.x == 0 || dim.y == 0) return result;
|
||||||
|
|
||||||
UI_Widget* w = ui_widget_pool_push(&ui->widgets, desc.string);
|
UI_Widget* w = ui_widget_pool_push(&ui->widgets, desc.string);
|
||||||
w->desc = desc;
|
w->desc = desc;
|
||||||
|
result.id = w->id;
|
||||||
|
|
||||||
if (has_flag(desc.style.flags, UIWidgetStyle_MouseClick))
|
UI_Widget_State* state = ui_widget_state_get(ui, w->id);
|
||||||
|
w->desc.fill_pct = state->scroll;
|
||||||
|
|
||||||
|
v2 mouse_p = ui->input->frame_hot->mouse_pos;
|
||||||
|
bool mouse_over = (
|
||||||
|
mouse_p.x >= desc.p_min.x && mouse_p.x <= desc.p_max.x &&
|
||||||
|
mouse_p.y >= desc.p_min.y && mouse_p.y <= desc.p_max.y
|
||||||
|
);
|
||||||
|
|
||||||
|
UI_Widget_Style_Flags flags = desc.style.flags;
|
||||||
|
UI_Widget_Style_Flags mask_drag = (UIWidgetStyle_MouseDragH | UIWidgetStyle_MouseDragV);
|
||||||
|
UI_Widget_Style_Flags mask_hover = (mask_drag | UIWidgetStyle_MouseClick);
|
||||||
|
if (has_flag(flags, mask_hover))
|
||||||
{
|
{
|
||||||
// CASES:
|
// CASES:
|
||||||
// Mouse Over | Mouse Clicked | Is Next Hot | Response
|
// Mouse Over | Mouse Clicked | Is Next Hot | Response
|
||||||
|
@ -323,12 +367,6 @@ ui_widget_push(UI* ui, UI_Widget_Desc desc)
|
||||||
// t | t | f | become next hot
|
// t | t | f | become next hot
|
||||||
// t | t | t | become hot
|
// t | t | t | become hot
|
||||||
|
|
||||||
v2 mouse_p = ui->input->frame_hot->mouse_pos;
|
|
||||||
bool mouse_over = (
|
|
||||||
mouse_p.x >= desc.p_min.x && mouse_p.x <= desc.p_max.x &&
|
|
||||||
mouse_p.y >= desc.p_min.y && mouse_p.y <= desc.p_max.y
|
|
||||||
);
|
|
||||||
|
|
||||||
if (mouse_over)
|
if (mouse_over)
|
||||||
{
|
{
|
||||||
if (ui_widget_id_equals(w->id, ui->widget_next_hot))
|
if (ui_widget_id_equals(w->id, ui->widget_next_hot))
|
||||||
|
@ -341,10 +379,11 @@ ui_widget_push(UI* ui, UI_Widget_Desc desc)
|
||||||
if (input_key_went_up(ui->input, KeyCode_MouseLeftButton))
|
if (input_key_went_up(ui->input, KeyCode_MouseLeftButton))
|
||||||
{
|
{
|
||||||
result.flags |= UIWidgetResult_MouseLeft_WentUp;
|
result.flags |= UIWidgetResult_MouseLeft_WentUp;
|
||||||
ui->widget_hot = UI_Widget_Id{0};
|
ui_widget_hot_set(ui, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((w->id.index >= ui->widget_next_hot.index) && ui->widget_hot.value == 0)
|
|
||||||
|
if ((w->id.index >= ui->widget_next_hot.index) && ui->widget_hot.value == 0)
|
||||||
{
|
{
|
||||||
ui_widget_next_hot_set(ui, w);
|
ui_widget_next_hot_set(ui, w);
|
||||||
}
|
}
|
||||||
|
@ -353,11 +392,37 @@ ui_widget_push(UI* ui, UI_Widget_Desc desc)
|
||||||
{
|
{
|
||||||
if (ui_widget_id_equals(w->id, ui->widget_next_hot))
|
if (ui_widget_id_equals(w->id, ui->widget_next_hot))
|
||||||
{
|
{
|
||||||
ui->widget_next_hot = UI_Widget_Id{0};
|
ui_widget_next_hot_set(ui, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ui_widget_id_equals(w->id, ui->widget_hot))
|
||||||
|
{
|
||||||
|
if (input_key_is_down(ui->input, KeyCode_MouseLeftButton))
|
||||||
|
{
|
||||||
|
ui_widget_next_hot_set(ui, w);
|
||||||
|
ui_widget_hot_set(ui, w);
|
||||||
|
result.flags |= UIWidgetResult_MouseLeft_IsDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_flag(flags, mask_drag))
|
||||||
|
{
|
||||||
|
v2 drag_pct_mask = {
|
||||||
|
has_flag(flags, UIWidgetStyle_MouseDragH) ? 1.0f : 0.0f,
|
||||||
|
has_flag(flags, UIWidgetStyle_MouseDragV) ? 1.0f : 0.0f
|
||||||
|
};
|
||||||
|
v2 drag = ui->input->frame_hot->mouse_pos - w->desc.p_min;
|
||||||
|
drag = v2{ clamp(0, drag.x, w->desc.p_max.x), clamp(0, drag.y, w->desc.p_max.y) };
|
||||||
|
drag *= drag_pct_mask;
|
||||||
|
v2 drag_pct = drag / dim;
|
||||||
|
drag_pct = v2{ clamp(0, drag_pct.x, 1), clamp(0, drag_pct.y, 1) };
|
||||||
|
result.drag = drag_pct;
|
||||||
|
|
||||||
|
state->scroll = drag_pct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,8 +452,8 @@ ui_widgets_to_geometry_recursive(UI* ui, UI_Widget* widget, r32 z_start, r32 z_s
|
||||||
}
|
}
|
||||||
if (ui_widget_id_equals(ui->widget_hot, child->id))
|
if (ui_widget_id_equals(ui->widget_hot, child->id))
|
||||||
{
|
{
|
||||||
color_fg = desc.style.color_fg;
|
//color_fg = desc.style.color_fg;
|
||||||
color_bg = desc.style.color_bg;
|
//color_bg = desc.style.color_bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_flag(child->desc.style.flags, UIWidgetStyle_Outline))
|
if (has_flag(child->desc.style.flags, UIWidgetStyle_Outline))
|
||||||
|
@ -397,7 +462,6 @@ ui_widgets_to_geometry_recursive(UI* ui, UI_Widget* widget, r32 z_start, r32 z_s
|
||||||
z_at += z_step;
|
z_at += z_step;
|
||||||
bg_min += v3{ 1, 1, 0};
|
bg_min += v3{ 1, 1, 0};
|
||||||
bg_max -= v3{ 1, 1, 0};
|
bg_max -= v3{ 1, 1, 0};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_flag(child->desc.style.flags, UIWidgetStyle_Bg))
|
if (has_flag(child->desc.style.flags, UIWidgetStyle_Bg))
|
||||||
|
@ -408,6 +472,45 @@ ui_widgets_to_geometry_recursive(UI* ui, UI_Widget* widget, r32 z_start, r32 z_s
|
||||||
z_at += z_step;
|
z_at += z_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (has_flag(child->desc.style.flags, (UIWidgetStyle_FillH | UIWidgetStyle_FillV)))
|
||||||
|
{
|
||||||
|
v3 fill_min = {};
|
||||||
|
v3 fill_max = {};
|
||||||
|
if (has_flag(child->desc.style.flags, UIWidgetStyle_FillH))
|
||||||
|
{
|
||||||
|
r32 fill_x = HMM_Lerp(bg_min.x, child->desc.fill_pct.x, bg_max.x);
|
||||||
|
|
||||||
|
if (has_flag(child->desc.style.flags, UIWidgetStyle_LineInsteadOfFill))
|
||||||
|
{
|
||||||
|
fill_min = v3{ fill_x, bg_min.y, z_at };
|
||||||
|
fill_max = v3{ fill_x + 1, bg_max.y, z_at };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fill_min = bg_min;
|
||||||
|
fill_max = v3{ fill_x, bg_max.y, z_at };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (has_flag(child->desc.style.flags, UIWidgetStyle_FillV))
|
||||||
|
{
|
||||||
|
r32 fill_y = HMM_Lerp(bg_min.y, child->desc.fill_pct.y, bg_max.y);
|
||||||
|
|
||||||
|
if (has_flag(child->desc.style.flags, UIWidgetStyle_LineInsteadOfFill))
|
||||||
|
{
|
||||||
|
fill_min = v3{ bg_min.x, fill_y, z_at };
|
||||||
|
fill_max = v3{ bg_max.x, fill_y + 1, z_at };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fill_min = bg_min;
|
||||||
|
fill_max = v3{ bg_max.x, fill_y, z_at };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_sprite_push(ui, fill_min, fill_max, WHITE_SPRITE_ID, color_fg);
|
||||||
|
z_at += z_step;
|
||||||
|
}
|
||||||
|
|
||||||
if (has_flag(child->desc.style.flags, UIWidgetStyle_TextWrap | UIWidgetStyle_TextClip))
|
if (has_flag(child->desc.style.flags, UIWidgetStyle_TextWrap | UIWidgetStyle_TextClip))
|
||||||
{
|
{
|
||||||
r32 space_width = ui->font_space_width;
|
r32 space_width = ui->font_space_width;
|
||||||
|
@ -460,6 +563,38 @@ ui_widgets_to_geometry_recursive(UI* ui, UI_Widget* widget, r32 z_start, r32 z_s
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// Layout Manager
|
// Layout Manager
|
||||||
|
|
||||||
|
internal void
|
||||||
|
ui_layout_set_row_info(UI* ui, UI_Layout* l)
|
||||||
|
{
|
||||||
|
l->row_height = (ui->font_ascent + ui->font_descent + ui->font_line_gap + 15);
|
||||||
|
l->row_gap = 2;
|
||||||
|
l->col_gap = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
ui_layout_push(UI* ui, UI_Layout* layout)
|
||||||
|
{
|
||||||
|
if (ui->layout)
|
||||||
|
{
|
||||||
|
layout->parent = ui->layout;
|
||||||
|
ui->layout = layout;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->layout = layout;
|
||||||
|
layout->parent = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
ui_layout_pop(UI* ui)
|
||||||
|
{
|
||||||
|
if (ui->layout)
|
||||||
|
{
|
||||||
|
ui->layout = ui->layout->parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
ui_layout_row_begin(UI_Layout* layout, u32 cols)
|
ui_layout_row_begin(UI_Layout* layout, u32 cols)
|
||||||
{
|
{
|
||||||
|
@ -481,6 +616,12 @@ internal UI_Layout_Bounds
|
||||||
ui_layout_get_next(UI_Layout* layout)
|
ui_layout_get_next(UI_Layout* layout)
|
||||||
{
|
{
|
||||||
UI_Layout_Bounds result = {};
|
UI_Layout_Bounds result = {};
|
||||||
|
if (layout->at.x >= layout->bounds_max.x || layout->at.y >= layout->bounds_max.y ||
|
||||||
|
layout->at.y + layout->row_height >= layout->bounds_max.y)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
switch (layout->mode)
|
switch (layout->mode)
|
||||||
{
|
{
|
||||||
case UILayout_Columns:
|
case UILayout_Columns:
|
||||||
|
@ -508,6 +649,14 @@ ui_layout_get_next(UI_Layout* layout)
|
||||||
|
|
||||||
invalid_default_case;
|
invalid_default_case;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.min.x < layout->bounds_min.x || result.min.y < layout->bounds_min.y ||
|
||||||
|
result.max.x < layout->bounds_min.x || result.max.y < layout->bounds_min.y)
|
||||||
|
{
|
||||||
|
result.min = {};
|
||||||
|
result.max = {};
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
internal UI_Layout_Bounds
|
internal UI_Layout_Bounds
|
||||||
|
@ -537,16 +686,16 @@ ui_create_default_style_sheet()
|
||||||
ui_default_style_sheet.styles[UIWidget_Dropdown] = ui_default_style_sheet.styles[UIWidget_Toggle];
|
ui_default_style_sheet.styles[UIWidget_Dropdown] = ui_default_style_sheet.styles[UIWidget_Toggle];
|
||||||
|
|
||||||
ui_default_style_sheet.styles[UIWidget_HSlider] = {
|
ui_default_style_sheet.styles[UIWidget_HSlider] = {
|
||||||
(UIWidgetStyle_TextClip | UIWidgetStyle_Bg | UIWidgetStyle_Outline | UIWidgetStyle_MouseDrag), BLACK_V4, WHITE_V4, WHITE_SPRITE_ID
|
(UIWidgetStyle_TextClip | UIWidgetStyle_Bg | UIWidgetStyle_Outline | UIWidgetStyle_MouseDragH | UIWidgetStyle_FillH ), BLACK_V4, WHITE_V4, WHITE_SPRITE_ID
|
||||||
};
|
};
|
||||||
ui_default_style_sheet.styles[UIWidget_VSlider] = {
|
ui_default_style_sheet.styles[UIWidget_VSlider] = {
|
||||||
(UIWidgetStyle_TextClip | UIWidgetStyle_Bg | UIWidgetStyle_Outline | UIWidgetStyle_MouseDrag), BLACK_V4, WHITE_V4, WHITE_SPRITE_ID
|
(UIWidgetStyle_TextClip | UIWidgetStyle_Bg | UIWidgetStyle_Outline | UIWidgetStyle_MouseDragV | UIWidgetStyle_FillV ), BLACK_V4, WHITE_V4, WHITE_SPRITE_ID
|
||||||
};
|
};
|
||||||
ui_default_style_sheet.styles[UIWidget_HScroll] = {
|
ui_default_style_sheet.styles[UIWidget_HScroll] = {
|
||||||
(UIWidgetStyle_TextClip | UIWidgetStyle_Bg | UIWidgetStyle_Outline | UIWidgetStyle_MouseDrag), BLACK_V4, WHITE_V4, WHITE_SPRITE_ID
|
(UIWidgetStyle_TextClip | UIWidgetStyle_Bg | UIWidgetStyle_Outline | UIWidgetStyle_MouseDragH | UIWidgetStyle_FillH | UIWidgetStyle_LineInsteadOfFill ), BLACK_V4, WHITE_V4, WHITE_SPRITE_ID
|
||||||
};
|
};
|
||||||
ui_default_style_sheet.styles[UIWidget_VScroll] = {
|
ui_default_style_sheet.styles[UIWidget_VScroll] = {
|
||||||
(UIWidgetStyle_TextClip | UIWidgetStyle_Bg | UIWidgetStyle_Outline | UIWidgetStyle_MouseDrag), BLACK_V4, WHITE_V4, WHITE_SPRITE_ID
|
(UIWidgetStyle_TextClip | UIWidgetStyle_Bg | UIWidgetStyle_Outline | UIWidgetStyle_MouseDragV | UIWidgetStyle_FillV | UIWidgetStyle_LineInsteadOfFill ), BLACK_V4, WHITE_V4, WHITE_SPRITE_ID
|
||||||
};
|
};
|
||||||
|
|
||||||
ui_default_style_sheet.styles[UIWidget_Window] = {
|
ui_default_style_sheet.styles[UIWidget_Window] = {
|
||||||
|
@ -581,6 +730,17 @@ ui_text(UI* ui, String string)
|
||||||
ui_widget_push(ui, d);
|
ui_widget_push(ui, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
ui_text_f(UI* ui, char* fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
String string = string_fv(scratch, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
return ui_text(ui, string);
|
||||||
|
}
|
||||||
|
|
||||||
internal bool
|
internal bool
|
||||||
ui_button(UI* ui, String string)
|
ui_button(UI* ui, String string)
|
||||||
{
|
{
|
||||||
|
@ -605,3 +765,78 @@ ui_toggle(UI* ui, String string, bool value)
|
||||||
if (has_flag(r.flags, UIWidgetResult_MouseLeft_WentUp)) result = !result;
|
if (has_flag(r.flags, UIWidgetResult_MouseLeft_WentUp)) result = !result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal UI_Layout*
|
||||||
|
ui_scroll_view_begin(UI* ui, String string, v2 bounds_min, v2 bounds_max, u32 rows)
|
||||||
|
{
|
||||||
|
r32 scroll_bar_dim = 15;
|
||||||
|
v2 scroll_bars_area = v2{0, 0};
|
||||||
|
v2 scroll_area_min = bounds_min;
|
||||||
|
v2 scroll_area_max = bounds_max - scroll_bars_area;
|
||||||
|
v2 scroll_area_dim = scroll_area_max - scroll_area_min;
|
||||||
|
|
||||||
|
v2 scroll_offset = {};
|
||||||
|
r32 rows_avail = floorf(scroll_area_dim.y / ui->layout->row_height);
|
||||||
|
if (rows > rows_avail)
|
||||||
|
{
|
||||||
|
scroll_bars_area = v2{ scroll_bar_dim, 0};
|
||||||
|
scroll_area_min = bounds_min;
|
||||||
|
scroll_area_max = bounds_max - scroll_bars_area;
|
||||||
|
scroll_area_dim = scroll_area_max - scroll_area_min;
|
||||||
|
|
||||||
|
UI_Widget_Desc vscroll_d = {};
|
||||||
|
vscroll_d.p_min = { bounds_max.x - scroll_bar_dim, bounds_min.y };
|
||||||
|
vscroll_d.p_max = { bounds_max.x, bounds_max.y };
|
||||||
|
vscroll_d.style = ui_get_style(ui, UIWidget_VScroll);
|
||||||
|
vscroll_d.string = string_f(scratch, "%.*s_vscroll", str_varg(string));
|
||||||
|
UI_Widget_Result r = ui_widget_push(ui, vscroll_d);
|
||||||
|
|
||||||
|
UI_Widget_State* vscroll_state = ui_widget_state_get(ui, r.id);
|
||||||
|
scroll_offset.y = vscroll_state->scroll.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
r32 rows_scroll_to = max(0, rows - (rows_avail - 1));
|
||||||
|
r32 y_scroll_dist = rows_scroll_to * ui->layout->row_height;
|
||||||
|
|
||||||
|
scroll_offset *= v2{ 0, y_scroll_dist };
|
||||||
|
|
||||||
|
UI_Layout* layout = allocator_alloc_struct(scratch, UI_Layout);
|
||||||
|
layout->mode = UILayout_Columns;
|
||||||
|
layout->bounds_min = scroll_area_min;
|
||||||
|
layout->bounds_max = scroll_area_max;
|
||||||
|
ui_layout_set_row_info(ui, layout);
|
||||||
|
layout->at = bounds_min - scroll_offset;
|
||||||
|
ui_layout_push(ui, layout);
|
||||||
|
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
ui_scroll_view_end(UI* ui)
|
||||||
|
{
|
||||||
|
ui_layout_pop(ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
internal bool
|
||||||
|
ui_dropdown_begin(UI* ui, String string, bool state)
|
||||||
|
{
|
||||||
|
bool result = ui_toggle(ui, string, state);
|
||||||
|
UI_Layout* layout = allocator_alloc_struct(scratch, UI_Layout);
|
||||||
|
zero_struct(*layout);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
ui_scroll_view_begin(ui, layout);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
ui_dropdown_end(UI* ui, bool state)
|
||||||
|
{
|
||||||
|
if (state)
|
||||||
|
{
|
||||||
|
ui_scroll_view_end(ui);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -31,12 +31,16 @@ typedef u32 UI_Widget_Style_Flags;
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
UIWidgetStyle_None = 0,
|
UIWidgetStyle_None = 0,
|
||||||
UIWidgetStyle_Bg = 1,
|
UIWidgetStyle_Bg = 1 << 0,
|
||||||
UIWidgetStyle_TextClip = 2,
|
UIWidgetStyle_TextClip = 1 << 1,
|
||||||
UIWidgetStyle_TextWrap = 4,
|
UIWidgetStyle_TextWrap = 1 << 2,
|
||||||
UIWidgetStyle_Outline = 8,
|
UIWidgetStyle_Outline = 1 << 3,
|
||||||
UIWidgetStyle_MouseClick = 16,
|
UIWidgetStyle_MouseClick = 1 << 4,
|
||||||
UIWidgetStyle_MouseDrag = 32,
|
UIWidgetStyle_MouseDragH = 1 << 5,
|
||||||
|
UIWidgetStyle_MouseDragV = 1 << 6,
|
||||||
|
UIWidgetStyle_FillH = 1 << 7,
|
||||||
|
UIWidgetStyle_FillV = 1 << 8,
|
||||||
|
UIWidgetStyle_LineInsteadOfFill = 1 << 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
// akin to a css class, could be used to style multiple
|
// akin to a css class, could be used to style multiple
|
||||||
|
@ -46,7 +50,6 @@ struct UI_Widget_Style
|
||||||
UI_Widget_Style_Flags flags;
|
UI_Widget_Style_Flags flags;
|
||||||
v4 color_bg;
|
v4 color_bg;
|
||||||
v4 color_fg;
|
v4 color_fg;
|
||||||
|
|
||||||
u32 sprite;
|
u32 sprite;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -54,6 +57,7 @@ struct UI_Widget_Style
|
||||||
struct UI_Widget_Desc
|
struct UI_Widget_Desc
|
||||||
{
|
{
|
||||||
UI_Widget_Style style;
|
UI_Widget_Style style;
|
||||||
|
v2 fill_pct;
|
||||||
String string;
|
String string;
|
||||||
v2 p_min;
|
v2 p_min;
|
||||||
v2 p_max;
|
v2 p_max;
|
||||||
|
@ -80,7 +84,9 @@ enum
|
||||||
|
|
||||||
struct UI_Widget_Result
|
struct UI_Widget_Result
|
||||||
{
|
{
|
||||||
|
UI_Widget_Id id;
|
||||||
UI_Widget_Result_Flags flags;
|
UI_Widget_Result_Flags flags;
|
||||||
|
v2 drag;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum UI_Widget_Kind
|
enum UI_Widget_Kind
|
||||||
|
@ -110,6 +116,11 @@ struct UI_Style_Sheet
|
||||||
UI_Widget_Style styles[UIWidget_Count];
|
UI_Widget_Style styles[UIWidget_Count];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UI_Widget_State
|
||||||
|
{
|
||||||
|
v2 scroll;
|
||||||
|
};
|
||||||
|
|
||||||
struct UI_Widget_Pool
|
struct UI_Widget_Pool
|
||||||
{
|
{
|
||||||
UI_Widget* free;
|
UI_Widget* free;
|
||||||
|
@ -118,6 +129,10 @@ struct UI_Widget_Pool
|
||||||
|
|
||||||
UI_Widget* root;
|
UI_Widget* root;
|
||||||
UI_Widget* active_parent;
|
UI_Widget* active_parent;
|
||||||
|
|
||||||
|
UI_Widget_State* states;
|
||||||
|
u32* states_hash;
|
||||||
|
u32 states_cap;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum UI_Layout_Mode
|
enum UI_Layout_Mode
|
||||||
|
@ -132,13 +147,15 @@ enum UI_Layout_Mode
|
||||||
|
|
||||||
struct UI_Layout
|
struct UI_Layout
|
||||||
{
|
{
|
||||||
|
UI_Layout_Mode mode;
|
||||||
|
UI_Layout* parent;
|
||||||
|
|
||||||
v2 bounds_min;
|
v2 bounds_min;
|
||||||
v2 bounds_max;
|
v2 bounds_max;
|
||||||
r32 row_height;
|
r32 row_height;
|
||||||
r32 row_gap;
|
r32 row_gap;
|
||||||
r32 col_gap;
|
r32 col_gap;
|
||||||
v2 at;
|
v2 at;
|
||||||
UI_Layout_Mode mode;
|
|
||||||
u32 cols;
|
u32 cols;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -199,6 +216,9 @@ internal UI_Widget_Id ui_widget_id_create(u32 index_in_parent, String string
|
||||||
internal bool ui_widget_id_equals(UI_Widget_Id a, UI_Widget_Id b);
|
internal bool ui_widget_id_equals(UI_Widget_Id a, UI_Widget_Id b);
|
||||||
internal bool ui_widget_id_is_valid(UI_Widget_Id h);
|
internal bool ui_widget_id_is_valid(UI_Widget_Id h);
|
||||||
|
|
||||||
|
internal void ui_widget_next_hot_set(UI* ui, UI_Widget* w);
|
||||||
|
internal void ui_widget_hot_set(UI* ui, UI_Widget* w);
|
||||||
|
|
||||||
internal UI_Widget* ui_widget_pool_push(UI_Widget_Pool* pool, String string);
|
internal UI_Widget* ui_widget_pool_push(UI_Widget_Pool* pool, String string);
|
||||||
internal void ui_widget_pool_pop(UI_Widget_Pool* pool);
|
internal void ui_widget_pool_pop(UI_Widget_Pool* pool);
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,12 @@ lumenarium_event(Platform_Window_Event evt, App_State* state)
|
||||||
case WindowEvent_ButtonUp:
|
case WindowEvent_ButtonUp:
|
||||||
{
|
{
|
||||||
frame->key_flags[evt.key_code] = evt.key_flags;
|
frame->key_flags[evt.key_code] = evt.key_flags;
|
||||||
|
if (evt.key_code == KeyCode_MouseLeftButton)
|
||||||
|
{
|
||||||
|
state->input_state->mouse_pos_down = v2{
|
||||||
|
(r32)evt.mouse_x, (r32)evt.mouse_y
|
||||||
|
};
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WindowEvent_Char:
|
case WindowEvent_Char:
|
||||||
|
|
|
@ -245,3 +245,25 @@ string_copy(String s, Allocator* a)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal String
|
||||||
|
string_fv(Allocator* a, char* fmt, va_list args)
|
||||||
|
{
|
||||||
|
va_list args1;
|
||||||
|
va_copy(args1, args);
|
||||||
|
s32 needed = vsnprintf(0, 0, fmt, args);
|
||||||
|
String result = allocator_alloc_string(a, needed + 1);
|
||||||
|
result.len = vsnprintf((char*)result.str, result.cap, fmt, args1);
|
||||||
|
result.str[result.len] = 0;
|
||||||
|
va_end(args1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String
|
||||||
|
string_f(Allocator* a, char* fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
String result = string_fv(a, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -57,6 +57,13 @@ data_create(u8* base, u64 size)
|
||||||
internal void memory_zero(u8* base, u64 size);
|
internal void memory_zero(u8* base, u64 size);
|
||||||
internal void memory_copy(u8* from, u8* to, u64 size);
|
internal void memory_copy(u8* from, u8* to, u64 size);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
// Math
|
||||||
|
|
||||||
|
#define lerp(a,t,b) (a) + ((1.0f - (t)) * (b))
|
||||||
|
#define clamp(r0,v,r1) min((r1),max((r0),(v)))
|
||||||
|
#define lerp_clamp(a,t,b) clamp((a),lerp((a),(t),(b)),(b))
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
//////////////////////////////////////////////
|
||||||
// String
|
// String
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,17 @@ win32_button_event(Platform_Key_Code key, bool is_down, bool was_down)
|
||||||
return evt;
|
return evt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
win32_set_mouse_pos_evt(Platform_Window_Event* evt)
|
||||||
|
{
|
||||||
|
POINT mouse_p;
|
||||||
|
GetCursorPos(&mouse_p);
|
||||||
|
ScreenToClient(win32_main_window.window_handle, &mouse_p);
|
||||||
|
|
||||||
|
evt->mouse_x = mouse_p.x;
|
||||||
|
evt->mouse_y = mouse_p.y;
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
win32_window_handle_event(MSG msg, Win32_Window* win, App_State* state)
|
win32_window_handle_event(MSG msg, Win32_Window* win, App_State* state)
|
||||||
{
|
{
|
||||||
|
@ -90,6 +101,7 @@ win32_window_handle_event(MSG msg, Win32_Window* win, App_State* state)
|
||||||
KeyCode_MouseLeftButton,
|
KeyCode_MouseLeftButton,
|
||||||
true, false
|
true, false
|
||||||
);
|
);
|
||||||
|
win32_set_mouse_pos_evt(&evt);
|
||||||
lumenarium_event(evt, state);
|
lumenarium_event(evt, state);
|
||||||
win32_mouse_capture(win);
|
win32_mouse_capture(win);
|
||||||
}break;
|
}break;
|
||||||
|
@ -100,6 +112,7 @@ win32_window_handle_event(MSG msg, Win32_Window* win, App_State* state)
|
||||||
KeyCode_MouseMiddleButton,
|
KeyCode_MouseMiddleButton,
|
||||||
true, false
|
true, false
|
||||||
);
|
);
|
||||||
|
win32_set_mouse_pos_evt(&evt);
|
||||||
lumenarium_event(evt, state);
|
lumenarium_event(evt, state);
|
||||||
win32_mouse_capture(win);
|
win32_mouse_capture(win);
|
||||||
}break;
|
}break;
|
||||||
|
@ -110,6 +123,7 @@ win32_window_handle_event(MSG msg, Win32_Window* win, App_State* state)
|
||||||
KeyCode_MouseRightButton,
|
KeyCode_MouseRightButton,
|
||||||
true, false
|
true, false
|
||||||
);
|
);
|
||||||
|
win32_set_mouse_pos_evt(&evt);
|
||||||
lumenarium_event(evt, state);
|
lumenarium_event(evt, state);
|
||||||
win32_mouse_capture(win);
|
win32_mouse_capture(win);
|
||||||
}break;
|
}break;
|
||||||
|
@ -120,6 +134,7 @@ win32_window_handle_event(MSG msg, Win32_Window* win, App_State* state)
|
||||||
KeyCode_MouseLeftButton,
|
KeyCode_MouseLeftButton,
|
||||||
false, true
|
false, true
|
||||||
);
|
);
|
||||||
|
win32_set_mouse_pos_evt(&evt);
|
||||||
lumenarium_event(evt, state);
|
lumenarium_event(evt, state);
|
||||||
win32_mouse_release(win);
|
win32_mouse_release(win);
|
||||||
}break;
|
}break;
|
||||||
|
@ -130,6 +145,7 @@ win32_window_handle_event(MSG msg, Win32_Window* win, App_State* state)
|
||||||
KeyCode_MouseMiddleButton,
|
KeyCode_MouseMiddleButton,
|
||||||
false, true
|
false, true
|
||||||
);
|
);
|
||||||
|
win32_set_mouse_pos_evt(&evt);
|
||||||
lumenarium_event(evt, state);
|
lumenarium_event(evt, state);
|
||||||
win32_mouse_release(win);
|
win32_mouse_release(win);
|
||||||
}break;
|
}break;
|
||||||
|
@ -140,6 +156,7 @@ win32_window_handle_event(MSG msg, Win32_Window* win, App_State* state)
|
||||||
KeyCode_MouseRightButton,
|
KeyCode_MouseRightButton,
|
||||||
false, true
|
false, true
|
||||||
);
|
);
|
||||||
|
win32_set_mouse_pos_evt(&evt);
|
||||||
lumenarium_event(evt, state);
|
lumenarium_event(evt, state);
|
||||||
win32_mouse_release(win);
|
win32_mouse_release(win);
|
||||||
}break;
|
}break;
|
||||||
|
|
Loading…
Reference in New Issue