From 64d831672a0617ee28ca522606ce91c95fc30006 Mon Sep 17 00:00:00 2001 From: bd_ Date: Tue, 28 Feb 2023 23:50:16 +0900 Subject: [PATCH] support disabling different parameters based on attached actions --- .../Editor/Inspector/Menu/MenuItemGUI.cs | 44 +++++--- .../Editor/Inspector/Menu/ParameterField.cs | 4 +- .../Menu/ActionProcessing/ActionGenerator.cs | 4 +- .../Menu/Actions/ActionToggleObject.cs | 61 ++--------- .../Runtime/Menu/Actions/MenuAction.cs | 102 ++++++++++++++++++ .../Runtime/Menu/Actions/MenuAction.cs.meta | 3 + 6 files changed, 143 insertions(+), 75 deletions(-) create mode 100644 Packages/nadena.dev.modular-avatar/Runtime/Menu/Actions/MenuAction.cs create mode 100644 Packages/nadena.dev.modular-avatar/Runtime/Menu/Actions/MenuAction.cs.meta diff --git a/Packages/nadena.dev.modular-avatar/Editor/Inspector/Menu/MenuItemGUI.cs b/Packages/nadena.dev.modular-avatar/Editor/Inspector/Menu/MenuItemGUI.cs index 3f755fe9..ce0a21a3 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/Inspector/Menu/MenuItemGUI.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/Inspector/Menu/MenuItemGUI.cs @@ -1,12 +1,9 @@ using System; using System.Linq; using System.Runtime.Serialization; -using Codice.CM.Common.Tree.Partial; using nadena.dev.modular_avatar.core.menu; -using NUnit.Framework; using UnityEditor; using UnityEngine; -using UnityEngine.UIElements; using VRC.SDK3.Avatars.ScriptableObjects; using static nadena.dev.modular_avatar.core.editor.Localization; @@ -54,11 +51,23 @@ namespace nadena.dev.modular_avatar.core.editor private bool _hasActions; - private bool HasActions() + private bool HasActions(TargetParameter? p = null) { return _toggleGroup != null && _obj.targetObjects.Any(o => - o is ModularAvatarMenuItem c && c.GetComponent() != null - ); + { + if (!(o is ModularAvatarMenuItem c)) return false; + if (p.HasValue) + { + foreach (var component in c.GetComponents()) + { + if (component.BindsParameter(p.Value)) return true; + } + + return false; + } + + return true; + }); } public MenuItemCoreGUI(SerializedObject obj, Action redraw) @@ -162,7 +171,7 @@ namespace nadena.dev.modular_avatar.core.editor } } - _parameterGUI.DoGUI(!_hasActions); + _parameterGUI.DoGUI(!_hasActions || !HasActions(TargetParameter.BaseParameter)); EditorGUILayout.EndVertical(); @@ -286,7 +295,8 @@ namespace nadena.dev.modular_avatar.core.editor { EnsureParameterCount(1); - _subParams[0].DoGUI(true, G("menuitem.param.rotation")); + _subParams[0].DoGUI(!_hasActions || !HasActions(TargetParameter.RadialParam), + G("menuitem.param.rotation")); break; } @@ -298,8 +308,10 @@ namespace nadena.dev.modular_avatar.core.editor EditorGUILayout.LabelField("Parameters", EditorStyles.boldLabel); EditorGUILayout.Space(2); - _subParams[0].DoGUI(true, G("menuitem.param.horizontal")); - _subParams[1].DoGUI(true, G("menuitem.param.vertical")); + _subParams[0].DoGUI(!_hasActions || !HasActions(TargetParameter.Horizontal), + G("menuitem.param.horizontal")); + _subParams[1].DoGUI(!_hasActions || !HasActions(TargetParameter.Vertical), + G("menuitem.param.vertical")); DoFourAxisLabels(false); @@ -396,10 +408,10 @@ namespace nadena.dev.modular_avatar.core.editor center.xMin += blockWidth; center.xMax -= blockWidth; - SingleLabel(0, up); - SingleLabel(1, right); - SingleLabel(2, down); - SingleLabel(3, left); + SingleLabel(0, up, TargetParameter.Up); + SingleLabel(1, right, TargetParameter.Right); + SingleLabel(2, down, TargetParameter.Down); + SingleLabel(3, left, TargetParameter.Left); var rect_param_l = center; rect_param_l.yMin = rect_param_l.yMax - EditorGUIUtility.singleLineHeight; @@ -409,7 +421,7 @@ namespace nadena.dev.modular_avatar.core.editor if (showParams) CenterLabel(rect_param_l, G("menuitem.prop.parameter"), EditorStyles.label); CenterLabel(rect_name_l, G("menuitem.prop.label"), EditorStyles.label); - void SingleLabel(int index, Rect block) + void SingleLabel(int index, Rect block, TargetParameter parameter) { var prop_name = _labels[index].FindPropertyRelative(nameof(VRCExpressionsMenu.Control.Label.name)); var prop_icon = _labels[index].FindPropertyRelative(nameof(VRCExpressionsMenu.Control.Label.icon)); @@ -426,7 +438,7 @@ namespace nadena.dev.modular_avatar.core.editor EditorGUI.PropertyField(rect_name, prop_name, GUIContent.none); if (showParams) { - _subParams[index].DoGUI(rect_param, true, GUIContent.none); + _subParams[index].DoGUI(rect_param, !_hasActions || !HasActions(parameter), GUIContent.none); } var tex = prop_icon.objectReferenceValue as Texture; diff --git a/Packages/nadena.dev.modular-avatar/Editor/Inspector/Menu/ParameterField.cs b/Packages/nadena.dev.modular-avatar/Editor/Inspector/Menu/ParameterField.cs index 04e4e5ef..90990032 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/Inspector/Menu/ParameterField.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/Inspector/Menu/ParameterField.cs @@ -23,7 +23,7 @@ namespace nadena.dev.modular_avatar.core.editor _redraw = redraw; } - public void DoGUI(bool enabled = true, GUIContent label = null) + public void DoGUI(bool enabled, GUIContent label = null) { DoGUI(EditorGUILayout.GetControlRect( true, @@ -31,7 +31,7 @@ namespace nadena.dev.modular_avatar.core.editor ), enabled, label); } - public void DoGUI(Rect rect, bool enabled = true, GUIContent label = null) + public void DoGUI(Rect rect, bool enabled, GUIContent label = null) { label = label ?? G("menuitem.prop.parameter"); diff --git a/Packages/nadena.dev.modular-avatar/Editor/Menu/ActionProcessing/ActionGenerator.cs b/Packages/nadena.dev.modular-avatar/Editor/Menu/ActionProcessing/ActionGenerator.cs index 98b0f869..1bc4e048 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/Menu/ActionProcessing/ActionGenerator.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/Menu/ActionProcessing/ActionGenerator.cs @@ -315,11 +315,11 @@ namespace nadena.dev.modular_avatar.core.editor void MergeCurves( IDictionary curves, ModularAvatarMenuItem item, - Func> getCurves, + Func> getCurves, bool ignoreDuplicates ) { - foreach (var action in item.GetComponents()) + foreach (var action in item.GetComponents()) { var newCurves = getCurves(action); diff --git a/Packages/nadena.dev.modular-avatar/Runtime/Menu/Actions/ActionToggleObject.cs b/Packages/nadena.dev.modular-avatar/Runtime/Menu/Actions/ActionToggleObject.cs index 7134a229..54de80c0 100644 --- a/Packages/nadena.dev.modular-avatar/Runtime/Menu/Actions/ActionToggleObject.cs +++ b/Packages/nadena.dev.modular-avatar/Runtime/Menu/Actions/ActionToggleObject.cs @@ -7,62 +7,8 @@ using Object = System.Object; namespace nadena.dev.modular_avatar.core { - public sealed class MenuCurveBinding - { - public readonly GameObject target; - public readonly Type type; - public readonly string property; - - public MenuCurveBinding(GameObject target, Type type, string property) - { - this.target = target; - this.type = type; - this.property = property; - } - - private bool Equals(MenuCurveBinding other) - { - return target == other.target && type == other.type && property == other.property; - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((MenuCurveBinding) obj); - } - - public override int GetHashCode() - { - unchecked - { - var hashCode = (target != null ? target.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (type != null ? type.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ (property != null ? property.GetHashCode() : 0); - return hashCode; - } - } - } - - public interface MenuAction - { - /// - /// Returns the curves applied when this action is active - /// - /// - ImmutableDictionary GetCurves(); - - /// - /// Returns the curves applied when this action is inactive (and no other actions override). - /// - /// True if this action is part of the default toggle option. - /// - ImmutableDictionary GetInactiveCurves(bool isDefault); - } - [RequireComponent(typeof(ModularAvatarMenuItem))] - public class ActionToggleObject : AvatarTagComponent, MenuAction + public class ActionToggleObject : AvatarTagComponent, SwitchedMenuAction { [Serializable] public class ObjectEntry @@ -102,5 +48,10 @@ namespace nadena.dev.modular_avatar.core } ).ToImmutableDictionary(); } + + public bool BindsParameter(TargetParameter parameter) + { + return parameter == TargetParameter.BaseParameter; + } } } \ No newline at end of file diff --git a/Packages/nadena.dev.modular-avatar/Runtime/Menu/Actions/MenuAction.cs b/Packages/nadena.dev.modular-avatar/Runtime/Menu/Actions/MenuAction.cs new file mode 100644 index 00000000..156b1400 --- /dev/null +++ b/Packages/nadena.dev.modular-avatar/Runtime/Menu/Actions/MenuAction.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Immutable; +using UnityEngine; + +namespace nadena.dev.modular_avatar.core +{ + public interface MenuAction + { + /// + /// Returns whether this action binds to the given parameter. + /// + /// + /// + bool BindsParameter(TargetParameter parameter); + } + + public interface SwitchedMenuAction : MenuAction + { + /// + /// Returns the curves applied when this action is active + /// + /// + ImmutableDictionary GetCurves(); + + /// + /// Returns the curves applied when this action is inactive (and no other actions override). + /// + /// True if this action is part of the default toggle option. + /// + ImmutableDictionary GetInactiveCurves(bool isDefault); + } + + public enum TargetParameter + { + BaseParameter, + RadialParam, + Horizontal, + Vertical, + Up, + Right, + Down, + Left + } + + public static class TargetParameterExtension + { + public static int Index(this TargetParameter p) + { + switch (p) + { + case TargetParameter.BaseParameter: + return -1; + case TargetParameter.RadialParam: return 0; + case TargetParameter.Horizontal: return 0; + case TargetParameter.Vertical: return 1; + case TargetParameter.Up: return 0; + case TargetParameter.Right: return 1; + case TargetParameter.Down: return 2; + case TargetParameter.Left: return 3; + default: throw new NotImplementedException(); + } + } + } + + public sealed class MenuCurveBinding + { + public readonly GameObject target; + public readonly Type type; + public readonly string property; + + public MenuCurveBinding(GameObject target, Type type, string property) + { + this.target = target; + this.type = type; + this.property = property; + } + + private bool Equals(MenuCurveBinding other) + { + return target == other.target && type == other.type && property == other.property; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((MenuCurveBinding) obj); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (target != null ? target.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (type != null ? type.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (property != null ? property.GetHashCode() : 0); + return hashCode; + } + } + } +} \ No newline at end of file diff --git a/Packages/nadena.dev.modular-avatar/Runtime/Menu/Actions/MenuAction.cs.meta b/Packages/nadena.dev.modular-avatar/Runtime/Menu/Actions/MenuAction.cs.meta new file mode 100644 index 00000000..8b49f440 --- /dev/null +++ b/Packages/nadena.dev.modular-avatar/Runtime/Menu/Actions/MenuAction.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 33005b045768474d8ae6f789aa03361b +timeCreated: 1677595006 \ No newline at end of file