summaryrefslogtreecommitdiff
path: root/Assets/Scripts/Common
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-04-07 21:33:14 +0800
committerchai <chaifix@163.com>2021-04-07 21:33:14 +0800
commitc47b92e92cf33ae8bf2f38929e137294397e4735 (patch)
treec67ae3419eaf15e84f1679186e107f598de33978 /Assets/Scripts/Common
Diffstat (limited to 'Assets/Scripts/Common')
-rw-r--r--Assets/Scripts/Common/BaseMaterialEffect.cs193
-rw-r--r--Assets/Scripts/Common/BaseMaterialEffect.cs.meta12
-rw-r--r--Assets/Scripts/Common/BaseMeshEffect.cs229
-rw-r--r--Assets/Scripts/Common/BaseMeshEffect.cs.meta11
-rw-r--r--Assets/Scripts/Common/EffectPlayer.cs154
-rw-r--r--Assets/Scripts/Common/EffectPlayer.cs.meta12
-rw-r--r--Assets/Scripts/Common/GraphicConnector.cs151
-rw-r--r--Assets/Scripts/Common/GraphicConnector.cs.meta11
-rw-r--r--Assets/Scripts/Common/MaterialCache.cs77
-rw-r--r--Assets/Scripts/Common/MaterialCache.cs.meta12
-rw-r--r--Assets/Scripts/Common/Matrix2x3.cs33
-rw-r--r--Assets/Scripts/Common/Matrix2x3.cs.meta12
-rw-r--r--Assets/Scripts/Common/Packer.cs61
-rw-r--r--Assets/Scripts/Common/Packer.cs.meta12
-rw-r--r--Assets/Scripts/Common/ParameterTexture.cs190
-rw-r--r--Assets/Scripts/Common/ParameterTexture.cs.meta12
16 files changed, 1182 insertions, 0 deletions
diff --git a/Assets/Scripts/Common/BaseMaterialEffect.cs b/Assets/Scripts/Common/BaseMaterialEffect.cs
new file mode 100644
index 0000000..0cf2d7a
--- /dev/null
+++ b/Assets/Scripts/Common/BaseMaterialEffect.cs
@@ -0,0 +1,193 @@
+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()
+ {
+ connector.SetMaterialDirty(graphic);
+
+ foreach (var effect in syncEffects)
+ {
+ effect.SetMaterialDirty();
+ }
+ }
+
+ public virtual Hash128 GetMaterialHash(Material baseMaterial)
+ {
+ return k_InvalidHash;
+ }
+
+ public Material GetModifiedMaterial(Material baseMaterial)
+ {
+ return GetModifiedMaterial(baseMaterial, graphic);
+ }
+
+ public virtual Material GetModifiedMaterial(Material baseMaterial, Graphic graphic)
+ {
+ if (!isActiveAndEnabled) return baseMaterial;
+
+ var oldHash = _effectMaterialHash;
+ _effectMaterialHash = GetMaterialHash(baseMaterial);
+ var modifiedMaterial = baseMaterial;
+ if (_effectMaterialHash.isValid)
+ {
+ modifiedMaterial = MaterialCache.Register(baseMaterial, _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 (isActiveAndEnabled && paramTex != null)
+ 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 (!isActiveAndEnabled) return;
+ SetMaterialDirty();
+ SetVerticesDirty();
+ SetEffectParamsDirty();
+ }
+
+ protected override void OnValidate()
+ {
+ if (!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 (paramTex != null)
+ {
+ 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 (paramTex != null)
+ {
+ paramTex.Unregister(this);
+ }
+
+ MaterialCache.Unregister(_effectMaterialHash);
+ _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 ();
+ //
+ //
+ // }
+ // }
+ // }
+ }
+}
diff --git a/Assets/Scripts/Common/BaseMaterialEffect.cs.meta b/Assets/Scripts/Common/BaseMaterialEffect.cs.meta
new file mode 100644
index 0000000..7b7e351
--- /dev/null
+++ b/Assets/Scripts/Common/BaseMaterialEffect.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: e8b7ed62cf1444b4ebfc5e5338bc6682
+timeCreated: 1485321967
+licenseType: Pro
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Common/BaseMeshEffect.cs b/Assets/Scripts/Common/BaseMeshEffect.cs
new file mode 100644
index 0000000..40d4e66
--- /dev/null
+++ b/Assets/Scripts/Common/BaseMeshEffect.cs
@@ -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 _connector ?? (_connector = GraphicConnector.FindConnector(graphic)); }
+ }
+
+ /// <summary>
+ /// The Graphic attached to this GameObject.
+ /// </summary>
+ public Graphic graphic
+ {
+ get { return _graphic ? _graphic : _graphic = GetComponent<Graphic>(); }
+ }
+
+ /// <summary>
+ /// The RectTransform attached to this GameObject.
+ /// </summary>
+ protected RectTransform rectTransform
+ {
+ get { return _rectTransform ? _rectTransform : _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, graphic);
+ }
+
+ public virtual void ModifyMesh(VertexHelper vh, Graphic graphic)
+ {
+ }
+
+ /// <summary>
+ /// Mark the vertices as dirty.
+ /// </summary>
+ protected virtual void SetVerticesDirty()
+ {
+ connector.SetVerticesDirty(graphic);
+
+ foreach (var effect in 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()
+ {
+ connector.OnEnable(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()
+ {
+ connector.OnDisable(graphic);
+ SetVerticesDirty();
+ }
+
+ /// <summary>
+ /// Mark the effect parameters as dirty.
+ /// </summary>
+ protected virtual void SetEffectParamsDirty()
+ {
+ if (!isActiveAndEnabled) return;
+ SetVerticesDirty();
+ }
+
+ /// <summary>
+ /// Callback for when properties have been changed by animation.
+ /// </summary>
+ protected override void OnDidApplyAnimationProperties()
+ {
+ if (!isActiveAndEnabled) return;
+ SetEffectParamsDirty();
+ }
+
+#if UNITY_EDITOR
+ protected override void Reset()
+ {
+ if (!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 (!isActiveAndEnabled) return;
+ SetEffectParamsDirty();
+ }
+#endif
+ }
+}
diff --git a/Assets/Scripts/Common/BaseMeshEffect.cs.meta b/Assets/Scripts/Common/BaseMeshEffect.cs.meta
new file mode 100644
index 0000000..1d3c8d1
--- /dev/null
+++ b/Assets/Scripts/Common/BaseMeshEffect.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 229ee7044e2514b0e9bd9fd40a2baa3a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Common/EffectPlayer.cs b/Assets/Scripts/Common/EffectPlayer.cs
new file mode 100644
index 0000000..f60165a
--- /dev/null
+++ b/Assets/Scripts/Common/EffectPlayer.cs
@@ -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 (play)
+ {
+ _time = -initialPlayDelay;
+ }
+ else
+ {
+ _time = 0;
+ }
+
+ _callback = callback;
+ }
+
+ /// <summary>
+ /// Unregister player.
+ /// </summary>
+ public void OnDisable()
+ {
+ _callback = null;
+ s_UpdateActions.Remove(OnWillRenderCanvases);
+ }
+
+ /// <summary>
+ /// Start playing.
+ /// </summary>
+ public void Play(bool reset, Action<float> callback = null)
+ {
+ if (reset)
+ {
+ _time = 0;
+ }
+
+ play = true;
+ if (callback != null)
+ {
+ _callback = callback;
+ }
+ }
+
+ /// <summary>
+ /// Stop playing.
+ /// </summary>
+ public void Stop(bool reset)
+ {
+ if (reset)
+ {
+ _time = 0;
+ if (_callback != null)
+ {
+ _callback(_time);
+ }
+ }
+
+ play = false;
+ }
+
+ //################################
+ // Private Members.
+ //################################
+ float _time = 0;
+ Action<float> _callback;
+
+ void OnWillRenderCanvases()
+ {
+ if (!play || !Application.isPlaying || _callback == null)
+ {
+ return;
+ }
+
+ _time += updateMode == AnimatorUpdateMode.UnscaledTime
+ ? Time.unscaledDeltaTime
+ : Time.deltaTime;
+ var current = _time / duration;
+
+ if (duration <= _time)
+ {
+ play = loop;
+ _time = loop ? -loopDelay : 0;
+ }
+
+ _callback(current);
+ }
+ }
+}
diff --git a/Assets/Scripts/Common/EffectPlayer.cs.meta b/Assets/Scripts/Common/EffectPlayer.cs.meta
new file mode 100644
index 0000000..661e073
--- /dev/null
+++ b/Assets/Scripts/Common/EffectPlayer.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 1656fb67110cd44298010d95c324e87a
+timeCreated: 1528296875
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Common/GraphicConnector.cs b/Assets/Scripts/Common/GraphicConnector.cs
new file mode 100644
index 0000000..3046297
--- /dev/null
+++ b/Assets/Scripts/Common/GraphicConnector.cs
@@ -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;
+ }
+ }
+}
diff --git a/Assets/Scripts/Common/GraphicConnector.cs.meta b/Assets/Scripts/Common/GraphicConnector.cs.meta
new file mode 100644
index 0000000..5652017
--- /dev/null
+++ b/Assets/Scripts/Common/GraphicConnector.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 66636f82e05e6453781a33c8b7da8b93
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Common/MaterialCache.cs b/Assets/Scripts/Common/MaterialCache.cs
new file mode 100644
index 0000000..8d8ed93
--- /dev/null
+++ b/Assets/Scripts/Common/MaterialCache.cs
@@ -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 (material)
+ {
+ UnityEngine.Object.DestroyImmediate(material, false);
+ }
+
+ 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,
+ System.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);
+ }
+ }
+}
diff --git a/Assets/Scripts/Common/MaterialCache.cs.meta b/Assets/Scripts/Common/MaterialCache.cs.meta
new file mode 100644
index 0000000..434e1ff
--- /dev/null
+++ b/Assets/Scripts/Common/MaterialCache.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 2160d2c55a6100642b6c7ba09df935da
+timeCreated: 1528509206
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Common/Matrix2x3.cs b/Assets/Scripts/Common/Matrix2x3.cs
new file mode 100644
index 0000000..ec2cb69
--- /dev/null
+++ b/Assets/Scripts/Common/Matrix2x3.cs
@@ -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;
+ 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
+ );
+ }
+ }
+}
diff --git a/Assets/Scripts/Common/Matrix2x3.cs.meta b/Assets/Scripts/Common/Matrix2x3.cs.meta
new file mode 100644
index 0000000..70ee757
--- /dev/null
+++ b/Assets/Scripts/Common/Matrix2x3.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5a9b962044ca64867b713425f7e5daab
+timeCreated: 1527590245
+licenseType: Pro
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Common/Packer.cs b/Assets/Scripts/Common/Packer.cs
new file mode 100644
index 0000000..ffdb64f
--- /dev/null
+++ b/Assets/Scripts/Common/Packer.cs
@@ -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);
+ }
+}
diff --git a/Assets/Scripts/Common/Packer.cs.meta b/Assets/Scripts/Common/Packer.cs.meta
new file mode 100644
index 0000000..4105720
--- /dev/null
+++ b/Assets/Scripts/Common/Packer.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b4970b3a69d3b472b8d66c1d92ec7bad
+timeCreated: 1527590285
+licenseType: Pro
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Common/ParameterTexture.cs b/Assets/Scripts/Common/ParameterTexture.cs
new file mode 100644
index 0000000..3249828
--- /dev/null
+++ b/Assets/Scripts/Common/ParameterTexture.cs
@@ -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>
+ [System.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)
+ {
+ _propertyName = propertyName;
+ _channels = ((channels - 1) / 4 + 1) * 4;
+ _instanceLimit = ((instanceLimit - 1) / 2 + 1) * 2;
+ _data = new byte[_channels * _instanceLimit];
+
+ _stack = new Stack<int>(_instanceLimit);
+ for (int i = 1; i < _instanceLimit + 1; i++)
+ {
+ _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 < _stack.Count)
+ {
+ target.parameterIndex = _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);
+ _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) * _channels + channelId;
+ if (0 < target.parameterIndex && _data[index] != value)
+ {
+ _data[index] = value;
+ _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 (_propertyId == 0)
+ {
+ _propertyId = Shader.PropertyToID(_propertyName);
+ }
+
+ if (mat)
+ {
+ mat.SetTexture(_propertyId, _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) / _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 (!_texture)
+ {
+ bool isLinear = QualitySettings.activeColorSpace == ColorSpace.Linear;
+ _texture = new Texture2D(_channels / 4, _instanceLimit, TextureFormat.RGBA32, false, isLinear);
+ _texture.filterMode = FilterMode.Point;
+ _texture.wrapMode = TextureWrapMode.Clamp;
+
+ updates.Add(UpdateParameterTexture);
+ _needUpload = true;
+ }
+ }
+
+ void UpdateParameterTexture()
+ {
+ if (_needUpload && _texture)
+ {
+ _needUpload = false;
+ _texture.LoadRawTextureData(_data);
+ _texture.Apply(false, false);
+ }
+ }
+ }
+}
diff --git a/Assets/Scripts/Common/ParameterTexture.cs.meta b/Assets/Scripts/Common/ParameterTexture.cs.meta
new file mode 100644
index 0000000..8b718d0
--- /dev/null
+++ b/Assets/Scripts/Common/ParameterTexture.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 65eafa89b3a3a494a99e185423ba6cad
+timeCreated: 1533006319
+licenseType: Pro
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: