Add the controls settings and some other things.

This commit is contained in:
IntegratedQuantum 2023-03-03 19:26:15 +01:00
parent df73bc964e
commit c9c6bcaece
10 changed files with 176 additions and 27 deletions

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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.", .{});
};
}
}

View File

@ -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();

View File

@ -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 {
}

View File

@ -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 {
}

View File

@ -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,

View File

@ -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);

View File

@ -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";