#include "SimpleDragZoomLayer.h"
//#include "PointExtension.h"
SimpleDragZoomLayer* SimpleDragZoomLayer::m_DragZoomManager = NULL;
#pragma mark -
#pragma mark default init
SimpleDragZoomLayer* SimpleDragZoomLayer::sharedInstance() {
if(m_DragZoomManager == NULL)
{
m_DragZoomManager = new SimpleDragZoomLayer();
}
return m_DragZoomManager;
}
SimpleDragZoomLayer::SimpleDragZoomLayer()
{
// monsterDictionary = CCDictionary::create();
// CC_SAFE_RETAIN(monsterDictionary);
bool result = this->cocos2d::Layer::init();
if (result) {
//make some instance here.
//this->setTouchEnabled(true);
init();
}
else
{
CCLOG("create SimpleDragZoomLayer ERROR when instance.");
}
}
SimpleDragZoomLayer::~SimpleDragZoomLayer()
{
if(!touchesVector.empty())
{
touchesVector.clear();
}
}
void SimpleDragZoomLayer::setZoomContent(Node* content)
{
this->contentZoomNode = content;
content->addChild(this, 99999);
this->winSize = Director::getInstance()->getVisibleSize();
this->winRect = Rect(Director::getInstance()->getVisibleOrigin().x,
Director::getInstance()->getVisibleOrigin().y,
this->winSize.width,
this->winSize.height);
CCLOG("win origin = %f,%f ; winsize = %f,%f",this->winRect.origin.x,this->winRect.origin.y,this->winRect.size.width,this->winRect.size.height);
CCLOG("simple drag zoom layer created.");
}
bool SimpleDragZoomLayer::init()
{
CCLOG("SimpleDragZoomLayer::init()");
if ( !Layer::init() )
{
return false;
}
auto listener = EventListenerTouchAllAtOnce::create();
listener->onTouchesBegan = CC_CALLBACK_2(SimpleDragZoomLayer::onTouchesBegan, this);
listener->onTouchesMoved = CC_CALLBACK_2(SimpleDragZoomLayer::onTouchesMoved, this);
listener->onTouchesEnded = CC_CALLBACK_2(SimpleDragZoomLayer::onTouchesEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
}
void SimpleDragZoomLayer::onEnter(){
CCLOG("enter");
// isContentAllowTap = true;
isContentScalable = true;
this->cocos2d::Layer::onEnter();
}
/*
void SimpleDragZoomLayer::setTouchEnabled(bool value){
this->Layer::setTouchEnabled(value);
if (!value) {
isContentAllowTap = false;
isContentScalable = false;
touchesVector.clear();
}
}
*/
#pragma mark -
#pragma mark touch delegates *
//触摸开始时调用
void SimpleDragZoomLayer::onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event)
{
//CCLOG("SimpleDragZoomLayer:onTouchesBegan %d",touches.size());
for (auto &item: touches)
{
auto touch = item;
Point tileMapPoint = contentZoomNode->getPosition();
Point touchPoint = touch->getLocation();
Point realPoint = touchPoint - tileMapPoint;
if (touchesVector.contains(touch) == false) {
touchesVector.pushBack(touch);
}
if (isAnimating) {
contentZoomNode->stopAllActions();
}
if (touchesVector.size() == 1) {
m_tScrollDistance = Point(0.0f, 0.0f);
m_tTouchPoint = this->convertTouchToNodeSpace(touch);
m_fTouchLength = 0.0f;
}
else if(touchesVector.size() == 2){
//count default length between 2 touches.
Point A = contentZoomNode->convertTouchToNodeSpace((Touch*)touchesVector.at(0));
Point B = contentZoomNode->convertTouchToNodeSpace((Touch*)touchesVector.at(1));
m_fTouchLength = A.getDistance(B);
m_tTouchPoint = A.getMidpoint(B);
}
if(m_iDoubleCounter == 1){ // have one touch befored.
if (millisecondNow() - m_dTouchTime > DOUBLECLICK_INTERVAL )
{
m_iDoubleCounter = 0; //reset when this touch cant be double click.
}
}
}
}
//触摸移动时调用
void SimpleDragZoomLayer::onTouchesMoved(const std::vector<Touch*>& touches, Event *unused_event)
{
for (auto &item: touches) //遍历容器中的各个成员!!!多点触摸时将显示同时显示多个精灵
{
auto touch = item;
if (touchesVector.contains(touch)) {
if (touchesVector.size() == 1) {
//only scrolling.
handleScrol();
}
else if(touchesVector.size() >= 2){
//zoom & scroll base on center touch point.
handlePitchZoom();
}
}
}
}
//触摸结束时调用
void SimpleDragZoomLayer::onTouchesEnded(const std::vector<Touch*>& touches, Event *unused_event)
{
for (auto &item: touches) //遍历容器中的各个成员!!!多点触摸时将显示同时显示多个精灵
{
auto touch = item;
if (touchesVector.size() == 1) {
/* detect the double click. */
long newTouchTime = millisecondNow();
if (m_iDoubleCounter == 0) {
m_dTouchTime = newTouchTime;
m_iDoubleCounter++;
}
else if(m_iDoubleCounter == 1){ // have one touch befored.
if (newTouchTime - m_dTouchTime <= DOUBLECLICK_INTERVAL )
{
//CCLOG("double click. = %f,%f",pTouch->getLocationInView().x,pTouch->getLocationInView().y);
isAnimating = true;
AnimateZoom* az = AnimateZoom::create(0.2f,
getMaxScaleOfZooming(),
Director::getInstance()->convertToGL(Point(Director::getInstance()->getVisibleSize().width * 0.5f,Director::getInstance()->getVisibleSize().height*0.5f)),
Director::getInstance()->convertToGL(touch->getLocationInView()),
contentZoomNode,
this,
callback_void(SimpleDragZoomLayer::applyFrameLimits));
CCCallFunc* cf = CCCallFunc::create(this, callfunc_selector(SimpleDragZoomLayer::finishAnimated));
contentZoomNode->runAction(CCSequence::create(az,cf,NULL));
}
m_iDoubleCounter = 0;
}
}
//end of touch,remove from array.
if (touchesVector.contains(touch)) {
touchesVector.eraseObject(touch);
}
}
}
#pragma mark -
#pragma mark zoom in/out or drag layer
void SimpleDragZoomLayer::handleScrol(){
//get min scale of content
float minScale = getMinScaleOfContent();
//CCLOG("handleScrol minscale = %f",minScale);
//if current scale more than that.
//获取当前的scale
float curScale = contentZoomNode->getScale();
if (curScale > minScale ) {
//get first touch.
Touch* touch = (Touch*)touchesVector.at(0);
Point touchLocation = touch->getLocationInView();
Point preLocation = touch->getPreviousLocationInView();
touchLocation = Director::getInstance()->convertToGL(touchLocation);
preLocation = Director::getInstance()->convertToGL(preLocation);
//subtract
Point diff = touchLocation - preLocation;
//new position
Point newPos = contentZoomNode->getPosition() + diff;
contentZoomNode->setPosition(newPos);
}
//last ! make frame limits at view rect!
applyFrameLimits();
}
void SimpleDragZoomLayer::handlePitchZoom(){
if (!isContentScalable) {
return;
}
//get 2 touch point
Touch* touch1 = (Touch*)touchesVector.at(0);
Touch* touch2 = (Touch*)touchesVector.at(1);
//ca