private static object GetFieldOwner(ReplaceUnit replaceUnit, GameObject root) { object fieldOwner = null; FieldInformation fieldInformation = replaceUnit.fieldInformation; Type monoType = fieldInformation.FieldOwnerType; Component mono = FabulousExtensions .GetGameObjectAtAddress(root, replaceUnit.MonoAddress) .GetComponent(monoType); if (mono == null) { throw new NullReferenceException($"Failed to find mono {monoType} for field {fieldInformation.FieldName} and type {fieldInformation.FieldType} by its address for prefab: {root} at path {replaceUnit.prefabPath} and address {string.Join(",", replaceUnit.MonoAddress.ToArray())}"); } if (fieldInformation.FieldType.HasOneOfTheFlags(FieldType.Nested | FieldType.External)) { ExternallyOwnedFieldInformation eofi = fieldInformation.GetFieldInformationParamter <ExternallyOwnedFieldInformation>(); FieldInfo externalObjectFieldInfo = monoType.GetField(eofi.ExternalOwnerFieldName, ReferenceFinder.GENEROUS_NONSTATIC_FIELD_SEARCH_FLAGS); if (eofi.fieldInformation.FieldType.HasOneOfTheFlags(FieldType.Arrayed | FieldType.Listed)) { var efi = eofi.fieldInformation.GetFieldInformationParamter <EnumerableFieldInformation>(); IEnumerable enumberableOwner = (IEnumerable)externalObjectFieldInfo.GetValue(mono); int index = 0; foreach (var item in enumberableOwner) { if (index == efi.index) { fieldOwner = item; } index++; } } else { fieldOwner = externalObjectFieldInfo.GetValue(mono); } } else { fieldOwner = mono; } return(fieldOwner); }
// ::::::::::::::help me::::: // ____.∧__∧::::::::::::::::: // ___(<'º yº) =3 ::::::🖥�::: // ___/  ⌒ヽ⊃� :::|===|:: // _�(人__�_�.:::::|===|:: // ___FAT IS GOOD____________ public static bool IsReferencingComponentOfType <T>(this object someObject, T component, ref List <FieldInformation> referencingFields) where T : Component { List <FieldInformation> methodLocalReferencingFields = null; FieldInformation fieldInformation; IterateOverFieldsOfType <T>( owner: someObject, onTypeMatchingField: (fieldOwner, fieldInfo, fieldValue) => { if (fieldValue == component) { Type fieldOwnerType = fieldOwner.GetType(); fieldInformation = new FieldInformation(fieldInfo.Name, fieldOwnerType); fieldInformation.FieldType = FieldType.Direct; if (fieldInfo.FieldType.IsGenericType) { if (fieldInfo.FieldType.GetGenericTypeDefinition() == typeof(List <>)) { //* This means text field is hidden within a list fieldInformation.FieldType |= FieldType.Listed; var list = (List <T>)fieldInfo.GetValue(fieldOwner); EnumerableFieldInformation efi = ScriptableObject.CreateInstance <EnumerableFieldInformation>(); efi.index = list.IndexOf(fieldValue); efi.length = list.Count; fieldInformation.AddFieldInformationParameter(efi); } } else if (fieldInfo.FieldType.IsArray) { //* This means text field is hidden within an array fieldInformation.FieldType |= FieldType.Arrayed; var array = (T[])fieldInfo.GetValue(fieldOwner); EnumerableFieldInformation efi = ScriptableObject.CreateInstance <EnumerableFieldInformation>(); efi.index = Array.IndexOf(array, fieldValue); efi.length = array.Length; fieldInformation.AddFieldInformationParameter(efi); } if (methodLocalReferencingFields == null) { methodLocalReferencingFields = new List <FieldInformation>(); } methodLocalReferencingFields.Add(fieldInformation); } }, onCustomClass: (fieldOwner, fieldInfo) => { //! follow the white rabbit List <FieldInformation> externalFieldsInformation = null; if (fieldOwner.IsReferencingComponentOfType(component, ref externalFieldsInformation)) { if (externalFieldsInformation == null) { Debug.LogError("oof"); } foreach (FieldInformation externalField in externalFieldsInformation) { ExternallyOwnedFieldInformation eofi = ScriptableObject.CreateInstance <ExternallyOwnedFieldInformation>(); eofi.fieldInformation = new FieldInformation(fieldInfo.Name, someObject.GetType()); if (fieldInfo.FieldType.IsGenericType && fieldInfo.FieldType.GetGenericTypeDefinition() == typeof(List <>)) { eofi.fieldInformation.FieldType |= FieldType.Listed; var list = (IList)fieldInfo.GetValue(someObject); EnumerableFieldInformation efi = ScriptableObject.CreateInstance <EnumerableFieldInformation>(); efi.index = list.IndexOf(fieldOwner); efi.length = list.Count; eofi.fieldInformation.AddFieldInformationParameter(efi); } else if (fieldInfo.FieldType.IsArray) { eofi.fieldInformation.FieldType |= FieldType.Arrayed; var array = (Array)fieldInfo.GetValue(someObject); EnumerableFieldInformation efi = ScriptableObject.CreateInstance <EnumerableFieldInformation>(); efi.index = Array.IndexOf(array, fieldOwner); efi.length = array.Length; eofi.fieldInformation.AddFieldInformationParameter(efi); } else { eofi.fieldInformation.FieldType = FieldType.Direct; } eofi.ExternalOwnerFieldName = fieldInfo.Name; //! Note that this might be a problem in case of inherited fields, check it eofi.ExternalOwnerType = someObject.GetType(); eofi.ExternalOwnerAssemblyName = someObject.GetType().AssemblyQualifiedName; externalField.AddFieldInformationParameter(eofi); FieldType fieldType = externalField.FieldType; fieldType &= ~FieldType.Direct; if (fieldOwner.GetType().IsNested) { //* This means a nested class fieldType |= FieldType.Nested; } else { //* This means an external class is a field that holds reference to the text component fieldType |= FieldType.External; } externalField.FieldType = fieldType; } if (methodLocalReferencingFields == null) { methodLocalReferencingFields = new List <FieldInformation>(); } methodLocalReferencingFields.AddRange(externalFieldsInformation); } }, includeParnetMonoFields: true); if (methodLocalReferencingFields != null) { referencingFields = methodLocalReferencingFields; return(true); } else { return(false); } }