Last active
May 10, 2024 01:59
-
-
Save mikerochip/ae80449a463433c9fafab87fba8d57eb to your computer and use it in GitHub Desktop.
Unity SerializedProperty extensions and utilities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using UnityEditor; | |
namespace MikeSchweitzer | |
{ | |
public static class SerializedPropertyExtensions | |
{ | |
public static T[] GetAllValues<T>(this SerializedProperty property) | |
{ | |
var targetObjects = property.serializedObject.targetObjects; | |
var values = new T[targetObjects.Length]; | |
for (var i = 0; i < targetObjects.Length; ++i) | |
values[i] = property.GetValue<T>(i); | |
return values; | |
} | |
public static void GetAllValues<T>(this SerializedProperty property, ref T[] values) | |
{ | |
var targetObjects = property.serializedObject.targetObjects; | |
if (values == null) | |
values = new T[targetObjects.Length]; | |
else | |
Array.Resize(ref values, targetObjects.Length); | |
for (var i = 0; i < targetObjects.Length; ++i) | |
values[i] = property.GetValue<T>(i); | |
} | |
public static T GetValue<T>(this SerializedProperty property, int targetObjectIndex = -1) | |
{ | |
var value = targetObjectIndex < 0 | |
? (object)property.serializedObject.targetObject | |
: property.serializedObject.targetObjects[targetObjectIndex]; | |
var path = property.propertyPath; | |
var prevIndex = -1; | |
do | |
{ | |
var nextIndex = path.IndexOf('.', prevIndex + 1); | |
var subPathLength = (nextIndex < 0 ? path.Length : nextIndex) - prevIndex - 1; | |
var subPath = path.AsSpan(prevIndex + 1, subPathLength).ToString(); | |
if (subPath == "Array") | |
{ | |
// list/array propertyPath values are weird and look like this | |
// {PropertyName}.Array.data[{ListIndex}] | |
// e.g. | |
// AudioLines.Array.data[0] | |
// RandomClipEntries.Array.data[0].ClipReference | |
var listIndexStart = path.IndexOf('[', nextIndex + 1) + 1; | |
var listIndexLength = path.IndexOf(']', listIndexStart) - listIndexStart; | |
var listIndexSpan = path.AsSpan(listIndexStart, listIndexLength); | |
var listIndex = int.Parse(listIndexSpan); | |
var enumerable = (IEnumerable)value; | |
var enumerator = enumerable!.GetEnumerator(); | |
using var disposeDummy = enumerator as IDisposable; | |
var hasItemAtIndex = false; | |
for (var i = 0; i <= listIndex; ++i) | |
hasItemAtIndex = enumerator.MoveNext(); | |
value = hasItemAtIndex ? enumerator.Current : null; | |
// have to move the prevIndex past the closing bracket and to the next dot | |
// OR the end of the string, whichever it happens to be | |
prevIndex = listIndexStart + listIndexLength + 1; | |
} | |
else | |
{ | |
value = value!.GetType().GetField(subPath).GetValue(value); | |
prevIndex = nextIndex; | |
} | |
} while (prevIndex >= 0 && prevIndex < path.Length); | |
return (T)value; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment