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) { void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) {
quint64 start = usecTimestampNow(); 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); broadcastAvatarDataToAgent(node);
} else if (node->getType() == NodeType::DownstreamAvatarMixer) { } else if (node->getType() == NodeType::DownstreamAvatarMixer) {
broadcastAvatarDataToDownstreamMixer(node); broadcastAvatarDataToDownstreamMixer(node);
@ -448,13 +448,6 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
// or that somehow we haven't sent // or that somehow we haven't sent
if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) { if (lastSeqToReceiver == lastSeqFromSender && lastSeqToReceiver != 0) {
++numAvatarsHeldBack; ++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; sendAvatar = false;
} else if (lastSeqFromSender == 0) { } else if (lastSeqFromSender == 0) {
// We have have not yet received any data about this avatar. Ignore it for now // 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"); this, "handleOctreePacket");
packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat"); packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat");
auto avatarHashMap = DependencyManager::set<AvatarHashMap>();
packetReceiver.registerListener(PacketType::ReloadEntityServerScript, this, "handleReloadEntityServerScriptPacket"); packetReceiver.registerListener(PacketType::ReloadEntityServerScript, this, "handleReloadEntityServerScriptPacket");
packetReceiver.registerListener(PacketType::EntityScriptGetStatus, this, "handleEntityScriptGetStatusPacket"); packetReceiver.registerListener(PacketType::EntityScriptGetStatus, this, "handleEntityScriptGetStatusPacket");
packetReceiver.registerListener(PacketType::EntityServerScriptLog, this, "handleEntityServerScriptLogPacket"); packetReceiver.registerListener(PacketType::EntityServerScriptLog, this, "handleEntityServerScriptLogPacket");
@ -255,6 +253,7 @@ void EntityScriptServer::handleEntityScriptCallMethodPacket(QSharedPointer<Recei
void EntityScriptServer::run() { void EntityScriptServer::run() {
DependencyManager::set<ScriptEngines>(ScriptEngine::ENTITY_SERVER_SCRIPT); DependencyManager::set<ScriptEngines>(ScriptEngine::ENTITY_SERVER_SCRIPT);
DependencyManager::set<EntityScriptServerServices>(); DependencyManager::set<EntityScriptServerServices>();
DependencyManager::set<AvatarHashMap>();
// make sure we request our script once the agent connects to the domain // make sure we request our script once the agent connects to the domain
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
@ -448,6 +447,7 @@ void EntityScriptServer::resetEntitiesScriptEngine() {
newEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue); newEngine->globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue);
newEngine->registerGlobalObject("SoundCache", DependencyManager::get<SoundCacheScriptingInterface>().data()); 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 // connect this script engines printedMessage signal to the global ScriptEngines these various messages
auto scriptEngines = DependencyManager::get<ScriptEngines>().data(); auto scriptEngines = DependencyManager::get<ScriptEngines>().data();

View file

@ -6,8 +6,8 @@ if (WIN32)
include(ExternalProject) include(ExternalProject)
ExternalProject_Add( ExternalProject_Add(
${EXTERNAL_NAME} ${EXTERNAL_NAME}
URL https://public.highfidelity.com/dependencies/qtaudio_wasapi11.zip URL https://public.highfidelity.com/dependencies/qtaudio_wasapi12.zip
URL_MD5 d0eb8489455e7f79d59155535a2c8861 URL_MD5 9e2eef41165f85344808f754b48bf08d
CONFIGURE_COMMAND "" CONFIGURE_COMMAND ""
BUILD_COMMAND "" BUILD_COMMAND ""
INSTALL_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 REF ab8f16961e19a86ee20c6a1d61f662392524cc77
SHA512 927742db29867517283d45e475f0c534a9a57e165cae221f26e08e88057253a1682ac9919b2dc547b9cf388ba0b931b175623461d44f28c9184796ba90b1ed55 SHA512 927742db29867517283d45e475f0c534a9a57e165cae221f26e08e88057253a1682ac9919b2dc547b9cf388ba0b931b175623461d44f28c9184796ba90b1ed55
HEAD_REF master HEAD_REF master
PATCHES "bullet-git-fix-build-clang-8.patch"
) )
vcpkg_configure_cmake( vcpkg_configure_cmake(

View file

@ -1,4 +1,4 @@
Source: hifi-deps Source: hifi-deps
Version: 0.1 Version: 0.3
Description: Collected dependencies for High Fidelity applications Description: Collected dependencies for High Fidelity applications
Build-Depends: bullet3, draco, etc2comp, glm, nvtt, openexr (!android), openssl (windows), tbb (!android&!osx), zlib, webrtc (!android) 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 downloadVcpkg = True
if not downloadVcpkg and not os.path.isfile(self.exe): if not downloadVcpkg and not os.path.isfile(self.exe):
print("Missing executable, boostrapping") print("Missing executable, boot-strapping")
downloadVcpkg = True downloadVcpkg = True
# Make sure we have a vcpkg executable # Make sure we have a vcpkg executable
@ -265,7 +265,7 @@ endif()
if platform.system() == 'Windows': if platform.system() == 'Windows':
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-windows3.tar.gz' url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-windows3.tar.gz'
elif platform.system() == 'Darwin': 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': elif platform.system() == 'Linux':
if platform.linux_distribution()[1][:3] == '16.': 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' 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", "easingType": "easeInOutQuad",
"id": "talk", "id": "talk",
"interpDuration": 1, "interpDuration": 20,
"interpTarget": 1, "interpTarget": 20,
"interpType": "evaluateBoth", "interpType": "evaluateBoth",
"priority": 0.33, "priority": 0.33,
"resume": true, "resume": true,
@ -2489,8 +2489,8 @@
{ {
"easingType": "easeInOutQuad", "easingType": "easeInOutQuad",
"id": "talk02", "id": "talk02",
"interpDuration": 1, "interpDuration": 20,
"interpTarget": 1, "interpTarget": 20,
"interpType": "evaluateBoth", "interpType": "evaluateBoth",
"priority": 0.33, "priority": 0.33,
"resume": true, "resume": true,
@ -2500,8 +2500,8 @@
{ {
"easingType": "easeInOutQuad", "easingType": "easeInOutQuad",
"id": "talk03", "id": "talk03",
"interpDuration": 1, "interpDuration": 20,
"interpTarget": 1, "interpTarget": 20,
"interpType": "evaluateBoth", "interpType": "evaluateBoth",
"priority": 0.33, "priority": 0.33,
"resume": true, "resume": true,
@ -2511,8 +2511,8 @@
{ {
"easingType": "easeInOutQuad", "easingType": "easeInOutQuad",
"id": "talk04", "id": "talk04",
"interpDuration": 1, "interpDuration": 20,
"interpTarget": 1, "interpTarget": 20,
"interpType": "evaluateBoth", "interpType": "evaluateBoth",
"priority": 0.33, "priority": 0.33,
"resume": true, "resume": true,
@ -2522,8 +2522,8 @@
{ {
"easingType": "easeInOutQuad", "easingType": "easeInOutQuad",
"id": "talk_armsdown", "id": "talk_armsdown",
"interpDuration": 1, "interpDuration": 20,
"interpTarget": 1, "interpTarget": 20,
"interpType": "evaluateBoth", "interpType": "evaluateBoth",
"priority": 0.33, "priority": 0.33,
"resume": true, "resume": true,
@ -2533,8 +2533,8 @@
{ {
"easingType": "easeInOutQuad", "easingType": "easeInOutQuad",
"id": "talk_lefthand", "id": "talk_lefthand",
"interpDuration": 1, "interpDuration": 20,
"interpTarget": 1, "interpTarget": 20,
"interpType": "evaluateBoth", "interpType": "evaluateBoth",
"priority": 0.33, "priority": 0.33,
"resume": true, "resume": true,
@ -2544,8 +2544,8 @@
{ {
"easingType": "easeInOutQuad", "easingType": "easeInOutQuad",
"id": "talk_righthand", "id": "talk_righthand",
"interpDuration": 1, "interpDuration": 20,
"interpTarget": 1, "interpTarget": 20,
"interpType": "evaluateBoth", "interpType": "evaluateBoth",
"priority": 0.33, "priority": 0.33,
"resume": true, "resume": true,
@ -4736,32 +4736,6 @@
}, },
{ {
"children": [ "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": [ "children": [
], ],
@ -4819,8 +4793,6 @@
"alpha": 0, "alpha": 0,
"alphaVar": "moveLateralAlpha", "alphaVar": "moveLateralAlpha",
"characteristicSpeeds": [ "characteristicSpeeds": [
0.1,
0.5,
1, 1,
2.55, 2.55,
3.35, 3.35,
@ -4834,34 +4806,6 @@
}, },
{ {
"children": [ "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": [ "children": [
], ],
@ -4923,8 +4867,6 @@
"alpha": 0, "alpha": 0,
"alphaVar": "moveLateralAlpha", "alphaVar": "moveLateralAlpha",
"characteristicSpeeds": [ "characteristicSpeeds": [
0.1,
0.5,
1, 1,
2.55, 2.55,
3.4, 3.4,
@ -5242,62 +5184,6 @@
"interpTarget": 6, "interpTarget": 6,
"interpType": "evaluateBoth", "interpType": "evaluateBoth",
"transitions": [ "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", "state": "idle",
"var": "isNotSeated" "var": "isNotSeated"
@ -5307,7 +5193,7 @@
{ {
"easingType": "easeInOutQuad", "easingType": "easeInOutQuad",
"id": "idle", "id": "idle",
"interpDuration": 20, "interpDuration": 15,
"interpTarget": 20, "interpTarget": 20,
"interpType": "evaluateBoth", "interpType": "evaluateBoth",
"transitions": [ "transitions": [
@ -5439,8 +5325,8 @@
{ {
"easingType": "easeInOutQuad", "easingType": "easeInOutQuad",
"id": "idleSettle", "id": "idleSettle",
"interpDuration": 15, "interpDuration": 13,
"interpTarget": 15, "interpTarget": 14,
"interpType": "snapshotPrev", "interpType": "snapshotPrev",
"transitions": [ "transitions": [
{ {
@ -5533,7 +5419,7 @@
"transitions": [ "transitions": [
{ {
"state": "idleSettle", "state": "idleSettle",
"var": "isNotInput" "var": "isNotInputSlow"
}, },
{ {
"state": "WALKBWD", "state": "WALKBWD",
@ -5597,7 +5483,7 @@
"transitions": [ "transitions": [
{ {
"state": "idleSettle", "state": "idleSettle",
"var": "isNotInput" "var": "isNotInputSlow"
}, },
{ {
"state": "WALKFWD", "state": "WALKFWD",
@ -5661,7 +5547,7 @@
"transitions": [ "transitions": [
{ {
"state": "idleSettle", "state": "idleSettle",
"var": "isNotInput" "var": "isNotInputSlow"
}, },
{ {
"state": "WALKFWD", "state": "WALKFWD",
@ -5673,7 +5559,7 @@
}, },
{ {
"state": "STRAFELEFT", "state": "STRAFELEFT",
"var": "isInputLeft" "var": "isMovingLeft"
}, },
{ {
"state": "turnRight", "state": "turnRight",
@ -5725,7 +5611,7 @@
"transitions": [ "transitions": [
{ {
"state": "idleSettle", "state": "idleSettle",
"var": "isNotInput" "var": "isNotInputSlow"
}, },
{ {
"state": "WALKFWD", "state": "WALKFWD",
@ -5737,7 +5623,7 @@
}, },
{ {
"state": "STRAFERIGHT", "state": "STRAFERIGHT",
"var": "isInputRight" "var": "isMovingRight"
}, },
{ {
"state": "turnRight", "state": "turnRight",

View file

@ -78,6 +78,15 @@
"to": "Actions.Yaw" "to": "Actions.Yaw"
}, },
{ "from": { "makeAxis" : [
["Keyboard.Left"],
["Keyboard.Right"]
]
},
"when": ["Application.CameraFirstPersonLookat", "!Keyboard.Shift"],
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [ { "from": { "makeAxis" : [
["Keyboard.Left"], ["Keyboard.Left"],
["Keyboard.Right"] ["Keyboard.Right"]
@ -114,6 +123,15 @@
"to": "Actions.Yaw" "to": "Actions.Yaw"
}, },
{ "from": { "makeAxis" : [
["Keyboard.A"],
["Keyboard.D"]
]
},
"when": ["Application.CameraFirstPersonLookat", "!Keyboard.Control"],
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [ { "from": { "makeAxis" : [
["Keyboard.A"], ["Keyboard.A"],
["Keyboard.D"] ["Keyboard.D"]
@ -150,6 +168,15 @@
"to": "Actions.Yaw" "to": "Actions.Yaw"
}, },
{ "from": { "makeAxis" : [
["Keyboard.TouchpadLeft"],
["Keyboard.TouchpadRight"]
]
},
"when": "Application.CameraFirstPersonLookat",
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [ { "from": { "makeAxis" : [
["Keyboard.TouchpadLeft"], ["Keyboard.TouchpadLeft"],
["Keyboard.TouchpadRight"] ["Keyboard.TouchpadRight"]
@ -222,10 +249,12 @@
{ "from": "Keyboard.Left", "when": "Keyboard.Shift", "to": "Actions.LATERAL_LEFT" }, { "from": "Keyboard.Left", "when": "Keyboard.Shift", "to": "Actions.LATERAL_LEFT" },
{ "from": "Keyboard.Right", "when": "Keyboard.Shift", "to": "Actions.LATERAL_RIGHT" }, { "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.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.CameraThirdPerson", "to": "Actions.LONGITUDINAL_FORWARD" },
{ "from": "Keyboard.Up", "when": "Application.CameraLookAt", "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.Up", "when": "Application.CameraSelfie", "to": "Actions.LONGITUDINAL_BACKWARD" },
{ "from": "Keyboard.Down", "when": "Application.CameraFirstPerson", "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.CameraThirdPerson", "to": "Actions.LONGITUDINAL_BACKWARD" },
{ "from": "Keyboard.Down", "when": "Application.CameraLookAt", "to": "Actions.LONGITUDINAL_BACKWARD" }, { "from": "Keyboard.Down", "when": "Application.CameraLookAt", "to": "Actions.LONGITUDINAL_BACKWARD" },
{ "from": "Keyboard.Down", "when": "Application.CameraSelfie", "to": "Actions.LONGITUDINAL_FORWARD" }, { "from": "Keyboard.Down", "when": "Application.CameraSelfie", "to": "Actions.LONGITUDINAL_FORWARD" },

View file

@ -33,6 +33,12 @@ Item {
property var item: null property var item: null
function load(url, scriptUrl) { 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) { QmlSurface.load("./controls/WebView.qml", root, function(newItem) {
root.item = newItem root.item = newItem
root.item.url = url root.item.url = url

View file

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

View file

@ -9,6 +9,7 @@
// //
import QtQuick 2.10 import QtQuick 2.10
import QtQuick.Layouts 1.3
import "../simplifiedConstants" as SimplifiedConstants import "../simplifiedConstants" as SimplifiedConstants
import "../simplifiedControls" as SimplifiedControls import "../simplifiedControls" as SimplifiedControls
import "./components" as AvatarAppComponents import "./components" as AvatarAppComponents
@ -79,7 +80,11 @@ Rectangle {
errorText.text = "There was a problem while retrieving your inventory. " + 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; "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) { } 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); avatarAppInventoryModel.handlePage(result.status !== "success" && result.message, result);
@ -140,8 +145,95 @@ Rectangle {
anchors.rightMargin: 24 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 { Item {
id: avatarInfoTextContainer id: avatarInfoTextContainer
visible: !emptyInventoryContainer.visible
width: parent.implicitWidth width: parent.implicitWidth
height: childrenRect.height height: childrenRect.height
anchors.top: displayNameHeader.bottom anchors.top: displayNameHeader.bottom
@ -164,7 +256,7 @@ Rectangle {
id: yourAvatarsSubtitle id: yourAvatarsSubtitle
text: "These are the avatars that you've created and uploaded via the Avatar Creator." text: "These are the avatars that you've created and uploaded via the Avatar Creator."
width: parent.width width: parent.width
wrapMode: Text.WordWrap wrapMode: Text.Wrap
anchors.top: yourAvatarsTitle.bottom anchors.top: yourAvatarsTitle.bottom
anchors.topMargin: 6 anchors.topMargin: 6
verticalAlignment: TextInput.AlignVCenter verticalAlignment: TextInput.AlignVCenter
@ -208,9 +300,10 @@ Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
visible: !emptyInventoryContainer.visible
AnimatedImage { AnimatedImage {
visible: !inventoryContentsList.visible && !errorText.visible visible: !(inventoryContentsList.visible || errorText.visible)
anchors.centerIn: parent anchors.centerIn: parent
width: 72 width: 72
height: width height: width
@ -271,6 +364,8 @@ Rectangle {
return; return;
} }
} }
root.avatarPreviewUrl = "../../images/defaultAvatar.svg";
} }
function fromScript(message) { 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 { SimplifiedControls.RadioButton {
id: firstPerson id: firstPerson
text: "First Person View" text: "First Person View"
checked: Camera.mode === "first person" checked: Camera.mode === "first person look at"
onClicked: { onClicked: {
Camera.mode = "first person" Camera.mode = "first person look at"
} }
} }
@ -254,7 +254,7 @@ Flickable {
target: Camera target: Camera
onModeUpdated: { onModeUpdated: {
if (Camera.mode === "first person") { if (Camera.mode === "first person look at") {
firstPerson.checked = true firstPerson.checked = true
} else if (Camera.mode === "look at") { } else if (Camera.mode === "look at") {
thirdPerson.checked = true thirdPerson.checked = true

View file

@ -54,8 +54,8 @@ Rectangle {
if ((MyAvatar.skeletonModelURL.indexOf("defaultAvatar") > -1 || MyAvatar.skeletonModelURL.indexOf("fst") === -1) && if ((MyAvatar.skeletonModelURL.indexOf("defaultAvatar") > -1 || MyAvatar.skeletonModelURL.indexOf("fst") === -1) &&
topBarInventoryModel.count > 0) { topBarInventoryModel.count > 0) {
Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatar", true); Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatarFromInventory", true);
MyAvatar.useFullAvatarURL = topBarInventoryModel.get(0).download_url; MyAvatar.useFullAvatarURL(topBarInventoryModel.get(0).download_url);
} }
} }
} }
@ -71,7 +71,7 @@ Rectangle {
if (isLoggedIn) { if (isLoggedIn) {
Commerce.getWalletStatus(); Commerce.getWalletStatus();
} else { } else {
// Show some error to the user // Show some error to the user in the UI?
} }
} }
@ -113,12 +113,68 @@ Rectangle {
topBarInventoryModel.getNextPage(); topBarInventoryModel.getNextPage();
} else { } else {
inventoryFullyReceived = true; 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... // Use `Settings.setValue("simplifiedUI/debugFTUE", 0);` to turn off FTUE Debug Mode.
if ((!Settings.getValue("simplifiedUI/alreadyAutoSelectedAvatar", false) || // Use `Settings.setValue("simplifiedUI/debugFTUE", 1);` to debug FTUE Screen 1.
MyAvatar.skeletonModelURL.indexOf("defaultAvatar") > -1 || MyAvatar.skeletonModelURL.indexOf("fst") === -1) && topBarInventoryModel.count > 0) { // Use `Settings.setValue("simplifiedUI/debugFTUE", 2);` to debug FTUE Screen 2.
Settings.setValue("simplifiedUI/alreadyAutoSelectedAvatar", true); // Use `Settings.setValue("simplifiedUI/debugFTUE", 3);` to debug FTUE Screen 3.
MyAvatar.skeletonModelURL = topBarInventoryModel.get(0).download_url; // 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 { SimplifiedControls.TextField {
id: goToTextField id: goToTextField
readonly property string shortPlaceholderText: "Jump to..." 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 anchors.centerIn: parent
width: Math.min(parent.width, 445) width: Math.min(parent.width, 445)
height: 35 height: 35
@ -384,6 +440,7 @@ Rectangle {
placeholderTextColor: "#8E8E8E" placeholderTextColor: "#8E8E8E"
font.pixelSize: 14 font.pixelSize: 14
placeholderText: width - leftPadding - rightPadding < goToTextFieldMetrics.width ? shortPlaceholderText : longPlaceholderText placeholderText: width - leftPadding - rightPadding < goToTextFieldMetrics.width ? shortPlaceholderText : longPlaceholderText
blankPlaceholderTextOnFocus: false
clip: true clip: true
selectByMouse: true selectByMouse: true
autoScroll: true autoScroll: true
@ -569,6 +626,8 @@ Rectangle {
return; return;
} }
} }
avatarButtonImage.source = "../images/defaultAvatar.svg";
} }

View file

@ -718,6 +718,7 @@ private:
static const QString STATE_IN_HMD = "InHMD"; static const QString STATE_IN_HMD = "InHMD";
static const QString STATE_CAMERA_FULL_SCREEN_MIRROR = "CameraFSM"; static const QString STATE_CAMERA_FULL_SCREEN_MIRROR = "CameraFSM";
static const QString STATE_CAMERA_FIRST_PERSON = "CameraFirstPerson"; 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_THIRD_PERSON = "CameraThirdPerson";
static const QString STATE_CAMERA_ENTITY = "CameraEntity"; static const QString STATE_CAMERA_ENTITY = "CameraEntity";
static const QString STATE_CAMERA_INDEPENDENT = "CameraIndependent"; static const QString STATE_CAMERA_INDEPENDENT = "CameraIndependent";
@ -939,7 +940,8 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
DependencyManager::set<AudioInjectorManager>(); DependencyManager::set<AudioInjectorManager>();
DependencyManager::set<MessagesClient>(); DependencyManager::set<MessagesClient>();
controller::StateController::setStateVariables({ { STATE_IN_HMD, STATE_CAMERA_FULL_SCREEN_MIRROR, 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_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 } }); STATE_PLATFORM_WINDOWS, STATE_PLATFORM_MAC, STATE_PLATFORM_ANDROID, STATE_LEFT_HAND_DOMINANT, STATE_RIGHT_HAND_DOMINANT, STATE_STRAFE_ENABLED } });
DependencyManager::set<UserInputMapper>(); DependencyManager::set<UserInputMapper>();
@ -974,6 +976,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
QObject::connect(PlatformHelper::instance(), &PlatformHelper::systemWillWake, [] { QObject::connect(PlatformHelper::instance(), &PlatformHelper::systemWillWake, [] {
QMetaObject::invokeMethod(DependencyManager::get<NodeList>().data(), "noteAwakening", Qt::QueuedConnection); 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 { _applicationStateDevice->setInputVariant(STATE_CAMERA_FIRST_PERSON, []() -> float {
return qApp->getCamera().getMode() == CAMERA_MODE_FIRST_PERSON ? 1 : 0; 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 { _applicationStateDevice->setInputVariant(STATE_CAMERA_THIRD_PERSON, []() -> float {
return qApp->getCamera().getMode() == CAMERA_MODE_THIRD_PERSON ? 1 : 0; 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(); settingsTimer->start();
}, QThread::LowestPriority); }, 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. getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN); // So that camera doesn't auto-switch to third person.
} }
@ -2958,13 +2964,29 @@ Application::~Application() {
qInstallMessageHandler(LogHandler::verboseMessageHandler); qInstallMessageHandler(LogHandler::verboseMessageHandler);
#ifdef Q_OS_MAC #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. // Clear the event queue before application is totally destructed.
// This will drain the messasge queue of pending "deleteLaters" queued up // This will drain the messasge queue of pending "deleteLaters" queued up
// during shutdown of the script engines. // during shutdown of the script engines.
// We do this here because there is a possiblty that [NSApplication terminate:] // We do this here because there is a possiblty that [NSApplication terminate:]
// will be called during processEvents which will invoke all static destructors. // will be called during processEvents which will invoke all static destructors.
// We want to postpone this utill the last possible moment. // We want to postpone this utill the last possible moment.
QCoreApplication::processEvents(); //QCoreApplication::processEvents();
#endif #endif
} }
@ -3610,14 +3632,17 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) {
// Using the latter will cause the camera to wobble with idle animations, // Using the latter will cause the camera to wobble with idle animations,
// or with changes from the face tracker // or with changes from the face tracker
CameraMode mode = _myCamera.getMode(); 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; _thirdPersonHMDCameraBoomValid= false;
if (isHMDMode()) { if (isHMDMode()) {
mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
_myCamera.setPosition(extractTranslation(camMat)); _myCamera.setPosition(extractTranslation(camMat));
_myCamera.setOrientation(glmExtractRotation(camMat)); _myCamera.setOrientation(glmExtractRotation(camMat));
} else if (mode == CAMERA_MODE_FIRST_PERSON) {
_myCamera.setPosition(myAvatar->getDefaultEyePosition());
_myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation());
} else { } else {
_myCamera.setPosition(myAvatar->getLookAtPivotPoint()); _myCamera.setPosition(myAvatar->getCameraEyesPosition(deltaTime));
_myCamera.setOrientation(myAvatar->getLookAtRotation()); _myCamera.setOrientation(myAvatar->getLookAtRotation());
} }
} else if (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE) { } 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: { case Qt::Key_1: {
Menu* menu = Menu::getInstance(); Menu* menu = Menu::getInstance();
menu->triggerOption(MenuOption::FirstPerson); menu->triggerOption(MenuOption::FirstPersonLookAt);
break; break;
} }
case Qt::Key_2: { case Qt::Key_2: {
@ -5491,7 +5516,7 @@ void Application::loadSettings() {
isFirstPerson = menu->isOptionChecked(MenuOption::FirstPersonHMD); isFirstPerson = menu->isOptionChecked(MenuOption::FirstPersonHMD);
} else { } else {
// if HMD is not active, only use first person if the menu option is checked // 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 // 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 // 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); 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(); cameraMenuChanged();
auto inputs = pluginManager->getInputPlugins(); auto inputs = pluginManager->getInputPlugins();
@ -5672,7 +5697,7 @@ void Application::pauseUntilLoginDetermined() {
menu->getMenu("Developer")->setVisible(false); menu->getMenu("Developer")->setVisible(false);
} }
_previousCameraMode = _myCamera.getMode(); _previousCameraMode = _myCamera.getMode();
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON); _myCamera.setMode(CAMERA_MODE_FIRST_PERSON_LOOK_AT);
cameraModeChanged(); cameraModeChanged();
// disconnect domain handler. // disconnect domain handler.
@ -5861,11 +5886,11 @@ void Application::cycleCamera() {
if (menu->isOptionChecked(MenuOption::FullscreenMirror)) { if (menu->isOptionChecked(MenuOption::FullscreenMirror)) {
menu->setIsOptionChecked(MenuOption::FullscreenMirror, false); 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); menu->setIsOptionChecked(MenuOption::LookAtCamera, true);
} else if (menu->isOptionChecked(MenuOption::LookAtCamera)) { } else if (menu->isOptionChecked(MenuOption::LookAtCamera)) {
@ -5884,8 +5909,8 @@ void Application::cycleCamera() {
void Application::cameraModeChanged() { void Application::cameraModeChanged() {
switch (_myCamera.getMode()) { switch (_myCamera.getMode()) {
case CAMERA_MODE_FIRST_PERSON: case CAMERA_MODE_FIRST_PERSON_LOOK_AT:
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, true); Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPersonLookAt, true);
break; break;
case CAMERA_MODE_LOOK_AT: case CAMERA_MODE_LOOK_AT:
Menu::getInstance()->setIsOptionChecked(MenuOption::LookAtCamera, true); Menu::getInstance()->setIsOptionChecked(MenuOption::LookAtCamera, true);
@ -5905,12 +5930,12 @@ void Application::changeViewAsNeeded(float boomLength) {
// This is called when the boom length has changed // This is called when the boom length has changed
bool boomLengthGreaterThanMinimum = (boomLength > MyAvatar::ZOOM_MIN); bool boomLengthGreaterThanMinimum = (boomLength > MyAvatar::ZOOM_MIN);
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON && boomLengthGreaterThanMinimum) { if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON_LOOK_AT && boomLengthGreaterThanMinimum) {
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, false); Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPersonLookAt, false);
Menu::getInstance()->setIsOptionChecked(MenuOption::LookAtCamera, true); Menu::getInstance()->setIsOptionChecked(MenuOption::LookAtCamera, true);
cameraMenuChanged(); cameraMenuChanged();
} else if (_myCamera.getMode() == CAMERA_MODE_LOOK_AT && !boomLengthGreaterThanMinimum) { } 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); Menu::getInstance()->setIsOptionChecked(MenuOption::LookAtCamera, false);
cameraMenuChanged(); cameraMenuChanged();
} }
@ -5918,9 +5943,9 @@ void Application::changeViewAsNeeded(float boomLength) {
void Application::cameraMenuChanged() { void Application::cameraMenuChanged() {
auto menu = Menu::getInstance(); auto menu = Menu::getInstance();
if (menu->isOptionChecked(MenuOption::FirstPerson)) { if (menu->isOptionChecked(MenuOption::FirstPersonLookAt)) {
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON) { if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON_LOOK_AT) {
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON); _myCamera.setMode(CAMERA_MODE_FIRST_PERSON_LOOK_AT);
getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN); getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN);
} }
} else if (menu->isOptionChecked(MenuOption::LookAtCamera)) { } else if (menu->isOptionChecked(MenuOption::LookAtCamera)) {
@ -9021,7 +9046,7 @@ void Application::setDisplayPlugin(DisplayPluginPointer newDisplayPlugin) {
} }
if (isHmd && menu->isOptionChecked(MenuOption::FirstPersonHMD)) { if (isHmd && menu->isOptionChecked(MenuOption::FirstPersonHMD)) {
menu->setIsOptionChecked(MenuOption::FirstPerson, true); menu->setIsOptionChecked(MenuOption::FirstPersonLookAt, true);
cameraMenuChanged(); cameraMenuChanged();
} }

View file

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

View file

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

View file

@ -152,7 +152,7 @@ static int triggerReactionNameToIndex(const QString& reactionName) {
} }
static int beginEndReactionNameToIndex(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); return BEGIN_END_REACTION_NAMES.indexOf(reactionName);
} }
@ -958,7 +958,8 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
head->setScale(getModelScale()); head->setScale(getModelScale());
head->simulate(deltaTime); head->simulate(deltaTime);
CameraMode mode = qApp->getCamera().getMode(); 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) { if (!_pointAtActive || !_isPointTargetValid) {
updateHeadLookAt(deltaTime); updateHeadLookAt(deltaTime);
} else { } else {
@ -2178,7 +2179,7 @@ void MyAvatar::computeMyLookAtTarget(const AvatarHash& hash) {
glm::vec3 myForward = _lookAtYaw * IDENTITY_FORWARD; glm::vec3 myForward = _lookAtYaw * IDENTITY_FORWARD;
glm::vec3 myPosition = getHead()->getEyePosition(); glm::vec3 myPosition = getHead()->getEyePosition();
CameraMode mode = qApp->getCamera().getMode(); 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(); myPosition = qApp->getCamera().getPosition();
} }
@ -2719,7 +2720,7 @@ void MyAvatar::updateMotors() {
if (_characterController.getState() == CharacterController::State::Hover || if (_characterController.getState() == CharacterController::State::Hover ||
_characterController.computeCollisionMask() == BULLET_COLLISION_MASK_COLLISIONLESS) { _characterController.computeCollisionMask() == BULLET_COLLISION_MASK_COLLISIONLESS) {
CameraMode mode = qApp->getCamera().getMode(); 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(); motorRotation = getLookAtRotation();
} else { } else {
motorRotation = getMyHead()->getHeadOrientation(); motorRotation = getMyHead()->getHeadOrientation();
@ -3399,7 +3400,8 @@ bool MyAvatar::cameraInsideHead(const glm::vec3& cameraPosition) const {
bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const {
bool defaultMode = renderArgs->_renderMode == RenderArgs::DEFAULT_RENDER_MODE; 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 overrideAnim = _skeletonModel ? _skeletonModel->getRig().isPlayingOverrideAnimation() : false;
bool insideHead = cameraInsideHead(renderArgs->getViewFrustum().getPosition()); bool insideHead = cameraInsideHead(renderArgs->getViewFrustum().getPosition());
return !defaultMode || (!firstPerson && !insideHead) || (overrideAnim && !insideHead); return !defaultMode || (!firstPerson && !insideHead) || (overrideAnim && !insideHead);
@ -3444,8 +3446,8 @@ void MyAvatar::updateOrientation(float deltaTime) {
float targetSpeed = getDriveKey(YAW) * _yawSpeed; float targetSpeed = getDriveKey(YAW) * _yawSpeed;
CameraMode mode = qApp->getCamera().getMode(); CameraMode mode = qApp->getCamera().getMode();
bool computeLookAt = isReadyForPhysics() && !qApp->isHMDMode() && bool computeLookAt = isReadyForPhysics() && !qApp->isHMDMode() &&
(mode == CAMERA_MODE_FIRST_PERSON || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE); (mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT || mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE);
bool smoothCameraYaw = computeLookAt && mode != CAMERA_MODE_FIRST_PERSON; bool smoothCameraYaw = computeLookAt && mode != CAMERA_MODE_FIRST_PERSON_LOOK_AT;
if (smoothCameraYaw) { if (smoothCameraYaw) {
// For "Look At" and "Selfie" camera modes we also smooth the yaw rotation from right-click mouse movement. // 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; float speedFromDeltaYaw = deltaTime > FLT_EPSILON ? getDriveKey(DELTA_YAW) / deltaTime : 0.0f;
@ -3569,11 +3571,11 @@ void MyAvatar::updateOrientation(float deltaTime) {
if (isMovingFwdBwd) { if (isMovingFwdBwd) {
if (isMovingSideways) { if (isMovingSideways) {
// Reorient avatar to face camera diagonal // 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; float turnSign = getDriveKey(TRANSLATE_Z) < 0.0f ? -1.0f : 1.0f;
turnSign = getDriveKey(TRANSLATE_X) > 0.0f ? -turnSign : turnSign; turnSign = getDriveKey(TRANSLATE_X) > 0.0f ? -turnSign : turnSign;
faceRotation = _lookAtYaw * glm::angleAxis(turnSign * 0.25f * PI, Vectors::UP); 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; blend = 1.0f;
} }
} }
@ -3644,11 +3646,11 @@ void MyAvatar::updateOrientation(float deltaTime) {
glm::vec3 ajustedYawVector = cameraYawVector; glm::vec3 ajustedYawVector = cameraYawVector;
float limitAngle = 0.0f; float limitAngle = 0.0f;
float triggerAngle = -glm::sin(glm::radians(TRIGGER_REORIENT_ANGLE)); 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)); limitAngle = glm::sin(glm::radians(90.0f - FIRST_PERSON_TRIGGER_REORIENT_ANGLE));
triggerAngle = limitAngle; 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 < limitAngle) {
if (frontBackDot < 0.0f) { if (frontBackDot < 0.0f) {
ajustedYawVector = (leftRightDot < 0.0f ? -avatarVectorRight : avatarVectorRight); ajustedYawVector = (leftRightDot < 0.0f ? -avatarVectorRight : avatarVectorRight);
@ -3684,7 +3686,7 @@ void MyAvatar::updateOrientation(float deltaTime) {
} }
_headLookAtActive = true; _headLookAtActive = true;
const float FIRST_PERSON_RECENTER_SECONDS = 15.0f; 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 (getDriveKey(YAW) + getDriveKey(STEP_YAW) + getDriveKey(DELTA_YAW) == 0.0f) {
if (_firstPersonSteadyHeadTimer < FIRST_PERSON_RECENTER_SECONDS) { if (_firstPersonSteadyHeadTimer < FIRST_PERSON_RECENTER_SECONDS) {
if (_firstPersonSteadyHeadTimer > 0.0f) { if (_firstPersonSteadyHeadTimer > 0.0f) {
@ -3772,7 +3774,7 @@ glm::vec3 MyAvatar::scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 rig
// Desktop mode. // Desktop mode.
direction = (zSpeed * forward) + (xSpeed * right); direction = (zSpeed * forward) + (xSpeed * right);
CameraMode mode = qApp->getCamera().getMode(); 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()){ zSpeed != 0.0f && xSpeed != 0.0f && !isFlying()){
direction = (zSpeed * forward); direction = (zSpeed * forward);
} }
@ -5437,7 +5439,7 @@ glm::quat MyAvatar::getOrientationForAudio() {
case AudioListenerMode::FROM_HEAD: { case AudioListenerMode::FROM_HEAD: {
// Using the camera's orientation instead, when the current mode is controlling the avatar's head. // Using the camera's orientation instead, when the current mode is controlling the avatar's head.
CameraMode mode = qApp->getCamera().getMode(); 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(); result = headFollowsCamera ? qApp->getCamera().getOrientation() : getHead()->getFinalOrientationInWorldFrame();
break; break;
} }
@ -6812,6 +6814,66 @@ glm::vec3 MyAvatar::getLookAtPivotPoint() {
return yAxisEyePosition; 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) { bool MyAvatar::setPointAt(const glm::vec3& pointAtTarget) {
if (QThread::currentThread() != thread()) { if (QThread::currentThread() != thread()) {
bool result = false; bool result = false;

View file

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

View file

@ -52,6 +52,23 @@ static const QVariantMap DOCK_AREA {
{ "RIGHT", DockArea::RIGHT } { "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) DesktopScriptingInterface::DesktopScriptingInterface(QObject* parent, bool restricted)
: QObject(parent), _restricted(restricted) { } : QObject(parent), _restricted(restricted) { }
@ -99,6 +116,10 @@ QVariantMap DesktopScriptingInterface::getDockArea() {
return DOCK_AREA; return DOCK_AREA;
} }
QVariantMap DesktopScriptingInterface::getRelativePositionAnchor() {
return RELATIVE_POSITION_ANCHOR;
}
void DesktopScriptingInterface::setHUDAlpha(float alpha) { void DesktopScriptingInterface::setHUDAlpha(float alpha) {
qApp->getApplicationCompositor().setAlpha(alpha); qApp->getApplicationCompositor().setAlpha(alpha);
} }

View file

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

View file

@ -82,11 +82,18 @@ void RenderScriptingInterface::forceShadowsEnabled(bool enabled) {
_shadowsEnabled = (enabled); _shadowsEnabled = (enabled);
_shadowsEnabledSetting.set(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) { if (lightingModelConfig) {
Menu::getInstance()->setIsOptionChecked(MenuOption::Shadows, enabled); Menu::getInstance()->setIsOptionChecked(MenuOption::Shadows, enabled);
lightingModelConfig->setShadow(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); 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() { void DialogsManager::showDomainConnectionDialog() {
// if the dialog already exists we delete it so the connection data is refreshed // if the dialog already exists we delete it so the connection data is refreshed
if (_domainConnectionDialog) { if (_domainConnectionDialog) {

View file

@ -53,7 +53,6 @@ public slots:
void lodTools(); void lodTools();
void hmdTools(bool showTools); void hmdTools(bool showTools);
void showDomainConnectionDialog(); void showDomainConnectionDialog();
void showTestingResults();
void toggleAddressBar(); void toggleAddressBar();
// Application Update // 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 OVERRIDE_FLAGS_PROPERTY = "overrideFlags";
static const char* const SOURCE_PROPERTY = "source"; static const char* const SOURCE_PROPERTY = "source";
static const char* const TITLE_PROPERTY = "title"; 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 POSITION_PROPERTY = "position";
static const char* const INTERACTIVE_WINDOW_POSITION_PROPERTY = "interactiveWindowPosition"; static const char* const INTERACTIVE_WINDOW_POSITION_PROPERTY = "interactiveWindowPosition";
static const char* const SIZE_PROPERTY = "size"; static const char* const SIZE_PROPERTY = "size";
@ -112,6 +115,15 @@ void InteractiveWindow::forwardKeyReleaseEvent(int key, int modifiers) {
QCoreApplication::postEvent(QCoreApplication::instance(), event); 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() { void InteractiveWindow::emitMainWindowResizeEvent() {
emit qApp->getWindow()->windowGeometryChanged(qApp->getWindow()->geometry()); emit qApp->getWindow()->windowGeometryChanged(qApp->getWindow()->geometry());
} }
@ -184,22 +196,32 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
*/ */
if (nativeWindowInfo.contains(DOCK_AREA_PROPERTY)) { if (nativeWindowInfo.contains(DOCK_AREA_PROPERTY)) {
DockArea dockedArea = (DockArea) nativeWindowInfo[DOCK_AREA_PROPERTY].toInt(); DockArea dockedArea = (DockArea) nativeWindowInfo[DOCK_AREA_PROPERTY].toInt();
int tempWidth = 0;
int tempHeight = 0;
switch (dockedArea) { switch (dockedArea) {
case DockArea::TOP: case DockArea::TOP:
dockArea = Qt::TopDockWidgetArea; dockArea = Qt::TopDockWidgetArea;
_dockWidget->setFixedHeight(windowSize.height()); tempHeight = windowSize.height();
_dockWidget->setFixedHeight(tempHeight);
qApp->getWindow()->setDockedWidgetRelativePositionOffset(QSize(0, -tempHeight));
break; break;
case DockArea::BOTTOM: case DockArea::BOTTOM:
dockArea = Qt::BottomDockWidgetArea; dockArea = Qt::BottomDockWidgetArea;
_dockWidget->setFixedHeight(windowSize.height()); tempHeight = windowSize.height();
_dockWidget->setFixedHeight(tempHeight);
qApp->getWindow()->setDockedWidgetRelativePositionOffset(QSize(0, tempHeight));
break; break;
case DockArea::LEFT: case DockArea::LEFT:
dockArea = Qt::LeftDockWidgetArea; dockArea = Qt::LeftDockWidgetArea;
_dockWidget->setFixedWidth(windowSize.width()); tempWidth = windowSize.width();
_dockWidget->setFixedWidth(tempWidth);
qApp->getWindow()->setDockedWidgetRelativePositionOffset(QSize(-tempWidth, 0));
break; break;
case DockArea::RIGHT: case DockArea::RIGHT:
dockArea = Qt::RightDockWidgetArea; dockArea = Qt::RightDockWidgetArea;
_dockWidget->setFixedWidth(windowSize.width()); tempWidth = windowSize.width();
_dockWidget->setFixedWidth(tempWidth);
qApp->getWindow()->setDockedWidgetRelativePositionOffset(QSize(tempWidth, 0));
break; break;
default: default:
@ -255,6 +277,9 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
if (properties.contains(TITLE_PROPERTY)) { if (properties.contains(TITLE_PROPERTY)) {
object->setProperty(TITLE_PROPERTY, properties[TITLE_PROPERTY].toString()); 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)) { if (properties.contains(SIZE_PROPERTY)) {
const auto size = vec2FromVariant(properties[SIZE_PROPERTY]); const auto size = vec2FromVariant(properties[SIZE_PROPERTY]);
object->setProperty(INTERACTIVE_WINDOW_SIZE_PROPERTY, QSize(size.x, size.y)); 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]); const auto position = vec2FromVariant(properties[POSITION_PROPERTY]);
object->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(position.x, position.y)); object->setProperty(INTERACTIVE_WINDOW_POSITION_PROPERTY, QPointF(position.x, position.y));
} }
if (properties.contains(VISIBLE_PROPERTY)) { if (properties.contains(RELATIVE_POSITION_ANCHOR_PROPERTY)) {
object->setProperty(VISIBLE_PROPERTY, properties[INTERACTIVE_WINDOW_VISIBLE_PROPERTY].toBool()); _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 // The qmlToScript method handles the thread-safety of this call. Because the QVariant argument
@ -289,6 +327,10 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
connect(object, SIGNAL(presentationModeChanged()), this, SLOT(parentNativeWindowToMainWindow()), Qt::QueuedConnection); connect(object, SIGNAL(presentationModeChanged()), this, SLOT(parentNativeWindowToMainWindow()), Qt::QueuedConnection);
#endif #endif
if (_isFullScreenWindow || _relativePositionAnchor != RelativePositionAnchor::NO_ANCHOR) {
connect(qApp->getWindow(), &MainWindow::windowGeometryChanged, this, &InteractiveWindow::onMainWindowGeometryChanged, Qt::QueuedConnection);
}
QUrl sourceURL{ sourceUrl }; QUrl sourceURL{ sourceUrl };
// If the passed URL doesn't correspond to a known scheme, assume it's a local file path // If the passed URL doesn't correspond to a known scheme, assume it's a local file path
if (!KNOWN_SCHEMES.contains(sourceURL.scheme(), Qt::CaseInsensitive)) { if (!KNOWN_SCHEMES.contains(sourceURL.scheme(), Qt::CaseInsensitive)) {
@ -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 { glm::vec2 InteractiveWindow::getSize() const {
if (!_qmlWindowProxy) { if (!_qmlWindowProxy) {
return {}; return {};

View file

@ -89,6 +89,15 @@ namespace InteractiveWindowEnums {
RIGHT RIGHT
}; };
Q_ENUM_NS(DockArea); Q_ENUM_NS(DockArea);
enum RelativePositionAnchor {
NO_ANCHOR,
TOP_LEFT,
TOP_RIGHT,
BOTTOM_RIGHT,
BOTTOM_LEFT
};
Q_ENUM_NS(RelativePositionAnchor);
} }
using namespace InteractiveWindowEnums; using namespace InteractiveWindowEnums;
@ -121,6 +130,8 @@ class InteractiveWindow : public QObject {
Q_PROPERTY(QString title READ getTitle WRITE setTitle) Q_PROPERTY(QString title READ getTitle WRITE setTitle)
Q_PROPERTY(glm::vec2 position READ getPosition WRITE setPosition) 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(glm::vec2 size READ getSize WRITE setSize)
Q_PROPERTY(bool visible READ isVisible WRITE setVisible) Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
Q_PROPERTY(int presentationMode READ getPresentationMode WRITE setPresentationMode) Q_PROPERTY(int presentationMode READ getPresentationMode WRITE setPresentationMode)
@ -137,6 +148,21 @@ private:
Q_INVOKABLE glm::vec2 getPosition() const; Q_INVOKABLE glm::vec2 getPosition() const;
Q_INVOKABLE void setPosition(const glm::vec2& position); 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 glm::vec2 getSize() const;
Q_INVOKABLE void setSize(const glm::vec2& size); Q_INVOKABLE void setSize(const glm::vec2& size);
@ -320,6 +346,7 @@ protected slots:
void forwardKeyPressEvent(int key, int modifiers); void forwardKeyPressEvent(int key, int modifiers);
void forwardKeyReleaseEvent(int key, int modifiers); void forwardKeyReleaseEvent(int key, int modifiers);
void emitMainWindowResizeEvent(); void emitMainWindowResizeEvent();
void onMainWindowGeometryChanged(QRect geometry);
private: private:
std::shared_ptr<QmlWindowProxy> _qmlWindowProxy; std::shared_ptr<QmlWindowProxy> _qmlWindowProxy;

View file

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

View file

@ -545,7 +545,8 @@ QStringList Rig::getAnimationRoles() const {
auto clipNode = std::dynamic_pointer_cast<AnimClip>(node); auto clipNode = std::dynamic_pointer_cast<AnimClip>(node);
if (clipNode) { if (clipNode) {
// filter out the userAnims, they are for internal use only. // 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()); list.append(node->getID());
} }
} }
@ -1432,6 +1433,69 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
} }
_lastEnableInverseKinematics = _enableInverseKinematics; _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; _lastForward = forward;
_lastPosition = worldPosition; _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; _headEnabled = params.primaryControllerFlags[PrimaryControllerType_Head] & (uint8_t)ControllerFlags::Enabled;
bool leftHandEnabled = params.primaryControllerFlags[PrimaryControllerType_LeftHand] & (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 AnimPose secondaryControllerPoses[NumSecondaryControllerTypes]; // rig space
uint8_t secondaryControllerFlags[NumSecondaryControllerTypes]; uint8_t secondaryControllerFlags[NumSecondaryControllerTypes];
bool isTalking; bool isTalking;
float inputX; float inputX = 0.0f;
float inputZ; float inputZ = 0.0f;
bool reactionEnabledFlags[NUM_AVATAR_BEGIN_END_REACTIONS]; bool reactionEnabledFlags[NUM_AVATAR_BEGIN_END_REACTIONS];
bool reactionTriggers[NUM_AVATAR_TRIGGER_REACTIONS]; bool reactionTriggers[NUM_AVATAR_TRIGGER_REACTIONS];
HFMJointShapeInfo hipsShapeInfo; 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) { bool AudioClient::switchOutputToAudioDevice(const HifiAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest) {
Q_ASSERT_X(QThread::currentThread() == thread(), Q_FUNC_INFO, "Function invoked on wrong thread"); 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 setOutputGain(float gain) { _outputGain = gain; };
void outputNotify(); void outputNotify();
void noteAwakening();
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();

View file

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

View file

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

View file

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

View file

@ -64,6 +64,11 @@ void RecordingScriptingInterface::playClip(NetworkClipLoaderPointer clipLoader,
} }
void RecordingScriptingInterface::loadRecording(const QString& url, QScriptValue callback) { 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); auto clipLoader = DependencyManager::get<recording::ClipCache>()->getClipLoader(url);
if (clipLoader->isLoaded()) { if (clipLoader->isLoaded()) {
@ -117,6 +122,11 @@ void RecordingScriptingInterface::startPlaying() {
} }
void RecordingScriptingInterface::setPlayerVolume(float volume) { 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)); _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) { void RecordingScriptingInterface::setPlayerLoop(bool loop) {
if (QThread::currentThread() != thread()) {
BLOCKING_INVOKE_METHOD(this, "setPlayerLoop", Q_ARG(bool, loop));
return;
}
_player->loop(loop); _player->loop(loop);
} }
@ -195,6 +210,16 @@ void RecordingScriptingInterface::startRecording() {
} }
void RecordingScriptingInterface::stopRecording() { 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(); _recorder->stop();
_lastClip = _recorder->getClip(); _lastClip = _recorder->getClip();
_lastClip->seek(0); _lastClip->seek(0);

View file

@ -25,8 +25,14 @@
* <tr> * <tr>
* <td><strong>First&nbsp;Person</strong></td> * <td><strong>First&nbsp;Person</strong></td>
* <td><code>"first&nbsp;person"</code></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 * <td>Legacy first person camera mode. The camera is positioned such that you have the same view as your avatar.
* avatar.</td> * 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>
* <tr> * <tr>
* <td><strong>Third&nbsp;Person</strong></td> * <td><strong>Third&nbsp;Person</strong></td>
@ -73,6 +79,8 @@ CameraMode stringToMode(const QString& mode) {
return CAMERA_MODE_THIRD_PERSON; return CAMERA_MODE_THIRD_PERSON;
} else if (mode == "first person") { } else if (mode == "first person") {
return CAMERA_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") { } else if (mode == "mirror") {
return CAMERA_MODE_MIRROR; return CAMERA_MODE_MIRROR;
} else if (mode == "independent") { } else if (mode == "independent") {
@ -92,6 +100,8 @@ QString modeToString(CameraMode mode) {
return "third person"; return "third person";
} else if (mode == CAMERA_MODE_FIRST_PERSON) { } else if (mode == CAMERA_MODE_FIRST_PERSON) {
return "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) { } else if (mode == CAMERA_MODE_MIRROR) {
return "mirror"; return "mirror";
} else if (mode == CAMERA_MODE_INDEPENDENT) { } else if (mode == CAMERA_MODE_INDEPENDENT) {

View file

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

View file

@ -24,6 +24,10 @@ public:
~MainWindow(); ~MainWindow();
static QWindow* findMainWindow(); 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: public slots:
void restoreGeometry(); void restoreGeometry();
void saveGeometry(); void saveGeometry();
@ -46,6 +50,7 @@ protected:
private: private:
Setting::Handle<QRect> _windowGeometry; Setting::Handle<QRect> _windowGeometry;
Setting::Handle<int> _windowState; Setting::Handle<int> _windowState;
QSize _dockedWidgetRelativePositionOffset{ 0, 0 };
}; };
#endif /* defined(__hifi__MainWindow__) */ #endif /* defined(__hifi__MainWindow__) */

View file

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

View file

@ -1,117 +1,38 @@
var isActive = false; (function () {
var toolBar = (function() { // Get the system toolbar.
var that = {}, var toolbar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system");
toolBar, if (!toolbar) {
activeButton, print("ERROR: Couldn't get system toolbar.");
newModelButton, return;
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();
} }
that.setActive = function(active) { Script.setTimeout(function () {
if (active != isActive) { // Report the system toolbar visibility.
isActive = active; var isToolbarVisible = toolbar.readProperty("visible");
that.showTools(isActive); print("Toolbar visible: " + isToolbarVisible);
}
};
// Sets visibility of tool buttons, excluding the power button // Briefly toggle the system toolbar visibility.
that.showTools = function(doShow) { print("Toggle toolbar");
newModelButton.writeProperty('visible', doShow); toolbar.writeProperty("visible", !isToolbarVisible);
newShapeButton.writeProperty('visible', doShow); Script.setTimeout(function () {
newLightButton.writeProperty('visible', doShow); print("Toggle toolbar");
newTextButton.writeProperty('visible', doShow); toolbar.writeProperty("visible", isToolbarVisible);
newWebButton.writeProperty('visible', doShow); }, 2000);
newZoneButton.writeProperty('visible', doShow); }, 2000);
newParticleButton.writeProperty('visible', doShow);
newMaterialButton.writeProperty('visible', doShow); 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 stylesUit 1.0
import controlsUit 1.0 as HifiControls import controlsUit 1.0 as HifiControls
import "../lib/prop" as Prop
Rectangle { Rectangle {
HifiConstants { id: hifi;} HifiConstants { id: hifi;}
color: Qt.rgba(hifi.colors.baseGray.r, hifi.colors.baseGray.g, hifi.colors.baseGray.b, 0.8); color: Qt.rgba(hifi.colors.baseGray.r, hifi.colors.baseGray.g, hifi.colors.baseGray.b, 0.8);
id: root; id: root;
property var theMaterial: {}
property var theMaterialAttributes: {}
property var hasMaterial: false
property var isReadOnly: true
function fromScript(message) { function fromScript(message) {
switch (message.method) { switch (message.method) {
case "setObjectInfo": case "setObjectInfo":
@ -26,10 +33,19 @@ Rectangle {
break; break;
case "setMaterialJSON": case "setMaterialJSON":
materialJSONText.text = message.params.materialJSONText; materialJSONText.text = message.params.materialJSONText;
theMaterial = JSON.parse(message.params.materialJSONText)
theMaterialAttributes = theMaterial.materials
hasMaterial = (theMaterial !== undefined)
break; break;
} }
} }
Column {
anchors.left: parent.left
anchors.right: parent.right
Rectangle { Rectangle {
id: entityIDContainer id: entityIDContainer
height: 52 height: 52
@ -45,8 +61,171 @@ Rectangle {
} }
} }
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 { Original.ScrollView {
anchors.top: entityIDContainer.bottom // anchors.top: entityIDContainer.bottom
height: root.height - entityIDContainer.height height: root.height - entityIDContainer.height
width: root.width width: root.width
clip: true clip: true
@ -63,3 +242,4 @@ Rectangle {
} }
} }
} }
}

View file

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

View file

@ -1,15 +1,40 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.6, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!-- Generator: Adobe Illustrator 23.1.0, 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" <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
viewBox="0 0 93.7 127.8" style="enable-background:new 0 0 93.7 127.8;" xml:space="preserve"> <!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
<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 <!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
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 <!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
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 <!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
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 <!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
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 <!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
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 <!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
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 <!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
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 <svg version="1.1" id="Layer_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
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"/> 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> </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 // START CONFIG OPTIONS
var DOCKED_QML_SUPPORTED = true;
var TOOLBAR_NAME = "com.highfidelity.interface.toolbar.system"; var TOOLBAR_NAME = "com.highfidelity.interface.toolbar.system";
var DEFAULT_SCRIPTS_PATH_PREFIX = ScriptDiscoveryService.defaultScriptsPath + "/"; var DEFAULT_SCRIPTS_PATH_PREFIX = ScriptDiscoveryService.defaultScriptsPath + "/";
// END CONFIG OPTIONS // END CONFIG OPTIONS
@ -160,6 +159,7 @@ var SETTINGS_APP_WINDOW_FLAGS = 0x00000001 | // Qt::Window
0x08000000 | // Qt::WindowCloseButtonHint 0x08000000 | // Qt::WindowCloseButtonHint
0x00008000 | // Qt::WindowMaximizeButtonHint 0x00008000 | // Qt::WindowMaximizeButtonHint
0x00004000; // Qt::WindowMinimizeButtonHint 0x00004000; // Qt::WindowMinimizeButtonHint
var SETTINGS_APP_RIGHT_MARGIN = 48;
var settingsAppWindow = false; var settingsAppWindow = false;
function toggleSettingsApp() { function toggleSettingsApp() {
if (settingsAppWindow) { if (settingsAppWindow) {
@ -179,7 +179,7 @@ function toggleSettingsApp() {
y: SETTINGS_APP_HEIGHT_PX y: SETTINGS_APP_HEIGHT_PX
}, },
position: { 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) y: Math.max(Window.y + POPOUT_SAFE_MARGIN_Y, Window.y + Window.innerHeight / 2 - SETTINGS_APP_HEIGHT_PX / 2)
}, },
overrideFlags: SETTINGS_APP_WINDOW_FLAGS overrideFlags: SETTINGS_APP_WINDOW_FLAGS
@ -283,28 +283,21 @@ function maybeDeleteOutputDeviceMutedOverlay() {
var outputDeviceMutedOverlay = false; var outputDeviceMutedOverlay = false;
var OUTPUT_DEVICE_MUTED_OVERLAY_DEFAULT_DIMS_PX = 300; var OUTPUT_DEVICE_MUTED_OVERLAY_DEFAULT_DIMS_PX = 300;
var OUTPUT_DEVICE_MUTED_MARGIN_BOTTOM_PX = 20; var OUTPUT_DEVICE_MUTED_OVERLAY_DEFAULT_MARGINS_PX = 20;
var OUTPUT_DEVICE_MUTED_MARGIN_LEFT_RIGHT_PX = 20; var OUTPUT_DEVICE_MUTED_DIMS_RATIO_TO_WINDOW_SIZE = 0.8;
function updateOutputDeviceMutedOverlay(isMuted) { function updateOutputDeviceMutedOverlay(isMuted) {
if (isMuted) { if (isMuted) {
var props = { var props = {
imageURL: Script.resolvePath("images/outputDeviceMuted.svg"), imageURL: Script.resolvePath("images/outputDeviceMuted.svg"),
alpha: 0.5 alpha: 0.5
}; };
var overlayDims = OUTPUT_DEVICE_MUTED_OVERLAY_DEFAULT_DIMS_PX; var overlayDims = OUTPUT_DEVICE_MUTED_OVERLAY_DEFAULT_DIMS_PX;
props.x = Window.innerWidth / 2 - overlayDims / 2; var overlayWithMarginsDims = overlayDims + 2 * OUTPUT_DEVICE_MUTED_OVERLAY_DEFAULT_MARGINS_PX;
props.y = Window.innerHeight / 2 - overlayDims / 2;
var outputDeviceMutedOverlayBottomY = props.y + overlayDims; if (overlayWithMarginsDims > Window.innerHeight || overlayWithMarginsDims > Window.innerWidth) {
var inputDeviceMutedOverlayTopY = INPUT_DEVICE_MUTED_MARGIN_TOP_PX; var minWindowDims = Math.min(Window.innerHeight, Window.innerWidth);
if (outputDeviceMutedOverlayBottomY + OUTPUT_DEVICE_MUTED_MARGIN_BOTTOM_PX > inputDeviceMutedOverlayTopY) { overlayDims = Math.round(minWindowDims * OUTPUT_DEVICE_MUTED_DIMS_RATIO_TO_WINDOW_SIZE);
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);
} }
props.width = overlayDims; 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; var WAIT_FOR_TOP_BAR_MS = 1000;
function sendLocalStatusToQml() { function sendLocalStatusToQml() {
@ -403,6 +514,14 @@ function onMessageFromTopBar(message) {
si.toggleStatus(); si.toggleStatus();
break; break;
case "displayInitialLaunchWindow":
displayInitialLaunchWindow();
break;
case "displaySecondLaunchWindow":
displaySecondLaunchWindow();
break;
default: default:
console.log("Unrecognized message from " + TOP_BAR_MESSAGE_SOURCE + ": " + JSON.stringify(message)); console.log("Unrecognized message from " + TOP_BAR_MESSAGE_SOURCE + ": " + JSON.stringify(message));
break; 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_WINDOW_TITLE = "Simplified Top Bar";
var TOP_BAR_PRESENTATION_MODE = Desktop.PresentationMode.NATIVE; var TOP_BAR_PRESENTATION_MODE = Desktop.PresentationMode.NATIVE;
var TOP_BAR_WIDTH_PX = Window.innerWidth; var TOP_BAR_WIDTH_PX = Window.innerWidth;
var TOP_BAR_HEIGHT_PX = 48;
var topBarWindow = false; var topBarWindow = false;
function loadSimplifiedTopBar() { function loadSimplifiedTopBar() {
var windowProps = { var windowProps = {
@ -442,16 +560,9 @@ function loadSimplifiedTopBar() {
y: TOP_BAR_HEIGHT_PX y: TOP_BAR_HEIGHT_PX
} }
}; };
if (DOCKED_QML_SUPPORTED) {
windowProps.presentationWindowInfo = { windowProps.presentationWindowInfo = {
dockArea: Desktop.DockArea.TOP dockArea: Desktop.DockArea.TOP
}; };
} else {
windowProps.position = {
x: Window.x,
y: Window.y
};
}
topBarWindow = Desktop.createWindow(TOP_BAR_QML_PATH, windowProps); topBarWindow = Desktop.createWindow(TOP_BAR_QML_PATH, windowProps);
topBarWindow.fromQml.connect(onMessageFromTopBar); topBarWindow.fromQml.connect(onMessageFromTopBar);
@ -516,32 +627,53 @@ function onHMDInputDeviceMutedChanged(isMuted) {
function onGeometryChanged(rect) { function onGeometryChanged(rect) {
updateInputDeviceMutedOverlay(Audio.muted); updateInputDeviceMutedOverlay(Audio.muted);
updateOutputDeviceMutedOverlay(isOutputMuted()); updateOutputDeviceMutedOverlay(isOutputMuted());
if (topBarWindow && !DOCKED_QML_SUPPORTED) { }
topBarWindow.size = {
"x": rect.width, var initialLaunchWindowIsMinimized = false;
"y": TOP_BAR_HEIGHT_PX var secondLaunchWindowIsMinimized = false;
}; function onWindowMinimizedChanged(isMinimized) {
topBarWindow.position = { if (isMinimized) {
"x": rect.x, handleInitialLaunchWindowVisibleChanged(false);
"y": rect.y handleSecondLaunchWindowVisibleChanged(false);
}; } else if (!HMD.active) {
handleInitialLaunchWindowVisibleChanged(true);
handleSecondLaunchWindowVisibleChanged(true);
} }
} }
function onWindowMinimizedChanged() { function handleInitialLaunchWindowVisibleChanged(shouldBeVisible) {
// prerequisite placeholder for Reduce Friction of Customer Acquisition sub task: https://highfidelity.atlassian.net/browse/DEV-585 if (shouldBeVisible && !initialLaunchWindow && initialLaunchWindowIsMinimized) {
print("WINDOW MINIMIZED CHANGED SIGNAL"); 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) { function onDisplayModeChanged(isHMDMode) {
if (isHMDMode) { if (isHMDMode) {
Camera.setModeString("first person"); Camera.setModeString("first person look at");
} }
if (isHMDMode) { if (isHMDMode) {
onHMDInputDeviceMutedChanged(Audio.mutedHMD); onHMDInputDeviceMutedChanged(Audio.mutedHMD);
handleInitialLaunchWindowVisibleChanged(false);
handleSecondLaunchWindowVisibleChanged(false);
} else { } else {
onDesktopInputDeviceMutedChanged(Audio.mutedDesktop); onDesktopInputDeviceMutedChanged(Audio.mutedDesktop);
handleInitialLaunchWindowVisibleChanged(true);
handleSecondLaunchWindowVisibleChanged(true);
} }
} }
@ -584,9 +716,9 @@ function restoreLODSettings() {
} }
var nametag = Script.require("./simplifiedNametag/simplifiedNametag.js?" + Date.now()); var nametag = Script.require("./simplifiedNametag/simplifiedNametag.js");
var si = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js?" + Date.now()); var si = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js");
var emote = Script.require("../simplifiedEmote/simplifiedEmote.js?" + Date.now()); var simplifiedEmote = Script.require("../simplifiedEmote/simplifiedEmote.js");
var oldShowAudioTools; var oldShowAudioTools;
var oldShowBubbleTools; var oldShowBubbleTools;
var keepExistingUIAndScriptsSetting = Settings.getValue("simplifiedUI/keepExistingUIAndScripts", false); var keepExistingUIAndScriptsSetting = Settings.getValue("simplifiedUI/keepExistingUIAndScripts", false);
@ -653,6 +785,14 @@ function shutdown() {
settingsAppWindow.close(); settingsAppWindow.close();
} }
if (initialLaunchWindow) {
closeInitialLaunchWindow();
}
if (secondLaunchWindow) {
closeSecondLaunchWindow();
}
maybeDeleteInputDeviceMutedOverlay(); maybeDeleteInputDeviceMutedOverlay();
maybeDeleteOutputDeviceMutedOverlay(); maybeDeleteOutputDeviceMutedOverlay();

View file

@ -50,11 +50,11 @@ var OVERLAY_DATA_HMD = {
}; };
var AWAY_INTRO = { 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, playbackRate: 30.0,
loopFlag: false, loopFlag: true,
startFrame: 0.0, startFrame: 1.0,
endFrame: 83.0 endFrame: 489.0
}; };
// MAIN CONTROL // 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." "tooltip": "The angle in deg at which light emits. Starts in the entity's -z direction, and rotates around its x axis."
}, },
"keyLight.castShadows": { "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": { "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." "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." "tooltip": "If enabled, grabbed entities will follow the movements of your hand controller instead of your avatar's hand."
}, },
"canCastShadow": { "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": { "ignorePickIntersection": {
"tooltip": "If enabled, this entity will not be considered for ray picks, and will also not occlude other entities when picking." "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 // Automatically enter first person mode when entering HMD mode
HMD.displayModeChanged.connect(function(isHMDMode) { HMD.displayModeChanged.connect(function(isHMDMode) {
if (isHMDMode) { if (isHMDMode) {
Camera.setModeString("first person"); Camera.setModeString("first person look at");
} }
}); });

View file

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

View file

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

View file

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

View file

@ -61,17 +61,21 @@ Item {
Rectangle { Rectangle {
width: 5 width: 5
height: 5 height: 5
color: "red" color: "blue"
ColorAnimation on color { loops: Animation.Infinite; from: "red"; to: "yellow"; duration: 1000 } ColorAnimation on color { loops: Animation.Infinite; from: "blue"; to: "yellow"; duration: 1000 }
} }
WebEngineView { WebEngineView {
id: root id: root
url: "https://google.com/" url: "https://www.webrtc-experiment.com/Pluginfree-Screen-Sharing/#19583796789766627"
x: 6; y: 6; // url: "https://vimeo.com/108650530"
width: parent.width * 0.8 // url: "https://www.youtube.com/watch?v=7EWQOeQf32U&autoplay=1&loop=1"
height: parent.height * 0.8 // 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->load(url, callback);
_surface->resize(_window->size()); _surface->resize(_window->size());
_surface->resume(); _surface->resume();
_window->installEventFilter(_surface.get());
} }
void MacQml::draw() { void MacQml::draw() {

View file

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

View file

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

View file

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

View file

@ -205,12 +205,22 @@ void TestWindow::resizeEvent(QResizeEvent* ev) {
int main(int argc, char** argv) { int main(int argc, char** argv) {
#ifdef Q_OS_MAC
auto format = getDefaultOpenGLSurfaceFormat(); 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); QSurfaceFormat::setDefaultFormat(format);
#endif
QGuiApplication app(argc, argv); 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); TestWindow window(builder);
return app.exec(); return app.exec();
} }

View file

@ -1,8 +1,10 @@
# General # General
This document describes the process to build Qt 5.12.3. 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. Note that there are several patches.
The second patch is to OpenSL ES audio. * 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 third is a patch to QScriptEngine to prevent crashes in QScriptEnginePrivate::reportAdditionalMemoryCost, during garbage collection. See https://bugreports.qt.io/browse/QTBUG-76176 * 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 ## Requirements
### Windows ### Windows
1. Visual Studio 2017 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` `cd qt5`
`git apply --ignore-space-change --ignore-whitespace patches/aec.patch` `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/qtscript-crash-fix.patch`
`git apply --ignore-space-change --ignore-whitespace patches/mac-web-video.patch`
`cd ..` `cd ..`
#### Configuring #### Configuring
`mkdir qt5-install` `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;