Loading...
Searching...
No Matches
ISFProcess.hpp
1#pragma once
2
3#include <Process/Dataflow/WidgetInlets.hpp>
4#include <Process/ProcessFactory.hpp>
5
6#include <Explorer/DocumentPlugin/DeviceDocumentPlugin.hpp>
7
8#include <Gfx/TexturePort.hpp>
9#include <Gfx/WindowDevice.hpp>
10
11#include <score/tools/File.hpp>
12
13#include <ossia/detail/flat_map.hpp>
14
15#include <QFile>
16
17#include <isf.hpp>
18
19namespace Gfx
20{
22{
23 template <typename T>
24 static Process::Descriptor descriptorFromISFFile(QString path)
25 {
27 if(path.isEmpty())
28 return base;
29
30 QFile f{path};
31 if(!f.open(QIODevice::ReadOnly))
32 return base;
33
34 try
35 {
36 auto [_, desc] = isf::parser::parse_isf_header(score::readFileAsString(f));
37 if(desc.credits.starts_with("Automatically converted from "))
38 desc.credits = desc.credits.substr(strlen("Automatically converted from "));
39 else if(desc.credits.starts_with("by "))
40 desc.credits = desc.credits.substr(strlen("by "));
41 if(!desc.credits.empty())
42 base.author = QString::fromStdString(desc.credits);
43 if(!desc.description.empty())
44 base.description = QString::fromStdString(desc.description);
45 for(auto& cat : desc.categories)
46 base.tags.push_back(QString::fromStdString(cat));
47 }
48 catch(...)
49 {
50 }
51
52 return base;
53 }
54
55 template <typename T>
56 static void setupISFModelPorts(
57 T& self, const isf::descriptor& desc,
58 const ossia::flat_map<QString, ossia::value>& previous_values)
59 {
60 /*
61 {
62 auto& [shader, error] = score::gfx::ShaderCache::get(
63 m_processedProgram.vertex.toLatin1(), QShader::Stage::VertexStage);
64 SCORE_ASSERT(error.isEmpty());
65 }
66 {
67 auto& [shader, error] = score::gfx::ShaderCache::get(
68 m_processedProgram.fragment.toLatin1(), QShader::Stage::FragmentStage);
69 SCORE_ASSERT(error.isEmpty());
70 }
71 */
72
73 int i = 0;
74 using namespace isf;
75
76 struct input_vis
77 {
78 const ossia::flat_map<QString, ossia::value>& previous_values;
79 const isf::input& input;
80 const int i;
81 T& self;
82
83 Process::Inlet* operator()(const float_input& v)
84 {
85 auto nm = QString::fromStdString(input.name);
86 auto port = new Process::FloatSlider(
87 v.min, v.max, v.def, nm, Id<Process::Port>(i), &self);
88
89 self.m_inlets.push_back(port);
90 if(auto it = previous_values.find(nm);
91 it != previous_values.end()
92 && it->second.get_type() == ossia::val_type::FLOAT)
93 port->setValue(it->second);
94
95 self.controlAdded(port->id());
96 return port;
97 }
98
99 Process::Inlet* operator()(const long_input& v)
100 {
101 auto nm = QString::fromStdString(input.name);
102
103 std::vector<std::pair<QString, ossia::value>> alternatives;
104 if(v.labels.size() == v.values.size())
105 {
106 // Sane, respectful example
107 for(std::size_t value_idx = 0; value_idx < v.values.size(); value_idx++)
108 {
109 auto& val = v.values[value_idx];
110 if(auto int_ptr = ossia::get_if<int64_t>(&val))
111 {
112 alternatives.emplace_back(
113 QString::fromStdString(v.labels[value_idx]), int(*int_ptr));
114 }
115 else if(auto dbl_ptr = ossia::get_if<double>(&val))
116 {
117 alternatives.emplace_back(
118 QString::fromStdString(v.labels[value_idx]), int(*dbl_ptr));
119 }
120 else
121 {
122 alternatives.emplace_back(
123 QString::fromStdString(v.labels[value_idx]), int(value_idx));
124 }
125 }
126 }
127 else
128 {
129 for(std::size_t value_idx = 0; value_idx < v.values.size(); value_idx++)
130 {
131 auto& val = v.values[value_idx];
132 if(auto int_ptr = ossia::get_if<int64_t>(&val))
133 {
134 alternatives.emplace_back(QString::number(*int_ptr), int(*int_ptr));
135 }
136 else if(auto dbl_ptr = ossia::get_if<double>(&val))
137 {
138 alternatives.emplace_back(QString::number(*dbl_ptr), int(*dbl_ptr));
139 }
140 else if(auto str_ptr = ossia::get_if<std::string>(&val))
141 {
142 alternatives.emplace_back(
143 QString::fromStdString(*str_ptr), int(value_idx));
144 }
145 }
146 }
147
148 if(alternatives.empty())
149 {
150 alternatives.emplace_back("0", 0);
151 alternatives.emplace_back("1", 1);
152 alternatives.emplace_back("2", 2);
153 }
154
155 auto port = new Process::ComboBox(
156 std::move(alternatives), (int)v.def, nm, Id<Process::Port>(i), &self);
157
158 if(auto it = previous_values.find(nm);
159 it != previous_values.end()
160 && it->second.get_type() == port->value().get_type())
161 port->setValue(it->second);
162
163 self.m_inlets.push_back(port);
164 self.controlAdded(port->id());
165 return port;
166 }
167
168 Process::Inlet* operator()(const event_input& v)
169 {
170 auto nm = QString::fromStdString(input.name);
171 auto port = new Process::Button(nm, Id<Process::Port>(i), &self);
172
173 self.m_inlets.push_back(port);
174 self.controlAdded(port->id());
175 return port;
176 }
177
178 Process::Inlet* operator()(const bool_input& v)
179 {
180 auto nm = QString::fromStdString(input.name);
181 auto port = new Process::Toggle(v.def, nm, Id<Process::Port>(i), &self);
182
183 if(auto it = previous_values.find(nm);
184 it != previous_values.end()
185 && it->second.get_type() == port->value().get_type())
186 port->setValue(it->second);
187
188 self.m_inlets.push_back(port);
189 self.controlAdded(port->id());
190 return port;
191 }
192
193 Process::Inlet* operator()(const point2d_input& v)
194 {
195 auto nm = QString::fromStdString(input.name);
196 ossia::vec2f min{-100., -100.};
197 ossia::vec2f max{100., 100.};
198 ossia::vec2f init{0.0, 0.0};
199 if(v.def)
200 std::copy_n(v.def->begin(), 2, init.begin());
201 if(v.min)
202 std::copy_n(v.min->begin(), 2, min.begin());
203 if(v.max)
204 std::copy_n(v.max->begin(), 2, max.begin());
205 auto port = new Process::XYSpinboxes{
206 min, max, init, false, nm, Id<Process::Port>(i), &self};
207
208 auto& ctx = score::IDocument::documentContext(self);
209 auto& device_plug = ctx.template plugin<Explorer::DeviceDocumentPlugin>();
210 const Device::DeviceList& list = device_plug.list();
211 QString firstWindowDeviceName;
212 for(auto dev : list.devices())
213 {
214 if(auto win = qobject_cast<WindowDevice*>(dev))
215 {
216 firstWindowDeviceName = win->name();
217 break;
218 }
219 }
220
221 if(!firstWindowDeviceName.isEmpty())
222 {
223 if(nm.contains("iMouse"))
224 port->setAddress(
226 State::Address{firstWindowDeviceName, {"cursor", "absolute"}}});
227 else if(nm.contains("mouse", Qt::CaseInsensitive))
228 port->setAddress(
230 State::Address{firstWindowDeviceName, {"cursor", "scaled"}}});
231 }
232
233 if(auto it = previous_values.find(nm);
234 it != previous_values.end()
235 && it->second.get_type() == port->value().get_type())
236 port->setValue(it->second);
237
238 self.m_inlets.push_back(port);
239 self.controlAdded(port->id());
240 return port;
241 }
242
243 Process::Inlet* operator()(const point3d_input& v)
244 {
245 auto nm = QString::fromStdString(input.name);
246 ossia::vec3f min{-100., -100., -100.};
247 ossia::vec3f max{100., 100., 100.};
248 ossia::vec3f init{0., 0., 0.};
249 if(v.def)
250 std::copy_n(v.def->begin(), 3, init.begin());
251 if(v.min)
252 std::copy_n(v.min->begin(), 3, min.begin());
253 if(v.max)
254 std::copy_n(v.max->begin(), 3, max.begin());
255 auto port = new Process::XYZSpinboxes{
256 min, max, init, false, nm, Id<Process::Port>(i), &self};
257
258 if(auto it = previous_values.find(nm);
259 it != previous_values.end()
260 && it->second.get_type() == port->value().get_type())
261 port->setValue(it->second);
262
263 self.m_inlets.push_back(port);
264 self.controlAdded(port->id());
265 return port;
266 }
267
268 Process::Inlet* operator()(const color_input& v)
269 {
270 auto nm = QString::fromStdString(input.name);
271 ossia::vec4f init{0.5, 0.5, 0.5, 1.};
272 if(v.def)
273 {
274 std::copy_n(v.def->begin(), 4, init.begin());
275 }
276 auto port = new Process::HSVSlider(
277 init, QString::fromStdString(input.name), Id<Process::Port>(i), &self);
278
279 if(auto it = previous_values.find(nm);
280 it != previous_values.end()
281 && it->second.get_type() == port->value().get_type())
282 port->setValue(it->second);
283
284 self.m_inlets.push_back(port);
285 self.controlAdded(port->id());
286 return port;
287 }
288 Process::Inlet* operator()(const image_input& v)
289 {
290 auto port = new Gfx::TextureInlet(
291 QString::fromStdString(input.name), Id<Process::Port>(i), &self);
292
293 self.m_inlets.push_back(port);
294 return port;
295 }
296 Process::Inlet* operator()(const audio_input& v)
297 {
298 auto port = new Process::AudioInlet(
299 QString::fromStdString(input.name), Id<Process::Port>(i), &self);
300 self.m_inlets.push_back(port);
301 return port;
302 }
303 Process::Inlet* operator()(const audioFFT_input& v)
304 {
305 auto port = new Process::AudioInlet(
306 QString::fromStdString(input.name), Id<Process::Port>(i), &self);
307 self.m_inlets.push_back(port);
308 return port;
309 }
310 Process::Inlet* operator()(const audioHist_input& v)
311 {
312 auto port = new Process::AudioInlet(
313 QString::fromStdString(input.name), Id<Process::Port>(i), &self);
314 self.m_inlets.push_back(port);
315 return port;
316 }
317
318 // CSF-specific input handlers
319 Process::Inlet* operator()(const storage_input& v) { return nullptr; }
320 Process::Inlet* operator()(const texture_input& v) { return nullptr; }
321 Process::Inlet* operator()(const csf_image_input& v) { return nullptr; }
322 };
323
324 for(const isf::input& input : desc.inputs)
325 {
326 ossia::visit(input_vis{previous_values, input, i, self}, input.data);
327 i++;
328 }
329 }
330};
331}
The DeviceList class.
Definition DeviceList.hpp:26
Definition Port.hpp:301
Definition Port.hpp:179
The id_base_t class.
Definition Identifier.hpp:59
Binds the rendering pipeline to ossia processes.
Definition CameraDevice.cpp:24
Definition ISFProcess.hpp:22
Static metadata implementation.
Definition lib/score/tools/Metadata.hpp:36
Definition WidgetInlets.hpp:488
Definition WidgetInlets.hpp:444
Definition score-lib-process/Process/ProcessMetadata.hpp:37
Definition WidgetInlets.hpp:158
Definition WidgetInlets.hpp:512
Definition WidgetInlets.hpp:324
Definition WidgetInlets.hpp:559
Definition WidgetInlets.hpp:583
Definition Address.hpp:108
The Address struct.
Definition Address.hpp:58