mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 21:21:17 +01:00
feature: add scripted nodes! (#10949) 6a61e45ac0
Co-authored-by: Luigi Rosso <luigi-rosso@users.noreply.github.com>
This commit is contained in:
@@ -1 +1 @@
|
||||
45400d839868605fe8df6b794ce4e481affb1881
|
||||
6a61e45ac0cbfe32bf249d904c42b698a9cd91b0
|
||||
|
||||
@@ -150,8 +150,18 @@ enum class LuaAtoms : int16_t
|
||||
// inputs
|
||||
hit,
|
||||
id,
|
||||
position
|
||||
position,
|
||||
|
||||
// nodes
|
||||
rotation,
|
||||
scale,
|
||||
worldTransform,
|
||||
scaleX,
|
||||
scaleY,
|
||||
decompose,
|
||||
children,
|
||||
parent,
|
||||
node
|
||||
};
|
||||
|
||||
struct ScriptedMat2D
|
||||
@@ -352,40 +362,58 @@ private:
|
||||
uint32_t m_saveCount = 0;
|
||||
};
|
||||
|
||||
class ScriptedArtboard
|
||||
class ScriptReffedArtboard : public RefCnt<ScriptReffedArtboard>
|
||||
{
|
||||
public:
|
||||
ScriptedArtboard(rcp<File> file,
|
||||
std::unique_ptr<ArtboardInstance>&& artboardInstance);
|
||||
|
||||
~ScriptedArtboard()
|
||||
{
|
||||
// Make sure artboard is deleted before file.
|
||||
m_artboard = nullptr;
|
||||
m_file = nullptr;
|
||||
}
|
||||
|
||||
static constexpr uint8_t luaTag = LUA_T_COUNT + 10;
|
||||
static constexpr const char* luaName = "Artboard";
|
||||
static constexpr bool hasMetatable = true;
|
||||
ScriptReffedArtboard(rcp<File> file,
|
||||
std::unique_ptr<ArtboardInstance>&& artboardInstance);
|
||||
|
||||
~ScriptReffedArtboard();
|
||||
rive::rcp<rive::File> file() { return m_file; }
|
||||
Artboard* artboard() { return m_artboard.get(); }
|
||||
int pushData(lua_State* L);
|
||||
int instance(lua_State* L);
|
||||
|
||||
bool advance(float seconds);
|
||||
StateMachineInstance* stateMachine() { return m_stateMachine.get(); }
|
||||
rcp<ViewModelInstance> viewModelInstance() { return m_viewModelInstance; }
|
||||
|
||||
private:
|
||||
rcp<File> m_file;
|
||||
std::unique_ptr<ArtboardInstance> m_artboard;
|
||||
std::unique_ptr<StateMachineInstance> m_stateMachine;
|
||||
rcp<ViewModelInstance> m_viewModelInstance;
|
||||
int m_dataRef = 0;
|
||||
// std::vector<WrappedDataBind*> m_dataBinds;
|
||||
};
|
||||
|
||||
// for parent data context
|
||||
// internalDataContext()
|
||||
// bindViewModelInstance on state machine
|
||||
class ScriptedArtboard
|
||||
{
|
||||
public:
|
||||
ScriptedArtboard(rcp<File> file,
|
||||
std::unique_ptr<ArtboardInstance>&& artboardInstance);
|
||||
|
||||
static constexpr uint8_t luaTag = LUA_T_COUNT + 10;
|
||||
static constexpr const char* luaName = "Artboard";
|
||||
static constexpr bool hasMetatable = true;
|
||||
|
||||
Artboard* artboard() { return m_scriptReffedArtboard->artboard(); }
|
||||
StateMachineInstance* stateMachine()
|
||||
{
|
||||
return m_scriptReffedArtboard->stateMachine();
|
||||
}
|
||||
rcp<ViewModelInstance> viewModelInstance()
|
||||
{
|
||||
return m_scriptReffedArtboard->viewModelInstance();
|
||||
}
|
||||
|
||||
rcp<ScriptReffedArtboard> scriptReffedArtboard()
|
||||
{
|
||||
return m_scriptReffedArtboard;
|
||||
}
|
||||
|
||||
int pushData(lua_State* L);
|
||||
int instance(lua_State* L);
|
||||
|
||||
bool advance(float seconds);
|
||||
|
||||
private:
|
||||
rcp<ScriptReffedArtboard> m_scriptReffedArtboard;
|
||||
int m_dataRef = 0;
|
||||
};
|
||||
|
||||
struct ScriptedListener
|
||||
@@ -755,6 +783,24 @@ public:
|
||||
HitResult m_hitResult = HitResult::none;
|
||||
};
|
||||
|
||||
class ScriptedNode
|
||||
{
|
||||
public:
|
||||
ScriptedNode(rcp<ScriptReffedArtboard> artboard,
|
||||
TransformComponent* component);
|
||||
|
||||
static constexpr uint8_t luaTag = LUA_T_COUNT + 25;
|
||||
static constexpr const char* luaName = "Node";
|
||||
static constexpr bool hasMetatable = true;
|
||||
|
||||
TransformComponent* component() { return m_component; }
|
||||
rcp<ScriptReffedArtboard> artboard() { return m_artboard; }
|
||||
|
||||
private:
|
||||
rcp<ScriptReffedArtboard> m_artboard;
|
||||
TransformComponent* m_component;
|
||||
};
|
||||
|
||||
static void interruptCPP(lua_State* L, int gc);
|
||||
|
||||
class CPPRuntimeScriptingContext : public ScriptingContext
|
||||
|
||||
@@ -2,12 +2,37 @@
|
||||
#include "rive/lua/rive_lua_libs.hpp"
|
||||
#include "rive/viewmodel/viewmodel_property_number.hpp"
|
||||
#include "rive/viewmodel/viewmodel_property_trigger.hpp"
|
||||
#include "rive/node.hpp"
|
||||
#include "rive/bones/root_bone.hpp"
|
||||
#include "rive/constraints/constraint.hpp"
|
||||
#include "rive/math/transform_components.hpp"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace rive;
|
||||
|
||||
ScriptReffedArtboard::ScriptReffedArtboard(
|
||||
rcp<File> file,
|
||||
std::unique_ptr<ArtboardInstance>&& artboardInstance) :
|
||||
m_file(file),
|
||||
m_artboard(std::move(artboardInstance)),
|
||||
m_stateMachine(m_artboard->defaultStateMachine())
|
||||
{
|
||||
m_viewModelInstance = m_file->createViewModelInstance(m_artboard.get());
|
||||
if (m_stateMachine && m_viewModelInstance)
|
||||
{
|
||||
m_stateMachine->bindViewModelInstance(m_viewModelInstance);
|
||||
}
|
||||
}
|
||||
|
||||
ScriptReffedArtboard::~ScriptReffedArtboard()
|
||||
{
|
||||
// Make sure artboard is deleted before file.
|
||||
m_artboard = nullptr;
|
||||
m_file = nullptr;
|
||||
}
|
||||
|
||||
static int artboard_draw(lua_State* L)
|
||||
{
|
||||
auto scriptedArtboard = lua_torive<ScriptedArtboard>(L, 1);
|
||||
@@ -21,13 +46,14 @@ static int artboard_draw(lua_State* L)
|
||||
|
||||
bool ScriptedArtboard::advance(float seconds)
|
||||
{
|
||||
if (m_stateMachine)
|
||||
auto machine = stateMachine();
|
||||
if (machine)
|
||||
{
|
||||
return m_stateMachine->advanceAndApply(seconds);
|
||||
return machine->advanceAndApply(seconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_artboard->advance(seconds);
|
||||
return artboard()->advance(seconds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +93,24 @@ static int artboard_namecall(lua_State* L)
|
||||
lua_pushvec2d(L, bounds.max());
|
||||
return 2;
|
||||
}
|
||||
case (int)LuaAtoms::node:
|
||||
{
|
||||
auto scriptedArtboard = lua_torive<ScriptedArtboard>(L, 1);
|
||||
const char* name = luaL_checkstring(L, 2);
|
||||
auto component =
|
||||
scriptedArtboard->artboard()->find<TransformComponent>(
|
||||
name);
|
||||
if (component == nullptr)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
lua_newrive<ScriptedNode>(
|
||||
L,
|
||||
scriptedArtboard->scriptReffedArtboard(),
|
||||
component);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,17 +128,14 @@ int ScriptedArtboard::pushData(lua_State* L)
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, m_dataRef);
|
||||
return 1;
|
||||
}
|
||||
if (m_viewModelInstance == nullptr)
|
||||
auto vm = viewModelInstance();
|
||||
if (!vm)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_newrive<ScriptedViewModel>(
|
||||
L,
|
||||
L,
|
||||
ref_rcp(m_viewModelInstance->viewModel()),
|
||||
m_viewModelInstance);
|
||||
lua_newrive<ScriptedViewModel>(L, L, ref_rcp(vm->viewModel()), vm);
|
||||
}
|
||||
m_dataRef = lua_ref(L, -1);
|
||||
|
||||
@@ -103,10 +144,17 @@ int ScriptedArtboard::pushData(lua_State* L)
|
||||
|
||||
int ScriptedArtboard::instance(lua_State* L)
|
||||
{
|
||||
lua_newrive<ScriptedArtboard>(L, m_file, m_artboard->instance());
|
||||
lua_newrive<ScriptedArtboard>(L,
|
||||
m_scriptReffedArtboard->file(),
|
||||
artboard()->instance());
|
||||
return 1;
|
||||
}
|
||||
|
||||
ScriptedNode::ScriptedNode(rcp<ScriptReffedArtboard> artboard,
|
||||
TransformComponent* component) :
|
||||
m_artboard(artboard), m_component(component)
|
||||
{}
|
||||
|
||||
static int artboard_index(lua_State* L)
|
||||
{
|
||||
int atom;
|
||||
@@ -136,8 +184,14 @@ static int artboard_index(lua_State* L)
|
||||
return scriptedArtboard->pushData(L);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
luaL_error(L,
|
||||
"'%s' is not a valid index of %s",
|
||||
key,
|
||||
ScriptedArtboard::luaName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int artboard_newindex(lua_State* L)
|
||||
@@ -167,21 +221,259 @@ static int artboard_newindex(lua_State* L)
|
||||
break;
|
||||
}
|
||||
|
||||
luaL_error(L,
|
||||
"'%s' is not a valid index of %s",
|
||||
key,
|
||||
ScriptedArtboard::luaName);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ScriptedArtboard::ScriptedArtboard(
|
||||
rcp<File> file,
|
||||
std::unique_ptr<ArtboardInstance>&& artboardInstance) :
|
||||
m_file(file),
|
||||
m_artboard(std::move(artboardInstance)),
|
||||
m_stateMachine(m_artboard->defaultStateMachine())
|
||||
m_scriptReffedArtboard(
|
||||
make_rcp<ScriptReffedArtboard>(file, std::move(artboardInstance)))
|
||||
{}
|
||||
|
||||
static int node_index(lua_State* L)
|
||||
{
|
||||
m_viewModelInstance = m_file->createViewModelInstance(m_artboard.get());
|
||||
if (m_stateMachine && m_viewModelInstance)
|
||||
int atom;
|
||||
const char* key = lua_tostringatom(L, 2, &atom);
|
||||
if (!key)
|
||||
{
|
||||
m_stateMachine->bindViewModelInstance(m_viewModelInstance);
|
||||
luaL_typeerrorL(L, 2, lua_typename(L, LUA_TSTRING));
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto scriptedNode = lua_torive<ScriptedNode>(L, 1);
|
||||
switch (atom)
|
||||
{
|
||||
case (int)LuaAtoms::position:
|
||||
lua_pushvector2(L,
|
||||
scriptedNode->component()->x(),
|
||||
scriptedNode->component()->y());
|
||||
return 1;
|
||||
|
||||
case (int)LuaAtoms::rotation:
|
||||
lua_pushnumber(L, scriptedNode->component()->rotation());
|
||||
return 1;
|
||||
|
||||
case (int)LuaAtoms::scale:
|
||||
lua_pushvector2(L,
|
||||
scriptedNode->component()->scaleX(),
|
||||
scriptedNode->component()->scaleY());
|
||||
return 1;
|
||||
|
||||
case (int)LuaAtoms::scaleX:
|
||||
lua_pushnumber(L, scriptedNode->component()->scaleX());
|
||||
return 1;
|
||||
|
||||
case (int)LuaAtoms::scaleY:
|
||||
lua_pushnumber(L, scriptedNode->component()->scaleY());
|
||||
return 1;
|
||||
|
||||
case (int)LuaAtoms::worldTransform:
|
||||
lua_newrive<ScriptedMat2D>(
|
||||
L,
|
||||
scriptedNode->component()->worldTransform());
|
||||
return 1;
|
||||
|
||||
case (int)LuaAtoms::children:
|
||||
{
|
||||
auto component = scriptedNode->component();
|
||||
if (component->is<ContainerComponent>())
|
||||
{
|
||||
auto container = component->as<ContainerComponent>();
|
||||
// speculative pre-alloc the table
|
||||
auto& children = container->children();
|
||||
lua_createtable(L, (int)children.size(), 0);
|
||||
|
||||
int index = 1;
|
||||
for (auto child : children)
|
||||
{
|
||||
if (child->is<TransformComponent>())
|
||||
{
|
||||
lua_newrive<ScriptedNode>(
|
||||
L,
|
||||
scriptedNode->artboard(),
|
||||
child->as<TransformComponent>());
|
||||
// Set table[i] = value, pops the value
|
||||
lua_rawseti(L, -2, index++);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
case (int)LuaAtoms::parent:
|
||||
{
|
||||
auto parent = scriptedNode->component()->parent();
|
||||
if (parent != nullptr && parent->is<TransformComponent>())
|
||||
{
|
||||
lua_newrive<ScriptedNode>(L,
|
||||
scriptedNode->artboard(),
|
||||
parent->as<TransformComponent>());
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
default:
|
||||
switch (key[0])
|
||||
{
|
||||
case 'x':
|
||||
lua_pushnumber(L, scriptedNode->component()->x());
|
||||
return 1;
|
||||
case 'y':
|
||||
lua_pushnumber(L, scriptedNode->component()->y());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
luaL_error(L,
|
||||
"'%s' is not a valid index of %s",
|
||||
key,
|
||||
ScriptedNode::luaName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int node_newindex(lua_State* L)
|
||||
{
|
||||
int atom;
|
||||
const char* key = lua_tostringatom(L, 2, &atom);
|
||||
if (!key)
|
||||
{
|
||||
luaL_typeerrorL(L, 2, lua_typename(L, LUA_TSTRING));
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto scriptedNode = lua_torive<ScriptedNode>(L, 1);
|
||||
auto component = scriptedNode->component();
|
||||
switch (atom)
|
||||
{
|
||||
case (int)LuaAtoms::position:
|
||||
{
|
||||
const float* vec = luaL_checkvector(L, 3);
|
||||
|
||||
if (component->is<Node>())
|
||||
{
|
||||
Node* node = component->as<Node>();
|
||||
node->x(vec[0]);
|
||||
node->y(vec[1]);
|
||||
}
|
||||
else if (component->is<RootBone>())
|
||||
{
|
||||
RootBone* bone = component->as<RootBone>();
|
||||
bone->x(vec[0]);
|
||||
bone->y(vec[1]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case (int)LuaAtoms::rotation:
|
||||
component->rotation(float(luaL_checknumber(L, 3)));
|
||||
return 0;
|
||||
|
||||
case (int)LuaAtoms::scale:
|
||||
{
|
||||
const float* vec = luaL_checkvector(L, 3);
|
||||
component->scaleX(vec[0]);
|
||||
component->scaleY(vec[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case (int)LuaAtoms::scaleX:
|
||||
component->scaleX(float(luaL_checknumber(L, 3)));
|
||||
return 0;
|
||||
|
||||
case (int)LuaAtoms::scaleY:
|
||||
component->scaleY(float(luaL_checknumber(L, 3)));
|
||||
return 0;
|
||||
|
||||
case (int)LuaAtoms::worldTransform:
|
||||
{
|
||||
Mat2D& transform = component->mutableWorldTransform();
|
||||
transform = *(Mat2D*)lua_torive<ScriptedMat2D>(L, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
switch (key[0])
|
||||
{
|
||||
case 'x':
|
||||
if (component->is<Node>())
|
||||
{
|
||||
Node* node = component->as<Node>();
|
||||
node->x(float(luaL_checknumber(L, 3)));
|
||||
}
|
||||
else if (component->is<RootBone>())
|
||||
{
|
||||
RootBone* bone = component->as<RootBone>();
|
||||
bone->x(float(luaL_checknumber(L, 3)));
|
||||
}
|
||||
return 0;
|
||||
case 'y':
|
||||
if (component->is<Node>())
|
||||
{
|
||||
Node* node = component->as<Node>();
|
||||
node->y(float(luaL_checknumber(L, 3)));
|
||||
}
|
||||
else if (component->is<RootBone>())
|
||||
{
|
||||
RootBone* bone = component->as<RootBone>();
|
||||
bone->y(float(luaL_checknumber(L, 3)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
luaL_error(L,
|
||||
"'%s' is not a valid index of %s",
|
||||
key,
|
||||
ScriptedNode::luaName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int node_namecall(lua_State* L)
|
||||
{
|
||||
int atom;
|
||||
const char* str = lua_namecallatom(L, &atom);
|
||||
if (str != nullptr)
|
||||
{
|
||||
switch (atom)
|
||||
{
|
||||
case (int)LuaAtoms::decompose:
|
||||
{
|
||||
auto scriptedNode = lua_torive<ScriptedNode>(L, 1);
|
||||
auto component = scriptedNode->component();
|
||||
Mat2D world = getParentWorld(*component).invertOrIdentity() *
|
||||
(*(Mat2D*)lua_torive<ScriptedMat2D>(L, 2));
|
||||
TransformComponents components = world.decompose();
|
||||
if (component->is<Node>())
|
||||
{
|
||||
Node* node = component->as<Node>();
|
||||
node->x(components.x());
|
||||
node->y(components.y());
|
||||
}
|
||||
else if (component->is<RootBone>())
|
||||
{
|
||||
RootBone* bone = component->as<RootBone>();
|
||||
bone->x(components.x());
|
||||
bone->y(components.y());
|
||||
}
|
||||
component->scaleX(components.scaleX());
|
||||
component->scaleY(components.scaleY());
|
||||
component->rotation(components.rotation());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
luaL_error(L, "%s is not a valid method of %s", str, ScriptedNode::luaName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int luaopen_rive_artboards(lua_State* L)
|
||||
@@ -200,6 +492,20 @@ int luaopen_rive_artboards(lua_State* L)
|
||||
lua_setreadonly(L, -1, true);
|
||||
lua_pop(L, 1); // pop the metatable
|
||||
|
||||
return 1;
|
||||
lua_register_rive<ScriptedNode>(L);
|
||||
|
||||
lua_pushcfunction(L, node_index, nullptr);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, node_newindex, nullptr);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, node_namecall, nullptr);
|
||||
lua_setfield(L, -2, "__namecall");
|
||||
|
||||
lua_setreadonly(L, -1, true);
|
||||
lua_pop(L, 1); // pop the metatable
|
||||
|
||||
return 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -103,6 +103,15 @@ std::unordered_map<std::string, int16_t> atoms = {
|
||||
{"hit", (int16_t)LuaAtoms::hit},
|
||||
{"id", (int16_t)LuaAtoms::id},
|
||||
{"position", (int16_t)LuaAtoms::position},
|
||||
{"rotation", (int16_t)LuaAtoms::rotation},
|
||||
{"scale", (int16_t)LuaAtoms::scale},
|
||||
{"worldTransform", (int16_t)LuaAtoms::worldTransform},
|
||||
{"scaleX", (int16_t)LuaAtoms::scaleX},
|
||||
{"scaleY", (int16_t)LuaAtoms::scaleY},
|
||||
{"decompose", (int16_t)LuaAtoms::decompose},
|
||||
{"children", (int16_t)LuaAtoms::children},
|
||||
{"parent", (int16_t)LuaAtoms::parent},
|
||||
{"node", (int16_t)LuaAtoms::node},
|
||||
};
|
||||
|
||||
static const luaL_Reg lualibs[] = {
|
||||
|
||||
BIN
tests/unit_tests/assets/joel_v3.riv
Normal file
BIN
tests/unit_tests/assets/joel_v3.riv
Normal file
Binary file not shown.
@@ -149,4 +149,116 @@ TEST_CASE("can detect hit test from PointerEvent", "[scripting]")
|
||||
CHECK(lua_pcall(L, 1, 1, 0) == LUA_OK);
|
||||
CHECK(pointerEvent->m_hitResult == HitResult::hitOpaque);
|
||||
CHECK(lua_tonumber(L, -1) == 22.0f);
|
||||
}
|
||||
|
||||
TEST_CASE("can access nodes from artboards", "[scripting]")
|
||||
{
|
||||
ScriptingTest vm("function getNode(artboard:Artboard):Node?\n"
|
||||
" return artboard:node('muzzle')\n"
|
||||
"end\n"
|
||||
"function getNodeX(artboard:Artboard):number\n"
|
||||
" return artboard:node('muzzle').x\n"
|
||||
"end\n"
|
||||
"function getNodeY(artboard:Artboard):number\n"
|
||||
" return artboard:node('muzzle').y\n"
|
||||
"end\n"
|
||||
"function getScaleX(artboard:Artboard):number\n"
|
||||
" return artboard:node('muzzle').scaleX\n"
|
||||
"end\n"
|
||||
"function getScaleY(artboard:Artboard):number\n"
|
||||
" return artboard:node('muzzle').scaleY\n"
|
||||
"end\n"
|
||||
"function decompose(artboard:Artboard)\n"
|
||||
" artboard:node('muzzle'):decompose(Mat2D.identity())\n"
|
||||
"end\n"
|
||||
"function getChildren(artboard:Artboard):number\n"
|
||||
" return #(artboard:node('muzzle').children)\n"
|
||||
"end\n"
|
||||
"function getWeaponChildren(artboard:Artboard):number\n"
|
||||
" return #(artboard:node('Weapon').children)\n"
|
||||
"end\n"
|
||||
"function getParent(artboard:Artboard):Node?\n"
|
||||
" return artboard:node('muzzle').parent\n"
|
||||
"end\n");
|
||||
lua_State* L = vm.state();
|
||||
auto file = ReadRiveFile("assets/joel_v3.riv", vm.serializer());
|
||||
auto artboard = file->artboard("Character");
|
||||
REQUIRE(artboard != nullptr);
|
||||
lua_newrive<ScriptedArtboard>(L, file, artboard->instance());
|
||||
|
||||
lua_getglobal(L, "getNode");
|
||||
lua_pushvalue(L, -2);
|
||||
CHECK(lua_pcall(L, 1, 1, 0) == LUA_OK);
|
||||
CHECK(lua_isuserdata(L, -1));
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getglobal(L, "getNodeX");
|
||||
lua_pushvalue(L, -2);
|
||||
CHECK(lua_pcall(L, 1, 1, 0) == LUA_OK);
|
||||
CHECK(lua_tonumber(L, -1) == 203.0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getglobal(L, "getNodeY");
|
||||
lua_pushvalue(L, -2);
|
||||
CHECK(lua_pcall(L, 1, 1, 0) == LUA_OK);
|
||||
CHECK(lua_tonumber(L, -1) == 0.0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getglobal(L, "getScaleX");
|
||||
lua_pushvalue(L, -2);
|
||||
CHECK(lua_pcall(L, 1, 1, 0) == LUA_OK);
|
||||
CHECK(lua_tonumber(L, -1) == Approx(1.2500029802));
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getglobal(L, "getScaleY");
|
||||
lua_pushvalue(L, -2);
|
||||
CHECK(lua_pcall(L, 1, 1, 0) == LUA_OK);
|
||||
CHECK(lua_tonumber(L, -1) == Approx(1.2500029802));
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getglobal(L, "decompose");
|
||||
lua_pushvalue(L, -2);
|
||||
CHECK(lua_pcall(L, 1, 0, 0) == LUA_OK);
|
||||
|
||||
lua_getglobal(L, "getNodeX");
|
||||
lua_pushvalue(L, -2);
|
||||
CHECK(lua_pcall(L, 1, 1, 0) == LUA_OK);
|
||||
CHECK(lua_tonumber(L, -1) == 0.0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getglobal(L, "getNodeY");
|
||||
lua_pushvalue(L, -2);
|
||||
CHECK(lua_pcall(L, 1, 1, 0) == LUA_OK);
|
||||
CHECK(lua_tonumber(L, -1) == 0.0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getglobal(L, "getScaleX");
|
||||
lua_pushvalue(L, -2);
|
||||
CHECK(lua_pcall(L, 1, 1, 0) == LUA_OK);
|
||||
CHECK(lua_tonumber(L, -1) == 1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getglobal(L, "getScaleY");
|
||||
lua_pushvalue(L, -2);
|
||||
CHECK(lua_pcall(L, 1, 1, 0) == LUA_OK);
|
||||
CHECK(lua_tonumber(L, -1) == 1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getglobal(L, "getChildren");
|
||||
lua_pushvalue(L, -2);
|
||||
CHECK(lua_pcall(L, 1, 1, 0) == LUA_OK);
|
||||
CHECK(lua_tonumber(L, -1) == 0);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getglobal(L, "getParent");
|
||||
lua_pushvalue(L, -2);
|
||||
CHECK(lua_pcall(L, 1, 1, 0) == LUA_OK);
|
||||
CHECK(lua_isuserdata(L, -1));
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getglobal(L, "getWeaponChildren");
|
||||
lua_pushvalue(L, -2);
|
||||
CHECK(lua_pcall(L, 1, 1, 0) == LUA_OK);
|
||||
CHECK(lua_tonumber(L, -1) == 9);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
Reference in New Issue
Block a user