A couple helpful macros and functions I've been using for manipulating Nodes ui::Widgets

These aren’t game changing, but I think it clarifies your intent and saves you a few keystrokes along the way.

First, SCHEDULE lets you declare a lambda, then schedule it to a target, calling it immediately, and using the same name as a function key

//calls the function immediately and schedules it with the same name
#define SCHEDULE(target,callbackname,FPS)callbackname(0.0f);target->schedule(callbackname, FPS, #callbackname)

//setup
auto callback = []() { CCLOG("updating"); };
auto widget = cocos2d::ui::Widget::create();

//usage
SCHEDULE(widget, callback, 1.0f);

//...instead of
widget->schedule(callback, 1.0f, "callback");
callback(0.0f);

I’m not sure about you guys but I spent a lot of time going through the prebuilt nodes I get from Cocos Studio, so I wrote the GET_CHILD_XYZ macros to save typing, because I’m super lazy. So first up GET_UI_CHILD takes a parent node, a child node, then the intended type of child and dynamic_casts it, then GET_CHILD_LAYOUT takes it a step further and passes all of them. The specified macros are helpful for autocompleting, so I’ve got one for Button, ImageView etc.

//helper for casting a parent's child
#define GET_UI_CHILD(parent, name, type)dynamic_cast<cocos2d::ui::##type*>(parent->getChildByName(name))
#define GET_CHILD_SLIDER(parent, name)GET_UI_CHILD(parent, name, Slider)
#define GET_CHILD_TEXT(parent, name)GET_UI_CHILD(parent, name, Text)
#define GET_CHILD_TEXTFIELD(parent, name)GET_UI_CHILD(parent, name, TextField)
#define GET_CHILD_TEXTBMFONT(parent, name)GET_UI_CHILD(parent, name, TextBMFont)
#define GET_CHILD_LAYOUT(parent, name)GET_UI_CHILD(parent, name, Layout)
#define GET_CHILD_BUTTON(parent, name)GET_UI_CHILD(parent, name, Button)
#define GET_CHILD_IMAGEVIEW(parent, name)GET_UI_CHILD(parent, name, ImageView)
#define GET_CHILD_LISTVIEW(parent, name)GET_UI_CHILD(parent, name, ListView)
#define GET_CHILD_PAGEVIEW(parent, name)GET_UI_CHILD(parent, name, PageView)


//usage
auto layout = GET_CHILD_LAYOUT(parent_node, "child_name");

//...instead of
auto layout = dynamic_cast<cocos2d::ui::Layout*>(parent_node->getChildByName("child_name"));

This one’s just a regular function for binding callbacks to TOUCH_ENDs on Buttons

void bind_touch_ended(cocos2d::ui::Widget* widget, std::function<void(void)> callback)
{
    auto touch_handler = [callback](cocos2d::Ref*, cocos2d::ui::Widget::TouchEventType evt)
    {
        if (evt == cocos2d::ui::Widget::TouchEventType::ENDED)
        {
            //vibrate()
            callback();
            //play_sound()
        }
    };
    widget->addTouchEventListener(touch_handler);
};


//usage
bind_touch_ended(my_button, [](){ CCLOG("button has been touched");});

Finally, I’ve got a bunch of timing constants for FPS updates, just so I don’t have to remember whether 60 FPS is .16ms or .016ms, you’ll get the picture, where x in FPS_X is the times per second

const float FPS_1   = 1.0f /   1.0f;
const float FPS_2   = 1.0f /   2.0f;
const float FPS_4   = 1.0f /   4.0f;
const float FPS_10  = 1.0f /  10.0f;
const float FPS_15  = 1.0f /  15.0f;
const float FPS_30  = 1.0f /  30.0f;
const float FPS_60  = 1.0f /  60.0f;
const float FPS_120 = 1.0f / 120.0f;

//usage
SCHEDULE(widget, callback, FPS_60); //for updates 60 times a second

Anyway, hope this helps someone, I know I’ve found enough help on here that I think its about time I give back at least a little

1 Like

Working on cloning a bunch of non ui::Widgets and started using this one:

#define GETSET(orig, child, name)child->set##name(orig->get##name())

and usage is:

Label* original_label = scene->getChildByName("my_label");
Label* cloned_label = Label::create();
GETSET(original_label, cloned_label, Name); 

which ends up working out to

cloned_label->setName(original_label->getName());

If I knew how, I’d make some sort of vararg macro to add a bunch of properties at once to make it even easier.