Callbacks for start and end of motion playback (Native)

Updated: 12/19/2024

Summary

Cubism SDK for Native allows callbacks to retrieve events at the start and end of motion playback.

In the sample, the callback function outputs log text notifying the user of the start and end of playback.

Callback Implementation

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class ACubismMotion
{
public:
// Definition of the motion playback start callback function
typedef void (*BeganMotionCallback)(ACubismMotion* self);
// Definition of the motion playback end callback function
typedef void (*FinishedMotionCallback)(ACubismMotion* self);
// Register motion playback start callback
void SetBeganMotionHandler(BeganMotionCallback onBeganMotionHandler);
// Register motion playback end callback
void SetFinishedMotionHandler(FinishedMotionCallback onFinishedMotionHandler);
// Obtain motion playback start callback
BeganMotionCallback GetBeganMotionHandler() const;
// Obtain motion playback end callback
FinishedMotionCallback GetFinishedMotionHandler();
private:
// Variable that contains the callback function to be called when motion playback starts
BeganMotionCallback _onBeganMotion;
// Variable that contains the callback function to be called when motion playback ends
FinishedMotionCallback _onFinishedMotion;
};
class ACubismMotion { public: // Definition of the motion playback start callback function typedef void (*BeganMotionCallback)(ACubismMotion* self); // Definition of the motion playback end callback function typedef void (*FinishedMotionCallback)(ACubismMotion* self); ・ ・ ・ // Register motion playback start callback void SetBeganMotionHandler(BeganMotionCallback onBeganMotionHandler); // Register motion playback end callback void SetFinishedMotionHandler(FinishedMotionCallback onFinishedMotionHandler); // Obtain motion playback start callback BeganMotionCallback GetBeganMotionHandler() const; // Obtain motion playback end callback FinishedMotionCallback GetFinishedMotionHandler(); ・ ・ ・ private: // Variable that contains the callback function to be called when motion playback starts BeganMotionCallback _onBeganMotion; // Variable that contains the callback function to be called when motion playback ends FinishedMotionCallback _onFinishedMotion; };
class ACubismMotion
{
public:
    // Definition of the motion playback start callback function
    typedef void (*BeganMotionCallback)(ACubismMotion* self);

    // Definition of the motion playback end callback function
    typedef void (*FinishedMotionCallback)(ACubismMotion* self);
    ・
    ・
    ・
    // Register motion playback start callback
    void SetBeganMotionHandler(BeganMotionCallback onBeganMotionHandler);

    // Register motion playback end callback
    void SetFinishedMotionHandler(FinishedMotionCallback onFinishedMotionHandler);

    // Obtain motion playback start callback
    BeganMotionCallback GetBeganMotionHandler() const;

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

private:
    // Variable that contains the callback function to be called when motion playback starts
    BeganMotionCallback _onBeganMotion;

    // 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.

The sample uses LAppPal::PrintLog() to output log text notifying the user of the start and end of motion playback.
To change the processing at the start and end of motion playback, change the implementation of the following functions.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
void BeganMotion(ACubismMotion* self)
{
LAppPal::PrintLog("Motion Began: %x", self);
}
void FinishedMotion(ACubismMotion* self)
{
LAppPal::PrintLog("Motion Finished: %x", self);
}
void BeganMotion(ACubismMotion* self) { LAppPal::PrintLog("Motion Began: %x", self); } void FinishedMotion(ACubismMotion* self) { LAppPal::PrintLog("Motion Finished: %x", self); }
void BeganMotion(ACubismMotion* self)
{
   LAppPal::PrintLog("Motion Began: %x", self);
}

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 motion is already present, SetBeganMotionHandler() and SetFinishedMotionHandler(), introduced in “Callback Implementation,” are used.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler)
{
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, onBeganMotionHandler));
}
else
{
motion->SetBeganMotionHandler(onBeganMotionHandler);
motion->SetFinishedMotionHandler(onFinishedMotionHandler);
}
}
CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler) { ・ ・ ・ 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, onBeganMotionHandler)); ・ ・ ・ } else { motion->SetBeganMotionHandler(onBeganMotionHandler); motion->SetFinishedMotionHandler(onFinishedMotionHandler); } }
CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt32 no, csmInt32 priority, ACubismMotion::FinishedMotionCallback onFinishedMotionHandler, ACubismMotion::BeganMotionCallback onBeganMotionHandler)
{
    ・
    ・
    ・
    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, onBeganMotionHandler));
        ・
        ・
        ・
    }
    else
    {
        motion->SetBeganMotionHandler(onBeganMotionHandler);
        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 allows the callback function to be passed to CubismMotion.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
CubismMotion* CubismMotion::Create(const csmByte* buffer, csmSizeInt size, FinishedMotionCallback onFinishedMotionHandler, BeganMotionCallback onBeganMotionHandler)
{
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;
ret->_onBeganMotion = onBeganMotionHandler;
}
CubismMotion* CubismMotion::Create(const csmByte* buffer, csmSizeInt size, FinishedMotionCallback onFinishedMotionHandler, BeganMotionCallback onBeganMotionHandler) { 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; ret->_onBeganMotion = onBeganMotionHandler; }
CubismMotion* CubismMotion::Create(const csmByte* buffer, csmSizeInt size, FinishedMotionCallback onFinishedMotionHandler, BeganMotionCallback onBeganMotionHandler)
{
    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;
    ret->_onBeganMotion = onBeganMotionHandler;
}

On the Development of Implementation

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

Was this article helpful?
YesNo
Please let us know what you think about this article.