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; } } } }}
阅读全文
0 0
- cocos2d ios触摸事件分发
- cocos2d-x 触摸事件的重新分发
- cocos2d-x 事件分发机制 ——触摸事件监听
- cocos2d-x 事件分发机制 ——触摸事件监听
- cocos2d-x 事件分发机制 ——触摸事件监听
- cocos2d-x 3.0 事件分发机制 —触摸事件监听
- Cocos2D 触摸分发原理
- cocos2d CCTouchDispatcher 触摸分发
- Cocos2D 触摸分发原理
- cocos2d-触摸分发原理
- Cocos2d触摸分发原理
- Cocos2D 触摸分发原理
- Cocos2D 触摸分发原理
- cocos2d-x 3.0 全新触摸检测与事件分发机制
- Android 触摸事件分发
- Android触摸事件分发
- 触摸事件分发-view
- 触摸事件分发响应
- 今年生男孩取什么名好的超简单起名方法
- TP5自带分页部分代码
- java简单的定时器实现
- Yii框架 AR 增删改查
- IOS 瀑布流
- cocos2d ios触摸事件分发
- Xlib.h No such file or directory 问题解决
- three.js 02-02 之使用几何与网格对象
- CentOS 6&&7进入救援模式的方法
- 万事开头难
- tcp的三次握手
- 浏览器 发展历史
- docker使用mysql时的端口映射问题
- Go语言Map(集合)