// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. using System.IO; using FlaxEngine; namespace FlaxEditor.GUI.Timeline.Tracks { /// /// The timeline track that represents an channel track with sub-tracks such as position/rotation/scale. /// /// sealed class AnimationChannelTrack : Track { /// /// Gets the archetype. /// /// The archetype. public static TrackArchetype GetArchetype() { return new TrackArchetype { TypeId = 17, Name = "Animation Channel", DisableSpawnViaGUI = true, Create = options => new AnimationChannelTrack(ref options), Load = LoadTrack, Save = SaveTrack, }; } private static void LoadTrack(int version, Track track, BinaryReader stream) { var e = (AnimationChannelTrack)track; } private static void SaveTrack(Track track, BinaryWriter stream) { var e = (AnimationChannelTrack)track; } /// /// Initializes a new instance of the class. /// /// The options. public AnimationChannelTrack(ref TrackCreateOptions options) : base(ref options) { _muteCheckbox.Visible = false; } } /// /// The timeline track for animating object property via Linear Curve. /// /// sealed class AnimationChannelDataTrack : CurvePropertyTrackBase { /// /// Gets the archetype. /// /// The archetype. public static TrackArchetype GetArchetype() { return new TrackArchetype { TypeId = 18, Name = "Animation Channel Data", DisableSpawnViaGUI = true, Create = options => new AnimationChannelDataTrack(ref options), Load = LoadTrack, Save = SaveTrack, }; } private static void LoadTrack(int version, Track track, BinaryReader stream) { var e = (AnimationChannelDataTrack)track; int type = stream.ReadByte(); int keyframesCount = stream.ReadInt32(); var propertyType = type == 1 ? typeof(Quaternion) : typeof(Float3); e.Title = type == 0 ? "Position" : (type == 1 ? "Rotation" : "Scale"); e._type = type; e.MemberTypeName = propertyType.FullName; e.ValueSize = type == 1 ? Quaternion.SizeInBytes : Float3.SizeInBytes; var keyframes = new object[keyframesCount]; for (int i = 0; i < keyframesCount; i++) { var time = stream.ReadSingle(); object value; if (type == 1) value = stream.ReadQuaternion(); else value = stream.ReadFloat3(); keyframes[i] = new LinearCurve.Keyframe { Time = time, Value = value, }; } if (e.Curve != null && e.Curve.ValueType != propertyType) { e.Curve.Dispose(); e.Curve = null; } if (e.Curve == null) { e.CreateCurve(propertyType, typeof(LinearCurveEditor<>)); } e.Curve.SetKeyframes(keyframes); } private static void SaveTrack(Track track, BinaryWriter stream) { var e = (AnimationChannelDataTrack)track; var keyframesCount = e.Curve?.KeyframesCount ?? 0; stream.Write((byte)e._type); stream.Write(keyframesCount); if (keyframesCount == 0) return; for (int i = 0; i < keyframesCount; i++) { e.Curve.GetKeyframe(i, out var time, out var value, out _, out _); stream.Write(time); if (e._type == 1) stream.Write((Quaternion)value); else stream.Write((Float3)value); } } private int _type; /// public AnimationChannelDataTrack(ref TrackCreateOptions options) : base(ref options) { _muteCheckbox.Visible = false; } /// public override void Update(float deltaTime) { base.Update(deltaTime); // Disable red tint on missing member TitleTintColor = Color.White; } } }