Compare commits
4 Commits
a00e39f36b
...
81cc3dae65
Author | SHA1 | Date | |
---|---|---|---|
81cc3dae65 | |||
d35ef7ddaf | |||
48a333e501 | |||
71a959b9a1 |
@ -131,7 +131,7 @@ fn Elem*? Ctx.get_parent(&ctx)
|
|||||||
Elem*? parent = ctx.cache.search(parent_id);
|
Elem*? parent = ctx.cache.search(parent_id);
|
||||||
if (catch parent) return parent;
|
if (catch parent) return parent;
|
||||||
if (parent.type != ETYPE_DIV) return WRONG_ELEMENT_TYPE?;
|
if (parent.type != ETYPE_DIV) return WRONG_ELEMENT_TYPE?;
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro @bits(#a) => $typeof(#a).sizeof*8;
|
macro @bits(#a) => $typeof(#a).sizeof*8;
|
||||||
|
@ -22,7 +22,7 @@ enum Anchor {
|
|||||||
|
|
||||||
struct Layout {
|
struct Layout {
|
||||||
Size w, h; // size of the CONTENT, does not include margin, border and padding
|
Size w, h; // size of the CONTENT, does not include margin, border and padding
|
||||||
struct children { // the children size includes the children's margin/border/pading
|
struct children { // the children size includes the children's margin/border/pading
|
||||||
Size w, h;
|
Size w, h;
|
||||||
}
|
}
|
||||||
TextSize text;
|
TextSize text;
|
||||||
@ -36,71 +36,59 @@ 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;
|
||||||
Size width = el.w.combine(content_width);
|
Size width = el.w.combine(content_width);
|
||||||
short final_width = width.greater();
|
short final_width = width.greater();
|
||||||
|
|
||||||
short text_height;
|
short text_height;
|
||||||
if (el.text.area != 0) {
|
if (el.text.area != 0) {
|
||||||
short text_width = (@exact(final_width) - el.children.w).combine(el.text.width).min;
|
short text_width = (@exact(final_width) - el.children.w).combine(el.text.width).min;
|
||||||
text_height = @exact((short)(el.text.area / text_width)).combine(el.text.height).min;
|
text_height = @exact((short)(el.text.area / text_width)).combine(el.text.height).min;
|
||||||
}
|
}
|
||||||
|
|
||||||
Size content_height = el.children.h.comb_max(@exact(text_height));
|
Size content_height = el.children.h.comb_max(@exact(text_height));
|
||||||
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);
|
||||||
Size width = el.w.combine(content_width);
|
Size width = el.w.combine(content_width);
|
||||||
short final_width = width.greater();
|
short final_width = width.greater();
|
||||||
|
|
||||||
short text_height;
|
short text_height;
|
||||||
if (el.text.area != 0) {
|
if (el.text.area != 0) {
|
||||||
short text_width = @exact(final_width).combine(el.text.width).min;
|
short text_width = @exact(final_width).combine(el.text.width).min;
|
||||||
text_height = @exact((short)(el.text.area / text_width)).combine(el.text.height).min;
|
text_height = @exact((short)(el.text.area / text_width)).combine(el.text.height).min;
|
||||||
}
|
}
|
||||||
|
|
||||||
Size content_height = el.children.h + @exact(text_height);
|
Size content_height = el.children.h + @exact(text_height);
|
||||||
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
|
||||||
@ -112,7 +100,7 @@ macro Point Elem.content_space(&e)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the parent element's grow children counter
|
// Update the parent element's grow children counter
|
||||||
fn void update_parent_grow(Elem* child, Elem* parent)
|
fn void update_parent_grow(Elem* child, Elem* parent)
|
||||||
{
|
{
|
||||||
switch (parent.layout.dir) {
|
switch (parent.layout.dir) {
|
||||||
@ -127,8 +115,8 @@ fn void update_parent_grow(Elem* child, Elem* parent)
|
|||||||
fn void update_parent_size(Elem* child, Elem* parent)
|
fn void update_parent_size(Elem* child, Elem* parent)
|
||||||
{
|
{
|
||||||
Layout* cl = &child.layout;
|
Layout* cl = &child.layout;
|
||||||
Layout* pl = &parent.layout;
|
Layout* pl = &parent.layout;
|
||||||
|
|
||||||
Point child_size = cl.get_dimensions();
|
Point child_size = cl.get_dimensions();
|
||||||
|
|
||||||
switch (pl.dir) {
|
switch (pl.dir) {
|
||||||
@ -174,35 +162,10 @@ fn void resolve_dimensions(Elem* e, Elem* p)
|
|||||||
{
|
{
|
||||||
Layout* el = &e.layout;
|
Layout* el = &e.layout;
|
||||||
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:
|
||||||
@ -218,7 +181,7 @@ fn void resolve_grow_elements(Elem* e, Elem* p)
|
|||||||
if (e.layout.w.@is_grow()) {
|
if (e.layout.w.@is_grow()) {
|
||||||
if (p.layout.dir == ROW) { // grow along the axis, divide the parent size
|
if (p.layout.dir == ROW) { // grow along the axis, divide the parent size
|
||||||
short slot = (short)((p.content_space().x - p.layout.occupied) / p.layout.grow_children);
|
short slot = (short)((p.content_space().x - p.layout.occupied) / p.layout.grow_children);
|
||||||
// the space slot accounts for the total size, while the element bounds does not account
|
// the space slot accounts for the total size, while the element bounds does not account
|
||||||
// for the margin
|
// for the margin
|
||||||
e.bounds.w = slot;
|
e.bounds.w = slot;
|
||||||
p.layout.grow_children--;
|
p.layout.grow_children--;
|
||||||
@ -227,7 +190,7 @@ fn void resolve_grow_elements(Elem* e, Elem* p)
|
|||||||
e.bounds.w = p.content_space().x;
|
e.bounds.w = p.content_space().x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HEIGHT
|
// HEIGHT
|
||||||
if (e.layout.h.@is_grow()) {
|
if (e.layout.h.@is_grow()) {
|
||||||
if (p.layout.dir == COLUMN) { // grow along the axis, divide the parent size
|
if (p.layout.dir == COLUMN) { // grow along the axis, divide the parent size
|
||||||
@ -372,7 +335,7 @@ fn void Ctx.layout_element_tree(&ctx)
|
|||||||
resolve_grow_elements(c, p);
|
resolve_grow_elements(c, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RESOLVE CHILDREN PLACEMENT
|
// RESOLVE CHILDREN PLACEMENT
|
||||||
ch_cur = 0;
|
ch_cur = 0;
|
||||||
ch = ctx.tree.children_it(current, &ch_cur)!!;
|
ch = ctx.tree.children_it(current, &ch_cur)!!;
|
||||||
|
@ -16,14 +16,14 @@ fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
|||||||
Elem *parent = ctx.get_parent()!;
|
Elem *parent = ctx.get_parent()!;
|
||||||
Elem *elem = ctx.get_elem(id, ETYPE_BUTTON)!;
|
Elem *elem = ctx.get_elem(id, ETYPE_BUTTON)!;
|
||||||
Style* style = ctx.styles.get_style(@str_hash("button"));
|
Style* style = ctx.styles.get_style(@str_hash("button"));
|
||||||
|
|
||||||
Sprite* sprite = icon != "" ? ctx.sprite_atlas.get(icon)! : &&(Sprite){};
|
Sprite* sprite = icon != "" ? ctx.sprite_atlas.get(icon)! : &&(Sprite){};
|
||||||
Rect icon_size = sprite.rect();
|
Rect icon_size = sprite.rect();
|
||||||
|
|
||||||
ushort min_size = style.size;
|
ushort min_size = style.size;
|
||||||
ushort half_lh = (ushort)(ctx.font.line_height() / 2);
|
ushort half_lh = (ushort)(ctx.font.line_height() / 2);
|
||||||
ushort inner_pad = label != "" && icon != "" ? half_lh : 0;
|
ushort inner_pad = label != "" && icon != "" ? half_lh : 0;
|
||||||
/*
|
/*
|
||||||
* +--------------------------------------+
|
* +--------------------------------------+
|
||||||
* | +--------+ |
|
* | +--------+ |
|
||||||
* | | | +-----------------+ |
|
* | | | +-----------------+ |
|
||||||
@ -105,7 +105,7 @@ fn void? Ctx.checkbox_id(&ctx, Id id, String description, bool* active, String t
|
|||||||
* +-------------------------|-------|---+
|
* +-------------------------|-------|---+
|
||||||
* |<----->| style.size
|
* |<----->| style.size
|
||||||
*/
|
*/
|
||||||
|
|
||||||
elem.layout.w = @fit(style.size);
|
elem.layout.w = @fit(style.size);
|
||||||
elem.layout.h = @fit(style.size);
|
elem.layout.h = @fit(style.size);
|
||||||
elem.layout.children.w = @exact(style.size + inner_pad);
|
elem.layout.children.w = @exact(style.size + inner_pad);
|
||||||
@ -139,7 +139,7 @@ fn void? Ctx.checkbox_id(&ctx, Id id, String description, bool* active, String t
|
|||||||
s.secondary = style.secondary;
|
s.secondary = style.secondary;
|
||||||
s.border = style.border;
|
s.border = style.border;
|
||||||
s.radius = style.radius;
|
s.radius = style.radius;
|
||||||
|
|
||||||
ctx.layout_string(description, text_bounds, CENTER, parent.div.z_index, style.fg)!;
|
ctx.layout_string(description, text_bounds, CENTER, parent.div.z_index, style.fg)!;
|
||||||
if (tick_sprite != "") {
|
if (tick_sprite != "") {
|
||||||
ctx.push_rect(check_bounds, parent.div.z_index, &s)!;
|
ctx.push_rect(check_bounds, parent.div.z_index, &s)!;
|
||||||
@ -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)!;
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -26,13 +26,13 @@ macro Ctx.@div(&ctx,
|
|||||||
LayoutDirection dir = ROW,
|
LayoutDirection dir = ROW,
|
||||||
Anchor anchor = TOP_LEFT,
|
Anchor anchor = TOP_LEFT,
|
||||||
bool scroll_x = false, bool scroll_y = false,
|
bool scroll_x = false, bool scroll_y = false,
|
||||||
...;
|
...;
|
||||||
@body()
|
@body()
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
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,
|
||||||
@ -80,7 +80,7 @@ fn void? Ctx.div_begin_id(&ctx,
|
|||||||
.anchor = anchor,
|
.anchor = anchor,
|
||||||
.content_offset = style.margin + style.border + style.padding,
|
.content_offset = style.margin + style.border + style.padding,
|
||||||
};
|
};
|
||||||
|
|
||||||
// update parent grow children
|
// update parent grow children
|
||||||
update_parent_grow(elem, parent);
|
update_parent_grow(elem, parent);
|
||||||
|
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
*/
|
|
@ -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;
|
||||||
|
120
src/main.c3
120
src/main.c3
@ -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
|
|
||||||
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.create_pipeline("UGUI_PIPELINE_FONT", SPRITE);
|
|
||||||
|
|
||||||
// send the atlas to the gpu
|
|
||||||
Atlas* font_atlas = ui.get_font_atlas("font1")!!;
|
|
||||||
ren.new_texture("font1", JUST_ALPHA, font_atlas.buffer, font_atlas.width, font_atlas.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
// create the rendering pipeline
|
||||||
// ICON LOADING
|
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.create_pipeline("UGUI_PIPELINE_FONT", SPRITE);
|
||||||
// create the atlas and upload some icons
|
|
||||||
ui.sprite_atlas_create("icons", AtlasType.ATLAS_R8G8B8A8, 512, 512)!!;
|
|
||||||
ui.import_sprite_file_qoi("tux", "resources/tux.qoi")!!;
|
|
||||||
ui.import_sprite_file_qoi("tick", "resources/tick_sdf.qoi", SpriteType.SPRITE_MSDF)!!;
|
|
||||||
|
|
||||||
// create the rendering pipelines
|
|
||||||
ren.sprite_atlas_id = ui.get_sprite_atlas_id("icons");
|
|
||||||
// normal sprite pipeline
|
|
||||||
ren.load_spirv_shader_from_file("UGUI_PIPELINE_SPRITE", SPRITE_VS_PATH, SPRITE_FS_PATH, 1, 0);
|
|
||||||
ren.create_pipeline("UGUI_PIPELINE_SPRITE", SPRITE);
|
|
||||||
// msdf sprite pipeline
|
|
||||||
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);
|
|
||||||
|
|
||||||
// upload the atlas to the gpu
|
|
||||||
Atlas atlas = ui.sprite_atlas.atlas;
|
|
||||||
ren.new_texture("icons", FULL_COLOR, atlas.buffer, atlas.width, atlas.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
// send the atlas to the gpu
|
||||||
// RECT PIPELINE
|
Atlas* font_atlas = ui.get_font_atlas("font1")!!;
|
||||||
//
|
ren.new_texture("font1", JUST_ALPHA, font_atlas.buffer, font_atlas.width, font_atlas.height);
|
||||||
|
|
||||||
|
// ========================================================================================== //
|
||||||
|
// ICON LOADING //
|
||||||
|
// ========================================================================================== //
|
||||||
|
// create the atlas and upload some icons
|
||||||
|
ui.sprite_atlas_create("icons", AtlasType.ATLAS_R8G8B8A8, 512, 512)!!;
|
||||||
|
ui.import_sprite_file_qoi("tux", "resources/tux.qoi")!!;
|
||||||
|
ui.import_sprite_file_qoi("tick", "resources/tick_sdf.qoi", SpriteType.SPRITE_MSDF)!!;
|
||||||
|
|
||||||
|
// create the rendering pipelines
|
||||||
|
ren.sprite_atlas_id = ui.get_sprite_atlas_id("icons");
|
||||||
|
// normal sprite pipeline
|
||||||
|
ren.load_spirv_shader_from_file("UGUI_PIPELINE_SPRITE", SPRITE_VS_PATH, SPRITE_FS_PATH, 1, 0);
|
||||||
|
ren.create_pipeline("UGUI_PIPELINE_SPRITE", SPRITE);
|
||||||
|
// msdf sprite pipeline
|
||||||
|
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);
|
||||||
|
|
||||||
|
// upload the atlas to the gpu
|
||||||
|
Atlas atlas = ui.sprite_atlas.atlas;
|
||||||
|
ren.new_texture("icons", FULL_COLOR, atlas.buffer, atlas.width, atlas.height);
|
||||||
|
|
||||||
|
// ========================================================================================== //
|
||||||
|
// 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;
|
||||||
@ -145,10 +142,10 @@ fn int main(String[] args)
|
|||||||
clock.mark();
|
clock.mark();
|
||||||
fps_clock.mark();
|
fps_clock.mark();
|
||||||
sleep_clock.mark();
|
sleep_clock.mark();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
case EVENT_QUIT:
|
case EVENT_QUIT:
|
||||||
quit = true;
|
quit = true;
|
||||||
case EVENT_KEY_UP: nextcase;
|
case EVENT_KEY_UP: nextcase;
|
||||||
case EVENT_KEY_DOWN:
|
case EVENT_KEY_DOWN:
|
||||||
@ -156,15 +153,15 @@ fn int main(String[] args)
|
|||||||
mod.lctrl = e.key.key == K_LCTRL ? !!(e.type == EVENT_KEY_DOWN) : mod.lctrl;
|
mod.lctrl = e.key.key == K_LCTRL ? !!(e.type == EVENT_KEY_DOWN) : mod.lctrl;
|
||||||
mod.bkspc = e.key.key == K_BACKSPACE ? !!(e.type == EVENT_KEY_DOWN) : mod.bkspc;
|
mod.bkspc = e.key.key == K_BACKSPACE ? !!(e.type == EVENT_KEY_DOWN) : mod.bkspc;
|
||||||
|
|
||||||
// pressing ctrl+key or alt+key does not generate a character as such no
|
// pressing ctrl+key or alt+key does not generate a character as such no
|
||||||
// TEXT_INPUT event is generated. When those keys are pressed we have to
|
// TEXT_INPUT event is generated. When those keys are pressed we have to
|
||||||
// do manual text input, bummer
|
// do manual text input, bummer
|
||||||
if (e.type == EVENT_KEY_DOWN && (mod.lctrl || mod.rctrl)) {
|
if (e.type == EVENT_KEY_DOWN && (mod.lctrl || mod.rctrl)) {
|
||||||
if (ascii::is_alnum_m((uint)e.key.key)) {
|
if (ascii::is_alnum_m((uint)e.key.key)) {
|
||||||
ui.input_char((char)e.key.key);
|
ui.input_char((char)e.key.key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.type == EVENT_KEY_DOWN && e.key.key == K_RETURN) ui.input_char('\n');
|
if (e.type == EVENT_KEY_DOWN && e.key.key == K_RETURN) ui.input_char('\n');
|
||||||
|
|
||||||
case EVENT_TEXT_INPUT:
|
case EVENT_TEXT_INPUT:
|
||||||
@ -235,7 +232,7 @@ $endswitch
|
|||||||
ren.begin_render(true);
|
ren.begin_render(true);
|
||||||
|
|
||||||
ren.render_ugui(&ui.cmd_queue);
|
ren.render_ugui(&ui.cmd_queue);
|
||||||
|
|
||||||
ren.end_render();
|
ren.end_render();
|
||||||
|
|
||||||
draw_times.push(clock.mark());
|
draw_times.push(clock.mark());
|
||||||
@ -245,7 +242,7 @@ $endswitch
|
|||||||
// wait for the next event, timeout after 100ms
|
// wait for the next event, timeout after 100ms
|
||||||
|
|
||||||
sdl::wait_event_timeout(&e, (int)(100.0-sleep_clock.mark().to_ms()-0.5));
|
sdl::wait_event_timeout(&e, (int)(100.0-sleep_clock.mark().to_ms()-0.5));
|
||||||
|
|
||||||
fps = 1.0 / fps_clock.mark().to_sec();
|
fps = 1.0 / fps_clock.mark().to_sec();
|
||||||
frame++;
|
frame++;
|
||||||
}
|
}
|
||||||
@ -292,7 +289,7 @@ fn void debug_app(ugui::Ctx* ui)
|
|||||||
ui.checkbox("", {}, &check, "tick")!!;
|
ui.checkbox("", {}, &check, "tick")!!;
|
||||||
ui.checkbox("", {}, &check)!!;
|
ui.checkbox("", {}, &check)!!;
|
||||||
ui.toggle("", {}, &toggle)!!;
|
ui.toggle("", {}, &toggle)!!;
|
||||||
|
|
||||||
ui.sprite("tux")!!;
|
ui.sprite("tux")!!;
|
||||||
static char[128] text_box = "ciao mamma";
|
static char[128] text_box = "ciao mamma";
|
||||||
static usz text_len = "ciao mamma".len;
|
static usz text_len = "ciao mamma".len;
|
||||||
@ -334,7 +331,7 @@ fn void calculator(ugui::Ctx* ui)
|
|||||||
static char[128] buffer;
|
static char[128] buffer;
|
||||||
static usz len;
|
static usz len;
|
||||||
bool eval;
|
bool eval;
|
||||||
|
|
||||||
// keyboard input
|
// keyboard input
|
||||||
switch(ui.get_keys()) {
|
switch(ui.get_keys()) {
|
||||||
case "+": nextcase;
|
case "+": nextcase;
|
||||||
@ -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])!!;
|
||||||
}!!;
|
}!!;
|
||||||
@ -400,7 +398,7 @@ fn void calculator(ugui::Ctx* ui)
|
|||||||
ui.button("C")!!.mouse_press ? len = 0 : 0;
|
ui.button("C")!!.mouse_press ? len = 0 : 0;
|
||||||
ui.button("D")!!.mouse_press ? len > 0 ? len-- : 0 : 0;
|
ui.button("D")!!.mouse_press ? len > 0 ? len-- : 0 : 0;
|
||||||
ui.button("-")!!.mouse_press ? buffer[len++] = '-' : 0;
|
ui.button("-")!!.mouse_press ? buffer[len++] = '-' : 0;
|
||||||
|
|
||||||
// eval the expression with 'bc'
|
// eval the expression with 'bc'
|
||||||
if (ui.button("=")!!.mouse_press || eval) {
|
if (ui.button("=")!!.mouse_press || eval) {
|
||||||
char[128] out;
|
char[128] out;
|
||||||
@ -411,11 +409,17 @@ 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)!!;
|
||||||
}!!;
|
}!!;
|
||||||
|
|
||||||
}!!; }!!;
|
}!!; }!!;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user