Skip to content

Commit

Permalink
moved ordered marks from WOverview to WaveformMarkSet, using as_const
Browse files Browse the repository at this point in the history
  • Loading branch information
m0dB committed Nov 5, 2023
1 parent 9129ace commit 725eb69
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 60 deletions.
8 changes: 5 additions & 3 deletions src/waveform/renderers/allshader/waveformrendermark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void allshader::WaveformRenderMark::initializeGL() {
m_rgbaShader.init();
m_textureShader.init();

for (const auto& pMark : m_marks) {
for (const auto& pMark : std::as_const(m_marks)) {
generateMarkImage(pMark);
}
generatePlayPosMarkTexture();
Expand Down Expand Up @@ -166,7 +166,7 @@ void allshader::WaveformRenderMark::paintGL() {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

for (const auto& pMark : m_marks) {
for (const auto& pMark : std::as_const(m_marks)) {
if (!pMark->isValid()) {
continue;
}
Expand Down Expand Up @@ -327,7 +327,7 @@ void allshader::WaveformRenderMark::drawTriangle(QPainter* painter,
}

void allshader::WaveformRenderMark::resizeGL(int, int) {
for (const auto& pMark : m_marks) {
for (const auto& pMark : std::as_const(m_marks)) {
generateMarkImage(pMark);
}
generatePlayPosMarkTexture();
Expand Down Expand Up @@ -386,6 +386,8 @@ void allshader::WaveformRenderMark::checkCuesUpdated() {
generateMarkImage(pMark);
}
}

m_marks.update();
}

void allshader::WaveformRenderMark::generateMarkImage(WaveformMarkPointer pMark) {
Expand Down
40 changes: 40 additions & 0 deletions src/waveform/renderers/waveformmarkset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,43 @@ WaveformMarkPointer WaveformMarkSet::getHotCueMark(int hotCue) const {
WaveformMarkPointer WaveformMarkSet::getDefaultMark() const {
return m_pDefaultMark;
}

void WaveformMarkSet::update() {
std::map<WaveformMarkSortKey, WaveformMarkPointer> map;
for (const auto& pMark : std::as_const(m_marks)) {
if (pMark->isValid() && pMark->isVisible()) {
double samplePosition = pMark->getSamplePosition();
if (samplePosition != Cue::kNoPosition) {
// Create a stable key for sorting, because the WaveformMark's samplePosition is a
// ControlObject which can change at any time by other threads. Such a change causes
// another updateCues() call, rebuilding map.
auto key = WaveformMarkSortKey(samplePosition, pMark->getHotCue());
map.emplace(key, pMark);
}
}
}

m_marksToRender.clear();
m_marksToRender.reserve(static_cast<QList<WaveformMarkPointer>::size_type>(map.size()));
std::transform(map.begin(),
map.end(),
std::back_inserter(m_marksToRender),
[](auto const& pair) { return pair.second; });
}

WaveformMarkPointer WaveformMarkSet::findHoveredMark(
QPoint pos, Qt::Orientation orientation) const {
// Non-hotcue marks (intro/outro cues, main cue, loop in/out) are sorted
// before hotcues in m_marksToRender so if there is a hotcue in the same
// location, the hotcue gets rendered on top. When right clicking, the
// the hotcue rendered on top must be assigned to m_pHoveredMark to show
// the CueMenuPopup. To accomplish this, m_marksToRender is iterated in
// reverse and the loop breaks as soon as m_pHoveredMark is set.
for (auto it = m_marksToRender.crbegin(); it != m_marksToRender.crend(); ++it) {
const WaveformMarkPointer& pMark = *it;
if (pMark->contains(pos, orientation)) {
return pMark;
}
}
return nullptr;
}
55 changes: 51 additions & 4 deletions src/waveform/renderers/waveformmarkset.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
class WaveformWidgetRenderer;

// This class helps share code between the WaveformRenderMark and WOverview
// constructors.
// constructors and allows to iterate over the orders marks that have to be
// rendered.
class WaveformMarkSet {
public:
WaveformMarkSet();
Expand All @@ -19,17 +20,63 @@ class WaveformMarkSet {
const SkinContext& context,
const WaveformSignalColors& signalColors);

inline QList<WaveformMarkPointer>::const_iterator begin() const { return m_marks.begin(); }
inline QList<WaveformMarkPointer>::const_iterator end() const { return m_marks.end(); }
template<typename Receiver, typename Slot>
void connectSamplePositionChanged(Receiver receiver, Slot slot) const {
for (const auto& pMark : std::as_const(m_marks)) {
if (pMark->isValid()) {
pMark->connectSamplePositionChanged(receiver, slot);
}
}
};

template<typename Receiver, typename Slot>
void connectSampleEndPositionChanged(Receiver receiver, Slot slot) const {
for (const auto& pMark : std::as_const(m_marks)) {
if (pMark->isValid()) {
pMark->connectSampleEndPositionChanged(receiver, slot);
}
}
};

template<typename Receiver, typename Slot>
void connectVisibleChanged(Receiver receiver, Slot slot) const {
for (const auto& pMark : std::as_const(m_marks)) {
if (pMark->hasVisible()) {
pMark->connectVisibleChanged(receiver, slot);
}
}
}

inline QList<WaveformMarkPointer>::const_iterator begin() const {
return m_marksToRender.begin();
}
inline QList<WaveformMarkPointer>::const_iterator end() const {
return m_marksToRender.end();
}
inline QList<WaveformMarkPointer>::const_iterator cbegin() const {
return m_marksToRender.cbegin();
}
inline QList<WaveformMarkPointer>::const_iterator cend() const {
return m_marksToRender.cend();
}

// hotCue must be valid (>= 0 and < NUM_HOT_CUES)
WaveformMarkPointer getHotCueMark(int hotCue) const;
WaveformMarkPointer getDefaultMark() const;
WaveformMarkPointer findHoveredMark(QPoint point, Qt::Orientation orientation) const;

void update();

private:
void clear() { m_marks.clear(); }
void clear() {
m_marks.clear();
m_marksToRender.clear();
}
WaveformMarkPointer m_pDefaultMark;
QList<WaveformMarkPointer> m_marks;
// List of visible WaveformMarks sorted by the order they appear in the track
QList<WaveformMarkPointer> m_marksToRender;

QMap<int, WaveformMarkPointer> m_hotCueMarks;

DISALLOW_COPY_AND_ASSIGN(WaveformMarkSet);
Expand Down
6 changes: 4 additions & 2 deletions src/waveform/renderers/waveformrendermark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ void WaveformRenderMark::draw(QPainter* painter, QPaintEvent* /*event*/) {

painter->setWorldMatrixEnabled(false);

for (const auto& pMark : m_marks) {
for (const auto& pMark : std::as_const(m_marks)) {
if (!pMark->isValid()) {
continue;
}
Expand Down Expand Up @@ -171,7 +171,7 @@ void WaveformRenderMark::draw(QPainter* painter, QPaintEvent* /*event*/) {

void WaveformRenderMark::onResize() {
// Flag that the mark image has to be updated. New images will be created on next paint.
for (const auto& pMark : m_marks) {
for (const auto& pMark : std::as_const(m_marks)) {
if (pMark->m_pGraphics) {
pMark->m_pGraphics->m_obsolete = true;
}
Expand Down Expand Up @@ -222,6 +222,8 @@ void WaveformRenderMark::slotCuesUpdated() {
generateMarkImage(pMark);
}
}

m_marks.update();
}

void WaveformRenderMark::generateMarkImage(WaveformMarkPointer pMark) {
Expand Down
60 changes: 12 additions & 48 deletions src/widget/woverview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,18 +151,9 @@ void WOverview::setup(const QDomNode& node, const SkinContext& context) {
auto colorPalette = colorPaletteSettings.getHotcueColorPalette();
m_pCueMenuPopup->setColorPalette(colorPalette);

for (const auto& pMark: m_marks) {
if (pMark->isValid()) {
pMark->connectSamplePositionChanged(this,
&WOverview::onMarkChanged);
pMark->connectSampleEndPositionChanged(this,
&WOverview::onMarkChanged);
}
if (pMark->hasVisible()) {
pMark->connectVisibleChanged(this,
&WOverview::onMarkChanged);
}
}
m_marks.connectSamplePositionChanged(this, &WOverview::onMarkChanged);
m_marks.connectSampleEndPositionChanged(this, &WOverview::onMarkChanged);
m_marks.connectVisibleChanged(this, &WOverview::onMarkChanged);

QDomNode child = node.firstChild();
while (!child.isNull()) {
Expand Down Expand Up @@ -220,8 +211,8 @@ void WOverview::setup(const QDomNode& node, const SkinContext& context) {

m_bShowCueTimes = context.selectBool(node, "ShowCueTimes", true);

//qDebug() << "WOverview : m_marks" << m_marks.size();
//qDebug() << "WOverview : m_markRanges" << m_markRanges.size();
// qDebug() << "WOverview : std::as_const(m_marks)" << m_marks.size();
// qDebug() << "WOverview : m_markRanges" << m_markRanges.size();
if (!m_connections.isEmpty()) {
ControlParameterWidgetConnection* defaultConnection = m_connections.at(0);
if (defaultConnection) {
Expand Down Expand Up @@ -414,7 +405,6 @@ void WOverview::onPassthroughChange(double v) {
}

void WOverview::updateCues(const QList<CuePointer> &loadedCues) {
m_marksToRender.clear();
for (const CuePointer& currentCue : loadedCues) {
const WaveformMarkPointer pMark = m_marks.getHotCueMark(currentCue->getHotCue());

Expand Down Expand Up @@ -444,18 +434,7 @@ void WOverview::updateCues(const QList<CuePointer> &loadedCues) {
}
}

for (const auto& pMark : m_marks) {
if (pMark->isValid() && pMark->isVisible()) {
double samplePosition = pMark->getSamplePosition();
if (samplePosition != Cue::kNoPosition) {
// Create a stable key for sorting, because the WaveformMark's samplePosition is a
// ControlObject which can change at any time by other threads. Such a change causes
// another updateCues() call, rebuilding m_marksToRender.
auto key = WaveformMarkSortKey(samplePosition, pMark->getHotCue());
m_marksToRender.emplace(key, pMark);
}
}
}
m_marks.update();
}

// connecting the tracks cuesUpdated and onMarkChanged is not possible
Expand Down Expand Up @@ -492,21 +471,7 @@ void WOverview::mouseMoveEvent(QMouseEvent* e) {
return;
}

m_pHoveredMark.clear();

// Non-hotcue marks (intro/outro cues, main cue, loop in/out) are sorted
// before hotcues in m_marksToRender so if there is a hotcue in the same
// location, the hotcue gets rendered on top. When right clicking, the
// the hotcue rendered on top must be assigned to m_pHoveredMark to show
// the CueMenuPopup. To accomplish this, m_marksToRender is iterated in
// reverse and the loop breaks as soon as m_pHoveredMark is set.
for (auto i = m_marksToRender.crbegin(); i != m_marksToRender.crend(); ++i) {
const WaveformMarkPointer& pMark = i->second;
if (pMark->contains(e->pos(), m_orientation)) {
m_pHoveredMark = pMark;
break;
}
}
m_pHoveredMark = m_marks.findHoveredMark(e->pos(), m_orientation);

//qDebug() << "WOverview::mouseMoveEvent" << e->pos() << m_iPos;
update();
Expand Down Expand Up @@ -872,9 +837,9 @@ void WOverview::drawMarks(QPainter* pPainter, const float offset, const float ga

bool markHovered = false;

for (auto i = m_marksToRender.cbegin(); i != m_marksToRender.cend(); ++i) {
for (auto it = m_marks.cbegin(); it != m_marks.cend(); ++it) {
PainterScope painterScope(pPainter);
const WaveformMarkPointer& pMark = i->second;
const WaveformMarkPointer& pMark = *it;
double samplePosition = pMark->getSamplePosition();
const float markPosition = math_clamp(
offset + static_cast<float>(samplePosition) * gain,
Expand Down Expand Up @@ -932,8 +897,8 @@ void WOverview::drawMarks(QPainter* pPainter, const float offset, const float ga

if (pMark != m_pHoveredMark) {
float nextMarkPosition = -1.0f;
for (auto m = std::next(i); m != m_marksToRender.cend(); ++m) {
const WaveformMarkPointer& otherMark = m->second;
for (auto m = std::next(it); m != m_marks.cend(); ++m) {
const WaveformMarkPointer& otherMark = *m;
bool otherAtSameHeight = valign == (otherMark->m_align & Qt::AlignVertical_Mask);
// Hotcues always show at least their number.
bool otherHasLabel = !otherMark->m_text.isEmpty() || otherMark->getHotCue() != Cue::kNoHotCue;
Expand Down Expand Up @@ -1184,8 +1149,7 @@ void WOverview::drawMarkLabels(QPainter* pPainter, const float offset, const flo
QFontMetricsF fontMetrics(markerFont);

// Draw WaveformMark labels
for (const auto& pair : m_marksToRender) {
const WaveformMarkPointer& pMark = pair.second;
for (const auto& pMark : std::as_const(m_marks)) {
if (m_pHoveredMark != nullptr && pMark != m_pHoveredMark) {
if (pMark->m_label.intersects(m_pHoveredMark->m_label)) {
continue;
Expand Down
3 changes: 0 additions & 3 deletions src/widget/woverview.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,7 @@ class WOverview : public WWidget, public TrackDropTarget {
int m_dimBrightThreshold;
QLabel* m_pPassthroughLabel;

// All WaveformMarks
WaveformMarkSet m_marks;
// List of visible WaveformMarks sorted by the order they appear in the track
std::map<WaveformMarkSortKey, WaveformMarkPointer> m_marksToRender;
std::vector<WaveformMarkRange> m_markRanges;
WaveformMarkLabel m_cuePositionLabel;
WaveformMarkLabel m_cueTimeDistanceLabel;
Expand Down

0 comments on commit 725eb69

Please sign in to comment.