Plonq / bevy_rts_camera

RTS-style camera controls plugin for Bevy Engine
Apache License 2.0
53 stars 5 forks source link

How to use a mesh from a GLTF asset as a ground #7

Closed tad-lispy closed 4 months ago

tad-lispy commented 5 months ago

Another question. I hope I don't bother you too much.

In my app I'm importing a "map" from a GLTF asset exported from Blender. It has multiple objects (trees, rocks, etc.) and one that should serve as the ground. It is named "Ground" so I can access it by name in my program. I tried the following:

    let scene = scenes_assets.get_mut(scene_handle.clone()).unwrap();

    let ground = scene
        .world
        .query::<(Entity, &Name)>()
        .iter(&scene.world)
        .filter_map(|(entity, name)| {
            if name.as_str() == "Ground" {
                Some(entity)
            } else {
                None
            }
        })
        .collect_vec();

    for entity in ground {
        scene
            .world
            .entity_mut(entity)
            .insert(Ground)
            .insert(Name::new("Ground"));
    }

This causes a runtime error:

thread 'main' panicked at /home/tad/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_scene-0.13.2/src/scene_spawner.rs:431:35:
scene contains the unregistered type `bevy_rts_camera::Ground`. consider reflecting it with `#[derive(Reflect)]` and registering the type using `app.register_type::<T>()`
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in exclusive system `bevy_scene::scene_spawner::scene_spawner_system`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!

It's a bit strange, since I can add the Ground component to entities spawned in the "main" world (with commands.spawn). It makes me think that I'm doing something wrong. Following the advice from the error message (to derive Reflect on Ground) seems impossible since they are both external to my crate, but I did call app.register_type::<Ground>(), alas with no effect. Any advice?

For reference, here is the code in my program where I want this to work: https://gitlab.com/otterhide/otterhide/-/blob/5ca98f1103d4836f86a3200fe28a28c1fa3fb1cb/src/ground.rs#L86-160

Plonq commented 5 months ago

Hey. I'm not familiar with importing GLTFs so I can't really help with that part. I'm not sure what scene.world is, but maybe you need to use Commands to insert the Ground component on the entity, assuming that entity already exists. Assuming entity is of type Entity, maybe this would work:

commands.entity(entity).insert(Ground);
tad-lispy commented 4 months ago

I'm not an expert on any of it myself. How I understand it is that after loading a 3d asset (like my GLTF exported from Blender), we have a number of scenes that reside in Assets<Scene> resource. They are not yet in the main world, but each scene has it's own world. Via this scene.world we can modify entities inside the scene, before it is spawned. Spawning a scene copies it, together with all those entities and their components into the main world. This provides a mechanism to process the scene before it is spawned.

Actually I was a bit wrong in my first post. Registering the Ground type gives me a compile time error:

cargo run --features bevy/dynamic_linking --bin otterhide -- --duration=5
   Compiling otterhide v0.1.0 (/home/tad/Projects/otterhide/otterhide)
error[E0277]: the trait bound `Ground: GetTypeRegistration` is not satisfied
   --> src/ground.rs:17:29
    |
17  |         app.register_type::<Ground>()
    |             -------------   ^^^^^^ the trait `GetTypeRegistration` is not implemented for `Ground`
    |             |
    |             required by a bound introduced by this call
    |
    = help: the following other types implement trait `GetTypeRegistration`:
              bool
              char
              isize
              i8
              i16
              i32
              i64
              i128
            and 451 others
note: required by a bound in `bevy::prelude::App::register_type`
   --> /home/tad/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_app-0.13.2/src/app.rs:769:29
    |
769 |     pub fn register_type<T: bevy_reflect::GetTypeRegistration>(&mut self) -> &mut Self {
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `App::register_type`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `otterhide` (lib) due to 1 previous error

Deriving Reflect on the Ground type solves it, but it needs to be done in this crate. A PR is on the way.

tad-lispy commented 4 months ago

Thank you!

This whole reflection stuff is black magic to me (along with a lot of Rust in general TBH :stuck_out_tongue_closed_eyes:). I guess one place to take a deep dive is here: https://docs.rs/bevy_reflect/0.13.2/bevy_reflect/index.html