zoukankan      html  css  js  c++  java
  • NGUI 源码分析- UIWidgetInspector

    NGUI Version 3.9.0

    //----------------------------------------------
    //            NGUI: Next-Gen UI kit
    // Copyright © 2011-2015 Tasharen Entertainment
    //----------------------------------------------
    
    using UnityEngine;
    using UnityEditor;
    using System.Collections.Generic;
    
    /// <summary>
    /// Inspector class used to edit UIWidgets.
    /// </summary>
    
    [CanEditMultipleObjects]
    [CustomEditor(typeof(UIWidget), true)]
    public class UIWidgetInspector : UIRectEditor
    {
    	static public new UIWidgetInspector instance; // 
    
    	public enum Action // YUTODO这个什么作用?
    	{
    		None,
    		Move, // 移动
    		Scale,// 缩放
    		Rotate,
    	}
    
    	Action mAction = Action.None;
    	Action mActionUnderMouse = Action.None;
    	bool mAllowSelection = true;
    
    	protected UIWidget mWidget; // 保存一个widget
    
    	static protected bool mUseShader = false;// 默认不使用shader
    
        // GUIStyle 是什么鬼? 
        // 各种颜色的点
    	static GUIStyle mBlueDot = null; //  蓝点?
    	static GUIStyle mYellowDot = null; 
    	static GUIStyle mRedDot = null;
    	static GUIStyle mOrangeDot = null;
    	static GUIStyle mGreenDot = null;
    	static GUIStyle mGreyDot = null;
    	static MouseCursor mCursor = MouseCursor.Arrow; // 还能控制鼠标光标?666
    
        // 枢轴点
    	static public UIWidget.Pivot[] pivotPoints =
    	{
    		UIWidget.Pivot.BottomLeft,
    		UIWidget.Pivot.TopLeft,
    		UIWidget.Pivot.TopRight,
    		UIWidget.Pivot.BottomRight,
    		UIWidget.Pivot.Left,
    		UIWidget.Pivot.Top,
    		UIWidget.Pivot.Right,
    		UIWidget.Pivot.Bottom,
    	};
    
        // 
    	static int s_Hash = "WidgetHash".GetHashCode();
    
        // 坐标 
    	Vector3 mLocalPos = Vector3.zero;
    	Vector3 mWorldPos = Vector3.zero;
    
        // 起始宽高
    	int mStartWidth = 0;
    	int mStartHeight = 0;
    
        // 起始拖动和鼠标?
    	Vector3 mStartDrag = Vector3.zero;
    	Vector2 mStartMouse = Vector2.zero;
    
        // 起始方向和旋转角度
    	Vector3 mStartRot = Vector3.zero;
    	Vector3 mStartDir = Vector3.right;
    
        // 起始的上下左右?
    	Vector2 mStartLeft = Vector2.zero;
    	Vector2 mStartRight = Vector2.zero;
    	Vector2 mStartBottom = Vector2.zero;
    	Vector2 mStartTop = Vector2.zero;
    
        // 拖动枢轴点 默认为中心
    	UIWidget.Pivot mDragPivot = UIWidget.Pivot.Center;
    
    	
        
        /// <summary>
        /// Raycast into the screen.
        /// 判断当前鼠标是否射中传入的平面
        /// </summary>
        /// <param name="corners">传入待检测平面的三个点</param>
        /// <param name="hit">射到的点的坐标</param>
        /// <returns>射到返回true</returns>
    	static public bool Raycast (Vector3[] corners, out Vector3 hit)
    	{
    		Plane plane = new Plane(corners[0], corners[1], corners[2]); // 三点确定一个平面
            Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); // 转换2D GUI位置到世界空间的ray
    		float dist = 0f;
    		bool isHit = plane.Raycast(ray, out dist); // 检查射线有没有射中平面
    		hit = isHit ? ray.GetPoint(dist) : Vector3.zero; // GetPoint 返回离射线距离为 dist 的那个点的位置。
    		return isHit;
    	}
    
    	/// <summary>
    	/// Color used by the handles based on the current color scheme.
    	/// 根据当前颜色主题返回颜色
    	/// </summary>
    
    	static public Color handlesColor
    	{
    		get
    		{
    			if (NGUISettings.colorMode == NGUISettings.ColorMode.Orange)
    			{
    				return new Color(1f, 0.5f, 0f);
    			}
    			else if (NGUISettings.colorMode == NGUISettings.ColorMode.Green)
    			{
    				return Color.green;
    			}
    			return Color.white;
    		}
    	}
    
    	/// <summary>
    	/// Draw a control dot at the specified world position.
    	/// 在世界坐标绘制控制点
    	/// </summary>
    
    	static public void DrawKnob (Vector3 point, bool selected, bool canResize, int id)
    	{
            // TODO 这是一种什么赋值方法?
    		if (mGreyDot == null) mGreyDot = "sv_label_0"; // 一种内置的编辑器风格
    		if (mBlueDot == null) mBlueDot = "sv_label_1";
    		if (mGreenDot == null) mGreenDot = "sv_label_3";
    		if (mYellowDot == null) mYellowDot = "sv_label_4";
    		if (mOrangeDot == null) mOrangeDot = "sv_label_5";
    		if (mRedDot == null) mRedDot = "sv_label_6";
    
    
            // 
    		Vector2 screenPoint = HandleUtility.WorldToGUIPoint(point);
    
            // 矩阵
    #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6
    		Rect rect = new Rect(screenPoint.x - 7f, screenPoint.y - 7f, 14f, 14f);
    #else
    		Rect rect = new Rect(screenPoint.x - 5f, screenPoint.y - 9f, 14f, 14f);
    #endif
    
            // 根据传入的状态判断显示的颜色
    		if (selected)
    		{
    			if (NGUISettings.colorMode == NGUISettings.ColorMode.Orange)
    			{
    				mRedDot.Draw(rect, GUIContent.none, id);
    			}
    			else
    			{
    				mOrangeDot.Draw(rect, GUIContent.none, id);
    			}
    		}
    		else if (canResize)
    		{
    			if (NGUISettings.colorMode == NGUISettings.ColorMode.Orange)
    			{
    				mOrangeDot.Draw(rect, GUIContent.none, id);
    			}
    			else if (NGUISettings.colorMode == NGUISettings.ColorMode.Green)
    			{
    				mGreenDot.Draw(rect, GUIContent.none, id);
    			}
    			else
    			{
    				mBlueDot.Draw(rect, GUIContent.none, id);
    			}
    		}
    		else mGreyDot.Draw(rect, GUIContent.none, id); // 
    	}
    
    	/// <summary>
    	/// Screen-space distance from the mouse position to the specified world position.
    	/// 屏幕空间下 鼠标到某点的距离
    	/// </summary>
    
    	static public float GetScreenDistance (Vector3 worldPos, Vector2 mousePos)
    	{
    		Vector2 screenPos = HandleUtility.WorldToGUIPoint(worldPos);
    		return Vector2.Distance(mousePos, screenPos);
    	}
    
    	/// <summary>
    	/// Closest screen-space distance from the mouse position to one of the specified world points.
    	/// 屏幕空间下 在鼠标到各点的距离中取最小距离
    	/// </summary>
    
    	static public float GetScreenDistance (Vector3[] worldPoints, Vector2 mousePos, out int index)
    	{
    		float min = float.MaxValue;
    		index = 0;
    
    		for (int i = 0; i < worldPoints.Length; ++i)
    		{
    			float distance = GetScreenDistance(worldPoints[i], mousePos);
    			
    			if (distance < min)
    			{
    				index = i;
    				min = distance;
    			}
    		}
    		return min;
    	}
    
    	/// <summary>
    	/// Set the mouse cursor rectangle, refreshing the screen when it gets changed.
    	/// 鼠标光标类型发生改变时重新设置它的矩形区域
    	/// </summary>
    
    	static public void SetCursorRect (Rect rect, MouseCursor cursor)
    	{
    		EditorGUIUtility.AddCursorRect(rect, cursor);
    
    		if (Event.current.type == EventType.MouseMove)
    		{
    			if (mCursor != cursor)
    			{
    				mCursor = cursor;
    				Event.current.Use();
    			}
    		}
    	}
    
        /// <summary>
        /// 
        /// </summary>
    	protected override void OnDisable ()
    	{
    		base.OnDisable();
    		NGUIEditorTools.HideMoveTool(false);
    		instance = null;
    	}
    
    	/// <summary>
    	/// Convert the specified 4 corners into 8 pivot points (adding left, top, right, bottom -- in that order).
    	/// 把四个角落的坐标数组扩展为八个点的坐标数组
    	/// </summary>
    
    	static public Vector3[] GetHandles (Vector3[] corners)
    	{
    		Vector3[] v = new Vector3[8];
    
    		v[0] = corners[0];
    		v[1] = corners[1];
    		v[2] = corners[2];
    		v[3] = corners[3];
    
    		v[4] = (corners[0] + corners[1]) * 0.5f;
    		v[5] = (corners[1] + corners[2]) * 0.5f;
    		v[6] = (corners[2] + corners[3]) * 0.5f;
    		v[7] = (corners[0] + corners[3]) * 0.5f;
    
    		return v;
    	}
    
    	/// <summary>
    	/// Determine what kind of pivot point is under the mouse and update the cursor accordingly.
    	/// 通过鼠标的位置判断应当进行什么样的操作。
    	/// 默认返回 center 锚点,能够缩放时返回 目标锚点
    	/// </summary>
    
    	static public UIWidget.Pivot GetPivotUnderMouse (Vector3[] worldPos, Event e, bool[] resizable, bool movable, ref Action action)
    	{
    		// Time to figure out what kind of action is underneath the mouse
    		UIWidget.Pivot pivotUnderMouse = UIWidget.Pivot.Center;// 初始化为 锚点中心
    
            // 
    		if (action == Action.None)
    		{
    			int index = 0;
    			float dist = GetScreenDistance(worldPos, e.mousePosition, out index); // 获取最小的距离,并记录最小距离对应点的下标
    			bool alt = (e.modifiers & EventModifiers.Alt) != 0; // 判断是不是按了组合键
    
                // 
    			if (resizable[index] && dist < 10f) // 如果这个位置能动,并且距离小于10f
    			{
    				pivotUnderMouse = pivotPoints[index]; //鼠标点到的枢轴点是index标示出的index
    				action = Action.Scale;// 进行缩放动作
    			}
    			else if (!alt && NGUIEditorTools.SceneViewDistanceToRectangle(worldPos, e.mousePosition) == 0f) // 没有按组合键并且鼠标点在矩形框里面
    			{
    				action = movable ? Action.Move : Action.Rotate; // 能移动仅进行移动,不能移动就进行旋转
    			}
    			else if (dist < 30f)
    			{
    				action = Action.Rotate; // 其他情况就进行旋转
    			}
    		}
    
    		// Change the mouse cursor to a more appropriate one
            // 
    		Vector2[] screenPos = new Vector2[8];
    		for (int i = 0; i < 8; ++i) screenPos[i] = HandleUtility.WorldToGUIPoint(worldPos[i]);
    
    		Bounds b = new Bounds(screenPos[0], Vector3.zero); // 给定中心点和大小。,后面那个大小代表(width,height,depth)
    		for (int i = 1; i < 8; ++i) b.Encapsulate(screenPos[i]);// 包含八个点的最小矩形框,在这里八个点都恰好在矩形框的边上。
    
            Vector2 min = b.min;// min = center - extents; extents 是 size 的一半。例如中心点为(0,0,0),extents(2,3,5),那么min(-2,-3,-5)
    		Vector2 max = b.max;
    
            // 在原来的基础上扩展 30f。depth 没用到所以这里没处理
    		min.x -= 30f;
    		max.x += 30f;
    		min.y -= 30f;
    		max.y += 30f;
    
    		Rect rect = new Rect(min.x, min.y, max.x - min.x, max.y - min.y); // 获取矩形框
    
            // 根据动作的状态 显示鼠标光标的形状
    		if (action == Action.Rotate)
    		{
    			SetCursorRect(rect, MouseCursor.RotateArrow);
    		}
    		else if (action == Action.Move)
    		{
    			SetCursorRect(rect, MouseCursor.MoveArrow);
    		}
    		else if (action == Action.Scale)
    		{
    			SetCursorRect(rect, MouseCursor.ScaleArrow);
    		}
    		else SetCursorRect(rect, MouseCursor.Arrow);
    
    		return pivotUnderMouse;
    	}
    
    	/// <summary>
    	/// Draw the specified anchor point.
    	/// 绘制黄色的锚点以及连接线、距离标签
    	/// </summary>
    
    	static public void DrawAnchorHandle (UIRect.AnchorPoint anchor, Transform myTrans, Vector3[] myCorners, int side, int id)
    	{
    		if (!anchor.target) return; // 没有定锚点就不用画了
    
    		int i0, i1;
            
            //矩形四个点在数组中的序列与相对位置的关系如下
            //12
            //03
    
            //根据是哪边的锚点来选出决定那条边的两个顶点
    		if (side == 0)
    		{
    			// Left
    			i0 = 0;
    			i1 = 1;
    		}
    		else if (side == 1)
    		{
    			// Top
    			i0 = 1;
    			i1 = 2;
    		}
    		else if (side == 2)
    		{
    			// Right
    			i0 = 3;
    			i1 = 2;
    		}
    		else
    		{
    			// Bottom
    			i0 = 0;
    			i1 = 3;
    		}
    
    
            // 
    		Vector3 myPos = (myCorners[i0] + myCorners[i1]) * 0.5f; // 锚点相关位置是对应边的中点
    
    		Vector3[] sides = null; // 目标对象矩形的四个节点
    
    		if (anchor.rect != null)
    		{
    			sides = anchor.rect.worldCorners; 
    		}
    		else
    		{
    #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6
    			Camera cam = anchor.target.camera; // 获取锚点目标的 camera
    #else
    			Camera cam = anchor.target.GetComponent<Camera>();
    #endif
    			if (cam != null) sides = cam.GetWorldCorners(); // 获取相机的边界
    		}
    
    		Vector3 theirPos; // 黄点位置,必然在目标矩形上面
    
    		if (sides != null)
    		{
    			Vector3 v0, v1;
    
    			if (side == 0 || side == 2)
    			{
    				// Left or right
    				v0 = Vector3.Lerp(sides[0], sides[3], anchor.relative); // 在两个向量V0、V1间做线性插值,根据第三个参数t决定返回某个插值。例如 t=0 返回V0,t=0.5 返回V0、V1的中间插值。
    				v1 = Vector3.Lerp(sides[1], sides[2], anchor.relative); // 
    			}
    			else
    			{
    				// Top or bottom
    				v0 = Vector3.Lerp(sides[0], sides[1], anchor.relative);
    				v1 = Vector3.Lerp(sides[3], sides[2], anchor.relative);
    			}
    
                // 黄点是 myPos 在 v0 和 v1 连接线上的投影点,如果超过v0v1线段,则黄点设置为v0或v1。
    			theirPos = HandleUtility.ProjectPointLine(myPos, v0, v1);
    		}
    		else
    		{
    			theirPos = anchor.target.position;
    		}
    
            // 画连接线
    		NGUIHandles.DrawShadowedLine(myCorners, myPos, theirPos, Color.yellow);
    
    
            // 位置偏离的时候在一定条件下绘制一个标记负值距离的标签
    		if (Event.current.GetTypeForControl(id) == EventType.Repaint) // 控制ID id 当前事件类型如果是重绘
    		{
    			Vector2 screenPoint = HandleUtility.WorldToGUIPoint(theirPos);
    
    #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6
    			Rect rect = new Rect(screenPoint.x - 7f, screenPoint.y - 7f, 14f, 14f);
    #else
    			Rect rect = new Rect(screenPoint.x - 5f, screenPoint.y - 9f, 14f, 14f);
    #endif
    			if (mYellowDot == null) mYellowDot = "sv_label_4";
    
    			Vector3 v0 = HandleUtility.WorldToGUIPoint(myPos);
    			Vector3 v1 = HandleUtility.WorldToGUIPoint(theirPos);
    
    			Handles.BeginGUI(); // 开始一个 2D 绘制块
    				
    			mYellowDot.Draw(rect, GUIContent.none, id); // 绘制黄点
    
    			Vector3 diff = v1 - v0; 
    			bool isHorizontal = Mathf.Abs(diff.x) > Mathf.Abs(diff.y);// 判断是否为水平线
    			float mag = diff.magnitude; // 获取线的长度
    
    			if ((isHorizontal && mag > 60f) || (!isHorizontal && mag > 30f)) // 长度超过 60 的水平线或者长度大于 30 的竖直线
    			{
    				Vector3 pos = (myPos + theirPos) * 0.5f; // 
    				string text = anchor.absolute.ToString();// 
    
    				GUI.color = Color.yellow;
    
    				if (side == 0)
    				{
                        if (theirPos.x < myPos.x) //如果目标点的位置比出发点的位置还要靠左,那么显示一个标记距离的label
    						NGUIHandles.DrawCenteredLabel(pos, text);
    				}
    				else if (side == 1)
    				{
    					if (theirPos.y > myPos.y)
    						NGUIHandles.DrawCenteredLabel(pos, text);
    				}
    				else if (side == 2)
    				{
    					if (theirPos.x > myPos.x)
    						NGUIHandles.DrawCenteredLabel(pos, text);
    				}
    				else if (side == 3)
    				{
    					if (theirPos.y < myPos.y)
    						NGUIHandles.DrawCenteredLabel(pos, text);
    				}
    				GUI.color = Color.white;
    			}
    			Handles.EndGUI();
    		}
    	}
    
    	/// <summary>
    	/// Draw the on-screen selection, knobs, and handle all interaction logic.
    	/// 
    	/// </summary>
    
    	public void OnSceneGUI ()
    	{
    		if (Selection.objects.Length > 1) return;  // 选中了多个对象,返回
    		NGUIEditorTools.HideMoveTool(true); // 隐藏移动工具
    		if (!UIWidget.showHandles) return; // 没有需要显示的 handles,返回
    
    		mWidget = target as UIWidget; // 把选中对象作为一个 UIWidget 组件处理
    
    		Transform t = mWidget.cachedTransform; // 获取对象的 transform
    
    		Event e = Event.current;               //  
    		int id = GUIUtility.GetControlID(s_Hash, FocusType.Passive); // 获取一个控制ID,这个控制不能获取键盘焦点
    		EventType type = e.GetTypeForControl(id); // 获取控制ID的事件类型
    
    		Action actionUnderMouse = mAction; // 移动、缩放或是旋转
    		Vector3[] handles = GetHandles(mWidget.worldCorners); // 获取组件的八个枢轴点点
    		
            // 绘制矩形框
    		NGUIHandles.DrawShadowedLine(handles, handles[0], handles[1], handlesColor);
    		NGUIHandles.DrawShadowedLine(handles, handles[1], handles[2], handlesColor);
    		NGUIHandles.DrawShadowedLine(handles, handles[2], handles[3], handlesColor);
    		NGUIHandles.DrawShadowedLine(handles, handles[0], handles[3], handlesColor);
    
    		// If the widget is anchored, draw the anchors
            // 组件有锚点的话就绘制锚点
    		if (mWidget.isAnchored)
    		{
    			DrawAnchorHandle(mWidget.leftAnchor, mWidget.cachedTransform, handles, 0, id);
    			DrawAnchorHandle(mWidget.topAnchor, mWidget.cachedTransform, handles, 1, id);
    			DrawAnchorHandle(mWidget.rightAnchor, mWidget.cachedTransform, handles, 2, id);
    			DrawAnchorHandle(mWidget.bottomAnchor, mWidget.cachedTransform, handles, 3, id);
    		}
    
            // 需要时显示细节
    		if (type == EventType.Repaint)
    		{
    			bool showDetails = (mAction == UIWidgetInspector.Action.Scale) || NGUISettings.drawGuides; // 进行缩放时显示细节
    			if (mAction == UIWidgetInspector.Action.None && e.modifiers == EventModifiers.Control) showDetails = true;
    			if (NGUITools.GetActive(mWidget) && mWidget.parent == null) showDetails = true;
    			if (showDetails) NGUIHandles.DrawSize(handles, mWidget.width, mWidget.height);
    		}
    
    		// Presence of the legacy stretch component prevents resizing
            // TODO 显示原来的轨迹组件放置重绘 ??
    
    		bool canResize = (mWidget.GetComponent<UIStretch>() == null); // 没有这个组件说明是可以自由缩放的
    		bool[] resizable = new bool[8]; // 
    
    		resizable[4] = canResize;	// left
    		resizable[5] = canResize;	// top
    		resizable[6] = canResize;	// right
    		resizable[7] = canResize;	// bottom
    
    		UILabel lbl = mWidget as UILabel; // 如果这个 widget 组件实际上是个一个 Label 组件
    		
    		if (lbl != null)
    		{
    			if (lbl.overflowMethod == UILabel.Overflow.ResizeFreely) // 如果 label 设置为可以随意缩放,那么其锚点都定住
    			{
    				resizable[4] = false;	// left
    				resizable[5] = false;	// top
    				resizable[6] = false;	// right
    				resizable[7] = false;	// bottom
    			}
    			else if (lbl.overflowMethod == UILabel.Overflow.ResizeHeight) // 如果是高度可以自由缩放,那么上下两个锚点也定住
    			{
    				resizable[5] = false;	// top
    				resizable[7] = false;	// bottom
    			}
    		}
    
    		if (mWidget.keepAspectRatio == UIWidget.AspectRatioSource.BasedOnHeight) // 基于高度变换,那么左右锚点就不需要设置了
    		{
    			resizable[4] = false;
    			resizable[6] = false;
    		}
    		else if (mWidget.keepAspectRatio == UIWidget.AspectRatioSource.BasedOnWidth)
    		{
    			resizable[5] = false;
    			resizable[7] = false;
    		}
    
            // 角落的锚点情况根据上下左右的可用情况设置
    		resizable[0] = resizable[7] && resizable[4]; // bottom-left
    		resizable[1] = resizable[5] && resizable[4]; // top-left
    		resizable[2] = resizable[5] && resizable[6]; // top-right
    		resizable[3] = resizable[7] && resizable[6]; // bottom-right
    		
            // 获取锚点,没有的话返回 center
    		UIWidget.Pivot pivotUnderMouse = GetPivotUnderMouse(handles, e, resizable, true, ref actionUnderMouse);
    		
    		switch (type)
    		{
    			case EventType.Repaint: // 绘制控制点
    			{
    				Vector3 v0 = HandleUtility.WorldToGUIPoint(handles[0]);
    				Vector3 v2 = HandleUtility.WorldToGUIPoint(handles[2]);
    				
    				if ((v2 - v0).magnitude > 60f) // 斜边 长度大于 60 才绘制控制点
    				{
    					Vector3 v1 = HandleUtility.WorldToGUIPoint(handles[1]);
    					Vector3 v3 = HandleUtility.WorldToGUIPoint(handles[3]);
    
                        Handles.BeginGUI();
    					{
    						for (int i = 0; i < 4; ++i)
    							DrawKnob(handles[i], mWidget.pivot == pivotPoints[i], resizable[i], id);
    
    						if ((v1 - v0).magnitude > 80f)
    						{
    							if (mWidget.leftAnchor.target == null || mWidget.leftAnchor.absolute != 0)
    								DrawKnob(handles[4], mWidget.pivot == pivotPoints[4], resizable[4], id);
    
    							if (mWidget.rightAnchor.target == null || mWidget.rightAnchor.absolute != 0)
    								DrawKnob(handles[6], mWidget.pivot == pivotPoints[6], resizable[6], id);
    						}
    
    						if ((v3 - v0).magnitude > 80f)
    						{
    							if (mWidget.topAnchor.target == null || mWidget.topAnchor.absolute != 0)
    								DrawKnob(handles[5], mWidget.pivot == pivotPoints[5], resizable[5], id);
    
    							if (mWidget.bottomAnchor.target == null || mWidget.bottomAnchor.absolute != 0)
    								DrawKnob(handles[7], mWidget.pivot == pivotPoints[7], resizable[7], id);
    						}
    					}
    					Handles.EndGUI();
    				}
    			}
    			break;
    
    			case EventType.MouseDown:
    			{
    				if (actionUnderMouse != Action.None)
    				{
    					mStartMouse = e.mousePosition; // 记录鼠标起始位置
    					mAllowSelection = true; // 标记拖动的开始,拖动过程中无法再次选中
    
    					if (e.button == 1) // 
    					{
    						if (e.modifiers == 0) // 没有用组合键
    						{
    							GUIUtility.hotControl = GUIUtility.keyboardControl = id;
    							e.Use(); // 使用该事件,用于表示这个事件已经处理过了
    						}
    					}
    					else if (e.button == 0 && actionUnderMouse != Action.None && Raycast(handles, out mStartDrag)) // 鼠标左键&&能够操作&&点到了这个平面 // TODO 不知道为什么需要这么多判断
    					{
    						mWorldPos = t.position;
    						mLocalPos = t.localPosition;
    						mStartRot = t.localRotation.eulerAngles;
    						mStartDir = mStartDrag - t.position; // 用向量来表示角度,鼠标与中点连线的夹角
    						mStartWidth = mWidget.width;
    						mStartHeight = mWidget.height;
                            // TODO 上下左右,
    						mStartLeft.x = mWidget.leftAnchor.relative;
    						mStartLeft.y = mWidget.leftAnchor.absolute;
    						mStartRight.x = mWidget.rightAnchor.relative;
    						mStartRight.y = mWidget.rightAnchor.absolute;
    						mStartBottom.x = mWidget.bottomAnchor.relative;
    						mStartBottom.y = mWidget.bottomAnchor.absolute;
    						mStartTop.x = mWidget.topAnchor.relative;
    						mStartTop.y = mWidget.topAnchor.absolute;
    
                            // 
    						mDragPivot = pivotUnderMouse;
    						mActionUnderMouse = actionUnderMouse;
                            // 
    						GUIUtility.hotControl = GUIUtility.keyboardControl = id;
    						e.Use();
    					}
    				}
    			}
    			break;
    
    			case EventType.MouseDrag: 
    			{
    				// Prevent selection once the drag operation begins
                    // 如果已经进行了拖动操作,那么无法再进行选中了
    				bool dragStarted = (e.mousePosition - mStartMouse).magnitude > 3f;
    				if (dragStarted) mAllowSelection = false;
    
    				if (GUIUtility.hotControl == id) // 如果热键控制 与 id 一致
    				{
    					e.Use(); // TODO 这个为什么设置在前面?
    
    					if (mAction != Action.None || mActionUnderMouse != Action.None) //
    					{
    						Vector3 pos;
    
    						if (Raycast(handles, out pos))
    						{
                                // 拖动开始时进行数据记录
    							if (mAction == Action.None && mActionUnderMouse != Action.None) // 前面的 mAction 用于标记是否是拖动刚开始
    							{
    								// Wait until the mouse moves by more than a few pixels
    								if (dragStarted)
    								{
    									if (mActionUnderMouse == Action.Move) // 
    									{
    										NGUISnap.Recalculate(mWidget); // 重新计算
    									}
    									else if (mActionUnderMouse == Action.Rotate) // 
    									{
    										mStartRot = t.localRotation.eulerAngles; // 返回欧垃角
    										mStartDir = mStartDrag - t.position; // 旋转的角度
    									}
    									else if (mActionUnderMouse == Action.Scale)
    									{
    										mStartWidth = mWidget.width;
    										mStartHeight = mWidget.height;
    										mDragPivot = pivotUnderMouse;
    									}
    									mAction = actionUnderMouse;
    								}
    							}
    
                                // 
    							if (mAction != Action.None)
    							{
                                    // 设置撤销点
    								NGUIEditorTools.RegisterUndo("Change Rect", t); 
    								NGUIEditorTools.RegisterUndo("Change Rect", mWidget);
    
    								// Reset the widget before adjusting anything
                                    // 在进行任何调整前先进行重置
    								t.position = mWorldPos;
    								mWidget.width = mStartWidth;
    								mWidget.height = mStartHeight;
                                    // widget 的上下左右锚点都重置为初始值
    								mWidget.leftAnchor.Set(mStartLeft.x, mStartLeft.y);
    								mWidget.rightAnchor.Set(mStartRight.x, mStartRight.y);
    								mWidget.bottomAnchor.Set(mStartBottom.x, mStartBottom.y);
    								mWidget.topAnchor.Set(mStartTop.x, mStartTop.y);
    
                                    // 移动操作
    								if (mAction == Action.Move)
    								{
    									// Move the widget
                                        t.position = mWorldPos + (pos - mStartDrag); // t.position = t.positon + (pos - mStartDrag);//mWorldPos 和 mStartDrag 应该是同一个值,不知道为什么要分开来
    									Vector3 after = t.localPosition; // 
    
    									bool snapped = false; //
    									Transform parent = t.parent; 
    
    									if (parent != null)
    									{
    										UIGrid grid = parent.GetComponent<UIGrid>(); // 
    
                                            // 如果说这个widget的父节点具有 Grid 组件,并且按照 CellSnap 的布局方式进行布局
                                            // 那么根据grid的cell大小进行对齐操作。
    										if (grid != null && grid.arrangement == UIGrid.Arrangement.CellSnap)
    										{
    											snapped = true;
    											if (grid.cellWidth > 0) after.x = Mathf.Round(after.x / grid.cellWidth) * grid.cellWidth;
    											if (grid.cellHeight > 0) after.y = Mathf.Round(after.y / grid.cellHeight) * grid.cellHeight;
    										}
    									}
    
                                        // 如果还没对齐过,进行对齐
    									if (!snapped)
    									{
    										// Snap the widget
    										after = NGUISnap.Snap(after, mWidget.localCorners, e.modifiers != EventModifiers.Control);
    									}
    
    									// Calculate the final delta
                                        // 本地坐标的变化量
    									Vector3 localDelta = (after - mLocalPos);
    
    									// Restore the position
    									t.position = mWorldPos; // 恢复坐标位置
    
    									// Adjust the widget by the delta
                                        // 根据 delta 来移动 Widget 。 // TODO 这跟直接移动 postion 有什么区别?
    									NGUIMath.MoveRect(mWidget, localDelta.x, localDelta.y);
    								}
    								else if (mAction == Action.Rotate)
    								{
                                        // 这部分代码不是太懂呢。。
    									Vector3 dir = pos - t.position;
    									float angle = Vector3.Angle(mStartDir, dir);
    
    									if (angle > 0f)
    									{
    										float dot = Vector3.Dot(Vector3.Cross(mStartDir, dir), t.forward);
    										if (dot < 0f) angle = -angle;
    										angle = mStartRot.z + angle; // 为什么要加 z 值
    										angle = (NGUISnap.allow && e.modifiers != EventModifiers.Control) ?
    											Mathf.Round(angle / 15f) * 15f : Mathf.Round(angle);
                                            // 计算欧拉角
    										t.localRotation = Quaternion.Euler(mStartRot.x, mStartRot.y, angle);
    									}
    								}
    								else if (mAction == Action.Scale)
    								{
    									// Move the widget
                                        // 
    									t.position = mWorldPos + (pos - mStartDrag);
    
    									// Calculate the final delta
    									Vector3 localDelta = (t.localPosition - mLocalPos);
    
    									// Restore the position
    									t.position = mWorldPos;
    
    									// Adjust the widget's position and scale based on the delta, restricted by the pivot
                                        // 以枢轴点为中心进行缩放
    									NGUIMath.ResizeWidget(mWidget, mDragPivot, localDelta.x, localDelta.y, 2, 2);
    									ReEvaluateAnchorType();
    								}
    							}
    						}
    					}
    				}
    			}
    			break;
    
                    // 释放鼠标
    			case EventType.MouseUp:
    			{
    				if (e.button == 2) break; // 中键不处理
    
    				if (GUIUtility.hotControl == id)
    				{
                        // 收尾处理
    					GUIUtility.hotControl = 0;
    					GUIUtility.keyboardControl = 0;
    
                        // 
    					if (e.button < 2)
    					{
    						bool handled = false; 
    
                            // 
    						if (e.button == 1)
    						{
    							// Right-click: Open a context menu listing all widgets underneath
    							NGUIEditorTools.ShowSpriteSelectionMenu(e.mousePosition);
    							handled = true;
    						}
    						else if (mAction == Action.None)
    						{
                                // 选择对象
    							if (mAllowSelection)
    							{
    								// Left-click: Select the topmost widget
    								NGUIEditorTools.SelectWidget(e.mousePosition);
    								handled = true;
    							}
    						}
    						else
    						{
    							// Finished dragging something
    							Vector3 pos = t.localPosition;
    							pos.x = Mathf.Round(pos.x);
    							pos.y = Mathf.Round(pos.y);
    							pos.z = Mathf.Round(pos.z);
    							t.localPosition = pos; //对相对位置进行圆整
    							handled = true;
    						}
    
    						if (handled) e.Use(); // 如果处理过了,那么该事件结束
    					}
    
    					// Clear the actions
    					mActionUnderMouse = Action.None;
    					mAction = Action.None;
    				}
    				else if (mAllowSelection) // 没控制但是允许选中,那么选择第一个 widget
    				{
    					List<UIWidget> widgets = NGUIEditorTools.SceneViewRaycast(e.mousePosition);
    					if (widgets.Count > 0) Selection.activeGameObject = widgets[0].gameObject;
    				}
    				mAllowSelection = true;
    			}
    			break;
    
                // 上下左右键对矩形框进行移动
    			case EventType.KeyDown:
    			{
    				if (e.keyCode == KeyCode.UpArrow)
    				{
    					NGUIEditorTools.RegisterUndo("Nudge Rect", t);
    					NGUIEditorTools.RegisterUndo("Nudge Rect", mWidget);
    					NGUIMath.MoveRect(mWidget, 0f, 1f);
    					e.Use();
    				}
    				else if (e.keyCode == KeyCode.DownArrow)
    				{
    					NGUIEditorTools.RegisterUndo("Nudge Rect", t);
    					NGUIEditorTools.RegisterUndo("Nudge Rect", mWidget);
    					NGUIMath.MoveRect(mWidget, 0f, -1f);
    					e.Use();
    				}
    				else if (e.keyCode == KeyCode.LeftArrow)
    				{
    					NGUIEditorTools.RegisterUndo("Nudge Rect", t);
    					NGUIEditorTools.RegisterUndo("Nudge Rect", mWidget);
    					NGUIMath.MoveRect(mWidget, -1f, 0f);
    					e.Use();
    				}
    				else if (e.keyCode == KeyCode.RightArrow)
    				{
    					NGUIEditorTools.RegisterUndo("Nudge Rect", t);
    					NGUIEditorTools.RegisterUndo("Nudge Rect", mWidget);
    					NGUIMath.MoveRect(mWidget, 1f, 0f);
    					e.Use();
    				}
    				else if (e.keyCode == KeyCode.Escape)
    				{
    					if (GUIUtility.hotControl == id)
    					{
    						if (mAction != Action.None)
    							Undo.PerformUndo();
    
    						GUIUtility.hotControl = 0;
    						GUIUtility.keyboardControl = 0;
    
    						mActionUnderMouse = Action.None;
    						mAction = Action.None;
    						e.Use();
    					}
    					else Selection.activeGameObject = null;
    				}
    			}
    			break;
    		}
    	}
    
    	/// <summary>
    	/// Cache the reference.
    	/// 记录引用
    	/// </summary>
    
    	protected override void OnEnable ()
    	{
    		base.OnEnable();
    		instance = this;
    		mWidget = target as UIWidget; // 在对 mWidget 进行操作时为什么不需要判空?
    	}
    
    	/// <summary>
    	/// All widgets have depth, color and make pixel-perfect options
        /// 所有组件都有 depth,color和 pixel-perfect 选项
    	/// </summary>
    	
        protected override void DrawCustomProperties ()
    	{
    		if (NGUISettings.unifiedTransform) // 这个不知道是哪里设置的。。如果是统一的transform,某些部分就不需要显示了。
    		{
    			DrawColor(serializedObject, mWidget);
    		}
    		else DrawInspectorProperties(serializedObject, mWidget, true); // 在检视器中显示Widget组件的操作面板
    	}
    
    	/// <summary>
    	/// Draw common widget properties that can be shown as a part of the Transform Inspector.
    	/// 在检视器中显示通用的 widget 属性,不显示颜色部分
    	/// </summary>
    
    	public void DrawWidgetTransform () { DrawInspectorProperties(serializedObject, mWidget, false); }
    
    	/// <summary>
    	/// Draw the widget's color.
    	/// 在检视器中显示,设置 widget 的颜色和透明度
    	/// </summary>
    
    	static public void DrawColor (SerializedObject so, UIWidget w)
    	{
    		if ((w.GetType() != typeof(UIWidget)))
    		{
    			NGUIEditorTools.DrawProperty("Color Tint", so, "mColor", GUILayout.MinWidth(20f));
    		}
    		else if (so.isEditingMultipleObjects)
    		{
    			NGUIEditorTools.DrawProperty("Alpha", so, "mColor.a", GUILayout.Width(120f));
    		}
    		else
    		{
    			GUI.changed = false;
    			float alpha = EditorGUILayout.Slider("Alpha", w.alpha, 0f, 1f);
    
    			if (GUI.changed)
    			{
    				NGUIEditorTools.RegisterUndo("Alpha change", w);
    				w.alpha = alpha;
    			}
    		}
    	}
    
    	/// <summary>
    	/// Draw common widget properties.
    	/// 在检视器中显示通用 widget 属性
    	/// </summary>
    
    	static public void DrawInspectorProperties (SerializedObject so, UIWidget w, bool drawColor)
    	{
    		if (drawColor)
    		{
    			DrawColor(so, w);
    			GUILayout.Space(3f);
    		}
    
    		PrefabType type = PrefabUtility.GetPrefabType(w.gameObject); // TODO 为什么要辨别出 prefab 的类型?有些情况不需要显示?
    
    		if (NGUIEditorTools.DrawHeader("Widget")) // 包裹起来
    		{
    			NGUIEditorTools.BeginContents();
    			if (NGUISettings.minimalisticLook) NGUIEditorTools.SetLabelWidth(70f);
    
    			DrawPivot(so, w); //枢轴点
    			DrawDepth(so, w, type == PrefabType.Prefab);// 深度
    			DrawDimensions(so, w, type == PrefabType.Prefab);// 大小
    			if (NGUISettings.minimalisticLook) NGUIEditorTools.SetLabelWidth(70f); 
    
    			SerializedProperty ratio = so.FindProperty("aspectRatio");
    			SerializedProperty aspect = so.FindProperty("keepAspectRatio");
    
    			GUILayout.BeginHorizontal();
    			{
    				if (!aspect.hasMultipleDifferentValues && aspect.intValue == 0) // 单个或多个对象选中时 aspect 都是第一种情况
    				{
    					EditorGUI.BeginDisabledGroup(true); // 设置为禁用
    					NGUIEditorTools.DrawProperty("Aspect", ratio, false, GUILayout.Width(130f));
    					EditorGUI.EndDisabledGroup();
    				}
    				else NGUIEditorTools.DrawProperty("Aspect", ratio, false, GUILayout.Width(130f));
    
    				NGUIEditorTools.DrawProperty("", aspect, false, GUILayout.MinWidth(20f));
    			}
    			GUILayout.EndHorizontal();
    
                // 编辑多个对象或者对象存在 碰撞盒的时候显示
    			if (so.isEditingMultipleObjects || w.hasBoxCollider)
    			{
    				GUILayout.BeginHorizontal();
    				{
    					NGUIEditorTools.DrawProperty("Collider", so, "autoResizeBoxCollider", GUILayout.Width(100f));
    					GUILayout.Label("auto-adjust to match");
    				}
    				GUILayout.EndHorizontal();
    			}
    			NGUIEditorTools.EndContents();
    		}
    	}
    
    	/// <summary>
    	/// Draw widget's dimensions.
    	/// </summary>
    
    	static void DrawDimensions (SerializedObject so, UIWidget w, bool isPrefab)
    	{
    		GUILayout.BeginHorizontal();
    		{
    			bool freezeSize = so.isEditingMultipleObjects;
    
    			UILabel lbl = w as UILabel;
    
    			if (!freezeSize && lbl) freezeSize = (lbl.overflowMethod == UILabel.Overflow.ResizeFreely);
    
    			if (freezeSize)
    			{
    				EditorGUI.BeginDisabledGroup(true);
    				NGUIEditorTools.DrawProperty("Size", so, "mWidth", GUILayout.MinWidth(100f));
    				EditorGUI.EndDisabledGroup();
    			}
    			else
    			{
    				GUI.changed = false;
    				int val = EditorGUILayout.IntField("Size", w.width, GUILayout.MinWidth(100f));
    
    				if (GUI.changed)
    				{
    					NGUIEditorTools.RegisterUndo("Dimensions Change", w);
    					w.width = val;
    				}
    			}
    
    			if (!freezeSize && lbl)
    			{
    				UILabel.Overflow ov = lbl.overflowMethod;
    				freezeSize = (ov == UILabel.Overflow.ResizeFreely || ov == UILabel.Overflow.ResizeHeight);
    			}
    
    			NGUIEditorTools.SetLabelWidth(12f);
    
    			if (freezeSize)
    			{
    				EditorGUI.BeginDisabledGroup(true);
    				NGUIEditorTools.DrawProperty("x", so, "mHeight", GUILayout.MinWidth(30f));
    				EditorGUI.EndDisabledGroup();
    			}
    			else
    			{
    				GUI.changed = false;
    				int val = EditorGUILayout.IntField("x", w.height, GUILayout.MinWidth(30f));
    
    				if (GUI.changed)
    				{
    					NGUIEditorTools.RegisterUndo("Dimensions Change", w);
    					w.height = val;
    				}
    			}
    
    			NGUIEditorTools.SetLabelWidth(80f);
    
    			if (isPrefab)
    			{
    				GUILayout.Space(70f);
    			}
    			else
    			{
    				EditorGUI.BeginDisabledGroup(so.isEditingMultipleObjects);
    
    				if (GUILayout.Button("Snap", GUILayout.Width(60f)))
    				{
    					foreach (GameObject go in Selection.gameObjects)
    					{
    						UIWidget pw = go.GetComponent<UIWidget>();
    
    						if (pw != null)
    						{
    							NGUIEditorTools.RegisterUndo("Snap Dimensions", pw);
    							NGUIEditorTools.RegisterUndo("Snap Dimensions", pw.transform);
    							pw.MakePixelPerfect();
    						}
    					}
    				}
    				EditorGUI.EndDisabledGroup();
    			}
    		}
    		GUILayout.EndHorizontal();
    	}
    
    	/// <summary>
    	/// Draw widget's depth.
    	/// </summary>
    
    	static void DrawDepth (SerializedObject so, UIWidget w, bool isPrefab)
    	{
    		if (isPrefab) return;
    
    		GUILayout.Space(2f);
    		GUILayout.BeginHorizontal();
    		{
    			EditorGUILayout.PrefixLabel("Depth");
    
    			if (GUILayout.Button("Back", GUILayout.MinWidth(46f)))
    			{
    				foreach (GameObject go in Selection.gameObjects)
    				{
    					UIWidget pw = go.GetComponent<UIWidget>();
    					if (pw != null) pw.depth = w.depth - 1;
    				}
    			}
    
    			NGUIEditorTools.DrawProperty("", so, "mDepth", GUILayout.MinWidth(20f));
    
    			if (GUILayout.Button("Forward", GUILayout.MinWidth(60f)))
    			{
    				foreach (GameObject go in Selection.gameObjects)
    				{
    					UIWidget pw = go.GetComponent<UIWidget>();
    					if (pw != null) pw.depth = w.depth + 1;
    				}
    			}
    		}
    		GUILayout.EndHorizontal();
    
    		int matchingDepths = 1;
    
    		UIPanel p = w.panel;
    
    		if (p != null)
    		{
    			for (int i = 0, imax = p.widgets.Count; i < imax; ++i)
    			{
    				UIWidget pw = p.widgets[i];
    				if (pw != w && pw.depth == w.depth)
    					++matchingDepths;
    			}
    		}
    
    		if (matchingDepths > 1)
    		{
    			EditorGUILayout.HelpBox(matchingDepths + " widgets are sharing the depth value of " + w.depth, MessageType.Info);
    		}
    	}
    
    	/// <summary>
    	/// Draw the widget's pivot.
    	/// </summary>
    
    	static void DrawPivot (SerializedObject so, UIWidget w)
    	{
    		SerializedProperty pv = so.FindProperty("mPivot");
    
    		if (pv.hasMultipleDifferentValues)
    		{
    			// TODO: Doing this doesn't keep the widget's position where it was. Another approach is needed.
    			NGUIEditorTools.DrawProperty("Pivot", so, "mPivot");
    		}
    		else
    		{
    			// Pivot point -- the new, more visual style
    			GUILayout.BeginHorizontal();
    			GUILayout.Label("Pivot", GUILayout.Width(NGUISettings.minimalisticLook ? 66f : 76f));
    			Toggle(w, "u25C4", "ButtonLeft", UIWidget.Pivot.Left, true);
    			Toggle(w, "u25AC", "ButtonMid", UIWidget.Pivot.Center, true);
    			Toggle(w, "u25BA", "ButtonRight", UIWidget.Pivot.Right, true);
    			Toggle(w, "u25B2", "ButtonLeft", UIWidget.Pivot.Top, false);
    			Toggle(w, "u258C", "ButtonMid", UIWidget.Pivot.Center, false);
    			Toggle(w, "u25BC", "ButtonRight", UIWidget.Pivot.Bottom, false);
    
    			GUILayout.EndHorizontal();
    			pv.enumValueIndex = (int)w.pivot;
    		}
    	}
    
    	/// <summary>
    	/// Draw a toggle button for the pivot point.
    	/// </summary>
    
    	static void Toggle (UIWidget w, string text, string style, UIWidget.Pivot pivot, bool isHorizontal)
    	{
    		bool isActive = false;
    
    		switch (pivot)
    		{
    			case UIWidget.Pivot.Left:
    			isActive = IsLeft(w.pivot);
    			break;
    
    			case UIWidget.Pivot.Right:
    			isActive = IsRight(w.pivot);
    			break;
    
    			case UIWidget.Pivot.Top:
    			isActive = IsTop(w.pivot);
    			break;
    
    			case UIWidget.Pivot.Bottom:
    			isActive = IsBottom(w.pivot);
    			break;
    
    			case UIWidget.Pivot.Center:
    			isActive = isHorizontal ? pivot == GetHorizontal(w.pivot) : pivot == GetVertical(w.pivot);
    			break;
    		}
    
    		if (GUILayout.Toggle(isActive, text, style) != isActive)
    			SetPivot(w, pivot, isHorizontal);
    	}
    
    	static bool IsLeft (UIWidget.Pivot pivot)
    	{
    		return pivot == UIWidget.Pivot.Left ||
    			pivot == UIWidget.Pivot.TopLeft ||
    			pivot == UIWidget.Pivot.BottomLeft;
    	}
    
    	static bool IsRight (UIWidget.Pivot pivot)
    	{
    		return pivot == UIWidget.Pivot.Right ||
    			pivot == UIWidget.Pivot.TopRight ||
    			pivot == UIWidget.Pivot.BottomRight;
    	}
    
    	static bool IsTop (UIWidget.Pivot pivot)
    	{
    		return pivot == UIWidget.Pivot.Top ||
    			pivot == UIWidget.Pivot.TopLeft ||
    			pivot == UIWidget.Pivot.TopRight;
    	}
    
    	static bool IsBottom (UIWidget.Pivot pivot)
    	{
    		return pivot == UIWidget.Pivot.Bottom ||
    			pivot == UIWidget.Pivot.BottomLeft ||
    			pivot == UIWidget.Pivot.BottomRight;
    	}
    
    	static UIWidget.Pivot GetHorizontal (UIWidget.Pivot pivot)
    	{
    		if (IsLeft(pivot)) return UIWidget.Pivot.Left;
    		if (IsRight(pivot)) return UIWidget.Pivot.Right;
    		return UIWidget.Pivot.Center;
    	}
    
    	static UIWidget.Pivot GetVertical (UIWidget.Pivot pivot)
    	{
    		if (IsTop(pivot)) return UIWidget.Pivot.Top;
    		if (IsBottom(pivot)) return UIWidget.Pivot.Bottom;
    		return UIWidget.Pivot.Center;
    	}
    
    	static UIWidget.Pivot Combine (UIWidget.Pivot horizontal, UIWidget.Pivot vertical)
    	{
    		if (horizontal == UIWidget.Pivot.Left)
    		{
    			if (vertical == UIWidget.Pivot.Top) return UIWidget.Pivot.TopLeft;
    			if (vertical == UIWidget.Pivot.Bottom) return UIWidget.Pivot.BottomLeft;
    			return UIWidget.Pivot.Left;
    		}
    
    		if (horizontal == UIWidget.Pivot.Right)
    		{
    			if (vertical == UIWidget.Pivot.Top) return UIWidget.Pivot.TopRight;
    			if (vertical == UIWidget.Pivot.Bottom) return UIWidget.Pivot.BottomRight;
    			return UIWidget.Pivot.Right;
    		}
    		return vertical;
    	}
    
    	static void SetPivot (UIWidget w, UIWidget.Pivot pivot, bool isHorizontal)
    	{
    		UIWidget.Pivot horizontal = GetHorizontal(w.pivot);
    		UIWidget.Pivot vertical = GetVertical(w.pivot);
    
    		pivot = isHorizontal ? Combine(pivot, vertical) : Combine(horizontal, pivot);
    
    		if (w.pivot != pivot)
    		{
    			NGUIEditorTools.RegisterUndo("Pivot change", w);
    			w.pivot = pivot;
    		}
    	}
    
    	protected override void OnDrawFinalProperties ()
    	{
    		if (mAnchorType == AnchorType.Advanced || !mWidget.isAnchored) return;
    
    		SerializedProperty sp = serializedObject.FindProperty("leftAnchor.target");
    
    		if (!IsRect(sp))
    		{
    			GUILayout.Space(3f);
    			GUILayout.BeginHorizontal();
    			GUILayout.Space(6f);
    			NGUIEditorTools.DrawProperty("", serializedObject, "hideIfOffScreen", GUILayout.Width(18f));
    			GUILayout.Label("Hide if off-screen", GUILayout.MinWidth(20f));
    			GUILayout.EndHorizontal();
    		}
    	}
    }
    
    
  • 相关阅读:
    【笔记】nRF24L01软件初始化
    【笔记】关于DSP连接CMD文件及连接存储块的理解
    【笔记】CCS4 出现 warning: entrypoint symbol other than "_c_int00" specified: "code_start" 的解决方法
    【转载】低压电流互感器实用技术问答30例
    【笔记】1、防止电压反充电,2、前后加速,3、开口三角PT(TV)原理
    Linux虚拟文件系统及其实例XORFS
    LINUX内核狂想曲之SLOB分配器
    程序的思想决定程序的世界
    LINUX内核之内存屏障
    插入排序——平均算法复杂度分析
  • 原文地址:https://www.cnblogs.com/tangyikejun/p/4824252.html
Copyright © 2011-2022 走看看