A game about forced loneliness, made by TACStudios
1using System;
2using System.Linq;
3using System.Collections.Generic;
4using UnityEngine;
5using UnityEngine.UIElements;
6
7namespace UnityEditor.U2D.Sprites
8{
9 /// <summary>Base class the Sprite Editor Window custom module inherits from.</summary>
10 /// <remarks>Sprite Editor Window functionality can be extended by providing custom module. By inheriting from SpriteEditorModuleBase, user will be able to activate the module's functionality from Sprite Editor Window.
11 /// </remarks>
12 public abstract class SpriteEditorModuleBase
13 {
14 /// <summary>The ISpriteEditor instance that instantiated the module.</summary>
15 /// <value>An instance of ISpriteEditor</value>
16 public ISpriteEditor spriteEditor { get; internal set; }
17 /// <summary>The module name to display in Sprite Editor Window.</summary>
18 /// <value>String to represent the name of the module</value>
19 public abstract string moduleName { get; }
20 /// <summary>Indicates if the module can be activated with the current ISpriteEditor state.</summary>
21 /// <returns>Return true if the module can be activated.</returns>
22 public abstract bool CanBeActivated();
23 /// <summary>Implement this to draw on the Sprite Editor Window.</summary>
24 /// <remarks>Called after Sprite Editor Window draws texture preview of the Asset.Use this to draw gizmos for Sprite data.</remarks>
25 public abstract void DoMainGUI();
26 /// <summary>Implement this to create a custom toolbar.</summary>
27 /// <param name = "drawArea" > Area for drawing tool bar.</param>
28 public abstract void DoToolbarGUI(Rect drawArea);
29 /// <summary>This is called when the user activates the module.</summary>
30 /// <remarks>When user switches to the module via Sprite Editor Window, this method will be called for the module to setup.</remarks>
31 public abstract void OnModuleActivate();
32 /// <summary>This is called when user switches to another module.</summary>
33 /// <remarks>When user switches to the another module in Sprite Editor Window, this method will be called for the module to clean up.</remarks>
34 public abstract void OnModuleDeactivate();
35 /// <summary>Implement this to draw widgets in Sprite Editor Window.</summary>
36 /// <remarks>This method is called last to allow drawing of widgets.</remarks>
37 public abstract void DoPostGUI();
38 /// <summary>This is called when user clicks on the Apply or Revert button in Sprite Editor Window.</summary>
39 /// <param name="apply">True when user wants to apply the data, false when user wants to revert.</param>
40 /// <returns>Return true to trigger a reimport.</returns>
41 public abstract bool ApplyRevert(bool apply);
42
43 }
44
45 /// <summary>
46 /// Base class for having SpriteEditorModule use as a mode in another SpriteEditorModuleBase
47 /// </summary>
48 internal abstract class SpriteEditorModuleModeSupportBase : SpriteEditorModuleBase
49 {
50 List<SpriteEditorModeBase> m_Modes = new();
51 event Action m_OnModuleActivate;
52 /// <summary>
53 /// Modes that the module can be activated as.
54 /// </summary>
55 /// <param name="modes">Enumerable list of mode Type that can be activated</param>
56 public virtual void SetModuleModes(IEnumerable<Type> modes)
57 {
58 m_Modes.Clear();
59 foreach (var t in modes)
60 {
61 var mode = Activator.CreateInstance(t);
62 if (mode is SpriteEditorModeBase moduleMode)
63 {
64 moduleMode.spriteEditor = modeSpriteEditor;
65 if (moduleMode.CanBeActivated())
66 {
67 m_Modes.Add(moduleMode);
68 }
69 }
70 }
71 }
72
73 public List<SpriteEditorModeBase> modes => m_Modes;
74 public virtual ISpriteEditor modeSpriteEditor => spriteEditor;
75
76 public void RegisterModuleActivate(Action onActivate)
77 {
78 m_OnModuleActivate += onActivate;
79 }
80
81 public void UnregisterModuleActivate(Action onActivate)
82 {
83 m_OnModuleActivate -= onActivate;
84 }
85
86 public void SignalModuleActivate()
87 {
88 m_OnModuleActivate?.Invoke();
89 }
90 }
91
92 /// <summary>
93 /// Base class for having SpriteEditorModuleBase use as a mode in another SpriteEditorModuleBase
94 /// </summary>
95 internal abstract class SpriteEditorModeBase : SpriteEditorModuleBase
96 {
97 /// <summary>
98 /// This is called when a SpriteEditorModeBase is activated as a mode.
99 /// </summary>
100 /// <returns>Return true if the mode is activated</returns>
101 public abstract bool ActivateMode();
102
103 /// <summary>
104 /// This is called when SpriteEditorModeBase is deactivated as a mode.
105 /// </summary>
106 public abstract void DeactivateMode();
107
108 /// <summary>
109 /// This is called SpriteEditorModeBase is added to a module.
110 /// </summary>
111 /// <param name="module">The module that added this mode</param>
112 public abstract void OnAddToModule(SpriteEditorModuleModeSupportBase module);
113
114 /// <summary>
115 /// This is called SpriteEditorModeBase is removed from a module.
116 /// </summary>
117 /// <param name="module">The module that removed this mode</param>
118 public abstract void OnRemoveFromModule(SpriteEditorModuleModeSupportBase module);
119
120 /// <summary>
121 /// Register a callback to be called when the mode is activated.
122 /// </summary>
123 /// <param name="onActivate">Callback delegate</param>
124 public abstract void RegisterOnModeRequestActivate(Action<SpriteEditorModeBase> onActivate);
125
126 /// <summary>
127 /// Unregister a previously registered callback.
128 /// </summary>
129 /// <param name="onActivate">Callback delegate</param>
130 public abstract void UnregisterOnModeRequestActivate(Action<SpriteEditorModeBase> onActivate);
131
132 /// <summary>
133 /// Inform the mode to apply or revert data changes.
134 /// </summary>
135 /// <param name="apply">True when data needs to be apply.</param>
136 /// <param name="dataProviderTypes">List of data provider type that has data applied before. Append to the list if new data type has changed.</param>
137 /// /// <returns>Return true to trigger a reimport.</returns>
138 public abstract bool ApplyModeData(bool apply, HashSet<Type> dataProviderTypes);
139 }
140
141 /// <summary>Interface that defines the functionality available for classes that inherits SpriteEditorModuleBase.</summary>
142 /// <remarks>Used by Sprite Editor Window to encapsulate functionality accessible for Sprite Editor modules when editing Sprite data.</remarks>
143 public interface ISpriteEditor
144 {
145 /// <summary>Sets current available Sprite rects.</summary>
146 List<SpriteRect> spriteRects { set; }
147 /// <summary>The current selected Sprite rect data.</summary>
148 SpriteRect selectedSpriteRect { get; set; }
149 /// <summary>Indicates if ISpriteEditor should be interested in mouse move events.</summary>
150 bool enableMouseMoveEvent { set; }
151 /// <summary>Indicates that if Sprite data editing should be disabled; for example when the Editor is in Play Mode.</summary>
152 bool editingDisabled { get; }
153 /// <summary>Property that defines the window's current screen position and size.</summary>
154 Rect windowDimension { get; }
155 /// <summary>
156 /// Gets data provider that is supported by the current selected object.
157 /// </summary>
158 /// <typeparam name="T">Data provider type</typeparam>
159 /// <returns>Instance of the data provider</returns>
160 T GetDataProvider<T>() where T : class;
161 /// <summary>The method updates ISpriteEditor.selectedSpriteRect based on current mouse down event and ISpriteEditor.spriteRects available.</summary>
162 /// <returns>Returns true when ISpriteEditor.selectedSpriteRect is changed.</returns>
163 bool HandleSpriteSelection();
164 /// <summary>Request to repaint the current view.</summary>
165 void RequestRepaint();
166 /// <summary>Indicates that there has been a change of data. In Sprite Editor Window, this enables the 'Apply' and 'Revert' button.</summary>
167 void SetDataModified();
168 /// <summary>The method will inform current active SpriteEditorModuleBase to apply or revert any data changes.</summary>
169 void ApplyOrRevertModification(bool apply);
170 /// <summary>
171 /// Returns a VisualElement for attaching child VisualElement onto the main view of a ISpriteEditor.
172 /// </summary>
173 /// <returns>Root VisualElement for the main view.</returns>
174 /// <remarks>This method returns the root VisualElement for SpriteEditorModuleBase which uses the UIElement instead of IMGUI for its UI.A VisualElement that is added to this container has the same draw order as SpriteEditorModuleBase.DoPostGUI.</remarks>
175 VisualElement GetMainVisualContainer();
176
177 /// <summary>
178 /// Returns a VisualElement for attaching child Toolbar onto the toolbar of a ISpriteEditor.
179 /// </summary>
180 /// <returns>Root VisualElement for the toolbar.</returns>
181 /// <remarks>This method returns the root VisualElement for SpriteEditorModuleBase which uses the UIElement instead of IMGUI for its UI.</remarks>
182 VisualElement GetToolbarRootElement()
183 {
184 return null;
185 }
186
187 /// <summary>Sets a custom texture to be used by the ISpriteEditor during setup of the editing space.</summary>
188 /// <param name = "texture" > The custom preview texture.</param>
189 /// <param name = "width" > The width dimension to render the preview texture.</param>
190 /// <param name = "height" > The height dimension to render the preview texture.</param>
191 /// <remarks>When the method is called, the editing space's dimensions are set to the width and height values, affecting operations such as Zoom and Pan in the ISpriteEditor view. The preview texture is rendered as the background of the editing space.</remarks>
192 void SetPreviewTexture(Texture2D texture, int width, int height);
193 /// <summary> Resets the zoom and scroll of the Sprite Editor Windows.</summary>
194 void ResetZoomAndScroll();
195 /// <summary>Current zoom level of the ISpriteEditor view. </summary>
196 float zoomLevel { get; set; }
197 /// <summary>Current scroll position of the ISpriteEditor view. Determines the viewing location of the Texture displayed</summary>
198 Vector2 scrollPosition { get; set; }
199 /// <summary>Whether the ISpriteEditor view is visualizing the Alpha of the Texture displayed</summary>
200 bool showAlpha { get; set; }
201 /// <summary>The current Mip Level of the Texture displayed in ISpriteEditor view</summary>
202 float mipLevel { get; set; }
203 }
204
205 /// <summary>Use this attribute on a class that inherits from SpriteEditorModuleBase to indicate what data provider it needs.</summary>
206 /// <remarks>When you use this attribute, Sprite Editor Window will only make the module available for selection if ISpriteEditorDataProvider.HasDataProvider returns true for all the data providers the module needs.
207 /// <code>
208 /// using UnityEditor.U2D;
209 /// using UnityEngine;
210 ///
211 /// [RequireSpriteDataProvider(typeof(ISpriteOutlineDataProvider), typeof(ITextureDataProvider))]
212 /// public class MySpriteEditorCustomModule : SpriteEditorModuleBase
213 /// {
214 /// public override string moduleName
215 /// {
216 /// get { return "MySpriteEditorCustomModule"; }
217 /// }
218 /// public override bool ApplyRevert(bool apply)
219 /// {
220 /// return true;
221 /// }
222 /// public override bool CanBeActivated()
223 /// {
224 /// return true;
225 /// }
226 /// public override void DoMainGUI() { }
227 /// public override void DoToolbarGUI(Rect drawArea) { }
228 /// public override void OnModuleActivate()
229 /// {
230 /// var outlineProvider = spriteEditor.GetDataProvider<ISpriteOutlineDataProvider>();
231 /// var spriteRects = spriteEditor.GetDataProvider<ISpriteEditorDataProvider>().GetSpriteRects();
232 /// foreach (var spriteRect in spriteRects)
233 /// {
234 /// // Access outline data
235 /// Debug.Log(outlineProvider.GetOutlines(spriteRect.spriteID));
236 /// }
237 /// }
238 /// public override void OnModuleDeactivate() { }
239 /// public override void DoPostGUI() { }
240 /// }
241 /// </code>
242 /// </remarks>
243 [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
244 public class RequireSpriteDataProviderAttribute : Attribute
245 {
246 Type[] m_Types;
247
248 /// <summary>Use the attribute to indicate the custom data provider that SpriteEditorBaseModule needs.</summary>
249 /// <param name="types">Data provider type.</param>
250 public RequireSpriteDataProviderAttribute(params Type[] types)
251 {
252 m_Types = types;
253 }
254
255 internal bool ContainsAllType(ISpriteEditorDataProvider provider)
256 {
257 return provider == null ? false : m_Types.Where(x =>
258 {
259 return provider.HasDataProvider(x);
260 }).Count() == m_Types.Length;
261 }
262 }
263
264 /// <summary>
265 /// Attribute to indicate the module that this module can be activated as a mode in.
266 /// </summary>
267 [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
268 internal class SpriteEditorModuleModeAttribute : Attribute
269 {
270 Type[] m_Types;
271 bool m_ShowAsModule;
272
273 /// <summary>Use the attribute to indicate the custom data provider that SpriteEditorBaseModule needs.</summary>
274 /// <param name="showAsModule">Indicate if this module should still be listed as a module.</param>
275 /// <param name="types">Type of module this can be activated as mode</param>
276 public SpriteEditorModuleModeAttribute(bool showAsModule = false, params Type[] types)
277 {
278 m_Types = types;
279 m_ShowAsModule = showAsModule;
280 }
281
282 /// <summary>
283 /// Indicate if this module should still be listed as a module.
284 /// </summary>
285 internal bool showAsModule => m_ShowAsModule;
286
287 /// <summary>
288 /// Modules that this module can be activated as a mode.
289 /// </summary>
290 /// <returns>List of module Type.</returns>
291 internal IEnumerable<Type> GetModuleTypes()
292 {
293 return m_Types;
294 }
295 }
296}