UI scissoring
This commit is contained in:
parent
c530ec16c0
commit
5c2ff7ca9f
File diff suppressed because it is too large
Load Diff
@ -212,6 +212,8 @@ Struct(V_Palette)
|
||||
UI_Key key;
|
||||
b32 is_showing;
|
||||
f32 show;
|
||||
f32 scroll;
|
||||
f32 scroll_begin;
|
||||
|
||||
V_TextboxState search_state;
|
||||
};
|
||||
|
||||
@ -643,8 +643,9 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
|
||||
b32 is_cursor_in_box = 0;
|
||||
{
|
||||
// TODO: More efficient test. This logic is just copied from the renderer's SDF function for now.
|
||||
Vec2 p0 = box->screen_rect.p0;
|
||||
Vec2 p1 = box->screen_rect.p1;
|
||||
Rng2 interactable_region = IntersectRng2(box->solved_scissor, box->screen_rect);
|
||||
Vec2 p0 = interactable_region.p0;
|
||||
Vec2 p1 = interactable_region.p1;
|
||||
Vec2 point = frame->cursor_pos;
|
||||
b32 is_corner = 0;
|
||||
f32 non_corner_edge_dist = MinF32(MinF32(point.x - p0.x, p1.x - point.x), MinF32(point.y - p0.y, p1.y - point.y));
|
||||
@ -1310,9 +1311,16 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
|
||||
}
|
||||
}
|
||||
// Solve floating violation
|
||||
if (is_floating && new_size > box_size && !AnyBit(child->desc.flags, UI_BoxFlag_NoFloatingClamp))
|
||||
if (is_floating && new_size > box_size)
|
||||
{
|
||||
new_size = MaxF32(new_size - flex, box_size);
|
||||
b32 should_clamp = (
|
||||
!(axis == Axis_X && AnyBit(child->desc.flags, UI_BoxFlag_NoFloatingClampX)) &&
|
||||
!(axis == Axis_Y && AnyBit(child->desc.flags, UI_BoxFlag_NoFloatingClampY))
|
||||
);
|
||||
if (should_clamp)
|
||||
{
|
||||
new_size = MaxF32(new_size - flex, box_size);
|
||||
}
|
||||
}
|
||||
if (!is_floating)
|
||||
{
|
||||
@ -1451,13 +1459,19 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
|
||||
|
||||
// Compute rect
|
||||
Vec2 screen_pos = parent ? AddVec2(parent->screen_rect.p0, offset) : VEC2(0, 0);
|
||||
if (is_floating && !AnyBit(box->desc.flags, UI_BoxFlag_NoFloatingClamp))
|
||||
if (is_floating)
|
||||
{
|
||||
Vec2 overshoot = Zi;
|
||||
overshoot.x = MaxF32(0, (screen_pos.x + box->solved_dims.x) - parent->screen_rect.p1.x);
|
||||
overshoot.y = MaxF32((screen_pos.y + box->solved_dims.y) - parent->screen_rect.p1.y, 0);
|
||||
screen_pos.x = MaxF32(parent->screen_rect.p0.x, screen_pos.x - overshoot.x);
|
||||
screen_pos.y = MaxF32(parent->screen_rect.p0.y, screen_pos.y - overshoot.y);
|
||||
if (!AnyBit(box->desc.flags, UI_BoxFlag_NoFloatingClampX))
|
||||
{
|
||||
overshoot.x = MaxF32(0, (screen_pos.x + box->solved_dims.x) - parent->screen_rect.p1.x);
|
||||
screen_pos.x = MaxF32(parent->screen_rect.p0.x, screen_pos.x - overshoot.x);
|
||||
}
|
||||
if (!AnyBit(box->desc.flags, UI_BoxFlag_NoFloatingClampY))
|
||||
{
|
||||
overshoot.y = MaxF32((screen_pos.y + box->solved_dims.y) - parent->screen_rect.p1.y, 0);
|
||||
screen_pos.y = MaxF32(parent->screen_rect.p0.y, screen_pos.y - overshoot.y);
|
||||
}
|
||||
}
|
||||
box->screen_rect.p0 = screen_pos;
|
||||
box->screen_rect.p1 = AddVec2(box->screen_rect.p0, box->solved_dims);
|
||||
@ -1470,6 +1484,19 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
|
||||
}
|
||||
}
|
||||
|
||||
// Solve scissor
|
||||
{
|
||||
box->solved_scissor = Rng2Inf;
|
||||
if (box->desc.flags & UI_BoxFlag_Scissor)
|
||||
{
|
||||
box->solved_scissor = box->screen_rect;
|
||||
}
|
||||
if (parent)
|
||||
{
|
||||
box->solved_scissor = IntersectRng2(box->solved_scissor, parent->solved_scissor);
|
||||
}
|
||||
}
|
||||
|
||||
// Solve screen rounding
|
||||
{
|
||||
UI_Round rounding = box->desc.rounding;
|
||||
@ -1500,7 +1527,8 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
|
||||
}
|
||||
|
||||
// Clamp rounding based on parent rounding
|
||||
if (parent && !AllBits(box->desc.flags, UI_BoxFlag_Floating | UI_BoxFlag_NoFloatingClamp))
|
||||
// if (parent && !AllBits(box->desc.flags, UI_BoxFlag_Floating | UI_BoxFlag_NoFloatingClamp))
|
||||
if (parent)
|
||||
{
|
||||
Vec2 vtl = SubVec2(VEC2(parent->screen_rect.p0.x, parent->screen_rect.p0.y), VEC2(box->screen_rect.p0.x, box->screen_rect.p0.y));
|
||||
Vec2 vtr = SubVec2(VEC2(parent->screen_rect.p1.x, parent->screen_rect.p0.y), VEC2(box->screen_rect.p1.x, box->screen_rect.p0.y));
|
||||
@ -1529,7 +1557,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
|
||||
//////////////////////////////
|
||||
//- Build render data
|
||||
|
||||
// Build rect instance data
|
||||
// Build GPU rect data
|
||||
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
|
||||
{
|
||||
UI_Box *box = boxes_pre[pre_index];
|
||||
@ -1537,21 +1565,22 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
|
||||
GC_Run raw_run = UI_ScaleRun(frame->arena, raw_run_unscaled, box->solved_scale);
|
||||
|
||||
// TODO: Check that sprite image is not empty
|
||||
b32 is_visible = 1;
|
||||
is_visible = is_visible && (box->desc.tint.w >= 0.0025);
|
||||
is_visible = is_visible && (box->screen_rect.p1.x - box->screen_rect.p0.x > 0.0025);
|
||||
is_visible = is_visible && (box->screen_rect.p1.y - box->screen_rect.p0.y > 0.0025);
|
||||
is_visible = is_visible && (
|
||||
b32 should_upload = 1;
|
||||
should_upload = should_upload && (box->desc.tint.w >= 0.0025);
|
||||
should_upload = should_upload && (box->screen_rect.p1.x - box->screen_rect.p0.x > 0.0025);
|
||||
should_upload = should_upload && (box->screen_rect.p1.y - box->screen_rect.p0.y > 0.0025);
|
||||
should_upload = should_upload && (
|
||||
!G_IsRefNil(box->raw_texture) ||
|
||||
!SPR_IsSheetKeyNil(box->desc.sprite_sheet) ||
|
||||
(AnyBit(box->desc.flags, UI_BoxFlag_DrawText) && raw_run.ready) ||
|
||||
box->desc.tint.a * box->desc.background_color.a >= 0.0025 ||
|
||||
box->desc.tint.a * box->desc.border_color.a >= 0.0025
|
||||
);
|
||||
should_upload = should_upload && (!IsRng2Empty(IntersectRng2(box->screen_rect, box->solved_scissor)));
|
||||
|
||||
if (is_visible || AnyBit(frame->frame_flags, UI_FrameFlag_Debug))
|
||||
if (should_upload || AnyBit(frame->frame_flags, UI_FrameFlag_Debug))
|
||||
{
|
||||
Vec4 debug_lin = is_visible ? LinearFromSrgb(box->desc.debug_color) : LinearFromSrgb(box->desc.invisible_debug_color);
|
||||
Vec4 debug_lin = should_upload ? LinearFromSrgb(box->desc.debug_color) : LinearFromSrgb(box->desc.invisible_debug_color);
|
||||
Vec4 tint_lin = LinearFromSrgb(box->desc.tint);
|
||||
Vec2 box_dims = DimsFromRng2(box->screen_rect);
|
||||
UI_RegionPair child_alignment = UI_PairFromRegion(box->desc.child_alignment);
|
||||
@ -1562,6 +1591,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
|
||||
{
|
||||
UI_GpuRect *rect = PushStruct(frame->rects_arena, UI_GpuRect);
|
||||
rect->bounds = box->screen_rect;
|
||||
rect->scissor = box->solved_scissor;
|
||||
rect->background_lin = LinearFromSrgb(box->desc.background_color);
|
||||
rect->border_lin = LinearFromSrgb(box->desc.border_color);
|
||||
rect->debug_lin = debug_lin;
|
||||
@ -1695,6 +1725,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
|
||||
rect->bounds = rr.bounds;
|
||||
rect->bounds = AddRng2Vec2(rect->bounds, baseline);
|
||||
rect->bounds = AddRng2Vec2(rect->bounds, VEC2(rr.baseline_pos, 0));
|
||||
rect->scissor = box->solved_scissor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,7 +90,9 @@ Enum(UI_BoxFlag)
|
||||
UI_BoxFlag_CaptureMouse = (1 << 1),
|
||||
UI_BoxFlag_NoTextTruncation = (1 << 2),
|
||||
UI_BoxFlag_Floating = (1 << 3),
|
||||
UI_BoxFlag_NoFloatingClamp = (1 << 4),
|
||||
UI_BoxFlag_NoFloatingClampX = (1 << 4),
|
||||
UI_BoxFlag_NoFloatingClampY = (1 << 5),
|
||||
UI_BoxFlag_Scissor = (1 << 6),
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -322,6 +324,7 @@ Struct(UI_Box)
|
||||
|
||||
//- Layout data
|
||||
Vec2 solved_scale;
|
||||
Rng2 solved_scissor;
|
||||
Vec2 final_children_size_accum;
|
||||
Vec2 solved_dims;
|
||||
f32 cursor;
|
||||
|
||||
@ -79,9 +79,6 @@ PixelShader(UI_DRectPS, UI_DRectPSOutput, UI_DRectPSInput input)
|
||||
}
|
||||
}
|
||||
|
||||
//- Compute borer color
|
||||
Vec4 border_premul = input.base_border_premul;
|
||||
|
||||
//- Compute border dist
|
||||
f32 border_dist = 0;
|
||||
border_dist = abs(rect_dist);
|
||||
@ -90,6 +87,9 @@ PixelShader(UI_DRectPS, UI_DRectPSOutput, UI_DRectPSInput input)
|
||||
border_dist -= rect.border_size;
|
||||
}
|
||||
|
||||
//- Compute borer color
|
||||
Vec4 border_premul = input.base_border_premul;
|
||||
|
||||
//- Compute anti-aliased border-over-background color
|
||||
Vec4 composite_premul = 0;
|
||||
{
|
||||
@ -98,8 +98,16 @@ PixelShader(UI_DRectPS, UI_DRectPSOutput, UI_DRectPSInput input)
|
||||
composite_premul = lerp(background_premul, border_premul, border_coverage);
|
||||
}
|
||||
|
||||
//- Finalize
|
||||
Vec4 result = composite_premul * input.tint_premul;
|
||||
|
||||
//- Scissor
|
||||
// FIXME: Inclusive
|
||||
if (p.x < rect.scissor.p0.x || p.x > rect.scissor.p1.x || p.y < rect.scissor.p0.y || p.y > rect.scissor.p1.y)
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
//- Finalize
|
||||
if (UI_GpuConst_DebugDraw)
|
||||
{
|
||||
result = input.debug_premul;
|
||||
|
||||
@ -10,6 +10,7 @@ G_DeclConstant(b32, UI_GpuConst_DebugDraw, 1);
|
||||
Struct(UI_GpuRect)
|
||||
{
|
||||
Rng2 bounds;
|
||||
Rng2 scissor;
|
||||
|
||||
G_TextureRef tex;
|
||||
Rng2 tex_slice_uv;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user