309 lines
8.7 KiB
C#
309 lines
8.7 KiB
C#
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using System;
|
|
using UnityEngine.Events;
|
|
using System.Collections.Generic;
|
|
|
|
namespace WXB
|
|
{
|
|
[RequireComponent(typeof(RectTransform))]
|
|
[RequireComponent(typeof(CanvasRenderer))]
|
|
[ExecuteInEditMode]
|
|
public class DrawObject : MonoBehaviour, Draw, IClippable, ICanvasElement
|
|
{
|
|
private RectMask2D m_ParentMask;
|
|
[Serializable]
|
|
public class CullStateChangedEvent : UnityEvent<bool> { }
|
|
|
|
// Event delegates triggered on click.
|
|
[SerializeField]
|
|
private CullStateChangedEvent m_OnCullStateChanged = new CullStateChangedEvent();
|
|
|
|
/// <summary>
|
|
/// Callback issued when culling changes.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Called whene the culling state of this MaskableGraphic either becomes culled or visible. You can use this to control other elements of your UI as culling happens.
|
|
/// </remarks>
|
|
public CullStateChangedEvent onCullStateChanged
|
|
{
|
|
get { return m_OnCullStateChanged; }
|
|
set { m_OnCullStateChanged = value; }
|
|
}
|
|
|
|
private Canvas m_Canvas;
|
|
|
|
/// <summary>
|
|
/// A reference to the Canvas this Graphic is rendering to.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// In the situation where the Graphic is used in a hierarchy with multiple Canvases, the Canvas closest to the root will be used.
|
|
/// </remarks>
|
|
public Canvas canvas
|
|
{
|
|
get
|
|
{
|
|
if (m_Canvas == null)
|
|
CacheCanvas();
|
|
return m_Canvas;
|
|
}
|
|
}
|
|
|
|
private void CacheCanvas()
|
|
{
|
|
var list = ListPool<Canvas>.Get();
|
|
gameObject.GetComponentsInParent(false, list);
|
|
if (list.Count > 0)
|
|
{
|
|
// Find the first active and enabled canvas.
|
|
for (int i = 0; i < list.Count; ++i)
|
|
{
|
|
if (list[i].isActiveAndEnabled)
|
|
{
|
|
m_Canvas = list[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_Canvas = null;
|
|
}
|
|
|
|
ListPool<Canvas>.Release(list);
|
|
}
|
|
|
|
readonly Vector3[] m_Corners = new Vector3[4];
|
|
private Rect rootCanvasRect
|
|
{
|
|
get
|
|
{
|
|
if (rectTransform == null)
|
|
{
|
|
return new Rect(Vector2.zero, Vector2.zero);
|
|
}
|
|
rectTransform.GetWorldCorners(m_Corners);
|
|
|
|
if (canvas)
|
|
{
|
|
Matrix4x4 mat = canvas.rootCanvas.transform.worldToLocalMatrix;
|
|
for (int i = 0; i < 4; ++i)
|
|
m_Corners[i] = mat.MultiplyPoint(m_Corners[i]);
|
|
}
|
|
|
|
// bounding box is now based on the min and max of all corners (case 1013182)
|
|
|
|
Vector2 min = m_Corners[0];
|
|
Vector2 max = m_Corners[0];
|
|
for (int i = 1; i < 4; i++)
|
|
{
|
|
min.x = Mathf.Min(m_Corners[i].x, min.x);
|
|
min.y = Mathf.Min(m_Corners[i].y, min.y);
|
|
max.x = Mathf.Max(m_Corners[i].x, max.x);
|
|
max.y = Mathf.Max(m_Corners[i].y, max.y);
|
|
}
|
|
|
|
return new Rect(min, max - min);
|
|
}
|
|
}
|
|
|
|
protected virtual void OnTransformParentChanged()
|
|
{
|
|
if (!isActiveAndEnabled)
|
|
return;
|
|
|
|
UpdateRect(Vector2.zero);
|
|
UpdateClipParent();
|
|
}
|
|
|
|
protected virtual void OnDisable()
|
|
{
|
|
if (canvasRenderer == null)
|
|
return;
|
|
|
|
canvasRenderer.Clear();
|
|
UpdateClipParent();
|
|
}
|
|
|
|
protected void OnEnable()
|
|
{
|
|
UpdateRect(Vector2.zero);
|
|
UpdateClipParent();
|
|
}
|
|
|
|
public void OnInit()
|
|
{
|
|
enabled = true;
|
|
UpdateRect(Vector2.zero);
|
|
}
|
|
|
|
protected void Start()
|
|
{
|
|
UpdateRect(Vector2.zero);
|
|
}
|
|
|
|
protected virtual void Init()
|
|
{
|
|
|
|
}
|
|
|
|
protected void Awake()
|
|
{
|
|
canvasRenderer = GetComponent<CanvasRenderer>();
|
|
rectTransform = GetComponent<RectTransform>();
|
|
Init();
|
|
}
|
|
|
|
public RectTransform rectTransform { get; private set; }
|
|
|
|
public virtual DrawType type { get { return DrawType.Default; } }
|
|
public virtual long key { get; set; }
|
|
|
|
public CanvasRenderer canvasRenderer
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
protected void UpdateRect(Vector2 offset)
|
|
{
|
|
Tools.UpdateRect(rectTransform, offset);
|
|
}
|
|
|
|
public virtual void UpdateSelf(float deltaTime)
|
|
{
|
|
|
|
}
|
|
|
|
Material m_Material;
|
|
Texture m_Texture;
|
|
|
|
public Material srcMat { get { return m_Material; } set { m_Material = value; } }
|
|
|
|
public Texture texture
|
|
{
|
|
get { return m_Texture; }
|
|
set { m_Texture = value; }
|
|
}
|
|
|
|
public void FillMesh(Mesh workerMesh)
|
|
{
|
|
canvasRenderer.SetMesh(workerMesh);
|
|
}
|
|
|
|
public virtual void UpdateMaterial(Material mat)
|
|
{
|
|
canvasRenderer.materialCount = 1;
|
|
canvasRenderer.SetMaterial(mat, 0);
|
|
canvasRenderer.SetTexture(m_Texture);
|
|
}
|
|
|
|
public virtual void Release()
|
|
{
|
|
m_Material = null;
|
|
m_Texture = null;
|
|
key = 0;
|
|
if (canvasRenderer != null)
|
|
{
|
|
canvasRenderer.Clear();
|
|
}
|
|
}
|
|
|
|
public void DestroySelf()
|
|
{
|
|
Tools.Destroy(gameObject);
|
|
}
|
|
|
|
private void UpdateClipParent()
|
|
{
|
|
var newParent = MaskUtilities.GetRectMaskForClippable(this);
|
|
|
|
// if the new parent is different OR is now inactive
|
|
if (m_ParentMask != null && (newParent != m_ParentMask || !newParent.IsActive()))
|
|
{
|
|
m_ParentMask.RemoveClippable(this);
|
|
UpdateCull(false);
|
|
}
|
|
|
|
// don't re-add it if the newparent is inactive
|
|
if (newParent != null && newParent.IsActive())
|
|
newParent.AddClippable(this);
|
|
|
|
m_ParentMask = newParent;
|
|
}
|
|
|
|
/// <summary>
|
|
/// See IClippable.RecalculateClipping
|
|
/// </summary>
|
|
public virtual void RecalculateClipping()
|
|
{
|
|
UpdateClipParent();
|
|
}
|
|
|
|
/// <summary>
|
|
/// See IClippable.Cull
|
|
/// </summary>
|
|
public virtual void Cull(Rect clipRect, bool validRect)
|
|
{
|
|
var cull = !validRect || !clipRect.Overlaps(rootCanvasRect, true);
|
|
UpdateCull(cull);
|
|
}
|
|
|
|
private void UpdateCull(bool cull)
|
|
{
|
|
if (canvasRenderer == null) return;
|
|
|
|
if (canvasRenderer.cull != cull)
|
|
{
|
|
canvasRenderer.cull = cull;
|
|
UISystemProfilerApi.AddMarker("MaskableGraphic.cullingChanged", this);
|
|
m_OnCullStateChanged.Invoke(cull);
|
|
//OnCullingChanged();
|
|
if (!canvasRenderer.cull && !CanvasUpdateRegistry.IsRebuildingGraphics() && !CanvasUpdateRegistry.IsRebuildingLayout())
|
|
{
|
|
/// When we were culled, we potentially skipped calls to <c>Rebuild</c>.
|
|
CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// See IClippable.SetClipRect
|
|
/// </summary>
|
|
public virtual void SetClipRect(Rect clipRect, bool validRect)
|
|
{
|
|
if (canvasRenderer == null) return;
|
|
|
|
if (validRect)
|
|
canvasRenderer.EnableRectClipping(clipRect);
|
|
else
|
|
canvasRenderer.DisableRectClipping();
|
|
}
|
|
|
|
public virtual void SetClipSoftness(Vector2 clipSoftness)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
public virtual void Rebuild(CanvasUpdate executing)
|
|
{
|
|
|
|
}
|
|
|
|
public virtual void LayoutComplete()
|
|
{
|
|
|
|
}
|
|
|
|
public virtual void GraphicUpdateComplete()
|
|
{
|
|
|
|
}
|
|
|
|
public virtual bool IsDestroyed()
|
|
{
|
|
return this == null;
|
|
}
|
|
}
|
|
} |