From fc2e56fc05cd72b2c070a79252b03323deaccabb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jhonny=20G=C3=B6ransson?= Date: Tue, 12 Nov 2024 14:58:03 +0100 Subject: [PATCH] Add new function: rive.get_state_machine_input (#124) * Add new function: rive.get_state_machine_input * Added a docstring for the inputs --- .gitignore | 1 + defold-rive/api/rive.script_api | 24 +++++++++++++ defold-rive/src/comp_rive.cpp | 49 ++++++++++++++++++++++++++ defold-rive/src/comp_rive.h | 27 ++++++++++++++ defold-rive/src/script_rive.cpp | 62 ++++++++++++++++++++++++++------- docs/index.md | 9 +++++ 6 files changed, 160 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index a1f3e44..e23d9b4 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ bob.jar /.editor_settings *.keystore* manifest.* +/main/ignore diff --git a/defold-rive/api/rive.script_api b/defold-rive/api/rive.script_api index 93010a7..62f6464 100644 --- a/defold-rive/api/rive.script_api +++ b/defold-rive/api/rive.script_api @@ -245,3 +245,27 @@ - name: matrix type: vmath.matrix4 desc: The projection matrix + +#***************************************************************************************************** + + - name: get_state_machine_input + type: function + desc: Get 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: Trigger inputs will not generate a value! + + parameters: + - name: url + type: url + desc: The Rive model + + - name: name + type: string + desc: The name of the input + + - name: nested_artboard + type: string + desc: (OPTIONAL) If specified, the input will be queried for the specified nested artboard + + return: + - name: value + type: number|bool + desc: The value of the input diff --git a/defold-rive/src/comp_rive.cpp b/defold-rive/src/comp_rive.cpp index fe60c3d..4b8317d 100644 --- a/defold-rive/src/comp_rive.cpp +++ b/defold-rive/src/comp_rive.cpp @@ -31,6 +31,7 @@ #include #include #include +#include // Rive extension #include "comp_rive.h" @@ -1548,6 +1549,54 @@ namespace dmRive } } + GetStateMachineInputData::Result CompRiveGetStateMachineInput(RiveComponent* component, const char* input_name, const char* nested_artboard_path, GetStateMachineInputData& 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 = GetStateMachineInputData::TYPE_INVALID; + + if (input_instance) + { + const rive::StateMachineInput* input = input_instance->input(); + + if (input->is()) + { + return GetStateMachineInputData::RESULT_TYPE_UNSUPPORTED; + } + else if (input->is()) + { + rive::SMIBool* v = (rive::SMIBool*)input_instance; + out_value.m_Type = GetStateMachineInputData::TYPE_BOOL; + out_value.m_BoolValue = v->value(); + return GetStateMachineInputData::RESULT_OK; + } + else if (input->is()) + { + rive::SMINumber* v = (rive::SMINumber*)input_instance; + out_value.m_Type = GetStateMachineInputData::TYPE_NUMBER; + out_value.m_NumberValue = v->value(); + return GetStateMachineInputData::RESULT_OK; + } + } + + return GetStateMachineInputData::RESULT_NOT_FOUND; + } + static inline rive::TextValueRun* GetTextRun(rive::ArtboardInstance* artboard, const char* name, const char* nested_artboard_path) { if (nested_artboard_path) diff --git a/defold-rive/src/comp_rive.h b/defold-rive/src/comp_rive.h index 5492eac..781fbe8 100644 --- a/defold-rive/src/comp_rive.h +++ b/defold-rive/src/comp_rive.h @@ -75,6 +75,31 @@ namespace dmRive // For scripting + struct GetStateMachineInputData + { + union + { + bool m_BoolValue; + float m_NumberValue; + }; + + enum Result + { + RESULT_NOT_FOUND = -2, + RESULT_TYPE_UNSUPPORTED = -1, + RESULT_OK = 0, + }; + + enum Type + { + TYPE_INVALID = -1, + TYPE_BOOL = 0, + TYPE_NUMBER = 1 + }; + + Type m_Type; + }; + // Get the game object identifier bool CompRiveGetBoneID(RiveComponent* component, dmhash_t bone_name, dmhash_t* id); @@ -88,6 +113,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); + float CompRiveGetDisplayScaleFactor(); // bool CompRiveSetIKTargetInstance(RiveComponent* component, dmhash_t constraint_id, float mix, dmhash_t instance_id); diff --git a/defold-rive/src/script_rive.cpp b/defold-rive/src/script_rive.cpp index 63de2af..81f8b59 100644 --- a/defold-rive/src/script_rive.cpp +++ b/defold-rive/src/script_rive.cpp @@ -294,6 +294,7 @@ namespace dmRive dmScript::GetComponentFromLua(L, 1, dmRive::RIVE_MODEL_EXT, 0, (void**)&component, 0); const char* name = luaL_checkstring(L, 2); + const char* text_run = luaL_checkstring(L, 3); const char* nested_artboard_path = 0; if (lua_isstring(L, 4)) @@ -301,8 +302,6 @@ namespace dmRive nested_artboard_path = lua_tostring(L, 4); } - const char* text_run = luaL_checkstring(L, 3); - if (!CompRiveSetTextRun(component, name, text_run, nested_artboard_path)) { return DM_LUA_ERROR("The text-run '%s' could not be found.", name); @@ -326,18 +325,57 @@ namespace dmRive return 1; } + static int RiveComp_GetStateMachineInput(lua_State* L) + { + DM_LUA_STACK_CHECK(L, 1); + + 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 + + if (lua_isstring(L, 3)) + { + nested_artboard_path = lua_tostring(L, 3); + } + + GetStateMachineInputData data; + GetStateMachineInputData::Result res = CompRiveGetStateMachineInput(component, input_name, nested_artboard_path, data); + + if (res != GetStateMachineInputData::RESULT_OK) + { + if (res == GetStateMachineInputData::RESULT_TYPE_UNSUPPORTED) + return DM_LUA_ERROR("The input '%s' has an unsupported type.", input_name); + assert(res == GetStateMachineInputData::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: + lua_pushboolean(L, data.m_BoolValue); + break; + case GetStateMachineInputData::TYPE_NUMBER: + lua_pushnumber(L, data.m_NumberValue); + break; + } + return 1; + } + static const luaL_reg RIVE_FUNCTIONS[] = { - {"play_anim", RiveComp_PlayAnim}, - {"play_state_machine", RiveComp_PlayStateMachine}, - {"cancel", RiveComp_Cancel}, - {"get_go", RiveComp_GetGO}, - {"pointer_move", RiveComp_PointerMove}, - {"pointer_up", RiveComp_PointerUp}, - {"pointer_down", RiveComp_PointerDown}, - {"set_text_run", RiveComp_SetTextRun}, - {"get_text_run", RiveComp_GetTextRun}, - {"get_projection_matrix", RiveComp_GetProjectionMatrix}, + {"play_anim", RiveComp_PlayAnim}, + {"play_state_machine", RiveComp_PlayStateMachine}, + {"cancel", RiveComp_Cancel}, + {"get_go", RiveComp_GetGO}, + {"pointer_move", RiveComp_PointerMove}, + {"pointer_up", RiveComp_PointerUp}, + {"pointer_down", RiveComp_PointerDown}, + {"set_text_run", RiveComp_SetTextRun}, + {"get_text_run", RiveComp_GetTextRun}, + {"get_projection_matrix", RiveComp_GetProjectionMatrix}, + {"get_state_machine_input", RiveComp_GetStateMachineInput}, {0, 0} }; diff --git a/docs/index.md b/docs/index.md index a073369..096cd27 100644 --- a/docs/index.md +++ b/docs/index.md @@ -231,6 +231,15 @@ go.set("#rivemodel", "Trigger 1", true) -- Set the numeric value "Number 1" to 0.8 go.set("#rivemodel", "Number 1", 0.8) + +-- Read the input value of the current state machine +local v = rive.get_state_machine_input("#rivemodel", "Number 1") + +-- Read the input value of a nested artboard from the current state machine +local v = rive.get_state_machine_input("#rivemodel", "Number 1", "My_Nested_Artboard") + +-- 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") ``` #### Events