29 void begin_path() { path = QPainterPath{}; }
30 void close_path() { path.closeSubpath(); }
31 void stroke() { painter.strokePath(path, painter.pen()); }
32 void fill() { painter.fillPath(path, painter.brush()); }
33 void update() { item.update(); }
35 void move_to(
double x,
double y) { path.moveTo(x, y); }
36 void line_to(
double x,
double y) { path.lineTo(x, y); }
37 void arc_to(
double x,
double y,
double w,
double h,
double start,
double length)
39 path.arcTo(x, y, w, h, start, length);
42 void cubic_to(
double c1x,
double c1y,
double c2x,
double c2y,
double endx,
double endy)
44 path.cubicTo(c1x, c1y, c2x, c2y, endx, endy);
47 void quad_to(
double x1,
double y1,
double x2,
double y2)
49 path.quadTo(x1, y1, x2, y2);
52 void translate(
double x,
double y) { painter.translate(x, y); }
53 void scale(
double x,
double y) { painter.scale(x, y); }
54 void rotate(
double a) { painter.rotate(a); }
55 void reset_transform() { painter.resetTransform(); }
58 void unset_stroke() { painter.setPen(score::Skin::instance().NoPen); }
62 const auto standard_color = avnd::get_color(c);
63 static constexpr auto convert = [](QColor c)
constexpr ->
rgba_color {
64 const auto rgba = c.rgba();
67 (uint8_t)qGreen(rgba),
69 (uint8_t)qAlpha(rgba),
73 using enum avnd::color_type;
74 switch(standard_color)
77 return convert(skin.Dark.main.brush.color());
79 return convert(skin.HalfDark.main.brush.color());
81 return convert(skin.Gray.main.brush.color());
83 return convert(skin.HalfLight.main.brush.color());
85 return convert(skin.Light.main.brush.color());
87 case background_darker:
88 return convert(skin.Background2.darker300.brush.color());
90 return convert(skin.Background2.darker.brush.color());
92 return convert(skin.Background2.main.brush.color());
93 case background_light:
94 return convert(skin.Background2.lighter.brush.color());
95 case background_lighter:
96 return convert(skin.Background2.lighter180.brush.color());
98 case runtime_value_dark:
99 return convert(skin.Base4.darker.brush.color());
100 case runtime_value_mid:
101 return convert(skin.Base4.main.brush.color());
102 case runtime_value_light:
103 return convert(skin.Base4.lighter.brush.color());
105 case editable_value_dark:
106 return convert(skin.Emphasis2.darker.brush.color());
107 case editable_value_mid:
108 return convert(skin.Emphasis2.main.brush.color());
109 case editable_value_light:
110 return convert(skin.Emphasis2.lighter.brush.color());
118 QPen p = painter.pen();
119 p.setColor(QColor::fromRgb(c.r, c.g, c.b, c.a));
123 template <
typename E>
124 requires std::is_enum_v<E>
125 void set_stroke_color(E c)
127 set_stroke_color(to_rgba(c));
130 void set_stroke_width(
double w)
132 QPen p = painter.pen();
139 painter.setBrush(QColor::fromRgb(c.r, c.g, c.b, c.a));
142 template <
typename E>
143 requires std::is_enum_v<E>
144 void set_fill_color(E c)
146 set_fill_color(to_rgba(c));
149 void set_linear_gradient(
152 QLinearGradient gradient(QPointF(x1, y1), QPointF(x2, y2));
153 gradient.setColorAt(0, QColor::fromRgb(c1.r, c1.g, c1.b, c1.a));
154 gradient.setColorAt(1, QColor::fromRgb(c2.r, c2.g, c2.b, c2.a));
155 painter.setBrush(gradient);
160 QRadialGradient gradient(cx, cy, cr);
161 gradient.setColorAt(0, QColor::fromRgb(c1.r, c1.g, c1.b, c1.a));
162 gradient.setColorAt(1, QColor::fromRgb(c2.r, c2.g, c2.b, c2.a));
163 painter.setBrush(gradient);
168 QConicalGradient gradient(x, y, a);
169 gradient.setColorAt(0, QColor::fromRgb(c1.r, c1.g, c1.b, c1.a));
170 gradient.setColorAt(1, QColor::fromRgb(c2.r, c2.g, c2.b, c2.a));
171 painter.setBrush(gradient);
174 template <
typename E>
175 requires std::is_enum_v<E>
177 set_linear_gradient(
double x1,
double y1,
double x2,
double y2, E c1,
rgba_color c2)
179 set_linear_gradient(x1, y1, x2, y2, to_rgba(c1), c2);
182 template <
typename E>
183 requires std::is_enum_v<E>
185 set_linear_gradient(
double x1,
double y1,
double x2,
double y2,
rgba_color c1, E c2)
187 set_linear_gradient(x1, y1, x2, y2, c1, to_rgba(c2));
190 template <
typename E1,
typename E2>
191 requires std::is_enum_v<E1> && std::is_enum_v<E2>
192 void set_linear_gradient(
double x1,
double y1,
double x2,
double y2, E1 c1, E2 c2)
194 set_linear_gradient(x1, y1, x2, y2, to_rgba(c1), to_rgba(c2));
197 template <
typename E>
198 requires std::is_enum_v<E>
200 set_radial_gradient(
double x1,
double y1,
double x2,
double y2, E c1,
rgba_color c2)
202 set_radial_gradient(x1, y1, x2, y2, to_rgba(c1), c2);
205 template <
typename E>
206 requires std::is_enum_v<E>
208 set_radial_gradient(
double x1,
double y1,
double x2,
double y2,
rgba_color c1, E c2)
210 set_radial_gradient(x1, y1, x2, y2, c1, to_rgba(c2));
213 template <
typename E1,
typename E2>
214 requires std::is_enum_v<E1> && std::is_enum_v<E2>
215 void set_radial_gradient(
double x1,
double y1,
double x2,
double y2, E1 c1, E2 c2)
217 set_radial_gradient(x1, y1, x2, y2, to_rgba(c1), to_rgba(c2));
220 template <
typename E>
221 requires std::is_enum_v<E>
223 set_conical_gradient(
double x1,
double y1,
double x2,
double y2, E c1,
rgba_color c2)
225 set_conical_gradient(x1, y1, x2, y2, to_rgba(c1), c2);
228 template <
typename E>
229 requires std::is_enum_v<E>
231 set_conical_gradient(
double x1,
double y1,
double x2,
double y2,
rgba_color c1, E c2)
233 set_conical_gradient(x1, y1, x2, y2, c1, to_rgba(c2));
236 template <
typename E1,
typename E2>
237 requires std::is_enum_v<E1> && std::is_enum_v<E2>
238 void set_conical_gradient(
double x1,
double y1,
double x2,
double y2, E1 c1, E2 c2)
240 set_conical_gradient(x1, y1, x2, y2, to_rgba(c1), to_rgba(c2));
244 void set_font(std::string_view f)
246 auto font = painter.font();
247 font.setFamily(QString::fromUtf8(f.data(), f.size()));
248 painter.setFont(font);
251 void set_font_size(
double f)
253 auto font = painter.font();
254 font.setPointSize(f);
255 painter.setFont(font);
258 void draw_text(
double x,
double y, std::string_view str)
260 path.addText(x, y, painter.font(), QString::fromUtf8(str.data(), str.size()));
263 void draw_text(
double x,
double y,
double w,
double h, std::string_view str)
265 QRectF rect{x, y, w, h};
266 const auto& m = painter.fontMetrics();
267 auto txt = QString::fromUtf8(str.data(), str.size());
268 auto text_rect = m.boundingRect(txt);
269 auto text_half_diagonal = (text_rect.center() - text_rect.topLeft()) / 2.;
270 auto pos = rect.center() + text_half_diagonal;
271 path.addText(pos.x(), pos.y(), painter.font(), txt);
275 void draw_line(
double x1,
double y1,
double x2,
double y2)
282 void draw_triangle(
double x1,
double y1,
double x2,
double y2,
double x3,
double y3)
288 painter.drawPath(path);
292 void draw_rect(
double x,
double y,
double w,
double h) { path.addRect(x, y, w, h); }
295 void draw_rounded_rect(
double x,
double y,
double w,
double h,
double r)
297 path.addRoundedRect(x, y, w, h, r, r);
301 void draw_pixmap(
double x,
double y,
const QString& str)
303 painter.drawPixmap(x, y, str);
307 void draw_ellipse(
double x,
double y,
double w,
double h)
309 path.addEllipse(x, y, w, h);
313 void draw_circle(
double cx,
double cy,
double cr)
315 path.addEllipse(QPointF{cx, cy}, cr, cr);
319 void draw_polygon(
const double* tab,
int count)
323 for(
int i = 0; i < count * 2; i += 2)
327 poly << QPointF(x, y);
329 path.addPolygon(poly);
333 int x,
int y,
int w,
int h,
const unsigned char* image,
int img_w,
int img_h,
336 auto img = QImage(image, img_w, img_h, QImage::Format_RGBA8888);
337 auto prev = painter.renderHints() & QPainter::SmoothPixmapTransform;
338 painter.setRenderHint(QPainter::SmoothPixmapTransform, smooth);
340 QRect(x, y, w, h), img, QRect(0, 0, img_w, img_h), Qt::ImageConversionFlags{});
342 painter.setRenderHint(QPainter::SmoothPixmapTransform, prev);
352 using item_type = std::decay_t<Item>;
361 this->setFlag(QGraphicsItem::ItemClipsToShape);
362 this->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
364 if constexpr(
requires { this->impl.update = [
this] {}; })
366 this->impl.update = [
this] { this->update(); };
370 QRectF boundingRect()
const override
372 return {0., 0., item_type::width(), item_type::height()};
375 void paint(QPainter* painter,
const QStyleOptionGraphicsItem* option, QWidget* widget)
378 auto& skin = score::Skin::instance();
379 painter->setRenderHint(QPainter::Antialiasing,
true);
380 painter->setPen(skin.Dark.main.pen1);
382 painter->setRenderHint(QPainter::Antialiasing,
false);
394 friend button& operator|=(button& lhs, button rhs)
noexcept
397 enum button&)(
reinterpret_cast<std::underlying_type_t<enum button>&
>(lhs) |=
reinterpret_cast<std::underlying_type_t<enum button>&
>(rhs));
407 friend modifier& operator|=(modifier& lhs, modifier rhs)
noexcept
410 enum modifier&)(
reinterpret_cast<std::underlying_type_t<enum modifier>&
>(lhs) |=
reinterpret_cast<std::underlying_type_t<enum modifier>&
>(rhs));
415 enum button button = {};
416 enum button held_buttons = {};
417 enum modifier modifiers = {};
425 p.x =
event->pos().x();
426 p.y =
event->pos().y();
428 if(event->button() == Qt::LeftButton)
429 p.button = custom_mouse_event::left;
430 else if(event->button() == Qt::RightButton)
431 p.button = custom_mouse_event::right;
432 else if(event->button() == Qt::MiddleButton)
433 p.button = custom_mouse_event::middle;
435 if(event->buttons() & Qt::LeftButton)
436 p.held_buttons |= p.left;
437 if(event->buttons() & Qt::RightButton)
438 p.held_buttons |= p.right;
439 if(event->buttons() & Qt::MiddleButton)
440 p.held_buttons |= p.middle;
442 if(event->modifiers() & Qt::ShiftModifier)
443 p.modifiers |= p.shift;
444 if(event->modifiers() & Qt::AltModifier)
445 p.modifiers |= p.alt;
446 if(event->modifiers() & Qt::ControlModifier)
447 p.modifiers |= p.ctrl;
448 if(event->modifiers() & Qt::MetaModifier)
449 p.modifiers |= p.meta;
454 void mousePressEvent(QGraphicsSceneMouseEvent* event)
override
456 if constexpr(
requires { impl.mouse_press(0, 0); })
458 if(impl.mouse_press(event->pos().x(), event->pos().y()))
461 else if constexpr(
requires { impl.mouse_press(custom_mouse_event{}); })
463 if(impl.mouse_press(make_event(event)))
469 void mouseMoveEvent(QGraphicsSceneMouseEvent* event)
override
471 if constexpr(
requires { impl.mouse_move(0, 0); })
473 impl.mouse_move(event->pos().x(),
event->pos().y());
476 else if constexpr(
requires { impl.mouse_move(custom_mouse_event{}); })
478 impl.mouse_move(make_event(event));
484 void mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
override
486 if constexpr(
requires { impl.mouse_release(0, 0); })
488 impl.mouse_release(event->pos().x(),
event->pos().y());
491 else if constexpr(
requires { impl.mouse_release(custom_mouse_event{}); })
493 impl.mouse_release(make_event(event));