Merge branch 'master' into DOC-191

This commit is contained in:
David Rowe 2019-10-24 08:23:27 +13:00
commit fffb81b474
78 changed files with 2094 additions and 542 deletions

View file

@ -265,7 +265,7 @@ static const int AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND = 45;
void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) {
quint64 start = usecTimestampNow();
if (node->getType() == NodeType::Agent && node->getLinkedData() && node->getActiveSocket() && !node->isUpstream()) {
if ((node->getType() == NodeType::Agent || node->getType() == NodeType::EntityScriptServer) && node->getLinkedData() && node->getActiveSocket() && !node->isUpstream()) {
broadcastAvatarDataToAgent(node);
} else if (node->getType() == NodeType::DownstreamAvatarMixer) {
broadcastAvatarDataToDownstreamMixer(node);
@ -448,13 +448,6 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
// or that somehow we haven't sent
if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) {
++numAvatarsHeldBack;
// BUGZ-781 verbose debugging:
auto usecLastTimeSent = destinationNodeData->getLastOtherAvatarEncodeTime(sourceAvatarNodeData->getNodeLocalID());
if (usecLastTimeSent != 0 && startIgnoreCalculation - usecLastTimeSent > 10 * USECS_PER_SECOND) {
qCDebug(avatars) << "Not sent avatar" << *sourceAvatarNode << "to Node" << *destinationNode << "in > 10 s";
}
sendAvatar = false;
} else if (lastSeqFromSender == 0) {
// We have have not yet received any data about this avatar. Ignore it for now

View file

@ -86,8 +86,6 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig
this, "handleOctreePacket");
packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat");
auto avatarHashMap = DependencyManager::set<AvatarHashMap>();
packetReceiver.registerListener(PacketType::ReloadEntityServerScript, this, "handleReloadEntityServerScriptPacket");
packetReceiver.registerListener(PacketType::EntityScriptGetStatus, this, "handleEntityScriptGetStatusPacket");
packetReceiver.registerListener(PacketType::EntityServerScriptLog, this, "handleEntityServerScriptLogPacket");
@ -255,6 +253,7 @@ void EntityScriptServer::handleEntityScriptCallMethodPacket(QSharedPointer<Recei
void EntityScriptServer::run() {
DependencyManager::set<ScriptEngines>(ScriptEngine::ENTITY_SERVER_SCRIPT);
DependencyManager::set<EntityScriptServerServices>();
DependencyManager::set<AvatarHashMap>();
// make sure we request our script once the agent connects to the domain
auto nodeList = DependencyManager::get<NodeList>();
@ -448,6 +447,7 @@ void EntityScriptServer::resetEntitiesScriptEngine() {
newEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue);
newEngine->registerGlobalObject("SoundCache", DependencyManager::get<SoundCacheScriptingInterface>().data());
newEngine->registerGlobalObject("AvatarList", DependencyManager::get<AvatarHashMap>().data());
// connect this script engines printedMessage signal to the global ScriptEngines these various messages
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();

View file

@ -6,8 +6,8 @@ if (WIN32)
include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://public.highfidelity.com/dependencies/qtaudio_wasapi11.zip
URL_MD5 d0eb8489455e7f79d59155535a2c8861
URL https://public.highfidelity.com/dependencies/qtaudio_wasapi12.zip
URL_MD5 9e2eef41165f85344808f754b48bf08d
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""

View file

@ -0,0 +1,36 @@
From 7638b7c5a659dceb4e580ae87d4d60b00847ef94 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emil=20Nord=C3=A9n?= <emilnorden@yahoo.se>
Date: Sat, 4 May 2019 08:38:53 +0200
Subject: [PATCH] fixed build on latest version of clang
---
src/Bullet3Common/b3Vector3.h | 2 +-
src/LinearMath/btVector3.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Bullet3Common/b3Vector3.h b/src/Bullet3Common/b3Vector3.h
index 56e6c13311..a70d68d6e1 100644
--- a/src/Bullet3Common/b3Vector3.h
+++ b/src/Bullet3Common/b3Vector3.h
@@ -36,7 +36,7 @@ subject to the following restrictions:
#pragma warning(disable : 4556) // value of intrinsic immediate argument '4294967239' is out of range '0 - 255'
#endif
-#define B3_SHUFFLE(x, y, z, w) ((w) << 6 | (z) << 4 | (y) << 2 | (x))
+#define B3_SHUFFLE(x, y, z, w) (((w) << 6 | (z) << 4 | (y) << 2 | (x)) & 0xff)
//#define b3_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) )
#define b3_pshufd_ps(_a, _mask) _mm_shuffle_ps((_a), (_a), (_mask))
#define b3_splat3_ps(_a, _i) b3_pshufd_ps((_a), B3_SHUFFLE(_i, _i, _i, 3))
diff --git a/src/LinearMath/btVector3.h b/src/LinearMath/btVector3.h
index 61fd8d1e46..d65ed9808d 100644
--- a/src/LinearMath/btVector3.h
+++ b/src/LinearMath/btVector3.h
@@ -36,7 +36,7 @@ subject to the following restrictions:
#pragma warning(disable : 4556) // value of intrinsic immediate argument '4294967239' is out of range '0 - 255'
#endif
-#define BT_SHUFFLE(x, y, z, w) ((w) << 6 | (z) << 4 | (y) << 2 | (x))
+#define BT_SHUFFLE(x, y, z, w) (((w) << 6 | (z) << 4 | (y) << 2 | (x)) & 0xff)
//#define bt_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) )
#define bt_pshufd_ps(_a, _mask) _mm_shuffle_ps((_a), (_a), (_mask))
#define bt_splat3_ps(_a, _i) bt_pshufd_ps((_a), BT_SHUFFLE(_i, _i, _i, 3))

View file

@ -27,6 +27,7 @@ vcpkg_from_github(
REF ab8f16961e19a86ee20c6a1d61f662392524cc77
SHA512 927742db29867517283d45e475f0c534a9a57e165cae221f26e08e88057253a1682ac9919b2dc547b9cf388ba0b931b175623461d44f28c9184796ba90b1ed55
HEAD_REF master
PATCHES "bullet-git-fix-build-clang-8.patch"
)
vcpkg_configure_cmake(

View file

@ -1,4 +1,4 @@
Source: hifi-deps
Version: 0.1
Version: 0.3
Description: Collected dependencies for High Fidelity applications
Build-Depends: bullet3, draco, etc2comp, glm, nvtt, openexr (!android), openssl (windows), tbb (!android&!osx), zlib, webrtc (!android)

View file

@ -134,7 +134,7 @@ endif()
downloadVcpkg = True
if not downloadVcpkg and not os.path.isfile(self.exe):
print("Missing executable, boostrapping")
print("Missing executable, boot-strapping")
downloadVcpkg = True
# Make sure we have a vcpkg executable
@ -265,7 +265,7 @@ endif()
if platform.system() == 'Windows':
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-windows3.tar.gz'
elif platform.system() == 'Darwin':
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-macos3.tar.gz'
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-macos.tar.gz?versionId=bLAgnoJ8IMKpqv8NFDcAu8hsyQy3Rwwz'
elif platform.system() == 'Linux':
if platform.linux_distribution()[1][:3] == '16.':
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04-with-symbols.tar.gz'

View file

@ -2478,8 +2478,8 @@
{
"easingType": "easeInOutQuad",
"id": "talk",
"interpDuration": 1,
"interpTarget": 1,
"interpDuration": 20,
"interpTarget": 20,
"interpType": "evaluateBoth",
"priority": 0.33,
"resume": true,
@ -2489,8 +2489,8 @@
{
"easingType": "easeInOutQuad",
"id": "talk02",
"interpDuration": 1,
"interpTarget": 1,
"interpDuration": 20,
"interpTarget": 20,
"interpType": "evaluateBoth",
"priority": 0.33,
"resume": true,
@ -2500,8 +2500,8 @@
{
"easingType": "easeInOutQuad",
"id": "talk03",
"interpDuration": 1,
"interpTarget": 1,
"interpDuration": 20,
"interpTarget": 20,
"interpType": "evaluateBoth",
"priority": 0.33,
"resume": true,
@ -2511,8 +2511,8 @@
{
"easingType": "easeInOutQuad",
"id": "talk04",
"interpDuration": 1,
"interpTarget": 1,
"interpDuration": 20,
"interpTarget": 20,
"interpType": "evaluateBoth",
"priority": 0.33,
"resume": true,
@ -2522,8 +2522,8 @@
{
"easingType": "easeInOutQuad",
"id": "talk_armsdown",
"interpDuration": 1,
"interpTarget": 1,
"interpDuration": 20,
"interpTarget": 20,
"interpType": "evaluateBoth",
"priority": 0.33,
"resume": true,
@ -2533,8 +2533,8 @@
{
"easingType": "easeInOutQuad",
"id": "talk_lefthand",
"interpDuration": 1,
"interpTarget": 1,
"interpDuration": 20,
"interpTarget": 20,
"interpType": "evaluateBoth",
"priority": 0.33,
"resume": true,
@ -2544,8 +2544,8 @@
{
"easingType": "easeInOutQuad",
"id": "talk_righthand",
"interpDuration": 1,
"interpTarget": 1,
"interpDuration": 20,
"interpTarget": 20,
"interpType": "evaluateBoth",
"priority": 0.33,
"resume": true,
@ -4736,32 +4736,6 @@
},
{
"children": [
{
"children": [
],
"data": {
"endFrame": 30,
"loopFlag": true,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/side_step_short_left.fbx"
},
"id": "strafeLeftShortStep_c",
"type": "clip"
},
{
"children": [
],
"data": {
"endFrame": 20,
"loopFlag": true,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/side_step_left.fbx"
},
"id": "strafeLeftStep_c",
"type": "clip"
},
{
"children": [
],
@ -4819,8 +4793,6 @@
"alpha": 0,
"alphaVar": "moveLateralAlpha",
"characteristicSpeeds": [
0.1,
0.5,
1,
2.55,
3.35,
@ -4834,34 +4806,6 @@
},
{
"children": [
{
"children": [
],
"data": {
"endFrame": 30,
"loopFlag": true,
"mirrorFlag": true,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/side_step_short_left.fbx"
},
"id": "strafeRightShortStep_c",
"type": "clip"
},
{
"children": [
],
"data": {
"endFrame": 20,
"loopFlag": true,
"mirrorFlag": true,
"startFrame": 1,
"timeScale": 1,
"url": "qrc:///avatar/animations/side_step_left.fbx"
},
"id": "strafeRightStep_c",
"type": "clip"
},
{
"children": [
],
@ -4923,8 +4867,6 @@
"alpha": 0,
"alphaVar": "moveLateralAlpha",
"characteristicSpeeds": [
0.1,
0.5,
1,
2.55,
3.4,
@ -5242,62 +5184,6 @@
"interpTarget": 6,
"interpType": "evaluateBoth",
"transitions": [
{
"state": "idle",
"var": "isNotInput"
},
{
"state": "WALKFWD",
"var": "isInputForward"
},
{
"state": "WALKBWD",
"var": "isInputBackward"
},
{
"state": "STRAFERIGHT",
"var": "isInputRight"
},
{
"state": "STRAFELEFT",
"var": "isInputLeft"
},
{
"state": "turnRight",
"var": "isTurningRight"
},
{
"state": "turnLeft",
"var": "isTurningLeft"
},
{
"state": "fly",
"var": "isFlying"
},
{
"state": "takeoffStand",
"var": "isTakeoffStand"
},
{
"state": "TAKEOFFRUN",
"var": "isTakeoffRun"
},
{
"state": "inAirStand",
"var": "isInAirStand"
},
{
"state": "INAIRRUN",
"var": "isInAirRun"
},
{
"state": "strafeRightHmd",
"var": "isMovingRightHmd"
},
{
"state": "strafeLeftHmd",
"var": "isMovingLeftHmd"
},
{
"state": "idle",
"var": "isNotSeated"
@ -5307,7 +5193,7 @@
{
"easingType": "easeInOutQuad",
"id": "idle",
"interpDuration": 20,
"interpDuration": 15,
"interpTarget": 20,
"interpType": "evaluateBoth",
"transitions": [
@ -5439,8 +5325,8 @@
{
"easingType": "easeInOutQuad",
"id": "idleSettle",
"interpDuration": 15,
"interpTarget": 15,
"interpDuration": 13,
"interpTarget": 14,
"interpType": "snapshotPrev",
"transitions": [
{
@ -5533,7 +5419,7 @@
"transitions": [
{
"state": "idleSettle",
"var": "isNotInput"
"var": "isNotInputSlow"
},
{
"state": "WALKBWD",
@ -5597,7 +5483,7 @@
"transitions": [
{
"state": "idleSettle",
"var": "isNotInput"
"var": "isNotInputSlow"
},
{
"state": "WALKFWD",
@ -5661,7 +5547,7 @@
"transitions": [
{
"state": "idleSettle",
"var": "isNotInput"
"var": "isNotInputSlow"
},
{
"state": "WALKFWD",
@ -5673,7 +5559,7 @@
},
{
"state": "STRAFELEFT",
"var": "isInputLeft"
"var": "isMovingLeft"
},
{
"state": "turnRight",
@ -5725,7 +5611,7 @@
"transitions": [
{
"state": "idleSettle",
"var": "isNotInput"
"var": "isNotInputSlow"
},
{
"state": "WALKFWD",
@ -5737,7 +5623,7 @@
},
{
"state": "STRAFERIGHT",
"var": "isInputRight"
"var": "isMovingRight"
},
{
"state": "turnRight",

View file

@ -78,6 +78,15 @@
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [
["Keyboard.Left"],
["Keyboard.Right"]
]
},
"when": ["Application.CameraFirstPersonLookat", "!Keyboard.Shift"],
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [
["Keyboard.Left"],
["Keyboard.Right"]
@ -113,7 +122,16 @@
"when": ["Application.CameraFirstPerson", "!Keyboard.Control"],
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [
["Keyboard.A"],
["Keyboard.D"]
]
},
"when": ["Application.CameraFirstPersonLookat", "!Keyboard.Control"],
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [
["Keyboard.A"],
["Keyboard.D"]
@ -149,6 +167,15 @@
"when": "Application.CameraFirstPerson",
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [
["Keyboard.TouchpadLeft"],
["Keyboard.TouchpadRight"]
]
},
"when": "Application.CameraFirstPersonLookat",
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [
["Keyboard.TouchpadLeft"],
@ -222,10 +249,12 @@
{ "from": "Keyboard.Left", "when": "Keyboard.Shift", "to": "Actions.LATERAL_LEFT" },
{ "from": "Keyboard.Right", "when": "Keyboard.Shift", "to": "Actions.LATERAL_RIGHT" },
{ "from": "Keyboard.Up", "when": "Application.CameraFirstPerson", "to": "Actions.LONGITUDINAL_FORWARD" },
{ "from": "Keyboard.Up", "when": "Application.CameraFirstPersonLookat", "to": "Actions.LONGITUDINAL_FORWARD" },
{ "from": "Keyboard.Up", "when": "Application.CameraThirdPerson", "to": "Actions.LONGITUDINAL_FORWARD" },
{ "from": "Keyboard.Up", "when": "Application.CameraLookAt", "to": "Actions.LONGITUDINAL_FORWARD" },
{ "from": "Keyboard.Up", "when": "Application.CameraSelfie", "to": "Actions.LONGITUDINAL_BACKWARD" },
{ "from": "Keyboard.Down", "when": "Application.CameraFirstPerson", "to": "Actions.LONGITUDINAL_BACKWARD" },
{ "from": "Keyboard.Down", "when": "Application.CameraFirstPersonLookat", "to": "Actions.LONGITUDINAL_BACKWARD" },
{ "from": "Keyboard.Down", "when": "Application.CameraThirdPerson", "to": "Actions.LONGITUDINAL_BACKWARD" },
{ "from": "Keyboard.Down", "when": "Application.CameraLookAt", "to": "Actions.LONGITUDINAL_BACKWARD" },
{ "from": "Keyboard.Down", "when": "Application.CameraSelfie", "to": "Actions.LONGITUDINAL_FORWARD" },

View file

@ -33,6 +33,12 @@ Item {
property var item: null
function load(url, scriptUrl) {
// Ensure we reset any existing item to "about:blank" to ensure web audio stops: DEV-2375
if (root.item != null) {
root.item.url = "about:blank"
root.item.destroy()
root.item = null
}
QmlSurface.load("./controls/WebView.qml", root, function(newItem) {
root.item = newItem
root.item.url = url

View file

@ -580,8 +580,9 @@ Rectangle {
sendToScript(msg);
} else if (msg.method === "showInvalidatedLightbox") {
lightboxPopup.titleText = "Item Invalidated";
lightboxPopup.bodyText = 'Your item is marked "invalidated" because this item has been suspended ' +
"from the Marketplace due to a claim against its author.";
lightboxPopup.bodyText = 'This item has been invalidated and is no longer available.<br>' +
'If you have questions, please contact marketplace@highfidelity.com.<br>' +
'Thank you!';
lightboxPopup.button1text = "CLOSE";
lightboxPopup.button1method = function() {
lightboxPopup.visible = false;

View file

@ -9,6 +9,7 @@
//
import QtQuick 2.10
import QtQuick.Layouts 1.3
import "../simplifiedConstants" as SimplifiedConstants
import "../simplifiedControls" as SimplifiedControls
import "./components" as AvatarAppComponents
@ -79,7 +80,11 @@ Rectangle {
errorText.text = "There was a problem while retrieving your inventory. " +
"Please try closing and re-opening the Avatar app.\n\nInventory status: " + result.status + "\nMessage: " + result.message;
} else if (result.data && result.data.assets && result.data.assets.length === 0 && avatarAppInventoryModel.count === 0) {
errorText.text = "You have not created any avatars yet! Create an avatar with the Avatar Creator, then close and re-open the Avatar App."
emptyInventoryContainer.visible = true;
}
if (Settings.getValue("simplifiedUI/debugFTUE", 0) === 4) {
emptyInventoryContainer.visible = true;
}
avatarAppInventoryModel.handlePage(result.status !== "success" && result.message, result);
@ -140,8 +145,95 @@ Rectangle {
anchors.rightMargin: 24
}
Item {
id: emptyInventoryContainer
visible: false
anchors.top: displayNameHeader.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
Flickable {
id: emptyInventoryFlickable
anchors.fill: parent
contentWidth: parent.width
contentHeight: emptyInventoryLayout.height
clip: true
ColumnLayout {
id: emptyInventoryLayout
anchors.top: parent.top
anchors.left: parent.left
anchors.leftMargin: 26
anchors.right: parent.right
anchors.rightMargin: 26
spacing: 0
HifiStylesUit.GraphikSemiBold {
text: "Stand out from the crowd!"
Layout.preferredWidth: parent.width
Layout.preferredHeight: paintedHeight
Layout.topMargin: 16
size: 28
color: simplifiedUI.colors.text.white
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
}
HifiStylesUit.GraphikRegular {
text: "Create your custom avatar."
Layout.preferredWidth: parent.width
Layout.preferredHeight: paintedHeight
Layout.topMargin: 2
size: 18
wrapMode: Text.Wrap
color: simplifiedUI.colors.text.white
horizontalAlignment: Text.AlignHCenter
}
Image {
id: avatarImage;
source: "images/avatarProfilePic.png"
Layout.preferredWidth: parent.width
Layout.preferredHeight: 450
Layout.alignment: Qt.AlignHCenter
mipmap: true
fillMode: Image.PreserveAspectFit
}
Image {
source: "images/qrCode.jpg"
Layout.preferredWidth: 190
Layout.preferredHeight: 190
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: -160
mipmap: true
fillMode: Image.PreserveAspectFit
}
HifiStylesUit.GraphikSemiBold {
text: "Scan for Mobile App"
Layout.preferredWidth: parent.width
Layout.preferredHeight: paintedHeight
Layout.topMargin: 12
size: 28
color: simplifiedUI.colors.text.white
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
}
}
}
SimplifiedControls.VerticalScrollBar {
parent: emptyInventoryFlickable
}
}
Item {
id: avatarInfoTextContainer
visible: !emptyInventoryContainer.visible
width: parent.implicitWidth
height: childrenRect.height
anchors.top: displayNameHeader.bottom
@ -164,7 +256,7 @@ Rectangle {
id: yourAvatarsSubtitle
text: "These are the avatars that you've created and uploaded via the Avatar Creator."
width: parent.width
wrapMode: Text.WordWrap
wrapMode: Text.Wrap
anchors.top: yourAvatarsTitle.bottom
anchors.topMargin: 6
verticalAlignment: TextInput.AlignVCenter
@ -208,9 +300,10 @@ Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
visible: !emptyInventoryContainer.visible
AnimatedImage {
visible: !inventoryContentsList.visible && !errorText.visible
visible: !(inventoryContentsList.visible || errorText.visible)
anchors.centerIn: parent
width: 72
height: width
@ -271,6 +364,8 @@ Rectangle {
return;
}
}
root.avatarPreviewUrl = "../../images/defaultAvatar.svg";
}
function fromScript(message) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

View file

@ -225,9 +225,9 @@ Flickable {
SimplifiedControls.RadioButton {
id: firstPerson
text: "First Person View"
checked: Camera.mode === "first person"
checked: Camera.mode === "first person look at"
onClicked: {
Camera.mode = "first person"
Camera.mode = "first person look at"
}
}
@ -254,7 +254,7 @@ Flickable {
target: Camera
onModeUpdated: {
if (Camera.mode === "first person") {
if (Camera.mode === "first person look at") {
firstPerson.checked = true
} else if (Camera.mode === "look at") {
thirdPerson.checked = true

View file

@ -54,8 +54,8 @@ Rectangle {
if ((MyAvatar.skeletonModelURL.indexOf("defaultAvatar") > -1 || MyAvatar.skeletonModelURL.indexOf("fst") === -1) &&
topBarInventoryModel.count > 0) {
Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatar", true);
MyAvatar.useFullAvatarURL = topBarInventoryModel.get(0).download_url;
Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatarFromInventory", true);
MyAvatar.useFullAvatarURL(topBarInventoryModel.get(0).download_url);
}
}
}
@ -71,7 +71,7 @@ Rectangle {
if (isLoggedIn) {
Commerce.getWalletStatus();
} else {
// Show some error to the user
// Show some error to the user in the UI?
}
}
@ -113,12 +113,68 @@ Rectangle {
topBarInventoryModel.getNextPage();
} else {
inventoryFullyReceived = true;
var scriptExecutionCount = Settings.getValue("simplifiedUI/SUIScriptExecutionCount");
var currentAvatarURL = MyAvatar.skeletonModelURL;
var currentAvatarURLContainsDefaultAvatar = currentAvatarURL.indexOf("defaultAvatar") > -1;
var currentAvatarURLContainsFST = currentAvatarURL.indexOf("fst") > -1;
var currentAvatarURLContainsSimplifiedAvatar = currentAvatarURL.indexOf("simplifiedAvatar") > -1;
var alreadyAutoSelectedAvatarFromInventory = Settings.getValue("simplifiedUI/alreadyAutoSelectedAvatarFromInventory", false);
var userHasValidAvatarInInventory = topBarInventoryModel.count > 0 &&
topBarInventoryModel.get(0).download_url.indexOf(".fst") > -1;
var simplifiedAvatarPrefix = "https://content.highfidelity.com/Experiences/Releases/simplifiedUI/simplifiedFTUE/avatars/simplifiedAvatar_";
var simplifiedAvatarColors = ["Blue", "Cyan", "Green", "Magenta", "Red"];
var simplifiedAvatarSuffix = "/avatar.fst";
// If we have an avatar in our inventory AND we haven't already auto-selected an avatar...
if ((!Settings.getValue("simplifiedUI/alreadyAutoSelectedAvatar", false) ||
MyAvatar.skeletonModelURL.indexOf("defaultAvatar") > -1 || MyAvatar.skeletonModelURL.indexOf("fst") === -1) && topBarInventoryModel.count > 0) {
Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatar", true);
MyAvatar.skeletonModelURL = topBarInventoryModel.get(0).download_url;
// Use `Settings.setValue("simplifiedUI/debugFTUE", 0);` to turn off FTUE Debug Mode.
// Use `Settings.setValue("simplifiedUI/debugFTUE", 1);` to debug FTUE Screen 1.
// Use `Settings.setValue("simplifiedUI/debugFTUE", 2);` to debug FTUE Screen 2.
// Use `Settings.setValue("simplifiedUI/debugFTUE", 3);` to debug FTUE Screen 3.
// Use `Settings.setValue("simplifiedUI/debugFTUE", 4);` to force the UI to show what would happen if the user had an empty Inventory.
var debugFTUE = Settings.getValue("simplifiedUI/debugFTUE", 0);
if (debugFTUE === 1 || debugFTUE === 2) {
scriptExecutionCount = 1;
currentAvatarURLContainsDefaultAvatar = true;
if (debugFTUE === 1) {
userHasValidAvatarInInventory = false;
currentAvatarURLContainsSimplifiedAvatar = false;
}
} else if (debugFTUE === 3) {
scriptExecutionCount = 2;
currentAvatarURLContainsDefaultAvatar = false;
currentAvatarURLContainsSimplifiedAvatar = true;
}
// If we have never auto-selected and the user is still using a default avatar or if the current avatar is not valid (fst), or if
// the current avatar is the old default (Woody), use top avatar from inventory or one of the new defaults.
// If the current avatar URL is invalid, OR the user is using the "default avatar" (Woody)...
if (!currentAvatarURLContainsFST || currentAvatarURLContainsDefaultAvatar) {
// If the user has a valid avatar in their inventory...
if (userHasValidAvatarInInventory) {
// ...use the first avatar in the user's inventory.
MyAvatar.useFullAvatarURL(topBarInventoryModel.get(0).download_url);
Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatarFromInventory", true);
// Else if the user isn't wearing a "Simplified Avatar"
} else if (!currentAvatarURLContainsSimplifiedAvatar) {
// ...assign to the user a new "Simplified Avatar" (i.e. a simple avatar of random color)
var avatarColor = simplifiedAvatarColors[Math.floor(Math.random() * simplifiedAvatarColors.length)];
var simplifiedAvatarModelURL = simplifiedAvatarPrefix + avatarColor + simplifiedAvatarSuffix;
MyAvatar.useFullAvatarURL(simplifiedAvatarModelURL);
currentAvatarURLContainsSimplifiedAvatar = true;
}
}
if (scriptExecutionCount === 1) {
sendToScript({
"source": "SimplifiedTopBar.qml",
"method": "displayInitialLaunchWindow"
});
} else if (scriptExecutionCount === 2 && currentAvatarURLContainsSimplifiedAvatar) {
sendToScript({
"source": "SimplifiedTopBar.qml",
"method": "displaySecondLaunchWindow"
});
}
}
}
@ -373,7 +429,7 @@ Rectangle {
SimplifiedControls.TextField {
id: goToTextField
readonly property string shortPlaceholderText: "Jump to..."
readonly property string longPlaceholderText: "Type the name of a location to quickly jump there..."
readonly property string longPlaceholderText: "Quickly jump to a location by typing '/LocationName'"
anchors.centerIn: parent
width: Math.min(parent.width, 445)
height: 35
@ -384,6 +440,7 @@ Rectangle {
placeholderTextColor: "#8E8E8E"
font.pixelSize: 14
placeholderText: width - leftPadding - rightPadding < goToTextFieldMetrics.width ? shortPlaceholderText : longPlaceholderText
blankPlaceholderTextOnFocus: false
clip: true
selectByMouse: true
autoScroll: true
@ -555,7 +612,7 @@ Rectangle {
}
function updatePreviewUrl() {
function updatePreviewUrl() {
var previewUrl = "";
var downloadUrl = "";
for (var i = 0; i < topBarInventoryModel.count; ++i) {
@ -569,6 +626,8 @@ Rectangle {
return;
}
}
avatarButtonImage.source = "../images/defaultAvatar.svg";
}

View file

@ -718,6 +718,7 @@ private:
static const QString STATE_IN_HMD = "InHMD";
static const QString STATE_CAMERA_FULL_SCREEN_MIRROR = "CameraFSM";
static const QString STATE_CAMERA_FIRST_PERSON = "CameraFirstPerson";
static const QString STATE_CAMERA_FIRST_PERSON_LOOK_AT = "CameraFirstPersonLookat";
static const QString STATE_CAMERA_THIRD_PERSON = "CameraThirdPerson";
static const QString STATE_CAMERA_ENTITY = "CameraEntity";
static const QString STATE_CAMERA_INDEPENDENT = "CameraIndependent";
@ -939,7 +940,8 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
DependencyManager::set<AudioInjectorManager>();
DependencyManager::set<MessagesClient>();
controller::StateController::setStateVariables({ { STATE_IN_HMD, STATE_CAMERA_FULL_SCREEN_MIRROR,
STATE_CAMERA_FIRST_PERSON, STATE_CAMERA_THIRD_PERSON, STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT, STATE_CAMERA_LOOK_AT, STATE_CAMERA_SELFIE,
STATE_CAMERA_FIRST_PERSON, STATE_CAMERA_FIRST_PERSON_LOOK_AT, STATE_CAMERA_THIRD_PERSON,
STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT, STATE_CAMERA_LOOK_AT, STATE_CAMERA_SELFIE,
STATE_SNAP_TURN, STATE_ADVANCED_MOVEMENT_CONTROLS, STATE_GROUNDED, STATE_NAV_FOCUSED,
STATE_PLATFORM_WINDOWS, STATE_PLATFORM_MAC, STATE_PLATFORM_ANDROID, STATE_LEFT_HAND_DOMINANT, STATE_RIGHT_HAND_DOMINANT, STATE_STRAFE_ENABLED } });
DependencyManager::set<UserInputMapper>();
@ -974,6 +976,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
QObject::connect(PlatformHelper::instance(), &PlatformHelper::systemWillWake, [] {
QMetaObject::invokeMethod(DependencyManager::get<NodeList>().data(), "noteAwakening", Qt::QueuedConnection);
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "noteAwakening", Qt::QueuedConnection);
});
@ -1886,6 +1889,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
_applicationStateDevice->setInputVariant(STATE_CAMERA_FIRST_PERSON, []() -> float {
return qApp->getCamera().getMode() == CAMERA_MODE_FIRST_PERSON ? 1 : 0;
});
_applicationStateDevice->setInputVariant(STATE_CAMERA_FIRST_PERSON_LOOK_AT, []() -> float {
return qApp->getCamera().getMode() == CAMERA_MODE_FIRST_PERSON_LOOK_AT ? 1 : 0;
});
_applicationStateDevice->setInputVariant(STATE_CAMERA_THIRD_PERSON, []() -> float {
return qApp->getCamera().getMode() == CAMERA_MODE_THIRD_PERSON ? 1 : 0;
});
@ -1995,7 +2001,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
settingsTimer->start();
}, QThread::LowestPriority);
if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPersonLookAt)) {
getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN); // So that camera doesn't auto-switch to third person.
}
@ -2958,13 +2964,29 @@ Application::~Application() {
qInstallMessageHandler(LogHandler::verboseMessageHandler);
#ifdef Q_OS_MAC
// 10/16/2019 - Disabling this call. This causes known crashes (A), and it is not
// fully understood whether it might cause other unknown crashes (B).
//
// (A) Although we try to shutdown the ScriptEngine threads in onAboutToQuit, there is
// currently no guarantee that they have stopped. Waiting on them to stop has so far appeared to
// never return on Mac, causing the application to hang on shutdown. Because ScriptEngines
// may still be running, they may end up receiving events that are triggered from this processEvents call,
// and then try to access resources that are no longer available at this point in time.
// If the ScriptEngine threads were fully destroyed before getting here, this would
// not be an issue.
//
// (B) It seems likely that a bunch of potential event handlers are dependent on Application
// and other common dependencies to be available and not destroyed or in the middle of being
// destroyed.
// Clear the event queue before application is totally destructed.
// This will drain the messasge queue of pending "deleteLaters" queued up
// during shutdown of the script engines.
// We do this here because there is a possiblty that [NSApplication terminate:]
// will be called during processEvents which will invoke all static destructors.
// We want to postpone this utill the last possible moment.
QCoreApplication::processEvents();
//QCoreApplication::processEvents();
#endif
}
@ -3610,14 +3632,17 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) {
// Using the latter will cause the camera to wobble with idle animations,
// or with changes from the face tracker
CameraMode mode = _myCamera.getMode();
if (mode == CAMERA_MODE_FIRST_PERSON) {
if (mode == CAMERA_MODE_FIRST_PERSON || mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT) {
_thirdPersonHMDCameraBoomValid= false;
if (isHMDMode()) {
mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
_myCamera.setPosition(extractTranslation(camMat));
_myCamera.setOrientation(glmExtractRotation(camMat));
} else if (mode == CAMERA_MODE_FIRST_PERSON) {
_myCamera.setPosition(myAvatar->getDefaultEyePosition());
_myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation());
} else {
_myCamera.setPosition(myAvatar->getLookAtPivotPoint());
_myCamera.setPosition(myAvatar->getCameraEyesPosition(deltaTime));
_myCamera.setOrientation(myAvatar->getLookAtRotation());
}
} else if (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE) {
@ -4406,7 +4431,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
case Qt::Key_1: {
Menu* menu = Menu::getInstance();
menu->triggerOption(MenuOption::FirstPerson);
menu->triggerOption(MenuOption::FirstPersonLookAt);
break;
}
case Qt::Key_2: {
@ -5491,7 +5516,7 @@ void Application::loadSettings() {
isFirstPerson = menu->isOptionChecked(MenuOption::FirstPersonHMD);
} else {
// if HMD is not active, only use first person if the menu option is checked
isFirstPerson = menu->isOptionChecked(MenuOption::FirstPerson);
isFirstPerson = menu->isOptionChecked(MenuOption::FirstPersonLookAt);
}
}
}
@ -5506,9 +5531,9 @@ void Application::loadSettings() {
// finish initializing the camera, based on everything we checked above. Third person camera will be used if no settings
// dictated that we should be in first person
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, isFirstPerson);
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPersonLookAt, isFirstPerson);
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !isFirstPerson);
_myCamera.setMode((isFirstPerson) ? CAMERA_MODE_FIRST_PERSON : CAMERA_MODE_LOOK_AT);
_myCamera.setMode((isFirstPerson) ? CAMERA_MODE_FIRST_PERSON_LOOK_AT : CAMERA_MODE_LOOK_AT);
cameraMenuChanged();
auto inputs = pluginManager->getInputPlugins();
@ -5672,7 +5697,7 @@ void Application::pauseUntilLoginDetermined() {
menu->getMenu("Developer")->setVisible(false);
}
_previousCameraMode = _myCamera.getMode();
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON_LOOK_AT);
cameraModeChanged();
// disconnect domain handler.
@ -5861,11 +5886,11 @@ void Application::cycleCamera() {
if (menu->isOptionChecked(MenuOption::FullscreenMirror)) {
menu->setIsOptionChecked(MenuOption::FullscreenMirror, false);
menu->setIsOptionChecked(MenuOption::FirstPerson, true);
menu->setIsOptionChecked(MenuOption::FirstPersonLookAt, true);
} else if (menu->isOptionChecked(MenuOption::FirstPerson)) {
} else if (menu->isOptionChecked(MenuOption::FirstPersonLookAt)) {
menu->setIsOptionChecked(MenuOption::FirstPerson, false);
menu->setIsOptionChecked(MenuOption::FirstPersonLookAt, false);
menu->setIsOptionChecked(MenuOption::LookAtCamera, true);
} else if (menu->isOptionChecked(MenuOption::LookAtCamera)) {
@ -5884,8 +5909,8 @@ void Application::cycleCamera() {
void Application::cameraModeChanged() {
switch (_myCamera.getMode()) {
case CAMERA_MODE_FIRST_PERSON:
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, true);
case CAMERA_MODE_FIRST_PERSON_LOOK_AT:
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPersonLookAt, true);
break;
case CAMERA_MODE_LOOK_AT:
Menu::getInstance()->setIsOptionChecked(MenuOption::LookAtCamera, true);
@ -5905,12 +5930,12 @@ void Application::changeViewAsNeeded(float boomLength) {
// This is called when the boom length has changed
bool boomLengthGreaterThanMinimum = (boomLength > MyAvatar::ZOOM_MIN);
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON && boomLengthGreaterThanMinimum) {
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, false);
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON_LOOK_AT && boomLengthGreaterThanMinimum) {
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPersonLookAt, false);
Menu::getInstance()->setIsOptionChecked(MenuOption::LookAtCamera, true);
cameraMenuChanged();
} else if (_myCamera.getMode() == CAMERA_MODE_LOOK_AT && !boomLengthGreaterThanMinimum) {
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, true);
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPersonLookAt, true);
Menu::getInstance()->setIsOptionChecked(MenuOption::LookAtCamera, false);
cameraMenuChanged();
}
@ -5918,9 +5943,9 @@ void Application::changeViewAsNeeded(float boomLength) {
void Application::cameraMenuChanged() {
auto menu = Menu::getInstance();
if (menu->isOptionChecked(MenuOption::FirstPerson)) {
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON) {
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
if (menu->isOptionChecked(MenuOption::FirstPersonLookAt)) {
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON_LOOK_AT) {
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON_LOOK_AT);
getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN);
}
} else if (menu->isOptionChecked(MenuOption::LookAtCamera)) {
@ -9021,7 +9046,7 @@ void Application::setDisplayPlugin(DisplayPluginPointer newDisplayPlugin) {
}
if (isHmd && menu->isOptionChecked(MenuOption::FirstPersonHMD)) {
menu->setIsOptionChecked(MenuOption::FirstPerson, true);
menu->setIsOptionChecked(MenuOption::FirstPersonLookAt, true);
cameraMenuChanged();
}

View file

@ -172,7 +172,7 @@ Menu::Menu() {
// View > First Person
auto firstPersonAction = cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(
viewMenu, MenuOption::FirstPerson, 0,
viewMenu, MenuOption::FirstPersonLookAt, 0,
true, qApp, SLOT(cameraMenuChanged())));
firstPersonAction->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(cameraModeGroup));
@ -640,11 +640,6 @@ Menu::Menu() {
}
#endif
// Developer >> Tests >>>
MenuWrapper* testMenu = developerMenu->addMenu("Tests");
addActionToQMenuAndActionHash(testMenu, MenuOption::RunClientScriptTests, 0, dialogsManager.data(), SLOT(showTestingResults()));
// Developer > Timing >>>
MenuWrapper* timingMenu = developerMenu->addMenu("Timing");
MenuWrapper* perfTimerMenu = timingMenu->addMenu("Performance Timer");

View file

@ -111,7 +111,8 @@ namespace MenuOption {
const QString ExpandSimulationTiming = "Expand /simulation";
const QString ExpandPhysicsTiming = "Expand /physics";
const QString ExpandUpdateTiming = "Expand /update";
const QString FirstPerson = "First Person";
const QString FirstPerson = "First Person Legacy";
const QString FirstPersonLookAt = "First Person";
const QString FirstPersonHMD = "Enter First Person Mode in HMD";
const QString FivePointCalibration = "5 Point Calibration";
const QString FixGaze = "Fix Gaze (no saccade)";
@ -178,7 +179,6 @@ namespace MenuOption {
const QString ResetAvatarSize = "Reset Avatar Size";
const QString ResetSensors = "Reset Sensors";
const QString RunningScripts = "Running Scripts...";
const QString RunClientScriptTests = "Run Client Script Tests";
const QString RunTimingTests = "Run Timing Tests";
const QString ScriptedMotorControl = "Enable Scripted Motor Control";
const QString ShowTrackedObjects = "Show Tracked Objects";

View file

@ -152,7 +152,7 @@ static int triggerReactionNameToIndex(const QString& reactionName) {
}
static int beginEndReactionNameToIndex(const QString& reactionName) {
assert(NUM_AVATAR_BEGIN_END_REACTIONS == TRIGGER_REACTION_NAMES.size());
assert(NUM_AVATAR_BEGIN_END_REACTIONS == BEGIN_END_REACTION_NAMES.size());
return BEGIN_END_REACTION_NAMES.indexOf(reactionName);
}
@ -958,7 +958,8 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
head->setScale(getModelScale());
head->simulate(deltaTime);
CameraMode mode = qApp->getCamera().getMode();
if (_scriptControlsHeadLookAt || mode == CAMERA_MODE_FIRST_PERSON || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE) {
if (_scriptControlsHeadLookAt || mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT || mode == CAMERA_MODE_FIRST_PERSON ||
mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE) {
if (!_pointAtActive || !_isPointTargetValid) {
updateHeadLookAt(deltaTime);
} else {
@ -2178,7 +2179,7 @@ void MyAvatar::computeMyLookAtTarget(const AvatarHash& hash) {
glm::vec3 myForward = _lookAtYaw * IDENTITY_FORWARD;
glm::vec3 myPosition = getHead()->getEyePosition();
CameraMode mode = qApp->getCamera().getMode();
if (mode == CAMERA_MODE_FIRST_PERSON) {
if (mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT || mode == CAMERA_MODE_FIRST_PERSON) {
myPosition = qApp->getCamera().getPosition();
}
@ -2719,7 +2720,7 @@ void MyAvatar::updateMotors() {
if (_characterController.getState() == CharacterController::State::Hover ||
_characterController.computeCollisionMask() == BULLET_COLLISION_MASK_COLLISIONLESS) {
CameraMode mode = qApp->getCamera().getMode();
if (mode == CAMERA_MODE_FIRST_PERSON || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE) {
if (!qApp->isHMDMode() && (mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE)) {
motorRotation = getLookAtRotation();
} else {
motorRotation = getMyHead()->getHeadOrientation();
@ -3399,7 +3400,8 @@ bool MyAvatar::cameraInsideHead(const glm::vec3& cameraPosition) const {
bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const {
bool defaultMode = renderArgs->_renderMode == RenderArgs::DEFAULT_RENDER_MODE;
bool firstPerson = qApp->getCamera().getMode() == CAMERA_MODE_FIRST_PERSON;
bool firstPerson = qApp->getCamera().getMode() == CAMERA_MODE_FIRST_PERSON_LOOK_AT ||
qApp->getCamera().getMode() == CAMERA_MODE_FIRST_PERSON;
bool overrideAnim = _skeletonModel ? _skeletonModel->getRig().isPlayingOverrideAnimation() : false;
bool insideHead = cameraInsideHead(renderArgs->getViewFrustum().getPosition());
return !defaultMode || (!firstPerson && !insideHead) || (overrideAnim && !insideHead);
@ -3444,8 +3446,8 @@ void MyAvatar::updateOrientation(float deltaTime) {
float targetSpeed = getDriveKey(YAW) * _yawSpeed;
CameraMode mode = qApp->getCamera().getMode();
bool computeLookAt = isReadyForPhysics() && !qApp->isHMDMode() &&
(mode == CAMERA_MODE_FIRST_PERSON || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE);
bool smoothCameraYaw = computeLookAt && mode != CAMERA_MODE_FIRST_PERSON;
(mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE);
bool smoothCameraYaw = computeLookAt && mode != CAMERA_MODE_FIRST_PERSON_LOOK_AT;
if (smoothCameraYaw) {
// For "Look At" and "Selfie" camera modes we also smooth the yaw rotation from right-click mouse movement.
float speedFromDeltaYaw = deltaTime > FLT_EPSILON ? getDriveKey(DELTA_YAW) / deltaTime : 0.0f;
@ -3569,11 +3571,11 @@ void MyAvatar::updateOrientation(float deltaTime) {
if (isMovingFwdBwd) {
if (isMovingSideways) {
// Reorient avatar to face camera diagonal
blend = mode == CAMERA_MODE_FIRST_PERSON ? 1.0f : DIAGONAL_TURN_BLEND;
blend = mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT ? 1.0f : DIAGONAL_TURN_BLEND;
float turnSign = getDriveKey(TRANSLATE_Z) < 0.0f ? -1.0f : 1.0f;
turnSign = getDriveKey(TRANSLATE_X) > 0.0f ? -turnSign : turnSign;
faceRotation = _lookAtYaw * glm::angleAxis(turnSign * 0.25f * PI, Vectors::UP);
} else if (mode == CAMERA_MODE_FIRST_PERSON) {
} else if (mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT) {
blend = 1.0f;
}
}
@ -3644,11 +3646,11 @@ void MyAvatar::updateOrientation(float deltaTime) {
glm::vec3 ajustedYawVector = cameraYawVector;
float limitAngle = 0.0f;
float triggerAngle = -glm::sin(glm::radians(TRIGGER_REORIENT_ANGLE));
if (mode == CAMERA_MODE_FIRST_PERSON) {
if (mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT) {
limitAngle = glm::sin(glm::radians(90.0f - FIRST_PERSON_TRIGGER_REORIENT_ANGLE));
triggerAngle = limitAngle;
}
float reorientAngle = mode == CAMERA_MODE_FIRST_PERSON ? FIRST_PERSON_REORIENT_ANGLE : DEFAULT_REORIENT_ANGLE;
float reorientAngle = mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT ? FIRST_PERSON_REORIENT_ANGLE : DEFAULT_REORIENT_ANGLE;
if (frontBackDot < limitAngle) {
if (frontBackDot < 0.0f) {
ajustedYawVector = (leftRightDot < 0.0f ? -avatarVectorRight : avatarVectorRight);
@ -3684,7 +3686,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
}
_headLookAtActive = true;
const float FIRST_PERSON_RECENTER_SECONDS = 15.0f;
if (mode == CAMERA_MODE_FIRST_PERSON) {
if (mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT) {
if (getDriveKey(YAW) + getDriveKey(STEP_YAW) + getDriveKey(DELTA_YAW) == 0.0f) {
if (_firstPersonSteadyHeadTimer < FIRST_PERSON_RECENTER_SECONDS) {
if (_firstPersonSteadyHeadTimer > 0.0f) {
@ -3772,7 +3774,7 @@ glm::vec3 MyAvatar::scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 rig
// Desktop mode.
direction = (zSpeed * forward) + (xSpeed * right);
CameraMode mode = qApp->getCamera().getMode();
if ((mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_FIRST_PERSON || mode == CAMERA_MODE_SELFIE) &&
if ((mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT || mode == CAMERA_MODE_SELFIE) &&
zSpeed != 0.0f && xSpeed != 0.0f && !isFlying()){
direction = (zSpeed * forward);
}
@ -5437,7 +5439,7 @@ glm::quat MyAvatar::getOrientationForAudio() {
case AudioListenerMode::FROM_HEAD: {
// Using the camera's orientation instead, when the current mode is controlling the avatar's head.
CameraMode mode = qApp->getCamera().getMode();
bool headFollowsCamera = mode == CAMERA_MODE_FIRST_PERSON || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE;
bool headFollowsCamera = mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE;
result = headFollowsCamera ? qApp->getCamera().getOrientation() : getHead()->getFinalOrientationInWorldFrame();
break;
}
@ -6812,6 +6814,66 @@ glm::vec3 MyAvatar::getLookAtPivotPoint() {
return yAxisEyePosition;
}
glm::vec3 MyAvatar::getCameraEyesPosition(float deltaTime) {
glm::vec3 defaultEyesPosition = getLookAtPivotPoint();
if (isFlying()) {
return defaultEyesPosition;
}
glm::vec3 avatarFrontVector = getWorldOrientation() * Vectors::FRONT;
glm::vec3 avatarUpVector = getWorldOrientation() * Vectors::UP;
// Compute the offset between the default and real eye positions.
glm::vec3 defaultEyesToEyesVector = getHead()->getEyePosition() - defaultEyesPosition;
float FRONT_OFFSET_IDLE_MULTIPLIER = 2.5f;
float FRONT_OFFSET_JUMP_MULTIPLIER = 1.5f;
float frontOffset = FRONT_OFFSET_IDLE_MULTIPLIER * glm::length(defaultEyesPosition - getDefaultEyePosition());
// Looking down will aproximate move the camera forward to meet the real eye position
float mixAlpha = glm::dot(_lookAtPitch * Vectors::FRONT, -avatarUpVector);
bool isLanding = false;
// When jumping the camera should follow the real eye on the Y coordenate
float upOffset = 0.0f;
if (isJumping() || _characterController.getState() == CharacterController::State::Takeoff) {
upOffset = glm::dot(defaultEyesToEyesVector, avatarUpVector);
frontOffset = glm::dot(defaultEyesToEyesVector, avatarFrontVector) * FRONT_OFFSET_JUMP_MULTIPLIER;
mixAlpha = 1.0f;
_landingAfterJumpTime = 0.0f;
} else {
// Limit the range effect from 45 to 0 degrees
// between the front camera and the down vectors
const float HEAD_OFFSET_RANGE_IN_DEGREES = 45.0f;
const float HEAD_OFFSET_RANGE_OUT_DEGREES = 0.0f;
float rangeIn = glm::cos(glm::radians(HEAD_OFFSET_RANGE_IN_DEGREES));
float rangeOut = glm::cos(glm::radians(HEAD_OFFSET_RANGE_OUT_DEGREES));
mixAlpha = mixAlpha < rangeIn ? 0.0f : (mixAlpha - rangeIn) / (rangeOut - rangeIn);
const float WAIT_TO_LAND_TIME = 1.0f;
if (_landingAfterJumpTime < WAIT_TO_LAND_TIME) {
_landingAfterJumpTime += deltaTime;
isLanding = true;
}
}
const float FPS = 60.0f;
float timeScale = deltaTime * FPS;
frontOffset = frontOffset < 0.0f ? 0.0f : mixAlpha * frontOffset;
glm::vec3 cameraOffset = upOffset * Vectors::UP + frontOffset * Vectors::FRONT;
const float JUMPING_TAU = 0.1f;
const float NO_JUMP_TAU = 0.3f;
const float LANDING_TAU = 0.05f;
float tau = NO_JUMP_TAU;
if (isJumping()) {
tau = JUMPING_TAU;
} else if (isLanding) {
tau = LANDING_TAU;
}
_cameraEyesOffset = _cameraEyesOffset + (cameraOffset - _cameraEyesOffset) * min(1.0f, tau * timeScale);
glm::vec3 estimatedCameraPosition = defaultEyesPosition + getWorldOrientation() * _cameraEyesOffset;
return estimatedCameraPosition;
}
bool MyAvatar::isJumping() {
return (_characterController.getState() == CharacterController::State::InAir ||
_characterController.getState() == CharacterController::State::Takeoff) && !isFlying();
}
bool MyAvatar::setPointAt(const glm::vec3& pointAtTarget) {
if (QThread::currentThread() != thread()) {
bool result = false;

View file

@ -1919,6 +1919,8 @@ public:
bool getIsJointOverridden(int jointIndex) const;
glm::vec3 getLookAtPivotPoint();
glm::vec3 getCameraEyesPosition(float deltaTime);
bool isJumping();
public slots:
@ -2973,6 +2975,9 @@ private:
// used to prevent character from jumping after endSit is called.
bool _endSitKeyPressComplete { false };
glm::vec3 _cameraEyesOffset;
float _landingAfterJumpTime { 0.0f };
};
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);

View file

@ -52,6 +52,23 @@ static const QVariantMap DOCK_AREA {
{ "RIGHT", DockArea::RIGHT }
};
/**jsdoc
* The possible "relative position anchors" of an <code>InteractiveWindow</code>. Used when defining the `relativePosition` property of an `InteractiveWindow`.
* @typedef {object} InteractiveWindow.RelativePositionAnchors
* @property {InteractiveWindow.RelativePositionAnchor} NO_ANCHOR - Specifies that the position of the `InteractiveWindow` will not be relative to any part of the Interface window.
* @property {InteractiveWindow.RelativePositionAnchor} TOP_LEFT - Specifies that the `relativePosition` of the `InteractiveWindow` will be offset from the top left of the Interface window.
* @property {InteractiveWindow.RelativePositionAnchor} TOP_RIGHT - Specifies that the `relativePosition` of the `InteractiveWindow` will be offset from the top right of the Interface window.
* @property {InteractiveWindow.RelativePositionAnchor} BOTTOM_RIGHT - Specifies that the `relativePosition` of the `InteractiveWindow` will be offset from the bottom right of the Interface window.
* @property {InteractiveWindow.RelativePositionAnchor} BOTTOM_LEFT - Specifies that the `relativePosition` of the `InteractiveWindow` will be offset from the bottom left of the Interface window.
*/
static const QVariantMap RELATIVE_POSITION_ANCHOR {
{ "NO_ANCHOR", RelativePositionAnchor::NO_ANCHOR },
{ "TOP_LEFT", RelativePositionAnchor::TOP_LEFT },
{ "TOP_RIGHT", RelativePositionAnchor::TOP_RIGHT },
{ "BOTTOM_RIGHT", RelativePositionAnchor::BOTTOM_RIGHT },
{ "BOTTOM_LEFT", RelativePositionAnchor::BOTTOM_LEFT }
};
DesktopScriptingInterface::DesktopScriptingInterface(QObject* parent, bool restricted)
: QObject(parent), _restricted(restricted) { }
@ -99,6 +116,10 @@ QVariantMap DesktopScriptingInterface::getDockArea() {
return DOCK_AREA;
}
QVariantMap DesktopScriptingInterface::getRelativePositionAnchor() {
return RELATIVE_POSITION_ANCHOR;
}
void DesktopScriptingInterface::setHUDAlpha(float alpha) {
qApp->getApplicationCompositor().setAlpha(alpha);
}

View file

@ -42,6 +42,9 @@
* @property {InteractiveWindow.DockAreas} DockArea - The possible docking locations of an {@link InteractiveWindow}: top,
* bottom, left, or right of the Interface window.
* <em>Read-only.</em>
* @property {InteractiveWindow.RelativePositionAnchors} RelativePositionAnchor - The possible "relative position anchors" for an {@link InteractiveWindow}: top left,
* top right, bottom right, or bottom left of the Interface window.
* <em>Read-only.</em>
*/
class DesktopScriptingInterface : public QObject, public Dependency {
Q_OBJECT
@ -50,6 +53,7 @@ class DesktopScriptingInterface : public QObject, public Dependency {
Q_PROPERTY(QVariantMap PresentationMode READ getPresentationMode CONSTANT FINAL)
Q_PROPERTY(QVariantMap DockArea READ getDockArea CONSTANT FINAL)
Q_PROPERTY(QVariantMap RelativePositionAnchor READ getRelativePositionAnchor CONSTANT FINAL)
Q_PROPERTY(int ALWAYS_ON_TOP READ flagAlwaysOnTop CONSTANT FINAL)
Q_PROPERTY(int CLOSE_BUTTON_HIDES READ flagCloseButtonHides CONSTANT FINAL)
@ -106,7 +110,7 @@ private:
Q_INVOKABLE InteractiveWindowPointer createWindowOnThread(const QString& sourceUrl, const QVariantMap& properties, QThread* targetThread);
static QVariantMap getDockArea();
static QVariantMap getRelativePositionAnchor();
Q_INVOKABLE static QVariantMap getPresentationMode();
const bool _restricted;
};

View file

@ -82,11 +82,18 @@ void RenderScriptingInterface::forceShadowsEnabled(bool enabled) {
_shadowsEnabled = (enabled);
_shadowsEnabledSetting.set(enabled);
auto lightingModelConfig = qApp->getRenderEngine()->getConfiguration()->getConfig<MakeLightingModel>("RenderMainView.LightingModel");
auto renderConfig = qApp->getRenderEngine()->getConfiguration();
assert(renderConfig);
auto lightingModelConfig = renderConfig->getConfig<MakeLightingModel>("RenderMainView.LightingModel");
if (lightingModelConfig) {
Menu::getInstance()->setIsOptionChecked(MenuOption::Shadows, enabled);
lightingModelConfig->setShadow(enabled);
}
auto secondaryLightingModelConfig = renderConfig->getConfig<MakeLightingModel>("RenderSecondView.LightingModel");
if (secondaryLightingModelConfig) {
Menu::getInstance()->setIsOptionChecked(MenuOption::Shadows, enabled);
secondaryLightingModelConfig->setShadow(enabled);
}
});
}

View file

@ -186,15 +186,6 @@ void DialogsManager::setAddressBarVisible(bool addressBarVisible) {
emit addressBarShown(_addressBarVisible);
}
void DialogsManager::showTestingResults() {
if (!_testingDialog) {
_testingDialog = new TestingDialog(qApp->getWindow());
connect(_testingDialog, SIGNAL(closed()), _testingDialog, SLOT(deleteLater()));
}
_testingDialog->show();
_testingDialog->raise();
}
void DialogsManager::showDomainConnectionDialog() {
// if the dialog already exists we delete it so the connection data is refreshed
if (_domainConnectionDialog) {

View file

@ -53,7 +53,6 @@ public slots:
void lodTools();
void hmdTools(bool showTools);
void showDomainConnectionDialog();
void showTestingResults();
void toggleAddressBar();
// Application Update

View file

@ -39,6 +39,9 @@ static const char* const ADDITIONAL_FLAGS_PROPERTY = "additionalFlags";
static const char* const OVERRIDE_FLAGS_PROPERTY = "overrideFlags";
static const char* const SOURCE_PROPERTY = "source";
static const char* const TITLE_PROPERTY = "title";
static const char* const RELATIVE_POSITION_ANCHOR_PROPERTY = "relativePositionAnchor";
static const char* const RELATIVE_POSITION_PROPERTY = "relativePosition";
static const char* const IS_FULL_SCREEN_WINDOW = "isFullScreenWindow";
static const char* const POSITION_PROPERTY = "position";
static const char* const INTERACTIVE_WINDOW_POSITION_PROPERTY = "interactiveWindowPosition";
static const char* const SIZE_PROPERTY = "size";
@ -112,6 +115,15 @@ void InteractiveWindow::forwardKeyReleaseEvent(int key, int modifiers) {
QCoreApplication::postEvent(QCoreApplication::instance(), event);
}
void InteractiveWindow::onMainWindowGeometryChanged(QRect geometry) {
// This handler is only connected `if (_isFullScreenWindow || _relativePositionAnchor != RelativePositionAnchor::NONE)`.
if (_isFullScreenWindow) {
repositionAndResizeFullScreenWindow();
} else if (_relativePositionAnchor != RelativePositionAnchor::NO_ANCHOR) {
setPositionUsingRelativePositionAndAnchor(geometry);
}
}
void InteractiveWindow::emitMainWindowResizeEvent() {
emit qApp->getWindow()->windowGeometryChanged(qApp->getWindow()->geometry());
}
@ -184,22 +196,32 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
*/
if (nativeWindowInfo.contains(DOCK_AREA_PROPERTY)) {
DockArea dockedArea = (DockArea) nativeWindowInfo[DOCK_AREA_PROPERTY].toInt();
int tempWidth = 0;
int tempHeight = 0;
switch (dockedArea) {
case DockArea::TOP:
dockArea = Qt::TopDockWidgetArea;
_dockWidget->setFixedHeight(windowSize.height());
tempHeight = windowSize.height();
_dockWidget->setFixedHeight(tempHeight);
qApp->getWindow()->setDockedWidgetRelativePositionOffset(QSize(0, -tempHeight));
break;
case DockArea::BOTTOM:
dockArea = Qt::BottomDockWidgetArea;
_dockWidget->setFixedHeight(windowSize.height());
tempHeight = windowSize.height();
_dockWidget->setFixedHeight(tempHeight);
qApp->getWindow()->setDockedWidgetRelativePositionOffset(QSize(0, tempHeight));
break;
case DockArea::LEFT:
dockArea = Qt::LeftDockWidgetArea;
_dockWidget->setFixedWidth(windowSize.width());
tempWidth = windowSize.width();
_dockWidget->setFixedWidth(tempWidth);
qApp->getWindow()->setDockedWidgetRelativePositionOffset(QSize(-tempWidth, 0));
break;
case DockArea::RIGHT:
dockArea = Qt::RightDockWidgetArea;
_dockWidget->setFixedWidth(windowSize.width());
tempWidth = windowSize.width();
_dockWidget->setFixedWidth(tempWidth);
qApp->getWindow()->setDockedWidgetRelativePositionOffset(QSize(tempWidth, 0));
break;
default:
@ -255,6 +277,9 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
if (properties.contains(TITLE_PROPERTY)) {
object->setProperty(TITLE_PROPERTY, properties[TITLE_PROPERTY].toString());
}
if (properties.contains(VISIBLE_PROPERTY)) {
object->setProperty(VISIBLE_PROPERTY, properties[INTERACTIVE_WINDOW_VISIBLE_PROPERTY].toBool());
}
if (properties.contains(SIZE_PROPERTY)) {
const auto size = vec2FromVariant(properties[SIZE_PROPERTY]);
object->setProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY, QSize(size.x, size.y));
@ -263,8 +288,21 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
const auto position = vec2FromVariant(properties[POSITION_PROPERTY]);
object->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(position.x, position.y));
}
if (properties.contains(VISIBLE_PROPERTY)) {
object->setProperty(VISIBLE_PROPERTY, properties[INTERACTIVE_WINDOW_VISIBLE_PROPERTY].toBool());
if (properties.contains(RELATIVE_POSITION_ANCHOR_PROPERTY)) {
_relativePositionAnchor = static_cast<RelativePositionAnchor>(properties[RELATIVE_POSITION_ANCHOR_PROPERTY].toInt());
}
if (properties.contains(RELATIVE_POSITION_PROPERTY)) {
_relativePosition = vec2FromVariant(properties[RELATIVE_POSITION_PROPERTY]);
setPositionUsingRelativePositionAndAnchor(qApp->getWindow()->geometry());
}
if (properties.contains(IS_FULL_SCREEN_WINDOW)) {
_isFullScreenWindow = properties[IS_FULL_SCREEN_WINDOW].toBool();
}
if (_isFullScreenWindow) {
QRect geo = qApp->getWindow()->geometry();
object->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(geo.x(), geo.y()));
object->setProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY, QSize(geo.width(), geo.height()));
}
// The qmlToScript method handles the thread-safety of this call. Because the QVariant argument
@ -288,6 +326,10 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
connect(object, SIGNAL(interactiveWindowVisibleChanged()), this, SLOT(parentNativeWindowToMainWindow()), Qt::QueuedConnection);
connect(object, SIGNAL(presentationModeChanged()), this, SLOT(parentNativeWindowToMainWindow()), Qt::QueuedConnection);
#endif
if (_isFullScreenWindow || _relativePositionAnchor != RelativePositionAnchor::NO_ANCHOR) {
connect(qApp->getWindow(), &MainWindow::windowGeometryChanged, this, &InteractiveWindow::onMainWindowGeometryChanged, Qt::QueuedConnection);
}
QUrl sourceURL{ sourceUrl };
// If the passed URL doesn't correspond to a known scheme, assume it's a local file path
@ -414,6 +456,71 @@ void InteractiveWindow::setPosition(const glm::vec2& position) {
}
}
RelativePositionAnchor InteractiveWindow::getRelativePositionAnchor() const {
return _relativePositionAnchor;
}
void InteractiveWindow::setRelativePositionAnchor(const RelativePositionAnchor& relativePositionAnchor) {
_relativePositionAnchor = relativePositionAnchor;
setPositionUsingRelativePositionAndAnchor(qApp->getWindow()->geometry());
}
glm::vec2 InteractiveWindow::getRelativePosition() const {
return _relativePosition;
}
void InteractiveWindow::setRelativePosition(const glm::vec2& relativePosition) {
_relativePosition = relativePosition;
setPositionUsingRelativePositionAndAnchor(qApp->getWindow()->geometry());
}
void InteractiveWindow::setPositionUsingRelativePositionAndAnchor(const QRect& mainWindowGeometry) {
RelativePositionAnchor relativePositionAnchor = getRelativePositionAnchor();
glm::vec2 relativePosition = getRelativePosition();
glm::vec2 newPosition;
switch (relativePositionAnchor) {
case RelativePositionAnchor::TOP_LEFT:
newPosition.x = mainWindowGeometry.x() + relativePosition.x;
newPosition.y = mainWindowGeometry.y() + relativePosition.y;
break;
case RelativePositionAnchor::TOP_RIGHT:
newPosition.x = mainWindowGeometry.x() + mainWindowGeometry.width() - relativePosition.x;
newPosition.y = mainWindowGeometry.y() + relativePosition.y;
break;
case RelativePositionAnchor::BOTTOM_RIGHT:
newPosition.x = mainWindowGeometry.x() + mainWindowGeometry.width() - relativePosition.x;
newPosition.y = mainWindowGeometry.y() + mainWindowGeometry.height() - relativePosition.y;
break;
case RelativePositionAnchor::BOTTOM_LEFT:
newPosition.x = mainWindowGeometry.x() + relativePosition.x;
newPosition.y = mainWindowGeometry.y() + mainWindowGeometry.height() - relativePosition.y;
break;
case RelativePositionAnchor::NO_ANCHOR:
// No-op.
break;
}
// Make sure we include the dimensions of the docked widget!
QSize dockedWidgetRelativePositionOffset = qApp->getWindow()->getDockedWidgetRelativePositionOffset();
newPosition.x = newPosition.x + dockedWidgetRelativePositionOffset.width();
newPosition.y = newPosition.y + dockedWidgetRelativePositionOffset.height();
if (_qmlWindowProxy) {
QMetaObject::invokeMethod(_qmlWindowProxy.get(), "writeProperty", Q_ARG(QString, INTERACTIVE_WINDOW_POSITION_PROPERTY),
Q_ARG(QVariant, QPointF(newPosition.x, newPosition.y)));
}
setPosition(newPosition);
}
void InteractiveWindow::repositionAndResizeFullScreenWindow() {
QRect windowGeometry = qApp->getWindow()->geometry();
setPosition(glm::vec2(windowGeometry.x(), windowGeometry.y()));
setSize(glm::vec2(windowGeometry.width(), windowGeometry.height()));
}
glm::vec2 InteractiveWindow::getSize() const {
if (!_qmlWindowProxy) {
return {};

View file

@ -89,6 +89,15 @@ namespace InteractiveWindowEnums {
RIGHT
};
Q_ENUM_NS(DockArea);
enum RelativePositionAnchor {
NO_ANCHOR,
TOP_LEFT,
TOP_RIGHT,
BOTTOM_RIGHT,
BOTTOM_LEFT
};
Q_ENUM_NS(RelativePositionAnchor);
}
using namespace InteractiveWindowEnums;
@ -121,6 +130,8 @@ class InteractiveWindow : public QObject {
Q_PROPERTY(QString title READ getTitle WRITE setTitle)
Q_PROPERTY(glm::vec2 position READ getPosition WRITE setPosition)
Q_PROPERTY(RelativePositionAnchor relativePositionAnchor READ getRelativePositionAnchor WRITE setRelativePositionAnchor)
Q_PROPERTY(glm::vec2 relativePosition READ getRelativePosition WRITE setRelativePosition)
Q_PROPERTY(glm::vec2 size READ getSize WRITE setSize)
Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
Q_PROPERTY(int presentationMode READ getPresentationMode WRITE setPresentationMode)
@ -136,6 +147,21 @@ private:
Q_INVOKABLE glm::vec2 getPosition() const;
Q_INVOKABLE void setPosition(const glm::vec2& position);
RelativePositionAnchor _relativePositionAnchor{ RelativePositionAnchor::NO_ANCHOR };
Q_INVOKABLE RelativePositionAnchor getRelativePositionAnchor() const;
Q_INVOKABLE void setRelativePositionAnchor(const RelativePositionAnchor& position);
// This "relative position" is relative to the "relative position anchor" and excludes the window frame.
// This position will ALWAYS include the geometry of a docked widget, if one is present.
glm::vec2 _relativePosition{ 0.0f, 0.0f };
Q_INVOKABLE glm::vec2 getRelativePosition() const;
Q_INVOKABLE void setRelativePosition(const glm::vec2& position);
Q_INVOKABLE void setPositionUsingRelativePositionAndAnchor(const QRect& mainWindowGeometry);
bool _isFullScreenWindow{ false };
Q_INVOKABLE void repositionAndResizeFullScreenWindow();
Q_INVOKABLE glm::vec2 getSize() const;
Q_INVOKABLE void setSize(const glm::vec2& size);
@ -320,6 +346,7 @@ protected slots:
void forwardKeyPressEvent(int key, int modifiers);
void forwardKeyReleaseEvent(int key, int modifiers);
void emitMainWindowResizeEvent();
void onMainWindowGeometryChanged(QRect geometry);
private:
std::shared_ptr<QmlWindowProxy> _qmlWindowProxy;

View file

@ -55,6 +55,8 @@ public:
float getFrame() const { return _frame; }
void loadURL(const QString& url);
AnimBlendType getBlendType() const { return _blendType; };
protected:
virtual void setCurrentFrameInternal(float frame) override;

View file

@ -545,7 +545,8 @@ QStringList Rig::getAnimationRoles() const {
auto clipNode = std::dynamic_pointer_cast<AnimClip>(node);
if (clipNode) {
// filter out the userAnims, they are for internal use only.
if (!clipNode->getID().startsWith("userAnim")) {
// also don't return additive blend node clips as valid roles.
if (!clipNode->getID().startsWith("userAnim") && clipNode->getBlendType() == AnimBlendType_Normal) {
list.append(node->getID());
}
}
@ -1432,6 +1433,69 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
}
_lastEnableInverseKinematics = _enableInverseKinematics;
//stategraph vars based on input
const float INPUT_DEADZONE_THRESHOLD = 0.05f;
const float SLOW_SPEED_THRESHOLD = 1.5f;
if (fabsf(_previousControllerParameters.inputX) <= INPUT_DEADZONE_THRESHOLD &&
fabsf(_previousControllerParameters.inputZ) <= INPUT_DEADZONE_THRESHOLD) {
// no WASD input
if (fabsf(forwardSpeed) <= SLOW_SPEED_THRESHOLD && fabsf(lateralSpeed) <= SLOW_SPEED_THRESHOLD) {
_animVars.set("isInputForward", false);
_animVars.set("isInputBackward", false);
_animVars.set("isInputRight", false);
_animVars.set("isInputLeft", false);
_animVars.set("isNotInput", true);
_animVars.set("isNotInputSlow", true);
} else {
_animVars.set("isInputForward", false);
_animVars.set("isInputBackward", false);
_animVars.set("isInputRight", false);
_animVars.set("isInputLeft", false);
_animVars.set("isNotInput", true);
_animVars.set("isNotInputSlow", false);
}
} else if (fabsf(_previousControllerParameters.inputZ) >= fabsf(_previousControllerParameters.inputX)) {
if (_previousControllerParameters.inputZ > 0.0f) {
// forward
_animVars.set("isInputForward", true);
_animVars.set("isInputBackward", false);
_animVars.set("isInputRight", false);
_animVars.set("isInputLeft", false);
_animVars.set("isNotInput", false);
_animVars.set("isNotInputSlow", false);
} else {
// backward
_animVars.set("isInputForward", false);
_animVars.set("isInputBackward", true);
_animVars.set("isInputRight", false);
_animVars.set("isInputLeft", false);
_animVars.set("isNotInput", false);
_animVars.set("isNotInputSlow", false);
}
} else {
if (_previousControllerParameters.inputX > 0.0f) {
// right
_animVars.set("isInputForward", false);
_animVars.set("isInputBackward", false);
_animVars.set("isInputRight", true);
_animVars.set("isInputLeft", false);
_animVars.set("isNotInput", false);
_animVars.set("isNotInputSlow", false);
} else {
// left
_animVars.set("isInputForward", false);
_animVars.set("isInputBackward", false);
_animVars.set("isInputRight", false);
_animVars.set("isInputLeft", true);
_animVars.set("isNotInput", false);
_animVars.set("isNotInputSlow", false);
}
}
}
_lastForward = forward;
_lastPosition = worldPosition;
@ -2160,50 +2224,6 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo
}
}
//deadzone constant
const float INPUT_DEADZONE_THRESHOLD = 0.05f;
if (fabsf(params.inputX) <= INPUT_DEADZONE_THRESHOLD && fabsf(params.inputZ) <= INPUT_DEADZONE_THRESHOLD) {
// no WASD input
_animVars.set("isInputForward", false);
_animVars.set("isInputBackward", false);
_animVars.set("isInputRight", false);
_animVars.set("isInputLeft", false);
_animVars.set("isNotInput", true);
} else if (fabsf(params.inputZ) >= fabsf(params.inputX)) {
if (params.inputZ > 0.0f) {
// forward
_animVars.set("isInputForward", true);
_animVars.set("isInputBackward", false);
_animVars.set("isInputRight", false);
_animVars.set("isInputLeft", false);
_animVars.set("isNotInput", false);
} else {
// backward
_animVars.set("isInputForward", false);
_animVars.set("isInputBackward", true);
_animVars.set("isInputRight", false);
_animVars.set("isInputLeft", false);
_animVars.set("isNotInput", false);
}
} else {
if (params.inputX > 0.0f) {
// right
_animVars.set("isInputForward", false);
_animVars.set("isInputBackward", false);
_animVars.set("isInputRight", true);
_animVars.set("isInputLeft", false);
_animVars.set("isNotInput", false);
} else {
// left
_animVars.set("isInputForward", false);
_animVars.set("isInputBackward", false);
_animVars.set("isInputRight", false);
_animVars.set("isInputLeft", true);
_animVars.set("isNotInput", false);
}
}
_headEnabled = params.primaryControllerFlags[PrimaryControllerType_Head] & (uint8_t)ControllerFlags::Enabled;
bool leftHandEnabled = params.primaryControllerFlags[PrimaryControllerType_LeftHand] & (uint8_t)ControllerFlags::Enabled;

View file

@ -88,8 +88,8 @@ public:
AnimPose secondaryControllerPoses[NumSecondaryControllerTypes]; // rig space
uint8_t secondaryControllerFlags[NumSecondaryControllerTypes];
bool isTalking;
float inputX;
float inputZ;
float inputX = 0.0f;
float inputZ = 0.0f;
bool reactionEnabledFlags[NUM_AVATAR_BEGIN_END_REACTIONS];
bool reactionTriggers[NUM_AVATAR_TRIGGER_REACTIONS];
HFMJointShapeInfo hipsShapeInfo;

View file

@ -1998,6 +1998,12 @@ void AudioClient::outputNotify() {
}
}
void AudioClient::noteAwakening() {
qCDebug(audioclient) << "Restarting the audio devices.";
switchInputToAudioDevice(_inputDeviceInfo);
switchOutputToAudioDevice(_outputDeviceInfo);
}
bool AudioClient::switchOutputToAudioDevice(const HifiAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest) {
Q_ASSERT_X(QThread::currentThread() == thread(), Q_FUNC_INFO, "Function invoked on wrong thread");

View file

@ -255,6 +255,7 @@ public slots:
void setOutputGain(float gain) { _outputGain = gain; };
void outputNotify();
void noteAwakening();
void loadSettings();
void saveSettings();

View file

@ -854,7 +854,8 @@ void Avatar::render(RenderArgs* renderArgs) {
float distanceToTarget = glm::length(toTarget);
const float DISPLAYNAME_DISTANCE = 20.0f;
updateDisplayNameAlpha(distanceToTarget < DISPLAYNAME_DISTANCE);
if (!isMyAvatar() || renderArgs->_cameraMode != (int8_t)CAMERA_MODE_FIRST_PERSON) {
if (!isMyAvatar() || !(renderArgs->_cameraMode == (int8_t)CAMERA_MODE_FIRST_PERSON_LOOK_AT
|| renderArgs->_cameraMode == (int8_t)CAMERA_MODE_FIRST_PERSON)) {
auto& frustum = renderArgs->getViewFrustum();
auto textPosition = getDisplayNamePosition();
if (frustum.pointIntersectsFrustum(textPosition)) {

View file

@ -335,8 +335,8 @@ namespace controller {
makeAxisPair(Action::STEP_PITCH, "StepPitch"),
makeAxisPair(Action::STEP_ROLL, "StepRoll"),
makeAxisPair(Action::STEP_TRANSLATE_X, "StepTranslateX"),
makeAxisPair(Action::STEP_TRANSLATE_X, "StepTranslateY"),
makeAxisPair(Action::STEP_TRANSLATE_X, "StepTranslateZ"),
makeAxisPair(Action::STEP_TRANSLATE_Y, "StepTranslateY"),
makeAxisPair(Action::STEP_TRANSLATE_Z, "StepTranslateZ"),
makePosePair(Action::LEFT_HAND, "LeftHand"),
makePosePair(Action::RIGHT_HAND, "RightHand"),

View file

@ -808,6 +808,8 @@ void AccountManager::requestAccountSettings() {
return;
}
qCDebug(networking) << "Requesting the Account Settings from the Metaverse API";
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QUrl lockerURL = _authURL;
@ -834,6 +836,9 @@ void AccountManager::requestAccountSettingsFinished() {
if (rootObject.contains("status") && rootObject["status"].toString() == "success") {
if (rootObject.contains("data") && rootObject["data"].isObject()) {
_settings.unpack(rootObject["data"].toObject());
_lastSuccessfulSyncTimestamp = _settings.lastChangeTimestamp();
qCDebug(networking) << "Received the Account Settings from the Metaverse API";
emit accountSettingsLoaded();
} else {
@ -874,6 +879,8 @@ void AccountManager::postAccountSettings() {
return;
}
qCDebug(networking) << "Account Settings have changed, pushing them to the Metaverse API";
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QUrl lockerURL = _authURL;

View file

@ -64,6 +64,11 @@ void RecordingScriptingInterface::playClip(NetworkClipLoaderPointer clipLoader,
}
void RecordingScriptingInterface::loadRecording(const QString& url, QScriptValue callback) {
if (QThread::currentThread() != thread()) {
BLOCKING_INVOKE_METHOD(this, "loadRecording", Q_ARG(const QString&, url), Q_ARG(QScriptValue, callback));
return;
}
auto clipLoader = DependencyManager::get<recording::ClipCache>()->getClipLoader(url);
if (clipLoader->isLoaded()) {
@ -117,6 +122,11 @@ void RecordingScriptingInterface::startPlaying() {
}
void RecordingScriptingInterface::setPlayerVolume(float volume) {
if (QThread::currentThread() != thread()) {
BLOCKING_INVOKE_METHOD(this, "setPlayerVolume", Q_ARG(float, volume));
return;
}
_player->setVolume(std::min(std::max(volume, 0.0f), 1.0f));
}
@ -137,6 +147,11 @@ void RecordingScriptingInterface::setPlayFromCurrentLocation(bool playFromCurren
}
void RecordingScriptingInterface::setPlayerLoop(bool loop) {
if (QThread::currentThread() != thread()) {
BLOCKING_INVOKE_METHOD(this, "setPlayerLoop", Q_ARG(bool, loop));
return;
}
_player->loop(loop);
}
@ -195,6 +210,16 @@ void RecordingScriptingInterface::startRecording() {
}
void RecordingScriptingInterface::stopRecording() {
if (!_recorder->isRecording()) {
qCWarning(scriptengine) << "Recorder is not running";
return;
}
if (QThread::currentThread() != thread()) {
BLOCKING_INVOKE_METHOD(this, "stopRecording");
return;
}
_recorder->stop();
_lastClip = _recorder->getClip();
_lastClip->seek(0);

View file

@ -25,8 +25,14 @@
* <tr>
* <td><strong>First&nbsp;Person</strong></td>
* <td><code>"first&nbsp;person"</code></td>
* <td>The camera is positioned such that you have the same view as your avatar. The camera moves and rotates with your
* avatar.</td>
* <td>Legacy first person camera mode. The camera is positioned such that you have the same view as your avatar.
* The camera moves and rotates with your avatar.</td>
* </tr>
* <tr>
* <td><strong>First&nbsp;Person&nbsp;Look&nbsp;At</strong></td>
* <td><code>"first&nbsp;person&nbsp;look&nbsp;at"</code></td>
* <td>Default first person camera mode. The camera is positioned such that you have the same view as your avatar.
* The camera moves and rotates with your avatar's head.</td>
* </tr>
* <tr>
* <td><strong>Third&nbsp;Person</strong></td>
@ -73,6 +79,8 @@ CameraMode stringToMode(const QString& mode) {
return CAMERA_MODE_THIRD_PERSON;
} else if (mode == "first person") {
return CAMERA_MODE_FIRST_PERSON;
} else if (mode == "first person look at") {
return CAMERA_MODE_FIRST_PERSON_LOOK_AT;
} else if (mode == "mirror") {
return CAMERA_MODE_MIRROR;
} else if (mode == "independent") {
@ -92,6 +100,8 @@ QString modeToString(CameraMode mode) {
return "third person";
} else if (mode == CAMERA_MODE_FIRST_PERSON) {
return "first person";
} else if (mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT) {
return "first person look at";
} else if (mode == CAMERA_MODE_MIRROR) {
return "mirror";
} else if (mode == CAMERA_MODE_INDEPENDENT) {

View file

@ -19,6 +19,7 @@ enum CameraMode
{
CAMERA_MODE_NULL = -1,
CAMERA_MODE_THIRD_PERSON,
CAMERA_MODE_FIRST_PERSON_LOOK_AT,
CAMERA_MODE_FIRST_PERSON,
CAMERA_MODE_MIRROR,
CAMERA_MODE_INDEPENDENT,

View file

@ -24,6 +24,10 @@ public:
~MainWindow();
static QWindow* findMainWindow();
// This offset is used for positioning children window relative to the main window.
void setDockedWidgetRelativePositionOffset(const QSize& newOffset) { _dockedWidgetRelativePositionOffset.setWidth(newOffset.width()); _dockedWidgetRelativePositionOffset.setHeight(newOffset.height()); }
QSize getDockedWidgetRelativePositionOffset() { return _dockedWidgetRelativePositionOffset; }
public slots:
void restoreGeometry();
void saveGeometry();
@ -46,6 +50,7 @@ protected:
private:
Setting::Handle<QRect> _windowGeometry;
Setting::Handle<int> _windowState;
QSize _dockedWidgetRelativePositionOffset{ 0, 0 };
};
#endif /* defined(__hifi__MainWindow__) */

View file

@ -92,15 +92,19 @@ public:
ToolbarProxy(QObject* qmlObject, QObject* parent = nullptr);
/**jsdoc
* <em>Currently doesn't work.</em>
* @function ToolbarProxy#addButton
* @param {object} properties
* @returns {ToolbarButtonProxy}
* @param {object} properties - Button properties
* @returns {object} The button added.
* @deprecated This method is deprecated and will be removed.
*/
Q_INVOKABLE ToolbarButtonProxy* addButton(const QVariant& properties);
/**jsdoc
* <em>Currently doesn't work.</em>
* @function ToolbarProxy#removeButton
* @param {string} name
* @param {string} name - Button name.
* @deprecated This method is deprecated and will be removed.
*/
Q_INVOKABLE void removeButton(const QVariant& name);

View file

@ -1,117 +1,38 @@
var isActive = false;
(function () {
var toolBar = (function() {
var that = {},
toolBar,
activeButton,
newModelButton,
newShapeButton,
newLightButton,
newTextButton,
newWebButton,
newZoneButton,
newParticleButton,
newMaterialButton
var toolIconUrl = Script.resolvePath("../../system/assets/images/tools/");
function initialize() {
print("Toolbars: " + Toolbars);
toolBar = Toolbars.getToolbar("highfidelity.edit.toolbar");
print("Toolbar: " + toolBar);
activeButton = toolBar.addButton({
objectName: "activeButton",
imageURL: toolIconUrl + "edit-01.svg",
visible: true,
alpha: 0.9,
});
print("Button " + activeButton);
print("Button signal " + activeButton.clicked);
activeButton.clicked.connect(function(){
print("Clicked on button " + isActive);
that.setActive(!isActive);
});
newModelButton = toolBar.addButton({
objectName: "newModelButton",
imageURL: toolIconUrl + "model-01.svg",
alpha: 0.9,
visible: false
});
newShapeButton = toolBar.addButton({
objectName: "newShapeButton",
imageURL: toolIconUrl + "cube-01.svg",
alpha: 0.9,
visible: false
});
newLightButton = toolBar.addButton({
objectName: "newLightButton",
imageURL: toolIconUrl + "light-01.svg",
alpha: 0.9,
visible: false
});
newTextButton = toolBar.addButton({
objectName: "newTextButton",
imageURL: toolIconUrl + "text-01.svg",
alpha: 0.9,
visible: false
});
newWebButton = toolBar.addButton({
objectName: "newWebButton",
imageURL: toolIconUrl + "web-01.svg",
alpha: 0.9,
visible: false
});
newZoneButton = toolBar.addButton({
objectName: "newZoneButton",
imageURL: toolIconUrl + "zone-01.svg",
alpha: 0.9,
visible: false
});
newParticleButton = toolBar.addButton({
objectName: "newParticleButton",
imageURL: toolIconUrl + "particle-01.svg",
alpha: 0.9,
visible: false
});
newMaterialButton = toolBar.addButton({
objectName: "newMaterialButton",
imageURL: toolIconUrl + "material-01.svg",
alpha: 0.9,
visible: false
});
that.setActive(false);
newModelButton.clicked();
// Get the system toolbar.
var toolbar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system");
if (!toolbar) {
print("ERROR: Couldn't get system toolbar.");
return;
}
that.setActive = function(active) {
if (active != isActive) {
isActive = active;
that.showTools(isActive);
}
};
Script.setTimeout(function () {
// Report the system toolbar visibility.
var isToolbarVisible = toolbar.readProperty("visible");
print("Toolbar visible: " + isToolbarVisible);
// Sets visibility of tool buttons, excluding the power button
that.showTools = function(doShow) {
newModelButton.writeProperty('visible', doShow);
newShapeButton.writeProperty('visible', doShow);
newLightButton.writeProperty('visible', doShow);
newTextButton.writeProperty('visible', doShow);
newWebButton.writeProperty('visible', doShow);
newZoneButton.writeProperty('visible', doShow);
newParticleButton.writeProperty('visible', doShow);
newMaterialButton.writeProperty('visible', doShow);
};
// Briefly toggle the system toolbar visibility.
print("Toggle toolbar");
toolbar.writeProperty("visible", !isToolbarVisible);
Script.setTimeout(function () {
print("Toggle toolbar");
toolbar.writeProperty("visible", isToolbarVisible);
}, 2000);
}, 2000);
Script.setTimeout(function () {
// Report the system toolbar visibility alternative method.
isToolbarVisible = toolbar.readProperties(["visible"]).visible;
print("Toolbar visible: " + isToolbarVisible);
// Briefly toggle the system toolbar visibility.
print("Toggle toolbar");
toolbar.writeProperties({ visible: !isToolbarVisible });
Script.setTimeout(function () {
print("Toggle toolbar");
toolbar.writeProperties({ visible: isToolbarVisible });
}, 2000);
}, 6000);
initialize();
return that;
}());

View file

@ -0,0 +1,43 @@
//
// PropItem.qml
//
// Created by Sam Gateau on 3/2/2019
// Copyright 2019 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
PropItem {
Global { id: global }
id: root
// Scalar Prop
// property bool integral: false
// property var numDigits: 2
Rectangle {
id: valueLabel
anchors.left: root.splitter.right
anchors.right: root.right
anchors.verticalCenter: root.verticalCenter
// horizontalAlignment: global.valueTextAlign
height: global.slimHeight
function getColor() {
var c = root.valueVarGetter();
return Qt.rgba(c.red, c.green, c.blue, 1.0);
}
// background: Rectangle {
color: { return getColor() }
border.color: global.colorBorderLight
border.width: global.valueBorderWidth
radius: global.valueBorderRadius
// }
}
}

View file

@ -13,12 +13,19 @@ import QtQuick.Layouts 1.3
import stylesUit 1.0
import controlsUit 1.0 as HifiControls
import "../lib/prop" as Prop
Rectangle {
HifiConstants { id: hifi;}
color: Qt.rgba(hifi.colors.baseGray.r, hifi.colors.baseGray.g, hifi.colors.baseGray.b, 0.8);
id: root;
property var theMaterial: {}
property var theMaterialAttributes: {}
property var hasMaterial: false
property var isReadOnly: true
function fromScript(message) {
switch (message.method) {
case "setObjectInfo":
@ -26,40 +33,213 @@ Rectangle {
break;
case "setMaterialJSON":
materialJSONText.text = message.params.materialJSONText;
theMaterial = JSON.parse(message.params.materialJSONText)
theMaterialAttributes = theMaterial.materials
hasMaterial = (theMaterial !== undefined)
break;
}
}
Rectangle {
id: entityIDContainer
height: 52
width: root.width
color: Qt.rgba(root.color.r * 0.7, root.color.g * 0.7, root.color.b * 0.7, 0.8);
TextEdit {
id: entityIDInfo
text: "Type: Unknown\nID: None\nMesh Part: Unknown"
font.pointSize: 9
color: "#FFFFFF"
readOnly: true
selectByMouse: true
}
}
Original.ScrollView {
anchors.top: entityIDContainer.bottom
height: root.height - entityIDContainer.height
width: root.width
clip: true
Original.ScrollBar.horizontal.policy: Original.ScrollBar.AlwaysOff
TextEdit {
id: materialJSONText
text: "Click an object to get material JSON"
Column {
anchors.left: parent.left
anchors.right: parent.right
Rectangle {
id: entityIDContainer
height: 52
width: root.width
font.pointSize: 10
color: "#FFFFFF"
readOnly: true
selectByMouse: true
wrapMode: Text.WordWrap
color: Qt.rgba(root.color.r * 0.7, root.color.g * 0.7, root.color.b * 0.7, 0.8);
TextEdit {
id: entityIDInfo
text: "Type: Unknown\nID: None\nMesh Part: Unknown"
font.pointSize: 9
color: "#FFFFFF"
readOnly: true
selectByMouse: true
}
}
Prop.PropString {
visible: hasMaterial && ("name" in theMaterialAttributes)
label: "name"
object: theMaterialAttributes
property: "name"
readOnly: isReadOnly
}
Prop.PropString {
visible: hasMaterial && ("model" in theMaterialAttributes)
label: "model"
object: theMaterialAttributes
property: "model"
readOnly: isReadOnly
}
Prop.PropColor {
visible: hasMaterial && ("albedo" in theMaterialAttributes)
label: "albedo"
object: theMaterialAttributes
property: "albedo"
readOnly: isReadOnly
}
Prop.PropString {
visible: hasMaterial && ("albedoMap" in theMaterialAttributes)
label: "albedoMap"
object: theMaterialAttributes
property: "albedoMap"
readOnly: isReadOnly
}
Prop.PropScalar {
visible: hasMaterial && ("opacity" in theMaterialAttributes)
label: "opacity"
object: theMaterialAttributes
property: "opacity"
readOnly: isReadOnly
}
Prop.PropString {
visible: hasMaterial && ("opacityMap" in theMaterialAttributes)
label: "opacityMap"
object: theMaterialAttributes
property: "opacityMap"
readOnly: isReadOnly
}
Prop.PropString {
visible: hasMaterial && ("opacityMapMode" in theMaterialAttributes)
label: "opacityMapMode"
object: theMaterialAttributes
property: "opacityMapMode"
readOnly: isReadOnly
}
/*Prop.PropEnum {
visible: hasMaterial && ("opacityMapMode" in theMaterialAttributes)
label: "opacityMapMode"
object: theMaterialAttributes
property: "opacityMapMode"
readOnly: isReadOnly
enums: ["None", "Mask", "Blend"]
} */
Prop.PropScalar {
visible: hasMaterial && ("opacityCutoff" in theMaterialAttributes)
label: "opacity Cutoff"
object: theMaterialAttributes
property: "opacityCutoff"
readOnly: isReadOnly
}
Prop.PropString {
visible: hasMaterial && ("occlusionMap" in theMaterialAttributes)
label: "occlusionMap"
object: theMaterialAttributes
property: "occlusionMap"
readOnly: isReadOnly
}
Prop.PropString {
visible: hasMaterial && ("normalMap" in theMaterialAttributes)
label: "normalMap"
object: theMaterialAttributes
property: "normalMap"
readOnly: isReadOnly
}
Prop.PropString {
visible: hasMaterial && ("bumpMap" in theMaterialAttributes)
label: "normalMap from bumpMap"
object: theMaterialAttributes
property: "bumpMap"
readOnly: isReadOnly
}
Prop.PropScalar {
visible: hasMaterial && ("roughness" in theMaterialAttributes)
label: "roughness"
object: theMaterialAttributes
property: "roughness"
readOnly: isReadOnly
}
Prop.PropScalar {
visible: hasMaterial && ("metallic" in theMaterialAttributes)
label: "metallic"
object: theMaterialAttributes
property: "metallic"
readOnly: isReadOnly
}
Prop.PropString {
visible: hasMaterial && ("roughnessMap" in theMaterialAttributes)
label: "roughnessMap"
object: theMaterialAttributes
property: "roughnessMap"
readOnly: isReadOnly
}
Prop.PropString {
visible: hasMaterial && ("glossMap" in theMaterialAttributes)
label: "roughnessMap from glossMap"
object: theMaterialAttributes
property: "glossMap"
readOnly: isReadOnly
}
Prop.PropString {
visible: hasMaterial && ("metallicMap" in theMaterialAttributes)
label: "metallicMap"
object: theMaterialAttributes
property: "metallicMap"
readOnly: isReadOnly
}
Prop.PropString {
visible: hasMaterial && ("specularMap" in theMaterialAttributes)
label: "metallicMap from specularMap"
object: theMaterialAttributes
property: "specularMap"
readOnly: isReadOnly
}
Prop.PropScalar {
visible: hasMaterial && ("scattering" in theMaterialAttributes)
label: "scattering"
object: theMaterialAttributes
property: "scattering"
readOnly: isReadOnly
}
Prop.PropString {
visible: hasMaterial && ("scatteringMap" in theMaterialAttributes)
label: "scatteringMap"
object: theMaterialAttributes
property: "scatteringMap"
readOnly: isReadOnly
}
Prop.PropColor {
visible: hasMaterial && ("emissive" in theMaterialAttributes)
label: "emissive"
object: theMaterialAttributes
property: "emissive"
readOnly: isReadOnly
}
Prop.PropString {
visible: hasMaterial && ("emissiveMap" in theMaterialAttributes)
label: "emissiveMap"
object: theMaterialAttributes
property: "emissiveMap"
readOnly: isReadOnly
}
Original.ScrollView {
// anchors.top: entityIDContainer.bottom
height: root.height - entityIDContainer.height
width: root.width
clip: true
Original.ScrollBar.horizontal.policy: Original.ScrollBar.AlwaysOff
TextEdit {
id: materialJSONText
text: "Click an object to get material JSON"
width: root.width
font.pointSize: 10
color: "#FFFFFF"
readOnly: true
selectByMouse: true
wrapMode: Text.WordWrap
}
}
}
}

View file

@ -444,17 +444,9 @@ function updateEmoteIndicatorIcon(iconURL) {
}
function onGeometryChanged(rect) {
updateEmoteAppBarPosition();
}
function onWindowMinimizedChanged(isMinimized) {
if (isMinimized) {
handleEmoteIndicatorVisibleChanged(false);
} else if (!HMD.active) {
handleEmoteIndicatorVisibleChanged(true);
}
isWindowMinimized = isMinimized;
maybeChangeEmoteIndicatorVisibility(!isMinimized);
}
@ -539,10 +531,11 @@ function showEmoteAppBar() {
x: EMOTE_APP_BAR_WIDTH_PX,
y: EMOTE_APP_BAR_HEIGHT_PX
},
position: {
x: Window.x + EMOTE_APP_BAR_LEFT_MARGIN,
y: Window.y + Window.innerHeight - EMOTE_APP_BAR_BOTTOM_MARGIN
relativePosition: {
x: EMOTE_APP_BAR_LEFT_MARGIN,
y: EMOTE_APP_BAR_BOTTOM_MARGIN
},
relativePositionAnchor: Desktop.RelativePositionAnchor.BOTTOM_LEFT,
overrideFlags: EMOTE_APP_BAR_WINDOW_FLAGS
});
@ -550,10 +543,18 @@ function showEmoteAppBar() {
}
function handleEmoteIndicatorVisibleChanged(shouldBeVisible) {
if (shouldBeVisible && !emoteAppBarWindow) {
// There is currently no property in the Window Scripting Interface to determine
// whether the Interface window is currently minimized. This feels like an oversight.
// We should add that functionality to the Window Scripting Interface, and remove `isWindowMinimized` below.
var isWindowMinimized = false;
function maybeChangeEmoteIndicatorVisibility(desiredVisibility) {
if (isWindowMinimized || HMD.active) {
desiredVisibility = false;
}
if (desiredVisibility && !emoteAppBarWindow) {
showEmoteAppBar();
} else if (emoteAppBarWindow) {
} else if (!desiredVisibility && emoteAppBarWindow) {
emoteAppBarWindow.fromQml.disconnect(onMessageFromEmoteAppBar);
emoteAppBarWindow.close();
emoteAppBarWindow = false;
@ -561,23 +562,25 @@ function handleEmoteIndicatorVisibleChanged(shouldBeVisible) {
}
function handleFTUEScreensVisibilityChanged(ftueScreenVisible) {
maybeChangeEmoteIndicatorVisibility(!ftueScreenVisible);
}
function onDisplayModeChanged(isHMDMode) {
reactionsBegun.forEach(function(react) {
endReactionWrapper(react);
});
if (isHMDMode) {
handleEmoteIndicatorVisibleChanged(false);
} else {
handleEmoteIndicatorVisibleChanged(true);
}
maybeChangeEmoteIndicatorVisibility(!isHMDMode);
}
var emojiAPI = Script.require("./emojiApp/simplifiedEmoji.js?" + Date.now());
var emojiAPI = Script.require("./emojiApp/simplifiedEmoji.js");
var keyPressSignalsConnected = false;
var emojiCodeMap;
var customEmojiCodeMap;
var _this;
function setup() {
deleteOldReticles();
@ -605,16 +608,25 @@ function setup() {
}, {});
Window.minimizedChanged.connect(onWindowMinimizedChanged);
Window.geometryChanged.connect(onGeometryChanged);
HMD.displayModeChanged.connect(onDisplayModeChanged);
getSounds();
handleEmoteIndicatorVisibleChanged(true);
maybeChangeEmoteIndicatorVisibility(true);
Controller.keyPressEvent.connect(keyPressHandler);
Controller.keyReleaseEvent.connect(keyReleaseHandler);
keyPressSignalsConnected = true;
Script.scriptEnding.connect(unload);
function Emote() {
_this = this;
}
Emote.prototype = {
handleFTUEScreensVisibilityChanged: handleFTUEScreensVisibilityChanged
};
return new Emote();
}
@ -638,7 +650,6 @@ function unload() {
maybeDeleteRemoteIndicatorTimeout();
Window.minimizedChanged.disconnect(onWindowMinimizedChanged);
Window.geometryChanged.disconnect(onGeometryChanged);
HMD.displayModeChanged.disconnect(onDisplayModeChanged);
if (keyPressSignalsConnected) {
@ -671,7 +682,6 @@ function unload() {
// #region EMOJI_UTILITY
var EMOJI_52_BASE_URL = "../../resources/images/emojis/52px/";
function selectedEmoji(code) {
emojiAPI.addEmoji(code);
// this URL needs to be relative to SimplifiedEmoteIndicator.qml
@ -786,4 +796,6 @@ function toggleEmojiApp() {
// END EMOJI
// *************************************
setup();
var emote = setup();
module.exports = emote;

View file

@ -1,15 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.6, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 93.7 127.8" style="enable-background:new 0 0 93.7 127.8;" xml:space="preserve">
<path d="M91.9,97c-7.6,9.6-17.8,16.7-29.3,20.3h-0.1c-0.4,0.1-0.8,0.3-1.3,0.4c-4.6,1.3-9.5,2-14.4,2c-4.9,0-9.8-0.7-14.4-2
c-0.4-0.1-0.8-0.3-1.3-0.4h-0.1C19.6,113.8,9.4,106.6,1.8,97c0,0-0.5-0.5-0.9,0.1C0.6,97.6,1,98.5,1,98.5
C9.9,116,27,127.8,46.8,127.8l0,0c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0l0,0c19.7-0.1,36.8-11.8,45.8-29.3c0,0,0.4-0.9,0.1-1.4
C92.4,96.6,91.9,97,91.9,97z M91.9,78.8C84.3,88.4,74.1,95.5,62.6,99h-0.1c-0.4,0.1-0.8,0.3-1.3,0.4c-4.6,1.3-9.5,2-14.4,2
c-4.9,0-9.8-0.7-14.4-2c-0.4-0.1-0.8-0.3-1.3-0.4h-0.1C19.6,95.5,9.4,88.4,1.8,78.8c0,0-0.5-0.5-0.9,0.1C0.6,79.3,1,80.2,1,80.2
c8.9,17.5,26.1,29.2,45.8,29.3l0,0c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0l0,0c19.7-0.1,36.8-11.8,45.8-29.3c0,0,0.4-0.9,0.1-1.4
C92.4,78.3,91.9,78.8,91.9,78.8z M46.9,92.7c25.8,0,46.9-20.7,46.9-46.4S72.7,0,46.9,0S0,20.7,0,46.4S20.9,92.7,46.9,92.7z
M65.5,30.8c2.8,0,5,2.2,5,5s-2.2,5-5,5c-2.8,0-5-2.2-5-5S62.8,30.8,65.5,30.8z M36,54.3c2.7,3.2,6.6,5,10.8,5s8.2-1.9,10.8-5
c0.9-1.1,2.7-1.2,3.8-0.4c1.1,0.9,1.3,2.6,0.3,3.7c-3.7,4.4-9.1,6.9-14.9,6.9c-5.8,0-11.2-2.5-14.9-6.9c-0.9-1.1-0.8-2.7,0.3-3.7
C33.4,53.1,35,53.2,36,54.3z M28.1,30.8c2.8,0,5,2.2,5,5s-2.2,5-5,5c-2.8,0-5-2.2-5-5S25.3,30.8,28.1,30.8z"/>
<!-- Generator: Adobe Illustrator 23.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
<!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
<!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
<!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
<!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
<!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
<!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
<!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
]>
<svg version="1.1" id="Layer_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 52.8 49"
style="enable-background:new 0 0 52.8 49;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.7;}
.st1{fill:#FFFFFF;}
</style>
<metadata>
<sfw xmlns="&ns_sfw;">
<slices></slices>
<sliceSourceBounds bottomLeftOrigin="true" height="49" width="52.8" x="8.3" y="11.1"></sliceSourceBounds>
</sfw>
</metadata>
<g class="st0">
<path class="st1" d="M10.3,47.8c5.1,0.8,10.3,1.2,15.3,1.2c0.3,0,0.6,0,0.8,0c5.4-0.1,10.8-0.6,16.2-1.5c4-0.8,7.8-4.5,8.7-8.5
c1-4.8,1.5-9.8,1.5-14.6s-0.5-9.8-1.5-14.6c-0.8-3.9-4.7-7.6-8.7-8.4C37.3,0.6,31.8,0,26.4,0c-5.3-0.1-10.8,0.3-16.2,1.2
c-4,0.7-7.9,4.5-8.7,8.5c-1,5-1.5,9.9-1.5,14.9s0.5,9.9,1.5,14.9C2.4,43.3,6.2,47.1,10.3,47.8z M6.2,10.6C6.7,8.6,9,6.3,11,5.9
c4.9-0.8,9.7-1.2,14.6-1.2c0.3,0,0.6,0,0.8,0c5.1,0.1,10.3,0.6,15.3,1.4c2,0.4,4.4,2.7,4.8,4.6c0.9,4.5,1.3,9.1,1.3,13.7
s-0.4,9.1-1.3,13.6c-0.4,1.9-2.8,4.3-4.8,4.7c-5.1,0.9-10.3,1.4-15.3,1.4c-5.1,0.1-10.3-0.3-15.3-1.2c-2-0.3-4.4-2.7-4.8-4.6
c-0.9-4.6-1.4-9.3-1.4-14C4.9,19.9,5.3,15.1,6.2,10.6z"/>
<path class="st1" d="M14.1,32.3c-0.3,0.9-0.1,1.9,0.6,2.6c0.2,0.2,5,4.5,11,4.5c0.6,0,1.2-0.1,1.8-0.1c6.8-1,10.7-7.6,11-7.9
c0.5-0.8,0.4-1.9-0.1-2.7c-0.6-0.8-1.6-1.1-2.6-0.9c-6.4,1.7-12.9,2.7-19.5,2.9C15.3,30.8,14.5,31.4,14.1,32.3z"/>
<path class="st1" d="M17.1,25.7c3.4,0,6.2-2.8,6.2-6.2c0-3.4-2.8-6.2-6.2-6.2c-3.4,0-6.2,2.8-6.2,6.2C10.8,23,13.6,25.7,17.1,25.7z
"/>
<path class="st1" d="M34.3,20.4h4.2c1.3,0,2.3-1,2.3-2.3c0-1.3-1-2.3-2.3-2.3h-4.2c-1.3,0-2.3,1-2.3,2.3
C32,19.5,33.1,20.4,34.3,20.4z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,350 @@
//
// InitialLaunchWindow.qml
//
// Copyright 2019 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.10
import QtQuick.Controls 2.3
import QtGraphicalEffects 1.0
import QtQuick.Layouts 1.3
import stylesUit 1.0 as HifiStylesUit
import TabletScriptingInterface 1.0
import hifi.simplifiedUI.simplifiedConstants 1.0 as SimplifiedConstants
import hifi.simplifiedUI.simplifiedControls 1.0 as SimplifiedControls
Rectangle {
id: root
color: simplifiedUI.colors.white
anchors.fill: parent
property bool landscapeOrientation: root.width > root.height
SimplifiedConstants.SimplifiedConstants {
id: simplifiedUI
}
Component.onCompleted: {
var debugFTUE = Settings.getValue("simplifiedUI/debugFTUE", 0);
if ((debugFTUE !== 1 &&
(Settings.getValue("simplifiedUI/alreadyAutoSelectedAvatarFromInventory", false) ||
Settings.getValue("simplifiedUI/closedAvatarPageOfInitialLaunchWindow", false))) ||
debugFTUE === 2) {
tempAvatarPageContainer.visible = false;
controlsContainer.visible = true;
}
}
Item {
id: tempAvatarPageContainer
anchors.fill: parent
Item {
id: contentContainer
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: firstPageBottomBarContainer.top
Image {
id: avatarImage
anchors.verticalCenter: parent.verticalCenter
height: Math.max(parent.height - 48, 350)
anchors.left: parent.left
anchors.leftMargin: 12
source: resourceDirectoryUrl + "qml/hifi/simplifiedUI/avatarApp/images/" +
MyAvatar.skeletonModelURL.substring(MyAvatar.skeletonModelURL.indexOf("simplifiedAvatar"), MyAvatar.skeletonModelURL.lastIndexOf("/")) + ".png"
mipmap: true
fillMode: Image.PreserveAspectFit
}
Flickable {
id: textContainer
clip: true
anchors.top: parent.top
anchors.topMargin: 128
anchors.bottom: qrAndInstructionsContainer.top
anchors.bottomMargin: 32
anchors.left: avatarImage.right
anchors.leftMargin: 48
anchors.right: parent.right
contentWidth: width
contentHeight: contentItem.childrenRect.height
interactive: contentHeight > height
HifiStylesUit.RalewayBold {
id: headerText
text: "We know this isn't you..."
color: simplifiedUI.colors.text.black
size: 48
height: paintedHeight
wrapMode: Text.Wrap
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: 16
}
HifiStylesUit.RalewayRegular {
id: descriptionText
anchors.top: headerText.bottom
anchors.topMargin: 10
anchors.left: parent.left
width: Math.min(700, parent.width) - headerText.anchors.rightMargin
height: paintedHeight
text: "...but we've given you this <b>temporary avatar</b> to use " +
"for today. If you see this avatar in-world, walk up and " +
"say hello to other new users!<br><br>" +
"<b>We want you to be you</b> so we've built " +
'<a href="https://www.highfidelity.com/knowledge/virtual-you/">Virtual You</a>, an Avatar Creator ' +
"App. Creating an avatar is as easy as taking a selfie and picking your " +
"outfits! Available now on iOS and Android."
color: simplifiedUI.colors.text.black
size: 22
wrapMode: Text.Wrap
onLinkActivated: {
Qt.openUrlExternally(link);
}
}
}
Item {
id: qrAndInstructionsContainer
anchors.left: avatarImage.right
anchors.leftMargin: 48
anchors.right: parent.right
anchors.rightMargin: 16
anchors.bottom: parent.bottom
height: 130
Image {
id: avatarAppQRCodeImage
source: resourceDirectoryUrl + "qml/hifi/simplifiedUI/avatarApp/images/qrCode.jpg"
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
width: 130
mipmap: true
fillMode: Image.PreserveAspectFit
}
HifiStylesUit.RalewayBold {
id: instructionText
anchors.top: avatarAppQRCodeImage.top
anchors.bottom: avatarAppQRCodeImage.bottom
anchors.left: avatarAppQRCodeImage.right
anchors.leftMargin: 30
anchors.right: parent.right
text: "Use your mobile phone to scan this QR code."
color: simplifiedUI.colors.text.black
size: 22
wrapMode: Text.Wrap
}
}
SimplifiedControls.VerticalScrollBar {
parent: textContainer
visible: parent.contentHeight > parent.height
size: parent.height / parent.contentHeight
}
}
Item {
id: firstPageBottomBarContainer
anchors.left: parent.left
anchors.leftMargin: 32
anchors.right: parent.right
anchors.rightMargin: 32
anchors.bottom: parent.bottom
height: continueLink.height + 48
HifiStylesUit.RalewayBold {
id: continueLink
anchors.centerIn: parent
text: "Continue >"
width: parent.width
height: paintedHeight
color: simplifiedUI.colors.text.lightBlue
opacity: continueMouseArea.containsMouse ? 1.0 : 0.7
size: 36
wrapMode: Text.Wrap
horizontalAlignment: Text.AlignHCenter
MouseArea {
id: continueMouseArea
hoverEnabled: true
anchors.fill: parent
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
tempAvatarPageContainer.visible = false;
Settings.setValue("simplifiedUI/closedAvatarPageOfInitialLaunchWindow", true);
controlsContainer.visible = true;
}
}
}
}
}
Item {
id: controlsContainer
visible: false
anchors.fill: parent
HifiStylesUit.RalewayRegular {
id: controlsDescriptionText
text: "Use these avatar controls to<br><b>interact with and move around in your new HQ.</b>"
anchors.top: parent.top
anchors.topMargin: 48
anchors.left: parent.left
anchors.leftMargin: 32
anchors.right: parent.right
anchors.rightMargin: 32
horizontalAlignment: Text.AlignHCenter
height: paintedHeight
color: simplifiedUI.colors.text.black
size: 36
wrapMode: Text.Wrap
}
Item {
anchors.top: controlsDescriptionText.bottom
anchors.topMargin: 16
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: bottomBarContainer.top
GridView {
id: controlsGrid
property int maxColumns: 2
property int idealCellWidth: 361
anchors.fill: parent
clip: true
cellWidth: width / Math.min(Math.floor(width / idealCellWidth), maxColumns)
cellHeight: 225
model: ListModel {
ListElement {
imageHeight: 198
imageSource: "images/walkingControls.png"
}
ListElement {
imageHeight: 193
imageSource: "images/mouseControls.png"
}
ListElement {
imageHeight: 146
imageSource: "images/runJumpControls.png"
}
ListElement {
imageHeight: 96
imageSource: "images/cameraControls.png"
}
}
delegate: Rectangle {
height: GridView.view.cellHeight
width: GridView.view.cellWidth
Image {
anchors.centerIn: parent
width: parent.GridView.view.idealCellWidth
height: model.imageHeight
source: model.imageSource
fillMode: Image.PreserveAspectFit
}
}
}
SimplifiedControls.VerticalScrollBar {
parent: controlsGrid
anchors.topMargin: 96
anchors.bottomMargin: anchors.topMargin
}
}
Item {
id: bottomBarContainer
anchors.left: parent.left
anchors.leftMargin: 32
anchors.right: parent.right
anchors.rightMargin: 32
anchors.bottom: parent.bottom
height: iHaveAGoodGrip.height + learnMoreLink.height + 48
HifiStylesUit.RalewayBold {
id: iHaveAGoodGrip
anchors.centerIn: parent
text: "I've got a good grip on the controls."
width: parent.width
height: paintedHeight
color: simplifiedUI.colors.text.lightBlue
opacity: goodGripMouseArea.containsMouse ? 1.0 : 0.7
size: 36
wrapMode: Text.Wrap
horizontalAlignment: Text.AlignHCenter
MouseArea {
id: goodGripMouseArea
hoverEnabled: true
anchors.fill: parent
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
sendToScript({
"source": "InitialLaunchWindow.qml",
"method": "closeInitialLaunchWindow"
});
}
}
}
HifiStylesUit.RalewayBold {
id: learnMoreLink
anchors.left: parent.left
anchors.leftMargin: 16
anchors.top: iHaveAGoodGrip.bottom
anchors.topMargin: 8
text: "Learn more about our controls."
width: paintedWidth
height: paintedHeight
color: simplifiedUI.colors.text.lightBlue
opacity: learnMoreAboutControlsMouseArea.containsMouse ? 1.0 : 0.7
size: 14
wrapMode: Text.Wrap
MouseArea {
id: learnMoreAboutControlsMouseArea
hoverEnabled: true
anchors.fill: parent
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
Qt.openUrlExternally("https://www.highfidelity.com/knowledge/get-around");
}
}
}
}
}
Image {
id: topLeftAccentImage
width: 400
height: 180
anchors.left: parent.left
anchors.top: parent.top
source: "images/defaultTopLeft.png"
}
Image {
id: bottomRightAccentImage
width: 80
height: 250
anchors.right: parent.right
anchors.bottom: parent.bottom
source: "images/defaultBottomRight.png"
}
signal sendToScript(var message);
}

View file

@ -0,0 +1,186 @@
//
// SecondLaunchWindow.qml
//
// Copyright 2019 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.10
import QtQuick.Controls 2.3
import QtGraphicalEffects 1.0
import QtQuick.Layouts 1.3
import stylesUit 1.0 as HifiStylesUit
import TabletScriptingInterface 1.0
import hifi.simplifiedUI.simplifiedConstants 1.0 as SimplifiedConstants
import hifi.simplifiedUI.simplifiedControls 1.0 as SimplifiedControls
Rectangle {
id: root
color: simplifiedUI.colors.white
anchors.fill: parent
SimplifiedConstants.SimplifiedConstants {
id: simplifiedUI
}
Item {
id: contentContainer
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: continueLink.top
Image {
id: avatarImage
anchors.verticalCenter: parent.verticalCenter
height: Math.max(parent.height - 48, 350)
anchors.left: parent.left
anchors.leftMargin: 12
source: resourceDirectoryUrl + "qml/hifi/simplifiedUI/avatarApp/images/hero.png"
mipmap: true
fillMode: Image.PreserveAspectFit
}
Item {
anchors.top: parent.top
anchors.topMargin: 196
anchors.bottom: parent.bottom
anchors.bottomMargin: 32
anchors.left: avatarImage.right
anchors.leftMargin: 48
anchors.right: parent.right
Flickable {
id: textContainer
clip: true
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
width: Math.min(700, parent.width)
contentWidth: width
contentHeight: contentItem.childrenRect.height
interactive: contentHeight > height
HifiStylesUit.RalewayBold {
id: headerText
text: "Stand out from the crowd!"
color: simplifiedUI.colors.text.black
size: 48
height: paintedHeight
wrapMode: Text.Wrap
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: 16
}
HifiStylesUit.RalewayRegular {
id: descriptionText
anchors.top: headerText.bottom
anchors.topMargin: 10
anchors.left: parent.left
width: parent.width - headerText.anchors.rightMargin
height: paintedHeight
text: "You can create and upload custom avatars from our Avatar Creator App. " +
"It's as easy as taking a selfie.<br>Available now on iOS and Android Platforms."
color: simplifiedUI.colors.text.black
size: 22
wrapMode: Text.Wrap
}
Item {
id: qrAndInstructionsContainer
anchors.top: descriptionText.bottom
anchors.topMargin: 24
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: 16
height: avatarAppQRCodeImage.height
Image {
id: avatarAppQRCodeImage
source: resourceDirectoryUrl + "qml/hifi/simplifiedUI/avatarApp/images/qrCode.jpg"
anchors.top: parent.top
anchors.left: parent.left
width: 130
height: width
mipmap: true
fillMode: Image.PreserveAspectFit
}
HifiStylesUit.RalewayBold {
id: instructionText
anchors.top: avatarAppQRCodeImage.top
anchors.bottom: avatarAppQRCodeImage.bottom
anchors.left: avatarAppQRCodeImage.right
anchors.leftMargin: 30
anchors.right: parent.right
text: "Use your mobile phone to scan this QR code."
color: simplifiedUI.colors.text.black
size: 22
wrapMode: Text.Wrap
}
}
}
}
SimplifiedControls.VerticalScrollBar {
parent: textContainer
visible: parent.contentHeight > parent.height
size: parent.height / parent.contentHeight
}
}
HifiStylesUit.RalewayBold {
id: continueLink
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.leftMargin: 16
anchors.right: parent.right
anchors.rightMargin: 16
height: 96
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: "No thanks, I'll keep using my default avatar."
color: simplifiedUI.colors.text.lightBlue
opacity: continueMouseArea.containsMouse ? 1.0 : 0.7
size: 24
MouseArea {
id: continueMouseArea
hoverEnabled: true
anchors.fill: parent
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
sendToScript({
"source": "SecondLaunchWindow.qml",
"method": "closeSecondLaunchWindow"
});
}
}
}
Image {
id: topLeftAccentImage
width: 130
height: 320
anchors.left: parent.left
anchors.top: parent.top
source: "images/standOutTopLeft.png"
}
Image {
id: bottomRightAccentImage
width: 250
height: 80
anchors.right: parent.right
anchors.bottom: parent.bottom
source: "images/standOutBottomRight.png"
}
signal sendToScript(var message);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View file

@ -14,7 +14,6 @@
// START CONFIG OPTIONS
var DOCKED_QML_SUPPORTED = true;
var TOOLBAR_NAME = "com.highfidelity.interface.toolbar.system";
var DEFAULT_SCRIPTS_PATH_PREFIX = ScriptDiscoveryService.defaultScriptsPath + "/";
// END CONFIG OPTIONS
@ -160,6 +159,7 @@ var SETTINGS_APP_WINDOW_FLAGS = 0x00000001 | // Qt::Window
0x08000000 | // Qt::WindowCloseButtonHint
0x00008000 | // Qt::WindowMaximizeButtonHint
0x00004000; // Qt::WindowMinimizeButtonHint
var SETTINGS_APP_RIGHT_MARGIN = 48;
var settingsAppWindow = false;
function toggleSettingsApp() {
if (settingsAppWindow) {
@ -179,7 +179,7 @@ function toggleSettingsApp() {
y: SETTINGS_APP_HEIGHT_PX
},
position: {
x: Math.max(Window.x + POPOUT_SAFE_MARGIN_X, Window.x + Window.innerWidth / 2 - SETTINGS_APP_WIDTH_PX / 2),
x: Window.x + Window.innerWidth - SETTINGS_APP_WIDTH_PX - SETTINGS_APP_RIGHT_MARGIN,
y: Math.max(Window.y + POPOUT_SAFE_MARGIN_Y, Window.y + Window.innerHeight / 2 - SETTINGS_APP_HEIGHT_PX / 2)
},
overrideFlags: SETTINGS_APP_WINDOW_FLAGS
@ -283,28 +283,21 @@ function maybeDeleteOutputDeviceMutedOverlay() {
var outputDeviceMutedOverlay = false;
var OUTPUT_DEVICE_MUTED_OVERLAY_DEFAULT_DIMS_PX = 300;
var OUTPUT_DEVICE_MUTED_MARGIN_BOTTOM_PX = 20;
var OUTPUT_DEVICE_MUTED_MARGIN_LEFT_RIGHT_PX = 20;
var OUTPUT_DEVICE_MUTED_OVERLAY_DEFAULT_MARGINS_PX = 20;
var OUTPUT_DEVICE_MUTED_DIMS_RATIO_TO_WINDOW_SIZE = 0.8;
function updateOutputDeviceMutedOverlay(isMuted) {
if (isMuted) {
var props = {
imageURL: Script.resolvePath("images/outputDeviceMuted.svg"),
alpha: 0.5
};
var overlayDims = OUTPUT_DEVICE_MUTED_OVERLAY_DEFAULT_DIMS_PX;
props.x = Window.innerWidth / 2 - overlayDims / 2;
props.y = Window.innerHeight / 2 - overlayDims / 2;
var overlayWithMarginsDims = overlayDims + 2 * OUTPUT_DEVICE_MUTED_OVERLAY_DEFAULT_MARGINS_PX;
var outputDeviceMutedOverlayBottomY = props.y + overlayDims;
var inputDeviceMutedOverlayTopY = INPUT_DEVICE_MUTED_MARGIN_TOP_PX;
if (outputDeviceMutedOverlayBottomY + OUTPUT_DEVICE_MUTED_MARGIN_BOTTOM_PX > inputDeviceMutedOverlayTopY) {
overlayDims = 2 * (inputDeviceMutedOverlayTopY - Window.innerHeight / 2 - OUTPUT_DEVICE_MUTED_MARGIN_BOTTOM_PX);
}
if (overlayDims + OUTPUT_DEVICE_MUTED_MARGIN_LEFT_RIGHT_PX > Window.innerWidth) {
overlayDims = Math.min(Window.innerWidth - OUTPUT_DEVICE_MUTED_MARGIN_LEFT_RIGHT_PX, overlayDims);
} else {
overlayDims = Math.min(OUTPUT_DEVICE_MUTED_OVERLAY_DEFAULT_DIMS_PX, overlayDims);
if (overlayWithMarginsDims > Window.innerHeight || overlayWithMarginsDims > Window.innerWidth) {
var minWindowDims = Math.min(Window.innerHeight, Window.innerWidth);
overlayDims = Math.round(minWindowDims * OUTPUT_DEVICE_MUTED_DIMS_RATIO_TO_WINDOW_SIZE);
}
props.width = overlayDims;
@ -358,6 +351,124 @@ function setOutputMuted(outputMuted) {
}
}
var TOP_BAR_HEIGHT_PX = 48;
var INITIAL_LAUNCH_QML_PATH = Script.resolvePath("./simplifiedFTUE/InitialLaunchWindow.qml");
var INITIAL_LAUNCH_WINDOW_TITLE = "Initial Launch";
var INITIAL_LAUNCH_PRESENTATION_MODE = Desktop.PresentationMode.NATIVE;
var INITIAL_WINDOW_FLAGS = 0x00000001 | // Qt::Window
0x00000008 | // Qt::Popup
0x00000002 | // Qt::Tool
0x00000800 | // Qt::FramelessWindowHint
0x40000000; // Qt::NoDropShadowWindowHint
var initialLaunchWindow = false;
function displayInitialLaunchWindow() {
if (initialLaunchWindow) {
return;
}
simplifiedEmote.handleFTUEScreensVisibilityChanged(true);
initialLaunchWindow = Desktop.createWindow(INITIAL_LAUNCH_QML_PATH, {
title: INITIAL_LAUNCH_WINDOW_TITLE,
presentationMode: INITIAL_LAUNCH_PRESENTATION_MODE,
isFullScreenWindow: true,
overrideFlags: INITIAL_WINDOW_FLAGS
});
initialLaunchWindow.fromQml.connect(onMessageFromInitialLaunchWindow);
Window.location = "file:///~/serverless/tutorial.json";
}
var SECOND_LAUNCH_QML_PATH = Script.resolvePath("simplifiedFTUE/SecondLaunchWindow.qml");
var SECOND_LAUNCH_WINDOW_TITLE = "Second Launch";
var SECOND_LAUNCH_PRESENTATION_MODE = Desktop.PresentationMode.NATIVE;
var SECOND_WINDOW_FLAGS = 0x00000001 | // Qt::Window
0x00000008 | // Qt::Popup
0x00000002 | // Qt::Tool
0x00000800 | // Qt::FramelessWindowHint
0x40000000; // Qt::NoDropShadowWindowHint
var secondLaunchWindow = false;
function displaySecondLaunchWindow() {
if (secondLaunchWindow) {
return;
}
simplifiedEmote.handleFTUEScreensVisibilityChanged(true);
secondLaunchWindow = Desktop.createWindow(SECOND_LAUNCH_QML_PATH, {
title: SECOND_LAUNCH_WINDOW_TITLE,
presentationMode: SECOND_LAUNCH_PRESENTATION_MODE,
isFullScreenWindow: true,
overrideFlags: SECOND_WINDOW_FLAGS
});
secondLaunchWindow.fromQml.connect(onMessageFromSecondLaunchWindow);
Window.location = "file:///~/serverless/tutorial.json";
}
function closeInitialLaunchWindow() {
if (initialLaunchWindow) {
initialLaunchWindow.fromQml.disconnect(onMessageFromInitialLaunchWindow);
initialLaunchWindow.close();
initialLaunchWindow = null;
}
simplifiedEmote.handleFTUEScreensVisibilityChanged(false);
}
function closeSecondLaunchWindow() {
if (secondLaunchWindow) {
secondLaunchWindow.fromQml.disconnect(onMessageFromSecondLaunchWindow);
secondLaunchWindow.close();
secondLaunchWindow = null;
}
simplifiedEmote.handleFTUEScreensVisibilityChanged(false);
}
var INITIAL_LAUNCH_WINDOW_MESSAGE_SOURCE = "InitialLaunchWindow.qml";
function onMessageFromInitialLaunchWindow(message) {
if (message.source !== INITIAL_LAUNCH_WINDOW_MESSAGE_SOURCE) {
return;
}
switch (message.method) {
case "closeInitialLaunchWindow":
closeInitialLaunchWindow();
var homeLocation = LocationBookmarks.getAddress("hqhome");
if (homeLocation) {
Window.location = homeLocation;
}
break;
default:
console.log("Unrecognized message from " + INITIAL_LAUNCH_WINDOW_MESSAGE_SOURCE + ": " + JSON.stringify(message));
break;
}
}
var SECOND_LAUNCH_WINDOW_MESSAGE_SOURCE = "SecondLaunchWindow.qml";
function onMessageFromSecondLaunchWindow(message) {
if (message.source !== SECOND_LAUNCH_WINDOW_MESSAGE_SOURCE) {
return;
}
switch (message.method) {
case "closeSecondLaunchWindow":
closeSecondLaunchWindow();
var homeLocation = LocationBookmarks.getAddress("hqhome");
if (homeLocation) {
Window.location = homeLocation;
}
break;
default:
console.log("Unrecognized message from " + SECOND_LAUNCH_WINDOW_MESSAGE_SOURCE + ": " + JSON.stringify(message));
break;
}
}
var WAIT_FOR_TOP_BAR_MS = 1000;
function sendLocalStatusToQml() {
@ -403,6 +514,14 @@ function onMessageFromTopBar(message) {
si.toggleStatus();
break;
case "displayInitialLaunchWindow":
displayInitialLaunchWindow();
break;
case "displaySecondLaunchWindow":
displaySecondLaunchWindow();
break;
default:
console.log("Unrecognized message from " + TOP_BAR_MESSAGE_SOURCE + ": " + JSON.stringify(message));
break;
@ -431,7 +550,6 @@ var TOP_BAR_QML_PATH = Script.resourcesPath() + "qml/hifi/simplifiedUI/topBar/Si
var TOP_BAR_WINDOW_TITLE = "Simplified Top Bar";
var TOP_BAR_PRESENTATION_MODE = Desktop.PresentationMode.NATIVE;
var TOP_BAR_WIDTH_PX = Window.innerWidth;
var TOP_BAR_HEIGHT_PX = 48;
var topBarWindow = false;
function loadSimplifiedTopBar() {
var windowProps = {
@ -442,16 +560,9 @@ function loadSimplifiedTopBar() {
y: TOP_BAR_HEIGHT_PX
}
};
if (DOCKED_QML_SUPPORTED) {
windowProps.presentationWindowInfo = {
dockArea: Desktop.DockArea.TOP
};
} else {
windowProps.position = {
x: Window.x,
y: Window.y
};
}
windowProps.presentationWindowInfo = {
dockArea: Desktop.DockArea.TOP
};
topBarWindow = Desktop.createWindow(TOP_BAR_QML_PATH, windowProps);
topBarWindow.fromQml.connect(onMessageFromTopBar);
@ -516,32 +627,53 @@ function onHMDInputDeviceMutedChanged(isMuted) {
function onGeometryChanged(rect) {
updateInputDeviceMutedOverlay(Audio.muted);
updateOutputDeviceMutedOverlay(isOutputMuted());
if (topBarWindow && !DOCKED_QML_SUPPORTED) {
topBarWindow.size = {
"x": rect.width,
"y": TOP_BAR_HEIGHT_PX
};
topBarWindow.position = {
"x": rect.x,
"y": rect.y
};
}
var initialLaunchWindowIsMinimized = false;
var secondLaunchWindowIsMinimized = false;
function onWindowMinimizedChanged(isMinimized) {
if (isMinimized) {
handleInitialLaunchWindowVisibleChanged(false);
handleSecondLaunchWindowVisibleChanged(false);
} else if (!HMD.active) {
handleInitialLaunchWindowVisibleChanged(true);
handleSecondLaunchWindowVisibleChanged(true);
}
}
function onWindowMinimizedChanged() {
// prerequisite placeholder for Reduce Friction of Customer Acquisition sub task: https://highfidelity.atlassian.net/browse/DEV-585
print("WINDOW MINIMIZED CHANGED SIGNAL");
function handleInitialLaunchWindowVisibleChanged(shouldBeVisible) {
if (shouldBeVisible && !initialLaunchWindow && initialLaunchWindowIsMinimized) {
displayInitialLaunchWindow();
initialLaunchWindowIsMinimized = false;
} else if (!shouldBeVisible && initialLaunchWindow) {
closeInitialLaunchWindow();
initialLaunchWindowIsMinimized = true;
}
}
function handleSecondLaunchWindowVisibleChanged(shouldBeVisible) {
if (shouldBeVisible && !secondLaunchWindow && secondLaunchWindowIsMinimized) {
displaySecondLaunchWindow();
secondLaunchWindowIsMinimized = false;
} else if (!shouldBeVisible && secondLaunchWindow) {
closeSecondLaunchWindow();
secondLaunchWindowIsMinimized = true;
}
}
function onDisplayModeChanged(isHMDMode) {
if (isHMDMode) {
Camera.setModeString("first person");
Camera.setModeString("first person look at");
}
if (isHMDMode) {
onHMDInputDeviceMutedChanged(Audio.mutedHMD);
handleInitialLaunchWindowVisibleChanged(false);
handleSecondLaunchWindowVisibleChanged(false);
} else {
onDesktopInputDeviceMutedChanged(Audio.mutedDesktop);
handleInitialLaunchWindowVisibleChanged(true);
handleSecondLaunchWindowVisibleChanged(true);
}
}
@ -584,9 +716,9 @@ function restoreLODSettings() {
}
var nametag = Script.require("./simplifiedNametag/simplifiedNametag.js?" + Date.now());
var si = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js?" + Date.now());
var emote = Script.require("../simplifiedEmote/simplifiedEmote.js?" + Date.now());
var nametag = Script.require("./simplifiedNametag/simplifiedNametag.js");
var si = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js");
var simplifiedEmote = Script.require("../simplifiedEmote/simplifiedEmote.js");
var oldShowAudioTools;
var oldShowBubbleTools;
var keepExistingUIAndScriptsSetting = Settings.getValue("simplifiedUI/keepExistingUIAndScripts", false);
@ -653,6 +785,14 @@ function shutdown() {
settingsAppWindow.close();
}
if (initialLaunchWindow) {
closeInitialLaunchWindow();
}
if (secondLaunchWindow) {
closeSecondLaunchWindow();
}
maybeDeleteInputDeviceMutedOverlay();
maybeDeleteOutputDeviceMutedOverlay();

View file

@ -50,11 +50,11 @@ var OVERLAY_DATA_HMD = {
};
var AWAY_INTRO = {
url: "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/kneel.fbx",
url: "https://hifi-content.s3.amazonaws.com/doug/animation/fbx/afk_texting.fbx",
playbackRate: 30.0,
loopFlag: false,
startFrame: 0.0,
endFrame: 83.0
loopFlag: true,
startFrame: 1.0,
endFrame: 489.0
};
// MAIN CONTROL

View file

@ -76,7 +76,7 @@
"tooltip": "The angle in deg at which light emits. Starts in the entity's -z direction, and rotates around its x axis."
},
"keyLight.castShadows": {
"tooltip": "If enabled, shadows are cast. The entity or avatar casting the shadow must also have Cast Shadows enabled."
"tooltip": "If enabled, shadows are cast. The entity or avatar casting the shadow must also have Cast Shadows enabled. Note: Shadows are rendered only on high-profiled computers. This setting will have no effect on computers profiled to medium or low graphics."
},
"keyLight.shadowBias": {
"tooltip": "The bias of the shadows cast by the light. Use this to fine-tune your shadows to your scene to prevent shadow acne and peter panning."
@ -500,7 +500,7 @@
"tooltip": "If enabled, grabbed entities will follow the movements of your hand controller instead of your avatar's hand."
},
"canCastShadow": {
"tooltip": "If enabled, this geometry of this entity casts shadows when a shadow-casting light source shines on it."
"tooltip": "If enabled, the geometry of this entity casts shadows when a shadow-casting light source shines on it. Note: Shadows are rendered only on high-profiled computers. This setting will have no effect on computers profiled to medium or low graphics.."
},
"ignorePickIntersection": {
"tooltip": "If enabled, this entity will not be considered for ray picks, and will also not occlude other entities when picking."

View file

@ -16,7 +16,7 @@
// Automatically enter first person mode when entering HMD mode
HMD.displayModeChanged.connect(function(isHMDMode) {
if (isHMDMode) {
Camera.setModeString("first person");
Camera.setModeString("first person look at");
}
});

View file

@ -272,7 +272,7 @@
currentProgress = 0.0;
connectionToDomainFailed = false;
previousCameraMode = Camera.mode;
Camera.mode = "first person";
Camera.mode = "first person look at";
updateProgressBar(0.0);
scaleInterstitialPage(MyAvatar.sensorToWorldScale);
timer = Script.setTimeout(update, 2000);

View file

@ -52,8 +52,8 @@ function calcSpawnInfo(hand, landscape) {
var LEFT_HAND = Controller.Standard.LeftHand;
var sensorToWorldScale = MyAvatar.sensorToWorldScale;
var headPos = (HMD.active && Camera.mode === "first person") ? HMD.position : Camera.position;
var headRot = Quat.cancelOutRollAndPitch((HMD.active && Camera.mode === "first person") ?
var headPos = (HMD.active && (Camera.mode === "first person" || Camera.mode === "first person look at")) ? HMD.position : Camera.position;
var headRot = Quat.cancelOutRollAndPitch((HMD.active && (Camera.mode === "first person" || Camera.mode === "first person look at")) ?
HMD.orientation : Camera.orientation);
var right = Quat.getRight(headRot);

View file

@ -53,7 +53,7 @@
function handJointName(hand) {
var jointName;
if (hand === LEFT_HAND) {
if (Camera.mode === "first person") {
if (Camera.mode === "first person" || Camera.mode === "first person look at") {
jointName = "_CONTROLLER_LEFTHAND";
} else if (Camera.mode === "third person") {
jointName = "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND";
@ -61,7 +61,7 @@
jointName = "LeftHand";
}
} else {
if (Camera.mode === "first person") {
if (Camera.mode === "first person" || Camera.mode === "first person look at") {
jointName = "_CONTROLLER_RIGHTHAND";
} else if (Camera.mode === "third person") {
jointName = "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND";

View file

@ -61,17 +61,21 @@ Item {
Rectangle {
width: 5
height: 5
color: "red"
ColorAnimation on color { loops: Animation.Infinite; from: "red"; to: "yellow"; duration: 1000 }
color: "blue"
ColorAnimation on color { loops: Animation.Infinite; from: "blue"; to: "yellow"; duration: 1000 }
}
WebEngineView {
id: root
url: "https://google.com/"
x: 6; y: 6;
width: parent.width * 0.8
height: parent.height * 0.8
url: "https://www.webrtc-experiment.com/Pluginfree-Screen-Sharing/#19583796789766627"
// url: "https://vimeo.com/108650530"
// url: "https://www.youtube.com/watch?v=7EWQOeQf32U&autoplay=1&loop=1"
// x: 6; y: 6;
anchors.fill: parent
// width: parent.width * 0.8
// height: parent.height * 0.8
}
}

View file

@ -39,7 +39,7 @@ void MacQml::init() {
_surface->load(url, callback);
_surface->resize(_window->size());
_surface->resume();
_window->installEventFilter(_surface.get());
}
void MacQml::draw() {

View file

@ -9,7 +9,7 @@ public:
QmlPtr _surface;
GLuint _fbo{ 0 };
MacQml(const QWindow* window) : Parent(window) {}
MacQml(QWindow* window) : Parent(window) {}
void update() override;
void init() override;
void draw() override;

View file

@ -24,7 +24,7 @@ public:
std::array<std::array<QmlInfo, DIVISIONS_Y>, DIVISIONS_X> _surfaces;
GLuint _fbo{ 0 };
StressWeb(const QWindow* window) : Parent(window) {}
StressWeb(QWindow* window) : Parent(window) {}
static QString getSourceUrl(bool video);
void buildSurface(QmlInfo& qmlInfo, bool video);
void destroySurface(QmlInfo& qmlInfo);

View file

@ -8,8 +8,8 @@
class TestCase {
public:
using QmlPtr = QSharedPointer<hifi::qml::OffscreenSurface>;
using Builder = std::function<TestCase*(const QWindow*)>;
TestCase(const QWindow* window) : _window(window) {}
using Builder = std::function<TestCase*(QWindow*)>;
TestCase(QWindow* window) : _window(window) {}
virtual void init();
virtual void destroy();
virtual void update();
@ -18,6 +18,6 @@ public:
protected:
QOpenGLFunctions_4_1_Core _glf;
const QWindow* _window;
QWindow* _window;
std::function<void(uint32_t, void*)> _discardLamdba;
};

View file

@ -205,12 +205,22 @@ void TestWindow::resizeEvent(QResizeEvent* ev) {
int main(int argc, char** argv) {
#ifdef Q_OS_MAC
auto format = getDefaultOpenGLSurfaceFormat();
format.setVersion(4, 1);
// Deal with some weirdness in the chromium context sharing on Mac.
// The primary share context needs to be 3.2, so that the Chromium will
// succeed in it's creation of it's command stub contexts.
format.setVersion(3, 2);
// This appears to resolve the issues with corrupted fonts on OSX. No
// idea why.
qputenv("QT_ENABLE_GLYPH_CACHE_WORKAROUND", "true");
// https://i.kym-cdn.com/entries/icons/original/000/008/342/ihave.jpg
QSurfaceFormat::setDefaultFormat(format);
#endif
QGuiApplication app(argc, argv);
TestCase::Builder builder = [](const QWindow* window)->TestCase*{ return new MacQml(window); };
TestCase::Builder builder = [](QWindow* window)->TestCase*{ return new MacQml(window); };
TestWindow window(builder);
return app.exec();
}

View file

@ -1,8 +1,10 @@
# General
This document describes the process to build Qt 5.12.3.
Note that there are three patches. The first (to qfloat16.h) is needed to compile QT 5.12.3 on Visual Studio 2017 due to a bug in Visual Studio (*bitset* will not compile. Note that there is a change in CMakeLists.txt to support this.
The second patch is to OpenSL ES audio.
The third is a patch to QScriptEngine to prevent crashes in QScriptEnginePrivate::reportAdditionalMemoryCost, during garbage collection. See https://bugreports.qt.io/browse/QTBUG-76176
Note that there are several patches.
* The first (to qfloat16.h) is needed to compile QT 5.12.3 on Visual Studio 2017 due to a bug in Visual Studio (*bitset* will not compile. Note that there is a change in CMakeLists.txt to support this.
* The second patch is to OpenSL ES audio and allow audio echo cancelllation on Android.
* The third is a patch to QScriptEngine to prevent crashes in QScriptEnginePrivate::reportAdditionalMemoryCost, during garbage collection. See https://bugreports.qt.io/browse/QTBUG-76176
* The fourth is a patch which fixes video playback on WebEngineViews on mac. See https://bugreports.qt.io/browse/QTBUG-70967
## Requirements
### Windows
1. Visual Studio 2017
@ -222,6 +224,7 @@ git clone --recursive git://code.qt.io/qt/qt5.git -b 5.12.3 --single-branch
`cd qt5`
`git apply --ignore-space-change --ignore-whitespace patches/aec.patch`
`git apply --ignore-space-change --ignore-whitespace patches/qtscript-crash-fix.patch`
`git apply --ignore-space-change --ignore-whitespace patches/mac-web-video.patch`
`cd ..`
#### Configuring
`mkdir qt5-install`

View file

@ -0,0 +1,247 @@
Submodule qtwebengine contains modified content
diff --git a/qtwebengine/src/core/stream_video_node.cpp b/qtwebengine/src/core/stream_video_node.cpp
index 29922f86..baa39d3b 100644
--- a/qtwebengine/src/core/stream_video_node.cpp
+++ b/qtwebengine/src/core/stream_video_node.cpp
@@ -62,38 +62,45 @@ protected:
const char *vertexShader() const override {
// Keep in sync with cc::VertexShaderVideoTransform
static const char *shader =
- "attribute highp vec4 a_position;\n"
- "attribute mediump vec2 a_texCoord;\n"
- "uniform highp mat4 matrix;\n"
- "uniform highp mat4 texMatrix;\n"
- "varying mediump vec2 v_texCoord;\n"
- "void main() {\n"
- " gl_Position = matrix * a_position;\n"
- " v_texCoord = vec4(texMatrix * vec4(a_texCoord.x, 1.0 - a_texCoord.y, 0.0, 1.0)).xy;\n"
- "}";
+ R"SHADER(#version 150 core
+in vec4 a_position;
+in vec2 a_texCoord;
+uniform mat4 matrix;
+uniform mat4 texMatrix;
+out vec2 v_texCoord;
+void main() {
+ gl_Position = matrix * a_position;
+ v_texCoord = vec4(texMatrix * vec4(a_texCoord.x, 1.0 - a_texCoord.y, 0.0, 1.0)).xy;
+}
+ )SHADER";
return shader;
}
const char *fragmentShader() const override {
// Keep in sync with cc::FragmentShaderRGBATexAlpha
static const char *shaderExternal =
- "#extension GL_OES_EGL_image_external : require\n"
- "varying mediump vec2 v_texCoord;\n"
- "uniform samplerExternalOES s_texture;\n"
- "uniform lowp float alpha;\n"
- "void main() {\n"
- " lowp vec4 texColor = texture2D(s_texture, v_texCoord);\n"
- " gl_FragColor = texColor * alpha;\n"
- "}";
+ R"SHADER(#version 150 core
+#extension GL_OES_EGL_image_external : require
+in vec2 v_texCoord;
+uniform samplerExternalOES s_texture;
+uniform float alpha;
+out vec4 fragColor;
+void main() {
+ vec4 texColor = texture(s_texture, v_texCoord);
+ fragColor = texColor * alpha;
+}
+ )SHADER";
static const char *shader2DRect =
- "#extension GL_ARB_texture_rectangle : require\n"
- "varying mediump vec2 v_texCoord;\n"
- "uniform sampler2DRect s_texture;\n"
- "uniform lowp float alpha;\n"
- "void main() {\n"
- " lowp vec4 texColor = texture2DRect(s_texture, v_texCoord);\n"
- " gl_FragColor = texColor * alpha;\n"
- "}";
+ R"SHADER(#version 150 core
+in vec2 v_texCoord;
+uniform sampler2D s_texture;
+uniform float alpha;
+out vec4 fragColor;
+void main() {
+ vec4 texColor = texture(s_texture, v_texCoord);
+ fragColor = texColor * alpha;
+}
+ )SHADER";
if (m_target == ExternalTarget)
return shaderExternal;
else
diff --git a/qtwebengine/src/core/yuv_video_node.cpp b/qtwebengine/src/core/yuv_video_node.cpp
index 4a436d95..dc4b6ff9 100644
--- a/qtwebengine/src/core/yuv_video_node.cpp
+++ b/qtwebengine/src/core/yuv_video_node.cpp
@@ -59,39 +59,41 @@ public:
YUVVideoMaterialShader(const gfx::ColorSpace &colorSpace)
{
static const char *shaderHead =
- "varying mediump vec2 v_yaTexCoord;\n"
- "varying mediump vec2 v_uvTexCoord;\n"
- "uniform sampler2D y_texture;\n"
- "uniform sampler2D u_texture;\n"
- "uniform sampler2D v_texture;\n"
- "uniform mediump float alpha;\n"
- "uniform mediump vec4 ya_clamp_rect;\n"
- "uniform mediump vec4 uv_clamp_rect;\n";
- static const char *shader =
- "void main() {\n"
- " mediump vec2 ya_clamped =\n"
- " max(ya_clamp_rect.xy, min(ya_clamp_rect.zw, v_yaTexCoord));\n"
- " mediump float y_raw = texture2D(y_texture, ya_clamped).x;\n"
- " mediump vec2 uv_clamped =\n"
- " max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord));\n"
- " mediump float u_unsigned = texture2D(u_texture, uv_clamped).x;\n"
- " mediump float v_unsigned = texture2D(v_texture, uv_clamped).x;\n"
- " mediump vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned);\n"
- " mediump vec3 rgb = DoColorConversion(yuv);\n"
- " gl_FragColor = vec4(rgb, 1.0) * alpha;\n"
- "}";
+ R"SHADER(#version 150 core
+in vec2 v_yaTexCoord;
+in vec2 v_uvTexCoord;
+uniform sampler2D y_texture;
+uniform sampler2D u_texture;
+uniform sampler2D v_texture;
+uniform float alpha;
+uniform vec4 ya_clamp_rect;
+uniform vec4 uv_clamp_rect;
+out vec4 fragColor;
+ )SHADER";
+
+ static const char *shader = R"SHADER(
+void main() {
+ vec2 ya_clamped =
+ max(ya_clamp_rect.xy, min(ya_clamp_rect.zw, v_yaTexCoord));
+ float y_raw = texture(y_texture, ya_clamped).x;
+ vec2 uv_clamped =
+ max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord));
+ float u_unsigned = texture(u_texture, uv_clamped).x;
+ float v_unsigned = texture(v_texture, uv_clamped).x;
+ vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned);
+ vec3 rgb = DoColorConversion(yuv);
+ fragColor = vec4(rgb, 1.0) * alpha;
+}
+ )SHADER";
+
// Invalid or unspecified color spaces should be treated as REC709.
gfx::ColorSpace src = colorSpace.IsValid() ? colorSpace : gfx::ColorSpace::CreateREC709();
gfx::ColorSpace dst = gfx::ColorSpace::CreateSRGB();
std::unique_ptr<gfx::ColorTransform> transform =
gfx::ColorTransform::NewColorTransform(src, dst, gfx::ColorTransform::Intent::INTENT_PERCEPTUAL);
- QByteArray header(shaderHead);
- if (QOpenGLContext::currentContext()->isOpenGLES())
- header = QByteArray("precision mediump float;\n") + header;
-
m_csShader = QByteArray::fromStdString(transform->GetShaderSource());
- m_fragmentShader = header + m_csShader + QByteArray(shader);
+ m_fragmentShader = QByteArray(shaderHead) + m_csShader + QByteArray(shader);
}
void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
@@ -108,20 +110,22 @@ protected:
const char *vertexShader() const override {
// Keep in sync with logic in VertexShader in components/viz/service/display/shader.cc
const char *shader =
- "attribute highp vec4 a_position;\n"
- "attribute mediump vec2 a_texCoord;\n"
- "uniform highp mat4 matrix;\n"
- "varying mediump vec2 v_yaTexCoord;\n"
- "varying mediump vec2 v_uvTexCoord;\n"
- "uniform mediump vec2 yaTexScale;\n"
- "uniform mediump vec2 yaTexOffset;\n"
- "uniform mediump vec2 uvTexScale;\n"
- "uniform mediump vec2 uvTexOffset;\n"
- "void main() {\n"
- " gl_Position = matrix * a_position;\n"
- " v_yaTexCoord = a_texCoord * yaTexScale + yaTexOffset;\n"
- " v_uvTexCoord = a_texCoord * uvTexScale + uvTexOffset;\n"
- "}";
+ R"SHADER(#version 150 core
+in vec4 a_position;
+in vec2 a_texCoord;
+uniform mat4 matrix;
+out vec2 v_yaTexCoord;
+out vec2 v_uvTexCoord;
+uniform vec2 yaTexScale;
+uniform vec2 yaTexOffset;
+uniform vec2 uvTexScale;
+uniform vec2 uvTexOffset;
+void main() {
+ gl_Position = matrix * a_position;
+ v_yaTexCoord = a_texCoord * yaTexScale + yaTexOffset;
+ v_uvTexCoord = a_texCoord * uvTexScale + uvTexOffset;
+}
+ )SHADER";
return shader;
}
@@ -168,33 +172,35 @@ public:
YUVAVideoMaterialShader(const gfx::ColorSpace &colorSpace) : YUVVideoMaterialShader(colorSpace)
{
static const char *shaderHead =
- "varying mediump vec2 v_yaTexCoord;\n"
- "varying mediump vec2 v_uvTexCoord;\n"
- "uniform sampler2D y_texture;\n"
- "uniform sampler2D u_texture;\n"
- "uniform sampler2D v_texture;\n"
- "uniform sampler2D a_texture;\n"
- "uniform mediump float alpha;\n"
- "uniform mediump vec4 ya_clamp_rect;\n"
- "uniform mediump vec4 uv_clamp_rect;\n";
+ R"SHADER(#version 150 core
+in vec2 v_yaTexCoord;
+in vec2 v_uvTexCoord;
+uniform sampler2D y_texture;
+uniform sampler2D u_texture;
+uniform sampler2D v_texture;
+uniform sampler2D a_texture;
+uniform float alpha;
+uniform vec4 ya_clamp_rect;
+uniform vec4 uv_clamp_rect;
+out vec4 fragColor;
+ )SHADER";
static const char *shader =
- "void main() {\n"
- " mediump vec2 ya_clamped =\n"
- " max(ya_clamp_rect.xy, min(ya_clamp_rect.zw, v_yaTexCoord));\n"
- " mediump float y_raw = texture2D(y_texture, ya_clamped).x;\n"
- " mediump vec2 uv_clamped =\n"
- " max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord));\n"
- " mediump float u_unsigned = texture2D(u_texture, uv_clamped).x;\n"
- " mediump float v_unsigned = texture2D(v_texture, uv_clamped).x;\n"
- " mediump float a_raw = texture2D(a_texture, ya_clamped).x;\n"
- " mediump vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned);\n"
- " mediump vec3 rgb = DoColorConversion(yuv);\n"
- " gl_FragColor = vec4(rgb, 1.0) * (alpha * a_raw);\n"
- "}";
- QByteArray header(shaderHead);
- if (QOpenGLContext::currentContext()->isOpenGLES())
- header = QByteArray("precision mediump float;\n") + header;
- m_fragmentShader = header + m_csShader + QByteArray(shader);
+ R"SHADER(
+void main() {
+ vec2 ya_clamped =
+ max(ya_clamp_rect.xy, min(ya_clamp_rect.zw, v_yaTexCoord));
+ float y_raw = texture(y_texture, ya_clamped).x;
+ vec2 uv_clamped =
+ max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord));
+ float u_unsigned = texture(u_texture, uv_clamped).x;
+ float v_unsigned = texture(v_texture, uv_clamped).x;
+ float a_raw = texture(a_texture, ya_clamped).x;
+ vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned);
+ vec3 rgb = DoColorConversion(yuv);
+ fragColor = vec4(rgb, 1.0) * (alpha * a_raw);
+}
+ )SHADER";
+ m_fragmentShader = QByteArray(shaderHead) + m_csShader + QByteArray(shader);
}
void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;