mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-04 03:37:59 -04:00
Add a Label component.
This commit is contained in:
parent
7ce9dc8716
commit
82ad5f2b98
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
39
src/gui/components/Label.zig
Normal file
39
src/gui/components/Label.zig
Normal file
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user