Example #1
0
        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);
            }
        }
Example #2
0
        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();
        }
Example #6
0
 /// <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);
 }