add mouse clipping to hidden boxes from scrolling
This commit is contained in:
parent
d744ab4b6b
commit
401056b676
@ -198,3 +198,16 @@ pub fn aligned(rect: Rect, align_x: AlignX, align_y: AlignY) rl.Vector2 {
|
||||
|
||||
return rl.Vector2.init(x, y);
|
||||
}
|
||||
|
||||
pub fn intersect(rect: Rect, other: Rect) Rect {
|
||||
const left_pos = @max(left(rect), left(other));
|
||||
const top_pos = @max(top(rect), top(other));
|
||||
const right_pos = @min(right(rect), right(other));
|
||||
const bottom_pos = @min(bottom(rect), bottom(other));
|
||||
return Rect{
|
||||
.x = left_pos,
|
||||
.y = top_pos,
|
||||
.width = right_pos - left_pos,
|
||||
.height = bottom_pos - top_pos
|
||||
};
|
||||
}
|
32
src/ui.zig
32
src/ui.zig
@ -378,6 +378,10 @@ pub const Box = struct {
|
||||
|
||||
return self.flags.contains(flag);
|
||||
}
|
||||
|
||||
fn hasClipping(self: *Box) bool {
|
||||
return self.view_offset.equals(Vec2.zero()) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
const BoxChildIterator = struct {
|
||||
@ -627,7 +631,7 @@ pub fn draw(self: *UI) void {
|
||||
fn drawBox(self: *UI, box: *Box) void {
|
||||
const box_rect = box.computedRect();
|
||||
|
||||
const do_scissor = box.view_offset.equals(Vec2.zero()) == 0;
|
||||
const do_scissor = box.hasClipping();
|
||||
if (do_scissor) {
|
||||
rl.beginScissorMode(
|
||||
@intFromFloat(box_rect.x),
|
||||
@ -1004,11 +1008,20 @@ fn findBoxByKey(self: *UI, key: Key) ?*Box {
|
||||
pub fn signalFromBox(self: *UI, box: *Box) Signal {
|
||||
var result = Signal{};
|
||||
|
||||
var rect = box.computedRect();
|
||||
{
|
||||
var parent_iter = self.iterUpwardByParent(box);
|
||||
while (parent_iter.next()) |parent| {
|
||||
if (parent.hasClipping()) {
|
||||
rect = rect_utils.intersect(rect, parent.computedRect());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const key = box.key;
|
||||
const rect = box.computedRect();
|
||||
const is_mouse_inside = rect_utils.isInsideVec2(rect, self.mouse);
|
||||
const clickable = box.flags.contains(.clickable);
|
||||
const draggable = box.flags.contains(.draggable_x) or box.flags.contains(.draggable_y);
|
||||
const is_mouse_inside = rect_utils.isInsideVec2(rect, self.mouse);
|
||||
|
||||
var event_index: usize = 0;
|
||||
while (event_index < self.events.len) {
|
||||
@ -1153,6 +1166,12 @@ pub fn pushScrollbar(self: *UI, key: UI.Key) *Box {
|
||||
};
|
||||
self.pushParent(content_area);
|
||||
|
||||
const visible_content_size = content_area.persistent.size.y;
|
||||
const used_content_size = content_area.persistent.children_size.y;
|
||||
const visible_percent = clamp(visible_content_size / used_content_size, 0, 1);
|
||||
const sroll_offset = content_area.persistent.sroll_offset;
|
||||
content_area.view_offset.y = sroll_offset * (1 - visible_percent) * used_content_size;
|
||||
|
||||
return content_area;
|
||||
}
|
||||
|
||||
@ -1182,19 +1201,16 @@ pub fn popScrollbar(self: *UI) void {
|
||||
.y = UI.Size.percent(visible_percent, 1),
|
||||
};
|
||||
|
||||
const sroll_offset = &content_area.persistent.sroll_offset;
|
||||
const scrollbar_height = scrollbar_area.persistent.size.y;
|
||||
|
||||
const max_offset = scrollbar_height * (1 - visible_percent);
|
||||
draggable.setFixedY(scrollbar_area.persistent.position.y + sroll_offset.* * max_offset);
|
||||
|
||||
const sroll_offset = &draggable.persistent.sroll_offset;
|
||||
const signal = self.signalFromBox(draggable);
|
||||
if (signal.dragged()) {
|
||||
sroll_offset.* += signal.drag.y / max_offset;
|
||||
sroll_offset.* = clamp(sroll_offset.*, 0, 1);
|
||||
}
|
||||
|
||||
draggable.setFixedY(scrollbar_area.persistent.position.y + sroll_offset.* * max_offset);
|
||||
content_area.view_offset.y = sroll_offset.* * (1 - visible_percent) * used_content_size;
|
||||
|
||||
self.popParent(); // pop container
|
||||
}
|
Loading…
Reference in New Issue
Block a user