From eb97a0d832d31ea7934a9ebc68f1fce77a7440a6 Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Fri, 7 Feb 2025 01:15:13 +0200 Subject: [PATCH] add scrolling using mouse wheel --- src/ui.zig | 49 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/src/ui.zig b/src/ui.zig index 48fc372..d9bac54 100644 --- a/src/ui.zig +++ b/src/ui.zig @@ -158,7 +158,8 @@ pub const Key = struct { pub const Event = union(enum) { mouse_pressed: rl.MouseButton, mouse_released: rl.MouseButton, - mouse_move: Vec2 + mouse_move: Vec2, + mouse_scroll: Vec2 }; pub const Signal = struct { @@ -173,11 +174,14 @@ pub const Signal = struct { right_clicked, left_dragging, - right_dragging + right_dragging, + + scrolled }; flags: std.EnumSet(Flag) = .{}, drag: Vec2 = .{ .x = 0, .y = 0 }, + scroll: Vec2 = .{ .x = 0, .y = 0 }, pub fn clicked(self: Signal) bool { return self.flags.contains(.left_clicked) or self.flags.contains(.right_clicked); @@ -187,6 +191,10 @@ pub const Signal = struct { return self.flags.contains(.left_dragging) or self.flags.contains(.right_dragging); } + pub fn scrolled(self: Signal) bool { + return self.flags.contains(.scrolled); + } + fn insertMousePressed(self: *Signal, mouse_button: rl.MouseButton) void { if (mouse_button == .mouse_button_left) { self.flags.insert(.left_pressed); @@ -237,6 +245,8 @@ pub const Box = struct { draggable_x, draggable_y, + scrollable, + fixed_x, fixed_y, fixed_width, @@ -503,6 +513,11 @@ pub fn begin(self: *UI) void { } } + const mouse_wheel = rl.getMouseWheelMoveV(); + if (mouse_wheel.x != 0 or mouse_wheel.y != 0) { + self.events.appendAssumeCapacity(Event{ .mouse_scroll = mouse_wheel }); + } + const root_box = self.newBox(root_box_key); root_box.size.x = Size.pixels(@floatFromInt(window_width), 1); root_box.size.y = Size.pixels(@floatFromInt(window_height), 1); @@ -1021,6 +1036,7 @@ pub fn signalFromBox(self: *UI, box: *Box) Signal { const key = box.key; const clickable = box.flags.contains(.clickable); const draggable = box.flags.contains(.draggable_x) or box.flags.contains(.draggable_y); + const scrollable = box.flags.contains(.scrollable); const is_mouse_inside = rect_utils.isInsideVec2(rect, self.mouse); var event_index: usize = 0; @@ -1055,6 +1071,13 @@ pub fn signalFromBox(self: *UI, box: *Box) Signal { taken = true; } + if (event == .mouse_scroll and is_mouse_inside and scrollable) { + result.scroll = event.mouse_scroll; + result.flags.insert(.scrolled); + + taken = true; + } + if (taken) { _ = self.events.swapRemove(event_index); } else { @@ -1160,6 +1183,7 @@ pub fn pushScrollbar(self: *UI, key: UI.Key) *Box { self.pushParent(container); const content_area = self.newBoxFromString("Scroll area"); + content_area.flags.insert(.scrollable); content_area.size = .{ .x = UI.Size.percent(1, 0), .y = UI.Size.percent(1, 0), @@ -1181,6 +1205,7 @@ pub fn popScrollbar(self: *UI) void { const scrollbar_area = self.newBoxFromString("Scrollbar area"); scrollbar_area.background = rl.Color.gold; + scrollbar_area.flags.insert(.scrollable); scrollbar_area.size = .{ .x = UI.Size.pixels(24, 1), .y = UI.Size.percent(1, 0), @@ -1206,11 +1231,23 @@ pub fn popScrollbar(self: *UI) void { const max_offset = scrollbar_height * (1 - visible_percent); draggable.setFixedY(scrollbar_area.persistent.position.y + sroll_offset.* * max_offset); - const signal = self.signalFromBox(draggable); - if (signal.dragged()) { - sroll_offset.* += signal.drag.y / max_offset; - sroll_offset.* = clamp(sroll_offset.*, 0, 1); + const draggable_signal = self.signalFromBox(draggable); + if (draggable_signal.dragged()) { + sroll_offset.* += draggable_signal.drag.y / max_offset; } + const scroll_speed = 16; + const scrollbar_signal = self.signalFromBox(scrollbar_area); + if (scrollbar_signal.scrolled()) { + sroll_offset.* -= scrollbar_signal.scroll.y / max_offset * scroll_speed; + } + + const content_area_signal = self.signalFromBox(content_area); + if (content_area_signal.scrolled()) { + sroll_offset.* -= content_area_signal.scroll.y / max_offset * scroll_speed; + } + + sroll_offset.* = clamp(sroll_offset.*, 0, 1); + self.popParent(); // pop container } \ No newline at end of file