// /*=============================================================================== // 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.Linq; using UnityEngine; using System.Reflection; using System.Threading.Tasks; using LitJson; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using UnityFusion.Reflection; using UnityEngine.Assertions; using UnityFusion.CLR.TypeSystem; using UnityFusion.CLRBinding.Adapter; using UnityFusion.Runtime.Enviorment; using UnityFusion.Runtime.Intepreter; using Phantom.XRMOD.XRMODPackageTools.Runtime; using Phantom.XRMOD.Core.Runtime; using AppDomain = UnityFusion.Runtime.Enviorment.AppDomain; using Object = UnityEngine.Object; using Phantom.XRMOD.ActionNotification.Runtime; using Phantom.XRMOD.Core.Runtime.Attribute; using Phantom.XRMOD.UnityFusion.Runtime.CodeHook.ICommand; using TMPro; using Unity.AI.Navigation; using UnityEngine.AI; using UnityEngine.Animations; using UnityEngine.Audio; using UnityEngine.Playables; using UnityEngine.Rendering; using UnityEngine.U2D; using UnityEngine.UI; using UnityEngine.Video; using TextMesh = UnityEngine.TextMesh; namespace Phantom.XRMOD.UnityFusion.Runtime.CodeHook { public class MonoBinder : MonoBehaviour { public List ScriptList; public RenderStateType DefaultRenderState = RenderStateType.None; private const BindingFlags AllBindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; private static readonly Type[] _TYPES_TO_CHECK = { 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_0_OR_NEWER 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) }; public async Task SetValues(MonoData _data) { // When the it has not fields we just set it to Bounded. if (_data.Fields.Count == 0) { _data.BoundData = true; return; } string tmp_ClassPath = $"{_data.ClassNamespace + (string.IsNullOrEmpty(_data.ClassName) ? "" : ".")}{_data.ClassName}"; Type tmp_Type = _data.ClassType; //Can not direct accessing the MonoBehaviour, Because they are difference of the type. //So we need accessing the `CrossBindingAdaptorType` first. // var tmp_ClrInstance = gameObject.GetComponents() // .Last(_clr => _clr.ILInstance.Type == tmp_Type as ILType); var tmp_ClrInstance = _data.ClrInstance; Assert.IsNotNull(tmp_ClrInstance, $"{_data.ClassName}"); _data.BoundData = false; var tmp_Fields = _data.Fields.ToArray(); var tmp_ProjectName = _data.ClassNamespace.Split(".")[0]; foreach (MonoField tmp_Field in tmp_Fields) { if (tmp_Field.FieldType == MonoField.FieldTypeEnum.NotSupported) continue; object tmp_Obj = null; switch (tmp_Field.FieldType) { case MonoField.FieldTypeEnum.Number: if (string.IsNullOrEmpty(tmp_Field.Value)) continue; tmp_Obj = FillInNumberFields(tmp_Type, tmp_Field, _data); break; case MonoField.FieldTypeEnum.String: if (string.IsNullOrEmpty(tmp_Field.Value)) continue; tmp_Obj = tmp_Field.Value; _data.BoundData = true; break; case MonoField.FieldTypeEnum.Bool: tmp_Obj = tmp_Field.Value.ToLower() == "true"; _data.BoundData = true; break; case MonoField.FieldTypeEnum.GameObject: if (tmp_Field.GameObject == null) continue; tmp_Obj = FillInGameObjectFields(tmp_Type, tmp_Field, _data); _data.BoundData = true; break; case MonoField.FieldTypeEnum.UnityComponent: if (tmp_Field.GameObject == null) continue; if (FillInUnityComponent(tmp_Field.GameObject, _data, tmp_Field, tmp_Type, tmp_ClassPath, out tmp_Obj)) continue; break; case MonoField.FieldTypeEnum.AssetReference: if (tmp_Field.Value == null) continue; if (CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDb)) { #region Load Assets if (tmp_Field.AssetType == typeof(Texture2D).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(Sprite).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(AudioClip).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(VideoClip).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(TextAsset).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(GameObject).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(Mesh).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(PhysicsMaterial2D).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(PhysicsMaterial).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(ComputeShader).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(AudioMixer).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(Animator).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(RenderTexture).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(Shader).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(Material).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(Cubemap).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } else if (tmp_Field.AssetType == typeof(SpriteAtlas).FullName) { tmp_AssetReferenceDb.GetAssetReference(tmp_Field.Value, out var tmp_Asset); tmp_Obj = tmp_Asset; } #endregion if (tmp_Obj == null) continue; _data.BoundData = true; MakeSureValue(tmp_Type, tmp_Field, tmp_Obj, tmp_ClrInstance, tmp_ClassPath); } continue; case MonoField.FieldTypeEnum.AssetReferenceArray: if (tmp_Field.Value == null) continue; //Loading the asset from xr experience package. var tmp_LoadAssetNames = JsonConvert.DeserializeObject>(tmp_Field.Value).ToArray(); if (tmp_Field.AssetType == typeof(GameObject).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(Sprite).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(AudioClip).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(VideoClip).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(TextAsset).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(Texture2D).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(Material).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(Mesh).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(RenderTexture).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(AnimationClip).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(AudioMixer).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(Cubemap).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(Shader).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(SpriteAtlas).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(Animator).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(ComputeShader).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(PhysicsMaterial).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } else if (tmp_Field.AssetType == typeof(PhysicsMaterial2D).FullName) { CodesHook.AssetReferences.TryGetValue(tmp_ProjectName, out var tmp_AssetReferenceDatabase); tmp_AssetReferenceDatabase.GetAssetReferences(tmp_LoadAssetNames, out var tmp_AssetReferences); tmp_Obj = tmp_AssetReferences; } if (tmp_Obj == null) continue; _data.BoundData = true; MakeSureValue(tmp_Type, tmp_Field, tmp_Obj, tmp_ClrInstance, tmp_ClassPath); continue; case MonoField.FieldTypeEnum.Enum: if (string.IsNullOrEmpty(tmp_Field.Value)) continue; tmp_Obj = int.Parse(tmp_Field.Value); _data.BoundData = true; break; case MonoField.FieldTypeEnum.LayerMask: if (string.IsNullOrEmpty(tmp_Field.Value)) continue; tmp_Obj = LayerMask.GetMask(tmp_Field.Value.Split(",")); _data.BoundData = true; break; case MonoField.FieldTypeEnum.Vector2: if (string.IsNullOrEmpty(tmp_Field.Value)) continue; tmp_Obj = JsonUtility.FromJson(tmp_Field.Value).ToVector2(); _data.BoundData = true; break; case MonoField.FieldTypeEnum.Vector3: if (string.IsNullOrEmpty(tmp_Field.Value)) continue; tmp_Obj = JsonUtility.FromJson(tmp_Field.Value).ToVector3(); _data.BoundData = true; break; case MonoField.FieldTypeEnum.Vector4: if (string.IsNullOrEmpty(tmp_Field.Value)) continue; tmp_Obj = JsonUtility.FromJson(tmp_Field.Value).ToVector4(); _data.BoundData = true; break; case MonoField.FieldTypeEnum.Quaternion: if (string.IsNullOrEmpty(tmp_Field.Value)) continue; var tmp_V4 = JsonUtility.FromJson(tmp_Field.Value).ToVector4(); tmp_Obj = new Quaternion(tmp_V4.x, tmp_V4.y, tmp_V4.z, tmp_V4.w); _data.BoundData = true; break; case MonoField.FieldTypeEnum.Color: if (string.IsNullOrEmpty(tmp_Field.Value)) continue; if (ColorUtility.TryParseHtmlString(tmp_Field.Value, out var tmp_Color)) tmp_Obj = tmp_Color; else { Debug.LogError("Unavailable color value, correct format: #RRGGBBAA"); tmp_Obj = tmp_Field.Value; } _data.BoundData = true; break; case MonoField.FieldTypeEnum.AnimationCurve: if (string.IsNullOrEmpty(tmp_Field.Value)) continue; tmp_Obj = tmp_Field.Value.DeserializeAnimationCurve(); _data.BoundData = true; break; case MonoField.FieldTypeEnum.DataProperty: if (string.IsNullOrEmpty(tmp_Field.Value)) continue; tmp_Obj = tmp_Field.Value; MakeSureValue(tmp_Type, tmp_Field, tmp_Obj, tmp_ClrInstance, tmp_ClassPath); _data.BoundData = true; continue; #region Array case MonoField.FieldTypeEnum.Primitives: if (string.IsNullOrEmpty(tmp_Field.Value)) continue; // ReSharper disable once ConvertTypeCheckToNullCheck if (tmp_Field.Value.Contains(typeof(string).ToString())) tmp_Obj = JsonUtility.FromJson>(tmp_Field.Value).List; #pragma warning disable CS0184 else if (tmp_Field.Value.Contains(typeof(int).ToString())) #pragma warning restore CS0184 tmp_Obj = JsonUtility.FromJson>(tmp_Field.Value).List; #pragma warning disable CS0184 else if (tmp_Field.Value.Contains(typeof(bool).ToString())) #pragma warning disable CS0184 tmp_Obj = JsonUtility.FromJson>(tmp_Field.Value).List; #pragma warning disable CS0184 else if (tmp_Field.Value.Contains(typeof(float).ToString())) #pragma warning disable CS0184 tmp_Obj = JsonUtility.FromJson>(tmp_Field.Value).List; _data.BoundData = true; break; case MonoField.FieldTypeEnum.Components: if (FillInUnityComponents(_data, tmp_Field, tmp_Type, tmp_ClassPath, out tmp_Obj)) continue; break; case MonoField.FieldTypeEnum.GameObjectArray: tmp_Obj = tmp_Field.GameObjectArray; _data.BoundData = true; break; case MonoField.FieldTypeEnum.AudioClipArray: tmp_Obj = tmp_Field.AudioClipArray; _data.BoundData = true; break; case MonoField.FieldTypeEnum.TextureArray: tmp_Obj = tmp_Field.TextureArray; _data.BoundData = true; break; case MonoField.FieldTypeEnum.AnimationClipArray: tmp_Obj = tmp_Field.AnimationClipArray; _data.BoundData = true; break; case MonoField.FieldTypeEnum.ShaderArray: tmp_Obj = tmp_Field.ShaderArray; _data.BoundData = true; break; case MonoField.FieldTypeEnum.SpriteArray: tmp_Obj = tmp_Field.SpriteArray; _data.BoundData = true; break; case MonoField.FieldTypeEnum.MaterialArray: tmp_Obj = tmp_Field.MaterialArray; _data.BoundData = true; break; case MonoField.FieldTypeEnum.ColorArray: tmp_Obj = tmp_Field.ColorArray; _data.BoundData = true; break; case MonoField.FieldTypeEnum.MeshArray: tmp_Obj = tmp_Field.MeshArray; _data.BoundData = true; break; case MonoField.FieldTypeEnum.VideoClipArray: tmp_Obj = tmp_Field.VideoClipArray; _data.BoundData = true; break; case MonoField.FieldTypeEnum.ScriptableObjectArray: tmp_Obj = tmp_Field.ScriptableObjectArray; _data.BoundData = true; break; #endregion case MonoField.FieldTypeEnum.NotSupported: Debug.LogError("Type not support."); break; } if (_data.BoundData) MakeSureValue(tmp_Type, tmp_Field, tmp_Obj, tmp_ClrInstance, tmp_ClassPath); } } private void MakeSureValue(Type _type, MonoField _field, object _value, CrossBindingAdaptorType _target, string _classPath) { var tmp_FieldInfo = _type.GetField(_field.FieldName, AllBindingFlags); if (tmp_FieldInfo != null && _value != null) { if (_field.FieldType == MonoField.FieldTypeEnum.DataProperty) { var tmp_DeserializedDataPropertyMethod = _type.GetMethod( $"DeserializedDataProperty_{_field.FieldName}", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (tmp_DeserializedDataPropertyMethod == null) return; var tmp_Result = tmp_DeserializedDataPropertyMethod.Invoke(_target.ILInstance, new object[] {_value}); var tmp_FieldOfInstance = _type.GetField(_field.FieldName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic); if (tmp_FieldOfInstance != null && tmp_FieldOfInstance.IsDefined(typeof(DataPropertyAttribute), true)) { if (!tmp_FieldOfInstance.IsPublic && !tmp_FieldOfInstance.IsDefined(typeof(SerializeField), true)) return; tmp_FieldOfInstance.SetValue(_target.ILInstance, tmp_Result); } } else { MakeSureValueFactory.MakeSureValue(ref tmp_FieldInfo, _target.ILInstance, _value); } } else { var tmp_PropertyInfo = _type.GetProperty(_field.FieldName, AllBindingFlags); if (tmp_PropertyInfo != null) { tmp_PropertyInfo.SetValue(_target.ILInstance, _value); } else { Debug.LogWarning( $"[Convert Error]:The {_classPath}.{_field.FieldName} field on {name} lost data.This may cause some bugs."); } } } public void AddRuntimeClass(MonoData _data) { if (DefaultRenderState == RenderStateType.None) { DefaultRenderState = gameObject.activeSelf ? RenderStateType.Visiable : RenderStateType.Hiden; } string tmp_ClassPath = $"{_data.ClassNamespace}.{_data.ClassName}"; if (!CodesHook.GetAppDomain.LoadedTypes.TryGetValue(tmp_ClassPath, out var tmp_Type)) { //Debug.LogError($"Auto binding {name} was error:{tmp_ClassPath} not exist - Skipped"); return; } Type tmp_ReflectionType = tmp_Type.ReflectionType; if (tmp_ReflectionType == null) return; _data.ClassType = tmp_ReflectionType; if (tmp_ReflectionType.BaseType == null) return; Type tmp_BaseType = tmp_ReflectionType.BaseType.BaseType is UnityFusionWrapperType tmp_WrapperType ? tmp_WrapperType.RealType : tmp_ReflectionType.BaseType; Type tmp_MonoType = typeof(MonoBehaviour); bool tmp_IsMono = tmp_ReflectionType.IsSubclassOf(tmp_MonoType) || (tmp_BaseType != null && tmp_BaseType.IsSubclassOf(tmp_MonoType)); bool tmp_NeedAdapter = tmp_BaseType != null && tmp_BaseType.GetInterfaces().Contains(typeof(CrossBindingAdaptorType)); ILTypeInstance tmp_ILInstance = tmp_IsMono ? new ILTypeInstance(tmp_Type as ILType, false) : CodesHook.GetAppDomain.Instantiate(tmp_ClassPath); tmp_ILInstance.CLRInstance = tmp_ILInstance; gameObject.SetActive(false); //Use this after generating adapters for cross-domain inheritance after multiple inheritance of the main project if (tmp_NeedAdapter && tmp_IsMono && tmp_BaseType.FullName != typeof(XRMODBehaviourAdapter.Adapter).FullName) { Type tmp_AdapterType = null; foreach (Assembly tmp_Assembly in System.AppDomain.CurrentDomain.GetAssemblies()) { var tmp_ComponentType = tmp_Assembly.GetType(tmp_ReflectionType.BaseType?.FullName ?? String.Empty); if (tmp_ComponentType == null) continue; tmp_AdapterType = tmp_ComponentType; break; } if (tmp_AdapterType == null) { Debug.LogError($"{tmp_ReflectionType.BaseType?.FullName} need to generate adapter."); return; } var tmp_AdapterComponent = gameObject.AddComponent(tmp_AdapterType); var tmp_ILInstanceInfo = tmp_ReflectionType.GetFields(AllBindingFlags) .First(f => f.Name == "instance" && f.FieldType == typeof(ILTypeInstance)); var tmp_AppDomainInfo = tmp_ReflectionType.GetFields(AllBindingFlags) .First(f => f.Name == "appdomain" && f.FieldType == typeof(AppDomain)); tmp_ILInstanceInfo.SetValue(tmp_AdapterComponent, tmp_ILInstance); tmp_AppDomainInfo.SetValue(tmp_AdapterComponent, CodesHook.GetAppDomain); tmp_ILInstance.CLRInstance = tmp_AdapterComponent; _data.ClrInstance = (CrossBindingAdaptorType) tmp_AdapterComponent; _data.Added = true; Utility.InvokeConstructor(tmp_ILInstance, tmp_Type); } else { if (tmp_BaseType is {IsAbstract: true}) { if (tmp_BaseType.IsGenericType && tmp_IsMono) { new InitMonoBehaviourAdapter(gameObject, tmp_ILInstance, _data, tmp_Type).Execute(); } } if (tmp_BaseType == null) return; if (tmp_BaseType.BaseType != null && (tmp_BaseType.IsSubclassOf(typeof(XRMODBehaviour)) || tmp_BaseType.FullName == typeof(XRMODBehaviourAdapter.Adapter).FullName)) { new InitMonoBehaviourAdapter(gameObject, tmp_ILInstance, _data, tmp_Type).Execute(); } else if ((tmp_BaseType.IsSubclassOf(typeof(UIMonoBehaviour)) || tmp_BaseType.FullName == typeof(UIBehaviourAdaptor.Adapter).FullName)) { new InitUIMonoBehaviourAdaptor(gameObject, tmp_ILInstance, _data, tmp_Type).Execute(); } else { ActionNotificationCenter.DefaultCenter.PostNotification(nameof(AddRuntimeClass), new BaseNotificationData() { BaseData = tmp_BaseType.FullName, }); } } } public void Active(MonoData _data) { string tmp_FullClassName = $"{_data.ClassNamespace + (_data.ClassNamespace == "" ? "" : ".")}{_data.ClassName}"; IType tmp_LoadedType = CodesHook.GetAppDomain.LoadedTypes[tmp_FullClassName]; Type tmp_ReflectionType = tmp_LoadedType.ReflectionType; var tmp_ClrInstance = gameObject.GetComponents() .Last(_clr => _clr.ILInstance.Type == tmp_LoadedType as ILType); if (_data.BoundData == false && _data.Fields != null && _data.Fields.Count > 0) { Debug.LogWarning( $"[Convert Error]:The {tmp_FullClassName} script on {name} lost data.This may cause some bugs."); } //Mono类型能设置enabled if (tmp_ClrInstance.GetType().IsSubclassOf(typeof(MonoBehaviour))) { ((MonoBehaviour) tmp_ClrInstance).enabled = true; } _data.Activated = true; } public void Remove() { if (gameObject.scene.IsValid()) Destroy(this); else DestroyImmediate(this, true); } public void SetupGameObjectRenderState(bool _render) { gameObject.SetActive(_render); } private bool FillInUnityComponent(GameObject _go, MonoData _data, MonoField _field, Type _reflectionType, string _classPath, out object _obj) { _obj = null; GameObject tmp_GO = _go; if (string.IsNullOrEmpty(_field.Value) && tmp_GO == null) return true; if (tmp_GO == null) tmp_GO = FillInGameObjectFields(_reflectionType, _field, _data); if (tmp_GO == null) return true; var tmp_FieldInfo = _reflectionType?.GetField(_field.FieldName, AllBindingFlags); if (tmp_FieldInfo != null) { string tmp_FieldTypeName = tmp_FieldInfo.FieldType.Name; if (tmp_FieldInfo.FieldType is UnityFusionType) { var tmp_Components = tmp_GO.GetComponents(); foreach (CrossBindingAdaptorType tmp_CrossBindingAdaptorType in tmp_Components) { if (tmp_CrossBindingAdaptorType.ILInstance.Type.Name == tmp_FieldTypeName) { _obj = tmp_CrossBindingAdaptorType.ILInstance; _data.BoundData = true; break; } } } else { var tmp_Components = tmp_GO.GetComponents().ToList(); var tmp_Component = tmp_Components.Find(_component => { if (_component == null) return false; return _component.GetType().Name == tmp_FieldTypeName || _component.GetType().IsAssignableFrom(tmp_FieldInfo.FieldType) || tmp_FieldInfo.FieldType.IsInstanceOfType(_component); }); if (!tmp_Component) return false; _obj = tmp_Component; _data.BoundData = true; } } else { var tmp_PropertyInfo = _reflectionType?.GetProperty(_field.FieldName, AllBindingFlags); if (tmp_PropertyInfo != null) { string tmp_PropertyTypeName = tmp_PropertyInfo.PropertyType.Name; if (tmp_PropertyInfo.PropertyType is UnityFusionType) { var tmp_Components = tmp_GO.GetComponents(); foreach (CrossBindingAdaptorType tmp_CrossBindingAdaptorType in tmp_Components) { if (tmp_CrossBindingAdaptorType.ILInstance.Type.Name != tmp_PropertyTypeName) continue; _obj = tmp_CrossBindingAdaptorType.ILInstance; _data.BoundData = true; break; } } else { var tmp_Component = tmp_GO.GetComponents().ToList() .Find(_component => _component.GetType().ToString().Contains(tmp_PropertyTypeName)); if (tmp_Component) { _obj = tmp_Component; _data.BoundData = true; } } } else { Debug.LogError( $"Auto binding {name} was error:{_classPath}.{_field.FieldName} assignment error:{_field.FieldName} was not exist!"); } } return false; } private bool FillInUnityComponents(MonoData _data, MonoField _field, Type _reflectionType, string _classPath, out object _obj) { List tmp_Objects = new(); List tmp_ObjectsComponents = new(); _obj = null; bool tmp_IsListType = false; Type tmp_CastType = null; foreach (GameObject tmp_GameObject in _field.Components) { if (string.IsNullOrEmpty(_field.Value) && tmp_GameObject == null) return true; Assert.IsNotNull(tmp_GameObject, "Element is Empty"); if (tmp_GameObject == null) return true; var tmp_FieldInfo = _reflectionType?.GetField(_field.FieldName, AllBindingFlags); try { if (tmp_FieldInfo != null) { tmp_IsListType = typeof(IList).IsAssignableFrom(tmp_FieldInfo.FieldType) && tmp_FieldInfo.FieldType.IsGenericType; tmp_CastType = tmp_FieldInfo.FieldType.IsArray || tmp_FieldInfo.FieldType.IsGenericType ? tmp_FieldInfo.FieldType.IsGenericType ? tmp_FieldInfo.FieldType.GenericTypeArguments[0] : tmp_FieldInfo.FieldType.GetElementType() : tmp_FieldInfo.FieldType; string tmp_FieldTypeName = tmp_CastType.Name; if (tmp_CastType is UnityFusionType) { tmp_Objects.AddRange(tmp_GameObject.GetComponents() .Where(_adaptorType => _adaptorType.ILInstance.Type.Name == tmp_FieldTypeName) .Select(_adaptorType => _adaptorType.ILInstance).ToList()); } else { var tmp_Components = tmp_GameObject.GetComponents(tmp_CastType); tmp_ObjectsComponents.AddRange(tmp_Components); } } else { var tmp_PropertyInfo = _reflectionType?.GetProperty(_field.FieldName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); if (tmp_PropertyInfo != null) { tmp_CastType = tmp_PropertyInfo.PropertyType; tmp_IsListType = typeof(IList).IsAssignableFrom(tmp_CastType) && tmp_CastType.IsGenericType; string tmp_PropertyTypeName = tmp_CastType.Name; if (tmp_CastType is UnityFusionType) { var tmp_Components = tmp_GameObject.GetComponents(); tmp_Objects.AddRange(tmp_Components.Where(_component => _component.ILInstance.Type.Name == tmp_PropertyTypeName) .Select(_component => _component.ILInstance) .ToList()); } else { tmp_ObjectsComponents.AddRange(tmp_GameObject.GetComponents(tmp_CastType)); } } else { Debug.LogError( $"Auto binding {name} was error:{_classPath}.{_field.FieldName} assignment error:{_field.FieldName} was not exist!"); } } } catch (Exception tmp_Exception) { Debug.LogError(tmp_Exception); } } if (tmp_Objects is {Count: > 0}) { _obj = tmp_IsListType ? tmp_Objects : tmp_Objects.ToArray(); _data.BoundData = true; } if (tmp_ObjectsComponents is {Count: > 0}) { if (tmp_CastType == typeof(MeshFilter)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(MeshRenderer)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(SkinnedMeshRenderer)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(TextMeshPro)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(Transform)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(LineRenderer)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(TrailRenderer)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(MonoBehaviour)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(SpriteRenderer)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(SortingGroup)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(ReflectionProbe)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(NavMeshAgent)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(NavMeshObstacle)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(NavMeshLink)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(Image)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(Text)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(Slider)) { var tmp_Casted = tmp_ObjectsComponents.Cast(); _obj = tmp_IsListType ? tmp_Casted.ToList() : tmp_Casted.ToArray(); } else if (tmp_CastType == typeof(Button)) { var tmp_Casted = tmp_ObjectsComponents.Cast