- EnTT v.3.9.0 (latest)
- sol2 v3.2.2 (latest)
> git clone https://github.com/skaarj1989/entt-meets-sol2.git
> cd entt-meets-sol2
> cmake -S . -B build
https://github.com/microsoft/vcpkg#getting-started
> git clone https://github.com/microsoft/vcpkg
> ./vcpkg/bootstrap-vcpkg.bat
Add the following environment variables
VCPKG_ROOT=path_to_vcpkg
VCPKG_DEFAULT_TRIPLET=x64-windows
Install required dependencies
> ./vcpkg install entt sol2 lua
- Expose
registry
to Lua scripts:- Manage entity lifetime
- Set components
- Get component by reference
runtime_view
- Some of MonoBehaviour functionality
struct Transform { int x, y; };
register_meta_component<Transform>();
sol::state lua{};
lua.require("dispatcher" ...);
lua.new_usertype<Transform>("Transform",
"type_id", &entt::type_hash<Transform>::value,
sol::call_constructor,
sol::factories([](int x, int y) {
return Transform{ x, y };
}),
"x", &Transform::x,
"y", &Transform::y
);
entt::registry registry{};
lua["registry"] = std::ref(registry); // Make the registry available to Lua
-- Create a registry inside a script
registry = entt.registry.new()
mario = registry:create()
registry:emplace(mario, Transform(1, 2))
material = registry:get(mario, Material)
if (registry:has(mario, Transform)) then
registry:emplace(mario, DeletionFlag())
end
-- Utilizes variadic args - pass as many types as you want
registry:runtime_view(Transform, DeletionFlag):each(
function(entity)
registry:remove(entity, DeletionFlag)
end
)
Want something like MonoBehaviour in Unity? examples/system
local node = {}
function node:init()
self.owner:emplace(self.id(), Transform(5, 9))
end
function node:update(dt)
local transform = self.owner:get(self.id(), Transform)
transform.x = transform.x + 1
end
function node:destroy()
-- ...
end
return node
struct ScriptComponent {
sol::table self;
struct {
sol::function update;
} hooks;
};
registry.emplace<ScriptComponent>(entity, lua.script_file("behavior.lua"));
while (true) {
auto view = registry.view<ScriptComponent>();
for (auto entity : view) {
auto &script = view.get<ScriptComponent>(entity);
script.hooks.update(script.self, delta_time);
}
}
- Either create new (inside script) or connect existing (native c++) dispatcher
- Trigger/enqueue events from Lua side
- Listen for events in Lua scripts
- Support disconnection of listeners
struct an_event { int value; };
register_meta_event<an_event>();
sol::state lua{}
lua.require("dispatcher", ...)
lua.new_usertype<an_event>("an_event",
"type_id", &entt::type_hash<an_event>::value,
sol::call_constructor,
sol::factories([](int value) {
return an_event{ value };
}),
"value", &an_event::value
);
entt::dispatcher dispatcher{};
lua["dispatcher"] = std::ref(dispatcher); // Make the dispatcher available to Lua
// load a script ...
dispatcher.update(); // inside loop
-- Create a dispatcher in a script
dispatcher = entt.dispatcher.new()
listener = {}
function listener.receive(evt)
-- ...
end
function listener.method(evt)
-- ...
end
-- You have to store result of 'connect()', otherwise listener will be
-- disconnected in lua garbage collection step.
conn = dispatcher:connect(an_event, listener.receive)
dispatcher:connect(another_event, listener.method)
-- Event type is deduced from bound 'type_id()' method
dispatcher:trigger(an_event(42))
dispatcher:enqueue(another_event())
conn = nil -- to disconnect listener
entt/wiki/cooperative-scheduler
- Define process class in Lua and attach it to
scheduler
either native c++ or dedicated to script - Allow process chaining
sol::state lua{};
lua.require("scheduler", ...);
entt::scheduler scheduler{};
lua["scheduler"] = std::ref(scheduler); // Make the scheduler available to Lua
scheduler.update(dt); // inside loop
-- Create a scheduler in a script
scheduler = entt.scheduler.new()
local process_a = {}
function process:update(dt)
-- ...
end
-- define init, succeeded and other methods ...
-- This one differs from entt attach().then().then ... but works the same
scheduler:attach(
process_a,
process_b,
process_n
-- etc ...
)
Code released under CC0 1.0 Universal