rapier_testbed3d/testbed/
graphics_context.rs

1//! Graphics context for a frame.
2
3use kiss3d::color::Color;
4use kiss3d::window::Window;
5use rapier::dynamics::RigidBodyHandle;
6use rapier::dynamics::RigidBodySet;
7use rapier::geometry::{ColliderHandle, ColliderSet};
8
9use crate::Camera;
10use crate::graphics::GraphicsManager;
11use crate::mouse::SceneMouse;
12use crate::settings::ExampleSettings;
13
14use super::keys::KeysState;
15
16/// Context for graphics operations during a frame
17pub struct TestbedGraphics<'a> {
18    pub graphics: &'a mut GraphicsManager,
19    pub window: &'a mut Window,
20    pub camera: &'a mut Camera,
21    pub mouse: &'a SceneMouse,
22    pub keys: &'a KeysState,
23    pub settings: Option<&'a mut ExampleSettings>,
24}
25
26impl<'a> TestbedGraphics<'a> {
27    pub fn set_body_color(&mut self, body: RigidBodyHandle, color: Color, tmp_color: bool) {
28        self.graphics.set_body_color(body, color, tmp_color);
29    }
30
31    pub fn add_body(
32        &mut self,
33        handle: RigidBodyHandle,
34        bodies: &RigidBodySet,
35        colliders: &ColliderSet,
36    ) {
37        self.graphics
38            .add_body_colliders(self.window, handle, bodies, colliders);
39    }
40
41    pub fn remove_body(&mut self, handle: RigidBodyHandle) {
42        self.graphics.remove_body_nodes(handle);
43    }
44
45    pub fn add_collider(&mut self, handle: ColliderHandle, colliders: &ColliderSet) {
46        self.graphics.add_collider(self.window, handle, colliders);
47    }
48
49    pub fn remove_collider(&mut self, handle: ColliderHandle) {
50        self.graphics.remove_collider_nodes(handle);
51    }
52
53    pub fn keys(&self) -> &KeysState {
54        self.keys
55    }
56
57    pub fn mouse(&self) -> &SceneMouse {
58        self.mouse
59    }
60
61    /// Update collider graphics after shape modification
62    pub fn update_collider(&mut self, handle: ColliderHandle, colliders: &ColliderSet) {
63        // Remove and re-add the collider to update its graphics
64        self.graphics.remove_collider_nodes(handle);
65        self.graphics.add_collider(self.window, handle, colliders);
66    }
67
68    /// Get the camera rotation as a unit quaternion (3D only)
69    #[cfg(feature = "dim3")]
70    pub fn camera_rotation(&self) -> na::UnitQuaternion<f32> {
71        // Calculate rotation from orbit camera angles
72        let rot_x = na::UnitQuaternion::from_axis_angle(&na::Vector3::y_axis(), self.camera.at().x);
73        let rot_y =
74            na::UnitQuaternion::from_axis_angle(&(-na::Vector3::x_axis()), self.camera.at().y);
75        rot_x * rot_y
76    }
77
78    /// Get the camera forward direction (3D only)
79    #[cfg(feature = "dim3")]
80    pub fn camera_fwd_dir(&self) -> na::Vector3<f32> {
81        let rot = self.camera_rotation();
82        rot * na::Vector3::z()
83    }
84
85    /// Get mutable access to the egui context for custom UI
86    pub fn egui_context(&self) -> &egui::Context {
87        self.window.egui_context()
88    }
89
90    /// Get mutable access to the egui context for custom UI
91    pub fn egui_context_mut(&mut self) -> &mut egui::Context {
92        self.window.egui_context_mut()
93    }
94}