Ejemplo n.º 1
0
        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);
            }
        }