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); }
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); } }
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}"); } }
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); } }