295 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			295 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Linq;
 | |
| using UnityEditor.U2D.Sprites;
 | |
| using UnityEditorInternal;
 | |
| using UnityEngine;
 | |
| using UnityEngine.UIElements;
 | |
| using Object = UnityEngine.Object;
 | |
| 
 | |
| namespace UnityEditor._2D.Sprite.Editor
 | |
| {
 | |
|     [RequireSpriteDataProvider(typeof(ISecondaryTextureDataProvider), typeof(ITextureDataProvider))]
 | |
|     internal class SpriteSecondaryTexturesModule : SpriteEditorModuleBase
 | |
|     {
 | |
|         private static class Styles
 | |
|         {
 | |
|             public static readonly string invalidEntriesWarning = L10n.Tr("Invalid secondary Texture entries (without names or Textures) have been removed.");
 | |
|             public static readonly string invalidSourcesWarning = L10n.Tr("Source texture used as secondary Texture. This is invalid and removed.");
 | |
|             public static readonly string nameUniquenessWarning = L10n.Tr("Every secondary Texture attached to the Sprite must have a unique name.");
 | |
|             public static readonly string builtInNameCollisionWarning = L10n.Tr("The names _MainTex and _AlphaTex are reserved for internal use.");
 | |
|             public static readonly GUIContent panelTitle = EditorGUIUtility.TrTextContent("Secondary Textures");
 | |
|             public static readonly GUIContent name = EditorGUIUtility.TrTextContent("Name");
 | |
|             public static readonly GUIContent texture = EditorGUIUtility.TrTextContent("Texture");
 | |
|             public const float textFieldDropDownWidth = 18.0f;
 | |
|         }
 | |
| 
 | |
| 
 | |
|         ReorderableList m_ReorderableList;
 | |
|         Vector2 m_ReorderableListScrollPosition;
 | |
|         string[] m_SuggestedNames;
 | |
|         private IMGUIContainer m_SecondaryTextureInspectorContainer;
 | |
|         internal List<SecondarySpriteTexture> secondaryTextureList { get; private set; }
 | |
|         Dictionary<int, Texture2D> m_PreviewTexture;
 | |
| 
 | |
|         public override string moduleName
 | |
|         {
 | |
|             get { return Styles.panelTitle.text; }
 | |
|         }
 | |
| 
 | |
|         public override bool ApplyRevert(bool apply)
 | |
|         {
 | |
|             if (apply)
 | |
|             {
 | |
|                 var spriteAssetPath = "";
 | |
|                 var secondaryTextureDataProvider = spriteEditor.GetDataProvider<ISecondaryTextureDataProvider>();
 | |
|                 var spriteDataProvider = spriteEditor.GetDataProvider<ISpriteEditorDataProvider>();
 | |
|                 if (spriteDataProvider != null)
 | |
|                 {
 | |
|                     var assetImporter = spriteDataProvider.targetObject as AssetImporter;
 | |
|                     spriteAssetPath = assetImporter != null ? assetImporter.assetPath : spriteAssetPath;
 | |
|                 }
 | |
| 
 | |
|                 // Remove invalid entries.
 | |
|                 var validEntries = secondaryTextureList.FindAll(x => (x.name != null && x.name != "" && x.texture != null));
 | |
|                 if (validEntries.Count < secondaryTextureList.Count)
 | |
|                     Debug.Log(Styles.invalidEntriesWarning);
 | |
| 
 | |
|                 // Remove entries with Sprite's source as secondary textures.
 | |
|                 var finalEntries = validEntries.FindAll(x => (AssetDatabase.GetAssetPath(x.texture) != spriteAssetPath));
 | |
|                 if (finalEntries.Count < validEntries.Count)
 | |
|                     Debug.Log(Styles.invalidSourcesWarning);
 | |
| 
 | |
|                 secondaryTextureDataProvider.textures = finalEntries.ToArray();
 | |
|             }
 | |
| 
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         public override bool CanBeActivated()
 | |
|         {
 | |
|             var dataProvider = spriteEditor.GetDataProvider<ISpriteEditorDataProvider>();
 | |
|             return dataProvider != null && dataProvider.spriteImportMode != SpriteImportMode.None;
 | |
|         }
 | |
| 
 | |
|         public override void DoPostGUI()
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         public void SecondaryTextureReorderableListUI()
 | |
|         {
 | |
|             using (new EditorGUI.DisabledScope(spriteEditor.editingDisabled))
 | |
|             {
 | |
|                 var windowDimension = spriteEditor.windowDimension;
 | |
| 
 | |
|                 GUILayout.BeginArea(new Rect(0, 0, 290, 290), Styles.panelTitle, GUI.skin.window);
 | |
|                 m_ReorderableListScrollPosition = GUILayout.BeginScrollView(m_ReorderableListScrollPosition);
 | |
|                 m_ReorderableList.DoLayoutList();
 | |
|                 GUILayout.EndScrollView();
 | |
|                 GUILayout.EndArea();
 | |
| 
 | |
|                 // Deselect the list item if left click outside the panel area.
 | |
|                 UnityEngine.Event e = UnityEngine.Event.current;
 | |
|                 if (e.type == EventType.MouseDown && e.button == 0)
 | |
|                 {
 | |
|                     m_ReorderableList.index = -1;
 | |
|                     OnSelectCallback(m_ReorderableList);
 | |
|                     spriteEditor.RequestRepaint();
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public override void DoMainGUI()
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         public override void DoToolbarGUI(Rect drawArea)
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         public override void OnModuleActivate()
 | |
|         {
 | |
|             m_PreviewTexture = new Dictionary<int, Texture2D>();
 | |
|             var secondaryTextureDataProvider = spriteEditor.GetDataProvider<ISecondaryTextureDataProvider>();
 | |
|             secondaryTextureList = secondaryTextureDataProvider.textures == null ? new List<SecondarySpriteTexture>() : secondaryTextureDataProvider.textures.ToList();
 | |
| 
 | |
|             m_ReorderableListScrollPosition = Vector2.zero;
 | |
|             m_ReorderableList = new ReorderableList(secondaryTextureList, typeof(SecondarySpriteTexture), false, false, true, true);
 | |
|             m_ReorderableList.drawElementCallback = DrawSpriteSecondaryTextureElement;
 | |
|             m_ReorderableList.onAddCallback = AddSpriteSecondaryTextureElement;
 | |
|             m_ReorderableList.onRemoveCallback = RemoveSpriteSecondaryTextureElement;
 | |
|             m_ReorderableList.onCanAddCallback = CanAddSpriteSecondaryTextureElement;
 | |
|             m_ReorderableList.elementHeightCallback = (int index) => (EditorGUIUtility.singleLineHeight * 3) + 5;
 | |
|             m_ReorderableList.onSelectCallback = OnSelectCallback;
 | |
| 
 | |
|             spriteEditor.selectedSpriteRect = null;
 | |
| 
 | |
|             string suggestedNamesPrefs = EditorPrefs.GetString("SecondarySpriteTexturePropertyNames");
 | |
|             if (!string.IsNullOrEmpty(suggestedNamesPrefs))
 | |
|             {
 | |
|                 m_SuggestedNames = suggestedNamesPrefs.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
 | |
| 
 | |
|                 for (int i = 0; i < m_SuggestedNames.Length; ++i)
 | |
|                     m_SuggestedNames[i] = m_SuggestedNames[i].Trim();
 | |
| 
 | |
|                 Array.Sort(m_SuggestedNames);
 | |
|             }
 | |
|             else
 | |
|                 m_SuggestedNames = null;
 | |
| 
 | |
|             m_SecondaryTextureInspectorContainer = new IMGUIContainer(SecondaryTextureReorderableListUI)
 | |
|             {
 | |
|                 style =
 | |
|                 {
 | |
|                     flexGrow = 0,
 | |
|                     flexBasis = 1,
 | |
|                     flexShrink = 0,
 | |
|                     minWidth = 290,
 | |
|                     minHeight = 290,
 | |
|                     bottom = 24,
 | |
|                     right = 24,
 | |
|                     position = new StyleEnum<Position>(Position.Absolute)
 | |
|                 },
 | |
|                 name = "SecondaryTextureInspector"
 | |
|             };
 | |
|             spriteEditor.GetMainVisualContainer().Add(m_SecondaryTextureInspectorContainer);
 | |
|         }
 | |
| 
 | |
|         void OnSelectCallback(ReorderableList list)
 | |
|         {
 | |
|             // Preview the current selected secondary texture.
 | |
|             Texture2D previewTexture = null;
 | |
|             int width = 0, height = 0;
 | |
| 
 | |
|             var textureDataProvider = spriteEditor.GetDataProvider<ITextureDataProvider>();
 | |
|             if (textureDataProvider != null)
 | |
|             {
 | |
|                 previewTexture = textureDataProvider.previewTexture;
 | |
|                 textureDataProvider.GetTextureActualWidthAndHeight(out width, out height);
 | |
|             }
 | |
| 
 | |
|             if (m_ReorderableList.index >= 0 && m_ReorderableList.index < secondaryTextureList.Count)
 | |
|             {
 | |
|                 var generatedPreview = GetPreviewTexture(secondaryTextureList[m_ReorderableList.index].texture, width, height);
 | |
|                 previewTexture = generatedPreview ?? secondaryTextureList[m_ReorderableList.index].texture;
 | |
|             }
 | |
| 
 | |
|             if (previewTexture != null)
 | |
|                 spriteEditor.SetPreviewTexture(previewTexture, width, height);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         Texture2D GetPreviewTexture(Object texture, int width, int height)
 | |
|         {
 | |
|             Texture2D previewTexture = null;
 | |
|             if (texture != null)
 | |
|             {
 | |
|                 int instanceID = texture.GetInstanceID();
 | |
|                 if (!m_PreviewTexture.TryGetValue(instanceID, out previewTexture))
 | |
|                 {
 | |
|                     var assetPath = AssetDatabase.GetAssetPath(texture);
 | |
|                     if (assetPath != null && assetPath.Length > 0)
 | |
|                     {
 | |
|                         previewTexture = AssetPreviewUpdater.CreatePreview(texture, null, assetPath, width, height);
 | |
|                         m_PreviewTexture[instanceID] = previewTexture;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return previewTexture;
 | |
|         }
 | |
| 
 | |
|         public override void OnModuleDeactivate()
 | |
|         {
 | |
|             DisplayMainTexture();
 | |
|             if (spriteEditor.GetMainVisualContainer().Contains(m_SecondaryTextureInspectorContainer))
 | |
|                 spriteEditor.GetMainVisualContainer().Remove(m_SecondaryTextureInspectorContainer);
 | |
|             m_PreviewTexture.Clear();
 | |
|             m_PreviewTexture = null;
 | |
|         }
 | |
| 
 | |
|         void DrawSpriteSecondaryTextureElement(Rect rect, int index, bool isActive, bool isFocused)
 | |
|         {
 | |
|             bool dataModified = false;
 | |
|             float oldLabelWidth = EditorGUIUtility.labelWidth;
 | |
|             EditorGUIUtility.labelWidth = 70.0f;
 | |
|             SecondarySpriteTexture secondaryTexture = secondaryTextureList[index];
 | |
| 
 | |
|             // "Name" text field
 | |
|             EditorGUI.BeginChangeCheck();
 | |
|             var r = new Rect(rect.x, rect.y + 5, rect.width - Styles.textFieldDropDownWidth, EditorGUIUtility.singleLineHeight);
 | |
|             string newName = EditorGUI.TextField(r, Styles.name, secondaryTexture.name);
 | |
|             dataModified = EditorGUI.EndChangeCheck();
 | |
| 
 | |
|             // Suggested names
 | |
|             if (m_SuggestedNames != null)
 | |
|             {
 | |
|                 var popupRect = new Rect(r.x + r.width, r.y, Styles.textFieldDropDownWidth, EditorGUIUtility.singleLineHeight);
 | |
|                 EditorGUI.BeginChangeCheck();
 | |
|                 int selected = EditorGUI.Popup(popupRect, -1, m_SuggestedNames, EditorStyles.textFieldDropDown);
 | |
|                 if (EditorGUI.EndChangeCheck())
 | |
|                 {
 | |
|                     newName = m_SuggestedNames[selected];
 | |
|                     dataModified = true;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (dataModified)
 | |
|             {
 | |
|                 if (!string.IsNullOrEmpty(newName) && newName != secondaryTexture.name && secondaryTextureList.Exists(x => x.name == newName))
 | |
|                     Debug.LogWarning(Styles.nameUniquenessWarning);
 | |
|                 else if (newName == "_MainTex" || newName == "_AlphaTex")
 | |
|                     Debug.LogWarning(Styles.builtInNameCollisionWarning);
 | |
|                 else
 | |
|                     secondaryTexture.name = newName;
 | |
|             }
 | |
| 
 | |
|             // "Texture" object field
 | |
|             EditorGUI.BeginChangeCheck();
 | |
|             r.width = rect.width;
 | |
|             r.y += EditorGUIUtility.singleLineHeight + 2.0f;
 | |
|             secondaryTexture.texture = EditorGUI.ObjectField(r, Styles.texture, secondaryTexture.texture, typeof(Texture2D), false) as Texture2D;
 | |
|             dataModified = dataModified || EditorGUI.EndChangeCheck();
 | |
| 
 | |
|             if (dataModified)
 | |
|             {
 | |
|                 secondaryTextureList[index] = secondaryTexture;
 | |
|                 spriteEditor.SetDataModified();
 | |
|             }
 | |
| 
 | |
|             EditorGUIUtility.labelWidth = oldLabelWidth;
 | |
|         }
 | |
| 
 | |
|         void AddSpriteSecondaryTextureElement(ReorderableList list)
 | |
|         {
 | |
|             m_ReorderableListScrollPosition += new Vector2(0.0f, list.elementHeightCallback(0));
 | |
|             secondaryTextureList.Add(new SecondarySpriteTexture());
 | |
|             spriteEditor.SetDataModified();
 | |
|         }
 | |
| 
 | |
|         void RemoveSpriteSecondaryTextureElement(ReorderableList list)
 | |
|         {
 | |
|             DisplayMainTexture();
 | |
|             secondaryTextureList.RemoveAt(list.index);
 | |
|             spriteEditor.SetDataModified();
 | |
|         }
 | |
| 
 | |
|         bool CanAddSpriteSecondaryTextureElement(ReorderableList list)
 | |
|         {
 | |
|             return list.count < 8;
 | |
|         }
 | |
| 
 | |
|         void DisplayMainTexture()
 | |
|         {
 | |
|             ITextureDataProvider textureDataProvider = spriteEditor.GetDataProvider<ITextureDataProvider>();
 | |
|             if (textureDataProvider != null && textureDataProvider.previewTexture != null)
 | |
|             {
 | |
|                 Texture2D mainTexture = textureDataProvider.previewTexture;
 | |
|                 int width = 0, height = 0;
 | |
|                 textureDataProvider.GetTextureActualWidthAndHeight(out width, out height);
 | |
|                 spriteEditor.SetPreviewTexture(mainTexture, width, height);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |