// MIT License - Copyright (c) 2025 wallstop
// Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE
namespace WallstopStudios.UnityHelpers.Editor.Utils.WGroup
{
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEditor.AnimatedValues;
using UnityEditorInternal;
using WallstopStudios.UnityHelpers.Core.Helper;
using WallstopStudios.UnityHelpers.Editor.Settings;
///
/// Centralized animation state management for WGroup foldouts.
/// Uses Unity's AnimBool for smooth expand/collapse transitions.
///
internal static class WGroupAnimationState
{
private static readonly Dictionary FoldoutAnimations = new();
///
/// Gets or creates an AnimBool for the given WGroup definition.
/// The AnimBool is keyed by (Name, AnchorPropertyPath, targetInstanceId) hash.
///
/// The WGroup definition to get animation state for.
/// The current expanded state of the foldout.
/// The instance ID of the target object (0 if unknown).
/// The AnimBool instance for this definition, with target set to expanded.
internal static AnimBool GetOrCreateAnim(
WGroupDefinition definition,
bool expanded,
int targetInstanceId = 0
)
{
int key = ComputeKey(definition, targetInstanceId);
float speed = UnityHelpersSettings.GetWGroupFoldoutSpeed();
if (!FoldoutAnimations.TryGetValue(key, out AnimBool anim) || anim == null)
{
anim = new AnimBool(expanded) { speed = speed };
anim.valueChanged.AddListener(RequestRepaint);
FoldoutAnimations[key] = anim;
}
anim.speed = speed;
anim.target = expanded;
return anim;
}
///
/// Gets the current fade progress for a WGroup foldout.
///
/// The WGroup definition.
/// The current expanded state.
/// The instance ID of the target object (0 if unknown).
///
/// A value between 0 and 1 representing the animation progress.
/// Returns 0 or 1 immediately if tweening is disabled.
///
internal static float GetFadeProgress(
WGroupDefinition definition,
bool expanded,
int targetInstanceId = 0
)
{
if (!UnityHelpersSettings.ShouldTweenWGroupFoldouts())
{
return expanded ? 1f : 0f;
}
AnimBool anim = GetOrCreateAnim(definition, expanded, targetInstanceId);
return anim.faded;
}
///
/// Clears all cached animation states.
/// Useful for testing and when settings change.
///
internal static void ClearCache()
{
foreach (KeyValuePair kvp in FoldoutAnimations)
{
AnimBool anim = kvp.Value;
if (anim != null)
{
anim.valueChanged.RemoveListener(RequestRepaint);
}
}
FoldoutAnimations.Clear();
}
private static int ComputeKey(WGroupDefinition definition, int targetInstanceId)
{
return Objects.HashCode(
definition.Name,
definition.AnchorPropertyPath,
targetInstanceId
);
}
private static void RequestRepaint()
{
InternalEditorUtility.RepaintAllViews();
}
}
#endif
}