Esempio n. 1
0
void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPointer& pickResult) {
    // TODO: avatars/HUD?
    auto pointerManager = DependencyManager::get<PointerManager>();

    // NOTE: After this loop: _prevButtons = buttons that were removed
    // If switching to disabled or should stop triggering, release all buttons
    Buttons buttons;
    Buttons newButtons;
    Buttons sameButtons;
    if (_enabled && shouldTrigger(pickResult)) {
        buttons = getPressedButtons(pickResult);
        for (const std::string& button : buttons) {
            if (_prevButtons.find(button) == _prevButtons.end()) {
                newButtons.insert(button);
            } else {
                sameButtons.insert(button);
                _prevButtons.erase(button);
            }
        }
    }

    // Hover events
    bool doHover = shouldHover(pickResult);
    Pointer::PickedObject hoveredObject = getHoveredObject(pickResult);
    PointerEvent hoveredEvent = buildPointerEvent(hoveredObject, pickResult);
    hoveredEvent.setType(PointerEvent::Move);
    hoveredEvent.setID(pointerID);
    bool moveOnHoverLeave = (!_enabled && _prevEnabled) || (!doHover && _prevDoHover);
    hoveredEvent.setMoveOnHoverLeave(moveOnHoverLeave);

    // if shouldHover && !_prevDoHover, only send hoverBegin
    if (_enabled && _hover && doHover && !_prevDoHover) {
        if (hoveredObject.type == ENTITY) {
            emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent);
        } else if (hoveredObject.type == LOCAL_ENTITY) {
            emit pointerManager->hoverBeginOverlay(hoveredObject.objectID, hoveredEvent);
        } else if (hoveredObject.type == HUD) {
            emit pointerManager->hoverBeginHUD(hoveredEvent);
        }
    } else if (_enabled && _hover && doHover) {
        if (hoveredObject.type == LOCAL_ENTITY) {
            if (_prevHoveredObject.type == LOCAL_ENTITY) {
                if (hoveredObject.objectID == _prevHoveredObject.objectID) {
                    emit pointerManager->hoverContinueOverlay(hoveredObject.objectID, hoveredEvent);
                } else {
                    PointerEvent prevHoveredEvent = buildPointerEvent(_prevHoveredObject, pickResult);
                    prevHoveredEvent.setID(pointerID);
                    prevHoveredEvent.setMoveOnHoverLeave(moveOnHoverLeave);
                    emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, prevHoveredEvent);
                    emit pointerManager->hoverBeginOverlay(hoveredObject.objectID, hoveredEvent);
                }
            } else {
                emit pointerManager->hoverBeginOverlay(hoveredObject.objectID, hoveredEvent);
                if (_prevHoveredObject.type == ENTITY) {
                    emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent);
                } else if (_prevHoveredObject.type == HUD) {
                    emit pointerManager->hoverEndHUD(hoveredEvent);
                }
            }
        }

        // TODO: this is basically repeated code.  is there a way to clean it up?
        if (hoveredObject.type == ENTITY) {
            if (_prevHoveredObject.type == ENTITY) {
                if (hoveredObject.objectID == _prevHoveredObject.objectID) {
                    emit pointerManager->hoverContinueEntity(hoveredObject.objectID, hoveredEvent);
                } else {
                    PointerEvent prevHoveredEvent = buildPointerEvent(_prevHoveredObject, pickResult);
                    prevHoveredEvent.setID(pointerID);
                    prevHoveredEvent.setMoveOnHoverLeave(moveOnHoverLeave);
                    emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, prevHoveredEvent);
                    emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent);
                }
            } else {
                emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent);
                if (_prevHoveredObject.type == LOCAL_ENTITY) {
                    emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent);
                } else if (_prevHoveredObject.type == HUD) {
                    emit pointerManager->hoverEndHUD(hoveredEvent);
                }
            }
        }

        if (hoveredObject.type == HUD) {
            if (_prevHoveredObject.type == HUD) {
                // There's only one HUD
                emit pointerManager->hoverContinueHUD(hoveredEvent);
            } else {
                emit pointerManager->hoverBeginHUD(hoveredEvent);
                if (_prevHoveredObject.type == ENTITY) {
                    emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent);
                } else if (_prevHoveredObject.type == LOCAL_ENTITY) {
                    emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent);
                }
            }
        }

        if (hoveredObject.type == NONE) {
            if (_prevHoveredObject.type == ENTITY) {
                emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent);
            } else if (_prevHoveredObject.type == LOCAL_ENTITY) {
                emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent);
            } else if (_prevHoveredObject.type == HUD) {
                emit pointerManager->hoverEndHUD(hoveredEvent);
            }
        }
    }

    // Trigger begin
    const std::string SHOULD_FOCUS_BUTTON = "Focus";
    for (const std::string& button : newButtons) {
        hoveredEvent.setType(PointerEvent::Press);
        hoveredEvent.setButton(chooseButton(button));
        hoveredEvent.setShouldFocus(button == SHOULD_FOCUS_BUTTON);
        if (hoveredObject.type == ENTITY) {
            emit pointerManager->triggerBeginEntity(hoveredObject.objectID, hoveredEvent);
        } else if (hoveredObject.type == LOCAL_ENTITY) {
            emit pointerManager->triggerBeginOverlay(hoveredObject.objectID, hoveredEvent);
        } else if (hoveredObject.type == HUD) {
            emit pointerManager->triggerBeginHUD(hoveredEvent);
        }
        _triggeredObjects[button] = hoveredObject;
    }

    // Trigger continue
    for (const std::string& button : sameButtons) {
        PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult, button, false);
        triggeredEvent.setID(pointerID);
        triggeredEvent.setType(PointerEvent::Move);
        triggeredEvent.setButton(chooseButton(button));
        if (_triggeredObjects[button].type == ENTITY) {
            emit pointerManager->triggerContinueEntity(_triggeredObjects[button].objectID, triggeredEvent);
        } else if (_triggeredObjects[button].type == LOCAL_ENTITY) {
            emit pointerManager->triggerContinueOverlay(_triggeredObjects[button].objectID, triggeredEvent);
        } else if (_triggeredObjects[button].type == HUD) {
            emit pointerManager->triggerContinueHUD(triggeredEvent);
        }
    }

    // Trigger end
    for (const std::string& button : _prevButtons) {
        PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult, button, false);
        triggeredEvent.setID(pointerID);
        triggeredEvent.setType(PointerEvent::Release);
        triggeredEvent.setButton(chooseButton(button));
        if (_triggeredObjects[button].type == ENTITY) {
            emit pointerManager->triggerEndEntity(_triggeredObjects[button].objectID, triggeredEvent);
        } else if (_triggeredObjects[button].type == LOCAL_ENTITY) {
            emit pointerManager->triggerEndOverlay(_triggeredObjects[button].objectID, triggeredEvent);
        } else if (_triggeredObjects[button].type == HUD) {
            emit pointerManager->triggerEndHUD(triggeredEvent);
        }
        _triggeredObjects.erase(button);
    }

    // if we disable the pointer or disable hovering, send hoverEnd events after triggerEnd
    if (_hover && ((!_enabled && _prevEnabled) || (!doHover && _prevDoHover))) {
        if (_prevHoveredObject.type == ENTITY) {
            emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent);
        } else if (_prevHoveredObject.type == LOCAL_ENTITY) {
            emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent);
        } else if (_prevHoveredObject.type == HUD) {
            emit pointerManager->hoverEndHUD(hoveredEvent);
        }
    }

    _prevHoveredObject = hoveredObject;
    _prevButtons = buttons;
    _prevEnabled = _enabled;
    _prevDoHover = doHover;
}