Loading...
Searching...
No Matches
Window/WindowDevice.hpp
1#pragma once
2
3#include <Gfx/GfxParameter.hpp>
4#include <Gfx/Graph/ScreenNode.hpp>
5#include <Gfx/Graph/Window.hpp>
6#include <Gfx/Settings/Model.hpp>
7
8#include <core/application/ApplicationSettings.hpp>
9#include <score/application/ApplicationContext.hpp>
10
11#include <ossia/network/base/device.hpp>
12#include <ossia/network/base/protocol.hpp>
13#include <ossia/network/generic/generic_node.hpp>
14
15#include <ossia-qt/invoke.hpp>
16
17#include <QGuiApplication>
18
19namespace Gfx
20{
21
22static score::gfx::ScreenNode* createScreenNode(
23 SwapchainFlag swapFlag = SwapchainFlag::NoFlag,
24 SwapchainFormat swapFormat = SwapchainFormat::SDR)
25{
26 const auto& settings = score::AppContext().applicationSettings;
27 const auto& gfx_settings = score::AppContext().settings<Gfx::Settings::Model>();
28
29 auto make_configuration = [&] {
31 double rate = gfx_settings.getRate();
32 if(rate > 0)
33 conf = {.manualRenderingRate = 1000. / rate, .supportsVSync = true};
34 else
35 conf = {.manualRenderingRate = {}, .supportsVSync = true};
36 return conf;
37 };
38
39 auto node = new score::gfx::ScreenNode{
40 make_configuration(), false, (settings.autoplay || !settings.gui)};
41 node->setSwapchainFlag(swapFlag);
42 node->setSwapchainFormat(swapFormat);
43
44 QObject::connect(
45 &gfx_settings, &Gfx::Settings::Model::RateChanged, node,
46 [node, make_configuration] { node->setConfiguration(make_configuration()); });
47
48 return node;
49}
50class window_device : public ossia::net::device_base
51{
52 score::gfx::ScreenNode* m_screen{};
53 gfx_node_base m_root;
54 QObject m_qtContext;
55
56 ossia::net::parameter_base* scaled_win{};
57 ossia::net::parameter_base* abs_win{};
58 ossia::net::parameter_base* abs_tablet_win{};
59 ossia::net::parameter_base* size_param{};
60 ossia::net::parameter_base* rendersize_param{};
61
62 void update_viewport()
63 {
64 auto v = rendersize_param->value();
65 if(auto val = v.target<ossia::vec2f>())
66 {
67 auto dom = abs_win->get_domain();
68 if((*val)[0] >= 1.f && (*val)[1] >= 1.f)
69 {
70 ossia::set_max(dom, *val);
71 abs_win->set_domain(std::move(dom));
72 abs_tablet_win->set_domain(std::move(dom));
73 }
74 else
75 {
76 // Use the normal size
77 v = size_param->value();
78 if(auto val = v.target<ossia::vec2f>())
79 {
80 auto dom = abs_win->get_domain();
81 if((*val)[0] >= 1.f && (*val)[1] >= 1.f)
82 {
83 ossia::set_max(dom, *val);
84 abs_win->set_domain(std::move(dom));
85 abs_tablet_win->set_domain(std::move(dom));
86 }
87 }
88 }
89 }
90 else
91 {
92 v = size_param->value();
93 if(auto val = v.target<ossia::vec2f>())
94 {
95 auto dom = abs_win->get_domain();
96 if((*val)[0] >= 1.f && (*val)[1] >= 1.f)
97 {
98 ossia::set_max(dom, *val);
99 abs_win->set_domain(std::move(dom));
100 abs_tablet_win->set_domain(std::move(dom));
101 }
102 }
103 }
104 }
105
106public:
108 {
109 if(auto w = m_screen->window())
110 w->close();
111
112 m_screen->onWindowMove = [](QPointF) { };
113 m_screen->onMouseMove = [](QPointF, QPointF) { };
114 m_screen->onTabletMove = [](QTabletEvent*) { };
115 m_screen->onKey = [](int, const QString&) { };
116 m_screen->onKeyRelease = [](int, const QString&) { };
117 m_screen->onFps = [](float) { };
118 m_protocol->stop();
119
120 m_root.clear_children();
121
122 m_protocol.reset();
123 }
124
126 std::unique_ptr<gfx_protocol_base> proto, std::string name,
127 SwapchainFlag swapFlag = SwapchainFlag::NoFlag,
128 SwapchainFormat swapFormat = SwapchainFormat::SDR)
129 : ossia::net::device_base{std::move(proto)}
130 , m_screen{createScreenNode(swapFlag, swapFormat)}
131 , m_root{*this, *static_cast<gfx_protocol_base*>(m_protocol.get()), m_screen, name}
132 {
133 this->m_capabilities.change_tree = true;
134 m_screen->setTitle(QString::fromStdString(name));
135
136 {
137 auto screen_node
138 = std::make_unique<ossia::net::generic_node>("screen", *this, m_root);
139 auto screen_param = screen_node->create_parameter(ossia::val_type::STRING);
140 screen_param->set_domain(ossia::make_domain(int(0), int(100)));
141 screen_param->add_callback([this](const ossia::value& v) {
142 if(auto val = v.target<int>())
143 {
144 ossia::qt::run_async(&m_qtContext, [screen = this->m_screen, scr = *val] {
145 const auto& cur_screens = qGuiApp->screens();
146 if(ossia::valid_index(scr, cur_screens))
147 {
148 screen->setScreen(cur_screens[scr]);
149 }
150 });
151 }
152 else if(auto val = v.target<std::string>())
153 {
154 ossia::qt::run_async(&m_qtContext, [screen = this->m_screen, scr = *val] {
155 const auto& cur_screens = qGuiApp->screens();
156 for(auto s : cur_screens)
157 {
158 if(s->name() == scr.c_str())
159 {
160 screen->setScreen(s);
161 break;
162 }
163 }
164 });
165 }
166 });
167 m_root.add_child(std::move(screen_node));
168 }
169
170 {
171 struct move_window_lock
172 {
173 bool locked{};
174 };
175 auto lock = std::make_shared<move_window_lock>();
176
177 auto pos_node
178 = std::make_unique<ossia::net::generic_node>("position", *this, m_root);
179 auto pos_param = pos_node->create_parameter(ossia::val_type::VEC2F);
180 pos_param->push_value(
181 ossia::vec2f{100.f, 100.f}); // FIXME Try to detect center of screen ?
182 pos_param->add_callback([this, lock](const ossia::value& v) {
183 if(lock->locked)
184 return;
185 if(auto val = v.target<ossia::vec2f>())
186 {
187 ossia::qt::run_async(&m_qtContext, [screen = this->m_screen, v = *val, lock] {
188 screen->setPosition({(int)v[0], (int)v[1]});
189 });
190 }
191 });
192
193 m_screen->onWindowMove = [this, pos_param, lock](QPointF pos) {
194 if(lock->locked)
195 return;
196 if(const auto& w = m_screen->window())
197 {
198 lock->locked = true;
199 pos_param->set_value(ossia::vec2f{float(pos.x()), float(pos.y())});
200 lock->locked = false;
201 }
202 };
203 m_root.add_child(std::move(pos_node));
204 }
205
206 // Mouse input
207 {
208 auto node = std::make_unique<ossia::net::generic_node>("cursor", *this, m_root);
209 {
210 auto scale_node
211 = std::make_unique<ossia::net::generic_node>("scaled", *this, *node);
212 scaled_win = scale_node->create_parameter(ossia::val_type::VEC2F);
213 scaled_win->set_domain(ossia::make_domain(0.f, 1.f));
214 scaled_win->push_value(ossia::vec2f{0.f, 0.f});
215 node->add_child(std::move(scale_node));
216 }
217 {
218 auto abs_node
219 = std::make_unique<ossia::net::generic_node>("absolute", *this, *node);
220 abs_win = abs_node->create_parameter(ossia::val_type::VEC2F);
221 abs_win->set_domain(
222 ossia::make_domain(ossia::vec2f{0.f, 0.f}, ossia::vec2f{1280, 270.f}));
223 abs_win->push_value(ossia::vec2f{0.f, 0.f});
224 node->add_child(std::move(abs_node));
225 }
226 {
227 auto visible
228 = std::make_unique<ossia::net::generic_node>("visible", *this, *node);
229 auto param = visible->create_parameter(ossia::val_type::BOOL);
230 param->add_callback([this](const ossia::value& v) {
231 if(auto val = v.target<bool>())
232 {
233 ossia::qt::run_async(&m_qtContext, [screen = this->m_screen, v = *val] {
234 screen->setCursor(v);
235 });
236 }
237 });
238 node->add_child(std::move(visible));
239 }
240
241 m_screen->onMouseMove = [this](QPointF screen, QPointF win) {
242 if(const auto& w = m_screen->window())
243 {
244 auto sz = w->size();
245 scaled_win->push_value(
246 ossia::vec2f{float(win.x() / sz.width()), float(win.y() / sz.height())});
247 abs_win->push_value(ossia::vec2f{float(win.x()), float(win.y())});
248 }
249 };
250
251 m_root.add_child(std::move(node));
252 }
253
254 // Tablet input
255 ossia::net::parameter_base* scaled_tablet_win{};
256 {
257 auto node = std::make_unique<ossia::net::generic_node>("tablet", *this, m_root);
258 ossia::net::parameter_base* tablet_pressure{};
259 ossia::net::parameter_base* tablet_z{};
260 ossia::net::parameter_base* tablet_tan{};
261 ossia::net::parameter_base* tablet_rot{};
262 ossia::net::parameter_base* tablet_tilt_x{};
263 ossia::net::parameter_base* tablet_tilt_y{};
264 {
265 auto scale_node
266 = std::make_unique<ossia::net::generic_node>("scaled", *this, *node);
267 scaled_tablet_win = scale_node->create_parameter(ossia::val_type::VEC2F);
268 scaled_tablet_win->set_domain(ossia::make_domain(0.f, 1.f));
269 scaled_tablet_win->push_value(ossia::vec2f{0.f, 0.f});
270 node->add_child(std::move(scale_node));
271 }
272 {
273 auto abs_node
274 = std::make_unique<ossia::net::generic_node>("absolute", *this, *node);
275 abs_tablet_win = abs_node->create_parameter(ossia::val_type::VEC2F);
276 abs_tablet_win->set_domain(
277 ossia::make_domain(ossia::vec2f{0.f, 0.f}, ossia::vec2f{1280, 270.f}));
278 abs_tablet_win->push_value(ossia::vec2f{0.f, 0.f});
279 node->add_child(std::move(abs_node));
280 }
281 {
282 auto scale_node = std::make_unique<ossia::net::generic_node>("z", *this, *node);
283 tablet_z = scale_node->create_parameter(ossia::val_type::INT);
284 node->add_child(std::move(scale_node));
285 }
286 {
287 auto scale_node
288 = std::make_unique<ossia::net::generic_node>("pressure", *this, *node);
289 tablet_pressure = scale_node->create_parameter(ossia::val_type::FLOAT);
290 //tablet_pressure->set_domain(ossia::make_domain(0.f, 1.f));
291 //tablet_pressure->push_value(0.f);
292 node->add_child(std::move(scale_node));
293 }
294 {
295 auto scale_node
296 = std::make_unique<ossia::net::generic_node>("tangential", *this, *node);
297 tablet_tan = scale_node->create_parameter(ossia::val_type::FLOAT);
298 tablet_tan->set_domain(ossia::make_domain(-1.f, 1.f));
299 //tablet_tan->push_value(0.f);
300 node->add_child(std::move(scale_node));
301 }
302 {
303 auto scale_node
304 = std::make_unique<ossia::net::generic_node>("rotation", *this, *node);
305 tablet_rot = scale_node->create_parameter(ossia::val_type::FLOAT);
306 tablet_rot->set_unit(ossia::degree_u{});
307 tablet_rot->set_domain(ossia::make_domain(-180.f, 180.f));
308 node->add_child(std::move(scale_node));
309 }
310 {
311 auto scale_node
312 = std::make_unique<ossia::net::generic_node>("tilt_x", *this, *node);
313 tablet_tilt_x = scale_node->create_parameter(ossia::val_type::FLOAT);
314 tablet_tilt_x->set_domain(ossia::make_domain(-60.f, 60.f));
315 tablet_tilt_x->set_unit(ossia::degree_u{});
316 node->add_child(std::move(scale_node));
317 }
318 {
319 auto scale_node
320 = std::make_unique<ossia::net::generic_node>("tilt_y", *this, *node);
321 tablet_tilt_y = scale_node->create_parameter(ossia::val_type::FLOAT);
322 tablet_tilt_y->set_domain(ossia::make_domain(-60.f, 60.f));
323 tablet_tilt_y->set_unit(ossia::degree_u{});
324 node->add_child(std::move(scale_node));
325 }
326
327 m_screen->onTabletMove = [=, this](QTabletEvent* ev) {
328 if(const auto& w = m_screen->window())
329 {
330 const auto sz = w->size();
331 const auto win = ev->position();
332 scaled_tablet_win->push_value(
333 ossia::vec2f{float(win.x() / sz.width()), float(win.y() / sz.height())});
334 abs_tablet_win->push_value(ossia::vec2f{float(win.x()), float(win.y())});
335 tablet_pressure->push_value(ev->pressure());
336 tablet_tan->push_value(ev->tangentialPressure());
337 tablet_rot->push_value(ev->rotation());
338 tablet_z->push_value(ev->z());
339 tablet_tilt_x->push_value(ev->xTilt());
340 tablet_tilt_y->push_value(ev->yTilt());
341 }
342 };
343
344 m_root.add_child(std::move(node));
345 }
346
347 {
348 auto size_node = std::make_unique<ossia::net::generic_node>("size", *this, m_root);
349 size_param = size_node->create_parameter(ossia::val_type::VEC2F);
350 size_param->push_value(ossia::vec2f{1280.f, 720.f});
351 size_param->add_callback([this](const ossia::value& v) {
352 if(auto val = v.target<ossia::vec2f>())
353 {
354 ossia::qt::run_async(&m_qtContext, [screen = this->m_screen, v = *val] {
355 screen->setSize({(int)v[0], (int)v[1]});
356 });
357
358 update_viewport();
359 }
360 });
361
362 m_root.add_child(std::move(size_node));
363 }
364
365 {
366 auto size_node
367 = std::make_unique<ossia::net::generic_node>("rendersize", *this, m_root);
368 ossia::net::set_description(
369 *size_node, "Set to [0, 0] to use the viewport's size");
370
371 rendersize_param = size_node->create_parameter(ossia::val_type::VEC2F);
372 rendersize_param->push_value(ossia::vec2f{0.f, 0.f});
373 rendersize_param->add_callback([this](const ossia::value& v) {
374 if(auto val = v.target<ossia::vec2f>())
375 {
376 ossia::qt::run_async(&m_qtContext, [screen = this->m_screen, v = *val] {
377 screen->setRenderSize({(int)v[0], (int)v[1]});
378 });
379
380 update_viewport();
381 }
382 });
383
384 m_root.add_child(std::move(size_node));
385 }
386
387 // Keyboard input
388 {
389 auto node = std::make_unique<ossia::net::generic_node>("key", *this, m_root);
390 {
391 auto press_node
392 = std::make_unique<ossia::net::generic_node>("press", *this, *node);
393 ossia::net::parameter_base* press_param{};
394 ossia::net::parameter_base* text_param{};
395 {
396 auto code_node
397 = std::make_unique<ossia::net::generic_node>("code", *this, *press_node);
398 press_param = code_node->create_parameter(ossia::val_type::INT);
399 press_param->push_value(ossia::vec2f{0.f, 0.f});
400 press_node->add_child(std::move(code_node));
401 }
402 {
403 auto text_node
404 = std::make_unique<ossia::net::generic_node>("text", *this, *press_node);
405 text_param = text_node->create_parameter(ossia::val_type::STRING);
406 press_node->add_child(std::move(text_node));
407 }
408
409 m_screen->onKey = [press_param, text_param](int key, const QString& text) {
410 press_param->push_value(key);
411 text_param->push_value(text.toStdString());
412 };
413 node->add_child(std::move(press_node));
414 }
415 {
416 auto release_node
417 = std::make_unique<ossia::net::generic_node>("release", *this, *node);
418 ossia::net::parameter_base* press_param{};
419 ossia::net::parameter_base* text_param{};
420 {
421 auto code_node
422 = std::make_unique<ossia::net::generic_node>("code", *this, *release_node);
423 press_param = code_node->create_parameter(ossia::val_type::INT);
424 press_param->push_value(ossia::vec2f{0.f, 0.f});
425 release_node->add_child(std::move(code_node));
426 }
427 {
428 auto text_node
429 = std::make_unique<ossia::net::generic_node>("text", *this, *release_node);
430 text_param = text_node->create_parameter(ossia::val_type::STRING);
431 release_node->add_child(std::move(text_node));
432 }
433
434 m_screen->onKeyRelease
435 = [press_param, text_param](int key, const QString& text) {
436 press_param->push_value(key);
437 text_param->push_value(text.toStdString());
438 };
439 node->add_child(std::move(release_node));
440 }
441
442 m_root.add_child(std::move(node));
443 }
444
445 {
446 auto fs_node
447 = std::make_unique<ossia::net::generic_node>("fullscreen", *this, m_root);
448 auto fs_param = fs_node->create_parameter(ossia::val_type::BOOL);
449 fs_param->add_callback([this](const ossia::value& v) {
450 if(auto val = v.target<bool>())
451 {
452 ossia::qt::run_async(&m_qtContext, [screen = this->m_screen, v = *val] {
453 screen->setFullScreen(v);
454 });
455 }
456 });
457 m_root.add_child(std::move(fs_node));
458 }
459
460 {
461 auto fps_node = std::make_unique<ossia::net::generic_node>("fps", *this, m_root);
462 auto fps_param = fps_node->create_parameter(ossia::val_type::FLOAT);
463 m_screen->onFps = [fps_param](float fps) { fps_param->push_value(fps); };
464 m_root.add_child(std::move(fps_node));
465 }
466 }
467
468 const gfx_node_base& get_root_node() const override { return m_root; }
469 gfx_node_base& get_root_node() override { return m_root; }
470};
471
472}
Definition score-plugin-gfx/Gfx/Settings/Model.hpp:41
Definition GfxParameter.hpp:60
Definition GfxParameter.hpp:41
Definition Window/WindowDevice.hpp:51
Binds the rendering pipeline to ossia processes.
Definition CameraDevice.cpp:30
T & settings() const
Access a specific Settings model instance.
Definition ApplicationContext.hpp:41
const score::ApplicationSettings & applicationSettings
Access to start-up command-line settings.
Definition ApplicationContext.hpp:94
Definition OutputNode.hpp:61
This node is used for rendering to a score::gfx::Window.
Definition ScreenNode.hpp:13