- Home /
Custom editor renders attributes that overlap properties
I have a custom editor explicitly manipulates Rect
s and calls EditorGUI
instead of EditorGUILayout
. This mostly works fine except for fields with Header
attributes, where it seems like too many things are being rendered into the same rect (i.e. the header overlaps the property). How can I explicitly pull out the Header
and render it separately, or ask EditorGUI
to hand me a Rect
that's resized to hold the Header
?
Example attempt to reimplement the default editor:
using UnityEditor;
using UnityEngine;
using System;
using System.Collections;
[CustomEditor(typeof(ScriptableObject), true)]
[CanEditMultipleObjects]
public class CustomEditorBase : Editor {
protected virtual void RenderProperty(Rect position, SerializedProperty property) {
EditorGUI.PropertyField(position, property); // if the property has a header attribute, this renders them overlapping
}
protected void RenderChildren(SerializedProperty property, SerializedProperty end) {
if (!property.NextVisible(true)) {
property = null;
}
while (!SerializedProperty.EqualContents(property, end)) {
RenderProperty(EditorGUILayout.GetControlRect(), property);
var nextSibling = property.Copy();
bool hasNext = nextSibling.NextVisible(false);
if (!hasNext) {
nextSibling = null;
}
if (property.isExpanded) {
EditorGUI.indentLevel++;
RenderChildren(property, nextSibling);
EditorGUI.indentLevel--;
}
property = nextSibling;
}
}
void RenderObject(SerializedObject obj) {
RenderChildren(obj.GetIterator(), null);
}
public override void OnInspectorGUI() {
serializedObject.Update();
RenderObject(serializedObject);
serializedObject.ApplyModifiedProperties();
}
}
Way too unspecific question. You have to give more details about your editor and show the relevant code. A "normal" custom editor uses the layoutsystem while the built-in inspector mainly uses fixed sized gui elements. That's what a PropertyDrawer / DecoratorDrawer are ment for. If a field has an Header attribute the header is not drawn automatically if you create a custom editor unless you use PropertyField.
Right, I am using PropertyField
, but something like EditorGUI.PropertyField(EditorGUILayout.GetControlRect(), property)
renders the header in a way that overlaps the property, which is surprising. How can I either manually render the header separately, or automatically get a rect
that is sized to incorporate the property and the header?
updated the question to be clearer
Answer by Bunny83 · Nov 16, 2017 at 02:55 AM
I don't quite get why you use the EditorGUI version of PropertyField instead of the EditorGUILayout version?.
Anyways, if you use EditorGUILayout.GetControlRect you have to specify the desired height. As you can read in the documentation if you don't specify the height it uses EditorGUIUtility.singleLineHeight which is simply a constant value of 16 pixels. This doesn't make much sense when using a PropertyField.
If you really want to keep using EditorGUI instead of EditorGUILayout you would have to use EditorGUI.GetPropertyHeight to get the required height for a given property. This height has to be passed to the GetControlRect method.
ps: Why do you create a copy of the iterator every iteration? The normal usage of an iterator is to just call Next / NextVisible and reuse the iterator. You should create a copy when you do a recursion since you need the current iterator in the current state when you want to continue this iteration. You somehow have inverted this logic. You create a new iterator every iteration but keep the current when doing a recursive call.
pps: You are aware of the existence of PropertyDrawers and DecoratorDrawers? Your custom inspector doesn't seem to do anything useful. Btw: the "Header" attribute is actually a DecoratorDrawer.
Perfect, thanks for your help!
This is a stripped down editor that just mirrors the default one. RenderProperty
is virtual so subclasses can do more interesting things, e.g. render ScriptableObject
s inline or turn lists into ReorderableList
s. Recursively rendering ScriptableObject
s inside ReorderableList
s using the the default layout manager doesn't seem to work as expected - the objects get rendered under the list ins$$anonymous$$d of inside it.
I haven't found a way to use PropertyDrawer
to recursively render in ScriptableObject
s, because I render them using OnInspectorGUI
, which causes the PropertyDrawer
to complain about layout events.
But i still don't get why your "RenderProperty" takes a Rect. This just introduces the same limitation as PropertyDrawers have with the addition that you can't actually define the rect size. Propertydrawers can override the GetPropertyHeight method in order to communicate how much space it needs. In your case you dictate from outside how much space the property gets. Again, why don't use just use the GUILayout version and just remove the Rect parameter?
Your answer
Follow this Question
Related Questions
Null reference exceptions when using a Custom Editor 0 Answers
Responsive Editor UI Button with custom style | How to remove GUIStyle.hover delay 0 Answers
How can i get SerializedProperty from UnityEvent which in List. Sorry for my Eng. 2 Answers
Custom Window with Hierarchy 1 Answer
Questions Regarding Images in Custom Inspector/Editor 1 Answer