Skip to content

Commit

Permalink
additional refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
BoxyUwU committed Mar 12, 2021
1 parent 9ddd607 commit 58bc666
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 69 deletions.
125 changes: 59 additions & 66 deletions crates/bevy_ecs/src/component/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,25 +121,29 @@ impl SparseSetIndex for RelationshipId {
}
}

pub mod default_relationship_kinds {
pub mod relationship_kinds {
pub struct HasComponent;
pub struct HasResource;
}

#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub enum ComponentIdOrEntity {
pub enum EntityOrDummyId {
Entity(crate::entity::Entity),
ComponentId(ComponentId),
/// DummyId is used so that we can fit regular components into the relationship model i.e.
/// HasComponent Position
/// however we dont want to implicitly spawn entities for use as the relationship target
/// so we use a dummy id
DummyId(DummyId),
}

#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub struct Relship {
kind: RelationshipKindId,
target: ComponentIdOrEntity,
target: EntityOrDummyId,
}

impl Relship {
pub fn new(kind: RelationshipKindId, target: ComponentIdOrEntity) -> Self {
pub fn new(kind: RelationshipKindId, target: EntityOrDummyId) -> Self {
Self { kind, target }
}
}
Expand Down Expand Up @@ -169,25 +173,26 @@ pub struct RelationshipKindInfo {
}

#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub struct ComponentInfo {
pub struct DummyInfo {
static_type: Option<TypeId>,
id: ComponentId,
id: DummyId,
}
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub struct ComponentId(usize);
pub struct DummyId(usize);

#[derive(Debug)]
pub struct Relationships {
relationships: Vec<RelationshipInfo>,
relationship_indices: HashMap<Relship, RelationshipId, fxhash::FxBuildHasher>,

kinds: Vec<RelationshipKindInfo>,
kind_indices: HashMap<DummyId, RelationshipKindId, fxhash::FxBuildHasher>,

components: Vec<ComponentInfo>,
// FIXME(Relationships) we use TypeId here because bevy needs to do this conversion *somewhere*
// scripting stuff can directly use ComponentId/RelationshipKindId somehow
typeid_to_component_id: HashMap<TypeId, ComponentId, fxhash::FxBuildHasher>,
kind_indices: HashMap<TypeId, RelationshipKindId, fxhash::FxBuildHasher>,
// These two fields are only use for bevy to map TypeId -> DummyId, scripting/modding
// support does not need to care about these two fields and should directly use DummyId's
// and roll their own mapping of ScriptingId -> DummyId if necessary
dummy_id_to_type_id: Vec<DummyInfo>,
type_id_to_dummy_id: HashMap<TypeId, DummyId, fxhash::FxBuildHasher>,
}

impl Default for Relationships {
Expand All @@ -197,16 +202,19 @@ impl Default for Relationships {
relationship_indices: Default::default(),

kinds: Default::default(),

components: Default::default(),
typeid_to_component_id: Default::default(),
kind_indices: Default::default(),

dummy_id_to_type_id: Default::default(),
type_id_to_dummy_id: Default::default(),
};

this.new_relationship_kind(Some(
TypeId::of::<default_relationship_kinds::HasComponent>(),
));
this.new_relationship_kind(Some(TypeId::of::<default_relationship_kinds::HasResource>()));
let has_component_id =
this.new_dummy_id(Some(TypeId::of::<relationship_kinds::HasComponent>()));
this.new_relationship_kind(has_component_id);

let has_resource_id =
this.new_dummy_id(Some(TypeId::of::<relationship_kinds::HasResource>()));
this.new_relationship_kind(has_resource_id);

this
}
Expand All @@ -220,80 +228,65 @@ pub enum ComponentsError {

impl Relationships {
pub fn relkind_of_has_component(&self) -> RelationshipKindId {
self.kind_indices[&TypeId::of::<default_relationship_kinds::HasComponent>()]
let has_component_id =
self.type_id_to_dummy_id[&TypeId::of::<relationship_kinds::HasComponent>()];
self.kind_indices[&has_component_id]
}

pub fn relkind_of_has_resource(&self) -> RelationshipKindId {
self.kind_indices[&TypeId::of::<default_relationship_kinds::HasResource>()]
let has_resource_id =
self.type_id_to_dummy_id[&TypeId::of::<relationship_kinds::HasResource>()];
self.kind_indices[&has_resource_id]
}

/// TypeId is used for bevy to map from relationship kind structs -> RelationshipKindId
/// scripting/untyped use of this should pass in None
pub fn new_relationship_kind(&mut self, type_id: Option<TypeId>) -> RelationshipKindId {
pub fn new_relationship_kind(&mut self, dummy_id: DummyId) -> RelationshipKindId {
let id = RelationshipKindId(self.kinds.len());

if let Some(type_id) = type_id {
let previously_inserted = self
.kind_indices
.insert(type_id, RelationshipKindId(self.kinds.len()));
assert!(previously_inserted.is_none());
}

self.kind_indices.insert(dummy_id, id);
self.kinds.push(RelationshipKindInfo { id });
id
}

/// TypeId is used by bevy to map from component type -> component id
/// scripting/untyped use of this should pass in None
pub(crate) fn new_component_id(&mut self, type_id: Option<TypeId>) -> ComponentId {
let component_id = ComponentId(self.components.len());
self.components.push(ComponentInfo {
/// TypeId is used by bevy to register a mapping from typeid -> dummyid
/// dynamic component use of this should pass in None or else it could
/// interfere with bevy's use of this `Relationships` struct
pub(crate) fn new_dummy_id(&mut self, type_id: Option<TypeId>) -> DummyId {
let dummy_id = DummyId(self.dummy_id_to_type_id.len());
self.dummy_id_to_type_id.push(DummyInfo {
static_type: type_id,
id: component_id,
id: dummy_id,
});

if let Some(type_id) = type_id {
let previously_inserted = self.typeid_to_component_id.insert(type_id, component_id);
let previously_inserted = self.type_id_to_dummy_id.insert(type_id, dummy_id);
assert!(previously_inserted.is_none());
}
component_id
dummy_id
}

pub(crate) fn type_id_to_component_id(&self, type_id: TypeId) -> Option<ComponentId> {
self.typeid_to_component_id.get(&type_id).copied()
pub(crate) fn type_id_to_dummy_id(&self, type_id: TypeId) -> Option<DummyId> {
self.type_id_to_dummy_id.get(&type_id).copied()
}

pub(crate) fn register_relationship(
&mut self,
relationship: Relship,
comp_descriptor: ComponentDescriptor,
) -> Result<&RelationshipInfo, ComponentsError> {
let new_id = RelationshipId(self.relationships.len());
let rel_id = RelationshipId(self.relationships.len());

if let Entry::Occupied(_) = self.relationship_indices.entry(relationship) {
return Err(ComponentsError::ComponentAlreadyExists(relationship));
}

if let Some(type_id) = comp_descriptor.type_id {
if let ComponentIdOrEntity::ComponentId(id) = relationship.target {
if let Some(stored_type_id) = self.components[id.0].static_type {
assert!(stored_type_id == type_id);
}

let component_id = self.typeid_to_component_id[&type_id];
assert!(ComponentIdOrEntity::ComponentId(component_id) == relationship.target);
}
}

self.relationship_indices.insert(relationship, new_id);
self.relationship_indices.insert(relationship, rel_id);
self.relationships.push(RelationshipInfo {
id: new_id,
id: rel_id,
relationship,
data: comp_descriptor,
});

// Safety: Just inserted ^^^
unsafe { Ok(self.get_relationship_info_unchecked(new_id)) }
unsafe { Ok(self.get_relationship_info_unchecked(rel_id)) }
}

#[inline]
Expand All @@ -310,7 +303,7 @@ impl Relationships {
pub fn get_resource_id(&self, type_id: TypeId) -> Option<RelationshipId> {
self.get_relationship_id(Relship {
kind: self.relkind_of_has_resource(),
target: ComponentIdOrEntity::ComponentId(self.type_id_to_component_id(type_id)?),
target: EntityOrDummyId::DummyId(self.type_id_to_dummy_id(type_id)?),
})
}
#[inline]
Expand All @@ -330,15 +323,15 @@ impl Relationships {
type_id: TypeId,
data_layout: impl FnOnce() -> TypeInfo,
) -> &RelationshipInfo {
let component_id = match self.type_id_to_component_id(type_id) {
let component_id = match self.type_id_to_dummy_id(type_id) {
Some(id) => id,
None => self.new_component_id(Some(type_id)),
None => self.new_dummy_id(Some(type_id)),
};

self.get_relationship_info_or_insert_with(
Relship {
kind: self.relkind_of_has_resource(),
target: ComponentIdOrEntity::ComponentId(component_id),
target: EntityOrDummyId::DummyId(component_id),
},
data_layout,
)
Expand All @@ -348,7 +341,7 @@ impl Relationships {
pub fn get_component_id(&self, type_id: TypeId) -> Option<RelationshipId> {
self.get_relationship_id(Relship {
kind: self.relkind_of_has_component(),
target: ComponentIdOrEntity::ComponentId(self.type_id_to_component_id(type_id)?),
target: EntityOrDummyId::DummyId(self.type_id_to_dummy_id(type_id)?),
})
}
#[inline]
Expand All @@ -361,15 +354,15 @@ impl Relationships {
type_id: TypeId,
data_layout: impl FnOnce() -> TypeInfo,
) -> &RelationshipInfo {
let component_id = match self.type_id_to_component_id(type_id) {
let component_id = match self.type_id_to_dummy_id(type_id) {
Some(id) => id,
None => self.new_component_id(Some(type_id)),
None => self.new_dummy_id(Some(type_id)),
};

self.get_relationship_info_or_insert_with(
Relship {
kind: self.relkind_of_has_component(),
target: ComponentIdOrEntity::ComponentId(component_id),
target: EntityOrDummyId::DummyId(component_id),
},
data_layout,
)
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub mod prelude {
pub use crate::reflect::ReflectComponent;
pub use crate::{
bundle::Bundle,
component::default_relationship_kinds::*,
component::relationship_kinds::*,
entity::Entity,
query::{Added, Changed, Flags, Mutated, Or, QueryState, With, WithBundle, Without},
schedule::{
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_ecs/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,11 @@ impl World {
) -> Result<RelationshipId, ComponentsError> {
let storage_type = descriptor.storage_type();

let component_id = self.relationships.new_component_id(descriptor.type_id());
let component_id = self.relationships.new_dummy_id(descriptor.type_id());
let relationship_info = self.relationships.register_relationship(
crate::component::Relship::new(
self.relationships.relkind_of_has_component(),
crate::component::ComponentIdOrEntity::ComponentId(component_id),
crate::component::EntityOrDummyId::DummyId(component_id),
),
descriptor,
)?;
Expand Down

0 comments on commit 58bc666

Please sign in to comment.