diff --git a/.rive_head b/.rive_head index 159dc006..61984959 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -9b416a02f6fffdcb2210cbb674ef7d746466e2d1 +62fcec60de0eea68dceb64758f284ef5b5e20c00 diff --git a/include/rive/assets/script_asset.hpp b/include/rive/assets/script_asset.hpp index d624c8c9..8ae0501d 100644 --- a/include/rive/assets/script_asset.hpp +++ b/include/rive/assets/script_asset.hpp @@ -7,6 +7,11 @@ #include "rive/generated/assets/script_asset_base.hpp" #include "rive/simple_array.hpp" #include + +#ifdef WITH_RIVE_SCRIPTING +struct lua_State; +#endif + namespace rive { class Artboard; @@ -24,7 +29,6 @@ enum ScriptProtocol }; #ifdef WITH_RIVE_SCRIPTING -class LuaState; class ScriptAssetImporter; #endif @@ -65,7 +69,7 @@ private: protected: #ifdef WITH_RIVE_SCRIPTING - bool verifyImplementation(ScriptedObject* object, LuaState* luaState); + bool verifyImplementation(ScriptedObject* object, lua_State* state); #endif public: @@ -173,7 +177,7 @@ public: void file(File* value) { m_file = value; } File* file() const { return m_file; } #ifdef WITH_RIVE_SCRIPTING - LuaState* vm(); + lua_State* vm(); void registrationComplete(int ref) override; #endif std::string moduleName() override diff --git a/include/rive/file.hpp b/include/rive/file.hpp index 711e678b..3d9bba3c 100644 --- a/include/rive/file.hpp +++ b/include/rive/file.hpp @@ -20,6 +20,10 @@ #include #include +#ifdef WITH_RIVE_SCRIPTING +struct lua_State; +#endif + /// /// Default namespace for Rive Cpp runtime code. /// @@ -39,7 +43,6 @@ class BindableArtboard; #ifdef WITH_RIVE_SCRIPTING class CPPRuntimeScriptingContext; class ScriptingVM; -class LuaState; #endif /// @@ -177,12 +180,12 @@ public: // we are running in the runtime and should instance our own VMs // and pass them down to the root #ifdef WITH_RIVE_SCRIPTING - void scriptingVM(LuaState* vm) + void scriptingVM(lua_State* vm) { cleanupScriptingVM(); m_luaState = vm; } - LuaState* scriptingVM() + lua_State* scriptingVM() { // For now, if we don't have a vm, create one. In the future, we // may need a way to create multiple vms in parallel @@ -192,6 +195,10 @@ public: } return m_luaState; } +#ifdef WITH_RIVE_TOOLS + void clearScriptingVM() { cleanupScriptingVM(); } + bool hasVM() { return m_luaState != nullptr; } +#endif #endif DataResolver* dataResolver() @@ -270,7 +277,7 @@ private: rcp m_assetLoader; #ifdef WITH_RIVE_SCRIPTING - LuaState* m_luaState = nullptr; + lua_State* m_luaState = nullptr; std::unique_ptr m_scriptingContext; std::unique_ptr m_scriptingVM; void makeScriptingVM(); diff --git a/include/rive/lua/lua_state.hpp b/include/rive/lua/lua_state.hpp index ad4c6e6a..985cc338 100644 --- a/include/rive/lua/lua_state.hpp +++ b/include/rive/lua/lua_state.hpp @@ -9,18 +9,10 @@ namespace rive { class ViewModel; -class LuaState -{ -public: + #ifdef WITH_RIVE_SCRIPTING - - LuaState(lua_State* state) : state(state) {} - ~LuaState() { state = nullptr; } - void initializeData(std::vector&); - - lua_State* state; +void initializeLuaData(lua_State* state, std::vector& viewModels); #endif -}; } // namespace rive #endif \ No newline at end of file diff --git a/include/rive/scripted/scripted_data_converter.hpp b/include/rive/scripted/scripted_data_converter.hpp index 1cdaad44..1b5879f6 100644 --- a/include/rive/scripted/scripted_data_converter.hpp +++ b/include/rive/scripted/scripted_data_converter.hpp @@ -1,8 +1,5 @@ #ifndef _RIVE_SCRIPTED_DATA_CONVERTER_HPP_ #define _RIVE_SCRIPTED_DATA_CONVERTER_HPP_ -#ifdef WITH_RIVE_SCRIPTING -#include "rive/lua/rive_lua_libs.hpp" -#endif #include "rive/generated/scripted/scripted_data_converter_base.hpp" #include "rive/advancing_component.hpp" #include "rive/scripted/scripted_object.hpp" @@ -41,7 +38,7 @@ private: public: ~ScriptedDataConverter(); #ifdef WITH_RIVE_SCRIPTING - bool scriptInit(LuaState* state) override; + bool scriptInit(lua_State* state) override; DataValue* convert(DataValue* value, DataBind* dataBind) override; DataValue* reverseConvert(DataValue* value, DataBind* dataBind) override; #endif diff --git a/include/rive/scripted/scripted_drawable.hpp b/include/rive/scripted/scripted_drawable.hpp index 382c1057..7c5a6c60 100644 --- a/include/rive/scripted/scripted_drawable.hpp +++ b/include/rive/scripted/scripted_drawable.hpp @@ -1,8 +1,5 @@ #ifndef _RIVE_SCRIPTED_DRAWABLE_HPP_ #define _RIVE_SCRIPTED_DRAWABLE_HPP_ -#ifdef WITH_RIVE_SCRIPTING -#include "rive/lua/rive_lua_libs.hpp" -#endif #include "rive/generated/scripted/scripted_drawable_base.hpp" #include "rive/animation/state_machine_instance.hpp" #include "rive/advancing_component.hpp" @@ -24,7 +21,7 @@ class ScriptedDrawable : public ScriptedDrawableBase, { public: #ifdef WITH_RIVE_SCRIPTING - bool scriptInit(LuaState* state) override; + bool scriptInit(lua_State* state) override; #endif void draw(Renderer* renderer) override; void update(ComponentDirt value) override; diff --git a/include/rive/scripted/scripted_layout.hpp b/include/rive/scripted/scripted_layout.hpp index 311aad6f..c5617188 100644 --- a/include/rive/scripted/scripted_layout.hpp +++ b/include/rive/scripted/scripted_layout.hpp @@ -1,8 +1,5 @@ #ifndef _RIVE_SCRIPTED_LAYOUT_HPP_ #define _RIVE_SCRIPTED_LAYOUT_HPP_ -#ifdef WITH_RIVE_SCRIPTING -#include "rive/lua/rive_lua_libs.hpp" -#endif #include "rive/layout/layout_enums.hpp" #include "rive/layout/layout_measure_mode.hpp" #include "rive/generated/scripted/scripted_layout_base.hpp" @@ -19,7 +16,7 @@ private: public: #ifdef WITH_RIVE_SCRIPTING - bool scriptInit(LuaState* luaState) override; + bool scriptInit(lua_State* state) override; #endif Vec2D measureLayout(float width, LayoutMeasureMode widthMode, diff --git a/include/rive/scripted/scripted_object.hpp b/include/rive/scripted/scripted_object.hpp index c4c94ad0..568a1715 100644 --- a/include/rive/scripted/scripted_object.hpp +++ b/include/rive/scripted/scripted_object.hpp @@ -1,8 +1,5 @@ #ifndef _RIVE_SCRIPTED_OBJECT_HPP_ #define _RIVE_SCRIPTED_OBJECT_HPP_ -#ifdef WITH_RIVE_SCRIPTING -#include "rive/lua/rive_lua_libs.hpp" -#endif #include "rive/assets/file_asset_referencer.hpp" #include "rive/assets/script_asset.hpp" #include "rive/custom_property.hpp" @@ -10,6 +7,11 @@ #include "rive/refcnt.hpp" #include "rive/generated/assets/script_asset_base.hpp" #include + +#ifdef WITH_RIVE_SCRIPTING +struct lua_State; +#endif + namespace rive { class Artboard; @@ -26,7 +28,10 @@ protected: int m_context = 0; virtual void disposeScriptInputs(); #ifdef WITH_RIVE_SCRIPTING - LuaState* m_state = nullptr; + lua_State* m_state = nullptr; +#endif +#ifdef WITH_RIVE_TOOLS + bool hasValidVM(); #endif public: @@ -45,8 +50,8 @@ public: virtual void markNeedsUpdate(); virtual DataContext* dataContext() { return nullptr; } #ifdef WITH_RIVE_SCRIPTING - virtual bool scriptInit(LuaState* state); - LuaState* state() { return m_state; } + virtual bool scriptInit(lua_State* state); + lua_State* state() { return m_state; } #endif void scriptDispose(); virtual bool addScriptedDirt(ComponentDirt value, bool recurse = false) = 0; diff --git a/include/rive/scripted/scripted_path_effect.hpp b/include/rive/scripted/scripted_path_effect.hpp index 0ba28520..bc7440b3 100644 --- a/include/rive/scripted/scripted_path_effect.hpp +++ b/include/rive/scripted/scripted_path_effect.hpp @@ -25,7 +25,7 @@ class ScriptedPathEffect : public ScriptedPathEffectBase, { public: #ifdef WITH_RIVE_SCRIPTING - bool scriptInit(LuaState* state) override; + bool scriptInit(lua_State* state) override; #endif void addProperty(CustomProperty* prop) override; StatusCode onAddedClean(CoreContext* context) override; diff --git a/src/assets/script_asset.cpp b/src/assets/script_asset.cpp index b8709522..c6eb4f60 100644 --- a/src/assets/script_asset.cpp +++ b/src/assets/script_asset.cpp @@ -45,9 +45,8 @@ void ScriptInput::initScriptedValue() {} #ifdef WITH_RIVE_SCRIPTING bool OptionalScriptedMethods::verifyImplementation(ScriptedObject* object, - LuaState* luaState) + lua_State* state) { - auto state = luaState->state; lua_pushvalue(state, -1); if (static_cast(rive_lua_pcall(state, 0, 1)) != LUA_OK) { @@ -161,7 +160,7 @@ bool OptionalScriptedMethods::verifyImplementation(ScriptedObject* object, return true; } -LuaState* ScriptAsset::vm() +lua_State* ScriptAsset::vm() { if (m_file == nullptr) { @@ -203,7 +202,8 @@ void ScriptAsset::registrationComplete(int ref) bool ScriptAsset::initScriptedObjectWith(ScriptedObject* object) { #if defined(WITH_RIVE_SCRIPTING) - if (vm() == nullptr) + auto state = vm(); + if (state == nullptr) { return false; } @@ -214,23 +214,22 @@ bool ScriptAsset::initScriptedObjectWith(ScriptedObject* object) name().c_str()); return false; } - auto vmState = vm()->state; - rive_lua_pushRef(vmState, generatorFunctionRef()); + rive_lua_pushRef(state, generatorFunctionRef()); if (!m_initted) { - if (!verifyImplementation(object, vm())) + if (!verifyImplementation(object, state)) { fprintf(stderr, "ScriptAsset failed to verify method implementation %s\n", name().c_str()); - rive_lua_pop(vmState, 1); + rive_lua_pop(state, 1); return false; } m_initted = true; } object->implementedMethods(implementedMethods()); - return object->scriptInit(vm()); + return object->scriptInit(state); #else return false; #endif diff --git a/src/file.cpp b/src/file.cpp index 7720c829..0b7dfac9 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -19,6 +19,7 @@ #include "rive/importers/import_stack.hpp" #ifdef WITH_RIVE_SCRIPTING #include "rive/lua/rive_lua_libs.hpp" +#include "rive/lua/lua_state.hpp" #endif #include "rive/importers/keyed_object_importer.hpp" #include "rive/importers/keyed_property_importer.hpp" @@ -639,16 +640,15 @@ void File::makeScriptingVM() m_scriptingContext = rivestd::make_unique(m_factory); m_scriptingVM = rivestd::make_unique(m_scriptingContext.get()); - m_luaState = new LuaState(m_scriptingVM->state()); - m_luaState->initializeData(m_ViewModels); + m_luaState = m_scriptingVM->state(); + initializeLuaData(m_luaState, m_ViewModels); } void File::cleanupScriptingVM() { + m_luaState = nullptr; if (m_scriptingVM != nullptr) { - delete m_luaState; - m_luaState = nullptr; m_scriptingVM.reset(); m_scriptingContext.reset(); } diff --git a/src/lua/lua_state.cpp b/src/lua/lua_state.cpp index 0cb1338a..0327364c 100644 --- a/src/lua/lua_state.cpp +++ b/src/lua/lua_state.cpp @@ -22,7 +22,8 @@ static int viewmodel_new(lua_State* L) return 1; } -void LuaState::initializeData(std::vector& viewModels) +void rive::initializeLuaData(lua_State* state, + std::vector& viewModels) { if (state) { diff --git a/src/scripted/scripted_data_converter.cpp b/src/scripted/scripted_data_converter.cpp index de0a0195..a499b0e5 100644 --- a/src/scripted/scripted_data_converter.cpp +++ b/src/scripted/scripted_data_converter.cpp @@ -41,7 +41,7 @@ void ScriptedDataConverter::disposeScriptInputs() } #ifdef WITH_RIVE_SCRIPTING -bool ScriptedDataConverter::scriptInit(LuaState* state) +bool ScriptedDataConverter::scriptInit(lua_State* state) { ScriptedObject::scriptInit(state); addScriptedDirt(ComponentDirt::Bindings); @@ -50,34 +50,33 @@ bool ScriptedDataConverter::scriptInit(LuaState* state) bool ScriptedDataConverter::pushDataValue(DataValue* value) { - auto state = m_state->state; // Stack: [self, field, self] if (value->is()) { lua_newrive( - state, - state, + m_state, + m_state, value->as()->value()); } else if (value->is()) { lua_newrive( - state, - state, + m_state, + m_state, value->as()->value()); } else if (value->is()) { lua_newrive( - state, - state, + m_state, + m_state, value->as()->value()); } else if (value->is()) { lua_newrive( - state, - state, + m_state, + m_state, value->as()->value()); } else @@ -94,21 +93,27 @@ DataValue* ScriptedDataConverter::applyConversion(DataValue* value, { return value; } - auto state = m_state->state; + +#ifdef WITH_RIVE_TOOLS + if (!hasValidVM()) + { + return value; + } +#endif // Stack: [] - rive_lua_pushRef(state, m_self); + rive_lua_pushRef(m_state, m_self); // Stack: [self] - lua_getfield(state, -1, method.c_str()); + lua_getfield(m_state, -1, method.c_str()); // Stack: [self, field] - lua_pushvalue(state, -2); + lua_pushvalue(m_state, -2); // Stack: [self, field, self] if (pushDataValue(value)) { // Stack: [self, field, self, ScriptedData] - if (static_cast(rive_lua_pcall(state, 2, 1)) == LUA_OK) + if (static_cast(rive_lua_pcall(m_state, 2, 1)) == LUA_OK) { - auto result = (ScriptedDataValue*)lua_touserdata(state, -1); + auto result = (ScriptedDataValue*)lua_touserdata(m_state, -1); if (result->isNumber()) { storeData(result->dataValue()); @@ -127,12 +132,12 @@ DataValue* ScriptedDataConverter::applyConversion(DataValue* value, } } // Stack: [self, status] or [self, result] - rive_lua_pop(state, 2); + rive_lua_pop(m_state, 2); } else { // Stack: [self, field, self] - rive_lua_pop(state, 3); + rive_lua_pop(m_state, 3); } if (!m_dataValue) { diff --git a/src/scripted/scripted_drawable.cpp b/src/scripted/scripted_drawable.cpp index 5c33a605..cb325e99 100644 --- a/src/scripted/scripted_drawable.cpp +++ b/src/scripted/scripted_drawable.cpp @@ -8,7 +8,7 @@ using namespace rive; #ifdef WITH_RIVE_SCRIPTING -bool ScriptedDrawable::scriptInit(LuaState* state) +bool ScriptedDrawable::scriptInit(lua_State* state) { ScriptedObject::scriptInit(state); addDirt(ComponentDirt::Paint); @@ -17,11 +17,17 @@ bool ScriptedDrawable::scriptInit(LuaState* state) void ScriptedDrawable::draw(Renderer* renderer) { - if (!draws()) + if (!draws() || !m_state) { return; } - auto state = m_state->state; + +#ifdef WITH_RIVE_TOOLS + if (!hasValidVM()) + { + return; + } +#endif if (m_needsSaveOperation) { @@ -38,24 +44,24 @@ void ScriptedDrawable::draw(Renderer* renderer) renderer->transform(worldTransform()); // Stack: [] - auto scriptedRenderer = lua_newrive(state, renderer); + auto scriptedRenderer = lua_newrive(m_state, renderer); // Stack: [scriptedRenderer] - rive_lua_pushRef(state, m_self); + rive_lua_pushRef(m_state, m_self); // Stack: [scriptedRenderer, self] - lua_getfield(state, -1, "draw"); + lua_getfield(m_state, -1, "draw"); // Stack: [scriptedRenderer, self, "draw"] - lua_pushvalue(state, -2); + lua_pushvalue(m_state, -2); // Stack: [scriptedRenderer, self, "draw", self] - lua_pushvalue(state, -4); + lua_pushvalue(m_state, -4); // Stack: [scriptedRenderer, self, "draw", self, scriptedRenderer] - if (static_cast(rive_lua_pcall(state, 2, 0)) != LUA_OK) + if (static_cast(rive_lua_pcall(m_state, 2, 0)) != LUA_OK) { // Stack: [scriptedRenderer, self, status] - rive_lua_pop(state, 1); + rive_lua_pop(m_state, 1); } scriptedRenderer->end(); // Stack: [scriptedRenderer, self] - rive_lua_pop(state, 2); + rive_lua_pop(m_state, 2); if (needsOpacitySave) { @@ -87,8 +93,8 @@ HitResult HitScriptedDrawable::processEvent(Vec2D position, { HitResult hitResult = HitResult::none; auto scriptAsset = m_drawable->scriptAsset(); - auto vm = m_drawable->state(); - if (vm == nullptr || scriptAsset == nullptr || + auto state = m_drawable->state(); + if (state == nullptr || scriptAsset == nullptr || !handlesEvent(canHit, hitType)) { return HitResult::none; @@ -99,7 +105,6 @@ HitResult HitScriptedDrawable::processEvent(Vec2D position, { return hitResult; } - auto state = vm->state; rive_lua_pushRef(state, m_drawable->self()); auto mName = methodName(canHit, hitType); if (static_cast(lua_getfield(state, -1, mName.c_str())) != diff --git a/src/scripted/scripted_layout.cpp b/src/scripted/scripted_layout.cpp index 4f45e4ab..bf6cf21c 100644 --- a/src/scripted/scripted_layout.cpp +++ b/src/scripted/scripted_layout.cpp @@ -8,7 +8,7 @@ using namespace rive; #ifdef WITH_RIVE_SCRIPTING -bool ScriptedLayout::scriptInit(LuaState* state) +bool ScriptedLayout::scriptInit(lua_State* state) { ScriptedDrawable::scriptInit(state); if (parent() != nullptr && parent()->is()) @@ -24,25 +24,24 @@ void ScriptedLayout::callScriptedResize(Vec2D size) { return; } - auto state = m_state->state; - rive_lua_pushRef(state, m_self); - if (static_cast(lua_getfield(state, -1, "resize")) != + rive_lua_pushRef(m_state, m_self); + if (static_cast(lua_getfield(m_state, -1, "resize")) != LUA_TFUNCTION) { fprintf(stderr, "expected resize to be a function\n"); - rive_lua_pop(state, 1); + rive_lua_pop(m_state, 1); } else { - lua_pushvalue(state, -2); - lua_pushvec2d(state, size); - if (static_cast(rive_lua_pcall(state, 2, 0)) != LUA_OK) + lua_pushvalue(m_state, -2); + lua_pushvec2d(m_state, size); + if (static_cast(rive_lua_pcall(m_state, 2, 0)) != LUA_OK) { fprintf(stderr, "resize failed\n"); - rive_lua_pop(state, 1); + rive_lua_pop(m_state, 1); } } - rive_lua_pop(state, 1); + rive_lua_pop(m_state, 1); } Vec2D ScriptedLayout::measureLayout(float width, @@ -56,37 +55,36 @@ Vec2D ScriptedLayout::measureLayout(float width, } auto measuredWidth = std::numeric_limits::max(); auto measuredHeight = std::numeric_limits::max(); - auto state = m_state->state; - rive_lua_pushRef(state, m_self); - if (static_cast(lua_getfield(state, -1, "measure")) != + rive_lua_pushRef(m_state, m_self); + if (static_cast(lua_getfield(m_state, -1, "measure")) != LUA_TFUNCTION) { fprintf(stderr, "expected measure to be a function\n"); - rive_lua_pop(state, 1); + rive_lua_pop(m_state, 1); } else { - lua_pushvalue(state, -2); - if (static_cast(rive_lua_pcall(state, 1, 1)) != LUA_OK) + lua_pushvalue(m_state, -2); + if (static_cast(rive_lua_pcall(m_state, 1, 1)) != LUA_OK) { fprintf(stderr, "measure failed\n"); } else { - if (static_cast(lua_type(state, -1)) != LUA_TVECTOR) + if (static_cast(lua_type(m_state, -1)) != LUA_TVECTOR) { fprintf(stderr, "expected measure to return a Vec2D\n"); } else { - auto size = lua_tovec2d(state, -1); + auto size = lua_tovec2d(m_state, -1); measuredWidth = size->x; measuredHeight = size->y; } } - rive_lua_pop(state, 1); + rive_lua_pop(m_state, 1); } - rive_lua_pop(state, 1); + rive_lua_pop(m_state, 1); return Vec2D(std::min((widthMode == LayoutMeasureMode::undefined ? std::numeric_limits::max() diff --git a/src/scripted/scripted_object.cpp b/src/scripted/scripted_object.cpp index 47304d16..00066b32 100644 --- a/src/scripted/scripted_object.cpp +++ b/src/scripted/scripted_object.cpp @@ -37,16 +37,15 @@ void ScriptedObject::setArtboardInput(std::string name, Artboard* artboard) return; } - auto state = m_state->state; - rive_lua_pushRef(state, m_self); + rive_lua_pushRef(m_state, m_self); auto artboardInstance = artboard->instance(); artboardInstance->frameOrigin(false); - lua_newrive(state, - state, + lua_newrive(m_state, + m_state, ref_rcp(scriptAsset()->file()), std::move(artboardInstance)); - lua_setfield(state, -2, name.c_str()); - rive_lua_pop(state, 1); + lua_setfield(m_state, -2, name.c_str()); + rive_lua_pop(m_state, 1); addScriptedDirt(ComponentDirt::ScriptUpdate); } @@ -56,11 +55,10 @@ void ScriptedObject::setBooleanInput(std::string name, bool value) { return; } - auto state = m_state->state; - rive_lua_pushRef(state, m_self); - lua_pushboolean(state, value); - lua_setfield(state, -2, name.c_str()); - rive_lua_pop(state, 1); + rive_lua_pushRef(m_state, m_self); + lua_pushboolean(m_state, value); + lua_setfield(m_state, -2, name.c_str()); + rive_lua_pop(m_state, 1); addScriptedDirt(ComponentDirt::ScriptUpdate); } @@ -70,11 +68,10 @@ void ScriptedObject::setNumberInput(std::string name, float value) { return; } - auto state = m_state->state; - rive_lua_pushRef(state, m_self); - lua_pushnumber(state, value); - lua_setfield(state, -2, name.c_str()); - rive_lua_pop(state, 1); + rive_lua_pushRef(m_state, m_self); + lua_pushnumber(m_state, value); + lua_setfield(m_state, -2, name.c_str()); + rive_lua_pop(m_state, 1); addScriptedDirt(ComponentDirt::ScriptUpdate); } @@ -84,11 +81,10 @@ void ScriptedObject::setIntegerInput(std::string name, int value) { return; } - auto state = m_state->state; - rive_lua_pushRef(state, m_self); - lua_pushunsigned(state, value); - lua_setfield(state, -2, name.c_str()); - rive_lua_pop(state, 1); + rive_lua_pushRef(m_state, m_self); + lua_pushunsigned(m_state, value); + lua_setfield(m_state, -2, name.c_str()); + rive_lua_pop(m_state, 1); addScriptedDirt(ComponentDirt::ScriptUpdate); } @@ -98,11 +94,10 @@ void ScriptedObject::setStringInput(std::string name, std::string value) { return; } - auto state = m_state->state; - rive_lua_pushRef(state, m_self); - lua_pushstring(state, value.c_str()); - lua_setfield(state, -2, name.c_str()); - rive_lua_pop(state, 1); + rive_lua_pushRef(m_state, m_self); + lua_pushstring(m_state, value.c_str()); + lua_setfield(m_state, -2, name.c_str()); + rive_lua_pop(m_state, 1); addScriptedDirt(ComponentDirt::ScriptUpdate); } @@ -113,8 +108,7 @@ void ScriptedObject::setViewModelInput(std::string name, { return; } - auto state = m_state->state; - rive_lua_pushRef(state, m_self); + rive_lua_pushRef(m_state, m_self); switch (value->coreType()) { case ViewModelInstanceViewModelBase::typeKey: @@ -130,8 +124,8 @@ void ScriptedObject::setViewModelInput(std::string name, return; } - lua_newrive(state, - state, + lua_newrive(m_state, + m_state, ref_rcp(vmi->viewModel()), vmi); break; @@ -139,8 +133,8 @@ void ScriptedObject::setViewModelInput(std::string name, default: break; } - lua_setfield(state, -2, name.c_str()); - rive_lua_pop(state, 1); + lua_setfield(m_state, -2, name.c_str()); + rive_lua_pop(m_state, 1); addScriptedDirt(ComponentDirt::ScriptUpdate); } @@ -150,38 +144,64 @@ void ScriptedObject::trigger(std::string name) { return; } - auto state = m_state->state; - rive_lua_pushRef(state, m_self); - if (static_cast(lua_getfield(state, -1, name.c_str())) != + rive_lua_pushRef(m_state, m_self); + if (static_cast(lua_getfield(m_state, -1, name.c_str())) != LUA_TFUNCTION) { - rive_lua_pop(state, 2); + rive_lua_pop(m_state, 2); return; } - lua_pushvalue(state, -2); - rive_lua_pcall(state, 1, 0); - rive_lua_pop(state, 1); + lua_pushvalue(m_state, -2); + rive_lua_pcall(m_state, 1, 0); + rive_lua_pop(m_state, 1); addScriptedDirt(ComponentDirt::ScriptUpdate); } +#ifdef WITH_RIVE_TOOLS +bool ScriptedObject::hasValidVM() +{ +#ifdef WITH_RIVE_SCRIPTING + if (!m_state) + { + return false; + } + if (asset()) + { + auto scriptAsset = asset()->as(); + if (!scriptAsset->file() || !scriptAsset->file()->hasVM()) + { + m_state = nullptr; + return false; + } + } +#endif + return true; +} +#endif + bool ScriptedObject::scriptAdvance(float elapsedSeconds) { if (!advances() || m_state == nullptr) { return false; } - auto state = m_state->state; - rive_lua_pushRef(state, m_self); - lua_getfield(state, -1, "advance"); - lua_pushvalue(state, -2); - lua_pushnumber(state, elapsedSeconds); - if (static_cast(rive_lua_pcall(state, 2, 1)) != LUA_OK) +#ifdef WITH_RIVE_TOOLS + if (!hasValidVM()) { - rive_lua_pop(state, 2); return false; } - bool result = lua_toboolean(state, -1); - rive_lua_pop(state, 2); +#endif + rive_lua_pushRef(m_state, m_self); + lua_getfield(m_state, -1, "advance"); + lua_pushvalue(m_state, -2); + lua_pushnumber(m_state, elapsedSeconds); + if (static_cast(rive_lua_pcall(m_state, 2, 1)) != LUA_OK) + { + rive_lua_pop(m_state, 2); + return false; + } + bool result = lua_toboolean(m_state, -1); + rive_lua_pop(m_state, 2); return result; } @@ -191,35 +211,39 @@ void ScriptedObject::scriptUpdate() { return; } - auto state = m_state->state; - // Stack: [] - rive_lua_pushRef(state, m_self); - // Stack: [self] - lua_getfield(state, -1, "update"); - // Stack: [self, field] Swap self and field - lua_insert(state, -2); - // Stack: [field, self] - if (static_cast(rive_lua_pcall(state, 1, 0)) != LUA_OK) + +#ifdef WITH_RIVE_TOOLS + if (!hasValidVM()) { - rive_lua_pop(state, 1); + return; + } +#endif + // Stack: [] + rive_lua_pushRef(m_state, m_self); + // Stack: [self] + lua_getfield(m_state, -1, "update"); + // Stack: [self, field] Swap self and field + lua_insert(m_state, -2); + // Stack: [field, self] + if (static_cast(rive_lua_pcall(m_state, 1, 0)) != LUA_OK) + { + rive_lua_pop(m_state, 1); } } -bool ScriptedObject::scriptInit(LuaState* luaState) +bool ScriptedObject::scriptInit(lua_State* state) { - auto state = luaState->state; - // Clean up old references if reinitializing if (m_state != nullptr && (m_self != 0 || m_context != 0)) { if (m_self != 0) { - lua_unref(m_state->state, m_self); + lua_unref(m_state, m_self); m_self = 0; } if (m_context != 0) { - lua_unref(m_state->state, m_context); + lua_unref(m_state, m_context); m_context = 0; } } @@ -251,7 +275,7 @@ bool ScriptedObject::scriptInit(LuaState* luaState) rive_lua_pop(state, 1); // Stack: [self] m_self = lua_ref(state, -1); - m_state = luaState; + m_state = state; for (auto prop : m_customProperties) { auto scriptInput = ScriptInput::from(prop); @@ -332,12 +356,12 @@ void ScriptedObject::scriptDispose() if (m_state != nullptr) { - lua_unref(m_state->state, m_self); - lua_unref(m_state->state, m_context); + lua_unref(m_state, m_self); + lua_unref(m_state, m_context); #ifdef TESTING // Force GC to collect any ScriptedArtboard instances created via // instance() - lua_gc(m_state->state, LUA_GCCOLLECT, 0); + lua_gc(m_state, LUA_GCCOLLECT, 0); #endif } m_state = nullptr; diff --git a/src/scripted/scripted_path_effect.cpp b/src/scripted/scripted_path_effect.cpp index 551ce367..297b9945 100644 --- a/src/scripted/scripted_path_effect.cpp +++ b/src/scripted/scripted_path_effect.cpp @@ -11,7 +11,7 @@ using namespace rive; void ScriptedEffectPath::invalidateEffect() { m_path.rewind(); } #ifdef WITH_RIVE_SCRIPTING -bool ScriptedPathEffect::scriptInit(LuaState* state) +bool ScriptedPathEffect::scriptInit(lua_State* state) { ScriptedObject::scriptInit(state); addScriptedDirt(ComponentDirt::Paint, true); @@ -26,6 +26,13 @@ void ScriptedPathEffect::updateEffect(PathProvider* pathProvider, { return; } + +#ifdef WITH_RIVE_TOOLS + if (!hasValidVM()) + { + return; + } +#endif auto effectPathIt = m_effectPaths.find(pathProvider); if (effectPathIt != m_effectPaths.end()) { @@ -43,35 +50,34 @@ void ScriptedPathEffect::updateEffect(PathProvider* pathProvider, { return; } - auto state = m_state->state; // Stack: [] - rive_lua_pushRef(state, m_self); + rive_lua_pushRef(m_state, m_self); // Stack: [self] - lua_getfield(state, -1, "update"); + lua_getfield(m_state, -1, "update"); // Stack: [self, "update"] - lua_pushvalue(state, -2); + lua_pushvalue(m_state, -2); // Stack: [self, "update", self] - lua_newrive(state, source->rawPath()); + lua_newrive(m_state, source->rawPath()); // Stack: [self, "update", self, pathData] - lua_newrive(state, + lua_newrive(m_state, nullptr, shapePaint->parentTransformComponent()); - auto scriptedNode = lua_torive(state, -1); + auto scriptedNode = lua_torive(m_state, -1); scriptedNode->shapePaint(shapePaint); // Stack: [self, "update", self, pathData, node] - if (static_cast(rive_lua_pcall(state, 3, 1)) != LUA_OK) + if (static_cast(rive_lua_pcall(m_state, 3, 1)) != LUA_OK) { fprintf(stderr, "update function failed\n"); } else { // Stack: [self, outputPathData] - auto scriptedPath = (ScriptedPathData*)lua_touserdata(state, -1); + auto scriptedPath = (ScriptedPathData*)lua_touserdata(m_state, -1); auto rawPath = path->mutableRawPath(); rawPath->addPath(scriptedPath->rawPath); } // Stack: [self, status] or [self, outputPathData] - rive_lua_pop(state, 2); + rive_lua_pop(m_state, 2); } } #else diff --git a/tests/unit_tests/runtime/scripting/scripting_input_test.cpp b/tests/unit_tests/runtime/scripting/scripting_input_test.cpp index 74c22a9f..6d9205f3 100644 --- a/tests/unit_tests/runtime/scripting/scripting_input_test.cpp +++ b/tests/unit_tests/runtime/scripting/scripting_input_test.cpp @@ -513,7 +513,7 @@ end ScriptedDrawable drawable; // Create LuaState from ScriptingTest's VM state - LuaState luaState(L); + lua_State* luaState = L; // Manually set the inits flag since we're not using ScriptAsset // The inits flag indicates that the script has an init function @@ -524,7 +524,7 @@ end // ScriptingTest already left it there, so we can call scriptInit directly // Call ScriptedObject::scriptInit directly to avoid addDirt which requires // an artboard - CHECK(drawable.ScriptedObject::scriptInit(&luaState)); + CHECK(drawable.ScriptedObject::scriptInit(luaState)); // Manually set implemented methods flags since we're not using ScriptAsset // Check if advance function exists and set the flag @@ -597,7 +597,7 @@ end ScriptedLayout layout; // Create LuaState from ScriptingTest's VM state - LuaState luaState(L); + lua_State* luaState = L; // Manually set the inits flag since we're not using ScriptAsset layout.implementedMethods(layout.implementedMethods() | @@ -606,7 +606,7 @@ end // scriptInit expects the factory function on the stack // Call ScriptedObject::scriptInit directly to avoid addDirt which requires // an artboard - CHECK(layout.ScriptedObject::scriptInit(&luaState)); + CHECK(layout.ScriptedObject::scriptInit(luaState)); // Manually set implemented methods flags // After scriptInit, the self table is stored in m_self @@ -708,22 +708,22 @@ end // Create LuaState from ScriptingTest's VM state // Keep it in scope for the entire test since converter stores a pointer to // it - LuaState luaState(L); + lua_State* luaState = L; // Manually set the inits flag since we're not using ScriptAsset converter->implementedMethods(converter->implementedMethods() | (1 << 9)); // m_initsBit // Verify LuaState is valid before using it - REQUIRE(luaState.state != nullptr); - REQUIRE(luaState.state == L); + REQUIRE(luaState != nullptr); + REQUIRE(luaState == L); // scriptInit expects the factory function on the stack // Verify stack state before calling scriptInit REQUIRE(lua_gettop(L) == stackTop); REQUIRE(lua_type(L, -1) == LUA_TFUNCTION); - REQUIRE(converter->ScriptedObject::scriptInit(&luaState)); + REQUIRE(converter->ScriptedObject::scriptInit(luaState)); converter->addScriptedDirt(ComponentDirt::Bindings); // Verify self() is valid before using it