diff options
Diffstat (limited to 'Assets/Scripts')
69 files changed, 4824 insertions, 0 deletions
diff --git a/Assets/Scripts/Common.meta b/Assets/Scripts/Common.meta new file mode 100644 index 0000000..36580c4 --- /dev/null +++ b/Assets/Scripts/Common.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 04feaefc7cdee4c13abcd553a1a6e3a9 +folderAsset: yes +timeCreated: 1528368324 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: 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: diff --git a/Assets/Scripts/Editor.meta b/Assets/Scripts/Editor.meta new file mode 100644 index 0000000..1e9742d --- /dev/null +++ b/Assets/Scripts/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ee1bfc8c299e6482cb7175ba2f94495a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/ImportSampleMenu.cs b/Assets/Scripts/Editor/ImportSampleMenu.cs new file mode 100644 index 0000000..c53fc9b --- /dev/null +++ b/Assets/Scripts/Editor/ImportSampleMenu.cs @@ -0,0 +1,75 @@ +#if !UNITY_2019_1_OR_NEWER +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using UnityEditor; + +namespace Coffee.UIEffects +{ + public static class ImportSampleMenu + { + private const string jsonGuid = "546af75b6221c4768be79d67c9cea1fb"; + + [MenuItem("Assets/Samples/UIEffect/Import Demo")] + private static void ImportDemo() + { + ImportSample(jsonGuid, "Demo"); + } + + private static void ImportSample(string jsonGuid, string sampleName) + { + var jsonPath = AssetDatabase.GUIDToAssetPath(jsonGuid); + var json = File.ReadAllText(jsonPath); + var version = Regex.Match(json, "\"version\"\\s*:\\s*\"([^\"]+)\"").Groups[1].Value; + var displayName = Regex.Match(json, "\"displayName\"\\s*:\\s*\"([^\"]+)\"").Groups[1].Value; + var src = string.Format("{0}/Samples~/{1}", Path.GetDirectoryName(jsonPath), sampleName); + var srcAlt = string.Format("{0}/Samples/{1}", Path.GetDirectoryName(jsonPath), sampleName); + var dst = string.Format("Assets/Samples/{0}/{1}/{2}", displayName, version, sampleName); + var previousPath = GetPreviousSamplePath(displayName, sampleName); + + // Remove the previous sample directory. + if (!string.IsNullOrEmpty(previousPath)) + { + var msg = "A different version of the sample is already imported at\n\n" + + previousPath + + "\n\nIt will be deleted when you update. Are you sure you want to continue?"; + if (!EditorUtility.DisplayDialog("Sample Importer", msg, "OK", "Cancel")) + return; + + FileUtil.DeleteFileOrDirectory(previousPath); + + var metaFile = previousPath + ".meta"; + if (File.Exists(metaFile)) + FileUtil.DeleteFileOrDirectory(metaFile); + } + + if (!Directory.Exists(dst)) + FileUtil.DeleteFileOrDirectory(dst); + + var dstDir = Path.GetDirectoryName(dst); + if (!Directory.Exists(dstDir)) + Directory.CreateDirectory(dstDir); + + if (Directory.Exists(src)) + FileUtil.CopyFileOrDirectory(src, dst); + else if (Directory.Exists(srcAlt)) + FileUtil.CopyFileOrDirectory(srcAlt, dst); + else + throw new DirectoryNotFoundException(src); + + AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive); + } + + private static string GetPreviousSamplePath(string displayName, string sampleName) + { + var sampleRoot = string.Format("Assets/Samples/{0}", displayName); + var sampleRootInfo = new DirectoryInfo(sampleRoot); + if (!sampleRootInfo.Exists) return null; + + return sampleRootInfo.GetDirectories() + .Select(versionDir => Path.Combine(versionDir.ToString(), sampleName)) + .FirstOrDefault(Directory.Exists); + } + } +} +#endif diff --git a/Assets/Scripts/Editor/ImportSampleMenu.cs.meta b/Assets/Scripts/Editor/ImportSampleMenu.cs.meta new file mode 100644 index 0000000..5057915 --- /dev/null +++ b/Assets/Scripts/Editor/ImportSampleMenu.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f1d002a431e7c4b1ca5db78469cb0d1c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/MaterialDirtyScope.cs b/Assets/Scripts/Editor/MaterialDirtyScope.cs new file mode 100644 index 0000000..435e66e --- /dev/null +++ b/Assets/Scripts/Editor/MaterialDirtyScope.cs @@ -0,0 +1,33 @@ +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace Coffee.UIEffects.Editors +{ + /// <summary> + /// Changes in this scope cause the graphic's material to be dirty. + /// When you change a property, it marks the material as dirty. + /// </summary> + internal class MaterialDirtyScope : EditorGUI.ChangeCheckScope + { + readonly Object[] targets; + + public MaterialDirtyScope(Object[] targets) + { + this.targets = targets; + } + + protected override void CloseScope() + { + if (changed) + { + foreach (var effect in targets.OfType<BaseMaterialEffect>()) + { + effect.SetMaterialDirty(); + } + } + + base.CloseScope(); + } + } +} diff --git a/Assets/Scripts/Editor/MaterialDirtyScope.cs.meta b/Assets/Scripts/Editor/MaterialDirtyScope.cs.meta new file mode 100644 index 0000000..c0c5053 --- /dev/null +++ b/Assets/Scripts/Editor/MaterialDirtyScope.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 16857cac7da564347876420ef55a734a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/UIDissolveEditor.cs b/Assets/Scripts/Editor/UIDissolveEditor.cs new file mode 100644 index 0000000..29c2782 --- /dev/null +++ b/Assets/Scripts/Editor/UIDissolveEditor.cs @@ -0,0 +1,121 @@ +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; +using System.Linq; +using System.Collections.Generic; +using UnityEngine.UI; + +namespace Coffee.UIEffects.Editors +{ + /// <summary> + /// UIEffect editor. + /// </summary> + [CustomEditor(typeof(UIDissolve))] + [CanEditMultipleObjects] + public class UIDissolveEditor : Editor + { + SerializedProperty _spEffectFactor; + SerializedProperty _spWidth; + SerializedProperty _spColor; + SerializedProperty _spSoftness; + SerializedProperty _spColorMode; + SerializedProperty _spTransitionTexture; + SerializedProperty _spEffectArea; + SerializedProperty _spKeepAspectRatio; + SerializedProperty _spReverse; + SerializedProperty _spPlay; + SerializedProperty _spLoop; + SerializedProperty _spLoopDelay; + SerializedProperty _spDuration; + SerializedProperty _spInitialPlayDelay; + SerializedProperty _spUpdateMode; + + //################################ + // Public/Protected Members. + //################################ + /// <summary> + /// This function is called when the object becomes enabled and active. + /// </summary> + protected void OnEnable() + { + _spEffectFactor = serializedObject.FindProperty("m_EffectFactor"); + _spEffectArea = serializedObject.FindProperty("m_EffectArea"); + _spKeepAspectRatio = serializedObject.FindProperty("m_KeepAspectRatio"); + _spWidth = serializedObject.FindProperty("m_Width"); + _spColor = serializedObject.FindProperty("m_Color"); + _spSoftness = serializedObject.FindProperty("m_Softness"); + _spColorMode = serializedObject.FindProperty("m_ColorMode"); + _spTransitionTexture = serializedObject.FindProperty("m_TransitionTexture"); + _spKeepAspectRatio = serializedObject.FindProperty("m_KeepAspectRatio"); + _spReverse = serializedObject.FindProperty("m_Reverse"); + var player = serializedObject.FindProperty("m_Player"); + _spPlay = player.FindPropertyRelative("play"); + _spDuration = player.FindPropertyRelative("duration"); + _spInitialPlayDelay = player.FindPropertyRelative("initialPlayDelay"); + _spLoop = player.FindPropertyRelative("loop"); + _spLoopDelay = player.FindPropertyRelative("loopDelay"); + _spUpdateMode = player.FindPropertyRelative("updateMode"); + } + + /// <summary> + /// Implement this function to make a custom inspector. + /// </summary> + public override void OnInspectorGUI() + { + serializedObject.Update(); + + //================ + // Effect setting. + //================ + EditorGUILayout.PropertyField(_spEffectFactor); + EditorGUILayout.PropertyField(_spWidth); + EditorGUILayout.PropertyField(_spSoftness); + EditorGUILayout.PropertyField(_spColor); + + using (new MaterialDirtyScope(targets)) + { + EditorGUILayout.PropertyField(_spColorMode); + EditorGUILayout.PropertyField(_spTransitionTexture); + } + + + //================ + // Advanced option. + //================ + EditorGUILayout.PropertyField(_spEffectArea); + EditorGUILayout.PropertyField(_spKeepAspectRatio); + + + //================ + // Effect player. + //================ + EditorGUILayout.PropertyField(_spPlay); + EditorGUILayout.PropertyField(_spDuration); + EditorGUILayout.PropertyField(_spInitialPlayDelay); + EditorGUILayout.PropertyField(_spLoop); + EditorGUILayout.PropertyField(_spLoopDelay); + EditorGUILayout.PropertyField(_spUpdateMode); + EditorGUILayout.PropertyField(_spReverse); + + + // Debug. + using (new EditorGUI.DisabledGroupScope(!Application.isPlaying)) + using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox)) + { + GUILayout.Label("Debug"); + + if (GUILayout.Button("Play", "ButtonLeft")) + { + (target as UIDissolve).Play(); + } + + if (GUILayout.Button("Stop", "ButtonRight")) + { + (target as UIDissolve).Stop(); + } + } + + serializedObject.ApplyModifiedProperties(); + } + } +}
\ No newline at end of file diff --git a/Assets/Scripts/Editor/UIDissolveEditor.cs.meta b/Assets/Scripts/Editor/UIDissolveEditor.cs.meta new file mode 100644 index 0000000..edf071c --- /dev/null +++ b/Assets/Scripts/Editor/UIDissolveEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f7f7349a5d61649b69946853317db047 +timeCreated: 1538806040 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/UIEffect-Editor.asmdef b/Assets/Scripts/Editor/UIEffect-Editor.asmdef new file mode 100644 index 0000000..56826a0 --- /dev/null +++ b/Assets/Scripts/Editor/UIEffect-Editor.asmdef @@ -0,0 +1,16 @@ +{ + "name": "UIEffect-Editor", + "references": [ + "UIEffect" + ], + "optionalUnityReferences": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": false, + "defineConstraints": [] +}
\ No newline at end of file diff --git a/Assets/Scripts/Editor/UIEffect-Editor.asmdef.meta b/Assets/Scripts/Editor/UIEffect-Editor.asmdef.meta new file mode 100644 index 0000000..a459a69 --- /dev/null +++ b/Assets/Scripts/Editor/UIEffect-Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4a03bd468489b4da08c028255886b30d +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/UIEffectEditor.cs b/Assets/Scripts/Editor/UIEffectEditor.cs new file mode 100644 index 0000000..028ee73 --- /dev/null +++ b/Assets/Scripts/Editor/UIEffectEditor.cs @@ -0,0 +1,114 @@ +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; +using System.Linq; +using System; + +namespace Coffee.UIEffects.Editors +{ + /// <summary> + /// UIEffect editor. + /// </summary> + [CustomEditor(typeof(UIEffect))] + [CanEditMultipleObjects] + public class UIEffectEditor : Editor + { + SerializedProperty _spEffectMode; + SerializedProperty _spEffectFactor; + SerializedProperty _spColorMode; + SerializedProperty _spColorFactor; + SerializedProperty _spBlurMode; + SerializedProperty _spBlurFactor; + SerializedProperty _spAdvancedBlur; + + protected void OnEnable() + { + _spEffectMode = serializedObject.FindProperty("m_EffectMode"); + _spEffectFactor = serializedObject.FindProperty("m_EffectFactor"); + _spColorMode = serializedObject.FindProperty("m_ColorMode"); + _spColorFactor = serializedObject.FindProperty("m_ColorFactor"); + _spBlurMode = serializedObject.FindProperty("m_BlurMode"); + _spBlurFactor = serializedObject.FindProperty("m_BlurFactor"); + _spAdvancedBlur = serializedObject.FindProperty("m_AdvancedBlur"); + } + + public override void OnInspectorGUI() + { + //================ + // Effect setting. + //================ + using (new MaterialDirtyScope(targets)) + EditorGUILayout.PropertyField(_spEffectMode); + + // When effect is enable, show parameters. + if (_spEffectMode.intValue != (int) EffectMode.None) + { + EditorGUI.indentLevel++; + EditorGUILayout.PropertyField(_spEffectFactor); + EditorGUI.indentLevel--; + } + + + //================ + // Color setting. + //================ + using (new MaterialDirtyScope(targets)) + EditorGUILayout.PropertyField(_spColorMode); + + // When color is enable, show parameters. + { + EditorGUI.indentLevel++; + EditorGUILayout.PropertyField(_spColorFactor); + EditorGUI.indentLevel--; + } + + + //================ + // Blur setting. + //================ + using (new MaterialDirtyScope(targets)) + EditorGUILayout.PropertyField(_spBlurMode); + + // When blur is enable, show parameters. + if (_spBlurMode.intValue != (int) BlurMode.None) + { + EditorGUI.indentLevel++; + EditorGUILayout.PropertyField(_spBlurFactor); + + // When you change a property, it marks the material as dirty. + using (new MaterialDirtyScope(targets)) + EditorGUILayout.PropertyField(_spAdvancedBlur); + EditorGUI.indentLevel--; + + // Advanced blur requires uv2 channel. + if (_spAdvancedBlur.boolValue) + { + ShowCanvasChannelsWarning(); + } + } + + serializedObject.ApplyModifiedProperties(); + } + + void ShowCanvasChannelsWarning() + { + var effect = target as UIEffect; + if (effect == null || !effect.graphic) return; + + var channel = effect.uvMaskChannel; + var canvas = effect.graphic.canvas; + if (canvas == null || (canvas.additionalShaderChannels & channel) == channel) return; + + EditorGUILayout.BeginHorizontal(); + { + var msg = string.Format("Enable '{0}' of Canvas.additionalShaderChannels to use 'UIEffect'.", channel); + EditorGUILayout.HelpBox(msg, MessageType.Warning); + if (GUILayout.Button("Fix")) + { + canvas.additionalShaderChannels |= channel; + } + } + EditorGUILayout.EndHorizontal(); + } + } +} diff --git a/Assets/Scripts/Editor/UIEffectEditor.cs.meta b/Assets/Scripts/Editor/UIEffectEditor.cs.meta new file mode 100644 index 0000000..02aa24f --- /dev/null +++ b/Assets/Scripts/Editor/UIEffectEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4f7e9f2ce1cb543ca88606769affbe24 +timeCreated: 1487152293 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/UIGradientEditor.cs b/Assets/Scripts/Editor/UIGradientEditor.cs new file mode 100644 index 0000000..493c51d --- /dev/null +++ b/Assets/Scripts/Editor/UIGradientEditor.cs @@ -0,0 +1,140 @@ +using UnityEditor; +using UnityEngine; +using UnityEngine.UI; + +namespace Coffee.UIEffects.Editors +{ + /// <summary> + /// UIEffect editor. + /// </summary> + [CustomEditor(typeof(UIGradient))] + [CanEditMultipleObjects] + public class UIGradientEditor : Editor + { + private static readonly GUIContent k_TextVerticalOffset = new GUIContent("Vertical Offset"); + private static readonly GUIContent k_TextHorizontalOffset = new GUIContent("Horizontal Offset"); + private static readonly GUIContent k_TextOffset = new GUIContent("Offset"); + private static readonly GUIContent k_TextLeft = new GUIContent("Left"); + private static readonly GUIContent k_TextRight = new GUIContent("Right"); + private static readonly GUIContent k_TextTop = new GUIContent("Top"); + private static readonly GUIContent k_TextBottom = new GUIContent("Bottom"); + private static readonly GUIContent k_TextColor1 = new GUIContent("Color 1"); + private static readonly GUIContent k_TextColor2 = new GUIContent("Color 2"); + private static readonly GUIContent k_TextDiagonalColor = new GUIContent("Diagonal Color"); + + SerializedProperty _spDirection; + SerializedProperty _spColor1; + SerializedProperty _spColor2; + SerializedProperty _spColor3; + SerializedProperty _spColor4; + SerializedProperty _spRotation; + SerializedProperty _spOffset1; + SerializedProperty _spOffset2; + SerializedProperty _spIgnoreAspectRatio; + SerializedProperty _spGradientStyle; + SerializedProperty _spColorSpace; + + //################################ + // Public/Protected Members. + //################################ + /// <summary> + /// This function is called when the object becomes enabled and active. + /// </summary> + protected void OnEnable() + { + _spIgnoreAspectRatio = serializedObject.FindProperty("m_IgnoreAspectRatio"); + _spDirection = serializedObject.FindProperty("m_Direction"); + _spColor1 = serializedObject.FindProperty("m_Color1"); + _spColor2 = serializedObject.FindProperty("m_Color2"); + _spColor3 = serializedObject.FindProperty("m_Color3"); + _spColor4 = serializedObject.FindProperty("m_Color4"); + _spRotation = serializedObject.FindProperty("m_Rotation"); + _spOffset1 = serializedObject.FindProperty("m_Offset1"); + _spOffset2 = serializedObject.FindProperty("m_Offset2"); + _spGradientStyle = serializedObject.FindProperty("m_GradientStyle"); + _spColorSpace = serializedObject.FindProperty("m_ColorSpace"); + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + //================ + // Direction. + //================ + EditorGUILayout.PropertyField(_spDirection); + + + //================ + // Color. + //================ + switch ((UIGradient.Direction) _spDirection.intValue) + { + case UIGradient.Direction.Horizontal: + EditorGUILayout.PropertyField(_spColor1, k_TextLeft); + EditorGUILayout.PropertyField(_spColor2, k_TextRight); + break; + case UIGradient.Direction.Vertical: + EditorGUILayout.PropertyField(_spColor1, k_TextTop); + EditorGUILayout.PropertyField(_spColor2, k_TextBottom); + break; + case UIGradient.Direction.Angle: + EditorGUILayout.PropertyField(_spColor1, k_TextColor1); + EditorGUILayout.PropertyField(_spColor2, k_TextColor2); + break; + case UIGradient.Direction.Diagonal: + Rect r = EditorGUILayout.GetControlRect(false, 34); + + r = EditorGUI.PrefixLabel(r, k_TextDiagonalColor); + float w = r.width / 2; + + EditorGUI.PropertyField(new Rect(r.x, r.y, w, 16), _spColor3, GUIContent.none); + EditorGUI.PropertyField(new Rect(r.x + w, r.y, w, 16), _spColor4, GUIContent.none); + EditorGUI.PropertyField(new Rect(r.x, r.y + 18, w, 16), _spColor1, GUIContent.none); + EditorGUI.PropertyField(new Rect(r.x + w, r.y + 18, w, 16), _spColor2, GUIContent.none); + break; + } + + + //================ + // Angle. + //================ + if ((int) UIGradient.Direction.Angle <= _spDirection.intValue) + { + EditorGUILayout.PropertyField(_spRotation); + } + + + //================ + // Offset. + //================ + if ((int) UIGradient.Direction.Diagonal == _spDirection.intValue) + { + EditorGUILayout.PropertyField(_spOffset1, k_TextVerticalOffset); + EditorGUILayout.PropertyField(_spOffset2, k_TextHorizontalOffset); + } + else + { + EditorGUILayout.PropertyField(_spOffset1, k_TextOffset); + } + + + //================ + // Advanced options. + //================ + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Advanced Options", EditorStyles.boldLabel); + EditorGUI.indentLevel++; + { + //if ((target as UIGradient).targetGraphic is Text) + EditorGUILayout.PropertyField(_spGradientStyle); + + EditorGUILayout.PropertyField(_spColorSpace); + EditorGUILayout.PropertyField(_spIgnoreAspectRatio); + } + EditorGUI.indentLevel--; + + serializedObject.ApplyModifiedProperties(); + } + } +}
\ No newline at end of file diff --git a/Assets/Scripts/Editor/UIGradientEditor.cs.meta b/Assets/Scripts/Editor/UIGradientEditor.cs.meta new file mode 100644 index 0000000..5070c14 --- /dev/null +++ b/Assets/Scripts/Editor/UIGradientEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c28dcc885fbba4a5187a6a1aa5fb1b3b +timeCreated: 1515895646 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/UIHsvModifierEditor.cs b/Assets/Scripts/Editor/UIHsvModifierEditor.cs new file mode 100644 index 0000000..6d54a55 --- /dev/null +++ b/Assets/Scripts/Editor/UIHsvModifierEditor.cs @@ -0,0 +1,53 @@ +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; +using System.Linq; + +namespace Coffee.UIEffects.Editors +{ + /// <summary> + /// UIEffect editor. + /// </summary> + [CustomEditor(typeof(UIHsvModifier))] + [CanEditMultipleObjects] + public class UIHsvModifierEditor : Editor + { + SerializedProperty _spTargetColor; + SerializedProperty _spRange; + SerializedProperty _spHue; + SerializedProperty _spSaturation; + SerializedProperty _spValue; + + /// <summary> + /// This function is called when the object becomes enabled and active. + /// </summary> + protected void OnEnable() + { + _spTargetColor = serializedObject.FindProperty("m_TargetColor"); + _spRange = serializedObject.FindProperty("m_Range"); + _spHue = serializedObject.FindProperty("m_Hue"); + _spSaturation = serializedObject.FindProperty("m_Saturation"); + _spValue = serializedObject.FindProperty("m_Value"); + } + + + /// <summary> + /// Implement this function to make a custom inspector. + /// </summary> + public override void OnInspectorGUI() + { + serializedObject.Update(); + + //================ + // Effect setting. + //================ + EditorGUILayout.PropertyField(_spTargetColor); + EditorGUILayout.PropertyField(_spRange); + EditorGUILayout.PropertyField(_spHue); + EditorGUILayout.PropertyField(_spSaturation); + EditorGUILayout.PropertyField(_spValue); + + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Assets/Scripts/Editor/UIHsvModifierEditor.cs.meta b/Assets/Scripts/Editor/UIHsvModifierEditor.cs.meta new file mode 100644 index 0000000..87f1694 --- /dev/null +++ b/Assets/Scripts/Editor/UIHsvModifierEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f002ba0ac474d487b936bc046dda56b4 +timeCreated: 1538806052 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/UIShadowEditor.cs b/Assets/Scripts/Editor/UIShadowEditor.cs new file mode 100644 index 0000000..64f01d6 --- /dev/null +++ b/Assets/Scripts/Editor/UIShadowEditor.cs @@ -0,0 +1,62 @@ +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; + +namespace Coffee.UIEffects.Editors +{ + /// <summary> + /// UIShadow editor. + /// </summary> + [CustomEditor(typeof(UIShadow))] + [CanEditMultipleObjects] + public class UIShadowEditor : Editor + { + UIEffect uiEffect; + SerializedProperty _spStyle; + SerializedProperty _spEffectDistance; + SerializedProperty _spEffectColor; + SerializedProperty _spUseGraphicAlpha; + SerializedProperty _spBlurFactor; + + void OnEnable() + { + uiEffect = (target as UIShadow).GetComponent<UIEffect>(); + _spStyle = serializedObject.FindProperty("m_Style"); + _spEffectDistance = serializedObject.FindProperty("m_EffectDistance"); + _spEffectColor = serializedObject.FindProperty("m_EffectColor"); + _spUseGraphicAlpha = serializedObject.FindProperty("m_UseGraphicAlpha"); + _spBlurFactor = serializedObject.FindProperty("m_BlurFactor"); + } + + /// <summary> + /// Implement this function to make a custom inspector. + /// </summary> + public override void OnInspectorGUI() + { + serializedObject.Update(); + + //================ + // Shadow setting. + //================ + EditorGUILayout.PropertyField(_spStyle); + + // When shadow is enable, show parameters. + if (_spStyle.intValue != (int) ShadowStyle.None) + { + EditorGUI.indentLevel++; + EditorGUILayout.PropertyField(_spEffectDistance); + EditorGUILayout.PropertyField(_spEffectColor); + EditorGUILayout.PropertyField(_spUseGraphicAlpha); + + if (uiEffect && uiEffect.blurMode != BlurMode.None) + { + EditorGUILayout.PropertyField(_spBlurFactor); + } + + EditorGUI.indentLevel--; + } + + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Assets/Scripts/Editor/UIShadowEditor.cs.meta b/Assets/Scripts/Editor/UIShadowEditor.cs.meta new file mode 100644 index 0000000..bc6a832 --- /dev/null +++ b/Assets/Scripts/Editor/UIShadowEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6e76e7f628f09af449321b4776123f13 +timeCreated: 1487152293 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/UIShinyEditor.cs b/Assets/Scripts/Editor/UIShinyEditor.cs new file mode 100644 index 0000000..e77432a --- /dev/null +++ b/Assets/Scripts/Editor/UIShinyEditor.cs @@ -0,0 +1,102 @@ +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; +using System.Linq; + +namespace Coffee.UIEffects.Editors +{ + /// <summary> + /// UIEffect editor. + /// </summary> + [CustomEditor(typeof(UIShiny))] + [CanEditMultipleObjects] + public class UIShinyEditor : Editor + { + SerializedProperty _spEffectFactor; + SerializedProperty _spWidth; + SerializedProperty _spRotation; + SerializedProperty _spSoftness; + SerializedProperty _spBrightness; + SerializedProperty _spGloss; + SerializedProperty _spEffectArea; + SerializedProperty _spPlay; + SerializedProperty _spLoop; + SerializedProperty _spLoopDelay; + SerializedProperty _spDuration; + SerializedProperty _spInitialPlayDelay; + SerializedProperty _spUpdateMode; + + /// <summary> + /// This function is called when the object becomes enabled and active. + /// </summary> + protected void OnEnable() + { + _spEffectFactor = serializedObject.FindProperty("m_EffectFactor"); + _spEffectArea = serializedObject.FindProperty("m_EffectArea"); + _spWidth = serializedObject.FindProperty("m_Width"); + _spRotation = serializedObject.FindProperty("m_Rotation"); + _spSoftness = serializedObject.FindProperty("m_Softness"); + _spBrightness = serializedObject.FindProperty("m_Brightness"); + _spGloss = serializedObject.FindProperty("m_Gloss"); + var player = serializedObject.FindProperty("m_Player"); + _spPlay = player.FindPropertyRelative("play"); + _spDuration = player.FindPropertyRelative("duration"); + _spInitialPlayDelay = player.FindPropertyRelative("initialPlayDelay"); + _spLoop = player.FindPropertyRelative("loop"); + _spLoopDelay = player.FindPropertyRelative("loopDelay"); + _spUpdateMode = player.FindPropertyRelative("updateMode"); + } + + /// <summary> + /// Implement this function to make a custom inspector. + /// </summary> + public override void OnInspectorGUI() + { + serializedObject.Update(); + + //================ + // Effect setting. + //================ + EditorGUILayout.PropertyField(_spEffectFactor); + EditorGUILayout.PropertyField(_spWidth); + EditorGUILayout.PropertyField(_spRotation); + EditorGUILayout.PropertyField(_spSoftness); + EditorGUILayout.PropertyField(_spBrightness); + EditorGUILayout.PropertyField(_spGloss); + + //================ + // Advanced option. + //================ + EditorGUILayout.PropertyField(_spEffectArea); + + //================ + // Effect player. + //================ + EditorGUILayout.PropertyField(_spPlay); + EditorGUILayout.PropertyField(_spDuration); + EditorGUILayout.PropertyField(_spInitialPlayDelay); + EditorGUILayout.PropertyField(_spLoop); + EditorGUILayout.PropertyField(_spLoopDelay); + EditorGUILayout.PropertyField(_spUpdateMode); + + // Debug. + using (new EditorGUI.DisabledGroupScope(!Application.isPlaying)) + using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox)) + { + GUILayout.Label("Debug"); + + if (GUILayout.Button("Play", "ButtonLeft")) + { + (target as UIShiny).Play(); + } + + if (GUILayout.Button("Stop", "ButtonRight")) + { + (target as UIShiny).Stop(); + } + } + + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Assets/Scripts/Editor/UIShinyEditor.cs.meta b/Assets/Scripts/Editor/UIShinyEditor.cs.meta new file mode 100644 index 0000000..7dd653a --- /dev/null +++ b/Assets/Scripts/Editor/UIShinyEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0080e984bad7545cd957d9121e99f988 +timeCreated: 1538806052 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/UITransitionEffectEditor.cs b/Assets/Scripts/Editor/UITransitionEffectEditor.cs new file mode 100644 index 0000000..803c9bf --- /dev/null +++ b/Assets/Scripts/Editor/UITransitionEffectEditor.cs @@ -0,0 +1,115 @@ +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; +using System.Linq; + +namespace Coffee.UIEffects.Editors +{ + /// <summary> + /// UIEffect editor. + /// </summary> + [CustomEditor(typeof(UITransitionEffect))] + [CanEditMultipleObjects] + public class UITransitionEffectEditor : Editor + { + SerializedProperty _spEffectMode; + SerializedProperty _spEffectFactor; + SerializedProperty _spEffectArea; + SerializedProperty _spKeepAspectRatio; + SerializedProperty _spDissolveWidth; + SerializedProperty _spDissolveSoftness; + SerializedProperty _spDissolveColor; + SerializedProperty _spTransitionTexture; + SerializedProperty _spPlay; + SerializedProperty _spLoop; + SerializedProperty _spLoopDelay; + SerializedProperty _spDuration; + SerializedProperty _spInitialPlayDelay; + SerializedProperty _spUpdateMode; + SerializedProperty _spPassRayOnHidden; + + /// <summary> + /// This function is called when the object becomes enabled and active. + /// </summary> + protected void OnEnable() + { + _spEffectMode = serializedObject.FindProperty("m_EffectMode"); + _spEffectFactor = serializedObject.FindProperty("m_EffectFactor"); + _spEffectArea = serializedObject.FindProperty("m_EffectArea"); + _spKeepAspectRatio = serializedObject.FindProperty("m_KeepAspectRatio"); + _spDissolveWidth = serializedObject.FindProperty("m_DissolveWidth"); + _spDissolveSoftness = serializedObject.FindProperty("m_DissolveSoftness"); + _spDissolveColor = serializedObject.FindProperty("m_DissolveColor"); + _spTransitionTexture = serializedObject.FindProperty("m_TransitionTexture"); + var player = serializedObject.FindProperty("m_Player"); + _spPlay = player.FindPropertyRelative("play"); + _spDuration = player.FindPropertyRelative("duration"); + _spInitialPlayDelay = player.FindPropertyRelative("initialPlayDelay"); + _spLoop = player.FindPropertyRelative("loop"); + _spLoopDelay = player.FindPropertyRelative("loopDelay"); + _spUpdateMode = player.FindPropertyRelative("updateMode"); + _spPassRayOnHidden = serializedObject.FindProperty("m_PassRayOnHidden"); + } + + /// <summary> + /// Implement this function to make a custom inspector. + /// </summary> + public override void OnInspectorGUI() + { + //================ + // Effect setting. + //================ + using (new MaterialDirtyScope(targets)) + EditorGUILayout.PropertyField(_spEffectMode); + + EditorGUI.indentLevel++; + EditorGUILayout.PropertyField(_spEffectFactor); + if (_spEffectMode.intValue == (int) UITransitionEffect.EffectMode.Dissolve) + { + EditorGUILayout.PropertyField(_spDissolveWidth); + EditorGUILayout.PropertyField(_spDissolveSoftness); + EditorGUILayout.PropertyField(_spDissolveColor); + } + + EditorGUI.indentLevel--; + + //================ + // Advanced option. + //================ + EditorGUILayout.PropertyField(_spEffectArea); + using (new MaterialDirtyScope(targets)) + EditorGUILayout.PropertyField(_spTransitionTexture); + EditorGUILayout.PropertyField(_spKeepAspectRatio); + EditorGUILayout.PropertyField(_spPassRayOnHidden); + + //================ + // Effect player. + //================ + EditorGUILayout.PropertyField(_spPlay); + EditorGUILayout.PropertyField(_spDuration); + EditorGUILayout.PropertyField(_spInitialPlayDelay); + EditorGUILayout.PropertyField(_spLoop); + EditorGUILayout.PropertyField(_spLoopDelay); + EditorGUILayout.PropertyField(_spUpdateMode); + + // Debug. + using (new EditorGUI.DisabledGroupScope(!Application.isPlaying)) + using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox)) + { + GUILayout.Label("Debug"); + + if (GUILayout.Button("Show", "ButtonLeft")) + { + (target as UITransitionEffect).Show(); + } + + if (GUILayout.Button("Hide", "ButtonRight")) + { + (target as UITransitionEffect).Hide(); + } + } + + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Assets/Scripts/Editor/UITransitionEffectEditor.cs.meta b/Assets/Scripts/Editor/UITransitionEffectEditor.cs.meta new file mode 100644 index 0000000..14054f8 --- /dev/null +++ b/Assets/Scripts/Editor/UITransitionEffectEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 631f363a54c834f1f846f823b31bd321 +timeCreated: 1538806067 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enums.meta b/Assets/Scripts/Enums.meta new file mode 100644 index 0000000..d1a3a2a --- /dev/null +++ b/Assets/Scripts/Enums.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 78cc1478fd16a484ba11857d5c4f4912 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enums/BlurMode.cs b/Assets/Scripts/Enums/BlurMode.cs new file mode 100644 index 0000000..e3ef417 --- /dev/null +++ b/Assets/Scripts/Enums/BlurMode.cs @@ -0,0 +1,13 @@ +namespace Coffee.UIEffects +{ + /// <summary> + /// Blur effect mode. + /// </summary> + public enum BlurMode + { + None = 0, + FastBlur = 1, + MediumBlur = 2, + DetailBlur = 3, + } +} diff --git a/Assets/Scripts/Enums/BlurMode.cs.meta b/Assets/Scripts/Enums/BlurMode.cs.meta new file mode 100644 index 0000000..504b62a --- /dev/null +++ b/Assets/Scripts/Enums/BlurMode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5645838b01af8764d8f381f04b62b9a2 +timeCreated: 1528296875 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enums/ColorMode.cs b/Assets/Scripts/Enums/ColorMode.cs new file mode 100644 index 0000000..567624b --- /dev/null +++ b/Assets/Scripts/Enums/ColorMode.cs @@ -0,0 +1,13 @@ +namespace Coffee.UIEffects +{ + /// <summary> + /// Color effect mode. + /// </summary> + public enum ColorMode + { + Multiply = 0, + Fill = 1, + Add = 2, + Subtract = 3, + } +} diff --git a/Assets/Scripts/Enums/ColorMode.cs.meta b/Assets/Scripts/Enums/ColorMode.cs.meta new file mode 100644 index 0000000..ba60cab --- /dev/null +++ b/Assets/Scripts/Enums/ColorMode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e6ba1e487e0a19644afde2bd5531bd04 +timeCreated: 1528296875 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enums/EffectArea.cs b/Assets/Scripts/Enums/EffectArea.cs new file mode 100644 index 0000000..4e5fa28 --- /dev/null +++ b/Assets/Scripts/Enums/EffectArea.cs @@ -0,0 +1,116 @@ +using UnityEngine; +using UnityEngine.UI; + +namespace Coffee.UIEffects +{ + /// <summary> + /// Area for effect. + /// </summary> + public enum EffectArea + { + RectTransform, + Fit, + Character, + } + + public static class EffectAreaExtensions + { + static readonly Rect rectForCharacter = new Rect(0, 0, 1, 1); + static readonly Vector2[] splitedCharacterPosition = {Vector2.up, Vector2.one, Vector2.right, Vector2.zero}; + + /// <summary> + /// Gets effect for area. + /// </summary> + public static Rect GetEffectArea(this EffectArea area, VertexHelper vh, Rect rectangle, float aspectRatio = -1) + { + Rect rect = default(Rect); + switch (area) + { + case EffectArea.RectTransform: + rect = rectangle; + break; + case EffectArea.Character: + rect = rectForCharacter; + break; + case EffectArea.Fit: + // Fit to contents. + UIVertex vertex = default(UIVertex); + float xMin = float.MaxValue; + float yMin = float.MaxValue; + float xMax = float.MinValue; + float yMax = float.MinValue; + for (int i = 0; i < vh.currentVertCount; i++) + { + vh.PopulateUIVertex(ref vertex, i); + float x = vertex.position.x; + float y = vertex.position.y; + xMin = Mathf.Min(xMin, x); + yMin = Mathf.Min(yMin, y); + xMax = Mathf.Max(xMax, x); + yMax = Mathf.Max(yMax, y); + } + + rect.Set(xMin, yMin, xMax - xMin, yMax - yMin); + break; + default: + rect = rectangle; + break; + } + + + if (0 < aspectRatio) + { + if (rect.width < rect.height) + { + rect.width = rect.height * aspectRatio; + } + else + { + rect.height = rect.width / aspectRatio; + } + } + + return rect; + } + + /// <summary> + /// Gets position factor for area. + /// </summary> + public static void GetPositionFactor(this EffectArea area, int index, Rect rect, Vector2 position, bool isText, + bool isTMPro, out float x, out float y) + { + if (isText && area == EffectArea.Character) + { + index = isTMPro ? (index + 3) % 4 : index % 4; + x = splitedCharacterPosition[index].x; + y = splitedCharacterPosition[index].y; + } + else 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); + } + } + + /// <summary> + /// Normalize vertex position by local matrix. + /// </summary> + public static void GetNormalizedFactor(this EffectArea area, int index, Matrix2x3 matrix, Vector2 position, + bool isText, out Vector2 nomalizedPos) + { + if (isText && area == EffectArea.Character) + { + nomalizedPos = matrix * splitedCharacterPosition[(index + 3) % 4]; + } + else + { + nomalizedPos = matrix * position; + } + } + } +} diff --git a/Assets/Scripts/Enums/EffectArea.cs.meta b/Assets/Scripts/Enums/EffectArea.cs.meta new file mode 100644 index 0000000..4bc2fa4 --- /dev/null +++ b/Assets/Scripts/Enums/EffectArea.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a78f43d1382a048a99411472ca714e1b +timeCreated: 1528636556 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enums/EffectMode.cs b/Assets/Scripts/Enums/EffectMode.cs new file mode 100644 index 0000000..84f3eb4 --- /dev/null +++ b/Assets/Scripts/Enums/EffectMode.cs @@ -0,0 +1,14 @@ +namespace Coffee.UIEffects +{ + /// <summary> + /// Effect mode. + /// </summary> + public enum EffectMode + { + None = 0, + Grayscale = 1, + Sepia = 2, + Nega = 3, + Pixel = 4, + } +} diff --git a/Assets/Scripts/Enums/EffectMode.cs.meta b/Assets/Scripts/Enums/EffectMode.cs.meta new file mode 100644 index 0000000..76773db --- /dev/null +++ b/Assets/Scripts/Enums/EffectMode.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 092769547c242d74cbad96631a00963f +timeCreated: 1528296875 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Enums/ShadowStyle.cs b/Assets/Scripts/Enums/ShadowStyle.cs new file mode 100644 index 0000000..1cfe058 --- /dev/null +++ b/Assets/Scripts/Enums/ShadowStyle.cs @@ -0,0 +1,14 @@ +namespace Coffee.UIEffects +{ + /// <summary> + /// Shadow effect style. + /// </summary> + public enum ShadowStyle + { + None = 0, + Shadow, + Outline, + Outline8, + Shadow3, + } +} diff --git a/Assets/Scripts/Enums/ShadowStyle.cs.meta b/Assets/Scripts/Enums/ShadowStyle.cs.meta new file mode 100644 index 0000000..337e823 --- /dev/null +++ b/Assets/Scripts/Enums/ShadowStyle.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b0eda5bf10146491c9cfe6a31c66f9a7 +timeCreated: 1528296875 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UIDissolve.cs b/Assets/Scripts/UIDissolve.cs new file mode 100644 index 0000000..de49ef2 --- /dev/null +++ b/Assets/Scripts/UIDissolve.cs @@ -0,0 +1,319 @@ +using System; +using UnityEngine; +using UnityEditor; +using UnityEngine.UI; +using UnityEngine.Serialization; +using System.Text; +using System.Linq; +using System.IO; + +namespace Coffee.UIEffects +{ + /// <summary> + /// Dissolve effect for uGUI. + /// </summary> + [AddComponentMenu("UI/UIEffects/UIDissolve", 3)] + public class UIDissolve : BaseMaterialEffect, IMaterialModifier + { + private const uint k_ShaderId = 0 << 3; + private static readonly ParameterTexture s_ParamTex = new ParameterTexture(8, 128, "_ParamTex"); + private static readonly int k_TransitionTexId = Shader.PropertyToID("_TransitionTex"); + + private bool _lastKeepAspectRatio; + private EffectArea _lastEffectArea; + private static Texture _defaultTransitionTexture; + + [Tooltip("Current location[0-1] for dissolve effect. 0 is not dissolved, 1 is completely dissolved.")] + [FormerlySerializedAs("m_Location")] + [SerializeField] + [Range(0, 1)] + float m_EffectFactor = 0.5f; + + [Tooltip("Edge width.")] [SerializeField] [Range(0, 1)] + float m_Width = 0.5f; + + [Tooltip("Edge softness.")] [SerializeField] [Range(0, 1)] + float m_Softness = 0.5f; + + [Tooltip("Edge color.")] [SerializeField] [ColorUsage(false)] + Color m_Color = new Color(0.0f, 0.25f, 1.0f); + + [Tooltip("Edge color effect mode.")] [SerializeField] + ColorMode m_ColorMode = ColorMode.Add; + + [Tooltip("Noise texture for dissolving (single channel texture).")] + [SerializeField] + [FormerlySerializedAs("m_NoiseTexture")] + Texture m_TransitionTexture; + + [Header("Advanced Option")] [Tooltip("The area for effect.")] [SerializeField] + protected EffectArea m_EffectArea; + + [Tooltip("Keep effect aspect ratio.")] [SerializeField] + bool m_KeepAspectRatio; + + [Header("Effect Player")] [SerializeField] + EffectPlayer m_Player; + + [Tooltip("Reverse the dissolve effect.")] [FormerlySerializedAs("m_ReverseAnimation")] [SerializeField] + bool m_Reverse = false; + + /// <summary> + /// Effect factor between 0(start) and 1(end). + /// </summary> + 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(); + } + } + + /// <summary> + /// Edge width. + /// </summary> + 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(); + } + } + + /// <summary> + /// Edge softness. + /// </summary> + public float softness + { + get { return m_Softness; } + set + { + value = Mathf.Clamp(value, 0, 1); + if (Mathf.Approximately(m_Softness, value)) return; + m_Softness = value; + SetEffectParamsDirty(); + } + } + + /// <summary> + /// Edge color. + /// </summary> + public Color color + { + get { return m_Color; } + set + { + if (m_Color == value) return; + m_Color = value; + SetEffectParamsDirty(); + } + } + + /// <summary> + /// Noise texture. + /// </summary> + public Texture transitionTexture + { + get + { + return m_TransitionTexture + ? m_TransitionTexture + : defaultTransitionTexture; + } + set + { + if (m_TransitionTexture == value) return; + m_TransitionTexture = value; + SetMaterialDirty(); + } + } + + private static Texture defaultTransitionTexture + { + get + { + return _defaultTransitionTexture + ? _defaultTransitionTexture + : (_defaultTransitionTexture = Resources.Load<Texture>("Default-Transition")); + } + } + + /// <summary> + /// The area for effect. + /// </summary> + public EffectArea effectArea + { + get { return m_EffectArea; } + set + { + if (m_EffectArea == value) return; + m_EffectArea = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Keep aspect ratio. + /// </summary> + public bool keepAspectRatio + { + get { return m_KeepAspectRatio; } + set + { + if (m_KeepAspectRatio == value) return; + m_KeepAspectRatio = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Color effect mode. + /// </summary> + public ColorMode colorMode + { + get { return m_ColorMode; } + set + { + if (m_ColorMode == value) return; + m_ColorMode = value; + SetMaterialDirty(); + } + } + + /// <summary> + /// Gets the parameter texture. + /// </summary> + public override ParameterTexture paramTex + { + get { return s_ParamTex; } + } + + public EffectPlayer effectPlayer + { + get { return m_Player ?? (m_Player = new EffectPlayer()); } + } + + public override Hash128 GetMaterialHash(Material material) + { + if (!isActiveAndEnabled || !material || !material.shader) + return k_InvalidHash; + + var shaderVariantId = (uint) ((int) m_ColorMode << 6); + var resourceId = (uint) transitionTexture.GetInstanceID(); + return new Hash128( + (uint) material.GetInstanceID(), + k_ShaderId + shaderVariantId, + resourceId, + 0 + ); + } + + public override void ModifyMaterial(Material newMaterial, Graphic graphic) + { + var connector = GraphicConnector.FindConnector(graphic); + newMaterial.shader = Shader.Find(string.Format("Hidden/{0} (UIDissolve)", newMaterial.shader.name)); + SetShaderVariants(newMaterial, m_ColorMode); + + newMaterial.SetTexture(k_TransitionTexId, transitionTexture); + paramTex.RegisterMaterial(newMaterial); + } + + /// <summary> + /// Modifies the mesh. + /// </summary> + public override void ModifyMesh(VertexHelper vh, Graphic graphic) + { + if (!isActiveAndEnabled) + return; + + // bool isText = isTMPro || graphic is Text; + var normalizedIndex = paramTex.GetNormalizedIndex(this); + + // rect. + var tex = transitionTexture; + var aspectRatio = m_KeepAspectRatio && tex ? ((float) tex.width) / tex.height : -1; + var rect = m_EffectArea.GetEffectArea(vh, rectTransform.rect, aspectRatio); + + // Calculate vertex position. + var vertex = default(UIVertex); + var count = vh.currentVertCount; + for (var i = 0; i < count; i++) + { + vh.PopulateUIVertex(ref vertex, i); + float x; + float y; + connector.GetPositionFactor(m_EffectArea, i, rect, vertex.position, out x, out y); + + vertex.uv0 = new Vector2( + Packer.ToFloat(vertex.uv0.x, vertex.uv0.y), + Packer.ToFloat(x, y, normalizedIndex) + ); + + vh.SetUIVertex(vertex, i); + } + } + + 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, 4, m_Color.r); // param2.x : red + paramTex.SetData(this, 5, m_Color.g); // param2.y : green + paramTex.SetData(this, 6, m_Color.b); // param2.z : blue + } + + protected override void SetVerticesDirty() + { + base.SetVerticesDirty(); + + _lastKeepAspectRatio = m_KeepAspectRatio; + _lastEffectArea = m_EffectArea; + } + + protected override void OnDidApplyAnimationProperties() + { + base.OnDidApplyAnimationProperties(); + + if (_lastKeepAspectRatio != m_KeepAspectRatio + || _lastEffectArea != m_EffectArea) + SetVerticesDirty(); + } + + /// <summary> + /// Play effect. + /// </summary> + public void Play(bool reset = true) + { + effectPlayer.Play(reset); + } + + /// <summary> + /// Stop effect. + /// </summary> + public void Stop(bool reset = true) + { + effectPlayer.Stop(reset); + } + + protected override void OnEnable() + { + base.OnEnable(); + effectPlayer.OnEnable((f) => effectFactor = m_Reverse ? 1f - f : f); + } + + protected override void OnDisable() + { + base.OnDisable(); + effectPlayer.OnDisable(); + } + } +} diff --git a/Assets/Scripts/UIDissolve.cs.meta b/Assets/Scripts/UIDissolve.cs.meta new file mode 100644 index 0000000..80d3101 --- /dev/null +++ b/Assets/Scripts/UIDissolve.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: ce76b7a490bd74f34a2f2752641aea24 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: + - m_TransitionTexture: {fileID: 2800000, guid: 3e04c247fb2604af186173fce0bc62de, + type: 3} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UIEffect.asmdef b/Assets/Scripts/UIEffect.asmdef new file mode 100644 index 0000000..2b24b63 --- /dev/null +++ b/Assets/Scripts/UIEffect.asmdef @@ -0,0 +1,3 @@ +{ + "name": "UIEffect" +} diff --git a/Assets/Scripts/UIEffect.asmdef.meta b/Assets/Scripts/UIEffect.asmdef.meta new file mode 100644 index 0000000..e73ac6b --- /dev/null +++ b/Assets/Scripts/UIEffect.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 735c8f008d0ad4caa9cdc4306f1c3042 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UIEffect.cs b/Assets/Scripts/UIEffect.cs new file mode 100644 index 0000000..63a8ccc --- /dev/null +++ b/Assets/Scripts/UIEffect.cs @@ -0,0 +1,368 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; +using UnityEngine.Serialization; +#if UNITY_EDITOR +using System.IO; +using System.Linq; +using UnityEditor; + +#endif + +namespace Coffee.UIEffects +{ + /// <summary> + /// UIEffect. + /// </summary> + [ExecuteInEditMode] + [RequireComponent(typeof(Graphic))] + [DisallowMultipleComponent] + [AddComponentMenu("UI/UIEffects/UIEffect", 1)] + public class UIEffect : BaseMaterialEffect, IMaterialModifier + { + private const uint k_ShaderId = 2 << 3; + private static readonly ParameterTexture s_ParamTex = new ParameterTexture(4, 1024, "_ParamTex"); + + [FormerlySerializedAs("m_ToneLevel")] + [Tooltip("Effect factor between 0(no effect) and 1(complete effect).")] + [SerializeField] + [Range(0, 1)] + float m_EffectFactor = 1; + + [Tooltip("Color effect factor between 0(no effect) and 1(complete effect).")] [SerializeField] [Range(0, 1)] + float m_ColorFactor = 1; + + [FormerlySerializedAs("m_Blur")] + [Tooltip("How far is the blurring from the graphic.")] + [SerializeField] + [Range(0, 1)] + float m_BlurFactor = 1; + + [FormerlySerializedAs("m_ToneMode")] [Tooltip("Effect mode")] [SerializeField] + EffectMode m_EffectMode = EffectMode.None; + + [Tooltip("Color effect mode")] [SerializeField] + ColorMode m_ColorMode = ColorMode.Multiply; + + [Tooltip("Blur effect mode")] [SerializeField] + BlurMode m_BlurMode = BlurMode.None; + + [Tooltip("Advanced blurring remove common artifacts in the blur effect for uGUI.")] [SerializeField] + bool m_AdvancedBlur = false; + + private enum BlurEx + { + None = 0, + Ex = 1, + } + + /// <summary> + /// Additional canvas shader channels to use this component. + /// </summary> + public AdditionalCanvasShaderChannels uvMaskChannel + { + get { return connector.extraChannel; } + } + + /// <summary> + /// Effect factor between 0(no effect) and 1(complete effect). + /// </summary> + 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(); + } + } + + /// <summary> + /// Color effect factor between 0(no effect) and 1(complete effect). + /// </summary> + public float colorFactor + { + get { return m_ColorFactor; } + set + { + value = Mathf.Clamp(value, 0, 1); + if (Mathf.Approximately(m_ColorFactor, value)) return; + m_ColorFactor = value; + SetEffectParamsDirty(); + } + } + + /// <summary> + /// How far is the blurring from the graphic. + /// </summary> + public float blurFactor + { + get { return m_BlurFactor; } + set + { + value = Mathf.Clamp(value, 0, 1); + if (Mathf.Approximately(m_BlurFactor, value)) return; + m_BlurFactor = value; + SetEffectParamsDirty(); + } + } + + /// <summary> + /// Effect mode. + /// </summary> + public EffectMode effectMode + { + get { return m_EffectMode; } + set + { + if (m_EffectMode == value) return; + m_EffectMode = value; + SetMaterialDirty(); + } + } + + /// <summary> + /// Color effect mode. + /// </summary> + public ColorMode colorMode + { + get { return m_ColorMode; } + set + { + if (m_ColorMode == value) return; + m_ColorMode = value; + SetMaterialDirty(); + } + } + + /// <summary> + /// Blur effect mode(readonly). + /// </summary> + public BlurMode blurMode + { + get { return m_BlurMode; } + set + { + if (m_BlurMode == value) return; + m_BlurMode = value; + SetMaterialDirty(); + } + } + + /// <summary> + /// Gets the parameter texture. + /// </summary> + public override ParameterTexture paramTex + { + get { return s_ParamTex; } + } + + /// <summary> + /// Advanced blurring remove common artifacts in the blur effect for uGUI. + /// </summary> + public bool advancedBlur + { + get { return m_AdvancedBlur; } + set + { + if (m_AdvancedBlur == value) return; + m_AdvancedBlur = value; + SetVerticesDirty(); + SetMaterialDirty(); + } + } + + public override Hash128 GetMaterialHash(Material material) + { + if (!isActiveAndEnabled || !material || !material.shader) + return k_InvalidHash; + + var shaderVariantId = (uint) (((int) m_EffectMode << 6) + ((int) m_ColorMode << 9) + + ((int) m_BlurMode << 11) + ((m_AdvancedBlur ? 1 : 0) << 13)); + return new Hash128( + (uint) material.GetInstanceID(), + k_ShaderId + shaderVariantId, + 0, + 0 + ); + } + + public override void ModifyMaterial(Material newMaterial, Graphic graphic) + { + var connector = GraphicConnector.FindConnector(graphic); + + newMaterial.shader = Shader.Find(string.Format("Hidden/{0} (UIEffect)", newMaterial.shader.name)); + SetShaderVariants(newMaterial, m_EffectMode, m_ColorMode, m_BlurMode, + m_AdvancedBlur ? BlurEx.Ex : BlurEx.None); + + paramTex.RegisterMaterial(newMaterial); + } + + /// <summary> + /// Modifies the mesh. + /// </summary> + public override void ModifyMesh(VertexHelper vh, Graphic graphic) + { + if (!isActiveAndEnabled) + { + return; + } + + var normalizedIndex = paramTex.GetNormalizedIndex(this); + + if (m_BlurMode != BlurMode.None && advancedBlur) + { + vh.GetUIVertexStream(s_TempVerts); + vh.Clear(); + var count = s_TempVerts.Count; + + // Bundle + int bundleSize = connector.IsText(graphic) ? 6 : count; + Rect posBounds = default(Rect); + Rect uvBounds = default(Rect); + Vector3 size = default(Vector3); + Vector3 tPos = default(Vector3); + Vector3 tUV = default(Vector3); + float expand = (float) blurMode * 6 * 2; + + for (int i = 0; i < count; i += bundleSize) + { + // min/max for bundled-quad + GetBounds(s_TempVerts, i, bundleSize, ref posBounds, ref uvBounds, true); + + // Pack uv mask. + Vector2 uvMask = new Vector2(Packer.ToFloat(uvBounds.xMin, uvBounds.yMin), + Packer.ToFloat(uvBounds.xMax, uvBounds.yMax)); + + // Quad + for (int j = 0; j < bundleSize; j += 6) + { + Vector3 cornerPos1 = s_TempVerts[i + j + 1].position; + Vector3 cornerPos2 = s_TempVerts[i + j + 4].position; + + // Is outer quad? + bool hasOuterEdge = (bundleSize == 6) + || !posBounds.Contains(cornerPos1) + || !posBounds.Contains(cornerPos2); + if (hasOuterEdge) + { + Vector3 cornerUv1 = s_TempVerts[i + j + 1].uv0; + Vector3 cornerUv2 = s_TempVerts[i + j + 4].uv0; + + Vector3 centerPos = (cornerPos1 + cornerPos2) / 2; + Vector3 centerUV = (cornerUv1 + cornerUv2) / 2; + size = (cornerPos1 - cornerPos2); + + size.x = 1 + expand / Mathf.Abs(size.x); + size.y = 1 + expand / Mathf.Abs(size.y); + size.z = 1 + expand / Mathf.Abs(size.z); + + tPos = centerPos - Vector3.Scale(size, centerPos); + tUV = centerUV - Vector3.Scale(size, centerUV); + } + + // Vertex + for (int k = 0; k < 6; k++) + { + UIVertex vt = s_TempVerts[i + j + k]; + + Vector3 pos = vt.position; + Vector2 uv0 = vt.uv0; + + if (hasOuterEdge && (pos.x < posBounds.xMin || posBounds.xMax < pos.x)) + { + pos.x = pos.x * size.x + tPos.x; + uv0.x = uv0.x * size.x + tUV.x; + } + + if (hasOuterEdge && (pos.y < posBounds.yMin || posBounds.yMax < pos.y)) + { + pos.y = pos.y * size.y + tPos.y; + uv0.y = uv0.y * size.y + tUV.y; + } + + vt.uv0 = new Vector2(Packer.ToFloat((uv0.x + 0.5f) / 2f, (uv0.y + 0.5f) / 2f), + normalizedIndex); + vt.position = pos; + + connector.SetExtraChannel(ref vt, uvMask); + + s_TempVerts[i + j + k] = vt; + } + } + } + + vh.AddUIVertexTriangleStream(s_TempVerts); + s_TempVerts.Clear(); + } + else + { + int count = vh.currentVertCount; + UIVertex vt = default(UIVertex); + for (int i = 0; i < count; i++) + { + vh.PopulateUIVertex(ref vt, i); + Vector2 uv0 = vt.uv0; + vt.uv0 = new Vector2( + Packer.ToFloat((uv0.x + 0.5f) / 2f, (uv0.y + 0.5f) / 2f), + normalizedIndex + ); + vh.SetUIVertex(vt, i); + } + } + } + + protected override void SetEffectParamsDirty() + { + paramTex.SetData(this, 0, m_EffectFactor); // param.x : effect factor + paramTex.SetData(this, 1, m_ColorFactor); // param.y : color factor + paramTex.SetData(this, 2, m_BlurFactor); // param.z : blur factor + } + + static void GetBounds(List<UIVertex> verts, int start, int count, ref Rect posBounds, ref Rect uvBounds, + bool global) + { + Vector2 minPos = new Vector2(float.MaxValue, float.MaxValue); + Vector2 maxPos = new Vector2(float.MinValue, float.MinValue); + Vector2 minUV = new Vector2(float.MaxValue, float.MaxValue); + Vector2 maxUV = new Vector2(float.MinValue, float.MinValue); + for (int i = start; i < start + count; i++) + { + UIVertex vt = verts[i]; + + Vector2 uv = vt.uv0; + Vector3 pos = vt.position; + + // Left-Bottom + if (minPos.x >= pos.x && minPos.y >= pos.y) + { + minPos = pos; + } + // Right-Top + else if (maxPos.x <= pos.x && maxPos.y <= pos.y) + { + maxPos = pos; + } + + // Left-Bottom + if (minUV.x >= uv.x && minUV.y >= uv.y) + { + minUV = uv; + } + // Right-Top + else if (maxUV.x <= uv.x && maxUV.y <= uv.y) + { + maxUV = uv; + } + } + + // Shrink coordinate for detect edge + posBounds.Set(minPos.x + 0.001f, minPos.y + 0.001f, maxPos.x - minPos.x - 0.002f, + maxPos.y - minPos.y - 0.002f); + uvBounds.Set(minUV.x, minUV.y, maxUV.x - minUV.x, maxUV.y - minUV.y); + } + } +} diff --git a/Assets/Scripts/UIEffect.cs.meta b/Assets/Scripts/UIEffect.cs.meta new file mode 100644 index 0000000..1155fe8 --- /dev/null +++ b/Assets/Scripts/UIEffect.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f8b2ed11d675446c5a49da1ea296d490 +timeCreated: 1485321967 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UIFlip.cs b/Assets/Scripts/UIFlip.cs new file mode 100644 index 0000000..2cb7055 --- /dev/null +++ b/Assets/Scripts/UIFlip.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +namespace Coffee.UIEffects +{ + [DisallowMultipleComponent] + [AddComponentMenu("UI/UIEffects/UIFlip", 102)] + public class UIFlip : BaseMeshEffect + { + [Tooltip("Flip horizontally.")] [SerializeField] + private bool m_Horizontal = false; + + [Tooltip("Flip vertically.")] [SerializeField] + private bool m_Veritical = false; + + /// <summary> + /// Gets or sets a value indicating whether this <see cref="Coffee.UIEffects.UIFlip"/> should be flipped horizontally. + /// </summary> + /// <value><c>true</c> if be flipped horizontally; otherwise, <c>false</c>.</value> + public bool horizontal + { + get { return m_Horizontal; } + set + { + if (m_Horizontal == value) return; + m_Horizontal = value; + SetEffectParamsDirty(); + } + } + + /// <summary> + /// Gets or sets a value indicating whether this <see cref="Coffee.UIEffects.UIFlip"/> should be flipped vertically. + /// </summary> + /// <value><c>true</c> if be flipped horizontally; otherwise, <c>false</c>.</value> + public bool vertical + { + get { return m_Veritical; } + set + { + if (m_Veritical == value) return; + m_Veritical = value; + SetEffectParamsDirty(); + } + } + + /// <summary> + /// Call used to modify mesh. + /// </summary> + /// <param name="vh">VertexHelper.</param> + public override void ModifyMesh(VertexHelper vh, Graphic graphic) + { + if (!isActiveAndEnabled) return; + + var vt = default(UIVertex); + for (var i = 0; i < vh.currentVertCount; i++) + { + vh.PopulateUIVertex(ref vt, i); + var pos = vt.position; + vt.position = new Vector3( + m_Horizontal ? -pos.x : pos.x, + m_Veritical ? -pos.y : pos.y + ); + vh.SetUIVertex(vt, i); + } + } + } +} diff --git a/Assets/Scripts/UIFlip.cs.meta b/Assets/Scripts/UIFlip.cs.meta new file mode 100644 index 0000000..86d3ecb --- /dev/null +++ b/Assets/Scripts/UIFlip.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9bb4e59514e90489d985e9a17c838085 +timeCreated: 1525607243 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UIGradient.cs b/Assets/Scripts/UIGradient.cs new file mode 100644 index 0000000..b184182 --- /dev/null +++ b/Assets/Scripts/UIGradient.cs @@ -0,0 +1,319 @@ +using UnityEngine; +using UnityEngine.UI; + +namespace Coffee.UIEffects +{ + /// <summary> + /// UIGradient. + /// </summary> + [DisallowMultipleComponent] + [AddComponentMenu("UI/UIEffects/UIGradient", 101)] + public class UIGradient : BaseMeshEffect + { + static readonly Vector2[] s_SplitedCharacterPosition = {Vector2.up, Vector2.one, Vector2.right, Vector2.zero}; + + /// <summary> + /// Gradient direction. + /// </summary> + public enum Direction + { + Horizontal, + Vertical, + Angle, + Diagonal, + } + + /// <summary> + /// Gradient space for Text. + /// </summary> + public enum GradientStyle + { + Rect, + Fit, + Split, + } + + + [Tooltip("Gradient Direction.")] [SerializeField] + Direction m_Direction; + + [Tooltip("Color1: Top or Left.")] [SerializeField] + Color m_Color1 = Color.white; + + [Tooltip("Color2: Bottom or Right.")] [SerializeField] + Color m_Color2 = Color.white; + + [Tooltip("Color3: For diagonal.")] [SerializeField] + Color m_Color3 = Color.white; + + [Tooltip("Color4: For diagonal.")] [SerializeField] + Color m_Color4 = Color.white; + + [Tooltip("Gradient rotation.")] [SerializeField] [Range(-180, 180)] + float m_Rotation; + + [Tooltip("Gradient offset for Horizontal, Vertical or Angle.")] [SerializeField] [Range(-1, 1)] + float m_Offset1; + + [Tooltip("Gradient offset for Diagonal.")] [SerializeField] [Range(-1, 1)] + float m_Offset2; + + [Tooltip("Gradient style for Text.")] [SerializeField] + GradientStyle m_GradientStyle; + + [Tooltip("Color space to correct color.")] [SerializeField] + ColorSpace m_ColorSpace = ColorSpace.Uninitialized; + + [Tooltip("Ignore aspect ratio.")] [SerializeField] + bool m_IgnoreAspectRatio = true; + + /// <summary> + /// Gradient Direction. + /// </summary> + public Direction direction + { + get { return m_Direction; } + set + { + if (m_Direction == value) return; + m_Direction = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Color1: Top or Left. + /// </summary> + public Color color1 + { + get { return m_Color1; } + set + { + if (m_Color1 == value) return; + m_Color1 = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Color2: Bottom or Right. + /// </summary> + public Color color2 + { + get { return m_Color2; } + set + { + if (m_Color2 == value) return; + m_Color2 = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Color3: For diagonal. + /// </summary> + public Color color3 + { + get { return m_Color3; } + set + { + if (m_Color3 == value) return; + m_Color3 = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Color4: For diagonal. + /// </summary> + public Color color4 + { + get { return m_Color4; } + set + { + if (m_Color4 == value) return; + m_Color4 = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Gradient rotation. + /// </summary> + public float rotation + { + get + { + return m_Direction == Direction.Horizontal ? -90 + : m_Direction == Direction.Vertical ? 0 + : m_Rotation; + } + set + { + if (Mathf.Approximately(m_Rotation, value)) return; + m_Rotation = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Gradient offset for Horizontal, Vertical or Angle. + /// </summary> + public float offset + { + get { return m_Offset1; } + set + { + if (Mathf.Approximately(m_Offset1, value)) return; + m_Offset1 = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Gradient offset for Diagonal. + /// </summary> + public Vector2 offset2 + { + get { return new Vector2(m_Offset2, m_Offset1); } + set + { + if (Mathf.Approximately(m_Offset1, value.y) && Mathf.Approximately(m_Offset2, value.x)) return; + m_Offset1 = value.y; + m_Offset2 = value.x; + SetVerticesDirty(); + } + } + + /// <summary> + /// Gradient style for Text. + /// </summary> + public GradientStyle gradientStyle + { + get { return m_GradientStyle; } + set + { + if (m_GradientStyle == value) return; + m_GradientStyle = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Color space to correct color. + /// </summary> + public ColorSpace colorSpace + { + get { return m_ColorSpace; } + set + { + if (m_ColorSpace == value) return; + m_ColorSpace = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Ignore aspect ratio. + /// </summary> + public bool ignoreAspectRatio + { + get { return m_IgnoreAspectRatio; } + set + { + if (m_IgnoreAspectRatio == value) return; + m_IgnoreAspectRatio = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Call used to modify mesh. + /// </summary> + public override void ModifyMesh(VertexHelper vh, Graphic graphic) + { + if (!isActiveAndEnabled) + return; + + // Gradient space. + var rect = default(Rect); + var vertex = default(UIVertex); + switch (m_GradientStyle) + { + case GradientStyle.Rect: + // RectTransform. + rect = graphic.rectTransform.rect; + break; + case GradientStyle.Split: + // Each characters. + rect.Set(0, 0, 1, 1); + break; + case GradientStyle.Fit: + { + // Fit to contents. + rect.xMin = rect.yMin = float.MaxValue; + rect.xMax = rect.yMax = float.MinValue; + for (var i = 0; i < vh.currentVertCount; i++) + { + vh.PopulateUIVertex(ref vertex, i); + rect.xMin = Mathf.Min(rect.xMin, vertex.position.x); + rect.yMin = Mathf.Min(rect.yMin, vertex.position.y); + rect.xMax = Mathf.Max(rect.xMax, vertex.position.x); + rect.yMax = Mathf.Max(rect.yMax, vertex.position.y); + } + + break; + } + } + + // Gradient rotation. + var rad = rotation * Mathf.Deg2Rad; + var dir = new Vector2(Mathf.Cos(rad), Mathf.Sin(rad)); + if (!m_IgnoreAspectRatio && Direction.Angle <= m_Direction) + { + dir.x *= rect.height / rect.width; + dir = dir.normalized; + } + + // Calculate vertex color. + var localMatrix = new Matrix2x3(rect, dir.x, dir.y); // Get local matrix. + for (var i = 0; i < vh.currentVertCount; i++) + { + vh.PopulateUIVertex(ref vertex, i); + + // Normalize vertex position by local matrix. + Vector2 normalizedPos; + if (m_GradientStyle == GradientStyle.Split) + { + // Each characters. + normalizedPos = localMatrix * s_SplitedCharacterPosition[i % 4] + offset2; + } + else + { + normalizedPos = localMatrix * vertex.position + offset2; + } + + // Interpolate vertex color. + Color color; + if (direction == Direction.Diagonal) + { + color = Color.LerpUnclamped( + Color.LerpUnclamped(m_Color1, m_Color2, normalizedPos.x), + Color.LerpUnclamped(m_Color3, m_Color4, normalizedPos.x), + normalizedPos.y); + } + else + { + color = Color.LerpUnclamped(m_Color2, m_Color1, normalizedPos.y); + } + + // Correct color. + vertex.color *= (m_ColorSpace == ColorSpace.Gamma) ? color.gamma + : (m_ColorSpace == ColorSpace.Linear) ? color.linear + : color; + + vh.SetUIVertex(vertex, i); + } + } + } +} diff --git a/Assets/Scripts/UIGradient.cs.meta b/Assets/Scripts/UIGradient.cs.meta new file mode 100644 index 0000000..8b596ad --- /dev/null +++ b/Assets/Scripts/UIGradient.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3fb48d82dc0e94a2b9246d17d04f8748 +timeCreated: 1515744842 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UIHsvModifier.cs b/Assets/Scripts/UIHsvModifier.cs new file mode 100644 index 0000000..8445bb7 --- /dev/null +++ b/Assets/Scripts/UIHsvModifier.cs @@ -0,0 +1,170 @@ +using System; +using UnityEngine; +using UnityEngine.Serialization; +using UnityEngine.UI; + + +namespace Coffee.UIEffects +{ + /// <summary> + /// HSV Modifier. + /// </summary> + [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; + + /// <summary> + /// Target color to affect hsv shift. + /// </summary> + public Color targetColor + { + get { return m_TargetColor; } + set + { + if (m_TargetColor == value) return; + m_TargetColor = value; + SetEffectParamsDirty(); + } + } + + /// <summary> + /// Color range to affect hsv shift [0 ~ 1]. + /// </summary> + 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(); + } + } + + /// <summary> + /// Saturation shift [-0.5 ~ 0.5]. + /// </summary> + 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(); + } + } + + /// <summary> + /// Value shift [-0.5 ~ 0.5]. + /// </summary> + 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(); + } + } + + /// <summary> + /// Hue shift [-0.5 ~ 0.5]. + /// </summary> + 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(); + } + } + + /// <summary> + /// Gets the parameter texture. + /// </summary> + 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 + } + } +} diff --git a/Assets/Scripts/UIHsvModifier.cs.meta b/Assets/Scripts/UIHsvModifier.cs.meta new file mode 100644 index 0000000..44ca568 --- /dev/null +++ b/Assets/Scripts/UIHsvModifier.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: efe700dddcd8341ff8607ac2c827b4b5 +timeCreated: 1523859834 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UIShadow.cs b/Assets/Scripts/UIShadow.cs new file mode 100644 index 0000000..42ec596 --- /dev/null +++ b/Assets/Scripts/UIShadow.cs @@ -0,0 +1,383 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Serialization; +using UnityEngine.UI; +#if UNITY_EDITOR +using System.IO; +using System.Linq; +using UnityEditor; + +#endif + +namespace Coffee.UIEffects +{ + /// <summary> + /// UIEffect. + /// </summary> + [RequireComponent(typeof(Graphic))] + [AddComponentMenu("UI/UIEffects/UIShadow", 100)] + public class UIShadow : BaseMeshEffect, IParameterTexture + { + static readonly List<UIShadow> tmpShadows = new List<UIShadow>(); + static readonly List<UIVertex> s_Verts = new List<UIVertex>(4096); + + int _graphicVertexCount; + UIEffect _uiEffect; + + [Tooltip("How far is the blurring shadow from the graphic.")] + [FormerlySerializedAs("m_Blur")] + [SerializeField] + [Range(0, 1)] + float m_BlurFactor = 1; + + [Tooltip("Shadow effect style.")] [SerializeField] + ShadowStyle m_Style = ShadowStyle.Shadow; + + [SerializeField] private Color m_EffectColor = new Color(0f, 0f, 0f, 0.5f); + + [SerializeField] private Vector2 m_EffectDistance = new Vector2(1f, -1f); + + [SerializeField] private bool m_UseGraphicAlpha = true; + + private const float kMaxEffectDistance = 600f; + + public Color effectColor + { + get { return m_EffectColor; } + set + { + if (m_EffectColor == value) return; + m_EffectColor = value; + SetVerticesDirty(); + } + } + + public Vector2 effectDistance + { + get { return m_EffectDistance; } + set + { + if (value.x > kMaxEffectDistance) + value.x = kMaxEffectDistance; + if (value.x < -kMaxEffectDistance) + value.x = -kMaxEffectDistance; + + if (value.y > kMaxEffectDistance) + value.y = kMaxEffectDistance; + if (value.y < -kMaxEffectDistance) + value.y = -kMaxEffectDistance; + + if (m_EffectDistance == value) return; + m_EffectDistance = value; + SetEffectParamsDirty(); + } + } + + public bool useGraphicAlpha + { + get { return m_UseGraphicAlpha; } + set + { + if (m_UseGraphicAlpha == value) return; + m_UseGraphicAlpha = value; + SetEffectParamsDirty(); + } + } + + /// <summary> + /// How far is the blurring shadow from the graphic. + /// </summary> + public float blurFactor + { + get { return m_BlurFactor; } + set + { + value = Mathf.Clamp(value, 0, 2); + if (Mathf.Approximately(m_BlurFactor, value)) return; + m_BlurFactor = value; + SetEffectParamsDirty(); + } + } + + /// <summary> + /// Shadow effect style. + /// </summary> + public ShadowStyle style + { + get { return m_Style; } + set + { + if (m_Style == value) return; + m_Style = value; + SetEffectParamsDirty(); + } + } + + /// <summary> + /// Gets or sets the parameter index. + /// </summary> + public int parameterIndex { get; set; } + + /// <summary> + /// Gets the parameter texture. + /// </summary> + public ParameterTexture paramTex { get; private set; } + + protected override void OnEnable() + { + base.OnEnable(); + + _uiEffect = GetComponent<UIEffect>(); + if (!_uiEffect) return; + + paramTex = _uiEffect.paramTex; + paramTex.Register(this); + } + + protected override void OnDisable() + { + base.OnDisable(); + + _uiEffect = null; + if (paramTex == null) return; + + paramTex.Unregister(this); + paramTex = null; + } + + +// #if UNITY_EDITOR +// protected override void OnValidate() +// { +// effectDistance = m_EffectDistance; +// base.OnValidate(); +// } +// #endif + + // #if TMP_PRESENT + // protected void OnCullStateChanged (bool state) + // { + // SetVerticesDirty (); + // } + // + // Vector2 res; + // protected override void LateUpdate () + // { + // if (res.x != Screen.width || res.y != Screen.height) + // { + // res.x = Screen.width; + // res.y = Screen.height; + // SetVerticesDirty (); + // } + // if (textMeshPro && transform.hasChanged) + // { + // transform.hasChanged = false; + // } + // base.LateUpdate (); + // } + // #endif + + /// <summary> + /// Modifies the mesh. + /// </summary> + public override void ModifyMesh(VertexHelper vh, Graphic graphic) + { + if (!isActiveAndEnabled || vh.currentVertCount <= 0 || m_Style == ShadowStyle.None) + { + return; + } + + vh.GetUIVertexStream(s_Verts); + + GetComponents<UIShadow>(tmpShadows); + + foreach (var s in tmpShadows) + { + if (!s.isActiveAndEnabled) continue; + if (s == this) + { + foreach (var s2 in tmpShadows) + { + s2._graphicVertexCount = s_Verts.Count; + } + } + + break; + } + + tmpShadows.Clear(); + + //================================ + // Append shadow vertices. + //================================ + { + _uiEffect = _uiEffect ? _uiEffect : GetComponent<UIEffect>(); + var start = s_Verts.Count - _graphicVertexCount; + var end = s_Verts.Count; + + if (paramTex != null && _uiEffect && _uiEffect.isActiveAndEnabled) + { + paramTex.SetData(this, 0, _uiEffect.effectFactor); // param.x : effect factor + paramTex.SetData(this, 1, 255); // param.y : color factor + paramTex.SetData(this, 2, m_BlurFactor); // param.z : blur factor + } + + ApplyShadow(s_Verts, effectColor, ref start, ref end, effectDistance, style, useGraphicAlpha); + } + + vh.Clear(); + vh.AddUIVertexTriangleStream(s_Verts); + + s_Verts.Clear(); + } + + /// <summary> + /// Append shadow vertices. + /// * It is similar to Shadow component implementation. + /// </summary> + private void ApplyShadow(List<UIVertex> verts, Color color, ref int start, ref int end, Vector2 distance, + ShadowStyle style, bool alpha) + { + if (style == ShadowStyle.None || color.a <= 0) + return; + + var x = distance.x; + var y = distance.y; + // Append Shadow. + ApplyShadowZeroAlloc(verts, color, ref start, ref end, x, y, alpha); + + switch (style) + { + // Append Shadow3. + case ShadowStyle.Shadow3: + ApplyShadowZeroAlloc(verts, color, ref start, ref end, x, 0, alpha); + ApplyShadowZeroAlloc(verts, color, ref start, ref end, 0, y, alpha); + break; + // Append Outline. + case ShadowStyle.Outline: + ApplyShadowZeroAlloc(verts, color, ref start, ref end, x, -y, alpha); + ApplyShadowZeroAlloc(verts, color, ref start, ref end, -x, y, alpha); + ApplyShadowZeroAlloc(verts, color, ref start, ref end, -x, -y, alpha); + break; + // Append Outline8. + case ShadowStyle.Outline8: + ApplyShadowZeroAlloc(verts, color, ref start, ref end, x, -y, alpha); + ApplyShadowZeroAlloc(verts, color, ref start, ref end, -x, y, alpha); + ApplyShadowZeroAlloc(verts, color, ref start, ref end, -x, -y, alpha); + ApplyShadowZeroAlloc(verts, color, ref start, ref end, -x, 0, alpha); + ApplyShadowZeroAlloc(verts, color, ref start, ref end, 0, -y, alpha); + ApplyShadowZeroAlloc(verts, color, ref start, ref end, x, 0, alpha); + ApplyShadowZeroAlloc(verts, color, ref start, ref end, 0, y, alpha); + break; + } + } + + /// <summary> + /// Append shadow vertices. + /// * It is similar to Shadow component implementation. + /// </summary> + private void ApplyShadowZeroAlloc(List<UIVertex> verts, Color color, ref int start, ref int end, float x, + float y, bool alpha) + { + // Check list capacity. + var count = end - start; + var neededCapacity = verts.Count + count; + if (verts.Capacity < neededCapacity) + verts.Capacity *= 2; + + var normalizedIndex = paramTex != null && _uiEffect && _uiEffect.isActiveAndEnabled + ? paramTex.GetNormalizedIndex(this) + : -1; + + // Add + var vt = default(UIVertex); + for (var i = 0; i < count; i++) + { + verts.Add(vt); + } + + // Move + for (var i = verts.Count - 1; count <= i; i--) + { + verts[i] = verts[i - count]; + } + + // Append shadow vertices to the front of list. + // * The original vertex is pushed backward. + for (var i = 0; i < count; ++i) + { + vt = verts[i + start + count]; + + var v = vt.position; + vt.position.Set(v.x + x, v.y + y, v.z); + + var vertColor = effectColor; + vertColor.a = alpha ? color.a * vt.color.a / 255 : color.a; + vt.color = vertColor; + + + // Set UIEffect parameters + if (0 <= normalizedIndex) + { + vt.uv0 = new Vector2( + vt.uv0.x, + normalizedIndex + ); + } + + verts[i] = vt; + } + + // Update next shadow offset. + start = end; + end = verts.Count; + } + + /// <summary> + /// Mark the UIEffect as dirty. + /// </summary> + // void _SetDirty() + // { + // if (graphic) + // graphic.SetVerticesDirty(); + // } + +// #if UNITY_EDITOR +// public void OnBeforeSerialize() +// { +// } +// +// public void OnAfterDeserialize() +// { +// EditorApplication.delayCall += UpgradeIfNeeded; +// } +// +// +// #pragma warning disable 0612 +// void UpgradeIfNeeded() +// { +// if (0 < m_AdditionalShadows.Count) +// { +// foreach (var s in m_AdditionalShadows) +// { +// if (s.style == ShadowStyle.None) +// { +// continue; +// } +// +// var shadow = gameObject.AddComponent<UIShadow>(); +// shadow.style = s.style; +// shadow.effectDistance = s.effectDistance; +// shadow.effectColor = s.effectColor; +// shadow.useGraphicAlpha = s.useGraphicAlpha; +// shadow.blurFactor = s.blur; +// } +// +// m_AdditionalShadows = null; +// } +// } +// #pragma warning restore 0612 +// #endif + } +} diff --git a/Assets/Scripts/UIShadow.cs.meta b/Assets/Scripts/UIShadow.cs.meta new file mode 100644 index 0000000..257198c --- /dev/null +++ b/Assets/Scripts/UIShadow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0848bff101191904ead4bb831f7084db +timeCreated: 1485321967 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: -400 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UIShiny.cs b/Assets/Scripts/UIShiny.cs new file mode 100644 index 0000000..3b938cb --- /dev/null +++ b/Assets/Scripts/UIShiny.cs @@ -0,0 +1,278 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Serialization; +using UnityEngine.UI; +using System.Collections; + +namespace Coffee.UIEffects +{ + /// <summary> + /// UIEffect. + /// </summary> + [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; + + /// <summary> + /// Effect factor between 0(start) and 1(end). + /// </summary> + 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(); + } + } + + /// <summary> + /// Width for shiny effect. + /// </summary> + 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(); + } + } + + /// <summary> + /// Softness for shiny effect. + /// </summary> + 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(); + } + } + + /// <summary> + /// Brightness for shiny effect. + /// </summary> + 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(); + } + } + + /// <summary> + /// Gloss factor for shiny effect. + /// </summary> + 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(); + } + } + + /// <summary> + /// Rotation for shiny effect. + /// </summary> + public float rotation + { + get { return m_Rotation; } + set + { + if (Mathf.Approximately(m_Rotation, value)) return; + m_Rotation = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// The area for effect. + /// </summary> + public EffectArea effectArea + { + get { return m_EffectArea; } + set + { + if (m_EffectArea == value) return; + m_EffectArea = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Gets the parameter texture. + /// </summary> + public override ParameterTexture paramTex + { + get { return s_ParamTex; } + } + + public EffectPlayer effectPlayer + { + get { return m_Player ?? (m_Player = new EffectPlayer()); } + } + + /// <summary> + /// This function is called when the object becomes enabled and active. + /// </summary> + protected override void OnEnable() + { + base.OnEnable(); + effectPlayer.OnEnable(f => effectFactor = f); + } + + /// <summary> + /// This function is called when the behaviour becomes disabled () or inactive. + /// </summary> + 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); + } + + /// <summary> + /// Modifies the mesh. + /// </summary> + 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); + } + } + + /// <summary> + /// Play effect. + /// </summary> + public void Play(bool reset = true) + { + effectPlayer.Play(reset); + } + + /// <summary> + /// Stop effect. + /// </summary> + 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(); + } + } +} diff --git a/Assets/Scripts/UIShiny.cs.meta b/Assets/Scripts/UIShiny.cs.meta new file mode 100644 index 0000000..97bec07 --- /dev/null +++ b/Assets/Scripts/UIShiny.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f19b7e2285c104f6ca47d583f3e5444f +timeCreated: 1523859834 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UISyncEffect.cs b/Assets/Scripts/UISyncEffect.cs new file mode 100644 index 0000000..ada9be8 --- /dev/null +++ b/Assets/Scripts/UISyncEffect.cs @@ -0,0 +1,83 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + + +namespace Coffee.UIEffects +{ + /// <summary> + /// Dissolve effect for uGUI. + /// </summary> + [ExecuteInEditMode] + public class UISyncEffect : BaseMaterialEffect + { + [Tooltip("The target effect to synchronize.")] [SerializeField] + private BaseMeshEffect m_TargetEffect; + + public BaseMeshEffect targetEffect + { + get { return m_TargetEffect != this ? m_TargetEffect : null; } + set + { + if (m_TargetEffect == value) return; + m_TargetEffect = value; + + SetVerticesDirty(); + SetMaterialDirty(); + SetEffectParamsDirty(); + } + } + + protected override void OnEnable() + { + if (targetEffect) + targetEffect.syncEffects.Add(this); + base.OnEnable(); + } + + protected override void OnDisable() + { + if (targetEffect) + targetEffect.syncEffects.Remove(this); + base.OnDisable(); + } + + public override Hash128 GetMaterialHash(Material baseMaterial) + { + if (!isActiveAndEnabled) return k_InvalidHash; + + var matEffect = targetEffect as BaseMaterialEffect; + if (!matEffect || !matEffect.isActiveAndEnabled) return k_InvalidHash; + + return matEffect.GetMaterialHash(baseMaterial); + } + + public override void ModifyMaterial(Material newMaterial, Graphic graphic) + { + if (!isActiveAndEnabled) return; + + var matEffect = targetEffect as BaseMaterialEffect; + if (!matEffect || !matEffect.isActiveAndEnabled) return; + + matEffect.ModifyMaterial(newMaterial, graphic); + } + + public override void ModifyMesh(VertexHelper vh, Graphic graphic) + { + if (!isActiveAndEnabled) return; + if (!targetEffect || !targetEffect.isActiveAndEnabled) return; + + targetEffect.ModifyMesh(vh, graphic); + } + +#if UNITY_EDITOR + protected override void OnValidate() + { + SetVerticesDirty(); + SetMaterialDirty(); + SetEffectParamsDirty(); + } +#endif + } +} diff --git a/Assets/Scripts/UISyncEffect.cs.meta b/Assets/Scripts/UISyncEffect.cs.meta new file mode 100644 index 0000000..5b14421 --- /dev/null +++ b/Assets/Scripts/UISyncEffect.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a7be078926b3448089fe9995b32f75f1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UITransitionEffect.cs b/Assets/Scripts/UITransitionEffect.cs new file mode 100644 index 0000000..b75dfd2 --- /dev/null +++ b/Assets/Scripts/UITransitionEffect.cs @@ -0,0 +1,332 @@ +using UnityEngine; +using UnityEngine.UI; +using UnityEngine.Serialization; +using System; + +namespace Coffee.UIEffects +{ + /// <summary> + /// Transition effect. + /// </summary> + [AddComponentMenu("UI/UIEffects/UITransitionEffect", 5)] + public class UITransitionEffect : BaseMaterialEffect + { + /// <summary> + /// Effect mode. + /// </summary> + public enum EffectMode + { + Fade = 1, + Cutoff = 2, + Dissolve = 3, + } + + private const uint k_ShaderId = 5 << 3; + private static readonly int k_TransitionTexId = Shader.PropertyToID("_TransitionTex"); + private static readonly ParameterTexture s_ParamTex = new ParameterTexture(8, 128, "_ParamTex"); + + private bool _lastKeepAspectRatio; + private static Texture _defaultTransitionTexture; + + [Tooltip("Effect mode.")] [SerializeField] + EffectMode m_EffectMode = EffectMode.Cutoff; + + [Tooltip("Effect factor between 0(hidden) and 1(shown).")] [SerializeField] [Range(0, 1)] + float m_EffectFactor = 0.5f; + + [Tooltip("Transition texture (single channel texture).")] [SerializeField] + Texture m_TransitionTexture; + + [Header("Advanced Option")] [Tooltip("The area for effect.")] [SerializeField] + EffectArea m_EffectArea = EffectArea.RectTransform; + + [Tooltip("Keep effect aspect ratio.")] [SerializeField] + bool m_KeepAspectRatio; + + [Tooltip("Dissolve edge width.")] [SerializeField] [Range(0, 1)] + float m_DissolveWidth = 0.5f; + + [Tooltip("Dissolve edge softness.")] [SerializeField] [Range(0, 1)] + float m_DissolveSoftness = 0.5f; + + [Tooltip("Dissolve edge color.")] [SerializeField] [ColorUsage(false)] + Color m_DissolveColor = new Color(0.0f, 0.25f, 1.0f); + + [Tooltip("Disable the graphic's raycast target on hidden.")] [SerializeField] + bool m_PassRayOnHidden; + + [Header("Effect Player")] [SerializeField] + EffectPlayer m_Player; + + + /// <summary> + /// Effect factor between 0(no effect) and 1(complete effect). + /// </summary> + 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(); + } + } + + /// <summary> + /// Transition texture. + /// </summary> + public Texture transitionTexture + { + get + { + return m_TransitionTexture + ? m_TransitionTexture + : defaultTransitionTexture; + } + set + { + if (m_TransitionTexture == value) return; + m_TransitionTexture = value; + SetMaterialDirty(); + } + } + + private static Texture defaultTransitionTexture + { + get + { + return _defaultTransitionTexture + ? _defaultTransitionTexture + : (_defaultTransitionTexture = Resources.Load<Texture>("Default-Transition")); + } + } + + /// <summary> + /// Effect mode. + /// </summary> + public EffectMode effectMode + { + get { return m_EffectMode; } + set + { + if (m_EffectMode == value) return; + m_EffectMode = value; + SetMaterialDirty(); + } + } + + /// <summary> + /// Keep aspect ratio. + /// </summary> + public bool keepAspectRatio + { + get { return m_KeepAspectRatio; } + set + { + if (m_KeepAspectRatio == value) return; + m_KeepAspectRatio = value; + SetVerticesDirty(); + } + } + + /// <summary> + /// Gets the parameter texture. + /// </summary> + public override ParameterTexture paramTex + { + get { return s_ParamTex; } + } + + /// <summary> + /// Dissolve edge width. + /// </summary> + public float dissolveWidth + { + get { return m_DissolveWidth; } + set + { + value = Mathf.Clamp(value, 0, 1); + if (Mathf.Approximately(m_DissolveWidth, value)) return; + m_DissolveWidth = value; + SetEffectParamsDirty(); + } + } + + /// <summary> + /// Dissolve edge softness. + /// </summary> + public float dissolveSoftness + { + get { return m_DissolveSoftness; } + set + { + value = Mathf.Clamp(value, 0, 1); + if (Mathf.Approximately(m_DissolveSoftness, value)) return; + m_DissolveSoftness = value; + SetEffectParamsDirty(); + } + } + + /// <summary> + /// Dissolve edge color. + /// </summary> + public Color dissolveColor + { + get { return m_DissolveColor; } + set + { + if (m_DissolveColor == value) return; + m_DissolveColor = value; + SetEffectParamsDirty(); + } + } + + /// <summary> + /// Disable graphic's raycast target on hidden. + /// </summary> + public bool passRayOnHidden + { + get { return m_PassRayOnHidden; } + set { m_PassRayOnHidden = value; } + } + + public EffectPlayer effectPlayer + { + get { return m_Player ?? (m_Player = new EffectPlayer()); } + } + + /// <summary> + /// Show transition. + /// </summary> + public void Show(bool reset = true) + { + effectPlayer.loop = false; + effectPlayer.Play(reset, f => effectFactor = f); + } + + /// <summary> + /// Hide transition. + /// </summary> + public void Hide(bool reset = true) + { + effectPlayer.loop = false; + effectPlayer.Play(reset, f => effectFactor = 1 - f); + } + + + public override Hash128 GetMaterialHash(Material material) + { + if (!isActiveAndEnabled || !material || !material.shader) + return k_InvalidHash; + + var shaderVariantId = (uint) ((int) m_EffectMode << 6); + var resourceId = (uint) transitionTexture.GetInstanceID(); + return new Hash128( + (uint) material.GetInstanceID(), + k_ShaderId + shaderVariantId, + resourceId, + 0 + ); + } + + public override void ModifyMaterial(Material newMaterial, Graphic graphic) + { + var connector = GraphicConnector.FindConnector(graphic); + newMaterial.shader = Shader.Find(string.Format("Hidden/{0} (UITransition)", newMaterial.shader.name)); + SetShaderVariants(newMaterial, m_EffectMode); + + newMaterial.SetTexture(k_TransitionTexId, transitionTexture); + paramTex.RegisterMaterial(newMaterial); + } + + /// <summary> + /// Modifies the mesh. + /// </summary> + public override void ModifyMesh(VertexHelper vh, Graphic graphic) + { + if (!isActiveAndEnabled) + { + return; + } + + var normalizedIndex = paramTex.GetNormalizedIndex(this); + + // rect. + var tex = transitionTexture; + var aspectRatio = m_KeepAspectRatio && tex ? ((float) tex.width) / tex.height : -1; + var rect = m_EffectArea.GetEffectArea(vh, rectTransform.rect, aspectRatio); + + // Set parameters to vertex. + var vertex = default(UIVertex); + var count = vh.currentVertCount; + for (var i = 0; i < count; i++) + { + vh.PopulateUIVertex(ref vertex, i); + float x; + float y; + connector.GetPositionFactor(m_EffectArea, i, rect, vertex.position, out x, out y); + + vertex.uv0 = new Vector2( + Packer.ToFloat(vertex.uv0.x, vertex.uv0.y), + Packer.ToFloat(x, y, normalizedIndex) + ); + vh.SetUIVertex(vertex, i); + } + } + + /// <summary> + /// This function is called when the object becomes enabled and active. + /// </summary> + protected override void OnEnable() + { + base.OnEnable(); + effectPlayer.OnEnable(null); + effectPlayer.loop = false; + } + + /// <summary> + /// This function is called when the behaviour becomes disabled () or inactive. + /// </summary> + protected override void OnDisable() + { + base.OnDisable(); + effectPlayer.OnDisable(); + } + + protected override void SetEffectParamsDirty() + { + paramTex.SetData(this, 0, m_EffectFactor); // param1.x : effect factor + if (m_EffectMode == EffectMode.Dissolve) + { + paramTex.SetData(this, 1, m_DissolveWidth); // param1.y : width + paramTex.SetData(this, 2, m_DissolveSoftness); // param1.z : softness + paramTex.SetData(this, 4, m_DissolveColor.r); // param2.x : red + paramTex.SetData(this, 5, m_DissolveColor.g); // param2.y : green + paramTex.SetData(this, 6, m_DissolveColor.b); // param2.z : blue + } + + // Disable graphic's raycastTarget on hidden. + if (m_PassRayOnHidden) + { + graphic.raycastTarget = 0 < m_EffectFactor; + } + } + + protected override void SetVerticesDirty() + { + base.SetVerticesDirty(); + + _lastKeepAspectRatio = m_KeepAspectRatio; + } + + protected override void OnDidApplyAnimationProperties() + { + base.OnDidApplyAnimationProperties(); + + if (_lastKeepAspectRatio != m_KeepAspectRatio) + SetVerticesDirty(); + } + } +} diff --git a/Assets/Scripts/UITransitionEffect.cs.meta b/Assets/Scripts/UITransitionEffect.cs.meta new file mode 100644 index 0000000..6069e80 --- /dev/null +++ b/Assets/Scripts/UITransitionEffect.cs.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 922b805bc01c243e5853d9cbb544118c +timeCreated: 1538827562 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: + - m_EffectMaterial: {instanceID: 0} + - m_PtexMaterial: {instanceID: 0} + - m_TransitionTexture: {fileID: 2800000, guid: 3e04c247fb2604af186173fce0bc62de, + type: 3} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: |