///|
pub(all) enum Key {
Backspace
Delete
Enter
Escape
Tab
Space
ArrowLeft
ArrowRight
ArrowUp
ArrowDown
Home
End
PageUp
PageDown
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
Num0
Num1
Num2
Num3
Num4
Num5
Num6
Num7
Num8
Num9
} derive(Eq, Debug, Hash)
///|
pub struct Modifiers {
ctrl : Bool
shift : Bool
alt : Bool
meta : Bool
} derive(Eq, Debug, Default)
///|
pub fn Modifiers::none() -> Modifiers {
{ ctrl: false, shift: false, alt: false, meta: false, }
}
///|
pub fn Modifiers::ctrl() -> Modifiers {
{ ctrl: true, shift: false, alt: false, meta: false, }
}
///|
pub fn Modifiers::shift() -> Modifiers {
{ ctrl: false, shift: true, alt: false, meta: false, }
}
///|
pub fn Modifiers::new(
ctrl : Bool,
shift : Bool,
alt : Bool,
meta : Bool,
) -> Modifiers {
{ ctrl, shift, alt, meta, }
}
///|
pub(all) enum Event {
Key(Key, Bool, Modifiers)
TextInput(String)
PointerWheel(@math.Vec2)
} derive(Eq, Debug)
///|
pub struct RawInput {
mouse_pos : @math.Vec2
mouse_down : Bool
scroll_delta : @math.Vec2
dt : Double
events : Array[Event]
text_input : String
modifiers : Modifiers
mouse_secondary_down : Bool
} derive(Eq, Debug)
///|
pub fn RawInput::new() -> RawInput {
{
mouse_pos: @math.Vec2::zero(),
mouse_down: false,
scroll_delta: @math.Vec2::zero(),
dt: 0.0166,
events: [],
text_input: "",
modifiers: Modifiers::none(),
mouse_secondary_down: false,
}
}
///|
pub fn RawInput::from_mouse(
mouse_pos : @math.Vec2,
mouse_down : Bool,
mouse_secondary_down? : Bool = false,
dt? : Double = 0.0166,
) -> RawInput {
{
mouse_pos,
mouse_down,
scroll_delta: @math.Vec2::zero(),
dt,
events: [],
text_input: "",
modifiers: Modifiers::none(),
mouse_secondary_down,
}
}
///|
/// Full constructor for host drivers: pointer state plus the input events
/// collected during the frame. `Key` and `Event` are `pub(all)`, so a host
/// builds the events and passes them in; `text_input` carries the plain text
/// typed this frame and may be left empty when text arrives as events instead.
pub fn RawInput::with_events(
mouse_pos : @math.Vec2,
mouse_down : Bool,
scroll_delta : @math.Vec2,
events : Array[Event],
text_input : String,
modifiers : Modifiers,
mouse_secondary_down? : Bool = false,
dt? : Double = 0.0166,
) -> RawInput {
{
mouse_pos,
mouse_down,
scroll_delta,
dt,
events,
text_input,
modifiers,
mouse_secondary_down,
}
}
///|
pub struct InputState {
mut mouse_pos : @math.Vec2
mut mouse_prev_pos : @math.Vec2
mut mouse_delta : @math.Vec2
mut mouse_initialized : Bool
mut mouse_down : Bool
mut mouse_pressed : Bool
mut mouse_released : Bool
mut mouse_secondary_down : Bool
mut mouse_secondary_pressed : Bool
mut mouse_secondary_released : Bool
mut scroll_delta : @math.Vec2
mut dt : Double
keys_down : Array[Key]
keys_pressed : Array[Key]
keys_released : Array[Key]
consumed_keys : Array[Key]
mut text_input : String
mut modifiers : Modifiers
events : Array[Event]
} derive(Eq, Debug, Default)
///|
pub fn InputState::new() -> InputState {
{
mouse_pos: @math.Vec2::zero(),
mouse_prev_pos: @math.Vec2::zero(),
mouse_delta: @math.Vec2::zero(),
mouse_initialized: false,
mouse_down: false,
mouse_pressed: false,
mouse_released: false,
mouse_secondary_down: false,
mouse_secondary_pressed: false,
mouse_secondary_released: false,
scroll_delta: @math.Vec2::zero(),
dt: 0.0166,
keys_down: [],
keys_pressed: [],
keys_released: [],
consumed_keys: [],
text_input: "",
modifiers: Modifiers::none(),
events: [],
}
}
///|
pub fn InputState::update(self : InputState, raw : RawInput) -> Unit {
if !self.mouse_initialized {
self.mouse_prev_pos = raw.mouse_pos
self.mouse_pos = raw.mouse_pos
self.mouse_delta = @math.Vec2::zero()
self.mouse_initialized = true
} else {
self.mouse_prev_pos = self.mouse_pos
self.mouse_pos = raw.mouse_pos
self.mouse_delta = self.mouse_pos.sub(self.mouse_prev_pos)
}
let was_down = self.mouse_down
self.mouse_down = raw.mouse_down
self.mouse_pressed = raw.mouse_down && !was_down
self.mouse_released = !raw.mouse_down && was_down
let was_sec_down = self.mouse_secondary_down
self.mouse_secondary_down = raw.mouse_secondary_down
self.mouse_secondary_pressed = raw.mouse_secondary_down && !was_sec_down
self.mouse_secondary_released = !raw.mouse_secondary_down && was_sec_down
self.scroll_delta = raw.scroll_delta
self.dt = raw.dt
self.keys_pressed.clear()
self.keys_released.clear()
self.consumed_keys.clear()
self.text_input = ""
self.modifiers = raw.modifiers
self.events.clear()
let mut has_event_text = false
for ev in raw.events {
self.events.push(ev)
match ev {
Key(k, is_pressed, _mods) =>
if is_pressed {
if !self.keys_down.contains(k) {
self.keys_down.push(k)
}
self.keys_pressed.push(k)
} else {
// Remove from keys_down
let mut found_idx = -1
for i = 0; i < self.keys_down.length(); i = i + 1 {
if self.keys_down[i] == k {
found_idx = i
break
}
}
if found_idx >= 0 {
let _ = self.keys_down.remove(found_idx)
}
self.keys_released.push(k)
}
TextInput(s) => {
has_event_text = true
self.text_input = self.text_input + s
}
PointerWheel(delta) => self.scroll_delta = self.scroll_delta.add(delta)
}
}
// Fallback to raw.text_input only if no TextInput events were processed
if !has_event_text && !raw.text_input.is_empty() {
self.text_input = raw.text_input
}
}
///|
pub fn InputState::mouse_pos(self : InputState) -> @math.Vec2 {
self.mouse_pos
}
///|
pub fn InputState::mouse_down(self : InputState) -> Bool {
self.mouse_down
}
///|
pub fn InputState::mouse_pressed(self : InputState) -> Bool {
self.mouse_pressed
}
///|
pub fn InputState::mouse_released(self : InputState) -> Bool {
self.mouse_released
}
///|
pub fn InputState::mouse_secondary_down(self : InputState) -> Bool {
self.mouse_secondary_down
}
///|
pub fn InputState::mouse_secondary_pressed(self : InputState) -> Bool {
self.mouse_secondary_pressed
}
///|
pub fn InputState::mouse_secondary_released(self : InputState) -> Bool {
self.mouse_secondary_released
}
///|
pub fn InputState::consume_key(self : InputState, key : Key) -> Unit {
if !self.consumed_keys.contains(key) {
self.consumed_keys.push(key)
}
}
///|
pub fn InputState::is_key_consumed(self : InputState, key : Key) -> Bool {
self.consumed_keys.contains(key)
}
///|
pub fn InputState::mouse_delta(self : InputState) -> @math.Vec2 {
self.mouse_delta
}
///|
pub fn InputState::scroll_delta(self : InputState) -> @math.Vec2 {
self.scroll_delta
}
///|
pub fn InputState::dt(self : InputState) -> Double {
self.dt
}
///|
pub fn InputState::key_down(self : InputState, key : Key) -> Bool {
self.keys_down.contains(key)
}
///|
pub fn InputState::key_pressed(self : InputState, key : Key) -> Bool {
self.keys_pressed.contains(key)
}
///|
pub fn InputState::key_released(self : InputState, key : Key) -> Bool {
self.keys_released.contains(key)
}
///|
pub fn InputState::text_input(self : InputState) -> String {
self.text_input
}
///|
pub fn InputState::modifiers(self : InputState) -> Modifiers {
self.modifiers
}
///|
pub fn InputState::events(self : InputState) -> Array[Event] {
self.events
}