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