c1_unity/Assets/Scripts/Component/UI/UIEffect/UIDynamicShinyEffect.cs
2023-04-03 11:04:31 +08:00

214 lines
5.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
namespace BF
{
[RequireComponent(typeof(MaskableGraphic))]
[ExecuteInEditMode]
[DisallowMultipleComponent]
public class UIDynamicShinyEffect : BaseMeshEffect
{
[SerializeField]
[Range(0, 1)]
float location = 0;
[SerializeField]
[Range(0, 1)]
float width = 0.25f;
[SerializeField]
[Range(0.01f, 1)]
float softness = 1f;
[SerializeField]
[Range(-180, 180)]
float rotation;
[SerializeField]
[Range(0, 1)]
float highlight = 1;
[SerializeField]
bool isRepeat = false;
[SerializeField]
[Range(1, 10)]
float intervalTime = 1f;
[SerializeField]
[Range(1, 10)]
float duration = 1f;
float counter = 0f;
public float Location
{
get { return location; }
set { location = Mathf.Clamp(value, 0, 1); SetDirty(); }
}
public float Width
{
get { return width; }
set { width = Mathf.Clamp(value, 0, 1); SetDirty(); }
}
public float Softness
{
get { return softness; }
set { softness = Mathf.Clamp(value, 0.01f, 1); SetDirty(); }
}
public float Highlight
{
get { return highlight; }
set { highlight = Mathf.Clamp(value, 0, 1); SetDirty(); }
}
public float Rotation
{
get { return rotation; }
set { if (!Mathf.Approximately(rotation, value)) { rotation = value; SetDirty(); } }
}
public Material effectmat;
protected override void OnEnable()
{
base.OnEnable();
if (effectmat == null)
{
effectmat = new Material(Shader.Find("BF/UI/UIDynamicShiny"));
}
graphic.material = effectmat;
}
protected override void OnDisable()
{
base.OnDisable();
graphic.material = BFMain.Instance.RenderMgr.UIDefaultMat;
}
public override void ModifyMesh(VertexHelper vh)
{
if (!IsActive())
{
return;
}
var rect = graphic.rectTransform.rect;
var rad = Rotation * Mathf.Deg2Rad;
var dir = new Vector2(Mathf.Cos(rad), Mathf.Sin(rad));
dir.x *= rect.height / rect.width;
dir = dir.normalized;
var vertex = new UIVertex();
Vector2 nomalizedPos;
var localMatrix = new Matrix2x3(rect, dir.x, dir.y);
for (var i = 0; i < vh.currentVertCount; i++)
{
vh.PopulateUIVertex(ref vertex, i);
nomalizedPos = localMatrix * vertex.position;
vertex.uv1 = new Vector2(
PackToFloat(Mathf.Clamp01(nomalizedPos.y), Softness, Width),
PackToFloat(Location, Highlight)
);
vh.SetUIVertex(vertex, i);
}
}
public void SetMarterial(Material material)
{
effectmat = material;
}
void SetDirty()
{
if (graphic)
{
graphic.SetVerticesDirty();
}
}
public void SetRepeat(float duration, float intervalTime)
{
isRepeat = true;
this.duration = Math.Max(1.0f, duration);
this.intervalTime = Math.Max(1.0f, intervalTime);
}
public void CancelRepeat()
{
isRepeat = false;
}
public void Play(float durationParam)
{
StopAllCoroutines();
StartCoroutine(CoPlay(durationParam));
}
IEnumerator CoPlay(float durationParam)
{
var time = 0f;
while (time < durationParam)
{
Location = time / durationParam;
time += Time.deltaTime;
yield return null;
}
}
void Update()
{
if (!isRepeat)
{
return;
}
if (counter <= 0f)
{
Play(duration);
}
counter += Time.deltaTime;
if (counter > duration + intervalTime)
{
counter = 0;
}
}
/// <summary>
/// 降低精度 把3个float合成一个floatshader中再拆出来
/// </summary>
float PackToFloat(float x, float y, float z)
{
const int precision = (1 << 6) - 1;
return (Mathf.FloorToInt(z * precision) << 12) + (Mathf.FloorToInt(y * precision) << 6) + Mathf.FloorToInt(x * precision);
}
float PackToFloat(float x, float y)
{
const int precision = (1 << 12) - 1;
return (Mathf.FloorToInt(y * precision) << 12) + Mathf.FloorToInt(x * precision);
}
struct Matrix2x3
{
public float m00, m01, m02, m10, m11, m12;
public Matrix2x3(Rect rect, float cos, float sin)
{
const float center = 0.5f;
var dx = -rect.xMin / rect.width - center;
var dy = -rect.yMin / rect.height - center;
m00 = cos / rect.width;
m01 = -sin / rect.height;
m02 = dx * cos - dy * sin + center;
m10 = sin / rect.width;
m11 = cos / rect.height;
m12 = dx * sin + dy * cos + center;
}
public static Vector2 operator * (Matrix2x3 m, Vector2 v)
{
return new Vector2(
(m.m00 * v.x) + (m.m01 * v.y) + m.m02,
(m.m10 * v.x) + (m.m11 * v.y) + m.m12
);
}
}
}
}