diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 5352b75..adb380f 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.2.6] +### Changed + - Removed the `Play` from the playtype, now is only `Backward` and `Forward` and `Forward` is the default one + - Implement manual reset of editor changes to avoid issues while previewing animation and stop + - Refactored the preview controllers to allow all the controllers to be able to play the animation when needed + - Improved inspector performance + +### Added + - Implemented a bunch of feedback from [nindim](https://github.com/nindim) + ## [0.2.5] ### Changed - Replaced TypeUtility for [Unity TypeCache](https://docs.unity3d.com/2019.4/Documentation/ScriptReference/TypeCache.html) @@ -95,6 +105,7 @@ Thanks for all the [suggestions](https://github.com/brunomikoski/Animation-Seque ### [Unreleased] +[0.2.6]: https://github.com/brunomikoski/Animation-Sequencer/releases/tag/v0.2.6 [0.2.5]: https://github.com/brunomikoski/Animation-Sequencer/releases/tag/v0.2.5 [0.2.4]: https://github.com/brunomikoski/Animation-Sequencer/releases/tag/v0.2.4 [0.2.3]: https://github.com/brunomikoski/Animation-Sequencer/releases/tag/v0.2.3 diff --git a/Scripts/Editor/Core/AnimationSequencerControllerCustomEditor.cs b/Scripts/Editor/Core/AnimationSequencerControllerCustomEditor.cs index bef379e..9906f63 100644 --- a/Scripts/Editor/Core/AnimationSequencerControllerCustomEditor.cs +++ b/Scripts/Editor/Core/AnimationSequencerControllerCustomEditor.cs @@ -30,20 +30,27 @@ private static AnimationStepAdvancedDropdown AnimationStepAdvancedDropdown private bool showSettings = false; private bool showCallbacks = false; private bool showSequenceSettings = false; + private bool showSteps = true; private void OnEnable() { sequencerController = target as AnimationSequencerController; - reorderableList = new ReorderableList(serializedObject, serializedObject.FindProperty("animationSteps"), true, true, true, true); + reorderableList = new ReorderableList(serializedObject, serializedObject.FindProperty("animationSteps"), true, false, true, true); reorderableList.drawElementCallback += OnDrawAnimationStep; reorderableList.elementHeightCallback += GetAnimationStepHeight; reorderableList.onAddDropdownCallback += OnClickToAddNew; reorderableList.onRemoveCallback += OnClickToRemove; reorderableList.onReorderCallback += OnListOrderChanged; reorderableList.drawHeaderCallback += OnDrawerHeader; + EditorApplication.playModeStateChanged += OnEditorPlayModeChanged; Repaint(); } + public override bool RequiresConstantRepaint() + { + return true; + } + private void OnDisable() { reorderableList.drawElementCallback -= OnDrawAnimationStep; @@ -52,11 +59,30 @@ private void OnDisable() reorderableList.onRemoveCallback -= OnClickToRemove; reorderableList.onReorderCallback -= OnListOrderChanged; reorderableList.drawHeaderCallback -= OnDrawerHeader; + EditorApplication.playModeStateChanged -= OnEditorPlayModeChanged; if (!Application.isPlaying) - DOTweenEditorPreview.Stop(); + { + if (DOTweenEditorPreview.isPreviewing) + { + sequencerController.ResetToInitialState(); + DOTweenEditorPreview.Stop(); + } + } } + private void OnEditorPlayModeChanged(PlayModeStateChange playModeState) + { + if (playModeState == PlayModeStateChange.ExitingEditMode) + { + if (DOTweenEditorPreview.isPreviewing) + { + sequencerController.ResetToInitialState(); + DOTweenEditorPreview.Stop(); + } + } + } + private void OnDrawerHeader(Rect rect) { EditorGUI.LabelField(rect, "Animation Steps"); @@ -109,12 +135,17 @@ public override void OnInspectorGUI() DrawFoldoutArea("Callback", ref showCallbacks, DrawCallbacks); DrawFoldoutArea("Preview", ref showPreview, DrawPreviewControls); DrawFoldoutArea("Sequence Settings", ref showSequenceSettings, DrawSequenceSettings); + DrawFoldoutArea("Steps", ref showSteps, DrawAnimationSteps); + } + + private void DrawAnimationSteps() + { bool wasGUIEnabled = GUI.enabled; if (DOTweenEditorPreview.isPreviewing) GUI.enabled = false; reorderableList.DoLayoutList(); - + GUI.enabled = wasGUIEnabled; } @@ -165,7 +196,6 @@ private void DrawSequenceSettings() SerializedProperty updateTypeSerializedProperty = serializedObject.FindProperty("updateType"); SerializedProperty timeScaleIndependentSerializedProperty = serializedObject.FindProperty("timeScaleIndependent"); - SerializedProperty autoKillSerializedProperty = serializedObject.FindProperty("autoKill"); SerializedProperty sequenceDirectionSerializedProperty = serializedObject.FindProperty("playType"); SerializedProperty loopsSerializedProperty = serializedObject.FindProperty("loops"); SerializedProperty loopTypeSerializedProperty = serializedObject.FindProperty("loopType"); @@ -173,7 +203,6 @@ private void DrawSequenceSettings() using (EditorGUI.ChangeCheckScope changedCheck = new EditorGUI.ChangeCheckScope()) { EditorGUILayout.PropertyField(timeScaleIndependentSerializedProperty); - EditorGUILayout.PropertyField(autoKillSerializedProperty); EditorGUILayout.PropertyField(sequenceDirectionSerializedProperty); EditorGUILayout.PropertyField(updateTypeSerializedProperty); @@ -182,20 +211,6 @@ private void DrawSequenceSettings() if (loopsSerializedProperty.intValue != 0) { EditorGUILayout.PropertyField(loopTypeSerializedProperty); - - if (loopTypeSerializedProperty.enumValueIndex != 0 && !Application.isPlaying) - { - EditorGUILayout.HelpBox( - "Anything but Restart loop type, can cause issues when stopping the preview on the editor," + - " strongly advice to save the prefab so you can easily revert it ", MessageType.Warning); - } - } - - if (loopsSerializedProperty.intValue == -1 && !Application.isPlaying) - { - EditorGUILayout.HelpBox( - "Infinity loops breaks the editor, in editor time the maximum of 10 loops will be set", - MessageType.Warning); } if (changedCheck.changed) @@ -215,78 +230,67 @@ private void DrawPreviewControls() GUILayout.FlexibleSpace(); bool guiEnabled = GUI.enabled; - GUI.enabled = sequencerController.PlayingSequence != null && Application.isPlaying || DOTweenEditorPreview.isPreviewing; GUIStyle previewButtonStyle = new GUIStyle(GUI.skin.button); previewButtonStyle.fixedWidth = previewButtonStyle.fixedHeight = 40; if (GUILayout.Button(AnimationSequenceEditorGUIUtility.BackButtonGUIContent, previewButtonStyle)) { + if (!sequencerController.IsPlaying) + PlaySequence(); + sequencerController.Rewind(); } - GUI.enabled = true; - if (!DOTweenEditorPreview.isPreviewing && !Application.isPlaying) + if (GUILayout.Button(AnimationSequenceEditorGUIUtility.StepBackGUIContent, previewButtonStyle)) { - if (GUILayout.Button(AnimationSequenceEditorGUIUtility.PlayButtonGUIContent, previewButtonStyle)) + if(!sequencerController.IsPlaying) + PlaySequence(); + + StepBack(); + } + + if (sequencerController.IsPlaying) + { + if (GUILayout.Button(AnimationSequenceEditorGUIUtility.PauseButtonGUIContent, previewButtonStyle)) { - if (!Application.isPlaying) - DOTweenEditorPreview.Start(); - - sequencerController.Play(); - - if (!Application.isPlaying) - DOTweenEditorPreview.PrepareTweenForPreview(sequencerController.PlayingSequence); + sequencerController.Pause(); } } else { - if (!sequencerController.IsPlaying) - { - if (GUILayout.Button(AnimationSequenceEditorGUIUtility.PlayButtonGUIContent, previewButtonStyle)) - { - if (sequencerController.PlayingSequence == null) - { - sequencerController.Play(); - } - else - { - if (sequencerController.PlayingSequence.IsComplete()) - sequencerController.Rewind(); - - sequencerController.TogglePause(); - } - } - } - else + if (GUILayout.Button(AnimationSequenceEditorGUIUtility.PlayButtonGUIContent, previewButtonStyle)) { - if (GUILayout.Button(AnimationSequenceEditorGUIUtility.PauseButtonGUIContent, previewButtonStyle)) - { - sequencerController.TogglePause(); - } + PlaySequence(); } } - GUI.enabled = sequencerController.PlayingSequence != null && Application.isPlaying || DOTweenEditorPreview.isPreviewing; - if (GUILayout.Button(AnimationSequenceEditorGUIUtility.ForwardButtonGUIContent, previewButtonStyle)) + + if (GUILayout.Button(AnimationSequenceEditorGUIUtility.StepNextGUIContent, previewButtonStyle)) { - sequencerController.Complete(); - } + if(!sequencerController.IsPlaying) + PlaySequence(); - float elapsedPercentage = 0; - if (sequencerController.PlayingSequence != null) - elapsedPercentage = sequencerController.PlayingSequence.ElapsedPercentage(); - if (!DOTweenEditorPreview.isPreviewing - || sequencerController.PlayingSequence.IsPlaying() && !Mathf.Approximately(elapsedPercentage, 0) - || !Mathf.Approximately(elapsedPercentage, 1)) + StepNext(); + } + + if (GUILayout.Button(AnimationSequenceEditorGUIUtility.ForwardButtonGUIContent, previewButtonStyle)) { - GUI.enabled = false; + if (!sequencerController.IsPlaying) + PlaySequence(); + + sequencerController.Complete(); } if (!Application.isPlaying) { + GUI.enabled = DOTweenEditorPreview.isPreviewing; if (GUILayout.Button(AnimationSequenceEditorGUIUtility.StopButtonGUIContent, previewButtonStyle)) { + sequencerController.Rewind(); + DOTween.Kill(sequencerController.PlayingSequence); DOTweenEditorPreview.Stop(); + sequencerController.ResetToInitialState(); + sequencerController.ClearPlayingSequence(); } } @@ -295,42 +299,91 @@ private void DrawPreviewControls() EditorGUILayout.EndHorizontal(); DrawTimeScaleSlider(); DrawProgressSlider(); - if (DOTweenEditorPreview.isPreviewing) + } + + private void StepBack() + { + if (!sequencerController.IsPlaying) + PlaySequence(); + + sequencerController.PlayingSequence.Goto((sequencerController.PlayingSequence.ElapsedPercentage() - + 0.01f) * sequencerController.PlayingSequence.Duration()); + } + + private void StepNext() + { + if (!sequencerController.IsPlaying) + PlaySequence(); + + sequencerController.PlayingSequence.Goto((sequencerController.PlayingSequence.ElapsedPercentage() + + 0.01f) * sequencerController.PlayingSequence.Duration()); + } + + private void PlaySequence() + { + if (!Application.isPlaying) + { + if (!DOTweenEditorPreview.isPreviewing) + { + DOTweenEditorPreview.Start(); + + sequencerController.Play(); + + DOTweenEditorPreview.PrepareTweenForPreview(sequencerController.PlayingSequence); + } + else + { + if (sequencerController.PlayingSequence == null) + { + sequencerController.Play(); + } + else + { + if (sequencerController.PlayingSequence.IsComplete()) + sequencerController.Rewind(); + + sequencerController.TogglePause(); + } + } + } + else { - EditorGUILayout.HelpBox( - "Please don't unselect this object or enter play mode before stopping Preview mode at the correct " - + "position (0% or 100% depending on the direction of the tween). Also don't save the scene!", - MessageType.Info - ); + if (sequencerController.PlayingSequence == null) + sequencerController.Play(); + else + { + if (sequencerController.PlayingSequence.IsActive()) + sequencerController.TogglePause(); + else + sequencerController.Play(); + } } } private void DrawProgressSlider() { GUILayout.FlexibleSpace(); - bool guiEnabled = GUI.enabled; - - GUI.enabled = sequencerController.PlayingSequence != null && DOTweenEditorPreview.isPreviewing; EditorGUI.BeginChangeCheck(); - float tweenProgress = 1; + float tweenProgress = 0; - if (sequencerController.PlayingSequence != null) + if (sequencerController.PlayingSequence != null && sequencerController.PlayingSequence.IsActive()) tweenProgress = sequencerController.PlayingSequence.ElapsedPercentage(); + else + tweenProgress = 0; EditorGUILayout.LabelField("Progress"); tweenProgress = EditorGUILayout.Slider(tweenProgress, 0, 1); if (EditorGUI.EndChangeCheck()) { - if (sequencerController.PlayingSequence != null) - { - sequencerController.PlayingSequence.Goto(tweenProgress * - sequencerController.PlayingSequence.Duration()); - } + if(!sequencerController.IsPlaying) + PlaySequence(); + + sequencerController.PlayingSequence.Goto(tweenProgress * + sequencerController.PlayingSequence.Duration()); } - GUI.enabled = guiEnabled; GUILayout.FlexibleSpace(); } @@ -382,13 +435,8 @@ private void OnDrawAnimationStep(Rect rect, int index, bool isActive, bool isFoc SerializedProperty element = reorderableList.serializedProperty.GetArrayElementAtIndex(index); SerializedProperty flowTypeSerializedProperty = element.FindPropertyRelative("flowType"); - if (element.TryGetTargetObjectOfProperty(out AnimationStepBase animationStepBase)) - { - if (animationStepBase.IsPlaying) - { - reorderableList.index = index; - } - } + if (!element.TryGetTargetObjectOfProperty(out AnimationStepBase animationStepBase)) + return; FlowType flowType = (FlowType)flowTypeSerializedProperty.enumValueIndex; diff --git a/Scripts/Editor/Core/DOTweenActions/AnimationSequenceEditorGUIUtility.cs b/Scripts/Editor/Core/DOTweenActions/AnimationSequenceEditorGUIUtility.cs index 53f1c98..8ab19b1 100644 --- a/Scripts/Editor/Core/DOTweenActions/AnimationSequenceEditorGUIUtility.cs +++ b/Scripts/Editor/Core/DOTweenActions/AnimationSequenceEditorGUIUtility.cs @@ -130,6 +130,36 @@ internal static GUIContent BackButtonGUIContent } } + private static GUIContent cachedStepBackGUIContent; + internal static GUIContent StepBackGUIContent + { + get + { + if (cachedStepBackGUIContent == null) + { + cachedStepBackGUIContent = EditorGUIUtility.IconContent("Animation.PrevKey"); + cachedStepBackGUIContent.tooltip = "Step Back"; + } + + return cachedStepBackGUIContent; + } + } + + private static GUIContent cachedStepNextGUIContent; + internal static GUIContent StepNextGUIContent + { + get + { + if (cachedStepNextGUIContent == null) + { + cachedStepNextGUIContent = EditorGUIUtility.IconContent("Animation.NextKey"); + cachedStepNextGUIContent.tooltip = "Step Next"; + } + + return cachedStepNextGUIContent; + } + } + private static GUIContent cachedStopButtonGUIContent; internal static GUIContent StopButtonGUIContent { diff --git a/Scripts/Runtime/Core/AnimationSequencerController.cs b/Scripts/Runtime/Core/AnimationSequencerController.cs index 393d8e4..2c51b60 100644 --- a/Scripts/Runtime/Core/AnimationSequencerController.cs +++ b/Scripts/Runtime/Core/AnimationSequencerController.cs @@ -11,41 +11,26 @@ public class AnimationSequencerController : MonoBehaviour { private enum PlayType { - Play, - Backward, - Forward + Forward, + Backward } [SerializeReference] private AnimationStepBase[] animationSteps = new AnimationStepBase[0]; - - [SerializeField] - private float duration; - public float Duration => duration; - [SerializeField] private UpdateType updateType = UpdateType.Normal; [SerializeField] private bool timeScaleIndependent = false; [SerializeField] - private bool autoKill = false; - [SerializeField] private bool playOnAwake; [SerializeField] private bool pauseOnAwake; [SerializeField] - private PlayType playType = PlayType.Play; - + private PlayType playType = PlayType.Forward; [SerializeField] private int loops = 0; [SerializeField] private LoopType loopType = LoopType.Restart; - - private Sequence playingSequence; - public Sequence PlayingSequence => playingSequence; - - public bool IsPlaying => playingSequence != null && playingSequence.IsPlaying(); - [SerializeField] private UnityEvent onStartEvent = new UnityEvent(); public UnityEvent OnStartEvent => onStartEvent; @@ -55,7 +40,12 @@ private enum PlayType [SerializeField] private UnityEvent onProgressEvent = new UnityEvent(); public UnityEvent OnProgressEvent => onProgressEvent; - + + private Sequence playingSequence; + public Sequence PlayingSequence => playingSequence; + + public bool IsPlaying => playingSequence != null && playingSequence.IsActive() && playingSequence.IsPlaying(); + public bool IsPaused => playingSequence != null && playingSequence.IsActive() && !playingSequence.IsPlaying(); private void Awake() { @@ -76,7 +66,7 @@ private void OnDestroy() public void Play(Action onCompleteCallback = null) { DOTween.Kill(this); - playingSequence?.Kill(); + DOTween.Kill(playingSequence); if (onCompleteCallback != null) onFinishedEvent.AddListener(onCompleteCallback.Invoke); @@ -160,16 +150,21 @@ public Sequence GenerateSequence() for (int i = 0; i < animationSteps.Length; i++) { - AnimationStepBase animationStepBase = animationSteps[i]; - - animationStepBase.AddTweenToSequence(sequence); + animationSteps[i].AddTweenToSequence(sequence); } sequence.SetTarget(this); sequence.SetUpdate(updateType, timeScaleIndependent); sequence.OnComplete(() => { - onStartEvent.Invoke(); + if (playType == PlayType.Forward) + { + onStartEvent.Invoke(); + } + else + { + onFinishedEvent.Invoke(); + } }); sequence.OnUpdate(() => { @@ -177,11 +172,16 @@ public Sequence GenerateSequence() }); sequence.OnComplete(() => { - onFinishedEvent.Invoke(); + if (playType == PlayType.Forward) + { + onFinishedEvent.Invoke(); + } + else + { + onStartEvent.Invoke(); + } }); - sequence.SetAutoKill(autoKill); - int targetLoops = loops; if (!Application.isPlaying) @@ -193,5 +193,19 @@ public Sequence GenerateSequence() sequence.SetLoops(targetLoops, loopType); return sequence; } + + public void ResetToInitialState() + { + for (int i = animationSteps.Length - 1; i >= 0; i--) + { + animationSteps[i].ResetToInitialState(); + } + } + + public void ClearPlayingSequence() + { + DOTween.Kill(playingSequence); + playingSequence = null; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/AnchoredPositionMoveDOTweenActionBase.cs b/Scripts/Runtime/Core/DOTweenActions/AnchoredPositionMoveDOTweenActionBase.cs index a20e23e..6720c84 100644 --- a/Scripts/Runtime/Core/DOTweenActions/AnchoredPositionMoveDOTweenActionBase.cs +++ b/Scripts/Runtime/Core/DOTweenActions/AnchoredPositionMoveDOTweenActionBase.cs @@ -15,6 +15,7 @@ public abstract class AnchoredPositionMoveDOTweenActionBase : DOTweenActionBase private AxisConstraint axisConstraint; private RectTransform rectTransform; + private Vector2 previousAnchorPosition; protected override Tweener GenerateTween_Internal(GameObject target, float duration) { @@ -29,6 +30,7 @@ protected override Tweener GenerateTween_Internal(GameObject target, float durat } } + previousAnchorPosition = rectTransform.anchoredPosition; TweenerCore anchorPosTween = rectTransform.DOAnchorPos(GetPosition(), duration); anchorPosTween.SetOptions(axisConstraint); @@ -37,5 +39,13 @@ protected override Tweener GenerateTween_Internal(GameObject target, float durat } protected abstract Vector2 GetPosition(); + + public override void ResetToInitialState() + { + if (rectTransform == null) + return; + + rectTransform.anchoredPosition = previousAnchorPosition; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/ColorGraphicDOTWeen.cs b/Scripts/Runtime/Core/DOTweenActions/ColorGraphicDOTWeen.cs index 7e2bf47..82eba4a 100644 --- a/Scripts/Runtime/Core/DOTweenActions/ColorGraphicDOTWeen.cs +++ b/Scripts/Runtime/Core/DOTweenActions/ColorGraphicDOTWeen.cs @@ -17,6 +17,7 @@ public sealed class ColorGraphicDOTWeen : DOTweenActionBase private Color color; private Graphic targetGraphic; + private Color previousColor; protected override Tweener GenerateTween_Internal(GameObject target, float duration) { @@ -30,9 +31,18 @@ protected override Tweener GenerateTween_Internal(GameObject target, float durat } } + previousColor = targetGraphic.color; TweenerCore graphicTween = targetGraphic.DOColor(color, duration); return graphicTween; } + + public override void ResetToInitialState() + { + if (targetGraphic == null) + return; + + targetGraphic.color = previousColor; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/DOTweenActionBase.cs b/Scripts/Runtime/Core/DOTweenActions/DOTweenActionBase.cs index 36105b5..4eba5c9 100644 --- a/Scripts/Runtime/Core/DOTweenActions/DOTweenActionBase.cs +++ b/Scripts/Runtime/Core/DOTweenActions/DOTweenActionBase.cs @@ -37,5 +37,7 @@ public Tween GenerateTween(GameObject target, float duration) tween.SetRelative(isRelative); return tween; } + + public abstract void ResetToInitialState(); } } diff --git a/Scripts/Runtime/Core/DOTweenActions/FadeCanvasGroupDOTweenAction.cs b/Scripts/Runtime/Core/DOTweenActions/FadeCanvasGroupDOTweenAction.cs index 83ef802..c48189c 100644 --- a/Scripts/Runtime/Core/DOTweenActions/FadeCanvasGroupDOTweenAction.cs +++ b/Scripts/Runtime/Core/DOTweenActions/FadeCanvasGroupDOTweenAction.cs @@ -16,6 +16,7 @@ public sealed class FadeCanvasGroupDOTweenAction : DOTweenActionBase [SerializeField] private float alpha; private CanvasGroup canvasGroup; + private float previousFade; protected override Tweener GenerateTween_Internal(GameObject target, float duration) { @@ -30,8 +31,17 @@ protected override Tweener GenerateTween_Internal(GameObject target, float durat } } + previousFade = canvasGroup.alpha; TweenerCore canvasTween = canvasGroup.DOFade(alpha, duration); return canvasTween; } + + public override void ResetToInitialState() + { + if (canvasGroup == null) + return; + + canvasGroup.alpha = previousFade; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/FadeGraphicDOTweenAction.cs b/Scripts/Runtime/Core/DOTweenActions/FadeGraphicDOTweenAction.cs index c65d436..201cdee 100644 --- a/Scripts/Runtime/Core/DOTweenActions/FadeGraphicDOTweenAction.cs +++ b/Scripts/Runtime/Core/DOTweenActions/FadeGraphicDOTweenAction.cs @@ -17,6 +17,7 @@ public sealed class FadeGraphicDOTweenAction : DOTweenActionBase private float alpha; private Graphic targetGraphic; + private float previousAlpha; protected override Tweener GenerateTween_Internal(GameObject target, float duration) { @@ -30,9 +31,19 @@ protected override Tweener GenerateTween_Internal(GameObject target, float durat } } + previousAlpha = targetGraphic.color.a; TweenerCore graphicTween = targetGraphic.DOFade(alpha, duration); return graphicTween; } + public override void ResetToInitialState() + { + if (targetGraphic == null) + return; + + Color color = targetGraphic.color; + color.a = previousAlpha; + targetGraphic.color = color; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/FillImageDOTweenAction.cs b/Scripts/Runtime/Core/DOTweenActions/FillImageDOTweenAction.cs index 57a84f3..309cf22 100644 --- a/Scripts/Runtime/Core/DOTweenActions/FillImageDOTweenAction.cs +++ b/Scripts/Runtime/Core/DOTweenActions/FillImageDOTweenAction.cs @@ -10,13 +10,13 @@ namespace BrunoMikoski.AnimationSequencer [Serializable] public sealed class FillImageDOTweenAction : DOTweenActionBase { - public override Type TargetComponentType => typeof(Image); public override string DisplayName => "Fill Amount"; [SerializeField, Range(0, 1)] private float fillAmount; private Image image; + private float previousFillAmount; protected override Tweener GenerateTween_Internal(GameObject target, float duration) { @@ -29,10 +29,18 @@ protected override Tweener GenerateTween_Internal(GameObject target, float durat return null; } } - + + previousFillAmount = image.fillAmount; TweenerCore tween = image.DOFillAmount(fillAmount, duration); return tween; } + public override void ResetToInitialState() + { + if (image == null) + return; + + image.fillAmount = previousFillAmount; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/MoveDOTweenActionBase.cs b/Scripts/Runtime/Core/DOTweenActions/MoveDOTweenActionBase.cs index 8abb57b..21f5fb8 100644 --- a/Scripts/Runtime/Core/DOTweenActions/MoveDOTweenActionBase.cs +++ b/Scripts/Runtime/Core/DOTweenActions/MoveDOTweenActionBase.cs @@ -16,20 +16,39 @@ public abstract class MoveDOTweenActionBase : DOTweenActionBase [SerializeField] private AxisConstraint axisConstraint; + private Vector3 previousPosition; + private GameObject previousTarget; + public override string DisplayName => "Move to Position"; protected override Tweener GenerateTween_Internal(GameObject target, float duration) { TweenerCore moveTween; + previousTarget = target; if (localMove) + { + previousPosition = target.transform.localPosition; moveTween = target.transform.DOLocalMove(GetPosition(), duration); + + } else + { + previousPosition = target.transform.position; moveTween = target.transform.DOMove(GetPosition(), duration); + } moveTween.SetOptions(axisConstraint); return moveTween; } protected abstract Vector3 GetPosition(); + + public override void ResetToInitialState() + { + if (localMove) + previousTarget.transform.localPosition = previousPosition; + else + previousTarget.transform.position = previousPosition; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/PathDOTweenActionBase.cs b/Scripts/Runtime/Core/DOTweenActions/PathDOTweenActionBase.cs index 46f5ea6..72d7e08 100644 --- a/Scripts/Runtime/Core/DOTweenActions/PathDOTweenActionBase.cs +++ b/Scripts/Runtime/Core/DOTweenActions/PathDOTweenActionBase.cs @@ -23,19 +23,40 @@ public abstract class PathDOTweenActionBase : DOTweenActionBase [SerializeField] private PathType pathType = PathType.CatmullRom; + private Transform previousTarget; + private Vector3 previousPosition; + protected override Tweener GenerateTween_Internal(GameObject target, float duration) { TweenerCore tween; - + + previousTarget = target.transform; if (!isLocal) + { tween = target.transform.DOPath(GetPathPositions(), duration, pathType, pathMode, resolution, gizmoColor); + previousPosition = target.transform.position; + } else + { tween = target.transform.DOLocalPath(GetPathPositions(), duration, pathType, pathMode, resolution, gizmoColor); + previousPosition = target.transform.localPosition; + } return tween; } protected abstract Vector3[] GetPathPositions(); + public override void ResetToInitialState() + { + if (isLocal) + { + previousTarget.transform.localPosition = previousPosition; + } + else + { + previousTarget.transform.position = previousPosition; + } + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/PunchPositionDOTweenAction.cs b/Scripts/Runtime/Core/DOTweenActions/PunchPositionDOTweenAction.cs index def5af4..9b35f4d 100644 --- a/Scripts/Runtime/Core/DOTweenActions/PunchPositionDOTweenAction.cs +++ b/Scripts/Runtime/Core/DOTweenActions/PunchPositionDOTweenAction.cs @@ -19,12 +19,21 @@ public sealed class PunchPositionDOTweenAction : DOTweenActionBase [SerializeField] private bool snapping; + private Transform previousTarget; + private Vector3 previousPosition; + protected override Tweener GenerateTween_Internal(GameObject target, float duration) { + previousTarget = target.transform; + previousPosition = target.transform.position; Tweener tween = target.transform.DOPunchPosition(punch, duration, vibrato, elasticity, snapping); return tween; } + public override void ResetToInitialState() + { + previousTarget.position = previousPosition; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/PunchRotationDOTweenAction.cs b/Scripts/Runtime/Core/DOTweenActions/PunchRotationDOTweenAction.cs index fee417d..ce0c790 100644 --- a/Scripts/Runtime/Core/DOTweenActions/PunchRotationDOTweenAction.cs +++ b/Scripts/Runtime/Core/DOTweenActions/PunchRotationDOTweenAction.cs @@ -17,12 +17,21 @@ public sealed class PunchRotationDOTweenAction : DOTweenActionBase [SerializeField] private float elasticity = 1f; + private Transform previousTarget; + private Quaternion previousRotation; + protected override Tweener GenerateTween_Internal(GameObject target, float duration) - { + { + previousTarget = target.transform; + previousRotation = target.transform.rotation; Tweener tween = target.transform.DOPunchRotation(punch, duration, vibrato, elasticity); return tween; } + public override void ResetToInitialState() + { + previousTarget.rotation = previousRotation; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/PunchScaleDOTweenAction.cs b/Scripts/Runtime/Core/DOTweenActions/PunchScaleDOTweenAction.cs index dc67a27..1a17260 100644 --- a/Scripts/Runtime/Core/DOTweenActions/PunchScaleDOTweenAction.cs +++ b/Scripts/Runtime/Core/DOTweenActions/PunchScaleDOTweenAction.cs @@ -17,12 +17,22 @@ public sealed class PunchScaleDOTweenAction : DOTweenActionBase [SerializeField] private float elasticity = 1f; + private Transform previousTarget; + private Vector3 previousScale; + protected override Tweener GenerateTween_Internal(GameObject target, float duration) { + previousTarget = target.transform; + previousScale = previousTarget.localScale; + Tweener tween = target.transform.DOPunchScale(punch, duration, vibrato, elasticity); return tween; } + public override void ResetToInitialState() + { + previousTarget.localScale = previousScale; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/RotateDOTweenActionBase.cs b/Scripts/Runtime/Core/DOTweenActions/RotateDOTweenActionBase.cs index 96b2ae4..e11d1fa 100644 --- a/Scripts/Runtime/Core/DOTweenActions/RotateDOTweenActionBase.cs +++ b/Scripts/Runtime/Core/DOTweenActions/RotateDOTweenActionBase.cs @@ -18,18 +18,39 @@ public abstract class RotateDOTweenActionBase : DOTweenActionBase [SerializeField] private RotateMode rotationMode = RotateMode.Fast; + private Transform previousTarget; + private Quaternion previousRotation; + protected override Tweener GenerateTween_Internal(GameObject target, float duration) { + previousTarget = target.transform; TweenerCore localTween; if (local) + { + previousRotation = target.transform.localRotation; localTween = target.transform.DOLocalRotate(GetRotation(), duration, rotationMode); + } else + { + previousRotation = target.transform.rotation; localTween = target.transform.DORotate(GetRotation(), duration, rotationMode); + } return localTween; } protected abstract Vector3 GetRotation(); + + public override void ResetToInitialState() + { + if (previousTarget == null) + return; + + if (!local) + previousTarget.rotation = previousRotation; + else + previousTarget.localRotation = previousRotation; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/ScaleDOTweenAction.cs b/Scripts/Runtime/Core/DOTweenActions/ScaleDOTweenAction.cs index 487be16..e2831be 100644 --- a/Scripts/Runtime/Core/DOTweenActions/ScaleDOTweenAction.cs +++ b/Scripts/Runtime/Core/DOTweenActions/ScaleDOTweenAction.cs @@ -17,12 +17,26 @@ public sealed class ScaleDOTweenAction : DOTweenActionBase [SerializeField] private AxisConstraint axisConstraint; + private Vector3? previousState; + private GameObject previousTarget; + protected override Tweener GenerateTween_Internal(GameObject target, float duration) { + previousState = target.transform.localScale; + previousTarget = target; + TweenerCore scaleTween = target.transform.DOScale(scale, duration).SetEase(ease); scaleTween.SetOptions(axisConstraint); return scaleTween; } + + public override void ResetToInitialState() + { + if (!previousState.HasValue) + return; + + previousTarget.transform.localScale = previousState.Value; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/ShakePositionDOTweenAction.cs b/Scripts/Runtime/Core/DOTweenActions/ShakePositionDOTweenAction.cs index 255874d..d7a13c5 100644 --- a/Scripts/Runtime/Core/DOTweenActions/ShakePositionDOTweenAction.cs +++ b/Scripts/Runtime/Core/DOTweenActions/ShakePositionDOTweenAction.cs @@ -21,12 +21,21 @@ public sealed class ShakePositionDOTweenAction : DOTweenActionBase [SerializeField] private bool fadeout = true; + private Transform previousTarget; + private Vector3 previousPosition; + protected override Tweener GenerateTween_Internal(GameObject target, float duration) { + previousTarget = target.transform; + previousPosition = previousTarget.position; Tweener tween = target.transform.DOShakePosition(duration, strength, vibrato, randomness, snapping, fadeout); return tween; } + public override void ResetToInitialState() + { + previousTarget.position = previousPosition; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/ShakeRotationDOTweenAction.cs b/Scripts/Runtime/Core/DOTweenActions/ShakeRotationDOTweenAction.cs index 28865e0..6f190a1 100644 --- a/Scripts/Runtime/Core/DOTweenActions/ShakeRotationDOTweenAction.cs +++ b/Scripts/Runtime/Core/DOTweenActions/ShakeRotationDOTweenAction.cs @@ -20,12 +20,22 @@ public sealed class ShakeRotationDOTweenAction : DOTweenActionBase [SerializeField] private bool fadeout = true; + private Transform previousTarget; + private Quaternion previousRotation; + protected override Tweener GenerateTween_Internal(GameObject target, float duration) { - Tweener tween = target.transform.DOShakeRotation(duration, strength, vibrato, randomness, fadeout); + previousTarget = target.transform; + previousRotation = previousTarget.rotation; + + Tweener tween = previousTarget.DOShakeRotation(duration, strength, vibrato, randomness, fadeout); return tween; } + public override void ResetToInitialState() + { + previousTarget.rotation = previousRotation; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/ShakeScaleDOTweenAction.cs b/Scripts/Runtime/Core/DOTweenActions/ShakeScaleDOTweenAction.cs index 20b9643..08ed39c 100644 --- a/Scripts/Runtime/Core/DOTweenActions/ShakeScaleDOTweenAction.cs +++ b/Scripts/Runtime/Core/DOTweenActions/ShakeScaleDOTweenAction.cs @@ -7,7 +7,6 @@ namespace BrunoMikoski.AnimationSequencer [Serializable] public sealed class ShakeScaleDOTweenAction : DOTweenActionBase { - public override Type TargetComponentType => typeof(Transform); public override string DisplayName => "Shake Scale"; @@ -20,11 +19,22 @@ public sealed class ShakeScaleDOTweenAction : DOTweenActionBase [SerializeField] private bool fadeout = true; + private Transform previousTarget; + private Vector3 previousScale; + protected override Tweener GenerateTween_Internal(GameObject target, float duration) { - Tweener tween = target.transform.DOShakeScale(duration, strength, vibrato, randomness, fadeout); + previousTarget = target.transform; + previousScale = previousTarget.localScale; + + Tweener tween = previousTarget.DOShakeScale(duration, strength, vibrato, randomness, fadeout); return tween; } + + public override void ResetToInitialState() + { + previousTarget.localScale = previousScale; + } } } diff --git a/Scripts/Runtime/Core/DOTweenActions/TMP_TextDOTweenAction.cs b/Scripts/Runtime/Core/DOTweenActions/TMP_TextDOTweenAction.cs index 215fb30..ea320de 100644 --- a/Scripts/Runtime/Core/DOTweenActions/TMP_TextDOTweenAction.cs +++ b/Scripts/Runtime/Core/DOTweenActions/TMP_TextDOTweenAction.cs @@ -24,6 +24,9 @@ public sealed class TMP_TextDOTweenAction : DOTweenActionBase private ScrambleMode scrambleMode = ScrambleMode.None; private TMP_Text tmpTextComponent; + + private string previousText; + private TMP_Text previousTarget; protected override Tweener GenerateTween_Internal(GameObject target, float duration) { @@ -37,11 +40,19 @@ protected override Tweener GenerateTween_Internal(GameObject target, float durat } } + previousText = tmpTextComponent.text; + previousTarget = tmpTextComponent; TweenerCore tween = tmpTextComponent.DOText(text, duration, richText, scrambleMode); return tween; } + public override void ResetToInitialState() + { + if (string.IsNullOrEmpty(previousText)) + return; + previousTarget.text = previousText; + } } } #endif diff --git a/Scripts/Runtime/Core/Steps/AnimationStepBase.cs b/Scripts/Runtime/Core/Steps/AnimationStepBase.cs index b37d680..336fe90 100644 --- a/Scripts/Runtime/Core/Steps/AnimationStepBase.cs +++ b/Scripts/Runtime/Core/Steps/AnimationStepBase.cs @@ -9,19 +9,18 @@ public abstract class AnimationStepBase { [SerializeField] private float delay; + public float Delay => delay; + [SerializeField] private FlowType flowType; - - public float Delay => delay; public FlowType FlowType => flowType; public abstract string DisplayName { get; } - //TODO find a way to discover if one step is playing or not. - public bool IsPlaying => false; - public abstract void AddTweenToSequence(Sequence animationSequence); + public abstract void ResetToInitialState(); + public virtual string GetDisplayNameForEditor(int index) { return $"{index}. {this}"; diff --git a/Scripts/Runtime/Core/Steps/DOTweenAnimationStep.cs b/Scripts/Runtime/Core/Steps/DOTweenAnimationStep.cs index 02bcf48..32d04c7 100644 --- a/Scripts/Runtime/Core/Steps/DOTweenAnimationStep.cs +++ b/Scripts/Runtime/Core/Steps/DOTweenAnimationStep.cs @@ -35,6 +35,14 @@ public override void AddTweenToSequence(Sequence animationSequence) } + public override void ResetToInitialState() + { + for (int i = actions.Length - 1; i >= 0; i--) + { + actions[i].ResetToInitialState(); + } + } + public override string GetDisplayNameForEditor(int index) { string targetName = "NULL"; diff --git a/Scripts/Runtime/Core/Steps/InvokeCallbackAnimationStep.cs b/Scripts/Runtime/Core/Steps/InvokeCallbackAnimationStep.cs index 9d5a785..55f22f2 100644 --- a/Scripts/Runtime/Core/Steps/InvokeCallbackAnimationStep.cs +++ b/Scripts/Runtime/Core/Steps/InvokeCallbackAnimationStep.cs @@ -20,6 +20,10 @@ public override void AddTweenToSequence(Sequence animationSequence) animationSequence.AppendCallback(() => callback.Invoke()); } + public override void ResetToInitialState() + { + } + public override string GetDisplayNameForEditor(int index) { string persistentTargetNames = String.Empty; diff --git a/Scripts/Runtime/Core/Steps/PlayParticleSystemAnimationStep.cs b/Scripts/Runtime/Core/Steps/PlayParticleSystemAnimationStep.cs index b204beb..b679386 100644 --- a/Scripts/Runtime/Core/Steps/PlayParticleSystemAnimationStep.cs +++ b/Scripts/Runtime/Core/Steps/PlayParticleSystemAnimationStep.cs @@ -31,6 +31,10 @@ public override void AddTweenToSequence(Sequence animationSequence) animationSequence.AppendCallback(FinishParticles); } + public override void ResetToInitialState() + { + } + private void FinishParticles() { if (stopEmittingWhenOver) diff --git a/Scripts/Runtime/Core/Steps/PlaySequenceAnimationStep.cs b/Scripts/Runtime/Core/Steps/PlaySequenceAnimationStep.cs index b7249f0..46c0c73 100644 --- a/Scripts/Runtime/Core/Steps/PlaySequenceAnimationStep.cs +++ b/Scripts/Runtime/Core/Steps/PlaySequenceAnimationStep.cs @@ -15,13 +15,18 @@ public sealed class PlaySequenceAnimationStep : AnimationStepBase public override void AddTweenToSequence(Sequence animationSequence) { Sequence sequence = sequencer.GenerateSequence(); - sequence.AppendInterval(Delay); + sequence.SetDelay(Delay); if (FlowType == FlowType.Join) animationSequence.Join(sequence); else animationSequence.Append(sequence); } + public override void ResetToInitialState() + { + sequencer.ResetToInitialState(); + } + public override string GetDisplayNameForEditor(int index) { string display = "NULL"; diff --git a/package.json b/package.json index e90191a..44c7094 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.brunomikoski.animationsequencer", "displayName": "Animation Sequencer", - "version": "0.2.4", + "version": "0.2.6", "unity": "2018.4", "description": "Animation sequencer is a way to create complex animations of sequence of events by a friendly user interface. Requires DOTween v1.2.632", "keywords": [