Skip to content

Commit

Permalink
Add rive.set_state_machine_input (#136)
Browse files Browse the repository at this point in the history
* Add rive.set_state_machine_input

* Add docs
  • Loading branch information
Jhonnyg authored Nov 21, 2024
1 parent 6925726 commit 7f227f1
Show file tree
Hide file tree
Showing 17 changed files with 216 additions and 192 deletions.
23 changes: 23 additions & 0 deletions defold-rive/api/rive.script_api
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,26 @@
- name: value
type: number|bool
desc: The value of the input

#*****************************************************************************************************

- name: set_state_machine_input
type: function
desc: Set the input values from a state machine input, either from the current top-level artboard, or from a nested artboard inside the Rive model artboard. Note - To set input for a trigger, use a bool value.

parameters:
- name: url
type: url
desc: The Rive model

- name: name
type: string
desc: The name of the input

- name: value
type: number|bool
desc: The value of the input to set

- name: nested_artboard
type: string
desc: (OPTIONAL) If specified, the input will be queried for the specified nested artboard
74 changes: 66 additions & 8 deletions defold-rive/src/comp_rive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1582,7 +1582,7 @@ namespace dmRive
}
}

GetStateMachineInputData::Result CompRiveGetStateMachineInput(RiveComponent* component, const char* input_name, const char* nested_artboard_path, GetStateMachineInputData& out_value)
StateMachineInputData::Result CompRiveSetStateMachineInput(RiveComponent* component, const char* input_name, const char* nested_artboard_path, const StateMachineInputData& value)
{
rive::ArtboardInstance* artboard = component->m_ArtboardInstance.get();
rive::SMIInput* input_instance = 0x0;
Expand All @@ -1601,33 +1601,91 @@ namespace dmRive
}
}

out_value.m_Type = GetStateMachineInputData::TYPE_INVALID;
if (input_instance)
{
const rive::StateMachineInput* input = input_instance->input();

if (input->is<rive::StateMachineTrigger>())
{
if (value.m_Type != StateMachineInputData::TYPE_BOOL)
{
return StateMachineInputData::RESULT_TYPE_MISMATCH;
}
rive::SMITrigger* trigger = (rive::SMITrigger*)input_instance;
trigger->fire();
return StateMachineInputData::RESULT_OK;
}
else if (input->is<rive::StateMachineBool>())
{
if (value.m_Type != StateMachineInputData::TYPE_BOOL)
{
return StateMachineInputData::RESULT_TYPE_MISMATCH;
}
rive::SMIBool* v = (rive::SMIBool*)input_instance;
v->value(value.m_BoolValue);
return StateMachineInputData::RESULT_OK;
}
else if (input->is<rive::StateMachineNumber>())
{
if (value.m_Type != StateMachineInputData::TYPE_NUMBER)
{
return StateMachineInputData::RESULT_TYPE_MISMATCH;
}
rive::SMINumber* v = (rive::SMINumber*)input_instance;
v->value(value.m_NumberValue);
return StateMachineInputData::RESULT_OK;
}
}

return StateMachineInputData::RESULT_NOT_FOUND;
}

StateMachineInputData::Result CompRiveGetStateMachineInput(RiveComponent* component, const char* input_name, const char* nested_artboard_path, StateMachineInputData& out_value)
{
rive::ArtboardInstance* artboard = component->m_ArtboardInstance.get();
rive::SMIInput* input_instance = 0x0;

if (nested_artboard_path)
{
input_instance = artboard->input(input_name, nested_artboard_path);
}
else
{
dmhash_t input_hash = dmHashString64(input_name);
int index = FindStateMachineInputIndex(component, input_hash);
if (index >= 0)
{
input_instance = component->m_StateMachineInstance->input(index);
}
}

out_value.m_Type = StateMachineInputData::TYPE_INVALID;

if (input_instance)
{
const rive::StateMachineInput* input = input_instance->input();

if (input->is<rive::StateMachineTrigger>())
{
return GetStateMachineInputData::RESULT_TYPE_UNSUPPORTED;
return StateMachineInputData::RESULT_TYPE_UNSUPPORTED;
}
else if (input->is<rive::StateMachineBool>())
{
rive::SMIBool* v = (rive::SMIBool*)input_instance;
out_value.m_Type = GetStateMachineInputData::TYPE_BOOL;
out_value.m_Type = StateMachineInputData::TYPE_BOOL;
out_value.m_BoolValue = v->value();
return GetStateMachineInputData::RESULT_OK;
return StateMachineInputData::RESULT_OK;
}
else if (input->is<rive::StateMachineNumber>())
{
rive::SMINumber* v = (rive::SMINumber*)input_instance;
out_value.m_Type = GetStateMachineInputData::TYPE_NUMBER;
out_value.m_Type = StateMachineInputData::TYPE_NUMBER;
out_value.m_NumberValue = v->value();
return GetStateMachineInputData::RESULT_OK;
return StateMachineInputData::RESULT_OK;
}
}

return GetStateMachineInputData::RESULT_NOT_FOUND;
return StateMachineInputData::RESULT_NOT_FOUND;
}

static inline rive::TextValueRun* GetTextRun(rive::ArtboardInstance* artboard, const char* name, const char* nested_artboard_path)
Expand Down
8 changes: 5 additions & 3 deletions defold-rive/src/comp_rive.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ namespace dmRive

// For scripting

struct GetStateMachineInputData
struct StateMachineInputData
{
union
{
Expand All @@ -87,7 +87,8 @@ namespace dmRive

enum Result
{
RESULT_NOT_FOUND = -2,
RESULT_NOT_FOUND = -3,
RESULT_TYPE_MISMATCH = -2,
RESULT_TYPE_UNSUPPORTED = -1,
RESULT_OK = 0,
};
Expand Down Expand Up @@ -115,7 +116,8 @@ namespace dmRive
const char* CompRiveGetTextRun(RiveComponent* component, const char* name, const char* nested_artboard_path);
bool CompRiveSetTextRun(RiveComponent* component, const char* name, const char* text_run, const char* nested_artboard_path);

GetStateMachineInputData::Result CompRiveGetStateMachineInput(RiveComponent* component, const char* input_name, const char* nested_artboard_path, GetStateMachineInputData& data);
StateMachineInputData::Result CompRiveGetStateMachineInput(RiveComponent* component, const char* input_name, const char* nested_artboard_path, StateMachineInputData& data);
StateMachineInputData::Result CompRiveSetStateMachineInput(RiveComponent* component, const char* input_name, const char* nested_artboard_path, const StateMachineInputData& data);

float CompRiveGetDisplayScaleFactor();

Expand Down
64 changes: 56 additions & 8 deletions defold-rive/src/script_rive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,51 @@ namespace dmRive
return 1;
}

static int RiveComp_SetStateMachineInput(lua_State* L)
{
DM_LUA_STACK_CHECK(L, 0);

RiveComponent* component = 0;
dmScript::GetComponentFromLua(L, 1, dmRive::RIVE_MODEL_EXT, 0, (void**)&component, 0);

const char* input_name = luaL_checkstring(L, 2);
const char* nested_artboard_path = 0; // optional

StateMachineInputData data = {};

if (lua_isnumber(L, 3))
{
data.m_Type = StateMachineInputData::TYPE_NUMBER;
data.m_NumberValue = lua_tonumber(L,3);
}
else if (lua_isboolean(L,3))
{
data.m_Type = StateMachineInputData::TYPE_BOOL;
data.m_BoolValue = lua_toboolean(L,3);
}
else
{
return DM_LUA_ERROR("Cannot set input '%s' with an unsupported type.", input_name);
}

if (lua_isstring(L, 4))
{
nested_artboard_path = lua_tostring(L, 4);
}

StateMachineInputData::Result res = CompRiveSetStateMachineInput(component, input_name, nested_artboard_path, data);
if (res != StateMachineInputData::RESULT_OK)
{
if (res == StateMachineInputData::RESULT_TYPE_MISMATCH)
{
return DM_LUA_ERROR("Type mismatch for input '%s'.", input_name);
}
assert(res == StateMachineInputData::RESULT_NOT_FOUND);
return DM_LUA_ERROR("The input '%s' could not be found (or an unknown error happened).", input_name);
}
return 0;
}

static int RiveComp_GetStateMachineInput(lua_State* L)
{
DM_LUA_STACK_CHECK(L, 1);
Expand All @@ -340,26 +385,28 @@ namespace dmRive
nested_artboard_path = lua_tostring(L, 3);
}

GetStateMachineInputData data;
GetStateMachineInputData::Result res = CompRiveGetStateMachineInput(component, input_name, nested_artboard_path, data);
StateMachineInputData data;
StateMachineInputData::Result res = CompRiveGetStateMachineInput(component, input_name, nested_artboard_path, data);

if (res != GetStateMachineInputData::RESULT_OK)
if (res != StateMachineInputData::RESULT_OK)
{
if (res == GetStateMachineInputData::RESULT_TYPE_UNSUPPORTED)
if (res == StateMachineInputData::RESULT_TYPE_UNSUPPORTED)
{
return DM_LUA_ERROR("The input '%s' has an unsupported type.", input_name);
assert(res == GetStateMachineInputData::RESULT_NOT_FOUND);
}
assert(res == StateMachineInputData::RESULT_NOT_FOUND);
return DM_LUA_ERROR("The input '%s' could not be found (or an unknown error happened).", input_name);
}

switch(data.m_Type)
{
case GetStateMachineInputData::TYPE_BOOL:
case StateMachineInputData::TYPE_BOOL:
lua_pushboolean(L, data.m_BoolValue);
break;
case GetStateMachineInputData::TYPE_NUMBER:
case StateMachineInputData::TYPE_NUMBER:
lua_pushnumber(L, data.m_NumberValue);
break;
case GetStateMachineInputData::TYPE_INVALID:
case StateMachineInputData::TYPE_INVALID:
break;
}
return 1;
Expand All @@ -378,6 +425,7 @@ namespace dmRive
{"get_text_run", RiveComp_GetTextRun},
{"get_projection_matrix", RiveComp_GetProjectionMatrix},
{"get_state_machine_input", RiveComp_GetStateMachineInput},
{"set_state_machine_input", RiveComp_SetStateMachineInput},
{0, 0}
};

Expand Down
9 changes: 9 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,15 @@ local v = rive.get_state_machine_input("#rivemodel", "Number 1", "My_Nested_Artb

-- To go deeper into the nested hierarchy, you can add slashes between each scope
local v = rive.get_state_machine_input("#rivemodel", "Number 1", "My_Nested_Artboard/My_Inner_Nested_Artboard")

-- Set the input value of the current state machine
rive.set_state_machine_input("#rivemodel", "Number 1", 0.5)

-- Set the input value of a nested artboard
rive.set_state_machine_input("#rivemodel", "Number 1", 0.5, "My_Nested_Artboard")

-- Same as the example above, to go even deeper, separate the scopers with slashes!
rive.set_state_machine_input("#rivemodel", "Number 1", 0.5, "My_Nested_Artboard/My_Inner_Nested_Artboard")
```

#### Events
Expand Down
65 changes: 1 addition & 64 deletions main/bones/bones.collection
Original file line number Diff line number Diff line change
Expand Up @@ -2,100 +2,37 @@ name: "bones"
instances {
id: "back"
prototype: "/main/menu/back.go"
position {
x: 0.0
y: 0.0
z: 0.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale3 {
x: 1.0
y: 1.0
z: 1.0
}
}
scale_along_z: 0
embedded_instances {
id: "go"
data: "components {\n"
" id: \"bones\"\n"
" component: \"/main/bones/bones.script\"\n"
" position {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
" property_decls {\n"
" }\n"
"}\n"
"embedded_components {\n"
" id: \"rivemodel\"\n"
" type: \"rivemodel\"\n"
" data: \"scene: \\\"/main/bones/marty.rivescene\\\"\\n"
"default_animation: \\\"Animation1\\\"\\n"
"material: \\\"/defold-rive/assets/rivemodel.material\\\"\\n"
"blend_mode: BLEND_MODE_ALPHA\\n"
"default_state_machine: \\\"\\\"\\n"
"create_go_bones: true\\n"
"artboard: \\\"\\\"\\n"
"artboard: \\\"New Artboard\\\"\\n"
"\"\n"
" position {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
"}\n"
"embedded_components {\n"
" id: \"bonefactory\"\n"
" type: \"factory\"\n"
" data: \"prototype: \\\"/main/bones/bone.go\\\"\\n"
"load_dynamically: false\\n"
"dynamic_prototype: false\\n"
"\"\n"
" position {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
"}\n"
""
position {
x: 486.0
y: 271.726
z: 0.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale3 {
x: 0.5
y: 0.5
z: 1.0
}
}
Loading

0 comments on commit 7f227f1

Please sign in to comment.