#Get gltf data

201 messages ยท Page 1 of 1 (latest)

dark raven
#

Hi,

How do i know what i get out of entity? How do i know it has a get::<Name>

or get::<GltfExtras> ?

I'm trying to read Scale variable to set it's coliders size

 commands.spawn(HookedSceneBundle {
        scene: SceneBundle {
            scene: level_one,
            transform: Transform::from_xyz(1.0, 0.6, 0.0),
            ..Default::default()
        },
        hook: SceneHook::new(|entity, cmds| {
            match entity.get::<GltfExtras>().map(|t| t) {
                Some(val) => {
                    let json: serde_json::Value =
                        serde_json::from_str(&val.value).expect("JSON was not well-formatted");

                    match entity.get::<Name>().map(|t| t) {
                        Some(name) => {
                            println!("{:?}", gltf_node);
                        }
                        None => todo!(),
                    };

                    println!("{:?}", entity_scale);
                    cmds.insert(RigidBody::Dynamic)
                        .insert(Collider::cuboid(0.5, 0.5, 0.5));
                    println!("{:?}", json);

                    return ();
                }
                None => cmds,
            };
        }),
    });
strong orbit
#

use a query and the Query::get function

dark raven
#

ok, i got it thanks

#

but now

#

it doesn't match my mesh ๐Ÿ˜ฆ

#

how do i get the size of my mesh

#

i'm trying to create a collider

#

so it has a child

#

and that child has amesh

#

ugh

#

@strong orbit how do you use Query::get, it needs self

strong orbit
#

like this

fn system(query: Query<&MyComponent>) {
  let entity = // get an `Entity` somehow
  let my_comp = query.get(entity);
}
dark raven
#

i can't

#

because it's in a callback

strong orbit
#

it doesn't look like it is? You mean the match entity.get::<Name>() part in the spawn call right?

#

nvm didn't see the scenehook bit

dark raven
#

so my child is 40v0

strong orbit
#

well, you have access to a commands there, worst case scenario you can ```
cmds.add(|world: &mut World| {

}```
and then that'll give you full access to everything, (and you actually can do world.entity(entity).get::<>()), but it'll execute later

dark raven
#

how do i get a component out of it

#

this is part of add_startup_system

#

๐Ÿ˜ฆ

#
                    if let Some(children) = entity.get::<Children>() {
                        for &child in children.iter() {
                            println!("{:?}", child);
                        }

#

trying to get component from that child

strong orbit
#

it'll execute at the end of the middle startup stage then

#

assuming you're not adding it to the early or late startup stages

#

I would think this callback system seems wonky but I have very little idea what you're trying to do here or what that system looks like. I think hacking it with commands should work?

dark raven
#

i'm trying to add a collider to my component

#

bascially importing a gltf and if it has a colider value, i'd like to add a collider there

#

So i now get the entity, but the mesh is in it's child

#

and i'd need to get that to spawn a colider mesh

strong orbit
#

so when does the callback go off?

dark raven
#

no clue, it's part of SceneHook

#

sourcecode is ez

#

only 2 files

#

so i'm writing it in .add_startup_system(setup)

strong orbit
#

oh lol that's pretty simple

#

but that will not run hooks in startup

#

only after startup

dark raven
#

it works fine for my case thinkGoose

strong orbit
#

I'm sure it does, but that means commands should work fine

#

since it's already delayed anyway

dark raven
#

so how can i get a child then

strong orbit
#

open up a cmds.add(|world: &mut World| { }) and call .entity or .entity_mut on world

#

(this would go inside the hook callback)

dark raven
#

not insert?

strong orbit
#

probably want to just put everything inside the command and add move (like move |world...)

#

idk what you mean by insert

#

that's not gonna help you get a child

dark raven
#

i'm already doing

#
              cmds.insert(RigidBody::Dynamic).insert(Collider::cuboid(
                            0.33 / 2.0,
                            2.92 / 2.0,
                            2.16 / 2.0,
                        ));
strong orbit
#

oh yeah no not insert

#

add

#

add lets you add arbitrary commands

#

you can use an arbitrary command to get access to components at the cost of executing at the end of a stage instead of immediately

#

but since you're in a callback, you're already executing non-immediately

dark raven
#

ok so, how do i get my child?

#
hook: SceneHook::new(|entity, cmds| {
            match entity.get::<GltfExtras>().map(|t| t) {
                Some(val) => {
                    let json: serde_json::Value =
                        serde_json::from_str(&val.value).expect("JSON was not well-formatted");

                    if let Some(children) = entity.get::<Children>() {
                        for &child in children.iter() {
                            println!("{:?}", child);
                        }

                        cmds.add(|world: &mut World| { 
                            world.entity(entity).get::<child>()
                        })

                        cmds.insert(RigidBody::Dynamic).insert(Collider::cuboid(
                            0.33 / 2.0,
                            2.92 / 2.0,
                            2.16 / 2.0,
                        ));

                        println!("{:?}", json);
                    }

                    return ();
                }
                None => cmds,
            };
        }),
#

how do i call entity.get child?

#

ah

#

i need to get it's mesh handle

strong orbit
#
hook: SceneHook::new(|entity, cmds| {
  cmds.add(move |world: &mut World| {
match world.entity(entity).get::<GltfExtras>().map(|t| t) {
                Some(val) => {
                    let json: serde_json::Value =
                        serde_json::from_str(&val.value).expect("JSON was not well-formatted");

                    if let Some(children) = world.entity(entity).get::<Children>() {
                        for &child in children.iter() {
                            println!("{:?}", child);
                        }

                        cmds.insert(RigidBody::Dynamic).insert(Collider::cuboid(
                            0.33 / 2.0,
                            2.92 / 2.0,
                            2.16 / 2.0,
                        ));

                        println!("{:?}", json);
                    }

                    return ();
                }
                None => cmds,
            };
        }),
  })

something like this

#

formatting hard on discord

dark raven
#

how do i get the cild though?

strong orbit
#

you're already iterating over the children

dark raven
#

yes but that gives me their entity id

#

i need to get mesh handle from that

strong orbit
#

run it through world.entity() again

#

might give you borrow issues in the loop though

#

ah but not if it's immutable

dark raven
#

wait

#

just to be clear

#

i can get the child entity without world already

#

it prints out 40v0

#

i just need to get it's components now

#

so no need to wrap it in world

#

the callback already provides entity

strong orbit
#

the callback provides an entity ref

dark raven
#

so no need to rewrite that line

strong orbit
#

not an entity

#

oh ok sure about that

#

I wasn't aware until just now that that was a ref

#

but to get child components you'll need to wrap in a command

dark raven
#

yes, it's a ref, sorry i have autotypes

#

can't use add

strong orbit
#

oh shit it's an entity commands not a normal commands

#

i think can just grab the inner commands tho lemme check docs

#

yes

#

cmds.commands().add(...

dark raven
#

lol

#

thx

#

closure may outlive the current function, but it borrows child, which is owned by the current function

#
                    if let Some(children) = entity.get::<Children>() {
                        for &child in children.iter() {
                            println!("{:?}", child);

                            cmds.commands().add(|world: &mut World| {
                                if let Some(mesh_handle) = world.entity(child).get::<Handle<Mesh>>()
                                {
                                    println!("{:?}", mesh_handle);
                                }
                            });
                        }
#

@strong orbit

strong orbit
#

do the suggestion

dark raven
#

ah

#

wait

#

how does move work here 0o

#

ah it's a callback

#

i assume

strong orbit
#

so a closure is basically a struct under the hood

#

|| {} roughly translates to

struct SomeUnnamedType {
  func: fn() -> (),
}

every captured variable adds a reference field:

struct SomeUnnamedType {
  capture0: &Whatever,
  capture1: &mut Whatever,
  capture2: &Whatever,
  func: fn() -> (),
}

if you add move, those references become ownership stealing

struct SomeUnnamedType {
  capture0: Whatever,
  capture1: Whatever,
  capture2: Whatever,
  func: fn() -> (),
}

this can be problematic sometimes, because you might not want to actually move certain types, but in this case we're just moving an Entity which is Copy so we don't have to think about it

dark raven
#

now i can't use cmds inside

#

ahhh

#

thanks

#

makes more sense now

strong orbit
#

yeah don't use cmds within the command

#

just insert directly using the world

#

world.entity_mut(entity).insert

dark raven
#

how do i get entity from entityref?

#
error[E0521]: borrowed data escapes outside of closure
   --> src\main.rs:181:29
    |
171 |           hook: SceneHook::new(|entity, cmds| {
    |                                 ------
    |                                 |
    |                                 `entity` is a reference that is only valid in the closure body
    |                                 has type `&'1 EntityRef<'_>`
...
181 | /                             cmds.commands().add(move |world: &mut World| {
182 | |                                 if let Some(mesh_handle) = world.entity(child).get::<Handle<Mesh>>()
183 | |                                 {
184 | |                                     println!("{:?}", mesh_handle);
...   |
194 | |                                 }
195 | |                             });
    | |                              ^
    | |                              |
    | |______________________________`entity` escapes the closure body here
    |                                argument requires that `'1` must outlive `'static`

error[E0521]: borrowed data escapes outside of closure
   --> src\main.rs:181:29
    |
171 |           hook: SceneHook::new(|entity, cmds| {
    |                                 ------
    |                                 |
    |                                 `entity` is a reference that is only valid in the closure body
    |                                 has type `&EntityRef<'2>`
...
181 | /                             cmds.commands().add(move |world: &mut World| {
182 | |                                 if let Some(mesh_handle) = world.entity(child).get::<Handle<Mesh>>()
183 | |                                 {
184 | |                                     println!("{:?}", mesh_handle);
...   |
194 | |                                 }
195 | |                             });
    | |                              ^
    | |                              |
    | |______________________________`entity` escapes the closure body here
    |                                argument requires that `'2` must outlive `'static`

For more information about this error, try `rustc --explain E0521`.
#

@strong orbit i have entityRef and so entity_mut doesn't work ๐Ÿ˜ฆ

#

but it can't be inside the closure

#

lol

#

got it to work with that

#

thanks!

#

no clue why i have to get the id outside of the closure though

strong orbit
#

the reference is a borrow of the world, and that gets funky. Would outlive its actual lifetime. By pulling out the id first and copying that, theres no outlived references

dark raven
#

gotcha

#

now i have another problem

#

I have a Handle<Mesh>

#

but the fn needs Mesh

#

how do i extract it?

strong orbit
#

you can do world.resource::<Assets<Mesh>>().get(mesh_handle).unwrap() to get a &Mesh

#

dunno about ComputedColliderShape, hopefully that's not too hard cause I've never heard of it

dark raven
#

Doesn't work cause world is used mutablz

#

Lele try again

dark raven
#

@strong orbit

#

๐Ÿ˜ฆ

#
cannot borrow `*world` as mutable because it is also borrowed as immutable
mutable borrow occurs hererustcClick for full compiler diagnostic
main.rs(189, 41): immutable borrow occurs here
main.rs(202, 49): immutable borrow later used here
dark raven
#

@strong orbit ๐Ÿ‘‹ how do i fix the immutable mutable borrow dilemma

strong orbit
#

can you show the full code? Not sure what's going on there

dark raven
#
cmds.commands().add(move |world: &mut World| {
                                if let Some(mesh_handle) = world.entity(child).get::<Handle<Mesh>>()
                                {
                                    println!("{:?}", mesh_handle);

                                    let mesh =
                                        world.resource::<Assets<Mesh>>().get(mesh_handle).unwrap();
                                    world
                                        .entity(entity_no_ref)
                                        .insert(RigidBody::Dynamic)
                                        .insert(
                                            Collider::from_bevy_mesh(
                                                mesh,
                                                &ComputedColliderShape::TriMesh,
                                            )
                                            .unwrap(),
                                        );
                                }
                            });
#

nor sure if world
.entity(entity_no_ref) is good

#

cause i have an entityref

strong orbit
#

so if you do this:
Some(&mesh_handle) it should copy the handle and stop that from being an issue
and then change the resource access to this:

let meshes = world.remove_resource::<Assets<Mesh>>();
let mesh = meshes.get(mesh_handle).unwrap();

// after everything else

world.insert_resource(meshes);

that'll stop that from being an issue. I think that's all you need to fix it?

dark raven
#

i can't do insert on the world

#

hmm now i have problems inserting rrb

#
                   world.get(child).insert(RigidBody::Dynamic).insert(
                                        Collider::from_bevy_mesh(
                                            mesh,
                                            &ComputedColliderShape::TriMesh,
                                        )
                                        .unwrap(),
                                    );
#

it wants references

strong orbit
#

right you need to entity_mut(child) and insert on that

dark raven
#

Thx

dark raven
#

@strong orbit ๐Ÿ˜ญ

strong orbit
#

oh
get rid of the & and just do let mesh_handle = mesh_handle.clone();

dark raven
#

but then i can't use the destroy fn

#

aah

#

yaay

#

that does work

#

i keep forgetting handles are meant to be copied

#

let wmeshes = world.remove_resource::<Assets<Mesh>>().unwrap();

#

this now crashes my app

#

ist: bevy_asset::assets::Assets<bevy_render::mesh::mesh::Mesh>', C:\Users\User.cargo\registry\src\github.com-1ecc6299db9ec823\bevy_ecs-0.9.1\src\system\system_param.rs:412:17
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace
thread 'main' panicked at 'called Option::unwrap() on a None value', C:\Users\User.cargo\registry\src\github.com-1ecc6299db9ec823\bevy_tasks-0.9.1\src\task_pool.rs:273:45

#

but i am confsed because

#

the if let Some should work

#

so i should be having a mesh?

#

how do i debug ๐Ÿ˜ฆ

#

me code

#
hook: SceneHook::new(|entity, cmds| {
            match entity.get::<GltfExtras>().map(|t| t) {
                Some(val) => {
                    let json: serde_json::Value =
                        serde_json::from_str(&val.value).expect("JSON was not well-formatted");

                    if let Some(children) = entity.get::<Children>() {
                        for &child in children.iter() {
                            println!("{:?}", child);

                            let entity_no_ref = entity.id();

                            cmds.commands().add(move |world: &mut World| {
                                if let Some(mesh_handle) = world.entity(child).get::<Handle<Mesh>>()
                                {

                                    let mesh_handle = mesh_handle.clone();

                                    let wmeshes = world.remove_resource::<Assets<Mesh>>().unwrap();
                                    let mesh = wmeshes.get(&mesh_handle).unwrap();

                                    world.entity_mut(child).insert(RigidBody::Dynamic).insert(
                                        Collider::from_bevy_mesh(
                                            mesh,
                                            &ComputedColliderShape::TriMesh,
                                        )
                                        .unwrap(),
                                    );
                                }
                            });
                        }
strong orbit
#

which unwrap is failing?

dark raven
#

let wmeshes = world.remove_resource::<Assets<Mesh>>().unwrap();

strong orbit
#

oh did you forget to reinsert the resource

#

that'd do it if this runs more than once

dark raven
#

it runs only once

#

reinsert?

#

i'm using scene hook to get the entity from gltf loader

#

then i want to add collision to it

strong orbit
#

yeah when you remove_resource you're removing the mesh assets from the world entirely

#

gotta put it back or no one can access it ever again

dark raven
#

ahh yess that works ๐Ÿ˜„

#

not sure what happened, but the colider is in the correct place, but now the entity got moved thinkGoose

tight haven
#
            match entity.get::<GltfExtras>().map(|t| t) {
                Some(val) => {
                    let json: serde_json::Value =
                        serde_json::from_str(&val.value).expect("JSON was not well-formatted");

                    if let Some(children) = entity.get::<Children>() {
                        for &child in children.iter() {
                            println!("{:?}", child);

                            let entity_no_ref = entity.id();

                            cmds.commands().add(move |world: &mut World| {
                                if let Some(mesh_handle) = world.entity(child).get::<Handle<Mesh>>()
                                {

                                    let mesh_handle = mesh_handle.clone();

                                    let wmeshes = world.remove_resource::<Assets<Mesh>>().unwrap();
                                    let mesh = wmeshes.get(&mesh_handle).unwrap();

                                    world.entity_mut(child).insert(RigidBody::Dynamic).insert(
                                        Collider::from_bevy_mesh(
                                            mesh,
                                            &ComputedColliderShape::TriMesh,
                                        )
                                        .unwrap(),
                                    );
                                }
                            });
                        }```
#

so this is the code

#

so cmds is the commands then, right?

dark raven
#

Yep

#

For the entity

tight haven
#

can you add a transform bundle?

#

I dont believe i see one

dark raven
#

I don't think so

tight haven
#

Why can't you? errors or?

dark raven
#

It should already have a transform

#

I'm using the hook callback

#

On the spawn of the object

#

I wanna make a collider on the object

#

Since it's gltf imported, it has a transform

#

All i wanna do is add a collider

tight haven
#

Can you try adding a transform bundle? I think the issue may be the GLTF may have a transform but the engine needs its own to place it properly and give a transform to its children

#

thatws my only guess for what could be causing the issue

#

like according to the documentation it is needed

#

*unofficial documentation but still

dark raven
#

I mean it works just fine without adding the collider

#

It's in the right spot

tight haven
#

like i say, just give it a shot. If it doesnt work, then its not the solution and you can pursue another, if it does then problem solved. No harm in it

dark raven
#

Ah so I should add it to the colliding mesh as well? ๐Ÿค”