A game about forced loneliness, made by TACStudios
1using System.Linq;
2using UnityEngine;
3using UnityEditor.AnimatedValues;
4using UnityEngine.UI;
5
6namespace UnityEditor.UI
7{
8 /// <summary>
9 /// Editor class used to edit UI Sprites.
10 /// </summary>
11
12 [CustomEditor(typeof(Image), true)]
13 [CanEditMultipleObjects]
14 /// <summary>
15 /// Custom Editor for the Image Component.
16 /// Extend this class to write a custom editor for a component derived from Image.
17 /// </summary>
18 public class ImageEditor : GraphicEditor
19 {
20 SerializedProperty m_FillMethod;
21 SerializedProperty m_FillOrigin;
22 SerializedProperty m_FillAmount;
23 SerializedProperty m_FillClockwise;
24 SerializedProperty m_Type;
25 SerializedProperty m_FillCenter;
26 SerializedProperty m_Sprite;
27 SerializedProperty m_PreserveAspect;
28 SerializedProperty m_UseSpriteMesh;
29 SerializedProperty m_PixelsPerUnitMultiplier;
30 GUIContent m_SpriteContent;
31 GUIContent m_SpriteTypeContent;
32 GUIContent m_ClockwiseContent;
33 AnimBool m_ShowSlicedOrTiled;
34 AnimBool m_ShowSliced;
35 AnimBool m_ShowTiled;
36 AnimBool m_ShowFilled;
37 AnimBool m_ShowType;
38 bool m_bIsDriven;
39
40 private class Styles
41 {
42 public static GUIContent text = EditorGUIUtility.TrTextContent("Fill Origin");
43 public static GUIContent[] OriginHorizontalStyle =
44 {
45 EditorGUIUtility.TrTextContent("Left"),
46 EditorGUIUtility.TrTextContent("Right")
47 };
48
49 public static GUIContent[] OriginVerticalStyle =
50 {
51 EditorGUIUtility.TrTextContent("Bottom"),
52 EditorGUIUtility.TrTextContent("Top")
53 };
54
55 public static GUIContent[] Origin90Style =
56 {
57 EditorGUIUtility.TrTextContent("BottomLeft"),
58 EditorGUIUtility.TrTextContent("TopLeft"),
59 EditorGUIUtility.TrTextContent("TopRight"),
60 EditorGUIUtility.TrTextContent("BottomRight")
61 };
62
63 public static GUIContent[] Origin180Style =
64 {
65 EditorGUIUtility.TrTextContent("Bottom"),
66 EditorGUIUtility.TrTextContent("Left"),
67 EditorGUIUtility.TrTextContent("Top"),
68 EditorGUIUtility.TrTextContent("Right")
69 };
70
71 public static GUIContent[] Origin360Style =
72 {
73 EditorGUIUtility.TrTextContent("Bottom"),
74 EditorGUIUtility.TrTextContent("Right"),
75 EditorGUIUtility.TrTextContent("Top"),
76 EditorGUIUtility.TrTextContent("Left")
77 };
78 }
79
80 protected override void OnEnable()
81 {
82 base.OnEnable();
83
84 m_SpriteContent = EditorGUIUtility.TrTextContent("Source Image");
85 m_SpriteTypeContent = EditorGUIUtility.TrTextContent("Image Type");
86 m_ClockwiseContent = EditorGUIUtility.TrTextContent("Clockwise");
87
88 m_Sprite = serializedObject.FindProperty("m_Sprite");
89 m_Type = serializedObject.FindProperty("m_Type");
90 m_FillCenter = serializedObject.FindProperty("m_FillCenter");
91 m_FillMethod = serializedObject.FindProperty("m_FillMethod");
92 m_FillOrigin = serializedObject.FindProperty("m_FillOrigin");
93 m_FillClockwise = serializedObject.FindProperty("m_FillClockwise");
94 m_FillAmount = serializedObject.FindProperty("m_FillAmount");
95 m_PreserveAspect = serializedObject.FindProperty("m_PreserveAspect");
96 m_UseSpriteMesh = serializedObject.FindProperty("m_UseSpriteMesh");
97 m_PixelsPerUnitMultiplier = serializedObject.FindProperty("m_PixelsPerUnitMultiplier");
98
99 m_ShowType = new AnimBool(m_Sprite.objectReferenceValue != null);
100 m_ShowType.valueChanged.AddListener(Repaint);
101
102 var typeEnum = (Image.Type)m_Type.enumValueIndex;
103
104 m_ShowSlicedOrTiled = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == Image.Type.Sliced);
105 m_ShowSliced = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == Image.Type.Sliced);
106 m_ShowTiled = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == Image.Type.Tiled);
107 m_ShowFilled = new AnimBool(!m_Type.hasMultipleDifferentValues && typeEnum == Image.Type.Filled);
108 m_ShowSlicedOrTiled.valueChanged.AddListener(Repaint);
109 m_ShowSliced.valueChanged.AddListener(Repaint);
110 m_ShowTiled.valueChanged.AddListener(Repaint);
111 m_ShowFilled.valueChanged.AddListener(Repaint);
112
113 SetShowNativeSize(true);
114
115 m_bIsDriven = false;
116 }
117
118 protected override void OnDisable()
119 {
120 base.OnDisable();
121
122 m_ShowType.valueChanged.RemoveListener(Repaint);
123 m_ShowSlicedOrTiled.valueChanged.RemoveListener(Repaint);
124 m_ShowSliced.valueChanged.RemoveListener(Repaint);
125 m_ShowTiled.valueChanged.RemoveListener(Repaint);
126 m_ShowFilled.valueChanged.RemoveListener(Repaint);
127 }
128
129 public override void OnInspectorGUI()
130 {
131 serializedObject.Update();
132
133 Image image = target as Image;
134 RectTransform rect = image.GetComponent<RectTransform>();
135 m_bIsDriven = (rect.drivenByObject as Slider)?.fillRect == rect;
136
137 SpriteGUI();
138 AppearanceControlsGUI();
139 RaycastControlsGUI();
140 MaskableControlsGUI();
141
142 m_ShowType.target = m_Sprite.objectReferenceValue != null;
143 if (EditorGUILayout.BeginFadeGroup(m_ShowType.faded))
144 TypeGUI();
145 EditorGUILayout.EndFadeGroup();
146
147 SetShowNativeSize(false);
148 if (EditorGUILayout.BeginFadeGroup(m_ShowNativeSize.faded))
149 {
150 EditorGUI.indentLevel++;
151
152 if ((Image.Type)m_Type.enumValueIndex == Image.Type.Simple)
153 EditorGUILayout.PropertyField(m_UseSpriteMesh);
154
155 EditorGUILayout.PropertyField(m_PreserveAspect);
156 EditorGUI.indentLevel--;
157 }
158 EditorGUILayout.EndFadeGroup();
159 NativeSizeButtonGUI();
160
161 serializedObject.ApplyModifiedProperties();
162 }
163
164 void SetShowNativeSize(bool instant)
165 {
166 Image.Type type = (Image.Type)m_Type.enumValueIndex;
167 bool showNativeSize = (type == Image.Type.Simple || type == Image.Type.Filled) && m_Sprite.objectReferenceValue != null;
168 base.SetShowNativeSize(showNativeSize, instant);
169 }
170
171 /// <summary>
172 /// Draw the atlas and Image selection fields.
173 /// </summary>
174
175 protected void SpriteGUI()
176 {
177 EditorGUI.BeginChangeCheck();
178 EditorGUILayout.PropertyField(m_Sprite, m_SpriteContent);
179 if (EditorGUI.EndChangeCheck())
180 {
181 var newSprite = m_Sprite.objectReferenceValue as Sprite;
182 if (newSprite)
183 {
184 Image.Type oldType = (Image.Type)m_Type.enumValueIndex;
185 if (newSprite.border.SqrMagnitude() > 0)
186 {
187 m_Type.enumValueIndex = (int)Image.Type.Sliced;
188 }
189 else if (oldType == Image.Type.Sliced)
190 {
191 m_Type.enumValueIndex = (int)Image.Type.Simple;
192 }
193 }
194 (serializedObject.targetObject as Image).DisableSpriteOptimizations();
195 }
196 }
197
198 /// <summary>
199 /// Sprites's custom properties based on the type.
200 /// </summary>
201
202 protected void TypeGUI()
203 {
204 EditorGUILayout.PropertyField(m_Type, m_SpriteTypeContent);
205
206 ++EditorGUI.indentLevel;
207 {
208 Image.Type typeEnum = (Image.Type)m_Type.enumValueIndex;
209
210 bool showSlicedOrTiled = (!m_Type.hasMultipleDifferentValues && (typeEnum == Image.Type.Sliced || typeEnum == Image.Type.Tiled));
211 if (showSlicedOrTiled && targets.Length > 1)
212 showSlicedOrTiled = targets.Select(obj => obj as Image).All(img => img.hasBorder);
213
214 m_ShowSlicedOrTiled.target = showSlicedOrTiled;
215 m_ShowSliced.target = (showSlicedOrTiled && !m_Type.hasMultipleDifferentValues && typeEnum == Image.Type.Sliced);
216 m_ShowTiled.target = (showSlicedOrTiled && !m_Type.hasMultipleDifferentValues && typeEnum == Image.Type.Tiled);
217 m_ShowFilled.target = (!m_Type.hasMultipleDifferentValues && typeEnum == Image.Type.Filled);
218
219 Image image = target as Image;
220 if (EditorGUILayout.BeginFadeGroup(m_ShowSlicedOrTiled.faded))
221 {
222 if (image.hasBorder)
223 EditorGUILayout.PropertyField(m_FillCenter);
224 EditorGUILayout.PropertyField(m_PixelsPerUnitMultiplier);
225 }
226 EditorGUILayout.EndFadeGroup();
227
228 if (EditorGUILayout.BeginFadeGroup(m_ShowSliced.faded))
229 {
230 if (image.sprite != null && !image.hasBorder)
231 EditorGUILayout.HelpBox("This Image doesn't have a border.", MessageType.Warning);
232 }
233 EditorGUILayout.EndFadeGroup();
234
235 if (EditorGUILayout.BeginFadeGroup(m_ShowTiled.faded))
236 {
237 if (image.sprite != null && !image.hasBorder && (image.sprite.texture != null && image.sprite.texture.wrapMode != TextureWrapMode.Repeat || image.sprite.packed))
238 EditorGUILayout.HelpBox("It looks like you want to tile a sprite with no border. It would be more efficient to modify the Sprite properties, clear the Packing tag and set the Wrap mode to Repeat.", MessageType.Warning);
239 }
240 EditorGUILayout.EndFadeGroup();
241
242 if (EditorGUILayout.BeginFadeGroup(m_ShowFilled.faded))
243 {
244 EditorGUI.BeginChangeCheck();
245 EditorGUILayout.PropertyField(m_FillMethod);
246 if (EditorGUI.EndChangeCheck())
247 {
248 m_FillOrigin.intValue = 0;
249 }
250 var shapeRect = EditorGUILayout.GetControlRect(true);
251 switch ((Image.FillMethod)m_FillMethod.enumValueIndex)
252 {
253 case Image.FillMethod.Horizontal:
254 EditorGUI.Popup(shapeRect, m_FillOrigin, Styles.OriginHorizontalStyle, Styles.text);
255 break;
256 case Image.FillMethod.Vertical:
257 EditorGUI.Popup(shapeRect, m_FillOrigin, Styles.OriginVerticalStyle, Styles.text);
258 break;
259 case Image.FillMethod.Radial90:
260 EditorGUI.Popup(shapeRect, m_FillOrigin, Styles.Origin90Style, Styles.text);
261 break;
262 case Image.FillMethod.Radial180:
263 EditorGUI.Popup(shapeRect, m_FillOrigin, Styles.Origin180Style, Styles.text);
264 break;
265 case Image.FillMethod.Radial360:
266 EditorGUI.Popup(shapeRect, m_FillOrigin, Styles.Origin360Style, Styles.text);
267 break;
268 }
269
270 if (m_bIsDriven)
271 EditorGUILayout.HelpBox("The Fill amount property is driven by Slider.", MessageType.None);
272 using (new EditorGUI.DisabledScope(m_bIsDriven))
273 {
274 EditorGUILayout.PropertyField(m_FillAmount);
275 }
276
277 if ((Image.FillMethod)m_FillMethod.enumValueIndex > Image.FillMethod.Vertical)
278 {
279 EditorGUILayout.PropertyField(m_FillClockwise, m_ClockwiseContent);
280 }
281 }
282 EditorGUILayout.EndFadeGroup();
283 }
284 --EditorGUI.indentLevel;
285 }
286
287 /// <summary>
288 /// All graphics have a preview.
289 /// </summary>
290
291 public override bool HasPreviewGUI() { return true; }
292
293 /// <summary>
294 /// Draw the Image preview.
295 /// </summary>
296
297 public override void OnPreviewGUI(Rect rect, GUIStyle background)
298 {
299 Image image = target as Image;
300 if (image == null) return;
301
302 Sprite sf = image.sprite;
303 if (sf == null) return;
304
305 SpriteDrawUtility.DrawSprite(sf, rect, image.canvasRenderer.GetColor());
306 }
307
308 /// <summary>
309 /// A string containing the Image details to be used as a overlay on the component Preview.
310 /// </summary>
311 /// <returns>
312 /// The Image details.
313 /// </returns>
314
315 public override string GetInfoString()
316 {
317 Image image = target as Image;
318 Sprite sprite = image.sprite;
319
320 int x = (sprite != null) ? Mathf.RoundToInt(sprite.rect.width) : 0;
321 int y = (sprite != null) ? Mathf.RoundToInt(sprite.rect.height) : 0;
322
323 return string.Format("Image Size: {0}x{1}", x, y);
324 }
325 }
326}