public static WrapMode ToUnityWrapMode(this MWAnimationWrapMode wrapMode) { switch (wrapMode) { case MWAnimationWrapMode.Loop: return(WrapMode.Loop); case MWAnimationWrapMode.PingPong: return(WrapMode.PingPong); case MWAnimationWrapMode.Once: return(WrapMode.Once); default: return(WrapMode.Once); } }
public static bool IsInterpolationLoopWrap(this MWAnimationWrapMode wrapMode) { switch (wrapMode) { case MWAnimationWrapMode.Loop: return(true); case MWAnimationWrapMode.PingPong: GD.PushError("WrapMode.PingPong is not supported."); return(true); case MWAnimationWrapMode.Once: return(false); default: return(true); } }
public virtual void ApplyPatch(AnimationPatch patch) { var wasMoving = IsPlaying && Speed != 0; if (patch.Name != null) { Name = patch.Name; } if (patch.Speed.HasValue) { Speed = patch.Speed.Value; } if (patch.Weight.HasValue) { Weight = patch.Weight.Value; } if (patch.WrapMode.HasValue) { WrapMode = patch.WrapMode.Value; } // only patch one of BasisTime and Time, based on play state if ((IsPlaying && Speed != 0 || !patch.Time.HasValue) && patch.BasisTime.HasValue) { BasisTime = patch.BasisTime.Value; } else if (patch.Time.HasValue) { Time = patch.Time.Value; } var isMoving = IsPlaying && Speed != 0; // send one transform update when the anim stops if (wasMoving && !isMoving) { foreach (var actor in targetActors) { actor.SendActorUpdate(Messaging.Payloads.ActorComponentType.Transform); } } }
internal void CreateAnimation( string animationName, IEnumerable <MWAnimationKeyframe> keyframes, IEnumerable <MWAnimationEvent> events, MWAnimationWrapMode wrapMode, MWSetAnimationStateOptions initialState, bool isInternal, bool managed, Action onCreatedCallback) { var continuation = new MWContinuation(AttachedActor, null, (result) => { var clip = new AnimationClip { legacy = true, wrapMode = wrapMode.ToUnityWrapMode(), }; var curves = new Dictionary <string, CurveInfo>(); CurveInfo GetOrCreateCurve(Type type, string propertyName) { if (!curves.TryGetValue(propertyName, out CurveInfo info)) { info = new CurveInfo() { Curve = new AnimationCurve(), Type = type }; curves.Add(propertyName, info); } return(info); } void AddFloatPatch(Type type, string propertyName, float time, float?value) { if (value.HasValue) { var curveInfo = GetOrCreateCurve(type, propertyName); var keyframe = new UnityEngine.Keyframe(time, value.Value, 0, 0, 0, 0); curveInfo.Curve.AddKey(keyframe); } } void AddVector3Patch(Type type, string propertyName, float time, Vector3Patch value) { AddFloatPatch(type, String.Format("{0}.x", propertyName), time, value?.X); AddFloatPatch(type, String.Format("{0}.y", propertyName), time, value?.Y); AddFloatPatch(type, String.Format("{0}.z", propertyName), time, value?.Z); } void AddQuaternionPatch(Type type, string propertyName, float time, QuaternionPatch value) { AddFloatPatch(type, String.Format("{0}.x", propertyName), time, value?.X); AddFloatPatch(type, String.Format("{0}.y", propertyName), time, value?.Y); AddFloatPatch(type, String.Format("{0}.z", propertyName), time, value?.Z); AddFloatPatch(type, String.Format("{0}.w", propertyName), time, value?.W); } void AddTransformPatch(float time, ScaledTransformPatch value) { // Work around a Unity bug/feature where all position components must be specified // in the keyframe or the missing fields get set to zero. Vector3Patch position = value?.Position; if (position != null && position.IsPatched()) { if (!position.X.HasValue) { position.X = transform.localPosition.x; } if (!position.Y.HasValue) { position.Y = transform.localPosition.y; } if (!position.Z.HasValue) { position.Z = transform.localPosition.z; } } // Work around a Unity bug/feature where all scale components must be specified // in the keyframe or the missing fields get set to one. Vector3Patch scale = value?.Scale; if (scale != null && scale.IsPatched()) { if (!scale.X.HasValue) { scale.X = transform.localScale.x; } if (!scale.Y.HasValue) { scale.Y = transform.localScale.y; } if (!scale.Z.HasValue) { scale.Z = transform.localScale.z; } } AddVector3Patch(typeof(Transform), "m_LocalPosition", time, value?.Position); AddQuaternionPatch(typeof(Transform), "m_LocalRotation", time, value?.Rotation); AddVector3Patch(typeof(Transform), "m_LocalScale", time, value?.Scale); } void AddActorPatch(float time, ActorPatch value) { AddTransformPatch(time, value?.Transform.Local); } void AddKeyframe(MWAnimationKeyframe keyframe) { AddActorPatch(keyframe.Time, keyframe.Value); } foreach (var keyframe in keyframes) { AddKeyframe(keyframe); } foreach (var kv in curves) { clip.SetCurve("", kv.Value.Type, kv.Key, kv.Value.Curve); } _animationData[animationName] = new AnimationData() { IsInternal = isInternal, Managed = managed }; float initialTime = 0f; float initialSpeed = 1f; bool initialEnabled = false; if (initialState != null) { initialTime = initialState.Time ?? initialTime; initialSpeed = initialState.Speed ?? initialSpeed; initialEnabled = initialState.Enabled ?? initialEnabled; } var animation = GetOrCreateUnityAnimationComponent(); animation.AddClip(clip, animationName); SetAnimationState(animationName, initialTime, initialSpeed, initialEnabled); onCreatedCallback?.Invoke(); }); continuation.Start(); }
internal void CreateAnimation( string animationName, IEnumerable <MWAnimationKeyframe> keyframes, IEnumerable <MWAnimationEvent> events, MWAnimationWrapMode wrapMode, MWSetAnimationStateOptions initialState, bool isInternal, bool managed, Action onCreatedCallback) { var continuation = new MWContinuation(AttachedActor, null, (result) => { var animationPlayer = GetOrCreateGodotAnimationPlayer(animationName); var animation = new GodotAnimation(); animation.Loop = wrapMode.IsInterpolationLoopWrap(); var curves = new Dictionary <string, int>(); int GetOrCreateCurve(Type type, string propertyName) { if (!curves.TryGetValue(propertyName, out int trackIndex)) { trackIndex = animation.AddTrack(GodotAnimation.TrackType.Bezier); curves.Add(propertyName, trackIndex); } return(trackIndex); } void AddFloatPatch(Type type, string propertyName, float time, float?value) { if (value.HasValue) { var trackIndex = GetOrCreateCurve(type, propertyName); animation.TrackSetPath(trackIndex, propertyName); animation.BezierTrackInsertKey(trackIndex, time, value.Value); } } void AddVector3Patch(Type type, string propertyName, float time, Vector3Patch value) { AddFloatPatch(type, String.Format("{0}:x", propertyName), time, value?.X); AddFloatPatch(type, String.Format("{0}:y", propertyName), time, value?.Y); AddFloatPatch(type, String.Format("{0}:z", propertyName), time, value?.Z); } void AddQuaternionPatch(Type type, string propertyName, float time, QuaternionPatch value) { AddFloatPatch(type, String.Format("{0}:x", propertyName), time, value?.X); AddFloatPatch(type, String.Format("{0}:y", propertyName), time, value?.Y); AddFloatPatch(type, String.Format("{0}:z", propertyName), time, value?.Z); AddFloatPatch(type, String.Format("{0}:w", propertyName), time, value?.W); } void AddTransformPatch(float time, ScaledTransformPatch value) { // Work around a Unity bug/feature where all position components must be specified // in the keyframe or the missing fields get set to zero. Vector3Patch position = value?.Position; if (position != null && position.IsPatched()) { if (!position.X.HasValue) { position.X = Transform.origin.x; } if (!position.Y.HasValue) { position.Y = Transform.origin.y; } if (!position.Z.HasValue) { position.Z = Transform.origin.z; } } // Work around a Unity bug/feature where all scale components must be specified // in the keyframe or the missing fields get set to one. Vector3Patch scale = value?.Scale; if (scale != null && scale.IsPatched()) { if (!scale.X.HasValue) { scale.X = Scale.x; } if (!scale.Y.HasValue) { scale.Y = Scale.y; } if (!scale.Z.HasValue) { scale.Z = Scale.z; } } AddVector3Patch(typeof(Transform), "..:translation", time, value?.Position); var ratation = value?.Rotation; var quat = new Quat(ratation.X.Value, ratation.Y.Value, ratation.Z.Value, ratation.W.Value); var vector3 = quat.GetEuler(); AddVector3Patch(typeof(Transform), "..:rotation_degrees", time, new Vector3Patch(vector3)); AddVector3Patch(typeof(Transform), "..:scale", time, value?.Scale); } void AddActorPatch(float time, ActorPatch value) { AddTransformPatch(time, value?.Transform.Local); } void AddKeyframe(MWAnimationKeyframe keyframe) { AddActorPatch(keyframe.Time, keyframe.Value); if (animation.Length < keyframe.Time) { animation.Length = keyframe.Time; } } foreach (var keyframe in keyframes) { AddKeyframe(keyframe); } _animationData[animationName] = new AnimationData() { IsInternal = isInternal, Managed = managed }; float initialTime = 0f; float initialSpeed = 1f; bool initialEnabled = false; if (initialState != null) { initialTime = initialState.Time ?? initialTime; initialSpeed = initialState.Speed ?? initialSpeed; initialEnabled = initialState.Enabled ?? initialEnabled; } animationPlayer.AddAnimation(animationName, animation); animationPlayer.AssignedAnimation = animationName; SetAnimationState(animationName, initialTime, initialSpeed, initialEnabled); onCreatedCallback?.Invoke(); }); continuation.Start(); }
/// <summary> /// Returns true if the mode is a looping mode. /// </summary> /// <param name="wrapMode"></param> /// <returns></returns> public static bool IsLooping(this MWAnimationWrapMode wrapMode) { return(wrapMode == MWAnimationWrapMode.Loop || wrapMode == MWAnimationWrapMode.PingPong); }