Exemplo n.º 1
0
        private static string GetAdapterGameObjectName(FieldInformation fieldInformation)
        {
            string adapterName = "";

            if (fieldInformation.FieldType.HasOneOfTheFlags(FieldType.Nested | FieldType.External))
            {
                var eofi = fieldInformation.GetFieldInformationParamter <ExternallyOwnedFieldInformation>();

                adapterName += $"{eofi.fieldInformation.FieldName}_";

                if (eofi.fieldInformation.FieldType.HasOneOfTheFlags(FieldType.Arrayed | FieldType.Listed))
                {
                    var efi = eofi.fieldInformation.GetFieldInformationParamter <EnumerableFieldInformation>();
                    adapterName += $"i{efi.index}_";
                }
            }

            adapterName += fieldInformation.FieldName;

            if (fieldInformation.FieldType.HasOneOfTheFlags(FieldType.Arrayed | FieldType.Listed))
            {
                adapterName += $"_i{fieldInformation.GetFieldInformationParamter<EnumerableFieldInformation>().index}";
            }

            return(adapterName);
        }
        private static Regex GetClass(FieldInformation fieldInformation)
        {
            string className  = fieldInformation.FieldDeclaringType.Name;
            string expression = $@"\bclass\s+{className}\b";

            return(new Regex(expression));
        }
        public ReplaceUnit(GameObject referencingPrefab, Text referencedText, MonoBehaviour referencingMono, FieldInformation fieldInformation)
        {
            SaveBaseData(referencingPrefab, referencedText);
            isReferenced = true;

            this.fieldInformation = fieldInformation;

            MonoAddress = GetComponentAddressInHierarchy(referencingPrefab, referencingMono);
        }
        /*
         * This method can only work guaranteed the script files follow convention of being named the
         * same as the class they contain.
         * TODO Something should be done about the possibility of partial classes
         * TODO Apparently not much can be done:
         * https://stackoverflow.com/questions/10960071/how-to-find-path-to-cs-file-by-its-type-in-c-sharp
         */
        private string GetScriptFilePath(FieldInformation fieldInformation)
        {
            FieldType fieldType      = fieldInformation.FieldType;
            string    scriptFileName = null;

            //* Below is a bold assumbtion that healthy standards of defining a matching file name with the class it contains
            if (fieldType.HasFlag(FieldType.External))
            {
                scriptFileName = fieldInformation.FieldDeclaringType.Name;
            }
            else
            {
                scriptFileName = fieldInformation.FieldOwnerType.Name;
            }

            string selectedAsset = GetAssetGUIDByFileName(scriptFileName);

            if (selectedAsset == null)
            {
                //* thats in case an external class is defined within the same file as the type using it please y u do that :sob:

                foreach (string monoTypeName in _updatedReferenceAddressBook._allFoundMonoBehaviourTypeNames)
                {
                    string otherMono     = GetAssetGUIDByFileName(monoTypeName);
                    var    otherMonoPath = AssetDatabase.GUIDToAssetPath(otherMono);
                    if (DoesScriptContain(otherMonoPath, $@"\bclass\s+{fieldInformation.FieldDeclaringType.Name}\b"))
                    {
                        Debug.Log($"Found {fieldInformation.FieldDeclaringType} in {monoTypeName} file");
                        return(otherMonoPath);
                    }
                }
            }

            if (selectedAsset == null)
            {
                Debug.LogError($"A river of tears");
            }

            var path = AssetDatabase.GUIDToAssetPath(selectedAsset);

            if (string.IsNullOrEmpty(path))
            {
                Debug.LogError($"Pth is null for {scriptFileName} of owner: {fieldInformation.FieldOwnerType} declaring {fieldInformation.FieldDeclaringType} and asset: {selectedAsset}");
            }

            // Debug.Log($"{path}");

            return(path);
        }
Exemplo n.º 5
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);
        }
        //
        // ─── SCRIPT REPLACEMENT ──────────────────────────────────────────
        //

        #region SCRIPT REPLACEMENT

        private void GatherFieldsToUpdate(ReplaceUnit reference)
        {
            if (reference.isReferenced)
            {
                Type             declaringType    = reference.fieldInformation.FieldDeclaringType;
                FieldInformation fieldInformation = reference.fieldInformation;

                if (!_fieldsToUpdateByFieldOwnerType.ContainsKey(declaringType))
                {
                    _fieldsToUpdateByFieldOwnerType[declaringType] = new List <FieldInformation>();
                }

                _fieldsToUpdateByFieldOwnerType[declaringType].Add(fieldInformation);
            }
        }
Exemplo n.º 7
0
        private static void GetAdapterAndTmproFieldInfos(
            FieldInformation fieldInformation,
            out FieldInfo adapterFieldInfo,
            out FieldInfo tmProFieldInfo)
        {
            Type type = Type.GetType(fieldInformation.FieldDefiningTypeAssemblyName);

            adapterFieldInfo = type.GetField(fieldInformation.FieldName, ReferenceFinder.GENEROUS_NONSTATIC_FIELD_SEARCH_FLAGS);
            tmProFieldInfo   = type.GetField($"{fieldInformation.FieldName}TMPro", ReferenceFinder.GENEROUS_NONSTATIC_FIELD_SEARCH_FLAGS);

            if (adapterFieldInfo == null || tmProFieldInfo == null)
            {
                Debug.Log($"Either adapterFieldinfo: {adapterFieldInfo} or tmprofieldinfo: {tmProFieldInfo} is still null for type {type} and field {fieldInformation.FieldName}");
            }
        }
Exemplo n.º 8
0
        private static void SetAdapterAndTMProFieldValues(TMProAdapter tmProAdapter, ReplaceUnit replaceUnit, object fieldOwner, FieldInfo adapterFieldInfo, FieldInfo tmProFieldInfo)
        {
            FieldInformation fieldInformation = replaceUnit.fieldInformation;
            FieldType        fieldType        = fieldInformation.FieldType;

            if (fieldType.HasOneOfTheFlags(FieldType.Listed | FieldType.Arrayed))
            {
                var adpaterField = adapterFieldInfo.GetValue(fieldOwner);
                var tmProField   = tmProFieldInfo.GetValue(fieldOwner);

                EnumerableFieldInformation efi = fieldInformation.GetFieldInformationParamter <EnumerableFieldInformation>();

                if (adpaterField != null && tmProField != null)
                {
                    if (adpaterField is List <TMProAdapter> adapterList)
                    {
                        adapterList[efi.index] = tmProAdapter;
                        (tmProField as List <TextMeshProUGUI>).Add(tmProAdapter.TMProText);
                    }
                    else if (adpaterField is TMProAdapter[] adapterArray)
                    {
                        adapterArray[efi.index] = tmProAdapter;

                        //* We don't need to do the same with above adapterArray since it already has the correct size as it
                        //* replaced the old array of text components
                        TextMeshProUGUI[] tmproFieldArray    = tmProField as TextMeshProUGUI[];
                        TextMeshProUGUI[] newTMProFieldArray = new TextMeshProUGUI[tmproFieldArray.Length + 1];
                        tmproFieldArray.CopyTo(newTMProFieldArray, 0);
                        newTMProFieldArray[tmproFieldArray.Length] = tmProAdapter.TMProText;
                        tmProFieldInfo.SetValue(fieldOwner, newTMProFieldArray);
                    }
                    else
                    {
                        Debug.LogError($"Huh? Thats weird");
                    }
                }
                else
                {
                    Debug.LogError($"Either adapter field: {adpaterField} or tmpro field: {tmProField} is null.");
                }
            }
            else
            {
                adapterFieldInfo.SetValue(fieldOwner, tmProAdapter);
                tmProFieldInfo.SetValue(fieldOwner, tmProAdapter.TMProText);
            }
        }
        private static List <string> GetAdapterTemplate(FieldInformation fieldInformation, FieldType fieldType)
        {
            FileStream stream = null;

            string templatePath = null;

            if (fieldType == FieldType.Direct || fieldType == FieldType.Nested || fieldType == FieldType.External)
            {
                templatePath = $"Packages/com.mariaheineboombyte.fabulous-text-replacer/Editor/Templates/{STANDARD_TEMPLATE}.txt";
            }
            else if (fieldType.HasFlag(FieldType.Arrayed))
            {
                templatePath = $"Packages/com.mariaheineboombyte.fabulous-text-replacer/Editor/Templates/{ARRAYED_TEMPLATE}.txt";
            }
            else if (fieldType.HasFlag(FieldType.Listed))
            {
                templatePath = $"Packages/com.mariaheineboombyte.fabulous-text-replacer/Editor/Templates/{LISTED_TEMPLATE}.txt";
            }
            else
            {
                Debug.LogError($"Unhandled field type: {fieldType} for {fieldInformation.FieldName} {fieldInformation.FieldOwnerType}, hacking around it.");
                templatePath = $"Packages/com.mariaheineboombyte.fabulous-text-replacer/Editor/Templates/{STANDARD_TEMPLATE}.txt";
            }

            stream = new FileStream(templatePath, FileMode.Open);

            if (stream == null)
            {
                Debug.LogError($"Failed to create template file streamfor path: {templatePath}");
            }

            string        line;
            List <string> templateLines = new List <string>();

            using (var reader = new StreamReader(stream))
            {
                while ((line = reader.ReadLine()) != null)
                {
                    line = Regex.Replace(line, @"\{0\}", fieldInformation.FieldName);
                    line = Regex.Replace(line, @"\{1\}", fieldInformation.FieldDeclaringType.Name);
                    templateLines.Add($"{line}");
                }
            }

            return(templateLines);
        }
        // ::::::::::::::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);
            }
        }