179 lines
7.3 KiB
C#
179 lines
7.3 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
#if UNITY_EDITOR
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace Microsoft.MixedReality.Toolkit.Utilities
|
|
{
|
|
public static class SerializedObjectUtils
|
|
{
|
|
/// <summary>
|
|
/// Copies properties of one serialized object to another (without undo)
|
|
/// </summary>
|
|
public static bool CopySerializedObject(SerializedObject source, SerializedObject target, IEnumerable<string> propsToIgnore = null)
|
|
{
|
|
bool madeChanges = false;
|
|
SerializedProperty sourceProp = source.GetIterator();
|
|
while (sourceProp.NextVisible(true))
|
|
{
|
|
if (propsToIgnore != null)
|
|
{
|
|
foreach (string propToIgnore in propsToIgnore)
|
|
{
|
|
if (propToIgnore == sourceProp.name)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
madeChanges |= target.CopyFromSerializedPropertyIfDifferent(sourceProp);
|
|
}
|
|
|
|
if (madeChanges)
|
|
{
|
|
target.ApplyModifiedPropertiesWithoutUndo();
|
|
}
|
|
|
|
return madeChanges;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Iterates through a serialized object's fields and sets any accompanying fields in the supplied struct.
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="propNamePrefixFilter">Prefix to remove from serialized object field name before searching for match in struct</param>
|
|
public static T CopySerializedObjectToStruct<T>(SerializedObject source, T target, string propNamePrefixFilter = null, bool errorOnFieldNotFound = false) where T : struct
|
|
{
|
|
Type targetType = typeof(T);
|
|
object targetObject = (object)target;
|
|
|
|
SerializedProperty sourceProp = source.GetIterator();
|
|
while (sourceProp.NextVisible(true))
|
|
{
|
|
string propName = sourceProp.name;
|
|
|
|
if (!string.IsNullOrEmpty(propNamePrefixFilter) && propName.StartsWith(propNamePrefixFilter))
|
|
{
|
|
propName = propName.Replace(propNamePrefixFilter, "");
|
|
}
|
|
|
|
FieldInfo field = targetType.GetField(propName, BindingFlags.Public | BindingFlags.Instance);
|
|
if (field != null)
|
|
{
|
|
SetTargetFieldToSerializedPropertyValue(field, ref targetObject, sourceProp);
|
|
}
|
|
if (errorOnFieldNotFound)
|
|
{
|
|
Debug.LogError("Field " + propName + " not found in struct type " + targetType.Name);
|
|
}
|
|
}
|
|
|
|
return (T)targetObject;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the target field to the value from property based on property type.
|
|
/// </summary>
|
|
public static void SetTargetFieldToSerializedPropertyValue(FieldInfo field, ref object target, SerializedProperty property)
|
|
{
|
|
switch (property.propertyType)
|
|
{
|
|
case SerializedPropertyType.Boolean:
|
|
field.SetValue(target, property.boolValue);
|
|
break;
|
|
case SerializedPropertyType.Integer:
|
|
field.SetValue(target, property.intValue);
|
|
break;
|
|
case SerializedPropertyType.String:
|
|
field.SetValue(target, property.stringValue);
|
|
break;
|
|
case SerializedPropertyType.Enum:
|
|
field.SetValue(target, property.enumValueIndex);
|
|
break;
|
|
case SerializedPropertyType.Float:
|
|
field.SetValue(target, property.floatValue);
|
|
break;
|
|
case SerializedPropertyType.Color:
|
|
field.SetValue(target, property.colorValue);
|
|
break;
|
|
case SerializedPropertyType.Vector2:
|
|
field.SetValue(target, property.vector2Value);
|
|
break;
|
|
case SerializedPropertyType.Vector3:
|
|
field.SetValue(target, property.vector3Value);
|
|
break;
|
|
case SerializedPropertyType.Vector4:
|
|
field.SetValue(target, property.vector4Value);
|
|
break;
|
|
case SerializedPropertyType.ObjectReference:
|
|
field.SetValue(target, property.objectReferenceValue);
|
|
break;
|
|
default:
|
|
throw new NotImplementedException("Type " + property.propertyType + " is not implemented.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Uses reflection to set all public fields of a struct in an accompanying serialized property
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
public static void SetStructValue<T>(SerializedProperty serializedProperty, T value) where T : struct
|
|
{
|
|
foreach (FieldInfo field in typeof(T).GetFields(BindingFlags.Public | BindingFlags.Instance))
|
|
{
|
|
SerializedProperty sourceProp = serializedProperty.FindPropertyRelative(field.Name);
|
|
if (sourceProp == null)
|
|
{
|
|
Debug.LogError("Couldn't find field " + field.Name + " in serialized property.");
|
|
}
|
|
else
|
|
{
|
|
Type sourcePropType = Type.GetType(sourceProp.type);
|
|
if (!sourcePropType.IsAssignableFrom(field.FieldType))
|
|
{
|
|
Debug.LogError("Couldn't assign field " + field.Name + " in serialized property - types do not match.");
|
|
}
|
|
else
|
|
{
|
|
SetSerializedPropertyByType(field.GetValue(value), sourceProp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets a serialized property value based on type of value object.
|
|
/// </summary>
|
|
public static void SetSerializedPropertyByType(object value, SerializedProperty property)
|
|
{
|
|
switch (property.propertyType)
|
|
{
|
|
case SerializedPropertyType.Boolean:
|
|
property.boolValue = (bool)value;
|
|
break;
|
|
case SerializedPropertyType.Integer:
|
|
property.intValue = (int)value;
|
|
break;
|
|
case SerializedPropertyType.String:
|
|
property.stringValue = (string)value;
|
|
break;
|
|
case SerializedPropertyType.Enum:
|
|
property.enumValueIndex = (int)value;
|
|
break;
|
|
case SerializedPropertyType.Float:
|
|
property.floatValue = (float)value;
|
|
break;
|
|
case SerializedPropertyType.ObjectReference:
|
|
property.objectReferenceValue = (UnityEngine.Object)value;
|
|
break;
|
|
default:
|
|
throw new NotImplementedException("Type " + property.propertyType + " is not implemented.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif |