Skip to content

Commit e45c90d

Browse files
committed
isf: geometry filter: update controls when live-coding
1 parent 44f9a70 commit e45c90d

File tree

5 files changed

+140
-45
lines changed

5 files changed

+140
-45
lines changed

src/plugins/score-plugin-gfx/Gfx/Filter/Executor.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,40 @@ class filter_node final : public gfx_exec_node
3434
{
3535
exec_context->ui->unregister_node(id);
3636

37+
for(int i = 0, n = std::ssize(controls); i < n; i++)
38+
{
39+
auto& ctl = controls[i];
40+
ctl->port->write_value(ctl->value, 0);
41+
}
42+
3743
auto n = std::make_unique<score::gfx::ISFNode>(isf, vert, frag);
3844

45+
{
46+
score::gfx::Message msg = exec_context->allocateMessage(this->m_inlets.size() + 1);
47+
msg.node_id = id;
48+
msg.token.date = m_last_flicks;
49+
msg.token.parent_duration = ossia::time_value{}; // FIXME
50+
msg.input.resize(this->m_inlets.size());
51+
int inlet_i = 0;
52+
for(ossia::inlet* inlet : this->m_inlets)
53+
{
54+
switch(inlet->which())
55+
{
56+
case ossia::value_port::which: {
57+
auto& p = inlet->cast<ossia::value_port>();
58+
if(!p.get_data().empty())
59+
{
60+
msg.input[inlet_i] = std::move(p.get_data().back().value);
61+
p.get_data().clear();
62+
}
63+
64+
break;
65+
}
66+
}
67+
inlet_i++;
68+
}
69+
n->process(std::move(msg)); // note: node_id is incorrect at that point, it's ok
70+
}
3971
id = exec_context->ui->register_node(std::move(n));
4072
}
4173

src/plugins/score-plugin-gfx/Gfx/Filter/Process.cpp

+63-17
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,15 @@ Process::ScriptChangeResult Model::setProgram(const ShaderSource& f)
114114
if(const auto& [processed, error] = ProgramCache::instance().get(api, version, f);
115115
bool(processed))
116116
{
117+
ossia::flat_map<QString, ossia::value> previous_values;
118+
for(auto inl : m_inlets)
119+
if(auto control = qobject_cast<Process::ControlInlet*>(inl))
120+
previous_values.emplace(control->name(), control->value());
121+
117122
auto inls = score::clearAndDeleteLater(m_inlets);
118123
m_processedProgram = *processed;
119124

120-
setupIsf(m_processedProgram.descriptor);
125+
setupIsf(m_processedProgram.descriptor, previous_values);
121126
return {.valid = true, .inlets = std::move(inls)};
122127
}
123128
return {};
@@ -165,7 +170,9 @@ QString Model::prettyName() const noexcept
165170
return tr("GFX Filter");
166171
}
167172

168-
void Model::setupIsf(const isf::descriptor& desc)
173+
void Model::setupIsf(
174+
const isf::descriptor& desc,
175+
const ossia::flat_map<QString, ossia::value>& previous_values)
169176
{
170177
/*
171178
{
@@ -184,23 +191,30 @@ void Model::setupIsf(const isf::descriptor& desc)
184191
using namespace isf;
185192
struct input_vis
186193
{
194+
const ossia::flat_map<QString, ossia::value>& previous_values;
187195
const isf::input& input;
188196
const int i;
189197
Model& self;
190198

191199
Process::Inlet* operator()(const float_input& v)
192200
{
201+
auto nm = QString::fromStdString(input.name);
193202
auto port = new Process::FloatSlider(
194203
v.min, v.max, v.def, QString::fromStdString(input.name), Id<Process::Port>(i),
195204
&self);
196205

197206
self.m_inlets.push_back(port);
207+
if(auto it = previous_values.find(nm);
208+
it != previous_values.end() && it->second.get_type() == ossia::val_type::FLOAT)
209+
port->setValue(it->second);
210+
198211
self.controlAdded(port->id());
199212
return port;
200213
}
201214

202215
Process::Inlet* operator()(const long_input& v)
203216
{
217+
auto nm = QString::fromStdString(input.name);
204218
std::vector<std::pair<QString, ossia::value>> alternatives;
205219
std::size_t value_idx = 0;
206220
for(; value_idx < v.values.size() && value_idx < v.labels.size(); value_idx++)
@@ -217,8 +231,12 @@ void Model::setupIsf(const isf::descriptor& desc)
217231
}
218232

219233
auto port = new Process::ComboBox(
220-
std::move(alternatives), (int)v.def, QString::fromStdString(input.name),
221-
Id<Process::Port>(i), &self);
234+
std::move(alternatives), (int)v.def, nm, Id<Process::Port>(i), &self);
235+
236+
if(auto it = previous_values.find(nm);
237+
it != previous_values.end()
238+
&& it->second.get_type() == port->value().get_type())
239+
port->setValue(it->second);
222240

223241
self.m_inlets.push_back(port);
224242
self.controlAdded(port->id());
@@ -227,24 +245,30 @@ void Model::setupIsf(const isf::descriptor& desc)
227245

228246
Process::Inlet* operator()(const event_input& v)
229247
{
230-
auto port = new Process::Button(
231-
QString::fromStdString(input.name), Id<Process::Port>(i), &self);
248+
auto nm = QString::fromStdString(input.name);
249+
auto port = new Process::Button(nm, Id<Process::Port>(i), &self);
232250

233251
self.m_inlets.push_back(port);
234252
self.controlAdded(port->id());
235253
return port;
236254
}
237255
Process::Inlet* operator()(const bool_input& v)
238256
{
239-
auto port = new Process::Toggle(
240-
v.def, QString::fromStdString(input.name), Id<Process::Port>(i), &self);
257+
auto nm = QString::fromStdString(input.name);
258+
auto port = new Process::Toggle(v.def, nm, Id<Process::Port>(i), &self);
259+
260+
if(auto it = previous_values.find(nm);
261+
it != previous_values.end()
262+
&& it->second.get_type() == port->value().get_type())
263+
port->setValue(it->second);
241264

242265
self.m_inlets.push_back(port);
243266
self.controlAdded(port->id());
244267
return port;
245268
}
246269
Process::Inlet* operator()(const point2d_input& v)
247270
{
271+
auto nm = QString::fromStdString(input.name);
248272
ossia::vec2f min{0., 0.};
249273
ossia::vec2f max{1., 1.};
250274
ossia::vec2f init{0.5, 0.5};
@@ -254,13 +278,13 @@ void Model::setupIsf(const isf::descriptor& desc)
254278
std::copy_n(v.min->begin(), 2, min.begin());
255279
if(v.max)
256280
std::copy_n(v.max->begin(), 2, max.begin());
257-
auto port = new Process::XYSpinboxes{min,
258-
max,
259-
init,
260-
false,
261-
QString::fromStdString(input.name),
262-
Id<Process::Port>(i),
263-
&self};
281+
auto port = new Process::XYSpinboxes{
282+
min, max, init, false, nm, Id<Process::Port>(i), &self};
283+
284+
if(auto it = previous_values.find(nm);
285+
it != previous_values.end()
286+
&& it->second.get_type() == port->value().get_type())
287+
port->setValue(it->second);
264288

265289
self.m_inlets.push_back(port);
266290
self.controlAdded(port->id());
@@ -269,7 +293,23 @@ void Model::setupIsf(const isf::descriptor& desc)
269293

270294
Process::Inlet* operator()(const point3d_input& v)
271295
{
272-
auto port = new Process::ControlInlet{Id<Process::Port>(i), &self};
296+
auto nm = QString::fromStdString(input.name);
297+
ossia::vec3f min{0., 0., 0.};
298+
ossia::vec3f max{1., 1., 1.};
299+
ossia::vec3f init{0.5, 0.5, 0.5};
300+
if(v.def)
301+
std::copy_n(v.def->begin(), 3, init.begin());
302+
if(v.min)
303+
std::copy_n(v.min->begin(), 3, min.begin());
304+
if(v.max)
305+
std::copy_n(v.max->begin(), 3, max.begin());
306+
auto port
307+
= new Process::XYZSpinboxes{min, max, init, nm, Id<Process::Port>(i), &self};
308+
309+
if(auto it = previous_values.find(nm);
310+
it != previous_values.end()
311+
&& it->second.get_type() == port->value().get_type())
312+
port->setValue(it->second);
273313

274314
self.m_inlets.push_back(port);
275315
self.controlAdded(port->id());
@@ -278,6 +318,7 @@ void Model::setupIsf(const isf::descriptor& desc)
278318

279319
Process::Inlet* operator()(const color_input& v)
280320
{
321+
auto nm = QString::fromStdString(input.name);
281322
ossia::vec4f init{0.5, 0.5, 0.5, 1.};
282323
if(v.def)
283324
{
@@ -286,6 +327,11 @@ void Model::setupIsf(const isf::descriptor& desc)
286327
auto port = new Process::HSVSlider(
287328
init, QString::fromStdString(input.name), Id<Process::Port>(i), &self);
288329

330+
if(auto it = previous_values.find(nm);
331+
it != previous_values.end()
332+
&& it->second.get_type() == port->value().get_type())
333+
port->setValue(it->second);
334+
289335
self.m_inlets.push_back(port);
290336
self.controlAdded(port->id());
291337
return port;
@@ -312,7 +358,7 @@ void Model::setupIsf(const isf::descriptor& desc)
312358

313359
for(const isf::input& input : desc.inputs)
314360
{
315-
ossia::visit(input_vis{input, i, *this}, input.data);
361+
ossia::visit(input_vis{previous_values, input, i, *this}, input.data);
316362
i++;
317363
}
318364

src/plugins/score-plugin-gfx/Gfx/Filter/Process.hpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ class Model final : public Process::ProcessModel
6363
private:
6464
void loadPreset(const Process::Preset& preset) override;
6565
Process::Preset savePreset() const noexcept override;
66-
void setupIsf(const isf::descriptor& d);
66+
void setupIsf(
67+
const isf::descriptor& d,
68+
const ossia::flat_map<QString, ossia::value>& previous_values);
6769
//void setupNormalShader();
6870
QString prettyName() const noexcept override;
6971

src/plugins/score-plugin-gfx/Gfx/GeometryFilter/Executor.cpp

+41-26
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,16 @@ class geometry_filter_node final : public gfx_exec_node
4040

4141
index = ++filter_index;
4242
this->m_last_input_filters = {};
43+
44+
for(int i = 0, n = std::ssize(controls); i < n; i++)
45+
{
46+
auto& ctl = controls[i];
47+
ctl->port->write_value(ctl->value, 0);
48+
}
49+
4350
auto n = std::make_unique<score::gfx::GeometryFilterNode>(isf, update_shader(vert));
51+
auto msg = create_message();
52+
n->process(std::move(msg)); // note: node_id is incorrect at that point, it's ok
4453

4554
id = exec_context->ui->register_node(std::move(n));
4655
}
@@ -49,34 +58,12 @@ class geometry_filter_node final : public gfx_exec_node
4958

5059
std::string label() const noexcept override { return "Gfx::GeometryFilter_node"; }
5160

52-
QString update_shader(QString cur)
61+
score::gfx::Message create_message()
5362
{
54-
cur.replace("%node%", QString::number(index));
55-
cur.replace("process_vertex", "process_vertex_" + QString::number(index));
56-
m_shader = cur.toStdString();
57-
return cur;
58-
}
59-
void run(const ossia::token_request& tk, ossia::exec_state_facade) noexcept override
60-
{
61-
m_last_flicks = tk.date;
62-
{
63-
// Copy all the UI controls
64-
const int n = std::ssize(controls);
65-
for(int i = 0; i < n; i++)
66-
{
67-
auto& ctl = controls[i];
68-
if(ctl->changed)
69-
{
70-
ctl->port->write_value(ctl->value, 0);
71-
ctl->changed = false;
72-
}
73-
}
74-
}
75-
7663
score::gfx::Message msg = exec_context->allocateMessage(this->m_inlets.size() + 1);
7764
msg.node_id = id;
78-
msg.token.date = tk.date;
79-
msg.token.parent_duration = tk.parent_duration;
65+
msg.token.date = m_last_req.date;
66+
msg.token.parent_duration = m_last_req.parent_duration;
8067
msg.input.resize(this->m_inlets.size());
8168
int inlet_i = 0;
8269
for(ossia::inlet* inlet : this->m_inlets)
@@ -108,8 +95,35 @@ class geometry_filter_node final : public gfx_exec_node
10895

10996
inlet_i++;
11097
}
98+
return msg;
99+
}
100+
101+
QString update_shader(QString cur)
102+
{
103+
cur.replace("%node%", QString::number(index));
104+
cur.replace("process_vertex", "process_vertex_" + QString::number(index));
105+
m_shader = cur.toStdString();
106+
return cur;
107+
}
108+
void run(const ossia::token_request& tk, ossia::exec_state_facade) noexcept override
109+
{
110+
m_last_req = tk;
111+
m_last_flicks = tk.date;
112+
{
113+
// Copy all the UI controls
114+
const int n = std::ssize(controls);
115+
for(int i = 0; i < n; i++)
116+
{
117+
auto& ctl = controls[i];
118+
if(ctl->changed)
119+
{
120+
ctl->port->write_value(ctl->value, 0);
121+
ctl->changed = false;
122+
}
123+
}
124+
}
111125

112-
exec_context->ui->send_message(std::move(msg));
126+
exec_context->ui->send_message(create_message());
113127

114128
SCORE_ASSERT(this->m_inlets.size() > 0);
115129
SCORE_ASSERT(this->m_inlets[0]->target<ossia::geometry_port>());
@@ -156,6 +170,7 @@ class geometry_filter_node final : public gfx_exec_node
156170
ossia::geometry_filter_list_ptr m_last_input_filters;
157171
int64_t m_dirty{-1};
158172
int64_t m_last_index{-1};
173+
ossia::token_request m_last_req{};
159174
};
160175

161176
ProcessExecutorComponent::ProcessExecutorComponent(

src/plugins/score-plugin-gfx/Gfx/GeometryFilter/Process.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ void main()
106106

107107
try
108108
{
109-
QString processed = m_script;
109+
QString processed = txt;
110110
isf::parser p{processed.toStdString()};
111111
auto res = p.geometry_filter();
112112
auto r= QString::fromStdString(res);

0 commit comments

Comments
 (0)