Import Oxide engine (Stages 0–10) under MIT license

Full project snapshot migrated to new Gitea remote without history:
engine, editor, physics, script, examples, tests, docs, and assets.
Relicensed from GPLv3 to MIT and updated repo URLs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Homer Simpson
2026-07-05 20:41:02 +02:00
parent 2afb56b329
commit 9eead719b0
157 changed files with 47270 additions and 2 deletions
+147
View File
@@ -0,0 +1,147 @@
//! [`Binding`] — one physical input that can drive a named action.
//!
//! A binding is the smallest unit an [`ActionMap`](super::ActionMap) maps
//! action names to. The enum is intentionally small (keys and mouse buttons
//! today; gamepad / pointer-axis variants will be added without breaking
//! existing serialized maps as long as new variants are appended).
use serde::{Deserialize, Serialize};
use winit::event::MouseButton;
use winit::keyboard::KeyCode;
use super::InputState;
/// One physical input that can be bound to a named action.
///
/// Two bindings compare equal only if they refer to the exact same physical
/// input — the enum derives `Hash`/`Eq` so a `HashSet<Binding>` can be used
/// to deduplicate a key's contribution to multiple actions without
/// allocating per-action sets.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Binding {
/// A keyboard key, identified by layout-independent physical position
/// (the same `KeyCode` an [`InputState`] query takes).
Key(KeyCode),
/// A mouse button.
Mouse(MouseButton),
}
impl Binding {
/// `true` if this binding's `pressed` edge fired in `input` this frame.
pub fn pressed(&self, input: &InputState) -> bool {
match *self {
Binding::Key(k) => input.pressed(k),
Binding::Mouse(b) => input.mouse_pressed(b),
}
}
/// `true` if this binding's `released` edge fired in `input` this frame.
pub fn released(&self, input: &InputState) -> bool {
match *self {
Binding::Key(k) => input.released(k),
Binding::Mouse(b) => input.mouse_released(b),
}
}
/// `true` if this binding is currently held down in `input`.
pub fn held(&self, input: &InputState) -> bool {
match *self {
Binding::Key(k) => input.held(k),
Binding::Mouse(b) => input.mouse_held(b),
}
}
/// `true` if this binding was held *going into* this frame — i.e. it was
/// held continuously from before the current frame's events arrived.
/// Used by [`ActionMap`](super::ActionMap) to recover prior-frame state
/// from the current frame's snapshot alone, without storing a previous
/// `InputState`.
///
/// Derivation: a binding was held before the frame iff it is currently
/// held or was released this frame (either way it was down going in),
/// **except** when it was also pressed this frame — a same-frame tap
/// goes idle → pressed → released, so it was not held going in.
pub(crate) fn held_before_frame(&self, input: &InputState) -> bool {
(self.held(input) || self.released(input)) && !self.pressed(input)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn key_binding_routes_to_keyboard_queries() {
let mut input = InputState::new();
let b = Binding::Key(KeyCode::Space);
input.press_key(KeyCode::Space);
assert!(b.pressed(&input));
assert!(b.held(&input));
assert!(!b.released(&input));
input.end_frame();
assert!(!b.pressed(&input));
assert!(b.held(&input));
input.release_key(KeyCode::Space);
assert!(b.released(&input));
assert!(!b.held(&input));
}
#[test]
fn mouse_binding_routes_to_mouse_queries() {
let mut input = InputState::new();
let b = Binding::Mouse(MouseButton::Right);
input.press_mouse(MouseButton::Right);
assert!(b.pressed(&input));
assert!(b.held(&input));
input.end_frame();
input.release_mouse(MouseButton::Right);
assert!(b.released(&input));
assert!(!b.held(&input));
}
#[test]
fn held_before_frame_distinguishes_press_release_tap() {
let b = Binding::Key(KeyCode::KeyJ);
// Idle → pressed this frame. Not held before.
let mut input = InputState::new();
input.press_key(KeyCode::KeyJ);
assert!(!b.held_before_frame(&input));
// Held continuously. Held before.
let mut input = InputState::new();
input.press_key(KeyCode::KeyJ);
input.end_frame();
assert!(b.held_before_frame(&input));
// Held → released this frame. Held before.
let mut input = InputState::new();
input.press_key(KeyCode::KeyJ);
input.end_frame();
input.release_key(KeyCode::KeyJ);
assert!(b.held_before_frame(&input));
// Same-frame tap (idle → pressed → released). Not held before.
let mut input = InputState::new();
input.press_key(KeyCode::KeyJ);
input.release_key(KeyCode::KeyJ);
assert!(!b.held_before_frame(&input));
}
#[test]
fn ron_round_trip_preserves_key_and_mouse_variants() {
let bindings = vec![
Binding::Key(KeyCode::Space),
Binding::Mouse(MouseButton::Left),
Binding::Key(KeyCode::ShiftLeft),
];
let s = ron::to_string(&bindings).unwrap();
let parsed: Vec<Binding> = ron::from_str(&s).unwrap();
assert_eq!(parsed, bindings);
}
}