Ejemplo n.º 1
0
    // ignorePassRay表示是否忽略窗口的isPassRay属性,true表示认为所有的都允许射线穿透
    // 但是ignorePassRay不会影响到PassOnlyArea和ParentPassOnly
    protected void raycastLayout(ref Ray ray,
                                 List <IMouseEventCollect> windowOrderList,
                                 List <IMouseEventCollect> retList,
                                 ref bool continueRay,
                                 bool clearList     = true,
                                 bool ignorePassRay = false)
    {
        if (clearList)
        {
            retList.Clear();
        }
        // mParentPassOnlyList需要重新整理,排除未启用的布局的窗口
        LIST(out List <IMouseEventCollect> activeParentList);
        // 在只允许父节点穿透的列表中已成功穿透的父节点列表
        LIST(out List <IMouseEventCollect> passParent);

        // 筛选出已激活的父节点穿透窗口
        int allParentCount = mParentPassOnlyList.Count;

        for (int i = 0; i < allParentCount; ++i)
        {
            if (mParentPassOnlyList[i].isActiveInHierarchy())
            {
                activeParentList.Add(mParentPassOnlyList[i]);
            }
        }

        // 射线检测
        continueRay = true;
        int windowCount = windowOrderList.Count;

        for (int i = 0; i < windowCount; ++i)
        {
            IMouseEventCollect window = windowOrderList[i];
            if (window.isActiveInHierarchy() && window.isHandleInput() && window.getCollider().Raycast(ray, out _, 10000.0f))
            {
                // 点击到了只允许父节点穿透的窗口,记录到列表中
                // 但是因为父节点一定是在子节点之后判断的,子节点可能已经拦截了射线,从而导致无法检测到父节点
                if (activeParentList.Contains(window))
                {
                    passParent.Add(window);
                    // 特殊窗口暂时不能接收输入事件,所以不放入相交窗口列表中
                    continue;
                }

                // 点击了只允许部分穿透的背景
                if (mPassOnlyArea.TryGetValue(window, out IMouseEventCollect passOnlyArea))
                {
                    //判断是否点到了背景中允许穿透的部分,如果是允许穿透的部分,则射线可以继续判断下层的窗口,否则不允许再继续穿透
                    continueRay = passOnlyArea.isActiveInHierarchy() && passOnlyArea.isHandleInput() && passOnlyArea.getCollider().Raycast(ray, out _, 10000.0f);
                    if (!continueRay)
                    {
                        break;
                    }
                    // 特殊窗口暂时不能接收输入事件,所以不放入相交窗口列表中
                    continue;
                }

                // 如果父节点不允许穿透
                if (!isParentPassed(window, activeParentList, passParent))
                {
                    continue;
                }

                // 射线成功与窗口相交,放入列表
                retList.Add(window);
                // 如果射线不能穿透当前按钮,则不再继续
                continueRay = ignorePassRay || window.isPassRay();
            }
            if (!continueRay)
            {
                break;
            }
        }
        UN_LIST(passParent);
        UN_LIST(activeParentList);
    }