/*
* @note :基础触碰效果封装(通用于具有触碰效果的节点或精灵,类似按钮,方便扩展)
* @author :Andy.Ro
* @email :Qwuloo@qq.com
*/
#ifndef _XBASETOUCH_SPRITE_H_INCLUDE_
#define _XBASETOUCH_SPRITE_H_INCLUDE_
#include "cocos2d.h"
#include <map>
USING_NS_CC;
class xBaseTouchSprite; /* 基础触碰精灵 */
class xBaseTouchDelegate; /* 基础触碰代理 */
// 基础触碰节点
typedef xBaseTouchSprite xBaseTouchNode;
//------------------------------------------------------------------------
// xBaseTouchDelegate
//------------------------------------------------------------------------
class xBaseTouchDelegate
{
public:
virtual void onTouch(cocos2d::CCObject* sender) = 0;
virtual void onMoved(cocos2d::CCObject* sender) = 0;
virtual void onEnded(cocos2d::CCObject* sender) = 0;
};
//------------------------------------------------------------------------
// BaseTouchSprite:基础触碰节点(2.1.4之后版本继承CCSprite和CCTargetedTouchDelegate)
//------------------------------------------------------------------------
class xBaseTouchSprite : /*public cocos2d::CCSprite, public cocos2d::CCTargetedTouchDelegate*/ public cocos2d::CCLayerColor
{
public:
xBaseTouchSprite(void);
static xBaseTouchSprite* create(float width, float height);
//
// @note:触屏使能
virtual void setTouchEnabled(bool bValue);
protected:
//
// @note:初始化
bool initWith(float width, float height);
//
// @note:检索子节点精灵颜色值
void traverseChildrenColor(void);
//
// @note:检索子节点精灵颜色值(递归遍历)
void recurseChildrenColor(CCNode* parent);
//
// @note:绘制选中或未选中状态
// @param bValue 是否选中
void recurseSmoothDraw(CCNode* parent, bool bValue);
//
// @note:绘制效果
virtual void draw(void);
protected:
//
// @note:单点触屏
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
//
// @note:触屏点判断
bool containsTouchLocation(CCTouch *pTouch);
//
// @note:消息回调
virtual void onTouch(cocos2d::CCObject* sender);
virtual void onMoved(cocos2d::CCObject* sender);
virtual void onEnded(cocos2d::CCObject* sender);
//
// @note:注册优先级
virtual void registerWithTouchDispatcher(void);
protected:
std::map<CCNode*,ccColor3B> _mapcolor;
CC_SYNTHESIZE(bool, _bSelected, Selected);
CC_SYNTHESIZE(BaseTouchDelegate*, _target, Delegate);
public:
virtual ~xBaseTouchSprite(void);
};
// @note:绘制矩形边框
extern void drawRect(CCRect const& rect);
#endif // _XBASETOUCH_SPRITE_H_INCLUDE_
/*
* @note :基础触碰效果封装(通用于具有触碰效果的节点或精灵,类似按钮,方便扩展)
* @author :Andy.Ro
* @email :Qwuloo@qq.com
*/
#include "xBaseTouchSprite.h"
// @note:绘制矩形边框
inline void drawRect(CCRect const& rect)
{
CCPoint pos1, pos2, pos3, pos4;
pos1 = ccp(rect.origin.x, rect.origin.y);
pos2 = ccp(rect.origin.x, rect.origin.y + rect.size.height);
pos3 = ccp(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
pos4 = ccp(rect.origin.x + rect.size.width, rect.origin.y);
ccDrawLine(pos1, pos2);
ccDrawLine(pos2, pos3);
ccDrawLine(pos3, pos4);
ccDrawLine(pos4, pos1);
}
//------------------------------------------------------------------------
// xBaseTouchSprite
//------------------------------------------------------------------------
xBaseTouchSprite::xBaseTouchSprite(void)
:_bSelected(0)
,_target(0)
{
}
xBaseTouchSprite* xBaseTouchSprite::create(float width, float height)
{
xBaseTouchSprite* s = new xBaseTouchSprite();
if ( s && s->initWith(width, height) )
{
s->autorelease();
}
else CC_SAFE_DELETE( s );
return s;
}
bool xBaseTouchSprite::initWith(float width, float height)
{
// 触碰节点
this->initWithColor( ccc4(255,0,0,0), width, height );
// 启用锚点(这里注意了)
this->ignoreAnchorPointForPosition(false);
// 节点锚点
this->setAnchorPoint( ccp(0.5f, 0.5f) );
return true;
}
void xBaseTouchSprite::setTouchEnabled(bool bValue)
{
__super::setTouchEnabled(bValue);
switch( bValue )
{
case true:
{
break;
}
case false:
{
this->setSelected(false);
break;
}
}
}
// @note:触屏点判断
inline bool xBaseTouchSprite::containsTouchLocation(CCTouch *pTouch)
{
//
// @note:自身节点坐标
CCRect const& rect = \
this->getAnchorPoint().equals(CCPointZero) ?
// @note:锚点(0,0)
CCRect(
0
,0
, this->getContentSize().width
, this->getContentSize().height) :
// @note:锚点(0.5,0.5)
CCRect(
-this->getContentSize().width * 0.5f
,-this->getContentSize().height * 0.5f
, this->getContentSize().width
, this->getContentSize().height);
//
// 变换触屏坐标为自身节点坐标,判断
return rect.containsPoint( convertTouchToNodeSpaceAR(pTouch) );
}
inline void xBaseTouchSprite::onTouch(CCObject* sender)
{
// std::cout<<"xBaseTouchSprite::onTouch()"<<std::endl;
CC_ASSERT( this->_target );
this->_target->onTouch( sender );
}
inline void xBaseTouchSprite::onMoved(CCObject* sender)
{
// std::cout<<"xBaseTouchSprite::onMoved()"<<std::endl;
CC_ASSERT( this->_target );
this->_target->onMoved( sender );
}
inline void xBaseTouchSprite::onEnded(CCObject* sender)
{
// std::cout<<"xBaseTouchSprite::onEnded()"<<std::endl;
CC_ASSERT( this->_target );
this->_target->onEnded( sender );
}
// @note:单点触屏
bool xBaseTouchSprite::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
// 触碰点位于节点区域内,则进行拦截
if ( this->containsTouchLocation(pTouch) )
{
this->onTouch( this );
return true;
}
// 触碰点不在节点区域内,则往下传递
return false;
}
void xBaseTouchSprite::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
{
// 触碰点位于节点区域内,则进行响应
if ( this->containsTouchLocation(pTouch) )
{
this->setSelected(true);
this->onMoved( this );
}
// 触碰点不在节点区域内,则另做处理
else
{
this->setSelected(false);
}
}
void xBaseTouchSprite::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
// 触碰点位于节点区域内,则进行响应
if ( this->containsTouchLocation(pTouch) )
{
this->setSelected(false);
this->onEnded( this );
}
}
void xBaseTouchSprite::registerWithTouchDispatcher(void)
{
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, kCCMenuHandlerPriority - 1, true);
}
inline void xBaseTouchSprite::draw(void)
{
if ( this->getSelected() )
{
ccDrawColor4F(0,255,0,100);
glLineWidth(2.0);
// this->recurseSmoothDraw(this, true);
// @note:绘制节点边框
drawRect(
CCRect(
0
,0
,this->getContentSize().width
,this->getContentSize().height) );
}
else
{
// this->recurseSmoothDraw(this, false);
}
}
// @note:检索子节点精灵颜色值
void xBaseTouchSprite::traverseChildrenColor(void)
{
this->recurseChildrenColor(this);
}
// @note:检索子节点精灵颜色值(递归遍历)
void xBaseTouchSprite::recurseChildrenColor(CCNode* parent)
{
CC_ASSERT( parent );
CCObject* obj = 0;
CCARRAY_FOREACH(parent->getChildren(), obj)
{
CCSprite* s = dynamic_cast<CCSprite*>(obj); CC_ASSERT( s );
this->recurseChildrenColor(s);
}
CCSprite* s = dynamic_cast<CCSprite*>(parent);/* CC_ASSERT( s );*/
if ( s )
{
this->_mapcolor[s] = s->getColor();
}
}
// @note:绘制选中或未选中状态
// @param bValue 是否选中
void xBaseTouchSprite::recurseSmoothDraw(CCNode* parent, bool bValue)
{
CC_ASSERT( parent );
CCObject* obj = 0;
CCARRAY_FOREACH(parent->getChildren(), obj)
{
CCSprite* s = dynamic_cast<CCSprite*>(obj); CC_ASSERT( s );
this->recurseSmoothDraw(s, bValue);
}
CCSprite* s = dynamic_cast<CCSprite*>(parent);/* CC_ASSERT( s );*/
if ( s )
{
s->setColor(bValue ? ccYELLOW : this->_mapcolor[s]);
}
}
xBaseTouchSprite::~xBaseTouchSprite(void)
{
} // class xBaseTouchSprite