You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
396 lines
9.8 KiB
396 lines
9.8 KiB
using UnityEngine; |
|
using UnityEngine.UI; |
|
using UnityEngine.EventSystems; |
|
using UnityEngine.Events; |
|
|
|
namespace UIWidgets |
|
{ |
|
/// <summary> |
|
/// Splitter type. |
|
/// </summary> |
|
public enum SplitterType |
|
{ |
|
Horizontal = 0, |
|
Vertical = 1, |
|
} |
|
|
|
/// <summary> |
|
/// Splitter resize event. |
|
/// </summary> |
|
[SerializeField] |
|
public class SplitterResizeEvent : UnityEvent<Splitter> { |
|
|
|
} |
|
|
|
/// <summary> |
|
/// Splitter. |
|
/// </summary> |
|
[AddComponentMenu("UI/UIWidgets/Splitter")] |
|
public class Splitter : MonoBehaviour, |
|
IInitializePotentialDragHandler, IBeginDragHandler, IEndDragHandler, IDragHandler, |
|
IPointerEnterHandler, IPointerExitHandler |
|
{ |
|
/// <summary> |
|
/// The type. |
|
/// </summary> |
|
public SplitterType Type = SplitterType.Vertical; |
|
|
|
/// <summary> |
|
/// Is need to update RectTransform on Resize. |
|
/// </summary> |
|
[SerializeField] |
|
public bool UpdateRectTransforms = true; |
|
|
|
/// <summary> |
|
/// Is need to update LayoutElement on Resize. |
|
/// </summary> |
|
[SerializeField] |
|
public bool UpdateLayoutElements = true; |
|
|
|
/// <summary> |
|
/// The current camera. For Screen Space - Overlay let it empty. |
|
/// </summary> |
|
[SerializeField] |
|
public Camera CurrentCamera; |
|
|
|
/// <summary> |
|
/// The cursor texture. |
|
/// </summary> |
|
[SerializeField] |
|
public Texture2D CursorTexture; |
|
|
|
/// <summary> |
|
/// The cursor hot spot. |
|
/// </summary> |
|
[SerializeField] |
|
public Vector2 CursorHotSpot = new Vector2(16, 16); |
|
|
|
/// <summary> |
|
/// The default cursor texture. |
|
/// </summary> |
|
[SerializeField] |
|
public Texture2D DefaultCursorTexture; |
|
|
|
/// <summary> |
|
/// The default cursor hot spot. |
|
/// </summary> |
|
[SerializeField] |
|
public Vector2 DefaultCursorHotSpot; |
|
|
|
/// <summary> |
|
/// OnStartResize event. |
|
/// </summary> |
|
public SplitterResizeEvent OnStartResize = new SplitterResizeEvent(); |
|
|
|
/// <summary> |
|
/// OnEndResize event. |
|
/// </summary> |
|
public SplitterResizeEvent OnEndResize = new SplitterResizeEvent(); |
|
|
|
RectTransform rectTransform; |
|
|
|
/// <summary> |
|
/// Gets the rect transform. |
|
/// </summary> |
|
/// <value>The rect transform.</value> |
|
public RectTransform RectTransform { |
|
get { |
|
if (rectTransform==null) |
|
{ |
|
rectTransform = transform as RectTransform; |
|
} |
|
return rectTransform; |
|
} |
|
} |
|
|
|
Canvas canvas; |
|
|
|
RectTransform leftTarget; |
|
RectTransform rightTarget; |
|
LayoutElement leftTargetElement; |
|
|
|
LayoutElement LeftTargetElement { |
|
get { |
|
if (leftTargetElement==null) |
|
{ |
|
leftTargetElement = leftTarget.GetComponent<LayoutElement>(); |
|
if (leftTargetElement==null) |
|
{ |
|
leftTargetElement = leftTarget.gameObject.AddComponent<LayoutElement>(); |
|
} |
|
} |
|
return leftTargetElement; |
|
} |
|
} |
|
|
|
LayoutElement rightTargetElement; |
|
|
|
LayoutElement RightTargetElement { |
|
get { |
|
if (rightTargetElement==null) |
|
{ |
|
rightTargetElement = rightTarget.GetComponent<LayoutElement>(); |
|
if (rightTargetElement==null) |
|
{ |
|
rightTargetElement = rightTarget.gameObject.AddComponent<LayoutElement>(); |
|
} |
|
} |
|
return rightTargetElement; |
|
} |
|
} |
|
|
|
Vector2 summarySize; |
|
|
|
bool processDrag; |
|
|
|
void Start() |
|
{ |
|
Init(); |
|
} |
|
|
|
/// <summary> |
|
/// Raises the initialize potential drag event. |
|
/// </summary> |
|
/// <param name="eventData">Event data.</param> |
|
public void OnInitializePotentialDrag(PointerEventData eventData) |
|
{ |
|
Init(); |
|
} |
|
|
|
/// <summary> |
|
/// Init this instance. |
|
/// </summary> |
|
public void Init() |
|
{ |
|
canvas = Utilites.FindTopmostCanvas(transform).GetComponent<Canvas>(); |
|
} |
|
|
|
bool cursorChanged = false; |
|
|
|
protected bool IsCursorOver; |
|
|
|
/// <summary> |
|
/// Called by a BaseInputModule when an OnPointerEnter event occurs. |
|
/// </summary> |
|
/// <param name="eventData">Event data.</param> |
|
public void OnPointerEnter(PointerEventData eventData) |
|
{ |
|
IsCursorOver = true; |
|
} |
|
|
|
/// <summary> |
|
/// Called by a BaseInputModule when an OnPointerExit event occurs. |
|
/// </summary> |
|
/// <param name="eventData">Event data.</param> |
|
public void OnPointerExit(PointerEventData eventData) |
|
{ |
|
IsCursorOver = false; |
|
|
|
cursorChanged = false; |
|
Cursor.SetCursor(DefaultCursorTexture, DefaultCursorHotSpot, Utilites.GetCursorMode()); |
|
} |
|
|
|
void LateUpdate() |
|
{ |
|
if (!IsCursorOver) |
|
{ |
|
return ; |
|
} |
|
if (processDrag) |
|
{ |
|
return ; |
|
} |
|
if (CursorTexture==null) |
|
{ |
|
return ; |
|
} |
|
if (!Input.mousePresent) |
|
{ |
|
return ; |
|
} |
|
|
|
Vector2 point; |
|
|
|
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(RectTransform, Input.mousePosition, CurrentCamera, out point)) |
|
{ |
|
return ; |
|
} |
|
|
|
var rect = RectTransform.rect; |
|
if (rect.Contains(point)) |
|
{ |
|
cursorChanged = true; |
|
Cursor.SetCursor(CursorTexture, CursorHotSpot, Utilites.GetCursorMode()); |
|
} |
|
else if (cursorChanged) |
|
{ |
|
cursorChanged = false; |
|
Cursor.SetCursor(DefaultCursorTexture, DefaultCursorHotSpot, Utilites.GetCursorMode()); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Raises the begin drag event. |
|
/// </summary> |
|
/// <param name="eventData">Event data.</param> |
|
public void OnBeginDrag(PointerEventData eventData) |
|
{ |
|
Vector2 point; |
|
processDrag = false; |
|
|
|
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(RectTransform, eventData.pressPosition, eventData.pressEventCamera, out point)) |
|
{ |
|
return ; |
|
} |
|
|
|
var index = transform.GetSiblingIndex(); |
|
|
|
if (index==0 || transform.parent.childCount==(index+1)) |
|
{ |
|
return ; |
|
} |
|
|
|
Cursor.SetCursor(CursorTexture, CursorHotSpot, Utilites.GetCursorMode()); |
|
cursorChanged = true; |
|
|
|
processDrag = true; |
|
|
|
leftTarget = transform.parent.GetChild(index - 1) as RectTransform; |
|
LeftTargetElement.preferredWidth = leftTarget.rect.width; |
|
LeftTargetElement.preferredHeight = leftTarget.rect.height; |
|
|
|
rightTarget = transform.parent.GetChild(index + 1) as RectTransform; |
|
RightTargetElement.preferredWidth = rightTarget.rect.width; |
|
RightTargetElement.preferredHeight = rightTarget.rect.height; |
|
|
|
summarySize = new Vector2(leftTarget.rect.width + rightTarget.rect.width, leftTarget.rect.height + rightTarget.rect.height); |
|
|
|
OnStartResize.Invoke(this); |
|
} |
|
|
|
/// <summary> |
|
/// Raises the end drag event. |
|
/// </summary> |
|
/// <param name="eventData">Event data.</param> |
|
public void OnEndDrag(PointerEventData eventData) |
|
{ |
|
Cursor.SetCursor(DefaultCursorTexture, DefaultCursorHotSpot, Utilites.GetCursorMode()); |
|
cursorChanged = false; |
|
|
|
processDrag = false; |
|
|
|
OnEndResize.Invoke(this); |
|
} |
|
|
|
/// <summary> |
|
/// Raises the drag event. |
|
/// </summary> |
|
/// <param name="eventData">Event data.</param> |
|
public void OnDrag(PointerEventData eventData) |
|
{ |
|
if (!processDrag) |
|
{ |
|
return ; |
|
} |
|
if (canvas==null) |
|
{ |
|
throw new MissingComponentException(gameObject.name + " not in Canvas hierarchy."); |
|
} |
|
|
|
Vector2 p1; |
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(RectTransform, eventData.position, CurrentCamera, out p1); |
|
Vector2 p2; |
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(RectTransform, eventData.position - eventData.delta, CurrentCamera, out p2); |
|
var delta = p1 - p2; |
|
|
|
if (UpdateRectTransforms) |
|
{ |
|
PerformUpdateRectTransforms(delta); |
|
} |
|
if (UpdateLayoutElements) |
|
{ |
|
PerformUpdateLayoutElements(delta); |
|
} |
|
} |
|
|
|
bool IsHorizontal() |
|
{ |
|
return SplitterType.Horizontal==Type; |
|
} |
|
|
|
|
|
void PerformUpdateRectTransforms(Vector2 delta) |
|
{ |
|
if (!IsHorizontal()) |
|
{ |
|
float left_width; |
|
float right_width; |
|
|
|
if (delta.x > 0) |
|
{ |
|
left_width = Mathf.Min(LeftTargetElement.preferredWidth + delta.x, summarySize.x - RightTargetElement.minWidth); |
|
right_width = summarySize.x - LeftTargetElement.preferredWidth; |
|
} |
|
else |
|
{ |
|
right_width = Mathf.Min(RightTargetElement.preferredWidth - delta.x, summarySize.x - LeftTargetElement.minWidth); |
|
left_width = summarySize.x - RightTargetElement.preferredWidth; |
|
} |
|
|
|
leftTarget.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, left_width); |
|
rightTarget.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, right_width); |
|
} |
|
else |
|
{ |
|
float left_height; |
|
float right_height; |
|
|
|
delta.y *= -1; |
|
if (delta.y > 0) |
|
{ |
|
left_height = Mathf.Min(LeftTargetElement.preferredHeight + delta.y, summarySize.y - RightTargetElement.minHeight); |
|
right_height = summarySize.y - LeftTargetElement.preferredHeight; |
|
} |
|
else |
|
{ |
|
right_height = Mathf.Min(RightTargetElement.preferredHeight - delta.y, summarySize.y - LeftTargetElement.minHeight); |
|
left_height = summarySize.y - RightTargetElement.preferredHeight; |
|
} |
|
|
|
leftTarget.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, left_height); |
|
rightTarget.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, right_height); |
|
} |
|
} |
|
|
|
void PerformUpdateLayoutElements(Vector2 delta) |
|
{ |
|
if (!IsHorizontal()) |
|
{ |
|
if (delta.x > 0) |
|
{ |
|
LeftTargetElement.preferredWidth = Mathf.Min(LeftTargetElement.preferredWidth + delta.x, summarySize.x - RightTargetElement.minWidth); |
|
RightTargetElement.preferredWidth = summarySize.x - LeftTargetElement.preferredWidth; |
|
} |
|
else |
|
{ |
|
RightTargetElement.preferredWidth = Mathf.Min(RightTargetElement.preferredWidth - delta.x, summarySize.x - LeftTargetElement.minWidth); |
|
LeftTargetElement.preferredWidth = summarySize.x - RightTargetElement.preferredWidth; |
|
} |
|
} |
|
else |
|
{ |
|
delta.y *= -1; |
|
if (delta.y > 0) |
|
{ |
|
LeftTargetElement.preferredHeight = Mathf.Min(LeftTargetElement.preferredHeight + delta.y, summarySize.y - RightTargetElement.minHeight); |
|
RightTargetElement.preferredHeight = summarySize.y - LeftTargetElement.preferredHeight; |
|
} |
|
else |
|
{ |
|
RightTargetElement.preferredHeight = Mathf.Min(RightTargetElement.preferredHeight - delta.y, summarySize.y - LeftTargetElement.minHeight); |
|
LeftTargetElement.preferredHeight = summarySize.y - RightTargetElement.preferredHeight; |
|
} |
|
} |
|
} |
|
} |
|
} |