From 467d5cf2d5a005d0f109c2ba4f05c6f9cc686568 Mon Sep 17 00:00:00 2001 From: originalnicodr Date: Tue, 13 Feb 2024 16:44:12 -0300 Subject: [PATCH] Fixed toggling NPC animators when we had too many to show at the same time. Also disabled the automatic stop of manually played animations if the user didn't have the animator disabled in the first place, or if they disabled it mid-animation. Also made the Animator panel longer and fixed the FreeCamPanel missing new line. --- src/Cinematic/AnimatorUI/AnimatorCell.cs | 44 ++++++++++++++---------- src/UI/Panels/AnimatorPanel.cs | 21 +++++++++-- src/UI/Panels/FreeCamPanel.cs | 2 +- 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/src/Cinematic/AnimatorUI/AnimatorCell.cs b/src/Cinematic/AnimatorUI/AnimatorCell.cs index 7c6e4b9..e06b1d2 100644 --- a/src/Cinematic/AnimatorUI/AnimatorCell.cs +++ b/src/Cinematic/AnimatorUI/AnimatorCell.cs @@ -11,7 +11,6 @@ namespace UnityExplorer.UI.Panels { public class AnimatorCell : ICell { - private bool autoIgnoreMasterToggleSet; public Toggle IgnoreMasterToggle; public Toggle AnimatorToggle; @@ -28,10 +27,10 @@ namespace UnityExplorer.UI.Panels public void Disable() => UIRoot.SetActive(false); // IL2CPP games seem to have animation-related code stripped from their builds + private bool stopAfterAnimationFinishes = false; #if MONO - ButtonRef playButton; - private bool manuallyPlayedAnimation; private bool skippedStopFrames; + ButtonRef playButton; private AnimationClip currentAnimation; private AnimationClip defaultAnimation; @@ -67,22 +66,23 @@ namespace UnityExplorer.UI.Panels skippedStopFrames = false; + stopAfterAnimationFinishes = !AnimatorToggle.isOn; AnimatorToggle.isOn = true; - manuallyPlayedAnimation = true; animator.Play(currentAnimation.name); } // Disables the animator when the animation we manually triggered isn't present on the subject anymore public bool IsPlayingSelectedAnimation(){ - if (animator != null && currentAnimation != null && name.text == "Player"){ - if (manuallyPlayedAnimation && !GetAllCurrentAnimations().Contains(currentAnimation)){ - + if (animator != null && currentAnimation != null){ + if (stopAfterAnimationFinishes && !GetAllCurrentAnimations().Contains(currentAnimation)){ + + // Wait a frame. Otherwise, it will stop the animation immediately. if (!skippedStopFrames){ skippedStopFrames = true; return false; } - manuallyPlayedAnimation = false; + stopAfterAnimationFinishes = false; AnimatorToggle.isOn = false; return true; } @@ -100,7 +100,7 @@ namespace UnityExplorer.UI.Panels public void ResetAnimation(){ if (defaultAnimation != null){ - manuallyPlayedAnimation = false; + stopAfterAnimationFinishes = false; animator.Play(defaultAnimation.name); AnimatorToggle.isOn = true; @@ -109,21 +109,18 @@ namespace UnityExplorer.UI.Panels } #endif - // If it's the first time we are rendering the AnimatorCell, assign the ignore value automatically based on it's name - public void MaybeSetIgnoreMasterToggleSet(){ - if (animator != null && !autoIgnoreMasterToggleSet){ - // A weird canse insensitive "Contains" to identify the player - IgnoreMasterToggle.isOn = animator.gameObject.name.IndexOf("play", 0, StringComparison.OrdinalIgnoreCase) >= 0; - autoIgnoreMasterToggleSet = true; - } - } - public virtual GameObject CreateContent(GameObject parent) { GameObject AnimatorToggleObj = UIFactory.CreateToggle(parent, $"AnimatorToggle", out AnimatorToggle, out Text animatorToggleText); UIFactory.SetLayoutElement(AnimatorToggleObj, minHeight: 25); AnimatorToggle.isOn = true; - AnimatorToggle.onValueChanged.AddListener(value => animator.enabled = value); + AnimatorToggle.onValueChanged.AddListener(value => { + //ExplorerCore.LogWarning($"Animator toggled: {animator} to {animator.enabled}"); + animator.enabled = value; + // If we play an animation and we disable the animator then don't stop the animation when it finishes after we enable the animator again + if (!value && stopAfterAnimationFinishes) stopAfterAnimationFinishes = false; + } + ); UIRoot = AnimatorToggleObj; UIRoot.SetActive(false); @@ -148,9 +145,18 @@ namespace UnityExplorer.UI.Panels GameObject ignoresMasterTogglerObj = UIFactory.CreateToggle(UIRoot, $"AnimatorIgnoreMasterToggle", out IgnoreMasterToggle, out Text ignoreMasterToggleText); UIFactory.SetLayoutElement(ignoresMasterTogglerObj, minHeight: 25); IgnoreMasterToggle.isOn = false; + IgnoreMasterToggle.onValueChanged.AddListener(IgnoreMasterToggle_Clicked); ignoreMasterToggleText.text = "Ignore Master Toggle "; return UIRoot; } + + internal void IgnoreMasterToggle_Clicked(bool value){ + GetAnimatorPanel().shouldIgnoreMasterToggle[animator] = value; + } + + public UnityExplorer.UI.Panels.AnimatorPanel GetAnimatorPanel(){ + return UIManager.GetPanel(UIManager.Panels.AnimatorPanel); + } } } diff --git a/src/UI/Panels/AnimatorPanel.cs b/src/UI/Panels/AnimatorPanel.cs index 09ff26e..8aee48c 100644 --- a/src/UI/Panels/AnimatorPanel.cs +++ b/src/UI/Panels/AnimatorPanel.cs @@ -19,7 +19,7 @@ using Animator = UnityEngine.Behaviour; namespace UnityExplorer.UI.Panels { - internal class AnimatorPanel : UEPanel, ICellPoolDataSource + public class AnimatorPanel : UEPanel, ICellPoolDataSource { public AnimatorPanel(UIBase owner) : base(owner) { @@ -27,7 +27,7 @@ namespace UnityExplorer.UI.Panels public override string Name => "Animator"; public override UIManager.Panels PanelType => UIManager.Panels.AnimatorPanel; - public override int MinWidth => 500; + public override int MinWidth => 750; public override int MinHeight => 200; public override Vector2 DefaultAnchorMin => new(0.4f, 0.4f); public override Vector2 DefaultAnchorMax => new(0.6f, 0.6f); @@ -40,6 +40,7 @@ namespace UnityExplorer.UI.Panels private static ScrollPool animatorScrollPool; internal List animators = new List(); + public Dictionary shouldIgnoreMasterToggle = new Dictionary(); public int ItemCount => animators.Count; private static bool DoneScrollPoolInit; @@ -64,7 +65,9 @@ namespace UnityExplorer.UI.Panels masterAnimatorToggle.isOn = true; // Will also trigger "MasterToggleAnimators(true)" animators.Clear(); animationEndedFunctions.Clear(); + shouldIgnoreMasterToggle.Clear(); #if MONO + // TODO: Move the reset behavior to this panel, because we would only get the cells being currently displayed. foreach (AnimatorCell animatorCell in animatorScrollPool.CellPool) { animatorCell.ResetAnimation(); @@ -79,18 +82,30 @@ namespace UnityExplorer.UI.Panels .OrderBy(x=>x.name) .ToList(); + foreach(Animator animator in animators){ + shouldIgnoreMasterToggle[animator] = animator.gameObject.name.IndexOf("play", 0, StringComparison.OrdinalIgnoreCase) >= 0; + } + animatorScrollPool.Refresh(true, false); } public void MasterToggleAnimators(bool enable){ // Load animators for the first time if there are not any if (animators.Count == 0) FindAllAnimators(); + foreach (AnimatorCell animatorCell in animatorScrollPool.CellPool) { if (animatorCell.animator != null && !animatorCell.IgnoreMasterToggle.isOn){ animatorCell.AnimatorToggle.isOn = enable; } } + + // We gotta do this for the animators which cell are not being currently rendered. + foreach (Animator animator in animators){ + if (!shouldIgnoreMasterToggle[animator]){ + animator.enabled = enable; + } + } } public void HotkeyToggleAnimators(){ @@ -146,8 +161,8 @@ namespace UnityExplorer.UI.Panels cell.animator = animator; cell.name.text = animator.gameObject.name; + cell.IgnoreMasterToggle.isOn = shouldIgnoreMasterToggle[animator]; - cell.MaybeSetIgnoreMasterToggleSet(); #if MONO cell.DrawAnimatorPlayer(); animationEndedFunctions[animator] = cell.IsPlayingSelectedAnimation; diff --git a/src/UI/Panels/FreeCamPanel.cs b/src/UI/Panels/FreeCamPanel.cs index 4938876..92af091 100644 --- a/src/UI/Panels/FreeCamPanel.cs +++ b/src/UI/Panels/FreeCamPanel.cs @@ -367,7 +367,7 @@ namespace UnityExplorer.UI.Panels $"- {ConfigManager.HUD_Toggle.Value}: HUD toggle\n" + $"- {ConfigManager.Pause.Value}: Pause\n" + $"- {ConfigManager.Frameskip.Value}: Frameskip\n" + - $"- {ConfigManager.Toggle_Animations.Value}: Toggle NPC animations"; + $"- {ConfigManager.Toggle_Animations.Value}: Toggle NPC animations\n"; if (ConfigManager.Frameskip.Value != KeyCode.None) instructions = instructions + $"- {ConfigManager.Screenshot.Value}: Screenshot\n";