| #ifdef WITH_RIVE_SCRIPTING | |
| #include "rive/lua/rive_lua_libs.hpp" | |
| #include "lualib.h" | |
| using namespace rive; | |
| static const char* hit_listener_type_string(int raw) | |
| { | |
| switch (static_cast<ListenerType>(raw)) | |
| { | |
| case ListenerType::enter: | |
| return "pointerEnter"; | |
| case ListenerType::exit: | |
| return "pointerExit"; | |
| case ListenerType::down: | |
| return "pointerDown"; | |
| case ListenerType::up: | |
| return "pointerUp"; | |
| case ListenerType::move: | |
| return "pointerMove"; | |
| case ListenerType::click: | |
| return "click"; | |
| case ListenerType::drag: | |
| return "pointerDrag"; | |
| default: | |
| return "unknown"; | |
| } | |
| return "unknown"; | |
| } | |
| static void pointer_event_direct_id(void* udata, void* result) | |
| { | |
| lua_userdatadirectfield_setnumber( | |
| result, | |
| (double)((ScriptedPointerEvent*)udata)->m_id); | |
| } | |
| static void pointer_event_direct_position(void* udata, void* result) | |
| { | |
| auto* self = (ScriptedPointerEvent*)udata; | |
| lua_userdatadirectfield_setvector( | |
| result, | |
| self->m_position.x, | |
| self->m_position.y, | |
| 0.0f | |
| #if LUA_VECTOR_SIZE == 4 | |
| , | |
| 0.0f | |
| #endif | |
| ); | |
| } | |
| static void pointer_event_direct_previousPosition(void* udata, void* result) | |
| { | |
| auto* self = (ScriptedPointerEvent*)udata; | |
| lua_userdatadirectfield_setvector( | |
| result, | |
| self->m_previousPosition.x, | |
| self->m_previousPosition.y, | |
| 0.0f | |
| #if LUA_VECTOR_SIZE == 4 | |
| , | |
| 0.0f | |
| #endif | |
| ); | |
| } | |
| static void pointer_event_direct_timeStamp(void* udata, void* result) | |
| { | |
| lua_userdatadirectfield_setnumber( | |
| result, | |
| ((ScriptedPointerEvent*)udata)->m_timeStamp); | |
| } | |
| static int pointer_event_index(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 pointerEvent = lua_torive<ScriptedPointerEvent>(L, 1); | |
| switch (atom) | |
| { | |
| case (int)LuaAtoms::id: | |
| lua_pushunsigned(L, (unsigned)pointerEvent->m_id); | |
| return 1; | |
| case (int)LuaAtoms::position: | |
| rive_lua_pushvector2( | |
| L, | |
| pointerEvent->m_position.x, | |
| pointerEvent->m_position.y); | |
| return 1; | |
| case (int)LuaAtoms::previousPosition: | |
| rive_lua_pushvector2( | |
| L, | |
| pointerEvent->m_previousPosition.x, | |
| pointerEvent->m_previousPosition.y); | |
| return 1; | |
| case (int)LuaAtoms::type: | |
| lua_pushstring( | |
| L, | |
| hit_listener_type_string(pointerEvent->m_hitListenerType)); | |
| return 1; | |
| case (int)LuaAtoms::timeStamp: | |
| lua_pushnumber(L, pointerEvent->m_timeStamp); | |
| return 1; | |
| } | |
| luaL_error( | |
| L, | |
| "%s is not a valid field of %s", | |
| luaL_checkstring(L, 1), | |
| ScriptedPointerEvent::luaName); | |
| return 0; | |
| } | |
| static int pointer_event_hit(lua_State* L) | |
| { | |
| auto pointerEvent = lua_torive<ScriptedPointerEvent>(L, 1); | |
| if (lua_isboolean(L, 2)) | |
| { | |
| pointerEvent->m_hitResult = lua_toboolean(L, 2) ? HitResult::hit | |
| : HitResult::hitOpaque; | |
| } | |
| else | |
| { | |
| pointerEvent->m_hitResult = HitResult::hitOpaque; | |
| } | |
| return 0; | |
| } | |
| static int pointer_event_namecall(lua_State* L) | |
| { | |
| int atom; | |
| const char* str = lua_namecallatom(L, &atom); | |
| if (str != nullptr) | |
| { | |
| switch (atom) | |
| { | |
| case (int)LuaAtoms::hit: | |
| return pointer_event_hit(L); | |
| } | |
| } | |
| luaL_error( | |
| L, | |
| "%s is not a valid method of %s", | |
| luaL_checkstring(L, 1), | |
| ScriptedPointerEvent::luaName); | |
| return 0; | |
| } | |
| static int pointer_event_new(lua_State* L) | |
| { | |
| int id = luaL_checkinteger(L, 1); | |
| auto vec = lua_checkvec2d(L, 2); | |
| lua_newrive<ScriptedPointerEvent>(L, id, Vec2D(vec->x, vec->y)); | |
| return 1; | |
| } | |
| // Indexed by ScrollPhase, null terminated for luaL_checkoption. | |
| static const char* const scrollPhaseNames[] = | |
| {"begin", "update", "end", "momentum", "inertiaCancel", nullptr}; | |
| static const char* scroll_phase_string(ScrollPhase phase) | |
| { | |
| auto index = (size_t)phase; | |
| return index < std::size(scrollPhaseNames) - 1 ? scrollPhaseNames[index] | |
| : "update"; | |
| } | |
| static int scroll_event_new(lua_State* L) | |
| { | |
| int id = luaL_checkinteger(L, 1); | |
| Vec2D position = *lua_checkvec2d(L, 2); | |
| ScrollEvent event; | |
| event.delta = *lua_checkvec2d(L, 3); | |
| event.phase = (ScrollPhase)luaL_checkoption(L, 4, "update", scrollPhaseNames); | |
| event.precise = luaL_optboolean(L, 5, false); | |
| lua_newrive<ScriptedScrollEvent>( | |
| L, | |
| id, | |
| position, | |
| event, | |
| (float)luaL_optnumber(L, 6, 0)); | |
| return 1; | |
| } | |
| static int scroll_event_index(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 scrollEvent = lua_torive<ScriptedScrollEvent>(L, 1); | |
| switch (atom) | |
| { | |
| case (int)LuaAtoms::id: | |
| lua_pushinteger(L, scrollEvent->m_id); | |
| return 1; | |
| case (int)LuaAtoms::position: | |
| rive_lua_pushvector2( | |
| L, | |
| scrollEvent->m_position.x, | |
| scrollEvent->m_position.y); | |
| return 1; | |
| case (int)LuaAtoms::delta: | |
| rive_lua_pushvector2( | |
| L, | |
| scrollEvent->m_event.delta.x, | |
| scrollEvent->m_event.delta.y); | |
| return 1; | |
| case (int)LuaAtoms::phase: | |
| lua_pushstring(L, scroll_phase_string(scrollEvent->m_event.phase)); | |
| return 1; | |
| case (int)LuaAtoms::precise: | |
| lua_pushboolean(L, scrollEvent->m_event.precise); | |
| return 1; | |
| case (int)LuaAtoms::timeStamp: | |
| lua_pushnumber(L, scrollEvent->m_timeStamp); | |
| return 1; | |
| } | |
| luaL_error( | |
| L, | |
| "%s is not a valid field of %s", | |
| key, | |
| ScriptedScrollEvent::luaName); | |
| return 0; | |
| } | |
| static int scroll_event_namecall(lua_State* L) | |
| { | |
| int atom; | |
| const char* str = lua_namecallatom(L, &atom); | |
| if (str != nullptr && atom == (int)LuaAtoms::hit) | |
| { | |
| lua_torive<ScriptedScrollEvent>(L, 1)->m_hitResult = HitResult::hitOpaque; | |
| return 0; | |
| } | |
| luaL_error( | |
| L, | |
| "%s is not a valid method of %s", | |
| str, | |
| ScriptedScrollEvent::luaName); | |
| return 0; | |
| } | |
| static const luaL_Reg pointerEventsStaticMethods[] = { | |
| {"new", pointer_event_new}, | |
| {nullptr, nullptr}}; | |
| static const luaL_Reg scrollEventsStaticMethods[] = { | |
| {"new", scroll_event_new}, | |
| {nullptr, nullptr}}; | |
| int luaopen_rive_input(lua_State* L) | |
| { | |
| { | |
| luaL_register(L, ScriptedPointerEvent::luaName, pointerEventsStaticMethods); | |
| } | |
| { | |
| lua_register_rive<ScriptedPointerEvent>(L); | |
| lua_pushcfunction(L, pointer_event_index, nullptr); | |
| lua_setfield(L, -2, "__index"); | |
| lua_pushcfunction(L, pointer_event_namecall, nullptr); | |
| lua_setfield(L, -2, "__namecall"); | |
| lua_setreadonly(L, -1, true); | |
| lua_pop(L, 1); // pop the metatable | |
| lua_registeruserdatadirectfieldget( | |
| L, | |
| ScriptedPointerEvent::luaTag, | |
| "id", | |
| pointer_event_direct_id); | |
| lua_registeruserdatadirectfieldget( | |
| L, | |
| ScriptedPointerEvent::luaTag, | |
| "position", | |
| pointer_event_direct_position); | |
| lua_registeruserdatadirectfieldget( | |
| L, | |
| ScriptedPointerEvent::luaTag, | |
| "previousPosition", | |
| pointer_event_direct_previousPosition); | |
| lua_registeruserdatadirectfieldget( | |
| L, | |
| ScriptedPointerEvent::luaTag, | |
| "timeStamp", | |
| pointer_event_direct_timeStamp); | |
| } | |
| { | |
| luaL_register(L, ScriptedScrollEvent::luaName, scrollEventsStaticMethods); | |
| } | |
| { | |
| lua_register_rive<ScriptedScrollEvent>(L); | |
| lua_pushcfunction(L, scroll_event_index, nullptr); | |
| lua_setfield(L, -2, "__index"); | |
| lua_pushcfunction(L, scroll_event_namecall, nullptr); | |
| lua_setfield(L, -2, "__namecall"); | |
| lua_setreadonly(L, -1, true); | |
| lua_pop(L, 1); // pop the metatable | |
| } | |
| rive_lua_register_listener_invocation_types(L); | |
| return 1; | |
| } | |
| #endif |