Loading...
Searching...
No Matches
BackgroundDevice.hpp
1#pragma once
2
3#include <Scenario/Document/ScenarioDocument/ScenarioDocumentView.hpp>
4
5#include <Gfx/GfxApplicationPlugin.hpp>
6#include <Gfx/GfxParameter.hpp>
7#include <Gfx/Graph/BackgroundNode.hpp>
8
9#include <score/graphics/BackgroundRenderer.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
17namespace Gfx
18{
20{
21public:
24 {
25 this->shared_readback = std::make_shared<QRhiReadbackResult>();
26 node.shared_readback = this->shared_readback;
27 }
28
29 ~DeviceBackgroundRenderer() override { }
30
31 bool render(QPainter* painter, const QRectF& rect) override
32 {
33 auto& m_readback = *shared_readback;
34 const auto w = m_readback.pixelSize.width();
35 const auto h = m_readback.pixelSize.height();
36 painter->setRenderHint(
37 QPainter::RenderHint::SmoothPixmapTransform,
38 w > rect.width() && h > rect.height());
39 int sz = w * h * 4;
40 int bytes = m_readback.data.size();
41 if(bytes > 0 && bytes >= sz)
42 {
43 QImage img{
44 (const unsigned char*)m_readback.data.data(), w, h, w * 4,
45 QImage::Format_RGBA8888};
46 painter->drawImage(rect, img);
47 return true;
48 }
49 return false;
50 }
51
52private:
53 QPointer<Gfx::DocumentPlugin> plug;
54 std::shared_ptr<QRhiReadbackResult> shared_readback;
55};
56
57class background_device : public ossia::net::device_base
58{
60 gfx_node_base m_root;
61 QObject m_qtContext;
62 QPointer<Scenario::ScenarioDocumentView> m_view;
63 DeviceBackgroundRenderer* m_renderer{};
64
65 ossia::net::parameter_base* scaled_win{};
66 ossia::net::parameter_base* gl_win{};
67 ossia::net::parameter_base* abs_win{};
68 ossia::net::parameter_base* abs_tablet_win{};
69 ossia::net::parameter_base* size_param{};
70 ossia::net::parameter_base* rendersize_param{};
71 ossia::net::parameter_base* press_param{};
72 ossia::net::parameter_base* text_param{};
73
74 boost::container::static_vector<QMetaObject::Connection, 8> con;
75
76 void update_viewport()
77 {
78 auto v = rendersize_param->value();
79 if(auto val = v.target<ossia::vec2f>())
80 {
81 auto dom = abs_win->get_domain();
82 if((*val)[0] >= 1.f && (*val)[1] >= 1.f)
83 {
84 ossia::set_max(dom, *val);
85 abs_win->set_domain(std::move(dom));
86 abs_tablet_win->set_domain(std::move(dom));
87 }
88 else
89 {
90 // Use the normal size
91 v = size_param->value();
92 if(auto val = v.target<ossia::vec2f>())
93 {
94 auto dom = abs_win->get_domain();
95 if((*val)[0] >= 1.f && (*val)[1] >= 1.f)
96 {
97 ossia::set_max(dom, *val);
98 abs_win->set_domain(std::move(dom));
99 abs_tablet_win->set_domain(std::move(dom));
100 }
101 }
102 }
103 }
104 else
105 {
106 v = size_param->value();
107 if(auto val = v.target<ossia::vec2f>())
108 {
109 auto dom = abs_win->get_domain();
110 if((*val)[0] >= 1.f && (*val)[1] >= 1.f)
111 {
112 ossia::set_max(dom, *val);
113 abs_win->set_domain(std::move(dom));
114 abs_tablet_win->set_domain(std::move(dom));
115 }
116 }
117 }
118 }
119
120public:
122 Scenario::ScenarioDocumentView& view, std::unique_ptr<gfx_protocol_base> proto,
123 std::string name)
124 : ossia::net::device_base{std::move(proto)}
125 , m_screen{new score::gfx::BackgroundNode}
126 , m_root{*this, *static_cast<gfx_protocol_base*>(m_protocol.get()), m_screen, name}
127 , m_view{&view}
128 {
129 this->m_capabilities.change_tree = true;
130 m_renderer = new DeviceBackgroundRenderer{*m_screen};
131 view.addBackgroundRenderer(m_renderer);
132
133 auto& v = view.view();
134
135 {
136 auto size_node = std::make_unique<ossia::net::generic_node>("size", *this, m_root);
137 size_param = size_node->create_parameter(ossia::val_type::VEC2F);
138 const auto sz = view.view().size();
139 m_screen->setSize(sz);
140 size_param->push_value(ossia::vec2f{(float)sz.width(), (float)sz.height()});
141 size_param->add_callback([this](const ossia::value& v) {
142 if(auto val = v.target<ossia::vec2f>())
143 {
144 ossia::qt::run_async(&m_qtContext, [screen = this->m_screen, v = *val] {
145 screen->setSize({(int)v[0], (int)v[1]});
146 });
147
148 update_viewport();
149 }
150 });
151
152 con.push_back(
153 QObject::connect(
154 &v, &Scenario::ProcessGraphicsView::sizeChanged, &m_qtContext,
155 [this, v = QPointer{&view}, ptr = QPointer{m_screen}](QSize e) {
156 if(ptr && v)
157 {
158 size_param->push_value(ossia::vec2f{(float)e.width(), (float)e.height()});
159 }
160 }, Qt::DirectConnection));
161
162 m_root.add_child(std::move(size_node));
163 }
164 {
165 auto size_node
166 = std::make_unique<ossia::net::generic_node>("rendersize", *this, m_root);
167
168 rendersize_param = size_node->create_parameter(ossia::val_type::VEC2F);
169 rendersize_param->push_value(ossia::vec2f{0.f, 0.f});
170 rendersize_param->add_callback([this](const ossia::value& v) {
171 if(auto val = v.target<ossia::vec2f>())
172 {
173 ossia::qt::run_async(&m_qtContext, [screen = m_screen, v = *val] {
174 screen->setRenderSize({(int)v[0], (int)v[1]});
175 });
176
177 update_viewport();
178 }
179 });
180
181 m_root.add_child(std::move(size_node));
182 }
183
184 // Mouse input
185 {
186 auto node = std::make_unique<ossia::net::generic_node>("cursor", *this, m_root);
187 {
188 auto scale_node
189 = std::make_unique<ossia::net::generic_node>("scaled", *this, *node);
190 scaled_win = scale_node->create_parameter(ossia::val_type::VEC2F);
191 scaled_win->set_domain(ossia::make_domain(0.f, 1.f));
192 scaled_win->push_value(ossia::vec2f{0.f, 0.f});
193 node->add_child(std::move(scale_node));
194 }
195 {
196 auto scale_node = std::make_unique<ossia::net::generic_node>("gl", *this, *node);
197 gl_win = scale_node->create_parameter(ossia::val_type::VEC2F);
198 gl_win->set_domain(ossia::make_domain(0.f, 1.f));
199 gl_win->push_value(ossia::vec2f{0.f, 0.f});
200 node->add_child(std::move(scale_node));
201 }
202 {
203 auto abs_node
204 = std::make_unique<ossia::net::generic_node>("absolute", *this, *node);
205 abs_win = abs_node->create_parameter(ossia::val_type::VEC2F);
206 abs_win->set_domain(
207 ossia::make_domain(ossia::vec2f{0.f, 0.f}, ossia::vec2f{1280, 270.f}));
208 abs_win->push_value(ossia::vec2f{0.f, 0.f});
209 node->add_child(std::move(abs_node));
210 }
211
212 con.push_back(
213 QObject::connect(
214 &v, &Scenario::ProcessGraphicsView::hoverMove, &m_qtContext,
215 [this, v = QPointer{&view}, ptr = QPointer{m_screen}](QHoverEvent* e) {
216 if(ptr && v)
217 {
218 const auto win = e->position();
219 const auto sz = v->view().size();
220 scaled_win->push_value(
221 ossia::vec2f{float(win.x() / sz.width()), float(win.y() / sz.height())});
222 gl_win->push_value(
223 ossia::vec2f{
224 float(win.x() / sz.width()), 1.f - float(win.y() / sz.height())});
225 abs_win->push_value(ossia::vec2f{float(win.x()), float(win.y())});
226 }
227 }, Qt::DirectConnection));
228
229 m_root.add_child(std::move(node));
230 }
231
232 // Tablet input
233 ossia::net::parameter_base* scaled_tablet_win{};
234 {
235 auto node = std::make_unique<ossia::net::generic_node>("tablet", *this, m_root);
236 ossia::net::parameter_base* tablet_pressure{};
237 ossia::net::parameter_base* tablet_z{};
238 ossia::net::parameter_base* tablet_tan{};
239 ossia::net::parameter_base* tablet_rot{};
240 ossia::net::parameter_base* tablet_tilt_x{};
241 ossia::net::parameter_base* tablet_tilt_y{};
242 {
243 auto scale_node
244 = std::make_unique<ossia::net::generic_node>("scaled", *this, *node);
245 scaled_tablet_win = scale_node->create_parameter(ossia::val_type::VEC2F);
246 scaled_tablet_win->set_domain(ossia::make_domain(0.f, 1.f));
247 scaled_tablet_win->push_value(ossia::vec2f{0.f, 0.f});
248 node->add_child(std::move(scale_node));
249 }
250 {
251 auto abs_node
252 = std::make_unique<ossia::net::generic_node>("absolute", *this, *node);
253 abs_tablet_win = abs_node->create_parameter(ossia::val_type::VEC2F);
254 abs_tablet_win->set_domain(
255 ossia::make_domain(ossia::vec2f{0.f, 0.f}, ossia::vec2f{1280, 270.f}));
256 abs_tablet_win->push_value(ossia::vec2f{0.f, 0.f});
257 node->add_child(std::move(abs_node));
258 }
259 {
260 auto scale_node = std::make_unique<ossia::net::generic_node>("z", *this, *node);
261 tablet_z = scale_node->create_parameter(ossia::val_type::INT);
262 node->add_child(std::move(scale_node));
263 }
264 {
265 auto scale_node
266 = std::make_unique<ossia::net::generic_node>("pressure", *this, *node);
267 tablet_pressure = scale_node->create_parameter(ossia::val_type::FLOAT);
268 //tablet_pressure->set_domain(ossia::make_domain(0.f, 1.f));
269 //tablet_pressure->push_value(0.f);
270 node->add_child(std::move(scale_node));
271 }
272 {
273 auto scale_node
274 = std::make_unique<ossia::net::generic_node>("tangential", *this, *node);
275 tablet_tan = scale_node->create_parameter(ossia::val_type::FLOAT);
276 tablet_tan->set_domain(ossia::make_domain(-1.f, 1.f));
277 //tablet_tan->push_value(0.f);
278 node->add_child(std::move(scale_node));
279 }
280 {
281 auto scale_node
282 = std::make_unique<ossia::net::generic_node>("rotation", *this, *node);
283 tablet_rot = scale_node->create_parameter(ossia::val_type::FLOAT);
284 tablet_rot->set_unit(ossia::degree_u{});
285 tablet_rot->set_domain(ossia::make_domain(-180.f, 180.f));
286 node->add_child(std::move(scale_node));
287 }
288 {
289 auto scale_node
290 = std::make_unique<ossia::net::generic_node>("tilt_x", *this, *node);
291 tablet_tilt_x = scale_node->create_parameter(ossia::val_type::FLOAT);
292 tablet_tilt_x->set_domain(ossia::make_domain(-60.f, 60.f));
293 tablet_tilt_x->set_unit(ossia::degree_u{});
294 node->add_child(std::move(scale_node));
295 }
296 {
297 auto scale_node
298 = std::make_unique<ossia::net::generic_node>("tilt_y", *this, *node);
299 tablet_tilt_y = scale_node->create_parameter(ossia::val_type::FLOAT);
300 tablet_tilt_y->set_domain(ossia::make_domain(-60.f, 60.f));
301 tablet_tilt_y->set_unit(ossia::degree_u{});
302 node->add_child(std::move(scale_node));
303 }
304
305 con.push_back(
306 QObject::connect(
307 &v, &Scenario::ProcessGraphicsView::tabletMove, m_screen,
308 [=, this, v = QPointer{&view},
309 ptr = QPointer{m_screen}](QTabletEvent* ev) {
310 if(ptr && v)
311 {
312 auto win = ev->position();
313 auto sz = v->view().size();
314 scaled_tablet_win->push_value(
315 ossia::vec2f{float(win.x() / sz.width()), float(win.y() / sz.height())});
316 abs_tablet_win->push_value(ossia::vec2f{float(win.x()), float(win.y())});
317 tablet_pressure->push_value(ev->pressure());
318 tablet_tan->push_value(ev->tangentialPressure());
319 tablet_rot->push_value(ev->rotation());
320 tablet_z->push_value(ev->z());
321 tablet_tilt_x->push_value(ev->xTilt());
322 tablet_tilt_y->push_value(ev->yTilt());
323 }
324 },
325 Qt::DirectConnection));
326 m_root.add_child(std::move(node));
327 }
328
329 // Keyboard input
330 {
331 auto node = std::make_unique<ossia::net::generic_node>("key", *this, m_root);
332 {
333 auto press_node
334 = std::make_unique<ossia::net::generic_node>("press", *this, *node);
335 {
336 auto code_node
337 = std::make_unique<ossia::net::generic_node>("code", *this, *press_node);
338 press_param = code_node->create_parameter(ossia::val_type::INT);
339 press_param->push_value(ossia::vec2f{0.f, 0.f});
340 press_node->add_child(std::move(code_node));
341 }
342 {
343 auto text_node
344 = std::make_unique<ossia::net::generic_node>("text", *this, *press_node);
345 text_param = text_node->create_parameter(ossia::val_type::STRING);
346 press_node->add_child(std::move(text_node));
347 }
348
349 con.push_back(
350 QObject::connect(
351 &v, &Scenario::ProcessGraphicsView::keyPress, m_screen,
352 [this, v = QPointer{&view}, ptr = QPointer{m_screen}](QKeyEvent* ev) {
353 if(ptr && v)
354 {
355 if(!ev->isAutoRepeat())
356 {
357 press_param->push_value(ev->key());
358 text_param->push_value(ev->text().toStdString());
359 }
360 }
361 }, Qt::DirectConnection));
362 node->add_child(std::move(press_node));
363 }
364 {
365 auto release_node
366 = std::make_unique<ossia::net::generic_node>("release", *this, *node);
367 ossia::net::parameter_base* press_param{};
368 ossia::net::parameter_base* text_param{};
369 {
370 auto code_node
371 = std::make_unique<ossia::net::generic_node>("code", *this, *release_node);
372 press_param = code_node->create_parameter(ossia::val_type::INT);
373 press_param->push_value(ossia::vec2f{0.f, 0.f});
374 release_node->add_child(std::move(code_node));
375 }
376 {
377 auto text_node
378 = std::make_unique<ossia::net::generic_node>("text", *this, *release_node);
379 text_param = text_node->create_parameter(ossia::val_type::STRING);
380 release_node->add_child(std::move(text_node));
381 }
382
383 con.push_back(
384 QObject::connect(
385 &v, &Scenario::ProcessGraphicsView::keyRelease, m_screen,
386 [=, v = QPointer{&view}, ptr = QPointer{m_screen}](QKeyEvent* ev) {
387 if(ptr && v)
388 {
389 if(!ev->isAutoRepeat())
390 {
391 press_param->push_value(ev->key());
392 text_param->push_value(ev->text().toStdString());
393 }
394 }
395 }, Qt::DirectConnection));
396 node->add_child(std::move(release_node));
397 }
398
399 m_root.add_child(std::move(node));
400 }
401 }
402
404 {
405 if(m_view)
406 {
407 m_view->removeBackgroundRenderer(m_renderer);
408 }
409 for(auto& c : con)
410 QObject::disconnect(c);
411 delete m_renderer;
412 m_protocol->stop();
413
414 m_root.clear_children();
415
416 m_protocol.reset();
417 }
418
419 const gfx_node_base& get_root_node() const override { return m_root; }
420 gfx_node_base& get_root_node() override { return m_root; }
421};
422
423}
Definition BackgroundDevice.hpp:20
Definition BackgroundDevice.hpp:58
Definition GfxParameter.hpp:60
Definition GfxParameter.hpp:41
Definition ScenarioDocumentView.hpp:139
Definition BackgroundRenderer.hpp:13
Binds the rendering pipeline to ossia processes.
Definition CameraDevice.cpp:30
Definition BackgroundNode.hpp:12