partial-channel copy/paste

portability/boost
zetaPRIME 2019-01-08 20:22:18 -05:00
parent 7001adb132
commit 60310bf6f1
3 changed files with 21 additions and 11 deletions

2
notes
View File

@ -47,7 +47,7 @@ TODO {
immediate frontburner {
- transpose selection (alt+up/down for semitone/0x01, left+right for octave/0x10)
- pattern cut+copy+paste
^ channel-column splitting
- ^ channel-column splitting (partial channel copy/paste)
add metadata and pattern properties (artist, song title, project bpm; pattern name, length etc.)
probably move the "process all nodes" part of tick processing into its own function?

View File

@ -148,8 +148,10 @@ PatternEditorView::PatternEditorView(QWidget *parent) : QTableView(parent) {
for (int ch = chMin; ch <= chMax; ch++) {
QCborArray chm;
int first = 0; // TODO ... later
int last = 255;
int first = 0, last = 255;
if (ch == chMin) first = Util::fieldForColumn(sel.left());
if (ch == chMax) last = Util::fieldForColumn(sel.right());
chm << first << last;
for (int r = sel.top(); r <= sel.bottom(); r++) {
QCborArray rm;
@ -189,18 +191,21 @@ PatternEditorView::PatternEditorView(QWidget *parent) : QTableView(parent) {
for (int ch = 0; ch < static_cast<int>(p->numChannels()) - chMin && ch < root.size(); ch++) {
auto chm = root[ch].toArray();
//int first = static_cast<int>(chm[0].toInteger());
//int last = static_cast<int>(chm[1].toInteger());
int first = static_cast<int>(chm[0].toInteger());
int last = static_cast<int>(chm[1].toInteger());
int pOff = 0;
if (ch == 0 && first >= 2) pOff = std::max(0, Util::fieldForColumn(idx.column()) - first);
for (int r = 0; r < p->rows - rMin && r < chm.size() - 2; r++) {
auto rm = chm[r+2].toArray();
auto c = new PatternDeltaCommand(p, ch+chMin, r+rMin);
auto& row = c->row;
row.port = static_cast<int16_t>(rm[0].toInteger());
row.note = static_cast<int16_t>(rm[1].toInteger());
for (int p = 0; p < (rm.size() - 2) / 2; p++)
row.setParam(static_cast<size_t>(p), static_cast<char>(rm[p*2+2].toInteger()), static_cast<unsigned char>(rm[p*2+3].toInteger()));
if (first <= 0 && last >= 0) row.port = static_cast<int16_t>(rm[0].toInteger());
if (first <= 1 && last >= 1) row.note = static_cast<int16_t>(rm[1].toInteger());
for (int p = 0; p < (rm.size() - 2) / 2 && p+pOff < Util::paramSoftCap; p++)
if (first <= p+2 && last >= p+2) row.setParam(static_cast<size_t>(p+pOff), static_cast<char>(rm[p*2+2].toInteger()), static_cast<unsigned char>(rm[p*2+3].toInteger()));
cc->compose(c);
}

View File

@ -4,7 +4,12 @@ namespace Xybrid::Util {
static constexpr int paramSoftCap = 16; // maximum number of parameter columns that can be displayed per channel; the rest are hidden
static constexpr int colsPerChannel = 2 + (2 * paramSoftCap);
inline int channelForColumn(int col) {
return (col - (col % colsPerChannel)) / colsPerChannel;
inline int channelForColumn(int col) { return (col - (col % colsPerChannel)) / colsPerChannel; }
inline int columnWithinChannel(int col) { return col % colsPerChannel; }
inline int fieldForColumn(int col) {
int cc = columnWithinChannel(col);
if (cc < 2) return cc;
return 2 + (cc-2) / 2;
}
}