How to use CCControlButton in JSB?

I use CCControlButton in my CocosBuilder project and set selector named “onBattle”.But It throw a error when I run it in cocos-html5 2.1.4 version.

Here is the code:

var MainMenu = function(){};

MainMenu.prototype.onDidLoadFromCCB = function()
{
cc.log(“file loaded”this.Index“,”this.Function“,”this.Bag“,”+this.Shop);
};

MainMenu.prototype.onBattle = function()
{
alert(“点击战斗”);
};

var MyScene = cc.Scene.extend({
ctor:function () {
this._super();

var node=cc.BuilderReader.load(“res/CCB/主界面.ccbi”);

if(node != null) {
this.addChild(node);
}

this.setPosition(cc.p(0, 0));

}

});

Here is the error:

TypeError: callbackNode is undefined extensions/CCBReader/CCBReader.js:979

Last time I checked, setting a callback via CCB doesn’t work correctly. I sent in a pull request to add manual support for CCButton’s target, which you can see in https://github.com/cocos2d/cocos2d-x/pull/2580/files. James mentioned he’d pull it into the develop branch, but I don’t think it’s been done yet. You can probably merge the relevant change yourself so you can actually use CCButton in a meaningful way.

Randy Chung wrote:

Last time I checked, setting a callback via CCB doesn’t work correctly. I sent in a pull request to add manual support for CCButton’s target, which you can see in https://github.com/cocos2d/cocos2d-x/pull/2580/files. James mentioned he’d pull it into the develop branch, but I don’t think it’s been done yet. You can probably merge the relevant change yourself so you can actually use CCButton in a meaningful way.

Hi Randy - does your CCControlButton fix for JSB work with CocosBuilder?

No, it doesn’t. I haven’t looked at the CCB/JSB side of things in a while, but I don’t recall it being a very difficult thing to add support for. We don’t often use CCControlButtons directly (we usually wrap it in a custom class), so I never got around to adding support for it in CCB.

Randy Chung wrote:

No, it doesn’t. I haven’t looked at the CCB/JSB side of things in a while, but I don’t recall it being a very difficult thing to add support for. We don’t often use CCControlButtons directly (we usually wrap it in a custom class), so I never got around to adding support for it in CCB.

Okay, thanks for the response. I’ll take a look into it.

I merge the PR :https://github.com/cocos2d/cocos2d-x/pull/2580/files to my codes, and use like this:
var button = cc.ControlButton.create(titleButton, backgroundButton);
button.setPosition(cc.p(200,400))
button.addTargetWithActionForControlEvents(this, this.touchDownAction, cc.CONTROL_EVENT_TOUCH_DOWN);
this.addChild(button);

……

but the method ‘touchDownAction’ can not be triggered at all. Where am wrong?
jsb_cocos2d_extension.js
cc.CONTROL_EVENT_TOUCH_DOWN = 1 << 0; // A touch-down event in the control.
cc.CONTROL_EVENT_TOUCH_DRAGINSIDE = 1 << 1; // An event where a finger is dragged inside the bounds of the control.
cc.CONTROL_EVENT_TOUCH_DRAGOUTSIDE = 1 << 2; // An event where a finger is dragged just outside the bounds of the control.
cc.CONTROL_EVENT_TOUCH_DRAGENTER = 1 << 3; // An event where a finger is dragged into the bounds of the control.
cc.CONTROL_EVENT_TOUCH_DRAGEXIT = 1 << 4; // An event where a finger is dragged from within a control to outside its bounds.
cc.CONTROL_EVENT_TOUCH_UPINSIDE = 1 << 5; // A touch-up event in the control where the finger is inside the bounds of the control.
cc.CONTROL_EVENT_TOUCH_UPOUTSIDE = 1 << 6; // A touch-up event in the control where the finger is outside the bounds of the control.
cc.CONTROL_EVENT_TOUCH_CANCEL = 1 << 7; // A system event canceling the current touches for the control.
cc.CONTROL_EVENT_VALUE_CHANGED = 1 << 8; // A touch dragging or otherwise manipulating a control, causing it to emit a series of different values.

jsb_cocos2dx_extension_manual.cpp

class JSB_ControlButtonTarget : public CCObject {    public:
        virtual void onEvent(CCObject *controlButton, CCControlEvent event) {
                js_proxy_t * p;
                JS_GET_PROXY(p, controlButton);
                if (!p) {
                        CCLog("Failed to get proxy for control button");
                        return;
                    }

                jsval dataVal[2];
                dataVal[0] = OBJECT_TO_JSVAL(p->obj);
                int arg1 = event;
                dataVal[1] = INT_TO_JSVAL(arg1);

                ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(m_pJSTarget), m_JSAction.c_str(), 2, dataVal, NULL);
            }

        void setJSTarget(JSObject* pJSTarget)
        {
                m_pJSTarget = pJSTarget;
            }

        void setJSAction(std::string JSAction) {
                m_JSAction = JSAction;
            }
    private:
        JSObject* m_pJSTarget;
        std::string m_JSAction;
    };

static JSBool js_cocos2dx_CCControl_addTargetWithActionForControlEvents(JSContext *cx, uint32_t argc, jsval *vp)
{
        jsval *argv = JS_ARGV(cx, vp);
        JSObject *obj = JS_THIS_OBJECT(cx, vp);
        js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj);
        cocos2d::extension::CCControl* cobj = (cocos2d::extension::CCControl *)(proxy ? proxy->ptr : NULL);
        JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object");

        if (argc == 3) {
                JSObject *tmpObj = JSVAL_TO_OBJECT(argv[0]);
                JS_GET_NATIVE_PROXY(proxy, tmpObj);
            cocos2d::CCObject *arg0 = (cocos2d::CCObject *)(proxy ? proxy->ptr : NULL);
                TEST_NATIVE_OBJECT(cx, arg0);

                std::string arg1;
               JSBool ok = jsval_to_std_string(cx, argv[1], &arg1);
                JSB_PRECONDITION2(ok, cx, JS_FALSE, "Error processing control function name");

                int arg2;
                ok &= jsval_to_int32(cx, argv[2], (int32_t *)&arg2);
                JSB_PRECONDITION2(ok, cx, JS_FALSE, "Error processing control event");

                // save the delegate
                JSObject *jsDelegate = JSVAL_TO_OBJECT(argv[0]);
                JSB_ControlButtonTarget* nativeDelegate = new JSB_ControlButtonTarget();
                nativeDelegate->setJSTarget(jsDelegate);
                nativeDelegate->setJSAction(arg1);
                cobj->addTargetWithActionForControlEvents(nativeDelegate, cccontrol_selector(JSB_ControlButtonTarget::onEvent), arg2);

                JS_SET_RVAL(cx, vp, JSVAL_VOID);

                return JS_TRUE;
            }
        JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 3);
        return JS_FALSE;
    }

static JSBool js_cocos2dx_CCControl_removeTargetWithActionForControlEvents(JSContext *cx, uint32_t argc, jsval *vp)
{
        jsval *argv = JS_ARGV(cx, vp);
        JSObject *obj = JS_THIS_OBJECT(cx, vp);
        js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj);
        cocos2d::extension::CCControl* cobj = (cocos2d::extension::CCControl *)(proxy ? proxy->ptr : NULL);
        JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object");

        if (argc == 3) {
                obj = JSVAL_TO_OBJECT(argv[0]);
                JS_GET_NATIVE_PROXY(proxy, obj);
                cocos2d::CCObject *arg0 = (cocos2d::CCObject *)(proxy ? proxy->ptr : NULL);
                TEST_NATIVE_OBJECT(cx, arg0);

                obj = JSVAL_TO_OBJECT(argv[2]);
                JS_GET_NATIVE_PROXY(proxy, obj);
                cocos2d::extension::CCControlEvent *arg2 = (cocos2d::extension::CCControlEvent *)(proxy ? proxy->ptr : NULL);
                TEST_NATIVE_OBJECT(cx, arg2);

                return JS_TRUE;
            }
        JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 3);
        return JS_FALSE;
    }

extern JSObject* jsb_CCControl_prototype;

JS_DefineFunction(cx, jsb_CCControl_prototype, "addTargetWithActionForControlEvents", js_cocos2dx_CCControl_addTargetWithActionForControlEvents, 3, JSPROP_READONLY | JSPROP_PERMANENT);
    JS_DefineFunction(cx, jsb_CCControl_prototype, "removeTargetWithActionForControlEvents", js_cocos2dx_CCControl_removeTargetWithActionForControlEvents, 3, JSPROP_READONLY | JSPROP_PERMANENT);

It’s not meant to be used like that. As shown in the code, it takes a string as a message to execute (which, to be fair, may not be the best way to go about it). Try this:

button.addTargetWithActionForControlEvents(this, “onEvent”, cc.CONTROL_EVENT_TOUCH_DOWN);

Randy

Hi, Randy,
It can work now, thanks for reply!

Randy Chung wrote:

It’s not meant to be used like that. As shown in the code, it takes a string as a message to execute (which, to be fair, may not be the best way to go about it). Try this:
>
button.addTargetWithActionForControlEvents(this, “onEvent”, cc.CONTROL_EVENT_TOUCH_DOWN);
>
Randy

I’m glad to let you know that cc.ControlXXX are fully supported in cocos2d-x 3.0.
Please refer to https://github.com/cocos2d/cocos2d-x/pull/3403 and https://github.com/cocos2d/cocos2d-x/pull/3413

Great job, Grate Guy

James Chen wrote:

I’m glad to let you know that cc.ControlXXX are fully supported in cocos2d-x 3.0.
Please refer to https://github.com/cocos2d/cocos2d-x/pull/3403 and https://github.com/cocos2d/cocos2d-x/pull/3413

James Chen wrote:

I’m glad to let you know that cc.ControlXXX are fully supported in cocos2d-x 3.0.
Please refer to https://github.com/cocos2d/cocos2d-x/pull/3403 and https://github.com/cocos2d/cocos2d-x/pull/3413

James,
Sorry have a question.
I use CCControlButton in Web,
but shows “Uncaught TypeError: Cannot call method ‘setCallback’ of undefined.”

Do you know waht’s the problem?

Thanks!

Simon Pan wrote:

James Chen wrote:
> I’m glad to let you know that cc.ControlXXX are fully supported in cocos2d-x 3.0.
> Please refer to https://github.com/cocos2d/cocos2d-x/pull/3403 and https://github.com/cocos2d/cocos2d-x/pull/3413
>
James,
Sorry have a question.
I use CCControlButton in Web,
but shows “Uncaught TypeError: Cannot call method ‘setCallback’ of undefined.”
>
Do you know waht’s the problem?
>
Thanks!

Solve the problem by myself and wrote a blogger to teach someone who need it.

James Chen wrote:

I’m glad to let you know that cc.ControlXXX are fully supported in cocos2d-x 3.0.
Please refer to https://github.com/cocos2d/cocos2d-x/pull/3403 and https://github.com/cocos2d/cocos2d-x/pull/3413

I am trying to use cc.ControlButton with JSB and v3.0alpha0-pre. I get this issue when trying to call

setBackgroundSpriteForState

or

setTitleColorForState

functions:

09-23 16:05:10.027: D/cocos2d-x debug info(28719): jsb: ERROR: File C:/cocos2d-x-3.0alpha0-pre/projects/PortTest/proj.android/../../../scripting/javascript/bindings/ScriptingCore.cpp: Line: 1104, Function: jsval_to_int32
09-23 16:05:10.027: D/cocos2d-x debug info(28719): Error processing arguments
09-23 16:05:10.027: D/cocos2d-x debug info(28719): jsb: ERROR: File C:/cocos2d-x-3.0alpha0-pre/projects/PortTest/proj.android/../../../scripting/javascript/bindings/generated/jsb_cocos2dx_extension_auto.cpp: Line: 3200, Function: js_cocos2dx_extension_ControlButton_setBackgroundSpriteForState
09-23 16:05:10.027: D/cocos2d-x debug info(28719): Error processing arguments
09-23 16:05:10.027: D/cocos2d-x debug info(28719): JS: assets/MainMenuScene.js:71:Error: Error processing arguments

Any advice? Thanks.