From 06e739381926f6982ac72806345f081adad5f9a4 Mon Sep 17 00:00:00 2001 From: Colin Tim Barndt Date: Sun, 6 Apr 2025 14:57:04 +0200 Subject: [PATCH] Make renaming spaces a button action; add config option for experimental string input renaming. --- DynamicVariablePowerTools/Locale/en.json | 8 +++ .../RenameButtonHelper.cs | 36 ++++++++++ DynamicVariablePowerTools/RenameConfig.cs | 20 ++++++ .../RenameDirectlyLinkedVariables.cs | 65 +++++++++++-------- .../RenameDynamicVariables.cs | 40 ++++++------ 5 files changed, 122 insertions(+), 47 deletions(-) create mode 100644 DynamicVariablePowerTools/RenameButtonHelper.cs create mode 100644 DynamicVariablePowerTools/RenameConfig.cs diff --git a/DynamicVariablePowerTools/Locale/en.json b/DynamicVariablePowerTools/Locale/en.json index bebefde..b8bda58 100644 --- a/DynamicVariablePowerTools/Locale/en.json +++ b/DynamicVariablePowerTools/Locale/en.json @@ -12,11 +12,19 @@ "DynamicVariablePowerTools.EnableLinkedComponentHierarchy.Button": "Output Component Hierarchy", "DynamicVariablePowerTools.EnableLinkedComponentHierarchy.Tooltip": "Generates a hierarchical list of all dynamic variable components linked to this space in the Output field.", + "DynamicVariablePowerTools.RenameDirectlyLinkedVariables.Name": "Rename Dynamic Variable Spaces", + "DynamicVariablePowerTools.RenameDirectlyLinkedVariables.Description": "Adds a button to dynamic variable spaces for renaming all linked variables.", + "DynamicVariablePowerTools.RenameDirectlyLinkedVariables.Button": "Rename", + "DynamicVariablePowerTools.RenameDirectlyLinkedVariables.Tooltip": "Renames all linked variables.", + "DynamicVariablePowerTools.RenameDynamicVariables.Name": "Rename Dynamic Variables", "DynamicVariablePowerTools.RenameDynamicVariables.Description": "Adds a button to dynamic variables for renaming all matching linked variables.", "DynamicVariablePowerTools.RenameDynamicVariables.Button": "Rename", "DynamicVariablePowerTools.RenameDynamicVariables.Tooltip": "Renames all matching linked variables.", + "DynamicVariablePowerTools.Config.RenameOptions.Name": "Rename Options", + "DynamicVariablePowerTools.Config.RenameOptions.Description": "Options for how dynamic variables should be renamed.", + "DynamicVariablePowerTools.DebugInfo.Name": "Debug Info" } } \ No newline at end of file diff --git a/DynamicVariablePowerTools/RenameButtonHelper.cs b/DynamicVariablePowerTools/RenameButtonHelper.cs new file mode 100644 index 0000000..8d02368 --- /dev/null +++ b/DynamicVariablePowerTools/RenameButtonHelper.cs @@ -0,0 +1,36 @@ +using Elements.Core; +using FrooxEngine; +using FrooxEngine.UIX; +using MonkeyLoader.Resonite; +using MonkeyLoader.Resonite.UI; +using System; +using System.Collections.Generic; +using System.Text; + +namespace DynamicVariablePowerTools +{ + internal static class RenameButtonHelper + { + internal static void BuildRenameUI(this UIBuilder builder, IField nameField, Action onRename, LocaleString buttonText, LocaleString tooltipText) + { + var layout = builder.HorizontalLayout(4).Slot.DestroyWhenLocalUserLeaves(); + builder.PushStyle(); + var style = builder.Style; + + style.FlexibleWidth = 1; + var newNameField = builder.TextField(nameField.Value, parseRTF: false); + + void ChangedListener(object _) => newNameField.Text.Content.Value = nameField.Value; + nameField.Changed += ChangedListener; + layout.Destroyed += _ => nameField.Changed -= ChangedListener; + + style.FlexibleWidth = -1; + style.MinWidth = 256; + builder.LocalActionButton(buttonText, button => onRename(newNameField.Text.Content.Value)) + .WithTooltip(tooltipText); + + builder.PopStyle(); + builder.NestOut(); + } + } +} \ No newline at end of file diff --git a/DynamicVariablePowerTools/RenameConfig.cs b/DynamicVariablePowerTools/RenameConfig.cs new file mode 100644 index 0000000..a578a7b --- /dev/null +++ b/DynamicVariablePowerTools/RenameConfig.cs @@ -0,0 +1,20 @@ +using MonkeyLoader.Configuration; +using System; +using System.Collections.Generic; +using System.Text; + +namespace DynamicVariablePowerTools +{ + internal sealed class RenameConfig : SingletonConfigSection + { + private static readonly DefiningConfigKey _changeProtoFluxStringInputs = new("ChangeProtoFluxStringInputs", "Search and rename ProtoFlux inputs with the old name in the form OldName/* (Experimental).", () => false); + + public bool ChangeProtoFluxStringInputs => _changeProtoFluxStringInputs; + + public override string Description => "Rename Options"; + + public override string Id => "RenameOptions"; + + public override Version Version { get; } = new(1, 0); + } +} \ No newline at end of file diff --git a/DynamicVariablePowerTools/RenameDirectlyLinkedVariables.cs b/DynamicVariablePowerTools/RenameDirectlyLinkedVariables.cs index dbdac45..bbc4e08 100644 --- a/DynamicVariablePowerTools/RenameDirectlyLinkedVariables.cs +++ b/DynamicVariablePowerTools/RenameDirectlyLinkedVariables.cs @@ -1,17 +1,15 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; using FrooxEngine; using FrooxEngine.ProtoFlux; using HarmonyLib; using MonkeyLoader.Resonite; +using MonkeyLoader.Resonite.UI.Inspectors; namespace DynamicVariablePowerTools { [HarmonyPatchCategory(nameof(RenameDirectlyLinkedVariables))] [HarmonyPatch(typeof(DynamicVariableSpace), nameof(DynamicVariableSpace.UpdateName))] - internal sealed class RenameDirectlyLinkedVariables : ResoniteMonkey + internal sealed class RenameDirectlyLinkedVariables : ConfiguredResoniteInspectorMonkey { //[AutoRegisterConfigKey] //private static ModConfigurationKey ChangeDynVarNamespaces = new ModConfigurationKey("ChangeDynVarNamespaces", "Enable searching and renaming directly linked variables and drivers when namespace changes.", () => false); @@ -19,51 +17,66 @@ internal sealed class RenameDirectlyLinkedVariables : ResoniteMonkey ChangeLogixStringInputs = new ModConfigurationKey("ChangeLogixStringInputs", "Search and rename logix inputs with the old name in the form OldName/.* (Experimental).", () => false); - private static void Prefix(DynamicVariableSpace __instance, string ____lastName, bool ____lastNameSet) + public override int Priority => HarmonyLib.Priority.Low; + + protected override void Handle(BuildInspectorBodyEvent eventData) + { + var space = (DynamicVariableSpace)eventData.Worker; + + eventData.UI.BuildRenameUI( + space.SpaceName, + onRename: newName => RenameSpace(space, newName), + buttonText: this.GetLocaleString("Button"), + tooltipText: this.GetLocaleString("Tooltip") + ); + } + + private static void RenameSpace(DynamicVariableSpace space, string newName) { - var newName = DynamicVariableHelper.ProcessName(__instance.SpaceName.Value); + newName = DynamicVariableHelper.ProcessName(newName); + var currentName = space.SpaceName.Value; - if (/*!Config.GetValue(ChangeDynVarNamespaces) || */newName == ____lastName && ____lastNameSet) - return; + var prefixName = $"{currentName}/"; - __instance.Slot.ForeachComponentInChildren(dynVar => + space.Slot.ForeachComponentInChildren(dynVar => { DynamicVariableHelper.ParsePath(dynVar.VariableName, out var spaceName, out var variableName); - if (spaceName == null || Traverse.Create(dynVar).Field("handler").Field("_currentSpace").GetValue() != __instance) + if (spaceName == null || Traverse.Create(dynVar).Field("handler").Field("_currentSpace").GetValue() != space) return; - var newVariableName = $"{newName}/{variableName}"; - // TODO: Move to helper method var nameField = ((Worker)dynVar).TryGetField("VariableName") ?? ((Worker)dynVar).TryGetField("_variableName"); - if (nameField is not null) + if (nameField is not null && nameField.Value.StartsWith(prefixName)) { - nameField.Value = newVariableName; + nameField.Value = $"{newName}/{variableName}"; return; } if (dynVar is ProtoFluxEngineProxy { Node.Target: IProtoFluxNode dynVarNode } && dynVarNode.TryGetField("VariableName") is SyncRef> nameProxyRef - && nameProxyRef.Target is GlobalValue nameProxy) + && nameProxyRef.Target is GlobalValue nameProxy + && nameProxy.Value.Value.StartsWith(prefixName)) { - nameProxy.Value.Value = newVariableName; + nameProxy.Value.Value = $"{newName}/{variableName}"; return; } - }, true, true); - - //if (!Config.GetValue(ChangeLogixStringInputs)) - // return; + }, includeLocal: true, cacheItems: true); - __instance.Slot.ForeachComponentInChildren>(stringInput => + if (ConfigSection.ChangeProtoFluxStringInputs) { - DynamicVariableHelper.ParsePath(stringInput.Value, out var spaceName, out var variableName); - if (spaceName == null || spaceName != ____lastName) - return; + space.Slot.ForeachComponentInChildren>(stringInput => + { + DynamicVariableHelper.ParsePath(stringInput.Value, out var spaceName, out var variableName); + if (spaceName == null || spaceName != currentName) + return; + + stringInput.Value = $"{newName}/{variableName}"; + }, includeLocal: true, cacheItems: true); + } - stringInput.Value = $"{newName}/{variableName}"; - }, true, true); + space.SpaceName.Value = newName; } } } \ No newline at end of file diff --git a/DynamicVariablePowerTools/RenameDynamicVariables.cs b/DynamicVariablePowerTools/RenameDynamicVariables.cs index bd0773e..7babfda 100644 --- a/DynamicVariablePowerTools/RenameDynamicVariables.cs +++ b/DynamicVariablePowerTools/RenameDynamicVariables.cs @@ -1,17 +1,13 @@ using Elements.Core; using FrooxEngine; using FrooxEngine.ProtoFlux; -using FrooxEngine.UIX; using MonkeyLoader.Resonite; -using MonkeyLoader.Resonite.UI; using MonkeyLoader.Resonite.UI.Inspectors; using System; -using System.Collections.Generic; -using System.Text; namespace DynamicVariablePowerTools { - internal class RenameDynamicVariables : ResoniteInspectorMonkey + internal sealed class RenameDynamicVariables : ResoniteInspectorMonkey { public override int Priority => HarmonyLib.Priority.Low; @@ -23,22 +19,12 @@ protected override void Handle(BuildInspectorBodyEvent eventData) var dynVar = (IDynamicVariable)eventData.Worker; var nameField = ((Worker)dynVar).TryGetField("VariableName"); - var builder = eventData.UI; - builder.HorizontalLayout(4).Slot.DestroyWhenLocalUserLeaves(); - builder.PushStyle(); - var style = builder.Style; - - style.FlexibleWidth = 1; - var newNameField = builder.TextField(dynVar.VariableName, parseRTF: false); - nameField.Changed += _ => newNameField.Text.Content.Value = dynVar.VariableName; - - style.FlexibleWidth = -1; - style.MinWidth = 256; - builder.LocalActionButton(this.GetLocaleString("Button"), button => RenameDynVar(dynVar, newNameField.Text.Content.Value)) - .WithTooltip(this.GetLocaleString("Tooltip")); - - builder.PopStyle(); - builder.NestOut(); + eventData.UI.BuildRenameUI( + nameField, + onRename: newName => RenameDynVar(dynVar, newName), + buttonText: this.GetLocaleString("Button"), + tooltipText: this.GetLocaleString("Tooltip") + ); } private static Type GetDynVarType(IDynamicVariable dynVar) @@ -83,6 +69,18 @@ private static void RenameDynVar(IDynamicVariable dynVar, string newName) continue; } } + + // Only attempt rename when the new name is directly binding ("space/name") + if (RenameConfig.Instance.ChangeProtoFluxStringInputs && currentSpaceName != null) + { + linkedSpace.Slot.ForeachComponentInChildren>(stringInput => + { + if (stringInput.Value != currentFullName) + return; + + stringInput.Value = newName; + }, includeLocal: true, cacheItems: true); + } } } } \ No newline at end of file