This commit is contained in:
Martin Fouilleul 2022-08-15 10:20:29 +02:00
parent 39cfa35bfd
commit 094b0efc33
9 changed files with 988 additions and 268 deletions

View File

@ -7,6 +7,7 @@
* *
*****************************************************************/ *****************************************************************/
#include<stdlib.h> #include<stdlib.h>
#include<string.h>
#include"milepost.h" #include"milepost.h"
#define LOG_SUBSYSTEM "Main" #define LOG_SUBSYSTEM "Main"
@ -137,36 +138,24 @@ int main()
mp_rect windowRect = mp_window_get_content_rect(window); mp_rect windowRect = mp_window_get_content_rect(window);
ui_style defaultStyle = {.borderSize = 2, ui_style defaultStyle = {.bgColor = {0.9, 0.9, 0.9, 1},
.borderColor = {0, 0, 1, 1},
.textColor = {0, 0, 0, 1},
.font = font,
.fontSize = 32};
ui_style buttonStyle[UI_STYLE_SELECTOR_COUNT];
for(int i=0; i<UI_STYLE_SELECTOR_COUNT; i++)
{
buttonStyle[i] = (ui_style){ .backgroundColor = {0.8, 0.8, 0.8, 1},
.foregroundColor = {0.5, 0.5, 0.5, 1},
.borderSize = 2, .borderSize = 2,
.borderColor = {0, 0, 1, 1}, .borderColor = {0, 0, 1, 1},
.textColor = {0, 0, 0, 1}, .fontColor = {0, 0, 0, 1},
.font = font, .font = font,
.fontSize = 32}; .fontSize = 32};
}
buttonStyle[UI_STYLE_HOT].borderColor = (mg_color){1, 0, 0, 1};
buttonStyle[UI_STYLE_ACTIVE].borderColor = (mg_color){1, 0, 0, 1};
buttonStyle[UI_STYLE_ACTIVE].foregroundColor = (mg_color){0.1, 0.1, 0.1, 1};
ui_begin_frame(windowRect.w, windowRect.h, defaultStyle); ui_begin_frame(windowRect.w, windowRect.h, defaultStyle);
{ {
ui_size_push(UI_AXIS_X, UI_SIZE_PIXELS, 600, 0); ui_push_bg_color_ext(UI_STYLE_TAG_BUTTON, UI_STYLE_SEL_ANY, (mg_color){0.8, 0.8, 0.8, 1});
ui_size_push(UI_AXIS_Y, UI_SIZE_PIXELS, 200, 0); ui_push_fg_color_ext(UI_STYLE_TAG_BUTTON, UI_STYLE_SEL_ANY, (mg_color){0.5, 0.5, 0.5, 1});
ui_push_border_color_ext(UI_STYLE_TAG_BUTTON, UI_STYLE_SEL_ANY, (mg_color){0, 0, 1, 1});
for(int i=0; i<UI_STYLE_SELECTOR_COUNT; i++) ui_push_border_color_ext(UI_STYLE_TAG_BUTTON, UI_STYLE_SEL_HOT|UI_STYLE_SEL_ACTIVE, (mg_color){1, 0, 0, 1});
{ ui_push_fg_color_ext(UI_STYLE_TAG_BUTTON, UI_STYLE_SEL_ACTIVE, (mg_color){0.1, 0.1, 0.1, 1});
ui_style_push(i, buttonStyle[i]);
} ui_push_size(UI_AXIS_X, UI_SIZE_PIXELS, 600, 0);
ui_push_size(UI_AXIS_Y, UI_SIZE_PIXELS, 200, 0);
ui_menu_bar("menu") ui_menu_bar("menu")
{ {
@ -194,8 +183,8 @@ int main()
ui_box* container = ui_box_begin("Test", UI_FLAG_DRAW_BORDER | UI_FLAG_DRAW_BACKGROUND); ui_box* container = ui_box_begin("Test", UI_FLAG_DRAW_BORDER | UI_FLAG_DRAW_BACKGROUND);
ui_box_set_layout(container, UI_AXIS_X, UI_ALIGN_END, UI_ALIGN_CENTER); ui_box_set_layout(container, UI_AXIS_X, UI_ALIGN_END, UI_ALIGN_CENTER);
{ {
ui_size_push(UI_AXIS_X, UI_SIZE_TEXT, 0, 0); ui_push_size(UI_AXIS_X, UI_SIZE_TEXT, 0, 0);
ui_size_push(UI_AXIS_Y, UI_SIZE_PARENT_RATIO, 0.25, 0); ui_push_size(UI_AXIS_Y, UI_SIZE_PARENT_RATIO, 0.25, 0);
ui_sig sig1 = ui_button("Child1"); ui_sig sig1 = ui_button("Child1");
if(sig1.hovering) if(sig1.hovering)
@ -220,29 +209,29 @@ int main()
ui_box_set_floating(block, UI_AXIS_X, 100); ui_box_set_floating(block, UI_AXIS_X, 100);
ui_box_set_floating(block, UI_AXIS_Y, 100); ui_box_set_floating(block, UI_AXIS_Y, 100);
ui_size_push(UI_AXIS_X, UI_SIZE_PIXELS, 200, 0); ui_push_size(UI_AXIS_X, UI_SIZE_PIXELS, 200, 0);
ui_size_push(UI_AXIS_Y, UI_SIZE_PIXELS, 20, 0); ui_push_size(UI_AXIS_Y, UI_SIZE_PIXELS, 20, 0);
static f32 scrollValue = 0.; static f32 scrollValue = 0.;
ui_scrollbar("scroll", .25, &scrollValue); ui_scrollbar("scroll", .25, &scrollValue);
ui_size_pop(UI_AXIS_X); ui_pop_size(UI_AXIS_X);
ui_size_pop(UI_AXIS_Y); ui_pop_size(UI_AXIS_Y);
ui_size_pop(UI_AXIS_X); ui_pop_size(UI_AXIS_X);
ui_size_pop(UI_AXIS_Y); ui_pop_size(UI_AXIS_Y);
} ui_box_end(); } ui_box_end();
ui_size_pop(UI_AXIS_X); ui_pop_size(UI_AXIS_X);
ui_size_pop(UI_AXIS_Y); ui_pop_size(UI_AXIS_Y);
ui_size_push(UI_AXIS_X, UI_SIZE_PIXELS, 200, 0); ui_push_size(UI_AXIS_X, UI_SIZE_PIXELS, 200, 0);
ui_size_push(UI_AXIS_Y, UI_SIZE_PIXELS, 200, 0); ui_push_size(UI_AXIS_Y, UI_SIZE_PIXELS, 200, 0);
ui_panel_begin("panel"); ui_panel_begin("panel");
ui_size_push(UI_AXIS_X, UI_SIZE_TEXT, 0, 0); ui_push_size(UI_AXIS_X, UI_SIZE_TEXT, 0, 0);
ui_size_push(UI_AXIS_Y, UI_SIZE_TEXT, 0, 0); ui_push_size(UI_AXIS_Y, UI_SIZE_TEXT, 0, 0);
ui_box* b = ui_box_begin("container", 0); ui_box* b = ui_box_begin("container", 0);
ui_box_set_size(b, UI_AXIS_X, UI_SIZE_CHILDREN, 0, 0); ui_box_set_size(b, UI_AXIS_X, UI_SIZE_CHILDREN, 0, 0);
@ -250,19 +239,24 @@ int main()
ui_button("Hello 1"); ui_button("Hello 1");
ui_button("Hello 2"); ui_button("Hello 2");
ui_button("Hello 3"); ui_button("Hello 3");
const u32 backingMaxSize = 4096;
static char backing[4096];
static str8 text = {};
ui_text_box_result res = ui_text_box("textbox", mem_scratch(), text);
memcpy(backing, res.text.ptr, minimum(res.text.len, backingMaxSize));
text = str8_from_buffer(res.text.len, backing);
ui_box_end(); ui_box_end();
ui_size_pop(UI_AXIS_X); ui_pop_size(UI_AXIS_X);
ui_size_pop(UI_AXIS_Y); ui_pop_size(UI_AXIS_Y);
ui_panel_end(); ui_panel_end();
ui_size_pop(UI_AXIS_X); ui_pop_size(UI_AXIS_X);
ui_size_pop(UI_AXIS_Y); ui_pop_size(UI_AXIS_Y);
for(int i=0; i<UI_STYLE_SELECTOR_COUNT; i++)
{
ui_style_pop(i);
}
} ui_end_frame(); } ui_end_frame();
@ -271,6 +265,8 @@ int main()
mg_canvas_flush(canvas); mg_canvas_flush(canvas);
mg_surface_present(surface); mg_surface_present(surface);
mem_arena_clear(mem_scratch());
} }
mg_surface_destroy(surface); mg_surface_destroy(surface);

View File

@ -3215,9 +3215,9 @@ int mg_font_get_codepoint_extents(mg_font font, utf32 codePoint, mg_text_extents
return(0); return(0);
} }
mp_rect mg_text_bounding_box(mg_font font, f32 fontSize, str8 text) mp_rect mg_text_bounding_box_utf32(mg_font font, f32 fontSize, str32 codePoints)
{ {
if(!text.len || !text.ptr) if(!codePoints.len || !codePoints.ptr)
{ {
return((mp_rect){}); return((mp_rect){});
} }
@ -3229,7 +3229,6 @@ mp_rect mg_text_bounding_box(mg_font font, f32 fontSize, str8 text)
} }
mem_arena* scratch = mem_scratch(); mem_arena* scratch = mem_scratch();
str32 codePoints = utf8_push_to_codepoints(scratch, text);
str32 glyphIndices = mg_font_push_glyph_indices(font, scratch, codePoints); str32 glyphIndices = mg_font_push_glyph_indices(font, scratch, codePoints);
//NOTE(martin): find width of missing character //NOTE(martin): find width of missing character
@ -3302,6 +3301,18 @@ mp_rect mg_text_bounding_box(mg_font font, f32 fontSize, str8 text)
return(rect); return(rect);
} }
mp_rect mg_text_bounding_box(mg_font font, f32 fontSize, str8 text)
{
if(!text.len || !text.ptr)
{
return((mp_rect){});
}
mem_arena* scratch = mem_scratch();
str32 codePoints = utf8_push_to_codepoints(scratch, text);
return(mg_text_bounding_box_utf32(font, fontSize, codePoints));
}
//----------------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------------
// Transform matrix settings // Transform matrix settings
//----------------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------------

View File

@ -135,6 +135,7 @@ int mg_font_get_codepoint_extents(mg_font font, utf32 codePoint, mg_text_extents
int mg_font_get_glyph_extents(mg_font font, str32 glyphIndices, mg_text_extents* outExtents); int mg_font_get_glyph_extents(mg_font font, str32 glyphIndices, mg_text_extents* outExtents);
mp_rect mg_text_bounding_box_utf32(mg_font font, f32 fontSize, str32 text);
mp_rect mg_text_bounding_box(mg_font font, f32 fontSize, str8 text); mp_rect mg_text_bounding_box(mg_font font, f32 fontSize, str8 text);
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------

View File

@ -636,7 +636,9 @@ static void mp_update_text(utf32 codepoint)
if(text->lastUpdate != frameCounter) if(text->lastUpdate != frameCounter)
{ {
text->codePoints.len = 0; text->codePoints.len = 0;
text->lastUpdate = frameCounter;
} }
text->codePoints.ptr = text->backing; text->codePoints.ptr = text->backing;
if(text->codePoints.len < MP_INPUT_TEXT_BACKING_SIZE) if(text->codePoints.len < MP_INPUT_TEXT_BACKING_SIZE)
{ {

984
src/ui.c

File diff suppressed because it is too large Load Diff

View File

@ -74,17 +74,22 @@ typedef struct ui_size
f32 strictness; f32 strictness;
} ui_size; } ui_size;
typedef enum { UI_STYLE_NORMAL, typedef enum { UI_STYLE_SEL_NORMAL = 1<<0,
UI_STYLE_HOT, UI_STYLE_SEL_HOT = 1<<1,
UI_STYLE_ACTIVE, UI_STYLE_SEL_ACTIVE = 1<<2,
UI_STYLE_SELECTOR_COUNT } ui_style_selector; UI_STYLE_SEL_ANY = UI_STYLE_SEL_NORMAL|UI_STYLE_SEL_HOT|UI_STYLE_SEL_ACTIVE,
} ui_style_selector;
typedef u32 ui_style_tag;
#define UI_STYLE_TAG_ANY (ui_style_tag)0
typedef struct ui_style typedef struct ui_style
{ {
mg_color backgroundColor; ui_size size[UI_AXIS_COUNT];
mg_color foregroundColor; mg_color bgColor;
mg_color fgColor;
mg_color borderColor; mg_color borderColor;
mg_color textColor; mg_color fontColor;
mg_font font; mg_font font;
f32 fontSize; f32 fontSize;
f32 borderSize; f32 borderSize;
@ -129,18 +134,15 @@ struct ui_box
ui_flags flags; ui_flags flags;
str8 string; str8 string;
// layout // styling and layout
ui_style_tag tag;
ui_style* targetStyle;
ui_style computedStyle;
u32 z; u32 z;
bool floating[UI_AXIS_COUNT]; bool floating[UI_AXIS_COUNT];
ui_size desiredSize[UI_AXIS_COUNT];
ui_layout layout; ui_layout layout;
mp_rect rect;
f32 childrenSum[2]; f32 childrenSum[2];
mp_rect rect;
// styling
ui_style* styles[UI_STYLE_SELECTOR_COUNT];
ui_style computedStyle;
ui_style_selector styleSelector;
// signals // signals
ui_sig* sig; ui_sig* sig;
@ -149,6 +151,7 @@ struct ui_box
bool closed; bool closed;
bool parentClosed; bool parentClosed;
bool dragging; bool dragging;
bool hot;
bool active; bool active;
vec2 scroll; vec2 scroll;
@ -178,14 +181,50 @@ void ui_box_set_style_selector(ui_box* box, ui_style_selector selector);
ui_sig ui_box_sig(ui_box* box); ui_sig ui_box_sig(ui_box* box);
void ui_size_push(ui_axis axis, ui_size_kind kind, f32 value, f32 strictness); void ui_push_size(ui_axis axis, ui_size_kind kind, f32 value, f32 strictness);
void ui_size_pop(ui_axis axis); void ui_push_size_ext(ui_style_tag tag, ui_style_selector selector, ui_axis axis, ui_size_kind kind, f32 value, f32 strictness);
void ui_style_push(ui_style_selector selector, ui_style style); void ui_pop_size(ui_axis axis);
void ui_style_pop(ui_style_selector selector);
void ui_push_bg_color(mg_color color);
void ui_push_fg_color(mg_color color);
void ui_push_font(mg_font font);
void ui_push_font_size(f32 size);
void ui_push_font_color(mg_color color);
void ui_push_border_size(f32 size);
void ui_push_border_color(mg_color color);
void ui_push_roundness(f32 roundness);
void ui_push_bg_color_ext(ui_style_tag tag, ui_style_selector selector, mg_color color);
void ui_push_fg_color_ext(ui_style_tag tag, ui_style_selector selector, mg_color color);
void ui_push_font_ext(ui_style_tag tag, ui_style_selector selector, mg_font font);
void ui_push_font_size_ext(ui_style_tag tag, ui_style_selector selector, f32 size);
void ui_push_font_color_ext(ui_style_tag tag, ui_style_selector selector, mg_color color);
void ui_push_border_size_ext(ui_style_tag tag, ui_style_selector selector, f32 size);
void ui_push_border_color_ext(ui_style_tag tag, ui_style_selector selector, mg_color color);
void ui_push_roundness_ext(ui_style_tag tag, ui_style_selector selector, f32 roundness);
void ui_pop_bg_color();
void ui_pop_fg_color();
void ui_pop_font();
void ui_pop_font_size();
void ui_pop_font_color();
void ui_pop_border_size();
void ui_pop_border_color();
void ui_pop_roundness();
// Basic helpers // Basic helpers
ui_sig ui_label(const char* label);
enum {
UI_STYLE_TAG_USER_MAX = 1<<16,
UI_STYLE_TAG_LABEL,
UI_STYLE_TAG_BUTTON,
UI_STYLE_TAG_SCROLLBAR,
UI_STYLE_TAG_PANEL,
UI_STYLE_TAG_TOOLTIP,
UI_STYLE_TAG_MENU
};
ui_sig ui_label(const char* label);
ui_sig ui_button(const char* label); ui_sig ui_button(const char* label);
ui_box* ui_scrollbar(const char* label, f32 thumbRatio, f32* scrollValue); ui_box* ui_scrollbar(const char* label, f32 thumbRatio, f32* scrollValue);
@ -205,6 +244,16 @@ void ui_menu_begin(const char* label);
void ui_menu_end(); void ui_menu_end();
#define ui_menu(name) defer_loop(ui_menu_begin(name), ui_menu_end()) #define ui_menu(name) defer_loop(ui_menu_begin(name), ui_menu_end())
typedef struct ui_text_box_result
{
bool changed;
bool accepted;
str8 text;
}ui_text_box_result;
ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

View File

@ -257,6 +257,57 @@ str32 str32_push_slice(mem_arena* arena, str32 s, u64 start, u64 end)
return(str32_push_copy(arena, slice)); return(str32_push_copy(arena, slice));
} }
void str32_list_init(str32_list* list)
{
ListInit(&list->list);
list->eltCount = 0;
list->len = 0;
}
void str32_list_push(mem_arena* arena, str32_list* list, str32 str)
{
str32_elt* elt = mem_arena_alloc_type(arena, str32_elt);
elt->string = str;
ListAppend(&list->list, &elt->listElt);
list->eltCount++;
list->len += str.len;
}
str32 str32_list_collate(mem_arena* arena, str32_list list, str32 prefix, str32 separator, str32 postfix)
{
str32 str = {};
str.len = prefix.len + list.len + list.eltCount*separator.len + postfix.len;
str.ptr = mem_arena_alloc_array(arena, u32, str.len);
char* dst = (char*)str.ptr;
memcpy(dst, prefix.ptr, prefix.len*sizeof(u32));
dst += prefix.len*sizeof(u32);
str32_elt* elt = ListFirstEntry(&list.list, str32_elt, listElt);
if(elt)
{
memcpy(dst, elt->string.ptr, elt->string.len*sizeof(u32));
dst += elt->string.len*sizeof(u32);
elt = ListNextEntry(&list.list, elt, str32_elt, listElt);
}
for( ; elt != 0; elt = ListNextEntry(&list.list, elt, str32_elt, listElt))
{
memcpy(dst, separator.ptr, separator.len*sizeof(u32));
dst += separator.len*sizeof(u32);
memcpy(dst, elt->string.ptr, elt->string.len*sizeof(u32));
dst += elt->string.len*sizeof(u32);
}
memcpy(dst, postfix.ptr, postfix.len*sizeof(u32));
return(str);
}
str32 str32_list_join(mem_arena* arena, str32_list list)
{
str32 empty = {.len = 0, .ptr = 0};
return(str32_list_collate(arena, list, empty, empty, empty));
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Paths helpers // Paths helpers
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -82,6 +82,23 @@ str32 str32_push_buffer(mem_arena* arena, u64 len, u32* buffer);
str32 str32_push_copy(mem_arena* arena, str32 s); str32 str32_push_copy(mem_arena* arena, str32 s);
str32 str32_push_slice(mem_arena* arena, str32 s, u64 start, u64 end); str32 str32_push_slice(mem_arena* arena, str32 s, u64 start, u64 end);
typedef struct str32_elt
{
list_elt listElt;
str32 string;
} str32_elt;
typedef struct str32_list
{
list_info list;
u64 eltCount;
u64 len;
} str32_list;
void str32_list_push(mem_arena* arena, str32_list* list, str32 str);
str32 str32_list_join(mem_arena* arena, str32_list list);
str32_list str32_split(mem_arena* arena, str32 str, str32_list separators);
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Paths helpers // Paths helpers
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -3,14 +3,19 @@
Shortlist Shortlist
--------- ---------
[x] let pass flat args in ui_size_push() and ui_box_set_size() [x] let pass flat args in ui_size_push() and ui_box_set_size()
[>>] separate style stacks [x] separate style stacks
[x] animation time stack
[>] margins? as part of size, or different styling stack? [>] margins? as part of size, or different styling stack?
[>] animation time stack
[ ] Let build code set target style directly, and animate from current to target [ ] Let build code set target style directly, and animate from current to target
[ ] filter styles stack by tag [ ] filter styles stack by tag
[ ] image backgrounds/gradients? [ ] image backgrounds/gradients?
[ ] animating open/close widgets? [ ] animating open/close widgets?
[.] Text box widget
[ ] Draw selection
[ ] Set cursor on click
[ ] Scroll to cursor
Canvas Drawing Canvas Drawing
-------------- --------------