internal InspectorElement(Editor editor, Mode mode) { AddToClassList(ussClassName); this.mode = mode; this.editor = editor; if (editor.targets.Length == 0) { return; } var targetObject = editor.targets[0]; if (targetObject == null) { if (!GenericInspector.ObjectIsMonoBehaviourOrScriptableObject(targetObject)) { return; } } this.Bind(editor.serializedObject); }
private VisualElement CreateInspectorElementFromEditor(Editor editor, bool reuseIMGUIContainer = false) { var serializedObject = editor.serializedObject; var target = editor.targets[0]; if (target == null) { if (!GenericInspector.ObjectIsMonoBehaviourOrScriptableObject(target)) { return(null); } } VisualElement inspectorElement = null; if ((mode & Mode.UIECustom) > 0) { inspectorElement = editor.CreateInspectorGUI(); if (inspectorElement != null) { AddToClassList(uIECustomVariantUssClassName); if (editor.UseDefaultMargins()) { AddToClassList(uIEInspectorVariantUssClassName); } inspectorElement.AddToClassList(customInspectorUssClassName); } } if (inspectorElement == null) { inspectorElement = CreateIMGUIInspectorFromEditor(serializedObject, editor, reuseIMGUIContainer); } if (inspectorElement == null && (mode & Mode.UIEDefault) > 0) { inspectorElement = CreateDefaultInspector(serializedObject); } if (inspectorElement == null) { AddToClassList(noInspectorFoundVariantUssClassName); AddToClassList(uIEInspectorVariantUssClassName); inspectorElement = new Label("No inspector found given the current Inspector.Mode."); } return(inspectorElement); }
internal InspectorElement(SerializedObject obj, Mode mode) { AddToClassList(ussClassName); this.mode = mode; if (obj.targetObject == null) { if (!GenericInspector.ObjectIsMonoBehaviourOrScriptableObject(obj.targetObject)) { return; } } this.Bind(obj); }
internal InspectorElement(Object obj, Mode mode) { m_IgnoreOnInspectorGUIErrors = false; AddToClassList(ussClassName); this.mode = mode; if (obj == null) { if (!GenericInspector.ObjectIsMonoBehaviourOrScriptableObject(obj)) { return; } } this.Bind(new SerializedObject(obj)); }
private VisualElement CreateIMGUIInspectorFromEditor(SerializedObject serializedObject, Editor editor, bool reuseIMGUIContainer) { if ((mode & (Mode.IMGUICustom | Mode.IMGUIDefault)) == 0) { return(null); } if ((mode & Mode.IMGUICustom) > 0 && (mode & Mode.IMGUIDefault) == 0 && editor is GenericInspector) { return(null); } if ((mode & Mode.IMGUICustom) == 0 && (mode & Mode.IMGUIDefault) > 0 && !(editor is GenericInspector)) { editor = ScriptableObject.CreateInstance <GenericInspector>(); editor.hideFlags = HideFlags.HideAndDontSave; editor.InternalSetTargets(new[] { serializedObject.targetObject }); } if (editor is GenericInspector) { AddToClassList(iMGUIDefaultVariantUssClassName); if ((mode & Mode.DebugMod) > 0) { AddToClassList(debugVariantUssClassName); editor.inspectorMode = InspectorMode.Debug; } else if ((mode & Mode.DebugInternalMod) > 0) { AddToClassList(debugInternalVariantUssClassName); editor.inspectorMode = InspectorMode.DebugInternal; } } else { AddToClassList(iMGUICustomVariantUssClassName); } IMGUIContainer inspector; // Reusing the existing IMGUIContainer allows us to re-use the existing gui state, when we are drawing the same inspector this will let us keep the same control ids if (reuseIMGUIContainer && m_IMGUIContainer != null) { inspector = m_IMGUIContainer; } else { inspector = new IMGUIContainer(); } m_IgnoreOnInspectorGUIErrors = false; inspector.onGUIHandler = () => { // It's possible to run 2-3 frames after the tracker of this inspector window has // been recreated, and with it the Editor and its SerializedObject. One example of // when this happens is when the Preview window is detached from a *second* instance // of an InspectorWindow and re-attached. // // This is only a problem for the *second* (or third, forth, etc) instance of // the InspectorWindow because only the first instance can use the // ActiveEditorTracker.sharedTracker in InspectorWindow.CreateTracker(). The // other instances have to create a new tracker...each time. // // Not an ideal solution, but basically we temporarily hold the printing to console // for errors for which GUIUtility.ShouldRethrowException(e) returns false. // The errors that may occur during this brief "bad state" are SerializedProperty // errors. If the custom Editor created and remembered references to some // SerializedProperties during its OnEnable(), those references will be invalid // when the tracker is refreshed, until this GUIHandler is reassigned. This fix // just ignores those errors. // // We don't simply early return here because that can break some tests that // rely heavily on yields and timing of UI redraws. Yes.. // // case 1119612 if (editor.m_SerializedObject == null) { editor.Repaint(); m_IgnoreOnInspectorGUIErrors = true; } if ((editor.target == null && !GenericInspector.ObjectIsMonoBehaviourOrScriptableObject(editor.target)) || !editor.serializedObject.isValid) { return; } EditorGUIUtility.ResetGUIState(); using (new EditorGUI.DisabledScope(!editor.IsEnabled())) { var genericEditor = editor as GenericInspector; if (genericEditor != null) { switch (mode) { case Mode.Normal: genericEditor.inspectorMode = InspectorMode.Normal; break; case Mode.Default: genericEditor.inspectorMode = InspectorMode.Debug; break; case Mode.Custom: genericEditor.inspectorMode = InspectorMode.DebugInternal; break; case Mode.IMGUI: break; } } //set the current PropertyHandlerCache to the current editor ScriptAttributeUtility.propertyHandlerCache = editor.propertyHandlerCache; var originalHierarchyMode = EditorGUIUtility.hierarchyMode; EditorGUIUtility.hierarchyMode = true; var originalWideMode = SetWideModeForWidth(inspector); GUIStyle editorWrapper = (editor.UseDefaultMargins() ? EditorStyles.inspectorDefaultMargins : GUIStyle.none); try { GUI.changed = false; using (new InspectorWindowUtils.LayoutGroupChecker()) { EditorGUILayout.BeginVertical(editorWrapper); { // we have no guarantees regarding what happens in the try/catch block below, // so we need to save state here and restore it afterwards, // the natural thing to do would be using SavedGUIState, // but it implicitly resets keyboards bindings and it breaks functionality. // We have identified issues with layout so we just save that for the time being. var layoutCache = new GUILayoutUtility.LayoutCache(GUILayoutUtility.current); try { var rebuildOptimizedGUIBlocks = GetRebuildOptimizedGUIBlocks(editor.target); rebuildOptimizedGUIBlocks |= editor.isInspectorDirty; float height; if (editor.GetOptimizedGUIBlock(rebuildOptimizedGUIBlocks, visible, out height)) { var contentRect = GUILayoutUtility.GetRect(0, visible ? height : 0); // Layout events are ignored in the optimized code path // The exception is when we are drawing a GenericInspector, they always use the optimized path and must therefore run at least one layout calculation in it if (Event.current.type == EventType.Layout && !(editor is GenericInspector)) { return; } InspectorWindowUtils.DrawAddedComponentBackground(contentRect, editor.targets); // Draw content if (visible) { GUI.changed = false; editor.OnOptimizedInspectorGUI(contentRect); } } else { InspectorWindowUtils.DrawAddedComponentBackground(contentRect, editor.targets); editor.OnInspectorGUI(); } } catch (Exception e) { if (GUIUtility.ShouldRethrowException(e)) { throw; } if (!m_IgnoreOnInspectorGUIErrors) { Debug.LogException(e); } } finally { GUILayoutUtility.current = layoutCache; } } EditorGUILayout.EndVertical(); } } finally { if (GUI.changed) { // This forces a relayout of all imguicontainers in this inspector window. // fixes part of case 1148706 var element = inspector.GetFirstAncestorOfType <EditorElement>(); if (element != null) { EditorElement.InvalidateIMGUILayouts(element.parent); } } EditorGUIUtility.wideMode = originalWideMode; EditorGUIUtility.hierarchyMode = originalHierarchyMode; } } }; inspector.style.overflow = Overflow.Visible; m_IMGUIContainer = inspector; if (!(editor is GenericInspector)) { inspector.AddToClassList(customInspectorUssClassName); } inspector.AddToClassList(iMGUIContainerUssClassName); AddToClassList(iMGUIInspectorVariantUssClassName); return(inspector); }