小 苏 CCButton - not use CCMenu
Posts 83
Added by 小 苏 over 1 year ago

I refer to http://www.cocos2d-x.org/boards/6/topics/1090?r=7731
and then make CCButton to be more similar to UIButton

here is some example

1:

CCButton * tmpBtn = CCButton::buttonWithFiles(this,menu_selector(HelloWorld::menuCloseCallback), "shop_btn.png", "shop_btn_click.png", NULL);
tmpBtn->setTitleForState("Show", CCControlStateNormal);
this->addChild(tmpBtn);
tmpBtn->setPosition(ccp(50,50));

2:
    CCSprite * tmpBgSprite = CCSprite::spriteWithFile("shop_btn.png");
    CCSprite * tmpBgSprite2 = CCSprite::spriteWithFile("shop_btn_click.png");

    CCButton * tmpBtn = CCButton::buttonWithFiles(this,menu_selector(HelloWorld::menuCloseCallback), NULL,NULL, NULL);
    tmpBtn->setBackgroundImageForState(tmpBgSprite, CCControlStateNormal);
    tmpBtn->setBackgroundImageForState(tmpBgSprite2, CCControlStateSelected);

    tmpBtn->setTitleForState("Show", CCControlStateNormal);

    this->addChild(tmpBtn);
    tmpBtn->setPosition(ccp(50,50));

3:
    CCButton * tmpBtn = CCButton::buttonWithFiles(this,menu_selector(HelloWorld::menuCloseCallback), NULL,NULL, NULL);
    tmpBtn->setTitleForState("Show", CCControlStateNormal);
    this->addChild(tmpBtn);
    tmpBtn->setPosition(ccp(50,50));

4:
CCButton * tmpBtn = CCButton::buttonWithFiles(this,menu_selector(HelloWorld::menuCloseCallback), "shop_btn.png", "shop_btn_click.png", NULL);
this->addChild(tmpBtn);
tmpBtn->setPosition(ccp(50,50)); 

here is the header file

#pragma once
#include "cocos2d.h" 
#define TAP_MAX_DRAG 10

using namespace cocos2d;

enum {
    CCControlStateNormal       = 0,
    CCControlStateSelected     = 1 << 0,                  // flag usable by app (see below)
    CCControlStateDisabled     = 1 << 1,
    CCControlStateHighlighted  = 1 << 2                 // todo
};
typedef unsigned int CCControlState;

class CCButton : public CCNode, public CCTargetedTouchDelegate
{
private:
    bool initWithFile(const char* filename, SelectorProtocol* target, SEL_MenuHandler selector);
    SelectorProtocol* target;
    SEL_MenuHandler selector;
    bool touched;
    CCPoint touchPoint;

    bool isDisabled;

    CCControlState curState;

    CCMutableDictionary<int,CCNode*> * backgroundNodes; //zOrder is 0
    CCMutableDictionary<int,CCNode*> * touchNodes;        //zOrder is 1
    CCMutableDictionary<int,CCString*> * titleCCStrings;  //zOrder is 2

    void setState(CCControlState mState);

public:
    CCButton();
    ~CCButton();

    void initWithFile(SelectorProtocol* target, SEL_MenuHandler selector,const char * mNormal,const char * mSelected,const char * mDisabled=NULL);
    static CCButton * buttonWithFiles(SelectorProtocol* target, SEL_MenuHandler selector,const char * mNormal,const char * mSelected,const char * mDisabled=NULL);

    void setTitleForState(const char * mTitle,CCControlState mState);
    const char* titleForState(CCControlState mState);

    void setDisable(bool mIsDisabled);

    //todo
    virtual void setTitleColorForState(ccColor3B mColor,CCControlState mState){CC_UNUSED_PARAM(mColor);CC_UNUSED_PARAM(mState);};
    virtual ccColor3B titleColorForState(CCControlState mState){CC_UNUSED_PARAM(mState);return ccYELLOW;};

    void setImageForState(CCNode* mNode,CCControlState mState);
    CCNode * imageForState(CCControlState mState);
    void setBackgroundImageForState(CCNode *mNode,CCControlState mState);// default is NULL
    CCNode * backgroundImageForState(CCControlState mState);

    // touch events
    CCRect rect();
    bool containsTouchLocation(CCTouch* touch);
    virtual void onEnter();
    virtual void onExit();
    virtual bool ccTouchBegan(CCTouch* pTouch, CCEvent* pEvent);
    virtual void ccTouchMoved(CCTouch* pTouch, CCEvent* pEvent);
    virtual void ccTouchEnded(CCTouch* pTouch, CCEvent* pEvent);
    virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
    virtual void touchDelegateRetain();
    virtual void touchDelegateRelease();
};

CCButton.cpp - CCButton.h (7.6 kB)

Zhe Wang RE: CCButton - not use CCMenu
Posts 1642
Location Amoy, China
Added by Zhe Wang over 1 year ago

Great extension. I'm considering to create a new sub-forum for extension discussion....

Enjoy Coding, Enjoy Life.

Leo Lou RE: CCButton - not use CCMenu
Posts 53
Added by Leo Lou about 1 year ago

For the latest stable version, should we change SelectorProtocol to CCObject?

小 苏 RE: CCButton - not use CCMenu
Posts 83
Added by 小 苏 about 1 year ago

yes, you can change SelectorProtocol to CCObject.
i had test it for the latest stable version

Markus Pfundstein RE: CCButton - not use CCMenu
Posts 8
Added by Markus Pfundstein about 1 year ago

Hey man,
awesome piece of work. Thanks a lot!

Only pity is that you use "using namespace cocos2d" in a header file. This is something you shouldn't do, as each file which will include CCButton will include using namespace cocos2d and all following files as well. Second, it would be cool if you could wrap extensions in your own namespace like cocos2d_ext or something. Than its easier to distinguish!

Besides that.. Great job!

Cookiebit Team RE: CCButton - not use CCMenu
Posts 3
Location Valencia, Spain
Added by Cookiebit Team 12 months ago

Hello.

We have updated CCButton to cocos2d-x 0.13

CCButton.h

#pragma once
#include "cocos2d.h" 
#define TAP_MAX_DRAG 10

enum {
    CCControlStateNormal       = 0,
    CCControlStateSelected     = 1 << 0,                  // flag usable by app (see below)
    CCControlStateDisabled     = 1 << 1,
    CCControlStateHighlighted  = 1 << 2                 // todo
};
typedef unsigned int CCControlState;

class CCButton : public cocos2d::CCNode, public cocos2d::CCTargetedTouchDelegate
{
private:
    bool initWithFile(const char* filename, cocos2d::CCObject* target, cocos2d::SEL_MenuHandler selector);
    cocos2d::CCObject* target;
    cocos2d::SEL_MenuHandler selector;
    bool touched;
    cocos2d::CCPoint touchPoint;

    bool isDisabled;

    CCControlState curState;

    cocos2d::CCMutableDictionary<int, cocos2d::CCNode*> * backgroundNodes; //zOrder is 0
    cocos2d::CCMutableDictionary<int, cocos2d::CCNode*> * touchNodes;        //zOrder is 1
    cocos2d::CCMutableDictionary<int, cocos2d::CCString*> * titleCCStrings;  //zOrder is 2

    void setState(CCControlState mState);

public:
    CCButton();
    ~CCButton();

    void initWithFile(cocos2d::CCObject* target, cocos2d::SEL_MenuHandler selector,const char * mNormal,const char * mSelected,const char * mDisabled=NULL);
    static CCButton * buttonWithFiles(cocos2d::CCObject* target, cocos2d::SEL_MenuHandler selector,const char * mNormal,const char * mSelected,const char * mDisabled=NULL);

    void setTitleForState(const char * mTitle,CCControlState mState);
    const char* titleForState(CCControlState mState);

    void setDisable(bool mIsDisabled);

    //todo
    virtual void setTitleColorForState(cocos2d::ccColor3B mColor,CCControlState mState){CC_UNUSED_PARAM(mColor);CC_UNUSED_PARAM(mState);};
    virtual cocos2d::ccColor3B titleColorForState(CCControlState mState){CC_UNUSED_PARAM(mState);return cocos2d::ccYELLOW;};

    void setImageForState(CCNode* mNode,CCControlState mState);
    CCNode * imageForState(CCControlState mState);
    void setBackgroundImageForState(CCNode *mNode,CCControlState mState);// default is NULL
    CCNode * backgroundImageForState(CCControlState mState);

    // touch events
    cocos2d::CCRect rect();
    bool containsTouchLocation(cocos2d::CCTouch* touch);
    virtual void onEnter();
    virtual void onExit();
    virtual bool ccTouchBegan(cocos2d::CCTouch* pTouch, cocos2d::CCEvent* pEvent);
    virtual void ccTouchMoved(cocos2d::CCTouch* pTouch, cocos2d::CCEvent* pEvent);
    virtual void ccTouchEnded(cocos2d::CCTouch* pTouch, cocos2d::CCEvent* pEvent);
    virtual void ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
    virtual void touchDelegateRetain();
    virtual void touchDelegateRelease();
};

CCButton.cpp

#include "CCButton.h" 

#define CCButtonZorder0    0
#define CCButtonZorder1    1
#define CCButtonZorder2    2

#define CCButtonBgTag  1000001
#define CCButtonTouchedTag  1000002
#define CCButtonTitleTag 1000003

using namespace cocos2d;

CCButton::CCButton():CCNode()
{
    backgroundNodes = new CCMutableDictionary<int,CCNode*>();
    touchNodes = new CCMutableDictionary<int,CCNode*>();
    titleCCStrings = new CCMutableDictionary<int,CCString*>();
    isDisabled = false;
}

CCButton::~CCButton()
{
    CC_SAFE_DELETE(backgroundNodes);
    CC_SAFE_DELETE(touchNodes);
    CC_SAFE_DELETE(titleCCStrings);
}

void CCButton::initWithFile(CCObject* target, SEL_MenuHandler selector,const char * mNormal,const char * mSelected,const char * mDisabled)
{
    this->target = target;
    this->selector = selector;

    if (mNormal != NULL) {
        CCSprite * mNormalSprite = CCSprite::spriteWithFile(mNormal);
        mNormalSprite->setTag(CCButtonTouchedTag);
        this->addChild(mNormalSprite, CCButtonZorder1);
        touchNodes->setObject(mNormalSprite,CCControlStateNormal);

        //set the content size.
        CCSize mContentSize = mNormalSprite->getContentSize();
        this->setContentSize(mContentSize);
    }

    if (mSelected != NULL) {
        CCSprite * mSelectedSprite = CCSprite::spriteWithFile(mSelected);
        mSelectedSprite->setTag(CCButtonTouchedTag);
        touchNodes->setObject(mSelectedSprite,CCControlStateSelected);
    }

    if (mDisabled != NULL) {
        CCSprite * mDisabledSprite = CCSprite::spriteWithFile(mDisabled);
        mDisabledSprite->setTag(CCButtonTouchedTag);
        touchNodes->setObject(mDisabledSprite,CCControlStateDisabled);
    }

    touched = false;
}

 CCButton * CCButton::buttonWithFiles(CCObject* target, SEL_MenuHandler selector,const char * mNormal,const char * mSelected,const char * mDisabled)
{
    CCButton *pRet = new CCButton();
    if (pRet)
    {
        pRet->initWithFile(target, selector,mNormal,mSelected,mDisabled);
        pRet->autorelease();
        return pRet;
    }
    CC_SAFE_DELETE(pRet)
    return NULL;
}

void CCButton::setState(CCControlState mState)
{
    ////set background node
    CCNode * bgNode = backgroundImageForState(mState);
    if (bgNode != NULL) {
        bgNode->setTag(CCButtonBgTag);
        CCNode * mTepNode = this->getChildByTag(CCButtonBgTag);
        if (mTepNode != NULL) {
            mTepNode->removeFromParentAndCleanup(true);
        }
        this->addChild(bgNode, CCButtonZorder0);
    }

    //set touch node
    CCNode * stateNode = imageForState(mState);
    if (stateNode != NULL) {
        stateNode->setTag(CCButtonTouchedTag);
        CCNode * mTepNode = this->getChildByTag(CCButtonTouchedTag);
        if (mTepNode != NULL) {
            mTepNode->removeFromParentAndCleanup(true);
        }
        this->addChild(stateNode, CCButtonZorder1);
    }

    //set title node
    const char*  titleForState = this->titleForState(mState);
    if (titleForState != NULL) {
        this->setTitleForState(titleForState,mState);
    }
}

void CCButton::setDisable(bool mIsDisabled)
{
    this->isDisabled = mIsDisabled;
    if (mIsDisabled == true) {
        setState(CCControlStateDisabled);
    }
    else {
        setState(CCControlStateNormal);
    }
}

void CCButton::setTitleForState(const char * mTitle,CCControlState mState)
{
    if (mTitle == NULL) {
        return;
    }

    CCLabelTTF * mTepNode = (CCLabelTTF *) (this->getChildByTag(CCButtonTitleTag));
    if (mTepNode != NULL) {
        mTepNode->setString(mTitle);
    }
    else {
        CCSize mContentSize = this->getContentSize();
        mTepNode = CCLabelTTF::labelWithString(mTitle, "Arial", 14);
        mTepNode->setTag(CCButtonTitleTag);
        this->setPosition(ccp(mContentSize.width/2.0,mContentSize.height/2.0));
        this->addChild(mTepNode, CCButtonZorder2);
    }

    CCSize mContentSize = mTepNode->getContentSize();
    mContentSize.width += 8;
    mContentSize.height += 6;
    this->setContentSize(mContentSize);

    CCString * mTepNodeInList = (CCString *) (this->titleCCStrings->objectForKey((int)mState));
    if (mTepNodeInList != NULL) {
        std::string mTepString = mTepNodeInList->toStdString();
        std::string mTepCompareString(mTitle);
        if (mTepString.compare(mTepCompareString) == 0) {
            return;
        }
        this->titleCCStrings->removeObjectForKey((int)mState);
    }

    //save string
    CCString * mNormalCCString = new CCString(mTitle);
    mNormalCCString->autorelease();
    this->titleCCStrings->setObject(mNormalCCString,mState);
}

const char * CCButton::titleForState(CCControlState mState)
{
    CCString * mTepNodeInList = (CCString *) (this->titleCCStrings->objectForKey((int)mState));
    if (mTepNodeInList != NULL) {
        return mTepNodeInList->toStdString().c_str();
    }
    return NULL;
}

/*
void CCButton::setTitleColorForState(ccColor3B mColor,CCControlState mState)
{
    CC_UNUSED_PARAM(mColor);
    CC_UNUSED_PARAM(mState);
}

ccColor3B CCButton::titleColorForState(CCControlState mState)
{
    CC_UNUSED_PARAM(mState);
}
 */

void CCButton::setImageForState(CCNode* mNode,CCControlState mState)
{
    if (mNode == NULL) {
        return;
    }

    CCSize mContentSize = mNode->getContentSize();
    this->setContentSize(mContentSize);

    CCNode * mTepNodeInList = (CCNode *) (this->touchNodes->objectForKey((int)mState));
    if (mTepNodeInList != NULL) {
        this->touchNodes->removeObjectForKey((int)mState);
    }

    this->touchNodes->setObject(mNode,(int)mState);

    if (mState == CCControlStateNormal) {
        this->setState(CCControlStateNormal);
    }
}

CCNode * CCButton::imageForState(CCControlState mState)
{
    if (this->touchNodes->count() == 0) {
        return NULL;
    }

    CCNode * mTepNodeInList = (CCNode *) (this->touchNodes->objectForKey((int)mState));
    if (mTepNodeInList != NULL) {
        return mTepNodeInList;
    }
    return NULL;
}

void CCButton::setBackgroundImageForState(CCNode *mNode,CCControlState mState)// default is nil
{
    if (mNode == NULL) {
        return;
    }

    CCSize mContentSize = mNode->getContentSize();
    this->setContentSize(mContentSize);

    CCNode * mTepNodeInList = (CCNode *) (this->backgroundNodes->objectForKey((int)mState));
    if (mTepNodeInList != NULL) {
        this->backgroundNodes->removeObjectForKey((int)mState);
    }

    this->backgroundNodes->setObject(mNode,(int)mState);

    if (mState == CCControlStateNormal) {
        this->setState(CCControlStateNormal);
    }
}

CCNode * CCButton::backgroundImageForState(CCControlState mState)
{
    if (this->backgroundNodes->count() == 0) {
        return NULL;
    }

    CCNode * mTepNodeInList = (CCNode *) (this->backgroundNodes->objectForKey((int)mState));
    if (mTepNodeInList != NULL) {
        return mTepNodeInList;
    }
    return NULL;
}

void CCButton::onEnter()
{
    CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, false);
    CCNode::onEnter();
}

void CCButton::onExit()
{
    CCTouchDispatcher::sharedDispatcher()->removeDelegate(this);
    CCNode::onExit();
}    

CCRect CCButton::rect()
{
    CCSize s = this->getContentSize();
    return CCRectMake(-s.width / 2, -s.height / 2, s.width, s.height);
}

bool CCButton::containsTouchLocation(CCTouch* touch)
{    
    return CCRect::CCRectContainsPoint(rect(), convertTouchToNodeSpaceAR(touch));
}

bool CCButton::ccTouchBegan(CCTouch* pTouch, CCEvent* pEvent)
{
    if (!this->isDisabled && containsTouchLocation(pTouch)) 
    {
        touched = true;
        touchPoint = pTouch->locationInView();
        this->setState(CCControlStateSelected);
        return true;
    }
    return false;
}

void CCButton::ccTouchMoved(CCTouch* pTouch, CCEvent* pEvent)
{    
    CCPoint currTouchPoint = pTouch->locationInView();
    // cancel touch if dragged too much
    if (ccpDistance(touchPoint,currTouchPoint) > TAP_MAX_DRAG)
    {
        this->setState(CCControlStateNormal);

        touched = false;
    }
}

void CCButton::ccTouchEnded(CCTouch* pTouch, CCEvent* pEvent)
{
    if (touched)
    {
        this->setState(CCControlStateNormal);

        //perform selector
        (target->*selector)(this);        
        touched = false;
    }
}

void CCButton::ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent)
{
    this->setState(CCControlStateNormal);

    touched = false;
}

void CCButton::touchDelegateRetain()
{
    this->retain();
}
void CCButton::touchDelegateRelease()
{
    this->release();
}

www.cookiebit.com

CCButton.h (2.6 kB)

Jose Antonio Andujar RE: CCButton - not use CCMenu
Posts 82
Location Spain
Added by Jose Antonio Andujar 12 months ago

I updated the cocos2d-extensions with your CCButton component. There is a bug in win32, maybe you can solve it and submit a patch.

https://github.com/jandujar/cocos2d-x-extensions

http://www.jandusoft.com
More than 7m downloads of my first game "Guess the Character"

Žygis Buzzy RE: CCButton - not use CCMenu
Posts 31
Added by Žygis Buzzy 10 months ago

So, it's better to use this CCButton instead of CCMenu?

Dawid Drozd RE: CCButton - not use CCMenu
Posts 39
Added by Dawid Drozd 3 months ago

@Jose Antonio Andujar Why your extensions aren't merged to cocos repo? :(

Jose Antonio Andujar RE: CCButton - not use CCMenu
Posts 82
Location Spain
Added by Jose Antonio Andujar 3 months ago

@Dawid Drozd

I haven't updated the extensions a long time ago.

I'm sure they need a lot of work for cross-platform working, and I'm not sure that will be accepted for a pull request.

http://www.jandusoft.com
More than 7m downloads of my first game "Guess the Character"


(1-9/9)