using System;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
namespace Coffee.UIEffects
{
///
/// HSV Modifier.
///
[AddComponentMenu("UI/UIEffects/UIHsvModifier", 4)]
public class UIHsvModifier : BaseMaterialEffect
{
private const uint k_ShaderId = 6 << 3;
private static readonly ParameterTexture s_ParamTex = new ParameterTexture(7, 128, "_ParamTex");
[Header("Target")] [Tooltip("Target color to affect hsv shift.")] [SerializeField] [ColorUsage(false)]
Color m_TargetColor = Color.red;
[Tooltip("Color range to affect hsv shift [0 ~ 1].")] [SerializeField] [Range(0, 1)]
float m_Range = 0.1f;
[Header("Adjustment")] [Tooltip("Hue shift [-0.5 ~ 0.5].")] [SerializeField] [Range(-0.5f, 0.5f)]
float m_Hue;
[Tooltip("Saturation shift [-0.5 ~ 0.5].")] [SerializeField] [Range(-0.5f, 0.5f)]
float m_Saturation;
[Tooltip("Value shift [-0.5 ~ 0.5].")] [SerializeField] [Range(-0.5f, 0.5f)]
float m_Value;
///
/// Target color to affect hsv shift.
///
public Color targetColor
{
get { return m_TargetColor; }
set
{
if (m_TargetColor == value) return;
m_TargetColor = value;
SetEffectParamsDirty();
}
}
///
/// Color range to affect hsv shift [0 ~ 1].
///
public float range
{
get { return m_Range; }
set
{
value = Mathf.Clamp(value, 0, 1);
if (Mathf.Approximately(m_Range, value)) return;
m_Range = value;
SetEffectParamsDirty();
}
}
///
/// Saturation shift [-0.5 ~ 0.5].
///
public float saturation
{
get { return m_Saturation; }
set
{
value = Mathf.Clamp(value, -0.5f, 0.5f);
if (Mathf.Approximately(m_Saturation, value)) return;
m_Saturation = value;
SetEffectParamsDirty();
}
}
///
/// Value shift [-0.5 ~ 0.5].
///
public float value
{
get { return m_Value; }
set
{
value = Mathf.Clamp(value, -0.5f, 0.5f);
if (Mathf.Approximately(m_Value, value)) return;
m_Value = value;
SetEffectParamsDirty();
}
}
///
/// Hue shift [-0.5 ~ 0.5].
///
public float hue
{
get { return m_Hue; }
set
{
value = Mathf.Clamp(value, -0.5f, 0.5f);
if (Mathf.Approximately(m_Hue, value)) return;
m_Hue = value;
SetEffectParamsDirty();
}
}
///
/// Gets the parameter texture.
///
public override ParameterTexture paramTex
{
get { return s_ParamTex; }
}
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} (UIHsvModifier)", newMaterial.shader.name));
paramTex.RegisterMaterial(newMaterial);
}
public override void ModifyMesh(VertexHelper vh, Graphic graphic)
{
if (!isActiveAndEnabled)
return;
var normalizedIndex = paramTex.GetNormalizedIndex(this);
var vertex = default(UIVertex);
var count = vh.currentVertCount;
for (var i = 0; i < count; i++)
{
vh.PopulateUIVertex(ref vertex, i);
vertex.uv0 = new Vector2(
Packer.ToFloat(vertex.uv0.x, vertex.uv0.y),
normalizedIndex
);
vh.SetUIVertex(vertex, i);
}
}
protected override void SetEffectParamsDirty()
{
float h, s, v;
Color.RGBToHSV(m_TargetColor, out h, out s, out v);
paramTex.SetData(this, 0, h); // param1.x : target hue
paramTex.SetData(this, 1, s); // param1.y : target saturation
paramTex.SetData(this, 2, v); // param1.z : target value
paramTex.SetData(this, 3, m_Range); // param1.w : target range
paramTex.SetData(this, 4, m_Hue + 0.5f); // param2.x : hue shift
paramTex.SetData(this, 5, m_Saturation + 0.5f); // param2.y : saturation shift
paramTex.SetData(this, 6, m_Value + 0.5f); // param2.z : value shift
}
}
}