/* Copyright © 2024 yonah_ag * * This program is free software; you can redistribute it or modify it under * the terms of the GNU General Public License version 3 as published by the * Free Software Foundation and appearing in the accompanying LICENSE file. * * Description * ----------- * */ import MuseScore 3.0 import QtQuick 2.2 import QtQuick.Controls 1.5 import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.3 // import QtQuick.Controls.Styles 1.3 // import Qt.labs.settings 1.0 // import FileIO 3.0 MuseScore { description: "Bowing"; requiresScore: true; version: "0.3.0"; menuPath: "Plugins.Bow Direction"; pluginType: "dialog"; // "dock"; property var noteName : [ "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] property var bowText : "xdup45678r" property var mTick : [] property var mBow : [] property var tinfo : "" // ======================================================================================================================= function mapAll() { infoWin.visible = true; var ix=0; var tick; var info; var elm; var etyp var zunk; // unknown element var zsys; // parent is system tinfo = ""; tinfo += "

All Elements

"; tinfo += ""; tinfo += ""; cmd('select-all') var selected = curScore.selection.elements; for (var ee in selected) { elm = selected[ee]; // if (elm.track > 0) break; zunk = false; zsys = false; etyp = elm.type; switch (etyp) { case Element.NOTE: if (elm.noteType==0) { tick = elm.parent.parent.tick; info = noteName[(elm.pitch % 12)]; } else { tick = elm.parent.parent.parent.tick + " *"; // grace note info = noteName[(elm.pitch % 12)] + " *"; } break; case Element.STEM: case Element.HOOK: case Element.ACCIDENTAL: case Element.ARPEGGIO: tick = ""; info = ""; break; case Element.REST: case Element.BAR_LINE: case Element.DYNAMIC: case Element.HARMONY: case Element.TEMPO_TEXT: case Element.CLEF: tick = elm.parent.tick; switch (etyp) { case Element.REST: info = elm.duration.str; break; case Element.DYNAMIC: info = "v = " + elm.velocity; break; case Element.HARMONY: info = elm.text; break; default: info = ""; } break; case Element.ARTICULATION: case Element.LYRICS: if (etyp==Element.ARTICULATION) { info = elm.symbol; if (info==2652) { info = "Down bow"; } else if (info==2677) { info = "Up bow"; } } else { info = elm.text; } tick = elm.parent.parent.tick; break; case Element.STAFF_TEXT: tick = elm.parent.tick; info = elm.text.substring(0,20); break; case Element.NOTEDOT: tick = elm.parent.parent.parent.tick; info = ""; break; case Element.BREATH: tick = elm.parent.tick; info = elm.symbol; break; case Element.BEAM: case Element.TIE: case Element.SLUR: case Element.TEXTLINE: case Element.VIBRATO: zsys = true; tick = ""; info = ""; break; default: tick = ""; info = ""; zunk = true; } ++ix; tinfo += ""; } curScore.selection.clear(); tinfo += "
 index  Track  Element Name  SegTick " tinfo += " Details  ^Parent^   ^^Parent^^ 
" + ix + " "; tinfo += "" + elm.track; tinfo += " " + elm.type + " - " + elm.name + " "; tinfo += "" + tick + " "; tinfo += " " + info + " "; if (zunk) tinfo += "  "; else if (zsys) tinfo += " System "; else { tinfo += " " + elm.parent.name + " "; tinfo += " " + elm.parent.parent.name + " "; } tinfo += "
"; popInfo.text = tinfo; } // ======================================================================================================================= function mapBow() { infoWin.visible = true; var ix=0; var tick; var info; var elm; var etyp; var zelm; var zunk; // unknown element var zsys; // parent is system tinfo = ""; tinfo += "

Bowing Elements

"; tinfo += ""; tinfo += ""; cmd('select-all') var selected = curScore.selection.elements; for (var ee in selected) { elm = selected[ee]; if (elm.track > 0) break; zunk = false; zsys = false; etyp = elm.type; switch (etyp) { case Element.NOTE: zelm = true; if (elm.noteType==0) { tick = elm.parent.parent.tick; info = noteName[(elm.pitch % 12)]; } else { tick = elm.parent.parent.parent.tick + " *"; // grace note info = noteName[(elm.pitch % 12)] + " *"; } break; case Element.REST: zelm = true; tick = elm.parent.tick; info = elm.duration.str; break; case Element.ARTICULATION: info = elm.symbol; zelm = false; if (info==2652) { info = "Down bow"; tick = elm.parent.parent.tick; zelm = true; } else if (info==2677) { info = "Up bow"; tick = elm.parent.parent.tick; zelm = true; } break; case Element.STAFF_TEXT: info = elm.text; zelm = (info == "pizz." || info == "arco"); if (zelm) tick = elm.parent.tick; break; case Element.BREATH: zelm = true; tick = elm.parent.tick; info = elm.symbol; break; case Element.TIE: case Element.SLUR: zelm = true; zsys = true; tick = ""; info = ""; break; default: zelm = false; } if (zelm) { ++ix; tinfo += ""; } } curScore.selection.clear(); tinfo += "
 index  Track  Element Name  SegTick " tinfo += " Details  ^Parent^   ^^Parent^^ 
" + ix + " "; tinfo += "" + elm.track; tinfo += " " + elm.name + " "; tinfo += "" + tick + " "; tinfo += " " + info + " "; if (zsys) tinfo += " System "; else { tinfo += " " + elm.parent.name + " "; tinfo += " " + elm.parent.parent.name + " "; } tinfo += "
"; popInfo.text = tinfo; } // ======================================================================================================================= function mapBowTick() { var ix; var ibow; var tick; var info; var elm; var etyp; if (inpMapType.currentIndex==2) infoBow.visible = true; cmd('select-all') var selected = curScore.selection.elements; mTick.length = 0; mBow.length = 0; ix = -1; ibow = 1; for (var ee in selected) { elm = selected[ee]; if (elm.track > 0) break; etyp = elm.type; switch (etyp) { case Element.NOTE: if (elm.noteType==0) { ix++; mTick.push(tick = elm.parent.parent.tick); mBow.push(ibow); if (ibow<3) ibow = 3-ibow; } break; case Element.REST: ix++; mTick.push(elm.parent.tick); mBow.push(9); ibow = 1; break; case Element.ARTICULATION: info = elm.symbol; if (info==2652) { mBow[ix]=1; ibow = 1; } else if (info==2677) { mBow[ix]=2; ibow = 2; } break; case Element.STAFF_TEXT: info = elm.text; if (info=="pizz.") { ibow = 3; } else if (info=="arco") { ibow = 1; } break; case Element.BREATH: tick = elm.parent.tick; break; case Element.TIE: break; } } curScore.selection.clear(); if (inpMapType.currentIndex==2) { tinfo = ""; tinfo += "

Bow At Tick

"; tinfo += ""; tinfo += ""; for (var ee = 0; ee < mTick.length; ee++) { tinfo += ""; } tinfo += "
 SegTick  Bow 
"+mTick[ee]+" "; tinfo += ""+bowText.substring(mBow[ee],mBow[ee]+1)+" 
"; popBow.text = tinfo; } else { curScore.startCmd(); var cur = curScore.newCursor(); var tob; // text object for (var ee = 0; ee < mTick.length; ee++) { cur.rewindToTick(mTick[ee]); tob = newElement(Element.STAFF_TEXT); tob.text = bowText.substring(mBow[ee],mBow[ee]+1); tob.color = "#0000D0"; tob.placement = Placement.BELOW; tob.align = 0; tob.fontFace = "FreeSans"; // tob.offsetX = 0.5; // tob.offsetY = 5; tob.fontSize = 10; tob.fontStyle = 0; // 0:Normal, 1:Bold tob.autoplace = true; cur.add(tob); } curScore.endCmd(); } } // ======================================================================================================================= function mapScore() { console.time("Process"); switch (inpMapType.currentIndex) { case 0: mapAll(); break; case 1: mapBow(); break; case 2: case 3: mapBowTick(); break; default: tinfo = "Unknown processing option!"; } tinfo = ""; console.timeEnd("Process"); } // ======================================================================================================================= onRun: {} width: 300; height: 50; RowLayout { id: uiRow1 x: 15; y:15 Label { id: lblRow2 Layout.preferredWidth: 50 color: "#000000" text: "Process" } ComboBox { id: inpMapType model: ["Map all elements", "Map bowing elements", "Map bow @ tick", "Add bow text to score"] Layout.leftMargin: 0 Layout.preferredWidth: 175 currentIndex: 0 } Button { id: btnMapIt Layout.leftMargin: 0 Layout.preferredWidth: 40 Layout.preferredHeight: 24 text: "Go" onClicked: mapScore(); } } ApplicationWindow { id: infoWin x: 20; y: 50 width: 550; height: 900 title: "Score Map" visible: false TextArea { id: popInfo width: infoWin.width; height: infoWin.height textMargin: 15 textFormat: TextEdit.RichText readOnly: true wrapMode: TextEdit.Wrap text: "Processing..." } } ApplicationWindow { id: infoBow x: 20; y: 50 width: 250; height: 900 title: "Bowing" visible: false TextArea { id: popBow width: infoBow.width; height: infoBow.height textMargin: 15 textFormat: TextEdit.RichText readOnly: true wrapMode: TextEdit.Wrap text: "Processing..." } } }