diff --git a/studio/src/scene.rs b/studio/src/scene.rs index c20d128..3b51f3d 100644 --- a/studio/src/scene.rs +++ b/studio/src/scene.rs @@ -11,12 +11,13 @@ use bevy::{ prelude::*, render::{camera::RenderTarget, primitives::Aabb}, scene::InstanceId, + utils::{EntityHashSet, HashSet}, }; #[cfg(feature = "wasm")] use serde_repr::{Deserialize_repr, Serialize_repr}; use space_editor::{ prelude::{EditorEvent, EditorPrefabPath, PrefabMarker}, - space_prefab::component::SceneAutoChild, + space_prefab::component::{GltfPrefab, SceneAutoChild}, }; #[cfg(feature = "wasm")] use wasm_bindgen::prelude::wasm_bindgen; @@ -28,6 +29,7 @@ use crate::{ change_tracking::{ChangeTracker, ChangeTrackingPlugin}, debug::DebugPoint, headless::{is_headless, is_not_headless, HeadlessSettings}, + is_editor, math::{Combinable, Extrema}, screenshot::ScreenCapture, MainCamera, @@ -72,7 +74,13 @@ impl Plugin for ScenePlugin { .in_set(SceneSpawnerSystem), ); - app.add_systems(Update, tag_scene_elements); + app.add_systems( + Update, + ( + tag_scene_elements, + autoplay_animations.run_if(not(is_editor)), + ), + ); //Auto loading screen //Register handles on which we will look to show loading screen @@ -360,7 +368,11 @@ fn init_object_loading(mut cmd: Commands, mut er: EventReader) { +fn init_scene_import( + mut cmd: Commands, + r_assets: Res, + mut er: EventReader, +) { if let Some(path) = er.read().last() { info!("Importing asset: {}", path.0); cmd.spawn(( @@ -370,6 +382,7 @@ fn init_scene_import(mut cmd: Commands, mut er: EventReader) { path: path.0.clone(), scene: "Scene0".to_string(), }, + r_assets.load::(&path.0), PrefabMarker, SceneRoot, )); @@ -415,6 +428,64 @@ fn tag_scene_elements( } } +fn autoplay_animations( + mut cmd: Commands, + mut l_done: Local>, + mut l_animating: Local>, + ra_gltfs: Res>, + ra_anims: Res>, + q_prefabs: Query<(&GltfPrefab, &Handle)>, + q_named_ents: Query<(Entity, &Name)>, + mut q_players: Query<&mut AnimationPlayer>, +) { + for (prefab, handle) in q_prefabs.iter() { + if l_done.contains(&prefab.path) { + continue; + } + + let Some(gltf) = ra_gltfs.get(handle) else { + continue; + }; + + let mut playing_anims = 0_usize; + for (anim_name, anim_handle) in gltf.named_animations.iter() { + let Some(anim) = ra_anims.get(anim_handle.clone()) else { + continue; + }; + + let Some((target, name)) = q_named_ents + .iter() + .find(|(_, name)| anim.compatible_with(name)) + else { + continue; + }; + + if !l_animating.contains(&target) { + info!( + "Playing animation '{}' on entity {:?} '{}'", + anim_name, target, name, + ); + if let Ok(mut player) = q_players.get_mut(target) { + if !player.is_playing_clip(anim_handle) { + player.play(anim_handle.clone()).repeat(); + } + } else { + let mut player = AnimationPlayer::default(); + player.play(anim_handle.clone()).repeat(); + cmd.entity(target).insert(player); + } + l_animating.insert(target); + } + + playing_anims += 1; + } + + if playing_anims == gltf.named_animations.len() { + l_done.insert(prefab.path.clone()); + } + } +} + fn frame_scene_in_view( mut cmd: Commands, q_aabbs: Query<(&Aabb, &GlobalTransform), With>,