wde_renderer/sync/
sync_entities.rs

1use bevy::{ecs::entity::EntityEquivalent, prelude::*};
2
3
4/// Component added on the Main world entities that are synced to the Render World in order to keep track of the corresponding render world entity.
5/// It points to the corresponding entity in the render world.
6#[derive(Component, Deref, Copy, Clone, Debug, Eq, Hash, PartialEq, Reflect)]
7#[component(clone_behavior = Ignore)]
8#[reflect(Component, Clone)]
9pub struct RenderEntity(pub(crate) Entity);
10impl RenderEntity {
11    #[inline]
12    pub fn id(&self) -> Entity {
13        self.0
14    }
15}
16impl From<Entity> for RenderEntity {
17    fn from(entity: Entity) -> Self {
18        RenderEntity(entity)
19    }
20}
21impl ContainsEntity for RenderEntity {
22    fn entity(&self) -> Entity {
23        self.id()
24    }
25}
26unsafe impl EntityEquivalent for RenderEntity {}
27
28
29/// Component added on the Render world entities that are synced from the Main World in order to keep track of the corresponding main world entity.
30/// It points to the corresponding entity in the main world.
31#[derive(Component, Deref, Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Reflect)]
32#[reflect(Component, Clone)]
33pub struct MainEntity(pub(crate) Entity);
34impl MainEntity {
35    #[inline]
36    pub fn id(&self) -> Entity {
37        self.0
38    }
39}
40impl From<Entity> for MainEntity {
41    fn from(entity: Entity) -> Self {
42        MainEntity(entity)
43    }
44}
45impl ContainsEntity for MainEntity {
46    fn entity(&self) -> Entity {
47        self.id()
48    }
49}
50unsafe impl EntityEquivalent for MainEntity {}
51
52
53
54/// This module exists to keep the complex unsafe code out of the main module.
55///
56/// The implementations for both [`MainEntity`] and [`RenderEntity`] should stay in sync,
57/// and are based off of the `&T` implementation in `bevy::ecs`.
58mod render_entities_world_query_impls {
59    use super::{MainEntity, RenderEntity};
60
61    use bevy::ecs::{
62        archetype::Archetype,
63        change_detection::Tick,
64        component::{ComponentId, Components},
65        entity::Entity,
66        query::{
67            ArchetypeQueryData, FilteredAccess, QueryData, ReadOnlyQueryData,
68            ReleaseStateQueryData, WorldQuery,
69        },
70        storage::{Table, TableRow},
71        world::{World, unsafe_world_cell::UnsafeWorldCell},
72    };
73
74    // SAFETY: defers completely to `&RenderEntity` implementation,
75    // and then only modifies the output safely.
76    unsafe impl WorldQuery for RenderEntity {
77        type Fetch<'w> = <&'static RenderEntity as WorldQuery>::Fetch<'w>;
78        type State = <&'static RenderEntity as WorldQuery>::State;
79
80        fn shrink_fetch<'wlong: 'wshort, 'wshort>(
81            fetch: Self::Fetch<'wlong>,
82        ) -> Self::Fetch<'wshort> {
83            fetch
84        }
85
86        #[inline]
87        unsafe fn init_fetch<'w>(
88            world: UnsafeWorldCell<'w>,
89            component_id: &ComponentId,
90            last_run: Tick,
91            this_run: Tick,
92        ) -> Self::Fetch<'w> {
93            // SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
94            unsafe {
95                <&RenderEntity as WorldQuery>::init_fetch(world, component_id, last_run, this_run)
96            }
97        }
98
99        const IS_DENSE: bool = <&'static RenderEntity as WorldQuery>::IS_DENSE;
100
101        #[inline]
102        unsafe fn set_archetype<'w>(
103            fetch: &mut Self::Fetch<'w>,
104            component_id: &ComponentId,
105            archetype: &'w Archetype,
106            table: &'w Table,
107        ) {
108            // SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
109            unsafe {
110                <&RenderEntity as WorldQuery>::set_archetype(fetch, component_id, archetype, table);
111            }
112        }
113
114        #[inline]
115        unsafe fn set_table<'w>(
116            fetch: &mut Self::Fetch<'w>,
117            &component_id: &ComponentId,
118            table: &'w Table,
119        ) {
120            // SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
121            unsafe { <&RenderEntity as WorldQuery>::set_table(fetch, &component_id, table) }
122        }
123
124        fn update_component_access(&component_id: &ComponentId, access: &mut FilteredAccess) {
125            <&RenderEntity as WorldQuery>::update_component_access(&component_id, access);
126        }
127
128        fn init_state(world: &mut World) -> ComponentId {
129            <&RenderEntity as WorldQuery>::init_state(world)
130        }
131
132        fn get_state(components: &Components) -> Option<Self::State> {
133            <&RenderEntity as WorldQuery>::get_state(components)
134        }
135
136        fn matches_component_set(
137            &state: &ComponentId,
138            set_contains_id: &impl Fn(ComponentId) -> bool,
139        ) -> bool {
140            <&RenderEntity as WorldQuery>::matches_component_set(&state, set_contains_id)
141        }
142    }
143
144    // SAFETY: Component access of Self::ReadOnly is a subset of Self.
145    // Self::ReadOnly matches exactly the same archetypes/tables as Self.
146    unsafe impl QueryData for RenderEntity {
147        const IS_READ_ONLY: bool = true;
148        const IS_ARCHETYPAL: bool = <&MainEntity as QueryData>::IS_ARCHETYPAL;
149        type ReadOnly = RenderEntity;
150        type Item<'w, 's> = Entity;
151
152        fn shrink<'wlong: 'wshort, 'wshort, 's>(
153            item: Self::Item<'wlong, 's>,
154        ) -> Self::Item<'wshort, 's> {
155            item
156        }
157
158        #[inline(always)]
159        unsafe fn fetch<'w, 's>(
160            state: &'s Self::State,
161            fetch: &mut Self::Fetch<'w>,
162            entity: Entity,
163            table_row: TableRow,
164        ) -> Option<Self::Item<'w, 's>> {
165            // SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
166            let component =
167                unsafe { <&RenderEntity as QueryData>::fetch(state, fetch, entity, table_row) };
168            component.map(RenderEntity::id)
169        }
170
171        fn iter_access(
172            state: &Self::State,
173        ) -> impl Iterator<Item = bevy::ecs::query::EcsAccessType<'_>> {
174            <&RenderEntity as QueryData>::iter_access(state)
175        }
176    }
177
178    // SAFETY: the underlying `Entity` is copied, and no mutable access is provided.
179    unsafe impl ReadOnlyQueryData for RenderEntity {}
180
181    impl ArchetypeQueryData for RenderEntity {}
182
183    impl ReleaseStateQueryData for RenderEntity {
184        fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
185            item
186        }
187    }
188
189    // SAFETY: defers completely to `&RenderEntity` implementation,
190    // and then only modifies the output safely.
191    unsafe impl WorldQuery for MainEntity {
192        type Fetch<'w> = <&'static MainEntity as WorldQuery>::Fetch<'w>;
193        type State = <&'static MainEntity as WorldQuery>::State;
194
195        fn shrink_fetch<'wlong: 'wshort, 'wshort>(
196            fetch: Self::Fetch<'wlong>,
197        ) -> Self::Fetch<'wshort> {
198            fetch
199        }
200
201        #[inline]
202        unsafe fn init_fetch<'w>(
203            world: UnsafeWorldCell<'w>,
204            component_id: &ComponentId,
205            last_run: Tick,
206            this_run: Tick,
207        ) -> Self::Fetch<'w> {
208            // SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
209            unsafe {
210                <&MainEntity as WorldQuery>::init_fetch(world, component_id, last_run, this_run)
211            }
212        }
213
214        const IS_DENSE: bool = <&'static MainEntity as WorldQuery>::IS_DENSE;
215
216        #[inline]
217        unsafe fn set_archetype<'w, 's>(
218            fetch: &mut Self::Fetch<'w>,
219            component_id: &ComponentId,
220            archetype: &'w Archetype,
221            table: &'w Table,
222        ) {
223            // SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
224            unsafe {
225                <&MainEntity as WorldQuery>::set_archetype(fetch, component_id, archetype, table);
226            }
227        }
228
229        #[inline]
230        unsafe fn set_table<'w>(
231            fetch: &mut Self::Fetch<'w>,
232            &component_id: &ComponentId,
233            table: &'w Table,
234        ) {
235            // SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
236            unsafe { <&MainEntity as WorldQuery>::set_table(fetch, &component_id, table) }
237        }
238
239        fn update_component_access(&component_id: &ComponentId, access: &mut FilteredAccess) {
240            <&MainEntity as WorldQuery>::update_component_access(&component_id, access);
241        }
242
243        fn init_state(world: &mut World) -> ComponentId {
244            <&MainEntity as WorldQuery>::init_state(world)
245        }
246
247        fn get_state(components: &Components) -> Option<Self::State> {
248            <&MainEntity as WorldQuery>::get_state(components)
249        }
250
251        fn matches_component_set(
252            &state: &ComponentId,
253            set_contains_id: &impl Fn(ComponentId) -> bool,
254        ) -> bool {
255            <&MainEntity as WorldQuery>::matches_component_set(&state, set_contains_id)
256        }
257    }
258
259    // SAFETY: Component access of Self::ReadOnly is a subset of Self.
260    // Self::ReadOnly matches exactly the same archetypes/tables as Self.
261    unsafe impl QueryData for MainEntity {
262        const IS_READ_ONLY: bool = true;
263        const IS_ARCHETYPAL: bool = <&MainEntity as QueryData>::IS_ARCHETYPAL;
264        type ReadOnly = MainEntity;
265        type Item<'w, 's> = Entity;
266
267        fn shrink<'wlong: 'wshort, 'wshort, 's>(
268            item: Self::Item<'wlong, 's>,
269        ) -> Self::Item<'wshort, 's> {
270            item
271        }
272
273        #[inline(always)]
274        unsafe fn fetch<'w, 's>(
275            state: &'s Self::State,
276            fetch: &mut Self::Fetch<'w>,
277            entity: Entity,
278            table_row: TableRow,
279        ) -> Option<Self::Item<'w, 's>> {
280            // SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
281            let component =
282                unsafe { <&MainEntity as QueryData>::fetch(state, fetch, entity, table_row) };
283            component.map(MainEntity::id)
284        }
285
286        fn iter_access(
287            state: &Self::State,
288        ) -> impl Iterator<Item = bevy::ecs::query::EcsAccessType<'_>> {
289            <&MainEntity as QueryData>::iter_access(state)
290        }
291    }
292
293    // SAFETY: the underlying `Entity` is copied, and no mutable access is provided.
294    unsafe impl ReadOnlyQueryData for MainEntity {}
295
296    impl ArchetypeQueryData for MainEntity {}
297
298    impl ReleaseStateQueryData for MainEntity {
299        fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
300            item
301        }
302    }
303}