mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 18:30:42 +02:00
Merge pull request #645 from keeshii/feature/qml_entities
Added support for QML inside web-entities.
This commit is contained in:
commit
79cf24d30f
12 changed files with 980 additions and 82 deletions
|
@ -9,68 +9,94 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtGraphicalEffects 1.0
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
id: root
|
||||||
|
anchors.fill: parent
|
||||||
|
property string url: ""
|
||||||
|
property string scriptUrl: null
|
||||||
|
property bool useBackground: true
|
||||||
|
property string userAgent: ""
|
||||||
|
|
||||||
property string url
|
onUrlChanged: {
|
||||||
RadialGradient {
|
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
||||||
|
}
|
||||||
|
|
||||||
|
onScriptUrlChanged: {
|
||||||
|
if (loader.item) {
|
||||||
|
if (root.webViewLoaded) {
|
||||||
|
loader.item.scriptUrl = root.scriptUrl;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onUseBackgroundChanged: {
|
||||||
|
if (loader.item) {
|
||||||
|
if (root.webViewLoaded) {
|
||||||
|
loader.item.useBackground = root.useBackground;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onUserAgentChanged: {
|
||||||
|
if (loader.item) {
|
||||||
|
if (root.webViewLoaded) {
|
||||||
|
loader.item.userAgent = root.userAgent;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle message traffic from our loaded QML to the script that launched us
|
||||||
|
onItemChanged: {
|
||||||
|
if (loader.item && loader.item.sendToScript) {
|
||||||
|
loader.item.sendToScript.connect(sendToScript);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
property var item: null
|
||||||
|
property bool webViewLoaded: false
|
||||||
|
|
||||||
|
// Handle message traffic from the script that launched us to the loaded QML
|
||||||
|
function fromScript(message) {
|
||||||
|
if (loader.item && loader.item.fromScript) {
|
||||||
|
loader.item.fromScript(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: loader
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
gradient: Gradient {
|
}
|
||||||
GradientStop { position: 0.0; color: "#262626" }
|
|
||||||
GradientStop { position: 1.0; color: "#000000" }
|
function load(url, scriptUrl, useBackground, userAgent) {
|
||||||
|
// Ensure we reset any existing item to "about:blank" to ensure web audio stops: DEV-2375
|
||||||
|
if (loader.item && root.webViewLoaded) {
|
||||||
|
loader.item.url = "about:blank"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.match(/\.qml$/)) {
|
||||||
|
root.webViewLoaded = false;
|
||||||
|
loader.setSource(url);
|
||||||
|
} else {
|
||||||
|
root.webViewLoaded = true;
|
||||||
|
loader.setSource("./Web3DSurfaceAndroid.qml", {
|
||||||
|
url: url,
|
||||||
|
scriptUrl: scriptUrl,
|
||||||
|
useBackground: useBackground,
|
||||||
|
userAgent: userAgent
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function shortUrl(url) {
|
Component.onCompleted: {
|
||||||
var hostBegin = url.indexOf("://");
|
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
||||||
if (hostBegin > -1) {
|
|
||||||
url = url.substring(hostBegin + 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
var portBegin = url.indexOf(":");
|
|
||||||
if (portBegin > -1) {
|
|
||||||
url = url.substring(0, portBegin);
|
|
||||||
}
|
|
||||||
|
|
||||||
var pathBegin = url.indexOf("/");
|
|
||||||
if (pathBegin > -1) {
|
|
||||||
url = url.substring(0, pathBegin);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url.length > 45) {
|
|
||||||
url = url.substring(0, 45);
|
|
||||||
}
|
|
||||||
|
|
||||||
return url;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
signal sendToScript(var message);
|
||||||
id: urlText
|
|
||||||
text: shortUrl(url)
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.rightMargin: 10
|
|
||||||
anchors.leftMargin: 10
|
|
||||||
font.family: "Cairo"
|
|
||||||
font.weight: Font.DemiBold
|
|
||||||
font.pointSize: 48
|
|
||||||
fontSizeMode: Text.Fit
|
|
||||||
color: "#FFFFFF"
|
|
||||||
minimumPixelSize: 5
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
|
||||||
id: hand
|
|
||||||
source: "../../icons/hand.svg"
|
|
||||||
width: 300
|
|
||||||
height: 300
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.bottomMargin: 100
|
|
||||||
anchors.rightMargin: 100
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
//
|
||||||
|
// Web3DSurface.qml
|
||||||
|
//
|
||||||
|
// Created by Gabriel Calero & Cristian Duarte on Jun 22, 2018
|
||||||
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
import QtQuick 2.5
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
|
||||||
|
Item {
|
||||||
|
|
||||||
|
property string url
|
||||||
|
property string scriptUrl
|
||||||
|
property bool useBackground
|
||||||
|
property string userAgent
|
||||||
|
|
||||||
|
RadialGradient {
|
||||||
|
anchors.fill: parent
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop { position: 0.0; color: "#262626" }
|
||||||
|
GradientStop { position: 1.0; color: "#000000" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function destroy() { }
|
||||||
|
|
||||||
|
function shortUrl(url) {
|
||||||
|
var hostBegin = url.indexOf("://");
|
||||||
|
if (hostBegin > -1) {
|
||||||
|
url = url.substring(hostBegin + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
var portBegin = url.indexOf(":");
|
||||||
|
if (portBegin > -1) {
|
||||||
|
url = url.substring(0, portBegin);
|
||||||
|
}
|
||||||
|
|
||||||
|
var pathBegin = url.indexOf("/");
|
||||||
|
if (pathBegin > -1) {
|
||||||
|
url = url.substring(0, pathBegin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.length > 45) {
|
||||||
|
url = url.substring(0, 45);
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: urlText
|
||||||
|
text: shortUrl(url)
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.rightMargin: 10
|
||||||
|
anchors.leftMargin: 10
|
||||||
|
font.family: "Cairo"
|
||||||
|
font.weight: Font.DemiBold
|
||||||
|
font.pointSize: 48
|
||||||
|
fontSizeMode: Text.Fit
|
||||||
|
color: "#FFFFFF"
|
||||||
|
minimumPixelSize: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: hand
|
||||||
|
source: "../../icons/hand.svg"
|
||||||
|
width: 300
|
||||||
|
height: 300
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottomMargin: 100
|
||||||
|
anchors.rightMargin: 100
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -10,8 +10,8 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
|
import controlsUit 1.0 as Controls
|
||||||
import "controls" as Controls
|
import "controls"
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
@ -26,45 +26,78 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
onScriptUrlChanged: {
|
onScriptUrlChanged: {
|
||||||
if (root.item) {
|
if (loader.item) {
|
||||||
root.item.scriptUrl = root.scriptUrl;
|
if (root.webViewLoaded) {
|
||||||
|
loader.item.scriptUrl = root.scriptUrl;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onUseBackgroundChanged: {
|
onUseBackgroundChanged: {
|
||||||
if (root.item) {
|
if (loader.item) {
|
||||||
root.item.useBackground = root.useBackground;
|
if (root.webViewLoaded) {
|
||||||
|
loader.item.useBackground = root.useBackground;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onUserAgentChanged: {
|
onUserAgentChanged: {
|
||||||
if (root.item) {
|
if (loader.item) {
|
||||||
root.item.userAgent = root.userAgent;
|
if (root.webViewLoaded) {
|
||||||
|
loader.item.userAgent = root.userAgent;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
load(root.url, root.scriptUrl, root.useBackground, root.userAgent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle message traffic from our loaded QML to the script that launched us
|
||||||
|
onItemChanged: {
|
||||||
|
if (loader.item && loader.item.sendToScript) {
|
||||||
|
loader.item.sendToScript.connect(sendToScript);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
property var item: null
|
property var item: null
|
||||||
|
property bool webViewLoaded: false
|
||||||
|
|
||||||
|
// Handle message traffic from the script that launched us to the loaded QML
|
||||||
|
function fromScript(message) {
|
||||||
|
if (loader.item && loader.item.fromScript) {
|
||||||
|
loader.item.fromScript(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: loader
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
function load(url, scriptUrl, useBackground, userAgent) {
|
function load(url, scriptUrl, useBackground, userAgent) {
|
||||||
// Ensure we reset any existing item to "about:blank" to ensure web audio stops: DEV-2375
|
// Ensure we reset any existing item to "about:blank" to ensure web audio stops: DEV-2375
|
||||||
if (root.item != null) {
|
if (loader.item && root.webViewLoaded) {
|
||||||
root.item.url = "about:blank"
|
if (root.webViewLoaded) {
|
||||||
root.item.destroy()
|
loader.item.url = "about:blank"
|
||||||
root.item = null
|
}
|
||||||
|
loader.setSource(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.match(/\.qml$/)) {
|
||||||
|
root.webViewLoaded = false;
|
||||||
|
loader.setSource(url);
|
||||||
|
} else {
|
||||||
|
root.webViewLoaded = true;
|
||||||
|
loader.setSource("./controls/WebView.qml", {
|
||||||
|
url: url,
|
||||||
|
scriptUrl: scriptUrl,
|
||||||
|
useBackground: useBackground,
|
||||||
|
userAgent: userAgent
|
||||||
|
});
|
||||||
}
|
}
|
||||||
QmlSurface.load("./controls/WebView.qml", root, function(newItem) {
|
|
||||||
root.item = newItem
|
|
||||||
root.item.url = url
|
|
||||||
root.item.scriptUrl = scriptUrl
|
|
||||||
root.item.useBackground = useBackground
|
|
||||||
root.item.userAgent = userAgent
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
|
|
@ -13,6 +13,8 @@ Rectangle {
|
||||||
property string url: "";
|
property string url: "";
|
||||||
property bool canGoBack: false
|
property bool canGoBack: false
|
||||||
property bool canGoForward: false
|
property bool canGoForward: false
|
||||||
|
property bool useBackground: false
|
||||||
|
property string userAgent: ""
|
||||||
property string icon: ""
|
property string icon: ""
|
||||||
property var profile: {}
|
property var profile: {}
|
||||||
|
|
||||||
|
|
599
interface/resources/serverless/Scripts/Wizard.qml
Normal file
599
interface/resources/serverless/Scripts/Wizard.qml
Normal file
|
@ -0,0 +1,599 @@
|
||||||
|
//
|
||||||
|
// Wizard.qml
|
||||||
|
//
|
||||||
|
// Created by keeshii on 26 Sep 2023
|
||||||
|
// Copyright 2023 Overte, Org.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
import Hifi 1.0 as Hifi
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Layouts 1.12
|
||||||
|
|
||||||
|
import stylesUit 1.0 as HifiStylesUit
|
||||||
|
import controlsUit 1.0 as HifiControls
|
||||||
|
import "qrc:////qml//styles" as HifiStyles
|
||||||
|
import "qrc:////qml//hifi" as Hifi
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: wizard
|
||||||
|
color: "#433952"
|
||||||
|
|
||||||
|
property int performancePreset: 0
|
||||||
|
property int refreshRateProfile: 0
|
||||||
|
property string displayName: ""
|
||||||
|
|
||||||
|
property bool keyboardEnabled: false
|
||||||
|
property bool punctuationMode: false
|
||||||
|
property bool keyboardRaised: false
|
||||||
|
|
||||||
|
function setStep(stepNum) {
|
||||||
|
stepList.completed = stepNum
|
||||||
|
switch (stepNum) {
|
||||||
|
case 0:
|
||||||
|
loader.sourceComponent = step1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
loader.sourceComponent = step2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
loader.sourceComponent = step3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
loader.sourceComponent = step4;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
loader.sourceComponent = step5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
loader.setSource(undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function completeWizard() {
|
||||||
|
var completionMessage = {
|
||||||
|
command: "complete-wizard",
|
||||||
|
data: {
|
||||||
|
performancePreset: wizard.performancePreset,
|
||||||
|
refreshRateProfile: wizard.refreshRateProfile,
|
||||||
|
displayName: wizard.displayName
|
||||||
|
}
|
||||||
|
};
|
||||||
|
eventBridge.emitWebEvent(JSON.stringify(completionMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleWebEvent(message) {
|
||||||
|
var messageJSON = JSON.parse(message);
|
||||||
|
if (messageJSON.command === "script-to-web-initialize") {
|
||||||
|
wizard.performancePreset = messageJSON.data.performancePreset;
|
||||||
|
wizard.refreshRateProfile = messageJSON.data.refreshRateProfile;
|
||||||
|
wizard.displayName = messageJSON.data.displayName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializeWizard() {
|
||||||
|
var initializeCommand = {"command": "first-run-wizard-ready"};
|
||||||
|
eventBridge.emitWebEvent(JSON.stringify(initializeCommand));
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop() {
|
||||||
|
wizard.keyboardEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layout constants constants
|
||||||
|
HifiStyles.HifiConstants { id: hifi }
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: steps
|
||||||
|
color: "#26202e"
|
||||||
|
width: parent.width - 8 * hifi.layout.spacing
|
||||||
|
height: hifi.layout.rowHeight + 6 * hifi.layout.spacing
|
||||||
|
anchors.top: wizard.top
|
||||||
|
anchors.topMargin: 4 * hifi.layout.spacing
|
||||||
|
anchors.horizontalCenter: wizard.horizontalCenter
|
||||||
|
radius: hifi.layout.spacing
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: stepList
|
||||||
|
anchors.fill: parent
|
||||||
|
orientation: ListView.Horizontal
|
||||||
|
|
||||||
|
property int completed: 0
|
||||||
|
|
||||||
|
delegate: Item {
|
||||||
|
id: stepItem
|
||||||
|
width: stepList.width / 5
|
||||||
|
height: stepList.height
|
||||||
|
property int num: index
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: 1
|
||||||
|
anchors.left: stepCircle.horizontalCenter
|
||||||
|
anchors.top: stepCircle.verticalCenter
|
||||||
|
visible: stepItem.num + 1 < stepList.model.count
|
||||||
|
color: stepList.completed > stepItem.num ? "#4bb543" : "gray"
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: stepCircle
|
||||||
|
color: stepList.completed > stepItem.num ? "#4bb543"
|
||||||
|
: (stepList.completed === stepItem.num ? "white" : "gray")
|
||||||
|
width: hifi.layout.rowHeight
|
||||||
|
height: hifi.layout.rowHeight
|
||||||
|
radius: hifi.layout.rowHeight / 2
|
||||||
|
anchors.top: stepItem.top
|
||||||
|
anchors.topMargin: hifi.layout.spacing
|
||||||
|
anchors.horizontalCenter: stepItem.horizontalCenter
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: stepNum
|
||||||
|
text: String(stepItem.num + 1)
|
||||||
|
color: stepList.completed === stepItem.num ? hifi.colors.text : "white"
|
||||||
|
anchors.centerIn: stepCircle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: stepName
|
||||||
|
text: name
|
||||||
|
color: "white"
|
||||||
|
anchors.top: stepCircle.bottom
|
||||||
|
anchors.topMargin: hifi.layout.spacing
|
||||||
|
anchors.horizontalCenter: stepItem.horizontalCenter
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
model: ListModel {
|
||||||
|
ListElement { name: "Welcome" }
|
||||||
|
ListElement { name: "Quality" }
|
||||||
|
ListElement { name: "Performance" }
|
||||||
|
ListElement { name: "Display Name" }
|
||||||
|
ListElement { name: "Completion" }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: loader
|
||||||
|
width: parent.width - 8 * hifi.layout.spacing
|
||||||
|
height: parent.height - steps.height - backButton.height - 12 * hifi.layout.spacing
|
||||||
|
anchors.top: steps.bottom
|
||||||
|
anchors.topMargin: 2 * hifi.layout.spacing
|
||||||
|
anchors.horizontalCenter: wizard.horizontalCenter
|
||||||
|
sourceComponent: step1
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: step1
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: step1Body
|
||||||
|
anchors.fill: loader
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: step1Header
|
||||||
|
width: parent.width
|
||||||
|
text: "Welcome to Overte!"
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: hifi.fonts.headerPixelSize
|
||||||
|
font.bold: true
|
||||||
|
|
||||||
|
anchors.top: step1Body.top
|
||||||
|
anchors.topMargin: 2 * hifi.layout.spacing
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: step1Text1
|
||||||
|
width: parent.width
|
||||||
|
text:
|
||||||
|
"Let's get you setup to experience the virtual world.<br />" +
|
||||||
|
"First, we need to select some performance and graphics quality options.<br />" +
|
||||||
|
"<br />" +
|
||||||
|
"Press <b><font color=\"#2e89ff\">Continue</font></b> when you are ready."
|
||||||
|
color: "white"
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
textFormat: TextEdit.RichText
|
||||||
|
|
||||||
|
anchors.top: step1Header.bottom
|
||||||
|
anchors.topMargin: 2 * hifi.layout.spacing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: step2
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: step2Body
|
||||||
|
anchors.fill: loader
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: step2Header
|
||||||
|
width: parent.width
|
||||||
|
text: "Quality"
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: hifi.fonts.headerPixelSize
|
||||||
|
font.bold: true
|
||||||
|
|
||||||
|
anchors.top: step2Body.top
|
||||||
|
anchors.topMargin: 2 * hifi.layout.spacing
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: step2Text1
|
||||||
|
width: parent.width
|
||||||
|
text:
|
||||||
|
"What level of visual quality would you like?<br />" +
|
||||||
|
"<b>Remember! If you do not have a powerful computer,<br />" +
|
||||||
|
"you may want to set this to low or medium at most.</b>"
|
||||||
|
color: "white"
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
textFormat: TextEdit.RichText
|
||||||
|
|
||||||
|
anchors.top: step2Header.bottom
|
||||||
|
anchors.topMargin: 2 * hifi.layout.spacing
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.top: step2Text1.bottom
|
||||||
|
anchors.topMargin: 2 * hifi.layout.spacing
|
||||||
|
|
||||||
|
RadioButton {
|
||||||
|
text:
|
||||||
|
"<font size=\"4\" color=\"#ff9900\"><b>Very Low Quality</b></font>\n" +
|
||||||
|
"<font color=\"white\">Slow Laptop / Very Slow Computer</font>"
|
||||||
|
onClicked: wizard.performancePreset = 1
|
||||||
|
checked: wizard.performancePreset === 1
|
||||||
|
}
|
||||||
|
RadioButton {
|
||||||
|
text:
|
||||||
|
"<font size=\"4\" color=\"#ffff00\"><b>Low Quality</b></font>\n" +
|
||||||
|
"<font color=\"white\">Average Laptop / Slow Computer</font>"
|
||||||
|
onClicked: wizard.performancePreset = 2
|
||||||
|
checked: wizard.performancePreset === 2
|
||||||
|
}
|
||||||
|
RadioButton {
|
||||||
|
text:
|
||||||
|
"<font size=\"4\" color=\"#00ba1c\"><b>Medium Quality</b></font>\n" +
|
||||||
|
"<font color=\"white\">Average Computer - </font><font color=\"#00ba1c\"><i>Recommended</i></font>"
|
||||||
|
onClicked: wizard.performancePreset = 3
|
||||||
|
checked: wizard.performancePreset === 3
|
||||||
|
}
|
||||||
|
RadioButton {
|
||||||
|
text:
|
||||||
|
"<font size=\"4\" color=\"#0096db\"><b>High Quality</b></font>\n" +
|
||||||
|
"<font color=\"white\">Gaming Computer</font>"
|
||||||
|
onClicked: wizard.performancePreset = 4
|
||||||
|
checked: wizard.performancePreset === 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: step3
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: step3Body
|
||||||
|
anchors.fill: loader
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: step3Header
|
||||||
|
width: parent.width
|
||||||
|
text: "Performance"
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: hifi.fonts.headerPixelSize
|
||||||
|
font.bold: true
|
||||||
|
|
||||||
|
anchors.top: step3Body.top
|
||||||
|
anchors.topMargin: 2 * hifi.layout.spacing
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: step3Text1
|
||||||
|
width: parent.width
|
||||||
|
text:
|
||||||
|
"Do you want a smooth experience <i>(high refresh rate)</i><br />" +
|
||||||
|
"or do you want to conserve power and resources <i>(low refresh rate)</i> on your computer?<br />" +
|
||||||
|
"<b><i>Note: This does not apply to virtual reality headsets.</i><b>"
|
||||||
|
color: "white"
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
textFormat: TextEdit.RichText
|
||||||
|
|
||||||
|
anchors.top: step3Header.bottom
|
||||||
|
anchors.topMargin: 2 * hifi.layout.spacing
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.top: step3Text1.bottom
|
||||||
|
anchors.topMargin: 2 * hifi.layout.spacing
|
||||||
|
|
||||||
|
RadioButton {
|
||||||
|
text:
|
||||||
|
"<font size=\"4\" color=\"#ff9900\"><b>Not Smooth (20 Hz)</b></font>\n" +
|
||||||
|
"<font color=\"white\">Conserve Power</font>"
|
||||||
|
onClicked: wizard.refreshRateProfile = 1
|
||||||
|
checked: wizard.refreshRateProfile === 1
|
||||||
|
}
|
||||||
|
RadioButton {
|
||||||
|
text:
|
||||||
|
"<font size=\"4\" color=\"#ffff00\"><b>Smooth (30 Hz)</b></font>\n" +
|
||||||
|
"<font color=\"white\">Use Average Resources</font>"
|
||||||
|
onClicked: wizard.refreshRateProfile = 2
|
||||||
|
checked: wizard.refreshRateProfile === 2
|
||||||
|
}
|
||||||
|
RadioButton {
|
||||||
|
text:
|
||||||
|
"<font size=\"4\" color=\"#00ba1c\"><b>Very Smooth (60 Hz)</b></font>\n" +
|
||||||
|
"<font color=\"white\">Use Maximum Resources - </font><font color=\"#00ba1c\"><i>Recommended</i></font>"
|
||||||
|
onClicked: wizard.refreshRateProfile = 3
|
||||||
|
checked: wizard.refreshRateProfile === 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: step4
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: step4Body
|
||||||
|
anchors.fill: loader
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: step4Header
|
||||||
|
width: parent.width
|
||||||
|
text: "Display Name"
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: hifi.fonts.headerPixelSize
|
||||||
|
font.bold: true
|
||||||
|
|
||||||
|
anchors.top: step4Body.top
|
||||||
|
anchors.topMargin: 2 * hifi.layout.spacing
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: step4Text1
|
||||||
|
width: parent.width
|
||||||
|
text:
|
||||||
|
"What should people call you?<br />" +
|
||||||
|
"This is simply a nickname, it will be shown in place of your username (if you have one)."
|
||||||
|
color: "white"
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
textFormat: TextEdit.RichText
|
||||||
|
|
||||||
|
anchors.top: step4Header.bottom
|
||||||
|
anchors.topMargin: 2 * hifi.layout.spacing
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: inputBar
|
||||||
|
width: parent.width
|
||||||
|
height: 40
|
||||||
|
color: 'white'
|
||||||
|
anchors.top: step4Text1.bottom
|
||||||
|
anchors.topMargin: 2 * hifi.layout.spacing
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: displayName
|
||||||
|
text: wizard.displayName
|
||||||
|
focus: true
|
||||||
|
width: inputBar.width - inputBar.anchors.leftMargin - inputBar.anchors.rightMargin;
|
||||||
|
anchors {
|
||||||
|
left: inputBar.left;
|
||||||
|
leftMargin: 8;
|
||||||
|
verticalCenter: inputBar.verticalCenter;
|
||||||
|
}
|
||||||
|
|
||||||
|
onTextChanged: wizard.displayName = text
|
||||||
|
placeholderText: "Enter display name"
|
||||||
|
verticalAlignment: TextInput.AlignBottom
|
||||||
|
onAccepted: {
|
||||||
|
if (HMD.active) {
|
||||||
|
wizard.keyboardEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
font {
|
||||||
|
family: hifi.fonts.fontFamily
|
||||||
|
pixelSize: hifi.fonts.pixelSize * 0.75
|
||||||
|
}
|
||||||
|
|
||||||
|
color: hifi.colors.text
|
||||||
|
background: Item {}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent;
|
||||||
|
onClicked: {
|
||||||
|
displayName.focus = true;
|
||||||
|
displayName.forceActiveFocus();
|
||||||
|
if (HMD.active) {
|
||||||
|
wizard.keyboardEnabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: step5
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: step5Body
|
||||||
|
anchors.fill: loader
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: step5Header
|
||||||
|
width: parent.width
|
||||||
|
text: "All done!"
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: hifi.fonts.headerPixelSize
|
||||||
|
font.bold: true
|
||||||
|
|
||||||
|
anchors.top: step5Body.top
|
||||||
|
anchors.topMargin: 2 * hifi.layout.spacing
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: step5Text1
|
||||||
|
width: parent.width
|
||||||
|
text:
|
||||||
|
"Now you're almost ready to go!<br />" +
|
||||||
|
"Press <font color=\"#1ee62e\">Complete</font> to save your setup.<br />" +
|
||||||
|
"Then take a look at the other information kiosks after completing this wizard."
|
||||||
|
color: "white"
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
textFormat: TextEdit.RichText
|
||||||
|
|
||||||
|
anchors.top: step5Header.bottom
|
||||||
|
anchors.topMargin: 2 * hifi.layout.spacing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: backButton
|
||||||
|
text: "< Back"
|
||||||
|
width: nextButton.width
|
||||||
|
anchors.bottom: wizard.bottom
|
||||||
|
anchors.left: wizard.left
|
||||||
|
anchors.bottomMargin: 4 * hifi.layout.spacing
|
||||||
|
anchors.leftMargin: 4 * hifi.layout.spacing
|
||||||
|
visible: stepList.completed > 0
|
||||||
|
onClicked: setStep(stepList.completed - 1)
|
||||||
|
|
||||||
|
contentItem: Text {
|
||||||
|
text: backButton.text
|
||||||
|
font.bold: true
|
||||||
|
color: "white"
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
implicitWidth: 100
|
||||||
|
implicitHeight: 40
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop { position: 0 ; color: backButton.hovered ? "#0599fc" : "#0599fc" }
|
||||||
|
GradientStop { position: 1 ; color: backButton.hovered ? "#003670" : "#002259" }
|
||||||
|
}
|
||||||
|
border.color: "#26282a"
|
||||||
|
border.width: 1
|
||||||
|
radius: 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: nextButton
|
||||||
|
text: "Continue >"
|
||||||
|
anchors.bottom: wizard.bottom
|
||||||
|
anchors.right: wizard.right
|
||||||
|
anchors.bottomMargin: 4 * hifi.layout.spacing
|
||||||
|
anchors.rightMargin: 4 * hifi.layout.spacing
|
||||||
|
visible: stepList.completed < 4
|
||||||
|
onClicked: setStep(stepList.completed + 1)
|
||||||
|
rightPadding: 2 * hifi.layout.spacing
|
||||||
|
leftPadding: 2 * hifi.layout.spacing
|
||||||
|
|
||||||
|
contentItem: Text {
|
||||||
|
text: nextButton.text
|
||||||
|
font.bold: true
|
||||||
|
color: "white"
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
implicitWidth: 100
|
||||||
|
implicitHeight: 40
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop { position: 0 ; color: nextButton.hovered ? "#0599fc" : "#0599fc" }
|
||||||
|
GradientStop { position: 1 ; color: nextButton.hovered ? "#003670" : "#002259" }
|
||||||
|
}
|
||||||
|
border.color: "#26282a"
|
||||||
|
border.width: 1
|
||||||
|
radius: 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: completeButton
|
||||||
|
text: "Complete"
|
||||||
|
width: nextButton.width
|
||||||
|
anchors.bottom: wizard.bottom
|
||||||
|
anchors.right: wizard.right
|
||||||
|
anchors.bottomMargin: 4 * hifi.layout.spacing
|
||||||
|
anchors.rightMargin: 4 * hifi.layout.spacing
|
||||||
|
visible: stepList.completed === 4
|
||||||
|
onClicked: completeWizard()
|
||||||
|
|
||||||
|
contentItem: Text {
|
||||||
|
text: completeButton.text
|
||||||
|
font.bold: true
|
||||||
|
color: "white"
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
implicitWidth: 100
|
||||||
|
implicitHeight: 40
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop { position: 0 ; color: nextButton.hovered ? "#59ffc2" : "#00ff00" }
|
||||||
|
GradientStop { position: 1 ; color: nextButton.hovered ? "#196144" : "#003600" }
|
||||||
|
}
|
||||||
|
border.color: "#26282a"
|
||||||
|
border.width: 1
|
||||||
|
radius: 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControls.Keyboard {
|
||||||
|
id: keyboard
|
||||||
|
raised: parent.keyboardEnabled && parent.keyboardRaised
|
||||||
|
numeric: parent.punctuationMode
|
||||||
|
anchors {
|
||||||
|
bottom: parent.bottom
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the client-entity script to load before sending events
|
||||||
|
Timer {
|
||||||
|
id: timer
|
||||||
|
function setTimeout(cb, delayTime) {
|
||||||
|
timer.interval = delayTime;
|
||||||
|
timer.repeat = false;
|
||||||
|
timer.triggered.connect(cb);
|
||||||
|
timer.triggered.connect(function release () {
|
||||||
|
timer.triggered.disconnect(cb); // This is important
|
||||||
|
timer.triggered.disconnect(release); // This is important as well
|
||||||
|
});
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
eventBridge.scriptEventReceived.connect(handleWebEvent);
|
||||||
|
timer.setTimeout(function(){ initializeWizard(); }, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onDestruction: {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
signal sendToScript(var message);
|
||||||
|
|
||||||
|
}
|
|
@ -13,7 +13,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var CONFIG_WIZARD_URL = "https://more.overte.org/tutorial/wizard.html?v=" + Math.floor(Math.random() * 65000);
|
var CONFIG_WIZARD_URL = "qrc:///serverless/Scripts/Wizard.qml";
|
||||||
|
|
||||||
var loaderEntityID;
|
var loaderEntityID;
|
||||||
var configWizardEntityID;
|
var configWizardEntityID;
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
"parentID": loaderEntityID,
|
"parentID": loaderEntityID,
|
||||||
"sourceUrl": CONFIG_WIZARD_URL,
|
"sourceUrl": CONFIG_WIZARD_URL,
|
||||||
"maxFPS": 60,
|
"maxFPS": 60,
|
||||||
"dpi": 19,
|
"dpi": 15,
|
||||||
"useBackground": true,
|
"useBackground": true,
|
||||||
"grab": {
|
"grab": {
|
||||||
"grabbable": false
|
"grabbable": false
|
||||||
|
|
|
@ -3226,7 +3226,7 @@ void Application::initializeUi() {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
for (const auto& str : safeURLS) {
|
for (const auto& str : safeURLS) {
|
||||||
if (!str.isEmpty() && str.endsWith(".qml") && url.toString().endsWith(".qml") &&
|
if (!str.isEmpty() && url.toString().endsWith(".qml") &&
|
||||||
url.toString().startsWith(str)) {
|
url.toString().startsWith(str)) {
|
||||||
qCDebug(interfaceapp) << "Found matching url!" << url.host();
|
qCDebug(interfaceapp) << "Found matching url!" << url.host();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -66,6 +66,10 @@ WebEntityRenderer::ContentType WebEntityRenderer::getContentType(const QString&
|
||||||
|
|
||||||
const QUrl url(urlString);
|
const QUrl url(urlString);
|
||||||
auto scheme = url.scheme();
|
auto scheme = url.scheme();
|
||||||
|
if (urlString.toLower().endsWith(".qml")) {
|
||||||
|
return ContentType::QmlContent;
|
||||||
|
}
|
||||||
|
|
||||||
if (scheme == HIFI_URL_SCHEME_ABOUT || scheme == HIFI_URL_SCHEME_HTTP || scheme == HIFI_URL_SCHEME_HTTPS ||
|
if (scheme == HIFI_URL_SCHEME_ABOUT || scheme == HIFI_URL_SCHEME_HTTP || scheme == HIFI_URL_SCHEME_HTTPS ||
|
||||||
scheme == URL_SCHEME_DATA ||
|
scheme == URL_SCHEME_DATA ||
|
||||||
urlString.toLower().endsWith(".htm") || urlString.toLower().endsWith(".html")) {
|
urlString.toLower().endsWith(".htm") || urlString.toLower().endsWith(".html")) {
|
||||||
|
|
149
scripts/system/+android_interface/androidControls.js
Normal file
149
scripts/system/+android_interface/androidControls.js
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
"use strict";
|
||||||
|
//
|
||||||
|
// androidControls.js
|
||||||
|
//
|
||||||
|
// Created by keeshii on September 26th, 2023.
|
||||||
|
// Copyright 2022-2023 Overte e.V.
|
||||||
|
//
|
||||||
|
// This script read touch screen events and triggers mouse events.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
|
var DISPATCHER_TOUCH_PROPERTIES = ["id", "position", "rotation", "dimensions", "registrationPoint"];
|
||||||
|
|
||||||
|
var TAP_DELAY = 300;
|
||||||
|
|
||||||
|
function AndroidControls() {
|
||||||
|
this.onTouchStartFn = null;
|
||||||
|
this.onTouchEndFn = null;
|
||||||
|
this.touchStartTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidControls.prototype.intersectsOverlay = function (intersection) {
|
||||||
|
if (intersection && intersection.intersects && intersection.overlayID) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidControls.prototype.intersectsEntity = function (intersection) {
|
||||||
|
if (intersection && intersection.intersects && intersection.entityID) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidControls.prototype.findRayIntersection = function (pickRay) {
|
||||||
|
// Check 3D overlays and entities. Argument is an object with origin and direction.
|
||||||
|
var overlayRayIntersection = Overlays.findRayIntersection(pickRay);
|
||||||
|
var entityRayIntersection = Entities.findRayIntersection(pickRay, true);
|
||||||
|
var isOverlayInters = this.intersectsOverlay(overlayRayIntersection);
|
||||||
|
var isEntityInters = this.intersectsEntity(entityRayIntersection);
|
||||||
|
|
||||||
|
if (isOverlayInters && (!isEntityInters || overlayRayIntersection.distance < entityRayIntersection.distance)) {
|
||||||
|
return {type: 'overlay', obj: overlayRayIntersection};
|
||||||
|
} else if (isEntityInters) {
|
||||||
|
return {type: 'entity', obj: entityRayIntersection};
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidControls.prototype.createEventProperties = function (entityId, info, eventType) {
|
||||||
|
var pointerEvent = {
|
||||||
|
type: eventType,
|
||||||
|
id: 1,
|
||||||
|
pos2D: {x: 0, y: 0},
|
||||||
|
pos3D: info.obj.intersection,
|
||||||
|
normal: info.obj.surfaceNormal,
|
||||||
|
direction: info.obj.direction,
|
||||||
|
button: "Primary",
|
||||||
|
isPrimaryButton: true,
|
||||||
|
isLeftButton: true,
|
||||||
|
isPrimaryHeld: eventType === 'Press',
|
||||||
|
isSecondaryHeld: false,
|
||||||
|
isTertiaryHeld: false,
|
||||||
|
keyboardModifiers: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
var properties = Entities.getEntityProperties(entityId, DISPATCHER_TOUCH_PROPERTIES);
|
||||||
|
if (properties.id === entityId) {
|
||||||
|
pointerEvent.pos2D = info.type === "entity"
|
||||||
|
? projectOntoEntityXYPlane(entityId, info.obj.intersection, properties)
|
||||||
|
: projectOntoOverlayXYPlane(entityId, info.obj.intersection, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pointerEvent;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidControls.prototype.triggerClick = function (event) {
|
||||||
|
var info = this.findRayIntersection(Camera.computePickRay(event.x, event.y));
|
||||||
|
|
||||||
|
if (!info) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entityId = info.type === "entity" ? info.obj.entityID : info.obj.overlayID;
|
||||||
|
var pressEvent = this.createEventProperties(entityId, info, 'Press');
|
||||||
|
var releaseEvent = this.createEventProperties(entityId, info, 'Release');
|
||||||
|
|
||||||
|
Entities.sendMousePressOnEntity(entityId, pressEvent);
|
||||||
|
Entities.sendClickDownOnEntity(entityId, pressEvent);
|
||||||
|
|
||||||
|
Script.setTimeout(function () {
|
||||||
|
Entities.sendMouseReleaseOnEntity(entityId, releaseEvent);
|
||||||
|
Entities.sendClickReleaseOnEntity(entityId, releaseEvent);
|
||||||
|
}, 75);
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidControls.prototype.onTouchStart = function (_event) {
|
||||||
|
this.touchStartTime = Date.now();
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidControls.prototype.onTouchEnd = function (event) {
|
||||||
|
var now = Date.now();
|
||||||
|
if (now - this.touchStartTime < TAP_DELAY) {
|
||||||
|
this.triggerClick(event);
|
||||||
|
}
|
||||||
|
this.touchStartTime = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidControls.prototype.init = function () {
|
||||||
|
var self = this;
|
||||||
|
this.onTouchStartFn = function (ev) {
|
||||||
|
self.onTouchStart(ev);
|
||||||
|
};
|
||||||
|
this.onTouchEndFn = function (ev) {
|
||||||
|
self.onTouchEnd(ev);
|
||||||
|
};
|
||||||
|
|
||||||
|
Controller.touchBeginEvent.connect(this.onTouchStartFn);
|
||||||
|
Controller.touchEndEvent.connect(this.onTouchEndFn);
|
||||||
|
};
|
||||||
|
|
||||||
|
AndroidControls.prototype.ending = function () {
|
||||||
|
if (this.onTouchStartFn) {
|
||||||
|
Controller.touchBeginEvent.disconnect(this.onTouchStartFn);
|
||||||
|
}
|
||||||
|
if (this.onTouchEndFn) {
|
||||||
|
Controller.touchEndEvent.disconnect(this.onTouchEndFn);
|
||||||
|
}
|
||||||
|
this.touchStartTime = 0;
|
||||||
|
this.onTouchStartFn = null;
|
||||||
|
this.onTouchEndFn = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
var androidControls = new AndroidControls();
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(function () {
|
||||||
|
androidControls.ending();
|
||||||
|
});
|
||||||
|
androidControls.init();
|
||||||
|
|
||||||
|
module.exports = androidControls;
|
||||||
|
}());
|
|
@ -69,12 +69,12 @@ function touchEnd(event) {
|
||||||
var propertiesToGet = {};
|
var propertiesToGet = {};
|
||||||
propertiesToGet[overlayID] = ['url'];
|
propertiesToGet[overlayID] = ['url'];
|
||||||
var properties = Overlays.getOverlaysProperties(propertiesToGet);
|
var properties = Overlays.getOverlaysProperties(propertiesToGet);
|
||||||
if (properties[overlayID].url) {
|
if (properties[overlayID].url && !properties[overlayID].url.match(/\.qml$/)) {
|
||||||
Window.openUrl(properties[overlayID].url);
|
Window.openUrl(properties[overlayID].url);
|
||||||
}
|
}
|
||||||
} else if (intersection && intersection.type == 'entity' && touchEntityID == intersection.obj.entityID) {
|
} else if (intersection && intersection.type == 'entity' && touchEntityID == intersection.obj.entityID) {
|
||||||
var properties = Entities.getEntityProperties(touchEntityID, ["sourceUrl"]);
|
var properties = Entities.getEntityProperties(touchEntityID, ["sourceUrl"]);
|
||||||
if (properties.sourceUrl) {
|
if (properties.sourceUrl && !properties.sourceUrl.match(/\.qml$/)) {
|
||||||
Window.openUrl(properties.sourceUrl);
|
Window.openUrl(properties.sourceUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ var radar = Script.require('./radar.js');
|
||||||
var uniqueColor = Script.require('./uniqueColor.js');
|
var uniqueColor = Script.require('./uniqueColor.js');
|
||||||
var displayNames = Script.require('./displayNames.js');
|
var displayNames = Script.require('./displayNames.js');
|
||||||
var clickWeb = Script.require('./clickWeb.js');
|
var clickWeb = Script.require('./clickWeb.js');
|
||||||
|
var androidControls = Script.require('./androidControls.js');
|
||||||
|
|
||||||
function printd(str) {
|
function printd(str) {
|
||||||
if (logEnabled) {
|
if (logEnabled) {
|
||||||
|
@ -99,10 +100,12 @@ function switchToMode(newMode) {
|
||||||
radar.startRadarMode();
|
radar.startRadarMode();
|
||||||
displayNames.ending();
|
displayNames.ending();
|
||||||
clickWeb.ending();
|
clickWeb.ending();
|
||||||
|
androidControls.ending();
|
||||||
} else if (currentMode == MODE_MY_VIEW) {
|
} else if (currentMode == MODE_MY_VIEW) {
|
||||||
// nothing to do yet
|
// nothing to do yet
|
||||||
displayNames.init();
|
displayNames.init();
|
||||||
clickWeb.init();
|
clickWeb.init();
|
||||||
|
androidControls.init();
|
||||||
} else {
|
} else {
|
||||||
printd("Unknown view mode " + currentMode);
|
printd("Unknown view mode " + currentMode);
|
||||||
}
|
}
|
||||||
|
@ -121,4 +124,4 @@ Script.scriptEnding.connect(function () {
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
}()); // END LOCAL_SCOPE
|
}()); // END LOCAL_SCOPE
|
||||||
|
|
|
@ -1119,7 +1119,7 @@ function startRadar() {
|
||||||
|
|
||||||
function endRadar() {
|
function endRadar() {
|
||||||
printd("-- endRadar");
|
printd("-- endRadar");
|
||||||
Camera.mode = "third person";
|
Camera.mode = "first person look at";
|
||||||
radar = false;
|
radar = false;
|
||||||
|
|
||||||
Controller.setVPadEnabled(true);
|
Controller.setVPadEnabled(true);
|
||||||
|
|
Loading…
Reference in a new issue