// // /*=============================================================================== // // Copyright (C) 2025 PhantomsXR Ltd. All Rights Reserved. // // // // This file is part of the Phantom.XRMOD.UnityFusion.Runtime.CodeHook. // // // // The QuestPlatform 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 System.Reflection; using TMPro; using Unity.AI.Navigation; using UnityEngine; using UnityEngine.AI; using UnityEngine.Animations; using UnityEngine.Assertions; using UnityEngine.Rendering; using UnityEngine.UI; using UnityEngine.Video; using UnityFusion.Reflection; using UnityFusion.Runtime.Enviorment; using UnityFusion.Runtime.Intepreter; namespace Phantom.XRMOD.UnityFusion.Runtime.CodeHook { public static class MonoBinderUtils { private const BindingFlags _CONST_ALL_BINDING_FLAGS = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; public static bool GetComponent(GameObject _go, 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 = GetGameObjectFields(_reflectionType, _field); if (tmp_GO == null) return true; var tmp_FieldInfo = _reflectionType?.GetField(_field.FieldName, _CONST_ALL_BINDING_FLAGS); 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 || tmp_CrossBindingAdaptorType.ILInstance.Type.BaseType.Name == tmp_FieldTypeName) { _obj = tmp_CrossBindingAdaptorType.ILInstance; break; } } return true; } 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; return true; } } else { var tmp_PropertyInfo = _reflectionType?.GetProperty(_field.FieldName, _CONST_ALL_BINDING_FLAGS); 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; break; } } else { var tmp_Component = tmp_GO.GetComponents().ToList() .Find(_component => _component.GetType().ToString().Contains(tmp_PropertyTypeName)); if (!tmp_Component) return false; _obj = tmp_Component; return true; } } else { Debug.LogError( $"Auto binding {_go.name} was error:{_classPath}.{_field.FieldName} assignment error:{_field.FieldName} was not exist!"); } } return false; } public static bool GetComponents(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, _CONST_ALL_BINDING_FLAGS); try { if (tmp_FieldInfo != null) { tmp_IsListType = typeof(IList).IsAssignableFrom(tmp_FieldInfo.FieldType) && tmp_FieldInfo.FieldType.IsGenericType; tmp_CastType = tmp_FieldInfo.FieldType.IsArray || tmp_IsListType ? 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_FusionType) { var tmp_CrossBindingAdaptorTypes = tmp_GameObject.GetComponents(); var tmp_Adapters = tmp_CrossBindingAdaptorTypes.Where(_apterType => { var tmp_ILType = _apterType.ILInstance.Type; return tmp_ILType.Name == tmp_FieldTypeName || tmp_ILType.ReflectionType.IsSubclassOf(tmp_FusionType); }) .Select(_adapterType => _adapterType.ILInstance).ToList(); tmp_Objects.AddRange(tmp_Adapters); } else if (tmp_CastType.GetInterfaces().Contains(typeof(CrossBindingAdaptorType))) { var tmp_CrossBindingAdaptorTypes = tmp_GameObject.GetComponents(); var tmp_Adapters = tmp_CrossBindingAdaptorTypes.Where(_apterType => { var tmp_ILType = _apterType.ILInstance.Type; return tmp_ILType.TypeForCLR.Name == tmp_FieldTypeName; }) .Select(_adapterType => _adapterType.ILInstance).ToList(); tmp_Objects.AddRange(tmp_Adapters); } else { // Builtin component types var tmp_Components = tmp_GameObject.GetComponents(tmp_CastType); if (tmp_Components.Length > 0) { tmp_ObjectsComponents.AddRange(tmp_Components); tmp_CastType = tmp_Components[0].GetType(); } } } else { // For properties 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 {tmp_GameObject.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(); return true; } if (tmp_ObjectsComponents is not {Count: > 0}) return false; 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(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