protected void checkHoverWindow(ref Vector3 mousePos, bool mouseDown) { IMouseEventCollect newWindow = null; // 模拟触摸状态下,如果鼠标未按下,则不会悬停在任何窗口上 if (mouseDown || !mSimulateTouch) { // 计算鼠标当前所在最前端的窗口 newWindow = getHoverWindow(ref mousePos); } // 判断鼠标是否还在当前窗口内 if (mHoverWindow != null) { // 鼠标已经移动到了其他窗口中,发送鼠标离开的事件 if (newWindow != mHoverWindow) { // 不过也许此时悬停窗口已经不接收输入事件了或者碰撞盒子被禁用了,需要判断一下 if (mHoverWindow.isActive() && mHoverWindow.isHandleInput()) { mHoverWindow.onMouseLeave(); } // 找到鼠标所在的新的窗口,给该窗口发送鼠标进入的事件 newWindow?.onMouseEnter(); } } // 如果上一帧鼠标没有在任何窗口内,则计算这一帧鼠标所在的窗口 else { // 发送鼠标进入的事件 newWindow?.onMouseEnter(); } mHoverWindow = newWindow; }
// ignorePassRay表示是否忽略窗口的isPassRay属性,true表示认为所有的都允许射线穿透 protected void raycastLayout(ref Ray ray, SortedDictionary <UIDepth, List <IMouseEventCollect> > windowOrderList, List <IMouseEventCollect> retList, ref bool continueRay, bool clearList = true, int maxCount = 0, bool ignorePassRay = false) { if (clearList) { retList.Clear(); } continueRay = true; RaycastHit hit; foreach (var box in windowOrderList) { int count = box.Value.Count; for (int i = 0; i < count; ++i) { IMouseEventCollect window = box.Value[i]; if (window.isActive() && window.isHandleInput() && window.getCollider().Raycast(ray, out hit, 10000.0f)) { // 点击了只允许部分穿透的背景 if (mPassOnlyArea.ContainsKey(window)) { IMouseEventCollect child = mPassOnlyArea[window]; //判断是否点到了背景中允许穿透的部分,如果是允许穿透的部分,则射线可以继续判断下层的窗口,否则不允许再继续穿透 continueRay = child.isActive() && child.isHandleInput() && child.getCollider().Raycast(ray, out hit, 10000.0f); if (!continueRay) { break; } } else { retList.Add(window); // 如果射线不能穿透当前按钮,或者已经达到最大数量,则不再继续 bool passRay = ignorePassRay || window.isPassRay(); bool countNotFull = maxCount <= 0 || retList.Count < maxCount; continueRay = passRay && countNotFull; if (!continueRay) { break; } } } } if (!continueRay) { break; } } }
protected void raycastMovableObject(ref Ray ray, List <IMouseEventCollect> moveObjectList, List <IMouseEventCollect> retList, ref bool continueRay, bool clearList = true) { if (clearList) { retList.Clear(); } continueRay = true; RaycastHit hit; LIST(out List <DistanceSortHelper> sortList); int objCount = moveObjectList.Count; for (int i = 0; i < objCount; ++i) { IMouseEventCollect box = moveObjectList[i]; // 将所有射线碰到的物体都放到列表中 if (box.isActive() && box.isHandleInput() && box.getCollider().Raycast(ray, out hit, 10000.0f)) { sortList.Add(new DistanceSortHelper(getSquaredLength(hit.point - ray.origin), box)); } } // 根据相交点由近到远的顺序排序 quickSort(sortList, DistanceSortHelper.mCompareAscend); int sortCount = sortList.Count; for (int i = 0; i < sortCount; ++i) { DistanceSortHelper item = sortList[i]; retList.Add(item.mObject); if (!item.mObject.isPassRay()) { continueRay = false; break; } } UN_LIST(sortList); }