24 ,
public QGraphicsItem
28 : QGraphicsItem{parent}
32 void setValue(
double normalized)
35 normalized = std::clamp(normalized, 0., 1.);
36 if(normalized == m_value)
42 QRectF boundingRect()
const override {
return {0., 0., 52., 4.}; }
44 void paint(QPainter* painter,
const QStyleOptionGraphicsItem*, QWidget*)
override
46 auto& skin = score::Skin::instance();
47 const QRectF r = boundingRect();
48 painter->fillRect(r, skin.Background2.darker.brush);
49 painter->fillRect(QRectF{r.x(), r.y(), r.width() * m_value, r.height()}, skin.Base4);
69 const auto& dom = port.domain().get();
70 const auto lo = ossia::get_min(dom);
71 const auto hi = ossia::get_max(dom);
72 if(!lo.valid() || !hi.valid())
76 if(
auto a = lo.target<ossia::vec2f>())
77 if(
auto b = hi.target<ossia::vec2f>())
79 const double tl = (*a)[0], th = (*b)[0];
80 return th == tl ? 0. : std::clamp((
scalarValue(v) - tl) / (th - tl), 0., 1.);
82 return h == l ? 0. : std::clamp((
scalarValue(v) - l) / (h - l), 0., 1.);
93 Item item_init, std::vector<Process::ControlInlet*> ports,
96 , m_ports{std::move(ports)}
98 , m_cmds(m_ports.size(),
nullptr)
100 const std::size_t n = std::min(m_ports.size(), std::size(this->impl.values));
101 for(std::size_t i = 0; i < n; i++)
103 auto* port = m_ports[i];
104 auto show = [
this, i, port](
const ossia::value& v) {
105 const auto n = normalize(*port, v);
106 if(n == this->impl.values[i])
108 this->impl.values[i] = n;
112 QObject::connect(port, &Process::ControlInlet::valueChanged,
this, show);
115 this->impl.transaction.start = [
this] {
116 m_ctx.commandStack.disableActions();
119 this->impl.transaction.update = [
this, n](
int i,
double normalized) {
120 if(i < 0 || std::size_t(i) >= n)
122 auto& port = *m_ports[i];
123 const ossia::value v = denormalize(port, normalized);
127 m_cmds[i]->update(port, v);
128 m_cmds[i]->redo(m_ctx);
130 this->impl.transaction.commit = [
this] {
132 if(std::ranges::any_of(m_cmds, [](
auto* cmd) {
return cmd !=
nullptr; }))
135 for(
auto& cmd : m_cmds)
138 all->addCommand(std::exchange(cmd,
nullptr));
140 SendStrategy::Quiet::send(m_ctx.commandStack, all);
142 m_ctx.commandStack.enableActions();
145 this->impl.transaction.rollback = [
this] { rollback(); };
158 for(
auto it = m_cmds.rbegin(); it != m_cmds.rend(); ++it)
160 if(
auto cmd = std::exchange(*it,
nullptr))
166 m_ctx.commandStack.enableActions();
172 const auto& dom = port.domain().get();
173 const auto lo = ossia::get_min(dom);
174 const auto hi = ossia::get_max(dom);
175 if(!lo.valid() || !hi.valid())
178 if(
auto a = lo.target<ossia::vec2f>())
179 if(
auto b = hi.target<ossia::vec2f>())
180 return {(*a)[0], (*b)[0]};
181 return {ossia::convert<double>(lo), ossia::convert<double>(hi)};
191 const auto [lo, hi] =
range(port);
192 const double v = lo + std::clamp(n, 0., 1.) * (hi - lo);
194 if(port.value().get_type() == ossia::val_type::INT)
195 return int(std::lround(v));
198 if(port.value().get_type() == ossia::val_type::VEC2F)
199 return ossia::vec2f{float(v), 0.f};
203 std::vector<Process::ControlInlet*> m_ports;
205 std::vector<Process::SetControlValue*> m_cmds;
double normalizedValue(const Process::ControlInlet &port, const ossia::value &v)
A control's value, normalized over its range.
Definition ControlViews.hpp:67
Definition DocumentContext.hpp:18