cocos2d-x下自己实现的一个button类,名字叫: TTButton
代码如下:
#include <iostream>
#include "cocos2d.h"
#include "cocos-ext.h"
USING_NS_CC;
USING_NS_CC_EXT;
#include "ClientDefine.h"
static const GLchar* pszGrayModeFragSource =
"#ifdef GL_ES \n \
precision mediump float; \n \
#endif \n \
uniform sampler2D u_texture; \n \
varying vec2 v_texCoord; \n \
varying vec4 v_fragmentColor; \n \
void main(void) \n \
{ \n \
// Convert to greyscale using NTSC weightings \n \
vec4 col = texture2D(u_texture, v_texCoord); \n \
float grey = dot(col.rgb, vec3(0.299, 0.587, 0.114)); \n \
gl_FragColor = vec4(grey, grey, grey, col.a); \n \
}";
void setSpriteGray(CCNode *pNode, bool isGray);
typedef enum _BTN_STATE
{
BTN_STATE_UNSET = -1,
BTN_STATE_NORMAL = 0,
BTN_STATE_PRESS = 1,
BTN_STATE_DISABLE = 2,
} BTN_STATE;
class TTButton :public CCLayer
{
public:
TTButton();
~TTButton();
bool initWithImages(std::string strNormal, std::string strSel , std::string strDisable );
bool initWithImage(std::string strNormal);
bool initWithImages(std::string strNormal, std::string strSel , std::string strDisable , CCSize rectSize);
bool initWithImage(std::string strNormal, CCSize rectSize);
//更新某种状态下的图像
void upDateImageForState(BTN_STATE btnState , CCTexture2D *texture);
static TTButton * createWithImage(std::string strNormal);
static TTButton * createWithImages(std::string strNormal, std::string strSel , std::string strDisable );
static TTButton * createWithImage(std::string strNormal, CCSize rectSize);
static TTButton * createWithImages(std::string strNormal, std::string strSel , std::string strDisable , CCSize rectSize);
//设置 颜色
void setColorForState(BTN_STATE btnState, ccColor3B color);
//更新状态UI
void upDateStatusUI();
//设置选中状态
void setSelected();
//设置非选中状态
void setUnSelected();
//设置是否是disable状态
void setIsDisable(bool bDisabel);
//获得当前状态
BTN_STATE getCurState();
//添加 处理handle
void addTouchupInsideHandle(CCNode * target , SEL_CallFuncO selector);
//判断是否是点击在有效区域
bool isTouchInvalidated(CCTouch* touch);
virtual void onEnter();
virtual void onExit();
virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
virtual void ccTouchEnded(CCTouch* touch, CCEvent* event);
virtual void ccTouchCancelled(CCTouch *touch, CCEvent* event);
virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);
public:
BTN_STATE m_btnState;
CCSprite * m_normalSprite;
CCSprite * m_pressedSprite;
CCSprite * m_disableSprite;
CCScale9Sprite * m_normalScaleSprite;
CCScale9Sprite * m_pressedScaleSprite;
CCScale9Sprite * m_disableScaleSprite;
CC_SYNTHESIZE(bool, m_bSelected, IsSelected);
CC_SYNTHESIZE(bool, m_bDisabled, IsDisabled);
CC_SYNTHESIZE(SEL_CallFuncO, m_touchupInsideSelector, TouchupSelector);
CC_SYNTHESIZE(CCNode *, m_target, Target);
CC_SYNTHESIZE_RETAIN(CCObject *, m_saveObj, SaveObj);
};
#include "TTButton.h"
void setSpriteGray(CCNode *pNode, bool isGray)
{
if(isGray)
{
CCGLProgram *pProgram = CCShaderCache::sharedShaderCache()->programForKey("GrayEffect");
if(!pProgram)
{
pProgram = new CCGLProgram();
pProgram->autorelease();
pProgram->initWithVertexShaderByteArray(ccPositionTextureColor_vert, pszGrayModeFragSource);
pProgram->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
pProgram->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
pProgram->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);
pProgram->link();
CHECK_GL_ERROR_DEBUG();
pProgram->updateUniforms();
CHECK_GL_ERROR_DEBUG();
CCShaderCache::sharedShaderCache()->addProgram(pProgram, "GrayEffect");
}
pNode->setShaderProgram(pProgram);
CHECK_GL_ERROR_DEBUG();
}
else
{
//CCSprite
pNode->setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColor));
}
}
TTButton::TTButton()
{
//让调用 registerWithTouchDispatcher 函数
m_bTouchEnabled = true;
m_bSelected = false;
m_bDisabled = false;
m_btnState = BTN_STATE_UNSET;
m_normalSprite = NULL;
m_pressedSprite = NULL;
m_disableSprite = NULL;
m_normalScaleSprite = NULL;
m_pressedScaleSprite = NULL;
m_disableScaleSprite = NULL;
m_saveObj = NULL;
m_touchupInsideSelector = NULL;
}
TTButton::~TTButton()
{
}
bool TTButton:: initWithImages(std::string strNormal, std::string strSel , std::string strDisable , CCSize rectSize)
{
if (strNormal.empty() )
{
return false;
}
//normal
CCSpriteFrame * normalFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(strNormal.c_str());
if (normalFrame )
{
m_normalScaleSprite = CCScale9Sprite::createWithSpriteFrame(normalFrame);
}
if (m_normalScaleSprite == NULL)
{
m_normalScaleSprite = CCScale9Sprite::create(strNormal.c_str());
}
if (m_normalScaleSprite == NULL)
{
return false;
}
else
{
m_normalScaleSprite->setContentSize(rectSize);
m_normalScaleSprite->setAnchorPoint(CCPointZero);
m_normalScaleSprite->setPosition(CCPointZero);
this->addChild(m_normalScaleSprite);
//set contentSize
this->setContentSize(rectSize );
}
//sel
if ( strSel.empty() )
{
CCSpriteFrame * normalFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(strNormal.c_str());
if (normalFrame )
{
m_pressedScaleSprite = CCScale9Sprite::createWithSpriteFrame(normalFrame);
}
if (m_pressedScaleSprite == NULL)
{
m_pressedScaleSprite = CCScale9Sprite::create(strNormal.c_str());
}
}
else
{
CCSpriteFrame * selFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(strSel.c_str());
if (selFrame )
{
m_pressedScaleSprite = CCScale9Sprite::createWithSpriteFrame(selFrame);
}
if (m_pressedScaleSprite == NULL)
{
m_pressedScaleSprite = CCScale9Sprite::create(strSel.c_str());
}
}
if (m_pressedScaleSprite )
{
m_pressedScaleSprite->setContentSize(rectSize);
m_pressedScaleSprite->setAnchorPoint(CCPointZero);
m_pressedScaleSprite->setPosition(CCPointZero);
this->addChild(m_pressedScaleSprite);
}
//disabel
if (strDisable.empty() )
{
CCSpriteFrame * normalFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(strNormal.c_str());
if (normalFrame )
{
m_disableScaleSprite = CCScale9Sprite::createWithSpriteFrame(normalFrame);
}
if (m_disableScaleSprite == NULL)
{
m_disableScaleSprite = CCScale9Sprite::create(strNormal.c_str());
}
//如果是用 normal处理的,那么灰化
if (m_disableScaleSprite)
{
setSpriteGray(m_disableScaleSprite, true);
}
}
else
{
CCSpriteFrame * disableFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(strDisable.c_str());
if (disableFrame )
{
m_disableScaleSprite = CCScale9Sprite::createWithSpriteFrame(disableFrame);
}
if (m_disableScaleSprite == NULL)
{
m_disableScaleSprite = CCScale9Sprite::create(strDisable.c_str());
}
}
if (m_disableScaleSprite)
{
m_disableScaleSprite->setContentSize(rectSize);
m_disableScaleSprite->setAnchorPoint(CCPointZero);
m_disableScaleSprite->setPosition(CCPointZero);
this->addChild(m_disableScaleSprite);
}
//显示正常状态
this->setUnSelected();
return true;
}
bool TTButton::initWithImage(std::string strNormal, CCSize rectSize)
{
return this->initWithImages(strNormal,"","", rectSize);
}
bool TTButton::initWithImage(std::string strNormal)
{
return this->initWithImages(strNormal, "", "");
}
bool TTButton::initWithImages(std::string strNormal, std::string strSel , std::string strDisable )
{
if (strNormal.empty() )
{
return false;
}
//normal
CCSpriteFrame * normalFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(strNormal.c_str());
if (normalFrame )
{
m_normalSprite = CCSprite::createWithSpriteFrame(normalFrame);
}
if (m_normalSprite == NULL)
{
m_normalSprite = CCSprite::create(strNormal.c_str());
}
if (m_normalSprite == NULL)
{
return false;
}
else
{
m_normalSprite->setAnchorPoint(CCPointZero);
m_normalSprite->setPosition(CCPointZero);
this->addChild(m_normalSprite);
//set contentSize
this->setContentSize(m_normalSprite->getContentSize() );
}
//sel
if ( strSel.empty() )
{
CCSpriteFrame * normalFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(strNormal.c_str());
if (normalFrame )
{
m_pressedSprite = CCSprite::createWithSpriteFrame(normalFrame);
}
if (m_pressedSprite == NULL)
{
m_pressedSprite = CCSprite::create(strNormal.c_str());
}
}
else
{
CCSpriteFrame * selFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(strSel.c_str());
if (selFrame )
{
m_pressedSprite = CCSprite::createWithSpriteFrame(selFrame);
}
if (m_pressedSprite == NULL)
{
m_pressedSprite = CCSprite::create(strSel.c_str());
}
}
if (m_pressedSprite )
{
m_pressedSprite->setAnchorPoint(CCPointZero);
m_pressedSprite->setPosition(CCPointZero);
this->addChild(m_pressedSprite);
}
//disabel
if (strDisable.empty() )
{
CCSpriteFrame * normalFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(strNormal.c_str());
if (normalFrame )
{
m_disableSprite = CCSprite::createWithSpriteFrame(normalFrame);
}
if (m_disableSprite == NULL)
{
m_disableSprite = CCSprite::create(strNormal.c_str());
}
//如果是用 normal处理的,那么灰化
if (m_disableSprite)
{
setSpriteGray(m_disableSprite, true);
}
}
else
{
CCSpriteFrame * disableFrame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(strDisable.c_str());
if (disableFrame )
{
m_disableSprite = CCSprite::createWithSpriteFrame(disableFrame);
}
if (m_disableSprite == NULL)
{
m_disableSprite = CCSprite::create(strDisable.c_str());
}
}
if (m_disableSprite)
{
m_disableSprite->setAnchorPoint(CCPointZero);
m_disableSprite->setPosition(CCPointZero);
this->addChild(m_disableSprite);
}
//显示正常状态
this->setUnSelected();
return true;
}
//更新某种状态下的图像
void TTButton::upDateImageForState(BTN_STATE btnState , CCTexture2D *texture)
{
if(texture == NULL)
{
return ;
}
if (btnState == BTN_STATE_NORMAL )
{
if (m_normalSprite )
{
m_normalSprite->setTexture(texture);
}
}
if (btnState == BTN_STATE_PRESS)
{
if (m_pressedSprite )
{
m_pressedSprite->setTexture(texture);
}
}
if (btnState == BTN_STATE_DISABLE)
{
if (m_disableSprite)
{
m_disableSprite->setTexture(texture);
}
}
}
TTButton * TTButton::createWithImage(std::string strNormal)
{
TTButton * pRet = new TTButton();
if (pRet && pRet->initWithImage(strNormal) )
{
pRet->autorelease();
}
else
{
delete pRet;
pRet = NULL;
}
return pRet;
}
TTButton * TTButton::createWithImages(std::string strNormal, std::string strSel , std::string strDisable )
{
TTButton * pRet = new TTButton();
if (pRet && pRet->initWithImages(strNormal,strSel,strDisable) )
{
pRet->autorelease();
}
else
{
delete pRet;
pRet = NULL;
}
return pRet;
}
TTButton * TTButton:: createWithImage(std::string strNormal, CCSize rectSize)
{
TTButton * pRet = new TTButton();
if (pRet && pRet->initWithImage(strNormal, rectSize))
{
pRet->autorelease();
}
else
{
CC_SAFE_DELETE(pRet);
}
return pRet;
}
TTButton * TTButton::createWithImages(std::string strNormal, std::string strSel , std::string strDisable , CCSize rectSize)
{
TTButton * pRet = new TTButton;
if (pRet && pRet->initWithImages(strNormal, strSel, strDisable, rectSize))
{
pRet->autorelease();
}
else
{
CC_SAFE_DELETE(pRet);
}
return pRet;
}
//设置 颜色
void TTButton::setColorForState(BTN_STATE btnState, ccColor3B color)
{
switch (btnState)
{
case BTN_STATE_NORMAL:
{
if (m_normalSprite)
{
m_normalSprite->setColor(color);
}
if (m_normalScaleSprite)
{
m_normalScaleSprite->setColor(color);
}
}
break;
case BTN_STATE_PRESS:
{
if (m_pressedSprite)
{
m_pressedSprite->setColor(color);
}
if (m_pressedScaleSprite)
{
m_pressedScaleSprite->setColor(color);
}
}
break;
case BTN_STATE_DISABLE:
{
if (m_disableSprite)
{
m_disableSprite->setColor(color);
}
if (m_disableScaleSprite)
{
m_disableScaleSprite->setColor(color);
}
}
break;
default:
break;
}
}
//更新状态UI
void TTButton::upDateStatusUI()
{
switch (m_btnState)
{
case BTN_STATE_PRESS:
{
if (m_normalSprite )
{
m_normalSprite->setVisible(false);
}
if (m_normalScaleSprite)
{
m_normalScaleSprite->setVisible(false);
}
if (m_disableSprite )
{
m_disableSprite->setVisible(false);
}
if (m_disableScaleSprite)
{
m_disableScaleSprite->setVisible(false);
}
if (m_pressedSprite )
{
m_pressedSprite->setVisible(true);
}
if (m_pressedScaleSprite)
{
m_pressedScaleSprite->setVisible(true);
}
}
break;
case BTN_STATE_NORMAL:
{
if (m_normalSprite )
{
m_normalSprite->setVisible(true);
}
if (m_normalScaleSprite)
{
m_normalScaleSprite->setVisible(true);
}
if (m_disableSprite )
{
m_disableSprite->setVisible(false);
}
if (m_disableScaleSprite)
{
m_disableScaleSprite->setVisible(false);
}
if (m_pressedSprite )
{
m_pressedSprite->setVisible(false);
}
if (m_pressedScaleSprite)
{
m_pressedScaleSprite->setVisible(false);
}
}
break;
case BTN_STATE_DISABLE:
{
if (m_normalSprite )
{
m_normalSprite->setVisible(false);
}
if (m_normalScaleSprite)
{
m_normalScaleSprite->setVisible(false);
}
if (m_disableSprite )
{
m_disableSprite->setVisible(true);
}
if (m_disableScaleSprite)
{
m_disableScaleSprite->setVisible(true);
}
if (m_pressedSprite )
{
m_pressedSprite->setVisible(false);
}
if(m_disableScaleSprite)
{
m_disableScaleSprite->setVisible(false);
}
}
break;
default:
break;
}
}
//设置选中状态
void TTButton::setSelected()
{
m_bSelected = true;
m_btnState = BTN_STATE_PRESS;
upDateStatusUI();
}
//设置非选中状态
void TTButton::setUnSelected()
{
m_bSelected = false;
m_btnState = BTN_STATE_NORMAL;
upDateStatusUI();
}
//设置是否是disable状态
void TTButton::setIsDisable(bool bDisabel)
{
m_bDisabled = bDisabel;
if (bDisabel )
{
m_btnState = BTN_STATE_DISABLE;
}
else
{
m_btnState = BTN_STATE_NORMAL;
}
upDateStatusUI();
}
//获得当前状态
BTN_STATE TTButton::getCurState()
{
return m_btnState;
}
//添加 处理handle
void TTButton::addTouchupInsideHandle(CCNode * target , SEL_CallFuncO selector)
{
m_target = target;
m_touchupInsideSelector = selector;
}
//判断是否是点击在有效区域
bool TTButton::isTouchInvalidated(CCTouch* touch)
{
CCPoint touchLocation = touch->getLocation();
CCPoint localLocation = this->convertToNodeSpace(touchLocation);
CCRect rc = CCRectMake(
0,
0,
this->getContentSize().width,
this->getContentSize().height
);
if (rc.containsPoint(localLocation))
{
return true;
}
else
{
return false;
}
}
void TTButton::onEnter()
{
CCLayer::onEnter();
CCDirector* pDirector = CCDirector::sharedDirector();
pDirector->getTouchDispatcher()->addTargetedDelegate(this, kCCMenuHandlerPriority -1, true);
}
void TTButton::onExit()
{
CCLayer::onExit();
CCDirector* pDirector = CCDirector::sharedDirector();
pDirector->getTouchDispatcher()->removeDelegate(this);
}
bool TTButton::ccTouchBegan(CCTouch* touch, CCEvent* event)
{
//如果是disabled的状态,那么就返回false
if (m_btnState == BTN_STATE_DISABLE)
{
return false;
}
//如果自己不可见,那么返回false
if (isVisible() == false)
{
return false;
}
//如果有parent不可见,那么返回false
CCNode * parent = NULL;
for (parent = this->getParent() ; parent !=NULL ; parent = parent->getParent() )
{
if (parent->isVisible() == false )
{
return false;
}
}
//然后判断是否是在自己的范围内
if ( isTouchInvalidated(touch) )
{
if (m_bSelected)
{
m_btnState = BTN_STATE_NORMAL;
}
else
{
m_btnState = BTN_STATE_PRESS;
}
upDateStatusUI();
return true;
}
return false;
}
void TTButton::ccTouchMoved(CCTouch* touch, CCEvent* event)
{
//如果是有效范围内,那么设置selected状态
if ( isTouchInvalidated(touch) )
{
if (m_bSelected)
{
m_btnState = BTN_STATE_NORMAL;
}
else
{
m_btnState = BTN_STATE_PRESS;
}
upDateStatusUI();
}
else
{
if (m_bSelected)
{
m_btnState = BTN_STATE_PRESS;
}
else
{
m_btnState = BTN_STATE_NORMAL;
}
upDateStatusUI();
}
}
void TTButton::ccTouchEnded(CCTouch* touch, CCEvent* event)
{
//然后判断是否是在自己的范围内
if ( isTouchInvalidated(touch) )
{
//如果是有处理函数,调用处理函数。
CCLOG("touch event handle \n");
if (m_bSelected)
{
setUnSelected();
}
else
{
setSelected();
}
if ( m_target && m_touchupInsideSelector )
{
(m_target->*m_touchupInsideSelector)(this);
}
}
}
void TTButton::ccTouchCancelled(CCTouch *touch, CCEvent* event)
{
if (m_btnState != BTN_STATE_DISABLE )
{
this->setUnSelected();
}
}
其中使用的方法如下:
这个控件的锚点是(0,0),需要注意下:
TTButton * buttonTest = TTButton::createWithImage("avatar.png");
buttonTest->setScale(39.0f/buttonTest->getContentSize().width);
buttonTest->setPosition(ccp(
m_originPoint.x + i * (buttonTest->getContentSize().width + 22/2 ) + 30/2 ,
this->getContentSize().height * 0.5f - buttonTest->getContentSize().height * 0.5f
));
buttonTest->addTouchupInsideHandle(this, callfuncO_selector(TTPlayerWall::onClickPlayerImage));
this->addChild(buttonTest);