2using System.Collections;
3using System.Collections.Generic;
4using System.Globalization;
20 internal Action<InspectorStackEntryBase[]> InspectorOpenCallback;
21 internal Action<Transform> TreeSelectionChangedCallback;
23 private readonly HashSet<GameObject> _openedObjects =
new HashSet<GameObject>();
24 private Vector2 _propertiesScrollPosition;
25 private Transform _selectedTransform;
26 private Vector2 _treeScrollPosition;
27 private Rect _windowRect;
28 private float _objectTreeHeight;
29 private int _singleObjectTreeItemHeight;
30 private bool _scrollTreeToSelected;
31 private bool _enabled;
33 private readonly Dictionary<Image, Texture2D> _imagePreviewCache =
new Dictionary<Image, Texture2D>();
34 private readonly GUILayoutOption _drawVector3FieldWidth = GUILayout.Width(38);
35 private readonly GUILayoutOption _drawVector3FieldHeight = GUILayout.Height(19);
36 private readonly GUILayoutOption _drawVector3SliderHeight = GUILayout.Height(10);
37 private readonly GUILayoutOption _drawVector3SliderWidth = GUILayout.Width(33);
38 private readonly
int _windowId;
44 if (target ==
null)
return;
46 target = target.parent;
47 while (target !=
null)
49 _openedObjects.Add(target.gameObject);
50 target = target.parent;
53 _scrollTreeToSelected =
true;
59 if (pluginObject ==
null)
throw new ArgumentNullException();
60 if (gameObjectSearcher ==
null)
throw new ArgumentNullException();
62 _gameObjectSearcher = gameObjectSearcher;
63 _windowId = GetHashCode();
65 pluginObject.StartCoroutine(SetWireframeCo());
68 private bool _wireframe;
69 private bool _actuallyInsideOnGui;
71 private IEnumerator SetWireframeCo()
77 _actuallyInsideOnGui =
true;
79 yield
return new WaitForEndOfFrame();
81 if (GL.wireframe != _wireframe)
82 GL.wireframe = _wireframe;
84 _actuallyInsideOnGui =
false;
97 if (value && !_enabled)
108 return _selectedTransform;
113 if (_selectedTransform != value)
115 _selectedTransform = value;
116 _searchTextComponents =
"";
117 if(TreeSelectionChangedCallback !=
null) TreeSelectionChangedCallback.Invoke(_selectedTransform);
124 _imagePreviewCache.Clear();
129 InspectorOpenCallback.Invoke(items);
134 _windowRect = windowRect;
135 _objectTreeHeight = _windowRect.height / 3;
138 private void DisplayObjectTreeHelper(GameObject go,
int indent, ref
int currentCount)
142 var needsHeightMeasure = _singleObjectTreeItemHeight == 0;
144 var isVisible = currentCount * _singleObjectTreeItemHeight >= _treeScrollPosition.y &&
145 (currentCount - 1) * _singleObjectTreeItemHeight <= _treeScrollPosition.y + _objectTreeHeight;
147 if (needsHeightMeasure || isVisible)
152 GUI.color =
Color.cyan;
153 if (_scrollTreeToSelected && Event.current.type == EventType.Repaint)
155 _scrollTreeToSelected =
false;
156 _treeScrollPosition.y = GUILayoutUtility.GetLastRect().y - 50;
159 else if (!go.activeSelf)
161 GUI.color =
new Color(1, 1, 1, 0.6f);
164 GUILayout.BeginHorizontal();
166 GUILayout.Space(indent * 20f);
168 GUILayout.BeginHorizontal();
170 if (go.transform.childCount != 0)
172 if (GUILayout.Toggle(_openedObjects.Contains(go),
"", GUILayout.ExpandWidth(
false)))
173 _openedObjects.Add(go);
175 _openedObjects.Remove(go);
179 GUILayout.Space(20f);
182 if (GUILayout.Button(go.name, GUI.skin.label, GUILayout.ExpandWidth(
true), GUILayout.MinWidth(200)))
187 if (!_openedObjects.Add(go))
188 _openedObjects.Remove(go);
198 GUILayout.EndHorizontal();
200 GUILayout.EndHorizontal();
202 if (needsHeightMeasure && Event.current.type == EventType.Repaint)
203 _singleObjectTreeItemHeight = Mathf.CeilToInt(GUILayoutUtility.GetLastRect().height);
207 GUILayout.Space(_singleObjectTreeItemHeight);
210 if (_openedObjects.Contains(go))
212 for (var i = 0; i < go.transform.childCount; ++i)
213 DisplayObjectTreeHelper(go.transform.GetChild(i).gameObject, indent + 1, ref currentCount);
219 if (_wireframe && _actuallyInsideOnGui && Event.current.type == EventType.Layout)
220 GL.wireframe =
false;
225 InterfaceMaker.EatInputInRect(_windowRect);
229 private void WindowFunc(
int id)
231 GUILayout.BeginVertical();
237 DisplayObjectProperties();
239 GUILayout.EndHorizontal();
244 private void DisplayControls()
246 GUILayout.BeginHorizontal();
248 GUILayout.BeginHorizontal(GUI.skin.box);
250 GUILayout.Label(
"Time", GUILayout.ExpandWidth(
false));
252 if (GUILayout.Button(
">", GUILayout.ExpandWidth(
false)))
254 if (GUILayout.Button(
"||", GUILayout.ExpandWidth(
false)))
257 if (
float.TryParse(GUILayout.TextField(Time.timeScale.ToString(
"F2", CultureInfo.InvariantCulture), _drawVector3FieldWidth), NumberStyles.Any, CultureInfo.InvariantCulture, out newVal))
259 Time.timeScale = newVal;
262 GUILayout.EndHorizontal();
264 GUILayout.BeginHorizontal(GUI.skin.box);
267 if (GUILayout.Button(
"Dump", GUILayout.ExpandWidth(
false)))
272 if (GUILayout.Button(
"Log", GUILayout.ExpandWidth(
false)))
273 UnityFeatureHelper.OpenLog();
275 GUILayout.FlexibleSpace();
277 _wireframe = GUILayout.Toggle(_wireframe,
"Wireframe");
279 GUILayout.EndHorizontal();
281 GUILayout.EndHorizontal();
283 AssetBundleManagerHelper.DrawButtonIfAvailable();
288 private void DisplayObjectProperties()
290 _propertiesScrollPosition = GUILayout.BeginScrollView(_propertiesScrollPosition, GUI.skin.box);
294 GUILayout.Label(
"No object selected");
298 DrawTransformControls();
300 GUILayout.BeginHorizontal();
302 GUILayout.Label(
"Search components ", GUILayout.ExpandWidth(
false));
304 _searchTextComponents = GUILayout.TextField(_searchTextComponents, GUILayout.ExpandWidth(
true));
306 if (GUILayout.Button(
"Clear", GUILayout.ExpandWidth(
false)))
307 _searchTextComponents =
string.Empty;
309 GUILayout.EndHorizontal();
313 if (component ==
null)
316 if (!
string.IsNullOrEmpty(_searchTextComponents) && !GameObjectSearcher.SearchInComponent(_searchTextComponents, component,
false))
319 DrawSingleComponent(component);
323 GUILayout.EndScrollView();
326 private void DrawTransformControls()
328 GUILayout.BeginVertical(GUI.skin.box);
332 GUILayout.TextArea(fullTransfromPath, GUI.skin.label);
334 GUILayout.BeginHorizontal();
336 GUILayout.Label(
string.Format(
"Layer {0} ({1})",
SelectedTransform.gameObject.layer,
345 GUILayout.FlexibleSpace();
347 if (GUILayout.Button(
"Inspect"))
350 if (GUILayout.Button(
"X"))
353 GUILayout.EndHorizontal();
361 GUILayout.EndVertical();
364 private void DrawVector3(
string name, Action<Vector3>
set, Func<Vector3>
get,
float minVal,
float maxVal)
370 GUILayout.BeginHorizontal();
372 GUILayout.Label(name, GUILayout.ExpandWidth(
true), _drawVector3FieldHeight);
373 v3New.x = GUILayout.HorizontalSlider(v3.x, minVal, maxVal, _drawVector3SliderWidth, _drawVector3SliderHeight);
374 float.TryParse(GUILayout.TextField(v3New.x.ToString(
"F2", CultureInfo.InvariantCulture), _drawVector3FieldWidth, _drawVector3FieldHeight), NumberStyles.Any, CultureInfo.InvariantCulture, out v3New.x);
375 v3New.y = GUILayout.HorizontalSlider(v3.y, minVal, maxVal, _drawVector3SliderWidth, _drawVector3SliderHeight);
376 float.TryParse(GUILayout.TextField(v3New.y.ToString(
"F2", CultureInfo.InvariantCulture), _drawVector3FieldWidth, _drawVector3FieldHeight), NumberStyles.Any, CultureInfo.InvariantCulture, out v3New.y);
377 v3New.z = GUILayout.HorizontalSlider(v3.z, minVal, maxVal, _drawVector3SliderWidth, _drawVector3SliderHeight);
378 float.TryParse(GUILayout.TextField(v3New.z.ToString(
"F2", CultureInfo.InvariantCulture), _drawVector3FieldWidth, _drawVector3FieldHeight), NumberStyles.Any, CultureInfo.InvariantCulture, out v3New.z);
380 GUILayout.EndHorizontal();
382 if (GUI.changed && v3 != v3New)
set(v3New);
385 private void DrawVector2(
string name, Action<Vector2>
set, Func<Vector2>
get,
float minVal,
float maxVal)
388 var vector2New = vector2;
391 GUILayout.BeginHorizontal();
393 GUILayout.Label(name, GUILayout.ExpandWidth(
true), _drawVector3FieldHeight);
394 vector2New.x = GUILayout.HorizontalSlider(vector2.x, minVal, maxVal, _drawVector3SliderWidth, _drawVector3SliderHeight);
395 float.TryParse(GUILayout.TextField(vector2New.x.ToString(
"F2", CultureInfo.InvariantCulture), _drawVector3FieldWidth, _drawVector3FieldHeight), NumberStyles.Any, CultureInfo.InvariantCulture, out vector2New.x);
396 vector2New.y = GUILayout.HorizontalSlider(vector2.y, minVal, maxVal, _drawVector3SliderWidth, _drawVector3SliderHeight);
397 float.TryParse(GUILayout.TextField(vector2New.y.ToString(
"F2", CultureInfo.InvariantCulture), _drawVector3FieldWidth, _drawVector3FieldHeight), NumberStyles.Any, CultureInfo.InvariantCulture, out vector2New.y);
399 GUILayout.EndHorizontal();
401 if (GUI.changed && vector2 != vector2New)
set(vector2New);
404 private void DrawSingleComponent(
Component component)
406 GUILayout.BeginHorizontal(GUI.skin.box);
408 var bh = component as Behaviour;
409 var img = component as
Image;
410 var b = component as Slider;
411 var text = component as Text;
412 var r = component as RawImage;
413 var re = component as Renderer;
414 var bu = component as
Button;
415 var to = component as Toggle;
416 var rt = component as RectTransform;
417 if (bh !=
null) bh.enabled = GUILayout.Toggle(bh.enabled,
"", GUILayout.ExpandWidth(
false));
419 if (GUILayout.Button(component.GetType().Name, GUI.skin.label))
421 OnInspectorOpen(
new InstanceStackEntry(component.transform, component.transform.name),
425 if (img !=
null && (img.sprite !=
null && img.sprite.texture !=
null))
427 GUILayout.Label(img.sprite.name);
429 if (!_imagePreviewCache.TryGetValue(img, out tex))
433 var newImg = img.sprite.texture.GetPixels(
434 (
int)img.sprite.textureRect.x, (
int)img.sprite.textureRect.y,
435 (
int)img.sprite.textureRect.width,
436 (
int)img.sprite.textureRect.height);
437 tex =
new Texture2D((
int)img.sprite.textureRect.width,
438 (
int)img.sprite.textureRect.height);
439 tex.SetPixels(newImg);
448 _imagePreviewCache.Add(img, tex);
452 GUILayout.Label(tex);
454 GUILayout.Label(
"Can't display texture");
459 for (var i = 0; i < b.onValueChanged.GetPersistentEventCount(); ++i)
460 GUILayout.Label(ToStringConverter.EventEntryToString(b.onValueChanged, i));
464 string.Format(
"{0} {1} {2} {3} {4} {5} {6}", text.text, text.font, text.fontStyle,
465 text.fontSize, text.alignment, text.resizeTextForBestFit, text.color));
467 if (r !=
null) GUILayout.Label(r.mainTexture);
469 GUILayout.Label(re !=
null && re.material !=
null
470 ? re.material.shader.name
474 var eventObj = bu.onClick;
475 for (var i = 0; i < eventObj.GetPersistentEventCount(); ++i)
476 GUILayout.Label(ToStringConverter.EventEntryToString(eventObj, i));
478 var calls = (IList)eventObj.GetPrivateExplicit<UnityEventBase>(
"m_Calls").GetPrivate(
"m_RuntimeCalls");
479 foreach (var call
in calls)
480 GUILayout.Label(ToStringConverter.ObjectToString(call.GetPrivate(
"Delegate")));
485 var eventObj = to.onValueChanged;
486 for (var i = 0; i < eventObj.GetPersistentEventCount(); ++i)
487 GUILayout.Label(ToStringConverter.EventEntryToString(to.onValueChanged, i));
489 var calls = (IList)to.onValueChanged.GetPrivateExplicit<UnityEventBase>(
"m_Calls").GetPrivate(
"m_RuntimeCalls");
490 foreach (var call
in calls)
491 GUILayout.Label(ToStringConverter.ObjectToString(call.GetPrivate(
"Delegate")));
496 GUILayout.BeginVertical();
498 DrawVector2(
"anchorMin", vector2 => rt.anchorMin = vector2, () => rt.anchorMin, 0, 1);
499 DrawVector2(
"anchorMax", vector2 => rt.anchorMax = vector2, () => rt.anchorMax, 0, 1);
500 DrawVector2(
"offsetMin", vector2 => rt.offsetMin = vector2, () => rt.offsetMin, -1000, 1000);
501 DrawVector2(
"offsetMax", vector2 => rt.offsetMax = vector2, () => rt.offsetMax, -1000, 1000);
502 DrawVector2(
"sizeDelta", vector2 => rt.sizeDelta = vector2, () => rt.sizeDelta, -1000, 1000);
503 GUILayout.Label(
"rect " + rt.rect);
505 GUILayout.EndVertical();
508 GUILayout.FlexibleSpace();
510 if (!(component is Transform))
527 if (GUILayout.Button(
"X"))
529 Object.Destroy(component);
533 GUILayout.EndHorizontal();
536 private string _searchText =
string.Empty;
537 private string _searchTextComponents =
string.Empty;
538 private void DisplayObjectTree()
540 GUILayout.BeginVertical(GUI.skin.box);
542 DisplayTreeSearchBox();
544 _treeScrollPosition = GUILayout.BeginScrollView(_treeScrollPosition,
545 GUILayout.Height(_objectTreeHeight), GUILayout.ExpandWidth(
true));
547 var currentCount = 0;
548 foreach (var rootGameObject
in _gameObjectSearcher.GetSearchedOrAllObjects())
549 DisplayObjectTreeHelper(rootGameObject, 0, ref currentCount);
551 GUILayout.EndScrollView();
553 GUILayout.EndVertical();
556 private void DisplayTreeSearchBox()
558 GUILayout.BeginHorizontal();
560 GUI.SetNextControlName(
"searchbox");
561 _searchText = GUILayout.TextField(_searchText, GUILayout.ExpandWidth(
true));
563 if (GUILayout.Button(
"Clear", GUILayout.ExpandWidth(
false)))
565 _searchText =
string.Empty;
566 _gameObjectSearcher.Search(_searchText,
false);
570 GUILayout.EndHorizontal();
572 GUILayout.BeginHorizontal();
574 if (GUILayout.Button(
"Search scene"))
575 _gameObjectSearcher.Search(_searchText,
false);
577 if (Event.current.isKey && (Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter) && GUI.GetNameOfFocusedControl() ==
"searchbox")
579 _gameObjectSearcher.Search(_searchText,
false);
583 if (GUILayout.Button(
"Deep scene"))
584 _gameObjectSearcher.Search(_searchText,
true);
586 if (GUILayout.Button(
"Search static"))
588 if (
string.IsNullOrEmpty(_searchText))
590 RuntimeUnityEditorCore.Logger.Log(
LogLevel.Message |
LogLevel.Warning,
"Can't search for empty string");
594 var matchedTypes = AppDomain.CurrentDomain.GetAssemblies()
595 .SelectMany(Extensions.GetTypesSafe)
596 .Where(x => x.GetSourceCodeRepresentation().Contains(_searchText, StringComparison.OrdinalIgnoreCase));
598 var stackEntries = matchedTypes.Select(t =>
new StaticStackEntry(t, t.FullName)).ToList();
600 if (stackEntries.Count == 0)
601 RuntimeUnityEditorCore.Logger.Log(
LogLevel.Message |
LogLevel.Warning,
"No static type names contained the search string");
602 else if (stackEntries.Count == 1)
603 RuntimeUnityEditorCore.Instance.Inspector.Push(stackEntries.Single(),
true);
605 RuntimeUnityEditorCore.Instance.Inspector.Push(
new InstanceStackEntry(stackEntries,
"Static type search"),
true);
609 GUILayout.EndHorizontal();
UnityEngine.Component Component
UnityEngine.UI.Button Button
RuntimeUnityEditor.Core.LogLevel LogLevel
System.Drawing.Image Image
static void DisplayControls()
Keeps track of root gameobjects and allows searching objects in the scene
void UpdateWindowSize(Rect windowRect)
Transform SelectedTransform
void SelectAndShowObject(Transform target)
ObjectTreeViewer(MonoBehaviour pluginObject, GameObjectSearcher gameObjectSearcher)