From: Mikko Rasa Date: Sun, 26 Jan 2025 16:20:03 +0000 (+0200) Subject: Rework the relationship between renderers and the view X-Git-Url: https://git.tdb.fi/?a=commitdiff_plain;h=503a9c6;p=libs%2Fgame.git Rework the relationship between renderers and the view A renderer can't just associate itself with the view in its constructor since stages may get activated multiple times during the application's lifetime and the renderer for each stage is only created the first time. --- diff --git a/source/gameview/presenter.cpp b/source/gameview/presenter.cpp index 06a644d..095d3e0 100644 --- a/source/gameview/presenter.cpp +++ b/source/gameview/presenter.cpp @@ -30,10 +30,17 @@ Presenter::~Presenter() void Presenter::stage_activated(const Game::Events::StageActivated &event) { - if(!event.stage.get_system()) - systems.push_back(&event.stage.add_system(ref(gl_view))); + if(active_renderer) + active_renderer->cancel_output(); + + active_renderer = event.stage.get_system(); + if(!active_renderer) + systems.push_back(active_renderer = &event.stage.add_system()); if(event.stage.get_system() && !event.stage.get_system()) systems.push_back(&event.stage.add_system()); + + if(active_renderer) + active_renderer->output_to_view(gl_view); } } // namespace Msp::GameView diff --git a/source/gameview/presenter.h b/source/gameview/presenter.h index f227d28..bbf3da5 100644 --- a/source/gameview/presenter.h +++ b/source/gameview/presenter.h @@ -10,6 +10,8 @@ namespace Msp::GameView { +class Renderer; + class MSPGAMEVIEW_API Presenter { private: @@ -18,6 +20,7 @@ private: DataFile::Collection &resources; Game::EventObserver event_observer; std::vector systems; + Renderer *active_renderer = nullptr; public: Presenter(Game::Director &, GL::View &); diff --git a/source/gameview/renderer.cpp b/source/gameview/renderer.cpp index 51bc9ca..9bea942 100644 --- a/source/gameview/renderer.cpp +++ b/source/gameview/renderer.cpp @@ -16,9 +16,8 @@ using namespace std; namespace Msp::GameView { -Renderer::Renderer(Game::Stage &s, GL::View &v): +Renderer::Renderer(Game::Stage &s): System(s), - view(v), event_observer(s.get_event_bus()) { declare_dependency(READ_FRESH); @@ -32,7 +31,6 @@ Renderer::Renderer(Game::Stage &s, GL::View &v): stage.synthesize_initial_events(event_observer); content_slot.set(&scene); - view.set_camera(&gl_camera); } Renderer::~Renderer() @@ -42,6 +40,52 @@ Renderer::~Renderer() entities.clear(); } +void Renderer::output_to_view(GL::View &v) +{ + cancel_output(); + gl_view = &v; + if(active_camera) + create_sequence(); +} + +void Renderer::cancel_output() +{ + if(gl_view) + { + gl_view->set_content(nullptr); + gl_view->set_camera(nullptr); + } + sequence = nullptr; +} + +void Renderer::create_sequence() +{ + unsigned w, h; + if(gl_view) + { + w = gl_view->get_width(); + h = gl_view->get_height(); + } + else + throw invalid_state("Renderer::create_sequence"); + + GL::FrameFormat fmt = (GL::COLOR_ATTACHMENT,GL::RGBA8, GL::DEPTH_ATTACHMENT); + sequence = make_unique(w, h, fmt); + sequence->set_clear_enabled(true); + sequence->set_clear_colors({ GL::Color(0.0f) }); + + GL::Sequence::Step &opaque = sequence->add_step(GL::Tag(), content_slot); + opaque.set_depth_test(GL::LEQUAL); + opaque.set_lighting(&lighting); + + unique_ptr colorcurve = make_unique(); + colorcurve->set_srgb(); + sequence->add_postprocessor(*colorcurve); + sequence->add_owned(colorcurve.release()); + + gl_view->set_content(sequence.get()); +} + void Renderer::component_created(const Game::Events::ComponentCreated &event) { Game::Handle mesh_source = dynamic_handle_cast(event.component); @@ -101,24 +145,8 @@ void Renderer::component_destroyed(const Game::Events::ComponentDestroyed &event void Renderer::camera_changed(const Game::Events::CameraChanged &event) { active_camera = event.camera; - if(event.camera) - { - GL::FrameFormat fmt = (GL::COLOR_ATTACHMENT,GL::RGBA8, GL::DEPTH_ATTACHMENT); - sequence = make_unique(view.get_width(), view.get_height(), fmt); - sequence->set_clear_enabled(true); - sequence->set_clear_colors({ GL::Color(0.0f) }); - - GL::Sequence::Step &opaque = sequence->add_step(GL::Tag(), content_slot); - opaque.set_depth_test(GL::LEQUAL); - opaque.set_lighting(&lighting); - - unique_ptr colorcurve = make_unique(); - colorcurve->set_srgb(); - sequence->add_postprocessor(*colorcurve); - sequence->add_owned(colorcurve.release()); - - view.set_content(sequence.get()); - } + if(active_camera && gl_view) + create_sequence(); } void Renderer::tick(Time::TimeDelta) @@ -200,7 +228,8 @@ void Renderer::tick(Time::TimeDelta) stage.iterate_objects([](MeshRenderer &m){ m.update_matrix(); }); stage.iterate_objects([](LightEmitter &e){ e.update_matrix(); }); - view.render(); + if(gl_view) + gl_view->render(); } diff --git a/source/gameview/renderer.h b/source/gameview/renderer.h index c37bc33..7b0d4ce 100644 --- a/source/gameview/renderer.h +++ b/source/gameview/renderer.h @@ -41,7 +41,6 @@ private: bool operator<(const ShadowedLight &other) const { return shadow_size>other.shadow_size; } }; - GL::View &view; Game::EventObserver event_observer; std::vector entities; GL::SimpleScene scene; @@ -54,12 +53,17 @@ private: GL::Slot content_slot; unsigned shadow_base_size = 4096; bool shadows_changed = false; + GL::View *gl_view = nullptr; public: - Renderer(Game::Stage &, GL::View &); + Renderer(Game::Stage &); ~Renderer(); + void output_to_view(GL::View &); + void cancel_output(); private: + void create_sequence(); + void component_created(const Game::Events::ComponentCreated &); RenderedEntity &get_rendered_entity(Game::Handle); void component_destroyed(const Game::Events::ComponentDestroyed &);