Skip to content

Commit

Permalink
Add labels to Gltf Node and Mesh assets (bevyengine#13558)
Browse files Browse the repository at this point in the history
# Objective

Add labels to GltfNode and GltfMesh - they are missing from the assets
even though they are need if one wants to write a custom Gltf spawning
logic.

Eg AnimationPlayer relies on Name component of the node entities to
control the animation. There is no way to actually get names of the gltf
nodes, thus you can't manually spawn subtree from the scene and animate
it.

## Solution

- Add label field and make use of existing label creation logic to store
it there.

## Testing

- Ran all tests
- Fixed tests for node_hierarchy to use lable now

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
  • Loading branch information
3 people authored Jun 5, 2024
1 parent 9a123cd commit 52215ce
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 83 deletions.
96 changes: 96 additions & 0 deletions crates/bevy_gltf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@ pub struct Gltf {
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-node).
#[derive(Asset, Debug, Clone, TypePath)]
pub struct GltfNode {
/// Index of the node inside the scene
pub index: usize,
/// Computed name for a node - either a user defined node name from gLTF or a generated name from index
pub name: String,
/// Subasset label for this node within the gLTF parent asset.
pub asset_label: GltfAssetLabel,
/// Direct children of the node.
pub children: Vec<GltfNode>,
/// Mesh of the node.
Expand All @@ -215,23 +221,81 @@ pub struct GltfNode {
pub extras: Option<GltfExtras>,
}

impl GltfNode {
/// Create a node extracting name and index from glTF def
pub fn new(
node: &gltf::Node,
children: Vec<GltfNode>,
mesh: Option<Handle<GltfMesh>>,
transform: bevy_transform::prelude::Transform,
extras: Option<GltfExtras>,
) -> Self {
Self {
index: node.index(),
asset_label: GltfAssetLabel::Node(node.index()),
name: if let Some(name) = node.name() {
name.to_string()
} else {
format!("GltfNode{}", node.index())
},
children,
mesh,
transform,
extras,
}
}
}

/// A glTF mesh, which may consist of multiple [`GltfPrimitives`](GltfPrimitive)
/// and an optional [`GltfExtras`].
///
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-mesh).
#[derive(Asset, Debug, Clone, TypePath)]
pub struct GltfMesh {
/// Index of the mesh inside the scene
pub index: usize,
/// Computed name for a mesh - either a user defined mesh name from gLTF or a generated name from index
pub name: String,
/// Subasset label for this mesh within the gLTF parent asset.
pub asset_label: GltfAssetLabel,
/// Primitives of the glTF mesh.
pub primitives: Vec<GltfPrimitive>,
/// Additional data.
pub extras: Option<GltfExtras>,
}

impl GltfMesh {
/// Create a mesh extracting name and index from glTF def
pub fn new(
mesh: &gltf::Mesh,
primitives: Vec<GltfPrimitive>,
extras: Option<GltfExtras>,
) -> Self {
Self {
index: mesh.index(),
asset_label: GltfAssetLabel::Mesh(mesh.index()),
name: if let Some(name) = mesh.name() {
name.to_string()
} else {
format!("GltfMesh{}", mesh.index())
},
primitives,
extras,
}
}
}

/// Part of a [`GltfMesh`] that consists of a [`Mesh`], an optional [`StandardMaterial`] and [`GltfExtras`].
///
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-mesh-primitive).
#[derive(Asset, Debug, Clone, TypePath)]
pub struct GltfPrimitive {
/// Index of the primitive inside the mesh
pub index: usize,
/// Computed name for a primitive - either a user defined primitive name from gLTF or a generated name from index
pub name: String,
/// Subasset label for this mesh within the gLTF parent asset.
pub asset_label: GltfAssetLabel,
/// Topology to be rendered.
pub mesh: Handle<Mesh>,
/// Material to apply to the `mesh`.
Expand All @@ -242,6 +306,38 @@ pub struct GltfPrimitive {
pub material_extras: Option<GltfExtras>,
}

impl GltfPrimitive {
/// Create a primitive extracting name and index from glTF def
pub fn new(
gltf_mesh: &gltf::Mesh,
gltf_primitive: &gltf::Primitive,
mesh: Handle<Mesh>,
material: Option<Handle<StandardMaterial>>,
extras: Option<GltfExtras>,
material_extras: Option<GltfExtras>,
) -> Self {
GltfPrimitive {
index: gltf_primitive.index(),
name: {
let mesh_name = gltf_mesh.name().unwrap_or("Mesh");
if gltf_mesh.primitives().len() > 1 {
format!("{}.{}", mesh_name, gltf_primitive.index())
} else {
mesh_name.to_string()
}
},
asset_label: GltfAssetLabel::Primitive {
mesh: gltf_mesh.index(),
primitive: gltf_primitive.index(),
},
mesh,
material,
extras,
material_extras,
}
}
}

/// Additional untyped data that can be present on most glTF types at the primitive level.
///
/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-extras).
Expand Down
Loading

0 comments on commit 52215ce

Please sign in to comment.