73 void operator()()
const noexcept { }
74 void operator()(ossia::impulse)
const noexcept { ret.push_back(1.f); }
75 void operator()(
int v)
const noexcept { ret.push_back(v); }
76 void operator()(
float v)
const noexcept { ret.push_back(v); }
77 void operator()(
bool v)
const noexcept { ret.push_back(v ? 1.f : 0.f); }
78 void operator()(std::string_view v)
const noexcept
80 if(
auto res = ossia::parse_strict<float>(v))
83 template <std::
size_t N>
84 void operator()(std::array<float, N> arr)
const noexcept
86 ret.insert(ret.end(), arr.begin(), arr.end());
88 void operator()(
const std::vector<ossia::value>& arr)
const noexcept
90 ret.reserve(1 + arr.size());
93 ret.push_back(ossia::convert<float>(val));
96 void operator()(
const ossia::value_map_type& arr)
const noexcept
98 ret.reserve(1 + arr.size());
99 for(
auto& [k, v] : arr)
101 ret.push_back(ossia::convert<float>(v));
126 static constexpr int timestamp_index = 0;
127 static constexpr int first_value_index = 1;
132 std::vector<vec_type> m_values;
139 QGraphicsItem* parent)
141 , m_interval{Scenario::closestParentInterval(process.parent())}
143 setAcceptedMouseButtons({});
149 auto inl = process.inlets().front();
152 if(parent->type() == Process::NodeItem::Type)
155 auto fact = portFactory.
get(inl->concreteKey());
156 auto port = fact->makePortItem(*inl, doc,
this,
this);
165 m_interval, &Scenario::IntervalModel::executionEvent,
this,
166 [
this](Scenario::IntervalExecutionEvent ev) {
169 case Scenario::IntervalExecutionEvent::Playing:
170 case Scenario::IntervalExecutionEvent::Stopped:
178 auto outl = safe_cast<Process::ControlOutlet*>(process.outlets().front());
180 outl, &Process::ControlOutlet::valueChanged,
this,
181 [
this](
const ossia::value& v) {
182 auto& val = *v.target<std::vector<ossia::value>>();
183 const int N = std::ssize(val);
186 this->num_rows = std::max(this->num_rows, N - 1);
189 min.resize(N, std::numeric_limits<float>::max());
191 max.resize(N, std::numeric_limits<float>::lowest());
194 vv.resize(N, boost::container::default_init);
197 for(
auto it = val.begin(); it != val.end(); ++it)
199 const float r = *it->target<
float>();
210 if(!m_values.empty() && !m_values.back().empty())
211 if(vv[timestamp_index] < m_values.back()[timestamp_index])
217 m_values.push_back(std::move(vv));
233 void draw_row_simple(QPainter* p, qreal w, qreal h,
int row_index,
auto to_01)
const
235 for(
int start_idx = 0; start_idx < std::ssize(m_values) - 1; start_idx++)
237 int end_idx = start_idx + 1;
239 const auto* p0 = &m_values[start_idx];
240 const auto& v0 = *p0;
241 const auto N0 = std::ssize(*p0);
244 const auto* p1 = &m_values[end_idx];
245 const auto& v1 = *p1;
246 const auto N1 = std::ssize(*p1);
249 QPointF start = {v0[timestamp_index] * w, to_01(v0[row_index]) * h};
250 QPointF end = {v1[timestamp_index] * w, to_01(v1[row_index]) * h};
251 p->drawLine(start, end);
255 void draw_row(QPainter* p, qreal w, qreal h,
int row_index,
auto to_01)
const
257 double quality = std::clamp(std::ceil(std::sqrt(0.1 + num_rows)), 1., 5.);
258 std::optional<int> last_idx;
259 for(
int start_idx = 0; start_idx < std::ssize(m_values) - 1; start_idx++)
261 const auto* p0 = &m_values[start_idx];
262 const auto& v0 = *p0;
263 const auto N0 = std::ssize(*p0);
268 if(last_idx && *last_idx < start_idx)
270 const auto& v0 = m_values[*last_idx];
272 QPointF p0 = {v0[timestamp_index] * w, to_01(v0[row_index]) * h};
273 QPointF p1 = {v1[timestamp_index] * w, to_01(v1[row_index]) * h};
275 if(QLineF l{p0, p1}; l.length() > quality && p0.x() < p1.x())
278 last_idx = start_idx;
283 auto x0 = v0[timestamp_index] * w;
284 decltype(p0) p1 =
nullptr;
285 std::optional<int> last_viable_end;
287 for(
int end_idx = start_idx + 1; end_idx < std::ssize(m_values); end_idx++)
289 auto pp1 = &m_values[end_idx];
290 const auto N1 = std::ssize(*pp1);
294 last_viable_end = end_idx;
296 const auto& v1 = *pp1;
297 x1 = v1[timestamp_index] * w;
298 if((x1 - x0) < quality)
302 else if(x1 - x0 > 10.)
315 const auto& v1 = *p1;
316 QPointF p0 = {x0, to_01(v0[row_index]) * h};
317 QPointF p1 = {x1, to_01(v1[row_index]) * h};
319 last_idx = last_viable_end;
324 void draw_row_constant(QPainter* p, qreal w, qreal h,
int row_index)
const
326 for(
auto& val : m_values)
328 if(std::ssize(val) > row_index)
330 QPointF p0 = {val[timestamp_index] * w, 0.5 * h};
336 void paint_impl(QPainter* p)
const override
338 if(m_values.size() < 2 || this->num_rows == 0)
342 p->setRenderHint(QPainter::Antialiasing,
true);
343 p->setPen(score::Skin::instance().Light.main.pen1_solid_flat_miter);
345 const auto w = m_defaultWidth;
346 const auto h = height() / num_rows;
348 for(
int row = 0; row < num_rows; ++row)
350 const int row_index = row + 1;
352 const auto min = this->min[row_index];
353 const auto max = this->max[row_index];
356 draw_row_simple(p, w, h, row_index, [min, max](
float v) {
357 return 1.f - (v - min) / (max - min);
362 draw_row_constant(p, w, h, row_index);
365 p->translate(QPointF{0, h});
368 p->setRenderHint(QPainter::Antialiasing,
false);