#include "Lightkeeper.h" #include #include #include #include #include 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(m_params.renderSize.x) / static_cast(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(); 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(newWidth) / static_cast(newHeight); camera.setAspectRatio(aspectRatio); }