dreamwell-engine 1.0.0

Dreamwell pure-logic engine library — transforms, hierarchy, canon pipeline, spatial math, hashing, tile rules, validation, waymark schema, material/lighting descriptors. No SpacetimeDB dependency.
Documentation
// InputAction — platform-independent game actions.
// Decouples "what the player wants to do" from "which key they pressed".

/// A game action produced by the input system. Platform-agnostic.
/// Consumed by game logic (movement, combat, UI) without knowing the source device.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum InputAction {
    // Movement
    MoveForward,
    MoveBackward,
    MoveLeft,
    MoveRight,
    MoveUp,
    MoveDown,
    Sprint,
    Crouch,
    Jump,

    // Camera
    CameraRotate,
    CameraPan,
    CameraZoomIn,
    CameraZoomOut,
    CameraReset,

    // Interaction
    PrimaryAction,
    SecondaryAction,
    Interact,
    Cancel,
    Confirm,

    // UI
    OpenInventory,
    OpenMap,
    OpenChat,
    OpenMenu,
    ToggleFullscreen,
    QuickSlot(u8),

    // Combat
    Attack,
    Block,
    Dodge,
    UseAbility(u8),

    // System
    Pause,
    Screenshot,
}

/// Input mode determines which bindings and camera behavior are active.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum InputMode {
    /// 2D tile-based: WASD moves on grid, scroll zooms, no rotation.
    #[default]
    TileMap,
    /// 3D free camera: WASD moves in camera-relative direction, mouse rotates.
    FreeCamera,
    /// UI focus: keyboard goes to text fields/menus, movement suppressed.
    UiFocus,
    /// Cinematic: input suppressed, camera follows scripted path.
    Cinematic,
}

impl InputMode {
    /// Whether WASD movement keys should produce movement actions.
    pub fn movement_enabled(&self) -> bool {
        matches!(self, Self::TileMap | Self::FreeCamera)
    }

    /// Whether mouse/stick rotation should produce camera rotation.
    pub fn camera_rotation_enabled(&self) -> bool {
        matches!(self, Self::FreeCamera)
    }

    /// Whether keyboard input should be routed to UI text fields.
    pub fn ui_capture(&self) -> bool {
        matches!(self, Self::UiFocus)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn input_mode_defaults_to_tilemap() {
        assert_eq!(InputMode::default(), InputMode::TileMap);
    }

    #[test]
    fn movement_enabled_modes() {
        assert!(InputMode::TileMap.movement_enabled());
        assert!(InputMode::FreeCamera.movement_enabled());
        assert!(!InputMode::UiFocus.movement_enabled());
        assert!(!InputMode::Cinematic.movement_enabled());
    }

    #[test]
    fn camera_rotation_only_free_camera() {
        assert!(!InputMode::TileMap.camera_rotation_enabled());
        assert!(InputMode::FreeCamera.camera_rotation_enabled());
        assert!(!InputMode::UiFocus.camera_rotation_enabled());
    }

    #[test]
    fn ui_capture_only_ui_focus() {
        assert!(!InputMode::TileMap.ui_capture());
        assert!(!InputMode::FreeCamera.ui_capture());
        assert!(InputMode::UiFocus.ui_capture());
        assert!(!InputMode::Cinematic.ui_capture());
    }

    #[test]
    fn input_action_quick_slot() {
        let a = InputAction::QuickSlot(0);
        let b = InputAction::QuickSlot(1);
        assert_ne!(a, b);
    }

    #[test]
    fn input_action_use_ability() {
        let a = InputAction::UseAbility(0);
        let b = InputAction::UseAbility(3);
        assert_ne!(a, b);
    }
}