bevy_tnua/ghost_overrides.rs
1use bevy::prelude::*;
2use bevy_tnua_physics_integration_layer::data_for_backends::TnuaProximitySensorOutput;
3
4use crate::sensor_sets::TnuaSensors;
5use crate::{TnuaBasis, TnuaScheme};
6
7/// A struct with fields of [`TnuaGhostOverwrite`] for each sensor that can have a ghost sensor.
8pub trait TnuaGhostOverwritesForBasis: 'static + Send + Sync + Default {
9 /// A struct that points to the sensor entities. Must match the entities of [the basis'
10 /// sensors](TnuaBasis::Sensors).
11 type Entities: 'static + Send + Sync + Default;
12}
13
14/// Add this component to an entity with a [`TnuaController`](crate::TnuaController) (that has the
15/// same control scheme) to generate ghost sensors and to control them.
16///
17/// This component holds and refers to a struct defined by the
18/// [`GhostOverwrites`](TnuaSensors::GhostOverwrites) of the [`Sensors`](TnuaBasis::Sensors) of the
19/// control scheme's basis. The fields of that struct should be of type [`TnuaGhostOverwrite`], and
20/// should have matching fields in the sensors' [`Entities`](TnuaSensors::Entities) (accessible via
21/// the [`TnuaSensorsEntities`](crate::TnuaSensorsEntities) component) that point to entities with
22/// a [`TnuaGhostSensor`](crate::TnuaGhostSensor) component on them that holds the ghost hits that
23/// can be set in the [`TnuaGhostOverwrite`] using its
24/// [`set`](TnuaGhostOverwrite::set) method.
25#[derive(Component, Deref, DerefMut)]
26#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
27pub struct TnuaGhostOverwrites<S: TnuaScheme>(pub <<<S as TnuaScheme>::Basis as TnuaBasis>::Sensors<'static> as TnuaSensors<'static>>::GhostOverwrites);
28
29impl<S: TnuaScheme> AsMut<
30<<<S as TnuaScheme>::Basis as TnuaBasis>::Sensors<'static> as TnuaSensors<'static>>::GhostOverwrites
31> for TnuaGhostOverwrites<S> {
32 fn as_mut(&mut self) -> &mut <<<S as TnuaScheme>::Basis as TnuaBasis>::Sensors<'static> as TnuaSensors<'static>>::GhostOverwrites {
33 &mut self.0
34 }
35}
36
37impl<S: TnuaScheme> Default for TnuaGhostOverwrites<S> {
38 fn default() -> Self {
39 Self(Default::default())
40 }
41}
42
43/// Controls how Tnua uses the ghost sensor of a single
44/// [`TnuaProximitySensor`](crate::TnuaProximitySensor).
45///
46/// Note that this is not a component because it is not stored on the sensor entity - instead it is
47/// stored with the entity that has the [`TnuaController`](crate::TnuaController) component, inside
48/// a [`TnuaGhostOverwrites`] component. The [`TnuaGhostSensor`](crate::TnuaGhostSensor) itself is
49/// stored on the sensor entity - to retrieve that [`Entity`] use the
50/// [`TnuaSensorsEntities`](crate::TnuaSensorsEntities) component.
51#[derive(Default)]
52#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
53pub struct TnuaGhostOverwrite(Option<Entity>);
54
55impl TnuaGhostOverwrite {
56 /// Set an output of the ghost sensor so that the controller will use it instead of the
57 /// (non-ghost) output of the proximity sensor.
58 ///
59 /// Note that the controller does not use that output has is - it picks an output from the
60 /// ghost sensor that matches the output provided here. This is important because the ghost
61 /// sensor will have its list of outputs refreshed before this happens.
62 ///
63 /// If set to `None`, the ghost sensor will not be used that frame and the output of the
64 /// regular proximity sensor will be used.
65 ///
66 /// The ghost overwrite will remain in place until one of the following happens:
67 /// 1. This method is invoked again - either with another output or with `None`.
68 /// 2. The ghost sensor no longer has a matching hit in its outputs list.
69 pub fn set(&mut self, sensor_output: Option<&TnuaProximitySensorOutput>) {
70 self.0 = sensor_output.map(|output| output.entity);
71 }
72
73 pub(crate) fn find_in<'a>(
74 &self,
75 ghost_outputs: &'a [TnuaProximitySensorOutput],
76 ) -> Option<&'a TnuaProximitySensorOutput> {
77 let entity = self.0?;
78 ghost_outputs.iter().find(|output| output.entity == entity)
79 }
80}