From 98dc056786bd447ffdc94cc850757bd9d06252f5 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Tue, 3 Jun 2025 11:12:45 +0200 Subject: [PATCH] adding loading screen --- Application/World.cpp | 143 +++++++++++++----- Application/World.h | 3 + .../Includes/Graphics/Cameras/FirstPerson3D.h | 3 + .../Graphics/Cameras/FirstPerson3D.cpp | 11 -- 4 files changed, 111 insertions(+), 49 deletions(-) diff --git a/Application/World.cpp b/Application/World.cpp index 655245d..6ea4a12 100644 --- a/Application/World.cpp +++ b/Application/World.cpp @@ -24,31 +24,12 @@ World::World(Scop::Scene& scene) : m_noisecollection(42), p_water_pipeline(std:: p_block_material = std::make_shared(material_params); scene.LoadFont(GetResourcesPath() / "OpenSans_Bold.ttf", 32.0f); - Scop::Text& text = scene.CreateText("FPS:"); - text.SetPosition(Scop::Vec2ui{ 30, 30 }); + Scop::Text& fps_text = scene.CreateText("FPS:"); + fps_text.SetPosition(Scop::Vec2ui{ 30, 30 }); std::thread(&World::GenerateWorld, this).detach(); - Scop::Vec2ui32 loading_size; - Scop::Sprite& loading = scene.CreateSprite(std::make_shared(Scop::LoadBMPFile(GetResourcesPath() / "loading.bmp", loading_size), loading_size.x, loading_size.y)); - - auto loading_update = [this, loading_size](Scop::NonOwningPtr scene, Scop::NonOwningPtr sprite, Scop::Inputs& input, float delta) - { - if(!m_show_loading_screen && Scop::CommandLineInterface::Get().HasFlag("no-loading-screen")) - { - sprite->SetColor(Scop::Vec4f{ 0.0f }); - return; - } - Scop::Vec2f scale = Scop::Vec2f{ - static_cast(Scop::ScopEngine::Get().GetWindow().GetWidth()) / static_cast(loading_size.x), - static_cast(Scop::ScopEngine::Get().GetWindow().GetHeight()) / static_cast(loading_size.y), - }; - sprite->SetScale(scale); - sprite->SetPosition(Scop::Vec2ui{ 0, 0 }); - }; - - using sprite_hook = std::function)>; - loading.AttachScript(std::make_shared(sprite_hook{}, loading_update, sprite_hook{})); + SetupLoading(); auto narrator_update = [this](Scop::NonOwningPtr scene, Scop::Inputs& input, float delta) { @@ -187,28 +168,52 @@ void World::GenerateWorld() } std::queue> mesh_generation_queue; - Scop::Vec2i x_range{ m_current_chunk_position.x - RENDER_DISTANCE - 1, m_current_chunk_position.x + RENDER_DISTANCE + 1 }; - Scop::Vec2i z_range{ m_current_chunk_position.y - RENDER_DISTANCE - 1, m_current_chunk_position.y + RENDER_DISTANCE + 1 }; - - for(std::int32_t x = x_range.x; x <= x_range.y; x++) { - for(std::int32_t z = z_range.x; z <= z_range.y; z++) + Scop::Vec2i x_range{ m_current_chunk_position.x - RENDER_DISTANCE - 1, m_current_chunk_position.x + RENDER_DISTANCE + 1 }; + Scop::Vec2i z_range{ m_current_chunk_position.y - RENDER_DISTANCE - 1, m_current_chunk_position.y + RENDER_DISTANCE + 1 }; + std::size_t range = (RENDER_DISTANCE + RENDER_DISTANCE + 2) * 2; + + float progress = 0.0f; + m_loading_progress = 0; + + float i = 0; + for(std::int32_t x = x_range.x; x <= x_range.y; x++, i++) { - QUIT_CHECK(); - auto res = m_chunks.try_emplace(Scop::Vec2i{ x, z }, *this, Scop::Vec2i{ x, z }); - res.first->second.GenerateChunk(); - if(!res.first->second.GetActor() && x > x_range.x && x < x_range.y && z > z_range.x && z < z_range.y) - mesh_generation_queue.push(std::ref(res.first->second)); + for(std::int32_t z = z_range.x; z <= z_range.y; z++) + { + QUIT_CHECK(); + auto res = m_chunks.try_emplace(Scop::Vec2i{ x, z }, *this, Scop::Vec2i{ x, z }); + res.first->second.GenerateChunk(); + + progress = (i / range) * 30; + m_loading_progress = progress; + + if(!res.first->second.GetActor() && x > x_range.x && x < x_range.y && z > z_range.x && z < z_range.y) + mesh_generation_queue.push(std::ref(res.first->second)); + } } } - while(!mesh_generation_queue.empty()) + { - QUIT_CHECK(); - auto chunk = mesh_generation_queue.front(); - mesh_generation_queue.pop(); - chunk.get().GenerateMesh(); - m_chunks_to_upload.Push(chunk); + float progress = 30.0f; + m_loading_progress = 30; + + std::size_t range = mesh_generation_queue.size() - 30; + + for(float i = 0.0f; !mesh_generation_queue.empty(); i++) + { + QUIT_CHECK(); + auto chunk = mesh_generation_queue.front(); + mesh_generation_queue.pop(); + chunk.get().GenerateMesh(); + m_chunks_to_upload.Push(chunk); + + progress = ((i - 30.0f) / range) * 70; + m_loading_progress = progress + 30; + } } + + m_loading_progress = 100; m_generation_status = GenerationState::Finished; } @@ -229,3 +234,65 @@ void World::Upload() Scop::RenderCore::Get().WaitQueueIdle(KVF_GRAPHICS_QUEUE); Scop::RenderCore::Get().ShouldStackSubmits(false); } + +void World::SetupLoading() +{ + Scop::CPUBuffer default_pixels{ sizeof(std::uint32_t) }; + default_pixels.GetDataAs()[0] = 0xFFFFFFFF; + Scop::Sprite& progress_bar = m_scene.CreateSprite(std::make_shared(std::move(default_pixels), 1, 1)); + + Scop::Text& loading_text = m_scene.CreateText("Loading..."); + + Scop::Vec2ui32 loading_size; + Scop::Sprite& loading = m_scene.CreateSprite(std::make_shared(Scop::LoadBMPFile(GetResourcesPath() / "loading.bmp", loading_size), loading_size.x, loading_size.y)); + + auto loading_update = [this, loading_size, &progress_bar, &loading_text](Scop::NonOwningPtr scene, Scop::NonOwningPtr sprite, Scop::Inputs& input, float delta) + { + static bool just_ended_loading = false; + static std::uint32_t last_percentage = 0; + + if(!m_show_loading_screen || Scop::CommandLineInterface::Get().HasFlag("no-loading-screen")) + { + if(!just_ended_loading) + { + sprite->SetColor(Scop::Vec4f{ 0.0f }); + progress_bar.SetColor(Scop::Vec4f{ 0.0f }); + reinterpret_cast(m_scene.GetCamera().get())->EnableCamera(); + if(p_loading_text) + m_scene.RemoveText(*p_loading_text); + m_scene.RemoveText(loading_text); + m_scene.RemoveSprite(progress_bar); + just_ended_loading = true; + } + return; + } + reinterpret_cast(m_scene.GetCamera().get())->DisableCamera(); + Scop::Vec2f scale = Scop::Vec2f{ + static_cast(Scop::ScopEngine::Get().GetWindow().GetWidth()) / static_cast(loading_size.x), + static_cast(Scop::ScopEngine::Get().GetWindow().GetHeight()) / static_cast(loading_size.y), + }; + sprite->SetScale(scale); + sprite->SetPosition(Scop::Vec2ui{ 0, 0 }); + + if(last_percentage != m_loading_progress) + { + last_percentage = m_loading_progress; + if(p_loading_text) + m_scene.RemoveText(*p_loading_text); + p_loading_text = &m_scene.CreateText(std::to_string(m_loading_progress) + '%'); + } + if(p_loading_text) + p_loading_text->SetPosition(Scop::Vec2ui{ (Scop::ScopEngine::Get().GetWindow().GetWidth() >> 1) + 70, (Scop::ScopEngine::Get().GetWindow().GetHeight() >> 1) - 55 }); + loading_text.SetPosition(Scop::Vec2ui{ (Scop::ScopEngine::Get().GetWindow().GetWidth() >> 1) - 70, (Scop::ScopEngine::Get().GetWindow().GetHeight() >> 1) - 55 }); + + Scop::Vec2ui progress_size = Scop::Vec2ui{ + static_cast(static_cast(m_loading_progress) * 4.0f), + 25 + }; + progress_bar.SetScale(Scop::Vec2f(progress_size)); + progress_bar.SetPosition(Scop::Vec2ui{ (Scop::ScopEngine::Get().GetWindow().GetWidth() >> 1) - 200, (Scop::ScopEngine::Get().GetWindow().GetHeight() >> 1) - (progress_size.y >> 1) + 25 }); + }; + + using sprite_hook = std::function)>; + loading.AttachScript(std::make_shared(sprite_hook{}, loading_update, sprite_hook{})); +} diff --git a/Application/World.h b/Application/World.h index ad85ed4..ac7153c 100644 --- a/Application/World.h +++ b/Application/World.h @@ -47,6 +47,7 @@ class World void UnloadChunks(); void GenerateWorld(); void Upload(); + void SetupLoading(); private: NoiseCollection m_noisecollection; @@ -62,6 +63,8 @@ class World Scop::Vec2i m_current_chunk_position; std::atomic m_generation_status = GenerationState::Ready; Scop::NonOwningPtr p_fps_text; + Scop::NonOwningPtr p_loading_text; + std::atomic_uint32_t m_loading_progress = 0; std::uint32_t m_last_fps_count = 0; bool m_show_loading_screen = true; }; diff --git a/ScopEngine/Runtime/Includes/Graphics/Cameras/FirstPerson3D.h b/ScopEngine/Runtime/Includes/Graphics/Cameras/FirstPerson3D.h index aab7260..94a386d 100644 --- a/ScopEngine/Runtime/Includes/Graphics/Cameras/FirstPerson3D.h +++ b/ScopEngine/Runtime/Includes/Graphics/Cameras/FirstPerson3D.h @@ -14,6 +14,9 @@ namespace Scop void Update(class Inputs& input, float aspect, float timestep) override; + inline constexpr void EnableCamera() noexcept { m_inputs_blocked = false; } + inline constexpr void DisableCamera() noexcept { m_inputs_blocked = true; } + [[nodiscard]] inline constexpr std::string GetCameraType() override { return "FirstPerson3D"; } [[nodiscard]] const Vec3f& GetPosition() const noexcept override { return m_position; } [[nodiscard]] const Vec3f& GetUp() const noexcept { return c_up; } diff --git a/ScopEngine/Runtime/Sources/Graphics/Cameras/FirstPerson3D.cpp b/ScopEngine/Runtime/Sources/Graphics/Cameras/FirstPerson3D.cpp index fb94381..46158c7 100644 --- a/ScopEngine/Runtime/Sources/Graphics/Cameras/FirstPerson3D.cpp +++ b/ScopEngine/Runtime/Sources/Graphics/Cameras/FirstPerson3D.cpp @@ -16,17 +16,6 @@ namespace Scop m_view = Mat4f::LookAt(m_position, m_target, c_up); m_proj = Mat4f::Perspective(RadianAnglef(m_fov), aspect, 0.1f, 100'000.f); - if(input.IsKeyPressed(SDL_SCANCODE_F1)) - { - m_inputs_blocked = true; - input.ReleaseMouse(); - } - if(input.IsKeyPressed(SDL_SCANCODE_F2)) - { - m_inputs_blocked = false; - input.GrabMouse(); - } - if(m_inputs_blocked) return;