457 lines
10 KiB
C#
457 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace EnergyBarToolkit
|
|
{
|
|
[SelectionBase]
|
|
[RequireComponent(typeof(EnergyBar))]
|
|
[ExecuteInEditMode]
|
|
public class RepeatedRendererUGUI : EnergyBarUGUIBase
|
|
{
|
|
public enum GrowType
|
|
{
|
|
None = 0,
|
|
Grow = 1,
|
|
Fade = 2,
|
|
Fill = 3
|
|
}
|
|
|
|
public enum BlinkOperator
|
|
{
|
|
LessThan = 0,
|
|
LessOrEqual = 1,
|
|
GreaterThan = 2,
|
|
GreaterOrEqual = 3
|
|
}
|
|
|
|
public SpriteTex spriteIcon = new SpriteTex();
|
|
|
|
public SpriteTex spriteSlot = new SpriteTex();
|
|
|
|
public int repeatCount = 5;
|
|
|
|
public Vector2 repeatPositionDelta = new Vector2(32f, 0f);
|
|
|
|
public GrowType growType;
|
|
|
|
public GrowDirection growDirection;
|
|
|
|
public bool effectBlink;
|
|
|
|
public float effectBlinkValue = 0.2f;
|
|
|
|
public float effectBlinkRatePerSecond = 1f;
|
|
|
|
public Color effectBlinkColor = new Color(1f, 1f, 1f, 0f);
|
|
|
|
public BlinkOperator effectBlinkOperator = BlinkOperator.LessOrEqual;
|
|
|
|
[SerializeField]
|
|
private int lastRebuildHash;
|
|
|
|
private bool dirty;
|
|
|
|
[SerializeField]
|
|
private List<Image2> slotImages = new List<Image2>(32);
|
|
|
|
[SerializeField]
|
|
private List<Image2> iconImages = new List<Image2>(32);
|
|
|
|
[SerializeField]
|
|
private List<Vector2> originPositions = new List<Vector2>(32);
|
|
|
|
[SerializeField]
|
|
private Vector2 sizeOrigin;
|
|
|
|
[SerializeField]
|
|
private Vector2 scaleRatio = Vector2.one;
|
|
|
|
private float _effectBlinkAccum;
|
|
|
|
public bool forceBlinking { get; set; }
|
|
|
|
private bool Blink { get; set; }
|
|
|
|
private Color IconTintTransparent
|
|
{
|
|
get
|
|
{
|
|
return new Color(spriteIcon.color.r, spriteIcon.color.g, spriteIcon.color.g, 0f);
|
|
}
|
|
}
|
|
|
|
public override void SetNativeSize()
|
|
{
|
|
if (spriteIcon == null)
|
|
{
|
|
Rebuild();
|
|
if (spriteIcon == null)
|
|
{
|
|
Debug.LogWarning("Cannot resize bar that has not been created yet");
|
|
return;
|
|
}
|
|
}
|
|
Vector2 size = ComputeNativeSize();
|
|
SetSize(rectTransform, size);
|
|
}
|
|
|
|
private Vector2 ComputeNativeSize()
|
|
{
|
|
if (spriteIcon.sprite == null)
|
|
{
|
|
return Vector2.zero;
|
|
}
|
|
int num = Mathf.RoundToInt(spriteIcon.sprite.rect.width);
|
|
int num2 = Mathf.RoundToInt(spriteIcon.sprite.rect.height);
|
|
int num3 = (int)((float)num + Mathf.Abs(repeatPositionDelta.x * (float)(repeatCount - 1)));
|
|
int num4 = (int)((float)num2 + Mathf.Abs(repeatPositionDelta.y * (float)(repeatCount - 1)));
|
|
return new Vector2(num3, num4);
|
|
}
|
|
|
|
public Image2 GetIconImage(int index)
|
|
{
|
|
return iconImages[index];
|
|
}
|
|
|
|
public Image2 GetSlotImage(int index)
|
|
{
|
|
return slotImages[index];
|
|
}
|
|
|
|
public int GetIconCount()
|
|
{
|
|
return repeatCount;
|
|
}
|
|
|
|
public int GetFullyVisibleIconCount()
|
|
{
|
|
float f = ValueF2 * (float)repeatCount;
|
|
return (int)Mathf.Floor(f);
|
|
}
|
|
|
|
public int GetVisibleIconCount()
|
|
{
|
|
float f = ValueF2 * (float)repeatCount;
|
|
return (int)Mathf.Ceil(f);
|
|
}
|
|
|
|
protected override void Update()
|
|
{
|
|
base.Update();
|
|
UpdateRebuild();
|
|
UpdateBar();
|
|
UpdateBlinkEffect();
|
|
UpdateVisible();
|
|
UpdateSize();
|
|
}
|
|
|
|
private void OnValidate()
|
|
{
|
|
repeatCount = Mathf.Max(1, repeatCount);
|
|
}
|
|
|
|
private void UpdateBar()
|
|
{
|
|
if (iconImages.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
float num = ValueF2 * (float)repeatCount;
|
|
int num2 = (int)Mathf.Floor(num);
|
|
float num3 = num - (float)num2;
|
|
for (int i = 0; i < repeatCount; i++)
|
|
{
|
|
Image2 image = iconImages[i];
|
|
if (slotImages.Count > 0)
|
|
{
|
|
Image2 image2 = slotImages[i];
|
|
UpdateSlot(image2);
|
|
}
|
|
if (i < num2)
|
|
{
|
|
SetIconVisible(image);
|
|
continue;
|
|
}
|
|
if (i > num2)
|
|
{
|
|
SetIconInvisible(image);
|
|
continue;
|
|
}
|
|
switch (growType)
|
|
{
|
|
case GrowType.None:
|
|
if (Mathf.Approximately(num3, 0f))
|
|
{
|
|
SetIconInvisible(image);
|
|
}
|
|
else
|
|
{
|
|
SetIconVisible(image);
|
|
}
|
|
break;
|
|
case GrowType.Fade:
|
|
SetIconVisible(image);
|
|
image.color = Color.Lerp(IconTintTransparent, spriteIcon.color, num3);
|
|
break;
|
|
case GrowType.Grow:
|
|
SetIconVisible(image, num3);
|
|
break;
|
|
case GrowType.Fill:
|
|
SetIconVisible(image);
|
|
image.growDirection = growDirection;
|
|
image.fillValue = num3;
|
|
break;
|
|
default:
|
|
Debug.Log("Unknown grow type: " + growType);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateSize()
|
|
{
|
|
if (!(spriteIcon.sprite == null))
|
|
{
|
|
Vector2 vector = ComputeNativeSize();
|
|
Vector2 size = rectTransform.rect.size;
|
|
scaleRatio = new Vector2(size.x / vector.x, size.y / vector.y);
|
|
Rect rect = spriteIcon.sprite.rect;
|
|
for (int i = 0; i < iconImages.Count; i++)
|
|
{
|
|
Vector2 originPosition = originPositions[i];
|
|
Image2 image = iconImages[i];
|
|
UpdateSpriteSize(originPosition, image, rect);
|
|
}
|
|
for (int j = 0; j < slotImages.Count; j++)
|
|
{
|
|
Vector2 originPosition2 = originPositions[j];
|
|
Image2 image2 = slotImages[j];
|
|
UpdateSpriteSize(originPosition2, image2, rect);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateSpriteSize(Vector2 originPosition, Image2 image, Rect spriteRect)
|
|
{
|
|
float x = originPosition.x * scaleRatio.x;
|
|
float y = originPosition.y * scaleRatio.y;
|
|
MadTransform.SetLocalPosition(image.rectTransform, new Vector3(x, y));
|
|
SetSize(image.rectTransform, new Vector2(spriteRect.width * scaleRatio.x, spriteRect.height * scaleRatio.y));
|
|
}
|
|
|
|
private void SetIconVisible(Image2 image, float scale = 1f)
|
|
{
|
|
image.color = ComputeColor(spriteIcon.color);
|
|
image.fillValue = 1f;
|
|
MadTransform.SetLocalScale(image.transform, new Vector3(scale, scale, scale));
|
|
image.enabled = true;
|
|
}
|
|
|
|
private void UpdateSlot(Image2 image)
|
|
{
|
|
if (image != null)
|
|
{
|
|
image.color = ComputeColor(spriteSlot.color);
|
|
}
|
|
}
|
|
|
|
private void SetIconInvisible(Image2 image)
|
|
{
|
|
image.enabled = false;
|
|
}
|
|
|
|
private void UpdateVisible()
|
|
{
|
|
if (!IsVisible())
|
|
{
|
|
for (int i = 0; i < iconImages.Count; i++)
|
|
{
|
|
Image2 image = iconImages[i];
|
|
image.enabled = false;
|
|
}
|
|
for (int j = 0; j < slotImages.Count; j++)
|
|
{
|
|
Image2 image2 = slotImages[j];
|
|
image2.enabled = false;
|
|
}
|
|
}
|
|
else if (Blink)
|
|
{
|
|
for (int k = 0; k < iconImages.Count; k++)
|
|
{
|
|
Image2 image3 = iconImages[k];
|
|
image3.enabled = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateBlinkEffect()
|
|
{
|
|
if (forceBlinking)
|
|
{
|
|
Blink = EnergyBarCommons.Blink(effectBlinkRatePerSecond, ref _effectBlinkAccum);
|
|
}
|
|
else if (CanBlink())
|
|
{
|
|
Blink = EnergyBarCommons.Blink(effectBlinkRatePerSecond, ref _effectBlinkAccum);
|
|
}
|
|
else
|
|
{
|
|
Blink = false;
|
|
}
|
|
}
|
|
|
|
private bool CanBlink()
|
|
{
|
|
if (!effectBlink)
|
|
{
|
|
return false;
|
|
}
|
|
switch (effectBlinkOperator)
|
|
{
|
|
case BlinkOperator.LessThan:
|
|
return ValueF2 < effectBlinkValue;
|
|
case BlinkOperator.LessOrEqual:
|
|
return ValueF2 <= effectBlinkValue;
|
|
case BlinkOperator.GreaterThan:
|
|
return ValueF2 > effectBlinkValue;
|
|
case BlinkOperator.GreaterOrEqual:
|
|
return ValueF2 >= effectBlinkValue;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
|
|
private void UpdateRebuild()
|
|
{
|
|
if (RebuildNeeded())
|
|
{
|
|
Rebuild();
|
|
}
|
|
}
|
|
|
|
private bool RebuildNeeded()
|
|
{
|
|
if (iconImages.Count == 0 && spriteIcon != null && repeatCount != 0)
|
|
{
|
|
return true;
|
|
}
|
|
if (iconImages.Count > 0 && iconImages[0] == null)
|
|
{
|
|
return true;
|
|
}
|
|
int currentHash = 37;
|
|
currentHash = MadHashCode.Add(currentHash, spriteIcon);
|
|
currentHash = MadHashCode.Add(currentHash, spriteSlot);
|
|
currentHash = MadHashCode.Add(currentHash, repeatCount);
|
|
currentHash = MadHashCode.Add(currentHash, repeatPositionDelta);
|
|
currentHash = MadHashCode.Add(currentHash, rectTransform.pivot);
|
|
if (currentHash != lastRebuildHash || dirty)
|
|
{
|
|
lastRebuildHash = currentHash;
|
|
dirty = false;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void Rebuild()
|
|
{
|
|
RemoveCreatedChildren();
|
|
iconImages.Clear();
|
|
slotImages.Clear();
|
|
originPositions.Clear();
|
|
BuildIconsAndSlots();
|
|
MoveLabelToTop();
|
|
}
|
|
|
|
private void BuildIconsAndSlots()
|
|
{
|
|
Vector2 min = Vector2.zero;
|
|
Vector2 max = Vector2.zero;
|
|
bool hasMinMax = false;
|
|
for (int i = 0; i < repeatCount; i++)
|
|
{
|
|
if (spriteSlot.sprite != null)
|
|
{
|
|
Image2 image = CreateChild<Image2>(string.Format("slot_{0:D2}", i + 1));
|
|
image.sprite = spriteSlot.sprite;
|
|
image.color = spriteSlot.color;
|
|
image.material = spriteSlot.material;
|
|
image.transform.localPosition = repeatPositionDelta * i;
|
|
slotImages.Add(image);
|
|
Expand(ref min, ref max, ref hasMinMax, image.rectTransform);
|
|
}
|
|
if (spriteIcon.sprite != null)
|
|
{
|
|
Image2 image2 = CreateChild<Image2>(string.Format("icon_{0:D2}", i + 1));
|
|
image2.sprite = spriteIcon.sprite;
|
|
image2.color = spriteIcon.color;
|
|
image2.material = spriteIcon.material;
|
|
image2.transform.localPosition = repeatPositionDelta * i;
|
|
iconImages.Add(image2);
|
|
Expand(ref min, ref max, ref hasMinMax, image2.rectTransform);
|
|
}
|
|
}
|
|
sizeOrigin = ComputeNativeSize();
|
|
SetNativeSize();
|
|
Vector2 vector = new Vector2(0.5f * sizeOrigin.x - rectTransform.pivot.x * sizeOrigin.x, 0.5f * sizeOrigin.y - rectTransform.pivot.y * sizeOrigin.y);
|
|
Vector2 vector2 = -repeatPositionDelta * (repeatCount - 1) * 0.5f;
|
|
for (int j = 0; j < slotImages.Count; j++)
|
|
{
|
|
Image2 image3 = slotImages[j];
|
|
image3.rectTransform.localPosition = repeatPositionDelta * j + (vector2 + vector);
|
|
}
|
|
for (int k = 0; k < iconImages.Count; k++)
|
|
{
|
|
Image2 image4 = iconImages[k];
|
|
image4.rectTransform.localPosition = repeatPositionDelta * k + (vector2 + vector);
|
|
originPositions.Add(image4.rectTransform.localPosition);
|
|
}
|
|
if (scaleRatio != Vector2.one)
|
|
{
|
|
Vector2 size = rectTransform.rect.size;
|
|
size.x *= scaleRatio.x;
|
|
size.y *= scaleRatio.y;
|
|
SetSize(rectTransform, size);
|
|
UpdateSize();
|
|
}
|
|
}
|
|
|
|
private void Expand(ref Vector2 min, ref Vector2 max, ref bool hasMinMax, RectTransform tr)
|
|
{
|
|
Rect rect = tr.rect;
|
|
float num = rect.xMin + tr.localPosition.x;
|
|
float num2 = rect.xMax + tr.localPosition.x;
|
|
float num3 = rect.yMin + tr.localPosition.y;
|
|
float num4 = rect.yMax + tr.localPosition.y;
|
|
if (!hasMinMax)
|
|
{
|
|
min.x = num;
|
|
min.y = num3;
|
|
max.x = num2;
|
|
max.y = num4;
|
|
hasMinMax = true;
|
|
return;
|
|
}
|
|
if (num < min.x)
|
|
{
|
|
min.x = num;
|
|
}
|
|
if (num3 < min.y)
|
|
{
|
|
min.y = num3;
|
|
}
|
|
if (num2 > max.x)
|
|
{
|
|
max.x = num2;
|
|
}
|
|
if (num4 > max.y)
|
|
{
|
|
max.y = num4;
|
|
}
|
|
}
|
|
}
|
|
}
|