Esempio n. 1
0
        private void FindCrossPrefabReferences()
        {
            _crossPrefabReferences = new Dictionary <GameObject, List <GameObject> >();
            _nestedPrefabs         = new Dictionary <GameObject, List <GameObject> >();

            foreach (var rootPrefab in _loadedPrefabs)
            {
                List <GameObject> foundNestedPrefabs = rootPrefab.CheckHierarchyForNestedPrefabs();

                if (foundNestedPrefabs.Count() > 0)
                {
                    _nestedPrefabs.Add(rootPrefab, foundNestedPrefabs);

                    bool foundErrors           = false;
                    MultilineStringBuilder msb = new MultilineStringBuilder($"Cross Prefab Reference serach, load failures f or <<{rootPrefab.name}>>");

                    foreach (var nestedPrefab in foundNestedPrefabs)
                    {
                        var overrides = PrefabUtility.GetObjectOverrides(nestedPrefab);

                        //TODO This has to be done with msb logger instead
                        //TODO Note there are obviously many overrides so this may cause problewms
                        if (overrides.Count > 0)
                        {
                            //Debug.Log($"{rootPrefab} has overrides at {nestedPrefab}");
                        }

                        //! This has to be done since nested prefabs are separate instances
                        // Than those we loaded with LoadAllPrefabs

                        var loadedInstance = _loadedPrefabs.FindInstanceOfTheSamePrefab(nestedPrefab);

                        if (loadedInstance == null)
                        {
                            foundErrors = true;
                            msb.AddLine($"Failed to find {nestedPrefab.name} in loadedPrefabs");
                            continue;
                        }

                        if (!_crossPrefabReferences.ContainsKey(loadedInstance))
                        {
                            _crossPrefabReferences[loadedInstance] = new List <GameObject>();
                        }

                        _crossPrefabReferences[loadedInstance].Add(rootPrefab);
                    }

                    if (foundErrors)
                    {
                        Debug.LogError(msb.ToString());
                    }
                }
            }
        }
Esempio n. 2
0
        //
        // ─── ANALYSIS ────────────────────────────────────────────────────
        //

        #region ANALYSIS

        private void AnalyzePrefab(GameObject originalPrefab, MultilineStringBuilder msb, ref int currentDepth)
        {
            // Skips execition if there were no text components found in the hierarchy
            if (!originalPrefab.TryGetComponentsInChildren(out List <Text> localTextComponents, skipNestedPrefabs: true))
            {
                return;
            }
            else
            {
                currentDepth++;
            }

            bool logthisone = true;

            foreach (Text text in localTextComponents)
            {
                string originalPrefabPath = AssetDatabase.GetAssetPath(originalPrefab);

                //* Internal text component references
                SaveTextReferences(originalPrefabPath, originalPrefab, text);

                // 2. Text components referenced by nested prefabs
                // 3. Text components of prefabs that are reference by the other nested prefabs
                // X???. Text components of prefabs that are referenced by parent of a parent OR by a nested prefab of a parent of a parent OOF

                //* Foreign text component references
                // Get all instances of a Text component along with the parentPrefab that is holding them
                // It is a list of Text components because parentPrefab may hold multiple references to that Text Component
                foreach (var kvp in GetAllTextInstances(originalPrefab, text))
                {
                    // * Clean this up, extract the recurring method
                    GameObject  instanceParentPreafab  = kvp.Key;
                    List <Text> textComponentInstances = kvp.Value;

                    foreach (Text textInstance in textComponentInstances)
                    {
                        SaveTextReferences(originalPrefabPath, instanceParentPreafab, textInstance);

                        // ? This is because the counter will
                        _replaceCounter.updatedTextComponentCount++;
                    }
                }
            }

            if (logthisone)
            {
                PrintPrefabAnalysis(originalPrefab, msb, localTextComponents);
            }
        }
Esempio n. 3
0
        private void LogScriptReferences(MultilineStringBuilder msb, int logDepth = 30)
        {
            int depth = 0;

            foreach (var c in _scriptReferences)
            {
                msb.AddLine(new[] { "mono: ", c.Key.Name, " has reference count: ", c.Value.Count.ToString() });

                foreach (var reference in c.Value)
                {
                    msb.AddLine(new[] { "---> ", reference.name });
                }

                if (depth > logDepth)
                {
                    return;
                }
                depth++;
            }
        }
Esempio n. 4
0
        private void PrintPrefabAnalysis(GameObject prefab, MultilineStringBuilder msb, List <Text> localTextComponents)
        {
            msb.AddLine($"Analysis of {prefab.name}");
            if (_nestedPrefabs.ContainsKey(prefab) && _nestedPrefabs[prefab].Count > 0)
            {
                msb.AddLine($"Has nested prefabs:");
                foreach (var n in _nestedPrefabs[prefab])
                {
                    msb.AddLine($"---> {n}");
                }
            }
            if (localTextComponents.Count > 0)
            {
                msb.AddLine($"Has text components:");
                foreach (var n in localTextComponents)
                {
                    msb.AddLine($"---> {n.gameObject}");
                }
            }
            if (_scriptsByPrefab[prefab].Count > 0)
            {
                msb.AddLine($"Has custom monobehaviours:");
                foreach (Type monoType in _scriptsByPrefab[prefab])
                {
                    msb.AddLine($"---> {monoType.Name}");
                }
            }
            if (_crossPrefabReferences.ContainsKey(prefab))
            {
                msb.AddLine($"Is referenced by other prefabs:");
                foreach (GameObject referencer in _crossPrefabReferences[prefab])
                {
                    msb.AddLine($"---> by: {referencer}");
                }
            }

            msb.AddSeparator();
        }
Esempio n. 5
0
        //
        // ─── LOGGING ────────────────────────────────────────────────────────────────────
        //

        #region LOGGING

        private void DrawLoggingButtons(VisualElement root)
        {
            var label = new Label()
            {
                text = "Logging"
            };
            var box = new Box();

            box.style.height   = StyleKeyword.Auto;
            box.style.overflow = Overflow.Visible;
            root.Add(label);
            root.Add(box);

            IntegerField loggingDepthField = new IntegerField("Logging Depth");

            loggingDepthField.value = 30;
            box.Add(loggingDepthField);

            var logOverridesButton = new Button(() =>
            {
                var msb = new MultilineStringBuilder("Log nested prefabs with overrides");

                foreach (var item in _nestedPrefabs)
                {
                    bool loggedOverride = false;

                    foreach (var nested in item.Value)
                    {
                        bool hasOverrides = PrefabUtility.HasPrefabInstanceAnyOverrides(nested, false);

                        if (hasOverrides && loggedOverride == false)
                        {
                            loggedOverride = true;
                            msb.AddLine($"{item.Key.gameObject.name} has overrides at:");
                        }

                        if (hasOverrides)
                        {
                            msb.AddLine($"---> {nested.name}");
                        }
                    }

                    loggedOverride = false;
                }

                DisplayInBox(GetTextElement(msb.ToString()));
            })
            {
                text = "Log overrides"
            };

            box.Add(logOverridesButton);

            var logCrossReferences = new Button(() =>
            {
                var msb = new MultilineStringBuilder("Log Cross References");

                LogCrossReferences(msb, loggingDepthField.value);

                DisplayInBox(GetTextElement(msb.ToString()));
            })
            {
                text = "Log Cross References"
            };

            box.Add(logCrossReferences);

            var logScriptReferencesButton = new Button(() =>
            {
                var msb = new MultilineStringBuilder("Log Script References");

                LogScriptReferences(msb, loggingDepthField.value);

                DisplayInBox(GetTextElement(msb.ToString()));
            })
            {
                text = "Log Script References"
            };

            box.Add(logScriptReferencesButton);

            // TODO this is dead
            var logUnhandledReferences = new Button(() =>
            {
                var msb = new MultilineStringBuilder("Unhandled script references");

                foreach (var kvp in _textFieldsByMonobehaviour)
                {
                    msb.AddLine(new string[] { kvp.Key.GetType().ToString(), " from ", _customMonobehavioursByPrefab.First(slot => slot.Value.Contains(kvp.Key)).Key.ToString() });
                    foreach (var unhandledField in kvp.Value)
                    {
                        msb.AddLine($"---> {unhandledField.Name}");
                    }
                }

                DisplayInBox(GetTextElement(msb.ToString()));
            })
            {
                text = "Unhandled script references"
            };

            box.Add(logUnhandledReferences);
        }
Esempio n. 6
0
        //
        // ─── EDITOR DRAWING ──────────────────────────────────────────────
        //

        #region Editor Drawing

        private void DrawReplacerMenu(VisualElement root)
        {
            var container = new Box();

            root.Add(container);

            var label = new Label()
            {
                text = "Replacer"
            };

            container.Add(label);

            _selectedPrefabsField = new ObjectField("Selected prefabs")
            {
                objectType = typeof(SelectedPrefabsBook)
            };
            container.Add(_selectedPrefabsField);

            _excludedPrefabsField = new ObjectField("Excluded prefabs")
            {
                objectType = typeof(SelectedPrefabsBook)
            };
            _excludedPrefabsField.value = AssetDatabase.LoadAssetAtPath(EXCLUDED_PREFABS_ASSET_PATH, typeof(SelectedPrefabsBook));
            container.Add(_excludedPrefabsField);

            Button initializeButton = new Button(() =>
            {
                //* Where to search for prefabs (depending on whether we make a backup or not)
                // ! Prefab backup abandoned
                UpdatedReferenceAddressBook.ClearAddressBook();
                LoadPrefabs();
                FindCrossPrefabReferences();
                FindScriptReferences();
                UpgradeProgressBar.Invoke();
            })
            {
                text = "Initialize"
            };

            container.Add(initializeButton);

            IntegerField analysisDepth = new IntegerField("Prefab Analysis Depth");

            analysisDepth.value = FabulousTextComponentReplacer.WORK_DEPTH;
            container.Add(analysisDepth);

            var analysePrefabsButton = new Button()
            {
                text = "Analyse prefabs"
            };

            container.Add(analysePrefabsButton);


            var updateScriptsButton = new Button()
            {
                text = "Update scripts"
            };

            _scriptUpdater =
                new ScriptUpdater(
                    UpdatedReferenceAddressBook,
                    updateScriptsButton);
            container.Add(updateScriptsButton);

            var updateComponentsButton = new Button()
            {
                text = "Update components"
            };

            _componentReplacer =
                new ComponentReplacer(
                    UpdatedReferenceAddressBook,
                    updateComponentsButton);
            container.Add(updateComponentsButton);

            analysePrefabsButton.clicked += () =>
            {
                List <string> analysisResultsParts = new List <string>();

                int currentDepth = 0;
                var msb          = new MultilineStringBuilder("1 - Prefab analysis");

                foreach (var prefab in _loadedPrefabs)
                {
                    if (msb.Length > 5000)
                    {
                        analysisResultsParts.Add(msb.ToString());
                        msb = new MultilineStringBuilder($"{analysisResultsParts.Count + 1} - Prefab analysis");
                    }

                    if (analysisDepth.value != -1 && currentDepth >= analysisDepth.value)
                    {
                        break;
                    }

                    AnalyzePrefab(prefab, msb, ref currentDepth);
                }

                analysisResultsParts.Add(msb.ToString());

                UpgradeProgressBar.Invoke();

                DisplayInBox(GetTextBlock(analysisResultsParts));
            };
        }