mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 21:21:17 +01:00
chore: Pass Lua VM from editor when decoding runtime File (#11458) f57124001d
The C++ runtime requires a ScriptingVM and lua_State to run scripts. Previously when a runtime File was built, we would always instance a ScriptingVM and lua_State. At runtime, this is required, however, when building the runtime in the editor, this resulted in additional objects being created that weren't needed. This PR passes the lua_State into File::import so that the file will only create the ScriptingVM once and either use the passed in lua_State or instance a new one if none is passed. Co-authored-by: Philip Chung <philterdesign@gmail.com>
This commit is contained in:
@@ -1 +1 @@
|
||||
f3a89390cb428a5ea841d21de91f9cb2adc312df
|
||||
f57124001d4ee388c32a3ec0cd08e292fafc268d
|
||||
|
||||
@@ -86,15 +86,17 @@ public:
|
||||
static rcp<File> import(Span<const uint8_t> data,
|
||||
Factory* factory,
|
||||
ImportResult* result = nullptr,
|
||||
FileAssetLoader* assetLoader = nullptr)
|
||||
FileAssetLoader* assetLoader = nullptr,
|
||||
void* vm = nullptr)
|
||||
{
|
||||
return import(data, factory, result, ref_rcp(assetLoader));
|
||||
return import(data, factory, result, ref_rcp(assetLoader), vm);
|
||||
}
|
||||
|
||||
static rcp<File> import(Span<const uint8_t> data,
|
||||
Factory*,
|
||||
ImportResult* result,
|
||||
rcp<FileAssetLoader> assetLoader);
|
||||
rcp<FileAssetLoader> assetLoader,
|
||||
void* vm = nullptr);
|
||||
|
||||
/// @returns the file's backboard. All files have exactly one backboard.
|
||||
Backboard* backboard() const { return m_backboard; }
|
||||
@@ -180,21 +182,8 @@ 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(lua_State* vm)
|
||||
{
|
||||
cleanupScriptingVM();
|
||||
m_luaState = vm;
|
||||
}
|
||||
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
|
||||
if (m_luaState == nullptr)
|
||||
{
|
||||
makeScriptingVM();
|
||||
}
|
||||
return m_luaState;
|
||||
}
|
||||
void scriptingState(lua_State* vm) { m_luaState = vm; }
|
||||
lua_State* scriptingState() { return m_luaState; }
|
||||
#ifdef WITH_RIVE_TOOLS
|
||||
void clearScriptingVM() { cleanupScriptingVM(); }
|
||||
bool hasVM() { return m_luaState != nullptr; }
|
||||
@@ -280,7 +269,7 @@ private:
|
||||
lua_State* m_luaState = nullptr;
|
||||
std::unique_ptr<CPPRuntimeScriptingContext> m_scriptingContext;
|
||||
std::unique_ptr<ScriptingVM> m_scriptingVM;
|
||||
void makeScriptingVM();
|
||||
void makeScriptingVM(lua_State* existingState = nullptr);
|
||||
void cleanupScriptingVM();
|
||||
void registerScripts();
|
||||
#endif
|
||||
|
||||
@@ -860,6 +860,7 @@ class ScriptingVM
|
||||
{
|
||||
public:
|
||||
ScriptingVM(ScriptingContext* context);
|
||||
ScriptingVM(ScriptingContext* context, lua_State* existingState);
|
||||
~ScriptingVM();
|
||||
|
||||
// ScriptingContext& context() { return m_context; }
|
||||
@@ -895,6 +896,7 @@ public:
|
||||
private:
|
||||
lua_State* m_state;
|
||||
ScriptingContext* m_context;
|
||||
bool m_ownsState;
|
||||
};
|
||||
|
||||
class ScriptedDataValue
|
||||
|
||||
@@ -169,7 +169,7 @@ lua_State* ScriptAsset::vm()
|
||||
}
|
||||
// We get the scripting VM from File for now, however,
|
||||
// this will need to change if/when we support multiple VMs
|
||||
return m_file->scriptingVM();
|
||||
return m_file->scriptingState();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
58
src/file.cpp
58
src/file.cpp
@@ -234,7 +234,8 @@ File::~File()
|
||||
rcp<File> File::import(Span<const uint8_t> bytes,
|
||||
Factory* factory,
|
||||
ImportResult* result,
|
||||
rcp<FileAssetLoader> assetLoader)
|
||||
rcp<FileAssetLoader> assetLoader,
|
||||
void* vm)
|
||||
{
|
||||
BinaryReader reader(bytes);
|
||||
RuntimeHeader header;
|
||||
@@ -262,6 +263,12 @@ rcp<File> File::import(Span<const uint8_t> bytes,
|
||||
return nullptr;
|
||||
}
|
||||
auto file = make_rcp<File>(factory, std::move(assetLoader));
|
||||
#ifdef WITH_RIVE_SCRIPTING
|
||||
if (vm != nullptr)
|
||||
{
|
||||
file->scriptingState(static_cast<lua_State*>(vm));
|
||||
}
|
||||
#endif
|
||||
|
||||
auto readResult = file->read(reader, header);
|
||||
if (result)
|
||||
@@ -609,39 +616,54 @@ ImportResult File::read(BinaryReader& reader, const RuntimeHeader& header)
|
||||
#ifdef WITH_RIVE_SCRIPTING
|
||||
void File::registerScripts()
|
||||
{
|
||||
if (m_scriptingVM == nullptr)
|
||||
{
|
||||
makeScriptingVM();
|
||||
}
|
||||
|
||||
// Add all scripts to the VM for registration
|
||||
// Check if we have any script assets in the file
|
||||
std::vector<ScriptAsset*> scripts;
|
||||
for (auto asset : m_fileAssets)
|
||||
{
|
||||
if (asset->is<ScriptAsset>())
|
||||
{
|
||||
ScriptAsset* scriptAsset = asset->as<ScriptAsset>();
|
||||
// At runtime, generatorFunctionRef should be 0, meaning
|
||||
// it hasn't been registered yet with a VM.
|
||||
scripts.push_back(asset->as<ScriptAsset>());
|
||||
}
|
||||
}
|
||||
// Only make the ScriptingVM if we have any script assets
|
||||
if (!scripts.empty())
|
||||
{
|
||||
makeScriptingVM(scriptingState());
|
||||
for (auto scriptAsset : scripts)
|
||||
{
|
||||
// At runtime, if the script is verified, add it to be
|
||||
// registered with the VM. At edit time, the script will
|
||||
// have already been registered, so this won't run
|
||||
if (scriptAsset->verified())
|
||||
{
|
||||
m_scriptingVM->addModule(scriptAsset);
|
||||
}
|
||||
}
|
||||
// Perform registration - ScriptingContext will handle dependencies and
|
||||
// retries
|
||||
m_scriptingVM->performRegistration();
|
||||
}
|
||||
|
||||
// Perform registration - ScriptingContext will handle dependencies and
|
||||
// retries
|
||||
m_scriptingVM->performRegistration();
|
||||
}
|
||||
|
||||
void File::makeScriptingVM()
|
||||
void File::makeScriptingVM(lua_State* existingState)
|
||||
{
|
||||
cleanupScriptingVM();
|
||||
m_scriptingContext =
|
||||
rivestd::make_unique<CPPRuntimeScriptingContext>(m_factory);
|
||||
m_scriptingVM = rivestd::make_unique<ScriptingVM>(m_scriptingContext.get());
|
||||
m_luaState = m_scriptingVM->state();
|
||||
initializeLuaData(m_luaState, m_ViewModels);
|
||||
if (existingState != nullptr)
|
||||
{
|
||||
m_scriptingVM =
|
||||
rivestd::make_unique<ScriptingVM>(m_scriptingContext.get(),
|
||||
existingState);
|
||||
m_luaState = existingState;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_scriptingVM =
|
||||
rivestd::make_unique<ScriptingVM>(m_scriptingContext.get());
|
||||
m_luaState = m_scriptingVM->state();
|
||||
initializeLuaData(m_luaState, m_ViewModels);
|
||||
}
|
||||
}
|
||||
|
||||
void File::cleanupScriptingVM()
|
||||
|
||||
@@ -342,13 +342,24 @@ void ScriptingVM::init(lua_State* state, ScriptingContext* context)
|
||||
luaL_sandboxthread(state);
|
||||
}
|
||||
|
||||
ScriptingVM::ScriptingVM(ScriptingContext* context) : m_context(context)
|
||||
ScriptingVM::ScriptingVM(ScriptingContext* context) :
|
||||
m_context(context), m_ownsState(true)
|
||||
{
|
||||
m_state = lua_newstate(l_alloc, nullptr);
|
||||
init(m_state, m_context);
|
||||
}
|
||||
|
||||
ScriptingVM::~ScriptingVM() { lua_close(m_state); }
|
||||
ScriptingVM::ScriptingVM(ScriptingContext* context, lua_State* existingState) :
|
||||
m_state(existingState), m_context(context), m_ownsState(false)
|
||||
{}
|
||||
|
||||
ScriptingVM::~ScriptingVM()
|
||||
{
|
||||
if (m_ownsState)
|
||||
{
|
||||
lua_close(m_state);
|
||||
}
|
||||
}
|
||||
|
||||
static int register_module(lua_State* L)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user