214 lines
5.9 KiB
C#
214 lines
5.9 KiB
C#
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合成一个float,shader中再拆出来
|
||
/// </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
|
||
);
|
||
}
|
||
}
|
||
}
|
||
}
|