cocos2d ios触摸事件分发

来源:互联网 发布:什么是软件嵌入式培养 编辑:程序博客网 时间:2024/06/07 02:23

移动设备玩家的交互基本是触摸,闲来翻看了一下cocos具体的触摸分发,主要思路就是通过ios的触摸,然后回调cocos的事件分发

1.具体目录 项目底下cocos2d/cocos/platform 这个目录下面有对应不同平台的相关代码我们主要看 /ios

//CCEAGLView-ios,这个类继承了UIView并实现了触摸代理,UIView//是IOS的系统的相关类,想了解更多IOS的触摸机制可以百度,我能看懂的//代码主要如下//#pragma mark CCEAGLView - Touch Delegate- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{    ...    //主要代码    auto glview = cocos2d::Director::getInstance()->getOpenGLView();    glview->handleTouchesBegin(i, (intptr_t*)ids, xs, ys);}- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{    ...    //主要代码    auto glview = cocos2d::Director::getInstance()->getOpenGLView();    glview->handleTouchesMove(i, (intptr_t*)ids, xs, ys);}- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{    ...    //主要代码    auto glview = cocos2d::Director::getInstance()->getOpenGLView();    glview->handleTouchesEnd(i, (intptr_t*)ids, xs, ys);}- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{     ...    //主要代码    auto glview = cocos2d::Director::getInstance()->getOpenGLView();    glview->handleTouchesCancel(i, (intptr_t*)ids, xs, ys);}//以上4个方法对应cocos里面的4个回调方法具体是怎么调用的需要继续看

2.glview->handleTouchesCancel(),从这继续

//GLView类void GLView::handleTouchesBegin(int num, intptr_t ids[], float xs[], float ys[]){    intptr_t id = 0;    float x = 0.0f;    float y = 0.0f;    int unusedIndex = 0;    EventTouch touchEvent;//触摸事件    for (int i = 0; i < num; ++i)    {        id = ids[i];        x = xs[i];        y = ys[i];        auto iter = g_touchIdReorderMap.find(id);        // it is a new touch        if (iter == g_touchIdReorderMap.end())        {            unusedIndex = getUnUsedIndex();            // The touches is more than MAX_TOUCHES ?            if (unusedIndex == -1) {                CCLOG("The touches is more than MAX_TOUCHES, unusedIndex = %d", unusedIndex);                continue;            }            Touch* touch = g_touches[unusedIndex] = new (std::nothrow) Touch();//触摸            touch->setTouchInfo(unusedIndex, (x - _viewPortRect.origin.x) / _scaleX,                                     (y - _viewPortRect.origin.y) / _scaleY);            CCLOGINFO("x = %f y = %f", touch->getLocationInView().x, touch->getLocationInView().y);            g_touchIdReorderMap.insert(std::make_pair(id, unusedIndex));            touchEvent._touches.push_back(touch);//压入            //vector中        }    }    if (touchEvent._touches.size() == 0)    {        CCLOG("touchesBegan: size = 0");        return;    }    //    touchEvent._eventCode = EventTouch::EventCode::BEGAN;    auto dispatcher = Director::getInstance()->getEventDispatcher();    dispatcher->dispatchEvent(&touchEvent);}

3.dispatcher->dispatchEvent(&touchEvent);

//EventDispatcher类void EventDispatcher::dispatchEvent(Event* event){    if (!_isEnabled)        return;    updateDirtyFlagForSceneGraph();    DispatchGuard guard(_inDispatch);    //触摸事件    if (event->getType() == Event::Type::TOUCH)    {        //看这里        dispatchTouchEvent(static_cast<EventTouch*>(event));        return;    }    auto listenerID = __getListenerID(event);    sortEventListeners(listenerID);    auto pfnDispatchEventToListeners = &EventDispatcher::dispatchEventToListeners;    if (event->getType() == Event::Type::MOUSE) {        pfnDispatchEventToListeners = &EventDispatcher::dispatchTouchEventToListeners;    }    auto iter = _listenerMap.find(listenerID);    if (iter != _listenerMap.end())    {        auto listeners = iter->second;        auto onEvent = [&event](EventListener* listener) -> bool{            event->setCurrentTarget(listener->getAssociatedNode());            listener->_onEvent(event);            return event->isStopped();        };        (this->*pfnDispatchEventToListeners)(listeners, onEvent);    }    updateListeners(event);}//void EventDispatcher::dispatchTouchEvent(EventTouch* event){    sortEventListeners(EventListenerTouchOneByOne::LISTENER_ID);    sortEventListeners(EventListenerTouchAllAtOnce::LISTENER_ID);    auto oneByOneListeners = getListeners(EventListenerTouchOneByOne::LISTENER_ID);    auto allAtOnceListeners = getListeners(EventListenerTouchAllAtOnce::LISTENER_ID);    // If there aren't any touch listeners, return directly.    if (nullptr == oneByOneListeners && nullptr == allAtOnceListeners)        return;    bool isNeedsMutableSet = (oneByOneListeners && allAtOnceListeners);    const std::vector<Touch*>& originalTouches = event->getTouches();//刚刚压入的触摸点    std::vector<Touch*> mutableTouches(originalTouches.size());    std::copy(originalTouches.begin(), originalTouches.end(), mutableTouches.begin());    //    // process the target handlers 1st    //    if (oneByOneListeners)    {        auto mutableTouchesIter = mutableTouches.begin();        auto touchesIter = originalTouches.begin();        for (; touchesIter != originalTouches.end(); ++touchesIter)        {            bool isSwallowed = false;            //lambda 表达式            auto onTouchEvent = [&](EventListener* l) -> bool { // Return true to break                EventListenerTouchOneByOne* listener = static_cast<EventListenerTouchOneByOne*>(l);                // Skip if the listener was removed.                if (!listener->_isRegistered)                    return false;                event->setCurrentTarget(listener->_node);                bool isClaimed = false;                std::vector<Touch*>::iterator removedIter;                EventTouch::EventCode eventCode = event->getEventCode();                if (eventCode == EventTouch::EventCode::BEGAN)                {                    if (listener->onTouchBegan)                    {                        //这里就是调用我们注册的触摸事件                        isClaimed = listener->onTouchBegan(*touchesIter, event);                        if (isClaimed && listener->_isRegistered)                        {                            listener->_claimedTouches.push_back(*touchesIter);                        }                    }                }                else if (listener->_claimedTouches.size() > 0                         && ((removedIter = std::find(listener->_claimedTouches.begin(), listener->_claimedTouches.end(), *touchesIter)) != listener->_claimedTouches.end()))                {                    isClaimed = true;                    switch (eventCode)                    {                        case EventTouch::EventCode::MOVED:                            if (listener->onTouchMoved)                            {                                listener->onTouchMoved(*touchesIter, event);                            }                            break;                        case EventTouch::EventCode::ENDED:                            if (listener->onTouchEnded)                            {                                listener->onTouchEnded(*touchesIter, event);                            }                            if (listener->_isRegistered)                            {                                listener->_claimedTouches.erase(removedIter);                            }                            break;                        case EventTouch::EventCode::CANCELLED:                            if (listener->onTouchCancelled)                            {                                listener->onTouchCancelled(*touchesIter, event);                            }                            if (listener->_isRegistered)                            {                                listener->_claimedTouches.erase(removedIter);                            }                            break;                        default:                            CCASSERT(false, "The eventcode is invalid.");                            break;                    }                }                // If the event was stopped, return directly.                if (event->isStopped())                {                    updateListeners(event);                    return true;                }                CCASSERT((*touchesIter)->getID() == (*mutableTouchesIter)->getID(),                         "touchesIter ID should be equal to mutableTouchesIter's ID.");                if (isClaimed && listener->_isRegistered && listener->_needSwallow)                {                    if (isNeedsMutableSet)                    {                        mutableTouchesIter = mutableTouches.erase(mutableTouchesIter);                        isSwallowed = true;                    }                    return true;                }                return false;            };            //lambda表达式传入这里            dispatchTouchEventToListeners(oneByOneListeners, onTouchEvent);            if (event->isStopped())            {                return;            }            if (!isSwallowed)                ++mutableTouchesIter;        }    }    ...}//到这里就是分情况去执行相应的触摸事件了void EventDispatcher::dispatchTouchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent){    bool shouldStopPropagation = false;    auto fixedPriorityListeners = listeners->getFixedPriorityListeners();    auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();    ssize_t i = 0;    //先执行 priority < 0,onEvent(l)就是上面lambda表达式执行了    if (fixedPriorityListeners)    {        CCASSERT(listeners->getGt0Index() <= static_cast<ssize_t>(fixedPriorityListeners->size()), "Out of range exception!");        if (!fixedPriorityListeners->empty())        {            for (; i < listeners->getGt0Index(); ++i)            {                auto l = fixedPriorityListeners->at(i);                if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))                {                    shouldStopPropagation = true;                    break;                }            }        }    }    //再执行 priority == 0,因为sceneGraphPriority事件都    //是priority = 0的    auto scene = Director::getInstance()->getRunningScene();    if (scene && sceneGraphPriorityListeners)    {        if (!shouldStopPropagation)        {            // priority == 0, scene graph priority            // first, get all enabled, unPaused and registered listeners            std::vector<EventListener*> sceneListeners;            for (auto& l : *sceneGraphPriorityListeners)            {                if (l->isEnabled() && !l->isPaused() && l->isRegistered())                {                    sceneListeners.push_back(l);                }            }            // second, for all camera call all listeners            // get a copy of cameras, prevent it's been modified in linstener callback            // if camera's depth is greater, process it earler            auto cameras = scene->getCameras();            Camera* camera;            for (int j = int(cameras.size()) - 1; j >= 0; --j)            {                camera = cameras[j];                if (camera->isVisible() == false)                {                    continue;                }                Camera::_visitingCamera = camera;                for (auto& l : sceneListeners)                {                    if (onEvent(l))                    {                        shouldStopPropagation = true;                        break;                    }                }                if (shouldStopPropagation)                {                    break;                }            }            Camera::_visitingCamera = nullptr;        }    }    if (fixedPriorityListeners)    {        if (!shouldStopPropagation)        {            //最后 priority > 0            ssize_t size = fixedPriorityListeners->size();            for (; i < size; ++i)            {                auto l = fixedPriorityListeners->at(i);                if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))                {                    shouldStopPropagation = true;                    break;                }            }        }    }}
原创粉丝点击