#include "Graphics/Narrator.h" #include #include #include #include #include #include #include #include #include namespace Scop { Scene::Scene(std::string_view name, SceneDescriptor desc) : m_name(name), m_descriptor(std::move(desc)), p_parent(nullptr) { } Scene::Scene(std::string_view name, SceneDescriptor desc, NonOwningPtr parent) : m_name(name), m_descriptor(std::move(desc)), p_parent(parent) { } Actor& Scene::CreateActor(Model model) noexcept { return m_actors.emplace_back(std::move(model)); } Actor& Scene::CreateActor(std::string_view name, Model model) { return m_actors.emplace_back(std::move(model)); } Narrator& Scene::CreateNarrator() noexcept { return m_narrators.emplace_back(); } Narrator& Scene::CreateNarrator(std::string_view name) { return m_narrators.emplace_back(); } Sprite& Scene::CreateSprite(std::shared_ptr texture) noexcept { return m_sprites.emplace_back(texture); } Sprite& Scene::CreateSprite(std::string_view name, std::shared_ptr texture) { return m_sprites.emplace_back(texture); } void Scene::RemoveActor(Actor& actor) noexcept { auto it = std::find_if(m_actors.begin(), m_actors.end(), [actor](const Actor& lhs) { return actor.GetUUID() == lhs.GetUUID(); }); if(it == m_actors.end()) { Error("Actor not found"); return; } m_actors.erase(it); } void Scene::RemoveNarrator(Narrator& narrator) noexcept { auto it = std::find_if(m_narrators.begin(), m_narrators.end(), [narrator](const Narrator& lhs) { return narrator.GetUUID() == lhs.GetUUID(); }); if(it == m_narrators.end()) { Error("Narrator not found"); return; } m_narrators.erase(it); } void Scene::RemoveSprite(Sprite& sprite) noexcept { auto it = std::find_if(m_sprites.begin(), m_sprites.end(), [sprite](const Sprite& lhs) { return sprite.GetUUID() == lhs.GetUUID(); }); if(it == m_sprites.end()) { Error("Sprite not found"); return; } m_sprites.erase(it); } void Scene::SwitchToChild(std::string_view name) const noexcept { auto it = std::find_if(m_scene_children.begin(), m_scene_children.end(), [name](const Scene& scene){ return name == scene.GetName(); }); if(it == m_scene_children.end()) { Error("Cannot switch to scene '%', scene not found in children of '%'", name, m_name); return; } ScopEngine::Get().SwitchToScene(const_cast(&(*it))); } void Scene::SwitchToParent() const noexcept { ScopEngine::Get().SwitchToScene(p_parent); } void Scene::Init(NonOwningPtr renderer) { std::function functor = [this, renderer](const EventBase& event) { if(event.What() == Event::ResizeEventCode) { m_depth.Destroy(); m_depth.Init(renderer->GetSwapchain().GetSwapchainImages().back().GetWidth(), renderer->GetSwapchain().GetSwapchainImages().back().GetHeight(), false, m_name + "_depth"); } if(event.What() == Event::ResizeEventCode || event.What() == Event::SceneHasChangedEventCode) m_pipeline.Destroy(); // Ugly but f*ck off }; EventBus::RegisterListener({ functor, m_name + std::to_string(reinterpret_cast(this)) }); auto vertex_shader = RenderCore::Get().GetDefaultVertexShader(); m_depth.Init(renderer->GetSwapchain().GetSwapchainImages().back().GetWidth(), renderer->GetSwapchain().GetSwapchainImages().back().GetHeight(), false, m_name + "_depth"); m_forward.matrices_buffer = std::make_shared(); m_forward.matrices_buffer->Init(sizeof(ViewerData), m_name + "_matrice_buffer"); m_forward.matrices_set = std::make_shared(vertex_shader->GetShaderLayout().set_layouts[0].second, vertex_shader->GetPipelineLayout().set_layouts[0], ShaderType::Vertex); for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { m_forward.matrices_set->SetUniformBuffer(i, 0, m_forward.matrices_buffer->Get(i)); m_forward.matrices_set->Update(i); } m_forward.albedo_set = std::make_shared(m_descriptor.fragment_shader->GetShaderLayout().set_layouts[0].second, m_descriptor.fragment_shader->GetPipelineLayout().set_layouts[0], ShaderType::Fragment); for(auto& child : m_scene_children) child.Init(renderer); } void Scene::Update(Inputs& input, float timestep, float aspect) { for(auto actor : m_actors) actor.Update(this, input, timestep); for(auto narrator : m_narrators) narrator.Update(this, input, timestep); for(auto sprite : m_sprites) sprite.Update(this, input, timestep); if(m_descriptor.camera) m_descriptor.camera->Update(input, aspect, timestep); } void Scene::Destroy() { RenderCore::Get().WaitDeviceIdle(); p_skybox.reset(); m_depth.Destroy(); m_actors.clear(); m_narrators.clear(); m_sprites.clear(); m_pipeline.Destroy(); m_descriptor.fragment_shader.reset(); m_forward.matrices_buffer->Destroy(); for(auto& child : m_scene_children) child.Destroy(); } }