Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions DynamicVariablePowerTools/Locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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 <i>Output</i> 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"
}
}
36 changes: 36 additions & 0 deletions DynamicVariablePowerTools/RenameButtonHelper.cs
Original file line number Diff line number Diff line change
@@ -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<string> nameField, Action<string> 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();
}
}
}
20 changes: 20 additions & 0 deletions DynamicVariablePowerTools/RenameConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using MonkeyLoader.Configuration;
using System;
using System.Collections.Generic;
using System.Text;

namespace DynamicVariablePowerTools
{
internal sealed class RenameConfig : SingletonConfigSection<RenameConfig>
{
private static readonly DefiningConfigKey<bool> _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);
}
}
65 changes: 39 additions & 26 deletions DynamicVariablePowerTools/RenameDirectlyLinkedVariables.cs
Original file line number Diff line number Diff line change
@@ -1,69 +1,82 @@
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<RenameDirectlyLinkedVariables>
internal sealed class RenameDirectlyLinkedVariables : ConfiguredResoniteInspectorMonkey<RenameDirectlyLinkedVariables, RenameConfig, BuildInspectorBodyEvent, DynamicVariableSpace>
{
//[AutoRegisterConfigKey]
//private static ModConfigurationKey<bool> ChangeDynVarNamespaces = new ModConfigurationKey<bool>("ChangeDynVarNamespaces", "Enable searching and renaming directly linked variables and drivers when namespace changes.", () => false);

//[AutoRegisterConfigKey]
//private static ModConfigurationKey<bool> ChangeLogixStringInputs = new ModConfigurationKey<bool>("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<IDynamicVariable>(dynVar =>
space.Slot.ForeachComponentInChildren<IDynamicVariable>(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<string>("VariableName") ?? ((Worker)dynVar).TryGetField<string>("_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<IGlobalValueProxy<string>> nameProxyRef
&& nameProxyRef.Target is GlobalValue<string> nameProxy)
&& nameProxyRef.Target is GlobalValue<string> 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<IInput<string>>(stringInput =>
if (ConfigSection.ChangeProtoFluxStringInputs)
{
DynamicVariableHelper.ParsePath(stringInput.Value, out var spaceName, out var variableName);
if (spaceName == null || spaceName != ____lastName)
return;
space.Slot.ForeachComponentInChildren<IInput<string>>(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;
}
}
}
40 changes: 19 additions & 21 deletions DynamicVariablePowerTools/RenameDynamicVariables.cs
Original file line number Diff line number Diff line change
@@ -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<RenameDynamicVariables, BuildInspectorBodyEvent>
internal sealed class RenameDynamicVariables : ResoniteInspectorMonkey<RenameDynamicVariables, BuildInspectorBodyEvent>
{
public override int Priority => HarmonyLib.Priority.Low;

Expand All @@ -23,22 +19,12 @@ protected override void Handle(BuildInspectorBodyEvent eventData)
var dynVar = (IDynamicVariable)eventData.Worker;
var nameField = ((Worker)dynVar).TryGetField<string>("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)
Expand Down Expand Up @@ -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<IInput<string>>(stringInput =>
{
if (stringInput.Value != currentFullName)
return;

stringInput.Value = newName;
}, includeLocal: true, cacheItems: true);
}
}
}
}
Loading