mmorpg2d/Assets/sliderProgressSc.cs
2025-08-19 14:19:44 +05:30

316 lines
9.5 KiB
C#

using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using System.Collections.Generic;
public class sliderProgressSc : MonoBehaviour
{
[Header("Slider Reference")]
[SerializeField] private Slider targetSlider;
[Header("Dots Configuration")]
[SerializeField] private List<Transform> dots = new List<Transform>();
[SerializeField] private List<Image> dotImages = new List<Image>();
[Header("Slider Animation")]
[SerializeField] private float sliderAnimationDuration = 0.8f;
[SerializeField] private Ease sliderEase = Ease.OutCubic;
[SerializeField] private bool animateSliderValue = true;
[Header("Dot Animation Settings")]
[SerializeField] private float scaleDuration = 0.3f;
[SerializeField] private float colorDuration = 0.2f;
[SerializeField] private Vector3 activeScale = Vector3.one * 1.2f;
[SerializeField] private Vector3 inactiveScale = Vector3.one;
[SerializeField] private Ease scaleEase = Ease.OutBack;
[SerializeField] private float dotStaggerDelay = 0.05f; // Delay between dot activations
[Header("Colors")]
[SerializeField] private Color inactiveColor = new Color(0.3f, 0.3f, 0.3f, 0.6f);
[SerializeField] private Color activeColor = new Color(0f, 1f, 0.4f, 1f); // Bright green
[SerializeField] private Color pulseColor = new Color(1f, 1f, 0.4f, 1f); // Yellow pulse
private float previousSliderValue;
private int lastActivatedDot = -1;
private Tween sliderTween;
private bool isAnimating = false;
void Start()
{
InitializeSlider();
SetupInitialState();
}
void Update()
{
// Check if slider value changed
if (Mathf.Abs(targetSlider.value - previousSliderValue) > 0.001f)
{
if (animateSliderValue && !isAnimating)
{
AnimateSliderToValue(targetSlider.value);
}
else
{
CheckAndAnimateDots(targetSlider.value);
}
previousSliderValue = targetSlider.value;
}
}
void InitializeSlider()
{
if (targetSlider == null)
targetSlider = GetComponent<Slider>();
if (targetSlider == null)
{
Debug.LogError("No slider found! Please assign a slider reference.");
return;
}
// Auto-populate dots if empty
if (dots.Count == 0)
{
Debug.Log("No dots found! Please assign dot transforms manually.");
}
previousSliderValue = targetSlider.value;
}
void SetupInitialState()
{
// Set all dots to inactive state
for (int i = 0; i < dots.Count; i++)
{
if (dots[i] != null)
{
dots[i].localScale = inactiveScale;
if (i < dotImages.Count && dotImages[i] != null)
{
dotImages[i].color = inactiveColor;
}
}
}
lastActivatedDot = -1;
}
void AnimateSliderToValue(float targetValue)
{
if (sliderTween != null && sliderTween.IsActive())
{
sliderTween.Kill();
}
isAnimating = true;
float startValue = targetSlider.value;
sliderTween = DOTween.To(() => targetSlider.value, x => {
targetSlider.value = x;
CheckAndAnimateDots(x);
}, targetValue, sliderAnimationDuration)
.SetEase(sliderEase)
.OnComplete(() => {
isAnimating = false;
});
}
void CheckAndAnimateDots(float sliderValue)
{
// Calculate how many dots should be active based on slider value
// For 10 dots: dot 0 at 0.1, dot 1 at 0.2, ..., dot 9 at 1.0
int dotsToActivate = Mathf.FloorToInt(sliderValue * dots.Count);
// Clamp to valid range
dotsToActivate = Mathf.Clamp(dotsToActivate, 0, dots.Count);
// The actual active dot index (0-based, -1 means no dots active)
int targetActiveDot = dotsToActivate - 1;
// Check if we've moved forward to activate more dots
if (targetActiveDot > lastActivatedDot)
{
// Activate dots with staggered delay for better visual effect
for (int i = lastActivatedDot + 1; i <= targetActiveDot; i++)
{
if (i < dots.Count && i >= 0)
{
float delay = (i - (lastActivatedDot + 1)) * dotStaggerDelay;
ActivateDotWithDelay(i, delay);
}
}
lastActivatedDot = targetActiveDot;
}
// Check if we've moved backward (deactivate dots)
else if (targetActiveDot < lastActivatedDot)
{
// Deactivate dots from lastActivatedDot down to targetActiveDot+1
for (int i = lastActivatedDot; i > targetActiveDot; i--)
{
if (i < dots.Count && i >= 0)
{
DeactivateDot(i);
}
}
lastActivatedDot = targetActiveDot;
}
}
void ActivateDotWithDelay(int dotIndex, float delay)
{
if (dotIndex >= dots.Count || dotIndex < 0 || dots[dotIndex] == null) return;
DOVirtual.DelayedCall(delay, () => ActivateDot(dotIndex));
}
void ActivateDot(int dotIndex)
{
if (dotIndex >= dots.Count || dotIndex < 0 || dots[dotIndex] == null) return;
Transform dot = dots[dotIndex];
// Scale up animation with bounce effect
dot.DOScale(activeScale, scaleDuration).SetEase(scaleEase);
// Color change to active with pulse effect
if (dotIndex < dotImages.Count && dotImages[dotIndex] != null)
{
Image dotImage = dotImages[dotIndex];
// Initial color change
dotImage.DOColor(activeColor, colorDuration);
// Add a subtle pulse effect
dotImage.DOColor(pulseColor, colorDuration * 0.5f)
.SetDelay(colorDuration)
.SetLoops(2, LoopType.Yoyo)
.SetEase(Ease.InOutSine);
}
}
void DeactivateDot(int dotIndex)
{
if (dotIndex >= dots.Count || dotIndex < 0 || dots[dotIndex] == null) return;
Transform dot = dots[dotIndex];
// Scale down animation
dot.DOScale(inactiveScale, scaleDuration * 0.7f).SetEase(Ease.OutQuad);
// Color change to inactive
if (dotIndex < dotImages.Count && dotImages[dotIndex] != null)
{
dotImages[dotIndex].DOColor(inactiveColor, colorDuration * 0.7f);
}
}
// Public methods for external control
public void SetSliderValue(float value)
{
if (targetSlider != null)
{
if (animateSliderValue)
{
AnimateSliderToValue(value);
}
else
{
targetSlider.value = value;
}
}
}
public void SetSliderValueInstant(float value)
{
if (targetSlider != null)
{
targetSlider.value = value;
CheckAndAnimateDots(value);
}
}
public void ResetDots()
{
// Kill any running animations
if (sliderTween != null && sliderTween.IsActive())
{
sliderTween.Kill();
}
for (int i = 0; i < dots.Count; i++)
{
if (dots[i] != null)
{
dots[i].DOKill();
}
if (i < dotImages.Count && dotImages[i] != null)
{
dotImages[i].DOKill();
}
}
// Reset state
lastActivatedDot = -1;
isAnimating = false;
SetupInitialState();
}
// Get current progress (0-10)
public int GetCurrentProgress()
{
return lastActivatedDot + 1;
}
// Check if specific dot is active
public bool IsDotActive(int dotIndex)
{
return dotIndex <= lastActivatedDot;
}
void OnDestroy()
{
// Clean up any running tweens
if (sliderTween != null && sliderTween.IsActive())
{
sliderTween.Kill();
}
for (int i = 0; i < dots.Count; i++)
{
if (dots[i] != null)
{
dots[i].DOKill();
}
if (i < dotImages.Count && dotImages[i] != null)
{
dotImages[i].DOKill();
}
}
}
// // Debug helper - shows current calculation values in inspector
// [System.Serializable]
// public class DebugInfo
// {
// [SerializeField] public float currentSliderValue;
// [SerializeField] public int dotsToActivate;
// [SerializeField] public int targetActiveDot;
// [SerializeField] public int lastActivatedDot;
// }
// [Header("Debug Info (Runtime Only)")]
// [SerializeField] private DebugInfo debugInfo = new DebugInfo();
// void LateUpdate()
// {
// // Update debug info for inspector visibility
// if (targetSlider != null)
// {
// debugInfo.currentSliderValue = targetSlider.value;
// debugInfo.dotsToActivate = Mathf.FloorToInt(targetSlider.value * dots.Count);
// debugInfo.targetActiveDot = debugInfo.dotsToActivate - 1;
// debugInfo.lastActivatedDot = lastActivatedDot;
// }
// }
}