using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
using System.Collections;
namespace Coffee.UIEffects
{
///
/// UIEffect.
///
[AddComponentMenu("UI/UIEffects/UIShiny", 2)]
public class UIShiny : BaseMaterialEffect
{
private const uint k_ShaderId = 1 << 3;
private static readonly ParameterTexture s_ParamTex = new ParameterTexture(8, 128, "_ParamTex");
float _lastRotation;
EffectArea _lastEffectArea;
[Tooltip("Location for shiny effect.")] [FormerlySerializedAs("m_Location")] [SerializeField] [Range(0, 1)]
float m_EffectFactor = 0.5f;
[Tooltip("Width for shiny effect.")] [SerializeField] [Range(0, 1)]
float m_Width = 0.25f;
[Tooltip("Rotation for shiny effect.")] [SerializeField] [Range(-180, 180)]
float m_Rotation = 135;
[Tooltip("Softness for shiny effect.")] [SerializeField] [Range(0.01f, 1)]
float m_Softness = 1f;
[Tooltip("Brightness for shiny effect.")] [FormerlySerializedAs("m_Alpha")] [SerializeField] [Range(0, 1)]
float m_Brightness = 1f;
[Tooltip("Gloss factor for shiny effect.")] [FormerlySerializedAs("m_Highlight")] [SerializeField] [Range(0, 1)]
float m_Gloss = 1;
[Header("Advanced Option")] [Tooltip("The area for effect.")] [SerializeField]
protected EffectArea m_EffectArea;
[SerializeField] EffectPlayer m_Player;
///
/// Effect factor between 0(start) and 1(end).
///
public float effectFactor
{
get { return m_EffectFactor; }
set
{
value = Mathf.Clamp(value, 0, 1);
if (Mathf.Approximately(m_EffectFactor, value)) return;
m_EffectFactor = value;
SetEffectParamsDirty();
}
}
///
/// Width for shiny effect.
///
public float width
{
get { return m_Width; }
set
{
value = Mathf.Clamp(value, 0, 1);
if (Mathf.Approximately(m_Width, value)) return;
m_Width = value;
SetEffectParamsDirty();
}
}
///
/// Softness for shiny effect.
///
public float softness
{
get { return m_Softness; }
set
{
value = Mathf.Clamp(value, 0.01f, 1);
if (Mathf.Approximately(m_Softness, value)) return;
m_Softness = value;
SetEffectParamsDirty();
}
}
///
/// Brightness for shiny effect.
///
public float brightness
{
get { return m_Brightness; }
set
{
value = Mathf.Clamp(value, 0, 1);
if (Mathf.Approximately(m_Brightness, value)) return;
m_Brightness = value;
SetEffectParamsDirty();
}
}
///
/// Gloss factor for shiny effect.
///
public float gloss
{
get { return m_Gloss; }
set
{
value = Mathf.Clamp(value, 0, 1);
if (Mathf.Approximately(m_Gloss, value)) return;
m_Gloss = value;
SetEffectParamsDirty();
}
}
///
/// Rotation for shiny effect.
///
public float rotation
{
get { return m_Rotation; }
set
{
if (Mathf.Approximately(m_Rotation, value)) return;
m_Rotation = value;
SetVerticesDirty();
}
}
///
/// The area for effect.
///
public EffectArea effectArea
{
get { return m_EffectArea; }
set
{
if (m_EffectArea == value) return;
m_EffectArea = value;
SetVerticesDirty();
}
}
///
/// Gets the parameter texture.
///
public override ParameterTexture paramTex
{
get { return s_ParamTex; }
}
public EffectPlayer effectPlayer
{
get { return m_Player ?? (m_Player = new EffectPlayer()); }
}
///
/// This function is called when the object becomes enabled and active.
///
protected override void OnEnable()
{
base.OnEnable();
effectPlayer.OnEnable(f => effectFactor = f);
}
///
/// This function is called when the behaviour becomes disabled () or inactive.
///
protected override void OnDisable()
{
base.OnDisable();
effectPlayer.OnDisable();
}
public override Hash128 GetMaterialHash(Material material)
{
if (!isActiveAndEnabled || !material || !material.shader)
return k_InvalidHash;
return new Hash128(
(uint) material.GetInstanceID(),
k_ShaderId,
0,
0
);
}
public override void ModifyMaterial(Material newMaterial, Graphic graphic)
{
var connector = GraphicConnector.FindConnector(graphic);
newMaterial.shader = Shader.Find(string.Format("Hidden/{0} (UIShiny)", newMaterial.shader.name));
paramTex.RegisterMaterial(newMaterial);
}
///
/// Modifies the mesh.
///
public override void ModifyMesh(VertexHelper vh, Graphic graphic)
{
if (!isActiveAndEnabled)
return;
var normalizedIndex = paramTex.GetNormalizedIndex(this);
var rect = m_EffectArea.GetEffectArea(vh, rectTransform.rect);
// rotation.
var rad = m_Rotation * Mathf.Deg2Rad;
var dir = new Vector2(Mathf.Cos(rad), Mathf.Sin(rad));
dir.x *= rect.height / rect.width;
dir = dir.normalized;
// Calculate vertex position.
var vertex = default(UIVertex);
var localMatrix = new Matrix2x3(rect, dir.x, dir.y); // Get local matrix.
for (int i = 0; i < vh.currentVertCount; i++)
{
vh.PopulateUIVertex(ref vertex, i);
Vector2 normalizedPos;
connector.GetNormalizedFactor(m_EffectArea, i, localMatrix, vertex.position, out normalizedPos);
vertex.uv0 = new Vector2(
Packer.ToFloat(vertex.uv0.x, vertex.uv0.y),
Packer.ToFloat(normalizedPos.y, normalizedIndex)
);
vh.SetUIVertex(vertex, i);
}
}
///
/// Play effect.
///
public void Play(bool reset = true)
{
effectPlayer.Play(reset);
}
///
/// Stop effect.
///
public void Stop(bool reset = true)
{
effectPlayer.Stop(reset);
}
protected override void SetEffectParamsDirty()
{
paramTex.SetData(this, 0, m_EffectFactor); // param1.x : location
paramTex.SetData(this, 1, m_Width); // param1.y : width
paramTex.SetData(this, 2, m_Softness); // param1.z : softness
paramTex.SetData(this, 3, m_Brightness); // param1.w : blightness
paramTex.SetData(this, 4, m_Gloss); // param2.x : gloss
}
protected override void SetVerticesDirty()
{
base.SetVerticesDirty();
_lastRotation = m_Rotation;
_lastEffectArea = m_EffectArea;
}
protected override void OnDidApplyAnimationProperties()
{
base.OnDidApplyAnimationProperties();
if (!Mathf.Approximately(_lastRotation, m_Rotation)
|| _lastEffectArea != m_EffectArea)
SetVerticesDirty();
}
}
}