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 struct input_vis
76 {
77 const ossia::flat_map<QString, ossia::value>& previous_values;
78 const isf::input& input;
79 const int i;
80 T& self;
81
82 Process::Inlet* operator()(const float_input& v)
83 {
84 auto nm = QString::fromStdString(input.name);
85 auto port = new Process::FloatSlider(
86 v.min, v.max, v.def, nm, Id<Process::Port>(i), &self);
87
88 self.m_inlets.push_back(port);
89 if(auto it = previous_values.find(nm);
90 it != previous_values.end()
91 && it->second.get_type() == ossia::val_type::FLOAT)
92 port->setValue(it->second);
93
94 self.controlAdded(port->id());
95 return port;
96 }
97
98 Process::Inlet* operator()(const long_input& v)
99 {
100 auto nm = QString::fromStdString(input.name);
101
102 std::vector<std::pair<QString, ossia::value>> alternatives;
103 if(v.labels.size() == v.values.size())
104 {
105 // Sane, respectful example
106 for(std::size_t value_idx = 0; value_idx < v.values.size(); value_idx++)
107 {
108 auto& val = v.values[value_idx];
109 if(auto int_ptr = ossia::get_if<int64_t>(&val))
110 {
111 alternatives.emplace_back(
112 QString::fromStdString(v.labels[value_idx]), int(*int_ptr));
113 }
114 else if(auto dbl_ptr = ossia::get_if<double>(&val))
115 {
116 alternatives.emplace_back(
117 QString::fromStdString(v.labels[value_idx]), int(*dbl_ptr));
118 }
119 else
120 {
121 alternatives.emplace_back(
122 QString::fromStdString(v.labels[value_idx]), int(value_idx));
123 }
124 }
125 }
126 else
127 {
128 for(std::size_t value_idx = 0; value_idx < v.values.size(); value_idx++)
129 {
130 auto& val = v.values[value_idx];
131 if(auto int_ptr = ossia::get_if<int64_t>(&val))
132 {
133 alternatives.emplace_back(QString::number(*int_ptr), int(*int_ptr));
134 }
135 else if(auto dbl_ptr = ossia::get_if<double>(&val))
136 {
137 alternatives.emplace_back(QString::number(*dbl_ptr), int(*dbl_ptr));
138 }
139 else if(auto str_ptr = ossia::get_if<std::string>(&val))
140 {
141 alternatives.emplace_back(
142 QString::fromStdString(*str_ptr), int(value_idx));
143 }
144 }
145 }
146
147 if(alternatives.empty())
148 {
149 alternatives.emplace_back("0", 0);
150 alternatives.emplace_back("1", 1);
151 alternatives.emplace_back("2", 2);
152 }
153
154 auto port = new Process::ComboBox(
155 std::move(alternatives), (int)v.def, nm, Id<Process::Port>(i), &self);
156
157 if(auto it = previous_values.find(nm);
158 it != previous_values.end()
159 && it->second.get_type() == port->value().get_type())
160 port->setValue(it->second);
161
162 self.m_inlets.push_back(port);
163 self.controlAdded(port->id());
164 return port;
165 }
166
167 Process::Inlet* operator()(const event_input& v)
168 {
169 auto nm = QString::fromStdString(input.name);
170 auto port = new Process::Button(nm, Id<Process::Port>(i), &self);
171
172 self.m_inlets.push_back(port);
173 self.controlAdded(port->id());
174 return port;
175 }
176
177 Process::Inlet* operator()(const bool_input& v)
178 {
179 auto nm = QString::fromStdString(input.name);
180 auto port = new Process::Toggle(v.def, nm, Id<Process::Port>(i), &self);
181
182 if(auto it = previous_values.find(nm);
183 it != previous_values.end()
184 && it->second.get_type() == port->value().get_type())
185 port->setValue(it->second);
186
187 self.m_inlets.push_back(port);
188 self.controlAdded(port->id());
189 return port;
190 }
191
192 Process::Inlet* operator()(const point2d_input& v)
193 {
194 auto nm = QString::fromStdString(input.name);
195 ossia::vec2f min{-100., -100.};
196 ossia::vec2f max{100., 100.};
197 ossia::vec2f init{0.0, 0.0};
198 if(v.def)
199 std::copy_n(v.def->begin(), 2, init.begin());
200 if(v.min)
201 std::copy_n(v.min->begin(), 2, min.begin());
202 if(v.max)
203 std::copy_n(v.max->begin(), 2, max.begin());
204 auto port = new Process::XYSpinboxes{
205 min, max, init, false, nm, Id<Process::Port>(i), &self};
206
207 auto& ctx = score::IDocument::documentContext(self);
208 auto& device_plug = ctx.template plugin<Explorer::DeviceDocumentPlugin>();
209 const Device::DeviceList& list = device_plug.list();
210 QString firstWindowDeviceName;
211 for(auto dev : list.devices())
212 {
213 if(auto win = qobject_cast<WindowDevice*>(dev))
214 {
215 firstWindowDeviceName = win->name();
216 break;
217 }
218 }
219
220 if(!firstWindowDeviceName.isEmpty())
221 {
222 if(nm.contains("iMouse"))
223 port->setAddress(
225 State::Address{firstWindowDeviceName, {"cursor", "absolute"}}});
226 else if(nm.contains("mouse", Qt::CaseInsensitive))
227 port->setAddress(
229 State::Address{firstWindowDeviceName, {"cursor", "scaled"}}});
230 }
231
232 if(auto it = previous_values.find(nm);
233 it != previous_values.end()
234 && it->second.get_type() == port->value().get_type())
235 port->setValue(it->second);
236
237 self.m_inlets.push_back(port);
238 self.controlAdded(port->id());
239 return port;
240 }
241
242 Process::Inlet* operator()(const point3d_input& v)
243 {
244 auto nm = QString::fromStdString(input.name);
245 ossia::vec3f min{-100., -100., -100.};
246 ossia::vec3f max{100., 100., 100.};
247 ossia::vec3f init{0., 0., 0.};
248 if(v.def)
249 std::copy_n(v.def->begin(), 3, init.begin());
250 if(v.min)
251 std::copy_n(v.min->begin(), 3, min.begin());
252 if(v.max)
253 std::copy_n(v.max->begin(), 3, max.begin());
254 auto port
255 = new Process::XYZSpinboxes{min, max, init, nm, Id<Process::Port>(i), &self};
256
257 if(auto it = previous_values.find(nm);
258 it != previous_values.end()
259 && it->second.get_type() == port->value().get_type())
260 port->setValue(it->second);
261
262 self.m_inlets.push_back(port);
263 self.controlAdded(port->id());
264 return port;
265 }
266
267 Process::Inlet* operator()(const color_input& v)
268 {
269 auto nm = QString::fromStdString(input.name);
270 ossia::vec4f init{0.5, 0.5, 0.5, 1.};
271 if(v.def)
272 {
273 std::copy_n(v.def->begin(), 4, init.begin());
274 }
275 auto port = new Process::HSVSlider(
276 init, QString::fromStdString(input.name), Id<Process::Port>(i), &self);
277
278 if(auto it = previous_values.find(nm);
279 it != previous_values.end()
280 && it->second.get_type() == port->value().get_type())
281 port->setValue(it->second);
282
283 self.m_inlets.push_back(port);
284 self.controlAdded(port->id());
285 return port;
286 }
287 Process::Inlet* operator()(const image_input& v)
288 {
289 auto port = new Gfx::TextureInlet(Id<Process::Port>(i), &self);
290 port->setName(QString::fromStdString(input.name));
291 self.m_inlets.push_back(port);
292 return port;
293 }
294 Process::Inlet* operator()(const audio_input& v)
295 {
296 auto port = new Process::AudioInlet(Id<Process::Port>(i), &self);
297 port->setName(QString::fromStdString(input.name));
298 self.m_inlets.push_back(port);
299 return port;
300 }
301 Process::Inlet* operator()(const audioFFT_input& v)
302 {
303 auto port = new Process::AudioInlet(Id<Process::Port>(i), &self);
304 port->setName(QString::fromStdString(input.name));
305 self.m_inlets.push_back(port);
306 return port;
307 }
308 Process::Inlet* operator()(const audioHist_input& v)
309 {
310 auto port = new Process::AudioInlet(Id<Process::Port>(i), &self);
311 port->setName(QString::fromStdString(input.name));
312 self.m_inlets.push_back(port);
313 return port;
314 }
315
316 // CSF-specific input handlers
317 Process::Inlet* operator()(const storage_input& v) { return nullptr; }
318 Process::Inlet* operator()(const texture_input& v) { return nullptr; }
319 Process::Inlet* operator()(const csf_image_input& v) { return nullptr; }
320 };
321
322 for(const isf::input& input : desc.inputs)
323 {
324 ossia::visit(input_vis{previous_values, input, i, self}, input.data);
325 i++;
326 }
327 }
328};
329}
The DeviceList class.
Definition DeviceList.hpp:26
Definition Port.hpp:300
Definition Port.hpp:177
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 score-lib-process/Process/ProcessMetadata.hpp:37
Definition Address.hpp:108
The Address struct.
Definition Address.hpp:58