Skip to content

Commit

Permalink
[curve] Optimize drawing when we have many many points
Browse files Browse the repository at this point in the history
  • Loading branch information
jcelerier committed Oct 23, 2024
1 parent 21fa8d4 commit 2e25d8e
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 5 deletions.
44 changes: 39 additions & 5 deletions src/plugins/score-plugin-curve/Curve/CurvePresenter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,24 @@ void Presenter::setPos(SegmentView& segment)
segment.setRect({0., 0., endx - startx, m_localRect.height()});
}

static constexpr int direct_draw_cutoff = 3000;
void Presenter::setupSignals()
{
con(m_model, &Model::segmentAdded, this, [&](const SegmentModel* segment) {
if(m_model.points().size() > direct_draw_cutoff)
{
m_view->setDirectDraw(true);
return;
}
addSegment(new SegmentView{segment, m_style, m_view});
});

con(m_model, &Model::pointAdded, this, [&](const PointModel* point) {
if(m_model.points().size() > direct_draw_cutoff)
{
m_view->setDirectDraw(true);
return;
}
addPoint(new PointView{point, m_style, m_view});
});

Expand All @@ -126,6 +137,7 @@ void Presenter::setupSignals()
[&](const Id<SegmentModel>& m) { m_segments.erase(m); });

con(m_model, &Model::cleared, this, [&]() {
m_view->setDirectDraw(false);
m_points.remove_all();
m_segments.remove_all();
});
Expand All @@ -136,14 +148,23 @@ void Presenter::setupSignals()
void Presenter::setupView()
{
// Initialize the elements
for(const auto& segment : m_model.segments())
m_view->setModel(this, &m_model);
if(m_model.points().size() < 3000)
{
addSegment(new SegmentView{&segment, m_style, m_view});
}
for(const auto& segment : m_model.segments())
{
addSegment(new SegmentView{&segment, m_style, m_view});
}

for(PointModel* pt : m_model.points())
for(PointModel* pt : m_model.points())
{
addPoint(new PointView{pt, m_style, m_view});
}
m_view->setDirectDraw(false);
}
else
{
addPoint(new PointView{pt, m_style, m_view});
m_view->setDirectDraw(true);
}
}

Expand Down Expand Up @@ -258,6 +279,19 @@ void Presenter::setupSegmentConnections(SegmentView* seg_view)

void Presenter::modelReset()
{
const int64_t model_points_n = m_model.points().size();
if(model_points_n > direct_draw_cutoff)
{
m_points.remove_all();
m_segments.remove_all();
m_view->setDirectDraw(true);
return;
}
else
{
m_view->setDirectDraw(false);
}

// 1. We put our current elements in our pool.
std::vector<PointView*> points = m_points.as_vec();
std::vector<SegmentView*> segments = m_segments.as_vec();
Expand Down
1 change: 1 addition & 0 deletions src/plugins/score-plugin-curve/Curve/CurvePresenter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class Model;

class SCORE_PLUGIN_CURVE_EXPORT Presenter final : public QObject
{
friend class View;
W_OBJECT(Presenter)
public:
Presenter(
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/score-plugin-curve/Curve/CurveStyle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,8 @@ void Style::update()
PenPointSelected = PointSelected.color();
BrushPoint = Point;
BrushPointSelected = PointSelected;

PenDataset = QPen{Segment, 1, Qt::PenStyle::SolidLine};
PenDatasetDisabled = QPen{SegmentDisabled, 1, Qt::PenStyle::SolidLine};
}
}
3 changes: 3 additions & 0 deletions src/plugins/score-plugin-curve/Curve/CurveStyle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ struct SCORE_PLUGIN_CURVE_EXPORT Style
QBrush BrushPoint{};
QBrush BrushPointSelected{};

QPen PenDataset{};
QPen PenDatasetDisabled{};

void init(const score::Skin& s);
void update();
};
Expand Down
39 changes: 39 additions & 0 deletions src/plugins/score-plugin-curve/Curve/CurveView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

#include <Process/Style/ScenarioStyle.hpp>

#include <Curve/CurveModel.hpp>
#include <Curve/CurvePresenter.hpp>
#include <Curve/CurveStyle.hpp>
#include <Curve/Point/CurvePointModel.hpp>

#include <QGraphicsSceneMouseEvent>
#include <QKeyEvent>
#include <QPainter>
Expand Down Expand Up @@ -33,6 +38,17 @@ View::View(QGraphicsItem* parent) noexcept

View::~View() { }

void View::setModel(const Presenter* p, const Model* m) noexcept
{
m_presenter = p;
m_model = m;
}

void View::setDirectDraw(bool d) noexcept
{
m_directDraw = d;
}

void View::paint(
QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
Expand All @@ -41,6 +57,29 @@ void View::paint(
painter->setPen(Qt::white);
painter->drawRect(m_selectArea);
}

if(m_directDraw)
{
auto& pts = m_model->points();
if(pts.size() < 2)
return;

auto& style = m_presenter->m_style;
painter->setPen(
m_presenter->m_enabled ? style.PenDataset : style.PenDatasetDisabled);
static constexpr auto scale = [](QPointF first, QSizeF second) {
return QPointF{first.x() * second.width(), (1. - first.y()) * second.height()};
};

auto sz = m_presenter->m_localRect.size();
for(auto orig = pts.begin(), next = ++pts.begin(); next != pts.end(); ++orig, ++next)
{
auto p1 = scale((*orig)->pos(), sz);
auto p2 = scale((*next)->pos(), sz);

painter->drawLine(p1.x(), p1.y(), p2.x(), p2.y());
}
}
}

void View::setSelectionArea(const QRectF& rect) noexcept
Expand Down
7 changes: 7 additions & 0 deletions src/plugins/score-plugin-curve/Curve/CurveView.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class QWidget;

namespace Curve
{
class Presenter;
class Model;
class SCORE_PLUGIN_CURVE_EXPORT View final
: public QObject
, public QGraphicsItem
Expand All @@ -27,6 +29,8 @@ class SCORE_PLUGIN_CURVE_EXPORT View final
explicit View(QGraphicsItem* parent) noexcept;
~View() override;

void setModel(const Curve::Presenter* p, const Curve::Model* m) noexcept;
void setDirectDraw(bool) noexcept;
void setDefaultWidth(double w) noexcept;
void setRect(const QRectF& theRect) noexcept;
QRectF boundingRect() const override;
Expand Down Expand Up @@ -64,10 +68,13 @@ class SCORE_PLUGIN_CURVE_EXPORT View final

void contextMenuEvent(QGraphicsSceneContextMenuEvent*) override;

const Curve::Presenter* m_presenter{};
const Curve::Model* m_model{};
QRectF m_rect; // The rect in which the whole curve must fit.
QRectF m_selectArea;
QPointF m_tooltipPos;
QString m_tooltip;
double m_defaultW{};
bool m_directDraw{false};
};
}

0 comments on commit 2e25d8e

Please sign in to comment.