How to catch the name of the frame event?

Maybe try this code. I can’t remember where I got it from and I haven’t had a chance to test it yet. Let us know if it works.

EventFrame* evnt = dynamic_cast<EventFrame*>(frame);
if(!evnt)
    return;

std::string str = evnt->getEvent();
if (str == "end_animation")
{
    CCLOG("frame event happened");
}

I have tried this code,it is from the cpp test,don’t seam yo work,maybe the definition of the frame event in cocostuid is wrong, so I’m asking for a reference for this

up, anyone?

Hi,

I’m interested in this too… any update?

Cheers.

Hi again,

@iQD, it seems you have some experience with the Frame Event thing. Do you know how to set a Frame Event in cocos studio 2.x? I have spend over 2 hours trying different things but wasn’t able to add events per frame.

I have been having a look at the sources and it really seems that the Frame class can send event per Frame. I mean, when the the current time is greater than the Frame time it schedules an event. But can’t figure out how to do this in Cocos Studio 2.x.

Any help would be really appreciated.

Cheers.

Just like in the first post of @rapt

You just insert an event name in the “Frame Event” filed like in the screenshot.

The examples states the following:

void TestTimelineFrameEvent::onFrameEvent(Frame* frame)
{
    EventFrame* evnt = dynamic_cast<EventFrame*>(frame);
    if(!evnt)
        return;

    std::string str = evnt->getEvent();

    if (str == "changeColor")
    {
        evnt->getNode()->setColor(Color3B(0,0,0));
    }
    else if(str == "endChangeColor")
    {
        evnt->getNode()->setColor(Color3B(255,255,255));
    }
}

The problem is, that the formal param of the callback is a Frame: class CC_STUDIO_DLL Frame : public cocos2d::Ref

But they cast it to an EventFrame:

Not to mix it with FrameEvent!

struct FrameEvent
{
    Bone *bone;
    std::string frameEventName;
    int originFrameIndex;
    int currentFrameIndex;
};

Thanks for the asnwer iQD. Really kind of you to brign all this info.

Anyway this is not what I’m asking. I would like to know how to add a Frame event to a node track.

I have seen this existed in a previous version:

But when I expand node tracks, Event does not exist anymore.

Cheers.

CS 2.3.2Beta: It’s on the right side under the “Advanced” tab: Frame Event and User Data

I digged again through the API. Forget what I said above. I oversaw that EventFrame is derived from Frame. so the tutorial code should work fine.

I mixed it with FrameEvent. So be careful or you end like me :blush:

What is not working exactly?

Which CS version are you using?

Check the pic… no Frame event track. I am using CS 2.3.2Beta on W10 O_O. This is something really odd…

why on earth it is not showing in my CS2.3.2B version?

Cheers

Because you did not add it.

You have to scroll to the frame properties on the right panel(look at my screenshot). After you entered a name/value it will appear in the dope-sheet.

Hi again,

Sorry iQD but it seems I’m doomed today:

Have tried to aproximate my screenshot to yours. And again nothing appears :/.

I have even created a new project. Then I went directly to the Default node (sprite) scrolled down and filled the Frame string and the user data with the values you had in your pic and nothing…

Cheers.

Because you did not tick “AutoRecord Frame”. Some properties(including events) need auto record.

CS still needs a lot of work :wink:

Holly shit! It is working… amazing… Thanks a lot for all the time and patience man.

Don’t understand why it needs AutoRecord Frame, but hey! it works!.

BTW: CS still need a lot of work but it feels much better than last year. I was plaing with cocos2d-x (comming from unity) and man it was a nightmare. Now it seems pretty stable. It needs a lot of features and little refinements but it is shaping great.

At last I will be able to give some more work to my designers :D.

On the other hand and if you don’t mind, coudl you explain what is the “Method” property and the little edit text shown when you select Click or Touch for a button in the properties?

Cheers.

You’re welcome. If you do, what needs to be done, it will work. All thanks to the “dumbness” of a Computer :smile:

Because CS still needs a lot of work :smile: It’s far from perfect.

Unity is driven by money. It’s their business to deliver good products for cash.

I don’t use CS at all, so it’s not a problem for me.

Just tell them, they should learn how to code :wink:

It’s for delegating the callback function. You can specify the function, which should get called on which event. Instead of defining the callback function in code, you can do it in CS.

E.g. Click myClickCallback
This will call the myClickCallBack function in your code. Of course you have to declare and implement it in your code.

Hi,

Thanks again. Really informative.

2 more questions:

if you don’t use cocos studio, how do you define your UI, scenes, etc…? please do not tell me you do all this programatically :smiley:

About the callback, it is a mistery how they do the binding later whitout rtti :O. I think I will have to take a look at the sources :).

And last thing about Unity comment. Unity is driven by money yes… but it grew mainly based on indies and its “free” model. I have switched because lately unity is starting to put too much “junk” into his free version. Like a friend of midn said… if the product is free it is because your are the product :D.
Cheers.

Of course!
I’m only using Plists for specific game-play and scene configurations, I don’t use any editors beside Spine for skeletal/frame animations. UI and overall game design is done by the designer and his tools(PS, Gimp, whatever) anyway.
Besides that, our games are heavily relying on run-time specific content anyway. So there is no advantage in designing scenes in an editor beforehand.

A mystery? Really?
Why would you need RTTI for that? It’s just a delegate. The engine code just dereferences the pointer of the delegate.
That’s why you have to set it with the setFrameEventCallFunc function. Internally the engine just calls something like callDelegate, which is a pointer to the function set in setFrameEventCallFunc.

They had to adopt the “freemium” model, because all major engine companies switched to that business model.
It’s also hard to tell these days, what “Indie” really is. Real Indies are not using Unity. They are/were using SDL :wink:

Regarding “junk”: they have to, or they will get left behind. Be it free or non-free, it does not mean quality per se.

Sure, many services out there are free because of that. But there are also paid plans from the same companies. Does that mean, you are not the product if you pay for the service? :wink:
If you want SLAs or anything professional, you have to pay for it anyway.

Nevertheless, the well known “Datakrakens” out there offer awesome SDKs, tech and frameworks for free, without becoming the product yourself.
The best industry tech was made Open Source by several leading companies. They don’t want something in return, hence they even released their stuff under the zlib/MIT/BSD licenses.

The best things in life are free! :smile:

Hi,

Nice point there, but not all are true IMO.

First of all, ussually when someone is providing you a free service, software, etc…, let’s take unity3d as an example, they are stacking on the base software “junk” that make in the end the free software we installed worthy for them. I know unity3d is heavily calling home with lot of metrics about the software created with the free version, and this does not happen (can be disabled) in the paid ones. This is what makes you the product, the service is free, and can be as good as the paid one but you are “paying” for it in another way.

About the “magic” behind binding the Frame Event callback function, I was supposing from your text that cocos2d-x was binding authomatically the callback by name, this is why I was talking about RTTI because signatures are all lost in release. This setFrameEventCallFunc fills the gap of my misunderstanding :D.

Again, thanks for the nice conversation and your patience. People like you are the ones that make this a really great community.

Cheers.

So does CS and cocos2d-x(like cocos console). It has a hidden silent switch, which was discussed in the forum and they promised change/clearing up. But it’s just metric about your PC, not the created software.

Go cocos2d-x/SDL then :wink: It does not make a product out of you :smile:
If you want to avoid metric and “the human product” stuff, stay away from third party SDKs and roll your own stuff.

Ah, I missed your point. Your mystery was about the automatic binding to the implementation/code. My conentration is sometimes lacking cause of “multitasking” :blush:

They would need some sort of reflection in C++ like in Java,
To solve that mystery for now: it seems it isn’t implemented yet. They just pass a nullptr if there is no callback. The Nodes itself are not even implementing the WidgetCallBackHandlerProtocol.

Node* CSLoader::nodeWithFlatBuffersFile(const std::string &fileName)
{
    return nodeWithFlatBuffersFile(fileName, nullptr);
}

Node* CSLoader::createNodeWithFlatBuffersFile(const std::string &filename, const ccNodeLoadCallback &callback)
{
    Node* node = nodeWithFlatBuffersFile(filename, callback);
    
    /* To reconstruct nest node as WidgetCallBackHandlerProtocol. */
    auto callbackHandler = dynamic_cast<WidgetCallBackHandlerProtocol *>(node);
    if (callbackHandler)
    {
        _callbackHandlers.popBack();
        if (_callbackHandlers.empty())
        {
            _rootNode = nullptr;
            CCLOG("Call back handler container has been clear.");
        }
        else
        {
            _rootNode = _callbackHandlers.back();
            CCLOG("after pop back _rootNode name = %s", _rootNode->getName().c_str());
        }
    }
    /**/
    
    return node;
}

Widget* widget = dynamic_cast<Widget*>(node);
if (widget)
{
    std::string callbackName = widget->getCallbackName();
    std::string callbackType = widget->getCallbackType();
                    
    bindCallback(callbackName, callbackType, widget, _rootNode);
}

bool CSLoader::bindCallback(const std::string &callbackName,
                            const std::string &callbackType,
                            cocos2d::ui::Widget *sender,
                            cocos2d::Node *handler)
{
    auto callbackHandler = dynamic_cast<WidgetCallBackHandlerProtocol *>(handler);
    if (callbackHandler) //The handler can handle callback
    {
        if (callbackType == "Click")
        {
            Widget::ccWidgetClickCallback callbackFunc = callbackHandler->onLocateClickCallback(callbackName);
            if (callbackFunc)
            {
                sender->addClickEventListener(callbackFunc);
                return true;
            }
        }
        else if (callbackType == "Touch")
        {
            Widget::ccWidgetTouchCallback callbackFunc = callbackHandler->onLocateTouchCallback(callbackName);
            if (callbackFunc)
            {
                sender->addTouchEventListener(callbackFunc);
                return true;
            }
        }
        else if (callbackType == "Event")
        {
            Widget::ccWidgetEventCallback callbackFunc = callbackHandler->onLocateEventCallback(callbackName);
            if (callbackFunc)
            {
                sender->addCCSEventListener(callbackFunc);
                return true;
            }
        }
    }
    
    CCLOG("callBackName %s cannot be found", callbackName.c_str());
    
    return false;
    
} 

As you can see, it’s just returning a nullptr, if it’s not implemented. None of the widgets is implementing it.

namespace cocostudio {
    
    class CC_STUDIO_DLL WidgetCallBackHandlerProtocol
    {
    public:
        WidgetCallBackHandlerProtocol() {};
        virtual ~WidgetCallBackHandlerProtocol() {};
        
        virtual cocos2d::ui::Widget::ccWidgetTouchCallback onLocateTouchCallback(const std::string &callBackName){ return nullptr; };
        virtual cocos2d::ui::Widget::ccWidgetClickCallback onLocateClickCallback(const std::string &callBackName){ return nullptr; };
        virtual cocos2d::ui::Widget::ccWidgetEventCallback onLocateEventCallback(const std::string &callBackName){ return nullptr; };
    };

}

It suggests it does automatic binding, but it doesn’t. You would have to implement the lookup yourself like in the example:

Widget::ccWidgetTouchCallback CustomRootNode::onLocateTouchCallback(const string &callBackName)
{
    if (callBackName == "onTouch")
    {
        return CC_CALLBACK_2(CustomRootNode::onTouch, this);
    }

    return nullptr;
}

This way you don’t need RTTI/reflection, because you delegate it in the code by hand. It’s just compile-time binding, not runtime-binding.

Thanks! I have to admit, that sometimes I realize that I posted a little BS and have to clean up afterwards :wink:

Hi,

Well I don’t really mind if they call home about my home PC, I have all this stuff disallowed by my firewall. What I can’t stand is logging inside my running game on the different platforms after being released.

On the other hand, I don’t have neither the time nor the energy to create my own framework/engine again… when you get 40’s this kind of things are ussually not he kind of things you want to do. I spent my earlier game programming years making this kind of things thought :slight_smile: (Crazy times).

Cheers.