Toast Engine
Loading...
Searching...
No Matches
script_runtime.hpp
Go to the documentation of this file.
1
11
12#pragma once
13
14#include <any>
15#include <atomic>
16#include <cstdint>
17#include <lua.hpp>
18#include <luabridge3/LuaBridge/LuaBridge.h>
19#include <memory>
20#include <optional>
21#include <set>
22#include <span>
23#include <string>
24#include <string_view>
26#include <toast/export.hpp>
28#include <toast/scripting/lua_signal.hpp>
32#include <toast/world/box.hpp>
33#include <unordered_map>
34#include <vector>
35
36namespace toast {
37class Node;
38}
39
40namespace scripting {
41
43struct ScriptBinding {
44 explicit ScriptBinding(NodeProxy node_proxy) : proxy(std::move(node_proxy)) { }
45
46 NodeProxy proxy;
47 std::atomic<bool> alive {true};
48};
49
50// One per script
51class ScriptInstance {
52public:
53 ScriptInstance(
54 size_t vm_index, lua_State* l, const assets::Handle<assets::Script>& script, NodeProxy proxy,
55 std::shared_ptr<RuntimeToken> token
56 );
57
60
61 ScriptInstance(ScriptInstance&&) = delete;
62 auto operator=(ScriptInstance&&) -> ScriptInstance& = delete;
63 ScriptInstance(const ScriptInstance&) = delete;
64 auto operator=(const ScriptInstance&) -> ScriptInstance& = delete;
65
67 void call(std::string_view fn_name) noexcept;
68
70 void callWithLuaStack(std::string_view name, lua_State* l, int args_base, int n_args) noexcept;
71
73 auto callEventMethod(std::string_view name, lua_State* l, int event_index) noexcept -> bool;
74
76 void callWithAnyArgs(std::string_view name, std::span<const std::any> args) noexcept;
77
80 auto setVar(std::string_view name, const std::any& value) noexcept -> bool;
81
83 [[nodiscard]]
84 auto getVar(std::string_view name) const noexcept -> std::any;
85
87 [[nodiscard]]
88 auto getVarByPath(std::string_view path) const noexcept -> std::any;
89
92 auto setVarByPath(std::string_view path, const std::any& value) noexcept -> bool;
93
95 [[nodiscard]]
96 auto hasFunction(std::string_view fn_name) const noexcept -> bool;
97
99 [[nodiscard]]
100 auto knowsFunction(std::string_view fn_name) const noexcept -> bool {
101 return m_function_names.contains(fn_name);
102 }
103
104 [[nodiscard]]
105 auto luaSignals() const noexcept -> const std::unordered_map<std::string, LuaSignal>& {
106 return m_lua_signals;
107 }
108
109 [[nodiscard]]
110 auto luaSignals() noexcept -> std::unordered_map<std::string, LuaSignal>& {
111 return m_lua_signals;
112 }
113
114 [[nodiscard]]
115 auto schema() const noexcept -> const ScriptSchema& {
116 return m_schema;
117 }
118
120 [[nodiscard]]
121 auto isValid() const noexcept -> bool {
122 return m_valid;
123 }
124
126 [[nodiscard]]
127 auto tickMask() const noexcept -> toast::TickFunctionList {
128 return m_tick_mask;
129 }
130
132 [[nodiscard]]
133 auto name() const noexcept -> const std::string& {
134 return m_name;
135 }
136
137private:
138 lua_State* m_state = nullptr;
139 size_t m_vm_index = 0;
140 std::shared_ptr<ScriptBinding> m_binding;
141 std::shared_ptr<RuntimeToken> m_token;
142 std::unique_ptr<luabridge::LuaRef> m_self;
143 bool m_valid = false;
144 std::string m_name;
145 ScriptSchema m_schema;
146 std::unordered_map<std::string, LuaSignal> m_lua_signals;
147 std::set<std::string, std::less<>>
148 m_function_names;
149 toast::TickFunctionList m_tick_mask = toast::TickFunctionList::none;
150
151 void installMetatable() noexcept;
152 void extractSchema(std::string_view src) noexcept;
153 void snapshotTickMask() noexcept;
154
156 [[nodiscard]]
157 auto pushByPath(std::string_view path) const noexcept -> bool;
158};
159
161[[nodiscard]]
162auto nodeOfSelfTable(const luabridge::LuaRef& table) -> NodeProxy;
163
164// One per node
165class TOAST_API ScriptRuntime {
166public:
173 toast::Box<toast::Node> node, const std::vector<assets::Handle<assets::Script>>& scripts, uint64_t group = 0,
174 std::optional<size_t> placed = std::nullopt
175 );
177
178 ScriptRuntime(const ScriptRuntime&) = delete;
179 auto operator=(const ScriptRuntime&) -> ScriptRuntime& = delete;
180
182 void call(toast::TickFunctionList phase) noexcept;
183
185 void call(std::string_view fn_name) noexcept;
186
188 [[nodiscard]]
189 auto hasFunction(std::string_view fn_name) const noexcept -> bool;
190
191 [[nodiscard]]
192 auto functions() const noexcept -> std::vector<LuaFunctionDesc>;
193
194 void callWithLuaStack(std::string_view name, lua_State* l, int args_base, int n_args) noexcept;
195 auto callEventMethod(std::string_view name, lua_State* l, int event_index) noexcept -> bool;
196
198 void callWithAnyArgs(std::string_view name, std::span<const std::any> args) noexcept;
199
201 void setVar(std::string_view name, const std::any& value) noexcept;
202
204 [[nodiscard]]
205 auto getVar(std::string_view name) const noexcept -> std::any;
206
207 [[nodiscard]]
208 auto luaSignals() const -> std::vector<std::string>;
209 [[nodiscard]]
210 auto luaSignalConnections(std::string_view name) const -> std::vector<signals::ConnectionInfo>;
211 [[nodiscard]]
212 auto luaSignalArgTypes(std::string_view name) const -> std::vector<std::string>;
213 auto connectLuaSignal(std::string_view name, toast::Node& target, std::string_view function, bool forwards_args) -> bool;
214 auto disconnectLuaSignal(std::string_view name, toast::Node& target, std::string_view function) -> bool;
215 void clearLuaSignal(std::string_view name);
216
218 [[nodiscard]]
219 auto instanceCount() const noexcept -> size_t {
220 return m_instances.size();
221 }
222
224 [[nodiscard]]
225 auto instanceSchema(size_t index) const noexcept -> const ScriptSchema*;
226
228 [[nodiscard]]
229 auto instanceScript(size_t index) const noexcept -> std::string_view;
230
232 [[nodiscard]]
233 auto getVarByPath(size_t index, std::string_view path) const noexcept -> std::any;
234
236 auto setVarByPath(size_t index, std::string_view path, const std::any& value) noexcept -> bool;
237
239 [[nodiscard]]
240 auto schemaVersion() const noexcept -> uint32_t {
241 return m_schema_version;
242 }
243
245 [[nodiscard]]
246 auto hasTick(toast::TickFunctionList mask = toast::TickFunctionList::tick_mask) const noexcept -> bool {
247 return (m_tick_mask & mask) != toast::TickFunctionList::none;
248 }
249
251 [[nodiscard]]
252 auto stateIndex() const noexcept -> size_t {
253 return m_state_index;
254 }
255
257 [[nodiscard]]
258 auto token() const noexcept -> const std::shared_ptr<RuntimeToken>& {
259 return m_token;
260 }
261
263 [[nodiscard]]
264 auto executing() const noexcept -> bool {
265 return m_active_calls.load(std::memory_order_acquire) != 0;
266 }
267
274 static void retire(std::unique_ptr<ScriptRuntime> runtime) noexcept;
275
277 static void drainRetired() noexcept;
278
279private:
280 std::vector<std::unique_ptr<ScriptInstance>> m_instances;
281 size_t m_state_index = 0;
282 uint64_t m_group = 0;
283 bool m_placed = false;
284 lua_State* m_lua = nullptr;
285 toast::Box<toast::Node> m_node;
286 std::shared_ptr<RuntimeToken> m_token;
287 toast::TickFunctionList m_tick_mask = toast::TickFunctionList::none;
288 uint32_t m_schema_version = 0;
289 mutable std::atomic<int> m_active_calls {0};
290
292 template<typename F>
293 void deferToDispatch(F&& work) const;
294};
295
296}
pseudo shared pointer for Nodes
Type-safe smart pointer for assets.
Definition core_types.hpp:149
Definition lua_signal.hpp:12
Definition node_proxy.hpp:55
Definition script_runtime.hpp:51
auto tickMask() const noexcept -> toast::TickFunctionList
Tick phases this script defines.
Definition script_runtime.hpp:127
auto getVar(std::string_view name) const noexcept -> std::any
Reads the instance variable named name.
Definition script_runtime.cpp:891
void callWithLuaStack(std::string_view name, lua_State *l, int args_base, int n_args) noexcept
rawget self[name]; if a function, pcall(self, forwarded_args...)
Definition script_runtime.cpp:680
auto isValid() const noexcept -> bool
Cached at load, never touches the interpreter.
Definition script_runtime.hpp:121
auto setVar(std::string_view name, const std::any &value) noexcept -> bool
Definition script_runtime.cpp:786
void callWithAnyArgs(std::string_view name, std::span< const std::any > args) noexcept
Fan-out call with args provided as std::any values.
Definition script_runtime.cpp:746
void call(std::string_view fn_name) noexcept
Calls the named lifecycle function.
Definition script_runtime.cpp:646
auto getVarByPath(std::string_view path) const noexcept -> std::any
Reads a variable through its schema path.
Definition script_runtime.cpp:839
auto setVarByPath(std::string_view path, const std::any &value) noexcept -> bool
Definition script_runtime.cpp:850
auto knowsFunction(std::string_view fn_name) const noexcept -> bool
True when the script defined a function with this name when it was loaded; touches no interpreter.
Definition script_runtime.hpp:100
auto name() const noexcept -> const std::string &
Asset path of the script.
Definition script_runtime.hpp:133
~ScriptInstance()
The owner of the interpreter has to run this, it releases registry references.
Definition script_runtime.cpp:433
auto callEventMethod(std::string_view name, lua_State *l, int event_index) noexcept -> bool
Calls a lua method on the self table.
Definition script_runtime.cpp:715
auto hasFunction(std::string_view fn_name) const noexcept -> bool
Returns true if the self table has a callable field with this name. Needs the interpreter.
Definition script_runtime.cpp:909
auto schemaVersion() const noexcept -> uint32_t
Unique for every runtime that was ever built, so it also tells a rebuilt runtime from the one it repl...
Definition script_runtime.hpp:240
ScriptRuntime(toast::Box< toast::Node > node, const std::vector< assets::Handle< assets::Script > > &scripts, uint64_t group=0, std::optional< size_t > placed=std::nullopt)
Definition script_runtime.cpp:992
auto stateIndex() const noexcept -> size_t
Index of the pooled Lua state this runtime is bound to.
Definition script_runtime.hpp:252
auto token() const noexcept -> const std::shared_ptr< RuntimeToken > &
Flips to dead as the runtime is torn down. Everything that calls into the scripts later holds it.
Definition script_runtime.hpp:258
auto hasTick(toast::TickFunctionList mask=toast::TickFunctionList::tick_mask) const noexcept -> bool
True if any instance defines a function matching the given phases.
Definition script_runtime.hpp:246
auto executing() const noexcept -> bool
True while a call into this runtime is on some thread's stack.
Definition script_runtime.hpp:264
auto instanceCount() const noexcept -> size_t
Number of attached script instances.
Definition script_runtime.hpp:219
Intrusive reference-counted handle to a Node.
Definition box.hpp:35
Definition node.hpp:81
Lua-side proxy for a toast::Node.
TickFunctionList
Bit-flag set describing which lifecycle phases a Node type implements.
Definition reflect_node.hpp:36
Lua source asset attached to nodes through Node::m_scripts.
Tracks the script that is executing on the current thread.
Description of a script's exported variables for the inspector.
Lifetime marker of one ScriptRuntime.
Definition script_context.hpp:29
std::atomic< bool > alive
false once the instance is destroyed
Definition script_runtime.hpp:47
Definition script_schema.hpp:66