UGUI是建立在3D网格下的。也就是说UI在被实例化时,第一件事就是构建网格
事件数据模块:
AxisEventData 记录滚轮数据信息
PointerEventData 记录鼠标触摸位置,点击位置,上次点击的时间,点击次数等数据
输入事件捕获模块:
BaseInputModule 基类模块,PointerInputModule继承自BaseInputModule。这个模块类内置了几个状态类如MouseState、MouseButtonEventData、ButtonState。给输入添加了类型和状态。
StandaloneInputModule、TouchInputModule 均继承自PointerInputModule
StandaloneInputModule和TouchInputModule才是真正处理事件的模块
ProcessMouseEvent函数处理鼠标所有的事件包括鼠标按下、移动、滚轮、拖拽。函数内部逻辑主要调用了ProcessMousePress、ProcessMove、ProcessDrag函数。
ProcessMousePress函数:
开始定义了一个名字为pointerEvent的参数用于存储调用鼠标事件句柄(如IPointerClickHandler鼠标按下)前后的数据。这里处理了鼠标按下、拖拽、鼠标抬起、点击、拖拽结束、等事件句柄。
ProcessDrag函数:
主要进行判断、根据拖拽情况执行开始拖拽句柄和拖拽中句柄等
ProcessMove函数:没有判断直接执行相应句柄
TouchInputModule模块中核心函数是ProcessTouchEvents这个函数是这样的, 具体执行和StandaloneInputModule差不多
// 所有触碰到的点都会执行
//
private void ProcessTouchEvents()
{
for (int i = 0; i < Input.touchCount; ++i)
{
Touch input = Input.GetTouch(i);
bool released;
bool pressed;
var pointer = GetTouchPointerEventData(input, out pressed, out released);
ProcessTouchPress(pointer, pressed, released);
if (!released)
{
ProcessMove(pointer);
ProcessDrag(pointer);
}
else
RemovePointerData(pointer);
}
}
这2个模块中调用大量ExecuteEvents.ExecuteHierarchy,ExecuteEvents.Execute。下面学习这2个函数组成。
private static readonly List s_InternalTransformList = new List(30);
public static GameObject ExecuteHierarchy(GameObject root, BaseEventData eventData, EventFunction callbackFunction) where T : IEventSystemHandler
{
// 获取物体的所有父节点,包括它自己
GetEventChain(root, s_InternalTransformList);
for (var i = 0; i < s_InternalTransformList.Count; i++)
{
var transform = s_InternalTransformList[i];
// 对每个父节点包括自己依次执行句柄响应
if (Execute(transform.gameObject, eventData, callbackFunction))
return transform.gameObject;
}
return null;
}
这里作者说的是 当前节点事件会通知到父节点。(TODO为什么要通知父节点)
射线检测模块
在GraphicRaycaster类中函数 private static void Raycast(Canvas canvas, Camera eventCamera, Vector2 pointerPosition, IList
事件处理逻辑
EventSystem是主要的逻辑入口、EventInterfaces,EventTrigger,EventTriggerType定义了一系列回调函数
其中主要通过判断事件是否成立然后调用ExecuteEvents.Execute,并将事件数据传入