diff --git a/src/gui/GuiComponent.zig b/src/gui/GuiComponent.zig index 365a012d..6c39420b 100644 --- a/src/gui/GuiComponent.zig +++ b/src/gui/GuiComponent.zig @@ -4,8 +4,9 @@ const main = @import("root"); const vec = main.vec; const Vec2f = vec.Vec2f; -const Button = @import("components/Button.zig"); -const VerticalList = @import("components/VerticalList.zig"); +pub const Button = @import("components/Button.zig"); +pub const Label = @import("components/Label.zig"); +pub const VerticalList = @import("components/VerticalList.zig"); const GuiComponent = @This(); @@ -15,6 +16,7 @@ impl: Impl, const Impl = union(enum) { button: Button, + label: Label, verticalList: VerticalList, }; @@ -37,7 +39,7 @@ pub fn update(self: *GuiComponent) void { // Only call the function if it exists: inline for(@typeInfo(@TypeOf(impl.*)).Struct.decls) |decl| { if(comptime std.mem.eql(u8, decl.name, "update")) { - impl.update(self); + impl.update(self.pos, self.size); } } } @@ -50,7 +52,7 @@ pub fn render(self: *GuiComponent, mousePosition: Vec2f) !void { // Only call the function if it exists: inline for(@typeInfo(@TypeOf(impl.*)).Struct.decls) |decl| { if(comptime std.mem.eql(u8, decl.name, "render")) { - try impl.render(self, mousePosition); + try impl.render(self.pos, self.size, mousePosition); } } } @@ -63,7 +65,7 @@ pub fn mainButtonPressed(self: *GuiComponent, mousePosition: Vec2f) void { // Only call the function if it exists: inline for(@typeInfo(@TypeOf(impl.*)).Struct.decls) |decl| { if(comptime std.mem.eql(u8, decl.name, "mainButtonPressed")) { - impl.mainButtonPressed(self, mousePosition); + impl.mainButtonPressed(self.pos, self.size, mousePosition); } } } @@ -76,13 +78,13 @@ pub fn mainButtonReleased(self: *GuiComponent, mousePosition: Vec2f) void { // Only call the function if it exists: inline for(@typeInfo(@TypeOf(impl.*)).Struct.decls) |decl| { if(comptime std.mem.eql(u8, decl.name, "mainButtonReleased")) { - impl.mainButtonReleased(self, mousePosition); + impl.mainButtonReleased(self.pos, self.size, mousePosition); } } } } } -pub fn contains(self: GuiComponent, pos: Vec2f) bool { - return @reduce(.And, pos >= self.pos) and @reduce(.And, pos < self.pos + self.size); +pub fn contains(pos: Vec2f, size: Vec2f, point: Vec2f) bool { + return @reduce(.And, point >= pos) and @reduce(.And, point < pos + size); } \ No newline at end of file diff --git a/src/gui/GuiWindow.zig b/src/gui/GuiWindow.zig index 7663cfd0..e01e7631 100644 --- a/src/gui/GuiWindow.zig +++ b/src/gui/GuiWindow.zig @@ -120,7 +120,7 @@ pub fn mainButtonPressed(self: *const GuiWindow) void { } else { var selectedComponent: ?*GuiComponent = null; for(self.components) |*component| { - if(component.contains(mousePosition)) { + if(GuiComponent.contains(component.pos, component.size, mousePosition)) { selectedComponent = component; } } diff --git a/src/gui/components/Button.zig b/src/gui/components/Button.zig index d84c7ccd..10d84ca2 100644 --- a/src/gui/components/Button.zig +++ b/src/gui/components/Button.zig @@ -14,6 +14,7 @@ const Vec2f = vec.Vec2f; const gui = @import("../gui.zig"); const GuiComponent = gui.GuiComponent; +const Label = GuiComponent.Label; const Button = @This(); @@ -36,8 +37,8 @@ var buttonUniforms: struct { pressed: bool = false, onAction: *const fn() void, -text: TextBuffer, -textSize: Vec2f = undefined, +textSize: Vec2f, +label: Label, randomOffset: Vec2f = undefined, pub fn __init() !void { @@ -57,40 +58,41 @@ pub fn __deinit() void { } pub fn init(pos: Vec2f, width: f32, allocator: Allocator, text: []const u8, onAction: *const fn() void) Allocator.Error!GuiComponent { + const labelComponent = try Label.init(allocator, undefined, width - 3*border, text); var self = Button { .onAction = onAction, - .text = try TextBuffer.init(allocator, text, .{}, false), + .label = labelComponent.impl.label, + .textSize = labelComponent.size, .randomOffset = Vec2f{ random.nextFloat(&main.seed), random.nextFloat(&main.seed), }, }; - self.textSize = try self.text.calculateLineBreaks(fontSize, width - 3*border); return GuiComponent { .pos = pos, - .size = .{@max(width, self.textSize[0] + 3*border), self.textSize[1] + 3*border}, + .size = Vec2f{@max(width, self.textSize[0] + 3*border), self.textSize[1] + 3*border}, .impl = .{.button = self} }; } pub fn deinit(self: Button) void { - self.text.deinit(); + self.label.deinit(); } -pub fn mainButtonPressed(self: *Button, _: *const GuiComponent, _: Vec2f) void { +pub fn mainButtonPressed(self: *Button, _: Vec2f, _: Vec2f, _: Vec2f) void { self.pressed = true; } -pub fn mainButtonReleased(self: *Button, component: *const GuiComponent, mousePosition: Vec2f) void { +pub fn mainButtonReleased(self: *Button, pos: Vec2f, size: Vec2f, mousePosition: Vec2f) void { if(self.pressed) { self.pressed = false; - if(component.contains(mousePosition)) { + if(GuiComponent.contains(pos, size, mousePosition)) { self.onAction(); } } } -pub fn render(self: *Button, component: *const GuiComponent, mousePosition: Vec2f) !void { +pub fn render(self: *Button, pos: Vec2f, size: Vec2f, mousePosition: Vec2f) !void { graphics.c.glActiveTexture(graphics.c.GL_TEXTURE0); texture.bind(); shader.bind(); @@ -99,12 +101,12 @@ pub fn render(self: *Button, component: *const GuiComponent, mousePosition: Vec2 if(self.pressed) { draw.setColor(0xff000000); graphics.c.glUniform1i(buttonUniforms.pressed, 1); - } else if(component.contains(mousePosition)) { + } else if(GuiComponent.contains(pos, size, mousePosition)) { draw.setColor(0xff000040); } else { draw.setColor(0xff000000); } - draw.customShadedRect(buttonUniforms, component.pos, component.size); - const textPos = component.pos + component.size/@splat(2, @as(f32, 2.0)) - self.textSize/@splat(2, @as(f32, 2.0)); - try self.text.render(textPos[0], textPos[1], fontSize); + draw.customShadedRect(buttonUniforms, pos, size); + const textPos = pos + size/@splat(2, @as(f32, 2.0)) - self.textSize/@splat(2, @as(f32, 2.0)); + try self.label.render(textPos, self.textSize, mousePosition - textPos); } \ No newline at end of file diff --git a/src/gui/components/Label.zig b/src/gui/components/Label.zig new file mode 100644 index 00000000..74b94f68 --- /dev/null +++ b/src/gui/components/Label.zig @@ -0,0 +1,39 @@ +const std = @import("std"); +const Allocator = std.mem.Allocator; + +const main = @import("root"); +const graphics = main.graphics; +const draw = graphics.draw; +const TextBuffer = graphics.TextBuffer; +const vec = main.vec; +const Vec2f = vec.Vec2f; + +const gui = @import("../gui.zig"); +const GuiComponent = gui.GuiComponent; + +const Label = @This(); + +const fontSize: f32 = 16; + +text: TextBuffer, +textSize: Vec2f = undefined, + +pub fn init(allocator: Allocator, pos: Vec2f, maxWidth: f32, text: []const u8) Allocator.Error!GuiComponent { + var self = Label { + .text = try TextBuffer.init(allocator, text, .{}, false), + }; + self.textSize = try self.text.calculateLineBreaks(fontSize, maxWidth); + return GuiComponent { + .pos = pos, + .size = self.textSize, + .impl = .{.label = self} + }; +} + +pub fn deinit(self: Label) void { + self.text.deinit(); +} + +pub fn render(self: *Label, pos: Vec2f, _: Vec2f, _: Vec2f) !void { + try self.text.render(pos[0], pos[1], fontSize); +} \ No newline at end of file diff --git a/src/gui/components/VerticalList.zig b/src/gui/components/VerticalList.zig index 0b50dc2f..c70d2489 100644 --- a/src/gui/components/VerticalList.zig +++ b/src/gui/components/VerticalList.zig @@ -50,22 +50,22 @@ pub fn add(self: *VerticalList, other: GuiComponent) Allocator.Error!void { self.maxWidth = @max(self.maxWidth, added.pos[0] + added.size[0]); } -pub fn update(self: *VerticalList, _: *const GuiComponent) void { +pub fn update(self: *VerticalList, _: Vec2f, _: Vec2f) void { for(self.children.items) |*child| { child.update(); } } -pub fn render(self: *VerticalList, _: *const GuiComponent, mousePosition: Vec2f) anyerror!void { // TODO: Remove anyerror once error union inference works in recursive loops. +pub fn render(self: *VerticalList, _: Vec2f, _: Vec2f, mousePosition: Vec2f) anyerror!void { // TODO: Remove anyerror once error union inference works in recursive loops. for(self.children.items) |*child| { try child.render(mousePosition); } } -pub fn mainButtonPressed(self: *VerticalList, _: *const GuiComponent, mousePosition: Vec2f) void { +pub fn mainButtonPressed(self: *VerticalList, _: Vec2f, _: Vec2f, mousePosition: Vec2f) void { var selectedChild: ?*GuiComponent = null; for(self.children.items) |*child| { - if(child.contains(mousePosition)) { + if(GuiComponent.contains(child.pos, child.size, mousePosition)) { selectedChild = child; } } @@ -74,7 +74,7 @@ pub fn mainButtonPressed(self: *VerticalList, _: *const GuiComponent, mousePosit } } -pub fn mainButtonReleased(self: *VerticalList, _: *const GuiComponent, mousePosition: Vec2f) void { +pub fn mainButtonReleased(self: *VerticalList, _: Vec2f, _: Vec2f, mousePosition: Vec2f) void { for(self.children.items) |*child| { child.mainButtonReleased(mousePosition); }