This commit is contained in:
2024-10-16 00:03:41 +08:00
commit 897058435c
5033 changed files with 1009728 additions and 0 deletions

View File

@@ -0,0 +1,192 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
namespace Coffee.UIEffects
{
/// <summary>
/// Abstract effect base for UI.
/// </summary>
[DisallowMultipleComponent]
public abstract class BaseMaterialEffect : BaseMeshEffect, IParameterTexture, IMaterialModifier
{
protected static readonly Hash128 k_InvalidHash = new Hash128();
protected static readonly List<UIVertex> s_TempVerts = new List<UIVertex>();
private static readonly StringBuilder s_StringBuilder = new StringBuilder();
Hash128 _effectMaterialHash;
/// <summary>
/// Gets or sets the parameter index.
/// </summary>
public int parameterIndex { get; set; }
/// <summary>
/// Gets the parameter texture.
/// </summary>
public virtual ParameterTexture paramTex
{
get { return null; }
}
/// <summary>
/// Mark the vertices as dirty.
/// </summary>
public void SetMaterialDirty()
{
this.connector.SetMaterialDirty(this.graphic);
foreach (var effect in this.syncEffects)
{
effect.SetMaterialDirty();
}
}
public virtual Hash128 GetMaterialHash(Material baseMaterial)
{
return k_InvalidHash;
}
public Material GetModifiedMaterial(Material baseMaterial)
{
return GetModifiedMaterial(baseMaterial, this.graphic);
}
public virtual Material GetModifiedMaterial(Material baseMaterial, Graphic graphic)
{
if (!this.isActiveAndEnabled) return baseMaterial;
var oldHash = this._effectMaterialHash;
this._effectMaterialHash = GetMaterialHash(baseMaterial);
var modifiedMaterial = baseMaterial;
if (this._effectMaterialHash.isValid)
{
modifiedMaterial = MaterialCache.Register(baseMaterial, this._effectMaterialHash, ModifyMaterial, graphic);
}
MaterialCache.Unregister(oldHash);
return modifiedMaterial;
}
// protected bool isTMProMobile (Material material)
// {
// return material && material.shader && material.shader.name.StartsWith ("TextMeshPro/Mobile/", StringComparison.Ordinal);
// }
public virtual void ModifyMaterial(Material newMaterial, Graphic graphic)
{
if (this.isActiveAndEnabled && this.paramTex != null) this.paramTex.RegisterMaterial(newMaterial);
}
protected void SetShaderVariants(Material newMaterial, params object[] variants)
{
// Set shader keywords as variants
var keywords = variants.Where(x => 0 < (int) x)
.Select(x => x.ToString().ToUpper())
.Concat(newMaterial.shaderKeywords)
.Distinct()
.ToArray();
newMaterial.shaderKeywords = keywords;
// Add variant name
s_StringBuilder.Length = 0;
s_StringBuilder.Append(Path.GetFileName(newMaterial.shader.name));
foreach (var keyword in keywords)
{
s_StringBuilder.Append("-");
s_StringBuilder.Append(keyword);
}
newMaterial.name = s_StringBuilder.ToString();
}
#if UNITY_EDITOR
protected override void Reset()
{
if (!this.isActiveAndEnabled) return;
SetMaterialDirty();
SetVerticesDirty();
SetEffectParamsDirty();
}
protected override void OnValidate()
{
if (!this.isActiveAndEnabled) return;
SetVerticesDirty();
SetEffectParamsDirty();
}
#endif
/// <summary>
/// This function is called when the object becomes enabled and active.
/// </summary>
protected override void OnEnable()
{
base.OnEnable();
if (this.paramTex != null)
{
this.paramTex.Register(this);
}
SetMaterialDirty();
SetEffectParamsDirty();
// foreach (var mr in GetComponentsInChildren<UIEffectMaterialResolver> ())
// {
// mr.GetComponent<Graphic> ().SetMaterialDirty ();
// mr.GetComponent<Graphic> ().SetVerticesDirty ();
// }
}
/// <summary>
/// This function is called when the behaviour becomes disabled () or inactive.
/// </summary>
protected override void OnDisable()
{
base.OnDisable();
SetMaterialDirty();
if (this.paramTex != null)
{
this.paramTex.Unregister(this);
}
MaterialCache.Unregister(this._effectMaterialHash);
this._effectMaterialHash = k_InvalidHash;
}
// protected override void OnDidApplyAnimationProperties()
// {
// SetEffectParamsDirty();
// }
// protected override void OnTextChanged (UnityEngine.Object obj)
// {
// base.OnTextChanged (obj);
//
//
// foreach (var sm in GetComponentsInChildren<TMPro.TMP_SubMeshUI> ())
// {
// if(!sm.GetComponent<UIEffectMaterialResolver>())
// {
// var mr = sm.gameObject.AddComponent<UIEffectMaterialResolver> ();
//
// targetGraphic.SetAllDirty ();
// //targetGraphic.SetVerticesDirty ();
//
// //mr.GetComponent<Graphic> ().SetMaterialDirty ();
// //mr.GetComponent<Graphic> ().SetVerticesDirty ();
//
//
// }
// }
// }
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e8b7ed62cf1444b4ebfc5e5338bc6682
timeCreated: 1485321967
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,229 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace Coffee.UIEffects
{
/// <summary>
/// Base class for effects that modify the generated Mesh.
/// It works well not only for standard Graphic components (Image, RawImage, Text, etc.) but also for TextMeshPro and TextMeshProUGUI.
/// </summary>
[RequireComponent(typeof(Graphic))]
[RequireComponent(typeof(RectTransform))]
[ExecuteInEditMode]
public abstract class BaseMeshEffect : UIBehaviour, IMeshModifier
{
RectTransform _rectTransform;
Graphic _graphic;
GraphicConnector _connector;
/// <summary>
/// The Graphic attached to this GameObject.
/// </summary>
protected GraphicConnector connector
{
get { return this._connector ?? (this._connector = GraphicConnector.FindConnector(this.graphic)); }
}
/// <summary>
/// The Graphic attached to this GameObject.
/// </summary>
public Graphic graphic
{
get { return this._graphic ? this._graphic : this._graphic = GetComponent<Graphic>(); }
}
/// <summary>
/// The RectTransform attached to this GameObject.
/// </summary>
protected RectTransform rectTransform
{
get { return this._rectTransform ? this._rectTransform : this._rectTransform = GetComponent<RectTransform>(); }
}
internal readonly List<UISyncEffect> syncEffects = new List<UISyncEffect>(0);
/// <summary>
/// Call used to modify mesh. (legacy)
/// </summary>
/// <param name="mesh">Mesh.</param>
public virtual void ModifyMesh(Mesh mesh)
{
}
/// <summary>
/// Call used to modify mesh.
/// </summary>
/// <param name="vh">VertexHelper.</param>
public virtual void ModifyMesh(VertexHelper vh)
{
ModifyMesh(vh, this.graphic);
}
public virtual void ModifyMesh(VertexHelper vh, Graphic graphic)
{
}
/// <summary>
/// Mark the vertices as dirty.
/// </summary>
protected virtual void SetVerticesDirty()
{
this.connector.SetVerticesDirty(this.graphic);
foreach (var effect in this.syncEffects)
{
effect.SetVerticesDirty();
}
// #if TMP_PRESENT
// if (textMeshPro)
// {
// foreach (var info in textMeshPro.textInfo.meshInfo)
// {
// var mesh = info.mesh;
// if (mesh)
// {
// mesh.Clear();
// mesh.vertices = info.vertices;
// mesh.uv = info.uvs0;
// mesh.uv2 = info.uvs2;
// mesh.colors32 = info.colors32;
// mesh.normals = info.normals;
// mesh.tangents = info.tangents;
// mesh.triangles = info.triangles;
// }
// }
//
// if (canvasRenderer)
// {
// canvasRenderer.SetMesh(textMeshPro.mesh);
//
// GetComponentsInChildren(false, s_SubMeshUIs);
// foreach (var sm in s_SubMeshUIs)
// {
// sm.canvasRenderer.SetMesh(sm.mesh);
// }
//
// s_SubMeshUIs.Clear();
// }
//
// textMeshPro.havePropertiesChanged = true;
// }
// else
// #endif
// if (graphic)
// {
// graphic.SetVerticesDirty();
// }
}
//################################
// Protected Members.
//################################
/// <summary>
/// Should the effect modify the mesh directly for TMPro?
/// </summary>
// protected virtual bool isLegacyMeshModifier
// {
// get { return false; }
// }
// protected virtual void Initialize()
// {
// if (_initialized) return;
//
// _initialized = true;
// _graphic = _graphic ? _graphic : GetComponent<Graphic>();
//
// _connector = GraphicConnector.FindConnector(_graphic);
//
// // _canvasRenderer = _canvasRenderer ?? GetComponent<CanvasRenderer> ();
// _rectTransform = _rectTransform ? _rectTransform : GetComponent<RectTransform>();
// // #if TMP_PRESENT
// // _textMeshPro = _textMeshPro ?? GetComponent<TMP_Text> ();
// // #endif
// }
/// <summary>
/// This function is called when the object becomes enabled and active.
/// </summary>
protected override void OnEnable()
{
this.connector.OnEnable(this.graphic);
SetVerticesDirty();
// SetVerticesDirty();
// #if TMP_PRESENT
// if (textMeshPro)
// {
// TMPro_EventManager.TEXT_CHANGED_EVENT.Add (OnTextChanged);
// }
// #endif
//
// #if UNITY_EDITOR && TMP_PRESENT
// if (graphic && textMeshPro)
// {
// GraphicRebuildTracker.TrackGraphic (graphic);
// }
// #endif
//
// #if UNITY_5_6_OR_NEWER
// if (graphic)
// {
// AdditionalCanvasShaderChannels channels = requiredChannels;
// var canvas = graphic.canvas;
// if (canvas && (canvas.additionalShaderChannels & channels) != channels)
// {
// Debug.LogWarningFormat (this, "Enable {1} of Canvas.additionalShaderChannels to use {0}.", GetType ().Name, channels);
// }
// }
// #endif
}
/// <summary>
/// This function is called when the behaviour becomes disabled () or inactive.
/// </summary>
protected override void OnDisable()
{
this.connector.OnDisable(this.graphic);
SetVerticesDirty();
}
/// <summary>
/// Mark the effect parameters as dirty.
/// </summary>
protected virtual void SetEffectParamsDirty()
{
if (!this.isActiveAndEnabled) return;
SetVerticesDirty();
}
/// <summary>
/// Callback for when properties have been changed by animation.
/// </summary>
protected override void OnDidApplyAnimationProperties()
{
if (!this.isActiveAndEnabled) return;
SetEffectParamsDirty();
}
#if UNITY_EDITOR
protected override void Reset()
{
if (!this.isActiveAndEnabled) return;
SetVerticesDirty();
}
/// <summary>
/// This function is called when the script is loaded or a value is changed in the inspector (Called in the editor only).
/// </summary>
protected override void OnValidate()
{
if (!this.isActiveAndEnabled) return;
SetEffectParamsDirty();
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 229ee7044e2514b0e9bd9fd40a2baa3a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,154 @@
using UnityEngine;
using System;
using System.Collections.Generic;
namespace Coffee.UIEffects
{
/// <summary>
/// Effect player.
/// </summary>
[Serializable]
public class EffectPlayer
{
//################################
// Public Members.
//################################
/// <summary>
/// Gets or sets a value indicating whether is playing.
/// </summary>
[Header("Effect Player")] [Tooltip("Playing.")]
public bool play = false;
/// <summary>
/// Gets or sets the delay before looping.
/// </summary>
[Tooltip("Initial play delay.")] [Range(0f, 10f)]
public float initialPlayDelay = 0;
/// <summary>
/// Gets or sets the duration.
/// </summary>
[Tooltip("Duration.")] [Range(0.01f, 10f)]
public float duration = 1;
/// <summary>
/// Gets or sets a value indicating whether can loop.
/// </summary>
[Tooltip("Loop.")] public bool loop = false;
/// <summary>
/// Gets or sets the delay before looping.
/// </summary>
[Tooltip("Delay before looping.")] [Range(0f, 10f)]
public float loopDelay = 0;
/// <summary>
/// Gets or sets the update mode.
/// </summary>
[Tooltip("Update mode")] public AnimatorUpdateMode updateMode = AnimatorUpdateMode.Normal;
static List<Action> s_UpdateActions;
/// <summary>
/// Register player.
/// </summary>
public void OnEnable(Action<float> callback = null)
{
if (s_UpdateActions == null)
{
s_UpdateActions = new List<Action>();
Canvas.willRenderCanvases += () =>
{
var count = s_UpdateActions.Count;
for (int i = 0; i < count; i++)
{
s_UpdateActions[i].Invoke();
}
};
}
s_UpdateActions.Add(OnWillRenderCanvases);
if (this.play)
{
this._time = -this.initialPlayDelay;
}
else
{
this._time = 0;
}
this._callback = callback;
}
/// <summary>
/// Unregister player.
/// </summary>
public void OnDisable()
{
this._callback = null;
s_UpdateActions.Remove(OnWillRenderCanvases);
}
/// <summary>
/// Start playing.
/// </summary>
public void Play(bool reset, Action<float> callback = null)
{
if (reset)
{
this._time = 0;
}
this.play = true;
if (callback != null)
{
this._callback = callback;
}
}
/// <summary>
/// Stop playing.
/// </summary>
public void Stop(bool reset)
{
if (reset)
{
this._time = 0;
if (this._callback != null)
{
this._callback(this._time);
}
}
this.play = false;
}
//################################
// Private Members.
//################################
float _time = 0;
Action<float> _callback;
void OnWillRenderCanvases()
{
if (!this.play || !Application.isPlaying || this._callback == null)
{
return;
}
this._time += this.updateMode == AnimatorUpdateMode.UnscaledTime
? Time.unscaledDeltaTime
: Time.deltaTime;
var current = this._time / this.duration;
if (this.duration <= this._time)
{
this.play = this.loop;
this._time = this.loop ? -this.loopDelay : 0;
}
this._callback(current);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1656fb67110cd44298010d95c324e87a
timeCreated: 1528296875
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,151 @@
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections.Generic;
namespace Coffee.UIEffects
{
public class GraphicConnector
{
private static readonly List<GraphicConnector> s_Connectors = new List<GraphicConnector>();
private static readonly Dictionary<Type, GraphicConnector> s_ConnectorMap =
new Dictionary<Type, GraphicConnector>();
private static readonly GraphicConnector s_EmptyConnector = new GraphicConnector();
#if UNITY_EDITOR
[UnityEditor.InitializeOnLoadMethod]
#endif
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Init()
{
AddConnector(new GraphicConnector());
}
protected static void AddConnector(GraphicConnector connector)
{
s_Connectors.Add(connector);
s_Connectors.Sort((x, y) => y.priority - x.priority);
}
public static GraphicConnector FindConnector(Graphic graphic)
{
if (!graphic) return s_EmptyConnector;
var type = graphic.GetType();
GraphicConnector connector = null;
if (s_ConnectorMap.TryGetValue(type, out connector)) return connector;
foreach (var c in s_Connectors)
{
if (!c.IsValid(graphic)) continue;
s_ConnectorMap.Add(type, c);
return c;
}
return s_EmptyConnector;
}
/// <summary>
/// Connector priority.
/// </summary>
protected virtual int priority
{
get { return -1; }
}
/// <summary>
/// Extra channel.
/// </summary>
public virtual AdditionalCanvasShaderChannels extraChannel
{
get { return AdditionalCanvasShaderChannels.TexCoord1; }
}
/// <summary>
/// The connector is valid for the component.
/// </summary>
protected virtual bool IsValid(Graphic graphic)
{
return true;
}
/// <summary>
/// Find effect shader.
/// </summary>
public virtual Shader FindShader(string shaderName)
{
return Shader.Find("Hidden/" + shaderName);
}
/// <summary>
/// This function is called when the object becomes enabled and active.
/// </summary>
public virtual void OnEnable(Graphic graphic)
{
}
/// <summary>
/// This function is called when the behaviour becomes disabled () or inactive.
/// </summary>
public virtual void OnDisable(Graphic graphic)
{
}
/// <summary>
/// Mark the vertices as dirty.
/// </summary>
public virtual void SetVerticesDirty(Graphic graphic)
{
if (graphic)
graphic.SetVerticesDirty();
}
/// <summary>
/// Mark the material as dirty.
/// </summary>
public virtual void SetMaterialDirty(Graphic graphic)
{
if (graphic)
graphic.SetMaterialDirty();
}
/// <summary>
/// Gets position factor for area.
/// </summary>
public virtual void GetPositionFactor(EffectArea area, int index, Rect rect, Vector2 position, out float x, out float y)
{
if (area == EffectArea.Fit)
{
x = Mathf.Clamp01((position.x - rect.xMin) / rect.width);
y = Mathf.Clamp01((position.y - rect.yMin) / rect.height);
}
else
{
x = Mathf.Clamp01(position.x / rect.width + 0.5f);
y = Mathf.Clamp01(position.y / rect.height + 0.5f);
}
}
public virtual bool IsText(Graphic graphic)
{
return graphic && graphic is Text;
}
public virtual void SetExtraChannel(ref UIVertex vertex, Vector2 value)
{
vertex.uv1 = value;
}
/// <summary>
/// Normalize vertex position by local matrix.
/// </summary>
public virtual void GetNormalizedFactor(EffectArea area, int index, Matrix2x3 matrix, Vector2 position,
out Vector2 normalizedPos)
{
normalizedPos = matrix * position;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 66636f82e05e6453781a33c8b7da8b93
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,77 @@
using System.Collections.Generic;
using System.Linq;
using System;
using UnityEngine;
using System.Text;
using UnityEngine.UI;
namespace Coffee.UIEffects
{
public class MaterialCache
{
static Dictionary<Hash128, MaterialEntry> materialMap = new Dictionary<Hash128, MaterialEntry>();
private class MaterialEntry
{
public Material material;
public int referenceCount;
public void Release()
{
if (this.material)
{
UnityEngine.Object.DestroyImmediate(this.material, false);
}
this.material = null;
}
}
#if UNITY_EDITOR
[UnityEditor.InitializeOnLoadMethod]
private static void ClearCache()
{
foreach (var entry in materialMap.Values)
{
entry.Release();
}
materialMap.Clear();
}
#endif
public static Material Register(Material baseMaterial, Hash128 hash,
Action<Material, Graphic> onModifyMaterial, Graphic graphic)
{
if (!hash.isValid) return null;
MaterialEntry entry;
if (!materialMap.TryGetValue(hash, out entry))
{
entry = new MaterialEntry()
{
material = new Material(baseMaterial)
{
hideFlags = HideFlags.HideAndDontSave,
},
};
onModifyMaterial(entry.material, graphic);
materialMap.Add(hash, entry);
}
entry.referenceCount++;
return entry.material;
}
public static void Unregister(Hash128 hash)
{
MaterialEntry entry;
if (!hash.isValid || !materialMap.TryGetValue(hash, out entry)) return;
if (--entry.referenceCount > 0) return;
entry.Release();
materialMap.Remove(hash);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2160d2c55a6100642b6c7ba09df935da
timeCreated: 1528509206
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
using UnityEngine;
namespace Coffee.UIEffects
{
/// <summary>
/// Matrix2x3.
/// </summary>
public struct Matrix2x3
{
public float m00, m01, m02, m10, m11, m12;
public Matrix2x3(Rect rect, float cos, float sin)
{
const float center = 0.5f;
float dx = -rect.xMin / rect.width - center;
float dy = -rect.yMin / rect.height - center;
this.m00 = cos / rect.width;
this.m01 = -sin / rect.height;
this.m02 = dx * cos - dy * sin + center;
this.m10 = sin / rect.width;
this.m11 = cos / rect.height;
this.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
);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 5a9b962044ca64867b713425f7e5daab
timeCreated: 1527590245
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,61 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class Packer
{
/// <summary>
/// Pack 4 low-precision [0-1] floats values to a float.
/// Each value [0-1] has 64 steps(6 bits).
/// </summary>
public static float ToFloat(float x, float y, float z, float w)
{
x = x < 0 ? 0 : 1 < x ? 1 : x;
y = y < 0 ? 0 : 1 < y ? 1 : y;
z = z < 0 ? 0 : 1 < z ? 1 : z;
w = w < 0 ? 0 : 1 < w ? 1 : w;
const int PRECISION = (1 << 6) - 1;
return (Mathf.FloorToInt(w * PRECISION) << 18)
+ (Mathf.FloorToInt(z * PRECISION) << 12)
+ (Mathf.FloorToInt(y * PRECISION) << 6)
+ Mathf.FloorToInt(x * PRECISION);
}
/// <summary>
/// Pack 4 low-precision [0-1] floats values to a float.
/// Each value [0-1] has 64 steps(6 bits).
/// </summary>
public static float ToFloat(Vector4 factor)
{
return ToFloat(Mathf.Clamp01(factor.x), Mathf.Clamp01(factor.y), Mathf.Clamp01(factor.z),
Mathf.Clamp01(factor.w));
}
/// <summary>
/// Pack 1 middle-precision & 2 low-precision [0-1] floats values to a float.
/// z value [0-1] has 4096 steps(12 bits) and xy value [0-1] has 64 steps(6 bits).
/// </summary>
public static float ToFloat(float x, float y, float z)
{
x = x < 0 ? 0 : 1 < x ? 1 : x;
y = y < 0 ? 0 : 1 < y ? 1 : y;
z = z < 0 ? 0 : 1 < z ? 1 : z;
const int PRECISION = (1 << 8) - 1;
return (Mathf.FloorToInt(z * PRECISION) << 16)
+ (Mathf.FloorToInt(y * PRECISION) << 8)
+ Mathf.FloorToInt(x * PRECISION);
}
/// <summary>
/// Pack 2 low-precision [0-1] floats values to a float.
/// Each value [0-1] has 4096 steps(12 bits).
/// </summary>
public static float ToFloat(float x, float y)
{
x = x < 0 ? 0 : 1 < x ? 1 : x;
y = y < 0 ? 0 : 1 < y ? 1 : y;
const int PRECISION = (1 << 12) - 1;
return (Mathf.FloorToInt(y * PRECISION) << 12)
+ Mathf.FloorToInt(x * PRECISION);
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b4970b3a69d3b472b8d66c1d92ec7bad
timeCreated: 1527590285
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,190 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using System;
namespace Coffee.UIEffects
{
public interface IParameterTexture
{
int parameterIndex { get; set; }
ParameterTexture paramTex { get; }
}
/// <summary>
/// Parameter texture.
/// </summary>
[Serializable]
public class ParameterTexture
{
//################################
// Public Members.
//################################
/// <summary>
/// Initializes a new instance of the <see cref="Coffee.UIEffects.ParameterTexture"/> class.
/// </summary>
/// <param name="channels">Channels.</param>
/// <param name="instanceLimit">Instance limit.</param>
/// <param name="propertyName">Property name.</param>
public ParameterTexture(int channels, int instanceLimit, string propertyName)
{
this._propertyName = propertyName;
this._channels = ((channels - 1) / 4 + 1) * 4;
this._instanceLimit = ((instanceLimit - 1) / 2 + 1) * 2;
this._data = new byte[this._channels * this._instanceLimit];
this._stack = new Stack<int>(this._instanceLimit);
for (int i = 1; i < this._instanceLimit + 1; i++)
{
this._stack.Push(i);
}
}
/// <summary>
/// Register the specified target.
/// </summary>
/// <param name="target">Target.</param>
public void Register(IParameterTexture target)
{
Initialize();
if (target.parameterIndex <= 0 && 0 < this._stack.Count)
{
target.parameterIndex = this._stack.Pop();
// Debug.LogFormat("<color=green>@@@ Register {0} : {1}</color>", target, target.parameterIndex);
}
}
/// <summary>
/// Unregister the specified target.
/// </summary>
/// <param name="target">Target.</param>
public void Unregister(IParameterTexture target)
{
if (0 < target.parameterIndex)
{
// Debug.LogFormat("<color=red>@@@ Unregister {0} : {1}</color>", target, target.parameterIndex);
this._stack.Push(target.parameterIndex);
target.parameterIndex = 0;
}
}
/// <summary>
/// Sets the data.
/// </summary>
/// <param name="target">Target.</param>
/// <param name="channelId">Channel identifier.</param>
/// <param name="value">Value.</param>
public void SetData(IParameterTexture target, int channelId, byte value)
{
int index = (target.parameterIndex - 1) * this._channels + channelId;
if (0 < target.parameterIndex && this._data[index] != value)
{
this._data[index] = value;
this._needUpload = true;
}
}
/// <summary>
/// Sets the data.
/// </summary>
/// <param name="target">Target.</param>
/// <param name="channelId">Channel identifier.</param>
/// <param name="value">Value.</param>
public void SetData(IParameterTexture target, int channelId, float value)
{
SetData(target, channelId, (byte) (Mathf.Clamp01(value) * 255));
}
/// <summary>
/// Registers the material.
/// </summary>
/// <param name="mat">Mat.</param>
public void RegisterMaterial(Material mat)
{
if (this._propertyId == 0)
{
this._propertyId = Shader.PropertyToID(this._propertyName);
}
if (mat)
{
mat.SetTexture(this._propertyId, this._texture);
}
}
/// <summary>
/// Gets the index of the normalized.
/// </summary>
/// <returns>The normalized index.</returns>
/// <param name="target">Target.</param>
public float GetNormalizedIndex(IParameterTexture target)
{
return ((float) target.parameterIndex - 0.5f) / this._instanceLimit;
}
//################################
// Private Members.
//################################
Texture2D _texture;
bool _needUpload;
int _propertyId;
readonly string _propertyName;
readonly int _channels;
readonly int _instanceLimit;
readonly byte[] _data;
readonly Stack<int> _stack;
static List<Action> updates;
/// <summary>
/// Initialize this instance.
/// </summary>
void Initialize()
{
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying && UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
{
return;
}
#endif
if (updates == null)
{
updates = new List<Action>();
Canvas.willRenderCanvases += () =>
{
var count = updates.Count;
for (int i = 0; i < count; i++)
{
updates[i].Invoke();
}
};
}
if (!this._texture)
{
bool isLinear = QualitySettings.activeColorSpace == ColorSpace.Linear;
this._texture = new Texture2D(this._channels / 4, this._instanceLimit, TextureFormat.RGBA32, false, isLinear);
this._texture.filterMode = FilterMode.Point;
this._texture.wrapMode = TextureWrapMode.Clamp;
updates.Add(UpdateParameterTexture);
this._needUpload = true;
}
}
void UpdateParameterTexture()
{
if (this._needUpload && this._texture)
{
this._needUpload = false;
this._texture.LoadRawTextureData(this._data);
this._texture.Apply(false, false);
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 65eafa89b3a3a494a99e185423ba6cad
timeCreated: 1533006319
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: