Skip to content

Commit

Permalink
Merge pull request #25608 from mathesoncalum/percussions_saving_loading
Browse files Browse the repository at this point in the history
Percussion panel - save/load drum pad panel positions
  • Loading branch information
mathesoncalum authored Nov 28, 2024
2 parents 17b7f90 + 264856e commit 7706808
Show file tree
Hide file tree
Showing 17 changed files with 296 additions and 114 deletions.
50 changes: 31 additions & 19 deletions src/engraving/dom/drumset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ String Drumset::translatedName(int pitch) const

void Drumset::save(XmlWriter& xml) const
{
for (int i = 0; i < 128; ++i) {
for (int i = 0; i < DRUM_INSTRUMENTS; ++i) {
if (!isValid(i)) {
continue;
}
Expand Down Expand Up @@ -107,6 +107,10 @@ void Drumset::save(XmlWriter& xml) const
}
xml.endElement();
}
if (panelRow(i) > -1 && panelColumn(i) > -1) {
xml.tag("panelRow", panelRow(i));
xml.tag("panelColumn", panelColumn(i));
}
xml.endElement();
}
}
Expand All @@ -119,31 +123,31 @@ bool Drumset::readProperties(XmlReader& e, int pitch)

const AsciiStringView tag(e.name());
if (tag == "head") {
m_drum[pitch].notehead = TConv::fromXml(e.readAsciiText(), NoteHeadGroup::HEAD_NORMAL);
m_drums[pitch].notehead = TConv::fromXml(e.readAsciiText(), NoteHeadGroup::HEAD_NORMAL);
} else if (tag == "noteheads") {
m_drum[pitch].notehead = NoteHeadGroup::HEAD_CUSTOM;
m_drums[pitch].notehead = NoteHeadGroup::HEAD_CUSTOM;
while (e.readNextStartElement()) {
const AsciiStringView nhTag(e.name());
int noteType = int(TConv::fromXml(nhTag, NoteHeadType::HEAD_AUTO));
if (noteType > int(NoteHeadType::HEAD_TYPES) - 1 || noteType < 0) {
return false;
}

m_drum[pitch].noteheads[noteType] = SymNames::symIdByName(e.readAsciiText());
m_drums[pitch].noteheads[noteType] = SymNames::symIdByName(e.readAsciiText());
}
} else if (tag == "line") {
m_drum[pitch].line = e.readInt();
m_drums[pitch].line = e.readInt();
} else if (tag == "voice") {
m_drum[pitch].voice = e.readInt();
m_drums[pitch].voice = e.readInt();
} else if (tag == "name") {
m_drum[pitch].name = e.readText();
m_drums[pitch].name = e.readText();
} else if (tag == "stem") {
m_drum[pitch].stemDirection = DirectionV(e.readInt());
m_drums[pitch].stemDirection = DirectionV(e.readInt());
} else if (tag == "shortcut") {
bool isNum;
AsciiStringView val = e.readAsciiText();
int i = val.toInt(&isNum);
m_drum[pitch].shortcut = isNum ? i : val.at(0).toUpper();
m_drums[pitch].shortcut = isNum ? i : val.at(0).toUpper();
} else if (tag == "variants") {
while (e.readNextStartElement()) {
const AsciiStringView tagv(e.name());
Expand All @@ -158,9 +162,13 @@ bool Drumset::readProperties(XmlReader& e, int pitch)
div.tremolo = TConv::fromXml(e.readAsciiText(), TremoloType::INVALID_TREMOLO);
}
}
m_drum[pitch].addVariant(div);
m_drums[pitch].addVariant(div);
}
}
} else if (tag == "panelRow") {
m_drums[pitch].panelRow = e.readInt();
} else if (tag == "panelColumn") {
m_drums[pitch].panelColumn = e.readInt();
} else {
return false;
}
Expand All @@ -174,7 +182,7 @@ bool Drumset::readProperties(XmlReader& e, int pitch)
void Drumset::load(XmlReader& e)
{
int pitch = e.intAttribute("pitch", -1);
if (pitch < 0 || pitch > 127) {
if (pitch < 0 || pitch > DRUM_INSTRUMENTS - 1) {
LOGD("load drumset: invalid pitch %d", pitch);
return;
}
Expand All @@ -192,11 +200,13 @@ void Drumset::load(XmlReader& e)

void Drumset::clear()
{
for (int i = 0; i < 128; ++i) {
m_drum[i].name = u"";
m_drum[i].notehead = NoteHeadGroup::HEAD_INVALID;
m_drum[i].shortcut = 0;
m_drum[i].variants.clear();
for (int i = 0; i < DRUM_INSTRUMENTS; ++i) {
m_drums[i].name = u"";
m_drums[i].notehead = NoteHeadGroup::HEAD_INVALID;
m_drums[i].shortcut = 0;
m_drums[i].variants.clear();
m_drums[i].panelRow = -1;
m_drums[i].panelColumn = -1;
}
}

Expand All @@ -206,7 +216,7 @@ void Drumset::clear()

int Drumset::nextPitch(int ii) const
{
for (int i = ii + 1; i < 127; ++i) {
for (int i = ii + 1; i < DRUM_INSTRUMENTS - 1; ++i) {
if (isValid(i)) {
return i;
}
Expand All @@ -230,7 +240,7 @@ int Drumset::prevPitch(int ii) const
return i;
}
}
for (int i = 127; i >= ii; --i) {
for (int i = DRUM_INSTRUMENTS - 1; i >= ii; --i) {
if (isValid(i)) {
return i;
}
Expand Down Expand Up @@ -273,12 +283,14 @@ DrumInstrumentVariant Drumset::findVariant(int p, const std::vector<Articulation
void Drumset::initDrumset()
{
smDrumset = new Drumset;
for (int i = 0; i < 128; ++i) {
for (int i = 0; i < DRUM_INSTRUMENTS; ++i) {
smDrumset->drum(i).notehead = NoteHeadGroup::HEAD_INVALID;
smDrumset->drum(i).line = 0;
smDrumset->drum(i).shortcut = 0;
smDrumset->drum(i).voice = 0;
smDrumset->drum(i).stemDirection = DirectionV::UP;
smDrumset->drum(i).panelRow = -1;
smDrumset->drum(i).panelColumn = -1;
}
smDrumset->drum(35) = DrumInstrument(TConv::userName(DrumNum(35)), NoteHeadGroup::HEAD_NORMAL, 8, DirectionV::DOWN, 1);
smDrumset->drum(36) = DrumInstrument(TConv::userName(DrumNum(36)), NoteHeadGroup::HEAD_NORMAL, 7, DirectionV::DOWN, 1, Key_B);
Expand Down
65 changes: 50 additions & 15 deletions src/engraving/dom/drumset.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ struct DrumInstrumentVariant {
int pitch = INVALID_PITCH;
TremoloType tremolo = TremoloType::INVALID_TREMOLO;
String articulationName;

bool operator==(const DrumInstrumentVariant& other) const
{
return pitch == other.pitch
&& tremolo == other.tremolo
&& articulationName == other.articulationName;
}
};

//---------------------------------------------------------
Expand All @@ -56,12 +63,28 @@ struct DrumInstrument {
char shortcut = '\0'; ///< accelerator key (CDEFGAB)
std::list<DrumInstrumentVariant> variants;

int panelRow = -1;
int panelColumn = -1;

DrumInstrument() {}
DrumInstrument(const char* s, NoteHeadGroup nh, int l, DirectionV d,
int v = 0, char sc = 0)
: name(String::fromUtf8(s)), notehead(nh), line(l), stemDirection(d), voice(v), shortcut(sc) {}

void addVariant(DrumInstrumentVariant v) { variants.push_back(v); }

bool operator==(const DrumInstrument& other) const
{
return notehead == other.notehead
&& noteheads == other.noteheads
&& line == other.line
&& stemDirection == other.stemDirection
&& voice == other.voice
&& shortcut == other.shortcut
&& variants == other.variants
&& panelRow == other.panelRow
&& panelColumn == other.panelColumn;
}
};

static const int DRUM_INSTRUMENTS = 128;
Expand All @@ -75,33 +98,45 @@ static const int DRUM_INSTRUMENTS = 128;
class Drumset
{
public:

bool isValid(int pitch) const { return !m_drum[pitch].name.empty(); }
NoteHeadGroup noteHead(int pitch) const { return m_drum[pitch].notehead; }
SymId noteHeads(int pitch, NoteHeadType t) const { return m_drum[pitch].noteheads[int(t)]; }
int line(int pitch) const { return m_drum[pitch].line; }
int voice(int pitch) const { return m_drum[pitch].voice; }
DirectionV stemDirection(int pitch) const { return m_drum[pitch].stemDirection; }
const String& name(int pitch) const { return m_drum[pitch].name; }
bool isValid(int pitch) const { return !m_drums[pitch].name.empty(); }
NoteHeadGroup noteHead(int pitch) const { return m_drums[pitch].notehead; }
SymId noteHeads(int pitch, NoteHeadType t) const { return m_drums[pitch].noteheads[int(t)]; }
int line(int pitch) const { return m_drums[pitch].line; }
int voice(int pitch) const { return m_drums[pitch].voice; }
DirectionV stemDirection(int pitch) const { return m_drums[pitch].stemDirection; }
const String& name(int pitch) const { return m_drums[pitch].name; }
String translatedName(int pitch) const;
int shortcut(int pitch) const { return m_drum[pitch].shortcut; }
std::list<DrumInstrumentVariant> variants(int pitch) const { return m_drum[pitch].variants; }
int shortcut(int pitch) const { return m_drums[pitch].shortcut; }
std::list<DrumInstrumentVariant> variants(int pitch) const { return m_drums[pitch].variants; }
int panelRow(int pitch) const { return m_drums[pitch].panelRow; }
int panelColumn(int pitch) const { return m_drums[pitch].panelColumn; }

void save(XmlWriter&) const;
void load(XmlReader&);
bool readProperties(XmlReader&, int);
void clear();
int nextPitch(int) const;
int prevPitch(int) const;
DrumInstrument& drum(int i) { return m_drum[i]; }
const DrumInstrument& drum(int i) const { return m_drum[i]; }
void setDrum(int pitch, const DrumInstrument& di) { m_drum[pitch] = di; }
DrumInstrument& drum(int i) { return m_drums[i]; }
const DrumInstrument& drum(int i) const { return m_drums[i]; }
void setDrum(int pitch, const DrumInstrument& di) { m_drums[pitch] = di; }
DrumInstrumentVariant findVariant(int pitch, const std::vector<Articulation*>& articulations, TremoloType tremType) const;

static void initDrumset();
private:

DrumInstrument m_drum[DRUM_INSTRUMENTS];
bool operator==(const Drumset& other) const
{
for (int pitch = 0; pitch < DRUM_INSTRUMENTS; ++pitch) {
if (m_drums[pitch] == other.m_drums[pitch]) {
continue;
}
return false;
}
return true;
}

private:
DrumInstrument m_drums[DRUM_INSTRUMENTS];
};

extern Drumset* smDrumset;
Expand Down
2 changes: 1 addition & 1 deletion src/engraving/dom/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ bool InputState::isValid() const
// drumset
//---------------------------------------------------------

const Drumset* InputState::drumset() const
Drumset* InputState::drumset() const
{
if (!m_segment || m_track == muse::nidx) {
return nullptr;
Expand Down
2 changes: 1 addition & 1 deletion src/engraving/dom/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class InputState
Segment* lastSegment() const { return m_lastSegment; }
void setLastSegment(Segment* s) { m_lastSegment = s; }

const Drumset* drumset() const;
Drumset* drumset() const;

int drumNote() const { return m_drumNote; }
void setDrumNote(int v) { m_drumNote = v; }
Expand Down
4 changes: 3 additions & 1 deletion src/importexport/guitarpro/internal/guitarprodrumset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ void initGuitarProDrumset()

if (!gpDrumset) {
gpDrumset = new Drumset();
for (int i = 0; i < 128; ++i) {
for (int i = 0; i < DRUM_INSTRUMENTS; ++i) {
gpDrumset->drum(i).notehead = NoteHeadGroup::HEAD_INVALID;
gpDrumset->drum(i).line = 0;
gpDrumset->drum(i).shortcut = 0;
gpDrumset->drum(i).voice = 0;
gpDrumset->drum(i).stemDirection = DirectionV::UP;
gpDrumset->drum(i).panelRow = -1;
gpDrumset->drum(i).panelColumn = -1;
}
// new drumset determined via guitar pro (third argument specifies position on staff, 10 = C3, 9 = D3, 8 = E3,...)

Expand Down
2 changes: 2 additions & 0 deletions src/importexport/ove/internal/importove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,8 @@ void OveToMScore::convertTrackHeader(ovebase::Track* track, Part* part)
drumset->drum(i).stemDirection = smDrumset->drum(i).stemDirection;
drumset->drum(i).voice = smDrumset->drum(i).voice;
drumset->drum(i).shortcut = 0;
drumset->drum(i).panelRow = smDrumset->drum(i).panelRow;
drumset->drum(i).panelColumn = smDrumset->drum(i).panelColumn;
}
QList<ovebase::Track::DrumNode> nodes = track->getDrumKit();
for (int i = 0; i < nodes.size(); ++i) {
Expand Down
2 changes: 1 addition & 1 deletion src/notation/notationtypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ struct NoteInputState
engraving::voice_idx_t currentVoiceIndex = 0;
engraving::track_idx_t currentTrack = 0;
int currentString = 0;
const Drumset* drumset = nullptr;
Drumset* drumset = nullptr;
StaffGroup staffGroup = StaffGroup::STANDARD;
const Staff* staff = nullptr;
Segment* segment = nullptr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ Item {
text: qsTrc("notation", "Add row")
orientation: Qt.Horizontal
onClicked: {
padGrid.model.addRow()
padGrid.model.addEmptyRow()
flickable.goToBottom()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ DropArea {

QtObject {
id: prv
readonly property bool isEmptySlot: Boolean(root.padModel) ? root.padModel.isEmptySlot : true
readonly property color enabledBackgroundColor: Utils.colorWithAlpha(ui.theme.buttonColor, ui.theme.buttonOpacityNormal)
readonly property color disabledBackgroundColor: Utils.colorWithAlpha(ui.theme.buttonColor, ui.theme.itemOpacityDisabled)
}
Expand All @@ -70,7 +69,7 @@ DropArea {
id: dragHandler

target: draggableArea
enabled: root.panelMode === PanelMode.EDIT_LAYOUT && !prv.isEmptySlot
enabled: Boolean(root.padModel) && root.panelMode === PanelMode.EDIT_LAYOUT

dragThreshold: 0 // prevents the flickable from stealing drag events

Expand Down Expand Up @@ -107,7 +106,7 @@ DropArea {
}
}

sourceComponent: prv.isEmptySlot ? emptySlotComponent : padContentComponent
sourceComponent: Boolean(root.padModel) ? padContentComponent : emptySlotComponent

Component {
id: padContentComponent
Expand Down
Loading

0 comments on commit 7706808

Please sign in to comment.