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.
699 lines
16 KiB
699 lines
16 KiB
3 years ago
|
using UnityEngine;
|
||
|
using UnityEngine.UI;
|
||
|
using UnityEngine.EventSystems;
|
||
|
using UnityEngine.Events;
|
||
|
using System.Collections.Generic;
|
||
|
using System;
|
||
|
|
||
|
namespace UIWidgets
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Resizable event.
|
||
|
/// </summary>
|
||
|
[Serializable]
|
||
|
public class ResizableEvent : UnityEvent<Resizable>
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Resizable.
|
||
|
/// N - north (top).
|
||
|
/// S - south (bottom).
|
||
|
/// E - east (right).
|
||
|
/// W - west (left).
|
||
|
/// </summary>
|
||
|
[AddComponentMenu("UI/UIWidgets/Resizable")]
|
||
|
public class Resizable : MonoBehaviour,
|
||
|
IInitializePotentialDragHandler, IBeginDragHandler, IEndDragHandler, IDragHandler,
|
||
|
IPointerEnterHandler, IPointerExitHandler
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Resize directions.
|
||
|
/// </summary>
|
||
|
[Serializable]
|
||
|
public struct Directions {
|
||
|
/// <summary>
|
||
|
/// Allow resize from top.
|
||
|
/// </summary>
|
||
|
public bool Top;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Allow resize from bottom.
|
||
|
/// </summary>
|
||
|
public bool Bottom;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Allow resize from left.
|
||
|
/// </summary>
|
||
|
public bool Left;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Allow resize from right.
|
||
|
/// </summary>
|
||
|
public bool Right;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes a new instance of the <see cref="UIWidgets.Resizable+Directions"/> struct.
|
||
|
/// </summary>
|
||
|
/// <param name="top">If set to <c>true</c> allow resize from top.</param>
|
||
|
/// <param name="bottom">If set to <c>true</c> allow resize from bottom.</param>
|
||
|
/// <param name="left">If set to <c>true</c> allow resize from left.</param>
|
||
|
/// <param name="right">If set to <c>true</c> allow resize from right.</param>
|
||
|
public Directions(bool top, bool bottom, bool left, bool right)
|
||
|
{
|
||
|
Top = top;
|
||
|
Bottom = bottom;
|
||
|
Left = left;
|
||
|
Right = right;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Active resize region.
|
||
|
/// </summary>
|
||
|
public struct Regions {
|
||
|
/// <summary>
|
||
|
/// The top.
|
||
|
/// </summary>
|
||
|
public bool Top;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The bottom.
|
||
|
/// </summary>
|
||
|
public bool Bottom;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The left.
|
||
|
/// </summary>
|
||
|
public bool Left;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The right.
|
||
|
/// </summary>
|
||
|
public bool Right;
|
||
|
|
||
|
/// <summary>
|
||
|
/// NWSE
|
||
|
/// </summary>
|
||
|
/// <value><c>true</c> if cursor mode is NWSE; otherwise, <c>false</c>.</value>
|
||
|
public bool NWSE {
|
||
|
get {
|
||
|
return (Top && Left) || (Bottom && Right);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// NESW.
|
||
|
/// </summary>
|
||
|
/// <value><c>true</c> if cursor mode is NESW; otherwise, <c>false</c>.</value>
|
||
|
public bool NESW {
|
||
|
get {
|
||
|
return (Top && Right) || (Bottom && Left);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// NS
|
||
|
/// </summary>
|
||
|
/// <value><c>true</c> if cursor mode is NS; otherwise, <c>false</c>.</value>
|
||
|
public bool NS {
|
||
|
get {
|
||
|
return (Top && !Right) || (Bottom && !Left);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// EW.
|
||
|
/// </summary>
|
||
|
/// <value><c>true</c> if cursor mode is EW; otherwise, <c>false</c>.</value>
|
||
|
public bool EW {
|
||
|
get {
|
||
|
return (!Top && Right) || (!Bottom && Left);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Is any region active.
|
||
|
/// </summary>
|
||
|
/// <value><c>true</c> if any region active; otherwise, <c>false</c>.</value>
|
||
|
public bool Active {
|
||
|
get {
|
||
|
return Top || Bottom || Left || Right;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Reset this instance.
|
||
|
/// </summary>
|
||
|
public void Reset()
|
||
|
{
|
||
|
Top = false;
|
||
|
Bottom = false;
|
||
|
Left = false;
|
||
|
Right = false;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns a string that represents the current object.
|
||
|
/// </summary>
|
||
|
/// <returns>A string that represents the current object.</returns>
|
||
|
public override string ToString()
|
||
|
{
|
||
|
return String.Format("Top: {0}; Bottom: {1}; Left: {2}; Right: {3}", Top, Bottom, Left, Right);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Is need to update RectTransform on Resize.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
public bool UpdateRectTransform = true;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Is need to update LayoutElement on Resize.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
public bool UpdateLayoutElement = true;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The active region in points from left or right border where resize allowed.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
[Tooltip("Maximum padding from border where resize active.")]
|
||
|
public float ActiveRegion = 5;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The minimum size.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
public Vector2 MinSize;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The maximum size.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
[Tooltip("Set 0 to unlimit.")]
|
||
|
public Vector2 MaxSize;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The keep aspect ratio.
|
||
|
/// Aspect ratio applied after MinSize and MaxSize, so if RectTransform aspect ratio not equal MinSize and MaxSize aspect ratio then real size may be outside limit with one of axis.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
public bool KeepAspectRatio;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Resize directions.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
public Directions ResizeDirections = new Directions(true, true, true, true);
|
||
|
|
||
|
/// <summary>
|
||
|
/// The current camera. For Screen Space - Overlay let it empty.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
public Camera CurrentCamera;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The cursor EW texture.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
public Texture2D CursorEWTexture;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The cursor EW hot spot.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
public Vector2 CursorEWHotSpot = new Vector2(16, 16);
|
||
|
|
||
|
/// <summary>
|
||
|
/// The cursor NS texture.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
public Texture2D CursorNSTexture;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The cursor NS hot spot.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
public Vector2 CursorNSHotSpot = new Vector2(16, 16);
|
||
|
|
||
|
/// <summary>
|
||
|
/// The cursor NESW texture.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
public Texture2D CursorNESWTexture;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The cursor NESW hot spot.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
public Vector2 CursorNESWHotSpot = new Vector2(16, 16);
|
||
|
|
||
|
/// <summary>
|
||
|
/// The cursor NWSE texture.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
public Texture2D CursorNWSETexture;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The cursor NWSE hot spot.
|
||
|
/// </summary>
|
||
|
[SerializeField]
|
||
|
public Vector2 CursorNWSEHotSpot = 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 ResizableEvent OnStartResize = new ResizableEvent();
|
||
|
|
||
|
/// <summary>
|
||
|
/// OnEndResize event.
|
||
|
/// </summary>
|
||
|
public ResizableEvent OnEndResize = new ResizableEvent();
|
||
|
|
||
|
RectTransform rectTransform;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the RectTransform.
|
||
|
/// </summary>
|
||
|
/// <value>RectTransform.</value>
|
||
|
public RectTransform RectTransform {
|
||
|
get {
|
||
|
if (rectTransform==null)
|
||
|
{
|
||
|
rectTransform = transform as RectTransform;
|
||
|
}
|
||
|
return rectTransform;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LayoutElement layoutElement;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Gets the LayoutElement.
|
||
|
/// </summary>
|
||
|
/// <value>LayoutElement.</value>
|
||
|
public LayoutElement LayoutElement {
|
||
|
get {
|
||
|
if (layoutElement==null)
|
||
|
{
|
||
|
layoutElement = GetComponent<LayoutElement>();
|
||
|
if (layoutElement==null)
|
||
|
{
|
||
|
layoutElement = gameObject.AddComponent<LayoutElement>();
|
||
|
}
|
||
|
}
|
||
|
return layoutElement;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Regions regions;
|
||
|
Regions dragRegions;
|
||
|
|
||
|
Canvas canvas;
|
||
|
RectTransform canvasRect;
|
||
|
|
||
|
bool processDrag;
|
||
|
|
||
|
void Start()
|
||
|
{
|
||
|
var layout = GetComponent<HorizontalOrVerticalLayoutGroup>();
|
||
|
if (layout)
|
||
|
{
|
||
|
Utilites.UpdateLayout(layout);
|
||
|
}
|
||
|
|
||
|
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()
|
||
|
{
|
||
|
canvasRect = Utilites.FindTopmostCanvas(transform) as RectTransform;
|
||
|
canvas = canvasRect.GetComponent<Canvas>();
|
||
|
}
|
||
|
|
||
|
protected static bool globalCursorSetted;
|
||
|
protected bool cursorChanged;
|
||
|
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;
|
||
|
|
||
|
globalCursorSetted = false;
|
||
|
cursorChanged = false;
|
||
|
Cursor.SetCursor(DefaultCursorTexture, DefaultCursorHotSpot, Utilites.GetCursorMode());
|
||
|
}
|
||
|
|
||
|
void LateUpdate()
|
||
|
{
|
||
|
if (globalCursorSetted && !cursorChanged)
|
||
|
{
|
||
|
return ;
|
||
|
}
|
||
|
globalCursorSetted = false;
|
||
|
if (!IsCursorOver)
|
||
|
{
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
if (processDrag)
|
||
|
{
|
||
|
return ;
|
||
|
}
|
||
|
if (!Input.mousePresent)
|
||
|
{
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
Vector2 point;
|
||
|
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(RectTransform, Input.mousePosition, CurrentCamera, out point))
|
||
|
{
|
||
|
return ;
|
||
|
}
|
||
|
var r = RectTransform.rect;
|
||
|
if (!r.Contains(point))
|
||
|
{
|
||
|
regions.Reset();
|
||
|
UpdateCursor();
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
UpdateRegions(point);
|
||
|
|
||
|
UpdateCursor();
|
||
|
}
|
||
|
|
||
|
void UpdateRegions(Vector2 point)
|
||
|
{
|
||
|
regions.Top = ResizeDirections.Top && CheckTop(point);
|
||
|
regions.Bottom = ResizeDirections.Bottom && CheckBottom(point);
|
||
|
regions.Left = ResizeDirections.Left && CheckLeft(point);
|
||
|
regions.Right = ResizeDirections.Right && CheckRight(point);
|
||
|
}
|
||
|
|
||
|
void UpdateCursor()
|
||
|
{
|
||
|
if (regions.NWSE)
|
||
|
{
|
||
|
globalCursorSetted = true;
|
||
|
cursorChanged = true;
|
||
|
Cursor.SetCursor(CursorNWSETexture, CursorNWSEHotSpot, Utilites.GetCursorMode());
|
||
|
}
|
||
|
else if (regions.NESW)
|
||
|
{
|
||
|
globalCursorSetted = true;
|
||
|
cursorChanged = true;
|
||
|
Cursor.SetCursor(CursorNESWTexture, CursorNESWHotSpot, Utilites.GetCursorMode());
|
||
|
}
|
||
|
else if (regions.NS)
|
||
|
{
|
||
|
globalCursorSetted = true;
|
||
|
cursorChanged = true;
|
||
|
Cursor.SetCursor(CursorNSTexture, CursorNSHotSpot, Utilites.GetCursorMode());
|
||
|
}
|
||
|
else if (regions.EW)
|
||
|
{
|
||
|
globalCursorSetted = true;
|
||
|
cursorChanged = true;
|
||
|
Cursor.SetCursor(CursorEWTexture, CursorEWHotSpot, Utilites.GetCursorMode());
|
||
|
}
|
||
|
else if (cursorChanged)
|
||
|
{
|
||
|
globalCursorSetted = false;
|
||
|
cursorChanged = false;
|
||
|
Cursor.SetCursor(DefaultCursorTexture, DefaultCursorHotSpot, Utilites.GetCursorMode());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Checks if point in the top region.
|
||
|
/// </summary>
|
||
|
/// <returns><c>true</c>, if point in the top region, <c>false</c> otherwise.</returns>
|
||
|
/// <param name="point">Point.</param>
|
||
|
bool CheckTop(Vector2 point)
|
||
|
{
|
||
|
var rect = RectTransform.rect;
|
||
|
|
||
|
rect.position = new Vector2(rect.position.x, rect.position.y + rect.height - ActiveRegion);
|
||
|
rect.height = ActiveRegion;
|
||
|
|
||
|
return rect.Contains(point);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Checks if point in the right region.
|
||
|
/// </summary>
|
||
|
/// <returns><c>true</c>, if right was checked, <c>false</c> otherwise.</returns>
|
||
|
/// <param name="point">Point.</param>
|
||
|
bool CheckBottom(Vector2 point)
|
||
|
{
|
||
|
var rect = RectTransform.rect;
|
||
|
rect.height = ActiveRegion;
|
||
|
|
||
|
return rect.Contains(point);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Checks if point in the left region.
|
||
|
/// </summary>
|
||
|
/// <returns><c>true</c>, if point in the left region, <c>false</c> otherwise.</returns>
|
||
|
/// <param name="point">Point.</param>
|
||
|
bool CheckLeft(Vector2 point)
|
||
|
{
|
||
|
var rect = RectTransform.rect;
|
||
|
rect.width = ActiveRegion;
|
||
|
|
||
|
return rect.Contains(point);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Checks if point in the right region.
|
||
|
/// </summary>
|
||
|
/// <returns><c>true</c>, if right was checked, <c>false</c> otherwise.</returns>
|
||
|
/// <param name="point">Point.</param>
|
||
|
bool CheckRight(Vector2 point)
|
||
|
{
|
||
|
var rect = RectTransform.rect;
|
||
|
|
||
|
rect.position = new Vector2(rect.position.x + rect.width - ActiveRegion, rect.position.y);
|
||
|
rect.width = ActiveRegion;
|
||
|
|
||
|
return rect.Contains(point);
|
||
|
}
|
||
|
|
||
|
/// <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 ;
|
||
|
}
|
||
|
|
||
|
UpdateRegions(point);
|
||
|
|
||
|
processDrag = regions.Active;
|
||
|
|
||
|
dragRegions = regions;
|
||
|
|
||
|
UpdateCursor();
|
||
|
|
||
|
LayoutElement.preferredHeight = RectTransform.rect.height;
|
||
|
LayoutElement.preferredWidth = RectTransform.rect.width;
|
||
|
|
||
|
OnStartResize.Invoke(this);
|
||
|
}
|
||
|
|
||
|
void ResetCursor()
|
||
|
{
|
||
|
globalCursorSetted = false;
|
||
|
cursorChanged = false;
|
||
|
|
||
|
Cursor.SetCursor(DefaultCursorTexture, DefaultCursorHotSpot, Utilites.GetCursorMode());
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Raises the end drag event.
|
||
|
/// </summary>
|
||
|
/// <param name="eventData">Event data.</param>
|
||
|
public void OnEndDrag(PointerEventData eventData)
|
||
|
{
|
||
|
ResetCursor();
|
||
|
|
||
|
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 (UpdateRectTransform)
|
||
|
{
|
||
|
PerformUpdateRectTransform(delta);
|
||
|
}
|
||
|
if (UpdateLayoutElement)
|
||
|
{
|
||
|
PerformUpdateLayoutElement(delta);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PerformUpdateRectTransform(Vector2 delta)
|
||
|
{
|
||
|
var pivot = RectTransform.pivot;
|
||
|
var size = RectTransform.rect.size;
|
||
|
var prev_size = size;
|
||
|
var sign = new Vector2(1, 1);
|
||
|
if (dragRegions.Left || dragRegions.Right)
|
||
|
{
|
||
|
sign.x = dragRegions.Right ? +1 : -1;
|
||
|
size.x = Mathf.Max(MinSize.x, size.x + (sign.x * delta.x));
|
||
|
if (MaxSize.x!=0f)
|
||
|
{
|
||
|
size.x = Mathf.Min(MaxSize.x, size.x);
|
||
|
}
|
||
|
}
|
||
|
if (dragRegions.Top || dragRegions.Bottom)
|
||
|
{
|
||
|
sign.y = dragRegions.Top ? +1 : -1;
|
||
|
size.y = Mathf.Max(MinSize.y, size.y + (sign.y * delta.y));
|
||
|
if (MaxSize.y!=0f)
|
||
|
{
|
||
|
size.y = Mathf.Min(MaxSize.y, size.y);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (KeepAspectRatio)
|
||
|
{
|
||
|
size = FixAspectRatio(size, prev_size);
|
||
|
}
|
||
|
|
||
|
var anchorSign = new Vector2(dragRegions.Right ? pivot.x : pivot.x - 1, dragRegions.Top ? pivot.y : pivot.y - 1);
|
||
|
var anchorDelta = size - prev_size;
|
||
|
anchorDelta = new Vector2(anchorDelta.x * anchorSign.x, anchorDelta.y * anchorSign.y);
|
||
|
|
||
|
RectTransform.anchoredPosition += anchorDelta;
|
||
|
RectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, size.x);
|
||
|
RectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size.y);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Fixs the aspect ratio.
|
||
|
/// </summary>
|
||
|
/// <returns>The aspect ratio.</returns>
|
||
|
/// <param name="newSize">New size.</param>
|
||
|
/// <param name="baseSize">Base size.</param>
|
||
|
protected Vector2 FixAspectRatio(Vector2 newSize, Vector2 baseSize)
|
||
|
{
|
||
|
var result = newSize;
|
||
|
|
||
|
var aspectRatio = baseSize.x / baseSize.y;
|
||
|
var sizeDelta = new Vector2(Mathf.Abs(newSize.x - baseSize.x), Mathf.Abs(newSize.y - baseSize.y));
|
||
|
if (sizeDelta.x >= sizeDelta.y)
|
||
|
{
|
||
|
result.y = result.x / aspectRatio;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
result.x = result.y * aspectRatio;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
void PerformUpdateLayoutElement(Vector2 delta)
|
||
|
{
|
||
|
var size = new Vector2(LayoutElement.preferredWidth, LayoutElement.preferredHeight);
|
||
|
var prev_size = size;
|
||
|
if (dragRegions.Left || dragRegions.Right)
|
||
|
{
|
||
|
var sign = (dragRegions.Right) ? +1 : -1;
|
||
|
var width = Mathf.Max(MinSize.x, LayoutElement.preferredWidth + (sign * delta.x));
|
||
|
if (MaxSize.x!=0f)
|
||
|
{
|
||
|
size.x = Mathf.Min(MaxSize.x, width);
|
||
|
}
|
||
|
}
|
||
|
if (dragRegions.Top || dragRegions.Bottom)
|
||
|
{
|
||
|
var sign = (dragRegions.Top) ? +1 : -1;
|
||
|
var height = Mathf.Max(MinSize.y, LayoutElement.preferredHeight + (sign * delta.y));
|
||
|
if (MaxSize.y!=0f)
|
||
|
{
|
||
|
size.y = Mathf.Min(MaxSize.y, height);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (KeepAspectRatio)
|
||
|
{
|
||
|
size = FixAspectRatio(size, prev_size);
|
||
|
}
|
||
|
|
||
|
LayoutElement.preferredWidth = size.x;
|
||
|
LayoutElement.preferredHeight = size.y;
|
||
|
}
|
||
|
}
|
||
|
}
|