/// <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); }
/// <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); }
public AnimationUndo(AnimationClipState prevClipState, AnimationClipState clipState) { this.prevClipState = prevClipState; this.clipState = clipState; }
/// <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; }
/// <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; }
/// <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); } } }
/// <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(); }
private static extern void Internal_setState(IntPtr thisPtr, RRef <AnimationClip> clip, ref AnimationClipState state);
private static extern bool Internal_getState(IntPtr thisPtr, RRef <AnimationClip> clip, out AnimationClipState state);
/// <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); }
/// <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)); }