diff --git a/src/activities/piano_composition/Note.qml b/src/activities/piano_composition/Note.qml index ce6ea0d1e..5c1e86862 100644 --- a/src/activities/piano_composition/Note.qml +++ b/src/activities/piano_composition/Note.qml @@ -1,122 +1,122 @@ /* GCompris - Note.qml * * Copyright (C) 2016 Johnny Jazeix * * Authors: * Beth Hadley (GTK+ version) * Johnny Jazeix (Qt Quick port) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import QtQuick 2.6 import QtGraphicalEffects 1.0 import GCompris 1.0 import "../../core" Item { id: note property string value property bool noteIsColored: true property int type: wholeNote property string noteType: type == wholeNote ? "whole" : type == halfNote ? "half" : type == quarterNote ? "quarter" : type == eighthNote ? "eighth" : "" property string blackType: "" // empty, "flat" or "sharp" //width: noteImage.width //height: noteImage.height readonly property int wholeNote: 1 readonly property int halfNote: 2 readonly property int quarterNote: 4 readonly property int eighthNote: 8 readonly property int noteDuration: 2000 / type property var noteColorMap: { "1": "#FF0000", "2": "#FF7F00", "3": "#FFFF00", "4": "#32CD32", "5": "#6495ED", "6": "#D02090", "7": "#FF1493", "8": "#FF0000", "9": "#FF7F00", "10": "#FFFF00", "11": "#32CD32", "-1": "#FF6347", "-2": "#FFD700", "-3": "#20B2AA", "-4": "#8A2BE2", "-5": "#FF00FF" } property var whiteNoteName: { "1": qsTr("C"), "2": qsTr("D"), "3": qsTr("E"), "4": qsTr("F"), "5": qsTr("G"), "6": qsTr("A"), "7": qsTr("B"), "8": qsTr("C") } property var blackNoteName: blackType == "flat" ? flatNoteName : sharpNoteName property var sharpNoteName: { "-1": qsTr("C#"), "-2": qsTr("D#"), "-3": qsTr("F#"), "-4": qsTr("G#"), "-5": qsTr("A#")} property var flatNoteName: { "-1": qsTr("Db"), "-2": qsTr("Eb"), "-3": qsTr("Gb"), "-4": qsTr("Ab"), "-5": qsTr("Bb")} property bool highlightWhenPlayed: false property alias highlightTimer: highlightTimer Image { id: blackTypeImage source: blackType !== "" ? "qrc:/gcompris/src/activities/piano_composition/resource/black" + blackType + ".svg" : "" visible: value[0] === '-' - sourceSize.width: noteImage.width/2.5 + sourceSize.width: noteImage.width / 2.5 anchors.right: noteImage.left - anchors.rightMargin: -width/2 + anchors.rightMargin: -width / 2 anchors.bottom: noteImage.bottom - anchors.bottomMargin: -height/2 + anchors.bottomMargin: height / 2 fillMode: Image.PreserveAspectFit } Image { id: highlightImage source: "qrc:/gcompris/src/activities/piano_composition/resource/note_highlight.png" visible: false sourceSize.width: noteImage.width height: noteImage.height / 2 anchors.bottom: noteImage.bottom } Rectangle { id: highlightRectangle width: noteImage.width * 0.9 height: noteImage.height * 0.9 color: "red" opacity: 0.6 border.color: "white" radius: width / 6 visible: false } Image { id: noteImage source: "qrc:/gcompris/src/activities/piano_composition/resource/" + noteType + "-note.svg" sourceSize.width: 200 width: note.width height: note.height } // If the result is not good enough maybe have a rectangle and use opacity mask with a note ColorOverlay { anchors.fill: noteImage source: noteImage color: noteColorMap[value] // make image like it lays under red glass visible: noteIsColored } Timer { id: highlightTimer interval: noteDuration onRunningChanged: { highlightRectangle.visible = running // highlightImage.visible = running } } } diff --git a/src/activities/piano_composition/Staff.qml b/src/activities/piano_composition/Staff.qml index 3f964e4d1..3333656f9 100644 --- a/src/activities/piano_composition/Staff.qml +++ b/src/activities/piano_composition/Staff.qml @@ -1,205 +1,201 @@ /* GCompris - Staff.qml * * Copyright (C) 2016 Johnny Jazeix * * Authors: * Beth Hadley (GTK+ version) * Johnny Jazeix (Qt Quick port) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import QtQuick 2.6 import GCompris 1.0 import "../../core" Item { id: staff property Item main: activity.main property int verticalDistanceBetweenLines: height / nbLines // todo width/nbLines * smth property string clef width: 400 height: 100 // Stave property int nbLines: 5 property bool lastPartition: false property bool isMetronomeDisplayed: false property bool showMetronome: false property alias notes: notes property int firstNoteX: defaultFirstNoteX property int defaultFirstNoteX: clefImage.width property int nbMaxNotesPerStaff property bool noteIsColored property alias notesRepeater: notesRepeater Image { id: clefImage source: clef ? "qrc:/gcompris/src/activities/piano_composition/resource/" + clef + "Clef.svg" : "" sourceSize.width: (nbLines - 2) * verticalDistanceBetweenLines } Repeater { model: nbLines Rectangle { width: staff.width height: 5 border.width: 5 color: "black" x: 0 y: index * verticalDistanceBetweenLines } } Rectangle { width: 5 border.width: 5 height: (nbLines - 1) * verticalDistanceBetweenLines + 5 color: "black" x: staff.width y: 0 } // end of partition line Rectangle { width: 5 border.width: 5 height: (nbLines - 1) * verticalDistanceBetweenLines + 5 visible: lastPartition color: "black" x: staff.width - 10 y: 0 } ListModel { id: notes } Rectangle { id: metronome width: 5 border.width: 10 height: (nbLines - 1) * verticalDistanceBetweenLines + 5 visible: isMetronomeDisplayed && showMetronome color: "red" x: firstNoteX - width/2 y: 0 Behavior on x { SmoothedAnimation { id: metronomeAnimation duration: -1 } } } property var mDuration function initMetronome() { var staffDuration = 0; for(var v = 0 ; v < notes.count ; ++ v) { staffDuration += notes.get(v).mDuration; } metronomeAnimation.velocity = 1; mDuration = staffDuration; metronome.x = staff.width; print("total duration " + staffDuration) print("total distance " + metronome.x) } function addNote(newValue_, newType_, newBlackType_, highlightWhenPlayed_) { var duration if(newType_ == 1) duration = 2000/newType_ else if(newType_ == 2) duration = 3000/newType_ else if(newType_ == 4) duration = 4000/newType_ else duration = 6500/newType_ notes.append({"mValue": newValue_, "mType": newType_, "mBlackType": newBlackType_, "mDuration": duration, "mHighlightWhenPlayed": highlightWhenPlayed_}); } function playNote(noteId) { metronomeAnimation.velocity = staff.width * 1000 / (notes.get(noteId).mDuration * notes.count); print("velocity " + metronomeAnimation.velocity) } function eraseAllNotes() { notes.clear(); } property int noteWidth: (staff.width - 10 - clefImage.width) / 10 Row { id: notesRow x: firstNoteX - noteWidth/2 Repeater { id: notesRepeater model: notes Note { value: mValue type: mType blackType: mBlackType highlightWhenPlayed: mHighlightWhenPlayed noteIsColored: staff.noteIsColored width: (notes.count == 1 && items.staffLength === "long") ? Math.min(items.background.width,items.background.height) * 0.1 : noteWidth height: staff.height MouseArea { anchors.fill: parent onClicked: { print(items.staffLength) print(items.background.width,items.background.height) } } function play() { // if(highlightWhenPlayed) { highlightTimer.start(); // } } y: { - var shift = 0; + var shift = 0 if(clef === "bass") { - shift = -3 * verticalDistanceBetweenLines + shift = -2.5 * verticalDistanceBetweenLines } if(blackType !== "") { if(blackType === "flat") { shift += - verticalDistanceBetweenLines } else { shift += - verticalDistanceBetweenLines / 2 } } - if(mValue > 0) { - return (nbLines - 2) * verticalDistanceBetweenLines - (parseInt(mValue) - 1) * verticalDistanceBetweenLines/2 + shift - } - else if(mValue >= -2) - return (nbLines - 3) * verticalDistanceBetweenLines - (Math.abs(parseInt(mValue)) - 1) * verticalDistanceBetweenLines/2 + shift + if(mValue >= -2) + return (nbLines - 3) * verticalDistanceBetweenLines - (Math.abs(parseInt(mValue)) - 1) * verticalDistanceBetweenLines / 2 + shift else - return (nbLines - 3) * verticalDistanceBetweenLines - (Math.abs(parseInt(mValue))) * verticalDistanceBetweenLines/2 + shift + return (nbLines - 3) * verticalDistanceBetweenLines - (Math.abs(parseInt(mValue))) * verticalDistanceBetweenLines / 2 + shift } } } - spacing: 0 } }