| #ifdef WITH_RIVE_SCRIPTING | |
| #include "lualib.h" | |
| #include "rive/math/vec2d.hpp" | |
| #include "rive/lua/rive_lua_libs.hpp" | |
| #include "rive/factory.hpp" | |
| #include <math.h> | |
| #include <stdio.h> | |
| using namespace rive; | |
| static int vertex_buffer_construct(lua_State* L) | |
| { | |
| lua_newrive<ScriptedVertexBuffer>(L); | |
| return 1; | |
| } | |
| static int vertex_buffer_reset(lua_State* L) | |
| { | |
| auto vertexBuffer = lua_torive<ScriptedVertexBuffer>(L, 1); | |
| vertexBuffer->values.clear(); | |
| vertexBuffer->vertexBuffer = nullptr; | |
| return 0; | |
| } | |
| static int vertex_buffer_add(lua_State* L) | |
| { | |
| auto vertexBuffer = lua_torive<ScriptedVertexBuffer>(L, 1); | |
| int nargs = lua_gettop(L) - 1; | |
| for (int i = 0; i < nargs; i++) | |
| { | |
| auto vec = lua_checkvec2d(L, 2 + i); | |
| vertexBuffer->values.push_back(*vec); | |
| } | |
| vertexBuffer->vertexBuffer = nullptr; | |
| return 0; | |
| } | |
| static int vertex_buffer_namecall(lua_State* L) | |
| { | |
| int atom; | |
| const char* str = lua_namecallatom(L, &atom); | |
| if (str != nullptr) | |
| { | |
| switch (atom) | |
| { | |
| case (int)LuaAtoms::reset: | |
| return vertex_buffer_reset(L); | |
| case (int)LuaAtoms::add: | |
| return vertex_buffer_add(L); | |
| } | |
| } | |
| luaL_error(L, | |
| "%s is not a valid method of %s", | |
| str, | |
| ScriptedVertexBuffer::luaName); | |
| return 0; | |
| } | |
| static int index_buffer_construct(lua_State* L) | |
| { | |
| lua_newrive<ScriptedTriangleBuffer>(L); | |
| return 1; | |
| } | |
| static int index_buffer_reset(lua_State* L) | |
| { | |
| auto indexBuffer = lua_torive<ScriptedTriangleBuffer>(L, 1); | |
| indexBuffer->values.clear(); | |
| indexBuffer->max = 0; | |
| indexBuffer->indexBuffer = nullptr; | |
| return 0; | |
| } | |
| static int index_buffer_add(lua_State* L) | |
| { | |
| auto indexBuffer = lua_torive<ScriptedTriangleBuffer>(L, 1); | |
| for (int i = 0; i < 3; i++) | |
| { | |
| auto index = luaL_checkunsigned(L, 2 + i); | |
| if (index > std::numeric_limits<uint16_t>::max()) | |
| { | |
| luaL_error(L, | |
| "index %i exceeds %i", | |
| index, | |
| std::numeric_limits<uint16_t>::max()); | |
| } | |
| if (index > indexBuffer->max) | |
| { | |
| indexBuffer->max = index; | |
| } | |
| indexBuffer->values.push_back((uint16_t)index); | |
| } | |
| indexBuffer->indexBuffer = nullptr; | |
| return 0; | |
| } | |
| static int index_buffer_namecall(lua_State* L) | |
| { | |
| int atom; | |
| const char* str = lua_namecallatom(L, &atom); | |
| if (str != nullptr) | |
| { | |
| switch (atom) | |
| { | |
| case (int)LuaAtoms::reset: | |
| return index_buffer_reset(L); | |
| case (int)LuaAtoms::add: | |
| return index_buffer_add(L); | |
| } | |
| } | |
| luaL_error(L, | |
| "%s is not a valid method of %s", | |
| str, | |
| ScriptedTriangleBuffer::luaName); | |
| return 0; | |
| } | |
| static const luaL_Reg empty[] = { | |
| {NULL, NULL}, | |
| }; | |
| static void register_vertex_buffer(lua_State* L) | |
| { | |
| luaL_register(L, ScriptedVertexBuffer::luaName, empty); | |
| lua_register_rive<ScriptedVertexBuffer>(L); | |
| lua_pushcfunction(L, vertex_buffer_namecall, nullptr); | |
| lua_setfield(L, -2, "__namecall"); | |
| // Create metatable for the metatable (so we can call it). | |
| lua_createtable(L, 0, 1); | |
| lua_pushcfunction(L, vertex_buffer_construct, nullptr); | |
| lua_setfield(L, -2, "__call"); | |
| // -3 as it's the library (Path) that we're setting this metatable on. | |
| lua_setmetatable(L, -3); | |
| lua_setreadonly(L, -1, true); | |
| lua_pop(L, 1); // pop the metatable | |
| } | |
| static void register_index_buffer(lua_State* L) | |
| { | |
| luaL_register(L, ScriptedTriangleBuffer::luaName, empty); | |
| lua_register_rive<ScriptedTriangleBuffer>(L); | |
| lua_pushcfunction(L, index_buffer_namecall, nullptr); | |
| lua_setfield(L, -2, "__namecall"); | |
| // Create metatable for the metatable (so we can call it). | |
| lua_createtable(L, 0, 1); | |
| lua_pushcfunction(L, index_buffer_construct, nullptr); | |
| lua_setfield(L, -2, "__call"); | |
| // -3 as it's the library (Path) that we're setting this metatable on. | |
| lua_setmetatable(L, -3); | |
| lua_setreadonly(L, -1, true); | |
| lua_pop(L, 1); // pop the metatable | |
| } | |
| void ScriptedVertexBuffer::update(Factory* factory) | |
| { | |
| // still valid? | |
| if (vertexBuffer) | |
| { | |
| return; | |
| } | |
| auto buffer = | |
| factory->makeRenderBuffer(RenderBufferType::vertex, | |
| RenderBufferFlags::mappedOnceAtInitialization, | |
| values.size() * sizeof(Vec2D)); | |
| if (buffer != nullptr) | |
| { | |
| float* pos = static_cast<float*>(buffer->map()); | |
| if (pos != nullptr) | |
| { | |
| memcpy(pos, values.data(), buffer->sizeInBytes()); | |
| buffer->unmap(); | |
| } | |
| } | |
| vertexBuffer = buffer; | |
| } | |
| void ScriptedTriangleBuffer::update(Factory* factory) | |
| { | |
| // still valid? | |
| if (indexBuffer) | |
| { | |
| return; | |
| } | |
| auto buffer = | |
| factory->makeRenderBuffer(RenderBufferType::index, | |
| RenderBufferFlags::mappedOnceAtInitialization, | |
| values.size() * sizeof(uint16_t)); | |
| if (buffer != nullptr) | |
| { | |
| void* indexData = buffer->map(); | |
| if (indexData != nullptr) | |
| { | |
| memcpy(indexData, values.data(), buffer->sizeInBytes()); | |
| buffer->unmap(); | |
| } | |
| } | |
| indexBuffer = buffer; | |
| } | |
| int luaopen_rive_mesh(lua_State* L) | |
| { | |
| register_vertex_buffer(L); | |
| register_index_buffer(L); | |
| return 2; | |
| } | |
| #endif |