Base input pass updated for sokol possibly done (untested)

Still need to figure out input event consumption, I don't want to do it with the event ring.

I would like to setup input binding layers and then have the push/pop input contextes with a set of bindings.
If the bindings are detected it should "consume" that binding from further use for the buffered time period.

This will be really important with how heavily model this app will be.I
This commit is contained in:
2024-06-18 01:33:50 -04:00
parent 3b395f3356
commit b698f5166b
14 changed files with 487 additions and 151 deletions

View File

@ -1,63 +0,0 @@
package sectr
InputEventType :: enum u32 {
Key_Pressed,
Key_Released,
Mouse_Pressed,
Mouse_Released,
Mouse_Scroll,
Mouse_Move,
Mouse_Enter,
Mouse_Leave,
Unicode,
}
InputEvent :: struct
{
frame_id : u64,
type : InputEventType,
key : KeyCode,
modifiers : ModifierCodeFlags,
mouse : struct {
btn : MouseBtn,
pos : Vec2,
delta : Vec2,
scroll : Vec2,
},
codepoint : rune,
// num_touches : u32,
// touches : Touchpoint,
_sokol_frame_id : u64,
}
InputKeyEvent :: struct {
frame_id : u64,
type : InputEventType,
key : KeyCode,
modifiers : ModifierCodeFlags,
}
InputMouseEvent :: struct {
frame_id : u64,
type : InputEventType,
key : KeyCode,
modifiers : ModifierCodeFlags,
}
// Note(Ed): There is a staged_input_events : Array(InputEvent), in the state.odin's State struct
append_staged_input_events :: #force_inline proc() {
// TODO(Ed) : Add guards for multi-threading
state := get_state()
array_append( & state.staged_input_events, event )
}
pull_staged_input_events :: proc( input : ^InputState, staged_events : ^Array(InputEvent) )
{
// TODO(Ed) : Add guards for multi-threading
}

View File

@ -0,0 +1,259 @@
package sectr
InputEventType :: enum u32 {
Key_Pressed,
Key_Released,
Mouse_Pressed,
Mouse_Released,
Mouse_Scroll,
Mouse_Move,
Mouse_Enter,
Mouse_Leave,
Unicode,
}
InputEvent :: struct
{
frame_id : u64,
type : InputEventType,
key : KeyCode,
modifiers : ModifierCodeFlags,
mouse : struct {
btn : MouseBtn,
pos : Vec2,
delta : Vec2,
scroll : Vec2,
},
codepoint : rune,
// num_touches : u32,
// touches : Touchpoint,
_sokol_frame_id : u64,
}
// TODO(Ed): May just use input event exclusively in the future and have pointers for key and mouse event filters
// I'm on the fence about this as I don't want to force
InputKeyEvent :: struct {
frame_id : u64,
type : InputEventType,
key : KeyCode,
modifiers : ModifierCodeFlags,
}
InputMouseEvent :: struct {
frame_id : u64,
type : InputEventType,
btn : MouseBtn,
pos : Vec2,
delta : Vec2,
scroll : Vec2,
modifiers : ModifierCodeFlags,
}
InputEvents :: struct {
events : Queue(InputEvent),
key_events : Queue(InputKeyEvent),
mouse_events : Queue(InputMouseEvent),
codes_pressed : Array(rune),
}
// Note(Ed): There is a staged_input_events : Array(InputEvent), in the state.odin's State struct
append_staged_input_events :: #force_inline proc( event : InputEvent ) {
// TODO(Ed) : Add guards for multi-threading
state := get_state()
append( & state.staged_input_events, event )
}
pull_staged_input_events :: proc( input : ^InputState, input_events : ^InputEvents, staged_events : Array(InputEvent) )
{
// TODO(Ed) : Add guards for multi-threading
staged_events_slice := array_to_slice(staged_events)
push( & input_events.events, staged_events_slice )
using input_events
for event in staged_events_slice
{
switch event.type {
case .Key_Pressed:
push( & key_events, InputKeyEvent {
frame_id = event.frame_id,
type = event.type,
key = event.key,
modifiers = event.modifiers
})
case .Key_Released:
push( & key_events, InputKeyEvent {
frame_id = event.frame_id,
type = event.type,
key = event.key,
modifiers = event.modifiers
})
case .Unicode:
append( & codes_pressed, event.codepoint )
case .Mouse_Pressed:
push( & mouse_events, InputMouseEvent {
frame_id = event.frame_id,
type = event.type,
btn = event.mouse.btn,
pos = event.mouse.pos,
delta = event.mouse.delta,
scroll = event.mouse.scroll,
modifiers = event.modifiers,
})
case .Mouse_Released:
push( & mouse_events, InputMouseEvent {
frame_id = event.frame_id,
type = event.type,
btn = event.mouse.btn,
pos = event.mouse.pos,
delta = event.mouse.delta,
scroll = event.mouse.scroll,
modifiers = event.modifiers,
})
case .Mouse_Scroll:
push( & mouse_events, InputMouseEvent {
frame_id = event.frame_id,
type = event.type,
btn = event.mouse.btn,
pos = event.mouse.pos,
delta = event.mouse.delta,
scroll = event.mouse.scroll,
modifiers = event.modifiers,
})
case .Mouse_Move:
push( & mouse_events, InputMouseEvent {
frame_id = event.frame_id,
type = event.type,
btn = event.mouse.btn,
pos = event.mouse.pos,
delta = event.mouse.delta,
scroll = event.mouse.scroll,
modifiers = event.modifiers,
})
case .Mouse_Enter:
push( & mouse_events, InputMouseEvent {
frame_id = event.frame_id,
type = event.type,
btn = event.mouse.btn,
pos = event.mouse.pos,
delta = event.mouse.delta,
scroll = event.mouse.scroll,
modifiers = event.modifiers,
})
case .Mouse_Leave:
push( & mouse_events, InputMouseEvent {
frame_id = event.frame_id,
type = event.type,
btn = event.mouse.btn,
pos = event.mouse.pos,
delta = event.mouse.delta,
scroll = event.mouse.scroll,
modifiers = event.modifiers,
})
}
}
clear( staged_events )
}
poll_input_events :: proc( input, prev_input : ^InputState, input_events : InputEvents )
{
input.keyboard = {}
input.mouse = {}
input_events := input_events
using input_events
@static prev_frame : u64 = u64_max
last_frame := peek_front( & events).frame_id
// No new events, don't update
if prev_frame != 0 && last_frame == prev_frame do return
Iterate_Key_Events:
{
iter_obj := iterator( key_events ); iter := & iter_obj
for event := next( iter ); event != nil; event = next( iter )
{
if last_frame == event.frame_id do return
key := & input.keyboard.keys[event.key]
prev_key := prev_input.keyboard.keys[event.key]
first_transition := key.half_transitions == 0
#partial switch event.type {
case .Key_Pressed:
key.half_transitions += 1
key.ended_down = true
case .Key_Released:
key.half_transitions += 1
key.ended_down = false
}
frame_transition := first_transition && prev_key.ended_down != key.ended_down ? i32(1) : i32(0)
key.half_transitions += frame_transition
}
}
Iterate_Mouse_Events:
{
iter_obj := iterator( mouse_events ); iter := & iter_obj
for event := next( iter ); event != nil; event = next( iter )
{
if last_frame == event.frame_id do return
process_digital_btn :: proc( btn : ^DigitalBtn, prev_btn : DigitalBtn, ended_down : b32 )
{
first_transition := btn.half_transitions == 0
btn.half_transitions += 1
btn.ended_down = ended_down
frame_transition := first_transition && prev_btn.ended_down != btn.ended_down ? i32(1) : i32(0)
btn.half_transitions += frame_transition
}
#partial switch event.type {
case .Mouse_Pressed:
btn := & input.mouse.btns[event.btn]
prev_btn := prev_input.mouse.btns[event.btn]
process_digital_btn( btn, prev_btn, true )
case .Mouse_Released:
btn := & input.mouse.btns[event.btn]
prev_btn := prev_input.mouse.btns[event.btn]
process_digital_btn( btn, prev_btn, false )
case .Mouse_Scroll:
input.mouse.scroll += event.scroll.x
case .Mouse_Move:
case .Mouse_Enter:
case .Mouse_Leave:
// Handled elsewhere
}
input.mouse.pos = event.pos
input.mouse.delta = event.delta
}
}
prev_frame = last_frame
}

View File

@ -10,7 +10,7 @@ AnalogStick :: struct {
DigitalBtn :: struct {
half_transitions : i32,
ended_down : b32
ended_down : b32,
}
btn_pressed :: proc( btn : DigitalBtn ) -> b32 {
@ -167,11 +167,11 @@ MouseState :: struct {
btns : [16] DigitalBtn,
using individual : struct {
left, middle, right : DigitalBtn,
side, forward, back, extra : DigitalBtn
side, forward, back, extra : DigitalBtn,
}
},
raw_pos, pos, delta : Vec2,
vertical_wheel, horizontal_wheel : AnalogAxis
raw_pos, pos, delta : Vec2,
scroll : [2]AnalogAxis,
}
mouse_world_delta :: #force_inline proc "contextless" () -> Vec2 {
@ -183,10 +183,4 @@ mouse_world_delta :: #force_inline proc "contextless" () -> Vec2 {
InputState :: struct {
keyboard : KeyboardState,
mouse : MouseState,
events : Array(InputEvent),
key_events : Array(InputKeyEvent),
mouse_events : Array(InputMouseEvent),
codes_pressed : Array(rune),
}

View File

@ -7,43 +7,18 @@ import sokol_app "thirdparty:sokol/app"
to_modifiers_code_from_sokol :: proc( sokol_modifiers : u32 ) -> ( modifiers : ModifierCodeFlags )
{
if sokol_modifiers & sokol_app.MODIFIER_SHIFT != 0 {
modifiers |= { .Shift }
}
if sokol_modifiers & sokol_app.MODIFIER_CTRL != 0 {
modifiers |= { .Control }
}
if sokol_modifiers & sokol_app.MODIFIER_ALT != 0 {
modifiers |= { .Alt }
}
if sokol_modifiers & sokol_app.MODIFIER_LMB != 0 {
modifiers |= { .Left_Mouse }
}
if sokol_modifiers & sokol_app.MODIFIER_RMB != 0 {
modifiers |= { .Right_Mouse }
}
if sokol_modifiers & sokol_app.MODIFIER_MMB != 0 {
modifiers |= { .Middle_Mouse }
}
if sokol_modifiers & sokol_app.MODIFIER_LSHIFT != 0 {
modifiers |= { .Left_Shift }
}
if sokol_modifiers & sokol_app.MODIFIER_RSHIFT != 0 {
modifiers |= { .Right_Shift }
}
if sokol_modifiers & sokol_app.MODIFIER_LCTRL != 0 {
modifiers |= { .Left_Control }
}
if sokol_modifiers & sokol_app.MODIFIER_RCTRL != 0 {
modifiers |= { .Right_Control }
}
if sokol_modifiers & sokol_app.MODIFIER_LALT != 0 {
modifiers |= { .Left_Alt }
}
if sokol_modifiers & sokol_app.MODIFIER_RALT != 0 {
modifiers |= { .Right_Alt }
}
if sokol_modifiers & sokol_app.MODIFIER_SHIFT != 0 do modifiers |= { .Shift }
if sokol_modifiers & sokol_app.MODIFIER_CTRL != 0 do modifiers |= { .Control }
if sokol_modifiers & sokol_app.MODIFIER_ALT != 0 do modifiers |= { .Alt }
if sokol_modifiers & sokol_app.MODIFIER_LMB != 0 do modifiers |= { .Left_Mouse }
if sokol_modifiers & sokol_app.MODIFIER_RMB != 0 do modifiers |= { .Right_Mouse }
if sokol_modifiers & sokol_app.MODIFIER_MMB != 0 do modifiers |= { .Middle_Mouse }
if sokol_modifiers & sokol_app.MODIFIER_LSHIFT != 0 do modifiers |= { .Left_Shift }
if sokol_modifiers & sokol_app.MODIFIER_RSHIFT != 0 do modifiers |= { .Right_Shift }
if sokol_modifiers & sokol_app.MODIFIER_LCTRL != 0 do modifiers |= { .Left_Control }
if sokol_modifiers & sokol_app.MODIFIER_RCTRL != 0 do modifiers |= { .Right_Control }
if sokol_modifiers & sokol_app.MODIFIER_LALT != 0 do modifiers |= { .Left_Alt }
if sokol_modifiers & sokol_app.MODIFIER_RALT != 0 do modifiers |= { .Right_Alt }
return
}