mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2024-12-29 18:55:06 +08:00
fix: rename parameters hook interferes with menu installer references
This commit is contained in:
parent
ff7c3ff702
commit
6b5fc80167
@ -526,6 +526,40 @@ namespace modular_avatar_tests.VirtualMenuTests
|
|||||||
Assert.True(assetSet.Contains(serialized_c));
|
Assert.True(assetSet.Contains(serialized_c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void InstallTargetToInstallerToInstaller()
|
||||||
|
{
|
||||||
|
var menu_a = Create<VRCExpressionsMenu>();
|
||||||
|
var menu_b = Create<VRCExpressionsMenu>();
|
||||||
|
var menu_c = Create<VRCExpressionsMenu>();
|
||||||
|
menu_c.controls = new List<VRCExpressionsMenu.Control>
|
||||||
|
{
|
||||||
|
GenerateTestControl()
|
||||||
|
};
|
||||||
|
|
||||||
|
var node_a = CreateInstaller("root");
|
||||||
|
var item_a = node_a.gameObject.AddComponent<ModularAvatarMenuInstallTarget>();
|
||||||
|
|
||||||
|
var node_b = CreateInstaller("menu_b");
|
||||||
|
node_b.menuToAppend = menu_c;
|
||||||
|
|
||||||
|
var node_c = CreateInstaller("menu_c");
|
||||||
|
node_c.installTargetMenu = menu_c;
|
||||||
|
|
||||||
|
node_b.transform.parent = node_a.transform;
|
||||||
|
item_a.installer = node_b;
|
||||||
|
|
||||||
|
var virtualMenu = new VirtualMenu(menu_a);
|
||||||
|
virtualMenu.RegisterMenuInstallTarget(item_a);
|
||||||
|
virtualMenu.RegisterMenuInstaller(node_a);
|
||||||
|
virtualMenu.RegisterMenuInstaller(node_b);
|
||||||
|
virtualMenu.RegisterMenuInstaller(node_c);
|
||||||
|
|
||||||
|
virtualMenu.FreezeMenu();
|
||||||
|
|
||||||
|
var root = virtualMenu.ResolvedMenu[menu_a];
|
||||||
|
Assert.AreEqual(1, root.Controls.Count);
|
||||||
|
}
|
||||||
|
|
||||||
ModularAvatarMenuInstaller CreateInstaller(string name)
|
ModularAvatarMenuInstaller CreateInstaller(string name)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEditor.Animations;
|
using UnityEditor.Animations;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@ -18,6 +19,13 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
internal readonly Dictionary<VRCExpressionsMenu, VRCExpressionsMenu> ClonedMenus
|
internal readonly Dictionary<VRCExpressionsMenu, VRCExpressionsMenu> ClonedMenus
|
||||||
= new Dictionary<VRCExpressionsMenu, VRCExpressionsMenu>();
|
= new Dictionary<VRCExpressionsMenu, VRCExpressionsMenu>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This dictionary overrides the _original contents_ of ModularAvatarMenuInstallers. Notably, this does not
|
||||||
|
/// replace the source menu for the purposes of identifying any other MAMIs that might install to the same
|
||||||
|
/// menu asset.
|
||||||
|
/// </summary>
|
||||||
|
internal readonly Dictionary<ModularAvatarMenuInstaller, Action<VRCExpressionsMenu.Control>> PostProcessControls
|
||||||
|
= new Dictionary<ModularAvatarMenuInstaller, Action<VRCExpressionsMenu.Control>>();
|
||||||
|
|
||||||
public BuildContext(VRCAvatarDescriptor avatarDescriptor)
|
public BuildContext(VRCAvatarDescriptor avatarDescriptor)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
private MenuPreviewGUI _previewGUI;
|
private MenuPreviewGUI _previewGUI;
|
||||||
|
|
||||||
private HashSet<VRCExpressionsMenu> _avatarMenus;
|
private HashSet<VRCExpressionsMenu> _avatarMenus;
|
||||||
|
private VirtualMenu _virtualMenuCache;
|
||||||
|
|
||||||
private Dictionary<VRCExpressionsMenu, List<ModularAvatarMenuInstaller>> _menuInstallersMap;
|
private Dictionary<VRCExpressionsMenu, List<ModularAvatarMenuInstaller>> _menuInstallersMap;
|
||||||
|
|
||||||
@ -45,6 +46,61 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
private long _cacheSeq = -1;
|
private long _cacheSeq = -1;
|
||||||
private ImmutableList<object> _cachedTargets = null;
|
private ImmutableList<object> _cachedTargets = null;
|
||||||
|
|
||||||
|
private void CacheMenu()
|
||||||
|
{
|
||||||
|
if (VirtualMenu.CacheSequence == _cacheSeq && _cachedTargets != null && _virtualMenuCache != null) return;
|
||||||
|
|
||||||
|
|
||||||
|
List<ImmutableList<object>> perTarget = new List<ImmutableList<object>>();
|
||||||
|
|
||||||
|
var commonAvatar = FindCommonAvatar();
|
||||||
|
if (commonAvatar == null)
|
||||||
|
{
|
||||||
|
_cacheSeq = VirtualMenu.CacheSequence;
|
||||||
|
_cachedTargets = ImmutableList<object>.Empty;
|
||||||
|
_virtualMenuCache = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_virtualMenuCache = VirtualMenu.ForAvatar(commonAvatar);
|
||||||
|
|
||||||
|
foreach (var target in targets)
|
||||||
|
{
|
||||||
|
var installer = (ModularAvatarMenuInstaller) target;
|
||||||
|
|
||||||
|
var installTargets = _virtualMenuCache.GetInstallTargetsForInstaller(installer)
|
||||||
|
.Select(o => (object) o).ToImmutableList();
|
||||||
|
if (installTargets.Any())
|
||||||
|
{
|
||||||
|
perTarget.Add(installTargets);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
perTarget.Add(ImmutableList<object>.Empty.Add(installer.installTargetMenu));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < perTarget.Count; i++)
|
||||||
|
{
|
||||||
|
if (perTarget[0].Count != perTarget[i].Count ||
|
||||||
|
perTarget[0].Zip(perTarget[i], (a, b) => (Resolve(a) != Resolve(b))).Any(differs => differs))
|
||||||
|
{
|
||||||
|
perTarget.Clear();
|
||||||
|
perTarget.Add(ImmutableList<object>.Empty);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_cacheSeq = VirtualMenu.CacheSequence;
|
||||||
|
_cachedTargets = perTarget[0];
|
||||||
|
|
||||||
|
object Resolve(object p0)
|
||||||
|
{
|
||||||
|
if (p0 is ModularAvatarMenuInstallTarget target && target != null) return target.transform.parent;
|
||||||
|
return p0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Interpretation:
|
// Interpretation:
|
||||||
// <empty> : Inconsistent install targets
|
// <empty> : Inconsistent install targets
|
||||||
// List of [null]: Install to root
|
// List of [null]: Install to root
|
||||||
@ -55,56 +111,18 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (VirtualMenu.CacheSequence == _cacheSeq && _cachedTargets != null) return _cachedTargets;
|
CacheMenu();
|
||||||
|
|
||||||
List<ImmutableList<object>> perTarget = new List<ImmutableList<object>>();
|
|
||||||
|
|
||||||
var commonAvatar = FindCommonAvatar();
|
|
||||||
if (commonAvatar == null)
|
|
||||||
{
|
|
||||||
_cacheSeq = VirtualMenu.CacheSequence;
|
|
||||||
_cachedTargets = ImmutableList<object>.Empty;
|
|
||||||
return _cachedTargets;
|
|
||||||
}
|
|
||||||
|
|
||||||
var virtualMenu = VirtualMenu.ForAvatar(commonAvatar);
|
|
||||||
|
|
||||||
foreach (var target in targets)
|
|
||||||
{
|
|
||||||
var installer = (ModularAvatarMenuInstaller) target;
|
|
||||||
|
|
||||||
var installTargets = virtualMenu.GetInstallTargetsForInstaller(installer)
|
|
||||||
.Select(o => (object) o).ToImmutableList();
|
|
||||||
if (installTargets.Any())
|
|
||||||
{
|
|
||||||
perTarget.Add(installTargets);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
perTarget.Add(ImmutableList<object>.Empty.Add(installer.installTargetMenu));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 1; i < perTarget.Count; i++)
|
|
||||||
{
|
|
||||||
if (perTarget[0].Count != perTarget[i].Count ||
|
|
||||||
perTarget[0].Zip(perTarget[i], (a, b) => (Resolve(a) != Resolve(b))).Any(differs => differs))
|
|
||||||
{
|
|
||||||
perTarget.Clear();
|
|
||||||
perTarget.Add(ImmutableList<object>.Empty);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_cacheSeq = VirtualMenu.CacheSequence;
|
|
||||||
_cachedTargets = perTarget[0];
|
|
||||||
return _cachedTargets;
|
return _cachedTargets;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object Resolve(object p0)
|
private VirtualMenu _virtualMenu
|
||||||
{
|
{
|
||||||
if (p0 is ModularAvatarMenuInstallTarget target && target != null) return target.transform.parent;
|
get
|
||||||
return p0;
|
{
|
||||||
}
|
CacheMenu();
|
||||||
|
return _virtualMenuCache;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,21 +38,47 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
private readonly ImmutableDictionary<object, ImmutableList<ModularAvatarMenuInstaller>>
|
private readonly ImmutableDictionary<object, ImmutableList<ModularAvatarMenuInstaller>>
|
||||||
_menuToInstallerMap;
|
_menuToInstallerMap;
|
||||||
|
|
||||||
|
private readonly ImmutableDictionary<ModularAvatarMenuInstaller, Action<VRCExpressionsMenu.Control>>
|
||||||
|
_postProcessControls
|
||||||
|
= ImmutableDictionary<ModularAvatarMenuInstaller, Action<VRCExpressionsMenu.Control>>.Empty;
|
||||||
|
|
||||||
private readonly VirtualMenuNode _node;
|
private readonly VirtualMenuNode _node;
|
||||||
private readonly NodeForDelegate _nodeFor;
|
private readonly NodeForDelegate _nodeFor;
|
||||||
private readonly Action<VRCExpressionsMenu> _visitedMenu;
|
private readonly Action<VRCExpressionsMenu> _visitedMenu;
|
||||||
private readonly HashSet<object> _visited = new HashSet<object>();
|
private readonly HashSet<object> _visited = new HashSet<object>();
|
||||||
|
|
||||||
|
private Action<VRCExpressionsMenu.Control> _currentPostprocessor = _control => { };
|
||||||
|
|
||||||
|
private class PostprocessorContext : IDisposable
|
||||||
|
{
|
||||||
|
private NodeContextImpl _context;
|
||||||
|
private Action<VRCExpressionsMenu.Control> _priorPreprocessor;
|
||||||
|
|
||||||
|
public PostprocessorContext(NodeContextImpl context, Action<VRCExpressionsMenu.Control> preprocessor)
|
||||||
|
{
|
||||||
|
this._context = context;
|
||||||
|
this._priorPreprocessor = context._currentPostprocessor;
|
||||||
|
context._currentPostprocessor = preprocessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_context._currentPostprocessor = _priorPreprocessor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public NodeContextImpl(
|
public NodeContextImpl(
|
||||||
VirtualMenuNode node,
|
VirtualMenuNode node,
|
||||||
NodeForDelegate nodeFor,
|
NodeForDelegate nodeFor,
|
||||||
ImmutableDictionary<object, ImmutableList<ModularAvatarMenuInstaller>> menuToInstallerMap,
|
ImmutableDictionary<object, ImmutableList<ModularAvatarMenuInstaller>> menuToInstallerMap,
|
||||||
|
ImmutableDictionary<ModularAvatarMenuInstaller, Action<VRCExpressionsMenu.Control>> postProcessControls,
|
||||||
Action<VRCExpressionsMenu> visitedMenu
|
Action<VRCExpressionsMenu> visitedMenu
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_node = node;
|
_node = node;
|
||||||
_nodeFor = nodeFor;
|
_nodeFor = nodeFor;
|
||||||
_menuToInstallerMap = menuToInstallerMap;
|
_menuToInstallerMap = menuToInstallerMap;
|
||||||
|
_postProcessControls = postProcessControls;
|
||||||
_visitedMenu = visitedMenu;
|
_visitedMenu = visitedMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +98,10 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
{
|
{
|
||||||
foreach (var installer in installers)
|
foreach (var installer in installers)
|
||||||
{
|
{
|
||||||
PushNode(installer);
|
using (new PostprocessorContext(this, null))
|
||||||
|
{
|
||||||
|
PushNode(installer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,7 +130,10 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
}
|
}
|
||||||
else if (installer.menuToAppend != null)
|
else if (installer.menuToAppend != null)
|
||||||
{
|
{
|
||||||
PushNode(installer.menuToAppend);
|
using (new PostprocessorContext(this, _postProcessControls.GetValueOrDefault(installer)))
|
||||||
|
{
|
||||||
|
PushNode(installer.menuToAppend);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -167,6 +199,10 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
private Dictionary<ModularAvatarMenuInstaller, List<ModularAvatarMenuInstallTarget>> _installerToTargetComponent
|
private Dictionary<ModularAvatarMenuInstaller, List<ModularAvatarMenuInstallTarget>> _installerToTargetComponent
|
||||||
= new Dictionary<ModularAvatarMenuInstaller, List<ModularAvatarMenuInstallTarget>>();
|
= new Dictionary<ModularAvatarMenuInstaller, List<ModularAvatarMenuInstallTarget>>();
|
||||||
|
|
||||||
|
private ImmutableDictionary<ModularAvatarMenuInstaller, Action<VRCExpressionsMenu.Control>>
|
||||||
|
_postprocessControlsHooks =
|
||||||
|
ImmutableDictionary<ModularAvatarMenuInstaller, Action<VRCExpressionsMenu.Control>>.Empty;
|
||||||
|
|
||||||
private Dictionary<object, VirtualMenuNode> _resolvedMenu = new Dictionary<object, VirtualMenuNode>();
|
private Dictionary<object, VirtualMenuNode> _resolvedMenu = new Dictionary<object, VirtualMenuNode>();
|
||||||
|
|
||||||
// TODO: immutable?
|
// TODO: immutable?
|
||||||
@ -180,8 +216,16 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
/// Initializes the VirtualMenu.
|
/// Initializes the VirtualMenu.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="rootMenu">The root VRCExpressionsMenu to import</param>
|
/// <param name="rootMenu">The root VRCExpressionsMenu to import</param>
|
||||||
internal VirtualMenu(VRCExpressionsMenu rootMenu)
|
internal VirtualMenu(
|
||||||
|
VRCExpressionsMenu rootMenu,
|
||||||
|
BuildContext context = null
|
||||||
|
)
|
||||||
{
|
{
|
||||||
|
if (context != null)
|
||||||
|
{
|
||||||
|
_postprocessControlsHooks = context.PostProcessControls.ToImmutableDictionary();
|
||||||
|
}
|
||||||
|
|
||||||
if (rootMenu != null)
|
if (rootMenu != null)
|
||||||
{
|
{
|
||||||
RootMenuKey = rootMenu;
|
RootMenuKey = rootMenu;
|
||||||
@ -192,9 +236,12 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static VirtualMenu ForAvatar(VRCAvatarDescriptor avatar)
|
internal static VirtualMenu ForAvatar(
|
||||||
|
VRCAvatarDescriptor avatar,
|
||||||
|
BuildContext context = null
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var menu = new VirtualMenu(avatar.expressionsMenu);
|
var menu = new VirtualMenu(avatar.expressionsMenu, context);
|
||||||
foreach (var installer in avatar.GetComponentsInChildren<ModularAvatarMenuInstaller>(true))
|
foreach (var installer in avatar.GetComponentsInChildren<ModularAvatarMenuInstaller>(true))
|
||||||
{
|
{
|
||||||
menu.RegisterMenuInstaller(installer);
|
menu.RegisterMenuInstaller(installer);
|
||||||
@ -278,7 +325,8 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
_resolvedMenu[RootMenuKey] = RootNode;
|
_resolvedMenu[RootMenuKey] = RootNode;
|
||||||
|
|
||||||
var rootContext =
|
var rootContext =
|
||||||
new NodeContextImpl(RootNode, NodeFor, menuToInstallerFiltered, m => _visitedMenus.Add(m));
|
new NodeContextImpl(RootNode, NodeFor, menuToInstallerFiltered, _postprocessControlsHooks,
|
||||||
|
m => _visitedMenus.Add(m));
|
||||||
if (RootMenuKey is VRCExpressionsMenu menu)
|
if (RootMenuKey is VRCExpressionsMenu menu)
|
||||||
{
|
{
|
||||||
foreach (var control in menu.controls)
|
foreach (var control in menu.controls)
|
||||||
@ -311,6 +359,7 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
BuildReport.ReportingObject(key as UnityEngine.Object, () =>
|
BuildReport.ReportingObject(key as UnityEngine.Object, () =>
|
||||||
{
|
{
|
||||||
var context = new NodeContextImpl(node, NodeFor, menuToInstallerFiltered,
|
var context = new NodeContextImpl(node, NodeFor, menuToInstallerFiltered,
|
||||||
|
_postprocessControlsHooks,
|
||||||
m => _visitedMenus.Add(m));
|
m => _visitedMenus.Add(m));
|
||||||
if (key is VRCExpressionsMenu expMenu)
|
if (key is VRCExpressionsMenu expMenu)
|
||||||
{
|
{
|
||||||
|
@ -48,7 +48,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
|
|
||||||
_rootMenu = avatar.expressionsMenu;
|
_rootMenu = avatar.expressionsMenu;
|
||||||
var virtualMenu = VirtualMenu.ForAvatar(avatar);
|
var virtualMenu = VirtualMenu.ForAvatar(avatar, context);
|
||||||
avatar.expressionsMenu = virtualMenu.SerializeMenu(asset =>
|
avatar.expressionsMenu = virtualMenu.SerializeMenu(asset =>
|
||||||
{
|
{
|
||||||
context.SaveAsset(asset);
|
context.SaveAsset(asset);
|
||||||
|
@ -173,7 +173,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
{
|
{
|
||||||
if (installer.menuToAppend != null && installer.enabled)
|
if (installer.menuToAppend != null && installer.enabled)
|
||||||
{
|
{
|
||||||
ProcessMenu(ref installer.menuToAppend, remaps);
|
ProcessMenuInstaller(installer, remaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -208,40 +208,22 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessMenu(ref VRCExpressionsMenu rootMenu, ImmutableDictionary<string, string> remaps)
|
private void ProcessMenuInstaller(ModularAvatarMenuInstaller installer,
|
||||||
|
ImmutableDictionary<string, string> remaps)
|
||||||
{
|
{
|
||||||
Dictionary<VRCExpressionsMenu, VRCExpressionsMenu> remapped =
|
Dictionary<VRCExpressionsMenu, VRCExpressionsMenu> remapped =
|
||||||
new Dictionary<VRCExpressionsMenu, VRCExpressionsMenu>();
|
new Dictionary<VRCExpressionsMenu, VRCExpressionsMenu>();
|
||||||
|
|
||||||
rootMenu = Transform(rootMenu);
|
if (installer.menuToAppend == null) return;
|
||||||
|
|
||||||
VRCExpressionsMenu Transform(VRCExpressionsMenu menu)
|
_context.PostProcessControls.Add(installer, control =>
|
||||||
{
|
{
|
||||||
if (menu == null) return null;
|
control.parameter.name = remap(remaps, control.parameter.name);
|
||||||
|
foreach (var subParam in control.subParameters)
|
||||||
if (remapped.TryGetValue(menu, out var newMenu)) return newMenu;
|
|
||||||
|
|
||||||
newMenu = Object.Instantiate(menu);
|
|
||||||
_context.SaveAsset(newMenu);
|
|
||||||
remapped[menu] = newMenu;
|
|
||||||
ClonedMenuMappings.Add(menu, newMenu);
|
|
||||||
|
|
||||||
foreach (var control in newMenu.controls)
|
|
||||||
{
|
{
|
||||||
control.parameter.name = remap(remaps, control.parameter.name);
|
subParam.name = remap(remaps, subParam.name);
|
||||||
foreach (var subParam in control.subParameters)
|
|
||||||
{
|
|
||||||
subParam.name = remap(remaps, subParam.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (control.type == VRCExpressionsMenu.Control.ControlType.SubMenu)
|
|
||||||
{
|
|
||||||
control.subMenu = Transform(control.subMenu);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
return newMenu;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessAnimator(ref AnimatorController controller, ImmutableDictionary<string, string> remaps)
|
private void ProcessAnimator(ref AnimatorController controller, ImmutableDictionary<string, string> remaps)
|
||||||
@ -494,9 +476,17 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
// This is generic to simplify remapping parameter driver fields, some of which are 'object's.
|
// This is generic to simplify remapping parameter driver fields, some of which are 'object's.
|
||||||
private T remap<T>(ImmutableDictionary<string, string> remaps, T x)
|
private T remap<T>(ImmutableDictionary<string, string> remaps, T x)
|
||||||
where T : class
|
where T : class
|
||||||
|
{
|
||||||
|
bool tmp = false;
|
||||||
|
return remap(remaps, x, ref tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private T remap<T>(ImmutableDictionary<string, string> remaps, T x, ref bool anyRemapped)
|
||||||
|
where T : class
|
||||||
{
|
{
|
||||||
if (x is string s && remaps.TryGetValue(s, out var newS))
|
if (x is string s && remaps.TryGetValue(s, out var newS))
|
||||||
{
|
{
|
||||||
|
anyRemapped = true;
|
||||||
return (T) (object) newS;
|
return (T) (object) newS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user