transform: add more control parent/child ordering and make parent/children insertion atomic
This commit is contained in:
parent
89af5ea4e0
commit
d79339ea62
@ -177,6 +177,21 @@ impl CommandsInternal {
|
|||||||
})));
|
})));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_world<W: WorldWriter + 'static>(&mut self, world_writer: W) -> &mut Self {
|
||||||
|
self.commands
|
||||||
|
.push(Command::WriteWorld(Box::new(world_writer)));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_resources<W: ResourcesWriter + 'static>(
|
||||||
|
&mut self,
|
||||||
|
resources_writer: W,
|
||||||
|
) -> &mut Self {
|
||||||
|
self.commands
|
||||||
|
.push(Command::WriteResources(Box::new(resources_writer)));
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
@ -260,11 +275,7 @@ impl Commands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_world<W: WorldWriter + 'static>(&mut self, world_writer: W) -> &mut Self {
|
pub fn write_world<W: WorldWriter + 'static>(&mut self, world_writer: W) -> &mut Self {
|
||||||
self.commands
|
self.commands.lock().unwrap().write_world(world_writer);
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.commands
|
|
||||||
.push(Command::WriteWorld(Box::new(world_writer)));
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,8 +286,7 @@ impl Commands {
|
|||||||
self.commands
|
self.commands
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.commands
|
.write_resources(resources_writer);
|
||||||
.push(Command::WriteResources(Box::new(resources_writer)));
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,6 +301,22 @@ impl Commands {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn current_entity(&self) -> Option<Entity> {
|
||||||
|
let commands = self.commands.lock().unwrap();
|
||||||
|
commands.current_entity
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn for_current_entity(&mut self, mut func: impl FnMut(Entity)) -> &mut Self {
|
||||||
|
{
|
||||||
|
let commands = self.commands.lock().unwrap();
|
||||||
|
let current_entity = commands
|
||||||
|
.current_entity
|
||||||
|
.expect("The 'current entity' is not set. You should spawn an entity first.");
|
||||||
|
func(current_entity);
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@ -14,7 +14,7 @@ impl WorldBuilderSource for World {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct WorldBuilder<'a> {
|
pub struct WorldBuilder<'a> {
|
||||||
world: &'a mut World,
|
pub world: &'a mut World,
|
||||||
pub current_entity: Option<Entity>,
|
pub current_entity: Option<Entity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,20 @@
|
|||||||
use bevy_ecs::Entity;
|
use bevy_ecs::{FromResources, Entity};
|
||||||
use bevy_property::Properties;
|
use bevy_property::Properties;
|
||||||
use std::ops::{DerefMut, Deref};
|
use std::ops::{DerefMut, Deref};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Properties)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Properties)]
|
||||||
pub struct Parent(pub Entity);
|
pub struct Parent(pub Entity);
|
||||||
|
|
||||||
|
// TODO: We need to impl either FromResources or Default so Parent can be registered as Properties.
|
||||||
|
// This is because Properties deserialize by creating an instance and apply a patch on top.
|
||||||
|
// However Parent should only ever be set with a real user-defined entity. Its worth looking into better
|
||||||
|
// ways to handle cases like this.
|
||||||
|
impl FromResources for Parent {
|
||||||
|
fn from_resources(_resources: &bevy_ecs::Resources) -> Self {
|
||||||
|
Parent(Entity::from_id(u32::MAX))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub struct PreviousParent(pub Option<Entity>);
|
pub struct PreviousParent(pub Option<Entity>);
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,83 @@
|
|||||||
use crate::prelude::{LocalTransform, Parent};
|
use crate::prelude::{Children, LocalTransform, Parent, PreviousParent};
|
||||||
use bevy_ecs::{Commands, CommandsInternal, Component, DynamicBundle, Entity};
|
use bevy_ecs::{Commands, CommandsInternal, Component, DynamicBundle, Entity, WorldWriter};
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
|
pub struct InsertChildren {
|
||||||
|
parent: Entity,
|
||||||
|
children: SmallVec<[Entity; 8]>,
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WorldWriter for InsertChildren {
|
||||||
|
fn write(self: Box<Self>, world: &mut bevy_ecs::World) {
|
||||||
|
for child in self.children.iter() {
|
||||||
|
world
|
||||||
|
.insert(
|
||||||
|
*child,
|
||||||
|
(
|
||||||
|
Parent(self.parent),
|
||||||
|
PreviousParent(None),
|
||||||
|
LocalTransform::default(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let mut added = false;
|
||||||
|
if let Ok(mut children) = world.get_mut::<Children>(self.parent) {
|
||||||
|
children.insert_from_slice(self.index, &self.children);
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: ideally this is just an else statement, but currently that _incorrectly_ fails borrow-checking
|
||||||
|
if !added {
|
||||||
|
world
|
||||||
|
.insert_one(self.parent, Children(SmallVec::from(self.children)))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PushChildren {
|
||||||
|
parent: Entity,
|
||||||
|
children: SmallVec<[Entity; 8]>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ChildBuilder<'a> {
|
pub struct ChildBuilder<'a> {
|
||||||
commands: &'a mut CommandsInternal,
|
commands: &'a mut CommandsInternal,
|
||||||
parent_entities: Vec<Entity>,
|
push_children: PushChildren,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WorldWriter for PushChildren {
|
||||||
|
fn write(self: Box<Self>, world: &mut bevy_ecs::World) {
|
||||||
|
for child in self.children.iter() {
|
||||||
|
world
|
||||||
|
.insert(
|
||||||
|
*child,
|
||||||
|
(
|
||||||
|
Parent(self.parent),
|
||||||
|
PreviousParent(None),
|
||||||
|
LocalTransform::default(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let mut added = false;
|
||||||
|
if let Ok(mut children) = world.get_mut::<Children>(self.parent) {
|
||||||
|
children.extend(self.children.iter().cloned());
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: ideally this is just an else statement, but currently that _incorrectly_ fails borrow-checking
|
||||||
|
if !added {
|
||||||
|
world
|
||||||
|
.insert_one(self.parent, Children(SmallVec::from(self.children)))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ChildBuilder<'a> {
|
impl<'a> ChildBuilder<'a> {
|
||||||
@ -16,14 +90,8 @@ impl<'a> ChildBuilder<'a> {
|
|||||||
entity: Entity,
|
entity: Entity,
|
||||||
components: impl DynamicBundle + Send + Sync + 'static,
|
components: impl DynamicBundle + Send + Sync + 'static,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
let parent_entity = self
|
self.commands.spawn_as_entity(entity, components);
|
||||||
.parent_entities
|
self.push_children.children.push(entity);
|
||||||
.last()
|
|
||||||
.cloned()
|
|
||||||
.expect("There should always be a parent at this point.");
|
|
||||||
self.commands
|
|
||||||
.spawn_as_entity(entity, components)
|
|
||||||
.with_bundle((Parent(parent_entity), LocalTransform::default()));
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,10 +107,21 @@ impl<'a> ChildBuilder<'a> {
|
|||||||
self.commands.with(component);
|
self.commands.with(component);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn for_current_entity(&mut self, mut func: impl FnMut(Entity)) -> &mut Self {
|
||||||
|
let current_entity = self
|
||||||
|
.commands
|
||||||
|
.current_entity
|
||||||
|
.expect("The 'current entity' is not set. You should spawn an entity first.");
|
||||||
|
func(current_entity);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BuildChildren {
|
pub trait BuildChildren {
|
||||||
fn with_children(&mut self, parent: impl FnMut(&mut ChildBuilder)) -> &mut Self;
|
fn with_children(&mut self, parent: impl FnMut(&mut ChildBuilder)) -> &mut Self;
|
||||||
|
fn push_children(&mut self, parent: Entity, children: &[Entity]) -> &mut Self;
|
||||||
|
fn insert_children(&mut self, parent: Entity, index: usize, children: &[Entity]) -> &mut Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuildChildren for Commands {
|
impl BuildChildren for Commands {
|
||||||
@ -50,12 +129,42 @@ impl BuildChildren for Commands {
|
|||||||
{
|
{
|
||||||
let mut commands = self.commands.lock().unwrap();
|
let mut commands = self.commands.lock().unwrap();
|
||||||
let current_entity = commands.current_entity.expect("Cannot add children because the 'current entity' is not set. You should spawn an entity first.");
|
let current_entity = commands.current_entity.expect("Cannot add children because the 'current entity' is not set. You should spawn an entity first.");
|
||||||
|
commands.current_entity = None;
|
||||||
|
let push_children = {
|
||||||
let mut builder = ChildBuilder {
|
let mut builder = ChildBuilder {
|
||||||
commands: &mut commands,
|
commands: &mut commands,
|
||||||
parent_entities: vec![current_entity],
|
push_children: PushChildren {
|
||||||
|
children: SmallVec::default(),
|
||||||
|
parent: current_entity,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
parent(&mut builder);
|
||||||
|
builder.push_children
|
||||||
};
|
};
|
||||||
|
|
||||||
parent(&mut builder);
|
commands.current_entity = Some(current_entity);
|
||||||
|
commands.write_world(push_children);
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
fn push_children(&mut self, parent: Entity, children: &[Entity]) -> &mut Self {
|
||||||
|
{
|
||||||
|
let mut commands = self.commands.lock().unwrap();
|
||||||
|
commands.write_world(PushChildren {
|
||||||
|
children: SmallVec::from(children),
|
||||||
|
parent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
fn insert_children(&mut self, parent: Entity, index: usize, children: &[Entity]) -> &mut Self {
|
||||||
|
{
|
||||||
|
let mut commands = self.commands.lock().unwrap();
|
||||||
|
commands.write_world(InsertChildren {
|
||||||
|
children: SmallVec::from(children),
|
||||||
|
index,
|
||||||
|
parent,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -63,16 +172,155 @@ impl BuildChildren for Commands {
|
|||||||
|
|
||||||
impl<'a> BuildChildren for ChildBuilder<'a> {
|
impl<'a> BuildChildren for ChildBuilder<'a> {
|
||||||
fn with_children(&mut self, mut spawn_children: impl FnMut(&mut ChildBuilder)) -> &mut Self {
|
fn with_children(&mut self, mut spawn_children: impl FnMut(&mut ChildBuilder)) -> &mut Self {
|
||||||
let current_entity = self
|
let current_entity = self.commands.current_entity.expect("Cannot add children because the 'current entity' is not set. You should spawn an entity first.");
|
||||||
.commands
|
|
||||||
.current_entity
|
|
||||||
.expect("Cannot add children without a parent. Try creating an entity first.");
|
|
||||||
self.parent_entities.push(current_entity);
|
|
||||||
self.commands.current_entity = None;
|
self.commands.current_entity = None;
|
||||||
|
let push_children = {
|
||||||
|
let mut builder = ChildBuilder {
|
||||||
|
commands: self.commands,
|
||||||
|
push_children: PushChildren {
|
||||||
|
children: SmallVec::default(),
|
||||||
|
parent: current_entity,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
spawn_children(self);
|
spawn_children(&mut builder);
|
||||||
|
builder.push_children
|
||||||
|
};
|
||||||
|
|
||||||
self.commands.current_entity = self.parent_entities.pop();
|
self.commands.current_entity = Some(current_entity);
|
||||||
|
self.commands.write_world(push_children);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_children(&mut self, parent: Entity, children: &[Entity]) -> &mut Self {
|
||||||
|
self.commands.write_world(PushChildren {
|
||||||
|
children: SmallVec::from(children),
|
||||||
|
parent,
|
||||||
|
});
|
||||||
|
self
|
||||||
|
}
|
||||||
|
fn insert_children(&mut self, parent: Entity, index: usize, children: &[Entity]) -> &mut Self {
|
||||||
|
self.commands.write_world(InsertChildren {
|
||||||
|
children: SmallVec::from(children),
|
||||||
|
index,
|
||||||
|
parent,
|
||||||
|
});
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::BuildChildren;
|
||||||
|
use crate::prelude::{Children, LocalTransform, Parent, PreviousParent};
|
||||||
|
use bevy_ecs::{Commands, Entity, Resources, World};
|
||||||
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn build_children() {
|
||||||
|
let mut world = World::default();
|
||||||
|
let mut resources = Resources::default();
|
||||||
|
let mut commands = Commands::default();
|
||||||
|
|
||||||
|
let mut parent = None;
|
||||||
|
let mut child1 = None;
|
||||||
|
let mut child2 = None;
|
||||||
|
|
||||||
|
commands
|
||||||
|
.spawn((1,))
|
||||||
|
.for_current_entity(|e| parent = Some(e))
|
||||||
|
.with_children(|parent| {
|
||||||
|
parent
|
||||||
|
.spawn((2,))
|
||||||
|
.for_current_entity(|e| child1 = Some(e))
|
||||||
|
.spawn((3,))
|
||||||
|
.for_current_entity(|e| child2 = Some(e));
|
||||||
|
});
|
||||||
|
|
||||||
|
commands.apply(&mut world, &mut resources);
|
||||||
|
let parent = parent.expect("parent should exist");
|
||||||
|
let child1 = child1.expect("child1 should exist");
|
||||||
|
let child2 = child2.expect("child2 should exist");
|
||||||
|
let expected_children: SmallVec<[Entity; 8]> = smallvec![child1, child2];
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
world.get::<Children>(parent).unwrap().0.clone(),
|
||||||
|
expected_children
|
||||||
|
);
|
||||||
|
assert_eq!(*world.get::<Parent>(child1).unwrap(), Parent(parent));
|
||||||
|
assert_eq!(*world.get::<Parent>(child2).unwrap(), Parent(parent));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
*world.get::<PreviousParent>(child1).unwrap(),
|
||||||
|
PreviousParent(None)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
*world.get::<PreviousParent>(child2).unwrap(),
|
||||||
|
PreviousParent(None)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(world.get::<LocalTransform>(child1).is_ok());
|
||||||
|
assert!(world.get::<LocalTransform>(child2).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn push_and_insert_children() {
|
||||||
|
let mut world = World::default();
|
||||||
|
let mut resources = Resources::default();
|
||||||
|
let mut commands = Commands::default();
|
||||||
|
let entities = world
|
||||||
|
.spawn_batch(vec![(1,), (2,), (3,), (4,), (5,)])
|
||||||
|
.collect::<Vec<Entity>>();
|
||||||
|
|
||||||
|
commands.push_children(entities[0], &entities[1..3]);
|
||||||
|
commands.apply(&mut world, &mut resources);
|
||||||
|
|
||||||
|
let parent = entities[0];
|
||||||
|
let child1 = entities[1];
|
||||||
|
let child2 = entities[2];
|
||||||
|
let child3 = entities[3];
|
||||||
|
let child4 = entities[4];
|
||||||
|
|
||||||
|
let expected_children: SmallVec<[Entity; 8]> = smallvec![child1, child2];
|
||||||
|
assert_eq!(
|
||||||
|
world.get::<Children>(parent).unwrap().0.clone(),
|
||||||
|
expected_children
|
||||||
|
);
|
||||||
|
assert_eq!(*world.get::<Parent>(child1).unwrap(), Parent(parent));
|
||||||
|
assert_eq!(*world.get::<Parent>(child2).unwrap(), Parent(parent));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
*world.get::<PreviousParent>(child1).unwrap(),
|
||||||
|
PreviousParent(None)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
*world.get::<PreviousParent>(child2).unwrap(),
|
||||||
|
PreviousParent(None)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(world.get::<LocalTransform>(child1).is_ok());
|
||||||
|
assert!(world.get::<LocalTransform>(child2).is_ok());
|
||||||
|
|
||||||
|
commands.insert_children(parent, 1, &entities[3..]);
|
||||||
|
commands.apply(&mut world, &mut resources);
|
||||||
|
|
||||||
|
let expected_children: SmallVec<[Entity; 8]> = smallvec![child1, child3, child4, child2];
|
||||||
|
assert_eq!(
|
||||||
|
world.get::<Children>(parent).unwrap().0.clone(),
|
||||||
|
expected_children
|
||||||
|
);
|
||||||
|
assert_eq!(*world.get::<Parent>(child3).unwrap(), Parent(parent));
|
||||||
|
assert_eq!(*world.get::<Parent>(child4).unwrap(), Parent(parent));
|
||||||
|
assert_eq!(
|
||||||
|
*world.get::<PreviousParent>(child3).unwrap(),
|
||||||
|
PreviousParent(None)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
*world.get::<PreviousParent>(child4).unwrap(),
|
||||||
|
PreviousParent(None)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(world.get::<LocalTransform>(child3).is_ok());
|
||||||
|
assert!(world.get::<LocalTransform>(child4).is_ok());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::prelude::{LocalTransform, Parent};
|
use crate::prelude::{LocalTransform, Parent, PreviousParent, Children};
|
||||||
use bevy_ecs::{Component, DynamicBundle, Entity, WorldBuilder};
|
use bevy_ecs::{Component, DynamicBundle, Entity, WorldBuilder};
|
||||||
|
|
||||||
pub struct WorldChildBuilder<'a, 'b> {
|
pub struct WorldChildBuilder<'a, 'b> {
|
||||||
@ -23,7 +23,26 @@ impl<'a, 'b> WorldChildBuilder<'a, 'b> {
|
|||||||
.expect("There should always be a parent at this point.");
|
.expect("There should always be a parent at this point.");
|
||||||
self.world_builder
|
self.world_builder
|
||||||
.spawn_as_entity(entity, components)
|
.spawn_as_entity(entity, components)
|
||||||
.with_bundle((Parent(parent_entity), LocalTransform::default()));
|
.with_bundle((
|
||||||
|
Parent(parent_entity),
|
||||||
|
PreviousParent(None),
|
||||||
|
LocalTransform::default(),
|
||||||
|
));
|
||||||
|
{
|
||||||
|
let world = &mut self.world_builder.world;
|
||||||
|
let mut added = false;
|
||||||
|
if let Ok(mut children) = world.get_mut::<Children>(parent_entity) {
|
||||||
|
children.push(entity);
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: ideally this is just an else statement, but currently that _incorrectly_ fails borrow-checking
|
||||||
|
if !added {
|
||||||
|
world
|
||||||
|
.insert_one(parent_entity, Children(smallvec::smallvec![entity]))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ pub mod prelude {
|
|||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use bevy_type_registry::RegisterType;
|
use bevy_type_registry::RegisterType;
|
||||||
use prelude::{Children, LocalTransform, NonUniformScale, Rotation, Scale, Transform, Translation};
|
use prelude::{Children, LocalTransform, NonUniformScale, Rotation, Scale, Transform, Translation, Parent};
|
||||||
|
|
||||||
pub(crate) fn transform_systems() -> Vec<Box<dyn System>> {
|
pub(crate) fn transform_systems() -> Vec<Box<dyn System>> {
|
||||||
let mut systems = Vec::with_capacity(5);
|
let mut systems = Vec::with_capacity(5);
|
||||||
@ -30,6 +30,7 @@ pub struct TransformPlugin;
|
|||||||
impl AppPlugin for TransformPlugin {
|
impl AppPlugin for TransformPlugin {
|
||||||
fn build(&self, app: &mut AppBuilder) {
|
fn build(&self, app: &mut AppBuilder) {
|
||||||
app.register_component::<Children>()
|
app.register_component::<Children>()
|
||||||
|
.register_component::<Parent>()
|
||||||
.register_component::<LocalTransform>()
|
.register_component::<LocalTransform>()
|
||||||
.register_component::<Transform>()
|
.register_component::<Transform>()
|
||||||
.register_component::<Translation>()
|
.register_component::<Translation>()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user