Skip to main content

wde_renderer/sync/
sync_entities.rs

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