-
Notifications
You must be signed in to change notification settings - Fork 433
Lua scripting
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 LuaScript.getEnvironment.
Each script can contain function update(dt) and this function is called each frame.
Universe g_universeEngine g_engine
All scenes are visible to script as global variables, each with prefix "g_scene_" and ends with the name of a plugin, e.g.:
g_scene_rendererg_scene_animationg_scene_audiog_scene_physicsg_scene_lua_script
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:
- Remove all nonalphabetic characters,
- If a character is after nonalphabetic character in the source name, it is uppercase in the Lua name.
For example:
-- property Fog color
GlobalLight.setFogColor(g_scene_renderer, cmp, {1, 0, 1})
local color = GlobalLight.getFogColor(g_scene_renderer, cmp) -- color == {1, 0, 1}Other than standard lua types there following types:
- Vec3 - a table with 3 numbers
- Quat - a table with 4 numbers
-
Entity Engine.createEntity(Universe universe) -
void Engine.logError(string text) -
void Engine.logInfo(string text) -
Vec3 Engine.multVecQuat(Vec3 vec, Vec3 axis, number angle) -
Vec3 Engine.multVecQuat(Vec3 vec, Quat quat) -
void Engine.setEntityPosition(Universe univ, Entity entity, Vec3 position) -
Vec3 Engine.getEntityPosition(Universe univ, Entity entity) -
void Engine.setEntityRotation(Universe univ, Entity entity, Vec3 axis, number angle) -
Quat Engine.getEntityRotation(Universe univ, Entity entity) -
void Engine.setEntityLocalRotation(Universe univ, Entity entity, Vec3 axis, number angle) -
Component Engine.createComponent(Scene scene, string type, Entity entity) -
void Engine.destroyComponent(Scene scene, string type, Component component) -
Component Engine.getRenderable(Scene scene, Entity entity) -
ComponentType Engine.getComponentType(string type_name) -
Component Engine.getComponent(Universe universe, Entity entity, ComponentType) -
PrefabResource Engine.preloadPrefab(Engine engine, string path) -
void Engine.unloadPrefab(Engine engine, PrefabResource prefab) -
Table Engine.instantiatePrefab(Engine engine, Universe universe, Vec3 position, PrefabResource prefab) -
Entity Engine.createEntityEx(Engine engine, Universe universe, Table entity_description)
Usage:
Engine.createEntityEx(g_engine, g_universe, {
renderable = { Source = "models/utils/cube/cube.msh" },
position = {6, 5, 5}
})-
number LuaScript.addScript(Scene scene, Component script) -
void LuaScript.setScriptSource(Scene scene, Component script, number index, string path) -
Table LuaScript.getEnvironment(Scene scene, Entity entity, number script_index)#620 -
Script LuaScript.preloadScript(Scene scene, string path) -
void LuaScript.setTimer(Scene scene, number time_seconds, function callback) -
void LuaScript.unloadScript(Scene scene, Script script)unloadScripthas to be called once for each call ofpreloadScript
Engine.INPUT_TYPE_DOWNEngine.INPUT_TYPE_PRESSEDEngine.INPUT_TYPE_MOUSE_XEngine.INPUT_TYPE_MOUSE_YEngine.INPUT_TYPE_LTHUMB_XEngine.INPUT_TYPE_LTHUMB_YEngine.INPUT_TYPE_RTHUMB_XEngine.INPUT_TYPE_RTHUMB_YEngine.INPUT_TYPE_RTRIGGEREngine.INPUT_TYPE_LTRIGGER
number Engine.getInputActionValue(Engine engine, number action)void Engine.addInputAction(Engine engine, number action, number type, number key)
local LEFT_ACTION = 0
function init()
cmp = Engine.createComponent(g_scene_physics, "physical_controller", this)
Engine.addInputAction(g_engine, LEFT_ACTION, Engine.INPUT_TYPE_PRESSED, string.byte("A"), -1)
end
function update(dt)
local speed = 1
if Engine.getInputActionValue(g_engine, LEFT_ACTION) > 0 then
local v = Engine.multVecQuat({-speed, 0, 0}, {0, 1, 0}, yaw)
Physics.moveController(g_scene_physics, cmp, v, dt)
end
end
void Physics.moveController(Scene scene, Component cmp, Vec3 velocity, number time_delta)number Physics.getActorSpeed(Scene scene, Component cmp)Component Physics.getActorComponent(Scene scene, Entity entity)void Physics.putToSleep(Scene scene, Component component)void Physics.applyForceToActor(Scene scene, Component component, Vec3 force)is_hit, hit_entity, hit_position Physics.raycast(Scene scene, Vec3 origin, Vec3 dir)
If two entities with a physical component collide, onContact function is called in script on both of them:
function onContact(entity)
API_logError("not implemented - onContact(" .. entity .. ")")
endSoundHandle Audio.playSound(Scene scene, Entity entity, string clip_name, bool is_3d)void Audio.setSoundVolume(Scene scene, SoundHandle sound_id, number volume)void Audio.setEcho(IScene* scene, SoundHandle sound, number wet_dry_mix, number feedback, number left_delay, number right_delay)
string Renderer.getCameraSlot(Camera component)Camera Renderer.getCameraComponent(Entity entity)Renderable Renderer.getRenderableComponent(Entity entity)void Renderer.addDebugCross(Vec3 center, number size, number rgba_color, number life)Material Renderer.getTerrainMaterial(Terrain component)Texture Renderer.getMaterialTexture(Material material, number texture_index)void Renderer.setRenderableMaterial(Scene scene, Renderable component, number material_index, string path)void Renderer.setRenderablePath(Scene scene, Renderable component, string path)
bool Navigation.generateNavmesh()void navigate(Entity entity, Vec3 destination, number speed)void debugDrawCompactHeightfield()void debugDrawNavmesh()void debugDrawHeightfield()void debugDrawPaths()void debugDrawContours()number getPolygonCount()void generateTile(number x, number y, bool keep_data)bool save(string path)bool load(string path)void setGeneratorParams(number cell_size, number cell_height, number agent_radius, number agent_height, number walkable_angle, number max_climb)
function 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
Engine.logError("Test clicked.")
end
-- drag float
local changed = false
changed, x = ImGui.DragFloat("Drag float", x)
if changed then
Engine.logError("X changed, new value = " .. tostring(x))
end
-- checkbox
changed, checked = ImGui.Checkbox("Checkbox", checked)
if changed then
if checked then
Engine.logError("Checkbox is checked")
else
Engine.logError("Checkbox is unchecked")
end
end
endEditor.importAsset(Editor.import_asset_dialog,
{
output_dir = "D:\\Projects\\lumixengine_data\\models\\test\\yyy",
srcs = {
{
src = "C:\\Users\\Miki\\Downloads\\Nature Pack\\Nature Pack\\Objects\\Birch_01.fbx" ,
materials = {
{
matching = function(idx, name) return name:lower():find("branch") ~= nil end,
import = true,
shader = "leaves",
alpha_cutout = true,
textures = {
{
import = false,
to_dds = true
}
},
},
{
matching = function(idx, name) return name:lower():find("branch") == nil end,
import = true,
textures = {
{
import = true,
to_dds = true,
src = "c:\\path\\to\\texture.tga"
}
},
},
}
}
},
create_billboard = false,
scale = 0.01
})Import all .obj from a directory (Windows only):
for filename in io.popen([[dir "C:\Users\Miki\Downloads\3D Nature pack\Models\" /b]]):lines() do
if string.sub(filename,-string.len(".obj"))==".obj" then
Editor.importAsset(Editor.import_asset_dialog,
{
output_dir = "C:\\projects\\lumixengine_data\\models\\test",
lods = { 10, 100, -1, -1}, -- -1 == infinite distance
srcs = {
{
src = [[C:\Users\Miki\Downloads\3D Nature pack\Models\]] .. filename,
materials = {
{
matching = function(idx, name) return true end,
import = true,
},
}
}
}
})
Engine.logError(filename .. " imported")
end
endApp.loadUniverse(App.instance, "universes/player.unv")
while Engine.hasFilesystemWork(g_engine) do Engine.processFilesystemWork(g_engine) end
Engine.startGame(g_engine, App.universe)