AniMultipleTouchGestureRecognizer.cpp 5.54 KB
//
//  AniMultipleTouchGestureRecognizer.cpp
//  SteveMaggieCpp
//
//  Created by Katarzyna Kalinowska-Górska on 19.05.2017.
//
//

#include <stdio.h>
#include "AniMultipleTouchGestureRecognizer.h"

/* Detect single-, double- or more finger touch and drag */
/* !! Warning: single touch will only work well with multiple touch if handled here!! */

//constructor

AniMultipleTouchGestureRecognizer::AniMultipleTouchGestureRecognizer() : AniGestureRecognizer({cocos2d::EventListener::Type::TOUCH_ALL_AT_ONCE})
{
    _onSingleTouchDetectedCallback = [](AniGestureRecognizer::TouchData touch){};
    _onSingleTouchMovedCallback = [](AniGestureRecognizer::TouchData touch){};
    _onSingleTouchEndedCallback = [](AniGestureRecognizer::TouchData touch){};
    _onMultipleTouchDetectedCallback = [](std::vector<AniGestureRecognizer::TouchData> touches){};
    _onMultipleTouchMovedCallback = [](std::vector<AniGestureRecognizer::TouchData> touches){};
    _onMultipleTouchEndedCallback = [](std::vector<AniGestureRecognizer::TouchData> touches){};
    
    _singleTouchHelperCallback = [](float){};
    _singleTouchHelperCallbackScheduled = false;
    
    _singleTouchInProgress = false;
    _multipleTouchInProgress = false;
}

AniMultipleTouchGestureRecognizer::~AniMultipleTouchGestureRecognizer()
{
}

void AniMultipleTouchGestureRecognizer::setOnSingleTouchDetectedCallback(std::function<void(AniGestureRecognizer::TouchData touchData)> callback)
{
    _onSingleTouchDetectedCallback = callback;
}

void AniMultipleTouchGestureRecognizer::setOnSingleTouchMovedCallback(std::function<void(AniGestureRecognizer::TouchData touchData)> callback)
{
    _onSingleTouchMovedCallback = callback;
}

void AniMultipleTouchGestureRecognizer::setOnSingleTouchEndedCallback(std::function<void(AniGestureRecognizer::TouchData touchData)> callback)
{
    _onSingleTouchEndedCallback = callback;
}

void AniMultipleTouchGestureRecognizer::setOnMultipleTouchDetectedCallback(std::function<void(std::vector<AniGestureRecognizer::TouchData>)> callback)
{
    _onMultipleTouchDetectedCallback = callback;
}

void AniMultipleTouchGestureRecognizer::setOnMultipleTouchMovedCallback(std::function<void(std::vector<AniGestureRecognizer::TouchData>)> callback)
{
    _onMultipleTouchMovedCallback = callback;
}

void AniMultipleTouchGestureRecognizer::setOnMultipleTouchEndedCallback(std::function<void(std::vector<AniGestureRecognizer::TouchData>)> callback)
{
    _onMultipleTouchEndedCallback = callback;
}

// internal

bool AniMultipleTouchGestureRecognizer::onTouchesBegan(const std::vector<cocos2d::Touch*>& touches, cocos2d::Event* event)
{
    if(_singleTouchInProgress){
        return true;
    }
    
    AniGestureRecognizer::onTouchesBegan(touches, event);
    
    if(!_singleTouchHelperCallbackScheduled){
        _singleTouchHelperCallback = [&](float){
        
            if(_rememberedTouches.size() == 1){
                _singleTouchInProgress = true;
                _onSingleTouchDetectedCallback(_rememberedTouches[0]);//todo if ended then no remembered touches are there
            }
        };
    }
    
    if(_rememberedTouches.size() == 1){
        
        _view->scheduleOnce(_singleTouchHelperCallback, 0.2, SingleTouchHelperCallbackKey);
        _singleTouchHelperCallbackScheduled = true;
        
    } else if(!_singleTouchInProgress && _rememberedTouches.size() > 1){
        
        if(_singleTouchHelperCallbackScheduled){
            _view->unschedule(SingleTouchHelperCallbackKey);
            _singleTouchHelperCallbackScheduled = false;
        }

        //        cocos2d::log("touches count: %d\n", _rememberedTouches.size());
        if(_rememberedTouches.size() == 2){
            _multipleTouchInProgress = true;
            _onMultipleTouchDetectedCallback(_rememberedTouches);
        } else {
            _rememberedTouches.clear();
        }
    }
    
    return true;
}

void AniMultipleTouchGestureRecognizer::onTouchesMoved(const std::vector<cocos2d::Touch*>& touches, cocos2d::Event* event)
{
    AniGestureRecognizer::onTouchesMoved(touches, event);
    
     if(_multipleTouchInProgress && _rememberedTouches.size() > 1){
                    
        _onMultipleTouchMovedCallback(_rememberedTouches);
        
     } else if(_singleTouchInProgress && _rememberedTouches.size() > 0){
     
        auto touch = this->findTouchWithID(touches, _rememberedTouches[0].touchId);
        if(touch){
            _onSingleTouchMovedCallback(_rememberedTouches[0]);
        }
     }
}
    
void AniMultipleTouchGestureRecognizer::onTouchesEnded(const std::vector<cocos2d::Touch*>& touches, cocos2d::Event* event)
{
    if(_multipleTouchInProgress){
        _onMultipleTouchEndedCallback(_rememberedTouches);
        _multipleTouchInProgress = false;
        _rememberedTouches.clear();
        
    } else if(_singleTouchInProgress){// && this.rememberedTouches.length > 0){
        
        auto touch = this->findTouchWithID(touches, _rememberedTouches[0].touchId);
        
        if(touch){
            _onSingleTouchEndedCallback(_rememberedTouches[0]);
            _singleTouchInProgress = false;
            _rememberedTouches.clear();
        }
        
    } else {
    
        if(_singleTouchHelperCallbackScheduled){
            _view->unschedule(SingleTouchHelperCallbackKey);
            _singleTouchHelperCallbackScheduled = false;
            
            if(_rememberedTouches.size() > 0){
                _onSingleTouchDetectedCallback(_rememberedTouches[0]);
                _onSingleTouchEndedCallback(_rememberedTouches[0]);
            }
        }
    
        AniGestureRecognizer::onTouchesEnded(touches, event);
    }
}