Files
Destrum/lightkeeper/src/Lightkeeper.cpp
T

213 lines
6.1 KiB
C++

#include "Lightkeeper.h"
#include <destrum/Components/CameraComponent.h>
#include <destrum/FS/AssetFS.h>
#include <destrum/Scene/Scene.h>
#include <components/FirstPersonController.h>
#include <components/GameComponentRegistry.h>
LightKeeper::LightKeeper() : App()
{
}
LightKeeper::~LightKeeper()
{
if (!cleanedUp) {
try {
cleanup();
} catch (...) {
}
}
}
void LightKeeper::customInit()
{
RegisterGameComponents();
resources.init(gfxDevice);
renderer.init(gfxDevice, resources, m_params.renderSize);
const float aspectRatio = static_cast<float>(m_params.renderSize.x) / static_cast<float>(m_params.renderSize.y);
camera.setAspectRatio(aspectRatio);
camera.SetRotation(glm::radians(glm::vec2(90.f, 0.f)));
window.Maximize();
setupSkybox();
auto& scene = SceneManager::GetInstance().CreateScene("Main");
mainScene = BuildMainScene(scene, gfxDevice, resources);
debug2DTexture = resources.loadImageFromFile(
gfxDevice, AssetFS::GetInstance().GetFullPath("engine://textures/kobe.png"));
}
void LightKeeper::setupSkybox()
{
const auto skyboxPath = AssetFS::GetInstance().GetCookedPathForFile("engine://DJI_0001_stitch.jpg");
const auto vertShaderPath = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/cubemap.vert");
const auto fragShaderPath = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/cubemap.frag");
skyboxCubemap = std::make_unique<CubeMap>();
skyboxCubemap->LoadCubeMap(gfxDevice, resources, skyboxPath.generic_string());
skyboxCubemap->InitCubemapPipeline(gfxDevice, resources, vertShaderPath.generic_string(), fragShaderPath.generic_string());
skyboxCubemap->CreateCubeMap(gfxDevice, resources);
renderer.setSkyboxTexture(skyboxCubemap->GetCubeMapImageID());
}
void LightKeeper::customUpdate(float dt)
{
updateViewMode();
// LightKeeper owns a camera that hides App::camera; update this instance
// after SDL events have been consumed.
if (!isPlayerViewActive() && getSceneCamera() == nullptr)
{
camera.Update(dt);
}
if (InputManager::GetInstance().WasKeyPressed(SDL_SCANCODE_F11))
{
window.ToggleFullscreen();
}
SceneManager::GetInstance().Update(dt);
SceneManager::GetInstance().LateUpdate(dt);
updateDebugUi();
}
void LightKeeper::updateViewMode()
{
auto& input = InputManager::GetInstance();
FirstPersonController* player = mainScene.playerController;
if (isPlaying() && !isPaused() && player != nullptr && input.WasKeyPressed(SDL_SCANCODE_F6))
{
player->SetPossessed(!player->IsPossessed());
}
if (!isPlayerViewActive())
{
const bool looking = input.IsMouseDown(SDL_BUTTON_RIGHT);
if (looking != input.IsMouseCaptured())
{
input.SetMouseCaptured(looking);
}
}
}
bool LightKeeper::isPlayerViewActive() const
{
return isPlaying() && !isPaused() && mainScene.playerController != nullptr && mainScene.playerController->IsPossessed();
}
CameraComponent* LightKeeper::getSceneCamera() const
{
const auto& activeScenes = SceneManager::GetInstance().GetActiveScenes();
if (!isPlaying() || useFreeCamera || activeScenes.empty()) {
return nullptr;
}
return activeScenes.front()->GetCurrentCamera();
}
Camera& LightKeeper::getViewCamera()
{
CameraComponent* sceneCamera = isPlayerViewActive() ? nullptr : getSceneCamera();
return sceneCamera != nullptr ? sceneCamera->GetCamera(camera.GetAspectRatio()) : camera;
}
void LightKeeper::customDraw()
{
const auto cmd = gfxDevice.beginFrame();
if (cmd == VK_NULL_HANDLE) {
return;
}
renderer.beginDrawing(gfxDevice);
submitDebugDraws();
if (isPlayerViewActive())
{
camera.SetRotation(mainScene.playerController->GetYaw(), mainScene.playerController->GetPitch());
camera.m_position = mainScene.playerController->GetEyePosition();
camera.CalculateViewMatrix();
camera.CalculateProjectionMatrix();
}
Camera& viewCamera = getViewCamera();
const SceneEnvironment& environment = SceneManager::GetInstance().GetCurrentScene().GetEnvironment();
const GameRenderer::SceneData sceneData{
.camera = viewCamera,
.ambientColor = environment.ambientColor,
.ambientIntensity = environment.ambientIntensity,
.fogColor = environment.fogColor,
.fogDensity = environment.fogDensity,
.skyboxRotation = environment.skyboxRotation,
};
const RenderContext ctx{
.renderer = renderer,
.camera = viewCamera,
.sceneData = sceneData,
};
SceneManager::GetInstance().Render(ctx);
renderer.endDrawing();
const auto& drawImage = renderer.getDrawImage();
renderer.draw(cmd, gfxDevice, viewCamera, sceneData);
gfxDevice.endFrame(
cmd, drawImage, {
.clearColor = {{0.f, 0.f, 0.5f, 1.f}},
.drawImageBlitRect = glm::ivec4{},
.imguiPass = &imguiPass,
});
}
void LightKeeper::customCleanup()
{
SceneManager::GetInstance().Destroy();
if (skyboxCubemap)
{
skyboxCubemap->cleanup(gfxDevice);
skyboxCubemap.reset();
}
renderer.cleanup(gfxDevice);
}
void LightKeeper::customFixedUpdate(float dt)
{
SceneManager::GetInstance().FixedUpdate(dt);
}
void LightKeeper::onPlayModeChanged(bool nowPlaying)
{
findPlayer();
if (nowPlaying) {
// The player view moves the free camera, put it back where the editor left it on Stop
editorCamera = camera;
if (mainScene.playerController != nullptr) {
mainScene.playerController->SetPossessed(true);
}
} else if (editorCamera) {
const float aspectRatio = camera.GetAspectRatio();
camera = *editorCamera;
camera.setAspectRatio(aspectRatio);
editorCamera.reset();
}
}
void LightKeeper::onWindowResize(int newWidth, int newHeight)
{
renderer.resize(gfxDevice, glm::ivec2{newWidth, newHeight});
const float aspectRatio = static_cast<float>(newWidth) / static_cast<float>(newHeight);
camera.setAspectRatio(aspectRatio);
}