How to Have a ReoderableList in a Custom Editor Window
I've made two scripts, a custom editor window and a script containing a reoderable list, but I can't put the list in the editor. The problem comes from the fact that the list script inherits from Editor, but the window script inherits from EditorWindow. How would I combine these?
ReoderableList Script:
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(LevelData))]
public class LevelDataEditor : Editor {
private ReorderableList list;
private void OnEnable() {
list = new ReorderableList(serializedObject,
serializedObject.FindProperty("Waves"),
true, true, true, true);
list.drawElementCallback =
(Rect rect, int index, bool isActive, bool isFocused) => {
var element = list.serializedProperty.GetArrayElementAtIndex(index);
rect.y += 2;
EditorGUI.PropertyField(
new Rect(rect.x, rect.y, 60, EditorGUIUtility.singleLineHeight),
element.FindPropertyRelative("Type"), GUIContent.none);
EditorGUI.PropertyField(
new Rect(rect.x + 60, rect.y, rect.width - 60 - 30, EditorGUIUtility.singleLineHeight),
element.FindPropertyRelative("Prefab"), GUIContent.none);
EditorGUI.PropertyField(
new Rect(rect.x + rect.width - 30, rect.y, 30, EditorGUIUtility.singleLineHeight),
element.FindPropertyRelative("Count"), GUIContent.none);
};
list.drawHeaderCallback = (Rect rect) => {
EditorGUI.LabelField(rect, "Monster Waves");
list.onCanRemoveCallback = (ReorderableList l) => {
return l.count > 1;
};
list.onRemoveCallback = (ReorderableList l) => {
if (EditorUtility.DisplayDialog("Warning!",
"Are you sure you want to delete the wave?", "Yes", "No")) {
ReorderableList.defaultBehaviours.DoRemoveButton(l);
}
};
};
}
public override void OnInspectorGUI() {
serializedObject.Update();
list.DoLayoutList();
serializedObject.ApplyModifiedProperties();
}
}
EditorWindow Script:
using UnityEditor;
using UnityEngine;
using UnityEditorInternal;
public class PathCreator : EditorWindow
{
float ScaleX;
float ScaleY;
float OriginX;
float OriginY;
float smoothingScale = 1f;
bool boundFoldout;
bool active;
bool smoothing;
float spacing;
Object m_MainCamera;
Object subject;
private ReorderableList list;
//Location of the editor
[MenuItem("Window/Path Creator")]
public static void ShowWindow ()
{
GetWindow<PathCreator>("Path Creator");
}
void OnGUI ()
{
//Create ReoderableList
list = new ReorderableList(serializedObject, serializedObject.FindProperty("Waves"), true, true, true, true);
EditorGUI.indentLevel++;
GUILayout.Label("Custom Camera Path", EditorStyles.boldLabel);
//Active checkbox
active = EditorGUI.Toggle(new Rect(3, 20, position.width, 20), "Active", active);
//Check if active is true
if(active)
{
smoothing = EditorGUI.Toggle(new Rect(3, 40, position.width, 20), "Edge Smoothing", smoothing);
if (smoothing)
{
EditorGUI.indentLevel++;
//Create smoothing slider
smoothingScale = EditorGUI.Slider(new Rect(5, 70, 300, 20), "Smoothing", smoothingScale, 1, 100);
spacing = 80f;
EditorGUI.indentLevel--;
}
else
{
spacing = 45f;
}
//Space accordingly
EditorGUILayout.Space(spacing);
//Create an empty field for Main Camera and Subject
m_MainCamera = EditorGUILayout.ObjectField("Main Camera", m_MainCamera, typeof(Camera), true);
subject = EditorGUILayout.ObjectField("Subject", subject, typeof(GameObject), true);
//Create bounds foldout
boundFoldout = EditorGUILayout.Foldout(boundFoldout,"Bounds");
//Check if the bounds are folded
if (boundFoldout)
{
EditorGUI.indentLevel++;
ScaleX = EditorGUILayout.FloatField("Scale X", ScaleX);
ScaleY = EditorGUILayout.FloatField("Scale Y", ScaleY);
OriginX = EditorGUILayout.FloatField("Origin X", OriginX);
OriginY = EditorGUILayout.FloatField("Origin Y", OriginY);
EditorGUI.indentLevel--;
}
}
}
}
Thanks <3
Answer by Mehrdad995 · Jun 01 at 12:55 PM
In order to have a built-in reorderable list using EditorWindow, just the same as the Editor you'll need a separate class to hold the data, however, this class can be derived from the ScriptableObject class instead of MonoBehaviour so you don't need to always have a GameObject in your scene carrying the script. Meanwhile, you can also have the class right inside the script you have your EditorWindow in.
Here is a very simple example of how it can be done:
MyEditorWindow.cs
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
public class MyScriptableObject : ScriptableObject
{
public List<string> strings = new List<string>();
}
public class MyEditorWindow : EditorWindow
{
ReorderableList strings_ro_list;
SerializedObject serializedObject;
SerializedProperty stringsProperty;
[MenuItem("Tools/Test Editor Window")]
public static void ShowWindow()
{
GetWindow<MyEditorWindow>("Test Editor");
}
private void OnEnable()
{
MyScriptableObject obj = ScriptableObject.CreateInstance<MyScriptableObject >();
serializedObject = new UnityEditor.SerializedObject(obj);
stringsProperty= serializedObject.FindProperty("strings");
strings_ro_list = new ReorderableList(serializedObject, stringsProperty, true, true, true, true);
strings_ro_list.drawElementCallback = StringsDrawListItems;
strings_ro_list.drawHeaderCallback = StringsDrawHeader;
}
private void OnGUI()
{
if (this.serializedObject == null)
{
return;
}
serializedObject.Update();
strings_ro_list .DoLayoutList();
serializedObject.ApplyModifiedProperties();
}
void StringsDrawListItems(Rect rect, int index, bool isActive, bool isFocused)
{
// your GUI code here for list content
}
void StringsDrawHeader(Rect rect)
{
// your GUI code here for list header
}
}
Your answer
Follow this Question
Related Questions
GUI.Window. Wanting to allow clickthrough 0 Answers
How to change the text of EditorGUILayout.TextField 2 Answers
My EditorWindow won't display properly, even when commented out. 0 Answers
Do Unity Editor GUI Utilities (Handles.DrawLine & EditorGUI.DrawRect) have limitations? 2 Answers
Editor Window 1 Answer