mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-28 08:58:07 +00:00
convert animation target to use an enum w/ values as a hash, rather than Entity.
This commit is contained in:
@@ -47,9 +47,9 @@ implements TreeSelectionProvider {
|
|||||||
@state() playHead = 0;
|
@state() playHead = 0;
|
||||||
@state() playing = false;
|
@state() playing = false;
|
||||||
|
|
||||||
@state() tracks : Record<string, {name?: string, target_type: studio.SceneElement }> = {};
|
@state() tracks : Record<string, {name?: string, target_type: studio.SceneElement, animation_target: studio.AnimationTarget }> = {};
|
||||||
|
|
||||||
@state() track_ordered : string[] = [];
|
@state() track_ordered : [string, studio.AnimationTarget][] = [];
|
||||||
|
|
||||||
@state() keyframes : Record<string, Keyframe> = {};
|
@state() keyframes : Record<string, Keyframe> = {};
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ implements TreeSelectionProvider {
|
|||||||
delete tracks[track_entity];
|
delete tracks[track_entity];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.track_ordered = Object.keys(tracks);
|
this.track_ordered = Object.keys(tracks).map(entity => [entity,tracks[entity].animation_target]);
|
||||||
|
|
||||||
if (typeof this.selectedTrack === "object") {
|
if (typeof this.selectedTrack === "object") {
|
||||||
if (!isOutsideEntity(this.selectedTrack) && !(this.selectedTrack.track in tracks)) {
|
if (!isOutsideEntity(this.selectedTrack) && !(this.selectedTrack.track in tracks)) {
|
||||||
@@ -262,9 +262,11 @@ implements TreeSelectionProvider {
|
|||||||
protected override render(): TemplateResult {
|
protected override render(): TemplateResult {
|
||||||
|
|
||||||
const track_order_hashed : Record<string, number> = {};
|
const track_order_hashed : Record<string, number> = {};
|
||||||
|
const track_animation_target_order_hashed : Record<studio.AnimationTarget, number> = {};
|
||||||
|
|
||||||
for (const [index, track] of this.track_ordered.entries()) {
|
for (const [index, [track, target]] of this.track_ordered.entries()) {
|
||||||
track_order_hashed[track] = index;
|
track_order_hashed[track] = index;
|
||||||
|
track_animation_target_order_hashed[target] = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
const selected = !isOutsideEntity(this.selectedTrack) && this.selectedTrack?.track || false;
|
const selected = !isOutsideEntity(this.selectedTrack) && this.selectedTrack?.track || false;
|
||||||
@@ -282,7 +284,7 @@ implements TreeSelectionProvider {
|
|||||||
'--clip-start': `${clip_start * 100}%`
|
'--clip-start': `${clip_start * 100}%`
|
||||||
};
|
};
|
||||||
|
|
||||||
const tracklist = this.track_ordered.map((entity) => {
|
const tracklist = this.track_ordered.map(([entity,]) => {
|
||||||
let track = this.tracks[entity];
|
let track = this.tracks[entity];
|
||||||
let name = track.name ?? track.target_type;
|
let name = track.name ?? track.target_type;
|
||||||
let icon = this.sceneData?.entityMap.get(entity)?.icon ?? "minus";
|
let icon = this.sceneData?.entityMap.get(entity)?.icon ?? "minus";
|
||||||
@@ -381,6 +383,7 @@ implements TreeSelectionProvider {
|
|||||||
.playHead=${bind(this, "playHead")}
|
.playHead=${bind(this, "playHead")}
|
||||||
.keyframes=${bind(this, "keyframes")}
|
.keyframes=${bind(this, "keyframes")}
|
||||||
.track_ordered=${track_order_hashed}
|
.track_ordered=${track_order_hashed}
|
||||||
|
.track_animation_target_ordered=${track_animation_target_order_hashed}
|
||||||
></sts-anim-timeline>
|
></sts-anim-timeline>
|
||||||
`
|
`
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -69,7 +69,8 @@ export class AnimTimelineElement extends LitElement {
|
|||||||
@property({ type: Number }) playHead = 0;
|
@property({ type: Number }) playHead = 0;
|
||||||
/** Keyframe positions (in seconds) */
|
/** Keyframe positions (in seconds) */
|
||||||
@property({ attribute: false }) keyframes: Record<string, studio.Keyframe> = {};
|
@property({ attribute: false }) keyframes: Record<string, studio.Keyframe> = {};
|
||||||
@property({ attribute: false }) track_ordered: Record<string, number> = {}
|
@property({ attribute: false }) track_ordered: Record<string, number> = {};
|
||||||
|
@property({ attribute: false }) track_animation_target_ordered: Record<string, number> = {};
|
||||||
|
|
||||||
@state() _selectedKeyframe: string | null = null;
|
@state() _selectedKeyframe: string | null = null;
|
||||||
|
|
||||||
@@ -344,7 +345,7 @@ export class AnimTimelineElement extends LitElement {
|
|||||||
Object.entries(this.keyframes),
|
Object.entries(this.keyframes),
|
||||||
([id]) => id,
|
([id]) => id,
|
||||||
([id, keyframe]) => {
|
([id, keyframe]) => {
|
||||||
let row = this.track_ordered[keyframe.target];
|
let row = this.track_animation_target_ordered[keyframe.target];
|
||||||
return html`
|
return html`
|
||||||
<div id=${id}
|
<div id=${id}
|
||||||
class=${classMap({
|
class=${classMap({
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ anyhow.workspace = true
|
|||||||
serde_repr = "0.1.18"
|
serde_repr = "0.1.18"
|
||||||
bevy_tweening = "0.9"
|
bevy_tweening = "0.9"
|
||||||
async-compat = "0.2"
|
async-compat = "0.2"
|
||||||
|
uuid = { version = "1", features = ["v4", "serde"]}
|
||||||
|
|
||||||
[dependencies.reqwest]
|
[dependencies.reqwest]
|
||||||
version = "0.11.24"
|
version = "0.11.24"
|
||||||
|
|||||||
+168
-101
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
|||||||
use std::time::Duration;
|
use std::{str::FromStr, time::Duration};
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
ecs::{
|
ecs::{
|
||||||
@@ -6,7 +6,7 @@ use bevy::{
|
|||||||
reflect::ReflectMapEntities,
|
reflect::ReflectMapEntities,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
utils::HashSet,
|
utils::{hashbrown::HashMap, HashSet},
|
||||||
};
|
};
|
||||||
|
|
||||||
use bevy_tweening::{
|
use bevy_tweening::{
|
||||||
@@ -14,7 +14,7 @@ use bevy_tweening::{
|
|||||||
Animator, EaseMethod, Sequence, Targetable, Tracks, Tween, TweenCompleted,
|
Animator, EaseMethod, Sequence, Targetable, Tracks, Tween, TweenCompleted,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
use space_editor::{prelude::PrefabMarker, space_prefab::editor_registry::EditorRegistryExt};
|
use space_editor::{prelude::PrefabMarker, space_prefab::editor_registry::EditorRegistryExt};
|
||||||
|
|
||||||
use crate::interaction::{MarkedForDeletion, Selectable};
|
use crate::interaction::{MarkedForDeletion, Selectable};
|
||||||
@@ -34,6 +34,7 @@ impl Plugin for TimelinePlugin {
|
|||||||
.register_type::<KeyframeOrder>()
|
.register_type::<KeyframeOrder>()
|
||||||
.editor_registry::<KeyframeOrder>()
|
.editor_registry::<KeyframeOrder>()
|
||||||
.register_type::<EaseType>()
|
.register_type::<EaseType>()
|
||||||
|
.register_type::<uuid::Uuid>()
|
||||||
.add_event::<TimelineInteractionEvent>()
|
.add_event::<TimelineInteractionEvent>()
|
||||||
.add_event::<KeyframeInteractionEvent>();
|
.add_event::<KeyframeInteractionEvent>();
|
||||||
|
|
||||||
@@ -131,10 +132,10 @@ impl Default for TransformKeyframe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Clone, Debug, Reflect, PartialEq)]
|
#[derive(Component, Clone, Debug, Reflect, PartialEq)]
|
||||||
#[reflect(Component, MapEntities)]
|
#[reflect(Component)]
|
||||||
pub struct Keyframe {
|
pub struct Keyframe {
|
||||||
target: Entity,
|
target: AnimationTarget,
|
||||||
time: f32,
|
time: f32
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Clone, Debug, Default, Reflect, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Component, Clone, Debug, Default, Reflect, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
@@ -147,17 +148,11 @@ impl PartialOrd for Keyframe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MapEntities for Keyframe {
|
|
||||||
fn map_entities(&mut self, entity_mapper: &mut EntityMapper) {
|
|
||||||
self.target = entity_mapper.get_or_reserve(self.target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Keyframe {
|
impl Default for Keyframe {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
target: Entity::PLACEHOLDER,
|
|
||||||
time: Default::default(),
|
time: Default::default(),
|
||||||
|
target: AnimationTarget::Unknown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,9 +189,59 @@ impl Default for TimedAnimationClipAsset {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Clone, Debug, Default, Reflect)]
|
#[derive(Component, Clone, Debug, Default, Reflect, PartialEq, Eq, Hash, Copy, Serialize, Deserialize)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct AnimationTarget;
|
#[serde(try_from = "&str", into = "String")]
|
||||||
|
pub enum AnimationTarget {
|
||||||
|
#[default]
|
||||||
|
Unknown,
|
||||||
|
MainCamera,
|
||||||
|
Uuid(uuid::Uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnimationTarget {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::Uuid(uuid::Uuid::new_v4())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToString for AnimationTarget {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Self::Unknown => "unknown".to_string(),
|
||||||
|
Self::MainCamera => "MainCamera".to_string(),
|
||||||
|
Self::Uuid(uuid) => uuid.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AnimationTarget> for String {
|
||||||
|
fn from(val: AnimationTarget) -> Self {
|
||||||
|
val.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&str> for AnimationTarget {
|
||||||
|
type Error = uuid::Error;
|
||||||
|
|
||||||
|
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||||
|
value.parse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for AnimationTarget {
|
||||||
|
type Err = uuid::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
if s == "unknown" {
|
||||||
|
Ok(Self::Unknown)
|
||||||
|
} else if s == "MainCamera" {
|
||||||
|
Ok(Self::MainCamera)
|
||||||
|
} else {
|
||||||
|
Ok(Self::Uuid(s.parse()?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn process_timeline_events(
|
fn process_timeline_events(
|
||||||
mut e_timeline_event: EventReader<TimelineInteractionEvent>,
|
mut e_timeline_event: EventReader<TimelineInteractionEvent>,
|
||||||
@@ -229,7 +274,7 @@ fn process_keyframe_events(
|
|||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut e_timeline_event: EventReader<KeyframeInteractionEvent>,
|
mut e_timeline_event: EventReader<KeyframeInteractionEvent>,
|
||||||
r_global_seek_time: Res<GlobalSeekTime>,
|
r_global_seek_time: Res<GlobalSeekTime>,
|
||||||
q_animation_targets: Query<(Entity, &Transform), With<AnimationTarget>>,
|
q_animation_targets: Query<(Entity, &Transform, &AnimationTarget)>,
|
||||||
q_potential_targets: Query<Entity, (With<Transform>, Without<AnimationTarget>)>,
|
q_potential_targets: Query<Entity, (With<Transform>, Without<AnimationTarget>)>,
|
||||||
mut q_keyframes: Query<(Entity, &mut Keyframe)>,
|
mut q_keyframes: Query<(Entity, &mut Keyframe)>,
|
||||||
) {
|
) {
|
||||||
@@ -237,10 +282,10 @@ fn process_keyframe_events(
|
|||||||
info!("Processing Keyframe Event {event:?}");
|
info!("Processing Keyframe Event {event:?}");
|
||||||
match event {
|
match event {
|
||||||
KeyframeInteractionEvent::RecordKeyframe { target } => {
|
KeyframeInteractionEvent::RecordKeyframe { target } => {
|
||||||
if let Ok((target, transform)) = q_animation_targets.get(*target) {
|
if let Ok((target, transform, animation_target)) = q_animation_targets.get(*target) {
|
||||||
let mut existing = None;
|
let mut existing = None;
|
||||||
for (entity, keyframe) in q_keyframes.iter_mut() {
|
for (entity, keyframe) in q_keyframes.iter_mut() {
|
||||||
if keyframe.target == target
|
if keyframe.target == *animation_target
|
||||||
&& (keyframe.time - r_global_seek_time.time).abs()
|
&& (keyframe.time - r_global_seek_time.time).abs()
|
||||||
< MIN_KEYFRAME_DISTANCE
|
< MIN_KEYFRAME_DISTANCE
|
||||||
{
|
{
|
||||||
@@ -253,8 +298,8 @@ fn process_keyframe_events(
|
|||||||
*transform,
|
*transform,
|
||||||
TransformKeyframe::default(),
|
TransformKeyframe::default(),
|
||||||
Keyframe {
|
Keyframe {
|
||||||
target,
|
|
||||||
time: r_global_seek_time.time,
|
time: r_global_seek_time.time,
|
||||||
|
target: *animation_target,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
@@ -266,8 +311,8 @@ fn process_keyframe_events(
|
|||||||
},
|
},
|
||||||
Selectable,
|
Selectable,
|
||||||
Keyframe {
|
Keyframe {
|
||||||
target,
|
|
||||||
time: r_global_seek_time.time,
|
time: r_global_seek_time.time,
|
||||||
|
target: *animation_target,
|
||||||
},
|
},
|
||||||
TransformKeyframe::default(),
|
TransformKeyframe::default(),
|
||||||
));
|
));
|
||||||
@@ -282,7 +327,7 @@ fn process_keyframe_events(
|
|||||||
KeyframeInteractionEvent::AddEntityTrack { target } => {
|
KeyframeInteractionEvent::AddEntityTrack { target } => {
|
||||||
if let Ok(target) = q_potential_targets.get(*target) {
|
if let Ok(target) = q_potential_targets.get(*target) {
|
||||||
info!("Adding Animation Target to Entity");
|
info!("Adding Animation Target to Entity");
|
||||||
commands.entity(target).insert(AnimationTarget);
|
commands.entity(target).insert(AnimationTarget::new());
|
||||||
} else {
|
} else {
|
||||||
warn!("Can't add animation target to entity");
|
warn!("Can't add animation target to entity");
|
||||||
}
|
}
|
||||||
@@ -304,10 +349,11 @@ fn generate_transform_animation(
|
|||||||
(&Keyframe, &Transform, &TransformKeyframe, Entity),
|
(&Keyframe, &Transform, &TransformKeyframe, Entity),
|
||||||
Without<MarkedForDeletion>,
|
Without<MarkedForDeletion>,
|
||||||
>,
|
>,
|
||||||
added_targets: Query<Entity, Added<AnimationTarget>>,
|
added_targets: Query<(Entity, &AnimationTarget), Added<AnimationTarget>>,
|
||||||
valid_targets: Query<Entity, With<AnimationTarget>>,
|
valid_targets: Query<(Entity, &AnimationTarget)>,
|
||||||
removed: Query<&Keyframe, With<MarkedForDeletion>>,
|
removed: Query<&Keyframe, With<MarkedForDeletion>>,
|
||||||
) {
|
) {
|
||||||
|
let available_targets = valid_targets.iter().map(|(e,a)| (*a,e)).collect::<HashMap<_,_>>();
|
||||||
let changed_targets = changed
|
let changed_targets = changed
|
||||||
.iter()
|
.iter()
|
||||||
.map(|keyframe| keyframe.target)
|
.map(|keyframe| keyframe.target)
|
||||||
@@ -315,18 +361,20 @@ fn generate_transform_animation(
|
|||||||
info!("Processing a removed keyframe {keyframe:?}");
|
info!("Processing a removed keyframe {keyframe:?}");
|
||||||
keyframe.target
|
keyframe.target
|
||||||
}))
|
}))
|
||||||
.chain(added_targets.iter())
|
.chain(added_targets.iter().map(|(_,a)| *a))
|
||||||
.collect::<HashSet<_>>();
|
.collect::<HashSet<_>>();
|
||||||
let keyframes = keyframes
|
let keyframes = keyframes
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(keyframe, _, _, _)| changed_targets.contains(&keyframe.target))
|
.filter(|(keyframe, _,_,_)| changed_targets.contains(&keyframe.target))
|
||||||
.group_by(|(keyframe, _, _, _)| keyframe.target);
|
.group_by(|(keyframe,_, _, _)| keyframe.target);
|
||||||
|
|
||||||
for (target, keyframes) in &keyframes {
|
for (target, keyframes) in &keyframes {
|
||||||
if !valid_targets.contains(target) {
|
let Some(target) = available_targets.get(&target) else {
|
||||||
info!("No valid target.");
|
info!("No valid target.");
|
||||||
continue;
|
continue;
|
||||||
}
|
};
|
||||||
|
let target = *target;
|
||||||
|
|
||||||
let keyframes = keyframes.sorted_by(|a, b| a.0.time.total_cmp(&b.0.time));
|
let keyframes = keyframes.sorted_by(|a, b| a.0.time.total_cmp(&b.0.time));
|
||||||
|
|
||||||
let (_, _, _, translation, rotation, scale) = keyframes.fold(
|
let (_, _, _, translation, rotation, scale) = keyframes.fold(
|
||||||
@@ -604,13 +652,13 @@ mod wasm {
|
|||||||
export interface UpdateAnimationTargets extends CustomEvent {
|
export interface UpdateAnimationTargets extends CustomEvent {
|
||||||
type: "update-animation-targets",
|
type: "update-animation-targets",
|
||||||
detail: {
|
detail: {
|
||||||
added: Record<string, { name?: string, target_type: SceneElement } >,
|
added: Record<string, { name?: string, target_type: SceneElement, animation_target: AnimationTarget } >,
|
||||||
removed: string[]
|
removed: string[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TransformKeyframeInfo {
|
export interface TransformKeyframeInfo {
|
||||||
target: string,
|
target: AnimationTarget,
|
||||||
time: number,
|
time: number,
|
||||||
entity: string,
|
entity: string,
|
||||||
incoming_easing: "linear" | "cubic-hermite",
|
incoming_easing: "linear" | "cubic-hermite",
|
||||||
@@ -620,7 +668,7 @@ mod wasm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface TimedAnimationClipInfo {
|
export interface TimedAnimationClipInfo {
|
||||||
target: string,
|
target: AnimationTarget,
|
||||||
time: number,
|
time: number,
|
||||||
entity: string,
|
entity: string,
|
||||||
type: 'animation-clip',
|
type: 'animation-clip',
|
||||||
@@ -631,6 +679,8 @@ mod wasm {
|
|||||||
|
|
||||||
export type Keyframe = TransformKeyframeInfo | TimedAnimationClipInfo;
|
export type Keyframe = TransformKeyframeInfo | TimedAnimationClipInfo;
|
||||||
|
|
||||||
|
export type AnimationTarget = string;
|
||||||
|
|
||||||
export interface UpdateKeyframes extends CustomEvent {
|
export interface UpdateKeyframes extends CustomEvent {
|
||||||
type: "update-keyframes",
|
type: "update-keyframes",
|
||||||
detail: {
|
detail: {
|
||||||
@@ -652,6 +702,7 @@ mod wasm {
|
|||||||
struct AddedAnimationTargetRecordItem {
|
struct AddedAnimationTargetRecordItem {
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
target_type: SceneElement,
|
target_type: SceneElement,
|
||||||
|
animation_target: AnimationTarget
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
@@ -663,7 +714,7 @@ mod wasm {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct TimedAnimationClipInfo {
|
struct TimedAnimationClipInfo {
|
||||||
entity: String,
|
entity: String,
|
||||||
target: String,
|
target: AnimationTarget,
|
||||||
time: f32,
|
time: f32,
|
||||||
clip: String,
|
clip: String,
|
||||||
duration: f32,
|
duration: f32,
|
||||||
@@ -674,7 +725,7 @@ mod wasm {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
struct TransformKeframeInfo {
|
struct TransformKeframeInfo {
|
||||||
entity: String,
|
entity: String,
|
||||||
target: String,
|
target: AnimationTarget,
|
||||||
time: f32,
|
time: f32,
|
||||||
incoming_easing: EaseType,
|
incoming_easing: EaseType,
|
||||||
affect_translation: bool,
|
affect_translation: bool,
|
||||||
@@ -690,13 +741,13 @@ mod wasm {
|
|||||||
|
|
||||||
pub(super) fn notify_updated_animation_targets(
|
pub(super) fn notify_updated_animation_targets(
|
||||||
q_window: Query<&Window, With<PrimaryWindow>>,
|
q_window: Query<&Window, With<PrimaryWindow>>,
|
||||||
q_cameras: Query<(Entity, Option<&Name>), (Added<AnimationTarget>, With<Camera>)>,
|
q_cameras: Query<(Entity, Option<&Name>, &AnimationTarget), (Added<AnimationTarget>, With<Camera>)>,
|
||||||
q_scene_elements: Query<
|
q_scene_elements: Query<
|
||||||
(Entity, Option<&Name>, &SceneElement),
|
(Entity, Option<&Name>, &SceneElement, &AnimationTarget),
|
||||||
(Added<AnimationTarget>, Without<Camera>),
|
(Added<AnimationTarget>, Without<Camera>),
|
||||||
>,
|
>,
|
||||||
q_transforms: Query<
|
q_transforms: Query<
|
||||||
(Entity, Option<&Name>),
|
(Entity, Option<&Name>, &AnimationTarget),
|
||||||
(
|
(
|
||||||
Added<AnimationTarget>,
|
Added<AnimationTarget>,
|
||||||
With<Transform>,
|
With<Transform>,
|
||||||
@@ -712,30 +763,33 @@ mod wasm {
|
|||||||
|
|
||||||
let added = q_transforms
|
let added = q_transforms
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(entity, name)| {
|
.map(|(entity, name, target)| {
|
||||||
(
|
(
|
||||||
format!("{entity:?}"),
|
format!("{entity:?}"),
|
||||||
AddedAnimationTargetRecordItem {
|
AddedAnimationTargetRecordItem {
|
||||||
name: name.map(|v| v.to_string()),
|
name: name.map(|v| v.to_string()),
|
||||||
target_type: SceneElement::Generic,
|
target_type: SceneElement::Generic,
|
||||||
|
animation_target: *target
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.chain(q_cameras.iter().map(|(entity, name)| {
|
.chain(q_cameras.iter().map(|(entity, name, target)| {
|
||||||
(
|
(
|
||||||
format!("{entity:?}"),
|
format!("{entity:?}"),
|
||||||
AddedAnimationTargetRecordItem {
|
AddedAnimationTargetRecordItem {
|
||||||
name: name.map(|v| v.to_string()),
|
name: name.map(|v| v.to_string()),
|
||||||
target_type: SceneElement::Camera,
|
target_type: SceneElement::Camera,
|
||||||
|
animation_target: *target
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
.chain(q_scene_elements.iter().map(|(entity, name, element)| {
|
.chain(q_scene_elements.iter().map(|(entity, name, element, target)| {
|
||||||
(
|
(
|
||||||
format!("{entity:?}"),
|
format!("{entity:?}"),
|
||||||
AddedAnimationTargetRecordItem {
|
AddedAnimationTargetRecordItem {
|
||||||
name: name.map(|v| v.to_string()),
|
name: name.map(|v| v.to_string()),
|
||||||
target_type: *element,
|
target_type: *element,
|
||||||
|
animation_target: *target
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
@@ -777,7 +831,7 @@ mod wasm {
|
|||||||
.map(|(entity, keyframe, transform_keyframe)| {
|
.map(|(entity, keyframe, transform_keyframe)| {
|
||||||
match serde_json::to_value(TransformKeframeInfo {
|
match serde_json::to_value(TransformKeframeInfo {
|
||||||
entity: format!("{entity:?}"),
|
entity: format!("{entity:?}"),
|
||||||
target: format!("{:?}", keyframe.target),
|
target: keyframe.target,
|
||||||
time: keyframe.time,
|
time: keyframe.time,
|
||||||
incoming_easing: transform_keyframe.incoming_easing,
|
incoming_easing: transform_keyframe.incoming_easing,
|
||||||
affect_translation: transform_keyframe.affect_translation,
|
affect_translation: transform_keyframe.affect_translation,
|
||||||
@@ -793,7 +847,7 @@ mod wasm {
|
|||||||
.chain(q_clips.iter().map(|(entity, keyframe, clip)| {
|
.chain(q_clips.iter().map(|(entity, keyframe, clip)| {
|
||||||
match serde_json::to_value(TimedAnimationClipInfo {
|
match serde_json::to_value(TimedAnimationClipInfo {
|
||||||
entity: format!("{entity:?}"),
|
entity: format!("{entity:?}"),
|
||||||
target: format!("{:?}", keyframe.target),
|
target: keyframe.target,
|
||||||
time: keyframe.time,
|
time: keyframe.time,
|
||||||
clip: clip.clip.id().to_string(),
|
clip: clip.clip.id().to_string(),
|
||||||
duration: clip.duration,
|
duration: clip.duration,
|
||||||
|
|||||||
+3
-3
@@ -106,7 +106,7 @@ impl Plugin for ScenePlugin {
|
|||||||
fn minimal_scene_setup(mut cmd: Commands) {
|
fn minimal_scene_setup(mut cmd: Commands) {
|
||||||
cmd.spawn((
|
cmd.spawn((
|
||||||
Name::new("Directional Light"),
|
Name::new("Directional Light"),
|
||||||
AnimationTarget,
|
AnimationTarget::new(),
|
||||||
DirectionalLightBundle {
|
DirectionalLightBundle {
|
||||||
directional_light: DirectionalLight {
|
directional_light: DirectionalLight {
|
||||||
shadows_enabled: false,
|
shadows_enabled: false,
|
||||||
@@ -271,7 +271,7 @@ fn initialize(mut cmd: Commands) {
|
|||||||
cmd.spawn((
|
cmd.spawn((
|
||||||
Name::new("Main Camera"),
|
Name::new("Main Camera"),
|
||||||
MainCamera,
|
MainCamera,
|
||||||
AnimationTarget,
|
AnimationTarget::MainCamera,
|
||||||
ChangeTracker,
|
ChangeTracker,
|
||||||
Camera3dBundle {
|
Camera3dBundle {
|
||||||
transform: camera_xform,
|
transform: camera_xform,
|
||||||
@@ -328,7 +328,7 @@ fn initialiaze_headless(
|
|||||||
cmd.spawn((
|
cmd.spawn((
|
||||||
Name::new("Main Camera"),
|
Name::new("Main Camera"),
|
||||||
MainCamera,
|
MainCamera,
|
||||||
AnimationTarget,
|
AnimationTarget::MainCamera,
|
||||||
Camera3dBundle {
|
Camera3dBundle {
|
||||||
transform: camera_xform,
|
transform: camera_xform,
|
||||||
tonemapping: Tonemapping::BlenderFilmic,
|
tonemapping: Tonemapping::BlenderFilmic,
|
||||||
|
|||||||
Reference in New Issue
Block a user