31 void begin_path() { path = QPainterPath{}; }
32 void close_path() { path.closeSubpath(); }
33 void stroke() { painter.strokePath(path, painter.pen()); }
34 void fill() { painter.fillPath(path, painter.brush()); }
35 void update() { item.update(); }
37 void move_to(
double x,
double y) { path.moveTo(x, y); }
38 void line_to(
double x,
double y) { path.lineTo(x, y); }
39 void arc_to(
double x,
double y,
double w,
double h,
double start,
double length)
41 path.arcTo(x, y, w, h, start, length);
44 void cubic_to(
double c1x,
double c1y,
double c2x,
double c2y,
double endx,
double endy)
46 path.cubicTo(c1x, c1y, c2x, c2y, endx, endy);
49 void quad_to(
double x1,
double y1,
double x2,
double y2)
51 path.quadTo(x1, y1, x2, y2);
54 void translate(
double x,
double y) { painter.translate(x, y); }
55 void scale(
double x,
double y) { painter.scale(x, y); }
56 void rotate(
double a) { painter.rotate(a); }
57 void reset_transform() { painter.resetTransform(); }
60 void unset_stroke() { painter.setPen(score::Skin::instance().NoPen); }
64 const auto standard_color = avnd::get_color(c);
65 static constexpr auto convert = [](QColor c)
constexpr ->
rgba_color {
66 const auto rgba = c.rgba();
69 (uint8_t)qGreen(rgba),
71 (uint8_t)qAlpha(rgba),
75 using enum avnd::color_type;
76 switch(standard_color)
79 return convert(skin.Dark.main.brush.color());
81 return convert(skin.HalfDark.main.brush.color());
83 return convert(skin.Gray.main.brush.color());
85 return convert(skin.HalfLight.main.brush.color());
87 return convert(skin.Light.main.brush.color());
89 case background_darker:
90 return convert(skin.Background2.darker300.brush.color());
92 return convert(skin.Background2.darker.brush.color());
94 return convert(skin.Background2.main.brush.color());
95 case background_light:
96 return convert(skin.Background2.lighter.brush.color());
97 case background_lighter:
98 return convert(skin.Background2.lighter180.brush.color());
100 case runtime_value_dark:
101 return convert(skin.Base4.darker.brush.color());
102 case runtime_value_mid:
103 return convert(skin.Base4.main.brush.color());
104 case runtime_value_light:
105 return convert(skin.Base4.lighter.brush.color());
107 case editable_value_dark:
108 return convert(skin.Emphasis2.darker.brush.color());
109 case editable_value_mid:
110 return convert(skin.Emphasis2.main.brush.color());
111 case editable_value_light:
112 return convert(skin.Emphasis2.lighter.brush.color());
120 QPen p = painter.pen();
121 p.setColor(QColor::fromRgb(c.r, c.g, c.b, c.a));
125 template <
typename E>
126 requires std::is_enum_v<E>
127 void set_stroke_color(E c)
129 set_stroke_color(to_rgba(c));
132 void set_stroke_width(
double w)
134 QPen p = painter.pen();
141 painter.setBrush(QColor::fromRgb(c.r, c.g, c.b, c.a));
144 template <
typename E>
145 requires std::is_enum_v<E>
146 void set_fill_color(E c)
148 set_fill_color(to_rgba(c));
151 void set_linear_gradient(
154 QLinearGradient gradient(QPointF(x1, y1), QPointF(x2, y2));
155 gradient.setColorAt(0, QColor::fromRgb(c1.r, c1.g, c1.b, c1.a));
156 gradient.setColorAt(1, QColor::fromRgb(c2.r, c2.g, c2.b, c2.a));
157 painter.setBrush(gradient);
162 QRadialGradient gradient(cx, cy, cr);
163 gradient.setColorAt(0, QColor::fromRgb(c1.r, c1.g, c1.b, c1.a));
164 gradient.setColorAt(1, QColor::fromRgb(c2.r, c2.g, c2.b, c2.a));
165 painter.setBrush(gradient);
170 QConicalGradient gradient(x, y, a);
171 gradient.setColorAt(0, QColor::fromRgb(c1.r, c1.g, c1.b, c1.a));
172 gradient.setColorAt(1, QColor::fromRgb(c2.r, c2.g, c2.b, c2.a));
173 painter.setBrush(gradient);
176 template <
typename E>
177 requires std::is_enum_v<E>
179 set_linear_gradient(
double x1,
double y1,
double x2,
double y2, E c1,
rgba_color c2)
181 set_linear_gradient(x1, y1, x2, y2, to_rgba(c1), c2);
184 template <
typename E>
185 requires std::is_enum_v<E>
187 set_linear_gradient(
double x1,
double y1,
double x2,
double y2,
rgba_color c1, E c2)
189 set_linear_gradient(x1, y1, x2, y2, c1, to_rgba(c2));
192 template <
typename E1,
typename E2>
193 requires std::is_enum_v<E1> && std::is_enum_v<E2>
194 void set_linear_gradient(
double x1,
double y1,
double x2,
double y2, E1 c1, E2 c2)
196 set_linear_gradient(x1, y1, x2, y2, to_rgba(c1), to_rgba(c2));
199 template <
typename E>
200 requires std::is_enum_v<E>
202 set_radial_gradient(
double x1,
double y1,
double x2,
double y2, E c1,
rgba_color c2)
204 set_radial_gradient(x1, y1, x2, y2, to_rgba(c1), c2);
207 template <
typename E>
208 requires std::is_enum_v<E>
210 set_radial_gradient(
double x1,
double y1,
double x2,
double y2,
rgba_color c1, E c2)
212 set_radial_gradient(x1, y1, x2, y2, c1, to_rgba(c2));
215 template <
typename E1,
typename E2>
216 requires std::is_enum_v<E1> && std::is_enum_v<E2>
217 void set_radial_gradient(
double x1,
double y1,
double x2,
double y2, E1 c1, E2 c2)
219 set_radial_gradient(x1, y1, x2, y2, to_rgba(c1), to_rgba(c2));
222 template <
typename E>
223 requires std::is_enum_v<E>
225 set_conical_gradient(
double x1,
double y1,
double x2,
double y2, E c1,
rgba_color c2)
227 set_conical_gradient(x1, y1, x2, y2, to_rgba(c1), c2);
230 template <
typename E>
231 requires std::is_enum_v<E>
233 set_conical_gradient(
double x1,
double y1,
double x2,
double y2,
rgba_color c1, E c2)
235 set_conical_gradient(x1, y1, x2, y2, c1, to_rgba(c2));
238 template <
typename E1,
typename E2>
239 requires std::is_enum_v<E1> && std::is_enum_v<E2>
240 void set_conical_gradient(
double x1,
double y1,
double x2,
double y2, E1 c1, E2 c2)
242 set_conical_gradient(x1, y1, x2, y2, to_rgba(c1), to_rgba(c2));
246 void set_font(std::string_view f)
248 auto font = painter.font();
249 font.setFamily(QString::fromUtf8(f.data(), f.size()));
250 painter.setFont(font);
256 auto font = painter.font();
257 font.setPixelSize(std::max(1, (
int)std::lround(f)));
258 painter.setFont(font);
261 void draw_text(
double x,
double y, std::string_view str)
263 path.addText(x, y, painter.font(), QString::fromUtf8(str.data(), str.size()));
266 void draw_text(
double x,
double y,
double w,
double h, std::string_view str)
268 QRectF rect{x, y, w, h};
269 const auto& m = painter.fontMetrics();
270 auto txt = QString::fromUtf8(str.data(), str.size());
271 auto text_rect = m.boundingRect(txt);
272 auto text_half_diagonal = (text_rect.center() - text_rect.topLeft()) / 2.;
273 auto pos = rect.center() + text_half_diagonal;
274 path.addText(pos.x(), pos.y(), painter.font(), txt);
278 void draw_line(
double x1,
double y1,
double x2,
double y2)
285 void draw_triangle(
double x1,
double y1,
double x2,
double y2,
double x3,
double y3)
291 painter.drawPath(path);
295 void draw_rect(
double x,
double y,
double w,
double h) { path.addRect(x, y, w, h); }
298 void draw_rounded_rect(
double x,
double y,
double w,
double h,
double r)
300 path.addRoundedRect(x, y, w, h, r, r);
304 void draw_pixmap(
double x,
double y,
const QString& str)
306 painter.drawPixmap(x, y, str);
310 void draw_ellipse(
double x,
double y,
double w,
double h)
312 path.addEllipse(x, y, w, h);
316 void draw_circle(
double cx,
double cy,
double cr)
318 path.addEllipse(QPointF{cx, cy}, cr, cr);
322 void draw_polygon(
const double* tab,
int count)
326 for(
int i = 0; i < count * 2; i += 2)
330 poly << QPointF(x, y);
332 path.addPolygon(poly);
336 int x,
int y,
int w,
int h,
const unsigned char* image,
int img_w,
int img_h,
339 auto img = QImage(image, img_w, img_h, QImage::Format_RGBA8888);
340 auto prev = painter.renderHints() & QPainter::SmoothPixmapTransform;
341 painter.setRenderHint(QPainter::SmoothPixmapTransform, smooth);
343 QRect(x, y, w, h), img, QRect(0, 0, img_w, img_h), Qt::ImageConversionFlags{});
345 painter.setRenderHint(QPainter::SmoothPixmapTransform, prev);
348 int x,
int y,
int w,
int h,
const float* image,
int img_w,
int img_h,
352 = QImage((
const unsigned char*)image, img_w, img_h, QImage::Format_RGBA32FPx4);
353 auto prev = painter.renderHints() & QPainter::SmoothPixmapTransform;
354 painter.setRenderHint(QPainter::SmoothPixmapTransform, smooth);
356 QRect(x, y, w, h), img, QRect(0, 0, img_w, img_h), Qt::ImageConversionFlags{});
358 painter.setRenderHint(QPainter::SmoothPixmapTransform, prev);
368 using item_type = std::decay_t<Item>;
377 this->setFlag(QGraphicsItem::ItemClipsToShape);
378 this->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
380 if constexpr(
requires { this->impl.update = [
this] {}; })
382 this->impl.update = [
this] { this->update(); };
386 QRectF boundingRect()
const override
388 return {0., 0., item_type::width(), item_type::height()};
391 void paint(QPainter* painter,
const QStyleOptionGraphicsItem* option, QWidget* widget)
394 auto& skin = score::Skin::instance();
395 painter->setRenderHint(QPainter::Antialiasing,
true);
396 painter->setPen(skin.Dark.main.pen1);
398 painter->setFont(skin.Medium8Pt);
400 painter->setRenderHint(QPainter::Antialiasing,
false);
412 friend button& operator|=(button& lhs, button rhs)
noexcept
415 enum button&)(
reinterpret_cast<std::underlying_type_t<enum button>&
>(lhs) |=
reinterpret_cast<std::underlying_type_t<enum button>&
>(rhs));
425 friend modifier& operator|=(modifier& lhs, modifier rhs)
noexcept
428 enum modifier&)(
reinterpret_cast<std::underlying_type_t<enum modifier>&
>(lhs) |=
reinterpret_cast<std::underlying_type_t<enum modifier>&
>(rhs));
433 enum button button = {};
434 enum button held_buttons = {};
435 enum modifier modifiers = {};
443 p.x =
event->pos().x();
444 p.y =
event->pos().y();
446 if(event->button() == Qt::LeftButton)
447 p.button = custom_mouse_event::left;
448 else if(event->button() == Qt::RightButton)
449 p.button = custom_mouse_event::right;
450 else if(event->button() == Qt::MiddleButton)
451 p.button = custom_mouse_event::middle;
453 if(event->buttons() & Qt::LeftButton)
454 p.held_buttons |= p.left;
455 if(event->buttons() & Qt::RightButton)
456 p.held_buttons |= p.right;
457 if(event->buttons() & Qt::MiddleButton)
458 p.held_buttons |= p.middle;
460 if(event->modifiers() & Qt::ShiftModifier)
461 p.modifiers |= p.shift;
462 if(event->modifiers() & Qt::AltModifier)
463 p.modifiers |= p.alt;
464 if(event->modifiers() & Qt::ControlModifier)
465 p.modifiers |= p.ctrl;
466 if(event->modifiers() & Qt::MetaModifier)
467 p.modifiers |= p.meta;
472 void mousePressEvent(QGraphicsSceneMouseEvent* event)
override
474 if constexpr(
requires { impl.mouse_press(0, 0); })
476 if(impl.mouse_press(event->pos().x(), event->pos().y()))
479 else if constexpr(
requires { impl.mouse_press(custom_mouse_event{}); })
481 if(impl.mouse_press(make_event(event)))
491 void mouseMoveEvent(QGraphicsSceneMouseEvent* event)
override
493 if constexpr(
requires { impl.mouse_move(0, 0); })
495 impl.mouse_move(event->pos().x(),
event->pos().y());
498 else if constexpr(
requires { impl.mouse_move(custom_mouse_event{}); })
500 impl.mouse_move(make_event(event));
510 void mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
override
512 if constexpr(
requires { impl.mouse_release(0, 0); })
514 impl.mouse_release(event->pos().x(),
event->pos().y());
517 else if constexpr(
requires { impl.mouse_release(custom_mouse_event{}); })
519 impl.mouse_release(make_event(event));
533 if constexpr(
requires { impl.wheel(0., 0., 0.); })
535 impl.wheel(event->pos().x(),
event->pos().y(),
event->delta());