private void RestoreMode(string serializedMode) { // Parse JSON back to objects var modeParams = JsonUtility.FromJson <ModeParameters>(serializedMode); // Build list that contains Components (only necessary information) var trackableComponentsList = modeParams.Parameters.Select(i => i.ComponentName); // Build list of gameObject's components that present in prev list var trackableComponents = gameObject.GetComponents(typeof(UnityEngine.Component)).Where(c => trackableComponentsList.Contains(c.GetType().ToString())); // Go through particular gameObject's components only foreach (var component in trackableComponents) { // Get type of component Type type = component.GetType(); // Go through each field in this component foreach (var f in type.GetFields().Where(i => i.IsPublic)) { // Find if there is a record for this field in ModeParameters var prm = modeParams.Parameters.FirstOrDefault(i => i.ComponentName == type.ToString() && i.ParamName == f.Name); // If record was found if (prm != default(Parameter)) { // If this is simple type then restore value if (prm.ParamType != "CachedUnityObject") { object obj = null; var converter = TypeDescriptor.GetConverter(f.FieldType); if (!converter.CanConvertFrom(typeof(String))) { if (f.FieldType == typeof(Vector3)) { obj = UnityTypesConverter.Vector3FromString(prm.Value); } if (f.FieldType == typeof(Quaternion)) { obj = UnityTypesConverter.QuaternionFromString(prm.Value); } } else { obj = converter.ConvertFromString(prm.Value); } f.SetValue(component, obj); } // Othervise take object from cache else { var cachedObj = this.cachedUnityObjects.FirstOrDefault(i => i.Key == prm.Value && i.ModeGUID == modeParams.GUID); if (cachedObj != default(CachedParameter)) { f.SetValue(component, cachedObj.Value); } } } } // Go through each property in this component BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; foreach (var p in type.GetProperties(flags)) { // Find if there is a record for this field in ModeParameters var prm = modeParams.Parameters.FirstOrDefault(i => i.ComponentName == type.ToString() && i.ParamName == p.Name); // If record was found if (prm != default(Parameter)) { // If this is simple type then restore value if (prm.ParamType != "CachedUnityObject") { object obj = null; var converter = TypeDescriptor.GetConverter(p.PropertyType); if (!converter.CanConvertFrom(typeof(String))) { if (p.PropertyType == typeof(Vector3)) { obj = UnityTypesConverter.Vector3FromString(prm.Value); } if (p.PropertyType == typeof(Quaternion)) { obj = UnityTypesConverter.QuaternionFromString(prm.Value); } } else { obj = converter.ConvertFromString(prm.Value); } p.SetValue(component, obj, null); } // Othervise take object from cache else { var cachedObj = this.cachedUnityObjects.FirstOrDefault(i => i.Key == prm.Value && i.ModeGUID == modeParams.GUID); if (cachedObj != default(CachedParameter)) { p.SetValue(component, cachedObj.Value, null); } } } } } }
/// <summary> /// Serializes the current mode. /// </summary> /// <returns>Serialized json</returns> /// <param name="modeName">Mode name.</param> /// <param name="modeGUID">Mode GUI. Used to map objects in JSON with Objects in cachedUnityObjects list on component</param> private string SerializeCurrentMode(string modeName, string modeGUID) { var modeParams = new ModeParameters(); modeParams.GUID = modeGUID; modeParams.ModeName = modeName; modeParams.Parameters = new List <Parameter>(); // Build list that contains Components (only necessary information) var trackComponentsList = this.trackableParameters.Select(i => i.Component); // Build list of gameObject's components that present in prev list var trackComponents = gameObject.GetComponents(typeof(UnityEngine.Component)).Where(c => trackComponentsList.Contains(c)); // Go through particular gameObject's components only foreach (var component in trackComponents) { // Get type of component Type type = component.GetType(); // Build list of required parameter names. To avoid reading all the properties var parameterList = this.trackableParameters.Where(i => i.Component == component).Select(i => i.property.ParamName); // Read only required parameters of gameObject's component foreach (var f in type.GetFields().Where(i => i.IsPublic && parameterList.Contains(i.Name))) { bool fieldHasConverter = TypeDescriptor.GetConverter(f.FieldType).CanConvertFrom(typeof(String)); bool fieldIsUnityObjectSubclass = f.FieldType.IsSubclassOf(typeof(UnityEngine.Object)); bool fieldTypeIsWrappedProperly = f.FieldType == typeof(Vector3) || f.FieldType == typeof(Quaternion); // Simple types derived from struct and string serialize as is if (fieldHasConverter || fieldTypeIsWrappedProperly) { string paramValue = string.Empty; if (f.FieldType == typeof(Vector3)) { paramValue = UnityTypesConverter.Vector3ToString(((Vector3)f.GetValue(component))); } else if (f.FieldType == typeof(Quaternion)) { paramValue = UnityTypesConverter.QuaternionToString(((Quaternion)f.GetValue(component))); } else { paramValue = TypeDescriptor.GetConverter(f.FieldType).ConvertToString(f.GetValue(component)); } Parameter param = new Parameter(); param.ComponentName = type.ToString(); param.ParamName = f.Name; param.ParamType = f.FieldType.ToString(); param.Value = paramValue; modeParams.Parameters.Add(param); } // UnityEngine objects save in cachedUnityObjects list which is serialized by Unity in UnityEditor if (fieldIsUnityObjectSubclass) { Parameter param = new Parameter(); param.ComponentName = type.ToString(); param.ParamName = f.Name; param.ParamType = "CachedUnityObject"; param.Value = type + "." + f.Name; // Remove old parameter for this mode this.cachedUnityObjects.RemoveAll(i => i.Key == param.Value && i.ModeGUID == modeGUID); // Add new parameter for this mode this.cachedUnityObjects.Add(new CachedParameter(param.Value, modeGUID, (UnityEngine.Object)f.GetValue(component))); modeParams.Parameters.Add(param); } } //TODO Implment processing Properties BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; foreach (var p in type.GetProperties(flags).Where(i => parameterList.Contains(i.Name))) { bool propHasConverter = TypeDescriptor.GetConverter(p.PropertyType).CanConvertFrom(typeof(String)); bool propIsUnityObjectSubclass = p.PropertyType.IsSubclassOf(typeof(UnityEngine.Object)); bool propTypeIsWrappedProperly = p.PropertyType == typeof(Vector3) || p.PropertyType == typeof(Quaternion); // Simple types derived from struct and string serialize as is if (propHasConverter || propTypeIsWrappedProperly) { string paramValue = string.Empty; if (p.PropertyType == typeof(Vector3)) { paramValue = UnityTypesConverter.Vector3ToString(((Vector3)p.GetValue(component, null))); } else if (p.PropertyType == typeof(Quaternion)) { paramValue = UnityTypesConverter.QuaternionToString(((Quaternion)p.GetValue(component, null))); } else { paramValue = TypeDescriptor.GetConverter(p.PropertyType).ConvertToString(p.GetValue(component, null)); } Parameter param = new Parameter(); param.ComponentName = type.ToString(); param.ParamName = p.Name; param.ParamType = p.PropertyType.ToString(); param.Value = paramValue; modeParams.Parameters.Add(param); } // UnityEngine objects save in cachedUnityObjects list which is serialized by Unity in UnityEditor if (propIsUnityObjectSubclass) { Parameter param = new Parameter(); param.ComponentName = type.ToString(); param.ParamName = p.Name; param.ParamType = "CachedUnityObject"; param.Value = type + "." + p.Name; // Remove old parameter for this mode this.cachedUnityObjects.RemoveAll(i => i.Key == param.Value && i.ModeGUID == modeGUID); // Add new parameter for this mode this.cachedUnityObjects.Add(new CachedParameter(param.Value, modeGUID, (UnityEngine.Object)p.GetValue(component, null))); modeParams.Parameters.Add(param); } } } return(JsonUtility.ToJson(modeParams, false)); }