-
I want to define different methods ( Originally I tried to use Then I tried: /// Trait for implementing how a game object works.
#[diagnostic::on_unimplemented(message = "`{Self}` is not an `Object`", label = "invalid `Object`")]
pub trait Object {
fn add_physics_components(&self, _commands: &mut EntityCommands) {}
fn add_visual_components(&self, commands: &mut EntityCommands, rpg_folder: &Res<RpgTextures>);
fn add_extra_components(&self, commands: &mut EntityCommands) {}
}
pub trait GameObject: Object + Send + Sync {}
/// Added when the entity is a game object.
#[derive(Component)]
pub struct IsObject(pub Arc<Mutex<dyn GameObject>>);
#[derive(Component)]
pub struct Barrier {
x_length: Scalar,
y_length: Scalar,
}
impl Object for Barrier {
fn add_physics_components(&self, commands: &mut EntityCommands) {
commands.insert((
RigidBody::Dynamic,
Collider::rectangle(self.x_length, self.y_length),
));
}
fn add_visual_components(&self, commands: &mut EntityCommands, _: &Res<RpgTextures>) {
commands.insert(Sprite::from_color(
bevy::color::palettes::basic::GRAY,
Vec2::new(self.x_length, self.y_length),
));
}
}
/// Trait for implementing how an item works.
pub trait Item {
// ...
}
pub trait GameItem: Object + Item + Send + Sync {}
/// Added when the entity can work as an item.
#[derive(Component)]
pub struct IsItem(pub Arc<Mutex<dyn GameItem>>); It's much better, but isn't ideal enough. I think having a sized data that points to the game object type is enough, but Currently I'm thinking of: no longer keeping the object type (like Is there any ECS-oriented way to do such type distribution, which avoids reflect? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
Here is a solution using reflect. Defining the struct that saves type-id: /// Trait for implementing how a game object works.
#[reflect_trait]
pub trait Object {
// ...
}
/// Added when the entity is a game object.
#[derive(Component, Clone)]
pub struct IsObject(pub TypeId);
impl IsObject {
pub fn spawn_attach_image(
&self,
world: &World,
ec: &mut EntityCommands,
entity: Entity,
rpg_folder: &Res<RpgTextures>,
type_registry: &AppTypeRegistry,
) {
let x = world.get_reflect(entity, self.0).unwrap();
let binding = type_registry.0.read();
let r = binding.get_type_data::<ReflectObject>(self.0).unwrap();
let e = r.get(&*x).unwrap();
// ...
}
} Defining related marker: /// Trait for implementing how an item works.
#[reflect_trait]
pub trait Item {
// ...
}
/// Added when the entity can work as an item.
#[derive(Component, Clone)]
pub struct IsItem;
impl IsItem {
pub fn inspect_then<F>(
world: &World,
entity: Entity,
type_registry: &AppTypeRegistry,
f: F,
) where
F: FnOnce(&dyn Item) -> (),
{
let id = world.entity(entity).get::<IsObject>().unwrap().0;
let comp = world.get_reflect(entity, id).unwrap();
let guard = type_registry.0.read();
let refl = guard.get_type_data::<ReflectItem>(id).unwrap();
let it = refl.get(&*comp).unwrap();
f(it);
}
} Example: /* EXAMPLE TYPE */
#[derive(Reflect, Component, Clone, Copy)]
#[reflect(Object, Item)]
pub struct MyItemType {
// ...
}
// remember to put `app.register_type::<MyItemType>()` somewhere
/* EXAMPLE USAGE */
pub fn setup_item_sprite(
world: &World,
item: Entity,
parent: &mut ChildBuilder,
rpg_folder: &Res<RpgTextures>,
q_obj: Query<&IsObject>,
) {
let registery = world.get_resource::<AppTypeRegistry>().unwrap();
let it = q_obj.get(item).unwrap();
let mut ec = parent.spawn((
// ...
));
it.spawn_attach_image(world, &mut ec, item, rpg_folder, registery);
} See ser/deserializing here. |
Beta Was this translation helpful? Give feedback.
Here is a solution using reflect.
Defining the struct that saves type-id: