-
-
Save der-hugo/4f676ede0d4a43bc187690ec3269cd9b to your computer and use it in GitHub Desktop.
public abstract class ObservedList { } | |
[Serializable] | |
public class ObservedList<T> : ObservedList, IList<T> | |
{ | |
public delegate void ChangedDelegate(int index, T oldValue, T newValue); | |
// In a bit of a dirty hack the editor scripts is looking for this field | |
// with exactly this name "_list" | |
[SerializeField] private List<T> _list = new List<T>(); | |
// NOTE: I changed the signature to provide a bit more information | |
// now it returns index, oldValue, newValue | |
public event ChangedDelegate Changed; | |
public event Action Updated; | |
public IEnumerator<T> GetEnumerator() | |
{ | |
return _list.GetEnumerator(); | |
} | |
IEnumerator IEnumerable.GetEnumerator() | |
{ | |
return GetEnumerator(); | |
} | |
public void Add(T item) | |
{ | |
_list.Add(item); | |
Updated?.Invoke(); | |
} | |
public void Clear() | |
{ | |
_list.Clear(); | |
Updated?.Invoke(); | |
} | |
public bool Contains(T item) | |
{ | |
return _list.Contains(item); | |
} | |
public void CopyTo(T[] array, int arrayIndex) | |
{ | |
_list.CopyTo(array, arrayIndex); | |
} | |
public bool Remove(T item) | |
{ | |
var output = _list.Remove(item); | |
Updated?.Invoke(); | |
return output; | |
} | |
public int Count => _list.Count; | |
public bool IsReadOnly => false; | |
public int IndexOf(T item) | |
{ | |
return _list.IndexOf(item); | |
} | |
public void InsertRange(int index, IEnumerable<T> collection) | |
{ | |
_list.InsertRange(index, collection); | |
Updated?.Invoke(); | |
} | |
public void AddRange(IEnumerable<T> collection) | |
{ | |
_list.AddRange(collection); | |
Updated?.Invoke(); | |
} | |
public void RemoveAll(Predicate<T> predicate) | |
{ | |
_list.RemoveAll(predicate); | |
Updated?.Invoke(); | |
} | |
public void RemoveRange(int index, int count) | |
{ | |
_list.RemoveRange(index, count); | |
Updated?.Invoke(); | |
} | |
public void Insert(int index, T item) | |
{ | |
_list.Insert(index, item); | |
Updated?.Invoke(); | |
} | |
public void RemoveAt(int index) | |
{ | |
_list.RemoveAt(index); | |
Updated?.Invoke(); | |
} | |
public T this[int index] | |
{ | |
get { return _list[index]; } | |
set | |
{ | |
var oldValue = _list[index]; | |
_list[index] = value; | |
Changed?.Invoke(index, oldValue, value); | |
// I would also call the generic one here | |
Updated?.Invoke(); | |
} | |
} | |
} |
[CustomPropertyDrawer(typeof(ObservedList), true)] | |
public class ObservedListDrawer : PropertyDrawer | |
{ | |
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) | |
{ | |
var list = property.FindPropertyRelative("_list"); | |
EditorGUI.PropertyField(position, list, label, true); | |
} | |
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) | |
{ | |
var list = property.FindPropertyRelative("_list"); | |
return EditorGUI.GetPropertyHeight(list, label, true); | |
} | |
} |
I get an error in unity 2022: NullReferenceException: Object reference not set to an instance of an object UnityEditor.PropertyHandler.GetHeight (UnityEditor.SerializedProperty property, UnityEngine.GUIContent label, System.Boolean includeChildren) (at <7d481861b3d34328a9633ade22dcedd6>:0)
I think the hack "_list" return null: var list = property.FindPropertyRelative("_list");
Where shoud I search to find the new way to get the "list" name ?
Hey there, tbh I don't remember why I did this here ^^
The issue here is that the custom editor is only for the base type ObservableList
which doesn't have any serialized property called _list
(which btw is not a hack but the normal way of accessing those) - only the generic implementation ObservableList<T>
has this.
As said I don't really remember and not sure if serialization / editor rules maybe changed since then.
Though I just tested and imported both into Unity 2021.3.8f1 (Latest LTS) and it works exactly as expected .. maybe stick to the LTS until the pre-release sorts out its bugs ;)
I get an error in unity 2022:
NullReferenceException: Object reference not set to an instance of an object
UnityEditor.PropertyHandler.GetHeight (UnityEditor.SerializedProperty property, UnityEngine.GUIContent label, System.Boolean includeChildren) (at <7d481861b3d34328a9633ade22dcedd6>:0)
I think the hack "_list" return null:
var list = property.FindPropertyRelative("_list");
Where shoud I search to find the new way to get the "list" name ?