Compare commits

...

4 Commits

Author SHA1 Message Date
81cc3dae65 div_end returns the div Id 2025-09-12 22:45:23 +02:00
d35ef7ddaf re-implemented toggles 2025-09-12 22:44:33 +02:00
48a333e501 simplified code 2025-09-12 22:18:15 +02:00
71a959b9a1 re-added sliders 2025-09-12 20:23:07 +02:00
7 changed files with 184 additions and 208 deletions

View File

@ -36,28 +36,13 @@ struct Layout {
Rect content_offset; // combined effect of margin, border and padding Rect content_offset; // combined effect of margin, border and padding
} }
// Total width of a layout element, complete with margin, border and padding
macro Size Layout.total_width(&el)
{
Rect min = (Rect){.w = el.w.min, .h = el.h.min}.expand(el.content_offset);
Rect max = (Rect){.w = el.w.max, .h = el.h.max}.expand(el.content_offset);
return {.min = min.w, .max = max.w};
}
// Total height of a layout element, complete with margin, border and padding
macro Size Layout.total_height(&el)
{
Rect min = (Rect){.w = el.w.min, .h = el.h.min}.expand(el.content_offset);
Rect max = (Rect){.w = el.w.max, .h = el.h.max}.expand(el.content_offset);
return {.min = min.h, .max = max.h};
}
// Returns the width and height of a @FIT() element based on it's wanted size (min/max) // Returns the width and height of a @FIT() element based on it's wanted size (min/max)
// and the content size, this function is used to both update the parent's children size and // and the content size, this function is used to both update the parent's children size and
// give the dimensions of a fit element // give the dimensions of a fit element
// TODO: test and cleanup this function // TODO: test and cleanup this function
macro Point Layout.get_dimensions(&el) macro Point Layout.get_dimensions(&el)
{ {
Point dim;
// if the direction is ROW then the text is placed horizontally with the children // if the direction is ROW then the text is placed horizontally with the children
if (el.dir == ROW) { if (el.dir == ROW) {
Size content_width = el.children.w + el.text.width; Size content_width = el.children.w + el.text.width;
@ -74,11 +59,10 @@ macro Point Layout.get_dimensions(&el)
Size height = el.h.combine(content_height); Size height = el.h.combine(content_height);
short final_height = height.greater(); short final_height = height.greater();
Point dim = { dim = {
.x = final_width + el.content_offset.x + el.content_offset.w, .x = final_width + el.content_offset.x + el.content_offset.w,
.y = final_height + el.content_offset.y + el.content_offset.h, .y = final_height + el.content_offset.y + el.content_offset.h,
}; };
return dim;
} else { } else {
// if the direction is COLUMN the text and children are one on top of the other // if the direction is COLUMN the text and children are one on top of the other
Size content_width = el.children.w.comb_max(el.text.width); Size content_width = el.children.w.comb_max(el.text.width);
@ -95,12 +79,16 @@ macro Point Layout.get_dimensions(&el)
Size height = el.h.combine(content_height); Size height = el.h.combine(content_height);
short final_height = height.greater(); short final_height = height.greater();
Point dim = { dim = {
.x = final_width + el.content_offset.x + el.content_offset.w, .x = final_width + el.content_offset.x + el.content_offset.w,
.y = final_height + el.content_offset.y + el.content_offset.h, .y = final_height + el.content_offset.y + el.content_offset.h,
}; };
return dim;
} }
// GROSS HACK FOR EXACT DIMENSIONS
if (el.w.@is_exact()) dim.x = el.w.min + el.content_offset.x + el.content_offset.w;
if (el.h.@is_exact()) dim.y = el.h.min + el.content_offset.y + el.content_offset.h;
return dim;
} }
// The content space of the element // The content space of the element
@ -176,33 +164,8 @@ fn void resolve_dimensions(Elem* e, Elem* p)
Layout* pl = &p.layout; Layout* pl = &p.layout;
Point elem_dimensions = el.get_dimensions(); Point elem_dimensions = el.get_dimensions();
e.bounds.w = elem_dimensions.x;
short text_min_height; e.bounds.h = elem_dimensions.y;
// ASSIGN WIDTH
switch {
case el.w.@is_exact():
// if width is exact then assign it to the bounds
e.bounds.w = el.total_width().min;
case el.w.@is_grow():
// done in another pass
break;
case el.w.@is_fit(): // fit the element's children
e.bounds.w = elem_dimensions.x;
default: unreachable("width is not exact, grow or fit");
}
// ASSIGN HEIGHT
switch {
case el.h.@is_exact():
// if width is exact then assign it to the bounds and add border and paddign
e.bounds.h = el.total_height().min;
case el.h.@is_grow():
break;
// done in another pass
case el.h.@is_fit(): // fit the element's children
e.bounds.h = elem_dimensions.y;
default: unreachable("width is not exact, grow or fit");
}
switch (pl.dir) { switch (pl.dir) {
case ROW: case ROW:

View File

@ -158,11 +158,9 @@ fn void? Ctx.checkbox_id(&ctx, Id id, String description, bool* active, String t
} }
} }
/* macro Ctx.toggle(&ctx, String desc, bool* active)
// FIXME: this should be inside the style => ctx.toggle_id(@compute_id($vasplat), desc, active);
macro Ctx.toggle(&ctx, String desc, Point off, bool* active) fn void? Ctx.toggle_id(&ctx, Id id, String description, bool* active)
=> ctx.toggle_id(@compute_id($vasplat), desc, off, active);
fn void? Ctx.toggle_id(&ctx, Id id, String description, Point off, bool* active)
{ {
id = ctx.gen_id(id)!; id = ctx.gen_id(id)!;
@ -170,22 +168,61 @@ fn void? Ctx.toggle_id(&ctx, Id id, String description, Point off, bool* active)
Elem *elem = ctx.get_elem(id, ETYPE_BUTTON)!; Elem *elem = ctx.get_elem(id, ETYPE_BUTTON)!;
Style* style = ctx.styles.get_style(@str_hash("toggle")); Style* style = ctx.styles.get_style(@str_hash("toggle"));
Rect size = {off.x, off.y, style.size*2, style.size}; short inner_pad = description != "" ? style.size/2 : 0;
elem.bounds = ctx.layout_element(parent, size, style); /*
* |< >| style.size/2
* +---------------------|---|-----------------+
* | | .-----------. ---|--
* | +-----------------+ ' ##### ' | ^
* | | description | | ##### | | style.size
* | +-----------------+ . ##### . | v
* | '-----------' ---|--
* +-------------------------|-------------|---+
* |<----->| style.size*2
*/
// if the bounds are null the element is outside the div view, elem.layout.w = @fit(style.size*2);
// no interaction should occur so just return elem.layout.h = @fit(style.size);
if (elem.bounds.is_null()) return; elem.layout.children.w = @exact(style.size*2 + inner_pad);
elem.layout.children.h = @exact(style.size);
elem.layout.text = ctx.measure_string(description)!;
elem.layout.content_offset = style.margin + style.border + style.padding;
update_parent_grow(elem, parent);
update_parent_size(elem, parent);
elem.events = ctx.get_elem_events(elem); elem.events = ctx.get_elem_events(elem);
if (elem.events.mouse_hover && elem.events.mouse_release) *active = !(*active); if (elem.events.mouse_hover && elem.events.mouse_release) *active = !(*active);
// Draw the button Rect content_bounds = elem.bounds.pad(elem.layout.content_offset);
// FIXME: THIS IS SHIT Rect text_bounds = {
ctx.push_rect(elem.bounds, parent.div.z_index, style)!; .x = content_bounds.x,
Rect t = elem.bounds.add({*active ? (style.size+3) : +3, +3, -style.size-6, -6}); .y = content_bounds.y,
Style s = *style; .w = content_bounds.w - inner_pad - style.size*2,
s.bg = s.primary; .h = content_bounds.h
s.margin = s.border = s.padding = {}; };
ctx.push_rect(t, parent.div.z_index, &s)!; Rect toggle_bounds = {
.x = content_bounds.x + text_bounds.w + inner_pad,
.y = content_bounds.y + (content_bounds.h - style.size)/2,
.w = style.size*2,
.h = style.size,
};
Rect toggle = {
.x = toggle_bounds.x + (*active ? style.size : 0),
.y = toggle_bounds.y,
.w = style.size,
.h = style.size
};
Style s;
s.bg = style.bg;
s.secondary = style.secondary;
s.border = style.border;
s.radius = style.radius;
ctx.layout_string(description, text_bounds, CENTER, parent.div.z_index, style.fg)!;
ctx.push_rect(toggle_bounds, parent.div.z_index, &s)!;
s.bg = style.primary;
s.border = {};
ctx.push_rect(toggle.pad(style.border), parent.div.z_index, &s)!;
} }

View File

@ -32,7 +32,7 @@ macro Ctx.@div(&ctx,
{ {
ctx.div_begin(width, height, dir, anchor, scroll_x, scroll_y, $vasplat)!; ctx.div_begin(width, height, dir, anchor, scroll_x, scroll_y, $vasplat)!;
@body(); @body();
ctx.div_end()!; return ctx.div_end()!;
} }
macro Ctx.div_begin(&ctx, macro Ctx.div_begin(&ctx,
@ -92,24 +92,14 @@ fn void? Ctx.div_begin_id(&ctx,
// TODO: check resizeable // TODO: check resizeable
} }
fn void? Ctx.div_end(&ctx) fn Id? Ctx.div_end(&ctx)
{ {
Elem* elem = ctx.get_active_div()!; Elem* elem = ctx.get_active_div()!;
/* FIXME: Redo slider functionality /* FIXME: this needs the absolute positioning to work
Rect cb = elem.div.pcb;
// children bounds bottom-right corner
Point cbc = {
.x = cb.x + cb.w,
.y = cb.y + cb.h,
};
// div bounds bottom-right corner
Point bc = {
.x = elem.bounds.x + elem.bounds.w,
.y = elem.bounds.y + elem.bounds.h,
};
// set the scrollbar flag, is used in layout // set the scrollbar flag, is used in layout
Point cbc = elem.children_bounds.bottom_right();
Point bc = elem.bounds.bottom_right();
// horizontal overflow // horizontal overflow
elem.div.scroll_x.on = cbc.x > bc.x && elem.div.scroll_x.enabled; elem.div.scroll_x.on = cbc.x > bc.x && elem.div.scroll_x.enabled;
// vertical overflow // vertical overflow
@ -127,16 +117,7 @@ fn void? Ctx.div_end(&ctx)
elem.div.scroll_y.value += ctx.input.mouse.scroll.y * 0.07f; elem.div.scroll_y.value += ctx.input.mouse.scroll.y * 0.07f;
elem.div.scroll_y.value = math::clamp(elem.div.scroll_y.value, 0.0f, 1.0f); elem.div.scroll_y.value = math::clamp(elem.div.scroll_y.value, 0.0f, 1.0f);
} }
Rect vslider = { ctx.slider_ver_id(vsid_raw, @exact(wdim), @exact(elem.bounds.h - hdim), &elem.div.scroll_y.value, max((float)bc.y / cbc.y, (float)0.15))!;
.x = elem.bounds.x + elem.bounds.w - wdim,
.y = elem.bounds.y,
.w = wdim,
.h = elem.bounds.h - hdim,
};
Layout prev_l = elem.div.layout;
elem.div.layout = LAYOUT_ABSOLUTE;
ctx.slider_ver_id(vsid_raw, vslider, &elem.div.scroll_y.value, max((float)bc.y / cbc.y, (float)0.15))!;
elem.div.layout = prev_l;
} }
if (elem.div.scroll_x.on) { if (elem.div.scroll_x.on) {
@ -144,16 +125,7 @@ fn void? Ctx.div_end(&ctx)
elem.div.scroll_x.value += ctx.input.mouse.scroll.x * 0.07f; elem.div.scroll_x.value += ctx.input.mouse.scroll.x * 0.07f;
elem.div.scroll_x.value = math::clamp(elem.div.scroll_x.value, 0.0f, 1.0f); elem.div.scroll_x.value = math::clamp(elem.div.scroll_x.value, 0.0f, 1.0f);
} }
Rect hslider = { ctx.slider_hor_id(hsid_raw, @exact(elem.bounds.w - wdim), @exact(hdim), &elem.div.scroll_x.value, max((float)bc.x / cbc.x, (float)0.15))!;
.x = elem.bounds.x,
.y = elem.bounds.y + elem.bounds.h - hdim,
.w = elem.bounds.w - wdim,
.h = hdim,
};
Layout prev_l = elem.div.layout;
elem.div.layout = LAYOUT_ABSOLUTE;
ctx.slider_hor_id(hsid_raw, hslider, &elem.div.scroll_x.value, max((float)bc.x / cbc.x, (float)0.15))!;
elem.div.layout = prev_l;
} }
*/ */
@ -164,4 +136,6 @@ fn void? Ctx.div_end(&ctx)
ctx.reset_scissor(elem.div.z_index)!; ctx.reset_scissor(elem.div.z_index)!;
update_parent_size(elem, parent); update_parent_size(elem, parent);
return elem.id;
} }

View File

@ -13,13 +13,12 @@ struct ElemSlider {
* | |#####| | * | |#####| |
* +----+-----+---------------------+ * +----+-----+---------------------+
*/ */
/* macro Ctx.slider_hor(&ctx, Size w, Size h, float* value, float hpercent = 0.25, ...)
macro Ctx.slider_hor(&ctx, Rect size, float* value, float hpercent = 0.25, ...) => ctx.slider_hor_id(@compute_id($vasplat), w, h, value, hpercent);
=> ctx.slider_hor_id(@compute_id($vasplat), size, value, hpercent);
<* <*
@require value != null @require value != null
*> *>
fn ElemEvents? Ctx.slider_hor_id(&ctx, Id id, Rect size, float* value, float hpercent = 0.25) fn ElemEvents? Ctx.slider_hor_id(&ctx, Id id, Size w, Size h, float* value, float hpercent = 0.25)
{ {
id = ctx.gen_id(id)!; id = ctx.gen_id(id)!;
@ -27,10 +26,14 @@ fn ElemEvents? Ctx.slider_hor_id(&ctx, Id id, Rect size, float* value, float hpe
Elem* elem = ctx.get_elem(id, ETYPE_SLIDER)!; Elem* elem = ctx.get_elem(id, ETYPE_SLIDER)!;
Style* style = ctx.styles.get_style(@str_hash("slider")); Style* style = ctx.styles.get_style(@str_hash("slider"));
// 2. Layout elem.layout.w = w;
elem.bounds = ctx.layout_element(parent, size, style); elem.layout.h = h;
if (elem.bounds.is_null()) return {}; elem.layout.content_offset = style.margin + style.border + style.padding;
Rect content_bounds = elem.content_bounds(style); update_parent_grow(elem, parent);
update_parent_size(elem, parent);
Rect bg_bounds = elem.bounds.pad(style.margin);
Rect content_bounds = elem.bounds.pad(style.margin + style.border + style.padding);
// handle width // handle width
short hw = (short)(content_bounds.w * hpercent); short hw = (short)(content_bounds.w * hpercent);
@ -55,7 +58,7 @@ fn ElemEvents? Ctx.slider_hor_id(&ctx, Id id, Rect size, float* value, float hpe
Style s = *style; Style s = *style;
Rect padding = s.padding; Rect padding = s.padding;
s.padding = {}; s.padding = {};
ctx.push_rect(elem.bounds, parent.div.z_index, &s)!; ctx.push_rect(bg_bounds, parent.div.z_index, &s)!;
s.bg = s.primary; s.bg = s.primary;
s.padding = padding; s.padding = padding;
s.border = {}; s.border = {};
@ -63,7 +66,6 @@ fn ElemEvents? Ctx.slider_hor_id(&ctx, Id id, Rect size, float* value, float hpe
return elem.events; return elem.events;
} }
*/
/* /*
@ -78,10 +80,9 @@ fn ElemEvents? Ctx.slider_hor_id(&ctx, Id id, Rect size, float* value, float hpe
* | | * | |
* +--+ * +--+
*/ */
/* macro Ctx.slider_ver(&ctx, Size w, Size h, float* value, float hpercent = 0.25, ...)
macro Ctx.slider_ver(&ctx, Rect size, float* value, float hpercent = 0.25, ...) => ctx.slider_ver_id(@compute_id($vasplat), w, h, value, hpercent);
=> ctx.slider_ver_id(@compute_id($vasplat), size, value, hpercent); fn ElemEvents? Ctx.slider_ver_id(&ctx, Id id, Size w, Size h, float* value, float hpercent = 0.25)
fn ElemEvents? Ctx.slider_ver_id(&ctx, Id id, Rect size, float* value, float hpercent = 0.25)
{ {
id = ctx.gen_id(id)!; id = ctx.gen_id(id)!;
@ -89,17 +90,15 @@ fn ElemEvents? Ctx.slider_ver_id(&ctx, Id id, Rect size, float* value, float hpe
Elem *elem = ctx.get_elem(id, ETYPE_SLIDER)!; Elem *elem = ctx.get_elem(id, ETYPE_SLIDER)!;
Style* style = ctx.styles.get_style(@str_hash("slider")); Style* style = ctx.styles.get_style(@str_hash("slider"));
// 1. Fill the element fields elem.layout.w = w;
if (elem.flags.is_new) { elem.layout.h = h;
elem.type = ETYPE_SLIDER; elem.layout.content_offset = style.margin + style.border + style.padding;
} else if (elem.type != ETYPE_SLIDER) { update_parent_grow(elem, parent);
return WRONG_ELEMENT_TYPE?; update_parent_size(elem, parent);
}
// 2. Layout // 2. Layout
elem.bounds = ctx.layout_element(parent, size, style); Rect bg_bounds = elem.bounds.pad(style.margin);
if (elem.bounds.is_null()) return {}; Rect content_bounds = elem.bounds.pad(style.margin + style.border + style.padding);
Rect content_bounds = elem.content_bounds(style);
// handle height // handle height
short hh = (short)(content_bounds.h * hpercent); short hh = (short)(content_bounds.h * hpercent);
@ -124,7 +123,7 @@ fn ElemEvents? Ctx.slider_ver_id(&ctx, Id id, Rect size, float* value, float hpe
Style s = *style; Style s = *style;
Rect padding = s.padding; Rect padding = s.padding;
s.padding = {}; s.padding = {};
ctx.push_rect(elem.bounds, parent.div.z_index, &s)!; ctx.push_rect(bg_bounds, parent.div.z_index, &s)!;
s.bg = s.primary; s.bg = s.primary;
s.padding = padding; s.padding = padding;
s.border = {}; s.border = {};
@ -136,4 +135,3 @@ fn ElemEvents? Ctx.slider_ver_id(&ctx, Id id, Rect size, float* value, float hpe
macro short calc_slider(short off, short dim, float value) => (short)off + (short)(dim * value); macro short calc_slider(short off, short dim, float value) => (short)off + (short)(dim * value);
macro float calc_value(short off, short mouse, short dim, short slider) macro float calc_value(short off, short mouse, short dim, short slider)
=> math::clamp((float)(mouse-off-slider/2)/(float)(dim-slider), 0.0f, 1.0f); => math::clamp((float)(mouse-off-slider/2)/(float)(dim-slider), 0.0f, 1.0f);
*/

View File

@ -41,7 +41,7 @@ toggle {
border: 2; border: 2;
padding: 1; padding: 1;
radius: 10; radius: 10;
size: 16; size: 20;
bg: #3c3836ff; bg: #3c3836ff;
fg: #fbf1c7ff; fg: #fbf1c7ff;
primary: #cc241dff; primary: #cc241dff;

View File

@ -73,54 +73,51 @@ fn int main(String[] args)
defer ren.free(); defer ren.free();
ui.input_window_size(800, 600)!!; ui.input_window_size(800, 600)!!;
// // ========================================================================================== //
// FONT LOADING // FONT LOADING //
// // ========================================================================================== //
{ // import font in the ui context
// import font in the ui context ui.load_font("font1", "resources/hack-nerd.ttf", 16)!!;
ui.load_font("font1", "resources/hack-nerd.ttf", 16)!!;
// create the rendering pipeline // create the rendering pipeline
ren.font_atlas_id = ui.get_font_id("font1"); ren.font_atlas_id = ui.get_font_id("font1");
ren.load_spirv_shader_from_file("UGUI_PIPELINE_FONT", SPRITE_VS_PATH, FONT_FS_PATH, 1, 0); ren.load_spirv_shader_from_file("UGUI_PIPELINE_FONT", SPRITE_VS_PATH, FONT_FS_PATH, 1, 0);
ren.create_pipeline("UGUI_PIPELINE_FONT", SPRITE); ren.create_pipeline("UGUI_PIPELINE_FONT", SPRITE);
// send the atlas to the gpu // send the atlas to the gpu
Atlas* font_atlas = ui.get_font_atlas("font1")!!; Atlas* font_atlas = ui.get_font_atlas("font1")!!;
ren.new_texture("font1", JUST_ALPHA, font_atlas.buffer, font_atlas.width, font_atlas.height); ren.new_texture("font1", JUST_ALPHA, font_atlas.buffer, font_atlas.width, font_atlas.height);
}
// // ========================================================================================== //
// ICON LOADING // ICON LOADING //
// // ========================================================================================== //
{ // create the atlas and upload some icons
// create the atlas and upload some icons ui.sprite_atlas_create("icons", AtlasType.ATLAS_R8G8B8A8, 512, 512)!!;
ui.sprite_atlas_create("icons", AtlasType.ATLAS_R8G8B8A8, 512, 512)!!; ui.import_sprite_file_qoi("tux", "resources/tux.qoi")!!;
ui.import_sprite_file_qoi("tux", "resources/tux.qoi")!!; ui.import_sprite_file_qoi("tick", "resources/tick_sdf.qoi", SpriteType.SPRITE_MSDF)!!;
ui.import_sprite_file_qoi("tick", "resources/tick_sdf.qoi", SpriteType.SPRITE_MSDF)!!;
// create the rendering pipelines // create the rendering pipelines
ren.sprite_atlas_id = ui.get_sprite_atlas_id("icons"); ren.sprite_atlas_id = ui.get_sprite_atlas_id("icons");
// normal sprite pipeline // normal sprite pipeline
ren.load_spirv_shader_from_file("UGUI_PIPELINE_SPRITE", SPRITE_VS_PATH, SPRITE_FS_PATH, 1, 0); ren.load_spirv_shader_from_file("UGUI_PIPELINE_SPRITE", SPRITE_VS_PATH, SPRITE_FS_PATH, 1, 0);
ren.create_pipeline("UGUI_PIPELINE_SPRITE", SPRITE); ren.create_pipeline("UGUI_PIPELINE_SPRITE", SPRITE);
// msdf sprite pipeline // msdf sprite pipeline
ren.load_spirv_shader_from_file("UGUI_PIPELINE_SPRITE_MSDF", SPRITE_VS_PATH, MSDF_FS_PATH, 1, 0); ren.load_spirv_shader_from_file("UGUI_PIPELINE_SPRITE_MSDF", SPRITE_VS_PATH, MSDF_FS_PATH, 1, 0);
ren.create_pipeline("UGUI_PIPELINE_SPRITE_MSDF", SPRITE); ren.create_pipeline("UGUI_PIPELINE_SPRITE_MSDF", SPRITE);
// upload the atlas to the gpu // upload the atlas to the gpu
Atlas atlas = ui.sprite_atlas.atlas; Atlas atlas = ui.sprite_atlas.atlas;
ren.new_texture("icons", FULL_COLOR, atlas.buffer, atlas.width, atlas.height); ren.new_texture("icons", FULL_COLOR, atlas.buffer, atlas.width, atlas.height);
}
// // ========================================================================================== //
// RECT PIPELINE // RECT PIPELINE //
// // ========================================================================================== //
ren.load_spirv_shader_from_file("UGUI_PIPELINE_RECT", RECT_VS_PATH, RECT_FS_PATH, 0, 0); ren.load_spirv_shader_from_file("UGUI_PIPELINE_RECT", RECT_VS_PATH, RECT_FS_PATH, 0, 0);
ren.create_pipeline("UGUI_PIPELINE_RECT", RECT); ren.create_pipeline("UGUI_PIPELINE_RECT", RECT);
// ========================================================================================== //
// CSS INPUT // CSS INPUT //
// ========================================================================================== //
io::printfn("imported %d styles", ui.import_style_from_file(STYLESHEET_PATH)); io::printfn("imported %d styles", ui.import_style_from_file(STYLESHEET_PATH));
isz frame; isz frame;
@ -132,9 +129,9 @@ fn int main(String[] args)
Times draw_times; Times draw_times;
// // ========================================================================================== //
// MAIN LOOP // MAIN LOOP //
// // ========================================================================================== //
sdl::start_text_input(ren.win); sdl::start_text_input(ren.win);
sdl::Event e; sdl::Event e;
@ -367,6 +364,7 @@ fn void calculator(ugui::Ctx* ui)
ui.@div(ugui::@grow(), ugui::@grow(), ROW, CENTER) { // center everything on the screen ui.@div(ugui::@grow(), ugui::@grow(), ROW, CENTER) { // center everything on the screen
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN, TOP_LEFT) { ui.@div(ugui::@fit(), ugui::@fit(), COLUMN, TOP_LEFT) {
ui.@div(ugui::@grow(), ugui::@fit(), ROW, CENTER) {ui.text("SHITTY AHH CALCULATOR")!!;}!!;
ui.@div(ugui::@grow(), ugui::@exact(100), ROW, RIGHT) { ui.@div(ugui::@grow(), ugui::@exact(100), ROW, RIGHT) {
ui.text((String)buffer[:len])!!; ui.text((String)buffer[:len])!!;
}!!; }!!;
@ -412,10 +410,16 @@ fn void calculator(ugui::Ctx* ui)
}!!; }!!;
}!!; }!!;
ui.@div(ugui::@grow(), ugui::@grow(), anchor: CENTER) { ui.@div(ugui::@grow(), ugui::@fit(), anchor: CENTER) {
static bool state; static bool state;
ui.checkbox("boolean", &state, "tick")!!; ui.checkbox("boolean", &state, "tick")!!;
ui.sprite("tux")!!; ui.sprite("tux")!!;
ui.toggle("lmao", &state)!!;
}!!;
ui.@div(ugui::@grow(), ugui::@exact(50), anchor: CENTER, scroll_y: true) {
static float f;
ui.slider_hor(ugui::@exact(100), ugui::@exact(20), &f)!!;
ui.slider_ver(ugui::@exact(20), ugui::@exact(100), &f)!!;
}!!; }!!;
}!!; }!!; }!!; }!!;