1959 lines
46 KiB
C#
1959 lines
46 KiB
C#
|
|
//----------------------------------------------
|
|||
|
|
// NGUI: Next-Gen UI kit
|
|||
|
|
// Copyright © 2011-2015 Tasharen Entertainment
|
|||
|
|
//----------------------------------------------
|
|||
|
|
#define FUNCELL_MODIFIED
|
|||
|
|
|
|||
|
|
using UnityEngine;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Base class for all UI components that should be derived from when creating new widget types.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
[ExecuteInEditMode]
|
|||
|
|
[AddComponentMenu("NGUI/UI/NGUI Widget")]
|
|||
|
|
public class UIWidget : UIRect
|
|||
|
|
{
|
|||
|
|
public enum Pivot
|
|||
|
|
{
|
|||
|
|
TopLeft,
|
|||
|
|
Top,
|
|||
|
|
TopRight,
|
|||
|
|
Left,
|
|||
|
|
Center,
|
|||
|
|
Right,
|
|||
|
|
BottomLeft,
|
|||
|
|
Bottom,
|
|||
|
|
BottomRight,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Cached and saved values
|
|||
|
|
[HideInInspector][SerializeField] protected Color mColor = Color.white;
|
|||
|
|
#if FUNCELL_MODIFIED
|
|||
|
|
//保存上一帧的alhpa值,用于判断改变后计算alpha
|
|||
|
|
private float _oldAlpha = -1f;
|
|||
|
|
[System.NonSerialized] public bool IsOnlyWidget = false;
|
|||
|
|
#endif
|
|||
|
|
[HideInInspector][SerializeField] public bool useGradient = false;
|
|||
|
|
[HideInInspector][SerializeField] public Color ltColor = Color.white;
|
|||
|
|
[HideInInspector][SerializeField] public Color lbColor = Color.white;
|
|||
|
|
[HideInInspector][SerializeField] public Color rtColor = Color.white;
|
|||
|
|
[HideInInspector][SerializeField] public Color rbColor = Color.white;
|
|||
|
|
|
|||
|
|
[HideInInspector][SerializeField] protected Pivot mPivot = Pivot.Center;
|
|||
|
|
[HideInInspector][SerializeField] protected int mWidth = 100;
|
|||
|
|
[HideInInspector][SerializeField] protected int mHeight = 100;
|
|||
|
|
[HideInInspector][SerializeField] protected int mDepth = 0;
|
|||
|
|
[HideInInspector][SerializeField] protected Vector2 lbOffset = Vector2.zero;
|
|||
|
|
[HideInInspector][SerializeField] protected Vector2 ltOffset = Vector2.zero;
|
|||
|
|
[HideInInspector][SerializeField] protected Vector2 rbOffset = Vector2.zero;
|
|||
|
|
[HideInInspector][SerializeField] protected Vector2 rtOffset = Vector2.zero;
|
|||
|
|
|
|||
|
|
public delegate void OnDimensionsChanged ();
|
|||
|
|
public delegate void OnPostFillCallback (UIWidget widget, int bufferOffset, BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols);
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Notification triggered when the widget's dimensions or position changes.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public OnDimensionsChanged onChange;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Notification triggered after the widget's buffer has been filled.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public OnPostFillCallback onPostFill;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Callback triggered when the widget is about to be renderered (OnWillRenderObject).
|
|||
|
|
/// NOTE: This property is only exposed for the sake of speed to avoid property execution.
|
|||
|
|
/// In most cases you will want to use UIWidget.onRender instead.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public UIDrawCall.OnRenderCallback mOnRender;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Set the callback that will be triggered when the widget is being rendered (OnWillRenderObject).
|
|||
|
|
/// This is where you would set material properties and shader values.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public UIDrawCall.OnRenderCallback onRender
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return mOnRender;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
#if UNITY_FLASH
|
|||
|
|
if (!(mOnRender == value))
|
|||
|
|
#else
|
|||
|
|
if (mOnRender != value)
|
|||
|
|
#endif
|
|||
|
|
{
|
|||
|
|
#if !UNITY_FLASH
|
|||
|
|
if (drawCall != null && drawCall.onRender != null && mOnRender != null)
|
|||
|
|
drawCall.onRender -= mOnRender;
|
|||
|
|
#endif
|
|||
|
|
mOnRender = value;
|
|||
|
|
if (drawCall != null) drawCall.onRender += value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// If set to 'true', the box collider's dimensions will be adjusted to always match the widget whenever it resizes.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public bool autoResizeBoxCollider = false;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Hide the widget if it happens to be off-screen.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public bool hideIfOffScreen = false;
|
|||
|
|
|
|||
|
|
public enum AspectRatioSource
|
|||
|
|
{
|
|||
|
|
Free,
|
|||
|
|
BasedOnWidth,
|
|||
|
|
BasedOnHeight,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Whether the rectangle will attempt to maintain a specific aspect ratio.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public AspectRatioSource keepAspectRatio = AspectRatioSource.Free;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// If you want the anchored rectangle to keep a specific aspect ratio, set this value.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public float aspectRatio = 1f;
|
|||
|
|
|
|||
|
|
public delegate bool HitCheck (Vector3 worldPos);
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Custom hit check function. If set, all hit checks (including events) will call this function,
|
|||
|
|
/// passing the world position. Return 'true' if it's within the bounds of your choice, 'false' otherwise.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public HitCheck hitCheck;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Panel that's managing this widget.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
[System.NonSerialized] public UIPanel panel;
|
|||
|
|
//当前Panel的ID
|
|||
|
|
private int _panelInstID = 0;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Widget's generated geometry.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
[System.NonSerialized] public UIGeometry geometry = new UIGeometry();
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// If set to 'false', the widget's OnFill function will not be called, letting you define custom geometry at will.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
[System.NonSerialized] public bool fillGeometry = true;
|
|||
|
|
[System.NonSerialized] protected bool mPlayMode = true;
|
|||
|
|
[System.NonSerialized] protected Vector4 mDrawRegion = new Vector4(0f, 0f, 1f, 1f);
|
|||
|
|
[System.NonSerialized] Matrix4x4 mLocalToPanel;
|
|||
|
|
[System.NonSerialized] bool mIsVisibleByAlpha = true;
|
|||
|
|
[System.NonSerialized] bool mIsVisibleByPanel = true;
|
|||
|
|
[System.NonSerialized] bool mIsInFront = true;
|
|||
|
|
[System.NonSerialized] float mLastAlpha = 0f;
|
|||
|
|
[System.NonSerialized] bool mMoved = false;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Internal usage -- draw call that's drawing the widget.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
[System.NonSerialized] public UIDrawCall drawCall;
|
|||
|
|
[System.NonSerialized] protected Vector3[] mCorners = new Vector3[4];
|
|||
|
|
|
|||
|
|
#if FUNCELL_MODIFIED
|
|||
|
|
//是否为灰色
|
|||
|
|
[HideInInspector]
|
|||
|
|
[SerializeField]
|
|||
|
|
private bool _isGray = false;
|
|||
|
|
public bool IsGray
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _isGray;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (_isGray != value)
|
|||
|
|
{
|
|||
|
|
_isGray = value;
|
|||
|
|
OnReDrawWidget();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//是否为流光
|
|||
|
|
[HideInInspector]
|
|||
|
|
[SerializeField]
|
|||
|
|
private bool _isFlowLight = false;
|
|||
|
|
public bool IsFlowLight
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _isFlowLight;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (_isFlowLight != value)
|
|||
|
|
{
|
|||
|
|
_isFlowLight = value;
|
|||
|
|
OnReDrawWidget();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//流光的颜色--这里使用整形,容易比较(很坑的是Color32不能比较,所以选择这个值)
|
|||
|
|
//这里使用int来表示float,有效数字为10000.
|
|||
|
|
[HideInInspector]
|
|||
|
|
[SerializeField]
|
|||
|
|
private Vector3Int _flowColor = new Vector3Int(3000, 3000, 3000);
|
|||
|
|
public Vector3Int FlowColor
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _flowColor;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (_flowColor != value)
|
|||
|
|
{
|
|||
|
|
_flowColor = value;
|
|||
|
|
OnReDrawWidget();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//流光的参数 v1:宽度[0,10000] v2:速度, 光在UI上流过的速度 v3:滚动的位置[0,10000]
|
|||
|
|
//这里使用int来表示float,有效数字为10000.
|
|||
|
|
[HideInInspector]
|
|||
|
|
[SerializeField]
|
|||
|
|
private Vector3Int _flowParam = new Vector3Int(5000, 0, 0);
|
|||
|
|
public Vector3Int FlowParam
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _flowParam;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (_flowParam != value)
|
|||
|
|
{
|
|||
|
|
_flowParam = value;
|
|||
|
|
OnReDrawWidget();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
public int FlowWidth
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _flowParam.x;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (_flowParam.x != value)
|
|||
|
|
{
|
|||
|
|
_flowParam.x = value;
|
|||
|
|
OnReDrawWidget();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public int FlowSpeed
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _flowParam.y;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (_flowParam.y != value)
|
|||
|
|
{
|
|||
|
|
_flowParam.y = value;
|
|||
|
|
OnReDrawWidget();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public int FlowValue
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _flowParam.z;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (_flowParam.z != value)
|
|||
|
|
{
|
|||
|
|
_flowParam.z = value;
|
|||
|
|
OnReDrawWidget();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
[HideInInspector]
|
|||
|
|
[SerializeField]
|
|||
|
|
private bool _isAutoFlow = false;
|
|||
|
|
public bool IsAutoFlow
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _isAutoFlow;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (_isAutoFlow != value)
|
|||
|
|
{
|
|||
|
|
_isAutoFlow = value;
|
|||
|
|
if (_isAutoFlow)
|
|||
|
|
{
|
|||
|
|
_flowParam.y = 15000;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
_flowParam.y = 0;
|
|||
|
|
}
|
|||
|
|
OnReDrawWidget();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//是否为叠加
|
|||
|
|
[HideInInspector]
|
|||
|
|
[SerializeField]
|
|||
|
|
private bool _isOverlay = false;
|
|||
|
|
public bool IsOverlay
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return _isOverlay;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (_isOverlay != value)
|
|||
|
|
{
|
|||
|
|
_isOverlay = value;
|
|||
|
|
OnReDrawWidget();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//重新刷新Widget
|
|||
|
|
private void OnReDrawWidget()
|
|||
|
|
{
|
|||
|
|
if (panel != null) panel.RemoveWidget(this);
|
|||
|
|
|
|||
|
|
if (panel != null)
|
|||
|
|
{
|
|||
|
|
panel.AddWidget(this);
|
|||
|
|
|
|||
|
|
if (!Application.isPlaying)
|
|||
|
|
{
|
|||
|
|
panel.SortWidgets();
|
|||
|
|
panel.RebuildAllDrawCalls();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
NGUITools.SetDirty(this);
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endif
|
|||
|
|
/// <summary>
|
|||
|
|
/// Draw region alters how the widget looks without modifying the widget's rectangle.
|
|||
|
|
/// A region is made up of 4 relative values (0-1 range). The order is Left (X), Bottom (Y), Right (Z) and Top (W).
|
|||
|
|
/// To have a widget's left edge be 30% from the left side, set X to 0.3. To have the widget's right edge be 30%
|
|||
|
|
/// from the right hand side, set Z to 0.7.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public Vector4 drawRegion
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return mDrawRegion;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (mDrawRegion != value)
|
|||
|
|
{
|
|||
|
|
mDrawRegion = value;
|
|||
|
|
if (autoResizeBoxCollider) ResizeCollider();
|
|||
|
|
MarkAsChanged();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Pivot offset in relative coordinates. Bottom-left is (0, 0). Top-right is (1, 1).
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public Vector2 pivotOffset { get { return NGUIMath.GetPivotOffset(pivot); } }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Widget's width in pixels.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public int width
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return mWidth;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
int min = minWidth;
|
|||
|
|
if (value < min) value = min;
|
|||
|
|
|
|||
|
|
if (mWidth != value && keepAspectRatio != AspectRatioSource.BasedOnHeight)
|
|||
|
|
{
|
|||
|
|
if (isAnchoredHorizontally)
|
|||
|
|
{
|
|||
|
|
if (leftAnchor.target != null && rightAnchor.target != null)
|
|||
|
|
{
|
|||
|
|
if (mPivot == Pivot.BottomLeft || mPivot == Pivot.Left || mPivot == Pivot.TopLeft)
|
|||
|
|
{
|
|||
|
|
NGUIMath.AdjustWidget(this, 0f, 0f, value - mWidth, 0f);
|
|||
|
|
}
|
|||
|
|
else if (mPivot == Pivot.BottomRight || mPivot == Pivot.Right || mPivot == Pivot.TopRight)
|
|||
|
|
{
|
|||
|
|
NGUIMath.AdjustWidget(this, mWidth - value, 0f, 0f, 0f);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
int diff = value - mWidth;
|
|||
|
|
diff = diff - (diff & 1);
|
|||
|
|
if (diff != 0) NGUIMath.AdjustWidget(this, -diff * 0.5f, 0f, diff * 0.5f, 0f);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (leftAnchor.target != null)
|
|||
|
|
{
|
|||
|
|
NGUIMath.AdjustWidget(this, 0f, 0f, value - mWidth, 0f);
|
|||
|
|
}
|
|||
|
|
else NGUIMath.AdjustWidget(this, mWidth - value, 0f, 0f, 0f);
|
|||
|
|
}
|
|||
|
|
else SetDimensions(value, mHeight);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Widget's height in pixels.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public int height
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return mHeight;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
int min = minHeight;
|
|||
|
|
if (value < min) value = min;
|
|||
|
|
|
|||
|
|
if (mHeight != value && keepAspectRatio != AspectRatioSource.BasedOnWidth)
|
|||
|
|
{
|
|||
|
|
if (isAnchoredVertically)
|
|||
|
|
{
|
|||
|
|
if (bottomAnchor.target != null && topAnchor.target != null)
|
|||
|
|
{
|
|||
|
|
if (mPivot == Pivot.BottomLeft || mPivot == Pivot.Bottom || mPivot == Pivot.BottomRight)
|
|||
|
|
{
|
|||
|
|
NGUIMath.AdjustWidget(this, 0f, 0f, 0f, value - mHeight);
|
|||
|
|
}
|
|||
|
|
else if (mPivot == Pivot.TopLeft || mPivot == Pivot.Top || mPivot == Pivot.TopRight)
|
|||
|
|
{
|
|||
|
|
NGUIMath.AdjustWidget(this, 0f, mHeight - value, 0f, 0f);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
int diff = value - mHeight;
|
|||
|
|
diff = diff - (diff & 1);
|
|||
|
|
if (diff != 0) NGUIMath.AdjustWidget(this, 0f, -diff * 0.5f, 0f, diff * 0.5f);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (bottomAnchor.target != null)
|
|||
|
|
{
|
|||
|
|
NGUIMath.AdjustWidget(this, 0f, 0f, 0f, value - mHeight);
|
|||
|
|
}
|
|||
|
|
else NGUIMath.AdjustWidget(this, 0f, mHeight - value, 0f, 0f);
|
|||
|
|
}
|
|||
|
|
else SetDimensions(mWidth, value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Color used by the widget.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public Color color
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return mColor;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (mColor != value)
|
|||
|
|
{
|
|||
|
|
bool alphaChange = (mColor.a != value.a);
|
|||
|
|
mColor = value;
|
|||
|
|
Invalidate(alphaChange);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Widget's alpha -- a convenience method.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public override float alpha
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return mColor.a;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
float val = Mathf.Clamp01(value);
|
|||
|
|
if (mColor.a != val)
|
|||
|
|
{
|
|||
|
|
mColor.a = val;
|
|||
|
|
Invalidate(true, true);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Whether the widget is currently visible.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public bool isVisible { get { return mIsVisibleByPanel && mIsVisibleByAlpha && mIsInFront && finalAlpha > 0.001f && NGUITools.GetActive(this); } }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Whether the widget has vertices to draw.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public bool hasVertices { get { return geometry != null && geometry.hasVertices; } }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Change the pivot point and do not attempt to keep the widget in the same place by adjusting its transform.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public Pivot rawPivot
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return mPivot;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (mPivot != value)
|
|||
|
|
{
|
|||
|
|
mPivot = value;
|
|||
|
|
if (autoResizeBoxCollider) ResizeCollider();
|
|||
|
|
MarkAsChanged();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Set or get the value that specifies where the widget's pivot point should be.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public Pivot pivot
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return mPivot;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (mPivot != value)
|
|||
|
|
{
|
|||
|
|
Vector3 before = worldCorners[0];
|
|||
|
|
|
|||
|
|
mPivot = value;
|
|||
|
|
mChanged = true;
|
|||
|
|
|
|||
|
|
Vector3 after = worldCorners[0];
|
|||
|
|
|
|||
|
|
Transform t = cachedTransform;
|
|||
|
|
Vector3 pos = t.position;
|
|||
|
|
float z = t.localPosition.z;
|
|||
|
|
pos.x += (before.x - after.x);
|
|||
|
|
pos.y += (before.y - after.y);
|
|||
|
|
cachedTransform.position = pos;
|
|||
|
|
|
|||
|
|
pos = cachedTransform.localPosition;
|
|||
|
|
pos.x = Mathf.Round(pos.x);
|
|||
|
|
pos.y = Mathf.Round(pos.y);
|
|||
|
|
pos.z = z;
|
|||
|
|
cachedTransform.localPosition = pos;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Depth controls the rendering order -- lowest to highest.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public int depth
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
// Experiment with a transform-based depth, uGUI style
|
|||
|
|
//if (mDepth == int.MinValue)
|
|||
|
|
//{
|
|||
|
|
// int val = cachedTransform.GetSiblingIndex();
|
|||
|
|
// UIWidget pt = parent as UIWidget;
|
|||
|
|
// if (pt != null) val += pt.depth;
|
|||
|
|
// return val;
|
|||
|
|
//}
|
|||
|
|
return mDepth;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
if (mDepth != value)
|
|||
|
|
{
|
|||
|
|
if (panel != null) panel.RemoveWidget(this);
|
|||
|
|
mDepth = value;
|
|||
|
|
|
|||
|
|
if (panel != null)
|
|||
|
|
{
|
|||
|
|
panel.AddWidget(this);
|
|||
|
|
|
|||
|
|
if (!Application.isPlaying)
|
|||
|
|
{
|
|||
|
|
panel.SortWidgets();
|
|||
|
|
panel.RebuildAllDrawCalls();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
NGUITools.SetDirty(this);
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Raycast depth order on widgets takes the depth of their panel into consideration.
|
|||
|
|
/// This functionality is used to determine the "final" depth of the widget for drawing and raycasts.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public int raycastDepth
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
if (panel == null) CreatePanel();
|
|||
|
|
return (panel != null) ? mDepth + panel.depth * 10000 : mDepth;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Local space corners of the widget. The order is bottom-left, top-left, top-right, bottom-right.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public override Vector3[] localCorners
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
Vector2 offset = pivotOffset;
|
|||
|
|
|
|||
|
|
float x0 = -offset.x * mWidth;
|
|||
|
|
float y0 = -offset.y * mHeight;
|
|||
|
|
float x1 = x0 + mWidth;
|
|||
|
|
float y1 = y0 + mHeight;
|
|||
|
|
|
|||
|
|
mCorners[0] = new Vector3(x0, y0);
|
|||
|
|
mCorners[1] = new Vector3(x0, y1);
|
|||
|
|
mCorners[2] = new Vector3(x1, y1);
|
|||
|
|
mCorners[3] = new Vector3(x1, y0);
|
|||
|
|
|
|||
|
|
return mCorners;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Local width and height of the widget in pixels.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public virtual Vector2 localSize
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
Vector3[] cr = localCorners;
|
|||
|
|
return cr[2] - cr[0];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Widget's center in local coordinates. Don't forget to transform by the widget's transform.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public Vector3 localCenter
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
Vector3[] cr = localCorners;
|
|||
|
|
return Vector3.Lerp(cr[0], cr[2], 0.5f);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// World-space corners of the widget. The order is bottom-left, top-left, top-right, bottom-right.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public override Vector3[] worldCorners
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
Vector2 offset = pivotOffset;
|
|||
|
|
|
|||
|
|
float x0 = -offset.x * mWidth;
|
|||
|
|
float y0 = -offset.y * mHeight;
|
|||
|
|
float x1 = x0 + mWidth;
|
|||
|
|
float y1 = y0 + mHeight;
|
|||
|
|
|
|||
|
|
Transform wt = cachedTransform;
|
|||
|
|
|
|||
|
|
mCorners[0] = wt.TransformPoint(x0, y0, 0f);
|
|||
|
|
mCorners[1] = wt.TransformPoint(x0, y1, 0f);
|
|||
|
|
mCorners[2] = wt.TransformPoint(x1, y1, 0f);
|
|||
|
|
mCorners[3] = wt.TransformPoint(x1, y0, 0f);
|
|||
|
|
|
|||
|
|
return mCorners;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// World-space center of the widget.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public Vector3 worldCenter { get { return cachedTransform.TransformPoint(localCenter); } }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Local space region where the actual drawing will take place.
|
|||
|
|
/// X = left, Y = bottom, Z = right, W = top.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public virtual Vector4 drawingDimensions
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
Vector2 offset = pivotOffset;
|
|||
|
|
|
|||
|
|
float x0 = -offset.x * mWidth;
|
|||
|
|
float y0 = -offset.y * mHeight;
|
|||
|
|
float x1 = x0 + mWidth;
|
|||
|
|
float y1 = y0 + mHeight;
|
|||
|
|
|
|||
|
|
return new Vector4(
|
|||
|
|
mDrawRegion.x == 0f ? x0 : Mathf.Lerp(x0, x1, mDrawRegion.x),
|
|||
|
|
mDrawRegion.y == 0f ? y0 : Mathf.Lerp(y0, y1, mDrawRegion.y),
|
|||
|
|
mDrawRegion.z == 1f ? x1 : Mathf.Lerp(x0, x1, mDrawRegion.z),
|
|||
|
|
mDrawRegion.w == 1f ? y1 : Mathf.Lerp(y0, y1, mDrawRegion.w));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Material used by the widget.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public virtual Material material
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
throw new System.NotImplementedException(GetType() + " has no material setter");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Texture used by the widget.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public virtual Texture mainTexture
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
Material mat = material;
|
|||
|
|
return (mat != null) ? mat.mainTexture : null;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
throw new System.NotImplementedException(GetType() + " has no mainTexture setter");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Shader is used to create a dynamic material if the widget has no material to work with.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public virtual Shader shader
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
Material mat = material;
|
|||
|
|
return (mat != null) ? mat.shader : null;
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
throw new System.NotImplementedException(GetType() + " has no shader setter");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Do not use this, it's obsolete.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
[System.Obsolete("There is no relative scale anymore. Widgets now have width and height instead")]
|
|||
|
|
public Vector2 relativeSize { get { return Vector2.one; } }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Convenience function that returns 'true' if the widget has a box collider.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public bool hasBoxCollider
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7
|
|||
|
|
BoxCollider box = collider as BoxCollider;
|
|||
|
|
#else
|
|||
|
|
BoxCollider box = GetComponent<Collider>() as BoxCollider;
|
|||
|
|
#endif
|
|||
|
|
if (box != null) return true;
|
|||
|
|
return GetComponent<BoxCollider2D>() != null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Adjust the widget's dimensions without going through the anchor validation logic.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public void SetDimensions (int w, int h)
|
|||
|
|
{
|
|||
|
|
if (mWidth != w || mHeight != h)
|
|||
|
|
{
|
|||
|
|
mWidth = w;
|
|||
|
|
mHeight = h;
|
|||
|
|
|
|||
|
|
if (keepAspectRatio == AspectRatioSource.BasedOnWidth)
|
|||
|
|
mHeight = Mathf.RoundToInt(mWidth / aspectRatio);
|
|||
|
|
else if (keepAspectRatio == AspectRatioSource.BasedOnHeight)
|
|||
|
|
mWidth = Mathf.RoundToInt(mHeight * aspectRatio);
|
|||
|
|
else if (keepAspectRatio == AspectRatioSource.Free)
|
|||
|
|
aspectRatio = mWidth / (float)mHeight;
|
|||
|
|
|
|||
|
|
mMoved = true;
|
|||
|
|
if (autoResizeBoxCollider) ResizeCollider();
|
|||
|
|
MarkAsChanged();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Get the sides of the rectangle relative to the specified transform.
|
|||
|
|
/// The order is left, top, right, bottom.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public override Vector3[] GetSides (Transform relativeTo)
|
|||
|
|
{
|
|||
|
|
Vector2 offset = pivotOffset;
|
|||
|
|
|
|||
|
|
float x0 = -offset.x * mWidth;
|
|||
|
|
float y0 = -offset.y * mHeight;
|
|||
|
|
float x1 = x0 + mWidth;
|
|||
|
|
float y1 = y0 + mHeight;
|
|||
|
|
float cx = (x0 + x1) * 0.5f;
|
|||
|
|
float cy = (y0 + y1) * 0.5f;
|
|||
|
|
|
|||
|
|
Transform trans = cachedTransform;
|
|||
|
|
mCorners[0] = trans.TransformPoint(x0, cy, 0f);
|
|||
|
|
mCorners[1] = trans.TransformPoint(cx, y1, 0f);
|
|||
|
|
mCorners[2] = trans.TransformPoint(x1, cy, 0f);
|
|||
|
|
mCorners[3] = trans.TransformPoint(cx, y0, 0f);
|
|||
|
|
|
|||
|
|
if (relativeTo != null)
|
|||
|
|
{
|
|||
|
|
for (int i = 0; i < 4; ++i)
|
|||
|
|
mCorners[i] = relativeTo.InverseTransformPoint(mCorners[i]);
|
|||
|
|
}
|
|||
|
|
return mCorners;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
[System.NonSerialized] int mAlphaFrameID = -1;
|
|||
|
|
|
|||
|
|
#if FUNCELL_MODIFIED
|
|||
|
|
public override void SelfCalculateFinalAlpha(float parentAlpha)
|
|||
|
|
{
|
|||
|
|
finalAlpha = parentAlpha * mColor.a;
|
|||
|
|
for(int i = 0; i < mChildren.size; ++i)
|
|||
|
|
{
|
|||
|
|
mChildren[i].SelfCalculateFinalAlpha(finalAlpha);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Widget's final alpha, after taking the panel's alpha into account.
|
|||
|
|
/// </summary>
|
|||
|
|
///
|
|||
|
|
|
|||
|
|
public override float CalculateFinalAlpha (int frameID)
|
|||
|
|
{
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
if (mAlphaFrameID != frameID || !Application.isPlaying)
|
|||
|
|
#else
|
|||
|
|
if (mAlphaFrameID != frameID)
|
|||
|
|
#endif
|
|||
|
|
{
|
|||
|
|
mAlphaFrameID = frameID;
|
|||
|
|
UpdateFinalAlpha(frameID);
|
|||
|
|
}
|
|||
|
|
return finalAlpha;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Force-calculate the final alpha value.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
protected void UpdateFinalAlpha (int frameID)
|
|||
|
|
{
|
|||
|
|
if (!mIsVisibleByAlpha || !mIsInFront)
|
|||
|
|
{
|
|||
|
|
finalAlpha = 0f;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
UIRect pt = parent;
|
|||
|
|
finalAlpha = (pt != null) ? pt.CalculateFinalAlpha(frameID) * mColor.a : mColor.a;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Update the widget's visibility and final alpha.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public override void Invalidate (bool includeChildren, bool onlyAlphaChange = false)
|
|||
|
|
{
|
|||
|
|
if(!onlyAlphaChange)
|
|||
|
|
{
|
|||
|
|
mChanged = true;
|
|||
|
|
}
|
|||
|
|
mAlphaFrameID = -1;
|
|||
|
|
|
|||
|
|
if (panel != null)
|
|||
|
|
{
|
|||
|
|
bool vis = (hideIfOffScreen || panel.hasCumulativeClipping) ? panel.IsVisible(this) : true;
|
|||
|
|
UpdateVisibility(CalculateCumulativeAlpha(Time.frameCount) > 0.001f, vis);
|
|||
|
|
UpdateFinalAlpha(Time.frameCount);
|
|||
|
|
if (includeChildren) base.Invalidate(true, onlyAlphaChange);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Same as final alpha, except it doesn't take own visibility into consideration. Used by panels.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public float CalculateCumulativeAlpha (int frameID)
|
|||
|
|
{
|
|||
|
|
UIRect pt = parent;
|
|||
|
|
return (pt != null) ? pt.CalculateFinalAlpha(frameID) * mColor.a : mColor.a;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Set the widget's rectangle.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public override void SetRect (float x, float y, float width, float height)
|
|||
|
|
{
|
|||
|
|
Vector2 po = pivotOffset;
|
|||
|
|
|
|||
|
|
float fx = Mathf.Lerp(x, x + width, po.x);
|
|||
|
|
float fy = Mathf.Lerp(y, y + height, po.y);
|
|||
|
|
|
|||
|
|
int finalWidth = Mathf.FloorToInt(width + 0.5f);
|
|||
|
|
int finalHeight = Mathf.FloorToInt(height + 0.5f);
|
|||
|
|
|
|||
|
|
if (po.x == 0.5f) finalWidth = ((finalWidth >> 1) << 1);
|
|||
|
|
if (po.y == 0.5f) finalHeight = ((finalHeight >> 1) << 1);
|
|||
|
|
|
|||
|
|
Transform t = cachedTransform;
|
|||
|
|
Vector3 pos = t.localPosition;
|
|||
|
|
pos.x = Mathf.Floor(fx + 0.5f);
|
|||
|
|
pos.y = Mathf.Floor(fy + 0.5f);
|
|||
|
|
|
|||
|
|
if (finalWidth < minWidth) finalWidth = minWidth;
|
|||
|
|
if (finalHeight < minHeight) finalHeight = minHeight;
|
|||
|
|
|
|||
|
|
t.localPosition = pos;
|
|||
|
|
this.width = finalWidth;
|
|||
|
|
this.height = finalHeight;
|
|||
|
|
|
|||
|
|
if (isAnchored)
|
|||
|
|
{
|
|||
|
|
t = t.parent;
|
|||
|
|
|
|||
|
|
if (leftAnchor.target) leftAnchor.SetHorizontal(t, x);
|
|||
|
|
if (rightAnchor.target) rightAnchor.SetHorizontal(t, x + width);
|
|||
|
|
if (bottomAnchor.target) bottomAnchor.SetVertical(t, y);
|
|||
|
|
if (topAnchor.target) topAnchor.SetVertical(t, y + height);
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
NGUITools.SetDirty(this);
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Adjust the widget's collider size to match the widget's dimensions.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public void ResizeCollider () { if (this.enabled) NGUITools.UpdateWidgetCollider(gameObject); }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Static widget comparison function used for depth sorting.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
[System.Diagnostics.DebuggerHidden]
|
|||
|
|
[System.Diagnostics.DebuggerStepThrough]
|
|||
|
|
static public int FullCompareFunc (UIWidget left, UIWidget right)
|
|||
|
|
{
|
|||
|
|
int val = UIPanel.CompareFunc(left.panel, right.panel);
|
|||
|
|
return (val == 0) ? PanelCompareFunc(left, right) : val;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Static widget comparison function used for inter-panel depth sorting.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
[System.Diagnostics.DebuggerHidden]
|
|||
|
|
[System.Diagnostics.DebuggerStepThrough]
|
|||
|
|
static public int PanelCompareFunc (UIWidget left, UIWidget right)
|
|||
|
|
{
|
|||
|
|
if (left.mDepth < right.mDepth) return -1;
|
|||
|
|
if (left.mDepth > right.mDepth) return 1;
|
|||
|
|
|
|||
|
|
Material leftMat = left.material;
|
|||
|
|
Material rightMat = right.material;
|
|||
|
|
|
|||
|
|
if (leftMat == rightMat) return 0;
|
|||
|
|
if (leftMat == null) return 1;
|
|||
|
|
if (rightMat == null) return -1;
|
|||
|
|
|
|||
|
|
#if FUNCELL_MODIFIED
|
|||
|
|
bool leftGray = left.IsGray;
|
|||
|
|
bool rightGray = right.IsGray;
|
|||
|
|
|
|||
|
|
if (leftGray == rightGray) return 0;
|
|||
|
|
if (leftGray) return 1;
|
|||
|
|
if (rightGray) return -1;
|
|||
|
|
|
|||
|
|
bool leftFlow = left.IsFlowLight;
|
|||
|
|
bool rightFlow = right.IsFlowLight;
|
|||
|
|
|
|||
|
|
if (leftFlow == rightFlow) return 0;
|
|||
|
|
if (leftFlow) return 1;
|
|||
|
|
if (rightFlow) return -1;
|
|||
|
|
|
|||
|
|
bool leftOverlay = left.IsOverlay;
|
|||
|
|
bool rightOverlay = right.IsOverlay;
|
|||
|
|
|
|||
|
|
if (leftOverlay == rightOverlay) return 0;
|
|||
|
|
if (leftOverlay) return 1;
|
|||
|
|
if (rightOverlay) return -1;
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
return (leftMat.GetHashCode() < rightMat.GetHashCode()) ? -1 : 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Calculate the widget's bounds, optionally making them relative to the specified transform.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public Bounds CalculateBounds () { return CalculateBounds(null); }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Calculate the widget's bounds, optionally making them relative to the specified transform.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public Bounds CalculateBounds (Transform relativeParent)
|
|||
|
|
{
|
|||
|
|
if (relativeParent == null)
|
|||
|
|
{
|
|||
|
|
Vector3[] corners = localCorners;
|
|||
|
|
Bounds b = new Bounds(corners[0], Vector3.zero);
|
|||
|
|
for (int j = 1; j < 4; ++j) b.Encapsulate(corners[j]);
|
|||
|
|
return b;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Matrix4x4 toLocal = relativeParent.worldToLocalMatrix;
|
|||
|
|
Vector3[] corners = worldCorners;
|
|||
|
|
Bounds b = new Bounds(toLocal.MultiplyPoint3x4(corners[0]), Vector3.zero);
|
|||
|
|
for (int j = 1; j < 4; ++j) b.Encapsulate(toLocal.MultiplyPoint3x4(corners[j]));
|
|||
|
|
return b;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Mark the widget as changed so that the geometry can be rebuilt.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public void SetDirty ()
|
|||
|
|
{
|
|||
|
|
if (drawCall != null)
|
|||
|
|
{
|
|||
|
|
drawCall.isDirty = true;
|
|||
|
|
}
|
|||
|
|
else if (isVisible && hasVertices)
|
|||
|
|
{
|
|||
|
|
CreatePanel();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Remove this widget from the panel.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public void RemoveFromPanel ()
|
|||
|
|
{
|
|||
|
|
if (panel != null)
|
|||
|
|
{
|
|||
|
|
panel.RemoveWidget(this);
|
|||
|
|
panel = null;
|
|||
|
|
_panelInstID = 0;
|
|||
|
|
}
|
|||
|
|
drawCall = null;
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
mOldTex = null;
|
|||
|
|
mOldShader = null;
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
[System.NonSerialized] Texture mOldTex;
|
|||
|
|
[System.NonSerialized] Shader mOldShader;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// This callback is sent inside the editor notifying us that some property has changed.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
protected override void OnValidate()
|
|||
|
|
{
|
|||
|
|
if (NGUITools.GetActive(this))
|
|||
|
|
{
|
|||
|
|
base.OnValidate();
|
|||
|
|
|
|||
|
|
// Prior to NGUI 2.7.0 width and height was specified as transform's local scale
|
|||
|
|
if ((mWidth == 100 || mWidth == minWidth) &&
|
|||
|
|
(mHeight == 100 || mHeight == minHeight) && cachedTransform.localScale.magnitude > 8f)
|
|||
|
|
{
|
|||
|
|
UpgradeFrom265();
|
|||
|
|
cachedTransform.localScale = Vector3.one;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (mWidth < minWidth) mWidth = minWidth;
|
|||
|
|
if (mHeight < minHeight) mHeight = minHeight;
|
|||
|
|
if (autoResizeBoxCollider) ResizeCollider();
|
|||
|
|
|
|||
|
|
// If the texture is changing, we need to make sure to rebuild the draw calls
|
|||
|
|
if (mOldTex != mainTexture || mOldShader != shader)
|
|||
|
|
{
|
|||
|
|
mOldTex = mainTexture;
|
|||
|
|
mOldShader = shader;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
aspectRatio = (keepAspectRatio == AspectRatioSource.Free) ?
|
|||
|
|
(float)mWidth / mHeight : Mathf.Max(0.01f, aspectRatio);
|
|||
|
|
|
|||
|
|
if (keepAspectRatio == AspectRatioSource.BasedOnHeight)
|
|||
|
|
{
|
|||
|
|
mWidth = Mathf.RoundToInt(mHeight * aspectRatio);
|
|||
|
|
}
|
|||
|
|
else if (keepAspectRatio == AspectRatioSource.BasedOnWidth)
|
|||
|
|
{
|
|||
|
|
mHeight = Mathf.RoundToInt(mWidth / aspectRatio);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!Application.isPlaying)
|
|||
|
|
{
|
|||
|
|
if (panel != null)
|
|||
|
|
{
|
|||
|
|
panel.RemoveWidget(this);
|
|||
|
|
panel = null;
|
|||
|
|
_panelInstID = 0;
|
|||
|
|
}
|
|||
|
|
CreatePanel();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (mWidth < minWidth) mWidth = minWidth;
|
|||
|
|
if (mHeight < minHeight) mHeight = minHeight;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Tell the panel responsible for the widget that something has changed and the buffers need to be rebuilt.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public virtual void MarkAsChanged ()
|
|||
|
|
{
|
|||
|
|
if (NGUITools.GetActive(this))
|
|||
|
|
{
|
|||
|
|
mChanged = true;
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
NGUITools.SetDirty(this);
|
|||
|
|
#endif
|
|||
|
|
// If we're in the editor, update the panel right away so its geometry gets updated.
|
|||
|
|
if (panel != null && enabled && NGUITools.GetActive(gameObject) && !mPlayMode)
|
|||
|
|
{
|
|||
|
|
SetDirty();
|
|||
|
|
CheckLayer();
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
// Mark the panel as dirty so it gets updated
|
|||
|
|
if (material != null) NGUITools.SetDirty(panel.gameObject);
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#if FUNCELL_MODIFIED
|
|||
|
|
/// <summary>
|
|||
|
|
/// Ensure we have a panel referencing this widget.
|
|||
|
|
/// </summary>
|
|||
|
|
public bool CreatePanel ()
|
|||
|
|
{
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
bool isActive = false;
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
isActive = NGUITools.GetActive(gameObject);
|
|||
|
|
}
|
|||
|
|
catch (System.Exception ex0)
|
|||
|
|
{
|
|||
|
|
Debug.LogError("NGUITools.GetActive::::::" + ID.ToString() + "::::" + ex0.Message);
|
|||
|
|
Debug.LogException(ex0);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
if (mStarted && panel == null && enabled && isActive)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
panel = UIPanel.Find(cachedTransform, true, cachedGameObject.layer);
|
|||
|
|
if (panel != null)
|
|||
|
|
{
|
|||
|
|
mParentFound = false;
|
|||
|
|
panel.AddWidget(this);
|
|||
|
|
CheckLayer();
|
|||
|
|
Invalidate(true);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (System.Exception ex1)
|
|||
|
|
{
|
|||
|
|
Debug.LogError("CreatePanel::::::" + ID.ToString() + "::::" + ex1.Message);
|
|||
|
|
Debug.LogException(ex1);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
_panelInstID = 0;
|
|||
|
|
if (panel) _panelInstID = panel.GetInstanceID();
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#else
|
|||
|
|
/// <summary>
|
|||
|
|
/// Ensure we have a panel referencing this widget.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public UIPanel CreatePanel ()
|
|||
|
|
{
|
|||
|
|
if (mStarted && panel == null && enabled && NGUITools.GetActive(gameObject))
|
|||
|
|
{
|
|||
|
|
panel = UIPanel.Find(cachedTransform, true, cachedGameObject.layer);
|
|||
|
|
|
|||
|
|
if (panel != null)
|
|||
|
|
{
|
|||
|
|
mParentFound = false;
|
|||
|
|
panel.AddWidget(this);
|
|||
|
|
CheckLayer();
|
|||
|
|
Invalidate(true);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (panel) _panelInstID = panel.GetInstanceID();
|
|||
|
|
return panel;
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Check to ensure that the widget resides on the same layer as its panel.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public void CheckLayer ()
|
|||
|
|
{
|
|||
|
|
if (panel != null && panel.gameObject.layer != gameObject.layer)
|
|||
|
|
{
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
Debug.LogWarning("You can't place widgets on a layer different than the UIPanel that manages them.\n" +
|
|||
|
|
"If you want to move widgets to a different layer, parent them to a new panel instead.", this);
|
|||
|
|
#endif
|
|||
|
|
gameObject.layer = panel.gameObject.layer;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Checks to ensure that the widget is still parented to the right panel.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public override void ParentHasChanged ()
|
|||
|
|
{
|
|||
|
|
base.ParentHasChanged();
|
|||
|
|
|
|||
|
|
if (panel != null)
|
|||
|
|
{
|
|||
|
|
UIPanel p = UIPanel.Find(cachedTransform, true, cachedGameObject.layer);
|
|||
|
|
|
|||
|
|
if (panel != p)
|
|||
|
|
{
|
|||
|
|
RemoveFromPanel();
|
|||
|
|
CreatePanel();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Remember whether we're in play mode.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
protected override void Awake ()
|
|||
|
|
{
|
|||
|
|
base.Awake();
|
|||
|
|
mPlayMode = Application.isPlaying;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Mark the widget and the panel as having been changed.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
protected override void OnInit ()
|
|||
|
|
{
|
|||
|
|
base.OnInit();
|
|||
|
|
RemoveFromPanel();
|
|||
|
|
mMoved = true;
|
|||
|
|
|
|||
|
|
// Prior to NGUI 2.7.0 width and height was specified as transform's local scale
|
|||
|
|
if (mWidth == 100 && mHeight == 100 && cachedTransform.localScale.magnitude > 8f)
|
|||
|
|
{
|
|||
|
|
UpgradeFrom265();
|
|||
|
|
cachedTransform.localScale = Vector3.one;
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
NGUITools.SetDirty(this);
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
#if FUNCELL_MODIFIED
|
|||
|
|
SelfUpdate();
|
|||
|
|
#else
|
|||
|
|
Update();
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Facilitates upgrading from NGUI 2.6.5 or earlier versions.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
protected virtual void UpgradeFrom265 ()
|
|||
|
|
{
|
|||
|
|
Vector3 scale = cachedTransform.localScale;
|
|||
|
|
mWidth = Mathf.Abs(Mathf.RoundToInt(scale.x));
|
|||
|
|
mHeight = Mathf.Abs(Mathf.RoundToInt(scale.y));
|
|||
|
|
NGUITools.UpdateWidgetCollider(gameObject, true);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Virtual Start() functionality for widgets.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
protected override void OnStart ()
|
|||
|
|
{
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
if (GetComponent<UIPanel>() != null)
|
|||
|
|
{
|
|||
|
|
Debug.LogError("Widgets and panels should not be on the same object! Widget must be a child of the panel.", this);
|
|||
|
|
}
|
|||
|
|
else if (!Application.isPlaying && GetComponents<UIWidget>().Length > 1)
|
|||
|
|
{
|
|||
|
|
Debug.LogError("You should not place more than one widget on the same object. Weird stuff will happen!", this);
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
CreatePanel();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Update the anchored edges and ensure the widget is registered with a panel.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
protected override void OnAnchor ()
|
|||
|
|
{
|
|||
|
|
float lt, bt, rt, tt;
|
|||
|
|
Transform trans = cachedTransform;
|
|||
|
|
Transform parent = trans.parent;
|
|||
|
|
Vector3 pos = trans.localPosition;
|
|||
|
|
Vector2 pvt = pivotOffset;
|
|||
|
|
|
|||
|
|
// Attempt to fast-path if all anchors match
|
|||
|
|
if (leftAnchor.target == bottomAnchor.target &&
|
|||
|
|
leftAnchor.target == rightAnchor.target &&
|
|||
|
|
leftAnchor.target == topAnchor.target)
|
|||
|
|
{
|
|||
|
|
Vector3[] sides = leftAnchor.GetSides(parent);
|
|||
|
|
|
|||
|
|
if (sides != null)
|
|||
|
|
{
|
|||
|
|
lt = NGUIMath.Lerp(sides[0].x, sides[2].x, leftAnchor.relative) + leftAnchor.absolute;
|
|||
|
|
rt = NGUIMath.Lerp(sides[0].x, sides[2].x, rightAnchor.relative) + rightAnchor.absolute;
|
|||
|
|
bt = NGUIMath.Lerp(sides[3].y, sides[1].y, bottomAnchor.relative) + bottomAnchor.absolute;
|
|||
|
|
tt = NGUIMath.Lerp(sides[3].y, sides[1].y, topAnchor.relative) + topAnchor.absolute;
|
|||
|
|
mIsInFront = true;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// Anchored to a single transform
|
|||
|
|
Vector3 lp = GetLocalPos(leftAnchor, parent);
|
|||
|
|
lt = lp.x + leftAnchor.absolute;
|
|||
|
|
bt = lp.y + bottomAnchor.absolute;
|
|||
|
|
rt = lp.x + rightAnchor.absolute;
|
|||
|
|
tt = lp.y + topAnchor.absolute;
|
|||
|
|
mIsInFront = (!hideIfOffScreen || lp.z >= 0f);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
mIsInFront = true;
|
|||
|
|
|
|||
|
|
// Left anchor point
|
|||
|
|
if (leftAnchor.target)
|
|||
|
|
{
|
|||
|
|
Vector3[] sides = leftAnchor.GetSides(parent);
|
|||
|
|
|
|||
|
|
if (sides != null)
|
|||
|
|
{
|
|||
|
|
lt = NGUIMath.Lerp(sides[0].x, sides[2].x, leftAnchor.relative) + leftAnchor.absolute;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
lt = GetLocalPos(leftAnchor, parent).x + leftAnchor.absolute;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else lt = pos.x - pvt.x * mWidth;
|
|||
|
|
|
|||
|
|
// Right anchor point
|
|||
|
|
if (rightAnchor.target)
|
|||
|
|
{
|
|||
|
|
Vector3[] sides = rightAnchor.GetSides(parent);
|
|||
|
|
|
|||
|
|
if (sides != null)
|
|||
|
|
{
|
|||
|
|
rt = NGUIMath.Lerp(sides[0].x, sides[2].x, rightAnchor.relative) + rightAnchor.absolute;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
rt = GetLocalPos(rightAnchor, parent).x + rightAnchor.absolute;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else rt = pos.x - pvt.x * mWidth + mWidth;
|
|||
|
|
|
|||
|
|
// Bottom anchor point
|
|||
|
|
if (bottomAnchor.target)
|
|||
|
|
{
|
|||
|
|
Vector3[] sides = bottomAnchor.GetSides(parent);
|
|||
|
|
|
|||
|
|
if (sides != null)
|
|||
|
|
{
|
|||
|
|
bt = NGUIMath.Lerp(sides[3].y, sides[1].y, bottomAnchor.relative) + bottomAnchor.absolute;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
bt = GetLocalPos(bottomAnchor, parent).y + bottomAnchor.absolute;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else bt = pos.y - pvt.y * mHeight;
|
|||
|
|
|
|||
|
|
// Top anchor point
|
|||
|
|
if (topAnchor.target)
|
|||
|
|
{
|
|||
|
|
Vector3[] sides = topAnchor.GetSides(parent);
|
|||
|
|
|
|||
|
|
if (sides != null)
|
|||
|
|
{
|
|||
|
|
tt = NGUIMath.Lerp(sides[3].y, sides[1].y, topAnchor.relative) + topAnchor.absolute;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
tt = GetLocalPos(topAnchor, parent).y + topAnchor.absolute;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else tt = pos.y - pvt.y * mHeight + mHeight;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Calculate the new position, width and height
|
|||
|
|
Vector3 newPos = new Vector3(Mathf.Lerp(lt, rt, pvt.x), Mathf.Lerp(bt, tt, pvt.y), pos.z);
|
|||
|
|
newPos.x = Mathf.Round(newPos.x);
|
|||
|
|
newPos.y = Mathf.Round(newPos.y);
|
|||
|
|
|
|||
|
|
int w = Mathf.FloorToInt(rt - lt + 0.5f);
|
|||
|
|
int h = Mathf.FloorToInt(tt - bt + 0.5f);
|
|||
|
|
|
|||
|
|
// Maintain the aspect ratio if requested and possible
|
|||
|
|
if (keepAspectRatio != AspectRatioSource.Free && aspectRatio != 0f)
|
|||
|
|
{
|
|||
|
|
if (keepAspectRatio == AspectRatioSource.BasedOnHeight)
|
|||
|
|
{
|
|||
|
|
w = Mathf.RoundToInt(h * aspectRatio);
|
|||
|
|
}
|
|||
|
|
else h = Mathf.RoundToInt(w / aspectRatio);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Don't let the width and height get too small
|
|||
|
|
if (w < minWidth) w = minWidth;
|
|||
|
|
if (h < minHeight) h = minHeight;
|
|||
|
|
|
|||
|
|
// Update the position if it has changed
|
|||
|
|
if (Vector3.SqrMagnitude(pos - newPos) > 0.001f)
|
|||
|
|
{
|
|||
|
|
cachedTransform.localPosition = newPos;
|
|||
|
|
if (mIsInFront) mChanged = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Update the width and height if it has changed
|
|||
|
|
if (mWidth != w || mHeight != h)
|
|||
|
|
{
|
|||
|
|
mWidth = w;
|
|||
|
|
mHeight = h;
|
|||
|
|
if (mIsInFront) mChanged = true;
|
|||
|
|
if (autoResizeBoxCollider) ResizeCollider();
|
|||
|
|
}
|
|||
|
|
if (AnchorChanged != null)
|
|||
|
|
{
|
|||
|
|
AnchorChanged(cachedTransform);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Ensure we have a panel to work with.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
protected override bool OnUpdate ()
|
|||
|
|
{
|
|||
|
|
bool result = true;
|
|||
|
|
#if FUNCELL_MODIFIED
|
|||
|
|
|
|||
|
|
//updatealpha
|
|||
|
|
if (_oldAlpha != mColor.a)
|
|||
|
|
{
|
|||
|
|
var frame = Time.frameCount;
|
|||
|
|
_oldAlpha = mColor.a;
|
|||
|
|
var parentAlpha = 1f;
|
|||
|
|
if(parent != null)
|
|||
|
|
{
|
|||
|
|
parentAlpha = parent.finalAlpha;
|
|||
|
|
}
|
|||
|
|
SelfCalculateFinalAlpha(parentAlpha);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
if (panel == null) result = CreatePanel();
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
else if (!mPlayMode) ParentHasChanged();
|
|||
|
|
#endif
|
|||
|
|
*/
|
|||
|
|
//这里把panel是否为空的判断,修改为通过InstID和异常来判断
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (_panelInstID == 0)
|
|||
|
|
{
|
|||
|
|
result = CreatePanel();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (_panelInstID != 0)
|
|||
|
|
{
|
|||
|
|
_panelInstID = panel.GetInstanceID();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
if (!mPlayMode) ParentHasChanged();
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
catch
|
|||
|
|
{
|
|||
|
|
result = CreatePanel();
|
|||
|
|
}
|
|||
|
|
return result;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#if !UNITY_EDITOR
|
|||
|
|
/// <summary>
|
|||
|
|
/// Mark the UI as changed when returning from paused state.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
void OnApplicationPause (bool paused) { if (!paused) MarkAsChanged(); }
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Clear references.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
protected override void OnDisable ()
|
|||
|
|
{
|
|||
|
|
geometry.FreeCache();
|
|||
|
|
RemoveFromPanel();
|
|||
|
|
base.OnDisable();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Unregister this widget.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
//void OnDestroy () { RemoveFromPanel(); }
|
|||
|
|
#if FUNCELL_MODIFIED
|
|||
|
|
//优化NGUI GC
|
|||
|
|
protected override void OnDestroy()
|
|||
|
|
{
|
|||
|
|
geometry.FreeCache();
|
|||
|
|
RemoveFromPanel();
|
|||
|
|
base.OnDestroy();
|
|||
|
|
}
|
|||
|
|
#else
|
|||
|
|
void OnDestroy ()
|
|||
|
|
{
|
|||
|
|
geometry.FreeCache();
|
|||
|
|
RemoveFromPanel();
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
//优化NGUI GC
|
|||
|
|
//void OnDestroy() { RemoveFromPanel(); }
|
|||
|
|
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
static int mHandles = -1;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Whether widgets will show handles with the Move Tool, or just the View Tool.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
static public bool showHandlesWithMoveTool
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
if (mHandles == -1)
|
|||
|
|
{
|
|||
|
|
mHandles = UnityEditor.EditorPrefs.GetInt("NGUI Handles", 1);
|
|||
|
|
}
|
|||
|
|
return (mHandles == 1);
|
|||
|
|
}
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
int val = value ? 1 : 0;
|
|||
|
|
|
|||
|
|
if (mHandles != val)
|
|||
|
|
{
|
|||
|
|
mHandles = val;
|
|||
|
|
UnityEditor.EditorPrefs.SetInt("NGUI Handles", mHandles);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Whether the widget should have some form of handles shown.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
static public bool showHandles
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
#if UNITY_4_3 || UNITY_4_5
|
|||
|
|
if (showHandlesWithMoveTool)
|
|||
|
|
{
|
|||
|
|
return UnityEditor.Tools.current == UnityEditor.Tool.Move;
|
|||
|
|
}
|
|||
|
|
return UnityEditor.Tools.current == UnityEditor.Tool.View;
|
|||
|
|
#else
|
|||
|
|
return UnityEditor.Tools.current == UnityEditor.Tool.Rect;
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Draw some selectable gizmos.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
void OnDrawGizmos ()
|
|||
|
|
{
|
|||
|
|
if (isVisible && NGUITools.GetActive(this))
|
|||
|
|
{
|
|||
|
|
if (UnityEditor.Selection.activeGameObject == gameObject && showHandles) return;
|
|||
|
|
|
|||
|
|
Color outline = new Color(1f, 1f, 1f, 0.2f);
|
|||
|
|
|
|||
|
|
float adjustment = (root != null) ? 0.05f : 0.001f;
|
|||
|
|
Vector2 offset = pivotOffset;
|
|||
|
|
Vector3 center = new Vector3(mWidth * (0.5f - offset.x), mHeight * (0.5f - offset.y), -mDepth * adjustment);
|
|||
|
|
Vector3 size = new Vector3(mWidth, mHeight, 1f);
|
|||
|
|
|
|||
|
|
// Draw the gizmo
|
|||
|
|
Gizmos.matrix = cachedTransform.localToWorldMatrix;
|
|||
|
|
Gizmos.color = (UnityEditor.Selection.activeGameObject == cachedTransform) ? Color.white : outline;
|
|||
|
|
Gizmos.DrawWireCube(center, size);
|
|||
|
|
|
|||
|
|
// Make the widget selectable
|
|||
|
|
size.z = 0.01f;
|
|||
|
|
Gizmos.color = Color.clear;
|
|||
|
|
Gizmos.DrawCube(center, size);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endif // UNITY_EDITOR
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Update the widget's visibility state.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public bool UpdateVisibility (bool visibleByAlpha, bool visibleByPanel)
|
|||
|
|
{
|
|||
|
|
if (mIsVisibleByAlpha != visibleByAlpha || mIsVisibleByPanel != visibleByPanel)
|
|||
|
|
{
|
|||
|
|
mChanged = true;
|
|||
|
|
mIsVisibleByAlpha = visibleByAlpha;
|
|||
|
|
mIsVisibleByPanel = visibleByPanel;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int mMatrixFrame = -1;
|
|||
|
|
Vector3 mOldV0;
|
|||
|
|
Vector3 mOldV1;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Check to see if the widget has moved relative to the panel that manages it
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public bool UpdateTransform (int frame)
|
|||
|
|
{
|
|||
|
|
Transform trans = cachedTransform;
|
|||
|
|
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
mPlayMode = Application.isPlaying;
|
|||
|
|
if (mMoved || !mPlayMode)
|
|||
|
|
#else
|
|||
|
|
mPlayMode = true;
|
|||
|
|
if (mMoved)
|
|||
|
|
#endif
|
|||
|
|
{
|
|||
|
|
mMoved = true;
|
|||
|
|
mMatrixFrame = -1;
|
|||
|
|
trans.hasChanged = false;
|
|||
|
|
Vector2 offset = pivotOffset;
|
|||
|
|
|
|||
|
|
float x0 = -offset.x * mWidth;
|
|||
|
|
float y0 = -offset.y * mHeight;
|
|||
|
|
float x1 = x0 + mWidth;
|
|||
|
|
float y1 = y0 + mHeight;
|
|||
|
|
|
|||
|
|
mOldV0 = panel.worldToLocal.MultiplyPoint3x4(trans.TransformPoint(x0, y0, 0f));
|
|||
|
|
mOldV1 = panel.worldToLocal.MultiplyPoint3x4(trans.TransformPoint(x1, y1, 0f));
|
|||
|
|
}
|
|||
|
|
else if (!panel.widgetsAreStatic && trans.hasChanged)
|
|||
|
|
{
|
|||
|
|
mMatrixFrame = -1;
|
|||
|
|
trans.hasChanged = false;
|
|||
|
|
Vector2 offset = pivotOffset;
|
|||
|
|
|
|||
|
|
float x0 = -offset.x * mWidth;
|
|||
|
|
float y0 = -offset.y * mHeight;
|
|||
|
|
float x1 = x0 + mWidth;
|
|||
|
|
float y1 = y0 + mHeight;
|
|||
|
|
|
|||
|
|
Vector3 v0 = panel.worldToLocal.MultiplyPoint3x4(trans.TransformPoint(x0, y0, 0f));
|
|||
|
|
Vector3 v1 = panel.worldToLocal.MultiplyPoint3x4(trans.TransformPoint(x1, y1, 0f));
|
|||
|
|
|
|||
|
|
if (Vector3.SqrMagnitude(mOldV0 - v0) > 0.000001f ||
|
|||
|
|
Vector3.SqrMagnitude(mOldV1 - v1) > 0.000001f)
|
|||
|
|
{
|
|||
|
|
mMoved = true;
|
|||
|
|
mOldV0 = v0;
|
|||
|
|
mOldV1 = v1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Notify the listeners
|
|||
|
|
if (mMoved && onChange != null) onChange();
|
|||
|
|
return mMoved || mChanged;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Update the widget and fill its geometry if necessary. Returns whether something was changed.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public bool UpdateGeometry (int frame)
|
|||
|
|
{
|
|||
|
|
// Has the alpha changed?
|
|||
|
|
#if FUNCELL_MODIFIED
|
|||
|
|
float finalAlpha = this.finalAlpha;
|
|||
|
|
#else
|
|||
|
|
float finalAlpha = CalculateFinalAlpha(frame);
|
|||
|
|
#endif
|
|||
|
|
var alphaChanged = false;
|
|||
|
|
if (mIsVisibleByAlpha && mLastAlpha != finalAlpha)
|
|||
|
|
{
|
|||
|
|
alphaChanged = true;
|
|||
|
|
}
|
|||
|
|
mLastAlpha = finalAlpha;
|
|||
|
|
|
|||
|
|
if (mChanged)
|
|||
|
|
{
|
|||
|
|
if (mIsVisibleByAlpha && finalAlpha > 0.001f && shader != null)
|
|||
|
|
{
|
|||
|
|
bool hadVertices = geometry.hasVertices;
|
|||
|
|
|
|||
|
|
if (fillGeometry)
|
|||
|
|
{
|
|||
|
|
geometry.Clear();
|
|||
|
|
OnFill(geometry.verts, geometry.uvs, geometry.cols);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (geometry.hasVertices)
|
|||
|
|
{
|
|||
|
|
// Want to see what's being filled? Uncomment this line.
|
|||
|
|
//Debug.Log("Fill " + name + " (" + Time.frameCount + ")");
|
|||
|
|
|
|||
|
|
if (mMatrixFrame != frame)
|
|||
|
|
{
|
|||
|
|
mLocalToPanel = panel.worldToLocal * cachedTransform.localToWorldMatrix;
|
|||
|
|
mMatrixFrame = frame;
|
|||
|
|
}
|
|||
|
|
geometry.ApplyTransform(mLocalToPanel, panel.generateNormals,height,width);
|
|||
|
|
mMoved = false;
|
|||
|
|
mChanged = false;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
mChanged = false;
|
|||
|
|
return hadVertices;
|
|||
|
|
}
|
|||
|
|
else if (geometry.hasVertices)
|
|||
|
|
{
|
|||
|
|
if (fillGeometry) geometry.Clear();
|
|||
|
|
mMoved = false;
|
|||
|
|
mChanged = false;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (mMoved && geometry.hasVertices)
|
|||
|
|
{
|
|||
|
|
// Want to see what's being moved? Uncomment this line.
|
|||
|
|
//Debug.Log("Moving " + name + " (" + Time.frameCount + ")");
|
|||
|
|
|
|||
|
|
if (mMatrixFrame != frame)
|
|||
|
|
{
|
|||
|
|
mLocalToPanel = panel.worldToLocal * cachedTransform.localToWorldMatrix;
|
|||
|
|
mMatrixFrame = frame;
|
|||
|
|
}
|
|||
|
|
geometry.ApplyTransform(mLocalToPanel, panel.generateNormals,height,width);
|
|||
|
|
mMoved = false;
|
|||
|
|
mChanged = false;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
else if(alphaChanged && geometry.hasVertices)
|
|||
|
|
{
|
|||
|
|
mMoved = false;
|
|||
|
|
mChanged = false;
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
mMoved = false;
|
|||
|
|
mChanged = false;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Append the local geometry buffers to the specified ones.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public void WriteToBuffers (BetterList<Vector3> v, BetterList<Vector2> u, BetterList<Color32> c, BetterList<Vector3> n, BetterList<Vector4> t)
|
|||
|
|
{
|
|||
|
|
geometry.WriteToBuffers(v, u, c, n, t, finalAlpha);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Make the widget pixel-perfect.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
virtual public void MakePixelPerfect ()
|
|||
|
|
{
|
|||
|
|
Vector3 pos = cachedTransform.localPosition;
|
|||
|
|
pos.z = Mathf.Round(pos.z);
|
|||
|
|
pos.x = Mathf.Round(pos.x);
|
|||
|
|
pos.y = Mathf.Round(pos.y);
|
|||
|
|
cachedTransform.localPosition = pos;
|
|||
|
|
|
|||
|
|
Vector3 ls = cachedTransform.localScale;
|
|||
|
|
cachedTransform.localScale = new Vector3(Mathf.Sign(ls.x), Mathf.Sign(ls.y), 1f);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Minimum allowed width for this widget.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
virtual public int minWidth { get { return 2; } }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Minimum allowed height for this widget.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
virtual public int minHeight { get { return 2; } }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Dimensions of the sprite's border, if any.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
virtual public Vector4 border { get { return Vector4.zero; } set { } }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Virtual function called by the UIPanel that fills the buffers.
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
virtual public void OnFill(BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
|
|||
|
|
{
|
|||
|
|
// Call this in your derived classes:
|
|||
|
|
//if (onPostFill != null)
|
|||
|
|
// onPostFill(this, verts.size, verts, uvs, cols);
|
|||
|
|
}
|
|||
|
|
}
|