Няма описание
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SpriteEditorWindow.cs 53KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398
  1. using System;
  2. using UnityEngine;
  3. using System.Collections.Generic;
  4. using UnityTexture2D = UnityEngine.Texture2D;
  5. using System.Linq;
  6. using System.Reflection;
  7. using UnityEngine.UIElements;
  8. namespace UnityEditor.U2D.Sprites
  9. {
  10. /// <summary>
  11. /// Interface for providing a ISpriteEditorDataProvider instance.
  12. /// </summary>
  13. /// <typeparam name="T">The object type the implemented interface is interested in.</typeparam>
  14. public interface ISpriteDataProviderFactory<T>
  15. {
  16. /// <summary>
  17. /// Implement the method to provide an instance of ISpriteEditorDataProvider for a given object.
  18. /// </summary>
  19. /// <param name="obj">The object that requires an instance of ISpriteEditorDataProvider.</param>
  20. /// <returns>An instance of ISpriteEditorDataProvider or null if not supported by the interface.</returns>
  21. ISpriteEditorDataProvider CreateDataProvider(T obj);
  22. }
  23. [AttributeUsage(AttributeTargets.Method)]
  24. internal class SpriteEditorAssetPathProviderAttribute : Attribute
  25. {
  26. [RequiredSignature]
  27. private static string GetAssetPath(UnityEngine.Object obj)
  28. {
  29. return null;
  30. }
  31. }
  32. [AttributeUsage(AttributeTargets.Method)]
  33. internal class SpriteObjectProviderAttribute : Attribute
  34. {
  35. [RequiredSignature]
  36. private static Sprite GetSpriteObject(UnityEngine.Object obj)
  37. {
  38. return null;
  39. }
  40. }
  41. /// <summary>
  42. /// Utility class that collects methods with SpriteDataProviderFactoryAttribute and SpriteDataProviderAssetPathProviderAttribute.
  43. /// </summary>
  44. public class SpriteDataProviderFactories
  45. {
  46. struct SpriteDataProviderFactory
  47. {
  48. public object instance;
  49. public MethodInfo method;
  50. public Type methodType;
  51. }
  52. static SpriteDataProviderFactory[] s_Factories;
  53. static TypeCache.MethodCollection s_AssetPathProvider;
  54. static TypeCache.MethodCollection s_SpriteObjectProvider;
  55. static SpriteDataProviderFactory[] GetFactories()
  56. {
  57. CacheDataProviders();
  58. return s_Factories;
  59. }
  60. static TypeCache.MethodCollection GetAssetPathProvider()
  61. {
  62. CacheDataProviders();
  63. return s_AssetPathProvider;
  64. }
  65. static TypeCache.MethodCollection GetSpriteObjectProvider()
  66. {
  67. CacheDataProviders();
  68. return s_SpriteObjectProvider;
  69. }
  70. static void CacheDataProviders()
  71. {
  72. if (s_Factories != null)
  73. return;
  74. var factories = TypeCache.GetTypesDerivedFrom(typeof(ISpriteDataProviderFactory<>));
  75. var factoryList = new List<SpriteDataProviderFactory>();
  76. foreach (var factory in factories)
  77. {
  78. try
  79. {
  80. var ins = Activator.CreateInstance(factory);
  81. foreach (var i in factory.GetInterfaces())
  82. {
  83. var genericArguments = i.GetGenericArguments();
  84. if (genericArguments.Length == 1)
  85. {
  86. var s = new SpriteDataProviderFactory();
  87. s.instance = ins;
  88. var method = i.GetMethod("CreateDataProvider");
  89. s.method = method;
  90. s.methodType = genericArguments[0];
  91. factoryList.Add(s);
  92. }
  93. }
  94. }
  95. catch (Exception ex)
  96. {
  97. Debug.LogAssertion(ex);
  98. }
  99. }
  100. s_Factories = factoryList.ToArray();
  101. s_AssetPathProvider = TypeCache.GetMethodsWithAttribute<SpriteEditorAssetPathProviderAttribute>();
  102. s_SpriteObjectProvider = TypeCache.GetMethodsWithAttribute<SpriteObjectProviderAttribute>();
  103. }
  104. /// <summary>
  105. /// Initialized and collect methods with SpriteDataProviderFactoryAttribute and SpriteDataProviderAssetPathProviderAttribute.
  106. /// </summary>
  107. public void Init()
  108. {
  109. CacheDataProviders();
  110. }
  111. /// <summary>
  112. /// Given a UnityEngine.Object, determine the ISpriteEditorDataProvider associate with the object by going
  113. /// going through the methods with SpriteDataProviderFactoryAttribute.
  114. /// </summary>
  115. /// <remarks>When none of the methods is able to provide ISpriteEditorDataProvider for the object, the method will
  116. /// try to cast the AssetImporter of the object to ISpriteEditorDataProvider.</remarks>
  117. /// <param name="obj">The UnityEngine.Object to query.</param>
  118. /// <returns>The ISpriteEditorDataProvider associated with the object.</returns>
  119. public ISpriteEditorDataProvider GetSpriteEditorDataProviderFromObject(UnityEngine.Object obj)
  120. {
  121. if (obj != null)
  122. {
  123. var objType = obj.GetType();
  124. foreach (var factory in GetFactories())
  125. {
  126. try
  127. {
  128. if (factory.methodType == objType)
  129. {
  130. var dataProvider = factory.method.Invoke(factory.instance, new[] { obj }) as ISpriteEditorDataProvider;
  131. if (dataProvider != null && !dataProvider.Equals(null))
  132. return dataProvider;
  133. }
  134. }
  135. catch (Exception ex)
  136. {
  137. Debug.LogAssertion(ex);
  138. }
  139. }
  140. if (obj is ISpriteEditorDataProvider)
  141. return (ISpriteEditorDataProvider)obj;
  142. // now we try the importer
  143. var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(obj));
  144. return importer as ISpriteEditorDataProvider;
  145. }
  146. return null;
  147. }
  148. /// <summary>
  149. /// Given a UnityEngine.Object, determine the asset path associate with the object by going
  150. /// going through the methods with SpriteDataProviderAssetPathProviderAttribute.
  151. /// </summary>
  152. /// <remarks>When none of the methods is able to provide the asset path for the object, the method will return null</remarks>
  153. /// <param name="obj">The UnityEngine.Object to query</param>
  154. /// <returns>The asset path for the object</returns>
  155. internal string GetAssetPath(UnityEngine.Object obj)
  156. {
  157. foreach (var assetPathProvider in GetAssetPathProvider())
  158. {
  159. try
  160. {
  161. var path = assetPathProvider.Invoke(null, new object[] { obj }) as string;
  162. if (!string.IsNullOrEmpty(path))
  163. return path;
  164. }
  165. catch (Exception ex)
  166. {
  167. Debug.LogException(ex);
  168. }
  169. }
  170. return null;
  171. }
  172. /// <summary>
  173. /// Given a UnityEngine.Object, determine the Sprite object associate with the object by going
  174. /// going through the methods with SpriteObjectProviderAttribute.
  175. /// </summary>
  176. /// <remarks>When none of the methods is able to provide a Sprite object, the method will return null</remarks>
  177. /// <param name="obj">The UnityEngine.Object to query</param>
  178. /// <returns>The Sprite object</returns>
  179. internal Sprite GetSpriteObject(UnityEngine.Object obj)
  180. {
  181. foreach (var spriteObjectProvider in GetSpriteObjectProvider())
  182. {
  183. try
  184. {
  185. var sprite = spriteObjectProvider.Invoke(null, new object[] { obj }) as Sprite;
  186. if (sprite != null && !sprite.Equals(null))
  187. return sprite;
  188. }
  189. catch (Exception ex)
  190. {
  191. Debug.LogException(ex);
  192. }
  193. }
  194. return null;
  195. }
  196. }
  197. [InitializeOnLoad]
  198. internal class SpriteEditorWindow : SpriteUtilityWindow, ISpriteEditor
  199. {
  200. static SpriteEditorWindow()
  201. {
  202. UnityEditor.SpriteUtilityWindow.SetShowSpriteEditorWindowWithObject((x) =>
  203. {
  204. SpriteEditorWindow.GetWindow(x);
  205. return true;
  206. });
  207. }
  208. private class SpriteEditorWindowStyles
  209. {
  210. public static readonly GUIContent editingDisableMessageBecausePlaymodeLabel = EditorGUIUtility.TrTextContent("Editing is disabled during play mode");
  211. public static readonly GUIContent editingDisableMessageBecauseNonEditableLabel = EditorGUIUtility.TrTextContent("Editing is disabled because the asset is not editable.");
  212. public static readonly GUIContent revertButtonLabel = EditorGUIUtility.TrTextContent("Revert");
  213. public static readonly GUIContent applyButtonLabel = EditorGUIUtility.TrTextContent("Apply");
  214. public static readonly GUIContent pendingChangesDialogContent = EditorGUIUtility.TrTextContent("The asset was modified outside of Sprite Editor Window.\nDo you want to apply pending changes?");
  215. public static readonly GUIContent applyRevertDialogTitle = EditorGUIUtility.TrTextContent("Unapplied import settings");
  216. public static readonly GUIContent applyRevertDialogContent = EditorGUIUtility.TrTextContent("Unapplied import settings for '{0}'");
  217. public static readonly GUIContent noSelectionWarning = EditorGUIUtility.TrTextContent("No texture or sprite selected");
  218. public static readonly GUIContent noModuleWarning = EditorGUIUtility.TrTextContent("No Sprite Editor module available");
  219. public static readonly GUIContent applyRevertModuleDialogTitle = EditorGUIUtility.TrTextContent("Unapplied module changes");
  220. public static readonly GUIContent applyRevertModuleDialogContent = EditorGUIUtility.TrTextContent("You have unapplied changes from the current module");
  221. public static readonly GUIContent revertConfirmationDialogTitle = EditorGUIUtility.TrTextContent("Revert Changes");
  222. public static readonly GUIContent revertConfirmationDialogContent = EditorGUIUtility.TrTextContent("Are you sure you want to revert the changes?");
  223. public static readonly GUIContent applyConfirmationDialogTitle = EditorGUIUtility.TrTextContent("Apply Changes");
  224. public static readonly GUIContent applyConfirmationDialogContent = EditorGUIUtility.TrTextContent("Are you sure you want to apply the changes?");
  225. public static readonly GUIContent yesLabel = EditorGUIUtility.TrTextContent("Yes");
  226. public static readonly GUIContent noLabel = EditorGUIUtility.TrTextContent("No");
  227. public static readonly string styleSheetPath = "Packages/com.unity.2d.sprite/Editor/UI/SpriteEditor/SpriteEditor.uss";
  228. }
  229. class CurrentResetContext
  230. {
  231. public string assetPath;
  232. }
  233. private const float k_MarginForFraming = 0.05f;
  234. private const float k_WarningMessageWidth = 250f;
  235. private const float k_WarningMessageHeight = 40f;
  236. private const float k_ModuleListWidth = 90f;
  237. private const string k_RefreshOnNextRepaintCommandEvent = "RefreshOnNextRepaintCommand";
  238. bool m_ResetOnNextRepaint;
  239. bool m_ResetCommandSent;
  240. private List<SpriteRect> m_RectsCache;
  241. ISpriteEditorDataProvider m_SpriteDataProvider;
  242. private bool m_RequestRepaint = false;
  243. public static bool s_OneClickDragStarted = false;
  244. string m_SelectedAssetPath;
  245. bool m_AssetNotEditable;
  246. private IEventSystem m_EventSystem;
  247. private IUndoSystem m_UndoSystem;
  248. private IAssetDatabase m_AssetDatabase;
  249. private IGUIUtility m_GUIUtility;
  250. private UnityTexture2D m_OutlineTexture;
  251. private UnityTexture2D m_ReadableTexture;
  252. private Dictionary<Type, RequireSpriteDataProviderAttribute> m_ModuleRequireSpriteDataProvider = new Dictionary<Type, RequireSpriteDataProviderAttribute>();
  253. private IMGUIContainer m_ToolbarIMGUIElement;
  254. private IMGUIContainer m_MainViewIMGUIElement;
  255. private VisualElement m_ModuleViewElement;
  256. private VisualElement m_MainViewElement;
  257. SpriteDataProviderFactories m_SpriteDataProviderFactories;
  258. [SerializeField]
  259. private UnityEngine.Object m_SelectedObject;
  260. [SerializeField]
  261. private string m_SelectedSpriteRectGUID;
  262. internal Func<string, string, bool> onHandleApplyRevertDialog = ShowHandleApplyRevertDialog;
  263. private CurrentResetContext m_CurrentResetContext = null;
  264. public static void GetWindow(UnityEngine.Object obj)
  265. {
  266. var window = EditorWindow.GetWindow<SpriteEditorWindow>();
  267. window.selectedObject = obj;
  268. }
  269. public SpriteEditorWindow()
  270. {
  271. m_EventSystem = new EventSystem();
  272. m_UndoSystem = new UndoSystem();
  273. m_AssetDatabase = new AssetDatabaseSystem();
  274. m_GUIUtility = new GUIUtilitySystem();
  275. }
  276. void ModifierKeysChanged()
  277. {
  278. if (EditorWindow.focusedWindow == this)
  279. {
  280. Repaint();
  281. }
  282. }
  283. private void OnFocus()
  284. {
  285. if (selectedObject != Selection.activeObject)
  286. OnSelectionChange();
  287. if (selectedProviderChanged)
  288. RefreshSpriteEditorWindow();
  289. }
  290. internal UnityEngine.Object selectedObject
  291. {
  292. get { return m_SelectedObject; }
  293. set
  294. {
  295. m_SelectedObject = value;
  296. RefreshSpriteEditorWindow();
  297. }
  298. }
  299. string selectedAssetPath
  300. {
  301. get => m_SelectedAssetPath;
  302. set
  303. {
  304. m_SelectedAssetPath = value;
  305. m_AssetNotEditable = !AssetDatabase.IsOpenForEdit(m_SelectedAssetPath);
  306. }
  307. }
  308. public void RefreshPropertiesCache()
  309. {
  310. var obj = AssetDatabase.LoadMainAssetAtPath(selectedAssetPath);
  311. m_SpriteDataProvider = spriteDataProviderFactories.GetSpriteEditorDataProviderFromObject(obj);
  312. if (!IsSpriteDataProviderValid())
  313. {
  314. selectedAssetPath = "";
  315. return;
  316. }
  317. m_SpriteDataProvider.InitSpriteEditorDataProvider();
  318. var textureProvider = m_SpriteDataProvider.GetDataProvider<ITextureDataProvider>();
  319. if (textureProvider != null)
  320. {
  321. int width = 0, height = 0;
  322. textureProvider.GetTextureActualWidthAndHeight(out width, out height);
  323. m_Texture = textureProvider.previewTexture == null ? null : new PreviewTexture2D(textureProvider.previewTexture, width, height);
  324. }
  325. }
  326. internal string GetSelectionAssetPath()
  327. {
  328. var path = spriteDataProviderFactories.GetAssetPath(selectedObject);
  329. if (string.IsNullOrEmpty(path))
  330. path = m_AssetDatabase.GetAssetPath(selectedObject);
  331. return path;
  332. }
  333. public void InvalidatePropertiesCache()
  334. {
  335. spriteRects = null;
  336. m_SpriteDataProvider = null;
  337. }
  338. private Rect warningMessageRect
  339. {
  340. get
  341. {
  342. return new Rect(
  343. position.width - k_WarningMessageWidth - k_InspectorWindowMargin - k_ScrollbarMargin,
  344. k_InspectorWindowMargin + k_ScrollbarMargin,
  345. k_WarningMessageWidth,
  346. k_WarningMessageHeight);
  347. }
  348. }
  349. public SpriteImportMode spriteImportMode
  350. {
  351. get { return !IsSpriteDataProviderValid() ? SpriteImportMode.None : m_SpriteDataProvider.spriteImportMode; }
  352. }
  353. bool activeDataProviderSelected
  354. {
  355. get { return m_SpriteDataProvider != null; }
  356. }
  357. public bool textureIsDirty
  358. {
  359. get
  360. {
  361. return hasUnsavedChanges;
  362. }
  363. set
  364. {
  365. hasUnsavedChanges = value;
  366. }
  367. }
  368. public bool selectedProviderChanged
  369. {
  370. get
  371. {
  372. var assetPath = GetSelectionAssetPath();
  373. var dataProvider = spriteDataProviderFactories.GetSpriteEditorDataProviderFromObject(selectedObject);
  374. return dataProvider != null && selectedAssetPath != assetPath;
  375. }
  376. }
  377. void OnSelectionChange()
  378. {
  379. selectedObject = Selection.activeObject;
  380. RefreshSpriteEditorWindow();
  381. }
  382. void RefreshSpriteEditorWindow()
  383. {
  384. // In case of changed of texture/sprite or selected on non texture object
  385. bool updateModules = false;
  386. if (selectedProviderChanged)
  387. {
  388. HandleApplyRevertDialog(SpriteEditorWindowStyles.applyRevertDialogTitle.text,
  389. String.Format(SpriteEditorWindowStyles.applyRevertDialogContent.text, selectedAssetPath));
  390. selectedAssetPath = GetSelectionAssetPath();
  391. ResetWindow();
  392. ResetZoomAndScroll();
  393. RefreshPropertiesCache();
  394. RefreshRects();
  395. updateModules = true;
  396. }
  397. if (m_RectsCache != null)
  398. {
  399. UpdateSelectedSpriteRectFromSelection();
  400. }
  401. // We only update modules when data provider changed
  402. if (updateModules)
  403. UpdateAvailableModules();
  404. Repaint();
  405. }
  406. private void UpdateSelectedSpriteRectFromSelection()
  407. {
  408. if (Selection.activeObject is UnityEngine.Sprite)
  409. {
  410. UpdateSelectedSpriteRect(Selection.activeObject as UnityEngine.Sprite);
  411. }
  412. else
  413. {
  414. var sprite = spriteDataProviderFactories.GetSpriteObject(Selection.activeObject);
  415. UpdateSelectedSpriteRect(sprite);
  416. }
  417. }
  418. public void ResetWindow()
  419. {
  420. InvalidatePropertiesCache();
  421. textureIsDirty = false;
  422. saveChangesMessage = SpriteEditorWindowStyles.applyRevertModuleDialogContent.text;
  423. }
  424. public void ResetZoomAndScroll()
  425. {
  426. m_Zoom = -1;
  427. m_ScrollPosition = Vector2.zero;
  428. }
  429. SpriteDataProviderFactories spriteDataProviderFactories
  430. {
  431. get
  432. {
  433. if (m_SpriteDataProviderFactories == null)
  434. {
  435. m_SpriteDataProviderFactories = new SpriteDataProviderFactories();
  436. m_SpriteDataProviderFactories.Init();
  437. }
  438. return m_SpriteDataProviderFactories;
  439. }
  440. }
  441. void OnEnable()
  442. {
  443. name = "SpriteEditorWindow";
  444. titleContent = EditorGUIUtility.TrTextContentWithIcon(L10n.Tr("Sprite Editor"), "Packages/com.unity.2d.sprite/Editor/Assets/SpriteEditor.png");
  445. selectedObject = Selection.activeObject;
  446. minSize = new Vector2(360, 200);
  447. m_UndoSystem.RegisterUndoCallback(UndoRedoPerformed);
  448. EditorApplication.modifierKeysChanged += ModifierKeysChanged;
  449. EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
  450. EditorApplication.quitting += OnEditorApplicationQuit;
  451. AssemblyReloadEvents.beforeAssemblyReload += OnBeforeAssemblyReload;
  452. if (selectedProviderChanged)
  453. selectedAssetPath = GetSelectionAssetPath();
  454. ResetWindow();
  455. RefreshPropertiesCache();
  456. bool noSelectedSprite = string.IsNullOrEmpty(m_SelectedSpriteRectGUID);
  457. RefreshRects();
  458. if (noSelectedSprite)
  459. UpdateSelectedSpriteRectFromSelection();
  460. UnityEditor.SpriteUtilityWindow.SetApplySpriteEditorWindow(RebuildCache);
  461. }
  462. void CreateGUI()
  463. {
  464. if (m_MainViewElement == null)
  465. {
  466. if (SetupVisualElements())
  467. InitModules();
  468. }
  469. }
  470. private bool SetupVisualElements()
  471. {
  472. var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>(SpriteEditorWindowStyles.styleSheetPath);
  473. if (styleSheet != null)
  474. {
  475. m_ToolbarIMGUIElement = new IMGUIContainer(DoToolbarGUI)
  476. {
  477. name = "spriteEditorWindowToolbar",
  478. };
  479. m_MainViewIMGUIElement = new IMGUIContainer(DoTextureAndModulesGUI)
  480. {
  481. name = "mainViewIMGUIElement"
  482. };
  483. m_MainViewElement = new VisualElement()
  484. {
  485. name = "spriteEditorWindowMainView",
  486. };
  487. m_ModuleViewElement = new VisualElement()
  488. {
  489. name = "moduleViewElement",
  490. pickingMode = PickingMode.Ignore
  491. };
  492. m_MainViewElement.Add(m_MainViewIMGUIElement);
  493. m_MainViewElement.Add(m_ModuleViewElement);
  494. var root = rootVisualElement;
  495. root.styleSheetList.Add(styleSheet);
  496. root.Add(m_ToolbarIMGUIElement);
  497. root.Add(m_MainViewElement);
  498. return true;
  499. }
  500. return false;
  501. }
  502. private void UndoRedoPerformed()
  503. {
  504. // Was selected texture changed by undo?
  505. if (selectedProviderChanged)
  506. RefreshSpriteEditorWindow();
  507. InitSelectedSpriteRect();
  508. Repaint();
  509. }
  510. private void InitSelectedSpriteRect()
  511. {
  512. SpriteRect newSpriteRect = null;
  513. if (m_RectsCache != null && m_RectsCache.Count > 0)
  514. {
  515. if (selectedSpriteRect != null)
  516. newSpriteRect = m_RectsCache.FirstOrDefault(x => x.spriteID == selectedSpriteRect.spriteID) != null ? selectedSpriteRect : m_RectsCache[0];
  517. else
  518. newSpriteRect = m_RectsCache[0];
  519. }
  520. selectedSpriteRect = newSpriteRect;
  521. }
  522. void OnGUI()
  523. {
  524. CreateGUI();
  525. }
  526. public override void SaveChanges()
  527. {
  528. var oldDelegate = onHandleApplyRevertDialog;
  529. onHandleApplyRevertDialog = (x, y) => true;
  530. HandleApplyRevertDialog(SpriteEditorWindowStyles.applyRevertDialogTitle.text,
  531. String.Format(SpriteEditorWindowStyles.applyRevertDialogContent.text, selectedAssetPath));
  532. onHandleApplyRevertDialog = oldDelegate;
  533. base.SaveChanges();
  534. }
  535. private void OnDisable()
  536. {
  537. Undo.undoRedoPerformed -= UndoRedoPerformed;
  538. InvalidatePropertiesCache();
  539. EditorApplication.modifierKeysChanged -= ModifierKeysChanged;
  540. EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
  541. EditorApplication.quitting -= OnEditorApplicationQuit;
  542. AssemblyReloadEvents.beforeAssemblyReload -= OnBeforeAssemblyReload;
  543. if (m_OutlineTexture != null)
  544. {
  545. DestroyImmediate(m_OutlineTexture);
  546. m_OutlineTexture = null;
  547. }
  548. if (m_ReadableTexture)
  549. {
  550. DestroyImmediate(m_ReadableTexture);
  551. m_ReadableTexture = null;
  552. }
  553. if (m_CurrentModule != null)
  554. m_CurrentModule.OnModuleDeactivate();
  555. UnityEditor.SpriteUtilityWindow.SetApplySpriteEditorWindow(null);
  556. if (m_MainViewElement != null)
  557. {
  558. rootVisualElement.Remove(m_MainViewElement);
  559. m_MainViewElement = null;
  560. }
  561. }
  562. void OnPlayModeStateChanged(PlayModeStateChange playModeState)
  563. {
  564. if (PlayModeStateChange.EnteredPlayMode == playModeState || PlayModeStateChange.EnteredEditMode == playModeState)
  565. {
  566. RebuildCache();
  567. }
  568. }
  569. void OnEditorApplicationQuit()
  570. {
  571. HandleApplyRevertDialog(SpriteEditorWindowStyles.applyRevertDialogTitle.text,
  572. String.Format(SpriteEditorWindowStyles.applyRevertDialogContent.text, selectedAssetPath));
  573. }
  574. void OnBeforeAssemblyReload()
  575. {
  576. HandleApplyRevertDialog(SpriteEditorWindowStyles.applyRevertDialogTitle.text,
  577. String.Format(SpriteEditorWindowStyles.applyRevertDialogContent.text, selectedAssetPath));
  578. }
  579. static bool ShowHandleApplyRevertDialog(string dialogTitle, string dialogContent)
  580. {
  581. return EditorUtility.DisplayDialog(dialogTitle, dialogContent,
  582. SpriteEditorWindowStyles.applyButtonLabel.text, SpriteEditorWindowStyles.revertButtonLabel.text);
  583. }
  584. void HandleApplyRevertDialog(string dialogTitle, string dialogContent)
  585. {
  586. if (textureIsDirty && IsSpriteDataProviderValid())
  587. {
  588. if (onHandleApplyRevertDialog(dialogTitle, dialogContent))
  589. DoApply();
  590. else
  591. DoRevert();
  592. SetupModule(m_CurrentModuleIndex);
  593. }
  594. }
  595. bool IsSpriteDataProviderValid()
  596. {
  597. return m_SpriteDataProvider != null && !m_SpriteDataProvider.Equals(null);
  598. }
  599. void RefreshRects()
  600. {
  601. spriteRects = null;
  602. if (IsSpriteDataProviderValid())
  603. {
  604. m_RectsCache = m_SpriteDataProvider.GetSpriteRects().ToList();
  605. }
  606. InitSelectedSpriteRect();
  607. }
  608. private void UpdateAssetSelectionChange()
  609. {
  610. if (selectedProviderChanged)
  611. {
  612. ResetOnNextRepaint();
  613. }
  614. if (m_ResetCommandSent || (UnityEngine.Event.current.type == EventType.ExecuteCommand && UnityEngine.Event.current.commandName == k_RefreshOnNextRepaintCommandEvent))
  615. {
  616. m_ResetCommandSent = false;
  617. if (selectedProviderChanged || !IsSpriteDataProviderValid())
  618. selectedAssetPath = GetSelectionAssetPath();
  619. RebuildCache();
  620. }
  621. }
  622. internal void ResetOnNextRepaint()
  623. {
  624. //Because we can't show dialog in a repaint/layout event, we need to send event to IMGUI to trigger this.
  625. //The event is now sent through the Update loop.
  626. m_ResetOnNextRepaint = true;
  627. if (textureIsDirty)
  628. {
  629. // We can't depend on the existing data provider to set data because a reimport might cause
  630. // the data provider to be invalid. We store up the current asset path so that in DoApply()
  631. // the modified data can be set correctly to correct asset.
  632. if (m_CurrentResetContext != null)
  633. Debug.LogError("Existing reset not completed for " + m_CurrentResetContext.assetPath);
  634. m_CurrentResetContext = new CurrentResetContext()
  635. {
  636. assetPath = selectedAssetPath
  637. };
  638. }
  639. }
  640. void Update()
  641. {
  642. if (m_ResetOnNextRepaint)
  643. {
  644. m_ResetOnNextRepaint = false;
  645. m_ResetCommandSent = true;
  646. var e = EditorGUIUtility.CommandEvent(k_RefreshOnNextRepaintCommandEvent);
  647. this.SendEvent(e);
  648. }
  649. }
  650. private void RebuildCache()
  651. {
  652. HandleApplyRevertDialog(SpriteEditorWindowStyles.applyRevertDialogTitle.text, SpriteEditorWindowStyles.pendingChangesDialogContent.text);
  653. ResetWindow();
  654. RefreshPropertiesCache();
  655. RefreshRects();
  656. UpdateAvailableModules();
  657. }
  658. private void DoTextureAndModulesGUI()
  659. {
  660. // Don't do anything until reset event is sent
  661. if (m_ResetOnNextRepaint)
  662. return;
  663. InitStyles();
  664. UpdateAssetSelectionChange();
  665. if (m_ResetCommandSent)
  666. return;
  667. if (!activeDataProviderSelected)
  668. {
  669. using (new EditorGUI.DisabledScope(true))
  670. {
  671. GUILayout.Label(SpriteEditorWindowStyles.noSelectionWarning);
  672. }
  673. return;
  674. }
  675. if (m_CurrentModule == null)
  676. {
  677. using (new EditorGUI.DisabledScope(true))
  678. {
  679. GUILayout.Label(SpriteEditorWindowStyles.noModuleWarning);
  680. }
  681. return;
  682. }
  683. textureViewRect = new Rect(0f, 0f, m_MainViewIMGUIElement.layout.width - k_ScrollbarMargin, m_MainViewIMGUIElement.layout.height - k_ScrollbarMargin);
  684. Matrix4x4 oldHandlesMatrix = Handles.matrix;
  685. DoTextureGUI();
  686. // Warning message if applicable
  687. DoEditingDisabledMessage();
  688. m_CurrentModule.DoPostGUI();
  689. Handles.matrix = oldHandlesMatrix;
  690. if (m_RequestRepaint)
  691. {
  692. Repaint();
  693. m_RequestRepaint = false;
  694. }
  695. }
  696. protected override void DoTextureGUIExtras()
  697. {
  698. HandleFrameSelected();
  699. if (m_EventSystem.current.type == EventType.Repaint)
  700. {
  701. SpriteEditorUtility.BeginLines(new Color(1f, 1f, 1f, 0.5f));
  702. var selectedRect = selectedSpriteRect != null ? selectedSpriteRect.spriteID : new GUID();
  703. for (int i = 0; i < m_RectsCache.Count; i++)
  704. {
  705. if (m_RectsCache[i].spriteID != selectedRect)
  706. SpriteEditorUtility.DrawBox(m_RectsCache[i].rect);
  707. }
  708. SpriteEditorUtility.EndLines();
  709. }
  710. m_CurrentModule.DoMainGUI();
  711. }
  712. private void DoToolbarGUI()
  713. {
  714. InitStyles();
  715. GUIStyle toolBarStyle = EditorStyles.toolbar;
  716. Rect toolbarRect = new Rect(0, 0, position.width, k_ToolbarHeight);
  717. if (m_EventSystem.current.type == EventType.Repaint)
  718. {
  719. toolBarStyle.Draw(toolbarRect, false, false, false, false);
  720. }
  721. if (!activeDataProviderSelected || m_CurrentModule == null)
  722. return;
  723. // Top menu bar
  724. var moduleListWidth = 0.0f;
  725. // only show popup if there is more than 1 module.
  726. if (m_RegisteredModules.Count > 1)
  727. {
  728. float moduleWidthPercentage = k_ModuleListWidth / minSize.x;
  729. moduleListWidth = position.width > minSize.x ? position.width * moduleWidthPercentage : k_ModuleListWidth;
  730. moduleListWidth = Mathf.Min(moduleListWidth, EditorStyles.toolbarPopup.CalcSize(m_RegisteredModuleNames[m_CurrentModuleIndex]).x);
  731. toolbarRect.x = moduleListWidth;
  732. }
  733. toolbarRect = DoAlphaZoomToolbarGUI(toolbarRect);
  734. Rect applyRevertDrawArea = toolbarRect;
  735. applyRevertDrawArea.x = applyRevertDrawArea.width;
  736. using (new EditorGUI.DisabledScope(!textureIsDirty))
  737. {
  738. applyRevertDrawArea.width = EditorStyles.toolbarButton.CalcSize(SpriteEditorWindowStyles.applyButtonLabel).x;
  739. applyRevertDrawArea.x -= applyRevertDrawArea.width;
  740. if (GUI.Button(applyRevertDrawArea, SpriteEditorWindowStyles.applyButtonLabel, EditorStyles.toolbarButton))
  741. {
  742. var apply = true;
  743. if (SpriteEditorWindowSettings.showApplyConfirmation)
  744. {
  745. apply = EditorUtility.DisplayDialog(SpriteEditorWindowStyles.applyConfirmationDialogTitle.text, SpriteEditorWindowStyles.applyConfirmationDialogContent.text,
  746. SpriteEditorWindowStyles.yesLabel.text, SpriteEditorWindowStyles.noLabel.text);
  747. }
  748. if (apply)
  749. {
  750. DoApply();
  751. SetupModule(m_CurrentModuleIndex);
  752. }
  753. }
  754. applyRevertDrawArea.width = EditorStyles.toolbarButton.CalcSize(SpriteEditorWindowStyles.revertButtonLabel).x;
  755. applyRevertDrawArea.x -= applyRevertDrawArea.width;
  756. if (GUI.Button(applyRevertDrawArea, SpriteEditorWindowStyles.revertButtonLabel, EditorStyles.toolbarButton))
  757. {
  758. var revert = true;
  759. if (SpriteEditorWindowSettings.showRevertConfirmation)
  760. {
  761. revert = EditorUtility.DisplayDialog(SpriteEditorWindowStyles.revertConfirmationDialogTitle.text, SpriteEditorWindowStyles.revertConfirmationDialogContent.text,
  762. SpriteEditorWindowStyles.yesLabel.text, SpriteEditorWindowStyles.noLabel.text);
  763. }
  764. if (revert)
  765. {
  766. DoRevert();
  767. SetupModule(m_CurrentModuleIndex);
  768. }
  769. }
  770. }
  771. toolbarRect.width = applyRevertDrawArea.x - toolbarRect.x;
  772. m_CurrentModule.DoToolbarGUI(toolbarRect);
  773. if (m_RegisteredModules.Count > 1)
  774. {
  775. int module = EditorGUI.Popup(new Rect(0, 0, moduleListWidth, k_ToolbarHeight), m_CurrentModuleIndex, m_RegisteredModuleNames, EditorStyles.toolbarPopup);
  776. if (module != m_CurrentModuleIndex)
  777. {
  778. if (textureIsDirty)
  779. {
  780. // Have pending module edit changes. Ask user if they want to apply or revert
  781. if (EditorUtility.DisplayDialog(SpriteEditorWindowStyles.applyRevertModuleDialogTitle.text,
  782. SpriteEditorWindowStyles.applyRevertModuleDialogContent.text,
  783. SpriteEditorWindowStyles.applyButtonLabel.text, SpriteEditorWindowStyles.revertButtonLabel.text))
  784. DoApply();
  785. else
  786. DoRevert();
  787. }
  788. m_LastUsedModuleTypeName = m_RegisteredModules[module].GetType().FullName;
  789. SetupModule(module);
  790. }
  791. }
  792. }
  793. private void DoEditingDisabledMessage()
  794. {
  795. if (editingDisabled)
  796. {
  797. GUILayout.BeginArea(warningMessageRect);
  798. var disableMessage = m_AssetNotEditable ? SpriteEditorWindowStyles.editingDisableMessageBecauseNonEditableLabel.text : SpriteEditorWindowStyles.editingDisableMessageBecausePlaymodeLabel.text;
  799. EditorGUILayout.HelpBox(disableMessage, MessageType.Warning);
  800. GUILayout.EndArea();
  801. }
  802. }
  803. private void DoApply()
  804. {
  805. textureIsDirty = false;
  806. bool reimport = true;
  807. var dataProvider = m_SpriteDataProvider;
  808. if (m_CurrentResetContext != null)
  809. {
  810. m_SpriteDataProvider =
  811. m_SpriteDataProviderFactories.GetSpriteEditorDataProviderFromObject(
  812. AssetDatabase.LoadMainAssetAtPath(m_CurrentResetContext.assetPath));
  813. m_SpriteDataProvider.InitSpriteEditorDataProvider();
  814. m_CurrentResetContext = null;
  815. }
  816. if (m_SpriteDataProvider != null)
  817. {
  818. if (m_CurrentModule != null)
  819. reimport = m_CurrentModule.ApplyRevert(true);
  820. m_SpriteDataProvider.Apply();
  821. }
  822. m_SpriteDataProvider = dataProvider;
  823. // Do this so that asset change save dialog will not show
  824. var originalValue = EditorPrefs.GetBool("VerifySavingAssets", false);
  825. EditorPrefs.SetBool("VerifySavingAssets", false);
  826. AssetDatabase.ForceReserializeAssets(new[] {selectedAssetPath}, ForceReserializeAssetsOptions.ReserializeMetadata);
  827. EditorPrefs.SetBool("VerifySavingAssets", originalValue);
  828. if (reimport)
  829. DoTextureReimport(selectedAssetPath);
  830. Repaint();
  831. RefreshRects();
  832. }
  833. private void DoRevert()
  834. {
  835. textureIsDirty = false;
  836. RefreshRects();
  837. GUI.FocusControl("");
  838. if (m_CurrentModule != null)
  839. m_CurrentModule.ApplyRevert(false);
  840. }
  841. public bool HandleSpriteSelection()
  842. {
  843. bool changed = false;
  844. if (m_EventSystem.current.type == EventType.MouseDown && m_EventSystem.current.button == 0 && GUIUtility.hotControl == 0 && !m_EventSystem.current.alt)
  845. {
  846. var oldSelected = selectedSpriteRect;
  847. var triedRect = TrySelect(m_EventSystem.current.mousePosition);
  848. if (triedRect != oldSelected)
  849. {
  850. Undo.RegisterCompleteObjectUndo(this, "Sprite Selection");
  851. selectedSpriteRect = triedRect;
  852. changed = true;
  853. }
  854. if (selectedSpriteRect != null)
  855. s_OneClickDragStarted = true;
  856. else
  857. RequestRepaint();
  858. if (changed && selectedSpriteRect != null)
  859. {
  860. m_EventSystem.current.Use();
  861. }
  862. }
  863. return changed;
  864. }
  865. private void HandleFrameSelected()
  866. {
  867. var evt = m_EventSystem.current;
  868. if ((evt.type == EventType.ValidateCommand || evt.type == EventType.ExecuteCommand)
  869. && evt.commandName == EventCommandNames.FrameSelected)
  870. {
  871. if (evt.type == EventType.ExecuteCommand)
  872. {
  873. // Do not do frame if there is none selected
  874. if (selectedSpriteRect == null)
  875. return;
  876. Rect rect = selectedSpriteRect.rect;
  877. // Calculate the require pixel to display the frame, then get the zoom needed.
  878. float targetZoom = m_Zoom;
  879. if (rect.width < rect.height)
  880. targetZoom = textureViewRect.height / (rect.height + textureViewRect.height * k_MarginForFraming);
  881. else
  882. targetZoom = textureViewRect.width / (rect.width + textureViewRect.width * k_MarginForFraming);
  883. // Apply the zoom
  884. zoomLevel = targetZoom;
  885. // Calculate the scroll values to center the frame
  886. m_ScrollPosition.x = (rect.center.x - (m_Texture.width * 0.5f)) * m_Zoom;
  887. m_ScrollPosition.y = (rect.center.y - (m_Texture.height * 0.5f)) * m_Zoom * -1.0f;
  888. Repaint();
  889. }
  890. evt.Use();
  891. }
  892. }
  893. void UpdateSelectedSpriteRect(UnityEngine.Sprite sprite)
  894. {
  895. if (m_RectsCache == null || sprite == null || sprite.Equals(null))
  896. return;
  897. var spriteGUID = sprite.GetSpriteID();
  898. for (int i = 0; i < m_RectsCache.Count; i++)
  899. {
  900. if (spriteGUID == m_RectsCache[i].spriteID)
  901. {
  902. selectedSpriteRect = m_RectsCache[i];
  903. return;
  904. }
  905. }
  906. selectedSpriteRect = null;
  907. }
  908. private SpriteRect TrySelect(Vector2 mousePosition)
  909. {
  910. float selectedSize = float.MaxValue;
  911. SpriteRect currentRect = null;
  912. mousePosition = Handles.inverseMatrix.MultiplyPoint(mousePosition);
  913. for (int i = 0; i < m_RectsCache.Count; i++)
  914. {
  915. var sr = m_RectsCache[i];
  916. if (sr.rect.Contains(mousePosition))
  917. {
  918. // If we clicked inside an already selected spriterect, always persist that selection
  919. if (sr == selectedSpriteRect)
  920. return sr;
  921. float width = sr.rect.width;
  922. float height = sr.rect.height;
  923. float newSize = width * height;
  924. if (width > 0f && height > 0f && newSize < selectedSize)
  925. {
  926. currentRect = sr;
  927. selectedSize = newSize;
  928. }
  929. }
  930. }
  931. return currentRect;
  932. }
  933. public void DoTextureReimport(string path)
  934. {
  935. if (m_SpriteDataProvider != null)
  936. {
  937. try
  938. {
  939. AssetDatabase.StartAssetEditing();
  940. AssetDatabase.ImportAsset(path);
  941. }
  942. finally
  943. {
  944. AssetDatabase.StopAssetEditing();
  945. }
  946. }
  947. }
  948. GUIContent[] m_RegisteredModuleNames;
  949. List<SpriteEditorModuleBase> m_AllRegisteredModules;
  950. List<SpriteEditorModuleBase> m_RegisteredModules;
  951. SpriteEditorModuleBase m_CurrentModule = null;
  952. int m_CurrentModuleIndex = 0;
  953. [SerializeField]
  954. string m_LastUsedModuleTypeName;
  955. internal void SetupModule(int newModuleIndex)
  956. {
  957. m_ModuleViewElement.Clear();
  958. if (m_RegisteredModules.Count > newModuleIndex)
  959. {
  960. m_CurrentModuleIndex = newModuleIndex;
  961. if (m_CurrentModule != null)
  962. m_CurrentModule.OnModuleDeactivate();
  963. m_CurrentModule = null;
  964. m_CurrentModule = m_RegisteredModules[newModuleIndex];
  965. m_CurrentModule.OnModuleActivate();
  966. }
  967. if (m_MainViewElement != null)
  968. m_MainViewElement.MarkDirtyRepaint();
  969. if (m_ModuleViewElement != null)
  970. m_ModuleViewElement.MarkDirtyRepaint();
  971. }
  972. void UpdateAvailableModules()
  973. {
  974. if (m_AllRegisteredModules == null)
  975. return;
  976. m_RegisteredModules = new List<SpriteEditorModuleBase>();
  977. foreach (var module in m_AllRegisteredModules)
  978. {
  979. if (module.CanBeActivated())
  980. {
  981. RequireSpriteDataProviderAttribute attribute = null;
  982. m_ModuleRequireSpriteDataProvider.TryGetValue(module.GetType(), out attribute);
  983. if (attribute == null || attribute.ContainsAllType(m_SpriteDataProvider))
  984. m_RegisteredModules.Add(module);
  985. }
  986. }
  987. m_RegisteredModuleNames = new GUIContent[m_RegisteredModules.Count];
  988. int lastUsedModuleIndex = 0;
  989. for (int i = 0; i < m_RegisteredModules.Count; i++)
  990. {
  991. m_RegisteredModuleNames[i] = new GUIContent(m_RegisteredModules[i].moduleName);
  992. if (m_RegisteredModules[i].GetType().FullName.Equals(m_LastUsedModuleTypeName))
  993. {
  994. lastUsedModuleIndex = i;
  995. }
  996. }
  997. SetupModule(lastUsedModuleIndex);
  998. }
  999. void InitModules()
  1000. {
  1001. m_AllRegisteredModules = new List<SpriteEditorModuleBase>();
  1002. m_ModuleRequireSpriteDataProvider.Clear();
  1003. if (m_OutlineTexture == null)
  1004. {
  1005. m_OutlineTexture = new UnityTexture2D(1, 16, TextureFormat.RGBA32, false);
  1006. m_OutlineTexture.SetPixels(new Color[]
  1007. {
  1008. new Color(0.5f, 0.5f, 0.5f, 0.5f), new Color(0.5f, 0.5f, 0.5f, 0.5f), new Color(0.8f, 0.8f, 0.8f, 0.8f), new Color(0.8f, 0.8f, 0.8f, 0.8f),
  1009. Color.white, Color.white, Color.white, Color.white,
  1010. new Color(.8f, .8f, .8f, 1f), new Color(.5f, .5f, .5f, .8f), new Color(0.3f, 0.3f, 0.3f, 0.5f), new Color(0.3f, .3f, 0.3f, 0.5f),
  1011. new Color(0.3f, .3f, 0.3f, 0.3f), new Color(0.3f, .3f, 0.3f, 0.3f), new Color(0.1f, 0.1f, 0.1f, 0.1f), new Color(0.1f, .1f, 0.1f, 0.1f)
  1012. });
  1013. m_OutlineTexture.Apply();
  1014. m_OutlineTexture.hideFlags = HideFlags.HideAndDontSave;
  1015. }
  1016. var outlineTexture = new Texture2DWrapper(m_OutlineTexture);
  1017. // Add your modules here
  1018. RegisterModule(new SpriteFrameModule(this, m_EventSystem, m_UndoSystem, m_AssetDatabase));
  1019. RegisterModule(new SpritePolygonModeModule(this, m_EventSystem, m_UndoSystem, m_AssetDatabase));
  1020. RegisterModule(new SpriteOutlineModule(this, m_EventSystem, m_UndoSystem, m_AssetDatabase, m_GUIUtility, new ShapeEditorFactory(), outlineTexture));
  1021. RegisterModule(new SpritePhysicsShapeModule(this, m_EventSystem, m_UndoSystem, m_AssetDatabase, m_GUIUtility, new ShapeEditorFactory(), outlineTexture));
  1022. RegisterCustomModules();
  1023. UpdateAvailableModules();
  1024. }
  1025. void RegisterModule(SpriteEditorModuleBase module)
  1026. {
  1027. var type = module.GetType();
  1028. var attributes = type.GetCustomAttributes(typeof(RequireSpriteDataProviderAttribute), false);
  1029. if (attributes.Length == 1)
  1030. m_ModuleRequireSpriteDataProvider.Add(type, (RequireSpriteDataProviderAttribute)attributes[0]);
  1031. m_AllRegisteredModules.Add(module);
  1032. }
  1033. void RegisterCustomModules()
  1034. {
  1035. foreach (var moduleClassType in TypeCache.GetTypesDerivedFrom<SpriteEditorModuleBase>())
  1036. {
  1037. if (!moduleClassType.IsAbstract)
  1038. {
  1039. bool moduleFound = false;
  1040. foreach (var module in m_AllRegisteredModules)
  1041. {
  1042. if (module.GetType() == moduleClassType)
  1043. {
  1044. moduleFound = true;
  1045. break;
  1046. }
  1047. }
  1048. if (!moduleFound)
  1049. {
  1050. var constructorType = new Type[0];
  1051. // Get the public instance constructor that takes ISpriteEditorModule parameter.
  1052. var constructorInfoObj = moduleClassType.GetConstructor(
  1053. BindingFlags.Instance | BindingFlags.Public, null,
  1054. CallingConventions.HasThis, constructorType, null);
  1055. if (constructorInfoObj != null)
  1056. {
  1057. try
  1058. {
  1059. var newInstance = constructorInfoObj.Invoke(new object[0]) as SpriteEditorModuleBase;
  1060. if (newInstance != null)
  1061. {
  1062. newInstance.spriteEditor = this;
  1063. RegisterModule(newInstance);
  1064. }
  1065. }
  1066. catch (Exception ex)
  1067. {
  1068. Debug.LogWarning("Unable to instantiate custom module " + moduleClassType.FullName + ". Exception:" + ex);
  1069. }
  1070. }
  1071. else
  1072. Debug.LogWarning(moduleClassType.FullName + " does not have a parameterless constructor");
  1073. }
  1074. }
  1075. }
  1076. }
  1077. internal List<SpriteEditorModuleBase> activatedModules
  1078. {
  1079. get { return m_RegisteredModules; }
  1080. }
  1081. public List<SpriteRect> spriteRects
  1082. {
  1083. set
  1084. {
  1085. m_RectsCache = value;
  1086. m_CachedSelectedSpriteRect = null;
  1087. }
  1088. }
  1089. private SpriteRect m_CachedSelectedSpriteRect;
  1090. public SpriteRect selectedSpriteRect
  1091. {
  1092. get
  1093. {
  1094. // Always return null if editing is disabled to prevent all possible action to selected frame.
  1095. if (editingDisabled || m_RectsCache == null || string.IsNullOrEmpty(m_SelectedSpriteRectGUID))
  1096. return null;
  1097. var guid = new GUID(m_SelectedSpriteRectGUID);
  1098. if (m_CachedSelectedSpriteRect == null || m_CachedSelectedSpriteRect.spriteID != guid)
  1099. {
  1100. m_CachedSelectedSpriteRect = m_RectsCache.FirstOrDefault(x => x.spriteID == guid);
  1101. }
  1102. return m_CachedSelectedSpriteRect;
  1103. }
  1104. set
  1105. {
  1106. if (editingDisabled)
  1107. return;
  1108. var oldSelected = m_SelectedSpriteRectGUID;
  1109. m_SelectedSpriteRectGUID = value != null ? value.spriteID.ToString() : new GUID().ToString();
  1110. if (oldSelected != m_SelectedSpriteRectGUID)
  1111. {
  1112. if (m_MainViewIMGUIElement != null)
  1113. m_MainViewIMGUIElement.MarkDirtyRepaint();
  1114. if (m_MainViewElement != null)
  1115. {
  1116. m_MainViewElement.MarkDirtyRepaint();
  1117. using (var e = SpriteSelectionChangeEvent.GetPooled())
  1118. {
  1119. e.target = m_ModuleViewElement;
  1120. m_MainViewElement.SendEvent(e);
  1121. }
  1122. }
  1123. }
  1124. }
  1125. }
  1126. public ISpriteEditorDataProvider spriteEditorDataProvider
  1127. {
  1128. get { return m_SpriteDataProvider; }
  1129. }
  1130. public bool enableMouseMoveEvent
  1131. {
  1132. set { wantsMouseMove = value; }
  1133. }
  1134. public void RequestRepaint()
  1135. {
  1136. if (focusedWindow != this)
  1137. Repaint();
  1138. else
  1139. m_RequestRepaint = true;
  1140. }
  1141. public void SetDataModified()
  1142. {
  1143. textureIsDirty = true;
  1144. }
  1145. public Rect windowDimension
  1146. {
  1147. get { return textureViewRect; }
  1148. }
  1149. public ITexture2D previewTexture
  1150. {
  1151. get { return m_Texture; }
  1152. }
  1153. public bool editingDisabled => EditorApplication.isPlayingOrWillChangePlaymode || m_AssetNotEditable;
  1154. public void SetPreviewTexture(UnityTexture2D texture, int width, int height)
  1155. {
  1156. m_Texture = new PreviewTexture2D(texture, width, height);
  1157. }
  1158. public void ApplyOrRevertModification(bool apply)
  1159. {
  1160. if (apply)
  1161. DoApply();
  1162. else
  1163. DoRevert();
  1164. }
  1165. internal class PreviewTexture2D : Texture2DWrapper
  1166. {
  1167. private int m_ActualWidth = 0;
  1168. private int m_ActualHeight = 0;
  1169. public PreviewTexture2D(UnityTexture2D t, int width, int height)
  1170. : base(t)
  1171. {
  1172. m_ActualWidth = width;
  1173. m_ActualHeight = height;
  1174. }
  1175. public override int width
  1176. {
  1177. get { return m_ActualWidth; }
  1178. }
  1179. public override int height
  1180. {
  1181. get { return m_ActualHeight; }
  1182. }
  1183. }
  1184. public T GetDataProvider<T>() where T : class
  1185. {
  1186. return m_SpriteDataProvider != null ? m_SpriteDataProvider.GetDataProvider<T>() : null;
  1187. }
  1188. public VisualElement GetMainVisualContainer()
  1189. {
  1190. return m_ModuleViewElement;
  1191. }
  1192. static internal void OnTextureReimport(SpriteEditorWindow win, string path)
  1193. {
  1194. if (win.selectedAssetPath == path)
  1195. {
  1196. win.ResetOnNextRepaint();
  1197. }
  1198. }
  1199. [MenuItem("Window/2D/Sprite Editor", false, 0)]
  1200. static private void OpenSpriteEditorWindow()
  1201. {
  1202. SpriteEditorWindow.GetWindow(Selection.activeObject);
  1203. }
  1204. }
  1205. internal class SpriteEditorTexturePostprocessor : AssetPostprocessor
  1206. {
  1207. public override int GetPostprocessOrder()
  1208. {
  1209. return 1;
  1210. }
  1211. static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
  1212. {
  1213. UnityEngine.Object[] wins = Resources.FindObjectsOfTypeAll(typeof(SpriteEditorWindow));
  1214. SpriteEditorWindow win = wins.Length > 0 ? (EditorWindow)(wins[0]) as SpriteEditorWindow : null;
  1215. if (win != null)
  1216. {
  1217. foreach (var deletedAsset in deletedAssets)
  1218. SpriteEditorWindow.OnTextureReimport(win, deletedAsset);
  1219. foreach (var importedAsset in importedAssets)
  1220. SpriteEditorWindow.OnTextureReimport(win, importedAsset);
  1221. }
  1222. }
  1223. }
  1224. internal class SpriteSelectionChangeEvent : EventBase<SpriteSelectionChangeEvent>
  1225. {
  1226. }
  1227. }