mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-07 14:28:40 +00:00
eliminate recursive version of final ui layout position pass
This commit is contained in:
+132
-140
@@ -1272,11 +1272,11 @@ ui_end_build(void)
|
|||||||
root->rect = new_root_rect;
|
root->rect = new_root_rect;
|
||||||
for(Axis2 axis = (Axis2)0; axis < Axis2_COUNT; axis = (Axis2)(axis + 1))
|
for(Axis2 axis = (Axis2)0; axis < Axis2_COUNT; axis = (Axis2)(axis + 1))
|
||||||
{
|
{
|
||||||
ui_calc_sizes_standalone__in_place_rec(root, axis);
|
ui_calc_sizes_standalone__in_place(root, axis);
|
||||||
ui_calc_sizes_upwards_dependent__in_place_rec(root, axis);
|
ui_calc_sizes_upwards_dependent__in_place(root, axis);
|
||||||
ui_calc_sizes_downwards_dependent__in_place_rec(root, axis);
|
ui_calc_sizes_downwards_dependent__in_place(root, axis);
|
||||||
ui_layout_enforce_constraints__in_place_rec(root, axis);
|
ui_layout_enforce_constraints__in_place(root, axis);
|
||||||
ui_layout_position__in_place_rec(root, axis);
|
ui_layout_position__in_place(root, axis);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1613,7 +1613,7 @@ ui_end_build(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
ui_calc_sizes_standalone__in_place_rec(UI_Box *root, Axis2 axis)
|
ui_calc_sizes_standalone__in_place(UI_Box *root, Axis2 axis)
|
||||||
{
|
{
|
||||||
ProfBeginFunction();
|
ProfBeginFunction();
|
||||||
for(UI_Box *b = root; !ui_box_is_nil(b); b = ui_box_rec_df_pre(b, root).next)
|
for(UI_Box *b = root; !ui_box_is_nil(b); b = ui_box_rec_df_pre(b, root).next)
|
||||||
@@ -1637,7 +1637,7 @@ ui_calc_sizes_standalone__in_place_rec(UI_Box *root, Axis2 axis)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
ui_calc_sizes_upwards_dependent__in_place_rec(UI_Box *root, Axis2 axis)
|
ui_calc_sizes_upwards_dependent__in_place(UI_Box *root, Axis2 axis)
|
||||||
{
|
{
|
||||||
ProfBeginFunction();
|
ProfBeginFunction();
|
||||||
for(UI_Box *b = root; !ui_box_is_nil(b); b = ui_box_rec_df_pre(b, root).next)
|
for(UI_Box *b = root; !ui_box_is_nil(b); b = ui_box_rec_df_pre(b, root).next)
|
||||||
@@ -1673,7 +1673,7 @@ ui_calc_sizes_upwards_dependent__in_place_rec(UI_Box *root, Axis2 axis)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
ui_calc_sizes_downwards_dependent__in_place_rec(UI_Box *root, Axis2 axis)
|
ui_calc_sizes_downwards_dependent__in_place(UI_Box *root, Axis2 axis)
|
||||||
{
|
{
|
||||||
ProfBeginFunction();
|
ProfBeginFunction();
|
||||||
UI_BoxRec rec = {0};
|
UI_BoxRec rec = {0};
|
||||||
@@ -1710,180 +1710,172 @@ ui_calc_sizes_downwards_dependent__in_place_rec(UI_Box *root, Axis2 axis)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
ui_layout_enforce_constraints__in_place_rec(UI_Box *root, Axis2 axis)
|
ui_layout_enforce_constraints__in_place(UI_Box *root, Axis2 axis)
|
||||||
{
|
{
|
||||||
ProfBeginFunction();
|
ProfBeginFunction();
|
||||||
Temp scratch = scratch_begin(0, 0);
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
for(UI_Box *box = root; !ui_box_is_nil(box); box = ui_box_rec_df_pre(box, root).next)
|
||||||
// NOTE(rjf): The "layout axis" is the direction in which children
|
|
||||||
// of some node are intended to be laid out.
|
|
||||||
|
|
||||||
//- rjf: fixup children sizes (if we're solving along the *non-layout* axis)
|
|
||||||
if(axis != root->child_layout_axis && !(root->flags & (UI_BoxFlag_AllowOverflowX << axis)))
|
|
||||||
{
|
{
|
||||||
F32 allowed_size = root->fixed_size.v[axis];
|
//- rjf: fixup children sizes (if we're solving along the *non-layout* axis)
|
||||||
for(UI_Box *child = root->first; !ui_box_is_nil(child); child = child->next)
|
if(axis != box->child_layout_axis && !(box->flags & (UI_BoxFlag_AllowOverflowX << axis)))
|
||||||
{
|
{
|
||||||
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
F32 allowed_size = box->fixed_size.v[axis];
|
||||||
|
for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next)
|
||||||
{
|
{
|
||||||
F32 child_size = child->fixed_size.v[axis];
|
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
||||||
F32 violation = child_size - allowed_size;
|
|
||||||
F32 max_fixup = child_size;
|
|
||||||
F32 fixup = Clamp(0, violation, max_fixup);
|
|
||||||
if(fixup > 0)
|
|
||||||
{
|
{
|
||||||
child->fixed_size.v[axis] -= fixup;
|
F32 child_size = child->fixed_size.v[axis];
|
||||||
|
F32 violation = child_size - allowed_size;
|
||||||
|
F32 max_fixup = child_size;
|
||||||
|
F32 fixup = Clamp(0, violation, max_fixup);
|
||||||
|
if(fixup > 0)
|
||||||
|
{
|
||||||
|
child->fixed_size.v[axis] -= fixup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: fixup children sizes (in the direction of the layout axis)
|
|
||||||
if(axis == root->child_layout_axis && !(root->flags & (UI_BoxFlag_AllowOverflowX << axis)))
|
|
||||||
{
|
|
||||||
// rjf: figure out total allowed size & total size
|
|
||||||
F32 total_allowed_size = root->fixed_size.v[axis];
|
|
||||||
F32 total_size = 0;
|
|
||||||
F32 total_weighted_size = 0;
|
|
||||||
for(UI_Box *child = root->first; !ui_box_is_nil(child); child = child->next)
|
|
||||||
{
|
|
||||||
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
|
||||||
{
|
|
||||||
total_size += child->fixed_size.v[axis];
|
|
||||||
total_weighted_size += child->fixed_size.v[axis] * (1-child->pref_size[axis].strictness);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rjf: if we have a violation, we need to subtract some amount from all children
|
//- rjf: fixup children sizes (in the direction of the layout axis)
|
||||||
F32 violation = total_size - total_allowed_size;
|
if(axis == box->child_layout_axis && !(box->flags & (UI_BoxFlag_AllowOverflowX << axis)))
|
||||||
if(violation > 0 && total_weighted_size > 0)
|
|
||||||
{
|
{
|
||||||
// rjf: figure out how much we can take in totality
|
// rjf: figure out total allowed size & total size
|
||||||
F32 child_fixup_sum = 0;
|
F32 total_allowed_size = box->fixed_size.v[axis];
|
||||||
F32 *child_fixups = push_array(scratch.arena, F32, root->child_count);
|
F32 total_size = 0;
|
||||||
|
F32 total_weighted_size = 0;
|
||||||
|
for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next)
|
||||||
{
|
{
|
||||||
U64 child_idx = 0;
|
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
||||||
for(UI_Box *child = root->first; !ui_box_is_nil(child); child = child->next, child_idx += 1)
|
|
||||||
{
|
{
|
||||||
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
total_size += child->fixed_size.v[axis];
|
||||||
{
|
total_weighted_size += child->fixed_size.v[axis] * (1-child->pref_size[axis].strictness);
|
||||||
F32 fixup_size_this_child = child->fixed_size.v[axis] * (1-child->pref_size[axis].strictness);
|
|
||||||
fixup_size_this_child = ClampBot(0, fixup_size_this_child);
|
|
||||||
child_fixups[child_idx] = fixup_size_this_child;
|
|
||||||
child_fixup_sum += fixup_size_this_child;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: fixup child sizes
|
// rjf: if we have a violation, we need to subtract some amount from all children
|
||||||
|
F32 violation = total_size - total_allowed_size;
|
||||||
|
if(violation > 0 && total_weighted_size > 0)
|
||||||
{
|
{
|
||||||
U64 child_idx = 0;
|
Temp temp = temp_begin(scratch.arena);
|
||||||
for(UI_Box *child = root->first; !ui_box_is_nil(child); child = child->next, child_idx += 1)
|
|
||||||
|
// rjf: figure out how much we can take in totality
|
||||||
|
F32 child_fixup_sum = 0;
|
||||||
|
F32 *child_fixups = push_array(temp.arena, F32, box->child_count);
|
||||||
{
|
{
|
||||||
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
U64 child_idx = 0;
|
||||||
|
for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next, child_idx += 1)
|
||||||
{
|
{
|
||||||
F32 fixup_pct = (violation / total_weighted_size);
|
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
||||||
fixup_pct = Clamp(0, fixup_pct, 1);
|
{
|
||||||
child->fixed_size.v[axis] -= child_fixups[child_idx] * fixup_pct;
|
F32 fixup_size_this_child = child->fixed_size.v[axis] * (1-child->pref_size[axis].strictness);
|
||||||
|
fixup_size_this_child = ClampBot(0, fixup_size_this_child);
|
||||||
|
child_fixups[child_idx] = fixup_size_this_child;
|
||||||
|
child_fixup_sum += fixup_size_this_child;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rjf: fixup child sizes
|
||||||
|
{
|
||||||
|
U64 child_idx = 0;
|
||||||
|
for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next, child_idx += 1)
|
||||||
|
{
|
||||||
|
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
||||||
|
{
|
||||||
|
F32 fixup_pct = (violation / total_weighted_size);
|
||||||
|
fixup_pct = Clamp(0, fixup_pct, 1);
|
||||||
|
child->fixed_size.v[axis] -= child_fixups[child_idx] * fixup_pct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
temp_end(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: fixup upwards-relative sizes
|
||||||
|
if(box->flags & (UI_BoxFlag_AllowOverflowX << axis))
|
||||||
|
{
|
||||||
|
for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next)
|
||||||
|
{
|
||||||
|
if(child->pref_size[axis].kind == UI_SizeKind_ParentPct)
|
||||||
|
{
|
||||||
|
child->fixed_size.v[axis] = box->fixed_size.v[axis] * child->pref_size[axis].value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
//- rjf: enforce clamps
|
||||||
//- rjf: fixup upwards-relative sizes
|
for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next)
|
||||||
if(root->flags & (UI_BoxFlag_AllowOverflowX << axis))
|
|
||||||
{
|
|
||||||
for(UI_Box *child = root->first; !ui_box_is_nil(child); child = child->next)
|
|
||||||
{
|
{
|
||||||
if(child->pref_size[axis].kind == UI_SizeKind_ParentPct)
|
child->fixed_size.v[axis] = Max(child->fixed_size.v[axis], child->min_size.v[axis]);
|
||||||
{
|
|
||||||
child->fixed_size.v[axis] = root->fixed_size.v[axis] * child->pref_size[axis].value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: enforce clamps
|
|
||||||
for(UI_Box *child = root->first; !ui_box_is_nil(child); child = child->next)
|
|
||||||
{
|
|
||||||
child->fixed_size.v[axis] = Max(child->fixed_size.v[axis], child->min_size.v[axis]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: recurse
|
|
||||||
for(UI_Box *child = root->first; !ui_box_is_nil(child); child = child->next)
|
|
||||||
{
|
|
||||||
ui_layout_enforce_constraints__in_place_rec(child, axis);
|
|
||||||
}
|
|
||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
ui_layout_position__in_place_rec(UI_Box *root, Axis2 axis)
|
ui_layout_position__in_place(UI_Box *root, Axis2 axis)
|
||||||
{
|
{
|
||||||
ProfBeginFunction();
|
ProfBeginFunction();
|
||||||
F32 layout_position = 0;
|
for(UI_Box *box = root; !ui_box_is_nil(box); box = ui_box_rec_df_pre(box, root).next)
|
||||||
|
|
||||||
//- rjf: lay out children
|
|
||||||
F32 bounds = 0;
|
|
||||||
for(UI_Box *child = root->first; !ui_box_is_nil(child); child = child->next)
|
|
||||||
{
|
{
|
||||||
// rjf: grab original position
|
F32 layout_position = 0;
|
||||||
F32 original_position = Min(child->rect.p0.v[axis], child->rect.p1.v[axis]);
|
|
||||||
|
|
||||||
// rjf: calculate fixed position & size
|
//- rjf: lay out children
|
||||||
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
F32 bounds = 0;
|
||||||
|
for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next)
|
||||||
{
|
{
|
||||||
child->fixed_position.v[axis] = layout_position;
|
// rjf: grab original position
|
||||||
if(root->child_layout_axis == axis)
|
F32 original_position = Min(child->rect.p0.v[axis], child->rect.p1.v[axis]);
|
||||||
|
|
||||||
|
// rjf: calculate fixed position & size
|
||||||
|
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
||||||
{
|
{
|
||||||
layout_position += child->fixed_size.v[axis];
|
child->fixed_position.v[axis] = layout_position;
|
||||||
bounds += child->fixed_size.v[axis];
|
if(box->child_layout_axis == axis)
|
||||||
|
{
|
||||||
|
layout_position += child->fixed_size.v[axis];
|
||||||
|
bounds += child->fixed_size.v[axis];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bounds = Max(bounds, child->fixed_size.v[axis]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: determine final rect for child, given fixed_position & size
|
||||||
|
if(child->flags & (UI_BoxFlag_AnimatePosX<<axis))
|
||||||
|
{
|
||||||
|
if(child->first_touched_build_index == child->last_touched_build_index)
|
||||||
|
{
|
||||||
|
child->fixed_position_animated = child->fixed_position;
|
||||||
|
}
|
||||||
|
child->rect.p0.v[axis] = box->rect.p0.v[axis] + child->fixed_position_animated.v[axis] - !(child->flags&(UI_BoxFlag_SkipViewOffX<<axis))*floor_f32(box->view_off.v[axis]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bounds = Max(bounds, child->fixed_size.v[axis]);
|
child->rect.p0.v[axis] = box->rect.p0.v[axis] + child->fixed_position.v[axis] - !(child->flags&(UI_BoxFlag_SkipViewOffX<<axis))*floor_f32(box->view_off.v[axis]);
|
||||||
}
|
}
|
||||||
|
child->rect.p1.v[axis] = child->rect.p0.v[axis] + child->fixed_size.v[axis];
|
||||||
|
child->rect.p0.x = floor_f32(child->rect.p0.x);
|
||||||
|
child->rect.p0.y = floor_f32(child->rect.p0.y);
|
||||||
|
child->rect.p1.x = floor_f32(child->rect.p1.x);
|
||||||
|
child->rect.p1.y = floor_f32(child->rect.p1.y);
|
||||||
|
|
||||||
|
// rjf: grab new position
|
||||||
|
F32 new_position = Min(child->rect.p0.v[axis], child->rect.p1.v[axis]);
|
||||||
|
|
||||||
|
// rjf: store position delta
|
||||||
|
child->position_delta.v[axis] = new_position - original_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rjf: determine final rect for child, given fixed_position & size
|
//- rjf: store view bounds
|
||||||
if(child->flags & (UI_BoxFlag_AnimatePosX<<axis))
|
|
||||||
{
|
{
|
||||||
if(child->first_touched_build_index == child->last_touched_build_index)
|
box->view_bounds.v[axis] = bounds;
|
||||||
{
|
|
||||||
child->fixed_position_animated = child->fixed_position;
|
|
||||||
}
|
|
||||||
child->rect.p0.v[axis] = root->rect.p0.v[axis] + child->fixed_position_animated.v[axis] - !(child->flags&(UI_BoxFlag_SkipViewOffX<<axis))*floor_f32(root->view_off.v[axis]);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
child->rect.p0.v[axis] = root->rect.p0.v[axis] + child->fixed_position.v[axis] - !(child->flags&(UI_BoxFlag_SkipViewOffX<<axis))*floor_f32(root->view_off.v[axis]);
|
|
||||||
}
|
|
||||||
child->rect.p1.v[axis] = child->rect.p0.v[axis] + child->fixed_size.v[axis];
|
|
||||||
child->rect.p0.x = floor_f32(child->rect.p0.x);
|
|
||||||
child->rect.p0.y = floor_f32(child->rect.p0.y);
|
|
||||||
child->rect.p1.x = floor_f32(child->rect.p1.x);
|
|
||||||
child->rect.p1.y = floor_f32(child->rect.p1.y);
|
|
||||||
|
|
||||||
// rjf: grab new position
|
|
||||||
F32 new_position = Min(child->rect.p0.v[axis], child->rect.p1.v[axis]);
|
|
||||||
|
|
||||||
// rjf: store position delta
|
|
||||||
child->position_delta.v[axis] = new_position - original_position;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: store view bounds
|
|
||||||
{
|
|
||||||
root->view_bounds.v[axis] = bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: recurse
|
|
||||||
for(UI_Box *child = root->first; !ui_box_is_nil(child); child = child->next)
|
|
||||||
{
|
|
||||||
ui_layout_position__in_place_rec(child, axis);
|
|
||||||
}
|
|
||||||
|
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1891,11 +1883,11 @@ internal void
|
|||||||
ui_layout_root(UI_Box *root, Axis2 axis)
|
ui_layout_root(UI_Box *root, Axis2 axis)
|
||||||
{
|
{
|
||||||
ProfBegin("ui layout pass (%s)", axis == Axis2_X ? "x" : "y");
|
ProfBegin("ui layout pass (%s)", axis == Axis2_X ? "x" : "y");
|
||||||
ui_calc_sizes_standalone__in_place_rec(root, axis);
|
ui_calc_sizes_standalone__in_place(root, axis);
|
||||||
ui_calc_sizes_upwards_dependent__in_place_rec(root, axis);
|
ui_calc_sizes_upwards_dependent__in_place(root, axis);
|
||||||
ui_calc_sizes_downwards_dependent__in_place_rec(root, axis);
|
ui_calc_sizes_downwards_dependent__in_place(root, axis);
|
||||||
ui_layout_enforce_constraints__in_place_rec(root, axis);
|
ui_layout_enforce_constraints__in_place(root, axis);
|
||||||
ui_layout_position__in_place_rec(root, axis);
|
ui_layout_position__in_place(root, axis);
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -862,11 +862,11 @@ internal UI_Box * ui_box_from_key(UI_Key key);
|
|||||||
|
|
||||||
internal void ui_begin_build(OS_Handle window, UI_EventList *events, UI_IconInfo *icon_info, UI_Theme *theme, UI_AnimationInfo *animation_info, F32 real_dt, F32 animation_dt);
|
internal void ui_begin_build(OS_Handle window, UI_EventList *events, UI_IconInfo *icon_info, UI_Theme *theme, UI_AnimationInfo *animation_info, F32 real_dt, F32 animation_dt);
|
||||||
internal void ui_end_build(void);
|
internal void ui_end_build(void);
|
||||||
internal void ui_calc_sizes_standalone__in_place_rec(UI_Box *root, Axis2 axis);
|
internal void ui_calc_sizes_standalone__in_place(UI_Box *root, Axis2 axis);
|
||||||
internal void ui_calc_sizes_upwards_dependent__in_place_rec(UI_Box *root, Axis2 axis);
|
internal void ui_calc_sizes_upwards_dependent__in_place(UI_Box *root, Axis2 axis);
|
||||||
internal void ui_calc_sizes_downwards_dependent__in_place_rec(UI_Box *root, Axis2 axis);
|
internal void ui_calc_sizes_downwards_dependent__in_place(UI_Box *root, Axis2 axis);
|
||||||
internal void ui_layout_enforce_constraints__in_place_rec(UI_Box *root, Axis2 axis);
|
internal void ui_layout_enforce_constraints__in_place(UI_Box *root, Axis2 axis);
|
||||||
internal void ui_layout_position__in_place_rec(UI_Box *root, Axis2 axis);
|
internal void ui_layout_position__in_place(UI_Box *root, Axis2 axis);
|
||||||
internal void ui_layout_root(UI_Box *root, Axis2 axis);
|
internal void ui_layout_root(UI_Box *root, Axis2 axis);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|||||||
Reference in New Issue
Block a user