Files
2026-02-21 16:45:37 +08:00

534 lines
13 KiB
C#

using System;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
namespace EnergyBarToolkit
{
[RequireComponent(typeof(EnergyBar))]
[SelectionBase]
[ExecuteInEditMode]
public class FilledRendererUGUI : EnergyBarUGUIBase
{
public enum BlinkOperator
{
LessThan = 0,
LessOrEqual = 1,
GreaterThan = 2,
GreaterOrEqual = 3
}
public Sprite spriteBar;
public Material spriteBarMaterial;
public ColorType spriteBarColorType;
public Color spriteBarColor = Color.white;
public Gradient spriteBarGradient;
public GrowDirection growDirection;
public float radialOffset;
public float radialLength = 1f;
public Vector3 barImageScale = new Vector3(1f, 1f, 1f);
public Vector3 barImageOffset = new Vector3(0f, 0f, 0f);
public Vector2 barImageRepeater = new Vector2(1f, 1f);
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;
public bool effectFollow;
public GameObject effectFollowObject;
public Vector3 effectFollowOffset = Vector3.zero;
public AnimationCurve effectFollowScaleX = AnimationCurve.Linear(0f, 1f, 1f, 1f);
public AnimationCurve effectFollowScaleY = AnimationCurve.Linear(0f, 1f, 1f, 1f);
public AnimationCurve effectFollowScaleZ = AnimationCurve.Linear(0f, 1f, 1f, 1f);
public AnimationCurve effectFollowRotation = AnimationCurve.Linear(0f, 0f, 1f, 0f);
public Gradient effectFollowColor;
public bool effectTiled;
public Sprite effectTiledSprite;
public Vector2 effectTiledTiling = new Vector2(2f, 2f);
public Vector2 effectTiledStartOffset = new Vector2(0f, 0f);
public Vector2 effectTiledOffsetChangeSpeed = new Vector2(-1f, 0f);
public Color effectTiledTint = Color.white;
[SerializeField]
private Image2 effectTilledImageBarMask;
[SerializeField]
private Image2 effectTilledImageTiles;
[SerializeField]
private int lastRebuildHash;
[SerializeField]
private bool dirty;
[FormerlySerializedAs("barImage")]
[SerializeField]
private Image2 imageBar;
[FormerlySerializedAs("burnImage")]
[SerializeField]
private Image2 imageBurn;
private float _effectBlinkAccum;
public bool forceBlinking { get; set; }
private bool Blink { get; set; }
public override void SetNativeSize()
{
if (imageBar == null)
{
Rebuild();
if (imageBar == null)
{
Debug.LogWarning("Cannot resize bar that has not been created yet");
return;
}
}
int num = Mathf.RoundToInt(imageBar.sprite.rect.width);
int num2 = Mathf.RoundToInt(imageBar.sprite.rect.height);
rectTransform.anchorMax = rectTransform.anchorMin;
rectTransform.sizeDelta = new Vector2(num, num2);
}
public bool GrowDirectionSupportedByFollowEffect(GrowDirection growDirection)
{
switch (growDirection)
{
case GrowDirection.LeftToRight:
case GrowDirection.RightToLeft:
case GrowDirection.BottomToTop:
case GrowDirection.TopToBottom:
return true;
default:
return false;
}
}
protected override void Start()
{
base.Start();
if (imageBar == null)
{
dirty = true;
}
}
protected override void Update()
{
base.Update();
UpdateRebuild();
UpdateNonIntrusive();
}
private void UpdateSize()
{
RectTransform component = GetComponent<RectTransform>();
for (int i = 0; i < createdChildren.Count; i++)
{
GameObject gameObject = createdChildren[i];
RectTransform component2 = gameObject.GetComponent<RectTransform>();
SetSize(component2, component.rect.size);
}
}
private void UpdateNonIntrusive()
{
UpdateSize();
UpdateBarScaleAndOffset();
UpdateValue();
UpdateBlinkEffect();
UpdateBurnEffect();
UpdateTiledEffect();
UpdateFollowEffect();
UpdateColor();
UpdateRadialOffset();
}
private void UpdateBarScaleAndOffset()
{
if (imageBar != null)
{
Vector2 pivot = rectTransform.pivot;
Rect rect = imageBar.rectTransform.rect;
float num = (0f - (pivot.x - 0.5f)) * rect.width;
float num2 = (0f - (pivot.y - 0.5f)) * rect.height;
Vector3 localPosition = new Vector3(barImageOffset.x + num, barImageOffset.y + num2, barImageOffset.z);
MadTransform.SetLocalScale(imageBar.transform, barImageScale);
MadTransform.SetLocalPosition(imageBar.transform, localPosition);
if (effectTilledImageBarMask != null)
{
MadTransform.SetLocalScale(effectTilledImageBarMask.transform, barImageScale);
MadTransform.SetLocalPosition(effectTilledImageBarMask.transform, localPosition);
}
}
}
private void UpdateTiledEffect()
{
if (effectTiled)
{
if (effectTilledImageTiles.uvTiling != effectTiledTiling)
{
effectTilledImageTiles.uvTiling = effectTiledTiling;
effectTilledImageTiles.SetVerticesDirty();
}
effectTilledImageTiles.color = effectTiledTint;
if (Application.isPlaying)
{
effectTilledImageTiles.uvOffset += effectTiledOffsetChangeSpeed * Time.deltaTime;
effectTilledImageTiles.SetVerticesDirty();
}
else if (effectTilledImageTiles.uvOffset != effectTiledStartOffset)
{
effectTilledImageTiles.uvOffset = effectTiledStartOffset;
effectTilledImageTiles.SetVerticesDirty();
}
}
}
private void UpdateValue()
{
if (!(imageBar == null))
{
imageBar.fillValue = ValueF2;
imageBar.SetAllDirty();
if (effectTilledImageBarMask != null)
{
effectTilledImageBarMask.fillValue = ValueF2;
effectTilledImageBarMask.SetAllDirty();
}
}
}
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 UpdateBurnEffect()
{
if (!(imageBurn == null))
{
if (Mathf.Approximately(ValueFBurn, ValueF2))
{
imageBurn.enabled = false;
return;
}
imageBurn.enabled = true;
imageBurn.color = GetBurnColor();
imageBurn.fillValue = ValueFBurn;
}
}
private void UpdateFollowEffect()
{
if (!effectFollow)
{
return;
}
UpdateEffectFollowDefaults();
Color color = effectFollowColor.Evaluate(ValueF2);
float x = effectFollowScaleX.Evaluate(ValueF2);
float y = effectFollowScaleY.Evaluate(ValueF2);
float z = effectFollowScaleZ.Evaluate(ValueF2);
float z2 = effectFollowRotation.Evaluate(ValueF2) * 360f;
if (effectFollowObject != null)
{
Vector3 position = imageBar.transform.TransformPoint(EdgePosition());
GameObject gameObject = effectFollowObject;
MadTransform.SetPosition(gameObject.transform, position);
MadTransform.SetLocalScale(gameObject.transform, new Vector3(x, y, z));
if (gameObject.GetComponent<Renderer>() != null)
{
gameObject.GetComponent<Renderer>().sharedMaterial.color = color;
}
Vector3 vector = new Vector3(0f, 0f, z2);
if (gameObject.transform.localEulerAngles != vector)
{
gameObject.transform.localEulerAngles = vector;
}
Graphic component = gameObject.GetComponent<Graphic>();
if ((bool)component)
{
component.color = color;
}
}
}
private void UpdateEffectFollowDefaults()
{
if (effectFollowScaleX.length == 0)
{
effectFollowScaleX = AnimationCurve.Linear(0f, 1f, 1f, 1f);
}
if (effectFollowScaleY.length == 0)
{
effectFollowScaleY = AnimationCurve.Linear(0f, 1f, 1f, 1f);
}
if (effectFollowScaleZ.length == 0)
{
effectFollowScaleZ = AnimationCurve.Linear(0f, 1f, 1f, 1f);
}
if (effectFollowRotation.length == 0)
{
effectFollowRotation = AnimationCurve.Linear(0f, 0f, 1f, 0f);
}
}
private Vector2 EdgePosition()
{
if (spriteBar == null)
{
return Vector2.zero;
}
Vector4 drawingDimensions = imageBar.GetDrawingDimensions(false);
float x = drawingDimensions.x;
float z = drawingDimensions.z;
float y = drawingDimensions.y;
float w = drawingDimensions.w;
float num = z - x;
float num2 = w - y;
float x2 = x + num / 2f;
float y2 = y + num2 / 2f;
Vector2 vector;
switch (growDirection)
{
case GrowDirection.LeftToRight:
vector = new Vector2(x + num * ValueF2, y2);
break;
case GrowDirection.RightToLeft:
vector = new Vector2(x + num * ValueF2, y2);
break;
case GrowDirection.BottomToTop:
vector = new Vector2(x2, y + num2 * ValueF2);
break;
case GrowDirection.TopToBottom:
vector = new Vector2(x2, y + num2 * ValueF2);
break;
default:
vector = Vector2.zero;
break;
}
return new Vector2(vector.x + effectFollowOffset.x, vector.y + effectFollowOffset.y);
}
private Color GetBurnColor()
{
Color localColor = effectBurnSprite.color;
if (Blink)
{
localColor = new Color(0f, 0f, 0f, 0f);
}
return ComputeColor(localColor);
}
private void UpdateColor()
{
Color color = ComputeBarColor();
imageBar.color = color;
if (effectTiled)
{
effectTilledImageTiles.color = EnergyBarBase.Multiply(new Color(1f, 1f, 1f, color.a), effectTiledTint);
}
}
private void UpdateRadialOffset()
{
if (!(imageBar == null))
{
imageBar.radialFillOffset = radialOffset;
imageBar.radialFillLength = radialLength;
if ((bool)imageBurn)
{
imageBurn.radialFillOffset = radialOffset;
imageBurn.radialFillLength = radialLength;
}
}
}
private Color ComputeBarColor()
{
Color localColor = Color.white;
if (growDirection == GrowDirection.ColorChange)
{
localColor = spriteBarGradient.Evaluate(base.energyBar.ValueF);
}
else
{
switch (spriteBarColorType)
{
case ColorType.Solid:
localColor = spriteBarColor;
break;
case ColorType.Gradient:
localColor = spriteBarGradient.Evaluate(base.energyBar.ValueF);
break;
default:
MadDebug.Assert(false, "Unkwnown option: " + spriteBarColorType);
break;
}
}
if (Blink)
{
localColor = effectBlinkColor;
}
return ComputeColor(localColor);
}
public void UpdateRebuild()
{
if (RebuildNeeded())
{
Rebuild();
}
}
private bool RebuildNeeded()
{
int currentHash = 37;
currentHash = MadHashCode.Add(currentHash, (spriteBar != null) ? spriteBar.GetInstanceID() : 0);
currentHash = MadHashCode.Add(currentHash, (spriteBarMaterial != null) ? spriteBarMaterial.GetInstanceID() : 0);
currentHash = MadHashCode.AddList(currentHash, spritesBackground);
currentHash = MadHashCode.AddList(currentHash, spritesForeground);
currentHash = MadHashCode.Add(currentHash, (int)spriteBarColorType);
currentHash = MadHashCode.Add(currentHash, (int)growDirection);
currentHash = MadHashCode.Add(currentHash, label);
currentHash = MadHashCode.Add(currentHash, effectBurn);
currentHash = MadHashCode.Add(currentHash, effectBurnSprite);
currentHash = MadHashCode.Add(currentHash, rectTransform.pivot);
currentHash = MadHashCode.Add(currentHash, effectTiled);
currentHash = MadHashCode.Add(currentHash, effectTiledSprite);
currentHash = MadHashCode.Add(currentHash, barImageRepeater);
if (currentHash != lastRebuildHash || dirty)
{
lastRebuildHash = currentHash;
dirty = false;
return true;
}
return false;
}
public void Rebuild()
{
RemoveCreatedChildren();
BuildBackgroundImages();
if (effectBurn)
{
BuildBurnBar();
}
BuildBar();
if (effectTiled)
{
BuildEffectTilled();
}
BuildForegroundImages();
UpdateSize();
MoveLabelToTop();
}
private void BuildBurnBar()
{
imageBurn = CreateChild<Image2>("burn_bar");
if ((bool)effectBurnSprite.sprite)
{
imageBurn.sprite = effectBurnSprite.sprite;
}
else
{
imageBurn.sprite = spriteBar;
}
imageBurn.material = effectBurnSprite.material;
imageBurn.SetNativeSize();
imageBurn.growDirection = growDirection;
imageBurn.uvTiling = barImageRepeater;
}
private void BuildBar()
{
imageBar = CreateChild<Image2>("bar");
imageBar.sprite = spriteBar;
imageBar.material = spriteBarMaterial;
imageBar.SetNativeSize();
imageBar.growDirection = growDirection;
imageBar.readable = true;
imageBar.uvTiling = barImageRepeater;
}
private void BuildEffectTilled()
{
effectTilledImageBarMask = CreateChild<Image2>("bar_mask");
effectTilledImageBarMask.sprite = spriteBar;
effectTilledImageBarMask.SetNativeSize();
effectTilledImageBarMask.growDirection = growDirection;
effectTilledImageBarMask.readable = true;
Mask mask = effectTilledImageBarMask.gameObject.AddComponent<Mask>();
mask.showMaskGraphic = false;
effectTilledImageTiles = CreateChild<Image2>("tiles", effectTilledImageBarMask.transform);
effectTilledImageTiles.sprite = effectTiledSprite;
}
}
}