diff --git a/packages/glfw/build.zig b/packages/glfw/build.zig new file mode 100644 index 0000000..d5a4e35 --- /dev/null +++ b/packages/glfw/build.zig @@ -0,0 +1,38 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + + const vm_dep = b.dependency("vecmath", .{ + .target = target, + }); + const vm_mod = vm_dep.module("vecmath"); + + const mod = b.addModule("glfw", .{ + .root_source_file = b.path("src/root.zig"), + .target = target, + .link_libc = true, + .imports = &.{ + .{ .name = "vecmath", .module = vm_mod }, + }, + }); + + mod.addCSourceFiles(.{ + .files = &.{}, + .flags = &.{ + "-std=c99", + "-Wall", + "-Wextra", + }, + .language = .c, + }); + + const mod_tests = b.addTest(.{ + .root_module = mod, + }); + + const run_mod_tests = b.addRunArtifact(mod_tests); + + const test_step = b.step("test", "Run tests"); + test_step.dependOn(&run_mod_tests.step); +} diff --git a/packages/glfw/build.zig.zon b/packages/glfw/build.zig.zon new file mode 100644 index 0000000..70f544b --- /dev/null +++ b/packages/glfw/build.zig.zon @@ -0,0 +1,17 @@ +.{ + .name = .glfw, + .version = "0.0.0", + .minimum_zig_version = "0.17.0", + .paths = .{ + "src", + "vendor", + "build.zig", + "build.zig.zon", + }, + .fingerprint = 0x3bbe0a5c4230f88e, + .dependencies = .{ + .vecmath = .{ + .path = "../vecmath", + }, + }, +} diff --git a/packages/glfw/src/root.zig b/packages/glfw/src/root.zig new file mode 100644 index 0000000..1d72f3f --- /dev/null +++ b/packages/glfw/src/root.zig @@ -0,0 +1,1117 @@ +const vm = @import("vecmath"); + +// --- GLFW API tokens --------------------------------------------------------- + +pub const VERSION_MAJOR = 3; +pub const VERSION_MINOR = 5; +pub const VERSION_REVISION = 1; + +pub const Bool = enum(c_int) { + FALSE = 0, + TRUE = 1, + + pub inline fn fromBool(value: bool) Bool { + return if (value) .TRUE else .FALSE; + } + + pub inline fn toBool(self: Bool) bool { + return switch (self) { + .FALSE => false, + .TRUE => true, + }; + } +}; + +pub const Action = enum(c_int) { + RELEASE = 0, + PRESS = 1, + REPEAT = 2, +}; + +pub const Hat = packed struct(u8) { + up: bool = false, + right: bool = false, + down: bool = false, + left: bool = false, + _pad4: u4 = 0, + + pub const centered: Hat = .{}; + pub const right_up: Hat = .{ .right = true, .up = true }; + pub const right_down: Hat = .{ .right = true, .down = true }; + pub const left_up: Hat = .{ .left = true, .up = true }; + pub const left_down: Hat = .{ .left = true, .down = true }; +}; + +pub const Key = enum(c_int) { + UNKNOWN = -1, + + // Printable keys + + SPACE = 32, + APOSTROPHE = 39, + COMMA = 44, + MINUS = 45, + PERIOD = 46, + SLASH = 47, + D0 = 48, + D1 = 49, + D2 = 50, + D3 = 51, + D4 = 52, + D5 = 53, + D6 = 54, + D7 = 55, + D8 = 56, + D9 = 57, + SEMICOLON = 59, + EQUAL = 61, + A = 65, + B = 66, + C = 67, + D = 68, + E = 69, + F = 70, + G = 71, + H = 72, + I = 73, + J = 74, + K = 75, + L = 76, + M = 77, + N = 78, + O = 79, + P = 80, + Q = 81, + R = 82, + S = 83, + T = 84, + U = 85, + V = 86, + W = 87, + X = 88, + Y = 89, + Z = 90, + LEFT_BRACKET = 91, + BACKSLASH = 92, + RIGHT_BRACKET = 93, + GRAVE_ACCENT = 96, + WORLD_1 = 61, + WORLD_2 = 62, + + // Function keys + + ESCAPE = 256, + ENTER = 257, + TAB = 258, + BACKSPACE = 259, + INSERT = 260, + DELETE = 261, + RIGHT = 262, + LEFT = 263, + DOWN = 264, + UP = 265, + PAGE_UP = 266, + PAGE_DOWN = 267, + HOME = 268, + END = 269, + CAPS_LOCK = 280, + SCROLL_LOCK = 281, + NUM_LOCK = 282, + PRINT_SCREEN = 283, + PAUSE = 284, + F1 = 290, + F2 = 291, + F3 = 292, + F4 = 293, + F5 = 294, + F6 = 295, + F7 = 296, + F8 = 297, + F9 = 298, + F10 = 299, + F11 = 300, + F12 = 301, + F13 = 302, + F14 = 303, + F15 = 304, + F16 = 305, + F17 = 306, + F18 = 307, + F19 = 308, + F20 = 309, + F21 = 310, + F22 = 311, + F23 = 312, + F24 = 313, + F25 = 314, + KP_0 = 320, + KP_1 = 321, + KP_2 = 322, + KP_3 = 323, + KP_4 = 324, + KP_5 = 325, + KP_6 = 326, + KP_7 = 327, + KP_8 = 328, + KP_9 = 329, + KP_DECIMAL = 330, + KP_DIVIDE = 331, + KP_MULTIPLY = 332, + KP_SUBTRACT = 333, + KP_ADD = 334, + KP_ENTER = 335, + KP_EQUAL = 336, + LEFT_SHIFT = 340, + LEFT_CONTROL = 341, + LEFT_ALT = 342, + LEFT_SUPER = 343, + RIGHT_SHIFT = 344, + RIGHT_CONTROL = 345, + RIGHT_ALT = 346, + RIGHT_SUPER = 347, + MENU = 348, + + pub const LAST: Key = .MENU; +}; + +pub const Modifiers = packed struct(c_int) { + shift: bool = false, + control: bool = false, + alt: bool = false, + super: bool = false, + caps_lock: bool = false, + num_lock: bool = false, + _pad6: u28 = 0, +}; + +pub const MouseButton = enum(c_int) { + LEFT = 0, + RIGHT = 1, + MIDDLE = 2, + B4 = 3, + B5 = 4, + B6 = 5, + B7 = 6, + B8 = 7, + + pub const B1: MouseButton = .LEFT; + pub const B2: MouseButton = .RIGHT; + pub const B3: MouseButton = .MIDDLE; + + pub const LAST: MouseButton = .B8; +}; + +pub const Joystick = enum(c_int) { + J1 = 0, + J2 = 1, + J3 = 2, + J4 = 3, + J5 = 4, + J6 = 5, + J7 = 6, + J8 = 7, + J9 = 8, + J10 = 9, + J11 = 10, + J12 = 11, + J13 = 12, + J14 = 13, + J15 = 14, + J16 = 15, + + pub const LAST: Joystick = .J16; + + pub inline fn present(self: Joystick) bool { + return import.glfwJoystickPresent(self).toBool(); + } + + pub inline fn getAxes(self: Joystick) ?[]const f32 { + var count: c_int = undefined; + if (import.glfwGetJoystickAxes(self, &count)) |ptr| { + return ptr[0..@intCast(count)]; + } else { + return null; + } + } + + pub inline fn getButtons(self: Joystick) ?[]const u8 { + var count: c_int = undefined; + if (import.glfwGetJoystickButtons(self, &count)) |ptr| { + return ptr[0..@intCast(count)]; + } else { + return null; + } + } + + pub inline fn getHats(self: Joystick) ?[*]const Hat { + var count: c_int = undefined; + if (import.glfwGetJoystickHats(self, &count)) |ptr| { + return ptr[0..@intCast(count)]; + } else { + return null; + } + } + + pub inline fn getName(self: Joystick) ?[*:0]const u8 { + return import.glfwGetJoystickName(self); + } + + pub inline fn getGUID(self: Joystick) ?[*:0]const u8 { + return import.glfwGetJoystickGUID(self); + } + + pub inline fn setUserPointer(self: Joystick, pointer: ?*anyopaque) void { + import.glfwSetJoystickUserPointer(self, pointer); + } + + pub inline fn getUserPointer(self: Joystick) ?*anyopaque { + return import.glfwGetJoystickUserPointer(self); + } + + pub inline fn isGamepad(self: Joystick) bool { + return import.glfwJoystickIsGamepad(self).toBool(); + } + + pub inline fn getGamepadName(self: Joystick) ?[*:0]const u8 { + return import.glfwGetGamepadName(self); + } + + pub inline fn getGamepadState(self: Joystick, state: *GamepadState) bool { + return import.glfwGetGamepadState(self, state).toBool(); + } +}; + +pub const GamepadButton = enum(c_int) { + A = 0, + B = 1, + X = 2, + Y = 3, + LEFT_BUMPER = 4, + RIGHT_BUMPER = 5, + BACK = 6, + START = 7, + GUIDE = 8, + LEFT_THUMB = 9, + RIGHT_THUMB = 10, + DPAD_UP = 11, + DPAD_RIGHT = 12, + DPAD_DOWN = 13, + DPAD_LEFT = 14, + + pub const CROSS: GamepadButton = .A; + pub const CIRCLE: GamepadButton = .B; + pub const SQUARE: GamepadButton = .X; + pub const TRIANGLE: GamepadButton = .Y; + + pub const LAST: GamepadButton = .DPAD_LEFT; +}; + +pub const GamepadAxis = enum(c_int) { + LEFT_X = 0, + LEFT_Y = 1, + RIGHT_X = 2, + RIGHT_Y = 3, + LEFT_TRIGGER = 4, + RIGHT_TRIGGER = 5, + + pub const LAST: GamepadAxis = .RIGHT_TRIGGER; +}; + +pub const ErrorCode = enum(c_int) { + NO_ERROR = 0, + /// GLFW has not been initialized. + NOT_INITIALIZED = 0x00010001, + /// No context is current for this thread. + NO_CURRENT_CONTEXT = 0x00010002, + /// One of the arguments to the function was an invalid enum value. + INVALID_ENUM = 0x00010003, + /// One of the arguments to the function was an invalid value. + INVALID_VALUE = 0x00010004, + /// A memory allocation failed. + OUT_OF_MEMORY = 0x00010005, + /// GLFW could not find support for the requested API on the system. + API_UNAVAILABLE = 0x00010006, + /// The requested OpenGL or OpenGL ES version is not available. + VERSION_UNAVAILABLE = 0x00010007, + /// A platform-specific error occurred that does not match any of the more specific categories. + PLATFORM_ERROR = 0x00010008, + /// The requested format is not supported or available. + FORMAT_UNAVAILABLE = 0x00010009, + /// The specified window does not have an OpenGL or OpenGL ES context. + NO_WINDOW_CONTEXT = 0x0001000A, + /// The specified cursor shape is not available. + CURSOR_UNAVAILABLE = 0x0001000B, + /// The requested feature is not provided by the platform. + FEATURE_UNAVAILABLE = 0x0001000C, + /// The requested feature is not implemented for the platform. + FEATURE_UNIMPLEMENTED = 0x0001000D, + /// Platform unavailable or no matching platform was found. + PLATFORM_UNAVAILABLE = 0x0001000E, + + pub inline fn toError(self: ErrorCode) Error!void { + return switch (self) { + .NO_ERROR => {}, + .NOT_INITIALIZED => error.NotInitialized, + .NO_CURRENT_CONTEXT => error.NoCurrentContext, + .INVALID_ENUM => error.InvalidEnum, + .INVALID_VALUE => error.InvalidValue, + .OUT_OF_MEMORY => error.OutOfMemory, + .API_UNAVAILABLE => error.ApiUnavailable, + .VERSION_UNAVAILABLE => error.VersionUnavailable, + .PLATFORM_ERROR => error.PlatformError, + .FORMAT_UNAVAILABLE => error.FormatUnavailable, + .NO_WINDOW_CONTEXT => error.NoWindowContext, + .CURSOR_UNAVAILABLE => error.CursorUnavailable, + .FEATURE_UNAVAILABLE => error.FeatureUnavailable, + .FEATURE_UNIMPLEMENTED => error.FeatureUnimplemented, + .PLATFORM_UNAVAILABLE => error.PlatformUnavailable, + }; + } +}; + +pub const Error = error{ + NotInitialized, + NoCurrentContext, + InvalidEnum, + InvalidValue, + OutOfMemory, + ApiUnavailable, + VersionUnavailable, + PlatformError, + FormatUnavailable, + NoWindowContext, + CursorUnavailable, + FeatureUnavailable, + FeatureUnimplemented, + PlatformUnavailable, +}; + +pub const WindowHint = enum(c_int) { + FOCUSED = 0x00020001, + ICONIFIED = 0x00020002, + RESIZABLE = 0x00020003, + VISIBLE = 0x00020004, + DECORATED = 0x00020005, + AUTO_ICONIFY = 0x00020006, + FLOATING = 0x00020007, + MAXIMIZED = 0x00020008, + CENTER_CURSOR = 0x00020009, + TRANSPARENT_FRAMEBUFFER = 0x0002000A, + HOVERED = 0x0002000B, + FOCUS_ON_SHOW = 0x0002000C, + MOUSE_PASSTHROUGH = 0x0002000D, + POSITION_X = 0x0002000E, + POSITION_Y = 0x0002000F, + RED_BITS = 0x00021001, + GREEN_BITS = 0x00021002, + BLUE_BITS = 0x00021003, + ALPHA_BITS = 0x00021004, + DEPTH_BITS = 0x00021005, + STENCIL_BITS = 0x00021006, + ACCUM_RED_BITS = 0x00021007, + ACCUM_GREEN_BITS = 0x00021008, + ACCUM_BLUE_BITS = 0x00021009, + ACCUM_ALPHA_BITS = 0x0002100A, + AUX_BUFFERS = 0x0002100B, + STEREO = 0x0002100C, + SAMPLES = 0x0002100D, + SRGB_CAPABLE = 0x0002100E, + REFRESH_RATE = 0x0002100F, + DOUBLEBUFFER = 0x00021010, + CLIENT_API = 0x00022001, + CONTEXT_VERSION_MAJOR = 0x00022002, + CONTEXT_VERSION_MINOR = 0x00022003, + CONTEXT_REVISION = 0x00022004, + CONTEXT_ROBUSTNESS = 0x00022005, + OPENGL_FORWARD_COMPAT = 0x00022006, + CONTEXT_DEBUG = 0x00022007, + OPENGL_PROFILE = 0x00022008, + CONTEXT_RELEASE_BEHAVIOR = 0x00022009, + CONTEXT_NO_ERROR = 0x0002200A, + CONTEXT_CREATION_API = 0x0002200B, + SCALE_TO_MONITOR = 0x0002200C, + SCALE_FRAMEBUFFER = 0x0002200D, + COCOA_RETINA_FRAMEBUFFER = 0x00023001, + COCOA_FRAME_NAME = 0x00023002, + COCOA_GRAPHICS_SWITCHING = 0x00023003, + X11_CLASS_NAME = 0x00024001, + X11_INSTANCE_NAME = 0x00024002, + WIN32_KEYBOARD_MENU = 0x00025001, + WIN32_SHOWDEFAULT = 0x00025002, + WAYLAND_APP_ID = 0x00026001, +}; + +pub const NO_API: c_int = 0; +pub const OPENGL_API: c_int = 0x00030001; +pub const OPENGL_ES_API: c_int = 0x00030002; + +pub const NO_ROBUSTNESS: c_int = 0; +pub const NO_RESET_NOTIFICATION: c_int = 0x00031001; +pub const LOSE_CONTEXT_ON_RESET: c_int = 0x00031002; + +pub const OPENGL_ANY_PROFILE: c_int = 0; +pub const OPENGL_CORE_PROFILE: c_int = 0x00032001; +pub const OPENGL_COMPAT_PROFILE: c_int = 0x00032002; + +pub const CURSOR: c_int = 0x00033001; +pub const STICKY_KEYS: c_int = 0x00033002; +pub const STICKY_MOUSE_BUTTONS: c_int = 0x00033003; +pub const LOCK_KEY_MODS: c_int = 0x00033004; +pub const RAW_MOUSE_MOTION: c_int = 0x00033005; +pub const UNLIMITED_MOUSE_BUTTONS: c_int = 0x00033006; + +pub const CURSOR_NORMAL: c_int = 0x00034001; +pub const CURSOR_HIDDEN: c_int = 0x00034002; +pub const CURSOR_DISABLED: c_int = 0x00034003; +pub const CURSOR_CAPTURED: c_int = 0x00034004; + +pub const ANY_RELEASE_BEHAVIOR: c_int = 0; +pub const RELEASE_BEHAVIOR_FLUSH: c_int = 0x00035001; +pub const RELEASE_BEHAVIOR_NONE: c_int = 0x00035002; + +pub const NATIVE_CONTEXT_API: c_int = 0x00036001; +pub const EGL_CONTEXT_API: c_int = 0x00036002; +pub const OSMESA_CONTEXT_API: c_int = 0x00036003; + +pub const ANGLE_PLATFORM_TYPE_NONE: c_int = 0x00037001; +pub const ANGLE_PLATFORM_TYPE_OPENGL: c_int = 0x00037002; +pub const ANGLE_PLATFORM_TYPE_OPENGLES: c_int = 0x00037003; +pub const ANGLE_PLATFORM_TYPE_D3D9: c_int = 0x00037004; +pub const ANGLE_PLATFORM_TYPE_D3D11: c_int = 0x00037005; +pub const ANGLE_PLATFORM_TYPE_VULKAN: c_int = 0x00037007; +pub const ANGLE_PLATFORM_TYPE_METAL: c_int = 0x00037008; + +pub const WAYLAND_PREFER_LIBDECOR: c_int = 0x00038001; +pub const WAYLAND_DISABLE_LIBDECOR: c_int = 0x00038002; + +pub const ANY_POSITION: c_int = 0x80000000; + +pub const CursorShape = enum(c_int) { + ARROW = 0x00036001, + IBEAM = 0x00036002, + CROSSHAIR = 0x00036003, + POINTING_HAND = 0x00036004, + RESIZE_EW = 0x00036005, + RESIZE_NS = 0x00036006, + RESIZE_NWSE = 0x00036007, + RESIZE_NESW = 0x00036008, + RESIZE_ALL = 0x00036009, + NOT_ALLOWED = 0x0003600A, +}; + +pub const Event = enum(c_int) { + CONNECTED = 0x00040001, + DISCONNECTED = 0x00040002, +}; + +pub const InitHint = enum(c_int) { + JOYSTICK_HAT_BUTTONS = 0x00050001, + ANGLE_PLATFORM_TYPE = 0x00050002, + PLATFORM = 0x00050003, + COCOA_CHDIR_RESOURCES = 0x00051001, + COCOA_MENUBAR = 0x00051002, + X11_XCB_VULKAN_SURFACE = 0x00052001, + WAYLAND_LIBDECOR = 0x00053001, +}; + +pub const ANY_PLATFORM: c_int = 0x00060000; +pub const PLATFORM_WIN32: c_int = 0x00060001; +pub const PLATFORM_COCOA: c_int = 0x00060002; +pub const PLATFORM_WAYLAND: c_int = 0x00060003; +pub const PLATFORM_X11: c_int = 0x00060004; +pub const PLATFORM_NULL: c_int = 0x00060005; + +pub const DONT_CARE: c_int = -1; + +// --- GLFW API types ---------------------------------------------------------- + +pub const GlProc = *const fn () callconv(.c) void; +pub const VkProc = *const fn () callconv(.c) void; + +pub const Monitor = opaque { + pub inline fn getMonitorPos(self: *Monitor) vm.Vector2Int { + var ret: vm.Vector2Int = undefined; + import.glfwGetMonitorPos(self, &ret.x, &ret.y); + return ret; + } + + pub const Workarea = struct { + pos: vm.Vector2Int, + size: vm.Vector2Int, + }; + + pub inline fn getWorkarea(self: *Monitor) Workarea { + var ret: Workarea = undefined; + import.glfwGetMonitorWorkarea(self, &ret.pos.x, &ret.pos.y, &ret.size.x, &ret.size.y); + return ret; + } + + pub inline fn getPhysicalSize(self: *Monitor) vm.Vector2Int { + var ret: vm.Vector2Int = undefined; + import.glfwGetMonitorPhysicalSize(self, &ret.x, &ret.y); + return ret; + } + + pub inline fn getContentScale(self: *Monitor) vm.Vector2 { + var ret: vm.Vector2 = undefined; + import.glfwGetMonitorContentScale(self, &ret.x, &ret.y); + return ret; + } + + pub inline fn getName(self: *Monitor) ?[*:0]const u8 { + return import.glfwGetMonitorName(self); + } + + pub inline fn setUserPointer(self: *Monitor, pointer: ?*anyopaque) void { + import.glfwSetMonitorUserPointer(self, pointer); + } + + pub inline fn getUserPointer(self: *Monitor) ?*anyopaque { + return import.glfwGetMonitorUserPointer(self); + } + + pub inline fn getVideoModes(self: *Monitor) ?[]const VidMode { + var count: c_int = undefined; + if (import.glfwGetVideoModes(self, &count)) |ptr| { + return ptr[0..@intCast(count)]; + } else { + return null; + } + } + + pub inline fn getVideoMode(self: *Monitor) ?*const VidMode { + return import.glfwGetVideoMode(self); + } + + pub inline fn setGamma(self: *Monitor, gamma: f32) void { + import.glfwSetGamma(self, gamma); + } + + pub inline fn getGammaRamp(self: *Monitor) ?*const GammaRamp { + return import.glfwGetGammaRamp(self); + } + + pub inline fn setGammaRamp(self: *Monitor, ramp: *const GammaRamp) void { + import.glfwSetGammaRamp(self, ramp); + } +}; + +pub const Window = opaque { + pub inline fn shouldClose(self: *Window) bool { + return import.glfwWindowShouldClose(self).toBool(); + } + + pub inline fn setShouldClose(self: *Window, value: bool) void { + import.glfwSetWindowShouldClose(self, .fromBool(value)); + } + + pub inline fn getTitle(self: *Window) ?[*:0]const u8 { + return import.glfwGetWindowTitle(self); + } + + pub inline fn setTitle(self: *Window, title: [*:0]const u8) void { + import.glfwSetWindowTitle(self, title); + } + + pub inline fn setIcon(self: *Window, images: []const Image) void { + import.glfwSetWindowIcon(self, @intCast(images.len), images.ptr); + } + + pub inline fn getPos(self: *Window) vm.Vector2Int { + var ret: vm.Vector2Int = undefined; + import.glfwGetWindowPos(self, &ret.x, &ret.y); + return ret; + } + + pub inline fn setPos(self: *Window, pos: vm.Vector2Int) void { + import.glfwSetWindowPos(self, pos.x, pos.y); + } + + pub inline fn getSize(self: *Window) vm.Vector2Int { + var ret: vm.Vector2Int = undefined; + import.glfwGetWindowSize(self, &ret.x, &ret.y); + return ret; + } + + pub inline fn setSizeLimits(self: *Window, min: vm.Vector2Int, max: vm.Vector2Int) void { + import.glfwSetWindowSizeLimits(self, min.x, min.y, max.x, max.y); + } + + pub inline fn setAspectRatio(self: *Window, numer: c_int, denom: c_int) void { + import.glfwSetWindowAspectRatio(self, numer, denom); + } + + pub inline fn setSize(self: *Window, size: vm.Vector2Int) void { + import.glfwSetWindowSize(self, size.x, size.y); + } + + pub inline fn getFramebufferSize(self: *Window) vm.Vector2Int { + var ret: vm.Vector2Int = undefined; + import.glfwGetFramebufferSize(self, &ret.x, &ret.y); + return ret; + } + + pub const FrameSize = struct { + left: c_int, + top: c_int, + right: c_int, + bottom: c_int, + }; + + pub inline fn getFrameSize(self: *Window) FrameSize { + var ret: FrameSize = undefined; + import.glfwGetWindowFrameSize(self, &ret.left, &ret.top, &ret.right, &ret.bottom); + return ret; + } + + pub inline fn getContentScale(self: *Window) vm.Vector2 { + var ret: vm.Vector2 = undefined; + import.glfwGetWindowContentScale(self, &ret.x, &ret.y); + return ret; + } + + pub inline fn getOpacity(self: *Window) f32 { + return import.glfwGetWindowOpacity(self); + } + + pub inline fn setOpacity(self: *Window, opacity: f32) void { + import.glfwSetWindowOpacity(self, opacity); + } + + pub inline fn iconify(self: *Window) void { + import.glfwIconifyWindow(self); + } + + pub inline fn restore(self: *Window) void { + import.glfwRestoreWindow(self); + } + + pub inline fn maximize(self: *Window) void { + import.glfwMaximizeWindow(self); + } + + pub inline fn show(self: *Window) void { + import.glfwShowWindow(self); + } + + pub inline fn hide(self: *Window) void { + import.glfwHideWindow(self); + } + + pub inline fn focus(self: *Window) void { + import.glfwFocusWindow(self); + } + + pub inline fn requestAttention(self: *Window) void { + import.glfwRequestWindowAttention(self); + } + + pub inline fn getMonitor(self: *Window) ?*Monitor { + return import.glfwGetWindowMonitor(self); + } + + pub inline fn setMonitor(self: *Window, monitor: ?*Monitor, pos: vm.Vector2Int, size: vm.Vector2Int, refresh_rate: c_int) void { + import.glfwSetWindowMonitor(self, monitor, pos.x, pos.y, size.x, size.y, refresh_rate); + } + + pub inline fn getAttrib(self: *Window, attrib: WindowHint) c_int { + return import.glfwGetWindowAttrib(self, attrib); + } + + pub inline fn setAttrib(self: *Window, attrib: WindowHint, value: c_int) void { + import.glfwSetWindowAttrib(self, attrib, value); + } + + pub inline fn setUserPointer(self: *Window, pointer: ?*anyopaque) void { + import.glfwSetWindowUserPointer(self, pointer); + } + + pub inline fn getUserPointer(self: *Window) ?*anyopaque { + return import.glfwGetWindowUserPointer(self); + } + + pub inline fn setPosCallback(self: *Window, callback: ?WindowPosFun) ?WindowPosFun { + return import.glfwSetWindowPosCallback(self, callback); + } + + pub inline fn setSizeCallback(self: *Window, callback: ?WindowSizeFun) ?WindowSizeFun { + return import.glfwSetWindowSizeCallback(self, callback); + } + + pub inline fn setCloseCallback(self: *Window, callback: ?WindowCloseFun) ?WindowCloseFun { + return import.glfwSetWindowCloseCallback(self, callback); + } + + pub inline fn setRefreshCallback(self: *Window, callback: ?WindowRefreshFun) ?WindowRefreshFun { + return import.glfwSetWindowRefreshCallback(self, callback); + } + + pub inline fn setFocusCallback(self: *Window, callback: ?WindowFocusFun) ?WindowFocusFun { + return import.glfwSetWindowFocusCallback(self, callback); + } + + pub inline fn setIconifyCallback(self: *Window, callback: ?WindowIconifyFun) ?WindowIconifyFun { + return import.glfwSetWindowIconifyCallback(self, callback); + } + + pub inline fn setMaximizeCallback(self: *Window, callback: ?WindowMaximazeFun) ?WindowMaximazeFun { + return import.glfwSetWindowMaximizeCallback(self, callback); + } + + pub inline fn setFramebufferSizeCallback(self: *Window, callback: ?FramebufferSizeFun) ?FramebufferSizeFun { + return import.glfwSetFramebufferSizeCallback(self, callback); + } + + pub inline fn setContentScaleCallback(self: *Window, callback: ?WindowContentScaleFun) ?WindowContentScaleFun { + return import.glfwSetWindowContentScaleCallback(self, callback); + } + + pub inline fn getInputMode(self: *Window, mode: c_int) c_int { + return import.glfwGetInputMode(self, mode); + } + + pub inline fn setInputMode(self: *Window, mode: c_int, value: c_int) void { + import.glfwSetInputMode(self, mode, value); + } + + pub inline fn getKey(self: *Window, key: Key) Action { + return import.glfwGetKey(self, key); + } + + pub inline fn getMouseButton(self: *Window, button: MouseButton) Action { + return import.glfwGetMouseButton(self, button); + } + + pub const CursorPos = struct { + x: f64, + y: f64, + }; + + pub inline fn getCursorPos(self: *Window) CursorPos { + var ret: CursorPos = undefined; + import.glfwGetCursorPos(self, &ret.x, &ret.y); + return ret; + } + + pub inline fn setCursorPos(self: *Window, pos: CursorPos) void { + import.glfwSetCursorPos(self, pos.x, pos.y); + } + + pub inline fn setCursor(self: *Window, cursor: ?*Cursor) void { + import.glfwSetCursor(self, cursor); + } + + pub inline fn setKeyCallback(self: *Window, callback: ?KeyFun) ?KeyFun { + return import.glfwSetKeyCallback(self, callback); + } + + pub inline fn setCharCallback(self: *Window, callback: ?CharFun) ?CharFun { + return import.glfwSetCharCallback(self, callback); + } + + pub inline fn setCharModsCallback(self: *Window, callback: ?CharModsFun) ?CharModsFun { + return import.glfwSetCharModsCallback(self, callback); + } + + pub inline fn setMouseButtonCallback(self: *Window, callback: ?MouseButtonFun) ?MouseButtonFun { + return import.glfwSetMouseButtonCallback(self, callback); + } + + pub inline fn setCursorPosCallback(self: *Window, callback: ?CursorPosFun) ?CursorPosFun { + return import.glfwSetCursorPosCallback(self, callback); + } + + pub inline fn setCursorEnterCallback(self: *Window, callback: ?CursorEnterFun) ?CursorEnterFun { + return import.glfwSetCursorEnterCallback(self, callback); + } + + pub inline fn setScrollCallback(self: *Window, callback: ?ScrollFun) ?ScrollFun { + return import.glfwSetScrollCallback(self, callback); + } + + pub inline fn setDropCallback(self: *Window, callback: ?DropFun) ?DropFun { + return import.glfwSetDropCallback(self, callback); + } + + pub inline fn makeContextCurrent(self: *Window) void { + import.glfwMakeContextCurrent(self); + } + + pub inline fn swapBuffers(self: *Window) void { + import.glfwSwapBuffers(self); + } +}; + +pub const Cursor = opaque { + pub inline fn destroy(self: *Cursor) void { + import.glfwDestroyCursor(self); + } +}; + +/// This function must return either a memory block at least `size` bytes long, +/// or `null` if allocation failed. Note that not all parts of GLFW handle +/// allocation failures gracefully yet. +/// +/// This function must support being called during `import.glfwInit` but before +/// the library is flagged as initialized, as well as during +/// `import.glfwTerminate` after the library is no longer flagged as +/// initialized. +/// +/// Any memory allocated via this function will be deallocated via the same +/// allocator during library termination or earlier. +/// +/// Any memory allocated via this function must be suitably aligned for any +/// object type. If you are using C99 or earlier, this alignment is +/// platform-dependent but will be the same as what `malloc` provides. If you +/// are using C11 or later, this is the value of `alignof(max_align_t)`. +/// +/// The size will always be greater than zero. Allocations of size zero are +/// filtered out before reaching the custom allocator. +/// +/// If this function returns `null`, GLFW will emit `error.OutOfMemory`. +/// +/// This function must not call any GLFW function. +pub const AllocateFun = *const fn (size: usize, user: ?*anyopaque) callconv(.c) ?*anyopaque; +/// This function must return a memory block at least `size` bytes long, or +/// `null` if allocation failed. Note that not all parts of GLFW handle +/// allocation failures gracefully yet. +/// +/// This function must support being called during `import.glfwInit` but before +/// the library is flagged as initialized, as well as during +/// `import.glfwTerminate` after the library is no longer flagged as +/// initialized. +/// +/// Any memory allocated via this function will be deallocated via the same +/// allocator during library termination or earlier. +/// +/// Any memory allocated via this function must be suitably aligned for any +/// object type. If you are using C99 or earlier, this alignment is +/// platform-dependent but will be the same as what `malloc` provides. If you +/// are using C11 or later, this is the value of `alignof(max_align_t)`. +/// +/// The block address will never be `null` and the size will always be greater +/// than zero. Reallocations of a block to size zero are converted into +/// deallocations before reaching the custom allocator. Reallocations of `null` +/// to a non-zero size are converted into regular allocations before reaching +/// the custom allocator. +/// +/// If this function returns `null`, GLFW will emit `error.OutOfMemory`. +/// +/// This function must not call any GLFW function. +pub const ReallocateFun = *const fn (block: *anyopaque, size: usize, user: ?*anyopaque) callconv(.c) ?*anyopaque; +/// This function may deallocate the specified memory block. This memory block +/// will have been allocated with the same allocator. +/// +/// This function must support being called during `import.glfwInit` but before +/// the library is flagged as initialized, as well as during +/// `import.glfwTerminate` after the library is no longer flagged as +/// initialized. +/// +/// The block address will never be `null`. Deallocations of `null` are filtered +/// out before reaching the custom allocator. +/// +/// This function must not call any GLFW function. +pub const DeallocateFun = *const fn (block: *anyopaque, user: ?*anyopaque) callconv(.c) void; +pub const ErrorFun = *const fn (error_code: ErrorCode, description: [*:0]const u8) callconv(.c) void; +pub const WindowPosFun = *const fn (window: *Window, xpos: c_int, ypos: c_int) callconv(.c) void; +pub const WindowSizeFun = *const fn (window: *Window, width: c_int, height: c_int) callconv(.c) void; +pub const WindowCloseFun = *const fn (window: *Window) callconv(.c) void; +pub const WindowRefreshFun = *const fn (window: *Window) callconv(.c) void; +pub const WindowFocusFun = *const fn (window: *Window, focused: Bool) callconv(.c) void; +pub const WindowIconifyFun = *const fn (window: *Window, iconified: Bool) callconv(.c) void; +pub const WindowMaximazeFun = *const fn (window: *Window, maximized: Bool) callconv(.c) void; +pub const FramebufferSizeFun = *const fn (window: *Window, width: c_int, height: c_int) callconv(.c) void; +pub const WindowContentScaleFun = *const fn (window: *Window, xscale: f32, yscale: f32) callconv(.c) void; +pub const MouseButtonFun = *const fn (window: *Window, button: MouseButton, action: Action, mods: Modifiers) callconv(.c) void; +pub const CursorPosFun = *const fn (window: *Window, xpos: f64, ypos: f64) callconv(.c) void; +pub const CursorEnterFun = *const fn (window: *Window, entered: Bool) callconv(.c) void; +pub const ScrollFun = *const fn (window: *Window, xoffset: f64, yoffset: f64) callconv(.c) void; +pub const KeyFun = *const fn (window: *Window, key: Key, scancode: c_int, action: Action, mods: Modifiers) callconv(.c) void; +pub const CharFun = *const fn (window: *Window, codepoint: c_uint) callconv(.c) void; +pub const CharModsFun = *const fn (window: *Window, codepoint: c_uint, mods: Modifiers) callconv(.c) void; +pub const DropFun = *const fn (window: *Window, path_count: c_int, paths: [*][*:0]const u8) callconv(.c) void; +pub const MonitorFun = *const fn (monitor: *Monitor, event: Event) callconv(.c) void; +pub const JoystickFun = *const fn (jid: Joystick, event: Event) callconv(.c) void; + +pub const VidMode = extern struct { + width: c_int, + height: c_int, + red_bits: c_int, + green_bits: c_int, + blue_bits: c_int, + refresh_rate: c_int, +}; + +pub const GammaRamp = extern struct { + red: [*]c_ushort, + green: [*]c_ushort, + blue: [*]c_ushort, + /// The number of elements in each array. + size: c_uint, + + pub inline fn redSlice(self: GammaRamp) []c_ushort { + return self.red[0..self.size]; + } + + pub inline fn greenSlice(self: GammaRamp) []c_ushort { + return self.green[0..self.size]; + } + + pub inline fn blueSlice(self: GammaRamp) []c_ushort { + return self.blue[0..self.size]; + } +}; + +pub const Image = extern struct { + width: c_int, + height: c_int, + /// left-to-right, top-to-bottom. + pixels: [*]u8, +}; + +pub const GamepadState = extern struct { + /// `Action.PRESS` or `Action.RELEASE`. + buttons: [15]u8, + /// In the range -1.0 to 1.0 inclusive. + axes: [6]f32, +}; + +pub const Allocator = extern struct { + allocate: AllocateFun, + reallocate: ReallocateFun, + deallocate: DeallocateFun, + user: ?*anyopaque, +}; + +// --- GLFW API functions ------------------------------------------------------ + +pub const import = struct { + pub extern fn glfwInit() Bool; + pub extern fn glfwTerminate() void; + pub extern fn glfwInitHint(hint: InitHint, value: c_int) void; + /// To use the default allocator, call this function with a `null` argument. + pub extern fn glfwInitAllocator(allocator: ?*const Allocator) void; + /// If set to `null`, GLFW will try to load the Vulkan loader dynamically by + /// its standard name and get this function from there. This is the default + /// behavior. + pub extern fn glfwInitVulkanLoader(loader: ?*const fn (instance: ?*anyopaque, name: [*:0]const u8) ?VkProc) void; + pub extern fn glfwGetVersion(major: ?*c_int, minor: ?*c_int, rev: ?*c_int) void; + pub extern fn glfwGetVersionString() [*:0]const u8; + pub extern fn glfwGetError(description: ?[*:0]const u8) ErrorCode; + pub extern fn glfwSetErrorCallback(callback: ?ErrorFun) ?ErrorFun; + pub extern fn glfwGetPlatform() c_int; + pub extern fn glfwPlatformSupported(platform: c_int) Bool; + pub extern fn glfwGetMonitors(count: *c_int) ?[*]*Monitor; + pub extern fn glfwGetPrimaryMonitor() ?*Monitor; + pub extern fn glfwGetMonitorPos(monitor: *Monitor, xpos: ?*c_int, ypos: ?*c_int) void; + pub extern fn glfwGetMonitorWorkarea(monitor: *Monitor, xpos: ?*c_int, ypos: ?*c_int, width: ?*c_int, height: ?*c_int) void; + pub extern fn glfwGetMonitorPhysicalSize(monitor: *Monitor, width_mm: ?*c_int, height_mm: ?*c_int) void; + pub extern fn glfwGetMonitorContentScale(monitor: *Monitor, xscale: ?*f32, yscale: ?*f32) void; + pub extern fn glfwGetMonitorName(monitor: *Monitor) ?[*:0]const u8; + pub extern fn glfwSetMonitorUserPointer(monitor: *Monitor, pointer: ?*anyopaque) void; + pub extern fn glfwGetMonitorUserPointer(monitor: *Monitor) ?*anyopaque; + pub extern fn glfwSetMonitorCallback(callback: ?MonitorFun) ?MonitorFun; + pub extern fn glfwGetVideoModes(monitor: *Monitor, count: *c_int) ?[*]const VidMode; + pub extern fn glfwGetVideoMode(monitor: *Monitor) ?*const VidMode; + pub extern fn glfwSetGamma(monitor: *Monitor, gamma: f32) void; + pub extern fn glfwGetGammaRamp(monitor: *Monitor) ?*const GammaRamp; + pub extern fn glfwSetGammaRamp(monitor: *Monitor, ramp: *const GammaRamp) void; + pub extern fn glfwDefaultWindowHints() void; + pub extern fn glfwWindowHint(hint: WindowHint, value: c_int) void; + pub extern fn glfwWindowHintString(hint: WindowHint, value: [*:0]const u8) void; + pub extern fn glfwCreateWindow(width: c_int, height: c_int, title: [*:0]const u8, monitor: ?*Monitor, share: ?*Window) ?*Window; + pub extern fn glfwDestroyWindow(window: *Window) void; + pub extern fn glfwWindowShouldClose(window: *Window) Bool; + pub extern fn glfwSetWindowShouldClose(window: *Window, value: Bool) void; + pub extern fn glfwGetWindowTitle(window: *Window) ?[*:0]const u8; + pub extern fn glfwSetWindowTitle(window: *Window, title: [*:0]const u8) void; + pub extern fn glfwSetWindowIcon(window: *Window, count: c_int, images: ?[*]const Image) void; + pub extern fn glfwGetWindowPos(window: *Window, xpos: ?*c_int, ypos: ?*c_int) void; + pub extern fn glfwSetWindowPos(window: *Window, xpos: c_int, ypos: c_int) void; + pub extern fn glfwGetWindowSize(window: *Window, width: ?*c_int, height: ?*c_int) void; + pub extern fn glfwSetWindowSizeLimits(window: *Window, minwidth: c_int, minheight: c_int, maxwidth: c_int, maxheight: c_int) void; + pub extern fn glfwSetWindowAspectRatio(window: *Window, numer: c_int, denom: c_int) void; + pub extern fn glfwSetWindowSize(window: *Window, width: c_int, height: c_int) void; + pub extern fn glfwGetFramebufferSize(window: *Window, width: ?*c_int, height: ?*c_int) void; + pub extern fn glfwGetWindowFrameSize(window: *Window, left: ?*c_int, top: ?*c_int, right: ?*c_int, bottom: ?*c_int) void; + pub extern fn glfwGetWindowContentScale(window: *Window, xscale: ?*f32, yscale: ?*f32) void; + pub extern fn glfwGetWindowOpacity(window: *Window) f32; + pub extern fn glfwSetWindowOpacity(window: *Window, opacity: f32) void; + pub extern fn glfwIconifyWindow(window: *Window) void; + pub extern fn glfwRestoreWindow(window: *Window) void; + pub extern fn glfwMaximizeWindow(window: *Window) void; + pub extern fn glfwShowWindow(window: *Window) void; + pub extern fn glfwHideWindow(window: *Window) void; + pub extern fn glfwFocusWindow(window: *Window) void; + pub extern fn glfwRequestWindowAttention(window: *Window) void; + pub extern fn glfwGetWindowMonitor(window: *Window) ?*Monitor; + pub extern fn glfwSetWindowMonitor(window: *Window, monitor: ?*Monitor, xpos: c_int, ypos: c_int, width: c_int, height: c_int, refresh_rate: c_int) void; + pub extern fn glfwGetWindowAttrib(window: *Window, attrib: WindowHint) c_int; + pub extern fn glfwSetWindowAttrib(window: *Window, attrib: WindowHint, value: c_int) void; + pub extern fn glfwSetWindowUserPointer(window: *Window, pointer: ?*anyopaque) void; + pub extern fn glfwGetWindowUserPointer(window: *Window) ?*anyopaque; + pub extern fn glfwSetWindowPosCallback(window: *Window, callback: ?WindowPosFun) ?WindowPosFun; + pub extern fn glfwSetWindowSizeCallback(window: *Window, callback: ?WindowSizeFun) ?WindowSizeFun; + pub extern fn glfwSetWindowCloseCallback(window: *Window, callback: ?WindowCloseFun) ?WindowCloseFun; + pub extern fn glfwSetWindowRefreshCallback(window: *Window, callback: ?WindowRefreshFun) ?WindowRefreshFun; + pub extern fn glfwSetWindowFocusCallback(window: *Window, callback: ?WindowFocusFun) ?WindowFocusFun; + pub extern fn glfwSetWindowIconifyCallback(window: *Window, callback: ?WindowIconifyFun) ?WindowIconifyFun; + pub extern fn glfwSetWindowMaximizeCallback(window: *Window, callback: ?WindowMaximazeFun) ?WindowMaximazeFun; + pub extern fn glfwSetFramebufferSizeCallback(window: *Window, callback: ?FramebufferSizeFun) ?FramebufferSizeFun; + pub extern fn glfwSetWindowContentScaleCallback(window: *Window, callback: ?WindowContentScaleFun) ?WindowContentScaleFun; + pub extern fn glfwPollEvents() void; + pub extern fn glfwWaitEvents() void; + pub extern fn glfwWaitEventsTimeout(timeout: f64) void; + pub extern fn glfwPostEmptyEvent() void; + pub extern fn glfwGetInputMode(window: *Window, mode: c_int) c_int; + pub extern fn glfwSetInputMode(window: *Window, mode: c_int, value: c_int) void; + pub extern fn glfwRawMouseMotionSupported() Bool; + pub extern fn glfwGetKeyName(key: Key, scancode: c_int) ?[*:0]const u8; + pub extern fn glfwGetKeyScancode(key: Key) c_int; + pub extern fn glfwGetKey(window: *Window, key: Key) Action; + pub extern fn glfwGetMouseButton(window: *Window, button: MouseButton) Action; + pub extern fn glfwGetCursorPos(window: *Window, xpos: ?*f64, ypos: ?*f64) void; + pub extern fn glfwSetCursorPos(window: *Window, xpos: f64, ypos: f64) void; + pub extern fn glfwCreateCursor(image: *const Image, xhot: c_int, yhot: c_int) ?*Cursor; + pub extern fn glfwCreateStandardCursor(shape: CursorShape) ?*Cursor; + pub extern fn glfwDestroyCursor(cursor: *Cursor) void; + pub extern fn glfwSetCursor(window: *Window, cursor: ?*Cursor) void; + pub extern fn glfwSetKeyCallback(window: *Window, callback: ?KeyFun) ?KeyFun; + pub extern fn glfwSetCharCallback(window: *Window, callback: ?CharFun) ?CharFun; + pub extern fn glfwSetCharModsCallback(window: *Window, callback: ?CharModsFun) ?CharModsFun; + pub extern fn glfwSetMouseButtonCallback(window: *Window, callback: ?MouseButtonFun) ?MouseButtonFun; + pub extern fn glfwSetCursorPosCallback(window: *Window, callback: ?CursorPosFun) ?CursorPosFun; + pub extern fn glfwSetCursorEnterCallback(window: *Window, callback: ?CursorEnterFun) ?CursorEnterFun; + pub extern fn glfwSetScrollCallback(window: *Window, callback: ?ScrollFun) ?ScrollFun; + pub extern fn glfwSetDropCallback(window: *Window, callback: ?DropFun) ?DropFun; + pub extern fn glfwJoystickPresent(jid: Joystick) Bool; + pub extern fn glfwGetJoystickAxes(jid: Joystick, count: *c_int) ?[*]const f32; + pub extern fn glfwGetJoystickButtons(jid: Joystick, count: *c_int) ?[*]const u8; + pub extern fn glfwGetJoystickHats(jid: Joystick, count: *c_int) ?[*]const Hat; + pub extern fn glfwGetJoystickName(jid: Joystick) ?[*:0]const u8; + pub extern fn glfwGetJoystickGUID(jid: Joystick) ?[*:0]const u8; + pub extern fn glfwSetJoystickUserPointer(jid: Joystick, pointer: ?*anyopaque) void; + pub extern fn glfwGetJoystickUserPointer(jid: Joystick) ?*anyopaque; + pub extern fn glfwJoystickIsGamepad(jid: Joystick) Bool; + pub extern fn glfwSetJoystickCallback(callback: ?JoystickFun) ?JoystickFun; + pub extern fn glfwUpdateGamepadMappings(string: [*:0]const u8) Bool; + pub extern fn glfwGetGamepadName(jid: Joystick) ?[*:0]const u8; + pub extern fn glfwGetGamepadState(jid: Joystick, state: *GamepadState) Bool; + pub extern fn glfwSetClipboardString(_: ?*Window, string: [*:0]const u8) void; + pub extern fn glfwGetClipboardString(_: ?*Window) ?[*:0]const u8; + pub extern fn glfwGetTime() f64; + pub extern fn glfwSetTime(time: f64) void; + pub extern fn glfwGetTimerValue() u64; + pub extern fn glfwGetTimerFrequency() u64; + pub extern fn glfwMakeContextCurrent(window: *Window) void; + pub extern fn glfwGetCurrentContext() ?*Window; + pub extern fn glfwSwapBuffers(window: *Window) void; + pub extern fn glfwSwapInterval(interval: c_int) void; + pub extern fn glfwExtensionSupported(extension: [*:0]const u8) Bool; + pub extern fn glfwGetProcAddress(procname: [*:0]const u8) ?GlProc; + pub extern fn glfwVulkanSupported() Bool; + pub extern fn glfwGetRequiredInstanceExtensions(count: *u32) ?[*][*:0]const u8; + pub extern fn glfwGetInstanceProcAddress(vk_instance: ?*anyopaque, procname: [*:0]const u8) ?VkProc; + pub extern fn glfwGetPhysicalDevicePresentationSupport(vk_instance: *anyopaque, vk_physical_device: *anyopaque, queuefamily: u32) Bool; + pub extern fn glfwCreateWindowSurface(vk_instance: *anyopaque, window: *Window, vk_allocation_callbacks: ?*anyopaque, vk_surface_khr: *u64) c_int; +};