-
Notifications
You must be signed in to change notification settings - Fork 433
Lua scripting
Calls from Lua to engine are not checked, they might crash if called incorrectly.
Lua script plugin provides an option to script using Lua. It provides a new type of component, which points to a lua script file. This file is executed when a game starts. Each component has lua sandboxed - it means that all variables and function are not accessible from other components unless they are put in the global table _G or accessed using entity.lua_script[idx]
Each script can contain function update(dt) and this function is called each frame.
function LumixAPI.logError(msg)
function LumixAPI.instantiatePrefab(universe, position, prefab)Example:
ext_prefab = -1
Editor.setPropertyType(this, "ext_prefab", Editor.RESOURCE_PROPERTY, "prefab")
-- alternative
-- local ext_prefab = LumixAPI.loadResource(LumixAPI.engine, "models/cube.fab", "prefab")
function start()
local s = 20
for i = 1, s do
for j = 1, s do
for k = 1, s do
local position = { i * 3, j * 3, k* 3 }
LumixAPI.instantiatePrefab(Lumix.main_universe, position, ext_prefab)
end
end
end
endLumix.Universe = {}
function Lumix.Universe:create()
function Lumix.Universe:destroy()
function Lumix.Universe:load(path, callback_fn)
function Lumix.Universe:createEntity()
function Lumix.Universe:createEntityEx(desc)
function Lumix.Universe:findEntityByName(parent, name)
-- `Main` universe can be accessed through `Lumix.main_universe`Lumix.Entity = {}
function Lumix.Entity:new(_universe, _entity)
function Lumix.Entity:destroy()
function Lumix.Entity:createComponent(cmp)
function Lumix.Entity:getComponent(cmp)
-- properties
local e = universe:createEntity()
-- e.universe == universe
e.name = "new name"
e.position = {1, 2, 3} -- vec3 x, y, z
e.rotation = {0, 0, 0, 1} -- quaternion x, y, z, w
e.scale = 1.0Components are directly exposed as properties of entity
-- e is entity
e.gui_rect.top_points = 50
-- is the same as
e.getComponent("gui_rect").top_points = 50A new lua object is created every time component is accessed this way, so cache the component to avoid the performance hit
local rect = e.gui_rect
rect.top_points = 50
rect.top_relative = 0.5You can access environments of other script like this:
local env = e.lua_script[script_index]Every Vec3, color, decimal, integer and boolean property (you can see properties in the property grid in the editor) can be accessed from Lua. However name of a property is transformed in following way:
- convert to lowercase
- replace all nonalphanumeric characters with
_,
For example:
-- property Fog color
-- "this" is current Entity accessible in from lua
local e = this.universe:createEntity()
local c = e:createComponent("environment")
c.fog_color = {1, 0, 1}Other than standard lua types there following types:
- Vec3 - a table with 3 numbers
- Quat - a table with 4 numbers
LumixAPI.INPUT_DEVICE_KEYBOARDLumixAPI.INPUT_DEVICE_MOUSELumixAPI.INPUT_DEVICE_CONTROLLERLumixAPI.INPUT_EVENT_BUTTONLumixAPI.INPUT_EVENT_AXISLumixAPI.INPUT_EVENT_DEVICE_ADDEDLumixAPI.INPUT_EVENT_DEVICE_REMOVED- scancodes
- keycodes
onInputEvent function is called on every input event.
-- event = {
-- device = {
-- type = ..., -- e.g. LumixAPI.INPUT_DEVICE_KEYBOARD
-- index = ..., -- number
-- },
-- down ..., -- boolean, valid only in case of button events
-- type = ..., -- e.g. LumixAPI.INPUT_EVENT_BUTTON
-- scancode = ..., -- see the list of scancodes, only valid for keyboard events
-- key_id = ..., -- id of button/key
-- x = ..., -- number
-- y = ..., -- number
-- x_abs = ..., -- number
-- y_abs = ... -- number
-- }
function onInputEvent(event)
if event.type == LumixAPI.INPUT_EVENT_BUTTON then
if event.device.type == LumixAPI.INPUT_DEVICE_KEYBOARD then
if event.key_id == LumixAPI.INPUT_KEYCODE_UP then
LumixAPI.logInfo("keyboard button event")
end
end
elseif event.type == LumixAPI.INPUT_EVENT_AXIS then
if event.device.type == LumixAPI.INPUT_DEVICE_MOUSE then
yaw = yaw + event.x * -0.005;
pitch = pitch + event.y * -0.005;
end
end
endIf two entities with a physical component collide, onContact function is called in script on both of them:
function onContact(entity)
endIf a physical entity enters a trigger, onTrigger function is called in script on both of them:
function onTrigger(other_entity, touch_lost)
endfunction onPathFinished() ...Lua function onPathFinished is called on an entity which finished its path.
Following dear imgui functions are available in lua:
bool, number ImGui.DragFloat(string label, number value)bool ImGui.Button(string label)bool, bool ImGui.Checkbox(string label, bool checked)void ImGui.Text(string text)void ImGui.SameLine()bool ImGui.BeginPopup(string str_id)void ImGui.EndPopup()bool ImGui.OpenPopup(string str_id)bool ImGui.BeginDock(string str_id)void ImGui.EndDock()bool ImGui.Begin(string str_id)void ImGui.End()void ImGui.Image(ImTextureID texture_id, number width, number height)
In case of imgui function changing one of its pointer parameters, Lua returns two values, one bool (true if the value is changed, false otherwise) and the new value. For example the return value from ImGui::Checbox(const char* label, bool* value) C function is the first return value from Lua function and the new *value is the second return value from Lua function.
x = 0
checked = true
function onGUI()
-- button
if ImGui.Button("Test") then
LumixAPI.logError("Test clicked.")
end
-- drag float
local changed = false
changed, x = ImGui.DragFloat("Drag float", x)
if changed then
LumixAPI.logError("X changed, new value = " .. tostring(x))
end
-- checkbox
changed, checked = ImGui.Checkbox("Checkbox", checked)
if changed then
if checked then
LumixAPI.logError("Checkbox is checked")
else
LumixAPI.logError("Checkbox is unchecked")
end
end
end-- create grid of 50x50x50 cubes
local s = 50
for i = 1, s do
for j = 1, s do
for k = 1, s do
local e = Lumix.main_universe:createEntity()
e.position = { i * 3, j * 3, k* 3 }
local c = e:createComponent("model_instance")
c.source = "models/shapes/cube.fbx"
end
end
end