264 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			264 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
	
|  | // Author: Daniele Giardini - http://www.demigiant.com | |||
|  | // Created: 2015/03/12 16:03 | |||
|  | 
 | |||
|  | using System; | |||
|  | using System.Collections.Generic; | |||
|  | using DG.DemiEditor; | |||
|  | using DG.DemiLib; | |||
|  | using DG.Tweening; | |||
|  | using DG.Tweening.Core; | |||
|  | using UnityEditor; | |||
|  | using UnityEditorInternal; | |||
|  | using UnityEngine; | |||
|  | using Object = UnityEngine.Object; | |||
|  | 
 | |||
|  | namespace DG.DOTweenEditor | |||
|  | { | |||
|  |     public static class DOTweenPreviewManager | |||
|  |     { | |||
|  |         static bool _previewOnlyIfSetToAutoPlay = true; | |||
|  |         static readonly Dictionary<DOTweenAnimation,TweenInfo> _AnimationToTween = new Dictionary<DOTweenAnimation,TweenInfo>(); | |||
|  |         static readonly List<DOTweenAnimation> _TmpKeys = new List<DOTweenAnimation>(); | |||
|  | 
 | |||
|  |         #region Public Methods & GUI | |||
|  | 
 | |||
|  |         /// <summary> | |||
|  |         /// Returns TRUE if its actually previewing animations | |||
|  |         /// </summary> | |||
|  |         public static bool PreviewGUI(DOTweenAnimation src) | |||
|  |         { | |||
|  |             if (EditorApplication.isPlaying) return false; | |||
|  | 
 | |||
|  |             Styles.Init(); | |||
|  | 
 | |||
|  |             bool isPreviewing = _AnimationToTween.Count > 0; | |||
|  |             bool isPreviewingThis = isPreviewing && _AnimationToTween.ContainsKey(src); | |||
|  | 
 | |||
|  |             // Preview in editor | |||
|  |             GUI.backgroundColor = isPreviewing | |||
|  |                 ? new DeSkinColor(new Color(0.49f, 0.8f, 0.86f), new Color(0.15f, 0.26f, 0.35f)) | |||
|  |                 : new DeSkinColor(Color.white, new Color(0.13f, 0.13f, 0.13f)); | |||
|  |             GUILayout.BeginVertical(Styles.previewBox); | |||
|  |             DeGUI.ResetGUIColors(); | |||
|  |             GUILayout.BeginHorizontal(); | |||
|  |             GUILayout.Label("Preview Mode - Experimental", Styles.previewLabel); | |||
|  |             _previewOnlyIfSetToAutoPlay = DeGUILayout.ToggleButton( | |||
|  |                 _previewOnlyIfSetToAutoPlay, | |||
|  |                 new GUIContent("AutoPlay only", "If toggled only previews animations that have AutoPlay turned ON"), | |||
|  |                 Styles.btOption | |||
|  |             ); | |||
|  |             GUILayout.EndHorizontal(); | |||
|  |             GUILayout.Space(1); | |||
|  |             // Preview - Play | |||
|  |             GUILayout.BeginHorizontal(); | |||
|  |             EditorGUI.BeginDisabledGroup( | |||
|  |                 isPreviewingThis || src.animationType == DOTweenAnimation.AnimationType.None | |||
|  |                 || !src.isActive || _previewOnlyIfSetToAutoPlay && !src.autoPlay | |||
|  |             ); | |||
|  |             if (GUILayout.Button("► Play", Styles.btPreview)) { | |||
|  |                 if (!isPreviewing) StartupGlobalPreview(); | |||
|  |                 AddAnimationToGlobalPreview(src); | |||
|  |             } | |||
|  |             EditorGUI.EndDisabledGroup(); | |||
|  |             EditorGUI.BeginDisabledGroup(isPreviewing); | |||
|  |             if (GUILayout.Button("► Play All <i>on GameObject</i>", Styles.btPreview)) { | |||
|  |                 if (!isPreviewing) StartupGlobalPreview(); | |||
|  |                 DOTweenAnimation[] anims = src.gameObject.GetComponents<DOTweenAnimation>(); | |||
|  |                 foreach (DOTweenAnimation anim in anims) AddAnimationToGlobalPreview(anim); | |||
|  |             } | |||
|  |             if (GUILayout.Button("► Play All <i>in Scene</i>", Styles.btPreview)) { | |||
|  |                 if (!isPreviewing) StartupGlobalPreview(); | |||
|  |                 DOTweenAnimation[] anims = Object.FindObjectsOfType<DOTweenAnimation>(); | |||
|  |                 foreach (DOTweenAnimation anim in anims) AddAnimationToGlobalPreview(anim); | |||
|  |             } | |||
|  |             EditorGUI.EndDisabledGroup(); | |||
|  |             GUILayout.EndHorizontal(); | |||
|  |             // Preview - Stop | |||
|  |             GUILayout.BeginHorizontal(); | |||
|  |             EditorGUI.BeginDisabledGroup(!isPreviewingThis); | |||
|  |             if (GUILayout.Button("■ Stop", Styles.btPreview)) { | |||
|  |                 if (_AnimationToTween.ContainsKey(src)) StopPreview(_AnimationToTween[src].tween); | |||
|  |             } | |||
|  |             EditorGUI.EndDisabledGroup(); | |||
|  |             EditorGUI.BeginDisabledGroup(!isPreviewing); | |||
|  |             if (GUILayout.Button("■ Stop All <i>on GameObject</i>", Styles.btPreview)) { | |||
|  |                 StopPreview(src.gameObject); | |||
|  |             } | |||
|  |             if (GUILayout.Button("■ Stop All <i>in Scene</i>", Styles.btPreview)) { | |||
|  |                 StopAllPreviews(); | |||
|  |             } | |||
|  |             EditorGUI.EndDisabledGroup(); | |||
|  |             GUILayout.EndHorizontal(); | |||
|  |             if (isPreviewing) { | |||
|  |                 int playingTweens = 0; | |||
|  |                 int completedTweens = 0; | |||
|  |                 int pausedTweens = 0; | |||
|  |                 foreach (KeyValuePair<DOTweenAnimation, TweenInfo> kvp in _AnimationToTween) { | |||
|  |                     Tween t = kvp.Value.tween; | |||
|  |                     if (t.IsPlaying()) playingTweens++; | |||
|  |                     else if (t.IsComplete()) completedTweens++; | |||
|  |                     else pausedTweens++; | |||
|  |                 } | |||
|  |                 GUILayout.Label("Playing Tweens: " + playingTweens, Styles.previewStatusLabel); | |||
|  |                 GUILayout.Label("Completed Tweens: " + completedTweens, Styles.previewStatusLabel); | |||
|  | //                GUILayout.Label("Paused Tweens: " + playingTweens); | |||
|  |             } | |||
|  |             GUILayout.EndVertical(); | |||
|  | 
 | |||
|  |             return isPreviewing; | |||
|  |         } | |||
|  | 
 | |||
|  | #if !(UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5) | |||
|  |         public static void StopAllPreviews(PlayModeStateChange state) | |||
|  |         { | |||
|  |             StopAllPreviews(); | |||
|  |         } | |||
|  | #endif | |||
|  | 
 | |||
|  |         public static void StopAllPreviews() | |||
|  |         { | |||
|  |             _TmpKeys.Clear(); | |||
|  |             foreach (KeyValuePair<DOTweenAnimation,TweenInfo> kvp in _AnimationToTween) { | |||
|  |                 _TmpKeys.Add(kvp.Key); | |||
|  |             } | |||
|  |             StopPreview(_TmpKeys); | |||
|  |             _TmpKeys.Clear(); | |||
|  |             _AnimationToTween.Clear(); | |||
|  | 
 | |||
|  |             DOTweenEditorPreview.Stop(); | |||
|  | #if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5 | |||
|  |             UnityEditor.EditorApplication.playmodeStateChanged -= StopAllPreviews; | |||
|  | #else | |||
|  |             UnityEditor.EditorApplication.playModeStateChanged -= StopAllPreviews; | |||
|  | #endif | |||
|  | //            EditorApplication.playmodeStateChanged -= StopAllPreviews; | |||
|  | 
 | |||
|  |             InternalEditorUtility.RepaintAllViews(); | |||
|  |         } | |||
|  | 
 | |||
|  | #endregion | |||
|  | 
 | |||
|  | #region Methods | |||
|  | 
 | |||
|  |         static void StartupGlobalPreview() | |||
|  |         { | |||
|  |             DOTweenEditorPreview.Start(); | |||
|  | #if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5 | |||
|  |             UnityEditor.EditorApplication.playmodeStateChanged += StopAllPreviews; | |||
|  | #else | |||
|  |             UnityEditor.EditorApplication.playModeStateChanged += StopAllPreviews; | |||
|  | #endif | |||
|  | //            EditorApplication.playmodeStateChanged += StopAllPreviews; | |||
|  |         } | |||
|  | 
 | |||
|  |         static void AddAnimationToGlobalPreview(DOTweenAnimation src) | |||
|  |         { | |||
|  |             if (!src.isActive) return; // Ignore sources whose tweens have been set to inactive | |||
|  |             if (_previewOnlyIfSetToAutoPlay && !src.autoPlay) return; | |||
|  | 
 | |||
|  |             Tween t = src.CreateEditorPreview(); | |||
|  |             _AnimationToTween.Add(src, new TweenInfo(src, t, src.isFrom)); | |||
|  |             // Tween setup | |||
|  |             DOTweenEditorPreview.PrepareTweenForPreview(t); | |||
|  |         } | |||
|  | 
 | |||
|  |         static void StopPreview(GameObject go) | |||
|  |         { | |||
|  |             _TmpKeys.Clear(); | |||
|  |             foreach (KeyValuePair<DOTweenAnimation,TweenInfo> kvp in _AnimationToTween) { | |||
|  |                 if (kvp.Key.gameObject != go) continue; | |||
|  |                 _TmpKeys.Add(kvp.Key); | |||
|  |             } | |||
|  |             StopPreview(_TmpKeys); | |||
|  |             _TmpKeys.Clear(); | |||
|  | 
 | |||
|  |             if (_AnimationToTween.Count == 0) StopAllPreviews(); | |||
|  |             else InternalEditorUtility.RepaintAllViews(); | |||
|  |         } | |||
|  | 
 | |||
|  |         static void StopPreview(Tween t) | |||
|  |         { | |||
|  |             TweenInfo tInfo = null; | |||
|  |             foreach (KeyValuePair<DOTweenAnimation,TweenInfo> kvp in _AnimationToTween) { | |||
|  |                 if (kvp.Value.tween != t) continue; | |||
|  |                 tInfo = kvp.Value; | |||
|  |                 _AnimationToTween.Remove(kvp.Key); | |||
|  |                 break; | |||
|  |             } | |||
|  |             if (tInfo == null) { | |||
|  |                 Debug.LogWarning("DOTween Preview ► Couldn't find tween to stop"); | |||
|  |                 return; | |||
|  |             } | |||
|  |             if (tInfo.isFrom) { | |||
|  |                 int totLoops = tInfo.tween.Loops(); | |||
|  |                 if (totLoops < 0 || totLoops > 1) { | |||
|  |                     tInfo.tween.Goto(tInfo.tween.Duration(false)); | |||
|  |                 } else tInfo.tween.Complete(); | |||
|  |             } else tInfo.tween.Rewind(); | |||
|  |             tInfo.tween.Kill(); | |||
|  |             EditorUtility.SetDirty(tInfo.animation); // Refresh views | |||
|  | 
 | |||
|  |             if (_AnimationToTween.Count == 0) StopAllPreviews(); | |||
|  |             else InternalEditorUtility.RepaintAllViews(); | |||
|  |         } | |||
|  | 
 | |||
|  |         // Stops while iterating inversely, which deals better with tweens that overwrite each other | |||
|  |         static void StopPreview(List<DOTweenAnimation> keys) | |||
|  |         { | |||
|  |             for (int i = keys.Count - 1; i > -1; --i) { | |||
|  |                 DOTweenAnimation anim = keys[i]; | |||
|  |                 TweenInfo tInfo = _AnimationToTween[anim]; | |||
|  |                 if (tInfo.isFrom) { | |||
|  |                     int totLoops = tInfo.tween.Loops(); | |||
|  |                     if (totLoops < 0 || totLoops > 1) { | |||
|  |                         tInfo.tween.Goto(tInfo.tween.Duration(false)); | |||
|  |                     } else tInfo.tween.Complete(); | |||
|  |                 } else tInfo.tween.Rewind(); | |||
|  |                 tInfo.tween.Kill(); | |||
|  |                 EditorUtility.SetDirty(anim); // Refresh views | |||
|  |                 _AnimationToTween.Remove(anim); | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  | #endregion | |||
|  | 
 | |||
|  |         // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | |||
|  |         // ███ INTERNAL CLASSES ████████████████████████████████████████████████████████████████████████████████████████████████ | |||
|  |         // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ | |||
|  | 
 | |||
|  |         class TweenInfo | |||
|  |         { | |||
|  |             public DOTweenAnimation animation; | |||
|  |             public Tween tween; | |||
|  |             public bool isFrom; | |||
|  |             public TweenInfo(DOTweenAnimation animation, Tween tween, bool isFrom) | |||
|  |             { | |||
|  |                 this.animation = animation; | |||
|  |                 this.tween = tween; | |||
|  |                 this.isFrom = isFrom; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         static class Styles | |||
|  |         { | |||
|  |             static bool _initialized; | |||
|  | 
 | |||
|  |             public static GUIStyle previewBox, previewLabel, btOption, btPreview, previewStatusLabel; | |||
|  | 
 | |||
|  |             public static void Init() | |||
|  |             { | |||
|  |                 if (_initialized) return; | |||
|  | 
 | |||
|  |                 _initialized = true; | |||
|  | 
 | |||
|  |                 previewBox = new GUIStyle(GUI.skin.box).Clone().Padding(1, 1, 0, 3) | |||
|  |                     .Background(DeStylePalette.squareBorderCurved_darkBorders).Border(7, 7, 7, 7); | |||
|  |                 previewLabel = new GUIStyle(GUI.skin.label).Clone(10, FontStyle.Bold).Padding(1, 0, 3, 0).Margin(3, 6, 0, 0).StretchWidth(false); | |||
|  |                 btOption = DeGUI.styles.button.bBlankBorderCompact.MarginBottom(2).MarginRight(4); | |||
|  |                 btPreview = EditorStyles.miniButton.Clone(Format.RichText); | |||
|  |                 previewStatusLabel = EditorStyles.miniLabel.Clone().Padding(4, 0, 0, 0).Margin(0); | |||
|  |             } | |||
|  |         } | |||
|  |     } | |||
|  | } |