blob: 1ab848df2ec800d69671bb306c94ac7ec7da41d0 [file] [log] [blame]
#include "rive/animation/scripted_transition_condition.hpp"
#include "rive/animation/state_machine_instance.hpp"
#include "rive/importers/state_machine_importer.hpp"
using namespace rive;
ScriptedTransitionCondition::~ScriptedTransitionCondition()
{
disposeScriptInputs();
}
void ScriptedTransitionCondition::disposeScriptInputs()
{
auto props = m_customProperties;
ScriptedObject::disposeScriptInputs();
for (auto prop : props)
{
auto scriptInput = ScriptInput::from(prop);
if (scriptInput != nullptr)
{
// ScriptedDataConverters need to delete their own inputs
// because they are not components
delete scriptInput;
}
}
}
// Note: evaluateStateful is the actual instance of the
// ScriptedTransitionCondition that will run the script. evaluate itself will
// look for the map between the stateless and the stateful instances of this
// class.
bool ScriptedTransitionCondition::evaluateStateful(
const StateMachineInstance* stateMachineInstance,
StateMachineLayerInstance* layerInstance) const
{
bool result = false;
#ifdef WITH_RIVE_SCRIPTING
if (m_state)
{
// Stack: []
rive_lua_pushRef(m_state, m_self);
// Stack: [self]
lua_getfield(m_state, -1, "evaluate");
// Stack: [self, field]
lua_insert(m_state, -2); // Swap self and field
// Stack: [field, self]
if (static_cast<lua_Status>(rive_lua_pcall(m_state, 1, 1)) == LUA_OK)
{
if (lua_isboolean(m_state, -1))
{
result = lua_toboolean(m_state, -1);
}
// Stack: [result]
rive_lua_pop(m_state, 1);
}
else
{
// Stack: [status]
rive_lua_pop(m_state, 1);
}
}
#endif
return result;
}
bool ScriptedTransitionCondition::evaluate(
const StateMachineInstance* stateMachineInstance,
StateMachineLayerInstance* layerInstance) const
{
#ifdef WITH_RIVE_SCRIPTING
auto scriptedObject = stateMachineInstance->scriptedObject(this);
if (scriptedObject != nullptr)
{
auto statefulListenerAction =
static_cast<ScriptedTransitionCondition*>(scriptedObject);
return statefulListenerAction->evaluateStateful(stateMachineInstance,
layerInstance);
}
#endif
return false;
}
StatusCode ScriptedTransitionCondition::import(ImportStack& importStack)
{
auto result = registerReferencer(importStack);
if (result != StatusCode::Ok)
{
return result;
}
auto stateMachineImporter =
importStack.latest<StateMachineImporter>(StateMachine::typeKey);
if (stateMachineImporter == nullptr)
{
return StatusCode::MissingObject;
}
stateMachineImporter->addScriptedObject(this);
return Super::import(importStack);
}
Core* ScriptedTransitionCondition::clone() const
{
ScriptedTransitionCondition* twin = ScriptedTransitionConditionBase::clone()
->as<ScriptedTransitionCondition>();
if (m_fileAsset != nullptr)
{
twin->setAsset(m_fileAsset);
}
return twin;
}
ScriptedObject* ScriptedTransitionCondition::cloneScriptedObject(
DataBindContainer* dataBindContainer) const
{
auto clonedScriptedObject = clone()->as<ScriptedTransitionCondition>();
cloneProperties(clonedScriptedObject, dataBindContainer);
clonedScriptedObject->reinit();
return clonedScriptedObject;
}
void ScriptedTransitionCondition::addProperty(CustomProperty* prop)
{
auto scriptInput = ScriptInput::from(prop);
if (scriptInput != nullptr)
{
scriptInput->scriptedObject(this);
}
CustomPropertyContainer::addProperty(prop);
}