forked from Shardstone/trail-into-darkness
211 lines
9.1 KiB
C#
211 lines
9.1 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Diagnostics;
|
|
using System.Text.RegularExpressions;
|
|
using UnityEngine;
|
|
using Debug = UnityEngine.Debug;
|
|
using Object = UnityEngine.Object;
|
|
using Type = System.Type;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
using System.Reflection;
|
|
#endif
|
|
|
|
namespace Jovian.Utilities {
|
|
|
|
public static class SerializedObjectUtility {
|
|
[Conditional("UNITY_EDITOR")]
|
|
public static void SaveObjectProperties(Object targetObject, params object[] args) {
|
|
#if UNITY_EDITOR
|
|
EditorSerializedObjectUtility.SaveObjectProperties(targetObject, args);
|
|
#endif
|
|
}
|
|
}
|
|
#if UNITY_EDITOR
|
|
public static class EditorSerializedObjectUtility {
|
|
|
|
//https://answers.unity.com/questions/929293/get-field-type-of-serializedproperty.html
|
|
public static Type GetTypeFromProperty(SerializedProperty property) {
|
|
//gets parent type info
|
|
string[] slices = property.propertyPath.Split('.');
|
|
System.Type type = property.serializedObject.targetObject.GetType();
|
|
|
|
for(int i = 0; i < slices.Length; i++)
|
|
if (slices[i] == "Array")
|
|
{
|
|
i++; //skips "data[x]"
|
|
type = type.GetElementType(); //gets info on array elements
|
|
}
|
|
|
|
//gets info on field and its type
|
|
else type = type.GetField(slices[i], BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Instance).FieldType;
|
|
|
|
//type is now the type of the property
|
|
return type;
|
|
}
|
|
|
|
private static readonly Regex isArrayElementRegex = new Regex("Array.data\\[\\d+\\]$");
|
|
|
|
public static bool IsPropertyAnArrayElement(SerializedProperty property) {
|
|
return isArrayElementRegex.IsMatch(property.propertyPath);
|
|
}
|
|
|
|
public static SerializedProperty GetArrayPropertyWithElementProperty(SerializedProperty property) {
|
|
SerializedObject serializedObject = property.serializedObject;
|
|
string propertyPath = property.propertyPath;
|
|
int arrayDataIndex = propertyPath.LastIndexOf(".Array.data", StringComparison.Ordinal);
|
|
string propertyPathWithoutArray = propertyPath.Substring(0, arrayDataIndex);
|
|
int pathDividerIndex = propertyPathWithoutArray.LastIndexOf(".", StringComparison.Ordinal);
|
|
|
|
string parentPropertyName = propertyPathWithoutArray;
|
|
if(pathDividerIndex != -1) {
|
|
parentPropertyName = propertyPathWithoutArray.Substring(pathDividerIndex);
|
|
}
|
|
return serializedObject.FindProperty(parentPropertyName);;
|
|
}
|
|
|
|
public static void SaveObjectProperties(Object targetObject, params object[] args) {
|
|
SerializedObject serializedObject = new SerializedObject(targetObject);
|
|
|
|
for(int i = 0; i < args.Length; i += 2) {
|
|
var keyArg = args[i];
|
|
var keyType = keyArg.GetType();
|
|
|
|
if((keyType == typeof(string)) == false) {
|
|
throw new System.NotSupportedException(string.Format("Key must be string. {0} is {1}", args[i], keyType));
|
|
}
|
|
else {
|
|
var property = serializedObject.FindProperty((string)keyArg);
|
|
object argValue = args[i + 1];
|
|
|
|
if(property == null) {
|
|
throw new System.Exception(string.Format("No property found for key {0}", keyArg));
|
|
}
|
|
|
|
if(argValue == null) {
|
|
property.objectReferenceValue = null;
|
|
}
|
|
else {
|
|
if(property.isArray) {
|
|
property.arraySize = 0;
|
|
IEnumerable argArray = (IEnumerable)argValue;
|
|
IEnumerator enumerator = argArray.GetEnumerator();
|
|
|
|
int index = 0;
|
|
while(enumerator.MoveNext()) {
|
|
property.InsertArrayElementAtIndex(index);
|
|
var arrayProperty = property.GetArrayElementAtIndex(index);
|
|
SetSerializedPropertyValue(arrayProperty, enumerator.Current);
|
|
index++;
|
|
}
|
|
|
|
}
|
|
else {
|
|
SetSerializedPropertyValue(property, argValue);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
private static void SetSerializedPropertyValue(SerializedProperty property, object value) {
|
|
if(property == null) {
|
|
UnityEngine.Debug.LogError("SetSerializedPropertyValue failed, property is null");
|
|
return;
|
|
}
|
|
switch(property.propertyType) {
|
|
case SerializedPropertyType.AnimationCurve:
|
|
property.animationCurveValue = (AnimationCurve)value;
|
|
break;
|
|
case SerializedPropertyType.Boolean:
|
|
property.boolValue = (bool)value;
|
|
break;
|
|
case SerializedPropertyType.BoundsInt:
|
|
property.boundsIntValue = (BoundsInt)value;
|
|
break;
|
|
case SerializedPropertyType.Character:
|
|
property.intValue = (int)(char)value;
|
|
break;
|
|
case SerializedPropertyType.Color: {
|
|
if(value is Color32) {
|
|
property.colorValue = (Color)(Color32)value;
|
|
}
|
|
else {
|
|
property.colorValue = (Color)value;
|
|
}
|
|
break;
|
|
}
|
|
case SerializedPropertyType.ExposedReference:
|
|
case SerializedPropertyType.ObjectReference:
|
|
property.objectReferenceValue = (Object)value;
|
|
break;
|
|
case SerializedPropertyType.Float:
|
|
property.floatValue = (float)value;
|
|
break;
|
|
case SerializedPropertyType.Integer:
|
|
property.intValue = (int)value;
|
|
break;
|
|
case SerializedPropertyType.LayerMask:
|
|
property.intValue = ((LayerMask)value).value;
|
|
break;
|
|
case SerializedPropertyType.Quaternion:
|
|
property.quaternionValue = (Quaternion)value;
|
|
break;
|
|
case SerializedPropertyType.Rect:
|
|
property.rectValue = (Rect)value;
|
|
break;
|
|
case SerializedPropertyType.RectInt:
|
|
property.rectIntValue = (RectInt)value;
|
|
break;
|
|
case SerializedPropertyType.String:
|
|
property.stringValue = (string)value;
|
|
break;
|
|
case SerializedPropertyType.Vector2:
|
|
property.vector2Value = (Vector2)value;
|
|
break;
|
|
case SerializedPropertyType.Vector2Int:
|
|
property.vector2IntValue = (Vector2Int)value;
|
|
break;
|
|
case SerializedPropertyType.Vector3:
|
|
property.vector3Value = (Vector3)value;
|
|
break;
|
|
case SerializedPropertyType.Vector3Int:
|
|
property.vector3IntValue = (Vector3Int)value;
|
|
break;
|
|
case SerializedPropertyType.Vector4:
|
|
property.vector4Value = (Vector4)value;
|
|
break;
|
|
case SerializedPropertyType.Enum:
|
|
property.enumValueIndex = (int)value; // need to test this
|
|
// flags???
|
|
break;
|
|
case SerializedPropertyType.Generic:
|
|
SaveGenericProperty(property, value);
|
|
break;
|
|
default:
|
|
throw new System.NotSupportedException($"PropertyType {property.propertyType} is not supported - yet. Array? {property.isArray} Path: {property.propertyPath}");
|
|
}
|
|
}
|
|
|
|
private static void SaveGenericProperty(SerializedProperty property, object instance) {
|
|
Type type = instance.GetType();
|
|
var fields = type.GetRuntimeFields();
|
|
foreach(FieldInfo field in fields) {
|
|
if(field.IsNotSerialized || field.IsStatic) {
|
|
continue;
|
|
}
|
|
SerializedProperty fieldProperty = property.FindPropertyRelative(field.Name);
|
|
if(fieldProperty != null) {
|
|
SetSerializedPropertyValue(property.FindPropertyRelative(field.Name), field.GetValue(instance));
|
|
}
|
|
else {
|
|
UnityEngine.Debug.Log($"SaveGenericProperty cannot field serializedProperty named '{field.Name}'");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
} |