DOTweenAnimationInspector.cs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. // Author: Daniele Giardini - http://www.demigiant.com
  2. // Created: 2015/03/12 16:03
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using DG.DemiEditor;
  7. using DG.DOTweenEditor.Core;
  8. using DG.DOTweenEditor.UI;
  9. using DG.Tweening;
  10. using DG.Tweening.Core;
  11. using UnityEditor;
  12. using UnityEngine;
  13. using DOTweenSettings = DG.Tweening.Core.DOTweenSettings;
  14. #if true // UI_MARKER
  15. using UnityEngine.UI;
  16. #endif
  17. #if false // TEXTMESHPRO_MARKER
  18. using TMPro;
  19. #endif
  20. namespace DG.DOTweenEditor
  21. {
  22. [CustomEditor(typeof(DOTweenAnimation))]
  23. public class DOTweenAnimationInspector : ABSAnimationInspector
  24. {
  25. enum FadeTargetType
  26. {
  27. CanvasGroup,
  28. Image
  29. }
  30. enum ChooseTargetMode
  31. {
  32. None,
  33. BetweenCanvasGroupAndImage
  34. }
  35. static readonly Dictionary<DOTweenAnimation.AnimationType, Type[]> _AnimationTypeToComponent = new Dictionary<DOTweenAnimation.AnimationType, Type[]>() {
  36. { DOTweenAnimation.AnimationType.Move, new[] {
  37. #if true // PHYSICS_MARKER
  38. typeof(Rigidbody),
  39. #endif
  40. #if true // PHYSICS2D_MARKER
  41. typeof(Rigidbody2D),
  42. #endif
  43. #if true // UI_MARKER
  44. typeof(RectTransform),
  45. #endif
  46. typeof(Transform)
  47. }},
  48. { DOTweenAnimation.AnimationType.Rotate, new[] {
  49. #if true // PHYSICS_MARKER
  50. typeof(Rigidbody),
  51. #endif
  52. #if true // PHYSICS2D_MARKER
  53. typeof(Rigidbody2D),
  54. #endif
  55. typeof(Transform)
  56. }},
  57. { DOTweenAnimation.AnimationType.LocalMove, new[] { typeof(Transform) } },
  58. { DOTweenAnimation.AnimationType.LocalRotate, new[] { typeof(Transform) } },
  59. { DOTweenAnimation.AnimationType.Scale, new[] { typeof(Transform) } },
  60. { DOTweenAnimation.AnimationType.Color, new[] {
  61. typeof(Light),
  62. #if true // SPRITE_MARKER
  63. typeof(SpriteRenderer),
  64. #endif
  65. #if true // UI_MARKER
  66. typeof(Image), typeof(Text), typeof(RawImage), typeof(Graphic),
  67. #endif
  68. typeof(Renderer),
  69. }},
  70. { DOTweenAnimation.AnimationType.Fade, new[] {
  71. typeof(Light),
  72. #if true // SPRITE_MARKER
  73. typeof(SpriteRenderer),
  74. #endif
  75. #if true // UI_MARKER
  76. typeof(Image), typeof(Text), typeof(CanvasGroup), typeof(RawImage), typeof(Graphic),
  77. #endif
  78. typeof(Renderer),
  79. }},
  80. #if true // UI_MARKER
  81. { DOTweenAnimation.AnimationType.Text, new[] { typeof(Text) } },
  82. #endif
  83. { DOTweenAnimation.AnimationType.PunchPosition, new[] {
  84. #if true // UI_MARKER
  85. typeof(RectTransform),
  86. #endif
  87. typeof(Transform)
  88. }},
  89. { DOTweenAnimation.AnimationType.PunchRotation, new[] { typeof(Transform) } },
  90. { DOTweenAnimation.AnimationType.PunchScale, new[] { typeof(Transform) } },
  91. { DOTweenAnimation.AnimationType.ShakePosition, new[] {
  92. #if true // UI_MARKER
  93. typeof(RectTransform),
  94. #endif
  95. typeof(Transform)
  96. }},
  97. { DOTweenAnimation.AnimationType.ShakeRotation, new[] { typeof(Transform) } },
  98. { DOTweenAnimation.AnimationType.ShakeScale, new[] { typeof(Transform) } },
  99. { DOTweenAnimation.AnimationType.CameraAspect, new[] { typeof(Camera) } },
  100. { DOTweenAnimation.AnimationType.CameraBackgroundColor, new[] { typeof(Camera) } },
  101. { DOTweenAnimation.AnimationType.CameraFieldOfView, new[] { typeof(Camera) } },
  102. { DOTweenAnimation.AnimationType.CameraOrthoSize, new[] { typeof(Camera) } },
  103. { DOTweenAnimation.AnimationType.CameraPixelRect, new[] { typeof(Camera) } },
  104. { DOTweenAnimation.AnimationType.CameraRect, new[] { typeof(Camera) } },
  105. #if true // UI_MARKER
  106. { DOTweenAnimation.AnimationType.UIWidthHeight, new[] { typeof(RectTransform) } },
  107. #endif
  108. };
  109. #if false // TK2D_MARKER
  110. static readonly Dictionary<DOTweenAnimation.AnimationType, Type[]> _Tk2dAnimationTypeToComponent = new Dictionary<DOTweenAnimation.AnimationType, Type[]>() {
  111. { DOTweenAnimation.AnimationType.Scale, new[] { typeof(tk2dBaseSprite), typeof(tk2dTextMesh) } },
  112. { DOTweenAnimation.AnimationType.Color, new[] { typeof(tk2dBaseSprite), typeof(tk2dTextMesh) } },
  113. { DOTweenAnimation.AnimationType.Fade, new[] { typeof(tk2dBaseSprite), typeof(tk2dTextMesh) } },
  114. { DOTweenAnimation.AnimationType.Text, new[] { typeof(tk2dTextMesh) } }
  115. };
  116. #endif
  117. #if false // TEXTMESHPRO_MARKER
  118. static readonly Dictionary<DOTweenAnimation.AnimationType, Type[]> _TMPAnimationTypeToComponent = new Dictionary<DOTweenAnimation.AnimationType, Type[]>() {
  119. { DOTweenAnimation.AnimationType.Color, new[] { typeof(TextMeshPro), typeof(TextMeshProUGUI) } },
  120. { DOTweenAnimation.AnimationType.Fade, new[] { typeof(TextMeshPro), typeof(TextMeshProUGUI) } },
  121. { DOTweenAnimation.AnimationType.Text, new[] { typeof(TextMeshPro), typeof(TextMeshProUGUI) } }
  122. };
  123. #endif
  124. static readonly string[] _AnimationType = new[] {
  125. "None",
  126. "Move", "LocalMove",
  127. "Rotate", "LocalRotate",
  128. "Scale",
  129. "Color", "Fade",
  130. #if true // UI_MARKER
  131. "Text",
  132. #endif
  133. #if false // TK2D_MARKER
  134. "Text",
  135. #endif
  136. #if false // TEXTMESHPRO_MARKER
  137. "Text",
  138. #endif
  139. #if true // UI_MARKER
  140. "UIWidthHeight",
  141. #endif
  142. "Punch/Position", "Punch/Rotation", "Punch/Scale",
  143. "Shake/Position", "Shake/Rotation", "Shake/Scale",
  144. "Camera/Aspect", "Camera/BackgroundColor", "Camera/FieldOfView", "Camera/OrthoSize", "Camera/PixelRect", "Camera/Rect"
  145. };
  146. static string[] _animationTypeNoSlashes; // _AnimationType list without slashes in values
  147. static string[] _datString; // String representation of DOTweenAnimation enum (here for caching reasons)
  148. DOTweenAnimation _src;
  149. DOTweenSettings _settings;
  150. bool _runtimeEditMode; // If TRUE allows to change and save stuff at runtime
  151. bool _refreshRequired; // If TRUE refreshes components data
  152. int _totComponentsOnSrc; // Used to determine if a Component is added or removed from the source
  153. bool _isLightSrc; // Used to determine if we're tweening a Light, to set the max Fade value to more than 1
  154. #pragma warning disable 414
  155. ChooseTargetMode _chooseTargetMode = ChooseTargetMode.None;
  156. #pragma warning restore 414
  157. static readonly GUIContent _GuiC_selfTarget_true = new GUIContent(
  158. "SELF", "Will animate components on this gameObject"
  159. );
  160. static readonly GUIContent _GuiC_selfTarget_false = new GUIContent(
  161. "OTHER", "Will animate components on the given gameObject instead than on this one"
  162. );
  163. static readonly GUIContent _GuiC_tweenTargetIsTargetGO_true = new GUIContent(
  164. "Use As Tween Target", "Will set the tween target (via SetTarget, used to control a tween directly from a target) to the \"OTHER\" gameObject"
  165. );
  166. static readonly GUIContent _GuiC_tweenTargetIsTargetGO_false = new GUIContent(
  167. "Use As Tween Target", "Will set the tween target (via SetTarget, used to control a tween directly from a target) to the gameObject containing this animation, not the \"OTHER\" one"
  168. );
  169. #region MonoBehaviour Methods
  170. void OnEnable()
  171. {
  172. _src = target as DOTweenAnimation;
  173. _settings = DOTweenUtilityWindow.GetDOTweenSettings();
  174. onStartProperty = base.serializedObject.FindProperty("onStart");
  175. onPlayProperty = base.serializedObject.FindProperty("onPlay");
  176. onUpdateProperty = base.serializedObject.FindProperty("onUpdate");
  177. onStepCompleteProperty = base.serializedObject.FindProperty("onStepComplete");
  178. onCompleteProperty = base.serializedObject.FindProperty("onComplete");
  179. onRewindProperty = base.serializedObject.FindProperty("onRewind");
  180. onTweenCreatedProperty = base.serializedObject.FindProperty("onTweenCreated");
  181. // Convert _AnimationType to _animationTypeNoSlashes
  182. int len = _AnimationType.Length;
  183. _animationTypeNoSlashes = new string[len];
  184. for (int i = 0; i < len; ++i) {
  185. string a = _AnimationType[i];
  186. a = a.Replace("/", "");
  187. _animationTypeNoSlashes[i] = a;
  188. }
  189. }
  190. void OnDisable()
  191. {
  192. DOTweenPreviewManager.StopAllPreviews();
  193. }
  194. override public void OnInspectorGUI()
  195. {
  196. base.OnInspectorGUI();
  197. GUILayout.Space(3);
  198. EditorGUIUtils.SetGUIStyles();
  199. bool playMode = Application.isPlaying;
  200. _runtimeEditMode = _runtimeEditMode && playMode;
  201. GUILayout.BeginHorizontal();
  202. EditorGUIUtils.InspectorLogo();
  203. GUILayout.Label(_src.animationType.ToString() + (string.IsNullOrEmpty(_src.id) ? "" : " [" + _src.id + "]"), EditorGUIUtils.sideLogoIconBoldLabelStyle);
  204. // Up-down buttons
  205. GUILayout.FlexibleSpace();
  206. if (GUILayout.Button("▲", DeGUI.styles.button.toolIco)) UnityEditorInternal.ComponentUtility.MoveComponentUp(_src);
  207. if (GUILayout.Button("▼", DeGUI.styles.button.toolIco)) UnityEditorInternal.ComponentUtility.MoveComponentDown(_src);
  208. GUILayout.EndHorizontal();
  209. if (playMode) {
  210. if (_runtimeEditMode) {
  211. } else {
  212. GUILayout.Space(8);
  213. GUILayout.Label("Animation Editor disabled while in play mode", EditorGUIUtils.wordWrapLabelStyle);
  214. if (!_src.isActive) {
  215. GUILayout.Label("This animation has been toggled as inactive and won't be generated", EditorGUIUtils.wordWrapLabelStyle);
  216. GUI.enabled = false;
  217. }
  218. if (GUILayout.Button(new GUIContent("Activate Edit Mode", "Switches to Runtime Edit Mode, where you can change animations values and restart them"))) {
  219. _runtimeEditMode = true;
  220. }
  221. GUILayout.Label("NOTE: when using DOPlayNext, the sequence is determined by the DOTweenAnimation Components order in the target GameObject's Inspector", EditorGUIUtils.wordWrapLabelStyle);
  222. GUILayout.Space(10);
  223. if (!_runtimeEditMode) return;
  224. }
  225. }
  226. Undo.RecordObject(_src, "DOTween Animation");
  227. Undo.RecordObject(_settings, "DOTween Animation");
  228. // _src.isValid = Validate(); // Moved down
  229. EditorGUIUtility.labelWidth = 110;
  230. if (playMode) {
  231. GUILayout.Space(4);
  232. DeGUILayout.Toolbar("Edit Mode Commands");
  233. DeGUILayout.BeginVBox(DeGUI.styles.box.stickyTop);
  234. GUILayout.BeginHorizontal();
  235. if (GUILayout.Button("TogglePause")) _src.tween.TogglePause();
  236. if (GUILayout.Button("Rewind")) _src.tween.Rewind();
  237. if (GUILayout.Button("Restart")) _src.tween.Restart();
  238. GUILayout.EndHorizontal();
  239. if (GUILayout.Button("Commit changes and restart")) {
  240. _src.tween.Rewind();
  241. _src.tween.Kill();
  242. if (_src.isValid) {
  243. _src.CreateTween();
  244. _src.tween.Play();
  245. }
  246. }
  247. GUILayout.Label("To apply your changes when exiting Play mode, use the Component's upper right menu and choose \"Copy Component\", then \"Paste Component Values\" after exiting Play mode", DeGUI.styles.label.wordwrap);
  248. DeGUILayout.EndVBox();
  249. } else {
  250. GUILayout.BeginHorizontal();
  251. bool hasManager = _src.GetComponent<DOTweenVisualManager>() != null;
  252. EditorGUI.BeginChangeCheck();
  253. _settings.showPreviewPanel = hasManager
  254. ? DeGUILayout.ToggleButton(_settings.showPreviewPanel, "Preview Controls", styles.custom.inlineToggle)
  255. : DeGUILayout.ToggleButton(_settings.showPreviewPanel, "Preview Controls", styles.custom.inlineToggle, GUILayout.Width(120));
  256. if (EditorGUI.EndChangeCheck()) {
  257. EditorUtility.SetDirty(_settings);
  258. DOTweenPreviewManager.StopAllPreviews();
  259. }
  260. if (!hasManager) {
  261. if (GUILayout.Button(new GUIContent("Add Manager", "Adds a manager component which allows you to choose additional options for this gameObject"))) {
  262. _src.gameObject.AddComponent<DOTweenVisualManager>();
  263. }
  264. }
  265. GUILayout.EndHorizontal();
  266. }
  267. // Preview in editor
  268. bool isPreviewing = _settings.showPreviewPanel ? DOTweenPreviewManager.PreviewGUI(_src) : false;
  269. EditorGUI.BeginDisabledGroup(isPreviewing);
  270. // Choose target
  271. GUILayout.BeginHorizontal();
  272. _src.isActive = EditorGUILayout.Toggle(new GUIContent("", "If unchecked, this animation will not be created"), _src.isActive, GUILayout.Width(14));
  273. EditorGUI.BeginChangeCheck();
  274. EditorGUI.BeginChangeCheck();
  275. _src.targetIsSelf = DeGUILayout.ToggleButton(
  276. _src.targetIsSelf, _src.targetIsSelf ? _GuiC_selfTarget_true : _GuiC_selfTarget_false,
  277. new Color(1f, 0.78f, 0f), DeGUI.colors.bg.toggleOn, new Color(0.33f, 0.14f, 0.02f), DeGUI.colors.content.toggleOn,
  278. null, GUILayout.Width(47)
  279. );
  280. bool innerChanged = EditorGUI.EndChangeCheck();
  281. if (innerChanged) {
  282. _src.targetGO = null;
  283. GUI.changed = true;
  284. }
  285. if (_src.targetIsSelf) GUILayout.Label(_GuiC_selfTarget_true.tooltip);
  286. else {
  287. using (new DeGUI.ColorScope(null, null, _src.targetGO == null ? Color.red : Color.white)) {
  288. _src.targetGO = (GameObject)EditorGUILayout.ObjectField(_src.targetGO, typeof(GameObject), true);
  289. }
  290. _src.tweenTargetIsTargetGO = DeGUILayout.ToggleButton(
  291. _src.tweenTargetIsTargetGO, _src.tweenTargetIsTargetGO ? _GuiC_tweenTargetIsTargetGO_true : _GuiC_tweenTargetIsTargetGO_false,
  292. GUILayout.Width(131)
  293. );
  294. }
  295. bool check = EditorGUI.EndChangeCheck();
  296. if (check) _refreshRequired = true;
  297. GUILayout.EndHorizontal();
  298. GameObject targetGO = _src.targetIsSelf ? _src.gameObject : _src.targetGO;
  299. if (targetGO == null) {
  300. // Uses external target gameObject but it's not set
  301. if (_src.targetGO != null || _src.target != null) {
  302. _src.targetGO = null;
  303. _src.target = null;
  304. GUI.changed = true;
  305. }
  306. } else {
  307. GUILayout.BeginHorizontal();
  308. DOTweenAnimation.AnimationType prevAnimType = _src.animationType;
  309. // _src.animationType = (DOTweenAnimation.AnimationType)EditorGUILayout.EnumPopup(_src.animationType, EditorGUIUtils.popupButton);
  310. GUI.enabled = GUI.enabled && _src.isActive;
  311. _src.animationType = AnimationToDOTweenAnimationType(_AnimationType[EditorGUILayout.Popup(DOTweenAnimationTypeToPopupId(_src.animationType), _AnimationType)]);
  312. _src.autoPlay = DeGUILayout.ToggleButton(_src.autoPlay, new GUIContent("AutoPlay", "If selected, the tween will play automatically"));
  313. _src.autoKill = DeGUILayout.ToggleButton(_src.autoKill, new GUIContent("AutoKill", "If selected, the tween will be killed when it completes, and won't be reusable"));
  314. GUILayout.EndHorizontal();
  315. if (prevAnimType != _src.animationType) {
  316. // Set default optional values based on animation type
  317. _src.endValueTransform = null;
  318. _src.useTargetAsV3 = false;
  319. switch (_src.animationType) {
  320. case DOTweenAnimation.AnimationType.Move:
  321. case DOTweenAnimation.AnimationType.LocalMove:
  322. case DOTweenAnimation.AnimationType.Rotate:
  323. case DOTweenAnimation.AnimationType.LocalRotate:
  324. case DOTweenAnimation.AnimationType.Scale:
  325. _src.endValueV3 = Vector3.zero;
  326. _src.endValueFloat = 0;
  327. _src.optionalBool0 = _src.animationType == DOTweenAnimation.AnimationType.Scale;
  328. break;
  329. case DOTweenAnimation.AnimationType.UIWidthHeight:
  330. _src.endValueV3 = Vector3.zero;
  331. _src.endValueFloat = 0;
  332. _src.optionalBool0 = _src.animationType == DOTweenAnimation.AnimationType.UIWidthHeight;
  333. break;
  334. case DOTweenAnimation.AnimationType.Color:
  335. case DOTweenAnimation.AnimationType.Fade:
  336. _isLightSrc = targetGO.GetComponent<Light>() != null;
  337. _src.endValueFloat = 0;
  338. break;
  339. case DOTweenAnimation.AnimationType.Text:
  340. _src.optionalBool0 = true;
  341. break;
  342. case DOTweenAnimation.AnimationType.PunchPosition:
  343. case DOTweenAnimation.AnimationType.PunchRotation:
  344. case DOTweenAnimation.AnimationType.PunchScale:
  345. _src.endValueV3 = _src.animationType == DOTweenAnimation.AnimationType.PunchRotation ? new Vector3(0, 180, 0) : Vector3.one;
  346. _src.optionalFloat0 = 1;
  347. _src.optionalInt0 = 10;
  348. _src.optionalBool0 = false;
  349. break;
  350. case DOTweenAnimation.AnimationType.ShakePosition:
  351. case DOTweenAnimation.AnimationType.ShakeRotation:
  352. case DOTweenAnimation.AnimationType.ShakeScale:
  353. _src.endValueV3 = _src.animationType == DOTweenAnimation.AnimationType.ShakeRotation ? new Vector3(90, 90, 90) : Vector3.one;
  354. _src.optionalInt0 = 10;
  355. _src.optionalFloat0 = 90;
  356. _src.optionalBool0 = false;
  357. break;
  358. case DOTweenAnimation.AnimationType.CameraAspect:
  359. case DOTweenAnimation.AnimationType.CameraFieldOfView:
  360. case DOTweenAnimation.AnimationType.CameraOrthoSize:
  361. _src.endValueFloat = 0;
  362. break;
  363. case DOTweenAnimation.AnimationType.CameraPixelRect:
  364. case DOTweenAnimation.AnimationType.CameraRect:
  365. _src.endValueRect = new Rect(0, 0, 0, 0);
  366. break;
  367. }
  368. }
  369. if (_src.animationType == DOTweenAnimation.AnimationType.None) {
  370. _src.isValid = false;
  371. if (GUI.changed) EditorUtility.SetDirty(_src);
  372. return;
  373. }
  374. if (_refreshRequired || prevAnimType != _src.animationType || ComponentsChanged()) {
  375. _refreshRequired = false;
  376. _src.isValid = Validate(targetGO);
  377. // See if we need to choose between multiple targets
  378. #if true // UI_MARKER
  379. if (_src.animationType == DOTweenAnimation.AnimationType.Fade && targetGO.GetComponent<CanvasGroup>() != null && targetGO.GetComponent<Image>() != null) {
  380. _chooseTargetMode = ChooseTargetMode.BetweenCanvasGroupAndImage;
  381. // Reassign target and forcedTargetType if lost
  382. if (_src.forcedTargetType == DOTweenAnimation.TargetType.Unset) _src.forcedTargetType = _src.targetType;
  383. switch (_src.forcedTargetType) {
  384. case DOTweenAnimation.TargetType.CanvasGroup:
  385. _src.target = targetGO.GetComponent<CanvasGroup>();
  386. break;
  387. case DOTweenAnimation.TargetType.Image:
  388. _src.target = targetGO.GetComponent<Image>();
  389. break;
  390. }
  391. } else {
  392. #endif
  393. _chooseTargetMode = ChooseTargetMode.None;
  394. _src.forcedTargetType = DOTweenAnimation.TargetType.Unset;
  395. #if true // UI_MARKER
  396. }
  397. #endif
  398. }
  399. if (!_src.isValid) {
  400. GUI.color = Color.red;
  401. GUILayout.BeginVertical(GUI.skin.box);
  402. GUILayout.Label("No valid Component was found for the selected animation", EditorGUIUtils.wordWrapLabelStyle);
  403. GUILayout.EndVertical();
  404. GUI.color = Color.white;
  405. if (GUI.changed) EditorUtility.SetDirty(_src);
  406. return;
  407. }
  408. #if true // UI_MARKER
  409. // Special cases in which multiple target types could be used (set after validation)
  410. if (_chooseTargetMode == ChooseTargetMode.BetweenCanvasGroupAndImage && _src.forcedTargetType != DOTweenAnimation.TargetType.Unset) {
  411. FadeTargetType fadeTargetType = (FadeTargetType)Enum.Parse(typeof(FadeTargetType), _src.forcedTargetType.ToString());
  412. DOTweenAnimation.TargetType prevTargetType = _src.forcedTargetType;
  413. _src.forcedTargetType = (DOTweenAnimation.TargetType)Enum.Parse(typeof(DOTweenAnimation.TargetType), EditorGUILayout.EnumPopup(_src.animationType + " Target", fadeTargetType).ToString());
  414. if (_src.forcedTargetType != prevTargetType) {
  415. // Target type change > assign correct target
  416. switch (_src.forcedTargetType) {
  417. case DOTweenAnimation.TargetType.CanvasGroup:
  418. _src.target = targetGO.GetComponent<CanvasGroup>();
  419. break;
  420. case DOTweenAnimation.TargetType.Image:
  421. _src.target = targetGO.GetComponent<Image>();
  422. break;
  423. }
  424. }
  425. }
  426. #endif
  427. GUILayout.BeginHorizontal();
  428. _src.duration = EditorGUILayout.FloatField("Duration", _src.duration);
  429. if (_src.duration < 0) _src.duration = 0;
  430. _src.isSpeedBased = DeGUILayout.ToggleButton(_src.isSpeedBased, new GUIContent("SpeedBased", "If selected, the duration will count as units/degree x second"), DeGUI.styles.button.tool, GUILayout.Width(75));
  431. GUILayout.EndHorizontal();
  432. _src.delay = EditorGUILayout.FloatField("Delay", _src.delay);
  433. if (_src.delay < 0) _src.delay = 0;
  434. _src.isIndependentUpdate = EditorGUILayout.Toggle("Ignore TimeScale", _src.isIndependentUpdate);
  435. _src.easeType = EditorGUIUtils.FilteredEasePopup("Ease", _src.easeType);
  436. if (_src.easeType == Ease.INTERNAL_Custom) {
  437. _src.easeCurve = EditorGUILayout.CurveField(" Ease Curve", _src.easeCurve);
  438. }
  439. _src.loops = EditorGUILayout.IntField(new GUIContent("Loops", "Set to -1 for infinite loops"), _src.loops);
  440. if (_src.loops < -1) _src.loops = -1;
  441. if (_src.loops > 1 || _src.loops == -1)
  442. _src.loopType = (LoopType)EditorGUILayout.EnumPopup(" Loop Type", _src.loopType);
  443. _src.id = EditorGUILayout.TextField("ID", _src.id);
  444. bool canBeRelative = true;
  445. // End value and eventual specific options
  446. switch (_src.animationType) {
  447. case DOTweenAnimation.AnimationType.Move:
  448. case DOTweenAnimation.AnimationType.LocalMove:
  449. GUIEndValueV3(targetGO, _src.animationType == DOTweenAnimation.AnimationType.Move);
  450. _src.optionalBool0 = EditorGUILayout.Toggle(" Snapping", _src.optionalBool0);
  451. canBeRelative = !_src.useTargetAsV3;
  452. break;
  453. case DOTweenAnimation.AnimationType.Rotate:
  454. case DOTweenAnimation.AnimationType.LocalRotate:
  455. bool isRigidbody2D = DOTweenModuleUtils.Physics.HasRigidbody2D(_src);
  456. if (isRigidbody2D) GUIEndValueFloat();
  457. else {
  458. GUIEndValueV3(targetGO);
  459. _src.optionalRotationMode = (RotateMode)EditorGUILayout.EnumPopup(" Rotation Mode", _src.optionalRotationMode);
  460. }
  461. break;
  462. case DOTweenAnimation.AnimationType.Scale:
  463. if (_src.optionalBool0) GUIEndValueFloat();
  464. else GUIEndValueV3(targetGO);
  465. _src.optionalBool0 = EditorGUILayout.Toggle("Uniform Scale", _src.optionalBool0);
  466. break;
  467. case DOTweenAnimation.AnimationType.UIWidthHeight:
  468. if (_src.optionalBool0) GUIEndValueFloat();
  469. else GUIEndValueV2();
  470. _src.optionalBool0 = EditorGUILayout.Toggle("Uniform Scale", _src.optionalBool0);
  471. break;
  472. case DOTweenAnimation.AnimationType.Color:
  473. GUIEndValueColor();
  474. canBeRelative = false;
  475. break;
  476. case DOTweenAnimation.AnimationType.Fade:
  477. GUIEndValueFloat();
  478. if (_src.endValueFloat < 0) _src.endValueFloat = 0;
  479. if (!_isLightSrc && _src.endValueFloat > 1) _src.endValueFloat = 1;
  480. canBeRelative = false;
  481. break;
  482. case DOTweenAnimation.AnimationType.Text:
  483. GUIEndValueString();
  484. _src.optionalBool0 = EditorGUILayout.Toggle("Rich Text Enabled", _src.optionalBool0);
  485. _src.optionalScrambleMode = (ScrambleMode)EditorGUILayout.EnumPopup("Scramble Mode", _src.optionalScrambleMode);
  486. _src.optionalString = EditorGUILayout.TextField(new GUIContent("Custom Scramble", "Custom characters to use in case of ScrambleMode.Custom"), _src.optionalString);
  487. break;
  488. case DOTweenAnimation.AnimationType.PunchPosition:
  489. case DOTweenAnimation.AnimationType.PunchRotation:
  490. case DOTweenAnimation.AnimationType.PunchScale:
  491. GUIEndValueV3(targetGO);
  492. canBeRelative = false;
  493. _src.optionalInt0 = EditorGUILayout.IntSlider(new GUIContent(" Vibrato", "How much will the punch vibrate"), _src.optionalInt0, 1, 50);
  494. _src.optionalFloat0 = EditorGUILayout.Slider(new GUIContent(" Elasticity", "How much the vector will go beyond the starting position when bouncing backwards"), _src.optionalFloat0, 0, 1);
  495. if (_src.animationType == DOTweenAnimation.AnimationType.PunchPosition) _src.optionalBool0 = EditorGUILayout.Toggle(" Snapping", _src.optionalBool0);
  496. break;
  497. case DOTweenAnimation.AnimationType.ShakePosition:
  498. case DOTweenAnimation.AnimationType.ShakeRotation:
  499. case DOTweenAnimation.AnimationType.ShakeScale:
  500. GUIEndValueV3(targetGO);
  501. canBeRelative = false;
  502. _src.optionalInt0 = EditorGUILayout.IntSlider(new GUIContent(" Vibrato", "How much will the shake vibrate"), _src.optionalInt0, 1, 50);
  503. _src.optionalFloat0 = EditorGUILayout.Slider(new GUIContent(" Randomness", "The shake randomness"), _src.optionalFloat0, 0, 90);
  504. if (_src.animationType == DOTweenAnimation.AnimationType.ShakePosition) _src.optionalBool0 = EditorGUILayout.Toggle(" Snapping", _src.optionalBool0);
  505. break;
  506. case DOTweenAnimation.AnimationType.CameraAspect:
  507. case DOTweenAnimation.AnimationType.CameraFieldOfView:
  508. case DOTweenAnimation.AnimationType.CameraOrthoSize:
  509. GUIEndValueFloat();
  510. canBeRelative = false;
  511. break;
  512. case DOTweenAnimation.AnimationType.CameraBackgroundColor:
  513. GUIEndValueColor();
  514. canBeRelative = false;
  515. break;
  516. case DOTweenAnimation.AnimationType.CameraPixelRect:
  517. case DOTweenAnimation.AnimationType.CameraRect:
  518. GUIEndValueRect();
  519. canBeRelative = false;
  520. break;
  521. }
  522. // Final settings
  523. if (canBeRelative) _src.isRelative = EditorGUILayout.Toggle(" Relative", _src.isRelative);
  524. // Events
  525. AnimationInspectorGUI.AnimationEvents(this, _src);
  526. }
  527. EditorGUI.EndDisabledGroup();
  528. if (GUI.changed) EditorUtility.SetDirty(_src);
  529. }
  530. #endregion
  531. #region Methods
  532. // Returns TRUE if the Component layout on the src gameObject changed (a Component was added or removed)
  533. bool ComponentsChanged()
  534. {
  535. int prevTotComponentsOnSrc = _totComponentsOnSrc;
  536. _totComponentsOnSrc = _src.gameObject.GetComponents<Component>().Length;
  537. return prevTotComponentsOnSrc != _totComponentsOnSrc;
  538. }
  539. // Checks if a Component that can be animated with the given animationType is attached to the src
  540. bool Validate(GameObject targetGO)
  541. {
  542. if (_src.animationType == DOTweenAnimation.AnimationType.None) return false;
  543. Component srcTarget;
  544. // First check for external plugins
  545. #if false // TK2D_MARKER
  546. if (_Tk2dAnimationTypeToComponent.ContainsKey(_src.animationType)) {
  547. foreach (Type t in _Tk2dAnimationTypeToComponent[_src.animationType]) {
  548. srcTarget = targetGO.GetComponent(t);
  549. if (srcTarget != null) {
  550. _src.target = srcTarget;
  551. _src.targetType = DOTweenAnimation.TypeToDOTargetType(t);
  552. return true;
  553. }
  554. }
  555. }
  556. #endif
  557. #if false // TEXTMESHPRO_MARKER
  558. if (_TMPAnimationTypeToComponent.ContainsKey(_src.animationType)) {
  559. foreach (Type t in _TMPAnimationTypeToComponent[_src.animationType]) {
  560. srcTarget = targetGO.GetComponent(t);
  561. if (srcTarget != null) {
  562. _src.target = srcTarget;
  563. _src.targetType = DOTweenAnimation.TypeToDOTargetType(t);
  564. return true;
  565. }
  566. }
  567. }
  568. #endif
  569. // Then check for regular stuff
  570. if (_AnimationTypeToComponent.ContainsKey(_src.animationType)) {
  571. foreach (Type t in _AnimationTypeToComponent[_src.animationType]) {
  572. srcTarget = targetGO.GetComponent(t);
  573. if (srcTarget != null) {
  574. _src.target = srcTarget;
  575. _src.targetType = DOTweenAnimation.TypeToDOTargetType(t);
  576. return true;
  577. }
  578. }
  579. }
  580. return false;
  581. }
  582. DOTweenAnimation.AnimationType AnimationToDOTweenAnimationType(string animation)
  583. {
  584. if (_datString == null) _datString = Enum.GetNames(typeof(DOTweenAnimation.AnimationType));
  585. animation = animation.Replace("/", "");
  586. return (DOTweenAnimation.AnimationType)(Array.IndexOf(_datString, animation));
  587. }
  588. int DOTweenAnimationTypeToPopupId(DOTweenAnimation.AnimationType animation)
  589. {
  590. return Array.IndexOf(_animationTypeNoSlashes, animation.ToString());
  591. }
  592. #endregion
  593. #region GUI Draw Methods
  594. void GUIEndValueFloat()
  595. {
  596. GUILayout.BeginHorizontal();
  597. GUIToFromButton();
  598. _src.endValueFloat = EditorGUILayout.FloatField(_src.endValueFloat);
  599. GUILayout.EndHorizontal();
  600. }
  601. void GUIEndValueColor()
  602. {
  603. GUILayout.BeginHorizontal();
  604. GUIToFromButton();
  605. _src.endValueColor = EditorGUILayout.ColorField(_src.endValueColor);
  606. GUILayout.EndHorizontal();
  607. }
  608. void GUIEndValueV3(GameObject targetGO, bool optionalTransform = false)
  609. {
  610. GUILayout.BeginHorizontal();
  611. GUIToFromButton();
  612. if (_src.useTargetAsV3) {
  613. Transform prevT = _src.endValueTransform;
  614. _src.endValueTransform = EditorGUILayout.ObjectField(_src.endValueTransform, typeof(Transform), true) as Transform;
  615. if (_src.endValueTransform != prevT && _src.endValueTransform != null) {
  616. #if true // UI_MARKER
  617. // Check that it's a Transform for a Transform or a RectTransform for a RectTransform
  618. if (targetGO.GetComponent<RectTransform>() != null) {
  619. if (_src.endValueTransform.GetComponent<RectTransform>() == null) {
  620. EditorUtility.DisplayDialog("DOTween Pro", "For Unity UI elements, the target must also be a UI element", "Ok");
  621. _src.endValueTransform = null;
  622. }
  623. } else if (_src.endValueTransform.GetComponent<RectTransform>() != null) {
  624. EditorUtility.DisplayDialog("DOTween Pro", "You can't use a UI target for a non UI object", "Ok");
  625. _src.endValueTransform = null;
  626. }
  627. #endif
  628. }
  629. } else {
  630. _src.endValueV3 = EditorGUILayout.Vector3Field("", _src.endValueV3, GUILayout.Height(16));
  631. }
  632. if (optionalTransform) {
  633. if (GUILayout.Button(_src.useTargetAsV3 ? "target" : "value", EditorGUIUtils.sideBtStyle, GUILayout.Width(44))) _src.useTargetAsV3 = !_src.useTargetAsV3;
  634. }
  635. GUILayout.EndHorizontal();
  636. #if true // UI_MARKER
  637. if (_src.useTargetAsV3 && _src.endValueTransform != null && _src.target is RectTransform) {
  638. EditorGUILayout.HelpBox("NOTE: when using a UI target, the tween will be created during Start instead of Awake", MessageType.Info);
  639. }
  640. #endif
  641. }
  642. void GUIEndValueV2()
  643. {
  644. GUILayout.BeginHorizontal();
  645. GUIToFromButton();
  646. _src.endValueV2 = EditorGUILayout.Vector2Field("", _src.endValueV2, GUILayout.Height(16));
  647. GUILayout.EndHorizontal();
  648. }
  649. void GUIEndValueString()
  650. {
  651. GUILayout.BeginHorizontal();
  652. GUIToFromButton();
  653. _src.endValueString = EditorGUILayout.TextArea(_src.endValueString, EditorGUIUtils.wordWrapTextArea);
  654. GUILayout.EndHorizontal();
  655. }
  656. void GUIEndValueRect()
  657. {
  658. GUILayout.BeginHorizontal();
  659. GUIToFromButton();
  660. _src.endValueRect = EditorGUILayout.RectField(_src.endValueRect);
  661. GUILayout.EndHorizontal();
  662. }
  663. void GUIToFromButton()
  664. {
  665. if (GUILayout.Button(_src.isFrom ? "FROM" : "TO", EditorGUIUtils.sideBtStyle, GUILayout.Width(90))) _src.isFrom = !_src.isFrom;
  666. GUILayout.Space(16);
  667. }
  668. #endregion
  669. }
  670. // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
  671. // ███ INTERNAL CLASSES ████████████████████████████████████████████████████████████████████████████████████████████████
  672. // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
  673. [InitializeOnLoad]
  674. static class Initializer
  675. {
  676. static Initializer()
  677. {
  678. DOTweenAnimation.OnReset += OnReset;
  679. }
  680. static void OnReset(DOTweenAnimation src)
  681. {
  682. DOTweenSettings settings = DOTweenUtilityWindow.GetDOTweenSettings();
  683. if (settings == null) return;
  684. Undo.RecordObject(src, "DOTweenAnimation");
  685. src.autoPlay = settings.defaultAutoPlay == AutoPlay.All || settings.defaultAutoPlay == AutoPlay.AutoPlayTweeners;
  686. src.autoKill = settings.defaultAutoKill;
  687. EditorUtility.SetDirty(src);
  688. }
  689. }
  690. }