10using System.Reflection;
11using System.Collections.Generic;
15using UnityEditorInternal;
26 private SerializedObject _serializedObject;
28 private SerializedProperty _supportInfo;
30 private SerializedProperty _groupProperty;
32 private SerializedProperty _multiFeatureList;
33 private SerializedProperty _multiRenderingMethod;
34 private SerializedProperty _featureTable;
35 private ReorderableList _featureList;
36 private MonoScript _renderingMethodMonoScript;
38 private List<SerializedProperty> _cachedPropertyList;
39 private List<float> _cachedPropertyHeights;
41 private SerializedProperty _renderingMethod;
43 private GenericMenu _addRenderingMethodMenu;
44 private GenericMenu _addFeatureMenu;
48 _serializedObject = serializedObject;
51 var allRenderingMethods = allTypes.Query().
52 Where(t => !t.IsAbstract &&
56 _addRenderingMethodMenu =
new GenericMenu();
57 foreach (var renderingMethod
in allRenderingMethods) {
61 serializedObject.ApplyModifiedProperties();
62 Undo.RecordObject(_renderer,
"Changed rendering method");
63 EditorUtility.SetDirty(_renderer);
64 _renderer.editor.ChangeRenderingMethodOfSelectedGroup(renderingMethod, addFeatures: false);
65 serializedObject.Update();
66 _renderer.editor.ScheduleRebuild();
67 _serializedObject.SetIsDifferentCacheDirty();
71 var allFeatures = allTypes.Query().
72 Where(t => !t.IsAbstract &&
76 allFeatures.Sort((a, b) => {
79 var orderA = tagA ==
null ? 0 : tagA.
order;
80 var orderB = tagB ==
null ? 0 : tagB.order;
81 return orderA - orderB;
84 _addFeatureMenu =
new GenericMenu();
85 foreach (var item
in allFeatures.Query().WithPrevious(includeStart:
true)) {
87 var order = tag ==
null ? 0 : tag.
order;
91 var prevOrder = prevTag ==
null ? 0 : prevTag.
order;
92 if ((prevOrder / 100) != (order / 100)) {
93 _addFeatureMenu.AddSeparator(
"");
97 _addFeatureMenu.AddItem(
new GUIContent(tag.name),
100 if (item.value.ImplementsInterface(typeof(ICustomChannelFeature)) && LeapGraphicPreferences.promptWhenAddCustomChannel) {
101 int result = EditorUtility.DisplayDialogComplex(
"Adding Custom Channel",
"Custom channels can only be utilized by writing custom shaders, are you sure you want to continue?",
"Add it",
"Cancel",
"Add it from now on");
108 LeapGraphicPreferences.promptWhenAddCustomChannel = false;
113 serializedObject.ApplyModifiedProperties();
114 Undo.RecordObject(_renderer,
"Added feature");
115 EditorUtility.SetDirty(_renderer);
116 _renderer.editor.AddFeatureToSelectedGroup(item.value);
117 _serializedObject.Update();
118 _serializedObject.SetIsDifferentCacheDirty();
125 _renderingMethodMonoScript =
null;
132 drawRendererHeader();
142 EditorGUILayout.PropertyField(_renderingMethod, includeChildren:
true);
144 EditorGUILayout.Space();
148 _featureList.DoLayoutList();
150 drawWarningDialogs();
154 private void init(SerializedProperty groupProperty) {
155 Assert.IsNotNull(groupProperty);
156 _groupProperty = groupProperty;
158 _multiFeatureList = _groupProperty.FindPropertyRelative(
"_features");
159 _multiRenderingMethod = _groupProperty.FindPropertyRelative(
"_renderingMethod");
162 Assert.IsNotNull(_featureTable);
164 if (_featureList ==
null || !SerializedProperty.EqualContents(_featureList.serializedProperty, _featureTable)) {
165 _featureList =
new ReorderableList(_serializedObject,
168 displayHeader:
false,
169 displayAddButton:
false,
170 displayRemoveButton:
false);
172 _featureList.showDefaultBackground =
false;
173 _featureList.headerHeight = 0;
174 _featureList.elementHeight = EditorGUIUtility.singleLineHeight;
175 _featureList.elementHeightCallback = featureHeightCallback;
176 _featureList.drawElementCallback = drawFeatureCallback;
177 _featureList.onReorderCallback = onReorderFeaturesCallback;
180 _renderingMethod = MultiTypedReferenceUtil.GetReferenceProperty(_multiRenderingMethod);
181 _supportInfo = _groupProperty.FindPropertyRelative(
"_supportInfo");
183 _cachedPropertyList =
new List<SerializedProperty>();
184 _cachedPropertyHeights =
new List<float>();
186 for (
int i = 0; i < _featureTable.arraySize; i++) {
187 var idIndex = _featureTable.GetArrayElementAtIndex(i);
188 var referenceProp =
MultiTypedListUtil.GetReferenceProperty(_multiFeatureList, idIndex);
189 _cachedPropertyList.Add(referenceProp);
192 _cachedPropertyHeights.Add(EditorGUI.GetPropertyHeight(referenceProp) + EditorGUIUtility.singleLineHeight);
195 _renderingMethod = MultiTypedReferenceUtil.GetReferenceProperty(_multiRenderingMethod);
197 if (_renderingMethodMonoScript ==
null) {
198 _renderingMethodMonoScript = AssetDatabase.FindAssets(_renderingMethod.type).
200 Where(guid => !
string.IsNullOrEmpty(guid)).
201 Select(guid => AssetDatabase.GUIDToAssetPath(guid)).
202 Where(path => Path.GetFileNameWithoutExtension(path) == _renderingMethod.type).
203 Select(path => AssetDatabase.LoadAssetAtPath<MonoScript>(path)).
208 private void drawGroupName() {
209 var nameProperty = _groupProperty.FindPropertyRelative(
"_groupName");
210 EditorGUILayout.PropertyField(nameProperty);
212 nameProperty.stringValue = nameProperty.stringValue.Trim();
214 if (
string.IsNullOrEmpty(nameProperty.stringValue)) {
215 nameProperty.stringValue =
"MyGroupName";
219 private void drawRendererHeader() {
220 Rect rect = EditorGUILayout.GetControlRect(GUILayout.MaxHeight(EditorGUIUtility.singleLineHeight));
222 rect.SplitHorizontallyWithRight(out left, out right, BUTTON_WIDTH * 2);
224 #if UNITY_2018_3_OR_NEWER
225 if (!EditorApplication.isPlaying &&
227 !PrefabUtility.IsPartOfAnyPrefab(_renderer) ||
228 PrefabUtility.GetPrefabInstanceStatus(_renderer) != PrefabInstanceStatus.NotAPrefab)
231 if (!EditorApplication.isPlaying &&
232 PrefabUtility.GetPrefabType(_renderer) != PrefabType.Prefab)
235 var mesher = _renderer.editor.GetSelectedRenderingMethod() as LeapMesherBase;
236 if (mesher !=
null) {
238 Color prevColor = GUI.color;
239 if (mesher.IsAtlasDirty) {
240 GUI.color =
Color.yellow;
244 left.SplitHorizontallyWithRight(out left, out middle, REFRESH_WIDTH);
245 if (GUI.Button(middle,
"Refresh Atlas", EditorStyles.miniButtonMid)) {
246 _serializedObject.ApplyModifiedProperties();
247 Undo.RecordObject(_renderer,
"Refreshed atlas");
248 EditorUtility.SetDirty(_renderer);
250 _renderer.editor.ScheduleRebuild();
251 _serializedObject.Update();
254 GUI.color = prevColor;
258 EditorGUI.LabelField(left,
"Renderer", EditorStyles.miniButtonLeft);
259 using (
new EditorGUI.DisabledGroupScope(EditorApplication.isPlaying)) {
260 if (GUI.Button(right,
"v", EditorStyles.miniButtonRight)) {
261 _addRenderingMethodMenu.ShowAsContext();
266 private void drawStatsArea() {
267 using (
new EditorGUI.DisabledGroupScope(
true)) {
268 var graphicList = _groupProperty.FindPropertyRelative(
"_graphics");
269 int count = graphicList.arraySize;
270 EditorGUILayout.IntField(
"Attached Graphic Count", count);
274 private void drawSpriteWarning() {
275 var list = Pool<List<LeapGraphicFeatureBase>>.Spawn();
278 foreach (var group
in _renderer.groups) {
279 list.AddRange(group.features);
281 SpriteAtlasUtil.ShowInvalidSpriteWarning(list);
284 Pool<List<LeapGraphicFeatureBase>>.Recycle(list);
288 private void drawMonoScript() {
289 using (
new EditorGUI.DisabledGroupScope(
true)) {
290 EditorGUILayout.ObjectField(
"Rendering Method",
291 _renderingMethodMonoScript,
293 allowSceneObjects:
false);
297 private void drawWarningDialogs() {
298 HashSet<string> shownMessages = Pool<HashSet<string>>.Spawn();
300 for (
int i = 0; i < _cachedPropertyList.Count; i++) {
301 if (!EditorApplication.isPlaying) {
302 var supportInfo = _supportInfo.GetArrayElementAtIndex(i);
303 var supportProperty = supportInfo.FindPropertyRelative(
"support");
304 var messageProperty = supportInfo.FindPropertyRelative(
"message");
306 if (shownMessages.Contains(messageProperty.stringValue)) {
309 shownMessages.Add(messageProperty.stringValue);
313 EditorGUILayout.HelpBox(messageProperty.stringValue, MessageType.Warning);
316 EditorGUILayout.HelpBox(messageProperty.stringValue, MessageType.Error);
322 shownMessages.Clear();
323 Pool<HashSet<string>>.Recycle(shownMessages);
328 private void drawFeatureHeader() {
329 Rect rect = EditorGUILayout.GetControlRect(GUILayout.MaxHeight(EditorGUIUtility.singleLineHeight));
330 Rect left, middle, right;
331 rect.SplitHorizontallyWithRight(out middle, out right, BUTTON_WIDTH);
332 middle.SplitHorizontallyWithRight(out left, out middle, BUTTON_WIDTH);
334 EditorGUI.LabelField(left,
"Graphic Features", EditorStyles.miniButtonLeft);
336 using (
new EditorGUI.DisabledGroupScope(EditorApplication.isPlaying)) {
337 EditorGUI.BeginDisabledGroup(_featureTable.arraySize == 0);
338 if (GUI.Button(middle,
"-", EditorStyles.miniButtonMid) && _featureList.index >= 0) {
339 _serializedObject.ApplyModifiedProperties();
340 Undo.RecordObject(_renderer,
"Removed Feature");
341 EditorUtility.SetDirty(_renderer);
342 _renderer.editor.RemoveFeatureFromSelectedGroup(_featureList.index);
343 _serializedObject.Update();
344 init(_groupProperty);
346 EditorGUI.EndDisabledGroup();
348 if (GUI.Button(right,
"+", EditorStyles.miniButtonRight)) {
349 _addFeatureMenu.ShowAsContext();
356 private void drawFeatureHeaderCallback(Rect rect) {
358 rect.SplitHorizontallyWithRight(out left, out right, BUTTON_WIDTH);
360 EditorGUI.LabelField(left,
"Graphic Features", EditorStyles.miniButtonLeft);
362 if (GUI.Button(right,
"+", EditorStyles.miniButtonRight)) {
363 _addFeatureMenu.ShowAsContext();
367 private float featureHeightCallback(
int index) {
368 return _cachedPropertyHeights[index];
371 delegate
void Action<T1, T2, T3, T4, T5>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5);
373 private void drawFeatureCallback(Rect rect,
int index,
bool isActive,
bool isFocused) {
374 var featureProperty = _cachedPropertyList[index];
376 rect = rect.SingleLine();
377 string featureName = LeapGraphicTagAttribute.GetTagName(featureProperty.type);
379 int lastIndexOf = featureName.LastIndexOf(
'/');
380 if (lastIndexOf >= 0) {
381 featureName = featureName.Substring(lastIndexOf + 1);
384 GUIContent featureLabel =
new GUIContent(featureName);
386 Color originalColor = GUI.color;
388 if (!EditorApplication.isPlaying &&
389 index < _supportInfo.arraySize) {
390 var supportInfo = _supportInfo.GetArrayElementAtIndex(index);
391 var supportProperty = supportInfo.FindPropertyRelative(
"support");
392 var messageProperty = supportInfo.FindPropertyRelative(
"message");
395 GUI.color =
Color.yellow;
396 featureLabel.tooltip = messageProperty.stringValue;
399 GUI.color =
Color.red;
400 featureLabel.tooltip = messageProperty.stringValue;
405 Vector2 size = EditorStyles.label.CalcSize(featureLabel);
407 Rect labelRect = rect;
408 labelRect.width = size.x;
410 GUI.Box(labelRect,
"");
411 EditorGUI.LabelField(labelRect, featureLabel);
412 GUI.color = originalColor;
415 rect = rect.NextLine().Indent();
416 EditorGUI.PropertyField(rect, featureProperty, includeChildren:
true);
419 private void onReorderFeaturesCallback(ReorderableList list) {
420 _renderer.editor.ScheduleRebuild();
static string GetTagName(Type type)
static LeapGraphicTagAttribute GetTag(Type type)
LeapGuiGroupEditor(LeapGraphicRenderer renderer, SerializedObject serializedObject)
void DoGuiLayout(SerializedProperty groupProperty)
This class allows you to easily give feedback of an action as it completes.
A utility struct for ease of use when you want to wrap a piece of code in a Profiler....
A Query object is a type of immutable ordered collection of elements that can be used to perform usef...