Lua Bindings

Gsage::GsageFacade::initialize() initializes Lua state in the engine. This is a single global Lua state for the whole engine (At least for now it’s single).

Gsage::LuaInterface binds the Core bindings:

  • bindings for entity and engine wrappers.

  • Gsage::GsageFacade bindings like Gsage::GsageFacade::shutdown().

  • Gsage::GameDataManager bindings.

  • and others.

Sol2 library is used for Lua bindings.

Besides bindings, LuaInterface initializes global variables:

  • core - Gsage::Engine instance.

  • game - Gsage::GsageFacade instance.

  • data - Gsage::GameDataManager instance.

  • log - provides easylogging++ API to lua.

Any script can be executed by calling Gsage::LuaInterface::runScript(). startupScript configuration variable can be used to define script which will be executed after Gsage::GsageFacade initialization.

LuaInterface also runs packager script.

Bindings Guidelines

All Core bindings are located in the LuaInterface file. If any plug-in needs to add some Lua bindings, it should override Gsage::IPlugin::setupLuaBindings method. Plug-in can access Lua state by using mLuaInterface->getSolState() function. It will return pointer to sol::state_view.

Note

Note that the pointer to Sol2 state can be 0 if the LuaInterface was not initialized by calling Gsage::LuaInterface::initialize().

Bind Engine Systems

If you create a new engine system, you may want to access it from Lua. Systems can be added dynamically at any point and Gsage::Engine functions should be updated in the runtime:

lua["Engine"]["script"] = &Engine::getSystem<LuaScriptSystem>;

This way, when a plugin registers a new system, it will also update Gsage::Engine to have getter for this system: core:script().

So, if you add a new system, you will need to create a new binding like this:

lua.new_usertype<KittySystem>("KittySystem"
  "getKitten", &KittySystem::getKitten
);

lua["Engine"]["kitty"] = &Engine::getSystem<KittySystem>;

After you make this binding, you will be able to get the system instance:

s = core:kitty()
s:getKitten()

Bind Entity Components

When registering a new Component, you should also update Gsage::Entity functions and add the getter for the new Component in the same way as for the new System, but instead of Engine binding, you should use Entity:

lua.new_usertype<KittyComponent>("KittyComponent"
  "meow", &KittyComponent::meow
);

lua["Entity"]["kitty"] = &Entity::getComponent<KittyComponent>;

After that it will be possible to get Component from Entity instance by using newly registered getter:

e = eal:getEntity("cat")
cat.kitty:meow()

Bind Events

Events can be handled in Lua script in two ways:

  • event:bind(...) will bind generic callback. You can use it if you do not need upcasting from Gsage::Event to derived event type.

  • event:<handlerID>(...) will bind callback specifically for some concrete type of event.

If you use bind, you will not be able to access derived class methods or variables:

local onSelect = function(event)
  print(e.hasFlags) -- prints nil
end

event:bind(core, "objectSelected", onSelect)

To listen for any specific event type use event:<handlerID>.

handlerID is defined when binding a new event type:

registerEvent<SelectEvent>("SelectEvent",
    "onSelect", // <-- handlerID
    sol::base_classes, sol::bases<Event>(),
    "hasFlags", &SelectEvent::hasFlags,
    "entity", sol::property(&SelectEvent::getEntityId),
);

To handle Gsage::SelectEvent in Lua:

local onSelect = function(event)
  -- you will be able to access derived class methods
  print(e:hasFlags(OgreSceneNode.DYNAMIC))
end

event:onSelect(core, "objectSelected", onSelect)