diff --git a/.markdown/Debug/AnimatorDebug.gif b/.markdown/Debug/AnimatorDebug.gif new file mode 100644 index 0000000..9aa1dcb Binary files /dev/null and b/.markdown/Debug/AnimatorDebug.gif differ diff --git a/.v3rsion b/.v3rsion index b8cbcb7..40881f9 100644 --- a/.v3rsion +++ b/.v3rsion @@ -1,2 +1,2 @@ -3.9.2 -https://github.com/BlackStartx/VRC-Gesture-Manager/releases/tag/v3.9.2 \ No newline at end of file +3.9.3 +https://github.com/BlackStartx/VRC-Gesture-Manager/releases/tag/v3.9.3 \ No newline at end of file diff --git a/README.md b/README.md index 7afba09..a0a7000 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,20 @@ You can switch between OSC Messages and OSC bundles by clicking the "Bundle" or ![img.png](.markdown/3.8/SendOsc.png) +# Animator Debugging + +While testing your avatar you can control and preview the flow of your animators in the "Animator" window +of the Unity Editor and gain information on why the avatar is not behaving how you would expect. + +Getting the preview of any Animator is very easy: + +> Select your Avatar > Double-Click the Playable Layer + +The Unity Animator window should open, and you can now preview the flow of the selected +Playable Layer, and dig up the reason on why things are not working as expected~ + +![img.gif](.markdown/Debug/AnimatorDebug.gif) + ### Knew Issues ♥ All the knew issues since the release of 3.0 has been addressed! ♥ diff --git a/Scripts/Editor/Data/GestureManagerSettings.cs b/Scripts/Editor/Data/GestureManagerSettings.cs index b433104..2aedb36 100644 --- a/Scripts/Editor/Data/GestureManagerSettings.cs +++ b/Scripts/Editor/Data/GestureManagerSettings.cs @@ -57,6 +57,7 @@ private static void SimulationSettings(GestureManager manager) GUILayout.Label("Default Parameters", GestureManagerStyles.ToolSubHeader); GUILayout.Label("Set the initial states of the default parameters!", GestureManagerStyles.SettingsText); using (new GUILayout.HorizontalScope()) DefaultParametersSettings(manager); + manager.settings.isOnFriendsList = GmgLayoutHelper.Toggle("IsOnFriendList: ", manager.settings.isOnFriendsList, manager); } private static void BlendShapeSettings(string label = "Blend-Shapes Clamping: ") diff --git a/Scripts/Editor/GestureManagerEditor.cs b/Scripts/Editor/GestureManagerEditor.cs index 776f3e1..d3c6e94 100644 --- a/Scripts/Editor/GestureManagerEditor.cs +++ b/Scripts/Editor/GestureManagerEditor.cs @@ -86,7 +86,8 @@ public override VisualElement CreateInspectorGUI() private void TryInitialize() { if (!Manager.enabled || !Manager.gameObject.activeInHierarchy || Manager.Module != null) return; - Manager.StartCoroutine(TryInitializeRoutine(ModuleHelper.GetModuleFor(Manager.settings.favourite))); + var enumerator = TryInitializeRoutine(ModuleHelper.GetModuleFor(Manager.settings.favourite)); + Manager.StartCoroutine(enumerator); } private IEnumerator TryInitializeRoutine(ModuleBase module) diff --git a/Scripts/Editor/Library/GmgLayoutHelper.cs b/Scripts/Editor/Library/GmgLayoutHelper.cs index 3c9d4b3..9e631b3 100644 --- a/Scripts/Editor/Library/GmgLayoutHelper.cs +++ b/Scripts/Editor/Library/GmgLayoutHelper.cs @@ -76,7 +76,7 @@ public static bool SettingsGearLabel(string text, bool active, int pixels = 25) } } - public static bool UnityFieldEnterListener(T1 initialText, T2 argument, Rect rect, Func field, Action onEscape, string controlName) + public static bool UnityFieldEnterListener(T1 initialText, T2 argument, Rect rect, Func field, Action onEscape, string controlName) { if (_unityFieldEnterListenerName != controlName) _unityFieldEnterListenerData = null; var isEnter = Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter; @@ -86,7 +86,7 @@ public static bool UnityFieldEnterListener(T1 initialText, T2 argument, GUI.FocusControl(controlName); _unityFieldEnterListenerData ??= initialText; var t = field(rect, _unityFieldEnterListenerData is T1 d ? d : default); - if (isEnter) onEscape(argument, _unityFieldEnterListenerData is T1 data ? data : default); + if (isEnter) onEscape(argument, _unityFieldEnterListenerData is T1 data ? data : default, null); else _unityFieldEnterListenerData = t; if (!isEnter && !isEscape) return false; _unityFieldEnterListenerData = null; diff --git a/Scripts/Editor/Modules/Vrc3/AvatarDynamics/AvatarDynamicReset.cs b/Scripts/Editor/Modules/Vrc3/AvatarDynamics/AvatarDynamicReset.cs index d65c401..2baa64b 100644 --- a/Scripts/Editor/Modules/Vrc3/AvatarDynamics/AvatarDynamicReset.cs +++ b/Scripts/Editor/Modules/Vrc3/AvatarDynamics/AvatarDynamicReset.cs @@ -1,6 +1,10 @@ #if VRC_SDK_VRCSDK3 +using System.Collections.Generic; +using System.Linq; using UnityEngine; using VRC.Dynamics; +using VRC.SDK3.Avatars.Components; +using VRC.SDK3.Dynamics.Contact.Components; using VRC.SDK3.Dynamics.PhysBone; namespace BlackStartX.GestureManager.Editor.Modules.Vrc3.AvatarDynamics @@ -10,10 +14,30 @@ public static class AvatarDynamicReset private const string TriggerManagerName = "TriggerManager"; private const string PhysBoneManagerName = "PhysBoneManager"; - public static void CheckSceneCollisions() + private const VRCAvatarDescriptor.ColliderConfig.State Disabled = VRCAvatarDescriptor.ColliderConfig.State.Disabled; + + private static readonly Dictionary, string[])> Bones = new() + { + { HumanBodyBones.Head, (vrc => vrc.collider_head, new[] { "Head" }) }, + { HumanBodyBones.Chest, (vrc => vrc.collider_torso, new[] { "Torso" }) }, + { HumanBodyBones.LeftFoot, (vrc => vrc.collider_footL, new[] { "Foot", "FootL" }) }, + { HumanBodyBones.RightFoot, (vrc => vrc.collider_footR, new[] { "Foot", "FootR" }) }, + { HumanBodyBones.LeftHand, (vrc => vrc.collider_handL, new[] { "Hand", "HandL" }) }, + { HumanBodyBones.RightHand, (vrc => vrc.collider_handR, new[] { "Hand", "HandR" }) }, + { HumanBodyBones.LeftRingProximal, (vrc => vrc.collider_fingerRingL, new[] { "Finger", "FingerL", "FingerRing", "FingerRingL" }) }, + { HumanBodyBones.RightRingProximal, (vrc => vrc.collider_fingerRingR, new[] { "Finger", "FingerR", "FingerRing", "FingerRingR" }) }, + { HumanBodyBones.LeftIndexProximal, (vrc => vrc.collider_fingerIndexL, new[] { "Finger", "FingerL", "FingerIndex", "FingerIndexL" }) }, + { HumanBodyBones.RightIndexProximal, (vrc => vrc.collider_fingerIndexR, new[] { "Finger", "FingerR", "FingerIndex", "FingerIndexR" }) }, + { HumanBodyBones.LeftLittleProximal, (vrc => vrc.collider_fingerLittleL, new[] { "Finger", "FingerL", "FingerLittle", "FingerLittleL" }) }, + { HumanBodyBones.RightLittleProximal, (vrc => vrc.collider_fingerLittleR, new[] { "Finger", "FingerR", "FingerLittle", "FingerLittleR" }) }, + { HumanBodyBones.LeftMiddleProximal, (vrc => vrc.collider_fingerMiddleL, new[] { "Finger", "FingerL", "FingerMiddle", "FingerMiddleL" }) }, + { HumanBodyBones.RightMiddleProximal, (vrc => vrc.collider_fingerMiddleR, new[] { "Finger", "FingerR", "FingerMiddle", "FingerMiddleR" }) } + }; + + public static void CheckOrRestartManagers() { - if (!ContactManager.Inst) ResumeContactManager(); - if (!PhysBoneManager.Inst) ResumePhysBoneManager(); + if (!ContactManager.Inst) RestartContactManager(); + if (!PhysBoneManager.Inst) RestartPhysBoneManager(); } private static void RecreateComponent(T original) where T : Component @@ -21,10 +45,11 @@ private static void RecreateComponent(T original) where T : Component var type = original.GetType(); var component = original.gameObject.AddComponent(type); foreach (var field in type.GetFields()) field.SetValue(component, field.GetValue(original)); + component.hideFlags = original.hideFlags; Object.DestroyImmediate(original); } - private static void ResumeContactManager() + private static void RestartContactManager() { Object.DestroyImmediate(GameObject.Find(TriggerManagerName)); var obj = new GameObject(TriggerManagerName); @@ -33,7 +58,7 @@ private static void ResumeContactManager() foreach (var contact in Resources.FindObjectsOfTypeAll()) RecreateComponent(contact); } - private static void ResumePhysBoneManager() + private static void RestartPhysBoneManager() { Object.DestroyImmediate(GameObject.Find(PhysBoneManagerName)); var obj = new GameObject(PhysBoneManagerName); @@ -44,6 +69,32 @@ private static void ResumePhysBoneManager() obj.AddComponent(); foreach (var physBone in Resources.FindObjectsOfTypeAll()) RecreateComponent(physBone); } + + public static void ReinstallAvatarColliders(ModuleVrc3 module) + { + var sEnumerable = module.Avatar.GetComponentsInChildren().Where(sender => sender.hideFlags == HideFlags.HideAndDontSave); + foreach (var sender in sEnumerable) Object.DestroyImmediate(sender); + foreach (var pair in Bones) + { + var transform = module.AvatarAnimator.GetBoneTransform(pair.Key); + var collider = pair.Value.Item1(module.AvatarDescriptor); + if (!transform || collider.state == Disabled) continue; + Install(transform, collider, pair.Value.Item2); + } + } + + private static void Install(Transform transform, VRCAvatarDescriptor.ColliderConfig collider, string[] tags) + { + var sender = transform.gameObject.AddComponent(); + sender.shapeType = ContactBase.ShapeType.Capsule; + sender.hideFlags = HideFlags.HideAndDontSave; + sender.position = collider.position; + sender.rotation = collider.rotation; + sender.collisionTags.AddRange(tags); + sender.rootTransform = transform; + sender.height = collider.height; + sender.radius = collider.radius; + } } } #endif \ No newline at end of file diff --git a/Scripts/Editor/Modules/Vrc3/ModuleVrc3.cs b/Scripts/Editor/Modules/Vrc3/ModuleVrc3.cs index 252100b..1b1a773 100644 --- a/Scripts/Editor/Modules/Vrc3/ModuleVrc3.cs +++ b/Scripts/Editor/Modules/Vrc3/ModuleVrc3.cs @@ -39,6 +39,7 @@ public class ModuleVrc3 : ModuleBase private const string OutputName = "Gesture Manager"; private const int OutputValue = 0; + private const int PlayerId = 1; internal readonly AvatarTools AvatarTools; internal readonly OscModule OscModule; @@ -47,8 +48,6 @@ public class ModuleVrc3 : ModuleBase private Vrc3AvatarDebugWindow _debugAvatarWindow; internal Vrc3OscDebugWindow DebugOscWindow; - internal Vrc3DummyMode DummyMode; - private PlayableGraph _playableGraph; private string _paramFilter; private Vector3 _baseScale; @@ -57,35 +56,36 @@ public class ModuleVrc3 : ModuleBase private float _scale; private bool _hooked; - internal readonly Vrc3Param PoseT; - internal readonly Vrc3Param PoseIK; - - private readonly Dictionary _layers = new(); - private readonly Dictionary<(Motion, VRCAvatarDescriptor.AnimLayerType), MotionItem> _motions = new(); private readonly Dictionary _weightControllers = new(); private readonly Dictionary _oscContainers = new(); private readonly Dictionary _radialMenus = new(); + private readonly List _brokenLayers = new(); private readonly List _warnings = new(); [PublicAPI] public readonly Dictionary Params = new(); - internal Dictionary FilteredParams = new(); + internal Dictionary UserFilteredParams = new(); + internal Dictionary VrcFilteredParams = new(); + internal readonly Dictionary TrackingControls = ModuleVrc3Styles.Data.DefaultTrackingState; internal bool LocomotionDisabled; internal bool PoseSpace; - internal bool PoseMode; - internal readonly Dictionary TrackingControls = ModuleVrc3Styles.Data.DefaultTrackingState; + private readonly Dictionary<(Motion, VRCAvatarDescriptor.AnimLayerType), MotionItem> _motions = new(); internal readonly Dictionary AnimationHashSet = new(); + private readonly Dictionary _layers = new(); internal readonly HashSet Receivers = new(); private readonly HashSet _physBones = new(); - private readonly HashSet _senders = new(); private readonly HashSet _animators = new(); private readonly HashSet _cloths = new(); + internal readonly Vrc3Param PoseIK; + internal readonly Vrc3Param PoseT; + internal Vrc3DummyMode DummyMode; internal int DebugToolBar; - internal string Edit; + internal bool PoseMode; internal bool Broken; + internal string Edit; private static readonly GUILayoutOption SizeOptions = GUILayout.Height(RadialMenu.Size); private static readonly GUILayoutOption[] Options = { GUILayout.ExpandWidth(true), SizeOptions }; @@ -161,7 +161,6 @@ public override void InitForAvatar() _animators.Clear(); _brokenLayers.Clear(); - _senders.Clear(); Receivers.Clear(); for (var i = 1; i < intCount; i++) @@ -179,10 +178,10 @@ public override void InitForAvatar() if (!_motions.ContainsKey((clip, layer.type))) _motions[(clip, layer.type)] = new MotionItem(clip, layer.type); - var controller = Vrc3ProxyOverride.OverrideController(layer.isDefault ? RequestBuiltInController(layer.type) : layer.animatorController); + var controller = layer.isDefault ? RequestBuiltInController(layer.type) : layer.animatorController; var mask = layer.isDefault || !layer.mask && isFx ? ModuleVrc3Styles.Data.MaskOf(layer.type) : layer.mask; - var playable = AnimatorControllerPlayable.Create(_playableGraph, controller); + var playable = AnimatorControllerPlayable.Create(_playableGraph, Vrc3ProxyOverride.OverrideController(controller)); var weight = new AnimatorControllerWeight(mixer, playable, i); _layers[layer.type] = new LayerData { Playable = playable, Weight = weight, Empty = playable.GetInput(0).IsNull() }; @@ -212,6 +211,7 @@ public override void InitForAvatar() GetParam(Vrc3DefaultParams.VRMode).InternalSet(Settings.vrMode ? 1f : 0f); GetParam(Vrc3DefaultParams.IsLocal).InternalSet(Settings.isRemote ? 0f : 1f); + GetParam(Vrc3DefaultParams.IsOnFriendsList).InternalSet(Settings.isOnFriendsList ? 1f : 0f); _playableGraph.Play(); _playableGraph.Evaluate(0f); @@ -418,7 +418,7 @@ private void SetVelocityMag() ).magnitude); } - private RuntimeAnimatorController RequestBuiltInController(VRCAvatarDescriptor.AnimLayerType type) + private AnimatorController RequestBuiltInController(VRCAvatarDescriptor.AnimLayerType type) { var controller = ModuleVrc3Styles.Data.ControllerOf(type); var restoreAsset = ModuleVrc3Styles.Data.RestoreOf(type); @@ -709,7 +709,7 @@ private void InitParams(VRCExpressionParameters parameters) if (Settings.loadStored) TryAddWarning(InitStored()); - FilteredParams = FilterParam(); + FilterParam(); } private Vrc3Warning InitStored() @@ -817,7 +817,7 @@ private static void SetBlendShapeWeight(SkinnedMeshRenderer skinnedMesh, string public void ParamFilterSearch() { if (_paramFilter == (_paramFilter = GmgLayoutHelper.SearchBar(_paramFilter))) return; - FilteredParams = FilterParam(); + FilterParam(); } internal void TryAddWarning(Vrc3Warning warning) @@ -828,9 +828,17 @@ internal void TryAddWarning(Vrc3Warning warning) internal void TryRemoveWarning(Vrc3Warning warning) => _warnings.Remove(warning); - private Dictionary FilterParam() => string.IsNullOrEmpty(_paramFilter) ? Params : Params.Where(ParamMatch).ToDictionary(pair => pair.Key, pair => pair.Value); + private void FilterParam() + { + UserFilteredParams = Params.Where(ParamMatch).Where(IsUserParam).ToDictionary(pair => pair.Key, pair => pair.Value); + VrcFilteredParams = Params.Where(ParamMatch).Where(IsVrcParam).ToDictionary(pair => pair.Key, pair => pair.Value); + } + + private bool ParamMatch(KeyValuePair pair) => string.IsNullOrEmpty(_paramFilter) || pair.Key.IndexOf(_paramFilter, StringComparison.OrdinalIgnoreCase) >= 0; + + private static bool IsUserParam(KeyValuePair pair) => !Vrc3DefaultParams.Parameters.ContainsKey(pair.Key); - private bool ParamMatch(KeyValuePair pair) => pair.Key.IndexOf(_paramFilter, StringComparison.OrdinalIgnoreCase) >= 0; + private static bool IsVrcParam(KeyValuePair pair) => Vrc3DefaultParams.Parameters.ContainsKey(pair.Key); /* * Vrc Hooks @@ -839,7 +847,8 @@ internal void TryAddWarning(Vrc3Warning warning) private void StartVrcHooks() { if (_hooked) return; - AvatarDynamicReset.CheckSceneCollisions(); + AvatarDynamicReset.CheckOrRestartManagers(); + AvatarDynamicReset.ReinstallAvatarColliders(this); EditorApplication.pauseStateChanged += OnEditorPauseChange; OnEditorPauseChange(EditorApplication.isPaused, Vrc3Warning.PausedEditor); @@ -908,7 +917,7 @@ private void AnimatorPlayAudioEnterState(VRC_AnimatorPlayAudio audio, Animator a { if (!_hooked || !_animators.Contains(animator)) return; - var source = audio.Source ? audio.Source : audio.Source = Avatar.transform.Find(audio.SourcePath).GetComponent(); + var source = audio.Source ? audio.Source : audio.Source = Avatar.transform.Find(audio.SourcePath)?.GetComponent(); if (!source) return; if (audio.StopOnEnter) source.Stop(); @@ -919,7 +928,7 @@ private void AnimatorPlayAudioExitState(VRC_AnimatorPlayAudio audio, Animator an { if (!_hooked || !_animators.Contains(animator)) return; - var source = audio.Source ? audio.Source : audio.Source = Avatar.transform.Find(audio.SourcePath).GetComponent(); + var source = audio.Source ? audio.Source : audio.Source = Avatar.transform.Find(audio.SourcePath)?.GetComponent(); if (!source) return; if (audio.StopOnExit) source.Stop(); @@ -952,7 +961,7 @@ private void AvatarParameterDriverSettings(VRC_AvatarParameterDriver driver, Ani switch (parameter.type) { case VRC_AvatarParameterDriver.ChangeType.Set: - param.Set(this, parameter.value); + param.Set(this, parameter.value, driver); break; case VRC_AvatarParameterDriver.ChangeType.Add: param.Add(this, parameter.value); @@ -1023,8 +1032,8 @@ private bool ContactBaseInit(ContactBase contactBase) private void ReceiverBaseSetup(ContactReceiver receiver) { Receivers.Add(receiver); + receiver.playerId = PlayerId; receiver.paramAccess = new AnimParameterAccessAvatarGmg(this, receiver.parameter); - if (receiver.shape != null) receiver.shape.OnEnter += shape => ContactShapeCheck(receiver, shape.component as ContactSender); } private void AudioSourcePlayAudio(AudioSource source, VRC_AnimatorPlayAudio audio, float delayValue = 0f) @@ -1039,6 +1048,8 @@ private void AudioSourcePlayAudio(AudioSource source, VRC_AnimatorPlayAudio audi source.PlayDelayed(delayValue); } + private static void SenderBaseSetup(ContactSender sender) => sender.playerId = PlayerId; + private static AudioClip NextClip(VRC_AnimatorPlayAudio audio, int index) => (audio.playbackIndex = index) < audio.Clips.Length ? audio.Clips[audio.playbackIndex] : null; private int NextIndex(VRC_AnimatorPlayAudio audio, int length) => audio.PlaybackOrder switch @@ -1052,15 +1063,6 @@ private void AudioSourcePlayAudio(AudioSource source, VRC_AnimatorPlayAudio audi private void ClothBaseSetup(Cloth cloth) => _cloths.Add(cloth); - private void SenderBaseSetup(ContactSender sender) => _senders.Add(sender); - - private void ContactShapeCheck(ContactReceiver receiver, ContactSender sender) - { - if (!sender || !receiver) return; - if (!receiver.allowSelf && _senders.Contains(sender)) receiver.shape.OnExit.Invoke(sender.shape); - if (!receiver.allowOthers && !_senders.Contains(sender)) receiver.shape.OnExit.Invoke(sender.shape); - } - private void AnimatorBaseSetup(Animator animator) { _animators.Add(animator); diff --git a/Scripts/Editor/Modules/Vrc3/Params/Vrc3Param.cs b/Scripts/Editor/Modules/Vrc3/Params/Vrc3Param.cs index 7170f71..43fda25 100644 --- a/Scripts/Editor/Modules/Vrc3/Params/Vrc3Param.cs +++ b/Scripts/Editor/Modules/Vrc3/Params/Vrc3Param.cs @@ -5,6 +5,7 @@ using UnityEngine; using UnityEngine.Animations; using UnityEngine.Playables; +using VRC.SDKBase; namespace BlackStartX.GestureManager.Editor.Modules.Vrc3.Params { @@ -31,11 +32,11 @@ public Vrc3Param(string name, AnimatorControllerParameterType type, Action Subscribe(playable, index); - public void Set(ModuleVrc3 module, float value) + public void Set(ModuleVrc3 module, float value, object source = null) { var isSame = RadialMenuUtility.Is(FloatValue(), value); LastUpdate = Time; - InternalSet(value); + InternalSet(value, source); if (isSame) return; _onChange?.Invoke(this, value); module.OscModule.OnParameterChange(this, value); @@ -48,18 +49,23 @@ public void Set(ModuleVrc3 module, float value) public void Subscribe(AnimatorControllerPlayable playable, int index) => _controllers[playable] = index; - public void Set(ModuleVrc3 module, bool value) => Set(module, value ? 1f : 0f); + public void Set(ModuleVrc3 module, bool value, object source = null) => Set(module, value ? 1f : 0f, source); - public void Set(ModuleVrc3 module, int value) => Set(module, (float)value); + public void Set(ModuleVrc3 module, int value, object source = null) => Set(module, (float)value, source); - public void Set(ModuleVrc3 module, float? value) + public void Set(ModuleVrc3 module, float? value, object source = null) { - if (value.HasValue) Set(module, value.Value); + if (value.HasValue) Set(module, value.Value, source); } - public void Set(ModuleVrc3 module, bool? value) + public void Set(ModuleVrc3 module, int? value, object source = null) { - if (value.HasValue) Set(module, value.Value); + if (value.HasValue) Set(module, value.Value, source); + } + + public void Set(ModuleVrc3 module, bool? value, object source = null) + { + if (value.HasValue) Set(module, value.Value, source); } public void SetOnChange(Action onChange) => _onChange = onChange; @@ -83,7 +89,10 @@ public virtual float FloatValue() _ => _value }; - protected internal virtual void InternalSet(float value) + [Obsolete] + protected internal virtual void InternalSet(float value) => InternalSet(value, source: null); + + protected internal virtual void InternalSet(float value, object source) { _value = value; foreach (var pair in _controllers.Where(pair => ModuleVrc3.IsValid(pair.Key))) @@ -97,7 +106,7 @@ protected internal virtual void InternalSet(float value) pair.Key.SetInteger(_hashId, (int)Math.Round(value)); break; case AnimatorControllerParameterType.Trigger: - pair.Key.SetTrigger(_hashId); + if (value != 0f || source is VRC_AvatarParameterDriver) pair.Key.SetTrigger(_hashId); break; case AnimatorControllerParameterType.Bool: pair.Key.SetBool(_hashId, value != 0f); diff --git a/Scripts/Editor/Modules/Vrc3/Tools/AvatarTools.cs b/Scripts/Editor/Modules/Vrc3/Tools/AvatarTools.cs index dc0f144..4fa4148 100644 --- a/Scripts/Editor/Modules/Vrc3/Tools/AvatarTools.cs +++ b/Scripts/Editor/Modules/Vrc3/Tools/AvatarTools.cs @@ -451,8 +451,6 @@ public class AnimatorPerformance : GmgDynamicFunction "PreLateUpdate.DirectorUpdateAnimationEnd" }; - private static readonly int[] Markers = new int[MarkerNames.Length]; - protected internal override string Name => "Animator Performance"; protected override string Description => "A simple benchmark using the Unity Profiler!\n\nAimed to show animator update calls usages!"; protected internal override bool Active => Profiler.enabled; @@ -503,13 +501,7 @@ private static void CacheMarkerIds() if (MarkerIds.Count != 0) return; using var frameData = ProfilerDriver.GetRawFrameDataView(ProfilerDriver.lastFrameIndex, Thread); _playerLoopMarkerId = frameData.GetMarkerId(PlayerLoopName); - for (var i = 0; i < MarkerNames.Length; i++) - { - var name = MarkerNames[i]; - var intValue = frameData.GetMarkerId(name); - MarkerIds.Add(intValue, name); - Markers[i] = intValue; - } + foreach (var name in MarkerNames) MarkerIds.Add(frameData.GetMarkerId(name), name); } private void GetIds(HierarchyFrameDataView frameData) diff --git a/Scripts/Editor/Modules/Vrc3/Vrc3Debug/Avatar/Vrc3AvatarDebugWindow.cs b/Scripts/Editor/Modules/Vrc3/Vrc3Debug/Avatar/Vrc3AvatarDebugWindow.cs index c71da9c..8d6fb1b 100644 --- a/Scripts/Editor/Modules/Vrc3/Vrc3Debug/Avatar/Vrc3AvatarDebugWindow.cs +++ b/Scripts/Editor/Modules/Vrc3/Vrc3Debug/Avatar/Vrc3AvatarDebugWindow.cs @@ -18,6 +18,7 @@ internal class Vrc3AvatarDebugWindow : EditorWindow private Vector2 _scroll; private static Color Color => EditorGUIUtility.isProSkin ? Color.magenta : Color.cyan; + private static readonly GUIStyle Style = new(EditorStyles.label) { fontSize = 10, alignment = TextAnchor.MiddleCenter }; internal static Vrc3AvatarDebugWindow Create(ModuleVrc3 source) { @@ -103,50 +104,68 @@ internal static void DummyLayout(string mode) private static void ParametersLayout(ModuleVrc3 module, float width) { - var widthOption = GUILayout.Width(width); - var innerOption = GUILayout.Width(width / 3); + var wOption = GUILayout.Width(width); + var iOption = GUILayout.Width(width / 3); using (new GUILayout.VerticalScope()) { - GUILayout.Label("Parameters", GestureManagerStyles.GuiHandTitle, widthOption); + GUILayout.Label("Parameters", GestureManagerStyles.GuiHandTitle, wOption); module.ParamFilterSearch(); GUILayout.Space(5); - using (new GUILayout.HorizontalScope(widthOption)) + using (new GUILayout.HorizontalScope(wOption)) { - GUILayout.Label("Parameter", GestureManagerStyles.GuiDebugTitle, innerOption); - GUILayout.Label("Type", GestureManagerStyles.GuiDebugTitle, innerOption); - GUILayout.Label("Value", GestureManagerStyles.GuiDebugTitle, innerOption); + GUILayout.Label("Parameter", GestureManagerStyles.GuiDebugTitle, iOption); + GUILayout.Label("Type", GestureManagerStyles.GuiDebugTitle, iOption); + GUILayout.Label("Value", GestureManagerStyles.GuiDebugTitle, iOption); } - var color = GUI.backgroundColor; var intTime = Vrc3Param.Time; - foreach (var paramPair in module.FilteredParams) - { - GUILayout.Space(-4); - GUI.backgroundColor = Color.Lerp(Color, color, (intTime - paramPair.Value.LastUpdate) / 100f); - using (new GUILayout.HorizontalScope(GUI.skin.box, widthOption)) - { - GUILayout.Label(paramPair.Key, innerOption); - GUILayout.Label(paramPair.Value.TypeText, innerOption); - ParametersLayoutValue(module, paramPair, innerOption); - } - } + ParametersCategory(module.UserFilteredParams, "[User Parameters]", width, wOption, iOption, intTime, module); + ParametersCategory(module.VrcFilteredParams, "[VRC Defaults]", width, wOption, iOption, intTime, module); + } + } + + private static void ParametersCategory(Dictionary vParams, string title, float width, GUILayoutOption wOption, GUILayoutOption iOption, int intTime, ModuleVrc3 module) + { + if (vParams.Count <= 0) return; + Foldout(title, GUILayout.Width(width + 16), GUILayout.Width(width / 3)); + foreach (var (kString, param) in vParams) ShowParam(module, intTime, kString, param, wOption, iOption); + } - GUI.backgroundColor = color; + private static void Foldout(string text, GUILayoutOption wWidth, GUILayoutOption iWidth) + { + GUILayout.Space(-4); + using (new GUILayout.HorizontalScope(GUI.skin.box, wWidth)) + { + EditorGUILayout.LabelField("", GUI.skin.horizontalSlider, iWidth); + GUILayout.Label(text, Style); + EditorGUILayout.LabelField("", GUI.skin.horizontalSlider, iWidth); + } + } + + private static void ShowParam(ModuleVrc3 module, int intTime, string key, Vrc3Param param, GUILayoutOption wOption, GUILayoutOption iOption) + { + GUILayout.Space(-4); + using (new GmgLayoutHelper.GuiBackground(Color.Lerp(Color, GUI.backgroundColor, (intTime - param.LastUpdate) / 100f))) + using (new GUILayout.HorizontalScope(GUI.skin.box, wOption)) + { + GUILayout.Label(key, iOption); + GUILayout.Label(param.TypeText, iOption); + ParametersLayoutValue(module, key, param, iOption); } } - private static void ParametersLayoutValue(ModuleVrc3 module, KeyValuePair paramPair, GUILayoutOption innerOption) + private static void ParametersLayoutValue(ModuleVrc3 module, string key, Vrc3Param param, GUILayoutOption iOption) { - if (module.Edit != paramPair.Key) + if (module.Edit != key) { - GmgLayoutHelper.GuiLabel(LabelTuple(paramPair.Value), innerOption); + GmgLayoutHelper.GuiLabel(LabelTuple(param), iOption); var rect = GUILayoutUtility.GetLastRect(); rect.x += rect.width - 20; rect.width = 15; - if (GUI.Toggle(rect, false, "")) module.Edit = paramPair.Key; + if (GUI.Toggle(rect, false, "")) module.Edit = key; } - else FieldTuple(paramPair.Value, module, innerOption); + else FieldTuple(param, module, iOption); } private static void TrackingControlLayout(float width, Dictionary data, Dictionary trackingControls, bool locomotionDisabled, bool poseSpace) diff --git a/Scripts/Editor/Modules/Vrc3/Vrc3DefaultParams.cs b/Scripts/Editor/Modules/Vrc3/Vrc3DefaultParams.cs index 7b9ffd6..66f416f 100644 --- a/Scripts/Editor/Modules/Vrc3/Vrc3DefaultParams.cs +++ b/Scripts/Editor/Modules/Vrc3/Vrc3DefaultParams.cs @@ -39,39 +39,39 @@ public static class Vrc3DefaultParams private const string AngularY = "AngularY"; private const string Voice = "Voice"; - public static IEnumerable<(string name, AnimatorControllerParameterType type)> Parameters => new[] + public static Dictionary Parameters => new() { - (GestureRightWeight, AnimatorControllerParameterType.Float), - (ScaleFactorInverse, AnimatorControllerParameterType.Float), - (EyeHeightAsPercent, AnimatorControllerParameterType.Float), - (EyeHeightAsMeters, AnimatorControllerParameterType.Float), - (GestureLeftWeight, AnimatorControllerParameterType.Float), - (VelocityMagnitude, AnimatorControllerParameterType.Float), - (IsOnFriendsList, AnimatorControllerParameterType.Bool), - (VrcFaceBlendH, AnimatorControllerParameterType.Float), - (VrcFaceBlendV, AnimatorControllerParameterType.Float), - (ScaleModified, AnimatorControllerParameterType.Bool), - (AvatarVersion, AnimatorControllerParameterType.Int), - (TrackingType, AnimatorControllerParameterType.Int), - (GestureRight, AnimatorControllerParameterType.Int), - (ScaleFactor, AnimatorControllerParameterType.Float), - (GestureLeft, AnimatorControllerParameterType.Int), - (VelocityX, AnimatorControllerParameterType.Float), - (VelocityY, AnimatorControllerParameterType.Float), - (VelocityZ, AnimatorControllerParameterType.Float), - (InStation, AnimatorControllerParameterType.Bool), - (AngularY, AnimatorControllerParameterType.Float), - (Earmuffs, AnimatorControllerParameterType.Bool), - (Grounded, AnimatorControllerParameterType.Bool), - (MuteSelf, AnimatorControllerParameterType.Bool), - (VrcEmote, AnimatorControllerParameterType.Int), - (Upright, AnimatorControllerParameterType.Float), - (IsLocal, AnimatorControllerParameterType.Bool), - (Seated, AnimatorControllerParameterType.Bool), - (VRMode, AnimatorControllerParameterType.Int), - (Voice, AnimatorControllerParameterType.Float), - (Vise, AnimatorControllerParameterType.Int), - (Afk, AnimatorControllerParameterType.Bool) + { GestureRightWeight, AnimatorControllerParameterType.Float }, + { ScaleFactorInverse, AnimatorControllerParameterType.Float }, + { EyeHeightAsPercent, AnimatorControllerParameterType.Float }, + { EyeHeightAsMeters, AnimatorControllerParameterType.Float }, + { GestureLeftWeight, AnimatorControllerParameterType.Float }, + { VelocityMagnitude, AnimatorControllerParameterType.Float }, + { IsOnFriendsList, AnimatorControllerParameterType.Bool }, + { VrcFaceBlendH, AnimatorControllerParameterType.Float }, + { VrcFaceBlendV, AnimatorControllerParameterType.Float }, + { ScaleModified, AnimatorControllerParameterType.Bool }, + { AvatarVersion, AnimatorControllerParameterType.Int }, + { TrackingType, AnimatorControllerParameterType.Int }, + { GestureRight, AnimatorControllerParameterType.Int }, + { ScaleFactor, AnimatorControllerParameterType.Float }, + { GestureLeft, AnimatorControllerParameterType.Int }, + { VelocityX, AnimatorControllerParameterType.Float }, + { VelocityY, AnimatorControllerParameterType.Float }, + { VelocityZ, AnimatorControllerParameterType.Float }, + { InStation, AnimatorControllerParameterType.Bool }, + { AngularY, AnimatorControllerParameterType.Float }, + { Earmuffs, AnimatorControllerParameterType.Bool }, + { Grounded, AnimatorControllerParameterType.Bool }, + { MuteSelf, AnimatorControllerParameterType.Bool }, + { VrcEmote, AnimatorControllerParameterType.Int }, + { Upright, AnimatorControllerParameterType.Float }, + { IsLocal, AnimatorControllerParameterType.Bool }, + { Seated, AnimatorControllerParameterType.Bool }, + { VRMode, AnimatorControllerParameterType.Int }, + { Voice, AnimatorControllerParameterType.Float }, + { Vise, AnimatorControllerParameterType.Int }, + { Afk, AnimatorControllerParameterType.Bool } }; } } diff --git a/Scripts/Runtime/Modules/ModuleSettings.cs b/Scripts/Runtime/Modules/ModuleSettings.cs index af5c714..17b7f54 100644 --- a/Scripts/Runtime/Modules/ModuleSettings.cs +++ b/Scripts/Runtime/Modules/ModuleSettings.cs @@ -15,6 +15,7 @@ public class ModuleSettings public Pose initialPose; public int userIndex; + public bool isOnFriendsList; public bool loadStored; public bool isRemote; public bool vrMode; diff --git a/package.json b/package.json index 41b8367..044ad46 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name" : "vrchat.blackstartx.gesture-manager", "displayName" : "Gesture Manager", - "version" : "3.9.2", + "version" : "3.9.3", "unity" : "2022.3", "description" : "A tool that will help you preview your VRChat Avatar animation directly in Unity.", "type" : "tool", - "url" : "https://github.com/BlackStartx/VRC-Gesture-Manager/archive/refs/tags/v3.9.2.zip", + "url" : "https://github.com/BlackStartx/VRC-Gesture-Manager/archive/refs/tags/v3.9.3.zip", "author" : { "name" : "BlackStartx", "email" : "leonardo.lorenzoni99@gmail.com",