Skip to content
Snippets Groups Projects
Ukulele.qml 5 KiB
Newer Older
/** This file is part of Nootka (http://nootka.sf.net)               *
 * Copyright (C) 2021 by Tomasz Bojczuk (seelook@gmail.com)          *
 * on the terms of GNU GPLv3 license (http://www.gnu.org/licenses)   */

SeeLook's avatar
SeeLook committed
import Nootka 1.0
import QtGraphicalEffects 1.0
SeeLook's avatar
SeeLook committed
import QtQuick 2.12
SeeLook's avatar
SeeLook committed
TguitarBg {
    id: instrItem
SeeLook's avatar
SeeLook committed
    // private
    property var correctAnim: null
    property var guitarZoom: null
SeeLook's avatar
SeeLook committed
    width: Math.max(nootkaWindow.width, GLOB.instrument.getItemHeight(nootkaWindow.height) * 5.4)
    height: GLOB.instrument.getItemHeight(nootkaWindow.shortEdge)
    transformOrigin: Item.TopLeft
SeeLook's avatar
SeeLook committed
    onCorrectInstrument: {
        if (!correctAnim)
            correctAnim = Qt.createComponent("qrc:/exam/CorrectInstrAnim.qml").createObject(instrItem);

        correctAnim.doCross = wrongItem === null;
        correctAnim.start();
    }
    Component.onCompleted: {
        if (NOO.isAndroid() && NOO.fingerPixels() * 4 > height)
            guitarZoom = Qt.createComponent("qrc:/instruments/InstrumentZoom.qml").createObject(instrItem);

    }
    onWantNoteName: {
        if (!extraName) {
            extraName = Qt.createComponent("qrc:/instruments/ExtraName.qml").createObject(instrItem);
            extraName.fSize = Qt.binding(function() {
                return instrItem.height * 0.25;
            });
        }
        if (origin) {
            extraName.text = name;
            extraName.x = Qt.binding(function() {
                return origin.x + (origin.width - extraName.width) / 2;
            });
            extraName.y = Qt.binding(function() {
                return origin.y - extraName.height * 0.4 + (origin.y > height / 2 ? -stringsGap : origin.height + stringsGap);
            });
        } else {
            extraName.text = "";
        }
    }

    Item {
        parent: nootkaWindow.contentItem
        width: instrFlick.width
        height: instrFlick.height
        y: instrFlick.y
        x: -instrFlick.contentX
        transformOrigin: Item.TopLeft
        scale: instrItem.scale

        // body
        Image {
            cache: false
            source: NOO.pix("body-ukulele")
            height: parent.height * 5
            width: height * (sourceSize.width / sourceSize.height)
            x: xiiFret
            y: parent.height - height * 0.67
        }

        // strings shadow over body
        Repeater {
            model: 4

            Rectangle {
                x: fbRect.x + fbRect.width
                y: fbRect.y + stringsGap / 2 + index * stringsGap + 2.5 * height
                width: parent.width - x - stringsGap * 0.8
                height: strWidth(index)
                color: "#201c1c1c"
            }

        }

        Image {
            cache: false
            source: NOO.pix("rosette-ukulele")
            x: fbRect.width + height * 0.5
            y: parent.height - fbRect.height * parent.scale
            width: fbRect.height
            height: fbRect.height
        }

    }

    Rectangle {
        id: finger

        color: GLOB.fingerColor
        width: fretWidth / 1.6
        height: width * 0.65
        radius: width * 0.5
        x: fingerPos.x
        y: fingerPos.y
        visible: false
SeeLook's avatar
SeeLook committed

    DropShadow {
        id: fingerShadow

        z: 5
        anchors.fill: finger
        horizontalOffset: finger.height / 6
        verticalOffset: finger.height / 6
        color: "black"
        radius: NOO.factor() / 3
        source: finger
        visible: fingerPos.x > 0 && active
        scale: !pressed && active && fingerPos.x > 0 ? 1 : 0

        Behavior on scale {
            enabled: GLOB.useAnimations

            NumberAnimation {
                duration: 150
            }

        }

SeeLook's avatar
SeeLook committed

    // string highlight
    Rectangle {
        z: 5
        color: finger.color
        width: parent.width - stringsGap - 2
        height: string < 6 ? strWidth(string) * 1.75 : 0
        x: 1
        y: string < 6 ? fbRect.y + stringsGap / 2 + string * stringsGap - height / 2 : 0
        visible: !pressed && active && string < 6 && fingerPos.x == 0
SeeLook's avatar
SeeLook committed

    Connections {
        target: instrFlick
        enabled: !NOO.isAndroid()
        function onMovementEnded() : void { instrument.pressedAt(0, 0) }
SeeLook's avatar
SeeLook committed
    MouseArea {
        property point startPos: Qt.point(0, 0)

        enabled: NOO.isAndroid() && (NOO.fingerPixels() * 4 <= height) || (guitarZoom && instrItem.scale > 1)
        width: parent.width
        height: parent.height
        onPressed: startPos = Qt.point(mouseX, mouseY)
        onReleased: {
            var dx = mouseX - startPos.x;
            var dy = mouseY - startPos.y;
            if (Math.sqrt(dx * dx + dy * dy) < fretWidth / 2)
                pressedAt(mouse.x, mouse.y);
SeeLook's avatar
SeeLook committed
        }
SeeLook's avatar
SeeLook committed

    OutScaleTip {
        show: !active && outOfScale
    }

    Behavior on scale {
        enabled: GLOB.useAnimations

        NumberAnimation {
            duration: 150
            onRunningChanged: {
                if (guitarZoom && !running && scale > 1)
                    instrFlick.contentX = guitarZoom.flickX;

            }
        }

    }