From f2f3791f844bf07047a9e526b04f9ccf3f62b62f Mon Sep 17 00:00:00 2001 From: JLChnToZ Date: Sat, 20 Apr 2024 22:59:45 +0800 Subject: [PATCH] Migration bug fixes --- .../Editor/Common/ComponentReplacer.cs | 71 ++++++++++++------- .../Editor/Common/TMProMigrator.cs | 11 ++- .../Runtime/I18N/LanguageReceiver.cs | 1 - .../Runtime/VVMW/ListEntry.cs | 1 + .../Runtime/VVMW/UIHandler.cs | 4 +- 5 files changed, 55 insertions(+), 33 deletions(-) diff --git a/Packages/idv.jlchntoz.vvmw/Editor/Common/ComponentReplacer.cs b/Packages/idv.jlchntoz.vvmw/Editor/Common/ComponentReplacer.cs index 827d3f7..d2bd370 100644 --- a/Packages/idv.jlchntoz.vvmw/Editor/Common/ComponentReplacer.cs +++ b/Packages/idv.jlchntoz.vvmw/Editor/Common/ComponentReplacer.cs @@ -9,11 +9,10 @@ namespace JLChnToZ.VRC.VVMW { public class ComponentReplacer { - static readonly List allComponents = new List(); + static readonly Dictionary> references = new Dictionary>(); static readonly Dictionary dependents = new Dictionary(); readonly List downstreams = new List(); readonly Type componentType; - readonly HashSet<(Component, string)> references = new HashSet<(Component, string)>(); readonly GameObject sourceGameObject; GameObject temporaryGameObject; readonly Component[] componentsInGameObject; @@ -55,44 +54,58 @@ static bool IsRequired(Type type, Type checkType) { return false; } - static void InitAllComponents(Scene scene) { - if (allComponents.Count != 0) return; + public static void InitAllComponents() { + #if UNITY_2022_2_OR_NEWER + int scneCount = SceneManager.loadedSceneCount; + #else + int scneCount = SceneManager.sceneCount; + #endif + var roots = new List(); var temp = new List(); var stack = new Stack(); - foreach (var root in scene.GetRootGameObjects()) - stack.Push(root.transform); + for (int i = 0; i < scneCount; i++) { + SceneManager.GetSceneAt(i).GetRootGameObjects(roots); + foreach (var root in roots) + stack.Push(root.transform); + } while (stack.Count > 0) { var current = stack.Pop(); for (int i = current.childCount - 1; i >= 0; i--) stack.Push(current.GetChild(i)); current.GetComponents(temp); - allComponents.AddRange(temp); + foreach (var c in temp) { + if (c == null || c is Transform) continue; + using (var so = new SerializedObject(c)) { + var sp = so.GetIterator(); + while (sp.Next(true)) { + if (sp.propertyType != SerializedPropertyType.ObjectReference) continue; + var target = sp.objectReferenceValue as Component; + if (target == null || target == c) continue; + if (!references.TryGetValue(target, out var mapping)) + references[target] = mapping = new List<(Component, string)>(); + mapping.Add((c, sp.propertyPath)); + } + } + } } } + public static ICollection<(Component, string)> GetReferencedComponents(Component component) => + component != null && references.TryGetValue(component, out var mapping) ? + mapping : Array.Empty<(Component, string)>(); + ComponentReplacer(GameObject sourceGameObject, Component[] components, int index) { this.sourceGameObject = sourceGameObject; componentsInGameObject = components; componentIndex = index; var component = components[index]; componentType = component.GetType(); - InitAllComponents(sourceGameObject.scene); - foreach (var c in allComponents) { - if (c == null || c == component) continue; - if (c.gameObject == sourceGameObject) - if (IsRequired(c.GetType(), componentType)) { - int i = Array.IndexOf(componentsInGameObject, c); - if (i >= 0) downstreams.Add(new ComponentReplacer(sourceGameObject, componentsInGameObject, i)); - else Debug.LogWarning($"Component {c.GetType()} is required by {componentType} but not found in the same GameObject."); - } - using (var so = new SerializedObject(c)) { - var sp = so.GetIterator(); - while (sp.Next(true)) - if (sp.propertyType == SerializedPropertyType.ObjectReference && sp.objectReferenceValue == component) - references.Add((c, sp.propertyPath)); - } + foreach (var c in componentsInGameObject) { + if (c == null || c == component || !IsRequired(c.GetType(), componentType)) continue; + int i = Array.IndexOf(componentsInGameObject, c); + if (i >= 0) downstreams.Add(new ComponentReplacer(sourceGameObject, componentsInGameObject, i)); + else Debug.LogWarning($"Component {c.GetType()} is required by {componentType} but not found in the same GameObject."); } - Debug.Log($"Component {component.name} has {downstreams.Count} downstreams and {references.Count} references."); } void CloneToTemporary() { @@ -133,10 +146,14 @@ void RestoreDependents() { var temp = sourceGameObject.AddComponent(current.componentType); current.componentsInGameObject[current.componentIndex] = temp; if (temp != null) EditorUtility.CopySerializedIfDifferent(current.componentsInTemporary[current.componentIndex], temp); - foreach (var (component, path) in current.references) { - var sp = new SerializedObject(component).FindProperty(path); - sp.objectReferenceValue = temp; - } + if (references.TryGetValue(current.componentsInTemporary[current.componentIndex], out var mapping)) + foreach (var (component, path) in mapping) { + using (var so = new SerializedObject(component)) { + var sp = so.FindProperty(path); + sp.objectReferenceValue = temp; + so.ApplyModifiedProperties(); + } + } } } diff --git a/Packages/idv.jlchntoz.vvmw/Editor/Common/TMProMigrator.cs b/Packages/idv.jlchntoz.vvmw/Editor/Common/TMProMigrator.cs index 264b407..9fb05ef 100644 --- a/Packages/idv.jlchntoz.vvmw/Editor/Common/TMProMigrator.cs +++ b/Packages/idv.jlchntoz.vvmw/Editor/Common/TMProMigrator.cs @@ -18,6 +18,7 @@ public static class TMProMigratator { [MenuItem("Tools/VizVid/Migrate TMPro Components")] static void MigrateSelected() { LoadFontMapping(); + ComponentReplacer.InitAllComponents(); foreach (var gameObject in Selection.gameObjects) Migrate(gameObject); } @@ -54,7 +55,7 @@ public static void Migrate(GameObject root) { } if (isTypeMigratable && monoBehaviour.TryGetComponent(out Text text)) Migrate(text); - if (mapping != null) + if (mapping != null) { foreach (var kv in mapping) { var sourceField = kv.Key; var targetField = kv.Value; @@ -65,9 +66,13 @@ public static void Migrate(GameObject root) { targetField.SetValue(monoBehaviour, targetText); } } + EditorUtility.SetDirty(monoBehaviour); + } + } + foreach (var text in root.GetComponentsInChildren(true)) { + var referencedComponents = ComponentReplacer.GetReferencedComponents(text); + if (referencedComponents.Count == 0) Migrate(text); } - foreach (var text in root.GetComponentsInChildren(true)) - Migrate(text); } public static TextMeshProUGUI Migrate(Text textComponent) { diff --git a/Packages/idv.jlchntoz.vvmw/Runtime/I18N/LanguageReceiver.cs b/Packages/idv.jlchntoz.vvmw/Runtime/I18N/LanguageReceiver.cs index 9c02098..94b8a48 100644 --- a/Packages/idv.jlchntoz.vvmw/Runtime/I18N/LanguageReceiver.cs +++ b/Packages/idv.jlchntoz.vvmw/Runtime/I18N/LanguageReceiver.cs @@ -8,7 +8,6 @@ namespace JLChnToZ.VRC.VVMW.I18N { [UdonBehaviourSyncMode(BehaviourSyncMode.NoVariableSync)] [AddComponentMenu("VizVid/Locales/Language Receiver")] [DefaultExecutionOrder(1)] - [TMProMigratable] public class LanguageReceiver : UdonSharpBehaviour { [SerializeField, HideInInspector, BindUdonSharpEvent] LanguageManager manager; [SerializeField] string key; diff --git a/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/ListEntry.cs b/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/ListEntry.cs index e1b3932..bb6187e 100644 --- a/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/ListEntry.cs +++ b/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/ListEntry.cs @@ -11,6 +11,7 @@ namespace JLChnToZ.VRC.VVMW { [AddComponentMenu("VizVid/Components/List Entry")] [DefaultExecutionOrder(3)] public class ListEntry : UdonSharpBehaviour { + [TMProMigratable(nameof(contentTMPro))] [SerializeField] Text content; [SerializeField] TextMeshProUGUI contentTMPro; [BindEvent(nameof(Button.onClick), nameof(_OnClick))] diff --git a/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/UIHandler.cs b/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/UIHandler.cs index 8e03ce2..678420e 100644 --- a/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/UIHandler.cs +++ b/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/UIHandler.cs @@ -440,7 +440,7 @@ public void _OnUIUpdate() { break; case 2: // Error if (idleScreenRoot != null) idleScreenRoot.SetActive(true); - if (statusText == null) break; + if (statusText == null && statusTMPro == null) break; if (timeContainer != null) { SetStatusEnabled(true); timeContainer.SetActive(false); @@ -706,7 +706,7 @@ void SetText(Text text, TextMeshProUGUI tmp, string content) { } void SetStatusEnabled(bool enabled) { - if (timeContainer == null || statusText == null || statusTMPro == null) return; + if (timeContainer == null || (statusText == null && statusTMPro == null)) return; timeContainer.SetActive(!enabled); if (statusText != null) statusText.enabled = enabled; if (statusTMPro != null) statusTMPro.enabled = enabled;