mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-07-10 03:21:37 -07: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;
|
||||
for(Axis2 axis = (Axis2)0; axis < Axis2_COUNT; axis = (Axis2)(axis + 1))
|
||||
{
|
||||
ui_calc_sizes_standalone__in_place_rec(root, axis);
|
||||
ui_calc_sizes_upwards_dependent__in_place_rec(root, axis);
|
||||
ui_calc_sizes_downwards_dependent__in_place_rec(root, axis);
|
||||
ui_layout_enforce_constraints__in_place_rec(root, axis);
|
||||
ui_layout_position__in_place_rec(root, axis);
|
||||
ui_calc_sizes_standalone__in_place(root, axis);
|
||||
ui_calc_sizes_upwards_dependent__in_place(root, axis);
|
||||
ui_calc_sizes_downwards_dependent__in_place(root, axis);
|
||||
ui_layout_enforce_constraints__in_place(root, axis);
|
||||
ui_layout_position__in_place(root, axis);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1613,7 +1613,7 @@ ui_end_build(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();
|
||||
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
|
||||
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();
|
||||
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
|
||||
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();
|
||||
UI_BoxRec rec = {0};
|
||||
@@ -1710,180 +1710,172 @@ ui_calc_sizes_downwards_dependent__in_place_rec(UI_Box *root, Axis2 axis)
|
||||
}
|
||||
|
||||
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();
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
// 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)))
|
||||
for(UI_Box *box = root; !ui_box_is_nil(box); box = ui_box_rec_df_pre(box, root).next)
|
||||
{
|
||||
F32 allowed_size = root->fixed_size.v[axis];
|
||||
for(UI_Box *child = root->first; !ui_box_is_nil(child); child = child->next)
|
||||
//- rjf: fixup children sizes (if we're solving along the *non-layout* axis)
|
||||
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];
|
||||
F32 violation = child_size - allowed_size;
|
||||
F32 max_fixup = child_size;
|
||||
F32 fixup = Clamp(0, violation, max_fixup);
|
||||
if(fixup > 0)
|
||||
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
||||
{
|
||||
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
|
||||
F32 violation = total_size - total_allowed_size;
|
||||
if(violation > 0 && total_weighted_size > 0)
|
||||
//- rjf: fixup children sizes (in the direction of the layout axis)
|
||||
if(axis == box->child_layout_axis && !(box->flags & (UI_BoxFlag_AllowOverflowX << axis)))
|
||||
{
|
||||
// rjf: figure out how much we can take in totality
|
||||
F32 child_fixup_sum = 0;
|
||||
F32 *child_fixups = push_array(scratch.arena, F32, root->child_count);
|
||||
// rjf: figure out total allowed size & total size
|
||||
F32 total_allowed_size = box->fixed_size.v[axis];
|
||||
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;
|
||||
for(UI_Box *child = root->first; !ui_box_is_nil(child); child = child->next, child_idx += 1)
|
||||
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
||||
{
|
||||
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
||||
{
|
||||
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;
|
||||
}
|
||||
total_size += child->fixed_size.v[axis];
|
||||
total_weighted_size += child->fixed_size.v[axis] * (1-child->pref_size[axis].strictness);
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
for(UI_Box *child = root->first; !ui_box_is_nil(child); child = child->next, child_idx += 1)
|
||||
Temp temp = temp_begin(scratch.arena);
|
||||
|
||||
// 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);
|
||||
fixup_pct = Clamp(0, fixup_pct, 1);
|
||||
child->fixed_size.v[axis] -= child_fixups[child_idx] * fixup_pct;
|
||||
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
||||
{
|
||||
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: fixup upwards-relative sizes
|
||||
if(root->flags & (UI_BoxFlag_AllowOverflowX << axis))
|
||||
{
|
||||
for(UI_Box *child = root->first; !ui_box_is_nil(child); child = child->next)
|
||||
|
||||
//- rjf: enforce clamps
|
||||
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] = root->fixed_size.v[axis] * child->pref_size[axis].value;
|
||||
}
|
||||
child->fixed_size.v[axis] = Max(child->fixed_size.v[axis], child->min_size.v[axis]);
|
||||
}
|
||||
}
|
||||
|
||||
//- 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);
|
||||
ProfEnd();
|
||||
}
|
||||
|
||||
internal void
|
||||
ui_layout_position__in_place_rec(UI_Box *root, Axis2 axis)
|
||||
ui_layout_position__in_place(UI_Box *root, Axis2 axis)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
F32 layout_position = 0;
|
||||
|
||||
//- rjf: lay out children
|
||||
F32 bounds = 0;
|
||||
for(UI_Box *child = root->first; !ui_box_is_nil(child); child = child->next)
|
||||
for(UI_Box *box = root; !ui_box_is_nil(box); box = ui_box_rec_df_pre(box, root).next)
|
||||
{
|
||||
// rjf: grab original position
|
||||
F32 original_position = Min(child->rect.p0.v[axis], child->rect.p1.v[axis]);
|
||||
F32 layout_position = 0;
|
||||
|
||||
// rjf: calculate fixed position & size
|
||||
if(!(child->flags & (UI_BoxFlag_FloatingX<<axis)))
|
||||
//- rjf: lay out children
|
||||
F32 bounds = 0;
|
||||
for(UI_Box *child = box->first; !ui_box_is_nil(child); child = child->next)
|
||||
{
|
||||
child->fixed_position.v[axis] = layout_position;
|
||||
if(root->child_layout_axis == axis)
|
||||
// rjf: grab original position
|
||||
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];
|
||||
bounds += child->fixed_size.v[axis];
|
||||
child->fixed_position.v[axis] = layout_position;
|
||||
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
|
||||
{
|
||||
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
|
||||
if(child->flags & (UI_BoxFlag_AnimatePosX<<axis))
|
||||
//- rjf: store view bounds
|
||||
{
|
||||
if(child->first_touched_build_index == child->last_touched_build_index)
|
||||
{
|
||||
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]);
|
||||
box->view_bounds.v[axis] = bounds;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -1891,11 +1883,11 @@ internal void
|
||||
ui_layout_root(UI_Box *root, Axis2 axis)
|
||||
{
|
||||
ProfBegin("ui layout pass (%s)", axis == Axis2_X ? "x" : "y");
|
||||
ui_calc_sizes_standalone__in_place_rec(root, axis);
|
||||
ui_calc_sizes_upwards_dependent__in_place_rec(root, axis);
|
||||
ui_calc_sizes_downwards_dependent__in_place_rec(root, axis);
|
||||
ui_layout_enforce_constraints__in_place_rec(root, axis);
|
||||
ui_layout_position__in_place_rec(root, axis);
|
||||
ui_calc_sizes_standalone__in_place(root, axis);
|
||||
ui_calc_sizes_upwards_dependent__in_place(root, axis);
|
||||
ui_calc_sizes_downwards_dependent__in_place(root, axis);
|
||||
ui_layout_enforce_constraints__in_place(root, axis);
|
||||
ui_layout_position__in_place(root, axis);
|
||||
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_end_build(void);
|
||||
internal void ui_calc_sizes_standalone__in_place_rec(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_downwards_dependent__in_place_rec(UI_Box *root, Axis2 axis);
|
||||
internal void ui_layout_enforce_constraints__in_place_rec(UI_Box *root, Axis2 axis);
|
||||
internal void ui_layout_position__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(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(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);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user