Callback for End of Motion Playback (Native)

Updated: 01/30/2020

Summary

Cubism SDK for Native allows callbacks to retrieve events when motion playback ends.

In the sample, the callback function outputs log text to notify of the end of playback.

Callback Implementation

In order to use callbacks when motion playback ends, callbacks have been implemented in Framework/src/Motion/ACubismMotion, an abstract class that manages motion.

class ACubismMotion
{
public:
    // Definition of the motion playback end callback function
    typedef void (*FinishedMotionCallback)(ACubismMotion* self);
    ・
    ・
    ・
    // Register motion playback end callback
    void SetFinishedMotionHandler(FinishedMotionCallback onFinishedMotionHandler);

    // Obtain motion playback end callback
    FinishedMotionCallback GetFinishedMotionHandler();
    ・
    ・
    ・

private:
    // Variable that contains the callback function to be called when motion playback ends
    FinishedMotionCallback _onFinishedMotion;
};
Tips

Please note that in the sample, callbacks cannot be invoked under the following conditions.

  • When the motion being played is set as “looping”
  • When NULL is registered in the callback

Use Callback Functions

Implement what you actually want to be processed in the callback function.

In the sample, log text notifying of the end of motion playback is implemented to be output using LAppPal::PrintLog(). 
To change the processing at the end of motion playback, change the implementation of the following function.

void FinishedMotion(ACubismMotion* self)
{
   LAppPal::PrintLog("Motion Finished: %x", self);
}

The callback function is registered when CubismUserMotion::LoadMotion() is used in the Framework layer to load motion data, and the callback function is passed at the same time the motion is generated.
When there is already a motion, SetFinishedMotionHandler() introduced in “Callback Implementation” is used.

CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler)
{
    ・
    ・
    ・
    if (motion == NULL)
    {
        csmString path = fileName;
        path = _modelHomeDir + path;

        csmByte* buffer;
        csmSizeInt size;
        buffer = CreateBuffer(path.GetRawString(), &size);
        // Register motion data by passing a callback function at the same time it is loaded.
        motion = static_cast<CubismMotion*>(LoadMotion(buffer, size, NULL, onFinishedMotionHandler));
        ・
        ・
        ・
    }
    else
    {
        motion->SetFinishedMotionHandler(onFinishedMotionHandler);
    }
}

In the sample, the callback function is passed fromStartRandomMotion(), which is called when OnTap() is executed to obtain the tap event.

In addition, since CubismMotion::DoUpdateParameters() is actually playing back the motion, the implementation is made so that the callback function can be passed to CubismMotion.

CubismMotion* CubismMotion::Create(const csmByte* buffer, csmSizeInt size, FinishedMotionCallback onFinishedMotionHandler)
{
    CubismMotion* ret = CSM_NEW CubismMotion();

    ret->Parse(buffer, size);
    ret->_sourceFrameRate = ret->_motionData->Fps;
    ret->_loopDurationSeconds = ret->_motionData->Duration;
    // Register callback functions
    ret->_onFinishedMotion = onFinishedMotionHandler;
}

On the Development of Implementation

In the sample, only the end of motion playback is implemented, but by developing the implementation, asynchronous processing can be used in callback functions after motion playback is finished. Alternately, by reversing the function from the actual process to which the callback is to be applied, callbacks can be implemented at points other than the end of motion playback.

Please let us know what you think about this article.