diff --git a/Packages/src/Editor/UIEffectTweenerEditor.cs b/Packages/src/Editor/UIEffectTweenerEditor.cs index 5adf8d07..7a5a8cd4 100644 --- a/Packages/src/Editor/UIEffectTweenerEditor.cs +++ b/Packages/src/Editor/UIEffectTweenerEditor.cs @@ -6,7 +6,7 @@ namespace Coffee.UIEffects.Editors { [CanEditMultipleObjects] [CustomEditor(typeof(UIEffectTweener))] - internal class UIMaterialPropertyTweenerEditor : Editor + internal class UIEffectTweenerEditor : Editor { private SerializedProperty _cullingMask; private SerializedProperty _direction; @@ -14,7 +14,7 @@ internal class UIMaterialPropertyTweenerEditor : Editor private SerializedProperty _delay; private SerializedProperty _duration; private SerializedProperty _interval; - private SerializedProperty _restartOnEnable; + private SerializedProperty _resetTimeOnEnable; private SerializedProperty _updateMode; private SerializedProperty _wrapMode; private SerializedProperty _startMode; @@ -24,7 +24,7 @@ private void OnEnable() _cullingMask = serializedObject.FindProperty("m_CullingMask"); _direction = serializedObject.FindProperty("m_Direction"); _curve = serializedObject.FindProperty("m_Curve"); - _restartOnEnable = serializedObject.FindProperty("m_RestartOnEnable"); + _resetTimeOnEnable = serializedObject.FindProperty("m_ResetTimeOnEnable"); _delay = serializedObject.FindProperty("m_Delay"); _duration = serializedObject.FindProperty("m_Duration"); _interval = serializedObject.FindProperty("m_Interval"); @@ -35,7 +35,7 @@ private void OnEnable() public override void OnInspectorGUI() { - Profiler.BeginSample("(MPI)[MPTweenerEditor] OnInspectorGUI"); + Profiler.BeginSample("(UIE)[UIEffectTweener] OnInspectorGUI"); serializedObject.UpdateIfRequiredOrScript(); EditorGUILayout.PropertyField(_cullingMask); EditorGUILayout.PropertyField(_direction); @@ -43,7 +43,7 @@ public override void OnInspectorGUI() EditorGUILayout.PropertyField(_delay); EditorGUILayout.PropertyField(_duration); EditorGUILayout.PropertyField(_interval); - EditorGUILayout.PropertyField(_restartOnEnable); + EditorGUILayout.PropertyField(_resetTimeOnEnable); EditorGUILayout.PropertyField(_wrapMode); EditorGUILayout.PropertyField(_updateMode); EditorGUILayout.PropertyField(_startMode); @@ -58,13 +58,17 @@ private void DrawPlayer(UIEffectTweener tweener) EditorGUILayout.BeginHorizontal(); EditorGUI.BeginDisabledGroup(!Application.isPlaying); - var icon = EditorGUIUtility.IconContent("icons/playbutton.png"); var r = EditorGUILayout.GetControlRect(false); + var rPlayButton = new Rect(r.x, r.y, 20, r.height); + if (GUI.Button(rPlayButton, EditorGUIUtility.IconContent("playbutton"), "IconButton")) + { + tweener.Play(false); + } - var rButton = new Rect(r.x, r.y, 20, r.height); - if (GUI.Button(rButton, icon, "IconButton")) + var rPauseButton = new Rect(r.x + 20, r.y, 20, r.height); + if (GUI.Button(rPauseButton, EditorGUIUtility.IconContent("pausebutton"), "IconButton")) { - tweener.SetTime(0); + tweener.SetPause(!tweener.isPaused); } EditorGUI.EndDisabledGroup(); @@ -72,54 +76,32 @@ private void DrawPlayer(UIEffectTweener tweener) var totalTime = tweener.totalTime; var time = tweener.time; var label = EditorGUIUtility.TrTempContent($"{time:N2}/{totalTime:N2}"); - var wLabel = Mathf.CeilToInt(EditorStyles.label.CalcSize(label).x / 5f) * 5f; - wLabel = 80; - var rLabel = new Rect(r.x + r.width - wLabel, r.y, wLabel, r.height); + var rLabel = new Rect(r.x + r.width - 80, r.y, 80, r.height); GUI.Label(rLabel, label, "RightLabel"); EditorGUILayout.EndHorizontal(); EditorGUI.BeginChangeCheck(); - var rSlider = new Rect(r.x + 20, r.y, r.width - wLabel - 20, r.height); - - // + var rSlider = new Rect(r.x + 40, r.y, r.width - 120, r.height); + var r0 = new Rect(rSlider.x, rSlider.y + 4, rSlider.width, rSlider.height - 8); + r0.x += DrawBackground(r0, rSlider.width * tweener.delay / totalTime, Color.blue); + r0.x += DrawBackground(r0, rSlider.width * tweener.duration / totalTime, Color.green); - var - r0 = rSlider; //new Rect(rSlider.x, rSlider.y, rSlider.width * tweener.interval / totalTime, rSlider.height); - r0.y += 4; - r0.height -= 8; - r0.width = rSlider.width * tweener.delay / totalTime; - GUI.color = Color.blue; - GUI.Label(r0, GUIContent.none, "TE DefaultTime"); - - r0.x += r0.width; - r0.width = rSlider.width * tweener.duration / totalTime; - GUI.color = Color.green; - GUI.Label(r0, GUIContent.none, "TE DefaultTime"); - - r0.x += r0.width; - r0.width = rSlider.width * tweener.interval / totalTime; - GUI.color = Color.red; - GUI.Label(r0, GUIContent.none, "TE DefaultTime"); + if (UIEffectTweener.WrapMode.Loop <= tweener.wrapMode) + { + r0.x += DrawBackground(r0, rSlider.width * tweener.interval / totalTime, Color.red); + } if (UIEffectTweener.WrapMode.PingPongOnce <= tweener.wrapMode) { - r0.x += r0.width; - r0.width = rSlider.width * tweener.duration / totalTime; - GUI.color = Color.green; - GUI.Label(r0, GUIContent.none, "TE DefaultTime"); + r0.x += DrawBackground(r0, rSlider.width * tweener.duration / totalTime, Color.green); } if (UIEffectTweener.WrapMode.PingPongLoop <= tweener.wrapMode) { - r0.x += r0.width; - r0.width = rSlider.width * tweener.interval / totalTime; - GUI.color = Color.red; - GUI.Label(r0, GUIContent.none, "TE DefaultTime"); + r0.x += DrawBackground(r0, rSlider.width * tweener.interval / totalTime, Color.red); } - GUI.color = Color.white; - time = GUI.HorizontalSlider(rSlider, time, 0, totalTime); if (EditorGUI.EndChangeCheck()) { @@ -132,21 +114,12 @@ private void DrawPlayer(UIEffectTweener tweener) } } - // private static void PostAddElement(SerializedProperty prop, string propertyName) - // { - // prop.FindPropertyRelative("m_From.m_Type").intValue = -1; - // prop.FindPropertyRelative("m_From.m_PropertyName").stringValue = propertyName; - // prop.FindPropertyRelative("m_To.m_Type").intValue = -1; - // prop.FindPropertyRelative("m_To.m_PropertyName").stringValue = propertyName; - // } - // - // private void ResetCallback() - // { - // var current = serializedObject.targetObject as UIEffectTweener; - // if (!current) return; - // - // Undo.RecordObject(current, "Reset Values"); - // current.ResetPropertiesToDefault(); - // } + private static float DrawBackground(Rect r, float width, Color color) + { + r.width = width; + GUI.color = color; + GUI.Label(r, GUIContent.none, "TE DefaultTime"); + return width; + } } } diff --git a/Packages/src/Runtime/UIEffectTweener.cs b/Packages/src/Runtime/UIEffectTweener.cs index e790dd1c..95f6c999 100644 --- a/Packages/src/Runtime/UIEffectTweener.cs +++ b/Packages/src/Runtime/UIEffectTweener.cs @@ -1,5 +1,6 @@ using System; using UnityEngine; +using UnityEngine.Serialization; namespace Coffee.UIEffects { @@ -70,9 +71,10 @@ public enum Direction [Range(0f, 10)] private float m_Interval; - [Tooltip("Whether to restart the tween when enabled.")] + [FormerlySerializedAs("m_RestartOnEnable")] + [Tooltip("Whether to reset the time when the component is enabled.")] [SerializeField] - private bool m_RestartOnEnable = true; + private bool m_ResetTimeOnEnable = true; [Tooltip("The wrap mode of the tween.\n" + " Clamp: Clamp the tween value (not loop).\n" + @@ -95,7 +97,7 @@ public enum Direction [SerializeField] private StartMode m_StartMode = StartMode.Automatic; - public bool _isAwaitingStart; + private bool _isPaused; private float _rate; private float _time; private UIEffectBase _target; @@ -171,19 +173,12 @@ public float time { get { - if (_time < delay) return _time; - var t = _time - delay; - switch (wrapMode) + if (wrapMode == WrapMode.Once || wrapMode == WrapMode.PingPongOnce) { - case WrapMode.Once: - case WrapMode.PingPongOnce: - return Mathf.Clamp(t, 0, totalTime - delay) + delay; - case WrapMode.Loop: - case WrapMode.PingPongLoop: - return Mathf.Repeat(t, totalTime - delay) + delay; - default: - throw new ArgumentOutOfRangeException(); + return Mathf.Clamp(_time, 0, totalTime); } + + return Mathf.Repeat(_time, totalTime); } } @@ -203,10 +198,18 @@ public float totalTime } } + public bool resetTimeOnEnable + { + get => m_ResetTimeOnEnable; + set => m_ResetTimeOnEnable = value; + } + + [Obsolete( + "UIEffectTweener.restartOnEnable has been deprecated. Use UIEffectTweener.resetTimeOnEnable instead (UnityUpgradable) -> resetTimeOnEnable")] public bool restartOnEnable { - get => m_RestartOnEnable; - set => m_RestartOnEnable = value; + get => m_ResetTimeOnEnable; + set => m_ResetTimeOnEnable = value; } public WrapMode wrapMode @@ -233,47 +236,90 @@ public AnimationCurve curve set => m_Curve = value; } - private void Awake() + public bool isPlaying { - _isAwaitingStart = m_StartMode == StartMode.Manual; + get + { + if (_isPaused) return false; + if (wrapMode == WrapMode.Loop || wrapMode == WrapMode.PingPongLoop) return true; + + return direction == Direction.Forward + ? _time < totalTime + : 0 < _time; + } } + public bool isPaused => _isPaused; + private void Update() { - if (m_StartMode == StartMode.Manual && _isAwaitingStart) - { - return; - } + if (!isPlaying) return; - float deltaTime = m_UpdateMode == UpdateMode.Unscaled ? Time.unscaledDeltaTime : Time.deltaTime; - UpdateTime(deltaTime); + var deltaTime = m_UpdateMode == UpdateMode.Unscaled + ? Time.unscaledDeltaTime + : Time.deltaTime; + UpdateTime(direction == Direction.Forward ? deltaTime : -deltaTime); } private void OnEnable() { - if (m_RestartOnEnable) + _isPaused = m_StartMode == StartMode.Manual; + if (resetTimeOnEnable) + { + ResetTime(); + } + } + + public void Play(bool resetTime) + { + if (resetTime) { - Restart(); + ResetTime(); } + + _isPaused = false; } public void Play() { - _isAwaitingStart = false; - Restart(); + Play(true); + } + + public void PlayForward() + { + direction = Direction.Forward; + _isPaused = false; + } + + public void PlayReverse() + { + direction = Direction.Reverse; + _isPaused = false; } public void Stop() { - _isAwaitingStart = true; - Restart(); + _isPaused = true; + ResetTime(); } - public void Restart() + public void SetPause(bool pause) + { + _isPaused = pause; + } + + public void ResetTime() { SetTime(0); } + [Obsolete( + "UIEffectTweener.Restart has been deprecated. Use UIEffectTweener.ResetTime instead (UnityUpgradable) -> ResetTime")] + public void Restart() + { + ResetTime(); + } + public void SetTime(float sec) { _time = 0; @@ -282,33 +328,52 @@ public void SetTime(float sec) public void UpdateTime(float deltaSec) { - rate = UpdateTime_Internal(Mathf.Max(0, deltaSec)) / duration; - } - - private float UpdateTime_Internal(float delta) - { - _time += direction == Direction.Forward ? delta : -delta; - if (_time < delay) return 0; + _time += deltaSec; + if (wrapMode == WrapMode.Once || wrapMode == WrapMode.PingPongOnce) + { + _time = Mathf.Clamp(_time, 0, totalTime); + if (startMode == StartMode.Manual && (_time <= 0 || totalTime <= _time)) + { + _isPaused = true; + } + } + else + { + _time = Mathf.Repeat(_time - delay, totalTime - delay) + delay; + } var t = _time - delay; + if (t < 0) + { + rate = 0; + return; + } + switch (wrapMode) { + case WrapMode.Once: + t = Mathf.Clamp(t, 0, duration); + _time = t + delay; + break; case WrapMode.Loop: t = Mathf.Repeat(t, duration + interval); + _time = t + delay; break; case WrapMode.PingPongOnce: t = Mathf.Clamp(t, 0, duration * 2 + interval); + _time = t + delay; t = Mathf.PingPong(t, duration + interval * 0.5f); break; case WrapMode.PingPongLoop: t = Mathf.Repeat(t, (duration + interval) * 2); + _time = t + delay; t = t < duration * 2 + interval ? Mathf.PingPong(t, duration + interval * 0.5f) : 0; break; } - return Mathf.Clamp(t, 0, duration); + rate = Mathf.Clamp(t, 0, duration) / duration; } } }