예제 #1
0
        /// <summary>Initializes the struct with default values.</summary>
        public static AnimationClipState Default()
        {
            AnimationClipState value = new AnimationClipState();

            value.layer    = 0;
            value.time     = 0f;
            value.speed    = 1f;
            value.weight   = 1f;
            value.wrapMode = AnimWrapMode.Loop;
            value.stopped  = false;

            return(value);
        }
예제 #2
0
        /// <summary>
        /// Allows the caller to play an animation clip during edit mode. This form of animation playback is limited as
        /// you have no control over clip properties, and features like blending, cross fade or animation events are not
        /// supported.
        ///
        /// Caller will need to manually call <see cref="UpdateFloatProperties"/> in order to apply evaluated animation data
        /// to relevant float properties (if required).
        ///
        /// Caller will also need to manually call <see cref="RefreshClipMappings"/> whenever the curves internal to the
        /// animation clip change. This should be called before the call to <see cref="UpdateFloatProperties"/>.
        /// </summary>
        /// <param name="clip">Animation clip to play.</param>
        /// <param name="startTime">Time to start playing at, in seconds.</param>
        /// <param name="freeze">If true, only the frame at the specified time will be shown, without advancing the
        ///                      animation.</param>
        internal void EditorPlay(RRef <AnimationClip> clip, float startTime, bool freeze = false)
        {
            bool inPreviewMode = Internal__togglePreviewMode(mCachedPtr, true);

            if (!inPreviewMode)
            {
                return;
            }

            if (freeze)
            {
                Sample(clip, startTime);
            }
            else
            {
                AnimationClipState clipState = AnimationClipState.Default();
                clipState.time = startTime;

                SetState(clip, clipState);
            }

            Internal__refreshClipMappings(mCachedPtr);
        }
예제 #3
0
 public AnimationUndo(AnimationClipState prevClipState, AnimationClipState clipState)
 {
     this.prevClipState = prevClipState;
     this.clipState = clipState;
 }
예제 #4
0
        /// <summary>
        /// Records current clip state for undo/redo purposes.
        /// </summary>
        internal void RecordClipState()
        {
            AnimationClipState clipState = CreateClipState();

            AnimationUndo undoCommand = new AnimationUndo(currentClipState, clipState);
            UndoRedo.RegisterCommand(undoCommand);

            currentClipState = clipState;
        }
예제 #5
0
        /// <summary>
        /// Records current clip state for undo/redo purposes.
        /// </summary>
        internal AnimationClipState CreateClipState()
        {
            AnimationClipState clipState = new AnimationClipState();

            clipState.events = new AnimationEvent[clipInfo.events.Length];
            for (int i = 0; i < clipState.events.Length; i++)
                clipState.events[i] = new AnimationEvent(clipInfo.events[i].Name, clipInfo.events[i].Time);

            foreach (var curveField in clipInfo.curves)
            {
                AnimationCurveState[] curveData = new AnimationCurveState[curveField.Value.curveInfos.Length];
                for (int i = 0; i < curveData.Length; i++)
                {
                    curveData[i] = new AnimationCurveState();

                    TangentMode[] tangentModes = curveField.Value.curveInfos[i].curve.TangentModes;
                    int numTangentModes = tangentModes.Length;
                    curveData[i].tangentModes = new TangentMode[numTangentModes];
                    Array.Copy(tangentModes, curveData[i].tangentModes, numTangentModes);

                    KeyFrame[] keyFrames = curveField.Value.curveInfos[i].curve.KeyFrames;
                    int numKeyframes = keyFrames.Length;
                    curveData[i].keyFrames = new KeyFrame[numKeyframes];
                    Array.Copy(keyFrames, curveData[i].keyFrames, numKeyframes);
                }

                clipState.curves[curveField.Key] = curveData;
            }

            return clipState;
        }
예제 #6
0
        /// <summary>
        /// Checks if the currently selected object has changed, and rebuilds the GUI and loads the animation clip if needed.
        /// </summary>
        /// <param name="force">If true the GUI rebuild and animation clip load will be forced regardless if the active
        ///                     scene object changed.</param>
        private void UpdateSelectedSO(bool force)
        {
            SceneObject so = Selection.SceneObject;
            if (selectedSO != so || force)
            {
                if (selectedSO != null && so == null)
                {
                    EditorInput.OnPointerPressed -= OnPointerPressed;
                    EditorInput.OnPointerMoved -= OnPointerMoved;
                    EditorInput.OnPointerReleased -= OnPointerReleased;
                    EditorInput.OnButtonUp -= OnButtonUp;
                }
                else if (selectedSO == null && so != null)
                {
                    EditorInput.OnPointerPressed += OnPointerPressed;
                    EditorInput.OnPointerMoved += OnPointerMoved;
                    EditorInput.OnPointerReleased += OnPointerReleased;
                    EditorInput.OnButtonUp += OnButtonUp;
                }

                SwitchState(State.Empty);

                selectedSO = so;
                zoomAmount = 0.0f;
                selectedFields.Clear();
                clipInfo = null;
                UndoRedo.Clear();

                RebuildGUI();

                // Load existing clip if one exists
                if (selectedSO != null)
                {
                    Animation animation = selectedSO.GetComponent<Animation>();
                    if (animation != null)
                    {
                        AnimationClip clip = animation.DefaultClip;
                        if (clip != null)
                            LoadAnimClip(clip);
                    }
                }

                if(clipInfo == null)
                    clipInfo = new EditorAnimClipInfo();

                SwitchState(State.Normal);

                currentClipState = CreateClipState();
                if (selectedSO != null)
                {
                    // Select first curve by default
                    foreach (var KVP in clipInfo.curves)
                    {
                        SelectField(KVP.Key, false);
                        break;
                    }

                    UpdateDisplayedCurves(true);
                }
            }
        }
예제 #7
0
        /// <summary>
        /// Updates the current animation fields from the keyframes and events in the provided state.
        /// </summary>
        /// <param name="animationClipState">Saved state of an animation clip.</param>
        internal void ApplyClipState(AnimationClipState animationClipState)
        {
            if (state == State.Empty)
                return;

            SwitchState(State.Normal);

            AnimationEvent[] events = animationClipState.events;
            clipInfo.events = new AnimationEvent[events.Length];
            for(int i = 0; i < events.Length; i++)
                clipInfo.events[i] = new AnimationEvent(events[i].Name, events[i].Time);

            foreach (var KVP in animationClipState.curves)
            {
                FieldAnimCurves fieldCurves;
                if (!clipInfo.curves.TryGetValue(KVP.Key, out fieldCurves))
                    continue;

                for (int i = 0; i < fieldCurves.curveInfos.Length; i++)
                {
                    AnimationCurve curve = fieldCurves.curveInfos[i].curve.Normal;
                    curve.KeyFrames = KVP.Value[i].keyFrames;

                    fieldCurves.curveInfos[i].curve = new EdAnimationCurve(curve, KVP.Value[i].tangentModes);
                }

                clipInfo.curves[KVP.Key] = fieldCurves;
            }

            // Clear all keyframes from curves not in the stored state
            foreach (var currentKVP in clipInfo.curves)
            {
                bool found = false;
                foreach (var stateKVP in animationClipState.curves)
                {
                    if (currentKVP.Key == stateKVP.Key)
                    {
                        found = true;
                        break;
                    }
                }

                if (found)
                    continue;

                FieldAnimCurves fieldCurves = currentKVP.Value;
                for (int i = 0; i < fieldCurves.curveInfos.Length; i++)
                {
                    AnimationCurve curve = currentKVP.Value.curveInfos[i].curve.Normal;
                    curve.KeyFrames = new KeyFrame[0];

                    fieldCurves.curveInfos[i].curve = new EdAnimationCurve(curve, new TangentMode[0]);
                }
            }

            currentClipState = animationClipState;

            UpdateDisplayedCurves();

            ApplyClipChanges();
            PreviewFrame(currentFrameIdx);

            EditorApplication.SetProjectDirty();
        }
예제 #8
0
 private static extern void Internal_setState(IntPtr thisPtr, RRef <AnimationClip> clip, ref AnimationClipState state);
예제 #9
0
 private static extern bool Internal_getState(IntPtr thisPtr, RRef <AnimationClip> clip, out AnimationClipState state);
예제 #10
0
 /// <summary>
 /// Changes the state of a playing animation clip. If animation clip is not currently playing the playback is started for
 /// the clip.
 /// </summary>
 /// <param name="clip">Clip to change the state for.</param>
 /// <param name="state">New state of the animation (e.g. changing the time for seeking).</param>
 public void SetState(RRef <AnimationClip> clip, AnimationClipState state)
 {
     Internal_setState(mCachedPtr, clip, ref state);
 }
예제 #11
0
 /// <summary>Retrieves detailed information about a currently playing animation clip.</summary>
 /// <param name="clip">Clip to retrieve the information for.</param>
 /// <param name="state">
 /// Animation clip state containing the requested information. Only valid if the method returns true.
 /// </param>
 /// <returns>True if the state was found (animation clip is playing), false otherwise.</returns>
 public bool GetState(RRef <AnimationClip> clip, out AnimationClipState state)
 {
     return(Internal_getState(mCachedPtr, clip, out state));
 }