Tatooine
interactive.h
Go to the documentation of this file.
1#ifndef TATOOINE_RENDERING_INTERACTIVE_H
2#define TATOOINE_RENDERING_INTERACTIVE_H
3//==============================================================================
12#include <tatooine/type_set.h>
13#include <tatooine/functional.h>
14//==============================================================================
16//==============================================================================
17namespace detail {
18//==============================================================================
19template <typename... Renderers>
21 invoke([&] {
22 if constexpr (requires { Renderers::set_view_matrix(V); }) {
23 Renderers::set_view_matrix(V);
24 }
25 }...);
26}
27//==============================================================================
28template <typename... Renderers>
31 invoke([&] {
32 if constexpr (requires { Renderers::set_projection_matrix(P); }) {
33 Renderers::set_projection_matrix(P);
34 }
35 }...);
36}
37//==============================================================================
38template <typename... Renderers>
41 invoke([&] {
42 if constexpr (requires { Renderers::set_view_projection_matrix(VP); }) {
43 Renderers::set_view_projection_matrix(VP);
44 }
45 }...);
46}
47struct window {
48 [[nodiscard]] static auto get() -> auto& {
49 static auto w = first_person_window{500, 500};
50 return w;
51 }
52};
53//==============================================================================
54} // namespace detail
55//==============================================================================
57auto pre_setup() { [[maybe_unused]] auto& w = detail::window::get(); }
58//==============================================================================
59template <std::size_t... Is, interactively_renderable... Renderables>
60auto show(std::index_sequence<Is...> /*seq*/, Renderables&&... renderables) {
61 using namespace detail;
62 using renderer_type_set = type_set<renderer<std::decay_t<Renderables>>...>;
63
64 auto& window = detail::window::get();
65 auto const max_num_dimensions = tatooine::max([&] {
66 using renderable_t = std::decay_t<decltype(renderables)>;
67 if constexpr (range<renderable_t>) {
68 return renderable_t::value_type::num_dimensions();
69 } else {
70 return renderables.num_dimensions();
71 }
72 }()...);
73 if (max_num_dimensions == 2) {
74 window.camera_controller().use_orthographic_camera();
75 window.camera_controller().use_orthographic_controller();
76 } else if (max_num_dimensions == 3) {
77 window.camera_controller().use_perspective_camera();
78 window.camera_controller().use_fps_controller();
79 }
80 window.add_resize_event([&](int /*width*/, int /*height*/) {
81 auto const P =
82 window.camera_controller().active_camera().projection_matrix();
83 set_projection_matrices(P, renderer_type_set{});
84 });
85 window.add_wheel_up_event([&]() {
86 auto const P =
87 window.camera_controller().active_camera().projection_matrix();
88 set_projection_matrices(P, renderer_type_set{});
89 });
90 window.add_wheel_down_event([&]() {
91 auto const P =
92 window.camera_controller().active_camera().projection_matrix();
93 set_projection_matrices(P, renderer_type_set{});
94 });
95
96 gl::clear_color(255, 255, 255, 255);
97
98 //auto& io = ImGui::GetIO();
99 //auto roboto = io.Fonts->AddFontFromFileTTF(
100 // "/home/steve/libs/tatooine2/resources/fonts/Roboto-Regular.ttf", 25);
101 auto enable_renderer = std::array{((void)renderables, true)...};
102 auto renderers = std::tuple{[&](auto&& renderable) {
103 using type = decltype(renderable);
104 using decayed_type = std::decay_t<type>;
105 if constexpr (
106 requires(type t) { t.render(); } ||
107 requires(type t) { t.late_render(); } ||
108 requires(type t) {
109 t.render(renderable, window.camera_controller().active_camera());
110 }) {
111 return renderable;
112 } else if constexpr (
113 requires(renderer<decayed_type> t) { t.render(); } ||
114 requires(renderer<decayed_type> t) { t.render(renderable); } ||
115 requires(renderer<decayed_type> t) { t.late_render(); } ||
116 requires(renderer<decayed_type> t) { t.late_render(renderable); } ||
117 requires(renderer<decayed_type> t) {
118 t.render(renderable, window.camera_controller().active_camera());
119 }) {
120 return renderer<decayed_type>(renderable);
121 }
122 }(renderables)...};
123
124 auto foreach_renderer = [&](auto&& f) {
125 (f(std::get<Is>(renderers), renderables, Is), ...);
126 };
127
128 window.add_button_released_event([&](gl::button b) {
129 foreach_renderer([&](auto& renderer, auto& /*renderable*/, auto i) {
130 if (enable_renderer[i]) {
131 if constexpr (requires { renderer.on_button_released(b); }) {
132 renderer.on_button_released(b);
133 }
134 if constexpr (requires {
135 renderer.on_button_released(
136 b, window.camera_controller().active_camera());
137 }) {
138 renderer.on_button_released(
139 b, window.camera_controller().active_camera());
140 }
141 }
142 });
143 });
144 window.add_button_pressed_event([&](gl::button b) {
145 foreach_renderer([&](auto& renderer, auto& /*renderable*/, auto i) {
146 if (enable_renderer[i]) {
147 if constexpr (requires { renderer.on_button_pressed(b); }) {
148 renderer.on_button_pressed(b);
149 }
150 if constexpr (requires {
151 renderer.on_button_pressed(
152 b, window.camera_controller().active_camera());
153 }) {
154 renderer.on_button_pressed(
155 b, window.camera_controller().active_camera());
156 }
157 }
158 });
159 });
160 window.add_cursor_moved_event([&](double const x, double const y) {
161 foreach_renderer([&](auto& renderer, auto& /*renderable*/, auto i) {
162 if (enable_renderer[i]) {
163 if constexpr (requires { renderer.on_cursor_moved(x, y); }) {
164 renderer.on_cursor_moved(x, y);
165 }
166 if constexpr (requires {
167 renderer.on_cursor_moved(
168 x, y, window.camera_controller().active_camera());
169 }) {
170 renderer.on_cursor_moved(x, y,
171 window.camera_controller().active_camera());
172 }
173 }
174 });
175 });
176
177 window.render_loop([&](auto const dt) {
178 auto const V = window.camera_controller().view_matrix();
179 set_view_matrices(V, renderer_type_set{});
180
182 ImGui::Begin("Properties");
183 //ImGui::PushFont(roboto);
184 foreach_renderer([&](auto& renderer, auto& renderable, auto i) {
185 if (enable_renderer[i]) {
186 if constexpr (requires { renderer.update(dt); }) {
187 renderer.update(dt);
188 }
189 if constexpr (requires { renderer.update(dt, renderable); }) {
190 renderer.update(dt, renderable);
191 }
192 if constexpr (requires {
193 renderer.update(
194 dt, renderable,
195 window.camera_controller().active_camera());
196 }) {
197 renderer.update(dt, renderable,
198 window.camera_controller().active_camera());
199 }
200 if constexpr (requires { renderer.render(); }) {
201 renderer.render();
202 }
203 if constexpr (requires { renderer.render(renderable); }) {
204 renderer.render(renderable);
205 }
206 if constexpr (requires {
207 renderer.render(
208 renderable,
209 window.camera_controller().active_camera());
210 }) {
211 renderer.render(renderable,
212 window.camera_controller().active_camera());
213 }
214 }
215
216 ImGui::PushID(static_cast<int>(i));
217 ImGui::ToggleButton("##enable", &enable_renderer[i]);
218 if constexpr (requires { renderer.properties(renderable); }) {
219 ImGui::BeginGroup();
220 renderer.properties(renderable);
221 ImGui::EndGroup();
222 }
223 if constexpr (requires { renderer.properties(); }) {
224 ImGui::BeginGroup();
225 renderer.properties();
226 ImGui::EndGroup();
227 }
228 ImGui::PopID();
229 });
230 //ImGui::PopFont();
231 ImGui::End();
233 // In this late render area you can use custom cameras.
234 foreach_renderer([&](auto& renderer, auto& renderable, auto i) {
235 if (enable_renderer[i]) {
236 if constexpr (requires { renderer.late_render(); }) {
237 renderer.late_render();
238 }
239 if constexpr (requires { renderer.late_render(renderable); }) {
240 renderer.late_render(renderable);
241 }
242 }
243 });
244 });
245}
246//------------------------------------------------------------------------------
247auto show(interactively_renderable auto&&... renderables) {
248 show(std::make_index_sequence<sizeof...(renderables)>{},
249 std::forward<decltype(renderables)>(renderables)...);
250}
251//==============================================================================
252} // namespace tatooine::rendering::interactive
253//==============================================================================
254#endif
Definition: concepts.h:84
Definition: interactively_renderable.h:12
typename type_set_constructor< type_list<>, Ts... >::type type_set
Definition: type_set.h:132
auto ToggleButton(const char *str_id, bool *v) -> bool
Definition: vtp_writer.h:3
DLL_API auto clear_color(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) -> void
button
Definition: mouse.h:8
DLL_API auto clear_depth_buffer() -> void
DLL_API auto clear_color_depth_buffer() -> void
auto set_view_projection_matrices(Mat4< GLfloat > const &VP, type_set_impl< Renderers... >)
Definition: interactive.h:39
auto set_projection_matrices(Mat4< GLfloat > const &P, type_set_impl< Renderers... >)
Definition: interactive.h:29
auto set_view_matrices(Mat4< GLfloat > const &V, type_set_impl< Renderers... >)
Definition: interactive.h:20
Definition: interactive.h:15
auto pre_setup()
Call this function if you need to create gpu data before calling render.
Definition: interactive.h:57
auto show(std::index_sequence< Is... >, Renderables &&... renderables)
Definition: interactive.h:60
constexpr auto invoke(invocable auto &&...funcs)
Definition: functional.h:8
constexpr auto max(A &&a, B &&b)
Definition: math.h:20
Definition: mat.h:14
Definition: first_person_window.h:15
static auto get() -> auto &
Definition: interactive.h:48
Inherits from a type_list with only unique types.
Definition: type_set.h:138