From 245ae62fadf4fcb8956081c47daac45998eb6ca8 Mon Sep 17 00:00:00 2001 From: flut2 <150191812+flut2@users.noreply.github.com> Date: Thu, 1 Jan 2026 13:32:21 +0000 Subject: [PATCH 1/5] Windy integration --- assets/resources.rc | 2 +- build.zig | 11 +-- build.zig.zon | 11 ++- client/libs/windy | 1 + client/src/Settings.zig | 8 +-- client/src/assets.zig | 70 +++++++++--------- client/src/input.zig | 72 +++++++++++-------- client/src/main.zig | 43 ++++++----- client/src/render/Context.zig | 37 +++++----- client/src/render/Renderer.zig | 49 +++++++------ client/src/render/Swapchain.zig | 8 +-- client/src/render/vma.zig | 2 +- client/src/ui/elements/Button.zig | 4 +- client/src/ui/elements/Container.zig | 4 +- client/src/ui/elements/Dropdown.zig | 4 +- client/src/ui/elements/DropdownContainer.zig | 4 +- client/src/ui/elements/Input.zig | 4 +- client/src/ui/elements/Item.zig | 4 +- client/src/ui/elements/KeyMapper.zig | 4 +- client/src/ui/elements/Minimap.zig | 4 +- .../src/ui/elements/ScrollableContainer.zig | 6 +- client/src/ui/elements/Slider.zig | 4 +- client/src/ui/elements/Toggle.zig | 4 +- client/src/ui/screens/MapEditorScreen.zig | 71 +++++++++--------- client/src/ui/systems.zig | 4 +- 25 files changed, 225 insertions(+), 210 deletions(-) create mode 160000 client/libs/windy diff --git a/assets/resources.rc b/assets/resources.rc index 5acb31aa..5d480cba 100644 --- a/assets/resources.rc +++ b/assets/resources.rc @@ -1 +1 @@ -GLFW_ICON ICON DISCARDABLE "icon.ico" \ No newline at end of file +WINDY_ICON ICON DISCARDABLE "icon.ico" \ No newline at end of file diff --git a/build.zig b/build.zig index 33115751..aadbe7b4 100644 --- a/build.zig +++ b/build.zig @@ -68,8 +68,11 @@ fn buildClient( const shared_dep = b.dependency("shared", .{ .target = target, .optimize = optimize }); const stbi_dep = b.dependency("stbi", .{ .target = target, .optimize = optimize }); const miniaudio_dep = b.dependency("miniaudio", .{ .target = target, .optimize = optimize }); - const zd_dep = b.dependency("zig_dialog", .{ .target = target, .optimize = optimize }); - const glfw_dep = b.dependency("glfw", .{ .target = target, .optimize = optimize }); + const windy_dep = b.dependency("windy", .{ + .target = target, + .optimize = optimize, + .vulkan_support = true, + }); inline for (.{ true, false }) |check| { const exe = b.addExecutable(.{ @@ -89,10 +92,9 @@ fn buildClient( .{ .name = "uv", .module = shared_dep.module("uv") }, .{ .name = "shared", .module = shared_dep.module("shared") }, .{ .name = "vulkan", .module = vulkan_dep.module("vulkan-zig") }, - .{ .name = "glfw", .module = glfw_dep.module("root") }, + .{ .name = "windy", .module = windy_dep.module("windy") }, .{ .name = "stbi", .module = stbi_dep.module("root") }, .{ .name = "miniaudio", .module = miniaudio_dep.module("root") }, - .{ .name = "zd", .module = zd_dep.module("zig-dialog") }, .{ .name = "ziggy", .module = b.dependency("ziggy", .{ @@ -114,7 +116,6 @@ fn buildClient( exe.root_module.linkLibrary(shared_dep.artifact("libuv")); exe.root_module.linkLibrary(stbi_dep.artifact("stbi")); exe.root_module.linkLibrary(miniaudio_dep.artifact("miniaudio")); - exe.root_module.linkLibrary(glfw_dep.artifact("glfw")); if (tracy) addTracy(b, exe.root_module, shared_dep.path("src/tracy.zig"), target, optimize); diff --git a/build.zig.zon b/build.zig.zon index 1ede6481..e51f7ac0 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -15,18 +15,17 @@ // client deps .miniaudio = .{ .path = "client/libs/miniaudio" }, .stbi = .{ .path = "client/libs/stbi" }, - .glfw = .{ .path = "client/libs/glfw" }, - .zig_dialog = .{ - .url = "git+https://github.com/flut2/zig-dialog.git#b9bf10c89065a1df584513c1c77f3ed7b3e0e730", - .hash = "zig_dialog-0.1.0-XalyXbZiAACnOzEhJVyV07WbknFWxvBIHKqrRy367_Y3", + .windy = .{ + .url = "git+https://github.com/flut2/windy.git#a349bf94cd5a99e1c96f47cf507c29c31aedb130", + .hash = "windy-0.2.0-wLI1BBxAAQApBlYXcbUfavAzQPhOf5nNjygFtGYHBZDc", }, .turbopack = .{ .url = "git+https://github.com/flut2/turbopack.git#d6995ce5a8f071bb759a274ac036dff65909905a", .hash = "turbopack-1.0.0-rSxRjlofAAAoHGx7mg6pkzI3gEh-g9OQcnmF7_px6Sg7", }, .vulkan_zig = .{ - .url = "git+https://github.com/Snektron/vulkan-zig.git#93bc6f1ac3e13dd98d918e242dc892f179a0d0f5", - .hash = "vulkan-0.0.0-r7YtxwA_AwAU4rmOITZD_KJs11Kie1sv0t-pcMDQGIqw", + .url = "git+https://github.com/Snektron/vulkan-zig.git#1446b0b994c2362264cc24513d7c7ec31b469c50", + .hash = "vulkan-0.0.0-r7Ytx_VDAwAiMl0YSu2UOkVMIGJN7CeIQaxJR-hUSfD6", }, .vma = .{ .url = "https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/archive/refs/tags/v3.3.0.tar.gz", diff --git a/client/libs/windy b/client/libs/windy new file mode 160000 index 00000000..039f79cb --- /dev/null +++ b/client/libs/windy @@ -0,0 +1 @@ +Subproject commit 039f79cbf4dfe31d0db761cc763b46eed545ac3a diff --git a/client/src/Settings.zig b/client/src/Settings.zig index a342872d..8f06d344 100644 --- a/client/src/Settings.zig +++ b/client/src/Settings.zig @@ -1,7 +1,7 @@ const std = @import("std"); const builtin = @import("builtin"); -const glfw = @import("glfw"); +const windy = @import("windy"); const ziggy = @import("ziggy"); const assets = @import("assets.zig"); @@ -10,7 +10,7 @@ const main = @import("main.zig"); const Settings = @This(); pub const CursorType = enum { basic, royal, ranger, aztec, fiery, target_enemy, target_ally }; -pub const Button = union(enum) { key: glfw.Key, mouse: glfw.MouseButton }; +pub const Button = union(enum) { key: windy.Key, mouse: windy.MouseButton }; var arena: std.heap.ArenaAllocator = undefined; pub var needs_char_id_dispose = false; @@ -30,10 +30,10 @@ escape: Button = .{ .key = .tab }, chat_up: Button = .{ .key = .page_up }, chat_down: Button = .{ .key = .page_down }, walk: Button = .{ .key = .left_shift }, -toggle_perf_stats: Button = .{ .key = .F3 }, +toggle_perf_stats: Button = .{ .key = .f3 }, chat: Button = .{ .key = .enter }, chat_cmd: Button = .{ .key = .slash }, -respond: Button = .{ .key = .F2 }, +respond: Button = .{ .key = .f2 }, shoot: Button = .{ .mouse = .left }, sfx_volume: f32 = 0.33, music_volume: f32 = 0.1, diff --git a/client/src/assets.zig b/client/src/assets.zig index 08b64463..4e59dcba 100644 --- a/client/src/assets.zig +++ b/client/src/assets.zig @@ -1,7 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const glfw = @import("glfw"); const miniaudio = @import("miniaudio"); const pack = @import("turbopack"); const shared = @import("shared"); @@ -10,6 +9,7 @@ const utils = shared.utils; const f32i = utils.f32i; const RGBA = utils.RGBA; const stbi = @import("stbi"); +const windy = @import("windy"); const ziggy = @import("ziggy"); const main = @import("main.zig"); @@ -326,21 +326,21 @@ pub var medium_data: ParsedFontData = undefined; pub var medium_italic_atlas: stbi.Image = undefined; pub var medium_italic_data: ParsedFontData = undefined; -// horrible, but no other option since cursor is opaque -pub var default_cursor_pressed: *glfw.Cursor = undefined; -pub var default_cursor: *glfw.Cursor = undefined; -pub var royal_cursor_pressed: *glfw.Cursor = undefined; -pub var royal_cursor: *glfw.Cursor = undefined; -pub var ranger_cursor_pressed: *glfw.Cursor = undefined; -pub var ranger_cursor: *glfw.Cursor = undefined; -pub var aztec_cursor_pressed: *glfw.Cursor = undefined; -pub var aztec_cursor: *glfw.Cursor = undefined; -pub var fiery_cursor_pressed: *glfw.Cursor = undefined; -pub var fiery_cursor: *glfw.Cursor = undefined; -pub var target_enemy_cursor_pressed: *glfw.Cursor = undefined; -pub var target_enemy_cursor: *glfw.Cursor = undefined; -pub var target_ally_cursor_pressed: *glfw.Cursor = undefined; -pub var target_ally_cursor: *glfw.Cursor = undefined; +// TODO: clean this up now that we're on Windy +pub var default_cursor_pressed: windy.Cursor = undefined; +pub var default_cursor: windy.Cursor = undefined; +pub var royal_cursor_pressed: windy.Cursor = undefined; +pub var royal_cursor: windy.Cursor = undefined; +pub var ranger_cursor_pressed: windy.Cursor = undefined; +pub var ranger_cursor: windy.Cursor = undefined; +pub var aztec_cursor_pressed: windy.Cursor = undefined; +pub var aztec_cursor: windy.Cursor = undefined; +pub var fiery_cursor_pressed: windy.Cursor = undefined; +pub var fiery_cursor: windy.Cursor = undefined; +pub var target_enemy_cursor_pressed: windy.Cursor = undefined; +pub var target_enemy_cursor: windy.Cursor = undefined; +pub var target_ally_cursor_pressed: windy.Cursor = undefined; +pub var target_ally_cursor: windy.Cursor = undefined; pub var sfx_copy_map: std.AutoHashMapUnmanaged(*miniaudio.Sound, std.ArrayList(*miniaudio.Sound)) = .empty; pub var sfx_map: std.StringHashMapUnmanaged(*miniaudio.Sound) = .empty; @@ -433,8 +433,12 @@ fn addCursors(comptime image_name: [:0]const u8, comptime cut_width: u32, compti @memcpy(temp[target_idx .. target_idx + 4], img.data[src_idx .. src_idx + 4]); } - const cursor = try glfw.Cursor.create( - .{ .w = cut_width, .h = cut_height, .pixels = temp.ptr }, + for (0..temp.len / 4) |j| std.mem.swap(u8, &temp[j * 4], &temp[j * 4 + 2]); + + const cursor: windy.Cursor = try .create( + temp, + cut_width, + cut_height, cut_width / 2, cut_height / 2, ); @@ -1411,8 +1415,8 @@ fn populateKeyMap() void { .{ Settings.Button{ .mouse = .left }, 46 }, .{ Settings.Button{ .mouse = .right }, 59 }, .{ Settings.Button{ .mouse = .middle }, 58 }, - .{ Settings.Button{ .mouse = .four }, 108 }, - .{ Settings.Button{ .mouse = .five }, 109 }, + .{ Settings.Button{ .mouse = .m4 }, 108 }, + .{ Settings.Button{ .mouse = .m5 }, 109 }, .{ Settings.Button{ .key = .zero }, 0 }, .{ Settings.Button{ .key = .one }, 4 }, .{ Settings.Button{ .key = .two }, 5 }, @@ -1433,18 +1437,18 @@ fn populateKeyMap() void { .{ Settings.Button{ .key = .kp_7 }, 98 }, .{ Settings.Button{ .key = .kp_8 }, 99 }, .{ Settings.Button{ .key = .kp_9 }, 100 }, - .{ Settings.Button{ .key = .F1 }, 68 }, - .{ Settings.Button{ .key = .F2 }, 69 }, - .{ Settings.Button{ .key = .F3 }, 70 }, - .{ Settings.Button{ .key = .F4 }, 71 }, - .{ Settings.Button{ .key = .F5 }, 72 }, - .{ Settings.Button{ .key = .F6 }, 73 }, - .{ Settings.Button{ .key = .F7 }, 74 }, - .{ Settings.Button{ .key = .F8 }, 75 }, - .{ Settings.Button{ .key = .F9 }, 76 }, - .{ Settings.Button{ .key = .F10 }, 1 }, - .{ Settings.Button{ .key = .F11 }, 2 }, - .{ Settings.Button{ .key = .F12 }, 3 }, + .{ Settings.Button{ .key = .f1 }, 68 }, + .{ Settings.Button{ .key = .f2 }, 69 }, + .{ Settings.Button{ .key = .f3 }, 70 }, + .{ Settings.Button{ .key = .f4 }, 71 }, + .{ Settings.Button{ .key = .f5 }, 72 }, + .{ Settings.Button{ .key = .f6 }, 73 }, + .{ Settings.Button{ .key = .f7 }, 74 }, + .{ Settings.Button{ .key = .f8 }, 75 }, + .{ Settings.Button{ .key = .f9 }, 76 }, + .{ Settings.Button{ .key = .f10 }, 1 }, + .{ Settings.Button{ .key = .f11 }, 2 }, + .{ Settings.Button{ .key = .f12 }, 3 }, .{ Settings.Button{ .key = .a }, 20 }, .{ Settings.Button{ .key = .b }, 34 }, .{ Settings.Button{ .key = .c }, 39 }, @@ -1496,7 +1500,7 @@ fn populateKeyMap() void { .{ Settings.Button{ .key = .enter }, 54 }, .{ Settings.Button{ .key = .delete }, 51 }, .{ Settings.Button{ .key = .end }, 53 }, - .{ Settings.Button{ .key = .print_screen }, 44 }, + .{ Settings.Button{ .key = .print }, 44 }, .{ Settings.Button{ .key = .insert }, 62 }, .{ Settings.Button{ .key = .escape }, 64 }, .{ Settings.Button{ .key = .home }, 87 }, diff --git a/client/src/input.zig b/client/src/input.zig index c4cf0139..13b1cf21 100644 --- a/client/src/input.zig +++ b/client/src/input.zig @@ -1,9 +1,9 @@ const std = @import("std"); -const glfw = @import("glfw"); const shared = @import("shared"); const game_data = shared.game_data; const f32i = shared.utils.f32i; +const windy = @import("windy"); const assets = @import("assets.zig"); const map = @import("game/map.zig"); @@ -160,7 +160,7 @@ fn handleChat() void { } fn handleChatCmd() void { - charEvent(main.window, @intFromEnum(glfw.Key.slash)); + charEvent(main.window, .press, @intFromEnum(windy.Key.slash), .{}); selected_input_field = ui_systems.screen.game.chat_input; ui_systems.screen.game.chat_input.last_input = 0; } @@ -185,7 +185,8 @@ fn handleAbility4() void { if (map.localPlayerRef()) |player| player.useAbility(3); } -pub fn charEvent(_: *glfw.Window, char: u32) callconv(.c) void { +pub fn charEvent(_: *windy.Window, state: windy.PressState, char: u21, _: windy.KeyMods) void { + if (state != .press) return; if (selected_input_field) |input_field| { if (char > std.math.maxInt(u8)) return; const byte_code: u8 = @intCast(char); @@ -199,8 +200,9 @@ pub fn charEvent(_: *glfw.Window, char: u32) callconv(.c) void { } } -pub fn keyEvent(window: *glfw.Window, key: glfw.Key, _: i32, action: glfw.Action, mods: glfw.Mods) callconv(.c) void { - if (action == .press or action == .repeat) { +pub fn keyEvent(window: *windy.Window, state: windy.PressState, key: windy.Key, mods: windy.KeyMods) void { + _ = window; // autofix + if (state == .press) { if (selected_key_mapper) |key_mapper| { key_mapper.settings_button.* = if (key == .escape) .{ .key = .invalid } else .{ .key = key }; key_mapper.listening = false; @@ -209,28 +211,35 @@ pub fn keyEvent(window: *glfw.Window, key: glfw.Key, _: i32, action: glfw.Action } if (selected_input_field) |input_field| { - if (mods.control) { + if (mods.ctrl) { switch (key) { .c => { const old = input_field.text_data.text; - input_field.text_data.backing_buffer[input_field.index] = 0; - window.setClipboardString(input_field.text_data.backing_buffer[0..input_field.index :0]); + windy.setClipboard(input_field.text_data.backing_buffer[0..input_field.index]) catch |e| { + std.log.err("Clipboard set failed: {}", .{e}); + if (@errorReturnTrace()) |trace| std.debug.dumpStackTrace(trace.*); + }; input_field.text_data.text = old; }, .v => { - if (window.getClipboardString()) |clip_str| { - if (clip_str.len > 256 - input_field.index) return; - const clip_len = clip_str.len; - @memcpy(input_field.text_data.backing_buffer[input_field.index .. input_field.index + clip_len], clip_str); - input_field.index += @intCast(clip_len); - input_field.text_data.text = input_field.text_data.backing_buffer[0..input_field.index]; - input_field.inputUpdate(); + const clip_str = windy.getClipboard() catch |e| { + std.log.err("Clipboard get failed: {}", .{e}); + if (@errorReturnTrace()) |trace| std.debug.dumpStackTrace(trace.*); return; - } + }; + if (clip_str.len > 256 - input_field.index) return; + const clip_len = clip_str.len; + @memcpy(input_field.text_data.backing_buffer[input_field.index .. input_field.index + clip_len], clip_str); + input_field.index += @intCast(clip_len); + input_field.text_data.text = input_field.text_data.backing_buffer[0..input_field.index]; + input_field.inputUpdate(); + return; }, .x => { - input_field.text_data.backing_buffer[input_field.index] = 0; - window.setClipboardString(input_field.text_data.backing_buffer[0..input_field.index :0]); + windy.setClipboard(input_field.text_data.backing_buffer[0..input_field.index]) catch |e| { + std.log.err("Clipboard set failed: {}", .{e}); + if (@errorReturnTrace()) |trace| std.debug.dumpStackTrace(trace.*); + }; input_field.clear(); return; }, @@ -303,7 +312,7 @@ pub fn keyEvent(window: *glfw.Window, key: glfw.Key, _: i32, action: glfw.Action inline for (press_mappings) |mapping| if ((mapping[2] or !is_editor) and mapping[0].* == .key and mapping[0].key == key) mapping[1](); if (is_editor) ui_systems.screen.editor.onKeyPress(key); - } else if (action == .release) { + } else if (state == .release) { const is_editor = ui_systems.screen == .editor; if ((ui_systems.screen == .game or is_editor) and !disable_input) inline for (release_mappings) |mapping| @@ -315,8 +324,8 @@ pub fn keyEvent(window: *glfw.Window, key: glfw.Key, _: i32, action: glfw.Action menu.cancelMenu(); } -pub fn mouseEvent(window: *glfw.Window, button: glfw.MouseButton, action: glfw.Action, mods: glfw.Mods) callconv(.c) void { - if (action == .press) { +pub fn mouseEvent(window: *windy.Window, state: windy.PressState, button: windy.MouseButton, _: i16, _: i16, mods: windy.MouseMods) void { + if (state == .press) { window.setCursor(switch (main.settings.cursor_type) { .basic => assets.default_cursor_pressed, .royal => assets.royal_cursor_pressed, @@ -325,7 +334,10 @@ pub fn mouseEvent(window: *glfw.Window, button: glfw.MouseButton, action: glfw.A .fiery => assets.fiery_cursor_pressed, .target_enemy => assets.target_enemy_cursor_pressed, .target_ally => assets.target_ally_cursor_pressed, - }); + }) catch |e| { + std.log.err("Cursor set failed: {}", .{e}); + if (@errorReturnTrace()) |trace| std.debug.dumpStackTrace(trace.*); + }; if (selected_input_field) |input_field| { input_field.last_input = -1; @@ -345,7 +357,7 @@ pub fn mouseEvent(window: *glfw.Window, button: glfw.MouseButton, action: glfw.A inline for (press_mappings) |mapping| if (mapping[0].* == .mouse and mapping[0].mouse == button) mapping[1](); if (is_editor) ui_systems.screen.editor.onMousePress(button); } - } else if (action == .release) { + } else if (state == .release) { window.setCursor(switch (main.settings.cursor_type) { .basic => assets.default_cursor, .royal => assets.royal_cursor, @@ -354,7 +366,11 @@ pub fn mouseEvent(window: *glfw.Window, button: glfw.MouseButton, action: glfw.A .fiery => assets.fiery_cursor, .target_enemy => assets.target_enemy_cursor, .target_ally => assets.target_ally_cursor, - }); + }) catch |e| { + std.log.err("Cursor set failed: {}", .{e}); + if (@errorReturnTrace()) |trace| std.debug.dumpStackTrace(trace.*); + }; + if (!ui_systems.mouseRelease(mouse_x, mouse_y)) { const is_editor = ui_systems.screen == .editor; if ((ui_systems.screen == .game or is_editor) and !disable_input) @@ -372,15 +388,15 @@ pub fn updateMove() void { move_angle = if (y_dt == 0 and x_dt == 0) std.math.nan(f32) else std.math.atan2(y_dt, x_dt); } -pub fn mouseMoveEvent(_: *glfw.Window, x_pos: f64, y_pos: f64) callconv(.c) void { - mouse_x = @floatCast(x_pos); - mouse_y = @floatCast(y_pos); +pub fn mouseMoveEvent(_: *windy.Window, x_pos: i16, y_pos: i16, _: windy.MouseMods) void { + mouse_x = @floatFromInt(x_pos); + mouse_y = @floatFromInt(y_pos); _ = ui_systems.mouseMove(mouse_x, mouse_y); if (ui_systems.screen == .editor) ui_systems.screen.editor.onMouseMove(mouse_x, mouse_y); } -pub fn scrollEvent(_: *glfw.Window, x_offset: f64, y_offset: f64) callconv(.c) void { +pub fn scrollEvent(_: *windy.Window, x_offset: f64, y_offset: f64, _: windy.MouseMods) void { if (!ui_systems.mouseScroll(mouse_x, mouse_y, @floatCast(x_offset), @floatCast(y_offset))) { switch (ui_systems.screen) { .game => { diff --git a/client/src/main.zig b/client/src/main.zig index 79841bc0..1ad16172 100644 --- a/client/src/main.zig +++ b/client/src/main.zig @@ -2,7 +2,6 @@ const std = @import("std"); const builtin = @import("builtin"); const build_options = @import("options"); -const glfw = @import("glfw"); const miniaudio = @import("miniaudio"); const shared = @import("shared"); const network_data = shared.network_data; @@ -13,6 +12,7 @@ const u32f = utils.u32f; const stbi = @import("stbi"); const uv = @import("uv"); const vk = @import("vulkan"); +const windy = @import("windy"); const ziggy = @import("ziggy"); const assets = @import("assets.zig"); @@ -106,10 +106,10 @@ pub var login_server: LoginServer = undefined; pub var camera: Camera = .{}; pub var settings: Settings = .{}; pub var main_loop: uv.uv_loop_t = .{}; -pub var window: *glfw.Window = undefined; +pub var window: *windy.Window = undefined; pub var callbacks: std.ArrayList(TimedCallback) = .empty; -fn onResize(_: *glfw.Window, w: i32, h: i32) callconv(.c) void { +fn onResize(_: *windy.Window, w: u16, h: u16) void { if (w <= 0 or h <= 0) return; const float_w = f32i(w); @@ -302,13 +302,16 @@ fn renderTick(renderer: *Renderer) !void { fn gameTick(idler: [*c]uv.uv_idle_t) callconv(.c) void { const renderer: *Renderer = @ptrCast(@alignCast(idler.*.data)); - if (window.shouldClose()) { + if (window.should_close) { @branchHint(.unlikely); uv.uv_stop(&main_loop); return; } - glfw.pollEvents(); + windy.pollEvents() catch |e| { + std.log.err("Event polling error: {}", .{e}); + if (@errorReturnTrace()) |trace| std.debug.dumpStackTrace(trace.*); + }; const time = std.time.microTimestamp() - start_time; current_time = time; @@ -406,13 +409,10 @@ pub fn main() !void { login_buffer_free_list.deinit(allocator); } - try glfw.init(allocator); - defer glfw.deinit(); - - if (!try glfw.isVulkanSupported()) { - std.log.err("GLFW could not find libvulkan", .{}); - return error.NoVulkan; - } + const clip_buf = try allocator.alloc(u8, std.math.maxInt(u12)); + defer allocator.free(clip_buf); + try windy.init(allocator, clip_buf); + defer windy.deinit(); stbi.init(allocator); defer stbi.deinit(); @@ -437,12 +437,11 @@ pub fn main() !void { defer input.deinit(); - glfw.windowHintTyped(.client_api, .no_api); - window = try glfw.Window.create(1280, 720, "Eclipse", null); + window = try .create(1280, 720, .{ .title = "Eclipse", .back_pixel = .black }); defer window.destroy(); - window.setSizeLimits(1280, 720, -1, -1); - window.setCursor(switch (settings.cursor_type) { + // window.setSizeLimits(1280, 720, -1, -1); + try window.setCursor(switch (settings.cursor_type) { .basic => assets.default_cursor, .royal => assets.royal_cursor, .ranger => assets.ranger_cursor, @@ -452,12 +451,12 @@ pub fn main() !void { .target_ally => assets.target_ally_cursor, }); - _ = window.setKeyCallback(input.keyEvent); - _ = window.setCharCallback(input.charEvent); - _ = window.setCursorPosCallback(input.mouseMoveEvent); - _ = window.setMouseButtonCallback(input.mouseEvent); - _ = window.setScrollCallback(input.scrollEvent); - _ = window.setFramebufferSizeCallback(onResize); + try window.registerKeyCb(input.keyEvent); + try window.registerCharCb(input.charEvent); + try window.registerMouseMoveCb(input.mouseMoveEvent); + try window.registerMouseCb(input.mouseEvent); + try window.registerScrollCb(input.scrollEvent); + try window.registerResizeCb(onResize); var renderer: Renderer = try .create(if (settings.enable_vsync) .fifo_khr else .immediate_khr); defer renderer.destroy() catch |e| { diff --git a/client/src/render/Context.zig b/client/src/render/Context.zig index 652c2190..0d98d6d2 100644 --- a/client/src/render/Context.zig +++ b/client/src/render/Context.zig @@ -1,13 +1,13 @@ const std = @import("std"); const build_options = @import("options"); -const glfw = @import("glfw"); const vk = @import("vulkan"); const BaseWrapper = vk.BaseWrapper; const InstanceWrapper = vk.InstanceWrapper; const DeviceWrapper = vk.DeviceWrapper; const Instance = vk.InstanceProxy; const Device = vk.DeviceProxy; +const windy = @import("windy"); const main = @import("../main.zig"); @@ -61,14 +61,15 @@ device: Device, graphics_queue: Queue, present_queue: Queue, -pub const VkProc = *const anyopaque; -extern fn glfwGetInstanceProcAddress(instance: vk.Instance, procname: [*:0]const u8) ?VkProc; +fn procAddrBounce(inst: vk.Instance, name: [*:0]const u8) vk.PfnVoidFunction { + return windy.vulkanProcAddr(vk, inst, name); +} -pub fn init(window: *glfw.Window) !Context { +pub fn init(window: *windy.Window) !Context { var self: Context = undefined; - self.base_dispatch = .load(glfwGetInstanceProcAddress); + self.base_dispatch = .load(procAddrBounce); - const glfw_exts = try glfw.getRequiredInstanceExtensions(); + const exts = windy.vulkanExts(); const app_info: vk.ApplicationInfo = .{ .p_application_name = "Eclipse", @@ -82,8 +83,8 @@ pub fn init(window: *glfw.Window) !Context { .p_application_info = &app_info, .enabled_layer_count = @intCast(required_layers.len), .pp_enabled_layer_names = @ptrCast(required_layers), - .enabled_extension_count = @intCast(glfw_exts.len), - .pp_enabled_extension_names = @ptrCast(glfw_exts), + .enabled_extension_count = @intCast(exts.len), + .pp_enabled_extension_names = @ptrCast(exts.ptr), }, null); const vki = try main.allocator.create(InstanceWrapper); @@ -92,7 +93,7 @@ pub fn init(window: *glfw.Window) !Context { self.instance = .init(instance, vki); errdefer self.instance.destroyInstance(null); - self.surface = try createSurface(self.instance, window); + self.surface = try window.createSurface(vk, self.instance); errdefer self.instance.destroySurfaceKHR(self.surface, null); const candidate = try pickPhysicalDevice(self.instance, self.surface); @@ -142,17 +143,10 @@ pub fn allocate(self: Context, requirements: vk.MemoryRequirements, flags: vk.Me }, null); } -extern fn glfwCreateWindowSurface( - instance: vk.Instance, - window: *glfw.Window, - allocator: ?*const vk.AllocationCallbacks, - surface: *vk.SurfaceKHR, -) vk.Result; - -fn createSurface(instance: Instance, window: *glfw.Window) !vk.SurfaceKHR { - var surface: vk.SurfaceKHR = undefined; - if (glfwCreateWindowSurface(instance.handle, window, null, &surface) != .success) return error.SurfaceInitFailed; - return surface; +fn createSurface(instance: Instance, window: *windy.Window) !vk.SurfaceKHR { + _ = instance; // autofix + _ = window; // autofix + } fn initializeCandidate(instance: Instance, candidate: DeviceCandidate) !vk.Device { @@ -208,7 +202,8 @@ fn allocateQueues(instance: Instance, phys_device: vk.PhysicalDevice, surface: v for (families, 0..) |properties, i| { const family: u32 = @intCast(i); if (graphics_family == null and properties.queue_flags.graphics_bit) graphics_family = family; - if (present_family == null and (try instance.getPhysicalDeviceSurfaceSupportKHR(phys_device, family, surface)) == vk.TRUE) + if (present_family == null and + (try instance.getPhysicalDeviceSurfaceSupportKHR(phys_device, family, surface)) == .true) present_family = family; } diff --git a/client/src/render/Renderer.zig b/client/src/render/Renderer.zig index aa90cbc2..e15c3ba9 100644 --- a/client/src/render/Renderer.zig +++ b/client/src/render/Renderer.zig @@ -1,6 +1,5 @@ const std = @import("std"); -const glfw = @import("glfw"); const shared = @import("shared"); const game_data = shared.game_data; const utils = shared.utils; @@ -400,14 +399,14 @@ pub fn create(present_mode: vk.PresentModeKHR) !Renderer { .address_mode_v = .repeat, .address_mode_w = .repeat, .mip_lod_bias = 0.0, - .anisotropy_enable = vk.FALSE, + .anisotropy_enable = .false, .max_anisotropy = 1.0, - .compare_enable = vk.FALSE, + .compare_enable = .false, .compare_op = .always, .min_lod = 0.0, .max_lod = 0.0, .border_color = .float_transparent_black, - .unnormalized_coordinates = vk.FALSE, + .unnormalized_coordinates = .false, }, null); self.linear_sampler = try self.context.device.createSampler(&.{ @@ -418,14 +417,14 @@ pub fn create(present_mode: vk.PresentModeKHR) !Renderer { .address_mode_v = .repeat, .address_mode_w = .repeat, .mip_lod_bias = 0.0, - .anisotropy_enable = vk.FALSE, + .anisotropy_enable = .false, .max_anisotropy = 1.0, - .compare_enable = vk.FALSE, + .compare_enable = .false, .compare_op = .always, .min_lod = 0.0, .max_lod = 0.0, .border_color = .float_transparent_black, - .unnormalized_coordinates = vk.FALSE, + .unnormalized_coordinates = .false, }, null); try self.createRenderPass(); @@ -1071,7 +1070,7 @@ fn createGenericMaterial(self: *Renderer) !void { defer self.context.device.destroyShaderModule(frag_shader, null); const attachments: []const vk.PipelineColorBlendAttachmentState = &.{.{ - .blend_enable = vk.TRUE, + .blend_enable = .true, .src_color_blend_factor = .one, .dst_color_blend_factor = .one_minus_src_alpha, .color_blend_op = .add, @@ -1091,7 +1090,7 @@ fn createGenericMaterial(self: *Renderer) !void { .p_vertex_input_state = &.{}, .p_input_assembly_state = &.{ .topology = .triangle_list, - .primitive_restart_enable = vk.FALSE, + .primitive_restart_enable = .false, }, .p_tessellation_state = null, .p_viewport_state = &.{ @@ -1101,12 +1100,12 @@ fn createGenericMaterial(self: *Renderer) !void { .p_scissors = undefined, }, .p_rasterization_state = &.{ - .depth_clamp_enable = vk.FALSE, - .rasterizer_discard_enable = vk.FALSE, + .depth_clamp_enable = .false, + .rasterizer_discard_enable = .false, .polygon_mode = .fill, .cull_mode = .{}, .front_face = .clockwise, - .depth_bias_enable = vk.FALSE, + .depth_bias_enable = .false, .depth_bias_constant_factor = 0, .depth_bias_clamp = 0, .depth_bias_slope_factor = 0, @@ -1114,14 +1113,14 @@ fn createGenericMaterial(self: *Renderer) !void { }, .p_multisample_state = &.{ .rasterization_samples = .{ .@"1_bit" = true }, - .sample_shading_enable = vk.FALSE, + .sample_shading_enable = .false, .min_sample_shading = 1, - .alpha_to_coverage_enable = vk.FALSE, - .alpha_to_one_enable = vk.FALSE, + .alpha_to_coverage_enable = .false, + .alpha_to_one_enable = .false, }, .p_depth_stencil_state = null, .p_color_blend_state = &.{ - .logic_op_enable = vk.FALSE, + .logic_op_enable = .false, .logic_op = .copy, .attachment_count = 1, .p_attachments = @ptrCast(attachments), @@ -1243,7 +1242,7 @@ fn createGroundMaterial(self: *Renderer) !void { defer self.context.device.destroyShaderModule(frag_shader, null); const attachments: []const vk.PipelineColorBlendAttachmentState = &.{.{ - .blend_enable = vk.FALSE, + .blend_enable = .false, .src_color_blend_factor = .one, .dst_color_blend_factor = .one, .color_blend_op = .add, @@ -1263,7 +1262,7 @@ fn createGroundMaterial(self: *Renderer) !void { .p_vertex_input_state = &.{}, .p_input_assembly_state = &.{ .topology = .triangle_list, - .primitive_restart_enable = vk.FALSE, + .primitive_restart_enable = .false, }, .p_tessellation_state = null, .p_viewport_state = &.{ @@ -1273,12 +1272,12 @@ fn createGroundMaterial(self: *Renderer) !void { .p_scissors = undefined, }, .p_rasterization_state = &.{ - .depth_clamp_enable = vk.FALSE, - .rasterizer_discard_enable = vk.FALSE, + .depth_clamp_enable = .false, + .rasterizer_discard_enable = .false, .polygon_mode = .fill, .cull_mode = .{}, .front_face = .clockwise, - .depth_bias_enable = vk.FALSE, + .depth_bias_enable = .false, .depth_bias_constant_factor = 0, .depth_bias_clamp = 0, .depth_bias_slope_factor = 0, @@ -1286,14 +1285,14 @@ fn createGroundMaterial(self: *Renderer) !void { }, .p_multisample_state = &.{ .rasterization_samples = .{ .@"1_bit" = true }, - .sample_shading_enable = vk.FALSE, + .sample_shading_enable = .false, .min_sample_shading = 1, - .alpha_to_coverage_enable = vk.FALSE, - .alpha_to_one_enable = vk.FALSE, + .alpha_to_coverage_enable = .false, + .alpha_to_one_enable = .false, }, .p_depth_stencil_state = null, .p_color_blend_state = &.{ - .logic_op_enable = vk.FALSE, + .logic_op_enable = .false, .logic_op = .copy, .attachment_count = 1, .p_attachments = @ptrCast(attachments), diff --git a/client/src/render/Swapchain.zig b/client/src/render/Swapchain.zig index c97cacfb..cfbaab9e 100644 --- a/client/src/render/Swapchain.zig +++ b/client/src/render/Swapchain.zig @@ -48,7 +48,7 @@ const SwapImage = struct { } fn deinit(self: SwapImage, ctx: Context) void { - _ = ctx.device.waitForFences(1, @ptrCast(&self.frame_fence), vk.TRUE, std.math.maxInt(u64)) catch {}; + _ = ctx.device.waitForFences(1, @ptrCast(&self.frame_fence), .true, std.math.maxInt(u64)) catch {}; ctx.device.destroyImageView(self.view, null); ctx.device.destroySemaphore(self.image_acquired, null); ctx.device.destroySemaphore(self.render_finished, null); @@ -107,7 +107,7 @@ pub fn initRecycle( .pre_transform = caps.current_transform, .composite_alpha = .{ .opaque_bit_khr = true }, .present_mode = final_present_mode, - .clipped = vk.TRUE, + .clipped = .true, .old_swapchain = old_handle, }, null); errdefer ctx.device.destroySwapchainKHR(handle, null); @@ -146,7 +146,7 @@ fn deinitExceptSwapchain(self: Swapchain, ctx: Context) void { pub fn waitForAllFences(self: Swapchain, ctx: Context) !void { for (self.swap_images) |swap_img| - _ = try ctx.device.waitForFences(1, @ptrCast(&swap_img.frame_fence), vk.TRUE, std.math.maxInt(u64)); + _ = try ctx.device.waitForFences(1, @ptrCast(&swap_img.frame_fence), .true, std.math.maxInt(u64)); } pub fn deinit(self: Swapchain, ctx: Context) void { @@ -168,7 +168,7 @@ pub fn recreate( pub fn present(self: *Swapchain, ctx: Context, cmd_buffer: vk.CommandBuffer) !PresentState { const current = &self.swap_images[self.image_index]; - _ = try ctx.device.waitForFences(1, @ptrCast(¤t.frame_fence), vk.TRUE, std.math.maxInt(u64)); + _ = try ctx.device.waitForFences(1, @ptrCast(¤t.frame_fence), .true, std.math.maxInt(u64)); try ctx.device.resetFences(1, @ptrCast(¤t.frame_fence)); const wait_stage = [_]vk.PipelineStageFlags{.{ .top_of_pipe_bit = true }}; diff --git a/client/src/render/vma.zig b/client/src/render/vma.zig index 7b2406d2..15549454 100644 --- a/client/src/render/vma.zig +++ b/client/src/render/vma.zig @@ -327,7 +327,7 @@ pub const AllocationInfo = extern struct { pub const AllocationInfo2 = extern struct { allocation_info: AllocationInfo = .{}, block_size: vk.DeviceSize = 0, - dedicated_memory: vk.Bool32 = vk.FALSE, + dedicated_memory: vk.Bool32 = .false, }; pub const Allocation = c.VmaAllocation; pub const DefragmentationFlags = packed struct(Flags) { diff --git a/client/src/ui/elements/Button.zig b/client/src/ui/elements/Button.zig index 48f1e42e..62dac78a 100644 --- a/client/src/ui/elements/Button.zig +++ b/client/src/ui/elements/Button.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const glfw = @import("glfw"); +const windy = @import("windy"); const shared = @import("shared"); const CharacterData = shared.network_data.CharacterData; const TalentData = shared.game_data.TalentData; @@ -29,7 +29,7 @@ char: ?*const CharacterData = null, // hack talent: ?*const TalentData = null, // hack 2 talent_index: u8 = std.math.maxInt(u8), -pub fn mousePress(self: *Button, x: f32, y: f32, _: f32, _: f32, _: glfw.Mods) bool { +pub fn mousePress(self: *Button, x: f32, y: f32, _: f32, _: f32, _: windy.MouseMods) bool { if (!self.base.visible or !self.enabled) return false; const in_bounds = element.intersects(self, x, y); diff --git a/client/src/ui/elements/Container.zig b/client/src/ui/elements/Container.zig index 56e69f5d..b24639d7 100644 --- a/client/src/ui/elements/Container.zig +++ b/client/src/ui/elements/Container.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const glfw = @import("glfw"); +const windy = @import("windy"); const main = @import("../../main.zig"); const Renderer = @import("../../render/Renderer.zig"); @@ -21,7 +21,7 @@ clamp_y: bool = false, clamp_to_screen: bool = false, elements: std.ArrayList(element.UiElement) = .empty, -pub fn mousePress(self: *Container, x: f32, y: f32, x_offset: f32, y_offset: f32, mods: glfw.Mods) bool { +pub fn mousePress(self: *Container, x: f32, y: f32, x_offset: f32, y_offset: f32, mods: windy.MouseMods) bool { if (!self.base.visible) return false; var iter = std.mem.reverseIterator(self.elements.items); diff --git a/client/src/ui/elements/Dropdown.zig b/client/src/ui/elements/Dropdown.zig index f9ef31ef..64b0c1b6 100644 --- a/client/src/ui/elements/Dropdown.zig +++ b/client/src/ui/elements/Dropdown.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const glfw = @import("glfw"); +const windy = @import("windy"); const shared = @import("shared"); const utils = shared.utils; const f32i = utils.f32i; @@ -44,7 +44,7 @@ next_index: u32 = 0, selected_index: u32 = std.math.maxInt(u32), children: std.ArrayList(*DropdownContainer) = .empty, -pub fn mousePress(self: *Dropdown, x: f32, y: f32, x_offset: f32, y_offset: f32, mods: glfw.Mods) bool { +pub fn mousePress(self: *Dropdown, x: f32, y: f32, x_offset: f32, y_offset: f32, mods: windy.MouseMods) bool { if (!self.base.visible) return false; const button_data = if (self.toggled) self.button_data_collapsed else self.button_data_extended; diff --git a/client/src/ui/elements/DropdownContainer.zig b/client/src/ui/elements/DropdownContainer.zig index 8373c5bf..07db167a 100644 --- a/client/src/ui/elements/DropdownContainer.zig +++ b/client/src/ui/elements/DropdownContainer.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const glfw = @import("glfw"); +const windy = @import("windy"); const Renderer = @import("../../render/Renderer.zig"); const systems = @import("../systems.zig"); @@ -18,7 +18,7 @@ background_data: element.InteractableImageData, state: element.InteractableState = .none, index: u32 = std.math.maxInt(u32), -pub fn mousePress(self: *DropdownContainer, x: f32, y: f32, _: f32, _: f32, _: glfw.Mods) bool { +pub fn mousePress(self: *DropdownContainer, x: f32, y: f32, _: f32, _: f32, _: windy.MouseMods) bool { if (!self.base.visible or self.index == self.parent.selected_index) return false; const in_bounds = element.intersects(self, x, y); diff --git a/client/src/ui/elements/Input.zig b/client/src/ui/elements/Input.zig index 6c923be6..a8eadf81 100644 --- a/client/src/ui/elements/Input.zig +++ b/client/src/ui/elements/Input.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const glfw = @import("glfw"); +const windy = @import("windy"); const assets = @import("../../assets.zig"); const input = @import("../../input.zig"); @@ -26,7 +26,7 @@ last_input: i64 = -1, x_offset: f32 = 0.0, index: u32 = 0, -pub fn mousePress(self: *Input, x: f32, y: f32, _: f32, _: f32, _: glfw.Mods) bool { +pub fn mousePress(self: *Input, x: f32, y: f32, _: f32, _: f32, _: windy.MouseMods) bool { if (!self.base.visible) return false; const in_bounds = element.intersects(self, x, y); diff --git a/client/src/ui/elements/Item.zig b/client/src/ui/elements/Item.zig index 53661d19..5d946427 100644 --- a/client/src/ui/elements/Item.zig +++ b/client/src/ui/elements/Item.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const glfw = @import("glfw"); +const windy = @import("windy"); const ItemData = @import("shared").network_data.ItemData; const main = @import("../../main.zig"); @@ -32,7 +32,7 @@ last_click_time: i64 = 0, data_id: u16 = std.math.maxInt(u16), item_data: ItemData = .{}, -pub fn mousePress(self: *Item, x: f32, y: f32, _: f32, _: f32, mods: glfw.Mods) bool { +pub fn mousePress(self: *Item, x: f32, y: f32, _: f32, _: f32, mods: windy.MouseMods) bool { if (!self.base.visible or !self.draggable) return false; const in_bounds = element.intersects(self, x, y); diff --git a/client/src/ui/elements/KeyMapper.zig b/client/src/ui/elements/KeyMapper.zig index 8f6cabc0..5d3521a4 100644 --- a/client/src/ui/elements/KeyMapper.zig +++ b/client/src/ui/elements/KeyMapper.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const glfw = @import("glfw"); +const windy = @import("windy"); const assets = @import("../../assets.zig"); const input = @import("../../input.zig"); @@ -22,7 +22,7 @@ tooltip_text: ?element.TextData = null, state: element.InteractableState = .none, listening: bool = false, -pub fn mousePress(self: *KeyMapper, x: f32, y: f32, _: f32, _: f32, _: glfw.Mods) bool { +pub fn mousePress(self: *KeyMapper, x: f32, y: f32, _: f32, _: f32, _: windy.MouseMods) bool { if (!self.base.visible) return false; const in_bounds = element.intersects(self, x, y); diff --git a/client/src/ui/elements/Minimap.zig b/client/src/ui/elements/Minimap.zig index 535c55a2..880078c2 100644 --- a/client/src/ui/elements/Minimap.zig +++ b/client/src/ui/elements/Minimap.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const glfw = @import("glfw"); +const windy = @import("windy"); const shared = @import("shared"); const game_data = shared.game_data; const network_data = shared.network_data; @@ -98,7 +98,7 @@ pub fn mouseMove(self: *Minimap, x: f32, y: f32, x_offset: f32, y_offset: f32) b return !(self.base.event_policy.pass_move or !in_bounds); } -pub fn mousePress(self: *Minimap, x: f32, y: f32, _: f32, _: f32, _: glfw.Mods) bool { +pub fn mousePress(self: *Minimap, x: f32, y: f32, _: f32, _: f32, _: windy.MouseMods) bool { if (!self.base.visible) return false; if (menu.current.* != .teleport and self.list_item_idx > 0) { diff --git a/client/src/ui/elements/ScrollableContainer.zig b/client/src/ui/elements/ScrollableContainer.zig index 79ba5f0e..fd1ef114 100644 --- a/client/src/ui/elements/ScrollableContainer.zig +++ b/client/src/ui/elements/ScrollableContainer.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const glfw = @import("glfw"); +const windy = @import("windy"); const main = @import("../../main.zig"); const Renderer = @import("../../render/Renderer.zig"); @@ -31,7 +31,7 @@ container: *Container = undefined, scroll_bar: *Slider = undefined, scroll_bar_decor: *Image = undefined, -pub fn mousePress(self: *ScrollableContainer, x: f32, y: f32, x_offset: f32, y_offset: f32, mods: glfw.Mods) bool { +pub fn mousePress(self: *ScrollableContainer, x: f32, y: f32, x_offset: f32, y_offset: f32, mods: windy.MouseMods) bool { if (!self.base.visible) return false; if (self.container.mousePress(x, y, x_offset, y_offset, mods) or self.scroll_bar.mousePress(x, y, x_offset, y_offset, mods)) return true; return !(self.base.event_policy.pass_press or !element.intersects(self, x, y)); @@ -188,7 +188,7 @@ pub fn update(self: *ScrollableContainer) void { } fn onScrollChanged(scroll_bar: *Slider) void { - var parent: *ScrollableContainer = @alignCast(@ptrCast(scroll_bar.userdata)); + var parent: *ScrollableContainer = @ptrCast(@alignCast(scroll_bar.userdata)); if (parent.scissor_h >= parent.container.height()) { parent.scroll_bar.base.visible = false; if (parent.hasScrollDecor()) parent.scroll_bar_decor.base.visible = false; diff --git a/client/src/ui/elements/Slider.zig b/client/src/ui/elements/Slider.zig index 0da31302..9361d369 100644 --- a/client/src/ui/elements/Slider.zig +++ b/client/src/ui/elements/Slider.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const glfw = @import("glfw"); +const windy = @import("windy"); const utils = @import("shared").utils; const main = @import("../../main.zig"); @@ -37,7 +37,7 @@ knob_offset_x: f32 = 0.0, knob_offset_y: f32 = 0.0, current_value: f32 = 0.0, -pub fn mousePress(self: *Slider, x: f32, y: f32, _: f32, _: f32, _: glfw.Mods) bool { +pub fn mousePress(self: *Slider, x: f32, y: f32, _: f32, _: f32, _: windy.MouseMods) bool { if (!self.base.visible) return false; if (utils.isInBounds(x, y, self.base.x, self.base.y, self.w, self.h)) { diff --git a/client/src/ui/elements/Toggle.zig b/client/src/ui/elements/Toggle.zig index e4c4a9bb..a71b3352 100644 --- a/client/src/ui/elements/Toggle.zig +++ b/client/src/ui/elements/Toggle.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const glfw = @import("glfw"); +const windy = @import("windy"); const assets = @import("../../assets.zig"); const main = @import("../../main.zig"); @@ -20,7 +20,7 @@ text_data: ?element.TextData = null, tooltip_text: ?element.TextData = null, state_change: ?*const fn (*Toggle) void = null, -pub fn mousePress(self: *Toggle, x: f32, y: f32, _: f32, _: f32, _: glfw.Mods) bool { +pub fn mousePress(self: *Toggle, x: f32, y: f32, _: f32, _: f32, _: windy.MouseMods) bool { if (!self.base.visible) return false; const in_bounds = element.intersects(self, x, y); diff --git a/client/src/ui/screens/MapEditorScreen.zig b/client/src/ui/screens/MapEditorScreen.zig index 20006075..aecbcdd8 100644 --- a/client/src/ui/screens/MapEditorScreen.zig +++ b/client/src/ui/screens/MapEditorScreen.zig @@ -1,7 +1,6 @@ const std = @import("std"); const build_options = @import("options"); -const glfw = @import("glfw"); const shared = @import("shared"); const map_data = shared.map_data; const game_data = shared.game_data; @@ -9,7 +8,7 @@ const utils = shared.utils; const f32i = utils.f32i; const u16f = utils.u16f; const usizef = utils.usizef; -const zd = @import("zd"); +const windy = @import("windy"); const assets = @import("../../assets.zig"); const Container = @import("../../game/Container.zig"); @@ -1125,22 +1124,23 @@ fn loadMap(screen: *MapEditorScreen, buffer: []const u8) !void { // for easier error handling fn openInner(screen: *MapEditorScreen) !void { + _ = screen; // autofix // TODO: popup for save - const path = try zd.openDialog(false, main.allocator, .file, &.{ - .{ .name = "Eclipse Map", .exts = &.{"map"} }, - }, "Select Map", null); - defer zd.freeResult(main.allocator, path); + // const path = try windy.openDialog(false, .file, &.{ + // .{ .name = "Eclipse Map", .exts = &.{"map"} }, + // }, "Select Map", null); + // defer windy.freeResult(main.allocator, path); - if (path.len == 0) return; + // if (path.len == 0) return; - const file = try std.fs.openFileAbsolute(path, .{}); - defer file.close(); + // const file = try std.fs.openFileAbsolute(path, .{}); + // defer file.close(); - const file_buf = try file.readToEndAlloc(main.allocator, std.math.maxInt(u32)); - defer main.allocator.free(file_buf); + // const file_buf = try file.readToEndAlloc(main.allocator, std.math.maxInt(u32)); + // defer main.allocator.free(file_buf); - try screen.loadMap(file_buf); + // try screen.loadMap(file_buf); } fn openCallback(ud: ?*anyopaque) void { @@ -1260,27 +1260,28 @@ fn mapData(screen: *MapEditorScreen) ![]u8 { } fn saveInner(screen: *MapEditorScreen) !void { + _ = screen; // autofix if (!main.needs_map_bg) return; - const path = try zd.saveDialog(main.allocator, &.{ - .{ .name = "Eclipse Map", .exts = &.{"map"} }, - }, "Save Map", null); - defer zd.freeResult(main.allocator, path); - - if (path.len == 0) return; - - const data = mapData(screen) catch { - dialog.showDialog(.text, .{ - .title = "Map Error", - .body = "Map was invalid", - }); - return; - }; - defer main.allocator.free(data); - - const file = try std.fs.createFileAbsolute(path, .{}); - defer file.close(); - try file.writeAll(data); + // const path = try windy.saveDialog(&.{ + // .{ .name = "Eclipse Map", .exts = &.{"map"} }, + // }, "Save Map", null); + // defer windy.freeResult(main.allocator, path); + + // if (path.len == 0) return; + + // const data = mapData(screen) catch { + // dialog.showDialog(.text, .{ + // .title = "Map Error", + // .body = "Map was invalid", + // }); + // return; + // }; + // defer main.allocator.free(data); + + // const file = try std.fs.createFileAbsolute(path, .{}); + // defer file.close(); + // try file.writeAll(data); } fn saveCallback(ud: ?*anyopaque) void { @@ -1419,7 +1420,7 @@ fn onSearchChange(text: []const u8) void { }; } -pub fn onMousePress(self: *MapEditorScreen, button: glfw.MouseButton) void { +pub fn onMousePress(self: *MapEditorScreen, button: windy.MouseButton) void { if (self.place_key == .mouse and button == self.place_key.mouse) self.action = .place else if (self.erase_key == .mouse and button == self.erase_key.mouse) @@ -1444,7 +1445,7 @@ pub fn onMousePress(self: *MapEditorScreen, button: glfw.MouseButton) void { }; } -pub fn onMouseRelease(self: *MapEditorScreen, button: glfw.MouseButton) void { +pub fn onMouseRelease(self: *MapEditorScreen, button: windy.MouseButton) void { if (self.place_key == .mouse and button == self.place_key.mouse or self.erase_key == .mouse and button == self.erase_key.mouse) self.action = .none; @@ -1464,7 +1465,7 @@ pub fn onMouseMove(self: *MapEditorScreen, mouse_x: f32, mouse_y: f32) void { self.processRectSelect(); } -pub fn onKeyPress(self: *MapEditorScreen, key: glfw.Key) void { +pub fn onKeyPress(self: *MapEditorScreen, key: windy.Key) void { if (self.place_key == .key and key == self.place_key.key) self.action = .place else if (self.erase_key == .key and key == self.erase_key.key) @@ -1499,7 +1500,7 @@ pub fn onKeyPress(self: *MapEditorScreen, key: glfw.Key) void { }; } -pub fn onKeyRelease(self: *MapEditorScreen, key: glfw.Key) void { +pub fn onKeyRelease(self: *MapEditorScreen, key: windy.Key) void { if (self.place_key == .key and key == self.place_key.key or self.erase_key == .key and key == self.erase_key.key) self.action = .none; diff --git a/client/src/ui/systems.zig b/client/src/ui/systems.zig index 0b059f78..f46b9b2b 100644 --- a/client/src/ui/systems.zig +++ b/client/src/ui/systems.zig @@ -1,7 +1,7 @@ const std = @import("std"); const build_options = @import("options"); -const glfw = @import("glfw"); +const windy = @import("windy"); const shared = @import("shared"); const utils = shared.utils; const network_data = shared.network_data; @@ -287,7 +287,7 @@ pub fn mouseMove(x: f32, y: f32) bool { return false; } -pub fn mousePress(x: f32, y: f32, button: glfw.MouseButton, mods: glfw.Mods) bool { +pub fn mousePress(x: f32, y: f32, button: windy.MouseButton, mods: windy.MouseMods) bool { var elem_iter = std.mem.reverseIterator(elements.items); while (elem_iter.next()) |elem| switch (elem) { inline else => |inner_elem| if (std.meta.hasFn(@typeInfo(@TypeOf(inner_elem)).pointer.child, "mousePress") and inner_elem.mousePress(x, y, 0, 0, mods)) From 3ff2b2033608c4e15225428736ab3c9385c4d731 Mon Sep 17 00:00:00 2001 From: flut2 <150191812+flut2@users.noreply.github.com> Date: Thu, 1 Jan 2026 13:37:03 +0000 Subject: [PATCH 2/5] fix ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6f70b5d..dbf85f08 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: - name: Install packages run: | sudo apt update - sudo apt install libglfw3 libglfw3-dev libatk1.0-0 libgtk-3-dev libglib2.0-dev + sudo apt install libgtk-3-dev libxcb-xkb-dev libxcb-render-util0-dev libxkbcommon-x11-dev - name: Install Zig uses: mlugg/setup-zig@v2 - name: Install Vulkan SDK From 408e89d92028bde635745fe407c122a7b28520c8 Mon Sep 17 00:00:00 2001 From: flut2 <150191812+flut2@users.noreply.github.com> Date: Sat, 3 Jan 2026 11:49:57 +0000 Subject: [PATCH 3/5] add missing features, update Windy --- build.zig.zon | 4 +- client/src/input.zig | 10 ++-- client/src/main.zig | 2 +- client/src/ui/elements/Button.zig | 4 +- client/src/ui/elements/Container.zig | 2 +- client/src/ui/elements/Dropdown.zig | 4 +- client/src/ui/elements/DropdownContainer.zig | 2 +- client/src/ui/elements/Input.zig | 2 +- client/src/ui/elements/Item.zig | 4 +- client/src/ui/elements/KeyMapper.zig | 2 +- client/src/ui/elements/Minimap.zig | 4 +- .../src/ui/elements/ScrollableContainer.zig | 2 +- client/src/ui/elements/Slider.zig | 4 +- client/src/ui/elements/Toggle.zig | 2 +- client/src/ui/screens/MapEditorScreen.zig | 60 +++++++++---------- client/src/ui/systems.zig | 4 +- 16 files changed, 55 insertions(+), 57 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index e51f7ac0..4e4013c0 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -16,8 +16,8 @@ .miniaudio = .{ .path = "client/libs/miniaudio" }, .stbi = .{ .path = "client/libs/stbi" }, .windy = .{ - .url = "git+https://github.com/flut2/windy.git#a349bf94cd5a99e1c96f47cf507c29c31aedb130", - .hash = "windy-0.2.0-wLI1BBxAAQApBlYXcbUfavAzQPhOf5nNjygFtGYHBZDc", + .url = "git+https://github.com/flut2/windy.git#9cf7bb833756aad30775def8bac4703e037e3677", + .hash = "windy-0.2.0-wLI1BCFRAQAI7e2qP5-KsuQWabAf7pBXzsMW3zMHFKvn", }, .turbopack = .{ .url = "git+https://github.com/flut2/turbopack.git#d6995ce5a8f071bb759a274ac036dff65909905a", diff --git a/client/src/input.zig b/client/src/input.zig index 13b1cf21..9b64c01f 100644 --- a/client/src/input.zig +++ b/client/src/input.zig @@ -185,7 +185,7 @@ fn handleAbility4() void { if (map.localPlayerRef()) |player| player.useAbility(3); } -pub fn charEvent(_: *windy.Window, state: windy.PressState, char: u21, _: windy.KeyMods) void { +pub fn charEvent(_: *windy.Window, state: windy.PressState, char: u21, _: windy.Mods) void { if (state != .press) return; if (selected_input_field) |input_field| { if (char > std.math.maxInt(u8)) return; @@ -200,7 +200,7 @@ pub fn charEvent(_: *windy.Window, state: windy.PressState, char: u21, _: windy. } } -pub fn keyEvent(window: *windy.Window, state: windy.PressState, key: windy.Key, mods: windy.KeyMods) void { +pub fn keyEvent(window: *windy.Window, state: windy.PressState, key: windy.Key, mods: windy.Mods) void { _ = window; // autofix if (state == .press) { if (selected_key_mapper) |key_mapper| { @@ -324,7 +324,7 @@ pub fn keyEvent(window: *windy.Window, state: windy.PressState, key: windy.Key, menu.cancelMenu(); } -pub fn mouseEvent(window: *windy.Window, state: windy.PressState, button: windy.MouseButton, _: i16, _: i16, mods: windy.MouseMods) void { +pub fn mouseEvent(window: *windy.Window, state: windy.PressState, button: windy.MouseButton, _: i16, _: i16, mods: windy.Mods) void { if (state == .press) { window.setCursor(switch (main.settings.cursor_type) { .basic => assets.default_cursor_pressed, @@ -388,7 +388,7 @@ pub fn updateMove() void { move_angle = if (y_dt == 0 and x_dt == 0) std.math.nan(f32) else std.math.atan2(y_dt, x_dt); } -pub fn mouseMoveEvent(_: *windy.Window, x_pos: i16, y_pos: i16, _: windy.MouseMods) void { +pub fn mouseMoveEvent(_: *windy.Window, x_pos: i16, y_pos: i16, _: windy.Mods) void { mouse_x = @floatFromInt(x_pos); mouse_y = @floatFromInt(y_pos); @@ -396,7 +396,7 @@ pub fn mouseMoveEvent(_: *windy.Window, x_pos: i16, y_pos: i16, _: windy.MouseMo if (ui_systems.screen == .editor) ui_systems.screen.editor.onMouseMove(mouse_x, mouse_y); } -pub fn scrollEvent(_: *windy.Window, x_offset: f64, y_offset: f64, _: windy.MouseMods) void { +pub fn scrollEvent(_: *windy.Window, x_offset: f64, y_offset: f64, _: windy.Mods) void { if (!ui_systems.mouseScroll(mouse_x, mouse_y, @floatCast(x_offset), @floatCast(y_offset))) { switch (ui_systems.screen) { .game => { diff --git a/client/src/main.zig b/client/src/main.zig index 1ad16172..be62ca09 100644 --- a/client/src/main.zig +++ b/client/src/main.zig @@ -440,7 +440,7 @@ pub fn main() !void { window = try .create(1280, 720, .{ .title = "Eclipse", .back_pixel = .black }); defer window.destroy(); - // window.setSizeLimits(1280, 720, -1, -1); + try window.setMinSize(.{.w = 1280, .h = 720}); try window.setCursor(switch (settings.cursor_type) { .basic => assets.default_cursor, .royal => assets.royal_cursor, diff --git a/client/src/ui/elements/Button.zig b/client/src/ui/elements/Button.zig index 62dac78a..f32b11da 100644 --- a/client/src/ui/elements/Button.zig +++ b/client/src/ui/elements/Button.zig @@ -1,9 +1,9 @@ const std = @import("std"); -const windy = @import("windy"); const shared = @import("shared"); const CharacterData = shared.network_data.CharacterData; const TalentData = shared.game_data.TalentData; +const windy = @import("windy"); const assets = @import("../../assets.zig"); const main = @import("../../main.zig"); @@ -29,7 +29,7 @@ char: ?*const CharacterData = null, // hack talent: ?*const TalentData = null, // hack 2 talent_index: u8 = std.math.maxInt(u8), -pub fn mousePress(self: *Button, x: f32, y: f32, _: f32, _: f32, _: windy.MouseMods) bool { +pub fn mousePress(self: *Button, x: f32, y: f32, _: f32, _: f32, _: windy.Mods) bool { if (!self.base.visible or !self.enabled) return false; const in_bounds = element.intersects(self, x, y); diff --git a/client/src/ui/elements/Container.zig b/client/src/ui/elements/Container.zig index b24639d7..573cc023 100644 --- a/client/src/ui/elements/Container.zig +++ b/client/src/ui/elements/Container.zig @@ -21,7 +21,7 @@ clamp_y: bool = false, clamp_to_screen: bool = false, elements: std.ArrayList(element.UiElement) = .empty, -pub fn mousePress(self: *Container, x: f32, y: f32, x_offset: f32, y_offset: f32, mods: windy.MouseMods) bool { +pub fn mousePress(self: *Container, x: f32, y: f32, x_offset: f32, y_offset: f32, mods: windy.Mods) bool { if (!self.base.visible) return false; var iter = std.mem.reverseIterator(self.elements.items); diff --git a/client/src/ui/elements/Dropdown.zig b/client/src/ui/elements/Dropdown.zig index 64b0c1b6..b73ae356 100644 --- a/client/src/ui/elements/Dropdown.zig +++ b/client/src/ui/elements/Dropdown.zig @@ -1,9 +1,9 @@ const std = @import("std"); -const windy = @import("windy"); const shared = @import("shared"); const utils = shared.utils; const f32i = utils.f32i; +const windy = @import("windy"); const assets = @import("../../assets.zig"); const main = @import("../../main.zig"); @@ -44,7 +44,7 @@ next_index: u32 = 0, selected_index: u32 = std.math.maxInt(u32), children: std.ArrayList(*DropdownContainer) = .empty, -pub fn mousePress(self: *Dropdown, x: f32, y: f32, x_offset: f32, y_offset: f32, mods: windy.MouseMods) bool { +pub fn mousePress(self: *Dropdown, x: f32, y: f32, x_offset: f32, y_offset: f32, mods: windy.Mods) bool { if (!self.base.visible) return false; const button_data = if (self.toggled) self.button_data_collapsed else self.button_data_extended; diff --git a/client/src/ui/elements/DropdownContainer.zig b/client/src/ui/elements/DropdownContainer.zig index 07db167a..728a7c06 100644 --- a/client/src/ui/elements/DropdownContainer.zig +++ b/client/src/ui/elements/DropdownContainer.zig @@ -18,7 +18,7 @@ background_data: element.InteractableImageData, state: element.InteractableState = .none, index: u32 = std.math.maxInt(u32), -pub fn mousePress(self: *DropdownContainer, x: f32, y: f32, _: f32, _: f32, _: windy.MouseMods) bool { +pub fn mousePress(self: *DropdownContainer, x: f32, y: f32, _: f32, _: f32, _: windy.Mods) bool { if (!self.base.visible or self.index == self.parent.selected_index) return false; const in_bounds = element.intersects(self, x, y); diff --git a/client/src/ui/elements/Input.zig b/client/src/ui/elements/Input.zig index a8eadf81..06df2618 100644 --- a/client/src/ui/elements/Input.zig +++ b/client/src/ui/elements/Input.zig @@ -26,7 +26,7 @@ last_input: i64 = -1, x_offset: f32 = 0.0, index: u32 = 0, -pub fn mousePress(self: *Input, x: f32, y: f32, _: f32, _: f32, _: windy.MouseMods) bool { +pub fn mousePress(self: *Input, x: f32, y: f32, _: f32, _: f32, _: windy.Mods) bool { if (!self.base.visible) return false; const in_bounds = element.intersects(self, x, y); diff --git a/client/src/ui/elements/Item.zig b/client/src/ui/elements/Item.zig index 5d946427..7453f26e 100644 --- a/client/src/ui/elements/Item.zig +++ b/client/src/ui/elements/Item.zig @@ -1,7 +1,7 @@ const std = @import("std"); -const windy = @import("windy"); const ItemData = @import("shared").network_data.ItemData; +const windy = @import("windy"); const main = @import("../../main.zig"); const Renderer = @import("../../render/Renderer.zig"); @@ -32,7 +32,7 @@ last_click_time: i64 = 0, data_id: u16 = std.math.maxInt(u16), item_data: ItemData = .{}, -pub fn mousePress(self: *Item, x: f32, y: f32, _: f32, _: f32, mods: windy.MouseMods) bool { +pub fn mousePress(self: *Item, x: f32, y: f32, _: f32, _: f32, mods: windy.Mods) bool { if (!self.base.visible or !self.draggable) return false; const in_bounds = element.intersects(self, x, y); diff --git a/client/src/ui/elements/KeyMapper.zig b/client/src/ui/elements/KeyMapper.zig index 5d3521a4..1704e785 100644 --- a/client/src/ui/elements/KeyMapper.zig +++ b/client/src/ui/elements/KeyMapper.zig @@ -22,7 +22,7 @@ tooltip_text: ?element.TextData = null, state: element.InteractableState = .none, listening: bool = false, -pub fn mousePress(self: *KeyMapper, x: f32, y: f32, _: f32, _: f32, _: windy.MouseMods) bool { +pub fn mousePress(self: *KeyMapper, x: f32, y: f32, _: f32, _: f32, _: windy.Mods) bool { if (!self.base.visible) return false; const in_bounds = element.intersects(self, x, y); diff --git a/client/src/ui/elements/Minimap.zig b/client/src/ui/elements/Minimap.zig index 880078c2..392c3024 100644 --- a/client/src/ui/elements/Minimap.zig +++ b/client/src/ui/elements/Minimap.zig @@ -1,11 +1,11 @@ const std = @import("std"); -const windy = @import("windy"); const shared = @import("shared"); const game_data = shared.game_data; const network_data = shared.network_data; const utils = shared.utils; const f32i = utils.f32i; +const windy = @import("windy"); const assets = @import("../../assets.zig"); const Camera = @import("../../Camera.zig"); @@ -98,7 +98,7 @@ pub fn mouseMove(self: *Minimap, x: f32, y: f32, x_offset: f32, y_offset: f32) b return !(self.base.event_policy.pass_move or !in_bounds); } -pub fn mousePress(self: *Minimap, x: f32, y: f32, _: f32, _: f32, _: windy.MouseMods) bool { +pub fn mousePress(self: *Minimap, x: f32, y: f32, _: f32, _: f32, _: windy.Mods) bool { if (!self.base.visible) return false; if (menu.current.* != .teleport and self.list_item_idx > 0) { diff --git a/client/src/ui/elements/ScrollableContainer.zig b/client/src/ui/elements/ScrollableContainer.zig index fd1ef114..415ac22e 100644 --- a/client/src/ui/elements/ScrollableContainer.zig +++ b/client/src/ui/elements/ScrollableContainer.zig @@ -31,7 +31,7 @@ container: *Container = undefined, scroll_bar: *Slider = undefined, scroll_bar_decor: *Image = undefined, -pub fn mousePress(self: *ScrollableContainer, x: f32, y: f32, x_offset: f32, y_offset: f32, mods: windy.MouseMods) bool { +pub fn mousePress(self: *ScrollableContainer, x: f32, y: f32, x_offset: f32, y_offset: f32, mods: windy.Mods) bool { if (!self.base.visible) return false; if (self.container.mousePress(x, y, x_offset, y_offset, mods) or self.scroll_bar.mousePress(x, y, x_offset, y_offset, mods)) return true; return !(self.base.event_policy.pass_press or !element.intersects(self, x, y)); diff --git a/client/src/ui/elements/Slider.zig b/client/src/ui/elements/Slider.zig index 9361d369..ae31c938 100644 --- a/client/src/ui/elements/Slider.zig +++ b/client/src/ui/elements/Slider.zig @@ -1,7 +1,7 @@ const std = @import("std"); -const windy = @import("windy"); const utils = @import("shared").utils; +const windy = @import("windy"); const main = @import("../../main.zig"); const Renderer = @import("../../render/Renderer.zig"); @@ -37,7 +37,7 @@ knob_offset_x: f32 = 0.0, knob_offset_y: f32 = 0.0, current_value: f32 = 0.0, -pub fn mousePress(self: *Slider, x: f32, y: f32, _: f32, _: f32, _: windy.MouseMods) bool { +pub fn mousePress(self: *Slider, x: f32, y: f32, _: f32, _: f32, _: windy.Mods) bool { if (!self.base.visible) return false; if (utils.isInBounds(x, y, self.base.x, self.base.y, self.w, self.h)) { diff --git a/client/src/ui/elements/Toggle.zig b/client/src/ui/elements/Toggle.zig index a71b3352..d26fcf6a 100644 --- a/client/src/ui/elements/Toggle.zig +++ b/client/src/ui/elements/Toggle.zig @@ -20,7 +20,7 @@ text_data: ?element.TextData = null, tooltip_text: ?element.TextData = null, state_change: ?*const fn (*Toggle) void = null, -pub fn mousePress(self: *Toggle, x: f32, y: f32, _: f32, _: f32, _: windy.MouseMods) bool { +pub fn mousePress(self: *Toggle, x: f32, y: f32, _: f32, _: f32, _: windy.Mods) bool { if (!self.base.visible) return false; const in_bounds = element.intersects(self, x, y); diff --git a/client/src/ui/screens/MapEditorScreen.zig b/client/src/ui/screens/MapEditorScreen.zig index aecbcdd8..34c1bd80 100644 --- a/client/src/ui/screens/MapEditorScreen.zig +++ b/client/src/ui/screens/MapEditorScreen.zig @@ -1124,23 +1124,22 @@ fn loadMap(screen: *MapEditorScreen, buffer: []const u8) !void { // for easier error handling fn openInner(screen: *MapEditorScreen) !void { - _ = screen; // autofix // TODO: popup for save - // const path = try windy.openDialog(false, .file, &.{ - // .{ .name = "Eclipse Map", .exts = &.{"map"} }, - // }, "Select Map", null); - // defer windy.freeResult(main.allocator, path); + const path = try windy.openDialog(false, .file, &.{ + .{ .name = "Eclipse Map", .exts = &.{"map"} }, + }, "Select Map", null); + defer windy.freeResult(path); - // if (path.len == 0) return; + if (path.len == 0) return; - // const file = try std.fs.openFileAbsolute(path, .{}); - // defer file.close(); + const file = try std.fs.openFileAbsolute(path, .{}); + defer file.close(); - // const file_buf = try file.readToEndAlloc(main.allocator, std.math.maxInt(u32)); - // defer main.allocator.free(file_buf); + const file_buf = try file.readToEndAlloc(main.allocator, std.math.maxInt(u32)); + defer main.allocator.free(file_buf); - // try screen.loadMap(file_buf); + try screen.loadMap(file_buf); } fn openCallback(ud: ?*anyopaque) void { @@ -1260,28 +1259,27 @@ fn mapData(screen: *MapEditorScreen) ![]u8 { } fn saveInner(screen: *MapEditorScreen) !void { - _ = screen; // autofix if (!main.needs_map_bg) return; - // const path = try windy.saveDialog(&.{ - // .{ .name = "Eclipse Map", .exts = &.{"map"} }, - // }, "Save Map", null); - // defer windy.freeResult(main.allocator, path); - - // if (path.len == 0) return; - - // const data = mapData(screen) catch { - // dialog.showDialog(.text, .{ - // .title = "Map Error", - // .body = "Map was invalid", - // }); - // return; - // }; - // defer main.allocator.free(data); - - // const file = try std.fs.createFileAbsolute(path, .{}); - // defer file.close(); - // try file.writeAll(data); + const path = try windy.saveDialog(&.{ + .{ .name = "Eclipse Map", .exts = &.{"map"} }, + }, "Save Map", null); + defer windy.freeResult(path); + + if (path.len == 0) return; + + const data = mapData(screen) catch { + dialog.showDialog(.text, .{ + .title = "Map Error", + .body = "Map was invalid", + }); + return; + }; + defer main.allocator.free(data); + + const file = try std.fs.createFileAbsolute(path, .{}); + defer file.close(); + try file.writeAll(data); } fn saveCallback(ud: ?*anyopaque) void { diff --git a/client/src/ui/systems.zig b/client/src/ui/systems.zig index f46b9b2b..906748b9 100644 --- a/client/src/ui/systems.zig +++ b/client/src/ui/systems.zig @@ -1,13 +1,13 @@ const std = @import("std"); const build_options = @import("options"); -const windy = @import("windy"); const shared = @import("shared"); const utils = shared.utils; const network_data = shared.network_data; const game_data = shared.game_data; const map_data = shared.map_data; const f32i = utils.f32i; +const windy = @import("windy"); const assets = @import("../assets.zig"); const Camera = @import("../Camera.zig"); @@ -287,7 +287,7 @@ pub fn mouseMove(x: f32, y: f32) bool { return false; } -pub fn mousePress(x: f32, y: f32, button: windy.MouseButton, mods: windy.MouseMods) bool { +pub fn mousePress(x: f32, y: f32, button: windy.MouseButton, mods: windy.Mods) bool { var elem_iter = std.mem.reverseIterator(elements.items); while (elem_iter.next()) |elem| switch (elem) { inline else => |inner_elem| if (std.meta.hasFn(@typeInfo(@TypeOf(inner_elem)).pointer.child, "mousePress") and inner_elem.mousePress(x, y, 0, 0, mods)) From ea472b3340b8da78b9f407eae94c1ab03c13ce12 Mon Sep 17 00:00:00 2001 From: flut2 <150191812+flut2@users.noreply.github.com> Date: Thu, 8 Jan 2026 13:12:35 +0000 Subject: [PATCH 4/5] update Windy --- build.zig.zon | 4 ++-- client/src/input.zig | 16 +++++++--------- client/src/render/Context.zig | 4 ++-- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index 4e4013c0..5e594065 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -16,8 +16,8 @@ .miniaudio = .{ .path = "client/libs/miniaudio" }, .stbi = .{ .path = "client/libs/stbi" }, .windy = .{ - .url = "git+https://github.com/flut2/windy.git#9cf7bb833756aad30775def8bac4703e037e3677", - .hash = "windy-0.2.0-wLI1BCFRAQAI7e2qP5-KsuQWabAf7pBXzsMW3zMHFKvn", + .url = "git+https://github.com/flut2/windy.git#f82673f6dcbfc1d5c1e586d73613d1e7d332fdb1", + .hash = "windy-0.3.0-wLI1BB-3AQCF2OMnDCLDAUKfWt7bVY6BDtBH8jDroR9y", }, .turbopack = .{ .url = "git+https://github.com/flut2/turbopack.git#d6995ce5a8f071bb759a274ac036dff65909905a", diff --git a/client/src/input.zig b/client/src/input.zig index 9b64c01f..8bd72bec 100644 --- a/client/src/input.zig +++ b/client/src/input.zig @@ -160,7 +160,7 @@ fn handleChat() void { } fn handleChatCmd() void { - charEvent(main.window, .press, @intFromEnum(windy.Key.slash), .{}); + charEvent(main.window, @intFromEnum(windy.Key.slash), .{}); selected_input_field = ui_systems.screen.game.chat_input; ui_systems.screen.game.chat_input.last_input = 0; } @@ -185,8 +185,7 @@ fn handleAbility4() void { if (map.localPlayerRef()) |player| player.useAbility(3); } -pub fn charEvent(_: *windy.Window, state: windy.PressState, char: u21, _: windy.Mods) void { - if (state != .press) return; +pub fn charEvent(_: *windy.Window, char: u21, _: windy.Mods) void { if (selected_input_field) |input_field| { if (char > std.math.maxInt(u8)) return; const byte_code: u8 = @intCast(char); @@ -200,8 +199,7 @@ pub fn charEvent(_: *windy.Window, state: windy.PressState, char: u21, _: windy. } } -pub fn keyEvent(window: *windy.Window, state: windy.PressState, key: windy.Key, mods: windy.Mods) void { - _ = window; // autofix +pub fn keyEvent(_: *windy.Window, state: windy.PressState, key: windy.Key, mods: windy.Mods) void { if (state == .press) { if (selected_key_mapper) |key_mapper| { key_mapper.settings_button.* = if (key == .escape) .{ .key = .invalid } else .{ .key = key }; @@ -396,22 +394,22 @@ pub fn mouseMoveEvent(_: *windy.Window, x_pos: i16, y_pos: i16, _: windy.Mods) v if (ui_systems.screen == .editor) ui_systems.screen.editor.onMouseMove(mouse_x, mouse_y); } -pub fn scrollEvent(_: *windy.Window, x_offset: f64, y_offset: f64, _: windy.Mods) void { - if (!ui_systems.mouseScroll(mouse_x, mouse_y, @floatCast(x_offset), @floatCast(y_offset))) { +pub fn scrollEvent(_: *windy.Window, x_offset: f32, y_offset: f32, _: windy.Mods) void { + if (!ui_systems.mouseScroll(mouse_x, mouse_y, x_offset, y_offset)) { switch (ui_systems.screen) { .game => { const size = @max(map.info.width, map.info.height); const max_zoom = f32i(@divFloor(size, 32)); const scroll_speed = f32i(size) / 1280; - main.camera.minimap_zoom += @floatCast(y_offset * scroll_speed); + main.camera.minimap_zoom += y_offset * scroll_speed; main.camera.minimap_zoom = @max(1, @min(max_zoom, main.camera.minimap_zoom)); }, .editor => { const min_zoom = 0.05; const scroll_speed = 0.01; - main.camera.scale += @floatCast(y_offset * scroll_speed); + main.camera.scale += y_offset * scroll_speed; main.camera.scale = @min(1, @max(min_zoom, main.camera.scale)); }, else => {}, diff --git a/client/src/render/Context.zig b/client/src/render/Context.zig index 0d98d6d2..3703e9d2 100644 --- a/client/src/render/Context.zig +++ b/client/src/render/Context.zig @@ -61,8 +61,8 @@ device: Device, graphics_queue: Queue, present_queue: Queue, -fn procAddrBounce(inst: vk.Instance, name: [*:0]const u8) vk.PfnVoidFunction { - return windy.vulkanProcAddr(vk, inst, name); +fn procAddrBounce(_: vk.Instance, name: [*:0]const u8) vk.PfnVoidFunction { + return windy.vulkanProcAddr(vk, name); } pub fn init(window: *windy.Window) !Context { From 202b22cb0f2f4cd80f824b94c2e5de1bb2dfeece Mon Sep 17 00:00:00 2001 From: flut2 <150191812+flut2@users.noreply.github.com> Date: Thu, 8 Jan 2026 13:26:19 +0000 Subject: [PATCH 5/5] fallback to default settings on error --- client/src/main.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/main.zig b/client/src/main.zig index be62ca09..ecb5b186 100644 --- a/client/src/main.zig +++ b/client/src/main.zig @@ -420,7 +420,7 @@ pub fn main() !void { miniaudio.init(allocator); defer miniaudio.deinit(); - settings = try .init(allocator); + settings = Settings.init(allocator) catch .{}; defer settings.deinit(); try assets.init();