1
0
mirror of https://github.com/originalnicodr/CinematicUnityExplorer.git synced 2026-10-10 13:03:15 +08:00

Refactored the animator panel to be able to play any animation, modified the pause animation feature with the recommended property, and added try/catch statements to the post-processing panel. Also deleted the "pause after an animation played" code since that doesn't work anymore with the new method.

This commit is contained in:
originalnicodr
2024-02-17 01:19:43 -03:00
parent 29c371e2c2
commit 9d5ae8558e
3 changed files with 42 additions and 75 deletions
+28 -51
View File
@@ -27,33 +27,34 @@ 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
private bool skippedStopFrames;
ButtonRef playButton;
private Dropdown animatorDropdown;
private AnimationClip currentAnimation;
private AnimationClip defaultAnimation;
private AnimationClip overridingAnimation;
private AnimationClip originalAnimation;
private RuntimeAnimatorController originalAnimatorController;
public void DrawAnimatorPlayer(){
if (playButton == null){
List<AnimationClip> animations = animator.runtimeAnimatorController.animationClips.OrderBy(x=>x.name).Where(c => c.length > 0).Distinct().ToList();
originalAnimatorController = animator.runtimeAnimatorController;
//ExplorerCore.LogWarning(animations.Count);
AnimatorClipInfo[] playingAnimations = animator.GetCurrentAnimatorClipInfo(0);
currentAnimation = playingAnimations.Count() != 0 ? playingAnimations[0].clip : animations[0];
overridingAnimation = playingAnimations.Count() != 0 ? playingAnimations[0].clip : animations[0];
ButtonRef prevAnimation = UIFactory.CreateButton(UIRoot, "PreviousAnimation", "◀", new Color(0.05f, 0.05f, 0.05f));
UIFactory.SetLayoutElement(prevAnimation.Component.gameObject, minHeight: 25, minWidth: 25);
prevAnimation.OnClick += () => animatorDropdown.value = animatorDropdown.value == 0 ? animatorDropdown.options.Count - 1 : animatorDropdown.value - 1;
GameObject currentAnimationObj = UIFactory.CreateDropdown(UIRoot, $"Animations_{animator.name}", out animatorDropdown, null, 14, (idx) => currentAnimation = animations[idx]);
UIFactory.SetLayoutElement(currentAnimationObj, minHeight: 25, minWidth: 200);
GameObject overridingAnimationObj = UIFactory.CreateDropdown(UIRoot, $"Animations_{animator.name}", out animatorDropdown, null, 14, (idx) => overridingAnimation = animations[idx]);
UIFactory.SetLayoutElement(overridingAnimationObj, minHeight: 25, minWidth: 200);
foreach (AnimationClip animation in animations)
animatorDropdown.options.Add(new Dropdown.OptionData(animation.name));
animatorDropdown.value = Math.Max(0, animations.FindIndex(a => a == currentAnimation));
animatorDropdown.value = Math.Max(0, animations.FindIndex(a => a == overridingAnimation));
if (animatorDropdown.value == 0) animatorDropdown.captionText.text = animations[0].name;
ButtonRef nextAnimation = UIFactory.CreateButton(UIRoot, "NextAnimation", "▶", new Color(0.05f, 0.05f, 0.05f));
@@ -68,38 +69,27 @@ namespace UnityExplorer.UI.Panels
private void PlayButton_OnClick(){
// We save the last animation played by the game in case we want to go back to it
if (defaultAnimation == null){
if (originalAnimation == null){
AnimatorClipInfo[] playingAnimations = animator.GetCurrentAnimatorClipInfo(0);
defaultAnimation = playingAnimations.Count() != 0 ? playingAnimations[0].clip : null;
originalAnimation = playingAnimations.Count() != 0 ? playingAnimations[0].clip : null;
}
// Need to assign the original animator controller back so to get the correct currentClip
animator.runtimeAnimatorController = originalAnimatorController;
AnimationClip currentClip = animator.GetCurrentAnimatorClipInfo(0)[0].clip;
skippedStopFrames = false;
AnimatorOverrideController animatorOverrideController = new AnimatorOverrideController();
animatorOverrideController.runtimeAnimatorController = originalAnimatorController;
animator.runtimeAnimatorController = animatorOverrideController;
stopAfterAnimationFinishes = !AnimatorToggle.isOn;
AnimatorToggle.isOn = true;
animator.Play(currentAnimation.name);
animatorOverrideController[currentClip.name] = overridingAnimation;
animator.Play(currentClip.name);
// Turn the toggle on to keep consistency
if (!AnimatorToggle.isOn) AnimatorToggle.isOn = true;
}
// Disables the animator when the animation we manually triggered isn't present on the subject anymore
public bool IsPlayingSelectedAnimation(){
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;
}
stopAfterAnimationFinishes = false;
AnimatorToggle.isOn = false;
return true;
}
}
return false;
}
private List<AnimationClip> GetAllCurrentAnimations(){
private List<AnimationClip> GetAllAnimations(){
List<AnimationClip> allAnimations = new List<AnimationClip>();
for (int layer = 0; layer < animator.layerCount; layer++){
allAnimations.AddRange(animator.GetCurrentAnimatorClipInfo(layer).Select(ainfo => ainfo.clip).ToList());
@@ -108,13 +98,7 @@ namespace UnityExplorer.UI.Panels
}
public void ResetAnimation(){
if (defaultAnimation != null){
stopAfterAnimationFinishes = false;
animator.Play(defaultAnimation.name);
AnimatorToggle.isOn = true;
defaultAnimation = null;
}
animator.runtimeAnimatorController = originalAnimatorController;
}
#endif
@@ -124,23 +108,16 @@ namespace UnityExplorer.UI.Panels
UIFactory.SetLayoutElement(AnimatorToggleObj, minHeight: 25);
AnimatorToggle.isOn = true;
AnimatorToggle.onValueChanged.AddListener(value => {
//ExplorerCore.LogWarning($"Animator toggled: {animator} to {animator.enabled}");
try {
Type animatorClass = ReflectionUtility.GetTypeByName("UnityEngine.Animator");
if (value) {
MethodInfo stopPlayBack = animatorClass.GetMethod("StopPlayback");
stopPlayBack.Invoke(animator.TryCast(), null);
} else {
MethodInfo startPlayBack = animatorClass.GetMethod("StartPlayback");
startPlayBack.Invoke(animator.TryCast(), null);
}
PropertyInfo animatorSpeed = animatorClass.GetProperty("speed");
animatorSpeed.SetValue(animator, value ? 1 : 0, null);
}
catch {
// Fallback in case reflection isn't working
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;
}
);
-11
View File
@@ -34,8 +34,6 @@ namespace UnityExplorer.UI.Panels
public override bool NavButtonWanted => true;
public override bool ShouldSaveActiveState => true;
Dictionary<Animator, Func<bool>> animationEndedFunctions = new Dictionary<Animator, Func<bool>>();
Toggle masterAnimatorToggle = new Toggle();
private static ScrollPool<AnimatorCell> animatorScrollPool;
@@ -64,7 +62,6 @@ namespace UnityExplorer.UI.Panels
if (animators.Count != 0) {
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.
@@ -125,13 +122,6 @@ namespace UnityExplorer.UI.Panels
masterAnimatorToggle.isOn = !masterAnimatorToggle.isOn;
}
#if MONO
public override void Update(){
foreach (Animator animator in animators){
animationEndedFunctions[animator]();
}
}
#endif
// ~~~~~~~~ UI construction / callbacks ~~~~~~~~
protected override void ConstructPanelContent()
@@ -178,7 +168,6 @@ namespace UnityExplorer.UI.Panels
#if MONO
cell.DrawAnimatorPlayer();
animationEndedFunctions[animator] = cell.IsPlayingSelectedAnimation;
#endif
}
+14 -13
View File
@@ -130,24 +130,25 @@ namespace UnityExplorer.UI.Panels
}
private void AddEffect(string baseClass, string effect){
Type searchType = ReflectionUtility.GetTypeByName($"{baseClass}.{effect}");
searchType = searchType is Type type ? type : searchType.GetActualType();
List<object> currentResults = RuntimeHelper.FindObjectsOfTypeAll(searchType).Select(obj => (object) obj).ToList();
try {
Type searchType = ReflectionUtility.GetTypeByName($"{baseClass}.{effect}");
searchType = searchType is Type type ? type : searchType.GetActualType();
List<object> currentResults = RuntimeHelper.FindObjectsOfTypeAll(searchType).Select(obj => (object) obj).ToList();
//ExplorerCore.LogWarning($"Found {currentResults.Count()} objects for {baseClass}.{effect}");
foreach (object obj in currentResults){
PPEffect entry = new PPEffect(obj);
// Ignore non-active objects and objects without a name, since those tend to be irrelevant
if ((bool) entry.Active.Value && entry.Name.Value.ToString() != ""){
if (!postProcessingEffects.ContainsKey(effect)){
postProcessingEffects.Add(effect, new List<PPEffect>());
}
foreach (object obj in currentResults){
PPEffect entry = new PPEffect(obj);
// Ignore non-active objects and objects without a name, since those tend to be irrelevant
if ((bool) entry.Active.Value && entry.Name.Value.ToString() != ""){
if (!postProcessingEffects.ContainsKey(effect)){
postProcessingEffects.Add(effect, new List<PPEffect>());
postProcessingEffects[effect].Add(entry);
}
postProcessingEffects[effect].Add(entry);
}
}
catch { ExplorerCore.Log($"Couldn't find {baseClass}.{effect}");}
}
private void SetEffect(bool value, List<PPEffect> effects){