khora_lanes/physics_lane/
physics_debug_lane.rs

1// Copyright 2025 eraflo
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use khora_core::physics::PhysicsProvider;
16use khora_data::ecs::{PhysicsDebugData, World};
17
18/// A lane dedicated to extracting debug information from the physics engine.
19#[derive(Debug, Default)]
20pub struct PhysicsDebugLane;
21
22impl PhysicsDebugLane {
23    /// Creates a new `PhysicsDebugLane`.
24    pub fn new() -> Self {
25        Self
26    }
27}
28
29impl khora_core::lane::Lane for PhysicsDebugLane {
30    fn strategy_name(&self) -> &'static str {
31        "PhysicsDebug"
32    }
33
34    fn lane_kind(&self) -> khora_core::lane::LaneKind {
35        khora_core::lane::LaneKind::Physics
36    }
37
38    fn execute(
39        &self,
40        ctx: &mut khora_core::lane::LaneContext,
41    ) -> Result<(), khora_core::lane::LaneError> {
42        use khora_core::lane::{LaneError, Slot};
43
44        let dt = ctx
45            .get::<khora_core::lane::PhysicsDeltaTime>()
46            .ok_or(LaneError::missing("PhysicsDeltaTime"))?
47            .0;
48        let world = ctx
49            .get::<Slot<World>>()
50            .ok_or(LaneError::missing("Slot<World>"))?
51            .get();
52        let provider = ctx
53            .get::<Slot<dyn PhysicsProvider>>()
54            .ok_or(LaneError::missing("Slot<dyn PhysicsProvider>"))?
55            .get();
56
57        self.step(world, provider, dt);
58        Ok(())
59    }
60
61    fn as_any(&self) -> &dyn std::any::Any {
62        self
63    }
64
65    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
66        self
67    }
68}
69
70impl PhysicsDebugLane {
71    /// Updates physics debug render data by querying the provider.
72    pub fn step(&self, world: &mut World, provider: &mut dyn PhysicsProvider, _dt: f32) {
73        // We look for a PhysicsDebugData component in the world.
74        // It's expected to be a singleton or attached to a specific debug entity.
75        let query = world.query_mut::<&mut PhysicsDebugData>();
76        for debug_data in query {
77            if debug_data.enabled {
78                let (vertices, indices) = provider.get_debug_render_data();
79                debug_data.vertices = vertices;
80                debug_data.indices = indices;
81            } else {
82                debug_data.vertices.clear();
83                debug_data.indices.clear();
84            }
85        }
86    }
87}