From c9c6bcaece39d1f0b13f6924ab7b7eb78216f3ea Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Fri, 3 Mar 2023 19:26:15 +0100 Subject: [PATCH] Add the controls settings and some other things. --- src/graphics.zig | 2 +- src/gui/GuiWindow.zig | 6 +- src/gui/components/VerticalList.zig | 19 +++--- src/gui/windows/controls.zig | 57 +++++++++++++++-- src/gui/windows/graphics.zig | 9 ++- src/gui/windows/healthbar.zig | 7 ++- src/gui/windows/hotbar.zig | 4 +- src/gui/windows/sound.zig | 2 +- src/main.zig | 95 ++++++++++++++++++++++++++++- src/settings.zig | 2 + 10 files changed, 176 insertions(+), 27 deletions(-) diff --git a/src/graphics.zig b/src/graphics.zig index 4c49f89c..f117b652 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -42,7 +42,7 @@ pub const draw = struct { /// Returns the previous translation. pub fn setTranslation(newTranslation: Vec2f) Vec2f { const oldTranslation = translation; - translation += newTranslation; + translation += newTranslation*@splat(2, scale); return oldTranslation; } diff --git a/src/gui/GuiWindow.zig b/src/gui/GuiWindow.zig index e01e7631..a494e1e1 100644 --- a/src/gui/GuiWindow.zig +++ b/src/gui/GuiWindow.zig @@ -58,9 +58,9 @@ id: []const u8, components: []GuiComponent, /// Called every frame. -renderFn: *const fn()void = &defaultFunction, +renderFn: *const fn()Allocator.Error!void = &defaultErrorFunction, /// Called every frame for the currently selected window. -updateFn: *const fn()void = &defaultFunction, +updateFn: *const fn()Allocator.Error!void = &defaultErrorFunction, onOpenFn: *const fn()Allocator.Error!void = &defaultErrorFunction, @@ -271,6 +271,7 @@ fn positionRelativeToConnectedWindow(self: *GuiWindow, other: *GuiWindow, i: usi } pub fn update(self: *GuiWindow) !void { + try self.updateFn(); const scale = @floor(settings.guiScale*self.scale); // TODO const mousePosition = main.Window.getMousePosition(); const windowSize = main.Window.getWindowSize(); @@ -396,6 +397,7 @@ pub fn render(self: *const GuiWindow) !void { shader.bind(); backgroundTexture.bind(); draw.customShadedRect(windowUniforms, .{0, 0}, self.size); + try self.renderFn(); for(self.components) |*component| { try component.render(mousePosition); } diff --git a/src/gui/components/VerticalList.zig b/src/gui/components/VerticalList.zig index c70d2489..86de3722 100644 --- a/src/gui/components/VerticalList.zig +++ b/src/gui/components/VerticalList.zig @@ -32,9 +32,6 @@ pub fn deinit(self: VerticalList) void { } pub fn toComponent(self: *VerticalList, pos: Vec2f) GuiComponent { - for(self.children.items) |*child| { - child.pos += pos; - } return GuiComponent { .pos = pos, .size = .{self.maxWidth, self.currentOffset}, @@ -56,26 +53,28 @@ pub fn update(self: *VerticalList, _: Vec2f, _: Vec2f) void { } } -pub fn render(self: *VerticalList, _: Vec2f, _: Vec2f, mousePosition: Vec2f) anyerror!void { // TODO: Remove anyerror once error union inference works in recursive loops. +pub fn render(self: *VerticalList, pos: Vec2f, _: Vec2f, mousePosition: Vec2f) anyerror!void { // TODO: Remove anyerror once error union inference works in recursive loops. + const oldTranslation = draw.setTranslation(pos); for(self.children.items) |*child| { - try child.render(mousePosition); + try child.render(mousePosition - pos); } + draw.restoreTranslation(oldTranslation); } -pub fn mainButtonPressed(self: *VerticalList, _: Vec2f, _: Vec2f, mousePosition: Vec2f) void { +pub fn mainButtonPressed(self: *VerticalList, pos: Vec2f, _: Vec2f, mousePosition: Vec2f) void { var selectedChild: ?*GuiComponent = null; for(self.children.items) |*child| { - if(GuiComponent.contains(child.pos, child.size, mousePosition)) { + if(GuiComponent.contains(child.pos + pos, child.size, mousePosition)) { selectedChild = child; } } if(selectedChild) |child| { - child.mainButtonPressed(mousePosition); + child.mainButtonPressed(mousePosition - pos); } } -pub fn mainButtonReleased(self: *VerticalList, _: Vec2f, _: Vec2f, mousePosition: Vec2f) void { +pub fn mainButtonReleased(self: *VerticalList, pos: Vec2f, _: Vec2f, mousePosition: Vec2f) void { for(self.children.items) |*child| { - child.mainButtonReleased(mousePosition); + child.mainButtonReleased(mousePosition - pos); } } \ No newline at end of file diff --git a/src/gui/windows/controls.zig b/src/gui/windows/controls.zig index 0bbcc907..d9305f4f 100644 --- a/src/gui/windows/controls.zig +++ b/src/gui/windows/controls.zig @@ -8,6 +8,7 @@ const gui = @import("../gui.zig"); const GuiComponent = gui.GuiComponent; const GuiWindow = gui.GuiWindow; const Button = @import("../components/Button.zig"); +const Label = @import("../components/Label.zig"); const VerticalList = @import("../components/VerticalList.zig"); var window: GuiWindow = undefined; @@ -19,20 +20,56 @@ pub fn init() !void { .title = "Controls", .onOpenFn = &onOpen, .onCloseFn = &onClose, + .renderFn = &render, .components = &components, }; try gui.addWindow(&window, true); } const padding: f32 = 8; +var selectedKey: ?*main.Key = null; +var needsUpdate: bool = false; + +fn functionBuilder(comptime name: []const u8) fn() void { + return struct { + fn function() void { + main.setNextKeypressListener(&keypressListener) catch return; + selectedKey = &@field(main.keyboard, name); + needsUpdate = true; + } + }.function; +} + +fn keypressListener(key: c_int, mouseButton: c_int, scancode: c_int) void { + selectedKey.?.key = key; + selectedKey.?.mouseButton = mouseButton; + selectedKey.?.scancode = scancode; + selectedKey = null; + needsUpdate = true; +} pub fn onOpen() Allocator.Error!void { var list = try VerticalList.init(main.globalAllocator); - // TODO - //try list.add(try Button.init(.{0, 16}, 128, main.globalAllocator, "Singleplayer TODO", &buttonCallbackTest)); - //try list.add(try Button.init(.{0, 16}, 128, main.globalAllocator, "Multiplayer TODO", &buttonCallbackTest)); - //try list.add(try Button.init(.{0, 16}, 128, main.globalAllocator, "Settings", gui.openWindowFunction("cubyz:settings"))); - //try list.add(try Button.init(.{0, 16}, 128, main.globalAllocator, "Exit TODO", &buttonCallbackTest)); + list.currentOffset = 8; + inline for(comptime std.meta.fieldNames(@TypeOf(main.keyboard))) |field| { + var label = try Label.init(main.globalAllocator, .{0, 8}, 128, field); + var button = if(&@field(main.keyboard, field) == selectedKey) ( + try Button.init(main.globalAllocator, .{128 + 16, 8}, 128, "...", null) + ) else ( + try Button.init(main.globalAllocator, .{128 + 16, 8}, 128, @field(main.keyboard, field).getName(), &functionBuilder(field)) + ); + if(label.size[1] > button.size[1]) { + button.pos[1] += (label.size[1] - button.size[1])/2; + try list.add(button); + label.pos[1] -= button.size[1] + button.pos[1]; + try list.add(label); + } else { + label.pos[1] += (button.size[1] - label.size[1])/2; + try list.add(label); + button.pos[1] -= label.size[1] + label.pos[1]; + try list.add(button); + } + } components[0] = list.toComponent(.{padding, padding}); window.contentSize = components[0].size + @splat(2, @as(f32, 2*padding)); gui.updateWindowPositions(); @@ -42,4 +79,14 @@ pub fn onClose() void { for(&components) |*comp| { comp.deinit(); } +} + +pub fn render() Allocator.Error!void { + if(needsUpdate) { + needsUpdate = false; + onClose(); + onOpen() catch { + std.log.err("Received out of memory error while rebuilding the controls GUI. This behavior is not handled.", .{}); + }; + } } \ No newline at end of file diff --git a/src/gui/windows/graphics.zig b/src/gui/windows/graphics.zig index 43b7771c..d53c1384 100644 --- a/src/gui/windows/graphics.zig +++ b/src/gui/windows/graphics.zig @@ -41,15 +41,20 @@ fn bloomCallback(newValue: bool) void { settings.bloom = newValue; } +fn vsyncCallback(newValue: bool) void { + settings.vsync = newValue; + main.Window.reloadSettings(); +} + pub fn onOpen() Allocator.Error!void { var list = try VerticalList.init(main.globalAllocator); const renderDistances = [_]u32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; try list.add(try Slider.init(main.globalAllocator, .{0, 16}, 128, "#ffffffRender Distance: ", "{}", &renderDistances, settings.renderDistance - 1, &renderDistanceCallback)); const LODFactors = [_]f32{0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8}; try list.add(try Slider.init(main.globalAllocator, .{0, 16}, 128, "#ffffffLOD Factor: ", "{d:.1}", &LODFactors, @floatToInt(u16, settings.LODFactor*2) - 1, &LODFactorCallback)); - // TODO: fog + // TODO: fog? try list.add(try CheckBox.init(main.globalAllocator, .{0, 16}, 128, "Bloom", settings.bloom, &bloomCallback)); - // TODO: vsync checkbox + try list.add(try CheckBox.init(main.globalAllocator, .{0, 16}, 128, "Vertical Synchronization", settings.vsync, &vsyncCallback)); components[0] = list.toComponent(.{padding, padding}); window.contentSize = components[0].size + @splat(2, @as(f32, 2*padding)); gui.updateWindowPositions(); diff --git a/src/gui/windows/healthbar.zig b/src/gui/windows/healthbar.zig index f897a992..eeef2f58 100644 --- a/src/gui/windows/healthbar.zig +++ b/src/gui/windows/healthbar.zig @@ -1,3 +1,6 @@ +const std = @import("std"); +const Allocator = std.mem.Allocator; + const main = @import("root"); const Vec2f = main.vec.Vec2f; @@ -18,10 +21,10 @@ pub fn init() !void { try gui.addWindow(&healthbarWindow, true); } -pub fn render() void { +pub fn render() Allocator.Error!void { } -pub fn update() void { +pub fn update() Allocator.Error!void { } \ No newline at end of file diff --git a/src/gui/windows/hotbar.zig b/src/gui/windows/hotbar.zig index 8aa28959..25fd03e6 100644 --- a/src/gui/windows/hotbar.zig +++ b/src/gui/windows/hotbar.zig @@ -41,10 +41,10 @@ pub fn init() !void { try gui.addWindow(&hotbarWindow3, true); } -pub fn render() void { +pub fn render() Allocator.Error!void { } -pub fn update() void { +pub fn update() Allocator.Error!void { } \ No newline at end of file diff --git a/src/gui/windows/sound.zig b/src/gui/windows/sound.zig index 638ecebd..c3ba1ff0 100644 --- a/src/gui/windows/sound.zig +++ b/src/gui/windows/sound.zig @@ -16,7 +16,7 @@ pub fn init() !void { window = GuiWindow{ .contentSize = Vec2f{128, 256}, .id = "cubyz:sound", - .title = "Sound", + .title = "Sound TODO", .onOpenFn = &onOpen, .onCloseFn = &onClose, .components = &components, diff --git a/src/main.zig b/src/main.zig index 0ded3fdf..d1a6c59d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -61,14 +61,93 @@ pub const std_options = struct { -const Key = struct { +pub const Key = struct { pressed: bool = false, key: c_int = c.GLFW_KEY_UNKNOWN, mouseButton: c_int = -1, scancode: c_int = 0, releaseAction: ?*const fn() void = null, pressAction: ?*const fn() void = null, + + pub fn getName(self: Key) []const u8 { + if(self.mouseButton == -1) { + const cName = c.glfwGetKeyName(self.key, self.scancode); + if(cName != null) return std.mem.span(cName); + return switch(self.key) { + c.GLFW_KEY_SPACE => "Space", + c.GLFW_KEY_GRAVE_ACCENT => "Grave Accent", + c.GLFW_KEY_ESCAPE => "Escape", + c.GLFW_KEY_ENTER => "Enter", + c.GLFW_KEY_TAB => "Tab", + c.GLFW_KEY_BACKSPACE => "Backspace", + c.GLFW_KEY_INSERT => "Insert", + c.GLFW_KEY_DELETE => "Delete", + c.GLFW_KEY_RIGHT => "Right", + c.GLFW_KEY_LEFT => "Left", + c.GLFW_KEY_DOWN => "Down", + c.GLFW_KEY_UP => "Up", + c.GLFW_KEY_PAGE_UP => "Page Up", + c.GLFW_KEY_PAGE_DOWN => "Page Down", + c.GLFW_KEY_HOME => "Home", + c.GLFW_KEY_END => "End", + c.GLFW_KEY_CAPS_LOCK => "Caps Lock", + c.GLFW_KEY_SCROLL_LOCK => "Scroll Lock", + c.GLFW_KEY_NUM_LOCK => "Num Lock", + c.GLFW_KEY_PRINT_SCREEN => "Print Screen", + c.GLFW_KEY_PAUSE => "Pause", + c.GLFW_KEY_F1 => "F1", + c.GLFW_KEY_F2 => "F2", + c.GLFW_KEY_F3 => "F3", + c.GLFW_KEY_F4 => "F4", + c.GLFW_KEY_F5 => "F5", + c.GLFW_KEY_F6 => "F6", + c.GLFW_KEY_F7 => "F7", + c.GLFW_KEY_F8 => "F8", + c.GLFW_KEY_F9 => "F9", + c.GLFW_KEY_F10 => "F10", + c.GLFW_KEY_F11 => "F11", + c.GLFW_KEY_F12 => "F12", + c.GLFW_KEY_F13 => "F13", + c.GLFW_KEY_F14 => "F14", + c.GLFW_KEY_F15 => "F15", + c.GLFW_KEY_F16 => "F16", + c.GLFW_KEY_F17 => "F17", + c.GLFW_KEY_F18 => "F18", + c.GLFW_KEY_F19 => "F19", + c.GLFW_KEY_F20 => "F20", + c.GLFW_KEY_F21 => "F21", + c.GLFW_KEY_F22 => "F22", + c.GLFW_KEY_F23 => "F23", + c.GLFW_KEY_F24 => "F24", + c.GLFW_KEY_F25 => "F25", + c.GLFW_KEY_KP_ENTER => "Keypad Enter", + c.GLFW_KEY_LEFT_SHIFT => "Left Shift", + c.GLFW_KEY_LEFT_CONTROL => "Left Control", + c.GLFW_KEY_LEFT_ALT => "Left Alt", + c.GLFW_KEY_LEFT_SUPER => "Left Super", + c.GLFW_KEY_RIGHT_SHIFT => "Right Shift", + c.GLFW_KEY_RIGHT_CONTROL => "Right Control", + c.GLFW_KEY_RIGHT_ALT => "Right Alt", + c.GLFW_KEY_RIGHT_SUPER => "Right Super", + c.GLFW_KEY_MENU => "Menu", + else => "Unknown Key", + }; + } else { + return switch(self.mouseButton) { + c.GLFW_MOUSE_BUTTON_LEFT => "Left Button", + c.GLFW_MOUSE_BUTTON_MIDDLE => "Middle Button", + c.GLFW_MOUSE_BUTTON_RIGHT => "Right Button", + else => "Other Mouse Button", + }; + } + } }; + +var nextKeypressListener: ?*const fn(c_int, c_int, c_int) void = null; +pub fn setNextKeypressListener(listener: ?*const fn(c_int, c_int, c_int) void) !void { + if(nextKeypressListener != null) return error.AlreadyUsed; + nextKeypressListener = listener; +} pub var keyboard: struct { forward: Key = Key{.key = c.GLFW_KEY_W}, left: Key = Key{.key = c.GLFW_KEY_A}, @@ -106,6 +185,10 @@ pub const Window = struct { } } } + if(nextKeypressListener) |listener| { + listener(key, -1, scancode); + nextKeypressListener = null; + } } else if(action == c.GLFW_RELEASE) { inline for(@typeInfo(@TypeOf(keyboard)).Struct.fields) |field| { if(key == @field(keyboard, field.name).key) { @@ -162,6 +245,10 @@ pub const Window = struct { } } } + if(nextKeypressListener) |listener| { + listener(c.GLFW_KEY_UNKNOWN, button, 0); + nextKeypressListener = null; + } } else if(action == c.GLFW_RELEASE) { inline for(@typeInfo(@TypeOf(keyboard)).Struct.fields) |field| { if(button == @field(keyboard, field.name).mouseButton) { @@ -206,6 +293,10 @@ pub const Window = struct { return Vec2f{@intToFloat(f32, width), @intToFloat(f32, height)}; } + pub fn reloadSettings() void { + c.glfwSwapInterval(@boolToInt(settings.vsync)); + } + fn init() !void { _ = c.glfwSetErrorCallback(GLFWCallbacks.errorCallback); @@ -231,7 +322,7 @@ pub const Window = struct { if(c.gladLoadGL() == 0) { return error.GLADFailed; } - c.glfwSwapInterval(0); + reloadSettings(); if(@import("builtin").mode == .Debug) { c.glEnable(c.GL_DEBUG_OUTPUT); diff --git a/src/settings.zig b/src/settings.zig index 91d7fba7..d44e84eb 100644 --- a/src/settings.zig +++ b/src/settings.zig @@ -27,6 +27,8 @@ pub var LODFactor: f32 = 2.0; pub var bloom: bool = true; +pub var vsync: bool = true; + pub var playerName: []const u8 = "quanturmdoelvloper"; pub var lastUsedIPAddress: []const u8 = "127.0.0.1";