From ea8e6678bc52ae47bc210d97cb42e760596f2f98 Mon Sep 17 00:00:00 2001 From: Danny McGee Date: Tue, 27 Feb 2024 14:55:14 -0500 Subject: [PATCH] Expose joints to hierarchy; Add entity type info --- studio/src/anim/mod.rs | 5 ++- studio/src/inspector/wasm.rs | 87 ++++++++++++++---------------------- studio/src/scene.rs | 24 +++++++--- 3 files changed, 56 insertions(+), 60 deletions(-) diff --git a/studio/src/anim/mod.rs b/studio/src/anim/mod.rs index 6c512fb..ce98564 100644 --- a/studio/src/anim/mod.rs +++ b/studio/src/anim/mod.rs @@ -6,7 +6,7 @@ use bevy::{ }; use space_editor::space_prefab::editor_registry::EditorRegistryExt; -use crate::hierarchy; +use crate::{hierarchy, scene::SceneElement}; pub use retargeting::*; mod camera; @@ -131,7 +131,7 @@ fn process_skinned_meshes( // skeleton let joints = joints.iter().copied().collect::>(); if let Some(root) = hierarchy::nearest_common_ancestor(&joints, &q_parents) { - cmd.entity(root).insert(Skeleton); + cmd.entity(root).insert((Skeleton, SceneElement::Skeleton)); } // Tag each joint and find its bind poses @@ -141,6 +141,7 @@ fn process_skinned_meshes( cmd.entity(joint).insert(( SkeletalJoint(Color::BLACK), + SceneElement::Bone, BindPoseLocal(bind_pose_local), BindPoseGlobal(bind_pose_global.affine()), InvBindPose(bind_pose_global.affine().inverse()), diff --git a/studio/src/inspector/wasm.rs b/studio/src/inspector/wasm.rs index 66c2548..286619a 100644 --- a/studio/src/inspector/wasm.rs +++ b/studio/src/inspector/wasm.rs @@ -4,10 +4,7 @@ use bevy::{prelude::*, utils::HashSet, window::PrimaryWindow}; use serde::Serialize; use wasm_bindgen::prelude::*; -use crate::{ - scene::SceneElement, - wasm::{self, AsJson}, -}; +use crate::{scene::SceneElement, wasm}; #[wasm_bindgen(typescript_custom_section)] const TYPE_DECLARATIONS: &str = r#" @@ -16,6 +13,7 @@ export interface SceneObject { id: string; /** A user-friendly name for displaying in the UI */ name: string; + type: SceneElement; /** The IDs of this object's children in the hierarchy */ children: string[]; /** The ID of this object's parent in the hierarchy, if it has one */ @@ -64,50 +62,50 @@ declare global { pub(super) struct SceneObject { id: String, name: String, + #[serde(rename = "type")] + type_: SceneElement, children: Vec, parent: Option, - transform: serde_json::Value, - #[serde(rename(serialize = "globalTransform"))] - global_transform: serde_json::Value, } -struct SceneObjectBuilder<'a> { +struct SceneObjectBuilder { id: Entity, name: Option, + type_: Option, children: Option>, parent: Option, - transform: Option<&'a Transform>, - global_transform: Option<&'a GlobalTransform>, } -impl<'a> SceneObjectBuilder<'a> { +impl SceneObjectBuilder { fn new(id: Entity) -> Self { Self { id, name: None, + type_: None, children: None, parent: None, - transform: None, - global_transform: None, } } fn finish(self) -> SceneObject { SceneObject { id: format!("{:?}", self.id), name: self.name.unwrap(), + type_: self.type_.unwrap(), children: self .children .map(|children| children.iter().map(|ent| format!("{ent:?}")).collect()) .unwrap_or_default(), parent: self.parent.map(|ent| format!("{ent:?}")), - transform: self.transform.unwrap().as_json(), - global_transform: self.global_transform.unwrap().as_json(), } } fn with_name(mut self, name: String) -> Self { self.name = Some(name); self } + fn with_type(mut self, type_: SceneElement) -> Self { + self.type_ = Some(type_); + self + } fn with_children(mut self, children: Vec) -> Self { self.children = Some(children); self @@ -116,18 +114,10 @@ impl<'a> SceneObjectBuilder<'a> { self.parent = Some(parent); self } - fn with_transform(mut self, transform: &'a Transform) -> Self { - self.transform = Some(transform); - self - } - fn with_global_transform(mut self, global_transform: &'a GlobalTransform) -> Self { - self.global_transform = Some(global_transform); - self - } } -impl<'a> SceneObject { - fn build(id: Entity) -> SceneObjectBuilder<'a> { +impl SceneObject { + fn build(id: Entity) -> SceneObjectBuilder { SceneObjectBuilder::new(id) } } @@ -140,8 +130,8 @@ pub(super) fn notify_entity_spawn_changes( mut l_despawned_entities: Local>, mut l_missing_parents: Local>, q_window: Query<&Window, With>, - q_inspectables: Query<(Entity, &Transform, &GlobalTransform), With>, - q_others: Query<(Entity, &Transform, &GlobalTransform), Without>, + q_inspectables: Query<(Entity, &SceneElement)>, + q_others: Query>, q_names: Query<&Name>, q_parents: Query<&Children>, q_children: Query<&Parent>, @@ -149,26 +139,21 @@ pub(super) fn notify_entity_spawn_changes( l_missing_parents.clear(); l_new_objects.clear(); - l_new_objects.extend( - q_inspectables - .iter() - .filter_map(|(ent, xform, world_xform)| { - build_scene_object( - &mut l_notified, - &mut l_missing_parents, - ent, - xform, - world_xform, - &q_inspectables, - &q_names, - &q_parents, - &q_children, - ) - }), - ); + l_new_objects.extend(q_inspectables.iter().filter_map(|(ent, &type_)| { + build_scene_object( + &mut l_notified, + &mut l_missing_parents, + ent, + type_, + &q_inspectables, + &q_names, + &q_parents, + &q_children, + ) + })); while let Some(parent) = l_missing_parents.pop_front() { - let Ok((ent, xform, world_xform)) = q_others.get(parent) else { + let Ok(ent) = q_others.get(parent) else { error!("Failed to find missing parent: {parent:?}"); l_notified.insert(parent); @@ -179,8 +164,7 @@ pub(super) fn notify_entity_spawn_changes( &mut l_notified, &mut l_missing_parents, ent, - xform, - world_xform, + SceneElement::Generic, &q_inspectables, &q_names, &q_parents, @@ -218,9 +202,8 @@ fn build_scene_object( notified: &mut HashSet, missing_parents: &mut VecDeque, ent: Entity, - xform: &Transform, - world_xform: &GlobalTransform, - q_inspectables: &Query<(Entity, &Transform, &GlobalTransform), With>, + type_: SceneElement, + q_inspectables: &Query<(Entity, &SceneElement)>, q_names: &Query<&Name>, q_parents: &Query<&Children>, q_children: &Query<&Parent>, @@ -231,9 +214,7 @@ fn build_scene_object( notified.insert(ent); - let mut result = SceneObject::build(ent) - .with_transform(xform) - .with_global_transform(world_xform); + let mut result = SceneObject::build(ent).with_type(type_); if let Ok(children) = q_parents.get(ent) { result = result.with_children(children.iter().cloned().collect()); diff --git a/studio/src/scene.rs b/studio/src/scene.rs index 875373a..1595965 100644 --- a/studio/src/scene.rs +++ b/studio/src/scene.rs @@ -12,7 +12,8 @@ use bevy::{ render::{camera::RenderTarget, primitives::Aabb}, scene::InstanceId, }; - +#[cfg(feature = "wasm")] +use serde_repr::{Deserialize_repr, Serialize_repr}; use space_editor::{ prelude::{EditorEvent, EditorPrefabPath, PrefabMarker}, space_prefab::component::SceneAutoChild, @@ -230,8 +231,21 @@ pub struct ImportSceneEvent(pub String); // soon. /// A tag that identifies its entity as a user-facing scene element like a prop, /// a light, or a camera. -#[derive(Component)] -pub struct SceneElement; +#[cfg_attr( + feature = "wasm", + repr(u8), + wasm_bindgen, + derive(Serialize_repr, Deserialize_repr) +)] +#[derive(Component, Clone, Copy, Debug, PartialEq, Eq)] +pub enum SceneElement { + Generic, + Mesh, + Skeleton, + Bone, + Light, + Camera, +} #[derive(Component)] pub struct SceneData { @@ -398,9 +412,9 @@ fn tag_scene_elements( } } if has_mesh { - cmd.entity(e).insert(SceneElement); + cmd.entity(e).insert(SceneElement::Mesh); } else { - cmd.entity(e).insert(NoMeshElement); + cmd.entity(e).insert(SceneElement::Generic); } } }