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* abs_win{};
67 ossia::net::parameter_base* abs_tablet_win{};
68 ossia::net::parameter_base* size_param{};
69 ossia::net::parameter_base* rendersize_param{};
70 ossia::net::parameter_base* press_param{};
71 ossia::net::parameter_base* text_param{};
72
73 boost::container::static_vector<QMetaObject::Connection, 8> con;
74
75 void update_viewport()
76 {
77 auto v = rendersize_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 else
88 {
89 // Use the normal size
90 v = size_param->value();
91 if(auto val = v.target<ossia::vec2f>())
92 {
93 auto dom = abs_win->get_domain();
94 if((*val)[0] >= 1.f && (*val)[1] >= 1.f)
95 {
96 ossia::set_max(dom, *val);
97 abs_win->set_domain(std::move(dom));
98 abs_tablet_win->set_domain(std::move(dom));
99 }
100 }
101 }
102 }
103 else
104 {
105 v = size_param->value();
106 if(auto val = v.target<ossia::vec2f>())
107 {
108 auto dom = abs_win->get_domain();
109 if((*val)[0] >= 1.f && (*val)[1] >= 1.f)
110 {
111 ossia::set_max(dom, *val);
112 abs_win->set_domain(std::move(dom));
113 abs_tablet_win->set_domain(std::move(dom));
114 }
115 }
116 }
117 }
118
119public:
121 Scenario::ScenarioDocumentView& view, std::unique_ptr<gfx_protocol_base> proto,
122 std::string name)
123 : ossia::net::device_base{std::move(proto)}
124 , m_screen{new score::gfx::BackgroundNode}
125 , m_root{*this, *static_cast<gfx_protocol_base*>(m_protocol.get()), m_screen, name}
126 , m_view{&view}
127 {
128 this->m_capabilities.change_tree = true;
129 m_renderer = new DeviceBackgroundRenderer{*m_screen};
130 view.addBackgroundRenderer(m_renderer);
131
132 auto& v = view.view();
133
134 {
135 auto size_node = std::make_unique<ossia::net::generic_node>("size", *this, m_root);
136 size_param = size_node->create_parameter(ossia::val_type::VEC2F);
137 const auto sz = view.view().size();
138 m_screen->setSize(sz);
139 size_param->push_value(ossia::vec2f{(float)sz.width(), (float)sz.height()});
140 size_param->add_callback([this](const ossia::value& v) {
141 if(auto val = v.target<ossia::vec2f>())
142 {
143 ossia::qt::run_async(&m_qtContext, [screen = this->m_screen, v = *val] {
144 screen->setSize({(int)v[0], (int)v[1]});
145 });
146
147 update_viewport();
148 }
149 });
150
151 con.push_back(
152 QObject::connect(
153 &v, &Scenario::ProcessGraphicsView::sizeChanged, &m_qtContext,
154 [this, v = QPointer{&view}, ptr = QPointer{m_screen}](QSize e) {
155 if(ptr && v)
156 {
157 size_param->push_value(ossia::vec2f{(float)e.width(), (float)e.height()});
158 }
159 }, Qt::DirectConnection));
160
161 m_root.add_child(std::move(size_node));
162 }
163 {
164 auto size_node
165 = std::make_unique<ossia::net::generic_node>("rendersize", *this, m_root);
166
167 rendersize_param = size_node->create_parameter(ossia::val_type::VEC2F);
168 rendersize_param->push_value(ossia::vec2f{0.f, 0.f});
169 rendersize_param->add_callback([this](const ossia::value& v) {
170 if(auto val = v.target<ossia::vec2f>())
171 {
172 ossia::qt::run_async(&m_qtContext, [screen = m_screen, v = *val] {
173 screen->setRenderSize({(int)v[0], (int)v[1]});
174 });
175
176 update_viewport();
177 }
178 });
179
180 m_root.add_child(std::move(size_node));
181 }
182
183 // Mouse input
184 {
185 auto node = std::make_unique<ossia::net::generic_node>("cursor", *this, m_root);
186 {
187 auto scale_node
188 = std::make_unique<ossia::net::generic_node>("scaled", *this, *node);
189 scaled_win = scale_node->create_parameter(ossia::val_type::VEC2F);
190 scaled_win->set_domain(ossia::make_domain(0.f, 1.f));
191 scaled_win->push_value(ossia::vec2f{0.f, 0.f});
192 node->add_child(std::move(scale_node));
193 }
194 {
195 auto abs_node
196 = std::make_unique<ossia::net::generic_node>("absolute", *this, *node);
197 abs_win = abs_node->create_parameter(ossia::val_type::VEC2F);
198 abs_win->set_domain(
199 ossia::make_domain(ossia::vec2f{0.f, 0.f}, ossia::vec2f{1280, 270.f}));
200 abs_win->push_value(ossia::vec2f{0.f, 0.f});
201 node->add_child(std::move(abs_node));
202 }
203
204 con.push_back(
205 QObject::connect(
206 &v, &Scenario::ProcessGraphicsView::hoverMove, &m_qtContext,
207 [this, v = QPointer{&view}, ptr = QPointer{m_screen}](QHoverEvent* e) {
208 if(ptr && v)
209 {
210 auto win = e->position();
211 auto sz = v->view().size();
212 scaled_win->push_value(
213 ossia::vec2f{float(win.x() / sz.width()), float(win.y() / sz.height())});
214 abs_win->push_value(ossia::vec2f{float(win.x()), float(win.y())});
215 }
216 }, Qt::DirectConnection));
217
218 m_root.add_child(std::move(node));
219 }
220
221 // Tablet input
222 ossia::net::parameter_base* scaled_tablet_win{};
223 {
224 auto node = std::make_unique<ossia::net::generic_node>("tablet", *this, m_root);
225 ossia::net::parameter_base* tablet_pressure{};
226 ossia::net::parameter_base* tablet_z{};
227 ossia::net::parameter_base* tablet_tan{};
228 ossia::net::parameter_base* tablet_rot{};
229 ossia::net::parameter_base* tablet_tilt_x{};
230 ossia::net::parameter_base* tablet_tilt_y{};
231 {
232 auto scale_node
233 = std::make_unique<ossia::net::generic_node>("scaled", *this, *node);
234 scaled_tablet_win = scale_node->create_parameter(ossia::val_type::VEC2F);
235 scaled_tablet_win->set_domain(ossia::make_domain(0.f, 1.f));
236 scaled_tablet_win->push_value(ossia::vec2f{0.f, 0.f});
237 node->add_child(std::move(scale_node));
238 }
239 {
240 auto abs_node
241 = std::make_unique<ossia::net::generic_node>("absolute", *this, *node);
242 abs_tablet_win = abs_node->create_parameter(ossia::val_type::VEC2F);
243 abs_tablet_win->set_domain(
244 ossia::make_domain(ossia::vec2f{0.f, 0.f}, ossia::vec2f{1280, 270.f}));
245 abs_tablet_win->push_value(ossia::vec2f{0.f, 0.f});
246 node->add_child(std::move(abs_node));
247 }
248 {
249 auto scale_node = std::make_unique<ossia::net::generic_node>("z", *this, *node);
250 tablet_z = scale_node->create_parameter(ossia::val_type::INT);
251 node->add_child(std::move(scale_node));
252 }
253 {
254 auto scale_node
255 = std::make_unique<ossia::net::generic_node>("pressure", *this, *node);
256 tablet_pressure = scale_node->create_parameter(ossia::val_type::FLOAT);
257 //tablet_pressure->set_domain(ossia::make_domain(0.f, 1.f));
258 //tablet_pressure->push_value(0.f);
259 node->add_child(std::move(scale_node));
260 }
261 {
262 auto scale_node
263 = std::make_unique<ossia::net::generic_node>("tangential", *this, *node);
264 tablet_tan = scale_node->create_parameter(ossia::val_type::FLOAT);
265 tablet_tan->set_domain(ossia::make_domain(-1.f, 1.f));
266 //tablet_tan->push_value(0.f);
267 node->add_child(std::move(scale_node));
268 }
269 {
270 auto scale_node
271 = std::make_unique<ossia::net::generic_node>("rotation", *this, *node);
272 tablet_rot = scale_node->create_parameter(ossia::val_type::FLOAT);
273 tablet_rot->set_unit(ossia::degree_u{});
274 tablet_rot->set_domain(ossia::make_domain(-180.f, 180.f));
275 node->add_child(std::move(scale_node));
276 }
277 {
278 auto scale_node
279 = std::make_unique<ossia::net::generic_node>("tilt_x", *this, *node);
280 tablet_tilt_x = scale_node->create_parameter(ossia::val_type::FLOAT);
281 tablet_tilt_x->set_domain(ossia::make_domain(-60.f, 60.f));
282 tablet_tilt_x->set_unit(ossia::degree_u{});
283 node->add_child(std::move(scale_node));
284 }
285 {
286 auto scale_node
287 = std::make_unique<ossia::net::generic_node>("tilt_y", *this, *node);
288 tablet_tilt_y = scale_node->create_parameter(ossia::val_type::FLOAT);
289 tablet_tilt_y->set_domain(ossia::make_domain(-60.f, 60.f));
290 tablet_tilt_y->set_unit(ossia::degree_u{});
291 node->add_child(std::move(scale_node));
292 }
293
294 con.push_back(
295 QObject::connect(
296 &v, &Scenario::ProcessGraphicsView::tabletMove, m_screen,
297 [=, this, v = QPointer{&view},
298 ptr = QPointer{m_screen}](QTabletEvent* ev) {
299 if(ptr && v)
300 {
301 auto win = ev->position();
302 auto sz = v->view().size();
303 scaled_tablet_win->push_value(
304 ossia::vec2f{float(win.x() / sz.width()), float(win.y() / sz.height())});
305 abs_tablet_win->push_value(ossia::vec2f{float(win.x()), float(win.y())});
306 tablet_pressure->push_value(ev->pressure());
307 tablet_tan->push_value(ev->tangentialPressure());
308 tablet_rot->push_value(ev->rotation());
309 tablet_z->push_value(ev->z());
310 tablet_tilt_x->push_value(ev->xTilt());
311 tablet_tilt_y->push_value(ev->yTilt());
312 }
313 },
314 Qt::DirectConnection));
315 m_root.add_child(std::move(node));
316 }
317
318 // Keyboard input
319 {
320 auto node = std::make_unique<ossia::net::generic_node>("key", *this, m_root);
321 {
322 auto press_node
323 = std::make_unique<ossia::net::generic_node>("press", *this, *node);
324 {
325 auto code_node
326 = std::make_unique<ossia::net::generic_node>("code", *this, *press_node);
327 press_param = code_node->create_parameter(ossia::val_type::INT);
328 press_param->push_value(ossia::vec2f{0.f, 0.f});
329 press_node->add_child(std::move(code_node));
330 }
331 {
332 auto text_node
333 = std::make_unique<ossia::net::generic_node>("text", *this, *press_node);
334 text_param = text_node->create_parameter(ossia::val_type::STRING);
335 press_node->add_child(std::move(text_node));
336 }
337
338 con.push_back(
339 QObject::connect(
340 &v, &Scenario::ProcessGraphicsView::keyPress, m_screen,
341 [this, v = QPointer{&view}, ptr = QPointer{m_screen}](QKeyEvent* ev) {
342 if(ptr && v)
343 {
344 if(!ev->isAutoRepeat())
345 {
346 press_param->push_value(ev->key());
347 text_param->push_value(ev->text().toStdString());
348 }
349 }
350 }, Qt::DirectConnection));
351 node->add_child(std::move(press_node));
352 }
353 {
354 auto release_node
355 = std::make_unique<ossia::net::generic_node>("release", *this, *node);
356 ossia::net::parameter_base* press_param{};
357 ossia::net::parameter_base* text_param{};
358 {
359 auto code_node
360 = std::make_unique<ossia::net::generic_node>("code", *this, *release_node);
361 press_param = code_node->create_parameter(ossia::val_type::INT);
362 press_param->push_value(ossia::vec2f{0.f, 0.f});
363 release_node->add_child(std::move(code_node));
364 }
365 {
366 auto text_node
367 = std::make_unique<ossia::net::generic_node>("text", *this, *release_node);
368 text_param = text_node->create_parameter(ossia::val_type::STRING);
369 release_node->add_child(std::move(text_node));
370 }
371
372 con.push_back(
373 QObject::connect(
374 &v, &Scenario::ProcessGraphicsView::keyRelease, m_screen,
375 [=, v = QPointer{&view}, ptr = QPointer{m_screen}](QKeyEvent* ev) {
376 if(ptr && v)
377 {
378 if(!ev->isAutoRepeat())
379 {
380 press_param->push_value(ev->key());
381 text_param->push_value(ev->text().toStdString());
382 }
383 }
384 }, Qt::DirectConnection));
385 node->add_child(std::move(release_node));
386 }
387
388 m_root.add_child(std::move(node));
389 }
390 }
391
393 {
394 if(m_view)
395 {
396 m_view->removeBackgroundRenderer(m_renderer);
397 }
398 for(auto& c : con)
399 QObject::disconnect(c);
400 delete m_renderer;
401 m_protocol->stop();
402
403 m_root.clear_children();
404
405 m_protocol.reset();
406 }
407
408 const gfx_node_base& get_root_node() const override { return m_root; }
409 gfx_node_base& get_root_node() override { return m_root; }
410};
411
412}
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