From 44de9a54f12cbddbf29cb16c75930abd5d3a4ffb Mon Sep 17 00:00:00 2001 From: regulus79 <117475203+regulus79@users.noreply.github.com> Date: Tue, 18 Mar 2025 16:56:55 -0400 Subject: [PATCH 1/6] Initial Implementation --- data/themes/default/step_btn_highlight.png | Bin 0 -> 11205 bytes include/MidiClip.h | 5 ++ include/MidiClipView.h | 1 + include/PatternEditor.h | 6 +++ include/TrackView.h | 6 +++ src/gui/clips/MidiClipView.cpp | 10 ++++ src/gui/editors/PatternEditor.cpp | 57 ++++++++++++++++++++- src/gui/tracks/TrackView.cpp | 1 + 8 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 data/themes/default/step_btn_highlight.png diff --git a/data/themes/default/step_btn_highlight.png b/data/themes/default/step_btn_highlight.png new file mode 100644 index 0000000000000000000000000000000000000000..e2cabfcd7f23dd0bed649e2ed9f9ac855632a884 GIT binary patch literal 11205 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˔xS`Q2{1?vR16 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 nU+z7aljDE%RXdw& getClipViews() + { + return m_clipViews; + } + inline TrackContainerView* trackContainerView() { return m_trackContainerView; @@ -151,6 +156,7 @@ public slots: Track * m_track; TrackContainerView * m_trackContainerView; + std::vector m_clipViews; TrackOperationsWidget m_trackOperationsWidget; QWidget m_trackSettingsWidget; diff --git a/src/gui/clips/MidiClipView.cpp b/src/gui/clips/MidiClipView.cpp index b735913e4d0..65c9f9cf13e 100644 --- a/src/gui/clips/MidiClipView.cpp +++ b/src/gui/clips/MidiClipView.cpp @@ -460,6 +460,7 @@ void MidiClipView::paintEvent( QPaintEvent * ) QPixmap stepon200; QPixmap stepoff; QPixmap stepoffl; + QPixmap stephighlight; const int steps = std::max(1, m_clip->m_steps); const int w = width() - 2 * BORDER_WIDTH; @@ -472,6 +473,8 @@ void MidiClipView::paintEvent( QPaintEvent * ) = m_stepBtnOff.scaled(w / steps, m_stepBtnOff.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); stepoffl = m_stepBtnOffLight.scaled( w / steps, m_stepBtnOffLight.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + stephighlight = m_stepBtnHighlight.scaled( + w / steps, m_stepBtnHighlight.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); for (int it = 0; it < steps; it++) // go through all the steps in the beat clip { @@ -481,6 +484,9 @@ void MidiClipView::paintEvent( QPaintEvent * ) const int x = BORDER_WIDTH + static_cast(it * w / steps); const int y = BeatStepButtonOffset; + const bool isAtPlayPos = Engine::getSong()->getPlayPos(Song::PlayMode::Pattern) * TimePos::stepsPerBar() / TimePos::ticksPerBar() == it + && Engine::getSong()->playMode() == Song::PlayMode::Pattern; + if (n) { const int vol = n->getVolume(); @@ -498,6 +504,10 @@ void MidiClipView::paintEvent( QPaintEvent * ) { p.drawPixmap(x, y, stepoff); } + if (isAtPlayPos) + { + p.drawPixmap(x, y, stephighlight); + } } // end for loop // draw a transparent rectangle over muted clips diff --git a/src/gui/editors/PatternEditor.cpp b/src/gui/editors/PatternEditor.cpp index 2915786981d..1da6c3ab88d 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -25,6 +25,7 @@ #include "PatternEditor.h" #include +#include #include "ClipView.h" #include "ComboBox.h" @@ -35,6 +36,7 @@ #include "PatternTrack.h" #include "Song.h" #include "StringPairDrag.h" +#include "TimeLineWidget.h" #include "TrackView.h" #include "MidiClip.h" @@ -46,9 +48,27 @@ namespace lmms::gui PatternEditor::PatternEditor(PatternStore* ps) : TrackContainerView(ps), - m_ps(ps) + m_ps(ps), + m_trackHeadWidth(ConfigManager::inst()->value("ui", "compacttrackbuttons").toInt() == 1 + ? DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT + TRACK_OP_WIDTH_COMPACT + : DEFAULT_SETTINGS_WIDGET_WIDTH + TRACK_OP_WIDTH), + m_maxSteps(TimePos::stepsPerBar()) { setModel(ps); + + m_timeLine = new TimeLineWidget(m_trackHeadWidth, 32, pixelsPerBar(), + Engine::getSong()->getPlayPos(Song::PlayMode::Pattern), + Engine::getSong()->getTimeline(Song::PlayMode::Pattern), + m_currentPosition, Song::PlayMode::Pattern, this + ); + connect(this, &TrackContainerView::positionChanged, m_timeLine, &TimeLineWidget::updatePosition); + static_cast( layout() )->insertWidget( 0, m_timeLine ); + + + // TO BE REMOVED after Timeline signals are refactored (#7454) + auto updateTimer = new QTimer(this); + connect(updateTimer, &QTimer::timeout, this, &PatternEditor::updatePosition); + updateTimer->start( 1000 / 60 ); // 60 fps } @@ -79,6 +99,7 @@ void PatternEditor::removeSteps() p->removeSteps(); } } + updateMaxSteps(); } @@ -118,6 +139,7 @@ void PatternEditor::saveSettings(QDomDocument& doc, QDomElement& element) void PatternEditor::loadSettings(const QDomElement& element) { MainWindow::restoreWidgetState(parentWidget(), element); + updateMaxSteps(); } @@ -160,18 +182,49 @@ void PatternEditor::dropEvent(QDropEvent* de) { TrackContainerView::dropEvent( de ); } + updateMaxSteps(); } +void PatternEditor::resizeEvent(QResizeEvent* re) +{ + setPixelsPerBar((width() - m_trackHeadWidth) * TimePos::stepsPerBar() / m_maxSteps); + m_timeLine->setPixelsPerBar(pixelsPerBar()); +} void PatternEditor::updatePosition() { //realignTracks(); + for (const auto& trackView : trackViews()) + { + if (trackView->getTrack()->type() == Track::Type::Instrument) + { + // Currently there is no way to get the clipviews corresponding to the current pattern index, so + // all of them get updated at once. It's not ideal but it works. + for (ClipView* cv : trackView->getClipViews()) { cv->update(); } + } + } emit positionChanged( m_currentPosition ); } +void PatternEditor::updateMaxSteps() +{ + const TrackContainer::TrackList& tl = model()->tracks(); + + m_maxSteps = TimePos::stepsPerBar(); + for (const auto& track : tl) + { + if (track->type() == Track::Type::Instrument) + { + auto p = static_cast(track->getClip(m_ps->currentPattern())); + m_maxSteps = std::max(m_maxSteps, p->steps()); + } + } + setPixelsPerBar((width() - m_trackHeadWidth) * TimePos::stepsPerBar() / m_maxSteps); + m_timeLine->setPixelsPerBar(pixelsPerBar()); +} void PatternEditor::makeSteps( bool clone ) @@ -192,6 +245,7 @@ void PatternEditor::makeSteps( bool clone ) } } } + updateMaxSteps(); } // Creates a clone of the current pattern track with the same content, but no clips in the song editor @@ -285,6 +339,7 @@ PatternEditorWindow::PatternEditorWindow(PatternStore* ps) : connect(&ps->m_patternComboBoxModel, SIGNAL(dataChanged()), m_editor, SLOT(updatePosition())); + connect(&ps->m_patternComboBoxModel, &ComboBoxModel::dataChanged, m_editor, &PatternEditor::updateMaxSteps); auto viewNext = new QAction(this); connect(viewNext, SIGNAL(triggered()), m_patternComboBox, SLOT(selectNext())); diff --git a/src/gui/tracks/TrackView.cpp b/src/gui/tracks/TrackView.cpp index ecd397975f1..6d68104be0f 100644 --- a/src/gui/tracks/TrackView.cpp +++ b/src/gui/tracks/TrackView.cpp @@ -428,6 +428,7 @@ void TrackView::createClipView( Clip * clip ) tv->setSelected( true ); } clip->selectViewOnCreate( false ); + m_clipViews.push_back(tv); } From a970bc1a9814e12012e4ff40d21c289e5ee40f6a Mon Sep 17 00:00:00 2001 From: regulus79 <117475203+regulus79@users.noreply.github.com> Date: Tue, 18 Mar 2025 17:38:50 -0400 Subject: [PATCH 2/6] Rework connections, remove QTimer --- src/gui/editors/PatternEditor.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/gui/editors/PatternEditor.cpp b/src/gui/editors/PatternEditor.cpp index 1da6c3ab88d..f7dfc18f3ff 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -61,14 +61,8 @@ PatternEditor::PatternEditor(PatternStore* ps) : Engine::getSong()->getTimeline(Song::PlayMode::Pattern), m_currentPosition, Song::PlayMode::Pattern, this ); - connect(this, &TrackContainerView::positionChanged, m_timeLine, &TimeLineWidget::updatePosition); + connect(m_timeLine, &TimeLineWidget::positionChanged, this, &PatternEditor::updatePosition); static_cast( layout() )->insertWidget( 0, m_timeLine ); - - - // TO BE REMOVED after Timeline signals are refactored (#7454) - auto updateTimer = new QTimer(this); - connect(updateTimer, &QTimer::timeout, this, &PatternEditor::updatePosition); - updateTimer->start( 1000 / 60 ); // 60 fps } From 8a5e6ae68ae0524282f4fef73d5733353bea5eec Mon Sep 17 00:00:00 2001 From: regulus79 <117475203+regulus79@users.noreply.github.com> Date: Tue, 18 Mar 2025 20:04:36 -0400 Subject: [PATCH 3/6] Update when timesig changes --- include/PatternEditor.h | 1 + src/gui/editors/PatternEditor.cpp | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/include/PatternEditor.h b/include/PatternEditor.h index 4b1faa01dee..6e1a6bcbb07 100644 --- a/include/PatternEditor.h +++ b/include/PatternEditor.h @@ -69,6 +69,7 @@ protected slots: void dropEvent(QDropEvent * de ) override; void resizeEvent(QResizeEvent * de ) override; void updatePosition(); + void updatePixelsPerBar(); private: PatternStore* m_ps; diff --git a/src/gui/editors/PatternEditor.cpp b/src/gui/editors/PatternEditor.cpp index f7dfc18f3ff..ba16bb210c0 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -63,6 +63,9 @@ PatternEditor::PatternEditor(PatternStore* ps) : ); connect(m_timeLine, &TimeLineWidget::positionChanged, this, &PatternEditor::updatePosition); static_cast( layout() )->insertWidget( 0, m_timeLine ); + + connect( Engine::getSong(), &Song::timeSignatureChanged, + this, &PatternEditor::updateMaxSteps); } @@ -182,8 +185,7 @@ void PatternEditor::dropEvent(QDropEvent* de) void PatternEditor::resizeEvent(QResizeEvent* re) { - setPixelsPerBar((width() - m_trackHeadWidth) * TimePos::stepsPerBar() / m_maxSteps); - m_timeLine->setPixelsPerBar(pixelsPerBar()); + updatePixelsPerBar(); } @@ -202,6 +204,13 @@ void PatternEditor::updatePosition() emit positionChanged( m_currentPosition ); } +void PatternEditor::updatePixelsPerBar() +{ + //const int num = Engine::getSong()->getTimeSigModel().getNumerator(); + //const int den = Engine::getSong()->getTimeSigModel().getDenominator(); + setPixelsPerBar((width() - m_trackHeadWidth) * TimePos::stepsPerBar() / m_maxSteps); + m_timeLine->setPixelsPerBar(pixelsPerBar()); +} void PatternEditor::updateMaxSteps() { @@ -216,8 +225,7 @@ void PatternEditor::updateMaxSteps() m_maxSteps = std::max(m_maxSteps, p->steps()); } } - setPixelsPerBar((width() - m_trackHeadWidth) * TimePos::stepsPerBar() / m_maxSteps); - m_timeLine->setPixelsPerBar(pixelsPerBar()); + updatePixelsPerBar(); } From 9d1c567d37f538935c88da30fd22f739047d478f Mon Sep 17 00:00:00 2001 From: regulus79 <117475203+regulus79@users.noreply.github.com> Date: Thu, 20 Mar 2025 17:47:05 -0400 Subject: [PATCH 4/6] Fix formatting and remove inlines Co-authored-by: Sotonye Atemie --- include/MidiClip.h | 2 +- include/PatternEditor.h | 2 +- include/TrackView.h | 2 +- src/gui/editors/PatternEditor.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/MidiClip.h b/include/MidiClip.h index 130657968d4..17bf6395587 100644 --- a/include/MidiClip.h +++ b/include/MidiClip.h @@ -91,7 +91,7 @@ class LMMS_EXPORT MidiClip : public Clip return m_clipType; } - inline int steps() const + int steps() const { return m_steps; } diff --git a/include/PatternEditor.h b/include/PatternEditor.h index 6e1a6bcbb07..0520c6d573c 100644 --- a/include/PatternEditor.h +++ b/include/PatternEditor.h @@ -67,7 +67,7 @@ public slots: protected slots: void dropEvent(QDropEvent * de ) override; - void resizeEvent(QResizeEvent * de ) override; + void resizeEvent(QResizeEvent* de) override; void updatePosition(); void updatePixelsPerBar(); diff --git a/include/TrackView.h b/include/TrackView.h index 3cd7496199a..f33c11e016a 100644 --- a/include/TrackView.h +++ b/include/TrackView.h @@ -73,7 +73,7 @@ class TrackView : public QWidget, public ModelView, public JournallingObject return m_track; } - inline const std::vector& getClipViews() + const std::vector& getClipViews() { return m_clipViews; } diff --git a/src/gui/editors/PatternEditor.cpp b/src/gui/editors/PatternEditor.cpp index ba16bb210c0..fbe062e7a5b 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -64,7 +64,7 @@ PatternEditor::PatternEditor(PatternStore* ps) : connect(m_timeLine, &TimeLineWidget::positionChanged, this, &PatternEditor::updatePosition); static_cast( layout() )->insertWidget( 0, m_timeLine ); - connect( Engine::getSong(), &Song::timeSignatureChanged, + connect(Engine::getSong(), &Song::timeSignatureChanged, this, &PatternEditor::updateMaxSteps); } From 485c449cec41d1ce347e30bc5425fc2e78a70438 Mon Sep 17 00:00:00 2001 From: regulus79 <117475203+regulus79@users.noreply.github.com> Date: Thu, 20 Mar 2025 18:25:16 -0400 Subject: [PATCH 5/6] Fix time signature updating issues --- include/PatternStore.h | 2 ++ src/core/PatternStore.cpp | 1 + src/gui/editors/PatternEditor.cpp | 6 ++---- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/PatternStore.h b/include/PatternStore.h index fcb55e4117a..512ac7cad80 100644 --- a/include/PatternStore.h +++ b/include/PatternStore.h @@ -100,6 +100,8 @@ public slots: void updateComboBox(); void currentPatternChanged(); +signals: + void trackUpdated(); private: ComboBoxModel m_patternComboBoxModel; diff --git a/src/core/PatternStore.cpp b/src/core/PatternStore.cpp index 6af434f65b3..f9c38d9bc56 100644 --- a/src/core/PatternStore.cpp +++ b/src/core/PatternStore.cpp @@ -152,6 +152,7 @@ void PatternStore::updatePatternTrack(Clip* clip) { t->dataChanged(); } + emit trackUpdated(); } diff --git a/src/gui/editors/PatternEditor.cpp b/src/gui/editors/PatternEditor.cpp index fbe062e7a5b..11806948f5b 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -64,7 +64,7 @@ PatternEditor::PatternEditor(PatternStore* ps) : connect(m_timeLine, &TimeLineWidget::positionChanged, this, &PatternEditor::updatePosition); static_cast( layout() )->insertWidget( 0, m_timeLine ); - connect(Engine::getSong(), &Song::timeSignatureChanged, + connect(m_ps, &PatternStore::trackUpdated, this, &PatternEditor::updateMaxSteps); } @@ -206,8 +206,6 @@ void PatternEditor::updatePosition() void PatternEditor::updatePixelsPerBar() { - //const int num = Engine::getSong()->getTimeSigModel().getNumerator(); - //const int den = Engine::getSong()->getTimeSigModel().getDenominator(); setPixelsPerBar((width() - m_trackHeadWidth) * TimePos::stepsPerBar() / m_maxSteps); m_timeLine->setPixelsPerBar(pixelsPerBar()); } @@ -216,7 +214,7 @@ void PatternEditor::updateMaxSteps() { const TrackContainer::TrackList& tl = model()->tracks(); - m_maxSteps = TimePos::stepsPerBar(); + m_maxSteps = 0; for (const auto& track : tl) { if (track->type() == Track::Type::Instrument) From 871f5faa12225927d7416e854e14f7bdcf72672d Mon Sep 17 00:00:00 2001 From: regulus79 <117475203+regulus79@users.noreply.github.com> Date: Thu, 20 Mar 2025 20:14:37 -0400 Subject: [PATCH 6/6] Simplify updating --- src/gui/editors/PatternEditor.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/gui/editors/PatternEditor.cpp b/src/gui/editors/PatternEditor.cpp index 11806948f5b..42d296a0fb4 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -194,12 +194,7 @@ void PatternEditor::updatePosition() //realignTracks(); for (const auto& trackView : trackViews()) { - if (trackView->getTrack()->type() == Track::Type::Instrument) - { - // Currently there is no way to get the clipviews corresponding to the current pattern index, so - // all of them get updated at once. It's not ideal but it works. - for (ClipView* cv : trackView->getClipViews()) { cv->update(); } - } + trackView->update(); } emit positionChanged( m_currentPosition ); }