362 lines
11 KiB
C#
362 lines
11 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
public class FishingUIEffects : MonoBehaviour
|
|
{
|
|
private readonly Dictionary<Object, Coroutine> runningEffects = new Dictionary<Object, Coroutine>();
|
|
private readonly Dictionary<Transform, Vector3> originalScales = new Dictionary<Transform, Vector3>();
|
|
private readonly Dictionary<RectTransform, Vector2> originalAnchoredPositions = new Dictionary<RectTransform, Vector2>();
|
|
|
|
public CanvasGroup EnsureCanvasGroup(GameObject target)
|
|
{
|
|
if (target == null)
|
|
return null;
|
|
|
|
CanvasGroup group = target.GetComponent<CanvasGroup>();
|
|
if (group == null)
|
|
group = target.AddComponent<CanvasGroup>();
|
|
|
|
return group;
|
|
}
|
|
|
|
public void SetCanvasGroupInstant(GameObject target, CanvasGroup group, bool visible)
|
|
{
|
|
if (target == null && group == null)
|
|
return;
|
|
|
|
if (target != null)
|
|
target.SetActive(visible);
|
|
|
|
if (group != null)
|
|
{
|
|
group.alpha = visible ? 1f : 0f;
|
|
group.interactable = visible;
|
|
group.blocksRaycasts = visible;
|
|
}
|
|
}
|
|
|
|
public void FadeCanvasGroup(GameObject target, CanvasGroup group, bool visible, float duration)
|
|
{
|
|
if (target == null && group == null)
|
|
return;
|
|
|
|
if (group == null && target != null)
|
|
group = EnsureCanvasGroup(target);
|
|
|
|
if (group == null)
|
|
{
|
|
if (target != null)
|
|
target.SetActive(visible);
|
|
return;
|
|
}
|
|
|
|
StopManaged(group);
|
|
runningEffects[group] = StartCoroutine(FadeCanvasGroupRoutine(target, group, visible, Mathf.Max(0f, duration)));
|
|
}
|
|
|
|
private IEnumerator FadeCanvasGroupRoutine(GameObject target, CanvasGroup group, bool visible, float duration)
|
|
{
|
|
if (target != null && visible)
|
|
target.SetActive(true);
|
|
|
|
group.interactable = visible;
|
|
group.blocksRaycasts = visible;
|
|
|
|
float startAlpha = group.alpha;
|
|
float endAlpha = visible ? 1f : 0f;
|
|
|
|
if (duration <= 0f)
|
|
{
|
|
group.alpha = endAlpha;
|
|
}
|
|
else
|
|
{
|
|
float timer = 0f;
|
|
while (timer < duration)
|
|
{
|
|
timer += Time.deltaTime;
|
|
float t = Mathf.Clamp01(timer / duration);
|
|
t = EaseOutCubic(t);
|
|
group.alpha = Mathf.Lerp(startAlpha, endAlpha, t);
|
|
yield return null;
|
|
}
|
|
|
|
group.alpha = endAlpha;
|
|
}
|
|
|
|
if (target != null && !visible)
|
|
target.SetActive(false);
|
|
|
|
runningEffects.Remove(group);
|
|
}
|
|
|
|
public void Pop(Transform target, float peakScale = 1.12f, float duration = 0.18f)
|
|
{
|
|
if (target == null)
|
|
return;
|
|
|
|
StopManaged(target);
|
|
runningEffects[target] = StartCoroutine(PopRoutine(target, Mathf.Max(1f, peakScale), Mathf.Max(0.01f, duration)));
|
|
}
|
|
|
|
private IEnumerator PopRoutine(Transform target, float peakScale, float duration)
|
|
{
|
|
if (!originalScales.TryGetValue(target, out Vector3 originalScale))
|
|
{
|
|
originalScale = target.localScale;
|
|
originalScales[target] = originalScale;
|
|
}
|
|
|
|
float half = duration * 0.5f;
|
|
float timer = 0f;
|
|
|
|
while (timer < half)
|
|
{
|
|
timer += Time.deltaTime;
|
|
float t = Mathf.Clamp01(timer / half);
|
|
target.localScale = Vector3.Lerp(originalScale, originalScale * peakScale, EaseOutCubic(t));
|
|
yield return null;
|
|
}
|
|
|
|
timer = 0f;
|
|
Vector3 peak = originalScale * peakScale;
|
|
|
|
while (timer < half)
|
|
{
|
|
timer += Time.deltaTime;
|
|
float t = Mathf.Clamp01(timer / half);
|
|
target.localScale = Vector3.Lerp(peak, originalScale, EaseOutCubic(t));
|
|
yield return null;
|
|
}
|
|
|
|
target.localScale = originalScale;
|
|
runningEffects.Remove(target);
|
|
}
|
|
|
|
public void Shake(RectTransform target, float strength = 12f, float duration = 0.18f)
|
|
{
|
|
if (target == null)
|
|
return;
|
|
|
|
StopManaged(target);
|
|
runningEffects[target] = StartCoroutine(ShakeRoutine(target, Mathf.Max(0f, strength), Mathf.Max(0.01f, duration)));
|
|
}
|
|
|
|
private IEnumerator ShakeRoutine(RectTransform target, float strength, float duration)
|
|
{
|
|
if (!originalAnchoredPositions.TryGetValue(target, out Vector2 originalPosition))
|
|
{
|
|
originalPosition = target.anchoredPosition;
|
|
originalAnchoredPositions[target] = originalPosition;
|
|
}
|
|
|
|
float timer = 0f;
|
|
while (timer < duration)
|
|
{
|
|
timer += Time.deltaTime;
|
|
float t = Mathf.Clamp01(timer / duration);
|
|
float power = Mathf.Lerp(strength, 0f, t);
|
|
Vector2 offset = UnityEngine.Random.insideUnitCircle * power;
|
|
target.anchoredPosition = originalPosition + offset;
|
|
yield return null;
|
|
}
|
|
|
|
target.anchoredPosition = originalPosition;
|
|
runningEffects.Remove(target);
|
|
}
|
|
|
|
public void Flash(Image image, Color color, float maxAlpha = 0.28f, float duration = 0.16f)
|
|
{
|
|
if (image == null)
|
|
return;
|
|
|
|
StopManaged(image);
|
|
runningEffects[image] = StartCoroutine(FlashRoutine(image, color, Mathf.Clamp01(maxAlpha), Mathf.Max(0.01f, duration)));
|
|
}
|
|
|
|
private IEnumerator FlashRoutine(Image image, Color color, float maxAlpha, float duration)
|
|
{
|
|
image.gameObject.SetActive(true);
|
|
image.raycastTarget = false;
|
|
|
|
float timer = 0f;
|
|
while (timer < duration)
|
|
{
|
|
timer += Time.deltaTime;
|
|
float t = Mathf.Clamp01(timer / duration);
|
|
Color current = color;
|
|
current.a = Mathf.Lerp(maxAlpha, 0f, EaseOutCubic(t));
|
|
image.color = current;
|
|
yield return null;
|
|
}
|
|
|
|
Color clear = color;
|
|
clear.a = 0f;
|
|
image.color = clear;
|
|
image.gameObject.SetActive(false);
|
|
runningEffects.Remove(image);
|
|
}
|
|
|
|
public void FillImage(Image image, float targetFill, float duration)
|
|
{
|
|
if (image == null)
|
|
return;
|
|
|
|
targetFill = Mathf.Clamp01(targetFill);
|
|
|
|
StopManaged(image);
|
|
runningEffects[image] = StartCoroutine(FillImageRoutine(image, targetFill, Mathf.Max(0f, duration)));
|
|
}
|
|
|
|
private IEnumerator FillImageRoutine(Image image, float targetFill, float duration)
|
|
{
|
|
float startFill = image.fillAmount;
|
|
|
|
if (duration <= 0f)
|
|
{
|
|
image.fillAmount = targetFill;
|
|
}
|
|
else
|
|
{
|
|
float timer = 0f;
|
|
while (timer < duration)
|
|
{
|
|
timer += Time.deltaTime;
|
|
float t = Mathf.Clamp01(timer / duration);
|
|
image.fillAmount = Mathf.Lerp(startFill, targetFill, EaseOutCubic(t));
|
|
yield return null;
|
|
}
|
|
|
|
image.fillAmount = targetFill;
|
|
}
|
|
|
|
runningEffects.Remove(image);
|
|
}
|
|
|
|
public void HighlightSlot(Image background, Image icon, Transform slotRoot, Color highlightColor, float duration, float popScale)
|
|
{
|
|
Object key = background != null ? background : icon != null ? icon : slotRoot;
|
|
if (key == null)
|
|
return;
|
|
|
|
StopManaged(key);
|
|
runningEffects[key] = StartCoroutine(HighlightSlotRoutine(background, icon, slotRoot, highlightColor, Mathf.Max(0.01f, duration), Mathf.Max(1f, popScale), key));
|
|
}
|
|
|
|
private IEnumerator HighlightSlotRoutine(Image background, Image icon, Transform slotRoot, Color highlightColor, float duration, float popScale, Object key)
|
|
{
|
|
Color? originalBackground = null;
|
|
Color? originalIcon = null;
|
|
Vector3 originalScale = Vector3.one;
|
|
|
|
if (background != null)
|
|
{
|
|
originalBackground = background.color;
|
|
Color c = Color.Lerp(background.color, highlightColor, 0.65f);
|
|
c.a = 1f;
|
|
background.color = c;
|
|
}
|
|
|
|
if (icon != null)
|
|
{
|
|
originalIcon = icon.color;
|
|
Color c = icon.color;
|
|
c.a = 1f;
|
|
icon.color = c;
|
|
}
|
|
|
|
if (slotRoot != null)
|
|
{
|
|
if (!originalScales.TryGetValue(slotRoot, out originalScale))
|
|
{
|
|
originalScale = slotRoot.localScale;
|
|
originalScales[slotRoot] = originalScale;
|
|
}
|
|
}
|
|
|
|
float half = duration * 0.5f;
|
|
float timer = 0f;
|
|
while (timer < half)
|
|
{
|
|
timer += Time.deltaTime;
|
|
float t = Mathf.Clamp01(timer / half);
|
|
if (slotRoot != null)
|
|
slotRoot.localScale = Vector3.Lerp(originalScale, originalScale * popScale, EaseOutCubic(t));
|
|
yield return null;
|
|
}
|
|
|
|
timer = 0f;
|
|
Vector3 peak = originalScale * popScale;
|
|
while (timer < half)
|
|
{
|
|
timer += Time.deltaTime;
|
|
float t = Mathf.Clamp01(timer / half);
|
|
|
|
if (slotRoot != null)
|
|
slotRoot.localScale = Vector3.Lerp(peak, originalScale, EaseOutCubic(t));
|
|
|
|
if (background != null && originalBackground.HasValue)
|
|
background.color = Color.Lerp(background.color, originalBackground.Value, t);
|
|
|
|
if (icon != null && originalIcon.HasValue)
|
|
icon.color = Color.Lerp(icon.color, originalIcon.Value, t);
|
|
|
|
yield return null;
|
|
}
|
|
|
|
if (slotRoot != null)
|
|
slotRoot.localScale = originalScale;
|
|
|
|
if (background != null && originalBackground.HasValue)
|
|
background.color = originalBackground.Value;
|
|
|
|
if (icon != null && originalIcon.HasValue)
|
|
icon.color = originalIcon.Value;
|
|
|
|
runningEffects.Remove(key);
|
|
}
|
|
|
|
public void StopAllEffects()
|
|
{
|
|
foreach (Coroutine coroutine in runningEffects.Values)
|
|
{
|
|
if (coroutine != null)
|
|
StopCoroutine(coroutine);
|
|
}
|
|
|
|
runningEffects.Clear();
|
|
|
|
foreach (KeyValuePair<Transform, Vector3> pair in originalScales)
|
|
{
|
|
if (pair.Key != null)
|
|
pair.Key.localScale = pair.Value;
|
|
}
|
|
|
|
foreach (KeyValuePair<RectTransform, Vector2> pair in originalAnchoredPositions)
|
|
{
|
|
if (pair.Key != null)
|
|
pair.Key.anchoredPosition = pair.Value;
|
|
}
|
|
}
|
|
|
|
private void StopManaged(Object key)
|
|
{
|
|
if (key == null)
|
|
return;
|
|
|
|
if (runningEffects.TryGetValue(key, out Coroutine coroutine) && coroutine != null)
|
|
StopCoroutine(coroutine);
|
|
|
|
runningEffects.Remove(key);
|
|
}
|
|
|
|
private float EaseOutCubic(float t)
|
|
{
|
|
t = Mathf.Clamp01(t);
|
|
t = 1f - Mathf.Pow(1f - t, 3f);
|
|
return t;
|
|
}
|
|
}
|