]> git.tdb.fi Git - libs/game.git/commitdiff
Rework the relationship between renderers and the view
authorMikko Rasa <tdb@tdb.fi>
Sun, 26 Jan 2025 16:20:03 +0000 (18:20 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sun, 26 Jan 2025 16:30:15 +0000 (18:30 +0200)
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.

source/gameview/presenter.cpp
source/gameview/presenter.h
source/gameview/renderer.cpp
source/gameview/renderer.h

index 06a644dd6bfc9fd159edac7c0caa08998f4f4b9f..095d3e0b98ce075651db876b8b2b21cbe459c619 100644 (file)
@@ -30,10 +30,17 @@ Presenter::~Presenter()
 
 void Presenter::stage_activated(const Game::Events::StageActivated &event)
 {
-       if(!event.stage.get_system<Renderer>())
-               systems.push_back(&event.stage.add_system<Renderer>(ref(gl_view)));
+       if(active_renderer)
+               active_renderer->cancel_output();
+
+       active_renderer = event.stage.get_system<Renderer>();
+       if(!active_renderer)
+               systems.push_back(active_renderer = &event.stage.add_system<Renderer>());
        if(event.stage.get_system<Game::Landscape>() && !event.stage.get_system<TerrainMeshCreator>())
                systems.push_back(&event.stage.add_system<TerrainMeshCreator>());
+
+       if(active_renderer)
+               active_renderer->output_to_view(gl_view);
 }
 
 } // namespace Msp::GameView
index f227d283cf7674b16f537695bee5e0b086bc3f78..bbf3da516fe0038b67f407e9ef2ebccffdedb026 100644 (file)
@@ -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<Game::System *> systems;
+       Renderer *active_renderer = nullptr;
 
 public:
        Presenter(Game::Director &, GL::View &);
index 51bc9ca0c2ca553d5313d6fa3233b9fad0dac08b..9bea942ae6113e63d1f13cbaececc2c512a04a7a 100644 (file)
@@ -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<Game::Transform>(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<GL::Sequence>(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<GL::ColorCurve> colorcurve = make_unique<GL::ColorCurve>();
+       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<Game::MeshSource> mesh_source = dynamic_handle_cast<Game::MeshSource>(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<GL::Sequence>(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<GL::ColorCurve> colorcurve = make_unique<GL::ColorCurve>();
-               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>([](MeshRenderer &m){ m.update_matrix(); });
        stage.iterate_objects<LightEmitter>([](LightEmitter &e){ e.update_matrix(); });
 
-       view.render();
+       if(gl_view)
+               gl_view->render();
 }
 
 
index c37bc338fa687af0c361e177df4257b7bf3d0c5b..7b0d4cea448971b40350b0f5f5810e0c87bed97b 100644 (file)
@@ -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<RenderedEntity> 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<Game::Entity>);
        void component_destroyed(const Game::Events::ComponentDestroyed &);