using System; using Pixelplacement; using Pixelplacement.TweenSystem; using UnityEngine; namespace Utils { /// /// Common animation utilities extracted from CardAnimator pattern. /// Provides reusable tween animations for UI elements. /// public static class TweenAnimationUtility { #region Scale Animations /// /// Animate scale to target value with ease in-out /// public static TweenBase AnimateScale(Transform transform, Vector3 targetScale, float duration, Action onComplete = null) { return Tween.LocalScale(transform, targetScale, duration, 0f, Tween.EaseInOut, completeCallback: onComplete); } /// /// Pulse scale animation (scale up then back to original) /// public static void PulseScale(Transform transform, float pulseAmount = 1.1f, float duration = 0.2f, Action onComplete = null) { Vector3 originalScale = transform.localScale; Vector3 pulseScale = originalScale * pulseAmount; Tween.LocalScale(transform, pulseScale, duration, 0f, Tween.EaseOutBack, completeCallback: () => { Tween.LocalScale(transform, originalScale, duration, 0f, Tween.EaseInBack, completeCallback: onComplete); }); } /// /// Pop-in animation (scale from 0 to target with overshoot) /// public static TweenBase PopIn(Transform transform, Vector3 targetScale, float duration = 0.5f, Action onComplete = null) { transform.localScale = Vector3.zero; return Tween.LocalScale(transform, targetScale, duration, 0f, Tween.EaseOutBack, completeCallback: onComplete); } /// /// Pop-out animation (scale from current to 0) /// public static TweenBase PopOut(Transform transform, float duration = 0.3f, Action onComplete = null) { return Tween.LocalScale(transform, Vector3.zero, duration, 0f, Tween.EaseInBack, completeCallback: onComplete); } /// /// Smooth scale transition with bounce /// public static TweenBase ScaleWithBounce(Transform transform, Vector3 targetScale, float duration, Action onComplete = null) { return Tween.LocalScale(transform, targetScale, duration, 0f, Tween.EaseOutBack, completeCallback: onComplete); } #endregion #region Position Animations /// /// Animate anchored position (for RectTransform UI elements) /// public static TweenBase AnimateAnchoredPosition(RectTransform rectTransform, Vector2 targetPosition, float duration, Action onComplete = null) { return Tween.AnchoredPosition(rectTransform, targetPosition, duration, 0f, Tween.EaseInOut, completeCallback: onComplete); } /// /// Animate local position (for regular transforms) /// public static TweenBase AnimateLocalPosition(Transform transform, Vector3 targetPosition, float duration, Action onComplete = null) { return Tween.LocalPosition(transform, targetPosition, duration, 0f, Tween.EaseInOut, completeCallback: onComplete); } /// /// Move with bounce effect /// public static TweenBase MoveWithBounce(RectTransform rectTransform, Vector2 targetPosition, float duration, Action onComplete = null) { return Tween.AnchoredPosition(rectTransform, targetPosition, duration, 0f, Tween.EaseOutBack, completeCallback: onComplete); } #endregion #region Combined Hover Animations /// /// Hover enter animation (lift and scale) for RectTransform /// public static void HoverEnter(RectTransform rectTransform, Vector2 originalPosition, float liftAmount = 20f, float scaleMultiplier = 1.05f, float duration = 0.2f, Action onComplete = null) { Vector2 targetPos = originalPosition + Vector2.up * liftAmount; Tween.AnchoredPosition(rectTransform, targetPos, duration, 0f, Tween.EaseOutBack); Tween.LocalScale(rectTransform, Vector3.one * scaleMultiplier, duration, 0f, Tween.EaseOutBack, completeCallback: onComplete); } /// /// Hover exit animation (return to original position and scale) for RectTransform /// public static void HoverExit(RectTransform rectTransform, Vector2 originalPosition, float duration = 0.2f, Action onComplete = null) { Tween.AnchoredPosition(rectTransform, originalPosition, duration, 0f, Tween.EaseInBack); Tween.LocalScale(rectTransform, Vector3.one, duration, 0f, Tween.EaseInBack, completeCallback: onComplete); } /// /// Glow pulse effect (scale up/down repeatedly) /// public static TweenBase StartGlowPulse(Transform transform, float pulseAmount = 1.1f, float duration = 0.8f) { Vector3 originalScale = transform.localScale; Vector3 pulseScale = originalScale * pulseAmount; return Tween.LocalScale(transform, pulseScale, duration, 0f, Tween.EaseIn, Tween.LoopType.PingPong); } /// /// Stop any active tweens on transform /// public static void StopTweens(Transform transform) { Tween.Cancel(transform.GetInstanceID()); } #endregion #region Fade Animations /// /// Fade CanvasGroup alpha /// public static TweenBase FadeCanvasGroup(CanvasGroup canvasGroup, float targetAlpha, float duration, Action onComplete = null) { return Tween.CanvasGroupAlpha(canvasGroup, targetAlpha, duration, 0f, Tween.EaseInOut, completeCallback: onComplete); } /// /// Fade Image alpha /// public static TweenBase FadeImageAlpha(UnityEngine.UI.Image image, float targetAlpha, float duration, Action onComplete = null) { return Tween.Value(image.color.a, targetAlpha, (alpha) => { if (image != null) { Color color = image.color; color.a = alpha; image.color = color; } }, duration, 0f, Tween.EaseInOut, completeCallback: onComplete); } /// /// Start blinking animation on Image (ping-pong alpha fade) /// /// Image to blink /// Minimum alpha value /// Maximum alpha value /// Duration for one complete cycle (in and out) /// TweenBase that can be cancelled public static TweenBase StartBlinkImage(UnityEngine.UI.Image image, float minAlpha = 0.3f, float maxAlpha = 1f, float duration = 1.5f) { // Set initial alpha to max if (image != null) { Color color = image.color; color.a = maxAlpha; image.color = color; } // Create ping-pong tween (half duration for each direction) return Tween.Value(maxAlpha, minAlpha, (alpha) => { if (image != null) { Color color = image.color; color.a = alpha; image.color = color; } }, duration / 2f, 0f, Tween.EaseInOut, Tween.LoopType.PingPong); } /// /// Pop-out with fade - scale to 0 and fade out simultaneously /// public static void PopOutWithFade(Transform transform, CanvasGroup canvasGroup, float duration, Action onComplete = null) { // Scale to 0 Tween.LocalScale(transform, Vector3.zero, duration, 0f, Tween.EaseInBack); // Fade out simultaneously if (canvasGroup != null) { Tween.CanvasGroupAlpha(canvasGroup, 0f, duration, 0f, Tween.EaseInOut, completeCallback: onComplete); } else { // If no canvas group, just call complete after scale Tween.LocalScale(transform, Vector3.zero, duration, 0f, Tween.EaseInBack, completeCallback: onComplete); } } #endregion } }