Compare commits
2
Commits
80bad9aad5
...
f1028acb10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1028acb10 | ||
|
|
90602ff1ff |
@@ -5,6 +5,8 @@ set -eu
|
||||
PROJECT="sindri"
|
||||
VERSION="dev-$(date -u '+%Y-%m-%d')-$(git rev-parse --short HEAD)"
|
||||
|
||||
OPTION="${1:-}"
|
||||
|
||||
# ------------------------------------------
|
||||
|
||||
# Setup compiled wgpu binary
|
||||
@@ -39,7 +41,7 @@ if pgrep -x $PROJECT >/dev/null; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$1" = "debug" ]; then
|
||||
if [ "$OPTION" = "debug" ]; then
|
||||
shift
|
||||
|
||||
odin build src/ -show-timings \
|
||||
|
||||
+7
-1
@@ -1,5 +1,6 @@
|
||||
package game
|
||||
|
||||
import "sindri:input"
|
||||
import "core:time"
|
||||
import "core:fmt"
|
||||
|
||||
@@ -8,6 +9,7 @@ import "sindri:core"
|
||||
// -----------------------------------------
|
||||
|
||||
Game_Memory :: struct {
|
||||
should_close: bool
|
||||
}
|
||||
|
||||
g: ^Game_Memory
|
||||
@@ -64,6 +66,10 @@ init :: proc() {
|
||||
@(export)
|
||||
update :: proc(dt: f32) {
|
||||
fmt.println("dt:", dt)
|
||||
|
||||
if input.key_state(.Key_Escape) == .Press {
|
||||
g.should_close = true
|
||||
}
|
||||
}
|
||||
|
||||
@(export)
|
||||
@@ -79,7 +85,7 @@ should_close :: proc() -> bool {
|
||||
seconds := time.duration_seconds(elapsed)
|
||||
if seconds > 4 do return true
|
||||
|
||||
return false
|
||||
return g.should_close
|
||||
}
|
||||
|
||||
@(export)
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
package event
|
||||
|
||||
import "core:fmt"
|
||||
|
||||
import "sindri:input"
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
// event category, bitfield (?)
|
||||
|
||||
Event :: union {
|
||||
Window_Close_Event,
|
||||
Window_Resize_Event,
|
||||
Joystick_Connect_Event,
|
||||
Joystick_Disconnect_Event,
|
||||
Key_Press_Event,
|
||||
Key_Release_Event,
|
||||
Key_Repeat_Event,
|
||||
Mouse_Button_Press_Event,
|
||||
Mouse_Button_Release_Event,
|
||||
Mouse_Position_Event,
|
||||
Mouse_Scroll_Event,
|
||||
}
|
||||
|
||||
Window_Close_Event :: struct {
|
||||
handled: bool,
|
||||
}
|
||||
|
||||
Window_Resize_Event :: struct {
|
||||
handled: bool,
|
||||
width: i32,
|
||||
height: i32,
|
||||
}
|
||||
|
||||
Joystick_Connect_Event :: struct {
|
||||
handled: bool,
|
||||
id: i32,
|
||||
}
|
||||
|
||||
Joystick_Disconnect_Event :: struct {
|
||||
handled: bool,
|
||||
id: i32,
|
||||
}
|
||||
|
||||
Key_Press_Event :: struct {
|
||||
handled: bool,
|
||||
key: input.Key,
|
||||
mods: input.Mod_Set,
|
||||
}
|
||||
|
||||
Key_Release_Event :: struct {
|
||||
handled: bool,
|
||||
key: input.Key,
|
||||
mods: input.Mod_Set,
|
||||
}
|
||||
|
||||
Key_Repeat_Event :: struct {
|
||||
handled: bool,
|
||||
key: input.Key,
|
||||
mods: input.Mod_Set,
|
||||
}
|
||||
|
||||
Mouse_Button_Press_Event :: struct {
|
||||
handled: bool,
|
||||
button: input.Mouse_Button,
|
||||
mods: input.Mod_Set,
|
||||
}
|
||||
|
||||
Mouse_Button_Release_Event :: struct {
|
||||
handled: bool,
|
||||
button: input.Mouse_Button,
|
||||
mods: input.Mod_Set,
|
||||
}
|
||||
|
||||
Mouse_Position_Event :: struct {
|
||||
handled: bool,
|
||||
x_pos: f32,
|
||||
y_pos: f32,
|
||||
}
|
||||
|
||||
Mouse_Scroll_Event :: struct {
|
||||
handled: bool,
|
||||
x_offset: f32,
|
||||
y_offset: f32,
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
// Dispatcher(Event) -> forwards to the right function
|
||||
on_event :: proc(event: Event) {
|
||||
fmt.println("toby!")
|
||||
|
||||
#partial switch e in event {
|
||||
case Window_Close_Event:
|
||||
fmt.println("Close")
|
||||
case Window_Resize_Event:
|
||||
fmt.println("Resize:", e.width, e.height)
|
||||
|
||||
case Key_Press_Event:
|
||||
fmt.println("Key press", e.key, e.mods)
|
||||
case Key_Release_Event:
|
||||
fmt.println("Key release", e.key, e.mods)
|
||||
case Key_Repeat_Event:
|
||||
fmt.println("Key repeat", e.key, e.mods)
|
||||
|
||||
case Mouse_Button_Press_Event:
|
||||
fmt.println("Mouse press", e.button, e.mods)
|
||||
case Mouse_Button_Release_Event:
|
||||
fmt.println("Mouse release", e.button, e.mods)
|
||||
case Mouse_Position_Event:
|
||||
fmt.printfln("Mouse pos: {}x{}", e.x_pos, e.y_pos)
|
||||
|
||||
case Joystick_Connect_Event:
|
||||
fmt.println("Joy con:", e.id)
|
||||
case Joystick_Disconnect_Event:
|
||||
fmt.println("Joy dis:", e.id)
|
||||
}
|
||||
}
|
||||
-118
@@ -1,118 +0,0 @@
|
||||
package sindri
|
||||
|
||||
import "core:strings"
|
||||
import "vendor:glfw"
|
||||
|
||||
import "wgpu:wgpu"
|
||||
import "wgpu:wgpu/glfwglue"
|
||||
|
||||
import "sindri:core"
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
OS :: struct {
|
||||
window: glfw.WindowHandle,
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
os_init :: proc(settings: core.Settings) {
|
||||
if !glfw.Init() {
|
||||
panic("[glfw] init failure")
|
||||
}
|
||||
|
||||
glfw.WindowHint(glfw.CLIENT_API, glfw.NO_API)
|
||||
state.os.window = glfw.CreateWindow(
|
||||
i32(settings.width),
|
||||
i32(settings.height),
|
||||
strings.unsafe_string_to_cstring(settings.title),
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
glfw.SetFramebufferSizeCallback(state.os.window, size_callback)
|
||||
}
|
||||
|
||||
os_set_monitor :: proc(settings: core.Settings) {
|
||||
monitor := glfw.GetPrimaryMonitor()
|
||||
x_pos: i32
|
||||
y_pos: i32
|
||||
width := i32(settings.width)
|
||||
height := i32(settings.height)
|
||||
target_monitor: glfw.MonitorHandle
|
||||
|
||||
mode := glfw.GetVideoMode(monitor)
|
||||
|
||||
switch settings.mode {
|
||||
case .Fullscreen:
|
||||
target_monitor = monitor
|
||||
case .Borderless:
|
||||
// FIXME: On macOS, borderless also fills the notch area
|
||||
|
||||
// Monitor origin on the virtual desktop
|
||||
x_pos, y_pos = glfw.GetMonitorPos(monitor)
|
||||
|
||||
width = mode.width
|
||||
height = mode.height
|
||||
|
||||
glfw.SetWindowAttrib(
|
||||
state.os.window,
|
||||
glfw.DECORATED,
|
||||
i32(glfw.FALSE),
|
||||
)
|
||||
case .Windowed:
|
||||
// Put window in the center of the monitor
|
||||
x_pos = (mode.width - width) / 2
|
||||
y_pos = (mode.height - height) / 2
|
||||
|
||||
glfw.SetWindowAttrib(
|
||||
state.os.window,
|
||||
glfw.DECORATED,
|
||||
i32(glfw.TRUE),
|
||||
)
|
||||
}
|
||||
|
||||
refresh := settings.vsync ? mode.refresh_rate : i32(settings.refresh)
|
||||
if refresh == 0 do refresh = glfw.DONT_CARE
|
||||
|
||||
glfw.SetWindowMonitor(
|
||||
state.os.window,
|
||||
target_monitor,
|
||||
x_pos,
|
||||
y_pos,
|
||||
width,
|
||||
height,
|
||||
refresh,
|
||||
)
|
||||
}
|
||||
|
||||
os_should_close :: proc() -> bool {
|
||||
return bool(glfw.WindowShouldClose(state.os.window))
|
||||
}
|
||||
|
||||
os_set_should_close :: proc(val: bool) {
|
||||
glfw.SetWindowShouldClose(state.os.window, b32(val))
|
||||
}
|
||||
|
||||
os_poll_events :: proc() {
|
||||
glfw.PollEvents()
|
||||
}
|
||||
|
||||
os_destroy :: proc() {
|
||||
glfw.DestroyWindow(state.os.window)
|
||||
glfw.Terminate()
|
||||
}
|
||||
|
||||
os_get_framebuffer_size :: proc() -> (width, height: u32) {
|
||||
iw, ih := glfw.GetFramebufferSize(state.os.window)
|
||||
return u32(iw), u32(ih)
|
||||
}
|
||||
|
||||
os_get_surface :: proc(instance: wgpu.Instance) -> wgpu.Surface {
|
||||
return glfwglue.GetSurface(instance, state.os.window)
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
size_callback :: proc "c" (window: glfw.WindowHandle, width, height: i32) {
|
||||
resize()
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package input
|
||||
|
||||
// -----------------------------------------
|
||||
// Public functions
|
||||
|
||||
// Returns the state of the keyboard key
|
||||
// implementation in platform package, to prevent cyclic dependency
|
||||
key_state: proc(key: Key) -> Action
|
||||
|
||||
// Returns the state of the mouse button
|
||||
// implementation in platform package, to prevent cyclic dependency
|
||||
mouse_button_state: proc(button: Mouse_Button) -> Action
|
||||
|
||||
// -----------------------------------------
|
||||
// Private functions
|
||||
@@ -0,0 +1,183 @@
|
||||
package input
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
// Button/Key states
|
||||
Action :: enum i8 {
|
||||
None = -1,
|
||||
Release = 0,
|
||||
Press = 1,
|
||||
Repeat = 2,
|
||||
}
|
||||
|
||||
Key :: enum i16 {
|
||||
// The unknown key
|
||||
Key_Unknown = -1,
|
||||
|
||||
// --- Printable keys ---
|
||||
|
||||
// Named printable keys
|
||||
Key_Space = 32,
|
||||
Key_Apostrophe = 39, // '
|
||||
Key_Comma = 44, // ,
|
||||
Key_Minus = 45, // -
|
||||
Key_Period = 46, // .
|
||||
Key_Slash = 47, // /
|
||||
Key_Semicolon = 59, // ;
|
||||
Key_Equal = 61, // =
|
||||
Key_Left_Bracket = 91, // [
|
||||
Key_Backslash = 92, // \
|
||||
Key_Right_Bracket = 93, // ]
|
||||
Key_Grave_Accent = 96, // `
|
||||
Key_World_1 = 161, // non-US #1
|
||||
Key_World_2 = 162, // non-US #2
|
||||
|
||||
// Alphanumeric characters
|
||||
Key_0 = 48,
|
||||
Key_1 = 49,
|
||||
Key_2 = 50,
|
||||
Key_3 = 51,
|
||||
Key_4 = 52,
|
||||
Key_5 = 53,
|
||||
Key_6 = 54,
|
||||
Key_7 = 55,
|
||||
Key_8 = 56,
|
||||
Key_9 = 57,
|
||||
Key_A = 65,
|
||||
Key_B = 66,
|
||||
Key_C = 67,
|
||||
Key_D = 68,
|
||||
Key_E = 69,
|
||||
Key_F = 70,
|
||||
Key_G = 71,
|
||||
Key_H = 72,
|
||||
Key_I = 73,
|
||||
Key_J = 74,
|
||||
Key_K = 75,
|
||||
Key_L = 76,
|
||||
Key_M = 77,
|
||||
Key_N = 78,
|
||||
Key_O = 79,
|
||||
Key_P = 80,
|
||||
Key_Q = 81,
|
||||
Key_R = 82,
|
||||
Key_S = 83,
|
||||
Key_T = 84,
|
||||
Key_U = 85,
|
||||
Key_V = 86,
|
||||
Key_W = 87,
|
||||
Key_X = 88,
|
||||
Key_Y = 89,
|
||||
Key_Z = 90,
|
||||
|
||||
// --- Function keys ---
|
||||
|
||||
// Named non-printable keys
|
||||
Key_Escape = 256,
|
||||
Key_Enter = 257,
|
||||
Key_Tab = 258,
|
||||
Key_Backspace = 259,
|
||||
Key_Insert = 260,
|
||||
Key_Delete = 261,
|
||||
Key_Right = 262,
|
||||
Key_Left = 263,
|
||||
Key_Down = 264,
|
||||
Key_Up = 265,
|
||||
Key_Page_Up = 266,
|
||||
Key_Page_Down = 267,
|
||||
Key_Home = 268,
|
||||
Key_End = 269,
|
||||
Key_Caps_Lock = 280,
|
||||
Key_Scroll_Lock = 281,
|
||||
Key_Num_Lock = 282,
|
||||
Key_Print_Screen = 283,
|
||||
Key_Pause = 284,
|
||||
|
||||
// Function keys
|
||||
Key_F1 = 290,
|
||||
Key_F2 = 291,
|
||||
Key_F3 = 292,
|
||||
Key_F4 = 293,
|
||||
Key_F5 = 294,
|
||||
Key_F6 = 295,
|
||||
Key_F7 = 296,
|
||||
Key_F8 = 297,
|
||||
Key_F9 = 298,
|
||||
Key_F10 = 299,
|
||||
Key_F11 = 300,
|
||||
Key_F12 = 301,
|
||||
Key_F13 = 302,
|
||||
Key_F14 = 303,
|
||||
Key_F15 = 304,
|
||||
Key_F16 = 305,
|
||||
Key_F17 = 306,
|
||||
Key_F18 = 307,
|
||||
Key_F19 = 308,
|
||||
Key_F20 = 309,
|
||||
Key_F21 = 310,
|
||||
Key_F22 = 311,
|
||||
Key_F23 = 312,
|
||||
Key_F24 = 313,
|
||||
Key_F25 = 314,
|
||||
|
||||
// Keypad numbers
|
||||
Key_KP_0 = 320,
|
||||
Key_KP_1 = 321,
|
||||
Key_KP_2 = 322,
|
||||
Key_KP_3 = 323,
|
||||
Key_KP_4 = 324,
|
||||
Key_KP_5 = 325,
|
||||
Key_KP_6 = 326,
|
||||
Key_KP_7 = 327,
|
||||
Key_KP_8 = 328,
|
||||
Key_KP_9 = 329,
|
||||
|
||||
// Keypad named function keys
|
||||
Key_KP_Decimal = 330,
|
||||
Key_KP_Divide = 331,
|
||||
Key_KP_Multiply = 332,
|
||||
Key_KP_Subtract = 333,
|
||||
Key_KP_Add = 334,
|
||||
Key_KP_Enter = 335,
|
||||
Key_KP_Equal = 336,
|
||||
|
||||
// Modifier keys
|
||||
Key_Left_Shift = 340,
|
||||
Key_Left_Control = 341,
|
||||
Key_Left_Alt = 342,
|
||||
Key_Left_Super = 343,
|
||||
Key_Right_Shift = 344,
|
||||
Key_Right_Control = 345,
|
||||
Key_Right_Alt = 346,
|
||||
Key_Right_Super = 347,
|
||||
Key_Menu = 348,
|
||||
Key_Last = Key_Menu,
|
||||
}
|
||||
|
||||
// Bitmask for modifier keys
|
||||
Mod :: enum i8 {
|
||||
Shift = 0,
|
||||
Control = 1,
|
||||
Alt = 2,
|
||||
Super = 3,
|
||||
Caps_Lock = 4,
|
||||
Num_Lock = 5,
|
||||
}
|
||||
Mod_Set :: bit_set[Mod]
|
||||
|
||||
// Mouse buttons
|
||||
Mouse_Button :: enum i8 {
|
||||
Button_1 = 0,
|
||||
Button_2 = 1,
|
||||
Button_3 = 2,
|
||||
Button_4 = 3,
|
||||
Button_5 = 4,
|
||||
Button_6 = 5,
|
||||
Button_7 = 6,
|
||||
Button_8 = 7,
|
||||
// Alias names
|
||||
Last = Button_8,
|
||||
Left = Button_1,
|
||||
Right = Button_2,
|
||||
Middle = Button_3,
|
||||
}
|
||||
+9
-8
@@ -4,6 +4,7 @@ import "core:fmt"
|
||||
import "core:time"
|
||||
|
||||
import "sindri:hot_reload"
|
||||
import "sindri:platform"
|
||||
|
||||
VERSION :: #config(VERSION, "dev")
|
||||
|
||||
@@ -20,13 +21,13 @@ main :: proc() {
|
||||
settings := api.settings()
|
||||
|
||||
// Initialize Window
|
||||
os_init(settings)
|
||||
os_set_monitor(settings)
|
||||
defer os_destroy()
|
||||
platform.os_init(settings)
|
||||
platform.os_set_monitor(settings)
|
||||
defer platform.os_destroy()
|
||||
|
||||
// Initialize GPU resources
|
||||
instance_init()
|
||||
defer instance_destroy()
|
||||
platform.instance_init()
|
||||
defer platform.instance_destroy()
|
||||
|
||||
api.init_once()
|
||||
api.init()
|
||||
@@ -34,13 +35,13 @@ main :: proc() {
|
||||
gt: f64 = 0
|
||||
dt: f32
|
||||
|
||||
for !os_should_close() && !hot_reload.should_close(&hr) {
|
||||
for !platform.os_should_close() && !hot_reload.should_close(&hr) {
|
||||
start := time.tick_now()
|
||||
|
||||
os_poll_events()
|
||||
platform.os_poll_events()
|
||||
api.update(dt)
|
||||
|
||||
frame(dt)
|
||||
platform.frame(dt)
|
||||
|
||||
dt = f32(time.duration_seconds(time.tick_since(start)))
|
||||
gt += f64(dt)
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
package platform
|
||||
|
||||
import "core:fmt"
|
||||
import "core:strings"
|
||||
import "vendor:glfw"
|
||||
|
||||
import "wgpu:wgpu"
|
||||
import "wgpu:wgpu/glfwglue"
|
||||
|
||||
import "sindri:core"
|
||||
import "sindri:event"
|
||||
import "sindri:input"
|
||||
|
||||
// -----------------------------------------
|
||||
// Types
|
||||
|
||||
OS :: struct {
|
||||
window: glfw.WindowHandle,
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// Constructor / destructor
|
||||
|
||||
os_init :: proc(settings: core.Settings) {
|
||||
if !glfw.Init() {
|
||||
panic("[glfw] init failure")
|
||||
}
|
||||
|
||||
// Set window properties
|
||||
glfw.WindowHint(glfw.CLIENT_API, glfw.NO_API) // do not create OpenGL context
|
||||
glfw.WindowHint(glfw.RESIZABLE, glfw.FALSE)
|
||||
|
||||
// Create GLFW window
|
||||
state.os.window = glfw.CreateWindow(
|
||||
i32(settings.width),
|
||||
i32(settings.height),
|
||||
strings.unsafe_string_to_cstring(settings.title),
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
glfw.SetErrorCallback(error_callback)
|
||||
glfw.SetWindowCloseCallback(state.os.window, window_close_callback)
|
||||
// NOTE: SetFramebufferSize over SetWindowSize, to handle different DPIs
|
||||
glfw.SetFramebufferSizeCallback(state.os.window, size_callback)
|
||||
glfw.SetKeyCallback(state.os.window, key_callback)
|
||||
glfw.SetMouseButtonCallback(state.os.window, mouse_button_callback)
|
||||
glfw.SetCursorPosCallback(state.os.window, cursor_pos_callback)
|
||||
glfw.SetScrollCallback(state.os.window, scroll_callback)
|
||||
glfw.SetJoystickCallback(joystick_callback)
|
||||
|
||||
// Register input functions
|
||||
input.key_state = key_state
|
||||
input.mouse_button_state = mouse_button_state
|
||||
|
||||
// TODO: Figure out proper vsync, found 3 spots so far
|
||||
// - glfw.SwapInterval(0) this is only for OpenGL it seems?
|
||||
// - glfw.SetWindowMonitor(refresh)
|
||||
// - wgpu presentMode = .Fifo
|
||||
}
|
||||
|
||||
os_destroy :: proc() {
|
||||
glfw.DestroyWindow(state.os.window)
|
||||
glfw.Terminate()
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// Public functions
|
||||
|
||||
os_set_monitor :: proc(settings: core.Settings) {
|
||||
monitor := glfw.GetPrimaryMonitor()
|
||||
x_pos: i32
|
||||
y_pos: i32
|
||||
width := i32(settings.width)
|
||||
height := i32(settings.height)
|
||||
target_monitor: glfw.MonitorHandle
|
||||
|
||||
mode := glfw.GetVideoMode(monitor)
|
||||
|
||||
switch settings.mode {
|
||||
case .Fullscreen:
|
||||
target_monitor = monitor
|
||||
case .Borderless:
|
||||
// FIXME: On macOS, borderless also fills the notch area
|
||||
|
||||
// Monitor origin on the virtual desktop
|
||||
x_pos, y_pos = glfw.GetMonitorPos(monitor)
|
||||
|
||||
width = mode.width
|
||||
height = mode.height
|
||||
|
||||
glfw.SetWindowAttrib(
|
||||
state.os.window,
|
||||
glfw.DECORATED,
|
||||
i32(glfw.FALSE),
|
||||
)
|
||||
case .Windowed:
|
||||
// Put window in the center of the monitor
|
||||
x_pos = (mode.width - width) / 2
|
||||
y_pos = (mode.height - height) / 2
|
||||
|
||||
glfw.SetWindowAttrib(
|
||||
state.os.window,
|
||||
glfw.DECORATED,
|
||||
i32(glfw.TRUE),
|
||||
)
|
||||
}
|
||||
|
||||
refresh := settings.vsync ? mode.refresh_rate : i32(settings.refresh)
|
||||
if refresh == 0 do refresh = glfw.DONT_CARE
|
||||
|
||||
glfw.SetWindowMonitor(
|
||||
state.os.window,
|
||||
target_monitor,
|
||||
x_pos,
|
||||
y_pos,
|
||||
width,
|
||||
height,
|
||||
refresh,
|
||||
)
|
||||
}
|
||||
|
||||
os_set_callback_proc :: proc(window: rawptr) {
|
||||
glfw.SetWindowUserPointer(state.os.window, window)
|
||||
}
|
||||
|
||||
os_should_close :: proc() -> bool {
|
||||
return bool(glfw.WindowShouldClose(state.os.window))
|
||||
}
|
||||
|
||||
os_set_should_close :: proc(val: bool) {
|
||||
glfw.SetWindowShouldClose(state.os.window, b32(val))
|
||||
}
|
||||
|
||||
os_poll_events :: proc() {
|
||||
glfw.PollEvents()
|
||||
}
|
||||
|
||||
os_get_framebuffer_size :: proc() -> (width, height: u32) {
|
||||
iw, ih := glfw.GetFramebufferSize(state.os.window)
|
||||
return u32(iw), u32(ih)
|
||||
}
|
||||
|
||||
os_get_surface :: proc(instance: wgpu.Instance) -> wgpu.Surface {
|
||||
return glfwglue.GetSurface(instance, state.os.window)
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// Private functions
|
||||
|
||||
@(private = "file")
|
||||
key_state :: proc(key: input.Key) -> input.Action {
|
||||
return input_action(glfw.GetKey(state.os.window, i32(key)))
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
mouse_button_state :: proc(button: input.Mouse_Button) -> input.Action {
|
||||
return input_action(glfw.GetMouseButton(state.os.window, i32(button)))
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
input_action :: proc(action: i32) -> input.Action {
|
||||
if action == glfw.RELEASE do return input.Action.Release
|
||||
else if action == glfw.PRESS do return input.Action.Press
|
||||
else if action == glfw.REPEAT do return input.Action.Repeat
|
||||
when ODIN_DEBUG do panic("[glfw] unknown action")
|
||||
return .None
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
input_key :: proc(key: i32) -> input.Key {
|
||||
return input.Key(key) // values match
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
input_mod_set :: proc(mods: i32) -> (set: input.Mod_Set) {
|
||||
return transmute(input.Mod_Set)i8(mods & 0x3f) // values match bit position
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
input_mouse_button :: proc(button: i32) -> input.Mouse_Button {
|
||||
return input.Mouse_Button(button) // values match
|
||||
}
|
||||
|
||||
// Error callback
|
||||
@(private = "file")
|
||||
error_callback :: proc "c" (error: i32, description: cstring) {
|
||||
context = state.ctx
|
||||
fmt.eprintfln("error: GLFW {}: {}", error, description)
|
||||
} // GLFWerrorfun
|
||||
|
||||
// Window close callback
|
||||
@(private = "file")
|
||||
window_close_callback :: proc "c" (window: glfw.WindowHandle) {
|
||||
context = state.ctx
|
||||
event.on_event(event.Window_Close_Event{})
|
||||
} // GLFWwindowclosefun
|
||||
|
||||
// Window resize callback
|
||||
@(private = "file")
|
||||
size_callback :: proc "c" (window: glfw.WindowHandle, width, height: i32) {
|
||||
resize()
|
||||
} // GLFWframebuffersizefun
|
||||
|
||||
// Keyboard callback
|
||||
@(private = "file")
|
||||
key_callback :: proc "c" (
|
||||
window: glfw.WindowHandle,
|
||||
key, scancode, action, mods: i32,
|
||||
) {
|
||||
context = state.ctx
|
||||
if action == glfw.PRESS {
|
||||
event.on_event(
|
||||
event.Key_Press_Event {
|
||||
key = input_key(key),
|
||||
mods = input_mod_set(mods),
|
||||
},
|
||||
)
|
||||
}
|
||||
if action == glfw.RELEASE {
|
||||
event.on_event(
|
||||
event.Key_Release_Event {
|
||||
key = input_key(key),
|
||||
mods = input_mod_set(mods),
|
||||
},
|
||||
)
|
||||
}
|
||||
if action == glfw.REPEAT {
|
||||
event.on_event(
|
||||
event.Key_Repeat_Event {
|
||||
key = input_key(key),
|
||||
mods = input_mod_set(mods),
|
||||
},
|
||||
)
|
||||
}
|
||||
} // GLFWkeyfun
|
||||
|
||||
// Mouse button callback
|
||||
@(private = "file")
|
||||
mouse_button_callback :: proc "c" (
|
||||
window: glfw.WindowHandle,
|
||||
button, action, mods: i32,
|
||||
) {
|
||||
context = state.ctx
|
||||
if action == glfw.PRESS {
|
||||
event.on_event(
|
||||
event.Mouse_Button_Press_Event {
|
||||
button = input_mouse_button(button),
|
||||
mods = input_mod_set(mods),
|
||||
},
|
||||
)
|
||||
}
|
||||
if action == glfw.RELEASE {
|
||||
event.on_event(
|
||||
event.Mouse_Button_Release_Event {
|
||||
button = input_mouse_button(button),
|
||||
mods = input_mod_set(mods),
|
||||
},
|
||||
)
|
||||
}
|
||||
} // GLFWmousebuttonfun
|
||||
|
||||
// Mouse position callback
|
||||
@(private = "file")
|
||||
cursor_pos_callback :: proc "c" (
|
||||
window: glfw.WindowHandle,
|
||||
x_pos, y_pos: f64,
|
||||
) {
|
||||
context = state.ctx
|
||||
event.on_event(
|
||||
event.Mouse_Position_Event{x_pos = f32(x_pos), y_pos = f32(y_pos)},
|
||||
)
|
||||
} // GLFWcursorposfun
|
||||
|
||||
// Mouse scroll callback
|
||||
@(private = "file")
|
||||
scroll_callback :: proc "c" (
|
||||
window: glfw.WindowHandle,
|
||||
x_offset, y_offset: f64,
|
||||
) {
|
||||
context = state.ctx
|
||||
event.on_event(
|
||||
event.Mouse_Scroll_Event {
|
||||
x_offset = f32(x_offset),
|
||||
y_offset = f32(y_offset),
|
||||
},
|
||||
)
|
||||
} // GLFWscrollfun
|
||||
|
||||
// Joystick connected / disconnected callback
|
||||
@(private = "file")
|
||||
joystick_callback :: proc "c" (id, connected: i32) {
|
||||
context = state.ctx
|
||||
if connected == glfw.CONNECTED {
|
||||
event.on_event(event.Joystick_Connect_Event{id = id})
|
||||
} else {
|
||||
event.on_event(event.Joystick_Disconnect_Event{id = id})
|
||||
}
|
||||
} // GLFWjoystickfun
|
||||
|
||||
// References:
|
||||
// - https://www.glfw.org/docs/latest/group__init.html
|
||||
// - https://www.glfw.org/docs/latest/group__window.html
|
||||
// - https://www.glfw.org/docs/latest/group__input.html
|
||||
@@ -1,4 +1,4 @@
|
||||
package sindri
|
||||
package platform
|
||||
|
||||
import "base:runtime"
|
||||
import "core:fmt"
|
||||
Reference in New Issue
Block a user