protected virtual Type GetDrawerTypeForAssets([NotNull] Object[] assets, [CanBeNull] out Object[] assetImporters, [CanBeNull] out Type customEditorType) { assetImporters = null; customEditorType = null; // handle mismatching types if (!assets.AllSameType()) { return(typeof(MultipleAssetDrawer)); } if (AssetImporters.TryGet(assets, ref assetImporters)) { var assetImporterType = assetImporters[0].GetType(); if (!CustomEditorUtility.TryGetCustomEditorType(assetImporterType, out customEditorType)) { #if DEV_MODE Debug.LogWarning("GetDrawerTypeForAssets(" + assets[0].GetType().Name + ") Setting assetImporters of type " + assetImporterType.Name + " to null because could not find CustomEditor type for them."); #endif assetImporters = null; CustomEditorUtility.TryGetCustomEditorType(assets[0].GetType(), out customEditorType); } } else { CustomEditorUtility.TryGetCustomEditorType(assets[0].GetType(), out customEditorType); #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(assetImporters == null); #endif } return(GetDrawerTypeForAsset(assets[0])); }
protected virtual Type GetDrawerTypeForComponent([NotNull] Type componentType, out Type customEditorType) { Type drawerType; if (drawersFor.components.TryGetValue(componentType, out drawerType)) { customEditorType = null; return(drawerType); } #if UNITY_EDITOR if (Platform.EditorMode) { if (PluginCompatibilityUtility.UseCompatibilityModeForDisplayingTarget(componentType)) { customEditorType = null; return(typeof(CustomEditorComponentDrawer)); } if (CustomEditorUtility.TryGetCustomEditorType(componentType, out customEditorType)) { return(typeof(CustomEditorComponentDrawer)); } } #endif customEditorType = null; return(typeof(ComponentDrawer)); }
protected override void DrawImportedObjectGUI() { if (!isAssetImporter || assetEditor == null || assetEditor.GetType() == editor.GetType()) { return; } GUILayout.Space(9f); var headerRect = GUILayoutUtility.GetRect(new GUIContent("Imported Object"), "OL Title", GUILayout.Height(25f)); headerRect.x = -1f; headerRect.width = Screen.width + 2f; headerRect.height = 25f; GUI.Label(headerRect, "Imported Object", "OL Title"); bool editingTextFieldWas; EventType eventType; KeyCode keyCode; CustomEditorUtility.BeginEditor(out editingTextFieldWas, out eventType, out keyCode); { if (ReadOnly) { GUI.enabled = false; } assetEditor.OnInspectorGUI(); GUI.enabled = true; } CustomEditorUtility.EndEditor(editingTextFieldWas, eventType, keyCode); }
/// <inheritdoc/> public void SetupInterface(object attribute, object setValue, LinkedMemberInfo setMemberInfo, IParentDrawer setParent, GUIContent setLabel, bool setReadOnly) { #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(setValue != null || setMemberInfo != null); #endif Type propertyDrawerType; if (attribute != null) { if (!CustomEditorUtility.TryGetPropertyDrawerType(attribute.GetType(), out propertyDrawerType)) { #if DEV_MODE Debug.LogError("CustomEditorUtility.TryGetPropertyDrawerType returned null for attribute " + StringUtils.TypeToString(attribute)); #endif } #if DEV_MODE && DEBUG_ENABLED else { Debug.Log("Drawer type for attribute " + StringUtils.TypeToString(attribute) + ": " + StringUtils.ToString(propertyDrawerType)); } #endif } else { if (setMemberInfo == null || !CustomEditorUtility.TryGetPropertyDrawerType(setMemberInfo.Type, out propertyDrawerType)) { if (setValue == null || !CustomEditorUtility.TryGetPropertyDrawerType(setValue.GetType(), out propertyDrawerType)) { propertyDrawerType = null; #if DEV_MODE if (setValue == null) { Debug.LogError("PropertyDrawerGUI.SetupInterface called with attribute=" + StringUtils.Null + ", setValue=" + StringUtils.Null + " and setMemberInfo=" + StringUtils.Null); } else { Debug.LogError("PropertyDrawerGUI.SetupInterface - TryGetPropertyDrawerType returned " + StringUtils.Null + " for type " + StringUtils.ToString(DrawerUtility.GetType(setMemberInfo, setValue)) + " with attribute " + StringUtils.Null); } #endif } } } #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(propertyDrawerType != null); #endif Setup(setValue, attribute, null, propertyDrawerType, setMemberInfo, setParent, setLabel, setReadOnly); }
/// <inheritdoc/> public bool TryGetForDecoratorDrawer([NotNull] PropertyAttribute fieldAttribute, [NotNull] Type propertyAttributeType, [CanBeNull] IParentDrawer parent, [NotNull] LinkedMemberInfo attributeTarget, [CanBeNull] out IDecoratorDrawerDrawer result) { var drawerType = GetDrawerTypeForDecoratorDrawerAttribute(propertyAttributeType); if (drawerType != null) { #if DEV_MODE && (DEBUG_GET_FOR_FIELD || DEBUG_GET_FOR_DECORATOR_DRAWER) Debug.Log("<color=green>DecoratorDrawer drawer</color> for field " + attributeTarget.Name + " and attribute " + fieldAttribute.GetType().Name + ": " + drawerType.Name); #endif result = GetOrCreateInstance <IDecoratorDrawerDrawer>(drawerType); #if UNITY_EDITOR Type decoratorDrawerType; if (CustomEditorUtility.TryGetDecoratorDrawerType(propertyAttributeType, out decoratorDrawerType)) { result.SetupInterface(fieldAttribute, decoratorDrawerType, parent, attributeTarget); result.LateSetup(); return(true); } #endif if (!result.RequiresDecoratorDrawerType) { result.SetupInterface(fieldAttribute, null, parent, attributeTarget); result.LateSetup(); return(true); } #if DEV_MODE Debug.LogError(result.GetType().Name + " was returned for propertyAttribute " + propertyAttributeType.Name + " but drawer requires a decoratorDrawerType which was not found."); #endif } #if DEV_MODE && (DEBUG_GET_FOR_FIELD || DEBUG_GET_FOR_DECORATOR_DRAWER) Debug.Log("<color=green>DecoratorDrawer drawer</color> for field " + attributeTarget.Name + " and attribute " + fieldAttribute.GetType().Name + ": " + StringUtils.Null); #endif result = null; return(false); }
/// <inheritdoc cref="IDrawer.Draw" /> public override bool Draw(Rect position) { #if SAFE_MODE || DEV_MODE var targets = memberInfo.UnityObjects; int targetCount = targets.Length; if (targetCount == 0) { #if DEV_MODE Debug.LogWarning(ToString() + ".Draw() - target count was zero, rebuilding drawer"); #endif InspectorUtility.ActiveInspector.RebuildDrawersIfTargetsChanged(); return(false); } if (targets.ContainsNullObjects()) { #if DEV_MODE Debug.LogWarning(ToString() + ".Draw() - target was null, rebuilding drawer"); #endif InspectorUtility.ActiveInspector.RebuildDrawersIfTargetsChanged(); return(false); } #endif var positionWithoutMargins = position; bool dirty = false; GenerateControlId(); if (Event.current.type == EventType.Layout) { OnLayoutEvent(position); } #if !DRAW_LABEL_RESIZE_CONTROL DrawGUI.Active.ColorRect(position, DrawGUI.Active.InspectorBackgroundColor); #endif position.height -= 2f; position.y += 1f; position.width -= DrawGUI.RightPadding; float labelWidthWas = EditorGUIUtility.labelWidth; float fieldWidthWas = EditorGUIUtility.fieldWidth; float leftPadding = DrawGUI.LeftPadding; int labelRightPadding = (int)(DrawGUI.MiddlePadding + DrawGUI.MiddlePadding); position.x += leftPadding; position.width -= leftPadding; //always use wide mode for properties because it works better with the prefix width control #if ALWAYS_USE_WIDEMODE bool wideModeWas = EditorGUIUtility.wideMode; EditorGUIUtility.wideMode = true; #endif EditorStyles.label.padding.right = labelRightPadding; GUILayout.BeginArea(positionWithoutMargins); { position.y -= positionWithoutMargins.y; position.x -= positionWithoutMargins.x; EditorGUI.BeginChangeCheck(); { DrawerUtility.BeginInputField(this, controlId, ref editField, ref focusField, memberInfo == null ? false : memberInfo.MixedContent); { var serializedProperty = SerializedProperty; if (serializedProperty == null) { // NOTE: This can happen during Remove Component for some reason #if DEV_MODE Debug.LogError(ToString() + ".Draw - SerializedProperty was null (parent=" + StringUtils.ToString(parent) + ") so can't use EditorGUI.PropertyField"); #endif EditorGUI.PrefixLabel(position, label); } else { bool editingTextFieldWas; EventType eventType; KeyCode keyCode; CustomEditorUtility.BeginPropertyDrawer(out editingTextFieldWas, out eventType, out keyCode); { // fix needed or foldouts will be drawn at incorrect positions var leftMarginWas = EditorStyles.foldout.margin.left; EditorStyles.foldout.margin.left = -12; try { EditorGUI.PropertyField(position, serializedProperty, label, serializedProperty.isExpanded); } catch (Exception e) { if (ExitGUIUtility.ShouldRethrowException(e)) { EditorStyles.foldout.margin.left = leftMarginWas; throw; } #if DEV_MODE Debug.LogWarning(ToString() + " " + e); #endif } EditorStyles.foldout.margin.left = leftMarginWas; } CustomEditorUtility.EndPropertyDrawer(editingTextFieldWas, eventType, keyCode); bool editingTextFieldIs = EditorGUIUtility.editingTextField; if (editingTextFieldIs != editingTextFieldWas) { DrawGUI.EditingTextField = editingTextFieldIs; } } } DrawerUtility.EndInputField(); } if (EditorGUI.EndChangeCheck()) { GUI.changed = true; SerializedProperty.serializedObject.ApplyModifiedProperties(); dirty = true; } } GUILayout.EndArea(); #if ALWAYS_USE_WIDEMODE EditorGUIUtility.wideMode = wideModeWas; #endif EditorStyles.label.padding.right = 2; EditorGUIUtility.labelWidth = labelWidthWas; EditorGUIUtility.fieldWidth = fieldWidthWas; return(dirty); }
/// <summary> Sets up an instance of the drawers for usage. </summary> /// <param name="setTargets"> The targets that the drawers represent. Can not be null. </param> /// <param name="setEditorTargets"> The targets for which the main Editor is created. E.g. the asset importers for targets. Can be null. </param> /// <param name="setParent"> The parent drawers of the created drawers. Can be null. </param> /// <param name="setInspector"> The inspector in which the IDrawer are contained. Can not be null. </param> /// <param name="setEditorType"> The type of the custom editor. Can be null. </param> protected virtual void Setup([NotNull] Object[] setTargets, [CanBeNull] Object[] setEditorTargets, [CanBeNull] Type setEditorType, [CanBeNull] IParentDrawer setParent, [NotNull] IInspector setInspector) { #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(setTargets.Length > 0); #endif headerHeight = DrawGUI.Active.AssetTitlebarHeight(false); headerHeightDetermined = false; allSameType = setTargets.AllSameType(); if (setEditorTargets == null) { if (!allSameType) { setEditorTargets = setTargets; } else { if (AssetImporters.TryGet(setTargets, ref setEditorTargets)) { var assetImporterType = setEditorTargets[0].GetType(); CustomEditorUtility.TryGetCustomEditorType(assetImporterType, out setEditorType); } else { setEditorTargets = setTargets; } } } else if (setEditorTargets[0] == null) { ArrayPool <Object> .Dispose(ref setEditorTargets); setEditorTargets = setTargets; } #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(setEditorTargets != null || !allSameType); Debug.Assert(!allSameType || setEditorTargets.Length > 0); #endif editorTargets = setEditorTargets; Sisus.AssetLabels.Get(setTargets, ref assetLabels, ref assetLabelsOnlyOnSomeTargets); Sisus.AssetLabels.OnAssetLabelsChanged += OnAssetLabelsChanged; var target = setTargets[0]; localPath = setTargets.Length == 1 ? AssetDatabase.GetAssetPath(target) : ""; isPackageAsset = FileUtility.IsPackageAsset(localPath); // base handles calling UpdateEditor base.Setup(setTargets, setParent, setInspector, setEditorType); FetchAssetEditor(); #if DEV_MODE && PI_ASSERTATIONS && UNITY_2017_2_OR_NEWER if (!isAssetImporter && editor != HeaderEditor) { #if DEV_MODE && DEBUG_SETUP_EDITOR Debug.LogError(Msg(ToString(), " non-asset importer editor did not match HeaderEditor! - targets=", StringUtils.TypesToString(setTargets), ", editorTargets=", StringUtils.TypesToString(setEditorTargets), ", editorType=", setEditorType, ", editor=", StringUtils.TypeToString(editor), ", HeaderEditor=", HeaderEditor)); #endif } #endif #if DEV_MODE && DEBUG_SETUP_EDITOR Debug.Log(Msg(ToString(), " Setup with targets=", StringUtils.TypesToString(setTargets), ", editorTargets=", StringUtils.TypesToString(setEditorTargets), ", editorType=", setEditorType, ", editor=", StringUtils.TypeToString(editor))); #endif #if DEV_MODE && PI_ASSERTATIONS if (editor == null) { Debug.LogWarning(Msg(ToString(), " editor was null after Setup with canHaveEditor=", canHaveEditor, " and targets: ", StringUtils.TypesToString(targets))); } #endif #if DEV_MODE && PI_ASSERTATIONS if (assetEditor == null) { Debug.LogWarning(Msg(ToString(), " headerEditor was null after Setup with canHaveEditor=", canHaveEditor, " and targets: ", StringUtils.TypesToString(targets))); } #endif }
/// <inheritdoc cref="GetEditor(ref Editor, Object[], Type, bool, Object, bool)"/> public void GetEditorInternal(ref Editor editor, [NotNull] Object[] targets, [CanBeNull] Type editorType, bool allTargetsHaveSameType, Object context = null, bool cache = true) { #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(targets != null); Debug.Assert(!targets.ContainsNullObjects(), "Editors.GetEditorInternal called with tagets containing null Objects"); Debug.Assert(allTargetsHaveSameType == targets.AllSameType()); Debug.Assert(targets.Length > 0, "GetEditor called with empty targets array! editorType was " + (editorType == null ? "null" : editorType.Name)); #endif if (editor != null) { #if !NET_STANDARD_2_0 var previousEditorTargets = getTargets(editor); var previousEditorContext = getContext(editor); #else var previousEditorTargets = getTargets.GetValue(editor) as Object[]; var previousEditorContext = getContext.GetValue(editor) as Object; #endif if (targets.ContentsMatch(previousEditorTargets) && context == previousEditorContext) { return; } DisposeInternal(ref editor); } if (!allTargetsHaveSameType) { GetEditor(ref editor, targets[0], editorType, context, cache); return; } #if UNITY_2017_2_OR_NEWER bool isAssetImporterEditor = editorType != null?Types.AssetImporterEditor.IsAssignableFrom(editorType) : typeof(AssetImporter).IsAssignableFrom(targets[0].GetType()); //editorType != null && Types.AssetImporterEditor.IsAssignableFrom(editorType); var editorKey = new EditorKey(targets, isAssetImporterEditor); #else var editorKey = new EditorKey(targets, false); #endif if (cachedEditors.TryGetValue(editorKey, out editor)) { if (editor != null) { if (!DisposeIfInvalid(ref editor)) { OnBecameActive(editor); #if DEV_MODE && DEBUG_GET_EDITOR Debug.Log("Editors.GetEditor: for targets " + StringUtils.TypesToString(targets) + " and editorType " + StringUtils.ToString(editorType) + " returning cached: " + editor.GetType().Name + " with key=" + editorKey.GetHashCode()); #endif return; } #if DEV_MODE && DEBUG_DESTROYED_CACHED_EDITORS Debug.LogWarning("cachedEditors for targets " + StringUtils.TypeToString(targets) + " and editorType " + StringUtils.ToString(editorType) + " with EditorKey hashCode " + editorKey.GetHashCode() + " contained editor with null targets!\nCachedEditors:\n" + StringUtils.ToString(cachedEditors, "\n")); #endif } #if DEV_MODE && DEBUG_DESTROYED_CACHED_EDITORS else { Debug.LogWarning("cachedEditors for targets " + StringUtils.TypesToString(targets) + " and editorType " + StringUtils.ToString(editorType) + " with EditorKey hashCode " + editorKey.GetHashCode() + " contained a null value!\nCachedEditors:\n" + StringUtils.ToString(cachedEditors, "\n")); } #endif } #if DEV_MODE && DEBUG_GET_EDITOR Debug.Log(StringUtils.ToColorizedString("Editors.GetEditor called for ", StringUtils.ToString(targets), " with editorType=", editorType, ", context=", context, ", key=", editorKey.GetHashCode(), ", cache=", cache)); #endif #if SUPPORT_EDITORS_FOR_INTERFACES if (editorType == null) { var interfaces = targets[0].GetType().GetInterfaces(); for (int n = interfaces.Length - 1; n >= 0; n--) { Type editorForInterface; if (CustomEditorUtility.TryGetCustomEditorType(interfaces[n], out editorForInterface)) { editorType = editorForInterface; #if DEV_MODE Debug.Log("Editors.GetEditor : Replaced null editorType with interface based type " + StringUtils.ToString(editorType)); #endif } } } #endif try { editor = Editor.CreateEditorWithContext(targets, context, editorType); } #if DEV_MODE catch (Exception e) { Debug.LogError("Editor.CreateEditor for targets " + StringUtils.TypesToString(targets) + " and editorType " + StringUtils.ToString(editorType) + ": " + e); #else catch { #endif return; } if (editor == null) { #if DEV_MODE Debug.LogWarning("Editor.CreateEditor for targets " + StringUtils.TypesToString(targets) + " and editorType " + StringUtils.ToString(editorType) + " returned null!"); #endif return; } #if DEV_MODE && DEBUG_GET_EDITOR Debug.Log("Editors.GetEditor: Created new: " + editor.GetType().Name + " for " + StringUtils.ToString(targets) + " with key=" + editorKey.GetHashCode() + ", cache=" + StringUtils.ToColorizedString(cache)); #endif if (cache) { cachedEditors[editorKey] = editor; } }