--[[ `CameraWrapper` notifies the Wwise Audio, Scatter and Terrain systems of the Camera's location, and is used in conjunction with the `WorldWrapper` and `LevelWrapper` to allow for automatic rendering of active cameras and the `Get Active Camera` and `Set Active Camera` flow nodes. ]]-- require 'core/appkit/lua/class' require 'core/appkit/lua/app' local ComponentManager = require 'core/appkit/lua/component_manager' Appkit.CameraWrapper = Appkit.class(Appkit.CameraWrapper) local CameraWrapper = Appkit.CameraWrapper local CameraModule = stingray.Camera local Unit = stingray.Unit local Matrix4x4 = stingray.Matrix4x4 local Vector3 = stingray.Vector3 local Level = stingray.Level -- Check if listeners/observers are available local USE_TIMPANI = false if stingray.World.timpani_world then USE_TIMPANI = true end local USE_WWISE = false if stingray.Wwise then USE_WWISE = true end local USE_SCATTER_SYSTEM = false if stingray.ScatterSystem then USE_SCATTER_SYSTEM = true end local USE_TERRAIN_DECORATOR = false if stingray.TerrainDecoration then USE_TERRAIN_DECORATOR = true end ComponentManager.give_manager(CameraWrapper, ComponentManager.update_post_world) function CameraWrapper.refresh_enabled_cameras() -- making use of component manager list. local manager = CameraWrapper.manager for _, component_wrapper in pairs(manager.components) do local camera_wrapper = component_wrapper[1] if camera_wrapper.is_enabled == true then local world_wrapper = Appkit.managed_world if world_wrapper and world_wrapper.world == camera_wrapper.world then world_wrapper:set_camera_enabled(camera_wrapper.camera, camera_wrapper.unit, true) end end end end function CameraWrapper:init(entity, unit, camera_index) self.entity = entity -- object this component is associated with, can be used to access other components self.unit = unit self.camera = Unit.camera(unit, camera_index) self.world = Unit.world(unit) self.is_enabled = false self.is_wwise_listener_enabled = true if USE_TERRAIN_DECORATOR then self.terrain_decorator = nil if self.world then self.terrain_decorator = stingray.TerrainDecoration.create_observer(self.world, stingray.Vector3(0,0,0)) end end if USE_SCATTER_SYSTEM then self.scatter_system = stingray.World.scatter_system(self.world) self.scatter_observer = nil if self.scatter_system then self.scatter_observer = stingray.ScatterSystem.make_observer(self.scatter_system, stingray.Vector3(0,0,0)) end end CameraWrapper.manager:add_component(entity, self, Unit.level(unit)) end function CameraWrapper:enable() if self.enabled == true then return end local world_wrapper = Appkit.managed_world if world_wrapper and world_wrapper.world == self.world then world_wrapper:set_camera_enabled(self.camera, self.unit, true) self.is_enabled = true end end function CameraWrapper:disable() if self.enabled == false then return end local world_wrapper = Appkit.managed_world if world_wrapper and world_wrapper.world == self.world then world_wrapper:set_camera_enabled(self.camera, self.unit, false) end self.is_enabled = false end function CameraWrapper:set_wwise_listener_enabled(enabled) self.is_wwise_listener_enabled = enabled end function CameraWrapper:get_camera() return self.camera end function CameraWrapper:world_pose() return CameraModule.world_pose(self.camera, self.unit) end function CameraWrapper:world_position() return CameraModule.world_position(self.camera, self.unit) end function CameraWrapper:world_rotation() return CameraModule.world_rotation(self.camera, self.unit) end function CameraWrapper:set_local_pose(pose) Unit.set_local_pose(self.unit, 1, pose) CameraModule.set_local_pose(self.camera, self.unit, pose) end function CameraWrapper:set_local_position(position) Unit.set_local_position(self.unit, 1, position) CameraModule.set_local_position(self.camera, self.unit, position) end function CameraWrapper:set_local_rotation(rotation) CameraModule.set_local_rotation(self.camera, self.unit, rotation) end function CameraWrapper:local_pose() return CameraModule.local_pose(self.camera, self.unit) end function CameraWrapper:local_position() return CameraModule.local_position(self.camera, self.unit) end function CameraWrapper:local_rotation() return CameraModule.local_rotation(self.camera, self.unit) end local function update_observers(self, pose) if USE_TIMPANI then local tw = stingray.Unit.world(self.unit):timpani_world() tw:set_listener(1, pose) tw:set_listener_mode(1, stingray.TimpaniWorld.LISTENER_3D) end if self.is_wwise_listener_enabled and USE_WWISE then local wwise_world = stingray.Wwise.wwise_world(self.world) stingray.WwiseWorld.set_listener(wwise_world, stingray.Wwise.LISTENER_0, pose) end local pos = Matrix4x4.translation(pose) if USE_TERRAIN_DECORATOR and self.terrain_decorator then stingray.TerrainDecoration.move_observer(self.world, self.terrain_decorator, pos) end if USE_SCATTER_SYSTEM and self.scatter_observer then stingray.ScatterSystem.move_observer(self.scatter_system, self.scatter_observer, pos) end end -- component callback function CameraWrapper:update(dt) if not self.is_enabled then return end -- Do not update if not an active world render camera local world_wrapper = Appkit.managed_world if world_wrapper then camera, unit = world_wrapper:get_enabled_camera() -- Only 1 active camera supported at the moment in Appkit. if camera ~= self.camera and unit ~= self.unit then return end end CameraModule.set_local_pose(self.camera, self.unit, Unit.local_pose(self.unit, 1)) update_observers(self, Unit.world_pose(self.unit, 1)) end local function destroy(self) if USE_TERRAIN_DECORATOR and self.terrain_decorator then stingray.TerrainDecoration.destroy_observer(self.world, self.terrain_decorator) self.terrain_decorator = nil end if USE_SCATTER_SYSTEM and self.scatter_observer then stingray.ScatterSystem.destroy_observer(self.scatter_system, self.scatter_observer) self.scatter_observer = nil end end -- component callback function CameraWrapper:on_level_shutdown() end -- component callback function CameraWrapper:shutdown() destroy(self) end return CameraWrapper