Skip to content

Commit e98a305

Browse files
committed
Adding SelectView/SelectViewMut/SelectBorrow and adding support for them in World view/view_mut/borrow functions
1 parent f8bd951 commit e98a305

7 files changed

Lines changed: 373 additions & 33 deletions

File tree

CHANGELOG

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
## [Unreleased]
2-
- Split `View` into `View` and `ViewMut`. Note that creating a `View` still requires mutable access to the
3-
archetype/world, but can be useful for passing around read-only access to a given entity.
4-
- The `iter`/`iter_mut` functions on archetypes now return a `View`/`ViewMut` with named component fields rather than
5-
anonymous tuples, making element access less sensitive to component order changes. This also makes iteration more
6-
compatible with the `ArchetypeHas` trait, as that can be used to generically access components from views.
2+
- Split `View` into `View` and `ViewMut`. Note that creating a `View` still requires mutable access to the archetype/world, but can be useful for passing around read-only access to a given entity.
3+
- The `iter`/`iter_mut` functions on archetypes now return a `View`/`ViewMut` with named component fields rather than anonymous tuples, making element access less sensitive to component order changes. This also makes iteration more compatible with the `ArchetypeHas` trait, as that can be used to generically access components from views.
4+
- Adding `SelectView`, `SelectViewMut`, and `SelectBorrow` for resolving views/borrows from `EntityAny` and `EntityDirectAny`. Also adding support for `EntityAny` and `EntityDirectAny` to `World::view`, `World::view_mut`, and `World::borrow`. This has a breaking change to generics using `WorldHas<A>` to access views -- the `World::view` function no longer takes an archetype as a generic argument. In generics, instead of using `World::view::<A>(entity)`, use `World::archetype[_mut]::<A>().view(entity)`. The same applies to `view_mut` and `borrow` calls.

macros/src/data.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ pub struct DataArchetype {
3535
pub struct DataComponent {
3636
pub id: u8,
3737
pub name: DataComponentName,
38+
3839
#[speedy(skip)]
39-
pub default: Option<Expr>, // Used in world generation only
40+
pub _default: Option<Expr>, // Preparation for future support for feature(default_field_values)
41+
// Not serialized due to being used in world generation only
4042
}
4143

4244
#[derive(Debug, Readable, Writable)]
@@ -91,7 +93,7 @@ impl DataWorld {
9193
components.push(DataComponent {
9294
id: last_component_id.expect("internal error"),
9395
name: DataComponentName::new(&component.name),
94-
default: component.default.clone(),
96+
_default: component.default.clone(),
9597
});
9698
}
9799

macros/src/generate/world.rs

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,21 @@ pub fn generate_world(world_data: &DataWorld, raw_input: &str) -> TokenStream {
3737
.iter()
3838
.map(|archetype| format_ident!("{}Direct", archetype.name))
3939
.collect::<Vec<_>>();
40+
let ArchetypeView = world_data
41+
.archetypes
42+
.iter()
43+
.map(|archetype| format_ident!("{}View", archetype.name))
44+
.collect::<Vec<_>>();
45+
let ArchetypeViewMut = world_data
46+
.archetypes
47+
.iter()
48+
.map(|archetype| format_ident!("{}ViewMut", archetype.name))
49+
.collect::<Vec<_>>();
50+
let ArchetypeBorrow = world_data
51+
.archetypes
52+
.iter()
53+
.map(|archetype| format_ident!("{}Borrow", archetype.name))
54+
.collect::<Vec<_>>();
4055

4156
// Variables and fields
4257
let archetype = world_data
@@ -93,6 +108,9 @@ pub fn generate_world(world_data: &DataWorld, raw_input: &str) -> TokenStream {
93108
SelectArchetype,
94109
SelectEntity,
95110
SelectEntityDirect,
111+
SelectView,
112+
SelectViewMut,
113+
SelectBorrow,
96114

97115
#(
98116
#Archetype,
@@ -246,6 +264,21 @@ pub fn generate_world(world_data: &DataWorld, raw_input: &str) -> TokenStream {
246264
#( #Archetype(EntityDirect<#Archetype>), )*
247265
}
248266

267+
/// See `SelectView` in the `gecs` docs for more information.
268+
pub enum SelectView<'a> {
269+
#( #Archetype(#ArchetypeView<'a>), )*
270+
}
271+
272+
/// See `SelectViewMut` in the `gecs` docs for more information.
273+
pub enum SelectViewMut<'a> {
274+
#( #Archetype(#ArchetypeViewMut<'a>), )*
275+
}
276+
277+
/// See `SelectBorrow` in the `gecs` docs for more information.
278+
pub enum SelectBorrow<'a> {
279+
#( #Archetype(#ArchetypeBorrow<'a>), )*
280+
}
281+
249282
// Combined dispatch table for resolving both entity key types.
250283
/// Used internally by world queries. Not for general use.
251284
#[doc(hidden)]
@@ -305,6 +338,27 @@ pub fn generate_world(world_data: &DataWorld, raw_input: &str) -> TokenStream {
305338
}
306339
}
307340

341+
impl<'a> From<#ArchetypeView<'a>> for SelectView<'a> {
342+
#[inline(always)]
343+
fn from(view: #ArchetypeView<'a>) -> Self {
344+
SelectView::#Archetype(view)
345+
}
346+
}
347+
348+
impl<'a> From<#ArchetypeViewMut<'a>> for SelectViewMut<'a> {
349+
#[inline(always)]
350+
fn from(view: #ArchetypeViewMut<'a>) -> Self {
351+
SelectViewMut::#Archetype(view)
352+
}
353+
}
354+
355+
impl<'a> From<#ArchetypeBorrow<'a>> for SelectBorrow<'a> {
356+
#[inline(always)]
357+
fn from(view: #ArchetypeBorrow<'a>) -> Self {
358+
SelectBorrow::#Archetype(view)
359+
}
360+
}
361+
308362
impl From<EntityDirect<#Archetype>> for #__WorldSelectTotal {
309363
#[inline(always)]
310364
fn from(entity: EntityDirect<#Archetype>) -> Self {
@@ -464,6 +518,39 @@ pub fn generate_world(world_data: &DataWorld, raw_input: &str) -> TokenStream {
464518
}
465519
}
466520

521+
impl<'a> From<SelectView<'a>> for SelectArchetype {
522+
#[inline(always)]
523+
fn from(view: SelectView<'a>) -> Self {
524+
match view {
525+
#(
526+
SelectView::#Archetype(_) => SelectArchetype::#Archetype,
527+
)*
528+
}
529+
}
530+
}
531+
532+
impl<'a> From<SelectViewMut<'a>> for SelectArchetype {
533+
#[inline(always)]
534+
fn from(view: SelectViewMut<'a>) -> Self {
535+
match view {
536+
#(
537+
SelectViewMut::#Archetype(_) => SelectArchetype::#Archetype,
538+
)*
539+
}
540+
}
541+
}
542+
543+
impl<'a> From<SelectBorrow<'a>> for SelectArchetype {
544+
#[inline(always)]
545+
fn from(view: SelectBorrow<'a>) -> Self {
546+
match view {
547+
#(
548+
SelectBorrow::#Archetype(_) => SelectArchetype::#Archetype,
549+
)*
550+
}
551+
}
552+
}
553+
467554
impl TryFrom<ArchetypeId> for SelectArchetype {
468555
type Error = EcsError;
469556

@@ -492,6 +579,20 @@ pub fn generate_world(world_data: &DataWorld, raw_input: &str) -> TokenStream {
492579
}
493580
}
494581

582+
impl TryFrom<EntityDirectAny> for SelectArchetype {
583+
type Error = EcsError;
584+
585+
#[inline(always)]
586+
fn try_from(entity: EntityDirectAny) -> Result<Self, EcsError> {
587+
match entity.archetype_id() {
588+
#(
589+
#Archetype::ARCHETYPE_ID => Ok(SelectArchetype::#Archetype),
590+
)*
591+
_ => Err(EcsError::InvalidEntityType),
592+
}
593+
}
594+
}
595+
495596
impl TryFrom<EntityAny> for SelectEntity {
496597
type Error = EcsError;
497598

@@ -647,6 +748,84 @@ pub fn generate_world(world_data: &DataWorld, raw_input: &str) -> TokenStream {
647748
(*entity).try_into()
648749
}
649750
}
751+
752+
impl<'a> EntityKeySelectable<'a, #World> for EntityAny {
753+
type View = SelectView<'a>;
754+
type ViewMut = SelectViewMut<'a>;
755+
type Borrow = SelectBorrow<'a>;
756+
757+
#[inline(always)]
758+
fn resolve_view(self, world: &'a mut #World) -> Option<Self::View> {
759+
match self.try_into() {
760+
#(
761+
Ok(SelectEntity::#Archetype(entity)) =>
762+
world.#archetype.view(entity).map(|v| v.into()),
763+
)*
764+
Err(_) => panic!("invalid entity type"),
765+
}
766+
}
767+
768+
#[inline(always)]
769+
fn resolve_view_mut(self, world: &'a mut #World) -> Option<Self::ViewMut> {
770+
match self.try_into() {
771+
#(
772+
Ok(SelectEntity::#Archetype(entity)) =>
773+
world.#archetype.view_mut(entity).map(|v| v.into()),
774+
)*
775+
Err(_) => panic!("invalid entity type"),
776+
}
777+
}
778+
779+
#[inline(always)]
780+
fn resolve_borrow(self, world: &'a #World) -> Option<Self::Borrow> {
781+
match self.try_into() {
782+
#(
783+
Ok(SelectEntity::#Archetype(entity)) =>
784+
world.#archetype.borrow(entity).map(|v| v.into()),
785+
)*
786+
Err(_) => panic!("invalid entity type"),
787+
}
788+
}
789+
}
790+
791+
impl<'a> EntityKeySelectable<'a, #World> for EntityDirectAny {
792+
type View = SelectView<'a>;
793+
type ViewMut = SelectViewMut<'a>;
794+
type Borrow = SelectBorrow<'a>;
795+
796+
#[inline(always)]
797+
fn resolve_view(self, world: &'a mut #World) -> Option<Self::View> {
798+
match self.try_into() {
799+
#(
800+
Ok(SelectEntityDirect::#Archetype(entity)) =>
801+
world.#archetype.view(entity).map(|v| v.into()),
802+
)*
803+
Err(_) => panic!("invalid entity type"),
804+
}
805+
}
806+
807+
#[inline(always)]
808+
fn resolve_view_mut(self, world: &'a mut #World) -> Option<Self::ViewMut> {
809+
match self.try_into() {
810+
#(
811+
Ok(SelectEntityDirect::#Archetype(entity)) =>
812+
world.#archetype.view_mut(entity).map(|v| v.into()),
813+
)*
814+
Err(_) => panic!("invalid entity type"),
815+
}
816+
}
817+
818+
#[inline(always)]
819+
fn resolve_borrow(self, world: &'a #World) -> Option<Self::Borrow> {
820+
match self.try_into() {
821+
#(
822+
Ok(SelectEntityDirect::#Archetype(entity)) =>
823+
world.#archetype.borrow(entity).map(|v| v.into()),
824+
)*
825+
Err(_) => panic!("invalid entity type"),
826+
}
827+
}
828+
}
650829
}
651830

652831
#[macro_export]

src/lib.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,21 @@ pub enum SelectEntity {}
789789
#[cfg(doc)]
790790
pub enum SelectEntityDirect {}
791791

792+
/// Similar to SelectEntity, but stores a [`View`](crate::traits::View) for the matched
793+
/// archetype. Returned as a result of the `view` function on [`World`](crate::traits::World).
794+
#[cfg(doc)]
795+
pub enum SelectView {}
796+
797+
/// Similar to SelectEntity, but stores a [`ViewMut`](crate::traits::ViewMut) for the matched
798+
/// archetype. Returned as a result of the `view_mut` function on [`World`](crate::traits::World).
799+
#[cfg(doc)]
800+
pub enum SelectViewMut {}
801+
802+
/// Similar to SelectEntity, but stores a [`Borrow`](crate::traits::Borrow) for the matched
803+
/// archetype. Returned as a result of the `borrow` function on [`World`](crate::traits::World).
804+
#[cfg(doc)]
805+
pub enum SelectBorrow {}
806+
792807
#[cfg(not(doc))]
793808
pub use gecs_macros::{ecs_component_id, ecs_world};
794809

@@ -803,7 +818,7 @@ pub mod prelude {
803818

804819
pub use iter::{EcsStepDestroy, EcsStep};
805820

806-
pub use traits::EntityKey;
821+
pub use traits::{EntityKey, EntityKeyTyped, EntityKeySelectable};
807822
pub use traits::{WorldCanResolve, ArchetypeCanResolve, StorageCanResolve};
808823

809824
pub use traits::{World, WorldHas};

0 commit comments

Comments
 (0)