#ifndef Magnifier_h
#define Magnifier_h
#include "cocos2d.h"
#include "STMacro.h"
#include "STFilter.h"
#include "STTouchableSprite.h"
NS_ST_BEGIN
USING_NS_CC;
using namespace std;
/**
放大镜
*/
class STMagnifier : public Node
{
STFilter *m_pFilter;
STTouchableSprite *m_handShank;
public:
/**
使用图片路径来初始化
@param handShank 放大镜手柄
@param stencil 透视图片
@param content 放大查看的图片
*/
static STMagnifier * create(STTouchableSprite *handShank,Sprite *stencil, Sprite *content);
/**
使用图片路径来初始化
@param handShank 手柄图片路径
@param stencil 透视图片路径
@param content 放大查看的图片路径
*/
static STMagnifier * createWithPath(const string &handShankPath,const string &stencilPath, const string &contentPath);
/**
使用图片Frame名称来初始化
@param handShank 手柄图片Frame名称
@param stencil 透视图片Frame名称
@param content 放大查看的图片Frame名称
*/
static STMagnifier * createWithFrameName(const string &handShankName,const string &stencilName, const string &contentName);
/*
屏幕快照
*/
static Sprite* snapshot();
public:
/*
设置放大倍数
*/
void setZoomSize(float size);
/*
获取手柄,用于设置手柄坐标
*/
STTouchableSprite* getHandShank();
/*
设置放大镜坐标
*/
void setMagnifierPosition(const Vec2 &pos);
protected:
STMagnifier();
virtual ~STMagnifier();
virtual bool init(STTouchableSprite *handShank,Sprite *stencil, Sprite *content);
virtual bool initWithPath(const string &handShankPath,const string &stencilPath, const string &contentPath);
virtual bool initWithFrameName(const string &handShankName,const string &stencilName, const string &contentName);
private:
/*
移动放大镜
*/
void moveMagnifier(const Vec2 &delta);
/*
获取放大区域在屏幕的百分比[0,1]
*/
Vec2 getZoomPosition();
};
/*
//手柄
auto hanshank = STTouchableSprite::createWithSpriteFrameName("stencil.png");
//镂空区域
auto stencil = Sprite::createWithSpriteFrameName("stencil.png");
//放大查看的内容
//auto content = Sprite::create("Levels/Level1/level1_body_3.jpg");
auto content = STMagnifier::snapshot();
//放大镜
auto magnifier = STMagnifier::create(hanshank,stencil, content);
//this->addToUILayer(magnifier,kPop);
this->addChild(magnifier,kPop);
//设置放大倍数
magnifier->setZoomSize(2);
//调整手柄坐标
magnifier->getHandShank()->setAnchorPoint(Vec2(0.5f, 0.5f));
// 设置初始坐标
magnifier->setMagnifierPosition(Vec2(200, 200));
*/
NS_ST_END
#endif /* Magnifier_hpp */
#include "STMagnifier.h"
#include "VisibleRect.h"
USING_NS_ST;
STMagnifier * STMagnifier::create(STTouchableSprite *handShank,Sprite *stencil, Sprite *content)
{
auto node = new (std::nothrow) STMagnifier();
if ( node && node->init(handShank,stencil, content) )
{
node->autorelease();
return node;
}
CC_SAFE_DELETE(node);
return nullptr;
}
STMagnifier * STMagnifier::createWithPath(const string &handShankPath,const std::string &stencilPath, const std::string &contentPath)
{
auto node = new (std::nothrow) STMagnifier();
if ( node && node->initWithPath(handShankPath,stencilPath, contentPath) )
{
node->autorelease();
return node;
}
CC_SAFE_DELETE(node);
return nullptr;
}
STMagnifier * STMagnifier::createWithFrameName(const string &handShankName,const std::string &stencilName, const std::string &contentName)
{
auto node = new (std::nothrow) STMagnifier();
if ( node && node->initWithFrameName(handShankName,stencilName, contentName) )
{
node->autorelease();
return node;
}
CC_SAFE_DELETE(node);
return nullptr;
}
STMagnifier::STMagnifier()
: m_pFilter(nullptr)
, m_handShank(nullptr)
{
}
STMagnifier::~STMagnifier()
{
}
bool STMagnifier::init(STTouchableSprite *handShank,Sprite *stencil, Sprite *content)
{
bool bRet = false;
do
{
CC_BREAK_IF(!handShank);
CC_BREAK_IF(!stencil);
CC_BREAK_IF(!content);
CC_BREAK_IF( !Node::init() );
m_pFilter = STFilter::create(stencil, content);
CC_BREAK_IF( !m_pFilter);
m_pFilter->setLimitedInScreen(false);
this->addChild(m_pFilter);
m_handShank = handShank;
this->addChild(m_handShank);
this->setZoomSize(2);
m_handShank->setPosition(VisibleRect::center());
m_handShank->
setTouchEnable(// began
[this](Touch *touch, Event *event)
{
auto node = event->getCurrentTarget();
if ( node->isVisible() )
{
Rect _rect = Rect(0,0,node->getContentSize().width,node->getContentSize().height);
_rect = RectApplyTransform(_rect,node->getNodeToWorldTransform());
if ( _rect.containsPoint(touch->getLocation()) )
{
return true;
}
}
return false;
},
// move
[this](Touch *touch, Event *event)
{
if ( !m_handShank->isVisible() )
return;
this->moveMagnifier(touch->getDelta());
}
);
// 屏蔽事件
auto touchListener = EventListenerTouchOneByOne::create();
touchListener->setSwallowTouches(true);
touchListener->onTouchBegan = [this](Touch*, Event*)
{
return true;
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
bRet = true;
} while (false);
return bRet;
}
bool STMagnifier::initWithPath(const string &handShankPath,const std::string &stencilPath, const std::string &contentPath)
{
auto handShank = STTouchableSprite::create(handShankPath);
if (!handShank)
return false;
auto stencil = Sprite::create(stencilPath);
if (!stencil)
return false;
auto content = Sprite::create(contentPath);
if (!content)
return false;
return init(handShank,stencil, content);
}
bool STMagnifier::initWithFrameName(const string &handShankName,const std::string &stencilName, const std::string &contentName)
{
auto handShank = STTouchableSprite::createWithSpriteFrameName(handShankName);
if (!handShank)
return false;
auto stencil = Sprite::createWithSpriteFrameName(stencilName);
if (!stencil)
return false;
auto content = Sprite::createWithSpriteFrameName(contentName);
if (!content)
return false;
return init(handShank,stencil, content);
}
Sprite* STMagnifier::snapshot()
{
Sprite *screenCotent = nullptr;
auto pRender = RenderTexture::create(VisibleRect::getVisibleRect().size.width, VisibleRect::getVisibleRect().size.height);
pRender->begin();
Director::getInstance()->getRunningScene()->visit();
pRender->end();
Director::getInstance()->getRenderer()->render();
pRender->getSprite()->getTexture()->setAliasTexParameters();
Image* image = pRender->newImage();
Texture2D* texture = new Texture2D();
if( texture && texture->initWithImage(image) )
{
screenCotent = Sprite::createWithTexture(texture);
}
// clean
CC_SAFE_RELEASE(image);
CC_SAFE_RELEASE(texture);
return screenCotent;
}
void STMagnifier::setZoomSize(float size)
{
m_pFilter->getContent()->setScale(size);
}
STTouchableSprite* STMagnifier::getHandShank()
{
return this->m_handShank;
}
void STMagnifier::setMagnifierPosition(const Vec2 &pos)
{
Vec2 delta = pos - m_handShank->getPosition();
m_handShank->setPosition(pos);
m_pFilter->move(delta);
//before
Vec2 anchpoint1 = this->m_pFilter->getContent()->getAnchorPoint();
Vec2 pos1 = this->m_pFilter->getContent()->getPosition();
Size size = this->m_pFilter->getContent()->getContentSize();
//after
Vec2 anchpoint2 = this->getZoomPosition();
Vec2 pos2;
pos2.x = pos1.x +(anchpoint2.x - anchpoint1.x) * size.width;
pos2.y = pos1.y +(anchpoint2.y - anchpoint1.y) * size.height;
m_pFilter->getContent()->setAnchorPoint(anchpoint2);
m_pFilter->getContent()->setPosition(pos2);
}
void STMagnifier::moveMagnifier(const Vec2 &delta)
{
Vec2 pos = m_handShank->getPosition() + delta;
this->setMagnifierPosition(pos);
}
Vec2 STMagnifier::getZoomPosition()
{
Vec2 pos = m_pFilter->getClippingNode()->convertToWorldSpace(m_pFilter->getStencil()->getPosition());
return Vec2(pos.x/VisibleRect::getVisibleRect().size.width, pos.y/VisibleRect::getVisibleRect().size.height);
}