// /*=============================================================================== // Copyright (C) 2020 PhantomsXR Ltd. All Rights Reserved. // // This file is part of the AR-MOD SDK. // // The AR-MOD SDK cannot be copied, distributed, or made available to // third-parties for commercial purposes without written permission of PhantomsXR Ltd. // // Contact info@phantomsxr.com for licensing requests. // ===============================================================================*/ using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; using Newtonsoft.Json; using Phantom.XRMOD.ActionNotification.Runtime; using Phantom.XRMOD.UnityFusion.Runtime.CodeHook; using UnityEditor; using UnityEngine; using UnityEngine.Audio; using UnityEngine.U2D; using UnityEngine.Video; using Phantom.XRMOD.Core.Runtime; using Phantom.XRMOD.UnityFusion.Runtime; using Phantom.XRMOD.XRMODPackageTools.Editor; using UnityEditorInternal; using Object = UnityEngine.Object; namespace Phantom.XRMOD.Runtime.Editor { [CustomEditor(typeof(MonoBinder)), CanEditMultipleObjects] public class MonoBinderEditor : UnityEditor.Editor { [RuntimeInitializeOnLoadMethod] private static void RunInEditor() { ActionNotificationCenter.DefaultCenter.AddObserver(ModifyTemplateScript, "ModifyTemplateMonoBinder"); } //private static Malee.List.ReorderableList BINDERS; private static MonoBehaviour TARGET_MONO; private static MonoBinder _MONO_BINDER; private static readonly Type[] _UNITY_TYPE = { typeof(GameObject), typeof(Texture2D), typeof(MonoBehaviour), typeof(Color), typeof(Transform), typeof(MeshRenderer), typeof(AudioClip), typeof(AnimationClip), typeof(AudioMixer), typeof(ComputeShader), typeof(Font), typeof(Material), typeof(Mesh), #if UNITY_6000 typeof(PhysicsMaterial), #else typeof(PhysicMaterial), #endif typeof(Shader), typeof(Sprite), typeof(Texture), typeof(TextAsset), typeof(SpriteAtlas), typeof(VideoClip), typeof(Vector2), typeof(LineRenderer), typeof(TrailRenderer), typeof(XRMODBehaviour), typeof(MeshFilter), typeof(Vector3), typeof(Vector4), typeof(Quaternion), typeof(ScriptableObject) }; private static readonly Type[] _NUM_ARRAY_TYPE = new[] { typeof(byte[]), typeof(sbyte[]), typeof(short[]), typeof(ushort[]), typeof(int[]), typeof(uint[]), typeof(long[]), typeof(ulong[]), typeof(float[]), typeof(decimal[]), typeof(double[]) }; private static readonly Type[] _NUM_TYPE = new[] { typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(decimal), typeof(double) }; [CustomEditor(typeof(XRMODBehaviour), true), CanEditMultipleObjects] public class MonoBehaviourEditor : UnityEditor.Editor { private static object self; public override void OnInspectorGUI() { base.OnInspectorGUI(); self = target; } [MenuItem("CONTEXT/XRMODBehaviour/Convert To MonoBinder")] private static async void ConvertToAdapter(MenuCommand _command) { if (self is not XRMODBehaviour tmp_Behaviour) return; var tmp_Target = tmp_Behaviour.gameObject; TARGET_MONO = tmp_Behaviour; TARGET_MONO.enabled = true; if (!EditorUtility.DisplayDialog("Convert to MonoBinder", "Convert to MonoBinder will remove this script! Are you sure?", "Ok", "Cancel")) return; if (!tmp_Target) return; if (!tmp_Target.TryGetComponent(out MonoBinder tmp_MonoBinder)) { tmp_MonoBinder = tmp_Target.AddComponent(); } var tmp_MonoType = tmp_Behaviour.GetType(); tmp_MonoBinder.ScriptList ??= new List(); var tmp_IndexOfScript = tmp_MonoBinder.ScriptList.FindIndex(_data => _data.ClassName.Equals(tmp_MonoType.Name)); if (tmp_IndexOfScript >= 0) { // EditorUtility.DisplayDialog("Error", $"Script {tmp_MonoType.Name} is invalid!", "OK"); tmp_MonoBinder.ScriptList.RemoveAt(tmp_IndexOfScript); tmp_MonoBinder.ScriptList.Insert(tmp_IndexOfScript, new MonoData() { ClassName = tmp_MonoType.Name, ClassNamespace = tmp_MonoType.Namespace }); } else { tmp_MonoBinder.ScriptList.Add(new MonoData() { ClassName = tmp_MonoType.Name, ClassNamespace = tmp_MonoType.Namespace }); } await Task.Delay(50); GrabFieldsType(tmp_MonoBinder); await Task.Delay(150); if (TARGET_MONO) TARGET_MONO.enabled = false; TARGET_MONO = null; } } private ReorderableList reorderableList; private MonoBinderFieldEditor monoBinderFieldEditor; private SerializedProperty scriptListProperty; private int indentLevel = 1; private void OnEnable() { _MONO_BINDER = target as MonoBinder; monoBinderFieldEditor = CreateInstance(); scriptListProperty = serializedObject.FindProperty("ScriptList"); reorderableList = new ReorderableList(serializedObject, scriptListProperty, true, true, true, true) { drawElementCallback = DrawScriptListItems, drawHeaderCallback = DrawHeader, elementHeightCallback = ElementHeightCallback, onChangedCallback = _list => { if (_list.count == 0) scriptListProperty.ClearArray(); }, onRemoveCallback = _list => { monoBinderFieldEditor.RemoveElement(_list.index); scriptListProperty.DeleteArrayElementAtIndex(_list.index); } }; } private float ElementHeightCallback(int _index) { float tmp_RectHeightOffset = 0; float tmp_ArrayRectHeightOffset = 0; SerializedProperty tmp_Element = reorderableList.serializedProperty.GetArrayElementAtIndex(_index); var tmp_FieldsProperty = tmp_Element.FindPropertyRelative("Fields"); if (tmp_FieldsProperty.arraySize > 0) { for (int tmp_Idx = 0; tmp_Idx < tmp_FieldsProperty.arraySize; tmp_Idx++) { var tmp_Field = tmp_FieldsProperty.GetArrayElementAtIndex(tmp_Idx); var tmp_FieldType = tmp_Field.FindPropertyRelative("FieldType"); var tmp_EnumIdx = (MonoField.FieldTypeEnum) tmp_FieldType.enumValueIndex; switch (tmp_EnumIdx) { case MonoField.FieldTypeEnum.TextureArray: case MonoField.FieldTypeEnum.AudioClipArray: case MonoField.FieldTypeEnum.ShaderArray: case MonoField.FieldTypeEnum.SpriteArray: case MonoField.FieldTypeEnum.MaterialArray: case MonoField.FieldTypeEnum.AnimationClipArray: case MonoField.FieldTypeEnum.VideoClipArray: case MonoField.FieldTypeEnum.MeshArray: case MonoField.FieldTypeEnum.ColorArray: case MonoField.FieldTypeEnum.ScriptableObjectArray: case MonoField.FieldTypeEnum.QuaternionArray: case MonoField.FieldTypeEnum.Vector2Array: case MonoField.FieldTypeEnum.Vector3Array: case MonoField.FieldTypeEnum.Vector4Array: case MonoField.FieldTypeEnum.ScriptableObject: case MonoField.FieldTypeEnum.AnimationCurveArray: case MonoField.FieldTypeEnum.Components: case MonoField.FieldTypeEnum.GameObjectArray: var tmp_ArrayPropert = tmp_Field.FindPropertyRelative($"{tmp_EnumIdx}"); if (tmp_ArrayPropert.isExpanded && tmp_Element.isExpanded && tmp_FieldsProperty.isExpanded) { tmp_ArrayRectHeightOffset += EditorGUI.GetPropertyHeight(tmp_ArrayPropert) - reorderableList.footerHeight; if (tmp_FieldsProperty.arraySize == 1) { tmp_ArrayRectHeightOffset += 40; tmp_ArrayRectHeightOffset += reorderableList.headerHeight; } } else if (tmp_Element.isExpanded && tmp_FieldsProperty.isExpanded) { var tmp_RowCount = tmp_FieldsProperty.arraySize * 40; tmp_RectHeightOffset = tmp_RowCount + reorderableList.footerHeight; } break; default: if (tmp_Element.isExpanded && tmp_FieldsProperty.isExpanded) { var tmp_RowCount = tmp_FieldsProperty.arraySize * 40; tmp_RectHeightOffset = tmp_RowCount + reorderableList.footerHeight; } break; } } tmp_RectHeightOffset += tmp_ArrayRectHeightOffset; } else if (tmp_Element.isExpanded && tmp_FieldsProperty.isExpanded) { tmp_RectHeightOffset += EditorGUIUtility.singleLineHeight; } if (tmp_Element.isExpanded) { return EditorGUI.GetPropertyHeight(tmp_Element) - 50 + tmp_RectHeightOffset; } return EditorGUI.GetPropertyHeight(tmp_Element) + tmp_RectHeightOffset; } private void DrawHeader(Rect _rect) { EditorGUI.LabelField(_rect, $"MonoScripts(Count:{scriptListProperty.arraySize})"); } private void DrawScriptListItems(Rect _rect, int _index, bool _isactive, bool _isfocused) { if (reorderableList.serializedProperty.arraySize == 0) return; SerializedProperty element = reorderableList.serializedProperty.GetArrayElementAtIndex(_index); var tmp_IndentLevel = EditorGUI.indentLevel; var tmp_ClassNameSpaceProperty = element.FindPropertyRelative("ClassNamespace"); var tmp_ClassNameProperty = element.FindPropertyRelative("ClassName"); var tmp_FieldsProperty = element.FindPropertyRelative("Fields"); var tmp_ClassNamespaceStr = tmp_ClassNameSpaceProperty.stringValue; var tmp_ClassNameStr = tmp_ClassNameProperty.stringValue; monoBinderFieldEditor.EnsureReorderableList(_rect, _index, tmp_FieldsProperty); if (string.IsNullOrEmpty(tmp_ClassNamespaceStr)) tmp_ClassNamespaceStr = "Missing Namespace"; if (string.IsNullOrEmpty(tmp_ClassNameStr)) tmp_ClassNameStr = "Missing Class Name"; var tmp_Title = $"{tmp_ClassNamespaceStr}.{tmp_ClassNameStr}"; float tmp_OffsetOfIcon = 9; if (tmp_Title.Contains("Missing")) { GUIContent tmp_WarningIcon = EditorGUIUtility.IconContent("console.warnicon"); EditorGUI.LabelField(new Rect(_rect.x, _rect.y, _rect.width, EditorGUIUtility.singleLineHeight), tmp_WarningIcon); tmp_OffsetOfIcon = 28; } _rect.x += tmp_OffsetOfIcon; _rect.width -= tmp_OffsetOfIcon; element.isExpanded = EditorGUI.Foldout(new Rect(_rect.x, _rect.y, _rect.width, EditorGUIUtility.singleLineHeight), element.isExpanded, tmp_Title); if (element.isExpanded) { EditorGUI.PropertyField( new Rect(_rect.x, _rect.y + Utilities.MakeSureHeight, _rect.width, EditorGUIUtility.singleLineHeight), tmp_ClassNameSpaceProperty ); EditorGUI.PropertyField( new Rect(_rect.x, _rect.y + Utilities.MakeSureHeight * 2, _rect.width, EditorGUIUtility.singleLineHeight), tmp_ClassNameProperty ); tmp_FieldsProperty.isExpanded = EditorGUI.Foldout(new Rect(_rect.x, _rect.y + Utilities.MakeSureHeight * 3, _rect.width, EditorGUIUtility.singleLineHeight), tmp_FieldsProperty.isExpanded, "Fields"); if (tmp_FieldsProperty.isExpanded) { _rect.y += Utilities.MakeSureHeight * 4; monoBinderFieldEditor.DrawLayout(_rect, _index); } } EditorGUI.indentLevel = tmp_IndentLevel; } public override void OnInspectorGUI() { serializedObject.Update(); reorderableList.DoLayoutList(); serializedObject.ApplyModifiedProperties(); } private static async void GrabFieldsType(MonoBinder _monoBinder, bool _auto = false) { try { if (TARGET_MONO == null || !TARGET_MONO.enabled) return; foreach (MonoData tmp_MonoData in _monoBinder.ScriptList) { var tmp_FullNamespace = $"{tmp_MonoData.ClassNamespace}.{tmp_MonoData.ClassName}"; if (TARGET_MONO == null || tmp_FullNamespace != TARGET_MONO.GetType().FullName) continue; tmp_MonoData.Fields.Clear(); Type tmp_Type; if (_auto) { string tmp_ClassFullName = $"{tmp_MonoData.ClassNamespace}.{tmp_MonoData.ClassName}"; var tmp_Path = Application.dataPath.Replace("Assets", $"Library/ScriptAssemblies/{tmp_MonoData.ClassNamespace}.Runtime.dll"); Assembly tmp_Assembly = Assembly.LoadFile(tmp_Path); tmp_Type = tmp_Assembly.GetType(tmp_ClassFullName); } else { tmp_Type = TARGET_MONO.GetType(); //tmp_Assembly.GetType(tmp_ClassFullName); } if (tmp_Type == null) { EditorUtility.DisplayDialog("Error", $"Can not load assembly", "Ok"); return; } var tmp_ExperienceInstance = _auto ? Activator.CreateInstance(tmp_Type) : TARGET_MONO; var tmp_AllFields = tmp_MonoData.Fields.Select(_monoField => _monoField.FieldName).ToList(); var tmp_Members = new List(); var tmp_FieldInfos = tmp_Type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo tmp_FieldInfo in tmp_FieldInfos) { if (tmp_FieldInfo.IsPublic) { tmp_Members.Add(tmp_FieldInfo); continue; } var tmp_HasSerializeAttribute = tmp_FieldInfo.GetCustomAttributes(typeof(SerializeField), true).Length > 0; if (tmp_HasSerializeAttribute) { tmp_Members.Add(tmp_FieldInfo); } } foreach (MemberInfo tmp_Info in tmp_Members) { EditorUtility.DisplayProgressBar("Converting", $"Converting {tmp_Type.Name}.{tmp_Info.Name}({tmp_Members.ToList().IndexOf(tmp_Info)}/{tmp_Members.Count})", tmp_Members.ToList().IndexOf(tmp_Info) / (float) tmp_Members.Count); if (!tmp_AllFields.Contains(tmp_Info.Name)) { MonoField tmp_MonoField = new MonoField(); string tmp_FieldName = tmp_Info.Name; tmp_MonoField.FieldName = tmp_FieldName; Type tmp_PropertyType = (tmp_Info is PropertyInfo tmp_PropertyInfo) ? tmp_PropertyInfo.PropertyType : ((FieldInfo) tmp_Info).FieldType; SetMonoFieldType(tmp_MonoField, tmp_PropertyType); CopyDataToMonoField(ref tmp_MonoField, tmp_Info, tmp_ExperienceInstance); tmp_MonoData.Fields.Add(tmp_MonoField); } await Task.Delay(10); } // Since the resource needs to be load, it is processed last. var tmp_NonSortData = tmp_MonoData.Fields.Where(_item => !(_item.FieldType is MonoField.FieldTypeEnum.AssetReference || _item.FieldType is MonoField.FieldTypeEnum.AssetReferenceArray)).ToList(); var tmp_NeedSortData = tmp_MonoData.Fields.Where(_item => _item.FieldType is MonoField.FieldTypeEnum.AssetReference or MonoField.FieldTypeEnum.AssetReferenceArray).ToList(); var tmp_SortedData = tmp_NonSortData.Concat(tmp_NeedSortData).ToList(); tmp_MonoData.Fields = tmp_SortedData; await Task.Delay(50); EditorUtility.ClearProgressBar(); } EditorUtility.SetDirty(_MONO_BINDER); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } catch (Exception tmp_E) { Debug.LogError(tmp_E); EditorUtility.ClearProgressBar(); } } private static void SetMonoFieldType(MonoField _monoField, Type _type) { if (_type == typeof(GameObject)) { _monoField.FieldType = MonoField.FieldTypeEnum.GameObject; } else if (_type == typeof(Component) || _type.IsSubclassOf(typeof(MonoBehaviour))) { _monoField.FieldType = MonoField.FieldTypeEnum.UnityComponent; } else if (_type.IsSubclassOf(typeof(UnityEngine.Object))) { _monoField.FieldType = MonoField.FieldTypeEnum.UnityComponent; } else if (_type == typeof(LayerMask)) { _monoField.FieldType = MonoField.FieldTypeEnum.LayerMask; } else if (_type == typeof(AnimationCurve)) { _monoField.FieldType = MonoField.FieldTypeEnum.AnimationCurve; } else if (_NUM_TYPE.Contains(_type)) { _monoField.FieldType = MonoField.FieldTypeEnum.Number; } else if (_type == typeof(string)) { _monoField.FieldType = MonoField.FieldTypeEnum.String; } else if (_type == typeof(bool)) { _monoField.FieldType = MonoField.FieldTypeEnum.Bool; } else if (_type.IsEnum) { _monoField.FieldType = MonoField.FieldTypeEnum.Enum; } else if (_type == typeof(Vector2)) { _monoField.FieldType = MonoField.FieldTypeEnum.Vector2; } else if (_type == typeof(Vector3)) { _monoField.FieldType = MonoField.FieldTypeEnum.Vector3; } else if (_type == typeof(Vector4)) { _monoField.FieldType = MonoField.FieldTypeEnum.Vector4; } else if (_type == typeof(Quaternion)) { _monoField.FieldType = MonoField.FieldTypeEnum.Quaternion; } else if (_type == typeof(Color)) { _monoField.FieldType = MonoField.FieldTypeEnum.Color; } else if (_type.IsArray || (_type.IsGenericType && typeof(IList).IsAssignableFrom(_type))) { var tmp_ElementType = _type.GetElementType() ?? _type.GenericTypeArguments[0]; _monoField.AssetType = tmp_ElementType.FullName; if (_UNITY_TYPE.Contains(tmp_ElementType)) { Dictionary tmp_TypeActions = new Dictionary() { {typeof(GameObject), MonoField.FieldTypeEnum.GameObjectArray}, {typeof(Texture), MonoField.FieldTypeEnum.TextureArray}, {typeof(Shader), MonoField.FieldTypeEnum.ShaderArray}, {typeof(Sprite), MonoField.FieldTypeEnum.SpriteArray}, {typeof(Material), MonoField.FieldTypeEnum.MaterialArray}, {typeof(MeshRenderer), MonoField.FieldTypeEnum.Components}, {typeof(AnimationClip), MonoField.FieldTypeEnum.AnimationClipArray}, {typeof(Mesh), MonoField.FieldTypeEnum.MeshArray}, {typeof(Color), MonoField.FieldTypeEnum.ColorArray}, {typeof(VideoClip), MonoField.FieldTypeEnum.VideoClipArray}, {typeof(Animator), MonoField.FieldTypeEnum.Components}, {typeof(Collider), MonoField.FieldTypeEnum.Components}, {typeof(AudioClip), MonoField.FieldTypeEnum.AudioClipArray}, {typeof(Transform), MonoField.FieldTypeEnum.Components}, {typeof(ScriptableObject), MonoField.FieldTypeEnum.ScriptableObjectArray}, {typeof(TrailRenderer), MonoField.FieldTypeEnum.Components}, {typeof(LineRenderer), MonoField.FieldTypeEnum.Components}, {typeof(ParticleSystem), MonoField.FieldTypeEnum.Components}, {typeof(Vector3), MonoField.FieldTypeEnum.Vector3Array}, {typeof(Vector2), MonoField.FieldTypeEnum.Vector2Array}, {typeof(Vector4), MonoField.FieldTypeEnum.Vector4Array}, {typeof(Quaternion), MonoField.FieldTypeEnum.QuaternionArray}, {typeof(AnimationCurve), MonoField.FieldTypeEnum.AnimationCurveArray}, {typeof(XRMODBehaviour), MonoField.FieldTypeEnum.Components}, {typeof(MeshFilter), MonoField.FieldTypeEnum.Components}, }; if (tmp_TypeActions.TryGetValue(tmp_ElementType, out var tmp_FieldType)) { _monoField.FieldType = tmp_FieldType; } } else if (tmp_ElementType.IsSubclassOf(typeof(MonoBehaviour)) || tmp_ElementType.IsSubclassOf(typeof(Component))) { _monoField.FieldType = MonoField.FieldTypeEnum.Components; } else if (_NUM_ARRAY_TYPE.Contains(_type)) { _monoField.FieldType = MonoField.FieldTypeEnum.Primitives; } else { _monoField.FieldType = MonoField.FieldTypeEnum.NotSupported; } } else { _monoField.FieldType = MonoField.FieldTypeEnum.NotSupported; } if (string.IsNullOrEmpty(_monoField.AssetType)) _monoField.AssetType = _type.FullName; } private static void CopyDataToMonoField(ref MonoField _monoField, MemberInfo _info, object _instance) { object tmp_Value; var tmp_Type = _info is PropertyInfo tmp_PropertyInfo ? tmp_PropertyInfo.PropertyType : ((FieldInfo) _info).FieldType; if (_instance == null) { tmp_Value = tmp_Type.IsValueType ? Activator.CreateInstance(tmp_Type) : null; } else { if (_info is PropertyInfo tmp_Info) { tmp_Value = tmp_Info.GetValue(_instance); } else { tmp_Value = ((FieldInfo) _info).GetValue(_instance); } // Processed regardless of whether they are Reference values or not. // Auto add assets to package tools for build switch (tmp_Value) { case IList tmp_List: { Dictionary tmp_ObjName = new(); foreach (object tmp_O in tmp_List) { if (tmp_O is not Object tmp_UObj) continue; if (AddAssetToPackageTools(tmp_UObj)) { tmp_ObjName.TryAdd(tmp_UObj.name, tmp_UObj); } } if (tmp_ObjName.Values.Count > 0) { tmp_Value = JsonConvert.SerializeObject(tmp_ObjName.Keys); _monoField.FieldType = MonoField.FieldTypeEnum.AssetReferenceArray; } break; } case Object tmp_AssetObject: { if (AddAssetToPackageTools(tmp_AssetObject)) { tmp_Value = tmp_AssetObject.name; _monoField.FieldType = MonoField.FieldTypeEnum.AssetReference; } break; } } } DataInput(_monoField, tmp_Type, tmp_Value, _instance); } private static bool AddAssetToPackageTools(Object _assetObject) { // Add this gameobject to package tool var tmp_PathStr = AssetDatabase.GetAssetPath(_assetObject); if (string.IsNullOrEmpty(tmp_PathStr)) return false; // Avoid treating nested prefabs as separate resources. var tmp_Extension = Path.GetExtension(tmp_PathStr); var tmp_PathOfAsset = Path.Combine(Path.GetDirectoryName(tmp_PathStr) ?? string.Empty, $"{_assetObject.name}{tmp_Extension}"); if (!File.Exists(Application.dataPath.Replace("Assets", tmp_PathOfAsset))) return false; try { var tmp_ContentList = PackageToolsEditor.ALL_PROJECT_CACHE.GetEditingProjectData() .DetailCacheData.Contents; var tmp_Idx = tmp_ContentList.FindIndex(_content => _content.DisplayName == _assetObject.name); if (tmp_Idx < 0) { tmp_ContentList.Add(new ContentModel { Id = tmp_ContentList.Count, DisplayName = _assetObject.name, AssetPathInUnity = tmp_PathStr, Type = _assetObject.GetType() }); } ContentView.treeRenderer?.Reload(); return true; } catch (Exception tmp_Exception) { Debug.LogError(tmp_Exception); throw; } } private static void DataInput(MonoField _monoField, Type _type, object _value, object _instance) { if (_type == typeof(object)) return; if (_value == null || _value is Exception) return; if (_NUM_TYPE.Contains(_value.GetType()) || _value is string || _value is bool) { string tmp_Value = _value.ToString(); if (tmp_Value.ToLower().Equals("null")) return; _monoField.Value = _value.ToString(); } else { switch (_value) { case Enum: var tmp_UnderlyingType = _value.GetType().GetEnumUnderlyingType(); _monoField.Value = tmp_UnderlyingType == typeof(byte) ? $"{(byte) _value}" : $"{(int) _value}"; break; case LayerMask tmp_LayerMask: _monoField.Value = string.Join(",", Utilities.GetLayerNamesFromMask(tmp_LayerMask)); break; case Vector2 tmp_Vector2: _monoField.Value = tmp_Vector2.Serializer(); break; case Vector3 tmp_Vector3: _monoField.Value = tmp_Vector3.Serializer(); break; case Vector4 tmp_Vector4: _monoField.Value = tmp_Vector4.Serializer(); break; case Quaternion tmp_Quaternion: _monoField.Value = tmp_Quaternion.Serializer(); break; case Color tmp_Color: _monoField.Value = tmp_Color.Serializer(); break; case GameObject tmp_GameObject: _monoField.GameObject = tmp_GameObject; break; // Ignore case Component tmp_Component when _value.ToString().ToLower().Equals("null"): return; case Component tmp_Component: _monoField.GameObject = tmp_Component?.gameObject; break; case AnimationCurve tmp_Curve: _monoField.Value = tmp_Curve.SerializeAnimationCurve(); break; default: if (_type.IsArray || typeof(IList).IsAssignableFrom(_type)) { var tmp_Type = _value.GetType().GetElementType() ?? _value.GetType().GetGenericArguments()[0]; if (tmp_Type.IsSubclassOf(typeof(MonoBehaviour)) || tmp_Type.IsSubclassOf(typeof(Component))) { int tmp_ComponentLength = 0; GameObject[] tmp_ComponentAttached; // Fix issues-89 if (_type.IsGenericType) { var tmp_ComponentArray = _value as IList; tmp_ComponentAttached = new GameObject[tmp_ComponentArray.Count]; int tmp_Idx = 0; foreach (object tmp_obj in tmp_ComponentArray) { tmp_ComponentAttached[tmp_Idx] = tmp_obj.GetGameObject(); tmp_Idx++; } } else { var tmp_ComponentArray = _value as Component[]; tmp_ComponentAttached = tmp_ComponentArray .Select(_component => _component.gameObject).ToArray(); } _monoField.Components = tmp_ComponentAttached; return; } Dictionary> tmp_TypeDictionary = new Dictionary> { {typeof(string), _value => _monoField.Value = MakePrimitiveGenericData(_value)}, {typeof(int), _value => _monoField.Value = MakePrimitiveGenericData(_value)}, {typeof(bool), _value => _monoField.Value = MakePrimitiveGenericData(_value)}, {typeof(float), _value => _monoField.Value = MakePrimitiveGenericData(_value)}, { typeof(GameObject), _value => { if (_value is IList) { var tmp_IGameObjectList = (IList) _value; _monoField.GameObjectArray = new GameObject[tmp_IGameObjectList.Count]; tmp_IGameObjectList.CopyTo(_monoField.GameObjectArray, 0); } else _monoField.GameObjectArray = _value as GameObject[]; } }, {typeof(Transform), _value => _monoField.Components = _value as GameObject[]}, {typeof(Texture2D), _value => _monoField.TextureArray = _value as Texture2D[]}, {typeof(AudioClip), _value => _monoField.AudioClipArray = _value as AudioClip[]}, {typeof(Shader), _value => _monoField.ShaderArray = _value as Shader[]}, {typeof(Sprite), _value => _monoField.SpriteArray = _value as Sprite[]}, {typeof(Material), _value => _monoField.MaterialArray = _value as Material[]}, {typeof(MonoBehaviour), _value => _monoField.Components = _value as GameObject[]}, {typeof(Color), _value => _monoField.ColorArray = _value as Color[]}, {typeof(MeshRenderer), _value => _monoField.Components = _value as GameObject[]}, {typeof(Mesh), _value => _monoField.MeshArray = _value as Mesh[]}, {typeof(VideoClip), _value => _monoField.VideoClipArray = _value as VideoClip[]}, { typeof(AnimationClip), _value => _monoField.AnimationClipArray = _value as AnimationClip[] }, {typeof(Collider), _value => _monoField.Components = _value as GameObject[]}, { typeof(ScriptableObject), _value => _monoField.ScriptableObjectArray = _value as ScriptableObject[] }, {typeof(ParticleSystem), _value => _monoField.Components = _value as GameObject[]}, {typeof(LineRenderer), _value => _monoField.Components = _value as GameObject[]}, {typeof(TrailRenderer), _value => _monoField.Components = _value as GameObject[]}, { typeof(AnimationCurve), _value => _monoField.AnimationCurveArray = _value as AnimationCurve[] }, {typeof(MeshFilter), _value => _monoField.Components = _value as GameObject[]}, {typeof(XRMODBehaviour), _value => _monoField.Components = _value as GameObject[]}, }; if (tmp_TypeDictionary.ContainsKey(tmp_Type)) { var tmp_IList = _value is IList; tmp_TypeDictionary[tmp_Type](tmp_IList ? (IList) _value : _value); } } break; } } } private static string MakePrimitiveGenericData(object _value) { var tmp_SystemObject = new GenericPrimitiveObject { List = _value as List, ListType = typeof(T).ToString() }; return JsonUtility.ToJson(tmp_SystemObject); } private static void ModifyTemplateScript(BaseNotificationData _data) { //Get all monoBinder scripts from prefab, //then change the script's field of namespace to specify project name var tmp_Data = _data.BaseData.Split('|'); //Path|ProjectName var tmp_PrefabPath = tmp_Data[0]; if (Directory.Exists(tmp_PrefabPath)) { var tmp_Files = Directory.GetFiles(Path.Combine(Application.dataPath.Replace("Assets", ""), tmp_PrefabPath), "*.prefab", SearchOption.TopDirectoryOnly); foreach (string tmp_File in tmp_Files) { var tmp_Prefab = AssetDatabase.LoadAssetAtPath(ShortenPath(tmp_File)); List tmp_MonoBinders = new List(); tmp_MonoBinders.AddRange(tmp_Prefab.GetComponents()); tmp_MonoBinders.AddRange(tmp_Prefab.GetComponentsInChildren()); foreach (MonoBinder tmp_MonoBinder in tmp_MonoBinders) { foreach (MonoData tmp_MonoData in tmp_MonoBinder.ScriptList) { tmp_MonoData.ClassNamespace = tmp_Data[1]; } } } } } private static string ShortenPath(string _fullPath) { int tmp_SubStringStartPos = _fullPath.IndexOf("Assets", StringComparison.Ordinal); return _fullPath.Substring(tmp_SubStringStartPos, _fullPath.Length - tmp_SubStringStartPos); } private void MakeSureUnityObjectField(Rect fieldRect, ref SerializedProperty unityObjectsProperty) { EditorGUI.indentLevel = 0; EditorGUI.PropertyField( new Rect(fieldRect.x, fieldRect.y, fieldRect.width, EditorGUIUtility.singleLineHeight), unityObjectsProperty); } } }