// // AniGestureRecognizer.cpp // SteveMaggieCpp // // Created by Katarzyna Kalinowska-Górska on 19.05.2017. // // #include #include "AniGestureRecognizer.h" AniGestureRecognizer::AniGestureRecognizerDirection AniGestureRecognizer::mapXToDirection(float x) { if(x < 0){ return AniGestureRecognizerDirection::LEFT; } else if(x > 0){ return AniGestureRecognizerDirection::RIGHT; } else { return AniGestureRecognizerDirection::NONE; } } AniGestureRecognizer::AniGestureRecognizerDirection AniGestureRecognizer::mapYToDirection(float y) { if(y < 0){ return AniGestureRecognizerDirection::DOWN; } else if(y > 0){ return AniGestureRecognizerDirection::UP; } else { return AniGestureRecognizerDirection::NONE; } } AniGestureRecognizer::AniGestureRecognizer(std::vector handledEvents) { _handledEvents = handledEvents; _view = NULL; _enabled = true; } AniGestureRecognizer::~AniGestureRecognizer(){ this->uninstall(); } // install gesture recognizer in given view void AniGestureRecognizer::install(cocos2d::Node* view) { if(!view){ cocos2d::log("Gesture Recognizer install fail: view must not be null"); return; } _view = view; if(std::find(_handledEvents.begin(), _handledEvents.end(), cocos2d::EventListener::Type::TOUCH_ONE_BY_ONE) != _handledEvents.end()){ auto touchListener = cocos2d::EventListenerTouchOneByOne::create(); touchListener->onTouchBegan = [&](cocos2d::Touch* touch, cocos2d::Event* event) -> bool { return _enabled && this->onTouchBegan(touch, event); }; touchListener->onTouchMoved = [&](cocos2d::Touch* touch, cocos2d::Event* event){ if(_enabled){ this->onTouchMoved(touch, event); } }; touchListener->onTouchEnded = [&](cocos2d::Touch* touch, cocos2d::Event* event){ if(_enabled){ this->onTouchEnded(touch, event); } }; touchListener->setSwallowTouches(false); _view->getEventDispatcher()->addEventListenerWithSceneGraphPriority(touchListener, _view); // _view->getEventDispatcher()->addEventListenerWithFixedPriority(touchListener, -1); // _view->getEventDispatcher()->addEventListenerWithSceneGraphPriority(touchListener, _view); _eventListener = touchListener; } if(std::find(_handledEvents.begin(), _handledEvents.end(), cocos2d::EventListener::Type::TOUCH_ALL_AT_ONCE) != _handledEvents.end()){ auto touchListener = cocos2d::EventListenerTouchAllAtOnce::create(); touchListener->onTouchesBegan = [&](const std::vector& touches, cocos2d::Event* event) -> bool{ return _enabled && this->onTouchesBegan(touches, event); }; touchListener->onTouchesMoved = [&](const std::vector& touches, cocos2d::Event* event){ if(_enabled){ this->onTouchesMoved(touches, event); } }; touchListener->onTouchesEnded = [&](const std::vector& touches, cocos2d::Event* event){ if(_enabled){ this->onTouchesEnded(touches, event); } }; _view->getEventDispatcher()->addEventListenerWithSceneGraphPriority(touchListener, _view); _eventListener = touchListener; } } void AniGestureRecognizer::uninstall() { if(_eventListener){ _view->getEventDispatcher()->removeEventListener(_eventListener); _eventListener = nullptr; } } void AniGestureRecognizer::changeTouchListenerPriorityToFixed(int newPriority) { if(_eventListener){ _view->getEventDispatcher()->removeEventListener(_eventListener); _view->getEventDispatcher()->addEventListenerWithFixedPriority(_eventListener, newPriority); } } void AniGestureRecognizer::changeTouchListenerPriorityToSceneGraphPriority() { if(_eventListener){ _view->getEventDispatcher()->removeEventListener(_eventListener); _view->getEventDispatcher()->addEventListenerWithSceneGraphPriority(_eventListener, _view); } } void AniGestureRecognizer::setSwallowsTouches(bool swallowsTouches) { auto eventListenerOneByOne = dynamic_cast(_eventListener); if(eventListenerOneByOne){ eventListenerOneByOne->setSwallowTouches(true); } } /////////////////////////////////////////////////////////////////////////// // internal /////////////////////////////////////////////////////////////////////////// // cc.EventListener.TOUCH_ONE_BY_ONE bool AniGestureRecognizer::onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event) { return false; } void AniGestureRecognizer::onTouchMoved(cocos2d::Touch* touch, cocos2d::Event* event) { } void AniGestureRecognizer::onTouchEnded(cocos2d::Touch* touch, cocos2d::Event* event) { } // cc.EventListener.TOUCH_ALL_AT_ONCE bool AniGestureRecognizer::onTouchesBegan(const std::vector& touches, cocos2d::Event* event) { this->saveTouches(_rememberedTouches, touches); return false; } void AniGestureRecognizer::onTouchesMoved(const std::vector& touches, cocos2d::Event* event) { this->updateTouches(_rememberedTouches, touches); } void AniGestureRecognizer::onTouchesEnded(const std::vector& touches, cocos2d::Event* event) { this->filterTouches(_rememberedTouches, touches); } // handle remembered touches void AniGestureRecognizer::saveTouches(std::vector& rememberedTouches, const std::vector& touches) { for(int i = 0; i < touches.size(); ++i){ rememberedTouches.push_back(TouchData(touches[i]->getID(), touches[i]->getLocation(), touches[i]->getPreviousLocation(), touches[i]->getLocation())); } } void AniGestureRecognizer::updateTouches(std::vector& rememberedTouches, const std::vector& touches) { for(int i = 0; i < rememberedTouches.size(); ++i){ for(int j = 0; j < touches.size(); ++j){ if(rememberedTouches[i].touchId == touches[j]->getID()){ rememberedTouches[i].currentTouchLocation = touches[j]->getLocation(); rememberedTouches[i].previousTouchLocation = touches[j]->getPreviousLocation(); break; } } } } void AniGestureRecognizer::filterTouches(std::vector& rememberedTouches, const std::vector& touches) { //todo: map? filter? for(int i = (int)rememberedTouches.size() - 1; i >= 0; --i){ for(int j = 0; j < touches.size(); ++j){ if(touches[j]->getID() == rememberedTouches[i].touchId){ rememberedTouches.erase(rememberedTouches.begin() + i); break; } } } } cocos2d::Touch* AniGestureRecognizer::findTouchWithID(const std::vector& touches, int touchId) { std::vector toReturn; std::copy_if(touches.begin(), touches.end(), std::back_inserter(toReturn), [&](const cocos2d::Touch* touch) { return touch->getID() == touchId; }); if(toReturn.size() > 0){ return toReturn[0]; } else { return NULL; } }