middle click to remove sequence entry

portability/boost
zetaPRIME 2019-07-12 03:19:56 -04:00
parent f173a0e87f
commit 9d45d78795
5 changed files with 32 additions and 20 deletions

14
notes
View File

@ -32,8 +32,9 @@ parameters {
TODO {
immediate frontburner {
- add standardized step values for knobs and set a default (int enum)
global pan (PXX) for InstrumentCore?
spacer rows on top/bottom of pattern editor (keep centered)
global pan (PXX) for InstrumentCore? *default* pan
- node function to release unneeded old data when stopping playback
...
@ -47,19 +48,12 @@ TODO {
bugs to fix {
-? it sometimes crashes on exit??
... does graph really need to call reset() on its children at this point
playback after stopping immediately after a note in the first pattern played sometimes skips that note
}
misc features needed before proper release {
- song metadata (title, artist, comment, default bpm)
at *least* js plugin support, with lua+lv2 highly preferable
- SAMPLES and SAMPLING
- gadget widgets (w/container) - at least a knob with nice range and such
different context menu for multiple selected nodes
/ pack/unpack selection to/from subgraph (partial; can copy/paste a selection)

View File

@ -362,7 +362,7 @@ Pattern* AudioEngine::findPattern(int adv) {
if (mode == Rendering && !s) return nullptr; // stop
else if (mode == Rendering && s->type == SequenceEntry::LoopTrigger) { seqPos++; continue; }
else if (!s || s->type == SequenceEntry::LoopTrigger) { // off end or explicit loop, find loop point
else if (!s || (s->type == SequenceEntry::LoopTrigger && seqPos > 0)) { // off end or explicit loop, find loop point
for (seqPos = std::min(seqPos, static_cast<int>(project->sequence.size()) - 1); seqPos >= 0; --seqPos)
if (project->sequence[static_cast<size_t>(seqPos)].type == SequenceEntry::LoopStart) break;
continue;

View File

@ -20,8 +20,8 @@ bool ProjectCommand::cancel() {
return false;
}
ProjectSequencerDeltaCommand::ProjectSequencerDeltaCommand(const std::shared_ptr<Project>& project) {
this->project = project;
ProjectSequencerDeltaCommand::ProjectSequencerDeltaCommand(const std::shared_ptr<Project>& project_) {
project = project_;
oldSeq = project->sequence;
oldSeqSel = project->socket->window->sequenceSelection();
seq = oldSeq;
@ -50,8 +50,8 @@ void ProjectSequencerDeltaCommand::undo() {
project->socket->window->sequenceSelection(oldSeqSel);
}
ProjectPatternMoveCommand::ProjectPatternMoveCommand(const std::shared_ptr<Project>& project, int f, int t) {
this->project = project;
ProjectPatternMoveCommand::ProjectPatternMoveCommand(const std::shared_ptr<Project>& project_, int f, int t) {
project = project_;
from = f;
to = t;
setText("move pattern");
@ -85,8 +85,8 @@ void ProjectPatternMoveCommand::undo() {
if (move) project->socket->window->patternSelection(from);
}
ProjectPatternAddCommand::ProjectPatternAddCommand(const std::shared_ptr<Project>& project, int at, int atSeq, const std::shared_ptr<Pattern>& copyOf) {
this->project = project;
ProjectPatternAddCommand::ProjectPatternAddCommand(const std::shared_ptr<Project>& project_, int at, int atSeq, const std::shared_ptr<Pattern>& copyOf) {
project = project_;
if (at < 0) at = std::numeric_limits<int>::max();
this->at = std::max(0, std::min(at, static_cast<int>(project->patterns.size())));
this->atSeq = atSeq;

View File

@ -207,6 +207,23 @@ MainWindow::MainWindow(QWidget *parent) :
this->selectPatternForEditing(project->sequence[idx].pattern().get());
});
// middle click
auto mouselmb = [this, seq = ui->patternSequencer](QObject*, QEvent* e) {
if (e->type() == QEvent::MouseButtonRelease) {
auto me = static_cast<QMouseEvent*>(e);
if (me->button() == Qt::MouseButton::MiddleButton) {
auto idx = static_cast<size_t>(seq->indexAt(me->pos()).column());
if (idx >= project->sequence.size()) return false; // nothing to remove
auto* c = new ProjectSequencerDeltaCommand(project);
c->seq.erase(c->seq.begin() + static_cast<ptrdiff_t>(idx));
c->seqSel = static_cast<int>(idx)-1;
return c->commit();
}
}
return false;
};
ui->patternSequencer->viewport()->installEventFilter(new LambdaEventFilter(this, mouselmb));
// rightclick menu
connect(ui->patternSequencer, &QTableView::customContextMenuRequested, this, [this](const QPoint& pt) {
size_t idx = static_cast<size_t>(ui->patternSequencer->indexAt(pt).column());
@ -223,7 +240,7 @@ MainWindow::MainWindow(QWidget *parent) :
menu->addAction("Insert Separator", this, [this, idx] {
int si = static_cast<int>(std::min(idx, project->sequence.size()));
auto* c = new ProjectSequencerDeltaCommand(project);
c->seq.insert(c->seq.begin() + si, { });
c->seq.insert(c->seq.begin() + si, SequenceEntry::Separator);
c->seqSel = si+1;
c->commit();
});
@ -263,7 +280,7 @@ MainWindow::MainWindow(QWidget *parent) :
menu->setAttribute(Qt::WA_DeleteOnClose);
menu->popup(ui->patternSequencer->mapToGlobal(pt));
});//*/
});
}
{ /* Set up keyboard shortcuts for pattern view */ } {

View File

@ -7,6 +7,7 @@ class LambdaEventFilter : public QObject {
Q_OBJECT
std::function<bool(QObject*, QEvent*)> filter;
public:
LambdaEventFilter(QObject* parent, std::function<bool(QObject*, QEvent*)> f) : QObject(parent), filter(f) { }
LambdaEventFilter(QObject* parent, const std::function<bool(QObject*, QEvent*)>& f) : QObject(parent), filter(f) { }
bool eventFilter(QObject* watched, QEvent* event) override { return filter(watched, event); }
static inline LambdaEventFilter* create(QObject* parent, const std::function<bool(QObject*, QEvent*)>& f) { return new LambdaEventFilter(parent, f); }
};