blob: ae41646af33677173ad56fa8f336401319b7eaea [file] [log] [blame] [edit]
#ifndef _RIVE_SCRIPT_ASSET_HPP_
#define _RIVE_SCRIPT_ASSET_HPP_
#ifdef WITH_RIVE_SCRIPTING
#include "rive/lua/rive_lua_libs.hpp"
#endif
#include "rive/file.hpp"
#include "rive/generated/assets/script_asset_base.hpp"
#include "rive/simple_array.hpp"
#include <stdio.h>
namespace rive
{
class Artboard;
class Component;
class DataBind;
class ScriptedObject;
enum ScriptProtocol
{
utility,
node,
layout,
converter,
pathEffect
};
#ifdef WITH_RIVE_SCRIPTING
class ScriptAssetImporter;
#endif
class ScriptInput
{
protected:
ScriptedObject* m_scriptedObject = nullptr;
DataBind* m_dataBind = nullptr;
public:
virtual ~ScriptInput() {};
virtual void initScriptedValue();
virtual bool validateForScriptInit() = 0;
static ScriptInput* from(Core* component);
DataBind* dataBind() { return m_dataBind; }
void dataBind(DataBind* dataBind) { m_dataBind = dataBind; }
ScriptedObject* scriptedObject() { return m_scriptedObject; }
void scriptedObject(ScriptedObject* object) { m_scriptedObject = object; }
};
class OptionalScriptedMethods
{
private:
static const int m_advancesBit = 1 << 0;
static const int m_updatesBit = 1 << 1;
static const int m_measuresBit = 1 << 2;
static const int m_wantsPointerDownBit = 1 << 3;
static const int m_wantsPointerMoveBit = 1 << 4;
static const int m_wantsPointerUpBit = 1 << 5;
static const int m_wantsPointerExitBit = 1 << 6;
static const int m_wantsPointerCancelBit = 1 << 7;
static const int m_drawsBit = 1 << 8;
static const int m_initsBit = 1 << 9;
int m_implementedMethods = 0;
protected:
bool verifyImplementation(ScriptedObject* object, LuaState* luaState);
public:
int implementedMethods() { return m_implementedMethods; }
void implementedMethods(int implemented)
{
m_implementedMethods = implemented;
}
bool listensToPointerEvents()
{
return (m_implementedMethods &
(m_wantsPointerDownBit | m_wantsPointerMoveBit |
m_wantsPointerUpBit | m_wantsPointerExitBit |
m_wantsPointerCancelBit)) != 0;
}
bool advances() { return (m_implementedMethods & m_advancesBit) != 0; }
bool updates() { return (m_implementedMethods & m_updatesBit) != 0; }
bool measures() { return (m_implementedMethods & m_measuresBit) != 0; }
bool wantsPointerDown()
{
return (m_implementedMethods & m_wantsPointerDownBit) != 0;
}
bool wantsPointerMove()
{
return (m_implementedMethods & m_wantsPointerMoveBit) != 0;
}
bool wantsPointerUp()
{
return (m_implementedMethods & m_wantsPointerUpBit) != 0;
}
bool wantsPointerExit()
{
return (m_implementedMethods & m_wantsPointerExitBit) != 0;
}
bool wantsPointerCancel()
{
return (m_implementedMethods & m_wantsPointerCancelBit) != 0;
}
bool draws() { return (m_implementedMethods & m_drawsBit) != 0; }
bool inits() { return (m_implementedMethods & m_initsBit) != 0; }
};
class ModuleDetails
{
public:
virtual ~ModuleDetails() = default;
virtual std::string moduleName() = 0;
virtual void registrationComplete(int ref) {}
virtual Span<uint8_t> moduleBytecode() { return Span<uint8_t>(); }
virtual bool isProtocolScript() = 0;
virtual bool verified() const { return false; }
void addMissingDependency(std::string name) { m_dependencies.insert(name); }
void clearMissingDependency(std::string name)
{
auto it = m_dependencies.find(name);
if (it != m_dependencies.end())
{
m_dependencies.erase(it);
}
}
std::unordered_set<std::string> missingDependencies()
{
return m_dependencies;
}
private:
std::unordered_set<std::string> m_dependencies;
};
class ScriptAsset : public ScriptAssetBase,
public OptionalScriptedMethods,
public ModuleDetails
{
public:
#ifdef WITH_RIVE_SCRIPTING
friend class ScriptAssetImporter;
bool verified() const override { return m_verified; }
Span<uint8_t> moduleBytecode() override { return m_bytecode; }
#endif
bool initScriptedObject(ScriptedObject* object);
/// Sets the bytecode from data with header format:
/// [flags:1] [signature:64 if signed] [luau_bytecode:N]
/// Flags byte: bits 0-6 = version, bit 7 = isSigned
/// Returns true if bytecode was set (verification is separate from return).
bool bytecode(Span<uint8_t> data);
/// Bytecode provided via decode should only happen with in-band bytecode.
/// The signature will later be verified once file loading completes, so it
/// is immediately marked as unverified.
bool decode(SimpleArray<uint8_t>& data, Factory* factory) override;
std::string fileExtension() const override { return "lua"; }
void file(File* value) { m_file = value; }
File* file() const { return m_file; }
#ifdef WITH_RIVE_SCRIPTING
LuaState* vm();
void registrationComplete(int ref) override;
#endif
std::string moduleName() override { return name(); }
bool isProtocolScript() override { return !isModule(); }
private:
File* m_file = nullptr;
#ifdef WITH_RIVE_SCRIPTING
bool m_scriptRegistered = false;
bool m_verified = false;
SimpleArray<uint8_t> m_bytecode;
bool m_initted = false;
#endif
bool initScriptedObjectWith(ScriptedObject* object);
};
} // namespace rive
#endif