diff --git a/include/trackerboy/engine/Engine.hpp b/include/trackerboy/engine/Engine.hpp index eeb8c492..e35f4d6d 100644 --- a/include/trackerboy/engine/Engine.hpp +++ b/include/trackerboy/engine/Engine.hpp @@ -58,6 +58,8 @@ class Engine { // void halt(); + void jump(int pattern); + // // Lock the given channel. Channel is reloaded with music settings. // diff --git a/include/trackerboy/engine/MusicRuntime.hpp b/include/trackerboy/engine/MusicRuntime.hpp index ec1f3bd7..9013708f 100644 --- a/include/trackerboy/engine/MusicRuntime.hpp +++ b/include/trackerboy/engine/MusicRuntime.hpp @@ -38,6 +38,8 @@ class MusicRuntime { void unlock(RuntimeContext const& rc, ChType ch); + void jump(int pattern); + bool step(RuntimeContext const& rc, Frame &frame); void repeatPattern(bool repeat); diff --git a/libtrackerboy/engine/Engine.cpp b/libtrackerboy/engine/Engine.cpp index 75304337..ef4ae12f 100644 --- a/libtrackerboy/engine/Engine.cpp +++ b/libtrackerboy/engine/Engine.cpp @@ -63,6 +63,12 @@ void Engine::halt() { } } +void Engine::jump(int pattern) { + if (mMusicContext) { + mMusicContext->jump(pattern); + } +} + void Engine::lock(ChType ch) { if (mMusicContext) { mMusicContext->lock(*mRc, ch); diff --git a/libtrackerboy/engine/MusicRuntime.cpp b/libtrackerboy/engine/MusicRuntime.cpp index 11b8611d..48783b78 100644 --- a/libtrackerboy/engine/MusicRuntime.cpp +++ b/libtrackerboy/engine/MusicRuntime.cpp @@ -33,6 +33,11 @@ void MusicRuntime::halt(RuntimeContext const &rc) { haltChannels(rc); } +void MusicRuntime::jump(int pattern) { + mOrderCounter = pattern; + mRowCounter = 0; +} + void MusicRuntime::lock(RuntimeContext const& rc, ChType ch) { // do nothing if channel is already locked if (mFlags.test(+ch)) { diff --git a/ui/core/audio/Renderer.cpp b/ui/core/audio/Renderer.cpp index c53b37a5..3c9f1b39 100644 --- a/ui/core/audio/Renderer.cpp +++ b/ui/core/audio/Renderer.cpp @@ -292,6 +292,13 @@ void Renderer::stepFromCursor() { } } +void Renderer::jumpToPattern(int pattern) { + if (mStream.isEnabled()) { + auto ctx = mContext.access(); + ctx->engine.jump(pattern); + } +} + void Renderer::setPatternRepeat(bool repeat) { if (mStream.isEnabled()) { diff --git a/ui/core/audio/Renderer.hpp b/ui/core/audio/Renderer.hpp index 582131d3..8cd1601e 100644 --- a/ui/core/audio/Renderer.hpp +++ b/ui/core/audio/Renderer.hpp @@ -159,6 +159,11 @@ public slots: void stepFromCursor(); + // + // Jumps to the given pattern if currently playing music + // + void jumpToPattern(int pattern); + // // Stop previewing an instrument, waveform or row. // diff --git a/ui/core/model/PatternModel.cpp b/ui/core/model/PatternModel.cpp index ff703ebd..8ddddf81 100644 --- a/ui/core/model/PatternModel.cpp +++ b/ui/core/model/PatternModel.cpp @@ -193,6 +193,10 @@ PatternClip PatternModel::clip() { // slots ------------------------------- void PatternModel::moveCursorRow(int amount, SelectMode mode) { + if (mPlaying && mFollowing) { + return; + } + if (mode == SelectionModify) { selectCursor(); } else if (mode == SelectionRemove) { @@ -221,6 +225,10 @@ void PatternModel::moveCursorTrack(int amount) { } void PatternModel::setCursorRow(int row) { + if (mPlaying && mFollowing) { + return; + } + CursorChangeFlags flags = CursorUnchanged; setCursorRowImpl(row, flags); emitIfChanged(flags); @@ -319,7 +327,9 @@ void PatternModel::setCursorTrackImpl(int track, CursorChangeFlags &flags) { void PatternModel::setCursor(PatternCursor const cursor) { CursorChangeFlags flags = CursorUnchanged; - setCursorRowImpl(cursor.row, flags); + if (!(mPlaying && mFollowing)) { + setCursorRowImpl(cursor.row, flags); + } setCursorColumnImpl(cursor.column, flags); setCursorTrackImpl(cursor.track, flags); emitIfChanged(flags); @@ -357,7 +367,9 @@ void PatternModel::setTrackerCursor(int row, int pattern) { if (changed) { if (mFollowing) { mDocument.orderModel().selectPattern(pattern); - setCursorRow(row); + CursorChangeFlags flags = CursorUnchanged; + setCursorRowImpl(row, flags); + emitIfChanged(flags); } emit trackerCursorChanged(row, pattern); } diff --git a/ui/forms/MainWindow.cpp b/ui/forms/MainWindow.cpp index 2e253e3a..1e192b0b 100644 --- a/ui/forms/MainWindow.cpp +++ b/ui/forms/MainWindow.cpp @@ -1196,6 +1196,8 @@ void MainWindow::setupUi() { mContextMenuOrder.popup(pos); }); + connect(&mSidebar, &Sidebar::patternJumpRequested, &mRenderer, &Renderer::jumpToPattern); + // order actions connect(&mActions[ActionSongOrderInsert], &QAction::triggered, this, [this]() { diff --git a/ui/widgets/PatternEditor.cpp b/ui/widgets/PatternEditor.cpp index 66571f41..b8304386 100644 --- a/ui/widgets/PatternEditor.cpp +++ b/ui/widgets/PatternEditor.cpp @@ -355,7 +355,8 @@ void PatternEditor::wheelEvent(QWheelEvent *evt) { } if (amount) { - mDocument->patternModel().moveCursorRow(amount); + auto &patternModel = mDocument->patternModel(); + patternModel.moveCursorRow(amount); } evt->accept(); @@ -375,12 +376,15 @@ void PatternEditor::hscrollAction(int action) { } void PatternEditor::vscrollAction(int action) { + + auto &patternModel = mDocument->patternModel(); + switch (action) { case QAbstractSlider::SliderSingleStepAdd: - mDocument->patternModel().moveCursorRow(1); + patternModel.moveCursorRow(1); break; case QAbstractSlider::SliderSingleStepSub: - mDocument->patternModel().moveCursorRow(-1); + patternModel.moveCursorRow(-1); break; default: break; diff --git a/ui/widgets/Sidebar.cpp b/ui/widgets/Sidebar.cpp index 8b6294bf..f093daba 100644 --- a/ui/widgets/Sidebar.cpp +++ b/ui/widgets/Sidebar.cpp @@ -233,7 +233,17 @@ void Sidebar::currentChanged(QModelIndex const ¤t, QModelIndex const &prev if (mDocument) { mIgnoreSelect = true; - mDocument->orderModel().select(current.row(), current.column()); + auto &orderModel = mDocument->orderModel(); + auto &patternModel = mDocument->patternModel(); + if (patternModel.isPlaying() && patternModel.isFollowing()) { + if (orderModel.currentPattern() != current.row()) { + // jump to this pattern instead of selecting it + emit patternJumpRequested(current.row()); + } + orderModel.selectTrack(current.column()); + } else { + orderModel.select(current.row(), current.column()); + } mIgnoreSelect = false; } } diff --git a/ui/widgets/Sidebar.hpp b/ui/widgets/Sidebar.hpp index e86c4747..32146258 100644 --- a/ui/widgets/Sidebar.hpp +++ b/ui/widgets/Sidebar.hpp @@ -36,6 +36,8 @@ class Sidebar : public QWidget { signals: void orderMenuRequested(QPoint const& pos); + void patternJumpRequested(int pattern); + private: void currentIndexChanged(QModelIndex const& index);