| #ifdef WITH_RIVE_SCRIPTING | |
| // The LuaAtoms name table and lookup, shared by the native runtime and the | |
| // wasm script module build; both install it as the state's useratom callback | |
| // so namecall dispatch and direct field getters agree everywhere. | |
| #include "rive/lua/rive_lua_libs.hpp" | |
| #include <array> | |
| #include <string_view> | |
| using namespace rive; | |
| namespace | |
| { | |
| struct LuaAtomName | |
| { | |
| std::string_view name; | |
| int16_t atom; | |
| }; | |
| constexpr LuaAtomName atoms[] = { | |
| {"length", (int16_t)LuaAtoms::length}, | |
| {"lengthSquared", (int16_t)LuaAtoms::lengthSquared}, | |
| {"normalized", (int16_t)LuaAtoms::normalized}, | |
| {"distance", (int16_t)LuaAtoms::distance}, | |
| {"distanceSquared", (int16_t)LuaAtoms::distanceSquared}, | |
| {"dot", (int16_t)LuaAtoms::dot}, | |
| {"lerp", (int16_t)LuaAtoms::lerp}, | |
| {"moveTo", (int16_t)LuaAtoms::moveTo}, | |
| {"lineTo", (int16_t)LuaAtoms::lineTo}, | |
| {"quadTo", (int16_t)LuaAtoms::quadTo}, | |
| {"cubicTo", (int16_t)LuaAtoms::cubicTo}, | |
| {"close", (int16_t)LuaAtoms::close}, | |
| {"type", (int16_t)LuaAtoms::type}, | |
| {"reset", (int16_t)LuaAtoms::reset}, | |
| {"add", (int16_t)LuaAtoms::add}, | |
| {"contours", (int16_t)LuaAtoms::contours}, | |
| {"measure", (int16_t)LuaAtoms::measure}, | |
| {"invert", (int16_t)LuaAtoms::invert}, | |
| {"isIdentity", (int16_t)LuaAtoms::isIdentity}, | |
| {"width", (int16_t)LuaAtoms::width}, | |
| {"height", (int16_t)LuaAtoms::height}, | |
| {"clamp", (int16_t)LuaAtoms::clamp}, | |
| {"repeat", (int16_t)LuaAtoms::repeat}, | |
| {"mirror", (int16_t)LuaAtoms::mirror}, | |
| {"bilinear", (int16_t)LuaAtoms::bilinear}, | |
| {"nearest", (int16_t)LuaAtoms::nearest}, | |
| {"style", (int16_t)LuaAtoms::style}, | |
| {"join", (int16_t)LuaAtoms::join}, | |
| {"cap", (int16_t)LuaAtoms::cap}, | |
| {"thickness", (int16_t)LuaAtoms::thickness}, | |
| {"blendMode", (int16_t)LuaAtoms::blendMode}, | |
| {"feather", (int16_t)LuaAtoms::feather}, | |
| {"gradient", (int16_t)LuaAtoms::gradient}, | |
| {"color", (int16_t)LuaAtoms::color}, | |
| {"stroke", (int16_t)LuaAtoms::stroke}, | |
| {"fill", (int16_t)LuaAtoms::fill}, | |
| {"miter", (int16_t)LuaAtoms::miter}, | |
| {"round", (int16_t)LuaAtoms::round}, | |
| {"bevel", (int16_t)LuaAtoms::bevel}, | |
| {"butt", (int16_t)LuaAtoms::butt}, | |
| {"square", (int16_t)LuaAtoms::square}, | |
| {"srcOver", (int16_t)LuaAtoms::srcOver}, | |
| {"screen", (int16_t)LuaAtoms::screen}, | |
| {"overlay", (int16_t)LuaAtoms::overlay}, | |
| {"darken", (int16_t)LuaAtoms::darken}, | |
| {"lighten", (int16_t)LuaAtoms::lighten}, | |
| {"colorDodge", (int16_t)LuaAtoms::colorDodge}, | |
| {"colorBurn", (int16_t)LuaAtoms::colorBurn}, | |
| {"hardLight", (int16_t)LuaAtoms::hardLight}, | |
| {"softLight", (int16_t)LuaAtoms::softLight}, | |
| {"difference", (int16_t)LuaAtoms::difference}, | |
| {"exclusion", (int16_t)LuaAtoms::exclusion}, | |
| {"multiply", (int16_t)LuaAtoms::multiply}, | |
| {"hue", (int16_t)LuaAtoms::hue}, | |
| {"saturation", (int16_t)LuaAtoms::saturation}, | |
| {"luminosity", (int16_t)LuaAtoms::luminosity}, | |
| {"copy", (int16_t)LuaAtoms::copy}, | |
| {"drawPath", (int16_t)LuaAtoms::drawPath}, | |
| {"drawImage", (int16_t)LuaAtoms::drawImage}, | |
| {"drawImageMesh", (int16_t)LuaAtoms::drawImageMesh}, | |
| {"clipPath", (int16_t)LuaAtoms::clipPath}, | |
| {"save", (int16_t)LuaAtoms::save}, | |
| {"restore", (int16_t)LuaAtoms::restore}, | |
| {"transform", (int16_t)LuaAtoms::transform}, | |
| {"value", (int16_t)LuaAtoms::value}, | |
| {"red", (int16_t)LuaAtoms::red}, | |
| {"green", (int16_t)LuaAtoms::green}, | |
| {"blue", (int16_t)LuaAtoms::blue}, | |
| {"alpha", (int16_t)LuaAtoms::alpha}, | |
| {"getNumber", (int16_t)LuaAtoms::getNumber}, | |
| {"getTrigger", (int16_t)LuaAtoms::getTrigger}, | |
| {"getString", (int16_t)LuaAtoms::getString}, | |
| {"getBoolean", (int16_t)LuaAtoms::getBoolean}, | |
| {"getColor", (int16_t)LuaAtoms::getColor}, | |
| {"getList", (int16_t)LuaAtoms::getList}, | |
| {"getViewModel", (int16_t)LuaAtoms::getViewModel}, | |
| {"getEnum", (int16_t)LuaAtoms::getEnum}, | |
| {"getIndex", (int16_t)LuaAtoms::getIndex}, | |
| {"getImage", (int16_t)LuaAtoms::getImage}, | |
| {"getFont", (int16_t)LuaAtoms::getFont}, | |
| {"getBlob", (int16_t)LuaAtoms::getBlob}, | |
| {"values", (int16_t)LuaAtoms::values}, | |
| {"addListener", (int16_t)LuaAtoms::addListener}, | |
| {"removeListener", (int16_t)LuaAtoms::removeListener}, | |
| {"fire", (int16_t)LuaAtoms::fire}, | |
| {"push", (int16_t)LuaAtoms::push}, | |
| {"insert", (int16_t)LuaAtoms::insert}, | |
| {"pop", (int16_t)LuaAtoms::pop}, | |
| {"swap", (int16_t)LuaAtoms::swap}, | |
| {"shift", (int16_t)LuaAtoms::shift}, | |
| {"clear", (int16_t)LuaAtoms::clear}, | |
| {"draw", (int16_t)LuaAtoms::draw}, | |
| {"advance", (int16_t)LuaAtoms::advance}, | |
| {"frameOrigin", (int16_t)LuaAtoms::frameOrigin}, | |
| {"data", (int16_t)LuaAtoms::data}, | |
| {"instance", (int16_t)LuaAtoms::instance}, | |
| {"animation", (int16_t)LuaAtoms::animation}, | |
| {"new", (int16_t)LuaAtoms::newAtom}, | |
| {"bounds", (int16_t)LuaAtoms::bounds}, | |
| {"pointerDown", (int16_t)LuaAtoms::pointerDown}, | |
| {"pointerUp", (int16_t)LuaAtoms::pointerUp}, | |
| {"pointerMove", (int16_t)LuaAtoms::pointerMove}, | |
| {"pointerExit", (int16_t)LuaAtoms::pointerExit}, | |
| {"isNumber", (int16_t)LuaAtoms::isNumber}, | |
| {"isString", (int16_t)LuaAtoms::isString}, | |
| {"isBoolean", (int16_t)LuaAtoms::isBoolean}, | |
| {"isColor", (int16_t)LuaAtoms::isColor}, | |
| {"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}, | |
| {"paint", (int16_t)LuaAtoms::paint}, | |
| {"asPath", (int16_t)LuaAtoms::asPath}, | |
| {"asPaint", (int16_t)LuaAtoms::asPaint}, | |
| {"addToPath", (int16_t)LuaAtoms::addToPath}, | |
| {"positionAndTangent", (int16_t)LuaAtoms::positionAndTangent}, | |
| {"warp", (int16_t)LuaAtoms::warp}, | |
| {"extract", (int16_t)LuaAtoms::extract}, | |
| {"next", (int16_t)LuaAtoms::next}, | |
| {"isClosed", (int16_t)LuaAtoms::isClosed}, | |
| {"markNeedsUpdate", (int16_t)LuaAtoms::markNeedsUpdate}, | |
| {"viewModel", (int16_t)LuaAtoms::viewModel}, | |
| {"rootViewModel", (int16_t)LuaAtoms::rootViewModel}, | |
| {"globalViewModel", (int16_t)LuaAtoms::globalViewModel}, | |
| {"globalViewModelNames", (int16_t)LuaAtoms::globalViewModelNames}, | |
| {"dataContext", (int16_t)LuaAtoms::dataContext}, | |
| {"image", (int16_t)LuaAtoms::image}, | |
| {"blob", (int16_t)LuaAtoms::blob}, | |
| {"size", (int16_t)LuaAtoms::size}, | |
| {"name", (int16_t)LuaAtoms::name}, | |
| {"duration", (int16_t)LuaAtoms::duration}, | |
| {"setTime", (int16_t)LuaAtoms::setTime}, | |
| {"setTimeFrames", (int16_t)LuaAtoms::setTimeFrames}, | |
| {"setTimePercentage", (int16_t)LuaAtoms::setTimePercentage}, | |
| {"isPointerEvent", (int16_t)LuaAtoms::isPointerEvent}, | |
| {"isKeyboardEvent", (int16_t)LuaAtoms::isKeyboardEvent}, | |
| {"isTextInput", (int16_t)LuaAtoms::isTextInput}, | |
| {"previousPosition", (int16_t)LuaAtoms::previousPosition}, | |
| {"timeStamp", (int16_t)LuaAtoms::timeStamp}, | |
| {"isFocus", (int16_t)LuaAtoms::isFocus}, | |
| {"isReportedEvent", (int16_t)LuaAtoms::isReportedEvent}, | |
| {"isViewModelChange", (int16_t)LuaAtoms::isViewModelChange}, | |
| {"isNone", (int16_t)LuaAtoms::isNone}, | |
| {"isGamepadConnected", (int16_t)LuaAtoms::isGamepadConnected}, | |
| {"isGamepadEvent", (int16_t)LuaAtoms::isGamepadEvent}, | |
| {"isGamepadDisconnected", (int16_t)LuaAtoms::isGamepadDisconnected}, | |
| {"asPointerEvent", (int16_t)LuaAtoms::asPointerEvent}, | |
| {"asKeyboardEvent", (int16_t)LuaAtoms::asKeyboardEvent}, | |
| {"asTextInput", (int16_t)LuaAtoms::asTextInput}, | |
| {"asFocus", (int16_t)LuaAtoms::asFocus}, | |
| {"asReportedEvent", (int16_t)LuaAtoms::asReportedEvent}, | |
| {"asViewModelChange", (int16_t)LuaAtoms::asViewModelChange}, | |
| {"asGamepadConnected", (int16_t)LuaAtoms::asGamepadConnected}, | |
| {"asGamepadEvent", (int16_t)LuaAtoms::asGamepadEvent}, | |
| {"asGamepadDisconnected", (int16_t)LuaAtoms::asGamepadDisconnected}, | |
| {"gamepadEvent", (int16_t)LuaAtoms::gamepadEvent}, | |
| {"gamepadConnected", (int16_t)LuaAtoms::gamepadConnected}, | |
| {"gamepadDisconnected", (int16_t)LuaAtoms::gamepadDisconnected}, | |
| {"asNone", (int16_t)LuaAtoms::asNone}, | |
| {"key", (int16_t)LuaAtoms::key}, | |
| {"shift", (int16_t)LuaAtoms::shift}, | |
| {"alt", (int16_t)LuaAtoms::alt}, | |
| {"control", (int16_t)LuaAtoms::control}, | |
| {"meta", (int16_t)LuaAtoms::meta}, | |
| {"text", (int16_t)LuaAtoms::text}, | |
| {"phase", (int16_t)LuaAtoms::phase}, | |
| {"delaySeconds", (int16_t)LuaAtoms::delaySeconds}, | |
| {"deviceId", (int16_t)LuaAtoms::deviceId}, | |
| {"buttonMask", (int16_t)LuaAtoms::buttonMask}, | |
| {"remove", (int16_t)LuaAtoms::remove}, | |
| {"removeAt", (int16_t)LuaAtoms::removeAt}, | |
| {"removeAllOf", (int16_t)LuaAtoms::removeAllOf}, | |
| {"axes", (int16_t)LuaAtoms::axes}, | |
| {"gamepadMapping", (int16_t)LuaAtoms::gamepadMapping}, | |
| {"mapping", (int16_t)LuaAtoms::mapping}, | |
| {"isStandardMapping", (int16_t)LuaAtoms::isStandardMapping}, | |
| {"buttons", (int16_t)LuaAtoms::buttons}, | |
| {"buttonPressed", (int16_t)LuaAtoms::buttonPressed}, | |
| {"buttonValue", (int16_t)LuaAtoms::buttonValue}, | |
| {"axis", (int16_t)LuaAtoms::axis}, | |
| {"west", (int16_t)LuaAtoms::west}, | |
| {"south", (int16_t)LuaAtoms::south}, | |
| {"north", (int16_t)LuaAtoms::north}, | |
| {"east", (int16_t)LuaAtoms::east}, | |
| {"leftShoulder", (int16_t)LuaAtoms::leftShoulder}, | |
| {"rightShoulder", (int16_t)LuaAtoms::rightShoulder}, | |
| {"back", (int16_t)LuaAtoms::gamepadBack}, | |
| {"forward", (int16_t)LuaAtoms::gamepadForward}, | |
| {"leftStickButton", (int16_t)LuaAtoms::leftStickButton}, | |
| {"rightStickButton", (int16_t)LuaAtoms::rightStickButton}, | |
| {"dpadUp", (int16_t)LuaAtoms::dpadUp}, | |
| {"dpadDown", (int16_t)LuaAtoms::dpadDown}, | |
| {"dpadLeft", (int16_t)LuaAtoms::dpadLeft}, | |
| {"dpadRight", (int16_t)LuaAtoms::dpadRight}, | |
| {"start", (int16_t)LuaAtoms::start}, | |
| {"leftStick", (int16_t)LuaAtoms::leftStick}, | |
| {"rightStick", (int16_t)LuaAtoms::rightStick}, | |
| {"leftTrigger", (int16_t)LuaAtoms::leftTrigger}, | |
| {"rightTrigger", (int16_t)LuaAtoms::rightTrigger}, | |
| {"leftTriggerPressed", (int16_t)LuaAtoms::leftTriggerPressed}, | |
| {"rightTriggerPressed", (int16_t)LuaAtoms::rightTriggerPressed}, | |
| {"changeKind", (int16_t)LuaAtoms::changeKind}, | |
| {"changeIndex", (int16_t)LuaAtoms::changeIndex}, | |
| {"changeValue", (int16_t)LuaAtoms::changeValue}, | |
| {"hasStandardButtonIntent", (int16_t)LuaAtoms::hasStandardButtonIntent}, | |
| {"hasStandardAxisIntent", (int16_t)LuaAtoms::hasStandardAxisIntent}, | |
| {"intentButton", (int16_t)LuaAtoms::intentButton}, | |
| {"intentAxis", (int16_t)LuaAtoms::intentAxis}, | |
| {"audio", (int16_t)LuaAtoms::audio}, | |
| {"play", (int16_t)LuaAtoms::play}, | |
| {"playAtTime", (int16_t)LuaAtoms::playAtTime}, | |
| {"playInTime", (int16_t)LuaAtoms::playInTime}, | |
| {"playAtFrame", (int16_t)LuaAtoms::playAtFrame}, | |
| {"playInFrame", (int16_t)LuaAtoms::playInFrame}, | |
| {"stop", (int16_t)LuaAtoms::stop}, | |
| {"pause", (int16_t)LuaAtoms::pause}, | |
| {"resume", (int16_t)LuaAtoms::resume}, | |
| {"seek", (int16_t)LuaAtoms::seek}, | |
| {"seekFrame", (int16_t)LuaAtoms::seekFrame}, | |
| {"volume", (int16_t)LuaAtoms::volume}, | |
| {"completed", (int16_t)LuaAtoms::completed}, | |
| {"time", (int16_t)LuaAtoms::time}, | |
| {"timeFrame", (int16_t)LuaAtoms::timeFrame}, | |
| {"sampleRate", (int16_t)LuaAtoms::sampleRate}, | |
| // GPU | |
| {"write", (int16_t)LuaAtoms::write}, | |
| {"upload", (int16_t)LuaAtoms::upload}, | |
| {"view", (int16_t)LuaAtoms::view}, | |
| {"setPipeline", (int16_t)LuaAtoms::setPipeline}, | |
| {"setVertexBuffer", (int16_t)LuaAtoms::setVertexBuffer}, | |
| {"setIndexBuffer", (int16_t)LuaAtoms::setIndexBuffer}, | |
| {"setBindGroup", (int16_t)LuaAtoms::setBindGroup}, | |
| {"setViewport", (int16_t)LuaAtoms::setViewport}, | |
| {"setScissorRect", (int16_t)LuaAtoms::setScissorRect}, | |
| {"setStencilReference", (int16_t)LuaAtoms::setStencilReference}, | |
| {"drawIndexed", (int16_t)LuaAtoms::drawIndexed}, | |
| {"finish", (int16_t)LuaAtoms::finish}, | |
| {"beginRenderPass", (int16_t)LuaAtoms::beginRenderPass}, | |
| {"beginFrame", (int16_t)LuaAtoms::beginFrame}, | |
| {"endFrame", (int16_t)LuaAtoms::endFrame}, | |
| {"colorView", (int16_t)LuaAtoms::colorView}, | |
| {"depthView", (int16_t)LuaAtoms::depthView}, | |
| {"setBlendColor", (int16_t)LuaAtoms::setBlendColor}, | |
| {"resize", (int16_t)LuaAtoms::resize}, | |
| {"canvas", (int16_t)LuaAtoms::canvas}, | |
| {"gpuCanvas", (int16_t)LuaAtoms::gpuCanvas}, | |
| {"features", (int16_t)LuaAtoms::features}, | |
| {"shader", (int16_t)LuaAtoms::shader}, | |
| {"format", (int16_t)LuaAtoms::format}, | |
| {"andThen", (int16_t)LuaAtoms::andThen}, | |
| {"catch", (int16_t)LuaAtoms::catch_}, | |
| {"finally", (int16_t)LuaAtoms::finally_}, | |
| {"cancel", (int16_t)LuaAtoms::cancel}, | |
| {"onCancel", (int16_t)LuaAtoms::onCancel}, | |
| {"getStatus", (int16_t)LuaAtoms::getStatus}, | |
| {"decodeImage", (int16_t)LuaAtoms::decodeImage}, | |
| // Mat4 | |
| {"transpose", (int16_t)LuaAtoms::transpose}, | |
| {"transformPoint", (int16_t)LuaAtoms::transformPoint}, | |
| {"transformVec4", (int16_t)LuaAtoms::transformVec4}, | |
| {"writeToBuffer", (int16_t)LuaAtoms::writeToBuffer}, | |
| {"invertAffine", (int16_t)LuaAtoms::invertAffine}, | |
| // Vector | |
| {"writeVec4", (int16_t)LuaAtoms::writeVec4}, | |
| }; | |
| constexpr size_t atomCount = std::size(atoms); | |
| // Power of two so the modulo is a mask, and roomy enough to keep probes short. | |
| constexpr size_t atomSlotCount = 1024; | |
| static_assert(atomCount < atomSlotCount, | |
| "atomSlotCount must exceed the number of atoms"); | |
| constexpr uint32_t hashAtomName(std::string_view name) | |
| { | |
| uint32_t hash = 2166136261u; | |
| for (char c : name) | |
| { | |
| hash = (hash ^ (uint8_t)c) * 16777619u; | |
| } | |
| return hash; | |
| } | |
| constexpr size_t longestAtomName() | |
| { | |
| size_t longest = 0; | |
| for (const LuaAtomName& entry : atoms) | |
| { | |
| if (entry.name.size() > longest) | |
| { | |
| longest = entry.name.size(); | |
| } | |
| } | |
| return longest; | |
| } | |
| constexpr size_t maxAtomNameLength = longestAtomName(); | |
| // Slots hold an index into atoms biased by one so zero reads as empty. | |
| constexpr std::array<uint16_t, atomSlotCount> buildAtomSlots() | |
| { | |
| std::array<uint16_t, atomSlotCount> slots{}; | |
| for (size_t i = 0; i < atomCount; i++) | |
| { | |
| size_t slot = hashAtomName(atoms[i].name) & (atomSlotCount - 1); | |
| while (slots[slot] != 0 && atoms[slots[slot] - 1].name != atoms[i].name) | |
| { | |
| slot = (slot + 1) & (atomSlotCount - 1); | |
| } | |
| if (slots[slot] == 0) | |
| { | |
| slots[slot] = (uint16_t)(i + 1); | |
| } | |
| } | |
| return slots; | |
| } | |
| constexpr std::array<uint16_t, atomSlotCount> atomSlots = buildAtomSlots(); | |
| int16_t findAtom(const char* chars, size_t length) | |
| { | |
| if (length > maxAtomNameLength) | |
| { | |
| return -1; | |
| } | |
| std::string_view name(chars, length); | |
| size_t slot = hashAtomName(name) & (atomSlotCount - 1); | |
| for (uint16_t index = atomSlots[slot]; index != 0; | |
| index = atomSlots[slot = (slot + 1) & (atomSlotCount - 1)]) | |
| { | |
| if (atoms[index - 1].name == name) | |
| { | |
| return atoms[index - 1].atom; | |
| } | |
| } | |
| return -1; | |
| } | |
| } // namespace | |
| namespace rive | |
| { | |
| int16_t rive_lua_findAtom(const char* chars, size_t length) | |
| { | |
| return findAtom(chars, length); | |
| } | |
| } // namespace rive | |
| #endif |