fix: parent parameters can override child menu item default value

This commit is contained in:
nekobako 2024-09-13 02:56:31 +09:00
parent 3648348184
commit 0b2c8e7ac7
6 changed files with 107 additions and 59 deletions

View File

@ -88,7 +88,7 @@ namespace nadena.dev.modular_avatar.core.editor
IsAnimatorOnly = animatorOnly, IsAnimatorOnly = animatorOnly,
WantSynced = !p.localOnly, WantSynced = !p.localOnly,
IsHidden = p.internalParameter, IsHidden = p.internalParameter,
DefaultValue = p.defaultValue DefaultValue = p.HasDefaultValue ? p.defaultValue : null
}; };
}); });
} }

View File

@ -62,7 +62,7 @@ namespace nadena.dev.modular_avatar.core.editor
_computeContext.Observe(mami, c => (c.Control?.parameter, c.Control?.type, c.Control?.value, c.isDefault)); _computeContext.Observe(mami, c => (c.Control?.parameter, c.Control?.type, c.Control?.value, c.isDefault));
var mami_condition = ParameterAssignerPass.AssignMenuItemParameter(mami, _simulationInitialStates); var mami_condition = ParameterAssignerPass.AssignMenuItemParameter(mami, _simulationInitialStates, context: _computeContext);
if (mami_condition != null && if (mami_condition != null &&
ForceMenuItems.TryGetValue(mami_condition.Parameter, out var forcedMenuItem)) ForceMenuItems.TryGetValue(mami_condition.Parameter, out var forcedMenuItem))

View File

@ -61,7 +61,9 @@ namespace nadena.dev.modular_avatar.core.editor
var (paramName, value) = _context.Observe(mami, m => (m.Control.parameter.name, m.Control.value)); var (paramName, value) = _context.Observe(mami, m => (m.Control.parameter.name, m.Control.value));
if (TryGetRegisteredParam(mami, paramName, out var providedParameter)) if (!_context.Observe(mami, m => m.automaticValue)
&& TryGetRegisteredParam(mami, paramName, out var providedParameter)
&& providedParameter.DefaultValue != null)
{ {
var defaultValue = providedParameter.DefaultValue ?? 0; var defaultValue = providedParameter.DefaultValue ?? 0;
return Mathf.Abs(defaultValue - value) < 0.01f; return Mathf.Abs(defaultValue - value) < 0.01f;

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using nadena.dev.ndmf; using nadena.dev.ndmf;
using nadena.dev.ndmf.preview;
using UnityEngine; using UnityEngine;
using VRC.SDK3.Avatars.ScriptableObjects; using VRC.SDK3.Avatars.ScriptableObjects;
@ -177,6 +178,7 @@ namespace nadena.dev.modular_avatar.core.editor
ModularAvatarMenuItem mami, ModularAvatarMenuItem mami,
Dictionary<string, float> simulationInitialStates = null, Dictionary<string, float> simulationInitialStates = null,
IDictionary<string, ModularAvatarMenuItem> isDefaultOverrides = null, IDictionary<string, ModularAvatarMenuItem> isDefaultOverrides = null,
ComputeContext context = null,
bool? forceSimulation = null bool? forceSimulation = null
) )
{ {
@ -207,6 +209,10 @@ namespace nadena.dev.modular_avatar.core.editor
if (string.IsNullOrWhiteSpace(paramName)) return null; if (string.IsNullOrWhiteSpace(paramName)) return null;
var isEnabledForPreview = context != null
? new MenuItemPreviewCondition(context).IsEnabledForPreview(mami)
: mami.isDefault;
return new ControlCondition return new ControlCondition
{ {
Parameter = paramName, Parameter = paramName,
@ -215,7 +221,7 @@ namespace nadena.dev.modular_avatar.core.editor
// Note: This slightly odd-looking value is key to making the Auto checkbox work for editor previews; // Note: This slightly odd-looking value is key to making the Auto checkbox work for editor previews;
// we basically force-disable any conditions for nonselected menu items and force-enable any for default // we basically force-disable any conditions for nonselected menu items and force-enable any for default
// menu items. // menu items.
InitialValue = mami.isDefault ? mami.Control.value : -999, InitialValue = isEnabledForPreview ? mami.Control.value : -999,
ParameterValueLo = mami.Control.value - 0.005f, ParameterValueLo = mami.Control.value - 0.005f,
ParameterValueHi = mami.Control.value + 0.005f, ParameterValueHi = mami.Control.value + 0.005f,
DebugReference = mami, DebugReference = mami,

View File

@ -122,13 +122,6 @@ namespace nadena.dev.modular_avatar.core.editor
public void MergeChild(ParameterInfo info) public void MergeChild(ParameterInfo info)
{ {
MergeCommon(info); MergeCommon(info);
if (!ResolvedParameter.HasDefaultValue && info.ResolvedParameter.HasDefaultValue)
{
ResolvedParameter.defaultValue = info.ResolvedParameter.defaultValue;
ResolvedParameter.hasExplicitDefaultValue = info.ResolvedParameter.hasExplicitDefaultValue;
ResolvedParameter.m_overrideAnimatorDefaults = info.ResolvedParameter.m_overrideAnimatorDefaults;
}
} }
void MergeCommon(ParameterInfo info) void MergeCommon(ParameterInfo info)
@ -137,12 +130,29 @@ namespace nadena.dev.modular_avatar.core.editor
{ {
ResolvedParameter.syncType = info.ResolvedParameter.syncType; ResolvedParameter.syncType = info.ResolvedParameter.syncType;
} else if (ResolvedParameter.syncType != info.ResolvedParameter.syncType && info.ResolvedParameter.syncType != ParameterSyncType.NotSynced) } else if (ResolvedParameter.syncType != info.ResolvedParameter.syncType && info.ResolvedParameter.syncType != ParameterSyncType.NotSynced)
{
if (TypeSources.All(x => x is ModularAvatarMenuItem) && info.TypeSources.All(x => x is ModularAvatarMenuItem))
{
if (ResolvedParameter.syncType == ParameterSyncType.Bool || info.ResolvedParameter.syncType == ParameterSyncType.Float)
{
ResolvedParameter.syncType = info.ResolvedParameter.syncType;
}
}
else
{ {
TypeConflict = true; TypeConflict = true;
ConflictingSyncTypes = ConflictingSyncTypes ConflictingSyncTypes = ConflictingSyncTypes
.Add(ResolvedParameter.syncType) .Add(ResolvedParameter.syncType)
.Add(info.ResolvedParameter.syncType); .Add(info.ResolvedParameter.syncType);
} }
}
if (!ResolvedParameter.HasDefaultValue && info.ResolvedParameter.HasDefaultValue)
{
ResolvedParameter.defaultValue = info.ResolvedParameter.defaultValue;
ResolvedParameter.hasExplicitDefaultValue = info.ResolvedParameter.hasExplicitDefaultValue;
ResolvedParameter.m_overrideAnimatorDefaults = info.ResolvedParameter.m_overrideAnimatorDefaults;
}
TypeSources.AddRange(info.TypeSources); TypeSources.AddRange(info.TypeSources);
DefaultSources.AddRange(info.DefaultSources); DefaultSources.AddRange(info.DefaultSources);
@ -318,18 +328,23 @@ namespace nadena.dev.modular_avatar.core.editor
{ {
var paramInfo = ndmf.ParameterInfo.ForContext(_context.PluginBuildContext); var paramInfo = ndmf.ParameterInfo.ForContext(_context.PluginBuildContext);
ImmutableDictionary<string, ParameterInfo> rv = ImmutableDictionary<string, ParameterInfo>.Empty; var pInfos = obj.TryGetComponent<ModularAvatarParameters>(out var p)
var p = obj.GetComponent<ModularAvatarParameters>(); ? BuildReport.ReportingObject(p, () => CollectParameters(p, paramInfo.GetParameterRemappingsAt(p, true)))
if (p != null) : Array.Empty<ParameterInfo>();
{ var mInfos = obj.TryGetComponent<ModularAvatarMenuItem>(out var m)
rv = BuildReport.ReportingObject(p, () => CollectParameters(p, paramInfo.GetParameterRemappingsAt(p, true))); ? BuildReport.ReportingObject(m, () => CollectParameters(m, paramInfo.GetParameterRemappingsAt(m, true)))
} : Array.Empty<ParameterInfo>();
foreach (var merger in obj.GetComponents<ModularAvatarMergeAnimator>()) var rv = ImmutableDictionary<string, ParameterInfo>.Empty;
foreach (var info in Enumerable.Concat(pInfos, mInfos))
{ {
if (merger.deleteAttachedAnimator) if (rv.TryGetValue(info.ResolvedParameter.nameOrPrefix, out var priorInfo))
{ {
break; priorInfo.MergeSibling(info);
}
else
{
rv = rv.SetItem(info.ResolvedParameter.nameOrPrefix, info);
} }
} }
@ -417,27 +432,6 @@ namespace nadena.dev.modular_avatar.core.editor
break; break;
} }
case ModularAvatarMenuItem menuItem:
{
var remaps = paramInfo.GetParameterRemappingsAt(obj);
if (menuItem.Control.parameter?.name != null &&
remaps.TryGetValue((ParameterNamespace.Animator, menuItem.Control.parameter.name), out var newVal))
{
menuItem.Control.parameter.name = newVal.ParameterName;
}
foreach (var subParam in menuItem.Control.subParameters ??
Array.Empty<VRCExpressionsMenu.Control.Parameter>())
{
if (subParam?.name != null && remaps.TryGetValue((ParameterNamespace.Animator, subParam.name), out var subNewVal))
{
subParam.name = subNewVal.ParameterName;
}
}
break;
}
} }
}); });
} }
@ -710,14 +704,10 @@ namespace nadena.dev.modular_avatar.core.editor
if (dirty) t.conditions = conditions; if (dirty) t.conditions = conditions;
} }
private ImmutableDictionary<string, ParameterInfo> CollectParameters(ModularAvatarParameters p, private IEnumerable<ParameterInfo> CollectParameters(ModularAvatarParameters p,
ImmutableDictionary<(ParameterNamespace, string), ParameterMapping> remaps ImmutableDictionary<(ParameterNamespace, string), ParameterMapping> remaps
) )
{ {
var remapper = ParameterRenameMappings.Get(_context.PluginBuildContext);
ImmutableDictionary<string, ParameterInfo> parameterInfos = ImmutableDictionary<string, ParameterInfo>.Empty;
foreach (var param in p.parameters) foreach (var param in p.parameters)
{ {
if (param.isPrefix) continue; if (param.isPrefix) continue;
@ -747,17 +737,58 @@ namespace nadena.dev.modular_avatar.core.editor
info.DefaultSources.Add(p); info.DefaultSources.Add(p);
} }
if (parameterInfos.TryGetValue(remapTo, out var existing)) yield return info;
{
existing.MergeSibling(info);
}
else
{
parameterInfos = parameterInfos.SetItem(remapTo, info);
} }
} }
return parameterInfos; private IEnumerable<ParameterInfo> CollectParameters(ModularAvatarMenuItem m,
ImmutableDictionary<(ParameterNamespace, string), ParameterMapping> remaps
)
{
if (!string.IsNullOrEmpty(m.Control?.parameter?.name)
&& remaps.TryGetValue((ParameterNamespace.Animator, m.Control.parameter.name), out var mapping))
{
m.Control.parameter.name = mapping.ParameterName;
}
foreach (var subParam in m.Control?.subParameters ?? Array.Empty<VRCExpressionsMenu.Control.Parameter>())
{
if (!string.IsNullOrEmpty(subParam?.name)
&& remaps.TryGetValue((ParameterNamespace.Animator, subParam.name), out var subParamMapping))
{
subParam.name = subParamMapping.ParameterName;
}
}
if (m.automaticValue) yield break;
if (string.IsNullOrWhiteSpace(m.Control?.parameter?.name)) yield break;
if (!ParameterAssignerPass.ShouldAssignParametersToMami(m)) yield break;
var info = new ParameterInfo()
{
ResolvedParameter = new()
{
nameOrPrefix = m.Control.parameter?.name,
remapTo = m.Control.parameter?.name,
syncType = m.ParameterSyncType,
saved = m.isSaved,
localOnly = !m.isSynced,
defaultValue = m.isDefault ? m.Control.value : 0,
hasExplicitDefaultValue = m.isDefault,
},
};
if (info.ResolvedParameter.syncType != ParameterSyncType.NotSynced)
{
info.TypeSources.Add(m);
}
if (info.ResolvedParameter.HasDefaultValue)
{
info.DefaultSources.Add(m);
}
yield return info;
} }
// 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.

View File

@ -181,6 +181,15 @@ namespace nadena.dev.modular_avatar.core
VRCExpressionParameters.ValueType.Float => AnimatorControllerParameterType.Float, VRCExpressionParameters.ValueType.Float => AnimatorControllerParameterType.Float,
_ => 0, _ => 0,
}; };
internal ParameterSyncType ParameterSyncType
=> ExpressionParametersValueType switch
{
VRCExpressionParameters.ValueType.Bool => ParameterSyncType.Bool,
VRCExpressionParameters.ValueType.Int => ParameterSyncType.Int,
VRCExpressionParameters.ValueType.Float => ParameterSyncType.Float,
_ => 0,
};
} }
} }