2023-06-19 13:29:46 +00:00
|
|
|
// Copyright (C) 2023 The Qt Company Ltd.
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
|
|
|
import QtQuick
|
|
|
|
import QtQuick.Window
|
|
|
|
import QtQuick.Controls
|
|
|
|
import QtQuick.Controls.Material
|
|
|
|
import QtQuick.Layouts
|
2023-08-17 03:49:16 +00:00
|
|
|
import QtSensors
|
2023-06-19 13:29:46 +00:00
|
|
|
|
|
|
|
ApplicationWindow {
|
|
|
|
id: root
|
|
|
|
width: 800
|
|
|
|
height: 600
|
|
|
|
visible: true
|
|
|
|
property real currDrawerWidth: drawer.width * drawer.position
|
|
|
|
|
2023-08-17 03:49:16 +00:00
|
|
|
Accelerometer {
|
|
|
|
id: accelerometer
|
|
|
|
dataRate: 25
|
|
|
|
active: true
|
2025-07-25 06:44:30 +00:00
|
|
|
readonly property vector3d force: {
|
|
|
|
let r = reading as AccelerometerReading
|
|
|
|
return Qt.vector3d(r.x, r.y, r.z)
|
|
|
|
}
|
2025-02-28 13:10:05 +00:00
|
|
|
readonly property bool highForce : Math.abs(force.length() - 9.81) > 16
|
|
|
|
|
|
|
|
onHighForceChanged: {
|
|
|
|
if (!highForce)
|
|
|
|
shakeTimeout.restart()
|
2023-08-17 03:49:16 +00:00
|
|
|
}
|
2025-02-28 13:10:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Timer {
|
|
|
|
id: shakeTimeout
|
|
|
|
interval: 200
|
|
|
|
running: false
|
|
|
|
repeat: false;
|
|
|
|
onTriggered: {
|
|
|
|
scene.rollForce = accelerometer.force.times(100.0)
|
|
|
|
scene.spawnDice()
|
2023-08-17 03:49:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-19 13:29:46 +00:00
|
|
|
Scene {
|
|
|
|
id: scene
|
2024-09-24 16:46:21 +00:00
|
|
|
width: parent.width
|
2023-06-19 13:29:46 +00:00
|
|
|
height: parent.height
|
|
|
|
|
|
|
|
settingsStaticFriction: staticFrictionSlider.value
|
|
|
|
settingsDynamicFriction: dynamicFrictionSlider.value
|
|
|
|
settingsRestitution: restitutionSlider.value
|
2025-02-28 09:30:42 +00:00
|
|
|
settingsDiceWidth: diceSize.value
|
|
|
|
settingsDiceCount: diceSlider.value
|
2025-02-28 09:56:29 +00:00
|
|
|
cameraControllerEnabled: !drawer.visible
|
2023-06-19 13:29:46 +00:00
|
|
|
|
|
|
|
Label {
|
|
|
|
id: tapLabel
|
2024-03-01 13:20:16 +00:00
|
|
|
anchors.fill: parent
|
|
|
|
padding: parent.width * 0.1
|
|
|
|
horizontalAlignment: Text.AlignHCenter
|
|
|
|
verticalAlignment: Text.AlignVCenter
|
|
|
|
fontSizeMode: Text.Fit
|
2023-06-19 13:29:46 +00:00
|
|
|
font.bold: true
|
2024-03-01 13:20:16 +00:00
|
|
|
font.pixelSize: 64
|
|
|
|
text: qsTr("Tap, click or shake to throw dice")
|
|
|
|
wrapMode: Text.NoWrap
|
2023-06-19 13:29:46 +00:00
|
|
|
style: Text.Raised
|
|
|
|
color: "white"
|
2023-12-12 11:56:40 +00:00
|
|
|
minimumPixelSize: 10
|
2025-02-28 10:10:16 +00:00
|
|
|
visible: opacity > 0
|
2023-06-19 13:29:46 +00:00
|
|
|
|
2025-02-28 10:10:16 +00:00
|
|
|
Behavior on opacity {
|
|
|
|
NumberAnimation {
|
|
|
|
duration: 300
|
|
|
|
easing.type: Easing.OutCirc
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MouseArea {
|
2025-02-28 10:10:16 +00:00
|
|
|
anchors.fill: parent
|
2023-06-19 13:29:46 +00:00
|
|
|
onClicked: {
|
2025-02-28 10:10:16 +00:00
|
|
|
tapLabel.opacity = 0
|
2025-02-28 09:30:42 +00:00
|
|
|
scene.rollForce = Qt.vector3d(0, 0, 0)
|
|
|
|
scene.spawnDice()
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function updateGravity() {
|
|
|
|
if (gravityZero.checked) {
|
2023-08-17 03:49:16 +00:00
|
|
|
scene.settingGravity = 0
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
|
|
|
if (gravityMoon.checked) {
|
2023-08-17 03:49:16 +00:00
|
|
|
scene.settingGravity = 162
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
|
|
|
if (gravityMars.checked) {
|
2023-08-17 03:49:16 +00:00
|
|
|
scene.settingGravity = 371
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
|
|
|
if (gravityEarth.checked) {
|
2023-08-17 03:49:16 +00:00
|
|
|
scene.settingGravity = 980.7
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Drawer {
|
|
|
|
id: drawer
|
|
|
|
height: root.height
|
|
|
|
width: column.width + 40
|
2024-02-20 13:24:36 +00:00
|
|
|
Flickable {
|
|
|
|
anchors.fill: parent
|
|
|
|
contentHeight: column.implicitHeight
|
|
|
|
flickableDirection: Flickable.AutoFlickIfNeeded
|
|
|
|
ScrollBar.vertical: ScrollBar {
|
|
|
|
policy: Screen.height < 600 ? ScrollBar.AlwaysOn : ScrollBar.AsNeeded
|
|
|
|
}
|
|
|
|
ColumnLayout {
|
|
|
|
id: column
|
|
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
2023-06-19 13:29:46 +00:00
|
|
|
|
2024-02-20 13:24:36 +00:00
|
|
|
// Static friction
|
2025-02-28 10:19:24 +00:00
|
|
|
Label {
|
2025-02-28 10:46:05 +00:00
|
|
|
text: qsTr("Static friction: %1").arg(staticFrictionSlider.value.toFixed(2))
|
2025-02-28 10:19:24 +00:00
|
|
|
Layout.fillWidth: true
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
2024-02-20 13:24:36 +00:00
|
|
|
Slider {
|
|
|
|
id: staticFrictionSlider
|
|
|
|
focusPolicy: Qt.NoFocus
|
|
|
|
from: 0
|
|
|
|
to: 1
|
|
|
|
value: 0.5
|
2025-02-28 10:46:05 +00:00
|
|
|
stepSize: 0.05
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
|
|
|
|
2024-02-20 13:24:36 +00:00
|
|
|
// Dynamic friction
|
2025-02-28 10:19:24 +00:00
|
|
|
Label {
|
2025-02-28 10:46:05 +00:00
|
|
|
text: qsTr("Dynamic friction: %1").arg(dynamicFrictionSlider.value.toFixed(2))
|
2025-02-28 10:19:24 +00:00
|
|
|
Layout.fillWidth: true
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
2024-02-20 13:24:36 +00:00
|
|
|
Slider {
|
|
|
|
id: dynamicFrictionSlider
|
|
|
|
focusPolicy: Qt.NoFocus
|
|
|
|
from: 0
|
|
|
|
to: 1
|
2025-02-28 15:09:06 +00:00
|
|
|
value: 0.4
|
2025-02-28 10:46:05 +00:00
|
|
|
stepSize: 0.05
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
|
|
|
|
2024-02-20 13:24:36 +00:00
|
|
|
// Restitution
|
2025-02-28 10:19:24 +00:00
|
|
|
Label {
|
2025-02-28 10:46:05 +00:00
|
|
|
text: qsTr("Restitution: %1").arg(restitutionSlider.value.toFixed(2))
|
2025-02-28 10:19:24 +00:00
|
|
|
Layout.fillWidth: true
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
2024-02-20 13:24:36 +00:00
|
|
|
Slider {
|
|
|
|
id: restitutionSlider
|
|
|
|
focusPolicy: Qt.NoFocus
|
|
|
|
from: 0
|
|
|
|
to: 1
|
2025-02-28 15:09:06 +00:00
|
|
|
value: 0.4
|
2024-02-20 13:24:36 +00:00
|
|
|
stepSize: 0.05
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
|
|
|
|
2024-02-20 13:24:36 +00:00
|
|
|
// Gravity
|
|
|
|
Label {
|
|
|
|
text: qsTr("Gravity")
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
2024-02-20 13:24:36 +00:00
|
|
|
GridLayout {
|
|
|
|
columns: 2
|
|
|
|
RadioButton {
|
|
|
|
id: gravityZero
|
|
|
|
text: qsTr("Zero")
|
|
|
|
onCheckedChanged: scene.updateGravity()
|
|
|
|
}
|
|
|
|
RadioButton {
|
|
|
|
id: gravityMoon
|
|
|
|
text: qsTr("Moon")
|
|
|
|
onCheckedChanged: scene.updateGravity()
|
|
|
|
}
|
|
|
|
RadioButton {
|
|
|
|
id: gravityMars
|
|
|
|
text: qsTr("Mars")
|
|
|
|
onCheckedChanged: scene.updateGravity()
|
|
|
|
}
|
|
|
|
RadioButton {
|
|
|
|
id: gravityEarth
|
|
|
|
text: qsTr("Earth")
|
|
|
|
onCheckedChanged: scene.updateGravity()
|
|
|
|
checked: true
|
|
|
|
}
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
2024-02-20 13:24:36 +00:00
|
|
|
|
|
|
|
// Number of dice
|
2025-02-28 10:19:24 +00:00
|
|
|
Label {
|
2025-02-28 10:46:05 +00:00
|
|
|
text: qsTr("Number of dice: %1").arg(diceSlider.value)
|
2025-02-28 10:19:24 +00:00
|
|
|
Layout.fillWidth: true
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
2024-02-20 13:24:36 +00:00
|
|
|
Slider {
|
|
|
|
id: diceSlider
|
|
|
|
focusPolicy: Qt.NoFocus
|
|
|
|
from: 1
|
2025-02-28 09:30:42 +00:00
|
|
|
to: 20
|
2024-02-20 13:24:36 +00:00
|
|
|
value: 5
|
|
|
|
stepSize: 1
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
|
|
|
|
2024-02-20 13:24:36 +00:00
|
|
|
// Dice size
|
2025-02-28 10:19:24 +00:00
|
|
|
Label {
|
2025-02-28 10:46:05 +00:00
|
|
|
text: qsTr("Dice size: %1cm").arg(diceSize.value.toFixed(1))
|
2025-02-28 10:19:24 +00:00
|
|
|
Layout.fillWidth: true
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
2024-02-20 13:24:36 +00:00
|
|
|
Slider {
|
|
|
|
id: diceSize
|
|
|
|
focusPolicy: Qt.NoFocus
|
|
|
|
from: 1
|
|
|
|
to: 10
|
2024-09-24 16:46:21 +00:00
|
|
|
value: 3.5
|
2025-02-28 09:30:42 +00:00
|
|
|
stepSize: 0.5
|
2024-01-11 10:06:55 +00:00
|
|
|
}
|
2023-06-19 13:29:46 +00:00
|
|
|
|
2024-02-20 13:24:36 +00:00
|
|
|
// Throw dice
|
|
|
|
Button {
|
|
|
|
id: throwButton
|
|
|
|
Layout.alignment: Qt.AlignHCenter
|
|
|
|
text: qsTr("Throw dice")
|
2025-02-28 09:30:42 +00:00
|
|
|
onClicked: {
|
|
|
|
scene.rollForce = Qt.vector3d(0, 0, 0)
|
|
|
|
scene.spawnDice()
|
|
|
|
}
|
2024-02-20 13:24:36 +00:00
|
|
|
}
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RoundButton {
|
|
|
|
id: iconOpen
|
2023-12-12 11:56:40 +00:00
|
|
|
icon.source: "Menu_Icon.svg"
|
2024-07-05 07:59:31 +00:00
|
|
|
x: root.currDrawerWidth
|
2025-02-28 13:17:10 +00:00
|
|
|
opacity: 1.0 - drawer.position
|
|
|
|
scale: opacity
|
|
|
|
transformOrigin: Item.Center
|
2023-06-19 13:29:46 +00:00
|
|
|
onClicked: {
|
2025-02-28 10:10:16 +00:00
|
|
|
tapLabel.opacity = 0
|
2023-08-17 03:49:16 +00:00
|
|
|
drawer.open()
|
2023-06-19 13:29:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|