Created
July 23, 2014 11:01
-
-
Save stramit/4a5e27713fff6a7a033d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using UnityEngine.EventSystems; | |
using UnityEngine.UI.CoroutineTween; | |
namespace UnityEngine.UI | |
{ | |
/// <summary> | |
/// Base class for all UI components that should be derived from when creating new Graphic types. | |
/// </summary> | |
[DisallowMultipleComponent] | |
[RequireComponent(typeof(CanvasRenderer))] | |
[RequireComponent(typeof(RectTransform))] | |
[ExecuteInEditMode] | |
public abstract class Graphic | |
: UIBehaviour, | |
ICanvasElement | |
{ | |
static protected Color32 s_White = Color.white; | |
static protected Material s_DefaultUI = null; | |
static protected Material s_DefaultText = null; | |
static protected Texture2D s_WhiteTexture = null; | |
/// <summary> | |
/// Default material used to draw everything if no explicit material was specified. | |
/// </summary> | |
static public Material defaultGraphicMaterial | |
{ | |
get | |
{ | |
if (s_DefaultUI == null) | |
{ | |
Shader shader = Shader.Find("uGUI/Default"); | |
s_DefaultUI = new Material(shader); | |
s_DefaultUI.hideFlags = HideFlags.DontSave; | |
s_DefaultUI.name = "Default UI Material"; | |
} | |
return s_DefaultUI; | |
} | |
} | |
// Temporary vertex array used to avoid memory allocations | |
static readonly List<UIVertex> s_Vbo = new List<UIVertex>(300); | |
// Cached and saved values | |
[SerializeField] protected Material m_Mat; | |
[SerializeField] private Color m_Color = Color.white; | |
public Color color { get { return m_Color; } set { SetPropertyUtility.Set (ref m_Color, value, SetAllDirty); } } | |
private float m_PixelsPerUnit = 1; // Don't serialize | |
public float pixelsPerUnit { get { return m_PixelsPerUnit; } set { SetPropertyUtility.Set (ref m_PixelsPerUnit, value, SetAllDirty); } } | |
[NonSerialized] private RectTransform m_RectTransform; | |
[NonSerialized] private CanvasRenderer m_CanvasRender; | |
[NonSerialized] private Canvas m_Canvas; | |
[NonSerialized] private bool m_VertsDirty; | |
[NonSerialized] private bool m_MaterialDirty; | |
// Tween controls for the Graphic | |
[NonSerialized] | |
private readonly TweenRunner<ColorTween> m_ColorTweenRunner; | |
// Called by Unity prior to deserialization, | |
// should not be called by users | |
protected Graphic() | |
{ | |
if (m_ColorTweenRunner == null) | |
m_ColorTweenRunner = new TweenRunner<ColorTween> (); | |
m_ColorTweenRunner.Init (this); | |
} | |
public virtual void SetAllDirty() | |
{ | |
SetLayoutDirty (); | |
SetVerticesDirty (); | |
SetMaterialDirty (); | |
} | |
public virtual void SetLayoutDirty() | |
{ | |
if (!IsActive()) | |
return; | |
LayoutRebuilder.MarkLayoutForRebuild(rectTransform); | |
} | |
public virtual void SetVerticesDirty() | |
{ | |
if (!IsActive()) | |
return; | |
m_VertsDirty = true; | |
CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild (this); | |
} | |
public virtual void SetMaterialDirty() | |
{ | |
if (!IsActive()) | |
return; | |
m_MaterialDirty = true; | |
CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); | |
} | |
protected virtual void OnRectTransformDimensionsChange () | |
{ | |
if (gameObject.activeInHierarchy) | |
{ | |
// prevent double dirtying... | |
if (CanvasUpdateRegistry.IsRebuildingLayout ()) | |
SetVerticesDirty (); | |
else | |
SetAllDirty (); | |
} | |
} | |
protected virtual void OnBeforeTransformParentChanged() | |
{ | |
LayoutRebuilder.MarkLayoutForRebuild (rectTransform); | |
} | |
protected virtual void OnTransformParentChanged() | |
{ | |
if (!IsActive ()) | |
return; | |
CacheCanvas(); | |
SetAllDirty (); | |
} | |
/// <summary> | |
/// Absolute depth of the graphic, used by rendering and events -- lowest to highest. | |
/// </summary> | |
public int depth { get { return canvasRenderer.absoluteDepth; } } | |
/// <summary> | |
/// Transform gets cached for speed. | |
/// </summary> | |
public RectTransform rectTransform | |
{ | |
get { return m_RectTransform ?? (m_RectTransform = GetComponent<RectTransform>()); } | |
} | |
public Canvas canvas | |
{ | |
get { return m_Canvas; } | |
} | |
private void CacheCanvas() | |
{ | |
GraphicRegistry.UnregisterGraphicForCanvas(canvas, this); | |
// TODO: upgrade this to allocation free | |
// Find the top most canvas for this graphic | |
Canvas[] canvases = gameObject.GetComponentsInParent<Canvas>(); | |
if (canvases.Length > 0) | |
m_Canvas = canvases[canvases.Length - 1]; | |
GraphicRegistry.RegisterGraphicForCanvas(canvas, this); | |
} | |
/// <summary> | |
/// UI Renderer component. | |
/// </summary> | |
public CanvasRenderer canvasRenderer | |
{ | |
get | |
{ | |
if (m_CanvasRender == null) | |
m_CanvasRender = GetComponent<CanvasRenderer>(); | |
return m_CanvasRender; | |
} | |
} | |
public virtual Material defaultMaterial | |
{ | |
get { return defaultGraphicMaterial; } | |
} | |
/// <summary> | |
/// Returns the material used by this Graphic. | |
/// </summary> | |
public virtual Material material | |
{ | |
get | |
{ | |
return (m_Mat != null) ? m_Mat : defaultMaterial; | |
} | |
set | |
{ | |
if (m_Mat == value) | |
return; | |
m_Mat = value; | |
SetMaterialDirty (); | |
} | |
} | |
private List<Component> m_MaterialModifiers = new List<Component> (); | |
public virtual Material materialForRendering | |
{ | |
get | |
{ | |
GetComponents (typeof (IMaterialModifier), m_MaterialModifiers); | |
var currentMat = material; | |
for (var i = 0; i < m_MaterialModifiers.Count; i++) | |
currentMat = (m_MaterialModifiers[i] as IMaterialModifier).GetModifiedMaterial (currentMat); | |
m_MaterialModifiers.Clear (); | |
return currentMat; | |
} | |
} | |
/// <summary> | |
/// Returns the texture used to draw this Graphic. | |
/// </summary> | |
public virtual Texture mainTexture | |
{ | |
get | |
{ | |
return s_WhiteTexture; | |
} | |
} | |
#region Unity Lifetime calls | |
/// <summary> | |
/// Mark the Graphic and the canvas as having been changed. | |
/// </summary> | |
protected override void OnEnable() | |
{ | |
#if UNITY_EDITOR | |
CanvasRenderer.onRequestRebuild += OnRebuildRequested; | |
#endif | |
if (s_WhiteTexture == null) | |
s_WhiteTexture = Texture2D.whiteTexture; | |
CacheCanvas (); | |
SetAllDirty(); | |
SendGraphicEnabledDisabled (); | |
} | |
/// <summary> | |
/// Clear references. | |
/// </summary> | |
protected override void OnDisable() | |
{ | |
#if UNITY_EDITOR | |
CanvasRenderer.onRequestRebuild -= OnRebuildRequested; | |
#endif | |
GraphicRegistry.UnregisterGraphicForCanvas (canvas, this); | |
CanvasUpdateRegistry.UnRegisterCanvasElementForRebuild (this); | |
if (canvasRenderer != null) | |
canvasRenderer.Clear (); | |
SendGraphicEnabledDisabled (); | |
} | |
private List<Component> m_GraphicEnabledDisabledListeners = new List<Component>(); | |
private void SendGraphicEnabledDisabled() | |
{ | |
GetComponents(typeof(IGraphicEnabledDisabled), m_GraphicEnabledDisabledListeners); | |
for (int i = 0; i < m_GraphicEnabledDisabledListeners.Count; i++) | |
(m_GraphicEnabledDisabledListeners[i] as IGraphicEnabledDisabled).OnSiblingGraphicEnabledDisabled(); | |
m_GraphicEnabledDisabledListeners.Clear(); | |
} | |
#endregion | |
public virtual void Rebuild(CanvasUpdate update) | |
{ | |
switch (update) | |
{ | |
case CanvasUpdate.PreRender: | |
if (m_VertsDirty) | |
{ | |
UpdateGeometry (); | |
m_VertsDirty = false; | |
} | |
if (m_MaterialDirty) | |
{ | |
UpdateMaterial (); | |
m_MaterialDirty = false; | |
} | |
break; | |
} | |
} | |
/// <summary> | |
/// Update the renderer's vertices. | |
/// </summary> | |
private List<Component> m_VertexModifiers = new List<Component>(); | |
protected virtual void UpdateGeometry () | |
{ | |
s_Vbo.Clear(); | |
if (rectTransform != null && rectTransform.rect.width >= 0 && rectTransform.rect.height >= 0) | |
OnFillVBO(s_Vbo); | |
GetComponents(typeof(IVertexModifier), m_VertexModifiers); | |
for (var i = 0; i < m_VertexModifiers.Count; i++) | |
(m_VertexModifiers[i] as IVertexModifier).ModifyVertices (s_Vbo); | |
m_VertexModifiers.Clear(); | |
canvasRenderer.SetVertices(s_Vbo); | |
} | |
/// <summary> | |
/// Update the renderer's material. | |
/// </summary> | |
protected virtual void UpdateMaterial () | |
{ | |
if (IsActive ()) | |
canvasRenderer.SetMaterial (materialForRendering, mainTexture); | |
} | |
/// <summary> | |
/// Fill the vertex buffer data. | |
/// </summary> | |
protected virtual void OnFillVBO(List<UIVertex> vbo) | |
{ | |
var r = GetPixelAdjustedRect(); | |
var v = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height); | |
var vert = UIVertex.simpleVert; | |
vert.color = color; | |
vert.position = new Vector3(v.x, v.y); | |
vert.uv0 = new Vector2(0f, 0f); | |
vbo.Add(vert); | |
vert.position = new Vector3(v.x, v.w); | |
vert.uv0 = new Vector2(0f, 1f); | |
vbo.Add(vert); | |
vert.position = new Vector3(v.z, v.w); | |
vert.uv0 = new Vector2(1f, 1f); | |
vbo.Add(vert); | |
vert.position = new Vector3(v.z, v.y); | |
vert.uv0 = new Vector2(1f, 0f); | |
vbo.Add(vert); | |
} | |
#if UNITY_EDITOR | |
protected virtual void OnRebuildRequested () | |
{ | |
SetAllDirty (); | |
} | |
#endif | |
// Call from unity if animation properties have changed | |
protected virtual void OnDidApplyAnimationProperties() | |
{ | |
SetAllDirty (); | |
} | |
/// <summary> | |
/// Make the Graphic have the native size of its content. | |
/// </summary> | |
public virtual void SetNativeSize () { } | |
private readonly List<Component> m_GetComponentsScratch = new List<Component>(10); | |
public virtual bool Raycast (Vector2 sp, Camera eventCamera) | |
{ | |
var t = transform; | |
while (t != null) | |
{ | |
t.GetComponents(m_GetComponentsScratch); | |
for (var i = 0; i < m_GetComponentsScratch.Count; i++) | |
{ | |
var filter = m_GetComponentsScratch[i] as ICanvasRaycastFilter; | |
if (filter == null) | |
continue; | |
if (!filter.IsRaycastLocationValid (sp, eventCamera)) | |
return false; | |
} | |
t = t.parent; | |
} | |
return true; | |
} | |
#if UNITY_EDITOR | |
protected override void OnValidate() | |
{ | |
base.OnValidate (); | |
m_PixelsPerUnit = Mathf.Max (m_PixelsPerUnit, 0.01f); | |
SetAllDirty (); | |
} | |
#endif | |
public Vector2 PixelAdjustPoint (Vector2 point) | |
{ | |
if (!canvas || !canvas.pixelPerfect) | |
return point; | |
return RectTransformUtility.PixelAdjustPoint (point, transform, canvas); | |
} | |
public Rect GetPixelAdjustedRect () | |
{ | |
if (!canvas || !canvas.pixelPerfect) | |
return rectTransform.rect; | |
return RectTransformUtility.PixelAdjustRect(rectTransform, canvas); | |
} | |
public void CrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha) | |
{ | |
CrossFadeColor(targetColor, duration, ignoreTimeScale, useAlpha, true); | |
} | |
private void CrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha, bool useRGB) | |
{ | |
if (canvasRenderer == null || (!useRGB && !useAlpha)) | |
return; | |
Color currentColor = canvasRenderer.GetColor(); | |
if (currentColor.Equals(targetColor)) | |
return; | |
ColorTween.ColorTweenMode mode = (useRGB && useAlpha ? | |
ColorTween.ColorTweenMode.All : | |
(useRGB ? ColorTween.ColorTweenMode.RGB : ColorTween.ColorTweenMode.Alpha)); | |
var colorTween = new ColorTween {duration = duration, startColor = canvasRenderer.GetColor(), targetColor = targetColor}; | |
colorTween.AddOnChangedCallback (canvasRenderer.SetColor); | |
colorTween.ignoreTimeScale = ignoreTimeScale; | |
colorTween.tweenMode = mode; | |
m_ColorTweenRunner.StartTween(colorTween); | |
} | |
static private Color CreateColorFromAlpha(float alpha) | |
{ | |
var alphaColor = Color.black; | |
alphaColor.a = alpha; | |
return alphaColor; | |
} | |
public void CrossFadeAlpha(float alpha, float duration, bool ignoreTimeScale) | |
{ | |
CrossFadeColor(CreateColorFromAlpha(alpha), duration, ignoreTimeScale, true, false); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment