diff --git a/src/activities/photo_hunter/Observe.qml b/src/activities/photo_hunter/Observe.qml index 4e3350ad9..217afe874 100644 --- a/src/activities/photo_hunter/Observe.qml +++ b/src/activities/photo_hunter/Observe.qml @@ -1,162 +1,181 @@ /* GCompris - Observe.qml * * Copyright (C) 2016 Stefan Toncu * * Authors: * (GTK+ version) * Stefan Toncu (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.1 import GCompris 1.0 import "../../core" import "photo_hunter.js" as Activity Image { id: card + sourceSize.width: background.startedHelp ? background.width : background.vert ? undefined : (background.width - 30) / 2 + sourceSize.height: background.startedHelp ? background.height - background.barHeight * 1.3 - frame.problemTextHeight - slider.height : background.vert ? + (background.height - background.barHeight - 40 - frame.problemTextHeight) / 2 : + background.height - background.barHeight - 30 - frame.problemTextHeight + property GCAudio audioEffects: activity.audioEffects property alias repeater: repeater property alias circleRepeater: circleRepeater property int good: 0 property bool show: false + Behavior on anchors.horizontalCenterOffset { + NumberAnimation { + duration: 1000 + easing.type: Easing.InOutQuad + } + } + Image { id: wrong source: Activity.url + "wrong.svg" width: 70 height: 70 opacity: 0 } NumberAnimation { id: wrongAnim target: wrong property: "opacity" from: 0 to: 1 duration: 400 } NumberAnimation { id: wrongAnim2 target: wrong property: "opacity" from: 1 to: 0 duration: 400 } MouseArea { id: big anchors.fill: parent + enabled: !background.startedHelp onClicked: { audioEffects.play('qrc:/gcompris/src/core/resource/sounds/brick.wav') wrongAnim.start() wrong.x = mouseX - wrong.width/2 wrong.y = mouseY - wrong.height/2 wrongAnim2.start() } } Repeater { id: repeater model: items.model Image { id: photo property alias particleLoader: particleLoader property alias differenceAnimation: differenceAnimation - property double widthScale - property double heightScale + property double widthScale: Activity.dataset[Activity.currentLevel].coordinates[index].w + property double heightScale: Activity.dataset[Activity.currentLevel].coordinates[index].h + + sourceSize.width: Activity.dataset[Activity.currentLevel].coordinates[index].r * 200 + sourceSize.height: Activity.dataset[Activity.currentLevel].coordinates[index].r * 200 width: card.width / 10 * widthScale height: card.height / 10 * heightScale - opacity: 1 + source: Activity.url + "photo" + (Activity.currentLevel + 1) + "_" + (index + 1) + ".svg" + opacity: card.show ? 1 : 0 x: modelData[0] * card.width / 1200 y: modelData[1] * card.height / 1700 NumberAnimation { id: differenceAnimation target: photo property: "opacity" from: 0 to: 1 duration: 500 } // Create a particle only for the strawberry Loader { id: particleLoader anchors.fill: parent active: true sourceComponent: particle } Component { id: particle ParticleSystemStarLoader { id: particles clip: false } } MouseArea { id: mouseArea anchors.centerIn: parent width: parent.width * 3 height: parent.height * 3 + enabled: !background.startedHelp onClicked: { Activity.photoClicked(card,index) audioEffects.play('qrc:/gcompris/src/core/resource/sounds/bleep.wav') } } } } Repeater { id: circleRepeater model: card.repeater.model Rectangle { id: circle color: "transparent" radius: width * 0.5 border.color: card.show ? "blue" : "red" border.width: 6 opacity: 0 - x: card.repeater.itemAt(index).x - width / 6 - y: card.repeater.itemAt(index).y - height / 6 - width: card.repeater.itemAt(index).width * 1.5 - height: card.repeater.itemAt(index).height * 1.5 + x: itemAt.x - width / 6 + y: itemAt.y - height / 6 + width: itemAt.width * 1.5 + height: itemAt.height * 1.5 property alias scaleAnim: scaleAnim + property var itemAt: card.repeater.itemAt(index) ? card.repeater.itemAt(index) : card NumberAnimation { id: scaleAnim target: circle property: "scale" from: 0 to: circle.scale duration: 700 } } } } diff --git a/src/activities/photo_hunter/PhotoHunter.qml b/src/activities/photo_hunter/PhotoHunter.qml index c4ad40505..45b4ab372 100644 --- a/src/activities/photo_hunter/PhotoHunter.qml +++ b/src/activities/photo_hunter/PhotoHunter.qml @@ -1,191 +1,289 @@ /* GCompris - PhotoHunter.qml * * Copyright (C) 2016 Stefan Toncu * * Authors: * (GTK+ version) * Stefan Toncu (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.1 import GCompris 1.0 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 import "../../core" import "photo_hunter.js" as Activity ActivityBase { id: activity onStart: focus = true onStop: {} pageComponent: Rectangle { id: background anchors.fill: parent color: "white" signal start signal stop Component.onCompleted: { activity.start.connect(start) activity.stop.connect(stop) } // Add here the QML items you need to access in javascript QtObject { id: items property Item main: activity.main property alias background: background property alias bar: bar property alias bonus: bonus property var model property bool notShowed: true property alias img1: img1 property alias img2: img2 + property alias helpButton: helpButton property int total property int totalFound: img1.good + img2.good property alias problem: problem property alias frame: frame + property int helpPressed: 0 property int barHeightAddon: ApplicationSettings.isBarHidden ? 1 : 3 property int cellSize: Math.min(background.width / 11 , background.height / (9 + barHeightAddon)) } onStart: { Activity.start(items) } onStop: { Activity.stop() } property bool vert: background.width < background.height property double barHeight: (items.barHeightAddon == 1) ? 0 : bar.height + property bool startedHelp: false function checkAnswer() { if (items.totalFound === items.model.length) { bonus.good("flower") + // after completing a level, mark the problem as shown + if (items.notShowed) { + items.notShowed = false + } + //remove the problem from the board after first level - if (problem.opacity != 0) { + if (problem.z > 0) Activity.hideProblem() - } } } Rectangle { id: problem width: parent.width height: problemText.height anchors.top: parent.top anchors.topMargin: 10 border.width: 2 border.color: "black" color: "red" + z: 5 property alias problemText: problemText GCText { id: problemText anchors.centerIn: parent width: parent.width * 3 / 4 fontSize: mediumSize wrapMode: Text.WordWrap horizontalAlignment: Text.AlignHCenter - text: qsTr("Click on the differences between the two images!") + text: background.startedHelp ? qsTr("Drag the slider to show the differences!") : + qsTr("Click on the differences between the two images!") color: "white" + onHeightChanged: { + if (!items.notShowed || !helpButton.notPressed) { + frame.problemTextHeight = problemText.height + print("GCText height changed to: ",frame.problemTextHeight) + } + } } MouseArea { anchors.fill: parent onClicked: Activity.hideProblem() } } Rectangle { id: frame color: "transparent" width: background.vert ? img1.width : parent.width - 20 height: parent.height - background.barHeight - 30 anchors.top: problem.bottom anchors.horizontalCenter: parent.horizontalCenter anchors.margins: 10 + property real problemTextHeight: problemText.height + //left/top image Observe { id: img1 - sourceSize.width: background.vert ? undefined : (background.width - 30 - problemText.height) / 2 - sourceSize.height: background.vert ? - (background.height - background.barHeight - 40 - problemText.height) /2 : - background.height - background.barHeight - 30 show: true anchors { top: parent.top horizontalCenter: parent.horizontalCenter - horizontalCenterOffset: background.vert ? 0 : -img1.width/2-5 + horizontalCenterOffset: background.startedHelp ? 0 : background.vert ? 0 : - img1.width/2 - 5 } } //right/bottom image Observe { id: img2 - sourceSize.width: background.vert ? undefined : (background.width - 30 - problemText.height) / 2 - sourceSize.height: background.vert ? - (background.height - background.barHeight - 40 - problemText.height) /2 : - background.height - background.barHeight - 30 + opacity: background.startedHelp ? 1 - slider.value : 1 show: false anchors { - top: background.vert ? img1.bottom : parent.top - topMargin: background.vert ? 10 : 0 - left: background.vert ? img1.left : img1.right - leftMargin: background.vert ? 0 : 10 + top: background.startedHelp ? img1.top : background.vert ? img1.bottom : parent.top + topMargin: background.startedHelp ? 0 : background.vert ? 10 : 0 + horizontalCenter: parent.horizontalCenter + horizontalCenterOffset: background.startedHelp ? 0 : background.vert ? 0 : img1.width/2 + 5 + } + } + + Slider { + id: slider + value: 0 + height: 50 + width: img1.width * 0.9 + z: background.startedHelp ? 5 : -5 + opacity: background.startedHelp ? 1 : 0 + enabled: background.startedHelp + + style: SliderStyle { + handle: Rectangle { + height: background.vert ? 80 : 70 + width: height + radius: width / 2 + color: "lightblue" + } + + groove: Rectangle { + implicitHeight: slider.height + implicitWidth: background.vert ? slider.width * 0.85 : slider.width + radius: height / 2 + border.color: "#6699ff" + color: "#99bbff" + + Rectangle { + height: parent.height + width: styleData.handlePosition + implicitHeight: 6 + implicitWidth: 100 + radius: height/2 + color: "#4d88ff" + } + } + } + + anchors { + top: img1.bottom + topMargin: 20 + horizontalCenter: img1.horizontalCenter + } + } + } + + //help button + Image { + id: helpButton + source: Activity.url + "help.svg" + sourceSize.height: background.vert ? bar.height * 0.7 : bar.height * 0.9 + fillMode: Image.PreserveAspectFit + anchors { + bottom: background.vert ? bar.top : bar.bottom + bottomMargin: 10 + left: background.vert ? parent.left : bar.right + leftMargin: background.vert || ApplicationSettings.isBarHidden ? 10 : bar.width * 3.55 + } + + property bool notPressed: true + + MouseArea { + id: mouseArea + anchors.fill: parent + enabled: items.helpPressed < 2 ? true : false + onClicked: { + background.startedHelp = !background.startedHelp + + if (!background.startedHelp) + items.helpPressed ++ + + if (!background.startedHelp && items.helpPressed < 2) + helpButton.opacity = 1 + else + helpButton.opacity = 0.6 + + if (helpButton.notPressed) { + items.frame.anchors.top = items.problem.bottom + items.problem.z = 5 + frame.problemTextHeight = problemText.height + helpButton.notPressed = false + } else if (!items.notShowed) + Activity.hideProblem() + + slider.value = 0 + } } } DialogHelp { id: dialogHelp onClose: home() } Bar { id: bar content: BarEnumContent { value: help | home | level } onHelpClicked: { displayDialog(dialogHelp) } onPreviousLevelClicked: Activity.previousLevel() onNextLevelClicked: Activity.nextLevel() onHomeClicked: activity.home() } Bonus { id: bonus Component.onCompleted: win.connect(Activity.nextLevel) } Score { anchors { bottom: parent.bottom bottomMargin: 10 * ApplicationInfo.ratio right: parent.right rightMargin: 10 * ApplicationInfo.ratio top: undefined left: undefined } numberOfSubLevels: items.total currentSubLevel: items.totalFound } } } diff --git a/src/activities/photo_hunter/photo_hunter.js b/src/activities/photo_hunter/photo_hunter.js index e038a9311..2109f9795 100644 --- a/src/activities/photo_hunter/photo_hunter.js +++ b/src/activities/photo_hunter/photo_hunter.js @@ -1,207 +1,185 @@ /* GCompris - photo_hunter.js * * Copyright (C) 2016 Stefan Toncu * * Authors: * (GTK+ version) * Stefan Toncu (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 . */ .pragma library .import QtQuick 2.0 as Quick var currentLevel = 0 var items var url = "qrc:/gcompris/src/activities/photo_hunter/resource/" var dataset = [ { "coordinates": [{x: 12, y:5, r: 0.5, w: 1.25, h: 1.25}, {x: 75, y:1170, r: 0.5, w: 0.35, h: 0.4}, {x: 343, y:1375, r: 1, w: 0.9, h: 0.9}] }, { "coordinates": [{x: 949.5, y:268.5, r: 0.7, w: 0.85, h: 0.92}, {x: 915, y:1555, r: 0.7, w: 0.75, h: 0.6}, {x: 510, y:1300, r: 1.7, w: 1.25, h: 2}] }, { "coordinates": [{x: 800, y:40, r: 1.8, w: 2.6, h: 1}, {x: 593, y:1450, r: 0.5, w: 0.8, h: 0.65}] }, { "coordinates": [{x: 975, y:140, r: 0.2, w: 0.3, h: 0.3}, {x: 680, y:720, r: 0.25, w: 0.3, h: 0.4}, {x: 570, y:1580, r: 1.3, w: 1.3, h: 0.6}, {x: 220, y:650, r: 0.7, w: 1, h: 1}] }, { "coordinates": [{x: 540, y:200, r: 0.25, w: 0.5, h: 0.5}, {x: 335, y:1228, r: 1, w: 0.25, h: 0.25}, {x: 600, y:1150, r: 0.25, w: 0.5, h: 0.5}, {x: 680, y:1330, r: 1, w: 1.3, h: 0.6}] }, { "coordinates": [{x: 130, y: 450, r: 1, w: 1.5, h: 1.5}, {x: 825, y: 234, r: 0.7, w: 0.8, h: 0.8}, {x: 950, y: 1450, r: 0.7, w: 1, h: 1}] }, { "coordinates": [{x: 70, y: 600, r: 1, w: 1.6, h: 0.8}, {x: 950, y: 1120, r: 1, w: 1.3, h: 0.45}, {x: 380, y: 815, r: 1, w: 0.3, h: 0.41}] }, { "coordinates": [{x: 445, y: 1135, r: 0.5, w: 0.8, h: 0.3}, {x: 17, y: 1300, r: 0.5, w: 0.6, h: 0.6}, {x: 782, y: 670, r: 0.75, w: 0.8, h: 0.8}, {x: 98, y: 1002, r: 0.5, w: 0.85, h: 0.3}, {x: 527, y: 415, r: 0.15, w: 0.178, h: 0.25}, {x: 337, y: 725, r: 0.15, w: 0.25, h: 0.25}] }, { "coordinates": [{x: 275, y: 345, r: 0.15, w: 0.25, h: 0.25}, {x: 1013, y: 1322, r: 0.15, w: 0.25, h: 0.25}, {x: 595, y: 1530, r: 0.7, w: 1, h: 0.15}] }, { "coordinates": [{x: 565, y:1120, r: 0.35, w: 0.6, h: 0.55}, {x: 595, y:1500, r: 0.35, w: 0.6, h: 0.55}, {x: 680, y:433, r: 0.5, w: 0.6, h: 0.8}, {x: 760, y:971, r: 0.5, w: 0.35, h: 0.6}] } ] var numberOfLevel = dataset.length function start(items_) { items = items_ currentLevel = 0 initLevel() } function stop() { } function initLevel() { items.bar.level = currentLevel + 1 setUp() } function setUp() { - if (items.notShowed === true) { - items.notShowed = false - } - else hideProblem() - loadCoordinate() - for (var i=0;i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Openclipart + + + Help button + 2011-01-22T01:26:55 + Help button, in the shape of a Staples "Easy" button. + https://openclipart.org/detail/109645/help-button-by-jhnri4 + + + jhnri4 + + + + + button + help + how i did it + red + + + + + + + + + + +