mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-09-09 12:16:24 -04:00
Refactor how components are handled.
- A `GuiComponent` now is union of pointers. - `pos` and `size` are now stored in each component rather than being passed down through functions.
This commit is contained in:
parent
fd0e903431
commit
5c74694611
@ -1,111 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
|
|
||||||
const main = @import("root");
|
|
||||||
const vec = main.vec;
|
|
||||||
const Vec2f = vec.Vec2f;
|
|
||||||
|
|
||||||
pub const Button = @import("components/Button.zig");
|
|
||||||
pub const CheckBox = @import("components/CheckBox.zig");
|
|
||||||
pub const Label = @import("components/Label.zig");
|
|
||||||
pub const Slider = @import("components/Slider.zig");
|
|
||||||
pub const ScrollBar = @import("components/ScrollBar.zig");
|
|
||||||
pub const TextInput = @import("components/TextInput.zig");
|
|
||||||
pub const VerticalList = @import("components/VerticalList.zig");
|
|
||||||
|
|
||||||
const GuiComponent = @This();
|
|
||||||
|
|
||||||
pos: Vec2f,
|
|
||||||
size: Vec2f,
|
|
||||||
impl: Impl,
|
|
||||||
|
|
||||||
const Impl = union(enum) {
|
|
||||||
button: Button,
|
|
||||||
checkBox: CheckBox,
|
|
||||||
label: Label,
|
|
||||||
scrollBar: ScrollBar,
|
|
||||||
slider: Slider,
|
|
||||||
textInput: TextInput,
|
|
||||||
verticalList: VerticalList,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn deinit(self: *GuiComponent) void {
|
|
||||||
switch(self.impl) {
|
|
||||||
inline else => |*impl| {
|
|
||||||
// Only call the function if it exists:
|
|
||||||
inline for(@typeInfo(@TypeOf(impl.*)).Struct.decls) |decl| {
|
|
||||||
if(comptime std.mem.eql(u8, decl.name, "deinit")) {
|
|
||||||
impl.deinit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn updateSelected(self: *GuiComponent) void {
|
|
||||||
switch(self.impl) {
|
|
||||||
inline else => |*impl| {
|
|
||||||
// Only call the function if it exists:
|
|
||||||
inline for(@typeInfo(@TypeOf(impl.*)).Struct.decls) |decl| {
|
|
||||||
if(comptime std.mem.eql(u8, decl.name, "updateSelected")) {
|
|
||||||
impl.updateSelected(self.pos, self.size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn updateHovered(self: *GuiComponent, mousePosition: Vec2f) void {
|
|
||||||
switch(self.impl) {
|
|
||||||
inline else => |*impl| {
|
|
||||||
// Only call the function if it exists:
|
|
||||||
inline for(@typeInfo(@TypeOf(impl.*)).Struct.decls) |decl| {
|
|
||||||
if(comptime std.mem.eql(u8, decl.name, "updateHovered")) {
|
|
||||||
impl.updateHovered(self.pos, self.size, mousePosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render(self: *GuiComponent, mousePosition: Vec2f) !void {
|
|
||||||
switch(self.impl) {
|
|
||||||
inline else => |*impl| {
|
|
||||||
// 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.pos, self.size, mousePosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mainButtonPressed(self: *GuiComponent, mousePosition: Vec2f) void {
|
|
||||||
switch(self.impl) {
|
|
||||||
inline else => |*impl| {
|
|
||||||
// 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.pos, self.size, mousePosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mainButtonReleased(self: *GuiComponent, mousePosition: Vec2f) void {
|
|
||||||
switch(self.impl) {
|
|
||||||
inline else => |*impl| {
|
|
||||||
// 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.pos, self.size, mousePosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn contains(pos: Vec2f, size: Vec2f, point: Vec2f) bool {
|
|
||||||
return @reduce(.And, point >= pos) and @reduce(.And, point < pos + size);
|
|
||||||
}
|
|
@ -119,7 +119,7 @@ pub fn mainButtonPressed(self: *const GuiWindow, mousePosition: Vec2f) void {
|
|||||||
} else {
|
} else {
|
||||||
var selectedComponent: ?*GuiComponent = null;
|
var selectedComponent: ?*GuiComponent = null;
|
||||||
for(self.components) |*component| {
|
for(self.components) |*component| {
|
||||||
if(GuiComponent.contains(component.pos, component.size, scaledMousePos)) {
|
if(GuiComponent.contains(component.pos(), component.size(), scaledMousePos)) {
|
||||||
selectedComponent = component;
|
selectedComponent = component;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,7 +326,7 @@ pub fn updateHovered(self: *GuiWindow, mousePosition: Vec2f) !void {
|
|||||||
while(i != 0) {
|
while(i != 0) {
|
||||||
i -= 1;
|
i -= 1;
|
||||||
const component = &self.components[i];
|
const component = &self.components[i];
|
||||||
if(GuiComponent.contains(component.pos, component.size, (mousePosition - self.pos)/@splat(2, self.scale))) {
|
if(GuiComponent.contains(component.pos(), component.size(), (mousePosition - self.pos)/@splat(2, self.scale))) {
|
||||||
component.updateHovered((mousePosition - self.pos)/@splat(2, self.scale));
|
component.updateHovered((mousePosition - self.pos)/@splat(2, self.scale));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -32,11 +32,12 @@ pub var buttonUniforms: struct {
|
|||||||
pressed: c_int,
|
pressed: c_int,
|
||||||
} = undefined;
|
} = undefined;
|
||||||
|
|
||||||
|
pos: Vec2f,
|
||||||
|
size: Vec2f,
|
||||||
pressed: bool = false,
|
pressed: bool = false,
|
||||||
hovered: bool = false,
|
hovered: bool = false,
|
||||||
onAction: *const fn() void,
|
onAction: *const fn() void,
|
||||||
textSize: Vec2f,
|
label: *Label,
|
||||||
label: Label,
|
|
||||||
|
|
||||||
pub fn __init() !void {
|
pub fn __init() !void {
|
||||||
shader = try Shader.initAndGetUniforms("assets/cubyz/shaders/ui/button.vs", "assets/cubyz/shaders/ui/button.fs", &buttonUniforms);
|
shader = try Shader.initAndGetUniforms("assets/cubyz/shaders/ui/button.vs", "assets/cubyz/shaders/ui/button.fs", &buttonUniforms);
|
||||||
@ -52,42 +53,47 @@ pub fn __deinit() void {
|
|||||||
|
|
||||||
fn defaultOnAction() void {}
|
fn defaultOnAction() void {}
|
||||||
|
|
||||||
pub fn init(pos: Vec2f, width: f32, text: []const u8, onAction: ?*const fn() void) Allocator.Error!GuiComponent {
|
pub fn init(pos: Vec2f, width: f32, text: []const u8, onAction: ?*const fn() void) Allocator.Error!*Button {
|
||||||
const labelComponent = try Label.init(undefined, width - 3*border, text, .center);
|
const label = try Label.init(undefined, width - 3*border, text, .center);
|
||||||
var self = Button {
|
const self = try gui.allocator.create(Button);
|
||||||
.onAction = if(onAction) |a| a else &defaultOnAction,
|
self.* = Button {
|
||||||
.label = labelComponent.impl.label,
|
|
||||||
.textSize = labelComponent.size,
|
|
||||||
};
|
|
||||||
return GuiComponent {
|
|
||||||
.pos = pos,
|
.pos = pos,
|
||||||
.size = Vec2f{width, self.textSize[1] + 3*border},
|
.size = Vec2f{width, label.size[1] + 3*border},
|
||||||
.impl = .{.button = self}
|
.onAction = if(onAction) |a| a else &defaultOnAction,
|
||||||
|
.label = label,
|
||||||
|
};
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *const Button) void {
|
||||||
|
self.label.deinit();
|
||||||
|
gui.allocator.destroy(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toComponent(self: *Button) GuiComponent {
|
||||||
|
return GuiComponent {
|
||||||
|
.button = self
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Button) void {
|
pub fn updateHovered(self: *Button, _: Vec2f) void {
|
||||||
self.label.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn updateHovered(self: *Button, _: Vec2f, _: Vec2f, _: Vec2f) void {
|
|
||||||
self.hovered = true;
|
self.hovered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mainButtonPressed(self: *Button, _: Vec2f, _: Vec2f, _: Vec2f) void {
|
pub fn mainButtonPressed(self: *Button, _: Vec2f) void {
|
||||||
self.pressed = true;
|
self.pressed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mainButtonReleased(self: *Button, pos: Vec2f, size: Vec2f, mousePosition: Vec2f) void {
|
pub fn mainButtonReleased(self: *Button, mousePosition: Vec2f) void {
|
||||||
if(self.pressed) {
|
if(self.pressed) {
|
||||||
self.pressed = false;
|
self.pressed = false;
|
||||||
if(GuiComponent.contains(pos, size, mousePosition)) {
|
if(GuiComponent.contains(self.pos, self.size, mousePosition)) {
|
||||||
self.onAction();
|
self.onAction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(self: *Button, pos: Vec2f, size: Vec2f, mousePosition: Vec2f) !void {
|
pub fn render(self: *Button, mousePosition: Vec2f) !void {
|
||||||
graphics.c.glActiveTexture(graphics.c.GL_TEXTURE0);
|
graphics.c.glActiveTexture(graphics.c.GL_TEXTURE0);
|
||||||
texture.bind();
|
texture.bind();
|
||||||
shader.bind();
|
shader.bind();
|
||||||
@ -95,14 +101,15 @@ pub fn render(self: *Button, pos: Vec2f, size: Vec2f, mousePosition: Vec2f) !voi
|
|||||||
if(self.pressed) {
|
if(self.pressed) {
|
||||||
draw.setColor(0xff000000);
|
draw.setColor(0xff000000);
|
||||||
graphics.c.glUniform1i(buttonUniforms.pressed, 1);
|
graphics.c.glUniform1i(buttonUniforms.pressed, 1);
|
||||||
} else if(GuiComponent.contains(pos, size, mousePosition) and self.hovered) {
|
} else if(GuiComponent.contains(self.pos, self.size, mousePosition) and self.hovered) {
|
||||||
draw.setColor(0xff000040);
|
draw.setColor(0xff000040);
|
||||||
} else {
|
} else {
|
||||||
draw.setColor(0xff000000);
|
draw.setColor(0xff000000);
|
||||||
}
|
}
|
||||||
self.hovered = false;
|
self.hovered = false;
|
||||||
draw.customShadedRect(buttonUniforms, pos, size);
|
draw.customShadedRect(buttonUniforms, self.pos, self.size);
|
||||||
graphics.c.glUniform1i(buttonUniforms.pressed, 0);
|
graphics.c.glUniform1i(buttonUniforms.pressed, 0);
|
||||||
const textPos = pos + size/@splat(2, @as(f32, 2.0)) - self.textSize/@splat(2, @as(f32, 2.0));
|
const textPos = self.pos + self.size/@splat(2, @as(f32, 2.0)) - self.label.size/@splat(2, @as(f32, 2.0));
|
||||||
try self.label.render(textPos, self.textSize, mousePosition - textPos);
|
self.label.pos = textPos;
|
||||||
|
try self.label.render(mousePosition - self.pos);
|
||||||
}
|
}
|
@ -25,12 +25,13 @@ const boxSize: f32 = 16;
|
|||||||
var textureChecked: Texture = undefined;
|
var textureChecked: Texture = undefined;
|
||||||
var textureEmpty: Texture = undefined;
|
var textureEmpty: Texture = undefined;
|
||||||
|
|
||||||
|
pos: Vec2f,
|
||||||
|
size: Vec2f,
|
||||||
state: bool = false,
|
state: bool = false,
|
||||||
pressed: bool = false,
|
pressed: bool = false,
|
||||||
hovered: bool = false,
|
hovered: bool = false,
|
||||||
onAction: *const fn(bool) void,
|
onAction: *const fn(bool) void,
|
||||||
textSize: Vec2f,
|
label: *Label,
|
||||||
label: Label,
|
|
||||||
|
|
||||||
pub fn __init() !void {
|
pub fn __init() !void {
|
||||||
textureChecked = try Texture.initFromFile("assets/cubyz/ui/checked_box.png");
|
textureChecked = try Texture.initFromFile("assets/cubyz/ui/checked_box.png");
|
||||||
@ -42,44 +43,49 @@ pub fn __deinit() void {
|
|||||||
textureEmpty.deinit();
|
textureEmpty.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(pos: Vec2f, width: f32, text: []const u8, initialValue: bool, onAction: *const fn(bool) void) Allocator.Error!GuiComponent {
|
pub fn init(pos: Vec2f, width: f32, text: []const u8, initialValue: bool, onAction: *const fn(bool) void) Allocator.Error!*CheckBox {
|
||||||
const labelComponent = try Label.init(undefined, width - 3*border - boxSize, text, .left);
|
const label = (try Label.init(undefined, width - 3*border - boxSize, text, .left));
|
||||||
var self = CheckBox {
|
const self = try gui.allocator.create(CheckBox);
|
||||||
|
self.* = CheckBox {
|
||||||
|
.pos = pos,
|
||||||
|
.size = Vec2f{@max(width, label.size[0] + 3*border + boxSize), label.size[1] + 3*border},
|
||||||
.state = initialValue,
|
.state = initialValue,
|
||||||
.onAction = onAction,
|
.onAction = onAction,
|
||||||
.label = labelComponent.impl.label,
|
.label = label,
|
||||||
.textSize = labelComponent.size,
|
|
||||||
};
|
|
||||||
return GuiComponent {
|
|
||||||
.pos = pos,
|
|
||||||
.size = Vec2f{@max(width, self.textSize[0] + 3*border + boxSize), self.textSize[1] + 3*border},
|
|
||||||
.impl = .{.checkBox = self}
|
|
||||||
};
|
};
|
||||||
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: CheckBox) void {
|
pub fn deinit(self: *const CheckBox) void {
|
||||||
self.label.deinit();
|
self.label.deinit();
|
||||||
|
gui.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateHovered(self: *CheckBox, _: Vec2f, _: Vec2f, _: Vec2f) void {
|
pub fn toComponent(self: *CheckBox) GuiComponent {
|
||||||
|
return GuiComponent {
|
||||||
|
.checkBox = self
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn updateHovered(self: *CheckBox, _: Vec2f) void {
|
||||||
self.hovered = true;
|
self.hovered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mainButtonPressed(self: *CheckBox, _: Vec2f, _: Vec2f, _: Vec2f) void {
|
pub fn mainButtonPressed(self: *CheckBox, _: Vec2f) void {
|
||||||
self.pressed = true;
|
self.pressed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mainButtonReleased(self: *CheckBox, pos: Vec2f, size: Vec2f, mousePosition: Vec2f) void {
|
pub fn mainButtonReleased(self: *CheckBox, mousePosition: Vec2f) void {
|
||||||
if(self.pressed) {
|
if(self.pressed) {
|
||||||
self.pressed = false;
|
self.pressed = false;
|
||||||
if(GuiComponent.contains(pos, size, mousePosition)) {
|
if(GuiComponent.contains(self.pos, self.size, mousePosition)) {
|
||||||
self.state = !self.state;
|
self.state = !self.state;
|
||||||
self.onAction(self.state);
|
self.onAction(self.state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(self: *CheckBox, pos: Vec2f, size: Vec2f, mousePosition: Vec2f) !void {
|
pub fn render(self: *CheckBox, mousePosition: Vec2f) !void {
|
||||||
graphics.c.glActiveTexture(graphics.c.GL_TEXTURE0);
|
graphics.c.glActiveTexture(graphics.c.GL_TEXTURE0);
|
||||||
if(self.state) {
|
if(self.state) {
|
||||||
textureChecked.bind();
|
textureChecked.bind();
|
||||||
@ -91,14 +97,15 @@ pub fn render(self: *CheckBox, pos: Vec2f, size: Vec2f, mousePosition: Vec2f) !v
|
|||||||
if(self.pressed) {
|
if(self.pressed) {
|
||||||
draw.setColor(0xff000000);
|
draw.setColor(0xff000000);
|
||||||
graphics.c.glUniform1i(Button.buttonUniforms.pressed, 1);
|
graphics.c.glUniform1i(Button.buttonUniforms.pressed, 1);
|
||||||
} else if(GuiComponent.contains(pos, size, mousePosition) and self.hovered) {
|
} else if(GuiComponent.contains(self.pos, self.size, mousePosition) and self.hovered) {
|
||||||
draw.setColor(0xff000040);
|
draw.setColor(0xff000040);
|
||||||
} else {
|
} else {
|
||||||
draw.setColor(0xff000000);
|
draw.setColor(0xff000000);
|
||||||
}
|
}
|
||||||
self.hovered = false;
|
self.hovered = false;
|
||||||
draw.customShadedRect(Button.buttonUniforms, pos + Vec2f{0, size[1]/2 - boxSize/2}, @splat(2, boxSize));
|
draw.customShadedRect(Button.buttonUniforms, self.pos + Vec2f{0, self.size[1]/2 - boxSize/2}, @splat(2, boxSize));
|
||||||
graphics.c.glUniform1i(Button.buttonUniforms.pressed, 0);
|
graphics.c.glUniform1i(Button.buttonUniforms.pressed, 0);
|
||||||
const textPos = pos + Vec2f{boxSize/2, 0} + size/@splat(2, @as(f32, 2.0)) - self.textSize/@splat(2, @as(f32, 2.0));
|
const textPos = self.pos + Vec2f{boxSize/2, 0} + self.size/@splat(2, @as(f32, 2.0)) - self.label.size/@splat(2, @as(f32, 2.0));
|
||||||
try self.label.render(textPos, self.textSize, mousePosition - textPos);
|
self.label.pos = textPos;
|
||||||
|
try self.label.render(mousePosition - textPos);
|
||||||
}
|
}
|
@ -15,25 +15,39 @@ const Label = @This();
|
|||||||
|
|
||||||
const fontSize: f32 = 16;
|
const fontSize: f32 = 16;
|
||||||
|
|
||||||
|
pos: Vec2f,
|
||||||
|
size: Vec2f,
|
||||||
text: TextBuffer,
|
text: TextBuffer,
|
||||||
textSize: Vec2f = undefined,
|
|
||||||
|
|
||||||
pub fn init(pos: Vec2f, maxWidth: f32, text: []const u8, alignment: TextBuffer.Alignment) Allocator.Error!GuiComponent {
|
pub fn init(pos: Vec2f, maxWidth: f32, text: []const u8, alignment: TextBuffer.Alignment) Allocator.Error!*Label {
|
||||||
var self = Label {
|
const self = try gui.allocator.create(Label);
|
||||||
|
self.* = Label {
|
||||||
.text = try TextBuffer.init(gui.allocator, text, .{}, false, alignment),
|
.text = try TextBuffer.init(gui.allocator, text, .{}, false, alignment),
|
||||||
};
|
|
||||||
self.textSize = try self.text.calculateLineBreaks(fontSize, maxWidth);
|
|
||||||
return GuiComponent {
|
|
||||||
.pos = pos,
|
.pos = pos,
|
||||||
.size = self.textSize,
|
.size = undefined,
|
||||||
.impl = .{.label = self}
|
};
|
||||||
|
self.size = try self.text.calculateLineBreaks(fontSize, maxWidth);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *const Label) void {
|
||||||
|
self.text.deinit();
|
||||||
|
gui.allocator.destroy(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toComponent(self: *Label) GuiComponent {
|
||||||
|
return GuiComponent{
|
||||||
|
.label = self
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Label) void {
|
pub fn updateText(self: *Label, newText: []const u8) !void {
|
||||||
|
const alignment = self.text.alignment;
|
||||||
self.text.deinit();
|
self.text.deinit();
|
||||||
|
self.text = try TextBuffer.init(gui.allocator, newText, .{}, false, alignment);
|
||||||
|
self.size = try self.text.calculateLineBreaks(fontSize, self.size[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(self: *Label, pos: Vec2f, _: Vec2f, _: Vec2f) !void {
|
pub fn render(self: *Label, _: Vec2f) !void {
|
||||||
try self.text.render(pos[0], pos[1], fontSize);
|
try self.text.render(self.pos[0], self.pos[1], fontSize);
|
||||||
}
|
}
|
@ -22,10 +22,10 @@ const fontSize: f32 = 16;
|
|||||||
|
|
||||||
var texture: Texture = undefined;
|
var texture: Texture = undefined;
|
||||||
|
|
||||||
|
pos: Vec2f,
|
||||||
|
size: Vec2f,
|
||||||
currentState: f32,
|
currentState: f32,
|
||||||
button: Button,
|
button: *Button,
|
||||||
buttonSize: Vec2f,
|
|
||||||
buttonPos: Vec2f = .{0, 0},
|
|
||||||
mouseAnchor: f32 = undefined,
|
mouseAnchor: f32 = undefined,
|
||||||
|
|
||||||
pub fn __init() !void {
|
pub fn __init() !void {
|
||||||
@ -36,34 +36,39 @@ pub fn __deinit() void {
|
|||||||
texture.deinit();
|
texture.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(pos: Vec2f, width: f32, height: f32, initialState: f32) Allocator.Error!GuiComponent {
|
pub fn init(pos: Vec2f, width: f32, height: f32, initialState: f32) Allocator.Error!*ScrollBar {
|
||||||
const buttonComponent = try Button.init(undefined, undefined, "", null);
|
const button = try Button.init(.{0, 0}, undefined, "", null);
|
||||||
var self = ScrollBar {
|
const self = try gui.allocator.create(ScrollBar);
|
||||||
.currentState = initialState,
|
self.* = ScrollBar {
|
||||||
.button = buttonComponent.impl.button,
|
|
||||||
.buttonSize = .{width, 16},
|
|
||||||
};
|
|
||||||
const size = Vec2f{width, height};
|
|
||||||
self.setButtonPosFromValue(size);
|
|
||||||
return GuiComponent {
|
|
||||||
.pos = pos,
|
.pos = pos,
|
||||||
.size = size,
|
.size = Vec2f{width, height},
|
||||||
.impl = .{.scrollBar = self}
|
.currentState = initialState,
|
||||||
|
.button = button,
|
||||||
|
};
|
||||||
|
self.button.size = .{width, 16};
|
||||||
|
self.setButtonPosFromValue();
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *const ScrollBar) void {
|
||||||
|
self.button.deinit();
|
||||||
|
gui.allocator.destroy(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toComponent(self: *ScrollBar) GuiComponent {
|
||||||
|
return GuiComponent{
|
||||||
|
.scrollBar = self
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: ScrollBar) void {
|
fn setButtonPosFromValue(self: *ScrollBar) void {
|
||||||
self.button.deinit();
|
const range: f32 = self.size[1] - self.button.size[1];
|
||||||
|
self.button.pos[1] = range*self.currentState;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setButtonPosFromValue(self: *ScrollBar, size: Vec2f) void {
|
fn updateValueFromButtonPos(self: *ScrollBar) void {
|
||||||
const range: f32 = size[1] - self.buttonSize[1];
|
const range: f32 = self.size[1] - self.button.size[1];
|
||||||
self.buttonPos[1] = range*self.currentState;
|
const value = self.button.pos[1]/range;
|
||||||
}
|
|
||||||
|
|
||||||
fn updateValueFromButtonPos(self: *ScrollBar, size: Vec2f) void {
|
|
||||||
const range: f32 = size[1] - self.buttonSize[1];
|
|
||||||
const value = self.buttonPos[1]/range;
|
|
||||||
if(value != self.currentState) {
|
if(value != self.currentState) {
|
||||||
self.currentState = value;
|
self.currentState = value;
|
||||||
}
|
}
|
||||||
@ -74,36 +79,38 @@ pub fn scroll(self: *ScrollBar, offset: f32) void {
|
|||||||
self.currentState = @min(1, @max(0, self.currentState));
|
self.currentState = @min(1, @max(0, self.currentState));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateHovered(self: *ScrollBar, pos: Vec2f, _: Vec2f, mousePosition: Vec2f) void {
|
pub fn updateHovered(self: *ScrollBar, mousePosition: Vec2f) void {
|
||||||
if(GuiComponent.contains(self.buttonPos + pos, self.buttonSize, mousePosition)) {
|
if(GuiComponent.contains(self.button.pos, self.button.size, mousePosition - self.pos)) {
|
||||||
self.button.updateHovered(self.buttonPos, self.buttonSize, mousePosition - pos);
|
self.button.updateHovered(mousePosition - self.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mainButtonPressed(self: *ScrollBar, pos: Vec2f, _: Vec2f, mousePosition: Vec2f) void {
|
pub fn mainButtonPressed(self: *ScrollBar, mousePosition: Vec2f) void {
|
||||||
if(GuiComponent.contains(self.buttonPos, self.buttonSize, mousePosition - pos)) {
|
if(GuiComponent.contains(self.button.pos, self.button.size, mousePosition - self.pos)) {
|
||||||
self.button.mainButtonPressed(self.buttonPos, self.buttonSize, mousePosition - pos);
|
self.button.mainButtonPressed(mousePosition - self.pos);
|
||||||
self.mouseAnchor = mousePosition[1] - self.buttonPos[1];
|
self.mouseAnchor = mousePosition[1] - self.button.pos[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mainButtonReleased(self: *ScrollBar, _: Vec2f, _: Vec2f, _: Vec2f) void {
|
pub fn mainButtonReleased(self: *ScrollBar, mousePosition: Vec2f) void {
|
||||||
self.button.mainButtonReleased(undefined, undefined, undefined);
|
self.button.mainButtonReleased(mousePosition - self.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(self: *ScrollBar, pos: Vec2f, size: Vec2f, mousePosition: Vec2f) !void {
|
pub fn render(self: *ScrollBar, mousePosition: Vec2f) !void {
|
||||||
graphics.c.glActiveTexture(graphics.c.GL_TEXTURE0);
|
graphics.c.glActiveTexture(graphics.c.GL_TEXTURE0);
|
||||||
texture.bind();
|
texture.bind();
|
||||||
Button.shader.bind();
|
Button.shader.bind();
|
||||||
draw.setColor(0xff000000);
|
draw.setColor(0xff000000);
|
||||||
draw.customShadedRect(Button.buttonUniforms, pos, size);
|
draw.customShadedRect(Button.buttonUniforms, self.pos, self.size);
|
||||||
|
|
||||||
const range: f32 = size[1] - self.buttonSize[1];
|
const range: f32 = self.size[1] - self.button.size[1];
|
||||||
self.setButtonPosFromValue(size);
|
self.setButtonPosFromValue();
|
||||||
if(self.button.pressed) {
|
if(self.button.pressed) {
|
||||||
self.buttonPos[1] = mousePosition[1] - self.mouseAnchor;
|
self.button.pos[1] = mousePosition[1] - self.mouseAnchor;
|
||||||
self.buttonPos[1] = @min(@max(self.buttonPos[1], 0), range - 0.001);
|
self.button.pos[1] = @min(@max(self.button.pos[1], 0), range - 0.001);
|
||||||
self.updateValueFromButtonPos(size);
|
self.updateValueFromButtonPos();
|
||||||
}
|
}
|
||||||
try self.button.render(pos + self.buttonPos, self.buttonSize, mousePosition);
|
const oldTranslation = draw.setTranslation(self.pos);
|
||||||
|
defer draw.restoreTranslation(oldTranslation);
|
||||||
|
try self.button.render(mousePosition - self.pos);
|
||||||
}
|
}
|
@ -23,16 +23,15 @@ const fontSize: f32 = 16;
|
|||||||
|
|
||||||
var texture: Texture = undefined;
|
var texture: Texture = undefined;
|
||||||
|
|
||||||
|
pos: Vec2f,
|
||||||
|
size: Vec2f,
|
||||||
callback: *const fn(u16) void,
|
callback: *const fn(u16) void,
|
||||||
currentSelection: u16,
|
currentSelection: u16,
|
||||||
text: []const u8,
|
text: []const u8,
|
||||||
currentText: []u8,
|
currentText: []u8,
|
||||||
values: [][]const u8,
|
values: [][]const u8,
|
||||||
label: Label,
|
label: *Label,
|
||||||
labelSize: Vec2f,
|
button: *Button,
|
||||||
button: Button,
|
|
||||||
buttonSize: Vec2f,
|
|
||||||
buttonPos: Vec2f = .{0, 0},
|
|
||||||
mouseAnchor: f32 = undefined,
|
mouseAnchor: f32 = undefined,
|
||||||
|
|
||||||
pub fn __init() !void {
|
pub fn __init() !void {
|
||||||
@ -43,7 +42,7 @@ pub fn __deinit() void {
|
|||||||
texture.deinit();
|
texture.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(pos: Vec2f, width: f32, text: []const u8, comptime fmt: []const u8, valueList: anytype, initialValue: u16, callback: *const fn(u16) void) Allocator.Error!GuiComponent {
|
pub fn init(pos: Vec2f, width: f32, text: []const u8, comptime fmt: []const u8, valueList: anytype, initialValue: u16, callback: *const fn(u16) void) Allocator.Error!*Slider {
|
||||||
var values = try gui.allocator.alloc([]const u8, valueList.len);
|
var values = try gui.allocator.alloc([]const u8, valueList.len);
|
||||||
var maxLen: usize = 0;
|
var maxLen: usize = 0;
|
||||||
for(valueList, 0..) |value, i| {
|
for(valueList, 0..) |value, i| {
|
||||||
@ -54,30 +53,28 @@ pub fn init(pos: Vec2f, width: f32, text: []const u8, comptime fmt: []const u8,
|
|||||||
const initialText = try gui.allocator.alloc(u8, text.len + maxLen);
|
const initialText = try gui.allocator.alloc(u8, text.len + maxLen);
|
||||||
std.mem.copy(u8, initialText, text);
|
std.mem.copy(u8, initialText, text);
|
||||||
std.mem.set(u8, initialText[text.len..], ' ');
|
std.mem.set(u8, initialText[text.len..], ' ');
|
||||||
const labelComponent = try Label.init(undefined, width - 3*border, initialText, .center);
|
const label = try Label.init(undefined, width - 3*border, initialText, .center);
|
||||||
const buttonComponent = try Button.init(undefined, undefined, "", null);
|
const button = try Button.init(.{0, 0}, undefined, "", null);
|
||||||
var self = Slider {
|
const self = try gui.allocator.create(Slider);
|
||||||
|
self.* = Slider {
|
||||||
|
.pos = pos,
|
||||||
|
.size = undefined,
|
||||||
.callback = callback,
|
.callback = callback,
|
||||||
.currentSelection = initialValue,
|
.currentSelection = initialValue,
|
||||||
.text = text,
|
.text = text,
|
||||||
.currentText = initialText,
|
.currentText = initialText,
|
||||||
.label = labelComponent.impl.label,
|
.label = label,
|
||||||
.button = buttonComponent.impl.button,
|
.button = button,
|
||||||
.labelSize = labelComponent.size,
|
|
||||||
.buttonSize = .{16, 16},
|
|
||||||
.values = values,
|
.values = values,
|
||||||
};
|
};
|
||||||
self.buttonPos[1] = self.labelSize[1] + 3.5*border;
|
self.button.size = .{16, 16};
|
||||||
const size = Vec2f{@max(width, self.labelSize[0] + 3*border), self.labelSize[1] + self.buttonSize[1] + 5*border};
|
self.button.pos[1] = self.label.size[1] + 3.5*border;
|
||||||
try self.setButtonPosFromValue(size);
|
self.size = Vec2f{@max(width, self.label.size[0] + 3*border), self.label.size[1] + self.button.size[1] + 5*border};
|
||||||
return GuiComponent {
|
try self.setButtonPosFromValue();
|
||||||
.pos = pos,
|
return self;
|
||||||
.size = size,
|
|
||||||
.impl = .{.slider = self}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Slider) void {
|
pub fn deinit(self: *const Slider) void {
|
||||||
self.label.deinit();
|
self.label.deinit();
|
||||||
self.button.deinit();
|
self.button.deinit();
|
||||||
for(self.values) |value| {
|
for(self.values) |value| {
|
||||||
@ -85,12 +82,19 @@ pub fn deinit(self: Slider) void {
|
|||||||
}
|
}
|
||||||
gui.allocator.free(self.values);
|
gui.allocator.free(self.values);
|
||||||
gui.allocator.free(self.currentText);
|
gui.allocator.free(self.currentText);
|
||||||
|
gui.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setButtonPosFromValue(self: *Slider, size: Vec2f) !void {
|
pub fn toComponent(self: *Slider) GuiComponent {
|
||||||
const range: f32 = size[0] - 3*border - self.buttonSize[0];
|
return GuiComponent {
|
||||||
self.buttonPos[0] = 1.5*border + range*(0.5 + @intToFloat(f32, self.currentSelection))/@intToFloat(f32, self.values.len);
|
.slider = self
|
||||||
try self.updateLabel(self.values[self.currentSelection], size[0]);
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setButtonPosFromValue(self: *Slider) !void {
|
||||||
|
const range: f32 = self.size[0] - 3*border - self.button.size[0];
|
||||||
|
self.button.pos[0] = 1.5*border + range*(0.5 + @intToFloat(f32, self.currentSelection))/@intToFloat(f32, self.values.len);
|
||||||
|
try self.updateLabel(self.values[self.currentSelection], self.size[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn updateLabel(self: *Slider, newValue: []const u8, width: f32) !void {
|
fn updateLabel(self: *Slider, newValue: []const u8, width: f32) !void {
|
||||||
@ -98,56 +102,58 @@ fn updateLabel(self: *Slider, newValue: []const u8, width: f32) !void {
|
|||||||
self.currentText = try gui.allocator.alloc(u8, newValue.len + self.text.len);
|
self.currentText = try gui.allocator.alloc(u8, newValue.len + self.text.len);
|
||||||
std.mem.copy(u8, self.currentText, self.text);
|
std.mem.copy(u8, self.currentText, self.text);
|
||||||
std.mem.copy(u8, self.currentText[self.text.len..], newValue);
|
std.mem.copy(u8, self.currentText[self.text.len..], newValue);
|
||||||
const labelComponent = try Label.init(undefined, width - 3*border, self.currentText, .center);
|
const label = try Label.init(undefined, width - 3*border, self.currentText, .center);
|
||||||
self.label.deinit();
|
self.label.deinit();
|
||||||
self.label = labelComponent.impl.label;
|
self.label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn updateValueFromButtonPos(self: *Slider, size: Vec2f) !void {
|
fn updateValueFromButtonPos(self: *Slider) !void {
|
||||||
const range: f32 = size[0] - 3*border - self.buttonSize[0];
|
const range: f32 = self.size[0] - 3*border - self.button.size[0];
|
||||||
const selection = @floatToInt(u16, (self.buttonPos[0] - 1.5*border)/range*@intToFloat(f32, self.values.len));
|
const selection = @floatToInt(u16, (self.button.pos[0] - 1.5*border)/range*@intToFloat(f32, self.values.len));
|
||||||
if(selection != self.currentSelection) {
|
if(selection != self.currentSelection) {
|
||||||
self.currentSelection = selection;
|
self.currentSelection = selection;
|
||||||
try self.updateLabel(self.values[selection], size[0]);
|
try self.updateLabel(self.values[selection], self.size[0]);
|
||||||
self.callback(selection);
|
self.callback(selection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateHovered(self: *Slider, pos: Vec2f, _: Vec2f, mousePosition: Vec2f) void {
|
pub fn updateHovered(self: *Slider, mousePosition: Vec2f) void {
|
||||||
if(GuiComponent.contains(self.buttonPos + pos, self.buttonSize, mousePosition)) {
|
if(GuiComponent.contains(self.button.pos, self.button.size, mousePosition - self.pos)) {
|
||||||
self.button.updateHovered(self.buttonPos, self.buttonSize, mousePosition - pos);
|
self.button.updateHovered(mousePosition - self.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mainButtonPressed(self: *Slider, pos: Vec2f, _: Vec2f, mousePosition: Vec2f) void {
|
pub fn mainButtonPressed(self: *Slider, mousePosition: Vec2f) void {
|
||||||
if(GuiComponent.contains(self.buttonPos, self.buttonSize, mousePosition - pos)) {
|
if(GuiComponent.contains(self.button.pos, self.button.size, mousePosition - self.pos)) {
|
||||||
self.button.mainButtonPressed(self.buttonPos, self.buttonSize, mousePosition - pos);
|
self.button.mainButtonPressed(mousePosition - self.pos);
|
||||||
self.mouseAnchor = mousePosition[0] - self.buttonPos[0];
|
self.mouseAnchor = mousePosition[0] - self.button.pos[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mainButtonReleased(self: *Slider, _: Vec2f, _: Vec2f, _: Vec2f) void {
|
pub fn mainButtonReleased(self: *Slider, _: Vec2f) void {
|
||||||
self.button.mainButtonReleased(undefined, undefined, undefined);
|
self.button.mainButtonReleased(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(self: *Slider, pos: Vec2f, size: Vec2f, mousePosition: Vec2f) !void {
|
pub fn render(self: *Slider, mousePosition: Vec2f) !void {
|
||||||
graphics.c.glActiveTexture(graphics.c.GL_TEXTURE0);
|
graphics.c.glActiveTexture(graphics.c.GL_TEXTURE0);
|
||||||
texture.bind();
|
texture.bind();
|
||||||
Button.shader.bind();
|
Button.shader.bind();
|
||||||
draw.setColor(0xff000000);
|
draw.setColor(0xff000000);
|
||||||
draw.customShadedRect(Button.buttonUniforms, pos, size);
|
draw.customShadedRect(Button.buttonUniforms, self.pos, self.size);
|
||||||
|
|
||||||
const range: f32 = size[0] - 3*border - self.buttonSize[0];
|
const range: f32 = self.size[0] - 3*border - self.button.size[0];
|
||||||
draw.setColor(0x80000000);
|
draw.setColor(0x80000000);
|
||||||
draw.rect(pos + Vec2f{1.5*border + self.buttonSize[0]/2, self.buttonPos[1] + self.buttonSize[1]/2 - border}, .{range, 2*border});
|
draw.rect(self.pos + Vec2f{1.5*border + self.button.size[0]/2, self.button.pos[1] + self.button.size[1]/2 - border}, .{range, 2*border});
|
||||||
|
|
||||||
const labelPos = pos + @splat(2, 1.5*border);
|
self.label.pos = self.pos + @splat(2, 1.5*border);
|
||||||
try self.label.render(labelPos, self.labelSize, mousePosition);
|
try self.label.render(mousePosition);
|
||||||
|
|
||||||
if(self.button.pressed) {
|
if(self.button.pressed) {
|
||||||
self.buttonPos[0] = mousePosition[0] - self.mouseAnchor;
|
self.button.pos[0] = mousePosition[0] - self.mouseAnchor;
|
||||||
self.buttonPos[0] = @min(@max(self.buttonPos[0], 1.5*border), 1.5*border + range - 0.001);
|
self.button.pos[0] = @min(@max(self.button.pos[0], 1.5*border), 1.5*border + range - 0.001);
|
||||||
try self.updateValueFromButtonPos(size);
|
try self.updateValueFromButtonPos();
|
||||||
}
|
}
|
||||||
try self.button.render(pos + self.buttonPos, self.buttonSize, mousePosition);
|
const oldTranslation = draw.setTranslation(self.pos);
|
||||||
|
defer draw.restoreTranslation(oldTranslation);
|
||||||
|
try self.button.render(mousePosition - self.pos);
|
||||||
}
|
}
|
@ -22,6 +22,8 @@ const fontSize: f32 = 16;
|
|||||||
|
|
||||||
var texture: Texture = undefined;
|
var texture: Texture = undefined;
|
||||||
|
|
||||||
|
pos: Vec2f,
|
||||||
|
size: Vec2f,
|
||||||
pressed: bool = false,
|
pressed: bool = false,
|
||||||
cursor: ?u32 = null,
|
cursor: ?u32 = null,
|
||||||
selectionStart: ?u32 = null,
|
selectionStart: ?u32 = null,
|
||||||
@ -30,8 +32,7 @@ textBuffer: TextBuffer,
|
|||||||
maxWidth: f32,
|
maxWidth: f32,
|
||||||
maxHeight: f32,
|
maxHeight: f32,
|
||||||
textSize: Vec2f = undefined,
|
textSize: Vec2f = undefined,
|
||||||
scrollBar: ScrollBar,
|
scrollBar: *ScrollBar,
|
||||||
scrollBarSize: Vec2f,
|
|
||||||
|
|
||||||
pub fn __init() !void {
|
pub fn __init() !void {
|
||||||
texture = try Texture.initFromFile("assets/cubyz/ui/text_input.png");
|
texture = try Texture.initFromFile("assets/cubyz/ui/text_input.png");
|
||||||
@ -41,49 +42,54 @@ pub fn __deinit() void {
|
|||||||
texture.deinit();
|
texture.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(pos: Vec2f, maxWidth: f32, maxHeight: f32, text: []const u8) Allocator.Error!GuiComponent {
|
pub fn init(pos: Vec2f, maxWidth: f32, maxHeight: f32, text: []const u8) Allocator.Error!*TextInput {
|
||||||
const scrollBarComponent = try ScrollBar.init(undefined, scrollBarWidth, maxHeight - 2*border, 0);
|
const scrollBar = try ScrollBar.init(undefined, scrollBarWidth, maxHeight - 2*border, 0);
|
||||||
var self = TextInput {
|
const self = try gui.allocator.create(TextInput);
|
||||||
|
self.* = TextInput {
|
||||||
|
.pos = pos,
|
||||||
|
.size = .{maxWidth, maxHeight},
|
||||||
.currentString = std.ArrayList(u8).init(gui.allocator),
|
.currentString = std.ArrayList(u8).init(gui.allocator),
|
||||||
.textBuffer = try TextBuffer.init(gui.allocator, text, .{}, true, .left),
|
.textBuffer = try TextBuffer.init(gui.allocator, text, .{}, true, .left),
|
||||||
.maxWidth = maxWidth,
|
.maxWidth = maxWidth,
|
||||||
.maxHeight = maxHeight,
|
.maxHeight = maxHeight,
|
||||||
.scrollBar = scrollBarComponent.impl.scrollBar,
|
.scrollBar = scrollBar,
|
||||||
.scrollBarSize = scrollBarComponent.size,
|
|
||||||
};
|
};
|
||||||
try self.currentString.appendSlice(text);
|
try self.currentString.appendSlice(text);
|
||||||
self.textSize = try self.textBuffer.calculateLineBreaks(fontSize, maxWidth - 2*border - scrollBarWidth);
|
self.textSize = try self.textBuffer.calculateLineBreaks(fontSize, maxWidth - 2*border - scrollBarWidth);
|
||||||
return GuiComponent {
|
return self;
|
||||||
.pos = pos,
|
|
||||||
.size = .{maxWidth, maxHeight},
|
|
||||||
.impl = .{.textInput = self}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: TextInput) void {
|
pub fn deinit(self: *const TextInput) void {
|
||||||
self.textBuffer.deinit();
|
self.textBuffer.deinit();
|
||||||
self.currentString.deinit();
|
self.currentString.deinit();
|
||||||
self.scrollBar.deinit();
|
self.scrollBar.deinit();
|
||||||
|
gui.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateHovered(self: *TextInput, pos: Vec2f, size: Vec2f, mousePosition: Vec2f) void {
|
pub fn toComponent(self: *TextInput) GuiComponent {
|
||||||
|
return GuiComponent {
|
||||||
|
.textInput = self
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn updateHovered(self: *TextInput, mousePosition: Vec2f) void {
|
||||||
if(self.textSize[1] > self.maxHeight - 2*border) {
|
if(self.textSize[1] > self.maxHeight - 2*border) {
|
||||||
const diff = self.textSize[1] - (self.maxHeight - 2*border);
|
const diff = self.textSize[1] - (self.maxHeight - 2*border);
|
||||||
self.scrollBar.scroll(-main.Window.scrollOffset*32/diff);
|
self.scrollBar.scroll(-main.Window.scrollOffset*32/diff);
|
||||||
}
|
}
|
||||||
if(self.textSize[1] > self.maxHeight - 2*border) {
|
if(self.textSize[1] > self.maxHeight - 2*border) {
|
||||||
const scrollBarPos = Vec2f{size[0] - border - scrollBarWidth, border};
|
self.scrollBar.pos = Vec2f{self.size[0] - border - scrollBarWidth, border};
|
||||||
if(GuiComponent.contains(scrollBarPos, self.scrollBarSize, mousePosition - pos)) {
|
if(GuiComponent.contains(self.scrollBar.pos, self.scrollBar.size, mousePosition - self.pos)) {
|
||||||
self.scrollBar.updateHovered(scrollBarPos, self.scrollBarSize, mousePosition - pos);
|
self.scrollBar.updateHovered(mousePosition - self.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mainButtonPressed(self: *TextInput, pos: Vec2f, size: Vec2f, mousePosition: Vec2f) void {
|
pub fn mainButtonPressed(self: *TextInput, mousePosition: Vec2f) void {
|
||||||
if(self.textSize[1] > self.maxHeight - 2*border) {
|
if(self.textSize[1] > self.maxHeight - 2*border) {
|
||||||
const scrollBarPos = Vec2f{size[0] - border - scrollBarWidth, border};
|
self.scrollBar.pos = Vec2f{self.size[0] - border - scrollBarWidth, border};
|
||||||
if(GuiComponent.contains(scrollBarPos, self.scrollBarSize, mousePosition - pos)) {
|
if(GuiComponent.contains(self.scrollBar.pos, self.scrollBar.size, mousePosition - self.pos)) {
|
||||||
self.scrollBar.mainButtonPressed(scrollBarPos, self.scrollBarSize, mousePosition - pos);
|
self.scrollBar.mainButtonPressed(mousePosition - self.pos);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,25 +99,26 @@ pub fn mainButtonPressed(self: *TextInput, pos: Vec2f, size: Vec2f, mousePositio
|
|||||||
const diff = self.textSize[1] - (self.maxHeight - 2*border);
|
const diff = self.textSize[1] - (self.maxHeight - 2*border);
|
||||||
textPos[1] -= diff*self.scrollBar.currentState;
|
textPos[1] -= diff*self.scrollBar.currentState;
|
||||||
}
|
}
|
||||||
self.selectionStart = self.textBuffer.mousePosToIndex(mousePosition - textPos - pos, self.currentString.items.len);
|
self.selectionStart = self.textBuffer.mousePosToIndex(mousePosition - textPos - self.pos, self.currentString.items.len);
|
||||||
self.pressed = true;
|
self.pressed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mainButtonReleased(self: *TextInput, pos: Vec2f, size: Vec2f, mousePosition: Vec2f) void {
|
pub fn mainButtonReleased(self: *TextInput, mousePosition: Vec2f) void {
|
||||||
if(self.pressed) {
|
if(self.pressed) {
|
||||||
var textPos = Vec2f{border, border};
|
var textPos = Vec2f{border, border};
|
||||||
if(self.textSize[1] > self.maxHeight - 2*border) {
|
if(self.textSize[1] > self.maxHeight - 2*border) {
|
||||||
const diff = self.textSize[1] - (self.maxHeight - 2*border);
|
const diff = self.textSize[1] - (self.maxHeight - 2*border);
|
||||||
textPos[1] -= diff*self.scrollBar.currentState;
|
textPos[1] -= diff*self.scrollBar.currentState;
|
||||||
}
|
}
|
||||||
self.cursor = self.textBuffer.mousePosToIndex(mousePosition - textPos - pos, self.currentString.items.len);
|
self.cursor = self.textBuffer.mousePosToIndex(mousePosition - textPos - self.pos, self.currentString.items.len);
|
||||||
if(self.cursor == self.selectionStart) {
|
if(self.cursor == self.selectionStart) {
|
||||||
self.selectionStart = null;
|
self.selectionStart = null;
|
||||||
}
|
}
|
||||||
self.pressed = false;
|
self.pressed = false;
|
||||||
gui.setSelectedTextInput(self);
|
gui.setSelectedTextInput(self);
|
||||||
} else if(self.textSize[1] > self.maxHeight - 2*border) {
|
} else if(self.textSize[1] > self.maxHeight - 2*border) {
|
||||||
self.scrollBar.mainButtonReleased(.{size[0] - border - scrollBarWidth, border}, self.scrollBarSize, mousePosition - pos);
|
self.scrollBar.pos = .{self.size[0] - border - scrollBarWidth, border};
|
||||||
|
self.scrollBar.mainButtonReleased(mousePosition - self.pos);
|
||||||
gui.setSelectedTextInput(self);
|
gui.setSelectedTextInput(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -435,26 +442,27 @@ fn ensureCursorVisibility(self: *TextInput) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(self: *TextInput, pos: Vec2f, size: Vec2f, mousePosition: Vec2f) !void {
|
pub fn render(self: *TextInput, mousePosition: Vec2f) !void {
|
||||||
graphics.c.glActiveTexture(graphics.c.GL_TEXTURE0);
|
graphics.c.glActiveTexture(graphics.c.GL_TEXTURE0);
|
||||||
texture.bind();
|
texture.bind();
|
||||||
Button.shader.bind();
|
Button.shader.bind();
|
||||||
draw.setColor(0xff000000);
|
draw.setColor(0xff000000);
|
||||||
draw.customShadedRect(Button.buttonUniforms, pos, size);
|
draw.customShadedRect(Button.buttonUniforms, self.pos, self.size);
|
||||||
const oldTranslation = draw.setTranslation(pos);
|
const oldTranslation = draw.setTranslation(self.pos);
|
||||||
defer draw.restoreTranslation(oldTranslation);
|
defer draw.restoreTranslation(oldTranslation);
|
||||||
const oldClip = draw.setClip(size);
|
const oldClip = draw.setClip(self.size);
|
||||||
defer draw.restoreClip(oldClip);
|
defer draw.restoreClip(oldClip);
|
||||||
|
|
||||||
var textPos = Vec2f{border, border};
|
var textPos = Vec2f{border, border};
|
||||||
if(self.textSize[1] > self.maxHeight - 2*border) {
|
if(self.textSize[1] > self.maxHeight - 2*border) {
|
||||||
const diff = self.textSize[1] - (self.maxHeight - 2*border);
|
const diff = self.textSize[1] - (self.maxHeight - 2*border);
|
||||||
textPos[1] -= diff*self.scrollBar.currentState;
|
textPos[1] -= diff*self.scrollBar.currentState;
|
||||||
try self.scrollBar.render(.{size[0] - self.scrollBarSize[0] - border, border}, self.scrollBarSize, mousePosition - pos);
|
self.scrollBar.pos = .{self.size[0] - self.scrollBar.size[0] - border, border};
|
||||||
|
try self.scrollBar.render(mousePosition - self.pos);
|
||||||
}
|
}
|
||||||
try self.textBuffer.render(textPos[0], textPos[1], fontSize);
|
try self.textBuffer.render(textPos[0], textPos[1], fontSize);
|
||||||
if(self.pressed) {
|
if(self.pressed) {
|
||||||
self.cursor = self.textBuffer.mousePosToIndex(mousePosition - textPos - pos, self.currentString.items.len);
|
self.cursor = self.textBuffer.mousePosToIndex(mousePosition - textPos - self.pos, self.currentString.items.len);
|
||||||
}
|
}
|
||||||
if(self.cursor) |cursor| {
|
if(self.cursor) |cursor| {
|
||||||
var cursorPos = textPos + self.textBuffer.indexToCursorPos(cursor);
|
var cursorPos = textPos + self.textBuffer.indexToCursorPos(cursor);
|
||||||
|
@ -13,80 +13,89 @@ const GuiComponent = gui.GuiComponent;
|
|||||||
|
|
||||||
const VerticalList = @This();
|
const VerticalList = @This();
|
||||||
|
|
||||||
|
pos: Vec2f,
|
||||||
|
size: Vec2f,
|
||||||
children: std.ArrayList(GuiComponent),
|
children: std.ArrayList(GuiComponent),
|
||||||
currentOffset: f32 = 0,
|
|
||||||
maxWidth: f32 = 0,
|
|
||||||
|
|
||||||
pub fn init() Allocator.Error!VerticalList {
|
pub fn init() Allocator.Error!*VerticalList {
|
||||||
const self = VerticalList {
|
const self = try gui.allocator.create(VerticalList);
|
||||||
|
self.* = VerticalList {
|
||||||
.children = std.ArrayList(GuiComponent).init(gui.allocator),
|
.children = std.ArrayList(GuiComponent).init(gui.allocator),
|
||||||
|
.pos = undefined,
|
||||||
|
.size = .{0, 0},
|
||||||
};
|
};
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: VerticalList) void {
|
pub fn deinit(self: *const VerticalList) void {
|
||||||
for(self.children.items) |*child| {
|
for(self.children.items) |*child| {
|
||||||
child.deinit();
|
child.deinit();
|
||||||
}
|
}
|
||||||
self.children.deinit();
|
self.children.deinit();
|
||||||
|
gui.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toComponent(self: *VerticalList, pos: Vec2f) GuiComponent {
|
pub fn toComponent(self: *VerticalList, pos: Vec2f) GuiComponent {
|
||||||
|
self.pos = pos;
|
||||||
return GuiComponent {
|
return GuiComponent {
|
||||||
.pos = pos,
|
.verticalList = self
|
||||||
.size = .{self.maxWidth, self.currentOffset},
|
|
||||||
.impl = .{.verticalList = self.*}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(self: *VerticalList, other: GuiComponent) Allocator.Error!void {
|
pub fn add(self: *VerticalList, _other: anytype) Allocator.Error!void {
|
||||||
|
var other: GuiComponent = undefined;
|
||||||
|
if(@TypeOf(_other) == GuiComponent) {
|
||||||
|
other = _other;
|
||||||
|
} else {
|
||||||
|
other = _other.toComponent();
|
||||||
|
}
|
||||||
const added = try self.children.addOne();
|
const added = try self.children.addOne();
|
||||||
added.* = other;
|
added.* = other;
|
||||||
added.pos[1] += self.currentOffset;
|
added.mutPos().*[1] += self.size[1];
|
||||||
self.currentOffset = added.pos[1] + added.size[1];
|
self.size[1] = added.pos()[1] + added.size()[1];
|
||||||
self.maxWidth = @max(self.maxWidth, added.pos[0] + added.size[0]);
|
self.size[0] = @max(self.size[0], added.pos()[0] + added.size()[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateSelected(self: *VerticalList, _: Vec2f, _: Vec2f) void {
|
pub fn updateSelected(self: *VerticalList) void {
|
||||||
for(self.children.items) |*child| {
|
for(self.children.items) |*child| {
|
||||||
child.updateSelected();
|
child.updateSelected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateHovered(self: *VerticalList, pos: Vec2f, _: Vec2f, mousePosition: Vec2f) void {
|
pub fn updateHovered(self: *VerticalList, mousePosition: Vec2f) void {
|
||||||
var i: usize = self.children.items.len;
|
var i: usize = self.children.items.len;
|
||||||
while(i != 0) {
|
while(i != 0) {
|
||||||
i -= 1;
|
i -= 1;
|
||||||
const child = &self.children.items[i];
|
const child = &self.children.items[i];
|
||||||
if(GuiComponent.contains(child.pos + pos, child.size, mousePosition)) {
|
if(GuiComponent.contains(child.pos() + self.pos, child.size(), mousePosition)) {
|
||||||
child.updateHovered(mousePosition - pos);
|
child.updateHovered(mousePosition - self.pos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(self: *VerticalList, pos: Vec2f, _: Vec2f, mousePosition: Vec2f) anyerror!void { // TODO: Remove anyerror once error union inference works in recursive loops.
|
pub fn render(self: *VerticalList, mousePosition: Vec2f) anyerror!void { // TODO: Remove anyerror once error union inference works in recursive loops.
|
||||||
const oldTranslation = draw.setTranslation(pos);
|
const oldTranslation = draw.setTranslation(self.pos);
|
||||||
for(self.children.items) |*child| {
|
for(self.children.items) |*child| {
|
||||||
try child.render(mousePosition - pos);
|
try child.render(mousePosition - self.pos);
|
||||||
}
|
}
|
||||||
draw.restoreTranslation(oldTranslation);
|
draw.restoreTranslation(oldTranslation);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mainButtonPressed(self: *VerticalList, pos: Vec2f, _: Vec2f, mousePosition: Vec2f) void {
|
pub fn mainButtonPressed(self: *VerticalList, mousePosition: Vec2f) void {
|
||||||
var selectedChild: ?*GuiComponent = null;
|
var selectedChild: ?*GuiComponent = null;
|
||||||
for(self.children.items) |*child| {
|
for(self.children.items) |*child| {
|
||||||
if(GuiComponent.contains(child.pos + pos, child.size, mousePosition)) {
|
if(GuiComponent.contains(child.pos() + self.pos, child.size(), mousePosition)) {
|
||||||
selectedChild = child;
|
selectedChild = child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(selectedChild) |child| {
|
if(selectedChild) |child| {
|
||||||
child.mainButtonPressed(mousePosition - pos);
|
child.mainButtonPressed(mousePosition - self.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mainButtonReleased(self: *VerticalList, pos: Vec2f, _: Vec2f, mousePosition: Vec2f) void {
|
pub fn mainButtonReleased(self: *VerticalList, mousePosition: Vec2f) void {
|
||||||
for(self.children.items) |*child| {
|
for(self.children.items) |*child| {
|
||||||
child.mainButtonReleased(mousePosition - pos);
|
child.mainButtonReleased(mousePosition - self.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,7 +14,7 @@ const CheckBox = @import("components/CheckBox.zig");
|
|||||||
const ScrollBar = @import("components/ScrollBar.zig");
|
const ScrollBar = @import("components/ScrollBar.zig");
|
||||||
const Slider = @import("components/Slider.zig");
|
const Slider = @import("components/Slider.zig");
|
||||||
const TextInput = @import("components/TextInput.zig");
|
const TextInput = @import("components/TextInput.zig");
|
||||||
pub const GuiComponent = @import("GuiComponent.zig");
|
pub const GuiComponent = @import("gui_component.zig").GuiComponent;
|
||||||
pub const GuiWindow = @import("GuiWindow.zig");
|
pub const GuiWindow = @import("GuiWindow.zig");
|
||||||
|
|
||||||
const windowlist = @import("windows/_windowlist.zig");
|
const windowlist = @import("windows/_windowlist.zig");
|
||||||
|
139
src/gui/gui_component.zig
Normal file
139
src/gui/gui_component.zig
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const main = @import("root");
|
||||||
|
const vec = main.vec;
|
||||||
|
const Vec2f = vec.Vec2f;
|
||||||
|
|
||||||
|
pub const GuiComponent = union(enum) {
|
||||||
|
|
||||||
|
pub const Button = @import("components/Button.zig");
|
||||||
|
pub const CheckBox = @import("components/CheckBox.zig");
|
||||||
|
pub const Label = @import("components/Label.zig");
|
||||||
|
pub const Slider = @import("components/Slider.zig");
|
||||||
|
pub const ScrollBar = @import("components/ScrollBar.zig");
|
||||||
|
pub const TextInput = @import("components/TextInput.zig");
|
||||||
|
pub const VerticalList = @import("components/VerticalList.zig");
|
||||||
|
|
||||||
|
|
||||||
|
button: *Button,
|
||||||
|
checkBox: *CheckBox,
|
||||||
|
label: *Label,
|
||||||
|
scrollBar: *ScrollBar,
|
||||||
|
slider: *Slider,
|
||||||
|
textInput: *TextInput,
|
||||||
|
verticalList: *VerticalList,
|
||||||
|
|
||||||
|
pub fn deinit(self: *GuiComponent) void {
|
||||||
|
switch(self.*) {
|
||||||
|
inline else => |impl| {
|
||||||
|
// Only call the function if it exists:
|
||||||
|
inline for(@typeInfo(@TypeOf(impl.*)).Struct.decls) |decl| {
|
||||||
|
if(comptime std.mem.eql(u8, decl.name, "deinit")) {
|
||||||
|
impl.deinit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mutPos(self: *GuiComponent) *Vec2f {
|
||||||
|
switch(self.*) {
|
||||||
|
inline else => |impl| {
|
||||||
|
return &impl.pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mutSize(self: *GuiComponent) *Vec2f {
|
||||||
|
switch(self.*) {
|
||||||
|
inline else => |impl| {
|
||||||
|
return &impl.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pos(self: *GuiComponent) Vec2f {
|
||||||
|
switch(self.*) {
|
||||||
|
inline else => |impl| {
|
||||||
|
return impl.pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size(self: *GuiComponent) Vec2f {
|
||||||
|
switch(self.*) {
|
||||||
|
inline else => |impl| {
|
||||||
|
return impl.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn updateSelected(self: *GuiComponent) void {
|
||||||
|
switch(self.*) {
|
||||||
|
inline else => |impl| {
|
||||||
|
// Only call the function if it exists:
|
||||||
|
inline for(@typeInfo(@TypeOf(impl.*)).Struct.decls) |decl| {
|
||||||
|
if(comptime std.mem.eql(u8, decl.name, "updateSelected")) {
|
||||||
|
impl.updateSelected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn updateHovered(self: *GuiComponent, mousePosition: Vec2f) void {
|
||||||
|
switch(self.*) {
|
||||||
|
inline else => |impl| {
|
||||||
|
// Only call the function if it exists:
|
||||||
|
inline for(@typeInfo(@TypeOf(impl.*)).Struct.decls) |decl| {
|
||||||
|
if(comptime std.mem.eql(u8, decl.name, "updateHovered")) {
|
||||||
|
impl.updateHovered(mousePosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(self: *GuiComponent, mousePosition: Vec2f) !void {
|
||||||
|
switch(self.*) {
|
||||||
|
inline else => |impl| {
|
||||||
|
// 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(mousePosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mainButtonPressed(self: *GuiComponent, mousePosition: Vec2f) void {
|
||||||
|
switch(self.*) {
|
||||||
|
inline else => |impl| {
|
||||||
|
// 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(mousePosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mainButtonReleased(self: *GuiComponent, mousePosition: Vec2f) void {
|
||||||
|
switch(self.*) {
|
||||||
|
inline else => |impl| {
|
||||||
|
// 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(mousePosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contains(_pos: Vec2f, _size: Vec2f, point: Vec2f) bool {
|
||||||
|
return @reduce(.And, point >= _pos) and @reduce(.And, point < _pos + _size);
|
||||||
|
}
|
||||||
|
};
|
@ -22,12 +22,12 @@ pub var window = GuiWindow {
|
|||||||
.onCloseFn = &onClose,
|
.onCloseFn = &onClose,
|
||||||
.components = &components,
|
.components = &components,
|
||||||
};
|
};
|
||||||
|
var textComponent: *TextInput = undefined;
|
||||||
|
|
||||||
const padding: f32 = 8;
|
const padding: f32 = 8;
|
||||||
|
|
||||||
fn apply() void {
|
fn apply() void {
|
||||||
const oldName = settings.playerName;
|
const oldName = settings.playerName;
|
||||||
const textComponent: *TextInput = &components[0].impl.verticalList.children.items[5].impl.textInput;
|
|
||||||
main.globalAllocator.free(settings.playerName);
|
main.globalAllocator.free(settings.playerName);
|
||||||
settings.playerName = main.globalAllocator.dupe(u8, textComponent.currentString.items) catch {
|
settings.playerName = main.globalAllocator.dupe(u8, textComponent.currentString.items) catch {
|
||||||
std.log.err("Encountered out of memory in change_name.apply.", .{});
|
std.log.err("Encountered out of memory in change_name.apply.", .{});
|
||||||
@ -55,10 +55,11 @@ pub fn onOpen() Allocator.Error!void {
|
|||||||
try list.add(try Label.init(.{0, 16}, width, "\\**italic*\\* \\*\\***bold**\\*\\* \\__underlined_\\_ \\_\\___strike-through__\\_\\_", .center));
|
try list.add(try Label.init(.{0, 16}, width, "\\**italic*\\* \\*\\***bold**\\*\\* \\__underlined_\\_ \\_\\___strike-through__\\_\\_", .center));
|
||||||
try list.add(try Label.init(.{0, 16}, width, "Even colors are possible, using the hexadecimal color code:", .center));
|
try list.add(try Label.init(.{0, 16}, width, "Even colors are possible, using the hexadecimal color code:", .center));
|
||||||
try list.add(try Label.init(.{0, 16}, width, "\\##ff0000ff#00000000#00000000#ff0000red#000000 \\##ff0000ff#00770077#00000000#ff7700orange#000000 \\##00000000#00ff00ff#00000000#00ff00green#000000 \\##00000000#00000000#0000ffff#0000ffblue", .center));
|
try list.add(try Label.init(.{0, 16}, width, "\\##ff0000ff#00000000#00000000#ff0000red#000000 \\##ff0000ff#00770077#00000000#ff7700orange#000000 \\##00000000#00ff00ff#00000000#00ff00green#000000 \\##00000000#00000000#0000ffff#0000ffblue", .center));
|
||||||
try list.add(try TextInput.init(.{0, 16}, width, 32, "quanturmdoelvloper"));
|
textComponent = try TextInput.init(.{0, 16}, width, 32, "quanturmdoelvloper");
|
||||||
|
try list.add(textComponent);
|
||||||
try list.add(try Button.init(.{0, 16}, 100, "Apply", &apply));
|
try list.add(try Button.init(.{0, 16}, 100, "Apply", &apply));
|
||||||
components[0] = list.toComponent(.{padding, padding});
|
components[0] = list.toComponent(.{padding, padding});
|
||||||
window.contentSize = components[0].size + @splat(2, @as(f32, 2*padding));
|
window.contentSize = components[0].size() + @splat(2, @as(f32, 2*padding));
|
||||||
gui.updateWindowPositions();
|
gui.updateWindowPositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ fn keypressListener(key: c_int, mouseButton: c_int, scancode: c_int) void {
|
|||||||
|
|
||||||
pub fn onOpen() Allocator.Error!void {
|
pub fn onOpen() Allocator.Error!void {
|
||||||
var list = try VerticalList.init();
|
var list = try VerticalList.init();
|
||||||
list.currentOffset = 8;
|
list.size[1] = 8;
|
||||||
inline for(comptime std.meta.fieldNames(@TypeOf(main.keyboard))) |field| {
|
inline for(comptime std.meta.fieldNames(@TypeOf(main.keyboard))) |field| {
|
||||||
var label = try Label.init(.{0, 8}, 128, field, .left);
|
var label = try Label.init(.{0, 8}, 128, field, .left);
|
||||||
var button = if(&@field(main.keyboard, field) == selectedKey) (
|
var button = if(&@field(main.keyboard, field) == selectedKey) (
|
||||||
@ -67,7 +67,7 @@ pub fn onOpen() Allocator.Error!void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
components[0] = list.toComponent(.{padding, padding});
|
components[0] = list.toComponent(.{padding, padding});
|
||||||
window.contentSize = components[0].size + @splat(2, @as(f32, 2*padding));
|
window.contentSize = components[0].size() + @splat(2, @as(f32, 2*padding));
|
||||||
gui.updateWindowPositions();
|
gui.updateWindowPositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ pub fn onOpen() Allocator.Error!void {
|
|||||||
try list.add(try CheckBox.init(.{0, 16}, 128, "Bloom", settings.bloom, &bloomCallback));
|
try list.add(try CheckBox.init(.{0, 16}, 128, "Bloom", settings.bloom, &bloomCallback));
|
||||||
try list.add(try CheckBox.init(.{0, 16}, 128, "Vertical Synchronization", settings.vsync, &vsyncCallback));
|
try list.add(try CheckBox.init(.{0, 16}, 128, "Vertical Synchronization", settings.vsync, &vsyncCallback));
|
||||||
components[0] = list.toComponent(.{padding, padding});
|
components[0] = list.toComponent(.{padding, padding});
|
||||||
window.contentSize = components[0].size + @splat(2, @as(f32, 2*padding));
|
window.contentSize = components[0].size() + @splat(2, @as(f32, 2*padding));
|
||||||
gui.updateWindowPositions();
|
gui.updateWindowPositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@ pub var window = GuiWindow {
|
|||||||
.title = "Hotbar",
|
.title = "Hotbar",
|
||||||
.id = "cubyz:hotbar",
|
.id = "cubyz:hotbar",
|
||||||
.renderFn = &render,
|
.renderFn = &render,
|
||||||
.components = &[_]GuiComponent{},
|
|
||||||
.isHud = true,
|
.isHud = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ pub fn onOpen() Allocator.Error!void {
|
|||||||
try list.add(try Button.init(.{0, 16}, 128, "Settings", gui.openWindowFunction("cubyz:settings")));
|
try list.add(try Button.init(.{0, 16}, 128, "Settings", gui.openWindowFunction("cubyz:settings")));
|
||||||
try list.add(try Button.init(.{0, 16}, 128, "Exit TODO", &buttonCallbackTest));
|
try list.add(try Button.init(.{0, 16}, 128, "Exit TODO", &buttonCallbackTest));
|
||||||
components[0] = list.toComponent(.{padding, padding});
|
components[0] = list.toComponent(.{padding, padding});
|
||||||
window.contentSize = components[0].size + @splat(2, @as(f32, 2*padding));
|
window.contentSize = components[0].size() + @splat(2, @as(f32, 2*padding));
|
||||||
gui.updateWindowPositions();
|
gui.updateWindowPositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ pub var window = GuiWindow {
|
|||||||
.components = &components,
|
.components = &components,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var ipAddressLabel: *Label = undefined;
|
||||||
|
|
||||||
const padding: f32 = 8;
|
const padding: f32 = 8;
|
||||||
|
|
||||||
var connection: ?*ConnectionManager = null;
|
var connection: ?*ConnectionManager = null;
|
||||||
@ -34,9 +36,7 @@ const width: f32 = 420;
|
|||||||
fn flawedDiscoverIpAddress() !void {
|
fn flawedDiscoverIpAddress() !void {
|
||||||
connection = try ConnectionManager.init(12347, true); // TODO: default port
|
connection = try ConnectionManager.init(12347, true); // TODO: default port
|
||||||
ipAddress = try std.fmt.allocPrint(main.globalAllocator, "{}", .{connection.?.externalAddress});
|
ipAddress = try std.fmt.allocPrint(main.globalAllocator, "{}", .{connection.?.externalAddress});
|
||||||
components[0].impl.verticalList.children.items[1].impl.label.deinit();
|
try ipAddressLabel.updateText(ipAddress);
|
||||||
const labelComponent = try Label.init(undefined, width, ipAddress, .center);
|
|
||||||
components[0].impl.verticalList.children.items[1].impl.label = labelComponent.impl.label;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn discoverIpAddress() void {
|
fn discoverIpAddress() void {
|
||||||
@ -87,12 +87,13 @@ pub fn onOpen() Allocator.Error!void {
|
|||||||
var list = try VerticalList.init();
|
var list = try VerticalList.init();
|
||||||
try list.add(try Label.init(.{0, 16}, width, "Please send your IP to the host of the game and enter the host's IP below.", .center));
|
try list.add(try Label.init(.{0, 16}, width, "Please send your IP to the host of the game and enter the host's IP below.", .center));
|
||||||
// 255.255.255.255:?65536 (longest possible ip address)
|
// 255.255.255.255:?65536 (longest possible ip address)
|
||||||
try list.add(try Label.init(.{0, 16}, width, " ", .center));
|
ipAddressLabel = try Label.init(.{0, 16}, width, " ", .center);
|
||||||
|
try list.add(ipAddressLabel);
|
||||||
try list.add(try Button.init(.{0, 16}, 100, "Copy IP", ©Ip));
|
try list.add(try Button.init(.{0, 16}, 100, "Copy IP", ©Ip));
|
||||||
try list.add(try TextInput.init(.{0, 16}, width, 32, settings.lastUsedIPAddress));
|
try list.add(try TextInput.init(.{0, 16}, width, 32, settings.lastUsedIPAddress));
|
||||||
try list.add(try Button.init(.{0, 16}, 100, "Join", &join));
|
try list.add(try Button.init(.{0, 16}, 100, "Join", &join));
|
||||||
components[0] = list.toComponent(.{padding, padding});
|
components[0] = list.toComponent(.{padding, padding});
|
||||||
window.contentSize = components[0].size + @splat(2, @as(f32, 2*padding));
|
window.contentSize = components[0].size() + @splat(2, @as(f32, 2*padding));
|
||||||
gui.updateWindowPositions();
|
gui.updateWindowPositions();
|
||||||
|
|
||||||
thread = std.Thread.spawn(.{}, discoverIpAddressFromNewThread, .{}) catch |err| blk: {
|
thread = std.Thread.spawn(.{}, discoverIpAddressFromNewThread, .{}) catch |err| blk: {
|
||||||
|
@ -29,7 +29,7 @@ pub fn onOpen() Allocator.Error!void {
|
|||||||
try list.add(try Button.init(.{0, 16}, 128, "Controls", gui.openWindowFunction("cubyz:controls")));
|
try list.add(try Button.init(.{0, 16}, 128, "Controls", gui.openWindowFunction("cubyz:controls")));
|
||||||
try list.add(try Button.init(.{0, 16}, 128, "Change Name", gui.openWindowFunction("cubyz:change_name")));
|
try list.add(try Button.init(.{0, 16}, 128, "Change Name", gui.openWindowFunction("cubyz:change_name")));
|
||||||
components[0] = list.toComponent(.{padding, padding});
|
components[0] = list.toComponent(.{padding, padding});
|
||||||
window.contentSize = components[0].size + @splat(2, @as(f32, 2*padding));
|
window.contentSize = components[0].size() + @splat(2, @as(f32, 2*padding));
|
||||||
gui.updateWindowPositions();
|
gui.updateWindowPositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ pub fn onOpen() Allocator.Error!void {
|
|||||||
var list = try VerticalList.init();
|
var list = try VerticalList.init();
|
||||||
// TODO
|
// TODO
|
||||||
components[0] = list.toComponent(.{padding, padding});
|
components[0] = list.toComponent(.{padding, padding});
|
||||||
window.contentSize = components[0].size + @splat(2, @as(f32, 2*padding));
|
window.contentSize = components[0].size() + @splat(2, @as(f32, 2*padding));
|
||||||
gui.updateWindowPositions();
|
gui.updateWindowPositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user