From cf3d4f142a31c917aaec2d38c1b581f503293227 Mon Sep 17 00:00:00 2001
From: hodasemi <michaelh.95@t-online.de>
Date: Tue, 11 Mar 2025 18:58:40 +0100
Subject: [PATCH] Start with control scheme

---
 engine/src/scene/content/components/draw.rs   |   9 ++
 .../content/components/free_space_control.rs  |   2 +-
 .../src/scene/content/components/location.rs  |  13 +-
 examples/free_space/src/game.rs               | 118 +++++++++++++++++-
 examples/free_space/src/main.rs               |   4 +-
 5 files changed, 134 insertions(+), 12 deletions(-)

diff --git a/engine/src/scene/content/components/draw.rs b/engine/src/scene/content/components/draw.rs
index 4f3d759..65f3bb8 100644
--- a/engine/src/scene/content/components/draw.rs
+++ b/engine/src/scene/content/components/draw.rs
@@ -1,6 +1,8 @@
 use crate::prelude::*;
 
+use anyhow::Result;
 use asset::AssetMesh;
+use context::prelude::cgmath::Matrix4;
 
 use std::{
     ops::{Index, IndexMut},
@@ -74,6 +76,13 @@ impl Draw {
         self.meshes.iter_mut()
     }
 
+    pub fn set_transform(&self, transform: Matrix4<f32>) -> Result<()> {
+        self.iter().try_for_each(|mesh| {
+            mesh.model_buffer()
+                .fill(&[(transform * mesh.model_matrix()).into()])
+        })
+    }
+
     pub fn len(&self) -> usize {
         self.meshes.len()
     }
diff --git a/engine/src/scene/content/components/free_space_control.rs b/engine/src/scene/content/components/free_space_control.rs
index c084204..8a8a13d 100644
--- a/engine/src/scene/content/components/free_space_control.rs
+++ b/engine/src/scene/content/components/free_space_control.rs
@@ -140,7 +140,7 @@ impl FreeSpaceControl {
         self.add_rotation(rotation_changes);
         self.position += rotated_position_changes;
 
-        Some(Matrix4::from(self.rotation_matrix()) * Matrix4::from_translation(self.position))
+        Some(Matrix4::from_translation(self.position) * Matrix4::from(self.rotation_matrix()))
     }
 
     #[rustfmt::skip]
diff --git a/engine/src/scene/content/components/location.rs b/engine/src/scene/content/components/location.rs
index 1b54a8c..688d914 100644
--- a/engine/src/scene/content/components/location.rs
+++ b/engine/src/scene/content/components/location.rs
@@ -174,8 +174,8 @@ impl Location {
             * Matrix4::from_nonuniform_scale(self.scale.x, self.scale.y, self.scale.z);
     }
 
-    pub fn transformation_matrix(&self) -> &Matrix4<f32> {
-        &self.transformation
+    pub fn transformation_matrix(&self) -> Matrix4<f32> {
+        self.transformation
     }
 
     fn update_apply(&mut self) -> Result<()> {
@@ -208,15 +208,10 @@ impl Location {
 
     pub unsafe fn apply_model_matrices(
         &self,
-        transformation: &Matrix4<f32>,
+        transformation: Matrix4<f32>,
         draw: &Draw,
     ) -> Result<()> {
-        for mesh in draw.iter() {
-            mesh.model_buffer()
-                .fill(&[(transformation * mesh.model_matrix()).into()])?;
-        }
-
-        Ok(())
+        draw.set_transform(transformation)
     }
 }
 
diff --git a/examples/free_space/src/game.rs b/examples/free_space/src/game.rs
index 7437d81..25f7159 100644
--- a/examples/free_space/src/game.rs
+++ b/examples/free_space/src/game.rs
@@ -1,8 +1,88 @@
+use std::collections::HashMap;
+
 use anyhow::Result;
 
 use ecs::*;
 use engine::prelude::*;
 
+#[derive(Clone, Copy, Debug)]
+struct PlayerEntity(Entity);
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+enum Input {
+    Axis(u8),
+    Button(Button),
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+enum Button {
+    One,
+}
+
+#[derive(Clone, Copy, Debug)]
+enum Control {
+    Throttle,
+    StrafeHorizontal,
+    StrafeVertical,
+    Yaw,
+    Pitch,
+    Roll,
+
+    PrimaryWeapon,
+    SecondaryWeapon,
+}
+
+#[derive(Clone, Debug)]
+struct ControllerSettings {
+    mappings: HashMap<(String, Input), Control>,
+}
+
+impl Default for ControllerSettings {
+    fn default() -> Self {
+        Self {
+            mappings: [
+                (
+                    ("Controller 1".to_string(), Input::Axis(0)),
+                    Control::Throttle,
+                ),
+                (
+                    ("Controller 1".to_string(), Input::Axis(1)),
+                    Control::StrafeHorizontal,
+                ),
+                (
+                    ("Controller 1".to_string(), Input::Axis(2)),
+                    Control::StrafeVertical,
+                ),
+                (("Controller 1".to_string(), Input::Axis(3)), Control::Pitch),
+                (
+                    ("Controller 1".to_string(), Input::Button(Button::One)),
+                    Control::PrimaryWeapon,
+                ),
+                (("Controller 2".to_string(), Input::Axis(1)), Control::Yaw),
+                (("Controller 2".to_string(), Input::Axis(0)), Control::Roll),
+                (
+                    ("Controller 2".to_string(), Input::Button(Button::One)),
+                    Control::SecondaryWeapon,
+                ),
+            ]
+            .into_iter()
+            .collect(),
+        }
+    }
+}
+
+impl ControllerSettings {
+    pub fn map_axis(
+        &self,
+        controller_name: impl ToString,
+        axes: ControllerAxis,
+    ) -> Vec<(Control, f32)> {
+        self.mappings
+            .get(&controller_name.to_string())
+            .map(|control| *control)
+    }
+}
+
 pub struct Game;
 
 impl Game {
@@ -11,6 +91,9 @@ impl Game {
     }
 
     pub fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> {
+        let player = world.resources.get::<PlayerEntity>();
+        let fighter_object = world.entity_mut(player.0)?;
+
         match event {
             EngineEvent::MouseButtonDown(MouseButton::Left) => {
                 let camera_control = world.resources.get_mut::<FreeCameraControl>();
@@ -28,6 +111,8 @@ impl Game {
                 camera_control.mouse_move(x, y, scene.view_mut())?;
             }
 
+            EngineEvent::ControllerAxis(controller, axis) => {}
+
             _ => (),
         }
 
@@ -37,7 +122,38 @@ impl Game {
 
 impl Game {
     pub fn setup_updates(world_builder: &mut WorldBuilder) -> Result<()> {
-        world_builder.add_update(name, priority, func, filter)?;
+        world_builder.add_update(
+            "player_rotation",
+            200,
+            Self::player_orientation,
+            EmptyFilter,
+        )?;
+
+        Ok(())
+    }
+
+    pub fn setup_scene(world: &mut World) -> Result<()> {
+        let mut fighter = AssetHandler::create(world).create_entity("fighter")?;
+        fighter.insert_component(FreeSpaceControl::new(FreeSpaceControlSettings::default()));
+
+        let player = PlayerEntity(world.add_entity(fighter)?);
+        world.resources.insert(player);
+
+        world.commit_entity_changes()
+    }
+}
+
+// updates
+impl Game {
+    fn player_orientation(
+        world: &mut World,
+        _entity: Entity,
+        draw: &mut Draw,
+        control: &mut FreeSpaceControl,
+    ) -> Result<()> {
+        if let Some(transform) = control.update(world.now()) {
+            draw.set_transform(transform)?;
+        }
 
         Ok(())
     }
diff --git a/examples/free_space/src/main.rs b/examples/free_space/src/main.rs
index ed1fe8c..76ee6a7 100644
--- a/examples/free_space/src/main.rs
+++ b/examples/free_space/src/main.rs
@@ -39,6 +39,8 @@ fn main() -> Result<()> {
     world_builder.resources.insert(camera_control);
 
     Game::setup_updates(&mut world_builder)?;
+    let mut world = world_builder.build();
+    Game::setup_scene(&mut world)?;
 
-    world_builder.build().run()
+    world.run()
 }