mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 21:21:17 +01:00
feature(scripting): add support for accessing view models and enum pr… (#11437) 620000211e
feature(scripting): add support for accessing view models and enum properties Co-authored-by: hernan <hernan@rive.app>
This commit is contained in:
@@ -1 +1 @@
|
||||
67006966a5ea7000971204e0dd9bc03613f2b9bc
|
||||
620000211e23da8be6c8603bf69f2b4d682817fd
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "rive/math/path_measure.hpp"
|
||||
#include "rive/shapes/paint/image_sampler.hpp"
|
||||
#include "rive/shapes/paint/shape_paint.hpp"
|
||||
#include "rive/viewmodel/data_enum.hpp"
|
||||
#include "rive/viewmodel/viewmodel_instance_boolean.hpp"
|
||||
#include "rive/viewmodel/viewmodel_instance_color.hpp"
|
||||
#include "rive/viewmodel/viewmodel_instance_enum.hpp"
|
||||
@@ -150,6 +151,9 @@ enum class LuaAtoms : int16_t
|
||||
getBoolean,
|
||||
getColor,
|
||||
getList,
|
||||
getViewModel,
|
||||
getEnum,
|
||||
values,
|
||||
addListener,
|
||||
removeListener,
|
||||
fire,
|
||||
@@ -702,6 +706,26 @@ public:
|
||||
void setValue(bool value);
|
||||
};
|
||||
|
||||
class ScriptedEnumValues
|
||||
{
|
||||
public:
|
||||
ScriptedEnumValues(lua_State* L, DataEnum* value) :
|
||||
m_state(L), m_dataEnum(value)
|
||||
{}
|
||||
static constexpr uint8_t luaTag = LUA_T_COUNT + 34;
|
||||
static constexpr const char* luaName = "EnumValues";
|
||||
static constexpr bool hasMetatable = true;
|
||||
void dataEnum(DataEnum* value) { m_dataEnum = value; }
|
||||
int pushValue(int index);
|
||||
int pushLength();
|
||||
|
||||
const lua_State* state() const { return m_state; }
|
||||
|
||||
private:
|
||||
lua_State* m_state = nullptr;
|
||||
DataEnum* m_dataEnum = nullptr;
|
||||
};
|
||||
|
||||
class ScriptedPropertyEnum : public ScriptedProperty
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
#include "rive/viewmodel/viewmodel_property_string.hpp"
|
||||
#include "rive/viewmodel/viewmodel_property_trigger.hpp"
|
||||
#include "rive/viewmodel/viewmodel_property_list.hpp"
|
||||
#include "rive/viewmodel/viewmodel_property_viewmodel.hpp"
|
||||
#include "rive/viewmodel/viewmodel_instance_list.hpp"
|
||||
#include "rive/viewmodel/viewmodel_instance_enum.hpp"
|
||||
#include "rive/viewmodel/viewmodel_instance_list_item.hpp"
|
||||
|
||||
#include <math.h>
|
||||
@@ -16,6 +18,7 @@
|
||||
using namespace rive;
|
||||
|
||||
static void pushViewModelInstanceValue(lua_State* L,
|
||||
rcp<ViewModel> viewModel,
|
||||
ViewModelInstanceValue* propValue)
|
||||
{
|
||||
switch (propValue->coreType())
|
||||
@@ -62,6 +65,13 @@ static void pushViewModelInstanceValue(lua_State* L,
|
||||
L,
|
||||
ref_rcp(propValue->as<ViewModelInstanceEnum>()));
|
||||
break;
|
||||
case ViewModelInstanceViewModelBase::typeKey:
|
||||
lua_newrive<ScriptedPropertyViewModel>(
|
||||
L,
|
||||
L,
|
||||
viewModel,
|
||||
ref_rcp(propValue->as<ViewModelInstanceViewModel>()));
|
||||
break;
|
||||
default:
|
||||
lua_pushnil(L);
|
||||
break;
|
||||
@@ -309,6 +319,12 @@ int ScriptedViewModel::pushValue(const char* name, int coreType)
|
||||
m_state,
|
||||
nullptr);
|
||||
break;
|
||||
case ViewModelPropertyViewModelBase::typeKey:
|
||||
lua_newrive<ScriptedPropertyViewModel>(m_state,
|
||||
m_state,
|
||||
nullptr,
|
||||
nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -322,7 +338,7 @@ int ScriptedViewModel::pushValue(const char* name, int coreType)
|
||||
}
|
||||
else
|
||||
{
|
||||
pushViewModelInstanceValue(m_state, propValue);
|
||||
pushViewModelInstanceValue(m_state, m_viewModel, propValue);
|
||||
}
|
||||
}
|
||||
m_propertyRefs[name] = lua_ref(m_state, -1);
|
||||
@@ -482,6 +498,23 @@ static int property_namecall_atom(lua_State* L,
|
||||
list->addItemAt(listItem, index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case (int)LuaAtoms::values:
|
||||
{
|
||||
auto viewModelInstanceEnum =
|
||||
property->instanceValue()->as<ViewModelInstanceValue>();
|
||||
DataEnum* dataEnum = nullptr;
|
||||
auto viewModelPropertyEnum =
|
||||
viewModelInstanceEnum->viewModelProperty()
|
||||
->as<ViewModelPropertyEnum>();
|
||||
if (viewModelPropertyEnum)
|
||||
{
|
||||
dataEnum = viewModelPropertyEnum->dataEnum();
|
||||
}
|
||||
lua_newrive<ScriptedEnumValues>(L, L, dataEnum);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
error = true;
|
||||
return 0;
|
||||
@@ -542,6 +575,21 @@ static int vm_namecall(lua_State* L)
|
||||
assert(vm->state() == L);
|
||||
return vm->pushValue(name, ViewModelInstanceListBase::typeKey);
|
||||
}
|
||||
case (int)LuaAtoms::getViewModel:
|
||||
{
|
||||
size_t namelen = 0;
|
||||
const char* name = luaL_checklstring(L, 2, &namelen);
|
||||
assert(vm->state() == L);
|
||||
return vm->pushValue(name,
|
||||
ViewModelInstanceViewModelBase::typeKey);
|
||||
}
|
||||
case (int)LuaAtoms::getEnum:
|
||||
{
|
||||
size_t namelen = 0;
|
||||
const char* name = luaL_checklstring(L, 2, &namelen);
|
||||
assert(vm->state() == L);
|
||||
return vm->pushValue(name, ViewModelInstanceEnumBase::typeKey);
|
||||
}
|
||||
case (int)LuaAtoms::instance:
|
||||
case (int)LuaAtoms::newAtom:
|
||||
{
|
||||
@@ -885,6 +933,36 @@ int ScriptedPropertyList::pushValue(int index)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ScriptedEnumValues::pushValue(int index)
|
||||
{
|
||||
if (m_dataEnum && m_state)
|
||||
{
|
||||
auto values = m_dataEnum->values();
|
||||
if (index >= 0 && index < values.size())
|
||||
{
|
||||
auto value = values[index];
|
||||
lua_pushstring(m_state, value->key().c_str());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
lua_pushnil(m_state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ScriptedEnumValues::pushLength()
|
||||
{
|
||||
|
||||
if (m_dataEnum)
|
||||
{
|
||||
lua_pushinteger(m_state, (int)m_dataEnum->values().size());
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pushinteger(m_state, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int property_list_index(lua_State* L)
|
||||
{
|
||||
int atom;
|
||||
@@ -907,6 +985,27 @@ static int property_list_index(lua_State* L)
|
||||
}
|
||||
}
|
||||
|
||||
static int enum_value_length(lua_State* L)
|
||||
{
|
||||
auto enumValues = lua_torive<ScriptedEnumValues>(L, 1);
|
||||
assert(enumValues->state() == L);
|
||||
return enumValues->pushLength();
|
||||
}
|
||||
|
||||
static int enum_value_index(lua_State* L)
|
||||
{
|
||||
int atom;
|
||||
const char* key = lua_tostringatom(L, 2, &atom);
|
||||
auto enumValues = lua_torive<ScriptedEnumValues>(L, 1);
|
||||
// if it's not an atom it should be an index into the array
|
||||
if (!key)
|
||||
{
|
||||
int index = luaL_checkinteger(L, 2);
|
||||
return enumValues->pushValue(index - 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int property_number_index(lua_State* L)
|
||||
{
|
||||
int atom;
|
||||
@@ -1266,6 +1365,19 @@ int luaopen_rive_properties(lua_State* L)
|
||||
lua_pop(L, 1); // pop the metatable
|
||||
}
|
||||
|
||||
{
|
||||
lua_register_rive<ScriptedEnumValues>(L);
|
||||
|
||||
lua_pushcfunction(L, enum_value_index, nullptr);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, enum_value_length, nullptr);
|
||||
lua_setfield(L, -2, "__len");
|
||||
|
||||
lua_setreadonly(L, -1, true);
|
||||
lua_pop(L, 1); // pop the metatable
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -96,6 +96,9 @@ std::unordered_map<std::string, int16_t> atoms = {
|
||||
{"getBoolean", (int16_t)LuaAtoms::getBoolean},
|
||||
{"getColor", (int16_t)LuaAtoms::getColor},
|
||||
{"getList", (int16_t)LuaAtoms::getList},
|
||||
{"getViewModel", (int16_t)LuaAtoms::getViewModel},
|
||||
{"getEnum", (int16_t)LuaAtoms::getEnum},
|
||||
{"values", (int16_t)LuaAtoms::values},
|
||||
{"addListener", (int16_t)LuaAtoms::addListener},
|
||||
{"removeListener", (int16_t)LuaAtoms::removeListener},
|
||||
{"fire", (int16_t)LuaAtoms::fire},
|
||||
|
||||
BIN
tests/unit_tests/assets/viewmodel_access.riv
Normal file
BIN
tests/unit_tests/assets/viewmodel_access.riv
Normal file
Binary file not shown.
@@ -551,4 +551,27 @@ end
|
||||
CHECK(vm.console[5] ==
|
||||
std::string("enum changed to ") + std::string("red"));
|
||||
CHECK(vm.console[6] == std::string("enum is ") + std::string("red"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Access view model properties and enum properties", "[silver]")
|
||||
{
|
||||
SerializingFactory silver;
|
||||
auto file = ReadRiveFile("assets/viewmodel_access.riv", &silver);
|
||||
|
||||
auto artboard = file->artboardDefault();
|
||||
silver.frameSize(artboard->width(), artboard->height());
|
||||
|
||||
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);
|
||||
auto renderer = silver.makeRenderer();
|
||||
stateMachine->advanceAndApply(0.016f);
|
||||
artboard->draw(renderer.get());
|
||||
|
||||
CHECK(silver.matches("viewmodel_access"));
|
||||
}
|
||||
|
||||
BIN
tests/unit_tests/silvers/viewmodel_access.sriv
Normal file
BIN
tests/unit_tests/silvers/viewmodel_access.sriv
Normal file
Binary file not shown.
Reference in New Issue
Block a user