Scripting namespaces (#11429) f810efd11a

Co-authored-by: Philip Chung <philterdesign@gmail.com>
This commit is contained in:
philter
2026-01-12 17:55:36 +00:00
parent a45d0a411d
commit c5fdfdb3d7
8 changed files with 102 additions and 2 deletions

View File

@@ -1 +1 @@
48d14f1521d7d1d7b7dc6095f3eadc1044033f5c
f810efd11a9d5339e0df76c31016819c5ea8e1ba

View File

@@ -48,6 +48,25 @@
"string": "ismodule"
},
"description": "Whether the script is a module (doesn't implement a protocol like Node, Layout, etc."
},
"folderPath": {
"type": "String",
"initialValue": "''",
"key": {
"int": 926,
"string": "folderpath"
},
"description": "Asset panel folder hierarchy that this ScriptAsset exists in. This is also used as the namespace for the Script when registering it"
},
"dependencyIds": {
"type": "List<Id>",
"initialValue": "[]",
"key": {
"int": 927,
"string": "dependencyids"
},
"description": "Ids of any scripts this script requires",
"runtime": false
}
}
}

View File

@@ -176,7 +176,10 @@ public:
LuaState* vm();
void registrationComplete(int ref) override;
#endif
std::string moduleName() override { return name(); }
std::string moduleName() override
{
return folderPath() == "" ? name() : folderPath() + "/" + name();
}
bool isProtocolScript() override { return !isModule(); }
private:

View File

@@ -1,7 +1,9 @@
#ifndef _RIVE_SCRIPT_ASSET_BASE_HPP_
#define _RIVE_SCRIPT_ASSET_BASE_HPP_
#include <string>
#include "rive/assets/file_asset.hpp"
#include "rive/core/field_types/core_bool_type.hpp"
#include "rive/core/field_types/core_string_type.hpp"
#include "rive/core/field_types/core_uint_type.hpp"
namespace rive
{
@@ -32,10 +34,12 @@ public:
static const uint16_t generatorFunctionRefPropertyKey = 893;
static const uint16_t isModulePropertyKey = 914;
static const uint16_t folderPathPropertyKey = 926;
protected:
uint32_t m_GeneratorFunctionRef = 0;
bool m_IsModule = false;
std::string m_FolderPath = "";
public:
inline uint32_t generatorFunctionRef() const
@@ -63,11 +67,23 @@ public:
isModuleChanged();
}
inline const std::string& folderPath() const { return m_FolderPath; }
void folderPath(std::string value)
{
if (m_FolderPath == value)
{
return;
}
m_FolderPath = value;
folderPathChanged();
}
Core* clone() const override;
void copy(const ScriptAssetBase& object)
{
m_GeneratorFunctionRef = object.m_GeneratorFunctionRef;
m_IsModule = object.m_IsModule;
m_FolderPath = object.m_FolderPath;
FileAsset::copy(object);
}
@@ -81,6 +97,9 @@ public:
case isModulePropertyKey:
m_IsModule = CoreBoolType::deserialize(reader);
return true;
case folderPathPropertyKey:
m_FolderPath = CoreStringType::deserialize(reader);
return true;
}
return FileAsset::deserialize(propertyKey, reader);
}
@@ -88,6 +107,7 @@ public:
protected:
virtual void generatorFunctionRefChanged() {}
virtual void isModuleChanged() {}
virtual void folderPathChanged() {}
};
} // namespace rive

View File

@@ -1598,6 +1598,9 @@ public:
case FileAssetBase::cdnBaseUrlPropertyKey:
object->as<FileAssetBase>()->cdnBaseUrl(value);
break;
case ScriptAssetBase::folderPathPropertyKey:
object->as<ScriptAssetBase>()->folderPath(value);
break;
}
}
static void setColor(Core* object, int propertyKey, int value)
@@ -3017,6 +3020,8 @@ public:
return object->as<AssetBase>()->name();
case FileAssetBase::cdnBaseUrlPropertyKey:
return object->as<FileAssetBase>()->cdnBaseUrl();
case ScriptAssetBase::folderPathPropertyKey:
return object->as<ScriptAssetBase>()->folderPath();
}
return "";
}
@@ -3852,6 +3857,7 @@ public:
case TextValueRunBase::textPropertyKey:
case AssetBase::namePropertyKey:
case FileAssetBase::cdnBaseUrlPropertyKey:
case ScriptAssetBase::folderPathPropertyKey:
return CoreStringType::id;
case ViewModelInstanceColorBase::propertyValuePropertyKey:
case CustomPropertyColorBase::propertyValuePropertyKey:
@@ -4632,6 +4638,8 @@ public:
return object->is<AssetBase>();
case FileAssetBase::cdnBaseUrlPropertyKey:
return object->is<FileAssetBase>();
case ScriptAssetBase::folderPathPropertyKey:
return object->is<ScriptAssetBase>();
case ViewModelInstanceColorBase::propertyValuePropertyKey:
return object->is<ViewModelInstanceColorBase>();
case CustomPropertyColorBase::propertyValuePropertyKey:

Binary file not shown.

View File

@@ -182,4 +182,54 @@ TEST_CASE(
CHECK(silver.matches(
"script_converter_with_dependency_with_library_with_update"));
}
// This test file uses 4 scripts in the following hierarchy:
// - rive
// - stringutil
// - StringReverse
// - StringPrefix
// - StringUpperCase
// - converter
// - StringConverter
// These scripts must have their full qualified namespace included in the
// require For example: require('rive/stringutil/StringReverse')
TEST_CASE("scripted data converter string with namespaced requires", "[silver]")
{
rive::SerializingFactory silver;
auto file = ReadRiveFile("assets/script_namespace_test.riv", &silver);
auto artboard = file->artboardNamed("Artboard");
silver.frameSize(artboard->width(), artboard->height());
REQUIRE(artboard != nullptr);
auto stateMachine = artboard->stateMachineAt(0);
int viewModelId = artboard.get()->viewModelId();
auto vmi = viewModelId == -1
? file->createViewModelInstance(artboard.get())
: file->createViewModelInstance(viewModelId, 0);
stateMachine->bindViewModelInstance(vmi);
stateMachine->advanceAndApply(0.1f);
auto renderer = silver.makeRenderer();
artboard->draw(renderer.get());
rive::ViewModelInstanceString* str =
vmi->propertyValue("InputString")->as<rive::ViewModelInstanceString>();
REQUIRE(str != nullptr);
std::vector<std::string> values = {"Hello world!",
"1,2,3",
"rive scripting",
"testing testing testing",
"Script Data Converter"};
for (int i = 0; i < values.size(); i++)
{
str->propertyValue(values[i]);
silver.addFrame();
stateMachine->advanceAndApply(0.016f);
artboard->draw(renderer.get());
}
CHECK(silver.matches("script_namespace_test"));
}

Binary file not shown.