Appkit: /level_wrapper.lua code sample - Stingray Lua API Reference
--[[
The `LevelWrapper` manages an engine `Level` object and
<ul>
<li>Loads the shading environment specfied for the Level in the editor</li>
<li>Spawns the Level background</li>
<li>Loads the level's BakedLighting map</li>
<li>Manage cameras that are set as active cameras, that are not managed by an
Appkit.CameraWrapper`. For example a camera unit added and managed in the
Level Editor.</li>
<li>Provides level object management so that Lua can register lua objects with a
Level to receive update and shutdown calls automatically.</li>
</ul>
The `LevelWrapper` works with the `ComponentManager` to allow components to be
ticked per level, and works with `Appkit` to allow for different Tick ordering
relative to `World` update.
]]--
require 'core/appkit/lua/class'
Appkit.LevelWrapper = Appkit.class(Appkit.LevelWrapper)
local LevelWrapper = Appkit.LevelWrapper
local World = stingray.World
local Level = stingray.Level
local Application = stingray.Application
local ShadingEnvironment = stingray.ShadingEnvironment
local function load_shading_environment(self)
local level = self.level
-- Load the shading environment for the level if there is one.
local env_name = nil
if Level.has_data(level, "shading_environment") then
env_name = Level.get_data(level, "shading_environment")
end
if env_name == nil or string.len(env_name) == 0 then
print "Warning: No shading environment set in Level, applying default"
local default_shading_environment_new = "core/stingray_renderer/environments/midday/midday"
local default_shading_environment_old = "core/rendering/default_outdoor"
env_name = default_shading_environment_new
if Application.can_get("shading_environment", default_shading_environment_old)
and not Application.can_get("shading_environment", default_shading_environment_new) then
env_name = default_shading_environment_old
end
end
local world = self.world
self.shading_environment = World.create_shading_environment(world, env_name)
require 'core/appkit/lua/app'
Appkit.set_shading_environment(world, self.shading_environment, env_name)
end
-- level_name necessary for lightmap loading. It should match the original level
-- file resource name (not the test level resource name).
function LevelWrapper:init(level, level_name, should_set_shading_env)
self.level = level
self.world = Level.world(level)
self.did_trigger_load_flow = false
self.managed_objects = {}
self.shading_environment = nil
self.cameras_to_cleanup = {}
Level.spawn_background(level)
if should_set_shading_env and should_set_shading_env == true then
load_shading_environment(self)
end
if stingray.Application.can_get("baked_lighting", level_name) then
print ("Loading baked_lighting for `"..level_name..".level`")
stingray.BakedLighting.map(self.world, level_name)
end
end
function LevelWrapper:update(dt)
Level.trigger_level_update(self.level)
for _, callback in ipairs(self.managed_objects) do
callback[1].update(callback[2], dt)
end
end
function LevelWrapper:shutdown()
Level.trigger_level_shutdown(self.level)
-- Make sure that any cameras enabled via Level flow are not in the world render list.
-- This is needed for Level-owned cameras that are enabled via the Appkit
-- Enable Camera flow node but not tracked by Appkit.CameraWrapper.
local world_wrapper = Appkit.get_managed_world_wrapper(self.world)
for camera, _ in pairs(self.cameras_to_cleanup) do
world_wrapper:set_camera_enabled(camera, nil, false) -- unit is only needed when enabling
end
self.cameras_to_cleanup = {}
-- Now make sure all Appkit cameras are properly enabled in the world render list.
-- Note: Lua cameras that are not using Appkit.CameraWrapper can possibly be
-- left disabled if they were originally enabled then retrieved and disabled in the
-- Level Flow!
local CameraWrapper = require 'core/appkit/lua/camera_wrapper'
CameraWrapper.refresh_enabled_cameras()
-- Now can Shutdown level objects
for _, object_pair in ipairs(self.managed_objects) do
object_pair[1].shutdown(object_pair[2], self)
end
self.managed_objects = {}
local ComponentManager = require 'core/appkit/lua/component_manager'
ComponentManager.notify_managers_level_shutdown(self.level)
stingray.BakedLighting.unmap(self.world)
if self.shading_environment then
World.destroy_shading_environment(self.world, self.shading_environment)
self.shading_environment = nil
end
end
function LevelWrapper:trigger_level_loaded_flow()
local level = self.level
if level and self.did_trigger_load_flow == false then
Level.trigger_level_loaded(level)
self.did_trigger_load_flow = true
end
end
function LevelWrapper:set_shading_blend(options)
if options then
ShadingEnvironment.blend(self.shading_environment, options)
else
ShadingEnvironment.blend(self.shading_environment, {"default", 1})
end
ShadingEnvironment.apply(self.shading_environment)
end
-- Managed objects receive type.update(object, dt) and type.shutdown(object) calls
function LevelWrapper:manage_object(type, object)
local list = self.managed_objects
list[#list + 1] = {type, object}
end
-- Managed objects receive type.update(object, dt) and type.shutdown(object) calls
function LevelWrapper:unmanage_object(type, object)
for i, callback in ipairs(self.managed_objects) do
if callback[1] == type and callback[2] == object then
table.remove(self.managed_objects, i)
return
end
end
print ("LevelWrapper:unmanage_object. Unabled to find ", type, object, "for removal.")
end
-- When a level unloads, we need a way to remove cameras that were placed in
-- the level and enabled via flow. For Appkit cameras (CameraWrapper),
-- this happens in the shutdown function. This means the Appkit Enable Camera flow
-- node requires the level to be an Appkit managed level.
function LevelWrapper:add_camera_to_cleanup(camera)
self.cameras_to_cleanup[camera] = true
end
return LevelWrapper