private MemberDrawer[] GetMembers(Type type) { MemberDrawer[] drawers; if (type.IsGenericTypeDefinition == true) { return(NGStaticInspectorWindow.Empty); } if (this.typesMembers.TryGetValue(type, out drawers) == false) { List <MemberDrawer> list = new List <MemberDrawer>(); FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); PropertyInfo[] properties = type.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); drawers = new MemberDrawer[fields.Length + properties.Length]; for (int i = 0; i < fields.Length; i++) { list.Add(new MemberDrawer(TypeDrawerManager.GetDrawer(type.GetShortAssemblyType() + '.' + fields[i].Name, fields[i].Name, fields[i].FieldType), new FieldModifier(fields[i]))); } for (int i = 0; i < properties.Length; i++) { if (properties[i].GetGetMethod() != null) { string niceName = Utility.NicifyVariableName(properties[i].Name); int j = 0; for (; j < list.Count; j++) { if (list[j].typeDrawer.label == niceName) { break; } } if (j == list.Count) { list.Add(new MemberDrawer(TypeDrawerManager.GetDrawer(type.GetShortAssemblyType() + '.' + properties[i].Name, properties[i].Name, properties[i].PropertyType), new PropertyModifier(properties[i]))); } } } drawers = list.ToArray(); this.typesMembers.Add(type, drawers); } return(drawers); }
protected virtual void OnGUI() { EditorGUILayout.BeginHorizontal(GeneralStyles.Toolbar); { this.showTypes = GUILayout.Toggle(this.showTypes, "", GeneralStyles.ToolbarDropDown, GUILayoutOptionPool.Width(20F)); EditorGUI.BeginChangeCheck(); this.searchKeywords = EditorGUILayout.TextField(this.searchKeywords, GeneralStyles.ToolbarSearchTextField, GUILayoutOptionPool.ExpandWidthTrue); if (EditorGUI.EndChangeCheck() == true) { this.showTypes = true; this.searchPatterns = Utility.SplitKeywords(this.searchKeywords, ' '); this.RefreshFilter(); } if (GUILayout.Button("", GeneralStyles.ToolbarSearchCancelButton) == true) { this.searchKeywords = string.Empty; this.searchPatterns = Utility.SplitKeywords(this.searchKeywords, ' '); GUI.FocusControl(null); this.RefreshFilter(); } } EditorGUILayout.EndHorizontal(); if (this.errorPopup.exception != null) { this.errorPopup.OnGUILayout(); } if (this.typeNameStyle == null) { this.typeNameStyle = new GUIStyle(EditorStyles.label); this.typeNameStyle.alignment = TextAnchor.MiddleLeft; this.typeNameStyle.fontSize = 15; } this.bodyRect = GUILayoutUtility.GetLastRect(); this.bodyRect.y += this.bodyRect.height; if (this.tabTypes.Count > 0 && NGStaticInspectorWindow.staticTypes != null) { float totalWidth = -NGStaticInspectorWindow.Spacing; for (int i = 0; i < this.tabTypes.Count; i++) { Utility.content.text = NGStaticInspectorWindow.staticTypes[this.tabTypes[i]].Name; totalWidth += GeneralStyles.ToolbarButton.CalcSize(Utility.content).x + NGStaticInspectorWindow.Spacing; } this.scrollPositionTabs.allowedMouseArea = new Rect(0F, this.bodyRect.y, this.position.width, 22F); this.scrollPositionTabs.SetPosition(0F, this.bodyRect.y); this.scrollPositionTabs.SetSize(this.position.width); this.scrollPositionTabs.RealWidth = totalWidth; this.scrollPositionTabs.OnGUI(); this.bodyRect.y += this.scrollPositionTabs.MaxHeight; Rect r3 = bodyRect; r3.height = 18F; r3.y += 2F; r3.x = -this.scrollPositionTabs.Offset; for (int i = 0; i < this.tabTypes.Count; i++) { Type type = NGStaticInspectorWindow.staticTypes[this.tabTypes[i]]; string name = type.Name; string @namespace = type.Namespace; Utility.content.text = name; if (@namespace != null) { Utility.content.tooltip = @namespace + '.' + name; } else { Utility.content.tooltip = null; } r3.width = GeneralStyles.ToolbarButton.CalcSize(Utility.content).x; if (GUI.Button(r3, name, GeneralStyles.ToolbarButton) == true) { if (Event.current.button == 2) { this.tabTypes.RemoveAt(i); } this.selectedType = type; Utility.content.tooltip = null; return; } if (this.selectedType == NGStaticInspectorWindow.staticTypes[this.tabTypes[i]]) { Utility.DrawUnfillRect(r3, NGStaticInspectorWindow.SelectedTabOutline); } if (Utility.content.tooltip != null) { TooltipHelper.Label(r3, Utility.content.tooltip); } r3.x += r3.width + NGStaticInspectorWindow.Spacing; } Utility.content.tooltip = null; this.bodyRect.y += 20F + 2F; } float maxY = this.bodyRect.yMax; Rect r = new Rect(); if (this.showTypes == true && NGStaticInspectorWindow.staticTypes != null) { if (Event.current.type == EventType.MouseMove) { this.Repaint(); } this.bodyRect.height = this.position.height - this.bodyRect.y; this.viewRect = new Rect(0F, 0F, 0F, this.CountTypes() * (NGStaticInspectorWindow.Spacing + NGStaticInspectorWindow.TypeHeight) - NGStaticInspectorWindow.Spacing); this.bodyRect.height -= this.contentHeight; if (this.viewRect.height < 100F) { if (this.bodyRect.height > this.viewRect.height) { this.bodyRect.height = this.viewRect.height; } } maxY = this.bodyRect.yMax; this.scrollPositionTypes = GUI.BeginScrollView(this.bodyRect, this.scrollPositionTypes, this.viewRect); { r.width = this.position.width - (viewRect.height > this.bodyRect.height ? 16F : 0F); r.height = NGStaticInspectorWindow.TypeHeight; int i = 0; if (this.viewRect.height > this.bodyRect.height) { i = (int)(this.scrollPositionTypes.y / (NGStaticInspectorWindow.Spacing + r.height)); r.y = i * (NGStaticInspectorWindow.Spacing + r.height); } r.xMin += 5F; foreach (Type type in this.EachType(i--)) { r.height = NGStaticInspectorWindow.TypeHeight; ++i; if (r.y + r.height + NGStaticInspectorWindow.Spacing <= this.scrollPositionTypes.y) { r.y += r.height + NGStaticInspectorWindow.Spacing; continue; } GUI.Box(r, ""); if (Event.current.type == EventType.Repaint) { if (this.selectedType == type) { Utility.DrawUnfillRect(r, NGStaticInspectorWindow.SelectedTypeOutline); } if (r.Contains(Event.current.mousePosition) == true) { r.x -= 2F; r.y -= 2F; r.width += 4F; r.height += 4F; Utility.DrawUnfillRect(r, NGStaticInspectorWindow.HoveredTypeOutline); r.x += 2F; r.y += 2F; r.width -= 4F; r.height -= 4F; } } else if (Event.current.type == EventType.MouseDown && r.Contains(Event.current.mousePosition) == true) { this.Repaint(); if (Event.current.button != 2) { this.selectedType = type; } if (string.IsNullOrEmpty(this.searchKeywords) == false) { i = this.filteredTypes[i]; } if (Event.current.button != 0 && this.tabTypes.Contains(i) == false) { this.tabTypes.Insert(0, i); } break; } r.height = 22F; GUI.Label(r, type.Name, this.typeNameStyle); r.y += 18F; r.height = 15F; GUI.Label(r, type.Namespace, GeneralStyles.SmallLabel); r.y += 14F + NGStaticInspectorWindow.Spacing; if (r.y - this.scrollPositionTypes.y > this.bodyRect.height) { break; } } r.xMin -= 5F; } GUI.EndScrollView(); this.bodyRect.y = maxY; } bool doubleClickResize = false; if (this.showTypes == true) { float minHeight = GUI.skin.label.CalcHeight(Utility.content, this.bodyRect.width); // Handle splitter bar. this.bodyRect.height = NGStaticInspectorWindow.SplitterHeight; GUI.Box(this.bodyRect, ""); EditorGUIUtility.AddCursorRect(this.bodyRect, MouseCursor.ResizeVertical); if (this.draggingSplitterBar == true && Event.current.type == EventType.MouseDrag) { this.contentHeight = Mathf.Clamp(this.originContentHeight + this.originPositionY - Event.current.mousePosition.y, NGStaticInspectorWindow.MinContentHeight, this.position.height - NGStaticInspectorWindow.MaxContentHeightLeft); Event.current.Use(); } else if (Event.current.type == EventType.MouseDown && this.bodyRect.Contains(Event.current.mousePosition) == true) { this.originPositionY = Event.current.mousePosition.y; this.originContentHeight = this.contentHeight; this.draggingSplitterBar = true; Event.current.Use(); } else if (this.draggingSplitterBar == true && Event.current.type == EventType.MouseUp) { // Auto adjust height on left click or double click. if (this.bodyRect.Contains(Event.current.mousePosition) == true && (Event.current.button == 1 || (this.lastClickTime + Constants.DoubleClickTime > EditorApplication.timeSinceStartup && Mathf.Abs(this.originPositionY - Event.current.mousePosition.y) < 5F))) { // 7F of margin, dont know why it is required. CalcHeight seems to give bad result. this.contentHeight = Mathf.Clamp(minHeight + 7F, NGStaticInspectorWindow.MinContentHeight, this.position.height - NGStaticInspectorWindow.MaxContentHeightLeft); doubleClickResize = true; } this.lastClickTime = EditorApplication.timeSinceStartup; this.draggingSplitterBar = false; Event.current.Use(); } this.bodyRect.height = this.position.height - this.bodyRect.y; if (this.bodyRect.height > this.position.height - NGStaticInspectorWindow.MaxContentHeightLeft) { this.contentHeight = this.position.height - NGStaticInspectorWindow.MaxContentHeightLeft; } // Smoothly stay at the minimum if not critical under the critical threshold. if (this.contentHeight < NGStaticInspectorWindow.MinContentHeight) { this.contentHeight = NGStaticInspectorWindow.MinContentHeight; } this.bodyRect.y += NGStaticInspectorWindow.TitleSpacing; } if (this.selectedType != null) { Utility.content.text = this.selectedType.Name; this.bodyRect.height = GeneralStyles.Title1.CalcHeight(Utility.content, this.position.width); bool isPinned = false; Rect starRect = this.bodyRect; starRect.x = 5F; starRect.y += 3F; starRect.width = 12F; starRect.height = 14F; EditorGUIUtility.AddCursorRect(starRect, MouseCursor.Link); for (int i = 0; i < this.tabTypes.Count; i++) { if (NGStaticInspectorWindow.staticTypes[this.tabTypes[i]] == this.selectedType) { isPinned = true; break; } } if (Event.current.type == EventType.MouseDown && starRect.Contains(Event.current.mousePosition) == true) { if (isPinned == true) { for (int i = 0; i < this.tabTypes.Count; i++) { if (NGStaticInspectorWindow.staticTypes[this.tabTypes[i]] == this.selectedType) { this.tabTypes.RemoveAt(i); break; } } } else { for (int i = 0; i < NGStaticInspectorWindow.staticTypes.Length; i++) { if (NGStaticInspectorWindow.staticTypes[i] == this.selectedType) { this.tabTypes.Insert(0, i); break; } } } Event.current.Use(); return; } if (isPinned == true) { Color c = GUI.color; GUI.color = Color.yellow; GUI.DrawTexture(starRect, this.starIcon); GUI.color = c; } else { GUI.DrawTexture(starRect, this.starIcon); } this.bodyRect.xMin += 20F; if (string.IsNullOrEmpty(this.selectedType.Namespace) == false) { GUI.Label(this.bodyRect, this.selectedType.Name + " (" + this.selectedType.Namespace + ")", GeneralStyles.Title1); } else { GUI.Label(this.bodyRect, this.selectedType.Name, GeneralStyles.Title1); } this.bodyRect.xMin -= 20F; this.bodyRect.y += this.bodyRect.height + NGStaticInspectorWindow.TitleSpacing; MemberDrawer[] members = this.GetMembers(this.selectedType); viewRect.height = 0F; try { for (int i = 0; i < members.Length; i++) { try { if (members[i].exception != null) { viewRect.height += NGStaticInspectorWindow.Spacing + 16F; } else { viewRect.height += NGStaticInspectorWindow.Spacing + members[i].typeDrawer.GetHeight(members[i].fieldModifier.GetValue(null)); } } catch (Exception ex) { members[i].exception = ex; } } // Remove last spacing. if (viewRect.height > NGStaticInspectorWindow.Spacing) { viewRect.height -= NGStaticInspectorWindow.Spacing; } if (doubleClickResize == true) { this.contentHeight = Mathf.Clamp(viewRect.height + this.bodyRect.height + NGStaticInspectorWindow.TitleSpacing + NGStaticInspectorWindow.TitleSpacing, NGStaticInspectorWindow.MinContentHeight, this.position.height - NGStaticInspectorWindow.MaxContentHeightLeft); } this.bodyRect.height = this.position.height - this.bodyRect.y; this.scrollPositionMembers = GUI.BeginScrollView(this.bodyRect, this.scrollPositionMembers, viewRect); { r.width = this.position.width - (viewRect.height > this.bodyRect.height ? 16F : 0F) - 8F; r.y = 0F; ++EditorGUI.indentLevel; for (int i = 0; i < members.Length; i++) { if (members[i].exception != null) { r.height = 16F; using (ColorContentRestorer.Get(Color.red)) EditorGUI.LabelField(r, members[i].fieldModifier.Name, "Property raised an exception"); r.y += r.height + NGStaticInspectorWindow.Spacing; continue; } object instance = members[i].fieldModifier.GetValue(null); float height = members[i].typeDrawer.GetHeight(instance); if (r.y + height + NGStaticInspectorWindow.Spacing <= this.scrollPositionMembers.y) { r.y += height + NGStaticInspectorWindow.Spacing; continue; } r.height = height; if (Event.current.type == EventType.MouseDown && r.Contains(Event.current.mousePosition) == true && Event.current.button == 1) { NGStaticInspectorWindow.forceMemberEditable = members[i]; this.Repaint(); Utility.RegisterIntervalCallback(() => { NGStaticInspectorWindow.forceMemberEditable = null; }, NGStaticInspectorWindow.ForceMemberEditableTickDuration, 1); } EditorGUI.BeginDisabledGroup(!members[i].isEditable && NGStaticInspectorWindow.forceMemberEditable != members[i]); EditorGUI.BeginChangeCheck(); object value = members[i].typeDrawer.OnGUI(r, instance); if (EditorGUI.EndChangeCheck() == true) { if (members[i].isEditable == true) { members[i].fieldModifier.SetValue(null, value); } } EditorGUI.EndDisabledGroup(); r.y += height + NGStaticInspectorWindow.Spacing; if (r.y - this.scrollPositionMembers.y > this.bodyRect.height) { break; } } --EditorGUI.indentLevel; } GUI.EndScrollView(); } catch (Exception ex) { this.errorPopup.exception = ex; } } TooltipHelper.PostOnGUI(); }