/*
* Copyright (C) 2021 sammik
* https://github.com/sammik/musescore-plugin-colornotes-hooktheory
* AGPL 3
*
* based on Musescore Colornotes Plugin https://github.com/musescore/MuseScore/blob/master/share/plugins/colornotes.qml
*
*/
import QtQuick 2.6
import QtQuick.Controls 2.2
import MuseScore 3.0
import QtQuick.Window 2.2
MuseScore {
version: "1.1"
description: qsTr("This plugin colors notes in the selection depending on their pitch in Hooktheory Hookpad style")
menuPath: "Plugins.Color Notes - Hooktheory - pitch based"
requiresScore: false
readonly property var colors : [ // "#rrggbb" with rr, gg, and bb being the hex values for red, green, and blue, respectively
"#ff0000", // I.
"#ffb014", // II.
"#efe600", // III.
"#00d300", // IV.
"#4800ff", // V.
"#b800e5", // VI.
"#ff00cb" // VII.
]
readonly property string black : "#000000"
readonly property string gray : "#333333"
readonly property var scale : [0, , 1, , 2, 3, , 4, , 5, , 6]
readonly property var modus : [0, 2, 4, 5, 7, 9, 11]
property var modalIndex : modalBox.currentIndex
property var tonalCenter : tonalBox.currentIndex
// Apply the given function to all notes (elements with pitch) in selection
// or, if nothing, or just single element is selected, in the entire score
function applyToNotesInSelection(func, restore) {
if (!curScore)
return
var fullScore = !(curScore.selection.elements.length > 1)
if (fullScore) {
cmd("select-all")
curScore.startCmd()
}
for (var i in curScore.selection.elements)
if (curScore.selection.elements[i].pitch)
func(curScore.selection.elements[i], restore)
if (fullScore) {
curScore.endCmd()
cmd("escape")
}
}
function colorNote(note, restore) {
console.log(note.pitch, ((note.pitch + modus[modalIndex]) % 12), ((scale[(note.pitch + modus[modalIndex] + 12 - tonalCenter) % 12] + 7 - modalIndex) % 7));
var color = (!restore) ? colors[(scale[(note.pitch + modus[modalIndex] + 12 - tonalCenter) % 12] + (modCenter.checkState == Qt.Checked ? (7 - modalIndex) : 0)) % 7] || gray : black;
//var color = (!restore) ? colors[scale[(note.pitch + modus[modalIndex] + 12 - tonalCenter) % 12]] || gray : black;
note.color = color;
if (note.accidental) {
note.accidental.color = color;
}
if (note.dots) {
for (var i = 0; i < note.dots.length; i++) {
if (note.dots[i]) {
note.dots[i].color = color;
}
}
}
}
onRun: {
console.log("hello hookstyle colornotes");
window.visible = true
}
Window {
id : window
width : 200;
height : 400
visible: true
Label {
id: label
width: column.width
topPadding : 6
wrapMode : Text.WordWrap
text : qsTr("Colorize notes in style of 'hooktheory.com', based on note pitch.")
anchors.horizontalCenter : parent.horizontalCenter
}
Column {
id: column
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: label.bottom
spacing : 6
topPadding : 6
Label {
font.pointSize : 12
text : qsTr("Select tonal center")
}
ComboBox {
width: parent.width
id: tonalBox
model: ["C", "C# / Db", "D", "D#/Eb", "E", "F", "F#/Gb", "G", "G#/Ab", "A", "A#/Bb", "B"]
}
CheckBox {
id: modCenter
text: "Modus base center"
}
ToolSeparator {
width: parent.width
orientation: Qt.Horizontal
}
Label {
font.pointSize : 12
text : qsTr("Select modus")
}
ComboBox {
width: parent.width
id: modalBox
model: ["Major", "Dorian", "Phrygian", "Lydian", "Mixolydian", "Minor", "Locrian"]
}
Button {
id: colorize
width: parent.width
text: "Apply colors"
onClicked: applyToNotesInSelection(colorNote)
}
ToolSeparator {
width: parent.width
orientation: Qt.Horizontal
}
Button {
id: restore
width: parent.width
text: "Remove colors"
onClicked: applyToNotesInSelection(colorNote, true)
}
}
onClosing: Qt.quit()
}
}