add scrolling using mouse wheel

This commit is contained in:
Rokas Puzonas 2025-02-07 01:15:13 +02:00
parent 401056b676
commit eb97a0d832

View File

@ -158,7 +158,8 @@ pub const Key = struct {
pub const Event = union(enum) { pub const Event = union(enum) {
mouse_pressed: rl.MouseButton, mouse_pressed: rl.MouseButton,
mouse_released: rl.MouseButton, mouse_released: rl.MouseButton,
mouse_move: Vec2 mouse_move: Vec2,
mouse_scroll: Vec2
}; };
pub const Signal = struct { pub const Signal = struct {
@ -173,11 +174,14 @@ pub const Signal = struct {
right_clicked, right_clicked,
left_dragging, left_dragging,
right_dragging right_dragging,
scrolled
}; };
flags: std.EnumSet(Flag) = .{}, flags: std.EnumSet(Flag) = .{},
drag: Vec2 = .{ .x = 0, .y = 0 }, drag: Vec2 = .{ .x = 0, .y = 0 },
scroll: Vec2 = .{ .x = 0, .y = 0 },
pub fn clicked(self: Signal) bool { pub fn clicked(self: Signal) bool {
return self.flags.contains(.left_clicked) or self.flags.contains(.right_clicked); 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); 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 { fn insertMousePressed(self: *Signal, mouse_button: rl.MouseButton) void {
if (mouse_button == .mouse_button_left) { if (mouse_button == .mouse_button_left) {
self.flags.insert(.left_pressed); self.flags.insert(.left_pressed);
@ -237,6 +245,8 @@ pub const Box = struct {
draggable_x, draggable_x,
draggable_y, draggable_y,
scrollable,
fixed_x, fixed_x,
fixed_y, fixed_y,
fixed_width, 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); const root_box = self.newBox(root_box_key);
root_box.size.x = Size.pixels(@floatFromInt(window_width), 1); root_box.size.x = Size.pixels(@floatFromInt(window_width), 1);
root_box.size.y = Size.pixels(@floatFromInt(window_height), 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 key = box.key;
const clickable = box.flags.contains(.clickable); const clickable = box.flags.contains(.clickable);
const draggable = box.flags.contains(.draggable_x) or box.flags.contains(.draggable_y); 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); const is_mouse_inside = rect_utils.isInsideVec2(rect, self.mouse);
var event_index: usize = 0; var event_index: usize = 0;
@ -1055,6 +1071,13 @@ pub fn signalFromBox(self: *UI, box: *Box) Signal {
taken = true; 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) { if (taken) {
_ = self.events.swapRemove(event_index); _ = self.events.swapRemove(event_index);
} else { } else {
@ -1160,6 +1183,7 @@ pub fn pushScrollbar(self: *UI, key: UI.Key) *Box {
self.pushParent(container); self.pushParent(container);
const content_area = self.newBoxFromString("Scroll area"); const content_area = self.newBoxFromString("Scroll area");
content_area.flags.insert(.scrollable);
content_area.size = .{ content_area.size = .{
.x = UI.Size.percent(1, 0), .x = UI.Size.percent(1, 0),
.y = 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"); const scrollbar_area = self.newBoxFromString("Scrollbar area");
scrollbar_area.background = rl.Color.gold; scrollbar_area.background = rl.Color.gold;
scrollbar_area.flags.insert(.scrollable);
scrollbar_area.size = .{ scrollbar_area.size = .{
.x = UI.Size.pixels(24, 1), .x = UI.Size.pixels(24, 1),
.y = UI.Size.percent(1, 0), .y = UI.Size.percent(1, 0),
@ -1206,11 +1231,23 @@ pub fn popScrollbar(self: *UI) void {
const max_offset = scrollbar_height * (1 - visible_percent); const max_offset = scrollbar_height * (1 - visible_percent);
draggable.setFixedY(scrollbar_area.persistent.position.y + sroll_offset.* * max_offset); draggable.setFixedY(scrollbar_area.persistent.position.y + sroll_offset.* * max_offset);
const signal = self.signalFromBox(draggable); const draggable_signal = self.signalFromBox(draggable);
if (signal.dragged()) { if (draggable_signal.dragged()) {
sroll_offset.* += signal.drag.y / max_offset; sroll_offset.* += draggable_signal.drag.y / max_offset;
sroll_offset.* = clamp(sroll_offset.*, 0, 1);
} }
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 self.popParent(); // pop container
} }