SDEngine
Game Engine
Loading...
Searching...
No Matches
LayerList.hpp
Go to the documentation of this file.
1// TODO(docs): Add file-level Doxygen header
2// - @file LayerList.hpp
3// - @brief Ordered collection of layers with lifecycle management
4// - Layer ordering and event propagation
5#pragma once
6
7#include <vulkan/vulkan.hpp>
8
9#include "SD/core/Layer.hpp"
10#include "SD/export.hpp"
11
12namespace sd {
13// TODO(docs): Document LayerList class
14// - Purpose: Manages an ordered collection of layers
15// - Layer lifecycle (PushLayer -> OnAttach, PopLayer -> OnDetach)
16// - Event propagation order (reverse iteration for bubbling)
17// - Iteration patterns
18// - Thread safety considerations
20
21{
22public:
23 LayerList() = default;
24 LayerList(const LayerList&) = delete;
25 LayerList& operator=(const LayerList&) = delete;
26
31
32 iterator begin() { return m_layers.begin(); }
33 iterator end() { return m_layers.end(); }
34 [[nodiscard]] const_iterator begin() const { return m_layers.begin(); }
35 [[nodiscard]] const_iterator end() const { return m_layers.end(); }
36
38 // Clear in reverse order (opposite of push)
39 for (auto it = m_layers.rbegin(); it != m_layers.rend(); ++it) {
40 if (*it) {
41 (*it)->on_detach();
42 }
43 }
44 }
45
46 void update(const float dt) const {
47 std::ranges::for_each(m_layers, [dt](const auto& layer) {
48 if (layer->is_active())
49 layer->on_update(dt);
50 });
51 }
52 void on_fixed_update(double dt) const {
53 std::ranges::for_each(m_layers, [dt](const auto& layer) {
54 if (layer->is_active())
55 layer->on_fixed_update(dt);
56 });
57 }
58 void gui_render() {
59 std::ranges::for_each(m_layers, [](const auto& layer) {
60 if (layer->is_active())
61 layer->on_gui_render();
62 });
63 }
65 std::ranges::for_each(m_layers, [](const auto& layer) {
66 if (layer->is_active())
67 layer->on_im_gui_menu_bar();
68 });
69 }
70
71 void on_event(Event& e) {
72 for (auto it = m_layers.rbegin(); it != m_layers.rend(); ++it) {
73 if ((*it)->is_active()) {
74 (*it)->on_event(e);
75 if (e.m_handled)
76 break;
77 }
78 }
79 }
80
81 template<IsLayer T, typename... Args>
82 T& push_layer(Args&&... args) {
83 auto layer = std::make_unique<T>(std::forward<Args>(args)...);
84 T* ptr = layer.get();
85
86 m_layers.emplace_back(std::move(layer));
87 ptr->on_attach();
88
89 return *ptr;
90 }
91
92 template<IsLayer T, typename... Args>
94 auto layer = std::make_unique<T>(std::forward<Args>(args)...);
95 T* ptr = layer.get();
96
97 // Vector specific: insert at begin
98 m_layers.insert(m_layers.begin(), std::move(layer));
99 ptr->on_attach();
100
101 return *ptr;
102 }
103
104 template<IsLayer T>
105 T& attach_layer(std::unique_ptr<T> layer) {
106 T* ptr = layer.get();
107 m_layers.emplace_back(std::move(layer));
108 ptr->on_attach();
109 return *ptr;
110 }
111 template<IsLayer T>
112 T* Get() {
113 for (auto& layer : m_layers) {
114 // dynamic_cast is safe here, but ensuring T is final/sealed helps compiler optimization
115 if (auto p = dynamic_cast<T*>(layer.get())) {
116 return p;
117 }
118 }
119 return nullptr;
120 }
121
122 template<IsLayer T>
123 std::unique_ptr<T> pop_layer() {
124 auto it = std::find_if(m_layers.begin(), m_layers.end(),
125 [](const auto& l) { return dynamic_cast<T*>(l.get()) != nullptr; });
126
127 if (it != m_layers.end()) {
128 (*it)->on_detach();
129
130 std::unique_ptr<T> result(static_cast<T*>(it->release()));
131 m_layers.erase(it);
132 return result;
133 }
134 return nullptr;
135 }
136
137 void clear() {
138 // Clear in reverse order (opposite of push)
139 for (auto it = m_layers.rbegin(); it != m_layers.rend(); ++it) {
140 if (*it) {
141 (*it)->on_detach();
142 }
143 }
144 m_layers.clear();
145 }
146
148 std::ranges::for_each(m_layers, [](const auto& layer) {
149 if (layer->is_active())
150 layer->on_swapchain_recreated();
151 });
152 }
153
154 void on_render(vk::CommandBuffer& cmd) const {
155 std::ranges::for_each(m_layers, [&cmd](const auto& layer) {
156 if (layer->is_active())
157 layer->on_render(cmd);
158 });
159 }
160
161private:
162 std::vector<std::unique_ptr<Layer>> m_layers{};
163};
164} // namespace sd
Definition Event.hpp:56
Definition LayerList.hpp:21
void on_imGui_menu_bar()
Definition LayerList.hpp:64
void on_fixed_update(double dt) const
Definition LayerList.hpp:52
T * Get()
Definition LayerList.hpp:112
iterator end()
Definition LayerList.hpp:33
LayerList & operator=(const LayerList &)=delete
void on_render(vk::CommandBuffer &cmd) const
Definition LayerList.hpp:154
T & push_bottom(Args &&... args)
Definition LayerList.hpp:93
std::vector< std::unique_ptr< Layer > >::const_iterator const_iterator
Definition LayerList.hpp:30
std::unique_ptr< T > pop_layer()
Definition LayerList.hpp:123
T & push_layer(Args &&... args)
Definition LayerList.hpp:82
LayerList(LayerList &&) noexcept=default
void on_swapchain_recreated()
Definition LayerList.hpp:147
LayerList(const LayerList &)=delete
void on_event(Event &e)
Definition LayerList.hpp:71
void update(const float dt) const
Definition LayerList.hpp:46
std::vector< std::unique_ptr< Layer > >::iterator iterator
Definition LayerList.hpp:29
void gui_render()
Definition LayerList.hpp:58
T & attach_layer(std::unique_ptr< T > layer)
Definition LayerList.hpp:105
const_iterator begin() const
Definition LayerList.hpp:34
const_iterator end() const
Definition LayerList.hpp:35
~LayerList()
Definition LayerList.hpp:37
void clear()
Definition LayerList.hpp:137
LayerList()=default
Base class for all layers. Prefer using System, RenderStage, or Panel instead.
Definition Layer.hpp:28
Definition Layer.hpp:19
Definition Application.hpp:28
constexpr T g_type_max
Definition types.hpp:21