Merge remote-tracking branch 'upstream/master' into enable_aec_by_default
|
@ -36,6 +36,7 @@ module.exports = {
|
||||||
"GlobalServices": false,
|
"GlobalServices": false,
|
||||||
"GooglePoly": false,
|
"GooglePoly": false,
|
||||||
"Graphics": false,
|
"Graphics": false,
|
||||||
|
"HifiAbout": false,
|
||||||
"HMD": false,
|
"HMD": false,
|
||||||
"LaserPointers": false,
|
"LaserPointers": false,
|
||||||
"location": true,
|
"location": true,
|
||||||
|
|
1
BUILD.md
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
- [cmake](https://cmake.org/download/): 3.9
|
- [cmake](https://cmake.org/download/): 3.9
|
||||||
- [Qt](https://www.qt.io/download-open-source): 5.10.1
|
- [Qt](https://www.qt.io/download-open-source): 5.10.1
|
||||||
|
- [Python](https://www.python.org/downloads/): 3.6 or higher
|
||||||
- [OpenSSL](https://www.openssl.org/): Use the latest available 1.0 version (**NOT** 1.1) of OpenSSL to avoid security vulnerabilities.
|
- [OpenSSL](https://www.openssl.org/): Use the latest available 1.0 version (**NOT** 1.1) of OpenSSL to avoid security vulnerabilities.
|
||||||
- [VHACD](https://github.com/virneo/v-hacd)(clone this repository)(Optional)
|
- [VHACD](https://github.com/virneo/v-hacd)(clone this repository)(Optional)
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,11 @@ Install build tools:
|
||||||
sudo apt-get install cmake
|
sudo apt-get install cmake
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Install Python 3:
|
||||||
|
```bash
|
||||||
|
sudo apt-get install python3.6
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### Get code and checkout the tag you need
|
### Get code and checkout the tag you need
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,10 @@ Please read the [general build guide](BUILD.md) for information on dependencies
|
||||||
|
|
||||||
brew install cmake openssl qt
|
brew install cmake openssl qt
|
||||||
|
|
||||||
|
### Python 3
|
||||||
|
|
||||||
|
Download an install Python 3.6.6 or higher from [here](https://www.python.org/downloads/). Execute the `Update Shell Profile.command` script that is provided with the installer.
|
||||||
|
|
||||||
### OpenSSL
|
### OpenSSL
|
||||||
|
|
||||||
Assuming you've installed OpenSSL using the homebrew instructions above, you'll need to set OPENSSL_ROOT_DIR so CMake can find your installations.
|
Assuming you've installed OpenSSL using the homebrew instructions above, you'll need to set OPENSSL_ROOT_DIR so CMake can find your installations.
|
||||||
|
@ -28,7 +32,9 @@ Note that this uses the version from the homebrew formula at the time of this wr
|
||||||
|
|
||||||
If Xcode is your editor of choice, you can ask CMake to generate Xcode project files instead of Unix Makefiles.
|
If Xcode is your editor of choice, you can ask CMake to generate Xcode project files instead of Unix Makefiles.
|
||||||
|
|
||||||
cmake .. -GXcode
|
cmake .. -G Xcode
|
||||||
|
|
||||||
|
If `cmake` complains about Python 3 being missing, you may need to update your CMake binary with command `brew upgrade cmake`, or by downloading and running the latest CMake installer, depending on how you originally instaled CMake
|
||||||
|
|
||||||
After running cmake, you will have the make files or Xcode project file necessary to build all of the components. Open the hifi.xcodeproj file, choose ALL_BUILD from the Product > Scheme menu (or target drop down), and click Run.
|
After running cmake, you will have the make files or Xcode project file necessary to build all of the components. Open the hifi.xcodeproj file, choose ALL_BUILD from the Product > Scheme menu (or target drop down), and click Run.
|
||||||
|
|
||||||
|
|
10
BUILD_WIN.md
|
@ -5,11 +5,17 @@ Note: We are now using Visual Studio 2017 and Qt 5.10.1. If you are upgrading fr
|
||||||
|
|
||||||
Note: The prerequisites will require about 10 GB of space on your drive. You will also need a system with at least 8GB of main memory.
|
Note: The prerequisites will require about 10 GB of space on your drive. You will also need a system with at least 8GB of main memory.
|
||||||
|
|
||||||
### Step 1. Visual Studio 2017
|
### Step 1. Visual Studio 2017 & Python
|
||||||
|
|
||||||
If you don’t have Community or Professional edition of Visual Studio 2017, download [Visual Studio Community 2017](https://www.visualstudio.com/downloads/).
|
If you don’t have Community or Professional edition of Visual Studio 2017, download [Visual Studio Community 2017](https://www.visualstudio.com/downloads/).
|
||||||
|
|
||||||
When selecting components, check "Desktop development with C++." Also on the right on the Summary toolbar, check "Windows 8.1 SDK and UCRT SDK" and "VC++ 2015.3 v140 toolset (x86,x64)".
|
When selecting components, check "Desktop development with C++". Also on the right on the Summary toolbar, check "Windows 8.1 SDK and UCRT SDK" and "VC++ 2015.3 v140 toolset (x86,x64)". If you do not already have a python development environment installed, also check "Python Development" in this screen.
|
||||||
|
|
||||||
|
If you already have Visual Studio installed and need to add python, open the "Add or remove programs" control panel and find the "Microsoft Visual Studio Installer". Select it and click "Modify". In the installer, select "Modify" again, then check "Python Development" and allow the installer to apply the changes.
|
||||||
|
|
||||||
|
### Step 1a. Alternate Python
|
||||||
|
|
||||||
|
If you do not wish to use the Python installation bundled with Visual Studio, you can download the installer from [here](https://www.python.org/downloads/). Ensure you get version 3.6.6 or higher.
|
||||||
|
|
||||||
### Step 2. Installing CMake
|
### Step 2. Installing CMake
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ if (ANDROID)
|
||||||
set(GLES_OPTION ON)
|
set(GLES_OPTION ON)
|
||||||
set(PLATFORM_QT_COMPONENTS AndroidExtras WebView)
|
set(PLATFORM_QT_COMPONENTS AndroidExtras WebView)
|
||||||
else ()
|
else ()
|
||||||
set(PLATFORM_QT_COMPONENTS WebEngine WebEngineWidgets)
|
set(PLATFORM_QT_COMPONENTS WebEngine)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (USE_GLES AND (NOT ANDROID))
|
if (USE_GLES AND (NOT ANDROID))
|
||||||
|
|
|
@ -24,7 +24,6 @@ android {
|
||||||
'-DANDROID_STL=c++_shared',
|
'-DANDROID_STL=c++_shared',
|
||||||
'-DQT_CMAKE_PREFIX_PATH=' + HIFI_ANDROID_PRECOMPILED + '/qt/lib/cmake',
|
'-DQT_CMAKE_PREFIX_PATH=' + HIFI_ANDROID_PRECOMPILED + '/qt/lib/cmake',
|
||||||
'-DNATIVE_SCRIBE=' + HIFI_ANDROID_PRECOMPILED + '/scribe' + EXEC_SUFFIX,
|
'-DNATIVE_SCRIBE=' + HIFI_ANDROID_PRECOMPILED + '/scribe' + EXEC_SUFFIX,
|
||||||
'-DNATIVE_SHREFLECT=' + HIFI_ANDROID_PRECOMPILED + '/shreflect' + EXEC_SUFFIX,
|
|
||||||
'-DHIFI_ANDROID_PRECOMPILED=' + HIFI_ANDROID_PRECOMPILED,
|
'-DHIFI_ANDROID_PRECOMPILED=' + HIFI_ANDROID_PRECOMPILED,
|
||||||
'-DRELEASE_NUMBER=' + RELEASE_NUMBER,
|
'-DRELEASE_NUMBER=' + RELEASE_NUMBER,
|
||||||
'-DRELEASE_TYPE=' + RELEASE_TYPE,
|
'-DRELEASE_TYPE=' + RELEASE_TYPE,
|
||||||
|
|
|
@ -161,31 +161,19 @@ def packages = [
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def scribeLocalFile='scribe' + EXEC_SUFFIX
|
def scribeLocalFile='scribe' + EXEC_SUFFIX
|
||||||
def scribeFile='scribe_linux_x86_64'
|
def scribeFile='scribe_linux_x86_64'
|
||||||
def scribeChecksum='ca4b904f52f4f993c29175ba96798fa6'
|
def scribeChecksum='4635c28192724281d2367ce9e94380ab'
|
||||||
def scribeVersion='u_iTrJDaE95i2abTPXOpPZckGBIim53G'
|
def scribeVersion='mPAY_N846oZH1tPY1bwChB_hzqkiYyoC'
|
||||||
|
|
||||||
def shreflectLocalFile='shreflect' + EXEC_SUFFIX
|
|
||||||
def shreflectFile='shreflect_linux_x86_64'
|
|
||||||
def shreflectChecksum='d6094a8580066c0b6f4e80b5adfb1d98'
|
|
||||||
def shreflectVersion='jnrpudh6fptIg6T2.Z6fgKP2ultAdKmE'
|
|
||||||
|
|
||||||
if (Os.isFamily(Os.FAMILY_MAC)) {
|
if (Os.isFamily(Os.FAMILY_MAC)) {
|
||||||
scribeFile = 'scribe_osx_x86_64'
|
scribeFile = 'scribe_osx_x86_64'
|
||||||
scribeChecksum='72db9d32d4e1e50add755570ac5eb749'
|
scribeChecksum='1ead61c285d265eba9a5ef91ae3b7c26'
|
||||||
scribeVersion='DAW0DmnjCRib4MD8x93bgc2Z2MpPojZC'
|
scribeVersion='4TAXWdo9fviw60N2wUA8HNyQ9TabjZa3'
|
||||||
shreflectFile='shreflect_osx_x86_64'
|
|
||||||
shreflectChecksum='d613ef0703c21371fee93fd2e54b964f'
|
|
||||||
shreflectVersion='.rYNzjSFq6WtWDnE5KIKRIAGyJtr__ad'
|
|
||||||
} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||||
scribeFile = 'scribe_win32_x86_64.exe'
|
scribeFile = 'scribe_win32_x86_64.exe'
|
||||||
scribeChecksum='678e43d290c90fda670c6fefe038a06d'
|
scribeChecksum='9c29a62595daf4844f95f6744d568c15'
|
||||||
scribeVersion='PuullrA_bPlO9kXZRt8rLe536X1UI.m7'
|
scribeVersion='DUoxjufeX8ZAIVRBKRczWTuZwT13enTv'
|
||||||
shreflectFile='shreflect_win32_x86_64.exe'
|
|
||||||
shreflectChecksum='6f4a77b8cceb3f1bbc655132c3665060'
|
|
||||||
shreflectVersion='iIyCyza1nelkbI7ihybF59bBlwrfAC3D'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def options = [
|
def options = [
|
||||||
|
@ -461,27 +449,11 @@ task fixScribePermissions(type: Exec, dependsOn: verifyScribe) {
|
||||||
commandLine 'chmod', 'a+x', HIFI_ANDROID_PRECOMPILED + '/' + scribeLocalFile
|
commandLine 'chmod', 'a+x', HIFI_ANDROID_PRECOMPILED + '/' + scribeLocalFile
|
||||||
}
|
}
|
||||||
|
|
||||||
task downloadShreflect(type: Download) {
|
task setupScribe(dependsOn: [verifyScribe]) { }
|
||||||
src baseUrl + shreflectFile + '?versionId=' + shreflectVersion
|
|
||||||
dest new File(baseFolder, shreflectLocalFile)
|
|
||||||
onlyIfNewer true
|
|
||||||
}
|
|
||||||
|
|
||||||
task verifyShreflect(type: Verify, dependsOn: downloadShreflect) {
|
|
||||||
src new File(baseFolder, shreflectLocalFile);
|
|
||||||
checksum shreflectChecksum
|
|
||||||
}
|
|
||||||
|
|
||||||
task fixShreflectPermissions(type: Exec, dependsOn: verifyShreflect) {
|
|
||||||
commandLine 'chmod', 'a+x', HIFI_ANDROID_PRECOMPILED + '/' + shreflectLocalFile
|
|
||||||
}
|
|
||||||
|
|
||||||
task setupScribe(dependsOn: [verifyScribe, verifyShreflect]) { }
|
|
||||||
|
|
||||||
// On Windows, we don't need to set the executable bit, but on OSX and Unix we do
|
// On Windows, we don't need to set the executable bit, but on OSX and Unix we do
|
||||||
if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
|
if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||||
setupScribe.dependsOn fixScribePermissions
|
setupScribe.dependsOn fixScribePermissions
|
||||||
setupScribe.dependsOn fixShreflectPermissions
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task extractGvrBinaries(dependsOn: extractDependencies) {
|
task extractGvrBinaries(dependsOn: extractDependencies) {
|
||||||
|
|
|
@ -222,7 +222,8 @@ void Agent::requestScript() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(this, scriptURL);
|
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||||
|
this, scriptURL, true, -1, "Agent::requestScript");
|
||||||
|
|
||||||
if (!request) {
|
if (!request) {
|
||||||
qWarning() << "Could not create ResourceRequest for Agent script at" << scriptURL.toString();
|
qWarning() << "Could not create ResourceRequest for Agent script at" << scriptURL.toString();
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
#include <ClientTraitsHandler.h>
|
|
||||||
#include <EntityEditPacketSender.h>
|
#include <EntityEditPacketSender.h>
|
||||||
#include <EntityTree.h>
|
#include <EntityTree.h>
|
||||||
#include <ScriptEngine.h>
|
#include <ScriptEngine.h>
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
#include "AssignmentClientLogging.h"
|
#include "AssignmentClientLogging.h"
|
||||||
#include "AssignmentFactory.h"
|
#include "AssignmentFactory.h"
|
||||||
|
#include "ResourceRequestObserver.h"
|
||||||
|
|
||||||
const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client";
|
const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client";
|
||||||
const long long ASSIGNMENT_REQUEST_INTERVAL_MSECS = 1 * 1000;
|
const long long ASSIGNMENT_REQUEST_INTERVAL_MSECS = 1 * 1000;
|
||||||
|
@ -49,6 +50,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
|
||||||
DependencyManager::set<tracing::Tracer>();
|
DependencyManager::set<tracing::Tracer>();
|
||||||
DependencyManager::set<StatTracker>();
|
DependencyManager::set<StatTracker>();
|
||||||
DependencyManager::set<AccountManager>();
|
DependencyManager::set<AccountManager>();
|
||||||
|
DependencyManager::set<ResourceRequestObserver>();
|
||||||
|
|
||||||
auto addressManager = DependencyManager::set<AddressManager>();
|
auto addressManager = DependencyManager::set<AddressManager>();
|
||||||
|
|
||||||
|
|
|
@ -541,7 +541,7 @@ void AvatarMixer::handleRequestsDomainListDataPacket(QSharedPointer<ReceivedMess
|
||||||
// ...For those nodes, reset the lastBroadcastTime to 0
|
// ...For those nodes, reset the lastBroadcastTime to 0
|
||||||
// so that the AvatarMixer will send Identity data to us
|
// so that the AvatarMixer will send Identity data to us
|
||||||
[&](const SharedNodePointer& node) {
|
[&](const SharedNodePointer& node) {
|
||||||
nodeData->setLastBroadcastTime(node->getUUID(), 0);
|
nodeData->setLastBroadcastTime(node->getLocalID(), 0);
|
||||||
nodeData->resetSentTraitData(node->getLocalID());
|
nodeData->resetSentTraitData(node->getLocalID());
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -565,7 +565,8 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> mes
|
||||||
// parse the identity packet and update the change timestamp if appropriate
|
// parse the identity packet and update the change timestamp if appropriate
|
||||||
bool identityChanged = false;
|
bool identityChanged = false;
|
||||||
bool displayNameChanged = false;
|
bool displayNameChanged = false;
|
||||||
avatar.processAvatarIdentity(message->getMessage(), identityChanged, displayNameChanged);
|
QDataStream avatarIdentityStream(message->getMessage());
|
||||||
|
avatar.processAvatarIdentity(avatarIdentityStream, identityChanged, displayNameChanged);
|
||||||
|
|
||||||
if (identityChanged) {
|
if (identityChanged) {
|
||||||
QMutexLocker nodeDataLocker(&nodeData->getMutex());
|
QMutexLocker nodeDataLocker(&nodeData->getMutex());
|
||||||
|
@ -637,7 +638,7 @@ void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage>
|
||||||
// Reset the lastBroadcastTime for the ignored avatar to 0
|
// Reset the lastBroadcastTime for the ignored avatar to 0
|
||||||
// so the AvatarMixer knows it'll have to send identity data about the ignored avatar
|
// so the AvatarMixer knows it'll have to send identity data about the ignored avatar
|
||||||
// to the ignorer if the ignorer unignores.
|
// to the ignorer if the ignorer unignores.
|
||||||
nodeData->setLastBroadcastTime(ignoredUUID, 0);
|
nodeData->setLastBroadcastTime(ignoredNode->getLocalID(), 0);
|
||||||
nodeData->resetSentTraitData(ignoredNode->getLocalID());
|
nodeData->resetSentTraitData(ignoredNode->getLocalID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,7 +648,7 @@ void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage>
|
||||||
// to the ignored if the ignorer unignores.
|
// to the ignored if the ignorer unignores.
|
||||||
AvatarMixerClientData* ignoredNodeData = reinterpret_cast<AvatarMixerClientData*>(ignoredNode->getLinkedData());
|
AvatarMixerClientData* ignoredNodeData = reinterpret_cast<AvatarMixerClientData*>(ignoredNode->getLinkedData());
|
||||||
if (ignoredNodeData) {
|
if (ignoredNodeData) {
|
||||||
ignoredNodeData->setLastBroadcastTime(senderNode->getUUID(), 0);
|
ignoredNodeData->setLastBroadcastTime(senderNode->getLocalID(), 0);
|
||||||
ignoredNodeData->resetSentTraitData(senderNode->getLocalID());
|
ignoredNodeData->resetSentTraitData(senderNode->getLocalID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,20 +26,20 @@ AvatarMixerClientData::AvatarMixerClientData(const QUuid& nodeID, Node::LocalID
|
||||||
_avatar->setID(nodeID);
|
_avatar->setID(nodeID);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t AvatarMixerClientData::getLastOtherAvatarEncodeTime(QUuid otherAvatar) const {
|
uint64_t AvatarMixerClientData::getLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar) const {
|
||||||
std::unordered_map<QUuid, uint64_t>::const_iterator itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
|
const auto itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
|
||||||
if (itr != _lastOtherAvatarEncodeTime.end()) {
|
if (itr != _lastOtherAvatarEncodeTime.end()) {
|
||||||
return itr->second;
|
return itr->second;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarMixerClientData::setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time) {
|
void AvatarMixerClientData::setLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar, uint64_t time) {
|
||||||
std::unordered_map<QUuid, uint64_t>::iterator itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
|
auto itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
|
||||||
if (itr != _lastOtherAvatarEncodeTime.end()) {
|
if (itr != _lastOtherAvatarEncodeTime.end()) {
|
||||||
itr->second = time;
|
itr->second = time;
|
||||||
} else {
|
} else {
|
||||||
_lastOtherAvatarEncodeTime.emplace(std::pair<QUuid, uint64_t>(otherAvatar, time));
|
_lastOtherAvatarEncodeTime.emplace(std::pair<NLPacket::LocalID, uint64_t>(otherAvatar, time));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ void AvatarMixerClientData::checkSkeletonURLAgainstWhitelist(const SlaveSharedDa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t AvatarMixerClientData::getLastBroadcastTime(const QUuid& nodeUUID) const {
|
uint64_t AvatarMixerClientData::getLastBroadcastTime(NLPacket::LocalID nodeUUID) const {
|
||||||
// return the matching PacketSequenceNumber, or the default if we don't have it
|
// return the matching PacketSequenceNumber, or the default if we don't have it
|
||||||
auto nodeMatch = _lastBroadcastTimes.find(nodeUUID);
|
auto nodeMatch = _lastBroadcastTimes.find(nodeUUID);
|
||||||
if (nodeMatch != _lastBroadcastTimes.end()) {
|
if (nodeMatch != _lastBroadcastTimes.end()) {
|
||||||
|
@ -229,9 +229,9 @@ uint64_t AvatarMixerClientData::getLastBroadcastTime(const QUuid& nodeUUID) cons
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t AvatarMixerClientData::getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const {
|
uint16_t AvatarMixerClientData::getLastBroadcastSequenceNumber(NLPacket::LocalID nodeID) const {
|
||||||
// return the matching PacketSequenceNumber, or the default if we don't have it
|
// return the matching PacketSequenceNumber, or the default if we don't have it
|
||||||
auto nodeMatch = _lastBroadcastSequenceNumbers.find(nodeUUID);
|
auto nodeMatch = _lastBroadcastSequenceNumbers.find(nodeID);
|
||||||
if (nodeMatch != _lastBroadcastSequenceNumbers.end()) {
|
if (nodeMatch != _lastBroadcastSequenceNumbers.end()) {
|
||||||
return nodeMatch->second;
|
return nodeMatch->second;
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ void AvatarMixerClientData::ignoreOther(const Node* self, const Node* other) {
|
||||||
} else {
|
} else {
|
||||||
killPacket->writePrimitive(KillAvatarReason::YourAvatarEnteredTheirBubble);
|
killPacket->writePrimitive(KillAvatarReason::YourAvatarEnteredTheirBubble);
|
||||||
}
|
}
|
||||||
setLastBroadcastTime(other->getUUID(), 0);
|
setLastBroadcastTime(other->getLocalID(), 0);
|
||||||
|
|
||||||
resetSentTraitData(other->getLocalID());
|
resetSentTraitData(other->getLocalID());
|
||||||
|
|
||||||
|
@ -331,9 +331,9 @@ AvatarMixerClientData::TraitsCheckTimestamp AvatarMixerClientData::getLastOtherA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarMixerClientData::cleanupKilledNode(const QUuid& nodeUUID, Node::LocalID nodeLocalID) {
|
void AvatarMixerClientData::cleanupKilledNode(const QUuid&, Node::LocalID nodeLocalID) {
|
||||||
removeLastBroadcastSequenceNumber(nodeUUID);
|
removeLastBroadcastSequenceNumber(nodeLocalID);
|
||||||
removeLastBroadcastTime(nodeUUID);
|
removeLastBroadcastTime(nodeLocalID);
|
||||||
_lastSentTraitsTimestamps.erase(nodeLocalID);
|
_lastSentTraitsTimestamps.erase(nodeLocalID);
|
||||||
_sentTraitVersions.erase(nodeLocalID);
|
_sentTraitVersions.erase(nodeLocalID);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,17 +49,16 @@ public:
|
||||||
const AvatarData* getConstAvatarData() const { return _avatar.get(); }
|
const AvatarData* getConstAvatarData() const { return _avatar.get(); }
|
||||||
AvatarSharedPointer getAvatarSharedPointer() const { return _avatar; }
|
AvatarSharedPointer getAvatarSharedPointer() const { return _avatar; }
|
||||||
|
|
||||||
|
uint16_t getLastBroadcastSequenceNumber(NLPacket::LocalID nodeID) const;
|
||||||
|
void setLastBroadcastSequenceNumber(NLPacket::LocalID nodeID, uint16_t sequenceNumber)
|
||||||
|
{ _lastBroadcastSequenceNumbers[nodeID] = sequenceNumber; }
|
||||||
|
Q_INVOKABLE void removeLastBroadcastSequenceNumber(NLPacket::LocalID nodeID) { _lastBroadcastSequenceNumbers.erase(nodeID); }
|
||||||
bool isIgnoreRadiusEnabled() const { return _isIgnoreRadiusEnabled; }
|
bool isIgnoreRadiusEnabled() const { return _isIgnoreRadiusEnabled; }
|
||||||
void setIsIgnoreRadiusEnabled(bool enabled) { _isIgnoreRadiusEnabled = enabled; }
|
void setIsIgnoreRadiusEnabled(bool enabled) { _isIgnoreRadiusEnabled = enabled; }
|
||||||
|
|
||||||
uint16_t getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const;
|
uint64_t getLastBroadcastTime(NLPacket::LocalID nodeUUID) const;
|
||||||
void setLastBroadcastSequenceNumber(const QUuid& nodeUUID, uint16_t sequenceNumber)
|
void setLastBroadcastTime(NLPacket::LocalID nodeUUID, uint64_t broadcastTime) { _lastBroadcastTimes[nodeUUID] = broadcastTime; }
|
||||||
{ _lastBroadcastSequenceNumbers[nodeUUID] = sequenceNumber; }
|
Q_INVOKABLE void removeLastBroadcastTime(NLPacket::LocalID nodeUUID) { _lastBroadcastTimes.erase(nodeUUID); }
|
||||||
Q_INVOKABLE void removeLastBroadcastSequenceNumber(const QUuid& nodeUUID) { _lastBroadcastSequenceNumbers.erase(nodeUUID); }
|
|
||||||
|
|
||||||
uint64_t getLastBroadcastTime(const QUuid& nodeUUID) const;
|
|
||||||
void setLastBroadcastTime(const QUuid& nodeUUID, uint64_t broadcastTime) { _lastBroadcastTimes[nodeUUID] = broadcastTime; }
|
|
||||||
Q_INVOKABLE void removeLastBroadcastTime(const QUuid& nodeUUID) { _lastBroadcastTimes.erase(nodeUUID); }
|
|
||||||
|
|
||||||
Q_INVOKABLE void cleanupKilledNode(const QUuid& nodeUUID, Node::LocalID nodeLocalID);
|
Q_INVOKABLE void cleanupKilledNode(const QUuid& nodeUUID, Node::LocalID nodeLocalID);
|
||||||
|
|
||||||
|
@ -93,7 +92,7 @@ public:
|
||||||
|
|
||||||
void loadJSONStats(QJsonObject& jsonObject) const;
|
void loadJSONStats(QJsonObject& jsonObject) const;
|
||||||
|
|
||||||
glm::vec3 getPosition() const { return _avatar ? _avatar->getWorldPosition() : glm::vec3(0); }
|
glm::vec3 getPosition() const { return _avatar ? _avatar->getClientGlobalPosition() : glm::vec3(0); }
|
||||||
bool isRadiusIgnoring(const QUuid& other) const;
|
bool isRadiusIgnoring(const QUuid& other) const;
|
||||||
void addToRadiusIgnoringSet(const QUuid& other);
|
void addToRadiusIgnoringSet(const QUuid& other);
|
||||||
void removeFromRadiusIgnoringSet(const QUuid& other);
|
void removeFromRadiusIgnoringSet(const QUuid& other);
|
||||||
|
@ -114,10 +113,10 @@ public:
|
||||||
|
|
||||||
const ConicalViewFrustums& getViewFrustums() const { return _currentViewFrustums; }
|
const ConicalViewFrustums& getViewFrustums() const { return _currentViewFrustums; }
|
||||||
|
|
||||||
uint64_t getLastOtherAvatarEncodeTime(QUuid otherAvatar) const;
|
uint64_t getLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar) const;
|
||||||
void setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time);
|
void setLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar, uint64_t time);
|
||||||
|
|
||||||
QVector<JointData>& getLastOtherAvatarSentJoints(QUuid otherAvatar) { return _lastOtherAvatarSentJoints[otherAvatar]; }
|
QVector<JointData>& getLastOtherAvatarSentJoints(NLPacket::LocalID otherAvatar) { return _lastOtherAvatarSentJoints[otherAvatar]; }
|
||||||
|
|
||||||
void queuePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node);
|
void queuePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node);
|
||||||
int processPackets(const SlaveSharedData& slaveSharedData); // returns number of packets processed
|
int processPackets(const SlaveSharedData& slaveSharedData); // returns number of packets processed
|
||||||
|
@ -150,13 +149,13 @@ private:
|
||||||
AvatarSharedPointer _avatar { new AvatarData() };
|
AvatarSharedPointer _avatar { new AvatarData() };
|
||||||
|
|
||||||
uint16_t _lastReceivedSequenceNumber { 0 };
|
uint16_t _lastReceivedSequenceNumber { 0 };
|
||||||
std::unordered_map<QUuid, uint16_t> _lastBroadcastSequenceNumbers;
|
std::unordered_map<NLPacket::LocalID, uint16_t> _lastBroadcastSequenceNumbers;
|
||||||
std::unordered_map<QUuid, uint64_t> _lastBroadcastTimes;
|
std::unordered_map<NLPacket::LocalID, uint64_t> _lastBroadcastTimes;
|
||||||
|
|
||||||
// this is a map of the last time we encoded an "other" avatar for
|
// this is a map of the last time we encoded an "other" avatar for
|
||||||
// sending to "this" node
|
// sending to "this" node
|
||||||
std::unordered_map<QUuid, uint64_t> _lastOtherAvatarEncodeTime;
|
std::unordered_map<NLPacket::LocalID, uint64_t> _lastOtherAvatarEncodeTime;
|
||||||
std::unordered_map<QUuid, QVector<JointData>> _lastOtherAvatarSentJoints;
|
std::unordered_map<NLPacket::LocalID, QVector<JointData>> _lastOtherAvatarSentJoints;
|
||||||
|
|
||||||
uint64_t _identityChangeTimestamp;
|
uint64_t _identityChangeTimestamp;
|
||||||
bool _avatarSessionDisplayNameMustChange{ true };
|
bool _avatarSessionDisplayNameMustChange{ true };
|
||||||
|
|
|
@ -68,13 +68,11 @@ void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) {
|
||||||
_stats.processIncomingPacketsElapsedTime += (end - start);
|
_stats.processIncomingPacketsElapsedTime += (end - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
int AvatarMixerSlave::sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode) {
|
int AvatarMixerSlave::sendIdentityPacket(NLPacketList& packetList, const AvatarMixerClientData* nodeData, const Node& destinationNode) {
|
||||||
if (destinationNode->getType() == NodeType::Agent && !destinationNode->isUpstream()) {
|
if (destinationNode.getType() == NodeType::Agent && !destinationNode.isUpstream()) {
|
||||||
QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray();
|
QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray();
|
||||||
individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious
|
individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious
|
||||||
auto identityPackets = NLPacketList::create(PacketType::AvatarIdentity, QByteArray(), true, true);
|
packetList.write(individualData);
|
||||||
identityPackets->write(individualData);
|
|
||||||
DependencyManager::get<NodeList>()->sendPacketList(std::move(identityPackets), *destinationNode);
|
|
||||||
_stats.numIdentityPackets++;
|
_stats.numIdentityPackets++;
|
||||||
return individualData.size();
|
return individualData.size();
|
||||||
} else {
|
} else {
|
||||||
|
@ -247,12 +245,12 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
// reset the internal state for correct random number distribution
|
// reset the internal state for correct random number distribution
|
||||||
distribution.reset();
|
distribution.reset();
|
||||||
|
|
||||||
|
// Estimate number to sort on number sent last frame (with min. of 20).
|
||||||
|
const int numToSendEst = std::max(int(nodeData->getNumAvatarsSentLastFrame() * 2.5f), 20);
|
||||||
|
|
||||||
// reset the number of sent avatars
|
// reset the number of sent avatars
|
||||||
nodeData->resetNumAvatarsSentLastFrame();
|
nodeData->resetNumAvatarsSentLastFrame();
|
||||||
|
|
||||||
// keep a counter of the number of considered avatars
|
|
||||||
int numOtherAvatars = 0;
|
|
||||||
|
|
||||||
// keep track of outbound data rate specifically for avatar data
|
// keep track of outbound data rate specifically for avatar data
|
||||||
int numAvatarDataBytes = 0;
|
int numAvatarDataBytes = 0;
|
||||||
int identityBytesSent = 0;
|
int identityBytesSent = 0;
|
||||||
|
@ -261,7 +259,6 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
// max number of avatarBytes per frame
|
// max number of avatarBytes per frame
|
||||||
int maxAvatarBytesPerFrame = int(_maxKbpsPerNode * BYTES_PER_KILOBIT / AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND);
|
int maxAvatarBytesPerFrame = int(_maxKbpsPerNode * BYTES_PER_KILOBIT / AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND);
|
||||||
|
|
||||||
|
|
||||||
// keep track of the number of other avatars held back in this frame
|
// keep track of the number of other avatars held back in this frame
|
||||||
int numAvatarsHeldBack = 0;
|
int numAvatarsHeldBack = 0;
|
||||||
|
|
||||||
|
@ -279,10 +276,6 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
int minimumBytesPerAvatar = PALIsOpen ? AvatarDataPacket::AVATAR_HAS_FLAGS_SIZE + NUM_BYTES_RFC4122_UUID +
|
int minimumBytesPerAvatar = PALIsOpen ? AvatarDataPacket::AVATAR_HAS_FLAGS_SIZE + NUM_BYTES_RFC4122_UUID +
|
||||||
sizeof(AvatarDataPacket::AvatarGlobalPosition) + sizeof(AvatarDataPacket::AudioLoudness) : 0;
|
sizeof(AvatarDataPacket::AvatarGlobalPosition) + sizeof(AvatarDataPacket::AudioLoudness) : 0;
|
||||||
|
|
||||||
// setup a PacketList for the avatarPackets
|
|
||||||
auto avatarPacketList = NLPacketList::create(PacketType::BulkAvatarData);
|
|
||||||
static auto maxAvatarDataBytes = avatarPacketList->getMaxSegmentSize() - NUM_BYTES_RFC4122_UUID;
|
|
||||||
|
|
||||||
// compute node bounding box
|
// compute node bounding box
|
||||||
const float MY_AVATAR_BUBBLE_EXPANSION_FACTOR = 4.0f; // magic number determined emperically
|
const float MY_AVATAR_BUBBLE_EXPANSION_FACTOR = 4.0f; // magic number determined emperically
|
||||||
AABox nodeBox = computeBubbleBox(avatar, MY_AVATAR_BUBBLE_EXPANSION_FACTOR);
|
AABox nodeBox = computeBubbleBox(avatar, MY_AVATAR_BUBBLE_EXPANSION_FACTOR);
|
||||||
|
@ -350,8 +343,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
// Don't bother with these checks if the other avatar has their bubble enabled and we're gettingAnyIgnored
|
// Don't bother with these checks if the other avatar has their bubble enabled and we're gettingAnyIgnored
|
||||||
if (nodeData->isIgnoreRadiusEnabled() || (avatarClientNodeData->isIgnoreRadiusEnabled() && !getsAnyIgnored)) {
|
if (nodeData->isIgnoreRadiusEnabled() || (avatarClientNodeData->isIgnoreRadiusEnabled() && !getsAnyIgnored)) {
|
||||||
// Perform the collision check between the two bounding boxes
|
// Perform the collision check between the two bounding boxes
|
||||||
const float OTHER_AVATAR_BUBBLE_EXPANSION_FACTOR = 2.4f; // magic number determined empirically
|
AABox otherNodeBox = avatarClientNodeData->getAvatar().getDefaultBubbleBox();
|
||||||
AABox otherNodeBox = computeBubbleBox(avatarClientNodeData->getAvatar(), OTHER_AVATAR_BUBBLE_EXPANSION_FACTOR);
|
|
||||||
if (nodeBox.touches(otherNodeBox)) {
|
if (nodeBox.touches(otherNodeBox)) {
|
||||||
nodeData->ignoreOther(destinationNode, avatarNode);
|
nodeData->ignoreOther(destinationNode, avatarNode);
|
||||||
shouldIgnore = !getsAnyIgnored;
|
shouldIgnore = !getsAnyIgnored;
|
||||||
|
@ -364,7 +356,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shouldIgnore) {
|
if (!shouldIgnore) {
|
||||||
AvatarDataSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(avatarNode->getUUID());
|
AvatarDataSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(avatarNode->getLocalID());
|
||||||
AvatarDataSequenceNumber lastSeqFromSender = avatarClientNodeData->getLastReceivedSequenceNumber();
|
AvatarDataSequenceNumber lastSeqFromSender = avatarClientNodeData->getLastReceivedSequenceNumber();
|
||||||
|
|
||||||
// FIXME - This code does appear to be working. But it seems brittle.
|
// FIXME - This code does appear to be working. But it seems brittle.
|
||||||
|
@ -396,7 +388,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
if (!shouldIgnore) {
|
if (!shouldIgnore) {
|
||||||
// sort this one for later
|
// sort this one for later
|
||||||
const AvatarData* avatarNodeData = avatarClientNodeData->getConstAvatarData();
|
const AvatarData* avatarNodeData = avatarClientNodeData->getConstAvatarData();
|
||||||
auto lastEncodeTime = nodeData->getLastOtherAvatarEncodeTime(avatarNodeData->getSessionUUID());
|
auto lastEncodeTime = nodeData->getLastOtherAvatarEncodeTime(avatarNode->getLocalID());
|
||||||
|
|
||||||
sortedAvatars.push(SortableAvatar(avatarNodeData, avatarNode, lastEncodeTime));
|
sortedAvatars.push(SortableAvatar(avatarNodeData, avatarNode, lastEncodeTime));
|
||||||
}
|
}
|
||||||
|
@ -406,8 +398,13 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
|
|
||||||
int remainingAvatars = (int)sortedAvatars.size();
|
int remainingAvatars = (int)sortedAvatars.size();
|
||||||
auto traitsPacketList = NLPacketList::create(PacketType::BulkAvatarTraits, QByteArray(), true, true);
|
auto traitsPacketList = NLPacketList::create(PacketType::BulkAvatarTraits, QByteArray(), true, true);
|
||||||
|
auto avatarPacket = NLPacket::create(PacketType::BulkAvatarData);
|
||||||
|
const int avatarPacketCapacity = avatarPacket->getPayloadCapacity();
|
||||||
|
int avatarSpaceAvailable = avatarPacketCapacity;
|
||||||
|
int numPacketsSent = 0;
|
||||||
|
auto identityPacketList = NLPacketList::create(PacketType::AvatarIdentity, QByteArray(), true, true);
|
||||||
|
|
||||||
const auto& sortedAvatarVector = sortedAvatars.getSortedVector();
|
const auto& sortedAvatarVector = sortedAvatars.getSortedVector(numToSendEst);
|
||||||
for (const auto& sortedAvatar : sortedAvatarVector) {
|
for (const auto& sortedAvatar : sortedAvatarVector) {
|
||||||
const Node* otherNode = sortedAvatar.getNode();
|
const Node* otherNode = sortedAvatar.getNode();
|
||||||
auto lastEncodeForOther = sortedAvatar.getTimestamp();
|
auto lastEncodeForOther = sortedAvatar.getTimestamp();
|
||||||
|
@ -432,21 +429,9 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
|
|
||||||
auto startAvatarDataPacking = chrono::high_resolution_clock::now();
|
auto startAvatarDataPacking = chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
++numOtherAvatars;
|
|
||||||
|
|
||||||
const AvatarMixerClientData* otherNodeData = reinterpret_cast<const AvatarMixerClientData*>(otherNode->getLinkedData());
|
const AvatarMixerClientData* otherNodeData = reinterpret_cast<const AvatarMixerClientData*>(otherNode->getLinkedData());
|
||||||
const AvatarData* otherAvatar = otherNodeData->getConstAvatarData();
|
const AvatarData* otherAvatar = otherNodeData->getConstAvatarData();
|
||||||
|
|
||||||
// If the time that the mixer sent AVATAR DATA about Avatar B to Avatar A is BEFORE OR EQUAL TO
|
|
||||||
// the time that Avatar B flagged an IDENTITY DATA change, send IDENTITY DATA about Avatar B to Avatar A.
|
|
||||||
if (otherAvatar->hasProcessedFirstIdentity()
|
|
||||||
&& nodeData->getLastBroadcastTime(otherNode->getUUID()) <= otherNodeData->getIdentityChangeTimestamp()) {
|
|
||||||
identityBytesSent += sendIdentityPacket(otherNodeData, node);
|
|
||||||
|
|
||||||
// remember the last time we sent identity details about this other node to the receiver
|
|
||||||
nodeData->setLastBroadcastTime(otherNode->getUUID(), usecTimestampNow());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Typically all out-of-view avatars but such avatars' priorities will rise with time:
|
// Typically all out-of-view avatars but such avatars' priorities will rise with time:
|
||||||
bool isLowerPriority = sortedAvatar.getPriority() <= OUT_OF_VIEW_THRESHOLD;
|
bool isLowerPriority = sortedAvatar.getPriority() <= OUT_OF_VIEW_THRESHOLD;
|
||||||
|
|
||||||
|
@ -456,71 +441,56 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
} else if (!overBudget) {
|
} else if (!overBudget) {
|
||||||
detail = distribution(generator) < AVATAR_SEND_FULL_UPDATE_RATIO ? AvatarData::SendAllData : AvatarData::CullSmallData;
|
detail = distribution(generator) < AVATAR_SEND_FULL_UPDATE_RATIO ? AvatarData::SendAllData : AvatarData::CullSmallData;
|
||||||
nodeData->incrementAvatarInView();
|
nodeData->incrementAvatarInView();
|
||||||
}
|
|
||||||
|
|
||||||
bool includeThisAvatar = true;
|
// If the time that the mixer sent AVATAR DATA about Avatar B to Avatar A is BEFORE OR EQUAL TO
|
||||||
QVector<JointData>& lastSentJointsForOther = nodeData->getLastOtherAvatarSentJoints(otherNode->getUUID());
|
// the time that Avatar B flagged an IDENTITY DATA change, send IDENTITY DATA about Avatar B to Avatar A.
|
||||||
|
if (otherAvatar->hasProcessedFirstIdentity()
|
||||||
|
&& nodeData->getLastBroadcastTime(otherNode->getLocalID()) <= otherNodeData->getIdentityChangeTimestamp()) {
|
||||||
|
identityBytesSent += sendIdentityPacket(*identityPacketList, otherNodeData, *destinationNode);
|
||||||
|
|
||||||
lastSentJointsForOther.resize(otherAvatar->getJointCount());
|
// remember the last time we sent identity details about this other node to the receiver
|
||||||
|
nodeData->setLastBroadcastTime(otherNode->getLocalID(), usecTimestampNow());
|
||||||
bool distanceAdjust = true;
|
|
||||||
glm::vec3 viewerPosition = myPosition;
|
|
||||||
AvatarDataPacket::HasFlags hasFlagsOut; // the result of the toByteArray
|
|
||||||
bool dropFaceTracking = false;
|
|
||||||
|
|
||||||
auto startSerialize = chrono::high_resolution_clock::now();
|
|
||||||
QByteArray bytes = otherAvatar->toByteArray(detail, lastEncodeForOther, lastSentJointsForOther,
|
|
||||||
hasFlagsOut, dropFaceTracking, distanceAdjust, viewerPosition,
|
|
||||||
&lastSentJointsForOther);
|
|
||||||
auto endSerialize = chrono::high_resolution_clock::now();
|
|
||||||
_stats.toByteArrayElapsedTime +=
|
|
||||||
(quint64) chrono::duration_cast<chrono::microseconds>(endSerialize - startSerialize).count();
|
|
||||||
|
|
||||||
if (bytes.size() > maxAvatarDataBytes) {
|
|
||||||
qCWarning(avatars) << "otherAvatar.toByteArray() for" << otherNode->getUUID()
|
|
||||||
<< "resulted in very large buffer of" << bytes.size() << "bytes - dropping facial data";
|
|
||||||
|
|
||||||
dropFaceTracking = true; // first try dropping the facial data
|
|
||||||
bytes = otherAvatar->toByteArray(detail, lastEncodeForOther, lastSentJointsForOther,
|
|
||||||
hasFlagsOut, dropFaceTracking, distanceAdjust, viewerPosition, &lastSentJointsForOther);
|
|
||||||
|
|
||||||
if (bytes.size() > maxAvatarDataBytes) {
|
|
||||||
qCWarning(avatars) << "otherAvatar.toByteArray() for" << otherNode->getUUID()
|
|
||||||
<< "without facial data resulted in very large buffer of" << bytes.size()
|
|
||||||
<< "bytes - reducing to MinimumData";
|
|
||||||
bytes = otherAvatar->toByteArray(AvatarData::MinimumData, lastEncodeForOther, lastSentJointsForOther,
|
|
||||||
hasFlagsOut, dropFaceTracking, distanceAdjust, viewerPosition, &lastSentJointsForOther);
|
|
||||||
|
|
||||||
if (bytes.size() > maxAvatarDataBytes) {
|
|
||||||
qCWarning(avatars) << "otherAvatar.toByteArray() for" << otherNode->getUUID()
|
|
||||||
<< "MinimumData resulted in very large buffer of" << bytes.size()
|
|
||||||
<< "bytes - refusing to send avatar";
|
|
||||||
includeThisAvatar = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeThisAvatar) {
|
QVector<JointData>& lastSentJointsForOther = nodeData->getLastOtherAvatarSentJoints(otherNode->getLocalID());
|
||||||
// start a new segment in the PacketList for this avatar
|
|
||||||
avatarPacketList->startSegment();
|
|
||||||
numAvatarDataBytes += avatarPacketList->write(otherNode->getUUID().toRfc4122());
|
|
||||||
numAvatarDataBytes += avatarPacketList->write(bytes);
|
|
||||||
avatarPacketList->endSegment();
|
|
||||||
|
|
||||||
if (detail != AvatarData::NoData) {
|
const bool distanceAdjust = true;
|
||||||
_stats.numOthersIncluded++;
|
const bool dropFaceTracking = false;
|
||||||
|
AvatarDataPacket::SendStatus sendStatus;
|
||||||
|
sendStatus.sendUUID = true;
|
||||||
|
|
||||||
// increment the number of avatars sent to this reciever
|
do {
|
||||||
nodeData->incrementNumAvatarsSentLastFrame();
|
auto startSerialize = chrono::high_resolution_clock::now();
|
||||||
|
QByteArray bytes = otherAvatar->toByteArray(detail, lastEncodeForOther, lastSentJointsForOther,
|
||||||
|
sendStatus, dropFaceTracking, distanceAdjust, myPosition,
|
||||||
|
&lastSentJointsForOther, avatarSpaceAvailable);
|
||||||
|
auto endSerialize = chrono::high_resolution_clock::now();
|
||||||
|
_stats.toByteArrayElapsedTime +=
|
||||||
|
(quint64)chrono::duration_cast<chrono::microseconds>(endSerialize - startSerialize).count();
|
||||||
|
|
||||||
// set the last sent sequence number for this sender on the receiver
|
avatarPacket->write(bytes);
|
||||||
nodeData->setLastBroadcastSequenceNumber(otherNode->getUUID(),
|
avatarSpaceAvailable -= bytes.size();
|
||||||
otherNodeData->getLastReceivedSequenceNumber());
|
numAvatarDataBytes += bytes.size();
|
||||||
nodeData->setLastOtherAvatarEncodeTime(otherNode->getUUID(), usecTimestampNow());
|
if (!sendStatus || avatarSpaceAvailable < (int)AvatarDataPacket::MIN_BULK_PACKET_SIZE) {
|
||||||
|
// Weren't able to fit everything.
|
||||||
|
nodeList->sendPacket(std::move(avatarPacket), *destinationNode);
|
||||||
|
++numPacketsSent;
|
||||||
|
avatarPacket = NLPacket::create(PacketType::BulkAvatarData);
|
||||||
|
avatarSpaceAvailable = avatarPacketCapacity;
|
||||||
}
|
}
|
||||||
} else {
|
} while (!sendStatus);
|
||||||
// TODO? this avatar is not included now, and will probably not be included next frame.
|
|
||||||
// It would be nice if we could tweak its future sort priority to put it at the back of the list.
|
if (detail != AvatarData::NoData) {
|
||||||
|
_stats.numOthersIncluded++;
|
||||||
|
|
||||||
|
// increment the number of avatars sent to this receiver
|
||||||
|
nodeData->incrementNumAvatarsSentLastFrame();
|
||||||
|
|
||||||
|
// set the last sent sequence number for this sender on the receiver
|
||||||
|
nodeData->setLastBroadcastSequenceNumber(otherNode->getLocalID(),
|
||||||
|
otherNodeData->getLastReceivedSequenceNumber());
|
||||||
|
nodeData->setLastOtherAvatarEncodeTime(otherNode->getLocalID(), usecTimestampNow());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto endAvatarDataPacking = chrono::high_resolution_clock::now();
|
auto endAvatarDataPacking = chrono::high_resolution_clock::now();
|
||||||
|
@ -532,17 +502,21 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
remainingAvatars--;
|
remainingAvatars--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nodeData->getNumAvatarsSentLastFrame() > numToSendEst) {
|
||||||
|
qCWarning(avatars) << "More avatars sent than upper estimate" << nodeData->getNumAvatarsSentLastFrame()
|
||||||
|
<< " / " << numToSendEst;
|
||||||
|
}
|
||||||
|
|
||||||
quint64 startPacketSending = usecTimestampNow();
|
quint64 startPacketSending = usecTimestampNow();
|
||||||
|
|
||||||
// close the current packet so that we're always sending something
|
if (avatarPacket->getPayloadSize() != 0) {
|
||||||
avatarPacketList->closeCurrentPacket(true);
|
nodeList->sendPacket(std::move(avatarPacket), *destinationNode);
|
||||||
|
++numPacketsSent;
|
||||||
|
}
|
||||||
|
|
||||||
_stats.numPacketsSent += (int)avatarPacketList->getNumPackets();
|
_stats.numPacketsSent += numPacketsSent;
|
||||||
_stats.numBytesSent += numAvatarDataBytes;
|
_stats.numBytesSent += numAvatarDataBytes;
|
||||||
|
|
||||||
// send the avatar data PacketList
|
|
||||||
nodeList->sendPacketList(std::move(avatarPacketList), *destinationNode);
|
|
||||||
|
|
||||||
// record the bytes sent for other avatar data in the AvatarMixerClientData
|
// record the bytes sent for other avatar data in the AvatarMixerClientData
|
||||||
nodeData->recordSentAvatarData(numAvatarDataBytes);
|
nodeData->recordSentAvatarData(numAvatarDataBytes);
|
||||||
|
|
||||||
|
@ -554,6 +528,12 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
nodeList->sendPacketList(std::move(traitsPacketList), *destinationNode);
|
nodeList->sendPacketList(std::move(traitsPacketList), *destinationNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send any AvatarIdentity packets:
|
||||||
|
identityPacketList->closeCurrentPacket();
|
||||||
|
if (identityBytesSent > 0) {
|
||||||
|
nodeList->sendPacketList(std::move(identityPacketList), *destinationNode);
|
||||||
|
}
|
||||||
|
|
||||||
// record the number of avatars held back this frame
|
// record the number of avatars held back this frame
|
||||||
nodeData->recordNumOtherAvatarStarves(numAvatarsHeldBack);
|
nodeData->recordNumOtherAvatarStarves(numAvatarsHeldBack);
|
||||||
nodeData->recordNumOtherAvatarSkips(numAvatarsWithSkippedFrames);
|
nodeData->recordNumOtherAvatarSkips(numAvatarsWithSkippedFrames);
|
||||||
|
@ -599,20 +579,20 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
|
||||||
// so we always send a full update for this avatar
|
// so we always send a full update for this avatar
|
||||||
|
|
||||||
quint64 start = usecTimestampNow();
|
quint64 start = usecTimestampNow();
|
||||||
AvatarDataPacket::HasFlags flagsOut;
|
AvatarDataPacket::SendStatus sendStatus;
|
||||||
|
|
||||||
QVector<JointData> emptyLastJointSendData { otherAvatar->getJointCount() };
|
QVector<JointData> emptyLastJointSendData { otherAvatar->getJointCount() };
|
||||||
|
|
||||||
QByteArray avatarByteArray = otherAvatar->toByteArray(AvatarData::SendAllData, 0, emptyLastJointSendData,
|
QByteArray avatarByteArray = otherAvatar->toByteArray(AvatarData::SendAllData, 0, emptyLastJointSendData,
|
||||||
flagsOut, false, false, glm::vec3(0), nullptr);
|
sendStatus, false, false, glm::vec3(0), nullptr, 0);
|
||||||
quint64 end = usecTimestampNow();
|
quint64 end = usecTimestampNow();
|
||||||
_stats.toByteArrayElapsedTime += (end - start);
|
_stats.toByteArrayElapsedTime += (end - start);
|
||||||
|
|
||||||
auto lastBroadcastTime = nodeData->getLastBroadcastTime(agentNode->getUUID());
|
auto lastBroadcastTime = nodeData->getLastBroadcastTime(agentNode->getLocalID());
|
||||||
if (lastBroadcastTime <= agentNodeData->getIdentityChangeTimestamp()
|
if (lastBroadcastTime <= agentNodeData->getIdentityChangeTimestamp()
|
||||||
|| (start - lastBroadcastTime) >= REBROADCAST_IDENTITY_TO_DOWNSTREAM_EVERY_US) {
|
|| (start - lastBroadcastTime) >= REBROADCAST_IDENTITY_TO_DOWNSTREAM_EVERY_US) {
|
||||||
sendReplicatedIdentityPacket(*agentNode, agentNodeData, *node);
|
sendReplicatedIdentityPacket(*agentNode, agentNodeData, *node);
|
||||||
nodeData->setLastBroadcastTime(agentNode->getUUID(), start);
|
nodeData->setLastBroadcastTime(agentNode->getLocalID(), start);
|
||||||
}
|
}
|
||||||
|
|
||||||
// figure out how large our avatar byte array can be to fit in the packet list
|
// figure out how large our avatar byte array can be to fit in the packet list
|
||||||
|
@ -630,14 +610,14 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
|
||||||
<< "-" << avatarByteArray.size() << "bytes";
|
<< "-" << avatarByteArray.size() << "bytes";
|
||||||
|
|
||||||
avatarByteArray = otherAvatar->toByteArray(AvatarData::SendAllData, 0, emptyLastJointSendData,
|
avatarByteArray = otherAvatar->toByteArray(AvatarData::SendAllData, 0, emptyLastJointSendData,
|
||||||
flagsOut, true, false, glm::vec3(0), nullptr);
|
sendStatus, true, false, glm::vec3(0), nullptr, 0);
|
||||||
|
|
||||||
if (avatarByteArray.size() > maxAvatarByteArraySize) {
|
if (avatarByteArray.size() > maxAvatarByteArraySize) {
|
||||||
qCWarning(avatars) << "Replicated avatar data without facial data still too large for"
|
qCWarning(avatars) << "Replicated avatar data without facial data still too large for"
|
||||||
<< otherAvatar->getSessionUUID() << "-" << avatarByteArray.size() << "bytes";
|
<< otherAvatar->getSessionUUID() << "-" << avatarByteArray.size() << "bytes";
|
||||||
|
|
||||||
avatarByteArray = otherAvatar->toByteArray(AvatarData::MinimumData, 0, emptyLastJointSendData,
|
avatarByteArray = otherAvatar->toByteArray(AvatarData::MinimumData, 0, emptyLastJointSendData,
|
||||||
flagsOut, true, false, glm::vec3(0), nullptr);
|
sendStatus, true, false, glm::vec3(0), nullptr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,7 +626,7 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
|
||||||
nodeData->incrementNumAvatarsSentLastFrame();
|
nodeData->incrementNumAvatarsSentLastFrame();
|
||||||
|
|
||||||
// set the last sent sequence number for this sender on the receiver
|
// set the last sent sequence number for this sender on the receiver
|
||||||
nodeData->setLastBroadcastSequenceNumber(agentNode->getUUID(),
|
nodeData->setLastBroadcastSequenceNumber(agentNode->getLocalID(),
|
||||||
agentNodeData->getLastReceivedSequenceNumber());
|
agentNodeData->getLastReceivedSequenceNumber());
|
||||||
|
|
||||||
// increment the number of avatars sent to this reciever
|
// increment the number of avatars sent to this reciever
|
||||||
|
|
|
@ -101,7 +101,7 @@ public:
|
||||||
void harvestStats(AvatarMixerSlaveStats& stats);
|
void harvestStats(AvatarMixerSlaveStats& stats);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode);
|
int sendIdentityPacket(NLPacketList& packet, const AvatarMixerClientData* nodeData, const Node& destinationNode);
|
||||||
int sendReplicatedIdentityPacket(const Node& agentNode, const AvatarMixerClientData* nodeData, const Node& destinationNode);
|
int sendReplicatedIdentityPacket(const Node& agentNode, const AvatarMixerClientData* nodeData, const Node& destinationNode);
|
||||||
|
|
||||||
qint64 addChangedTraitsToBulkPacket(AvatarMixerClientData* listeningNodeData,
|
qint64 addChangedTraitsToBulkPacket(AvatarMixerClientData* listeningNodeData,
|
||||||
|
|
|
@ -69,10 +69,10 @@ void ScriptableAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||||
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static AnimPose composeAnimPose(const FBXJoint& fbxJoint, const glm::quat rotation, const glm::vec3 translation) {
|
static AnimPose composeAnimPose(const HFMJoint& joint, const glm::quat rotation, const glm::vec3 translation) {
|
||||||
glm::mat4 translationMat = glm::translate(translation);
|
glm::mat4 translationMat = glm::translate(translation);
|
||||||
glm::mat4 rotationMat = glm::mat4_cast(fbxJoint.preRotation * rotation * fbxJoint.postRotation);
|
glm::mat4 rotationMat = glm::mat4_cast(joint.preRotation * rotation * joint.postRotation);
|
||||||
glm::mat4 finalMat = translationMat * fbxJoint.preTransform * rotationMat * fbxJoint.postTransform;
|
glm::mat4 finalMat = translationMat * joint.preTransform * rotationMat * joint.postTransform;
|
||||||
return AnimPose(finalMat);
|
return AnimPose(finalMat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ void ScriptableAvatar::update(float deltatime) {
|
||||||
}
|
}
|
||||||
_animationDetails.currentFrame = currentFrame;
|
_animationDetails.currentFrame = currentFrame;
|
||||||
|
|
||||||
const QVector<FBXJoint>& modelJoints = _bind->getGeometry().joints;
|
const QVector<HFMJoint>& modelJoints = _bind->getGeometry().joints;
|
||||||
QStringList animationJointNames = _animation->getJointNames();
|
QStringList animationJointNames = _animation->getJointNames();
|
||||||
|
|
||||||
const int nJoints = modelJoints.size();
|
const int nJoints = modelJoints.size();
|
||||||
|
@ -102,8 +102,8 @@ void ScriptableAvatar::update(float deltatime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const int frameCount = _animation->getFrames().size();
|
const int frameCount = _animation->getFrames().size();
|
||||||
const FBXAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
|
const HFMAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
|
||||||
const FBXAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
|
const HFMAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
|
||||||
const float frameFraction = glm::fract(currentFrame);
|
const float frameFraction = glm::fract(currentFrame);
|
||||||
std::vector<AnimPose> poses = _animSkeleton->getRelativeDefaultPoses();
|
std::vector<AnimPose> poses = _animSkeleton->getRelativeDefaultPoses();
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,10 @@ if (NOT "${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||||
message( FATAL_ERROR "Only 64 bit builds supported." )
|
message( FATAL_ERROR "Only 64 bit builds supported." )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (USE_CCACHE OR "$ENV{USE_CCACHE}")
|
||||||
|
configure_ccache()
|
||||||
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)
|
add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)
|
||||||
|
|
||||||
|
|
42
cmake/externals/glslang/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
set(EXTERNAL_NAME glslang)
|
||||||
|
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||||
|
|
||||||
|
include(ExternalProject)
|
||||||
|
|
||||||
|
ExternalProject_Add(
|
||||||
|
${EXTERNAL_NAME}
|
||||||
|
URL https://github.com/KhronosGroup/glslang/archive/7.8.2853.zip
|
||||||
|
URL_MD5 4f93e3818528176c622c137fba05cbf8
|
||||||
|
CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>-$<CONFIG>
|
||||||
|
LOG_DOWNLOAD 1
|
||||||
|
LOG_CONFIGURE 1
|
||||||
|
LOG_BUILD 1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Hide this external target (for ide users)
|
||||||
|
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||||
|
|
||||||
|
# includes
|
||||||
|
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||||
|
set(SUFFIXED_INSTALL_DIR "${INSTALL_DIR}-$<CONFIG>")
|
||||||
|
|
||||||
|
list(APPEND INCLUDE_DIRS ${SUFFIXED_INSTALL_DIR}/include)
|
||||||
|
#list(APPEND INCLUDE_DIRS ${INSTALL_DIR}/include)
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INCLUDE_DIRS} CACHE PATH "List of glslang include directories")
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${${EXTERNAL_NAME_UPPER}_INCLUDE_DIR} CACHE PATH "List of glslang include directories")
|
||||||
|
|
||||||
|
|
||||||
|
set(LIB_DIR ${SUFFIXED_INSTALL_DIR}/lib)
|
||||||
|
list(APPEND LIB_NAMES glslang HLSL OGLCompiler OSDependent SPIRV SPVRemapper)
|
||||||
|
include(SelectLibraryConfigurations)
|
||||||
|
|
||||||
|
foreach(BASE_LIB ${LIB_NAMES})
|
||||||
|
string(TOUPPER ${BASE_LIB} BASE_LIB_UPPER)
|
||||||
|
list(APPEND ${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE "${LIB_DIR}/${BASE_LIB}.lib")
|
||||||
|
list(APPEND ${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "${LIB_DIR}/${BASE_LIB}d.lib")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
select_library_configurations(${EXTERNAL_NAME_UPPER})
|
||||||
|
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_LIBRARY ${${EXTERNAL_NAME_UPPER}_LIBRARY} CACHE FILEPATH "Location of glslang libraries")
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Location of glslang libraries")
|
|
@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content)
|
||||||
|
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
${EXTERNAL_NAME}
|
${EXTERNAL_NAME}
|
||||||
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC73.zip
|
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC75.zip
|
||||||
URL_MD5 0c5edfb63cafb042311d3cf25261fbf2
|
URL_MD5 b4225d058952e17976ac228330ce8d51
|
||||||
CONFIGURE_COMMAND ""
|
CONFIGURE_COMMAND ""
|
||||||
BUILD_COMMAND ""
|
BUILD_COMMAND ""
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
|
|
34
cmake/externals/spirv_binaries/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
set(EXTERNAL_NAME spirv_binaries)
|
||||||
|
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||||
|
|
||||||
|
include(ExternalProject)
|
||||||
|
if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/vulkan/vulkansdk-win32-1.1.82.1.tar.gz)
|
||||||
|
set(DOWNLOAD_MD5 3a83ef490bce248b1a4d6726a3e5893e)
|
||||||
|
set(BIN_DIR "Bin")
|
||||||
|
elseif (CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
|
set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/vulkan/vulkansdk-macos-1.1.82.1.tar.gz)
|
||||||
|
set(DOWNLOAD_MD5 a57d37275b2c5db023ba8e84a63461ff)
|
||||||
|
set(BIN_DIR "macOS/bin")
|
||||||
|
else ()
|
||||||
|
set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/vulkan/vulkansdk-linux-x86_64-1.1.82.1.tar.gz)
|
||||||
|
set(DOWNLOAD_MD5 5a7c9eeda8cee6b36724da7f7cbe5ec6)
|
||||||
|
set(BIN_DIR "x86_64/bin")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
ExternalProject_Add(
|
||||||
|
${EXTERNAL_NAME}
|
||||||
|
URL ${DOWNLOAD_URL}
|
||||||
|
URL_MD5 ${DOWNLOAD_MD5}
|
||||||
|
BUILD_COMMAND ""
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
LOG_DOWNLOAD ON
|
||||||
|
)
|
||||||
|
|
||||||
|
# Hide this external target (for ide users)
|
||||||
|
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||||
|
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||||
|
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_DIR "${SOURCE_DIR}/${BIN_DIR}" CACHE FILEPATH "SPIRV binary tools location")
|
||||||
|
|
35
cmake/externals/spirv_cross/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
set(EXTERNAL_NAME spirv_cross)
|
||||||
|
|
||||||
|
include(ExternalProject)
|
||||||
|
ExternalProject_Add(
|
||||||
|
${EXTERNAL_NAME}
|
||||||
|
URL https://github.com/KhronosGroup/SPIRV-Cross/archive/2018-08-07.zip
|
||||||
|
URL_MD5 11198e4dc6a815ffbdb7a0a56d2d9261
|
||||||
|
CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>-$<CONFIG> ${EXTRA_CMAKE_FLAGS}
|
||||||
|
LOG_DOWNLOAD 1
|
||||||
|
LOG_CONFIGURE 1
|
||||||
|
LOG_BUILD 1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Hide this external target (for ide users)
|
||||||
|
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||||
|
|
||||||
|
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||||
|
set(SUFFIXED_INSTALL_DIR "${INSTALL_DIR}-$<CONFIG>")
|
||||||
|
|
||||||
|
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||||
|
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SUFFIXED_INSTALL_DIR}/include CACHE PATH "List of Draco include directories")
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
set(LIB_PREFIX "lib")
|
||||||
|
set(LIB_EXT "a")
|
||||||
|
elseif (WIN32)
|
||||||
|
set(LIB_EXT "lib")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
foreach(lib glsl msl cpp hlsl reflect util core)
|
||||||
|
list(APPEND ${EXTERNAL_NAME_UPPER}_LIBRARIES ${SUFFIXED_INSTALL_DIR}/lib/spirv-cross-${lib}.${LIB_EXT})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Path to SPIRV-Cross libraries")
|
18
cmake/externals/spirv_headers/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
set(EXTERNAL_NAME spirv_headers)
|
||||||
|
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||||
|
|
||||||
|
include(ExternalProject)
|
||||||
|
ExternalProject_Add(
|
||||||
|
${EXTERNAL_NAME}
|
||||||
|
URL https://github.com/KhronosGroup/SPIRV-Headers/archive/2c512180ca03b5d4f56283efc85745775b45fdc4.zip
|
||||||
|
URL_MD5 83e652221b5f21d5fdb61c45f5b4d9f9
|
||||||
|
CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> ${EXTRA_CMAKE_FLAGS}
|
||||||
|
LOG_DOWNLOAD 1
|
||||||
|
LOG_CONFIGURE 1
|
||||||
|
LOG_BUILD 1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Hide this external target (for ide users)
|
||||||
|
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||||
|
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_ROOT ${INSTALL_DIR} CACHE PATH "List of include directories")
|
33
cmake/externals/spirv_tools/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
set(EXTERNAL_NAME spirv_tools)
|
||||||
|
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||||
|
|
||||||
|
include(ExternalProject)
|
||||||
|
ExternalProject_Add(
|
||||||
|
${EXTERNAL_NAME}
|
||||||
|
URL https://github.com/KhronosGroup/SPIRV-Tools/archive/v2018.4.zip
|
||||||
|
URL_MD5 7a7c69cf6ff0318910b4bfbdf30bcfc9
|
||||||
|
CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DSPIRV-Headers_SOURCE_DIR=${SPIRV_HEADERS_ROOT} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>-$<CONFIG> ${EXTRA_CMAKE_FLAGS}
|
||||||
|
LOG_DOWNLOAD 1
|
||||||
|
LOG_CONFIGURE 1
|
||||||
|
LOG_BUILD 1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Hide this external target (for ide users)
|
||||||
|
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||||
|
|
||||||
|
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||||
|
set(SUFFIXED_INSTALL_DIR "${INSTALL_DIR}-$<CONFIG>")
|
||||||
|
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SUFFIXED_INSTALL_DIR}/include CACHE PATH "List of SPIRV-Tools include directories")
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
set(LIB_PREFIX "lib")
|
||||||
|
set(LIB_EXT "a")
|
||||||
|
elseif (WIN32)
|
||||||
|
set(LIB_EXT "lib")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
list(APPEND ${EXTERNAL_NAME_UPPER}_LIBRARIES ${SUFFIXED_INSTALL_DIR}/lib/SPIRV-Tools-opt.${LIB_EXT})
|
||||||
|
list(APPEND ${EXTERNAL_NAME_UPPER}_LIBRARIES ${SUFFIXED_INSTALL_DIR}/lib/SPIRV-Tools-link.${LIB_EXT})
|
||||||
|
list(APPEND ${EXTERNAL_NAME_UPPER}_LIBRARIES ${SUFFIXED_INSTALL_DIR}/lib/SPIRV-Tools.${LIB_EXT})
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Path to SPIRV-Tool libraries")
|
|
@ -10,6 +10,10 @@ if (POLICY CMP0042)
|
||||||
cmake_policy(SET CMP0042 NEW)
|
cmake_policy(SET CMP0042 NEW)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if (POLICY CMP0074)
|
||||||
|
cmake_policy(SET CMP0074 OLD)
|
||||||
|
endif ()
|
||||||
|
|
||||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets")
|
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets")
|
||||||
# Hide automoc folders (for IDEs)
|
# Hide automoc folders (for IDEs)
|
||||||
|
|
|
@ -8,34 +8,132 @@
|
||||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# FIXME use the built tools
|
||||||
|
|
||||||
|
macro(AUTOSCRIBE_APPEND_QRC)
|
||||||
|
string(CONCAT SHADER_QRC "${SHADER_QRC}" "<file alias=\"${ARGV0}\">${ARGV1}</file>\n")
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
set(VULKAN_DIR $ENV{VULKAN_SDK})
|
||||||
|
set(GLSLANG_EXEC "${VULKAN_DIR}/Bin/glslangValidator.exe")
|
||||||
|
set(SPIRV_CROSS_EXEC "${VULKAN_DIR}/Bin/spirv-cross.exe")
|
||||||
|
set(SPIRV_OPT_EXEC "${VULKAN_DIR}/Bin/spirv-opt.exe")
|
||||||
|
set(GLSLC_EXEC "${VULKAN_DIR}/Bin/glslc.exe")
|
||||||
|
set(SCRIBE_EXEC "D:/scribe.exe")
|
||||||
|
|
||||||
|
macro(AUTOSCRIBE_PLATFORM_SHADER)
|
||||||
|
set(AUTOSCRIBE_PLATFORM_PATH "${ARGV0}")
|
||||||
|
string(REGEX MATCH "([0-9]+(es)?)(/stereo)?" PLATFORM_PATH_REGEX ${AUTOSCRIBE_PLATFORM_PATH})
|
||||||
|
set(AUTOSCRIBE_DIALECT "${CMAKE_MATCH_1}")
|
||||||
|
if (CMAKE_MATCH_3)
|
||||||
|
set(AUTOSCRIBE_VARIANT "stereo")
|
||||||
|
else()
|
||||||
|
set(AUTOSCRIBE_VARIANT "mono")
|
||||||
|
endif()
|
||||||
|
string(REGEX REPLACE "/" "\\\\" SOURCE_GROUP_PATH ${AUTOSCRIBE_PLATFORM_PATH})
|
||||||
|
set(SOURCE_GROUP_PATH "${SHADER_LIB}\\${SOURCE_GROUP_PATH}")
|
||||||
|
set(AUTOSCRIBE_DIALECT_HEADER "${AUTOSCRIBE_HEADER_DIR}/${AUTOSCRIBE_DIALECT}/header.glsl")
|
||||||
|
set(AUTOSCRIBE_VARIANT_HEADER "${AUTOSCRIBE_HEADER_DIR}/${AUTOSCRIBE_VARIANT}.glsl")
|
||||||
|
|
||||||
|
set(AUTOSCRIBE_OUTPUT_FILE "${SHADERS_DIR}/${SHADER_LIB}/${AUTOSCRIBE_PLATFORM_PATH}/${SHADER_NAME}.${SHADER_TYPE}")
|
||||||
|
AUTOSCRIBE_APPEND_QRC("${SHADER_COUNT}/${AUTOSCRIBE_PLATFORM_PATH}/scribe" "${AUTOSCRIBE_OUTPUT_FILE}")
|
||||||
|
source_group(${SOURCE_GROUP_PATH} FILES ${AUTOSCRIBE_OUTPUT_FILE})
|
||||||
|
set_property(SOURCE ${AUTOSCRIBE_OUTPUT_FILE} PROPERTY SKIP_AUTOMOC ON)
|
||||||
|
list(APPEND SCRIBED_SHADERS ${AUTOSCRIBE_OUTPUT_FILE})
|
||||||
|
|
||||||
|
set(AUTOSCRIBE_SPIRV_FILE "${AUTOSCRIBE_OUTPUT_FILE}.spv")
|
||||||
|
# don't add unoptimized spirv to the QRC
|
||||||
|
#AUTOSCRIBE_APPEND_QRC("${SHADER_COUNT}/${AUTOSCRIBE_PLATFORM_PATH}/spirv_unopt" "${AUTOSCRIBE_SPIRV_FILE}")
|
||||||
|
source_group(${SOURCE_GROUP_PATH} FILES ${AUTOSCRIBE_SPIRV_FILE})
|
||||||
|
set_property(SOURCE ${AUTOSCRIBE_SPIRV_FILE} PROPERTY SKIP_AUTOMOC ON)
|
||||||
|
list(APPEND SPIRV_SHADERS ${AUTOSCRIBE_SPIRV_FILE})
|
||||||
|
|
||||||
|
set(AUTOSCRIBE_SPIRV_OPT_FILE "${AUTOSCRIBE_OUTPUT_FILE}.opt.spv")
|
||||||
|
AUTOSCRIBE_APPEND_QRC("${SHADER_COUNT}/${AUTOSCRIBE_PLATFORM_PATH}/spirv" "${AUTOSCRIBE_SPIRV_OPT_FILE}")
|
||||||
|
source_group(${SOURCE_GROUP_PATH} FILES ${AUTOSCRIBE_SPIRV_OPT_FILE})
|
||||||
|
set_property(SOURCE ${AUTOSCRIBE_SPIRV_OPT_FILE} PROPERTY SKIP_AUTOMOC ON)
|
||||||
|
list(APPEND SPIRV_SHADERS ${AUTOSCRIBE_SPIRV_OPT_FILE})
|
||||||
|
|
||||||
|
set(AUTOSCRIBE_SPIRV_GLSL_FILE "${AUTOSCRIBE_OUTPUT_FILE}.glsl")
|
||||||
|
AUTOSCRIBE_APPEND_QRC("${SHADER_COUNT}/${AUTOSCRIBE_PLATFORM_PATH}/glsl" "${AUTOSCRIBE_SPIRV_GLSL_FILE}")
|
||||||
|
source_group(${SOURCE_GROUP_PATH} FILES ${AUTOSCRIBE_SPIRV_GLSL_FILE})
|
||||||
|
set_property(SOURCE ${AUTOSCRIBE_SPIRV_GLSL_FILE} PROPERTY SKIP_AUTOMOC ON)
|
||||||
|
list(APPEND SPIRV_SHADERS ${AUTOSCRIBE_SPIRV_GLSL_FILE})
|
||||||
|
|
||||||
|
set(AUTOSCRIBE_SPIRV_JSON_FILE "${AUTOSCRIBE_OUTPUT_FILE}.json")
|
||||||
|
AUTOSCRIBE_APPEND_QRC("${SHADER_COUNT}/${AUTOSCRIBE_PLATFORM_PATH}/json" "${AUTOSCRIBE_SPIRV_JSON_FILE}")
|
||||||
|
source_group(${SOURCE_GROUP_PATH} FILES ${AUTOSCRIBE_SPIRV_JSON_FILE})
|
||||||
|
set_property(SOURCE ${AUTOSCRIBE_SPIRV_JSON_FILE} PROPERTY SKIP_AUTOMOC ON)
|
||||||
|
list(APPEND REFLECTED_SHADERS ${AUTOSCRIBE_SPIRV_JSON_FILE})
|
||||||
|
|
||||||
|
unset(SHADER_GEN_LINE)
|
||||||
|
list(APPEND SHADER_GEN_LINE ${AUTOSCRIBE_DIALECT})
|
||||||
|
list(APPEND SHADER_GEN_LINE ${AUTOSCRIBE_VARIANT})
|
||||||
|
file(RELATIVE_PATH TEMP_PATH ${CMAKE_SOURCE_DIR} ${SHADER_FILE})
|
||||||
|
list(APPEND SHADER_GEN_LINE ${TEMP_PATH})
|
||||||
|
file(RELATIVE_PATH TEMP_PATH ${CMAKE_SOURCE_DIR} ${AUTOSCRIBE_OUTPUT_FILE})
|
||||||
|
list(APPEND SHADER_GEN_LINE ${TEMP_PATH})
|
||||||
|
list(APPEND SHADER_GEN_LINE ${AUTOSCRIBE_SHADER_SEEN_LIBS})
|
||||||
|
string(CONCAT AUTOSCRIBE_SHADERGEN_COMMANDS "${AUTOSCRIBE_SHADERGEN_COMMANDS}" "${SHADER_GEN_LINE}\n")
|
||||||
|
|
||||||
|
# # FIXME need better mechanism for determining the include files
|
||||||
|
# add_custom_command(
|
||||||
|
# OUTPUT ${AUTOSCRIBE_OUTPUT_FILE}
|
||||||
|
# COMMAND ${SCRIBE_COMMAND} ${SHADER_FILE} ${SCRIBE_ARGS} -o ${AUTOSCRIBE_OUTPUT_FILE} -h ${AUTOSCRIBE_DIALECT_HEADER} -h ${AUTOSCRIBE_VARIANT_HEADER}
|
||||||
|
# DEPENDS ${SCRIBE_COMMAND} ${SHADER_FILE} ${AUTOSCRIBE_DIALECT_HEADER} ${AUTOSCRIBE_VARIANT_HEADER})
|
||||||
|
|
||||||
|
# # Generate the spirv file
|
||||||
|
# add_custom_command(
|
||||||
|
# OUTPUT ${AUTOSCRIBE_SPIRV_FILE}
|
||||||
|
# COMMAND ${GLSLANG_EXEC} -V110 -o ${AUTOSCRIBE_SPIRV_FILE} ${AUTOSCRIBE_OUTPUT_FILE}
|
||||||
|
# DEPENDS ${AUTOSCRIBE_OUTPUT_FILE} ${GLSLANG_EXEC})
|
||||||
|
|
||||||
|
# # Generate the optimized spirv file
|
||||||
|
# add_custom_command(
|
||||||
|
# OUTPUT ${AUTOSCRIBE_SPIRV_OPT_FILE}
|
||||||
|
# COMMAND ${SPIRV_OPT_EXEC} -O ${AUTOSCRIBE_SPIRV_FILE} -o ${AUTOSCRIBE_SPIRV_OPT_FILE}
|
||||||
|
# DEPENDS ${AUTOSCRIBE_SPIRV_FILE} ${SPIRV_OPT_EXEC})
|
||||||
|
|
||||||
|
# # Generate the optimized GLSL file
|
||||||
|
# add_custom_command(
|
||||||
|
# OUTPUT ${AUTOSCRIBE_SPIRV_GLSL_FILE}
|
||||||
|
# COMMAND ${SPIRV_CROSS_EXEC} ${SPIRV_CROSS_ARGS} ${AUTOSCRIBE_SPIRV_OPT_FILE} --output ${AUTOSCRIBE_SPIRV_GLSL_FILE}
|
||||||
|
# DEPENDS ${AUTOSCRIBE_SPIRV_OPT_FILE} ${SPIRV_CROSS_EXEC})
|
||||||
|
|
||||||
|
# # Generate the optimized spirv file
|
||||||
|
# add_custom_command(
|
||||||
|
# OUTPUT ${AUTOSCRIBE_SPIRV_JSON_FILE}
|
||||||
|
# COMMAND ${SPIRV_CROSS_EXEC} --reflect json ${AUTOSCRIBE_SPIRV_OPT_FILE} --output ${AUTOSCRIBE_SPIRV_JSON_FILE}
|
||||||
|
# DEPENDS ${AUTOSCRIBE_SPIRV_OPT_FILE} ${SPIRV_CROSS_EXEC})
|
||||||
|
endmacro()
|
||||||
|
|
||||||
macro(AUTOSCRIBE_SHADER)
|
macro(AUTOSCRIBE_SHADER)
|
||||||
|
#
|
||||||
|
# Set the include paths
|
||||||
|
#
|
||||||
|
# FIXME base the include paths off of output from the scribe tool,
|
||||||
|
# instead of treating every previously seen shader as a possible header
|
||||||
unset(SHADER_INCLUDE_FILES)
|
unset(SHADER_INCLUDE_FILES)
|
||||||
# Grab include files
|
|
||||||
foreach(includeFile ${ARGN})
|
foreach(includeFile ${ARGN})
|
||||||
list(APPEND SHADER_INCLUDE_FILES ${includeFile})
|
list(APPEND SHADER_INCLUDE_FILES ${includeFile})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
foreach(SHADER_INCLUDE ${SHADER_INCLUDE_FILES})
|
foreach(SHADER_INCLUDE ${SHADER_INCLUDE_FILES})
|
||||||
get_filename_component(INCLUDE_DIR ${SHADER_INCLUDE} PATH)
|
get_filename_component(INCLUDE_DIR ${SHADER_INCLUDE} PATH)
|
||||||
list(APPEND SHADER_INCLUDES_PATHS ${INCLUDE_DIR})
|
list(APPEND SHADER_INCLUDES_PATHS ${INCLUDE_DIR})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
list(REMOVE_DUPLICATES SHADER_INCLUDES_PATHS)
|
|
||||||
#Extract the unique include shader paths
|
|
||||||
set(INCLUDES ${HIFI_LIBRARIES_SHADER_INCLUDE_FILES})
|
set(INCLUDES ${HIFI_LIBRARIES_SHADER_INCLUDE_FILES})
|
||||||
foreach(EXTRA_SHADER_INCLUDE ${INCLUDES})
|
foreach(EXTRA_SHADER_INCLUDE ${INCLUDES})
|
||||||
list(APPEND SHADER_INCLUDES_PATHS ${EXTRA_SHADER_INCLUDE})
|
list(APPEND SHADER_INCLUDES_PATHS ${EXTRA_SHADER_INCLUDE})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
list(REMOVE_DUPLICATES SHADER_INCLUDES_PATHS)
|
list(REMOVE_DUPLICATES SHADER_INCLUDES_PATHS)
|
||||||
#message(ready for includes ${SHADER_INCLUDES_PATHS})
|
unset(SCRIBE_INCLUDES)
|
||||||
|
|
||||||
# make the scribe include arguments
|
|
||||||
set(SCRIBE_INCLUDES)
|
|
||||||
foreach(INCLUDE_PATH ${SHADER_INCLUDES_PATHS})
|
foreach(INCLUDE_PATH ${SHADER_INCLUDES_PATHS})
|
||||||
set(SCRIBE_INCLUDES ${SCRIBE_INCLUDES} -I ${INCLUDE_PATH}/)
|
set(SCRIBE_INCLUDES ${SCRIBE_INCLUDES} -I ${INCLUDE_PATH}/)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Figure out the various output names
|
||||||
|
#
|
||||||
# Define the final name of the generated shader file
|
# Define the final name of the generated shader file
|
||||||
get_filename_component(SHADER_NAME ${SHADER_FILE} NAME_WE)
|
get_filename_component(SHADER_NAME ${SHADER_FILE} NAME_WE)
|
||||||
get_filename_component(SHADER_EXT ${SHADER_FILE} EXT)
|
get_filename_component(SHADER_EXT ${SHADER_FILE} EXT)
|
||||||
|
@ -46,38 +144,36 @@ macro(AUTOSCRIBE_SHADER)
|
||||||
elseif(${SHADER_EXT} STREQUAL .slg)
|
elseif(${SHADER_EXT} STREQUAL .slg)
|
||||||
set(SHADER_TYPE geom)
|
set(SHADER_TYPE geom)
|
||||||
endif()
|
endif()
|
||||||
file(MAKE_DIRECTORY "${SHADERS_DIR}/${SHADER_LIB}")
|
|
||||||
set(SHADER_TARGET "${SHADERS_DIR}/${SHADER_LIB}/${SHADER_NAME}.${SHADER_TYPE}")
|
|
||||||
file(TO_CMAKE_PATH "${SHADER_TARGET}" COMPILED_SHADER)
|
|
||||||
set(REFLECTED_SHADER "${COMPILED_SHADER}.json")
|
|
||||||
|
|
||||||
set(SCRIBE_ARGS -T ${SHADER_TYPE} -D GLPROFILE ${GLPROFILE} ${SCRIBE_INCLUDES} -o ${SHADER_TARGET} ${SHADER_FILE})
|
set(SCRIBE_ARGS -D GLPROFILE ${GLPROFILE} -T ${SHADER_TYPE} ${SCRIBE_INCLUDES} )
|
||||||
|
|
||||||
# Generate the frag/vert file
|
# SHADER_SCRIBED -> the output of scribe
|
||||||
add_custom_command(
|
set(SHADER_SCRIBED "${SHADERS_DIR}/${SHADER_LIB}/${SHADER_NAME}.${SHADER_TYPE}")
|
||||||
OUTPUT ${SHADER_TARGET}
|
|
||||||
COMMAND ${SCRIBE_COMMAND} ${SCRIBE_ARGS}
|
|
||||||
DEPENDS ${SHADER_FILE} ${SCRIBE_COMMAND} ${SHADER_INCLUDE_FILES})
|
|
||||||
|
|
||||||
# Generate the json reflection
|
# SHADER_NAME_FILE -> a file containing the shader name and extension (useful for debugging and for
|
||||||
# FIXME move to spirv-cross for this task after we have spirv compatible shaders
|
# determining the type of shader from the filename)
|
||||||
add_custom_command(
|
set(SHADER_NAME_FILE "${SHADER_SCRIBED}.name")
|
||||||
OUTPUT ${REFLECTED_SHADER}
|
file(TO_CMAKE_PATH "${SHADER_SCRIBED}" SHADER_SCRIBED)
|
||||||
COMMAND ${SHREFLECT_COMMAND} ${COMPILED_SHADER}
|
file(WRITE "${SHADER_SCRIBED}.name" "${SHADER_NAME}.${SHADER_TYPE}")
|
||||||
DEPENDS ${SHREFLECT_DEPENDENCY} ${COMPILED_SHADER})
|
AUTOSCRIBE_APPEND_QRC("${SHADER_COUNT}/name" "${SHADER_NAME_FILE}")
|
||||||
|
|
||||||
#output the generated file name
|
if (USE_GLES)
|
||||||
source_group("Compiled/${SHADER_LIB}" FILES ${COMPILED_SHADER})
|
set(SPIRV_CROSS_ARGS --version 310es)
|
||||||
set_property(SOURCE ${COMPILED_SHADER} PROPERTY SKIP_AUTOMOC ON)
|
AUTOSCRIBE_PLATFORM_SHADER("310es")
|
||||||
list(APPEND COMPILED_SHADERS ${COMPILED_SHADER})
|
AUTOSCRIBE_PLATFORM_SHADER("310es/stereo")
|
||||||
|
else()
|
||||||
|
set(SPIRV_CROSS_ARGS --version 410 --no-420pack-extension)
|
||||||
|
AUTOSCRIBE_PLATFORM_SHADER("410")
|
||||||
|
AUTOSCRIBE_PLATFORM_SHADER("410/stereo")
|
||||||
|
if (NOT APPLE)
|
||||||
|
set(SPIRV_CROSS_ARGS --version 450)
|
||||||
|
AUTOSCRIBE_PLATFORM_SHADER("450")
|
||||||
|
AUTOSCRIBE_PLATFORM_SHADER("450/stereo")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
source_group("Reflected/${SHADER_LIB}" FILES ${REFLECTED_SHADER})
|
|
||||||
list(APPEND REFLECTED_SHADERS ${REFLECTED_SHADER})
|
|
||||||
|
|
||||||
string(CONCAT SHADER_QRC "${SHADER_QRC}" "<file alias=\"${SHADER_COUNT}\">${COMPILED_SHADER}</file>\n")
|
|
||||||
string(CONCAT SHADER_QRC "${SHADER_QRC}" "<file alias=\"${SHADER_COUNT}_reflection\">${REFLECTED_SHADER}</file>\n")
|
|
||||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${SHADER_NAME} = ${SHADER_COUNT},\n")
|
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${SHADER_NAME} = ${SHADER_COUNT},\n")
|
||||||
|
string(CONCAT SHADER_SHADERS_ARRAY "${SHADER_SHADERS_ARRAY}" "${SHADER_COUNT},\n")
|
||||||
MATH(EXPR SHADER_COUNT "${SHADER_COUNT}+1")
|
MATH(EXPR SHADER_COUNT "${SHADER_COUNT}+1")
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
@ -86,6 +182,8 @@ macro(AUTOSCRIBE_SHADER_LIB)
|
||||||
message(FATAL_ERROR "AUTOSCRIBE_SHADER_LIB can only be used by the shaders library")
|
message(FATAL_ERROR "AUTOSCRIBE_SHADER_LIB can only be used by the shaders library")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
file(MAKE_DIRECTORY "${SHADERS_DIR}/${SHADER_LIB}")
|
||||||
|
|
||||||
list(APPEND HIFI_LIBRARIES_SHADER_INCLUDE_FILES "${CMAKE_SOURCE_DIR}/libraries/${SHADER_LIB}/src")
|
list(APPEND HIFI_LIBRARIES_SHADER_INCLUDE_FILES "${CMAKE_SOURCE_DIR}/libraries/${SHADER_LIB}/src")
|
||||||
string(REGEX REPLACE "[-]" "_" SHADER_NAMESPACE ${SHADER_LIB})
|
string(REGEX REPLACE "[-]" "_" SHADER_NAMESPACE ${SHADER_LIB})
|
||||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "namespace ${SHADER_NAMESPACE} {\n")
|
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "namespace ${SHADER_NAMESPACE} {\n")
|
||||||
|
@ -165,66 +263,103 @@ macro(AUTOSCRIBE_SHADER_LIB)
|
||||||
|
|
||||||
# Finish the shader enums
|
# Finish the shader enums
|
||||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "} // namespace ${SHADER_NAMESPACE}\n")
|
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "} // namespace ${SHADER_NAMESPACE}\n")
|
||||||
#file(RELATIVE_PATH RELATIVE_LIBRARY_DIR_PATH ${CMAKE_CURRENT_SOURCE_DIR} "${HIFI_LIBRARY_DIR}")
|
|
||||||
#foreach(HIFI_LIBRARY ${ARGN})
|
|
||||||
#list(APPEND HIFI_LIBRARIES_SHADER_INCLUDE_FILES ${HIFI_LIBRARY_DIR}/${HIFI_LIBRARY}/src)
|
|
||||||
#endforeach()
|
|
||||||
#endif()
|
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
macro(AUTOSCRIBE_SHADER_LIBS)
|
macro(AUTOSCRIBE_SHADER_LIBS)
|
||||||
set(SCRIBE_COMMAND scribe)
|
message(STATUS "Shader processing start")
|
||||||
set(SHREFLECT_COMMAND shreflect)
|
set(AUTOSCRIBE_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/headers)
|
||||||
set(SHREFLECT_DEPENDENCY shreflect)
|
|
||||||
|
|
||||||
# Target dependant Custom rule on the SHADER_FILE
|
|
||||||
if (ANDROID)
|
|
||||||
set(GLPROFILE LINUX_GL)
|
|
||||||
set(SCRIBE_COMMAND ${NATIVE_SCRIBE})
|
|
||||||
set(SHREFLECT_COMMAND ${NATIVE_SHREFLECT})
|
|
||||||
unset(SHREFLECT_DEPENDENCY)
|
|
||||||
else()
|
|
||||||
if (APPLE)
|
|
||||||
set(GLPROFILE MAC_GL)
|
|
||||||
elseif(UNIX)
|
|
||||||
set(GLPROFILE LINUX_GL)
|
|
||||||
else()
|
|
||||||
set(GLPROFILE PC_GL)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Start the shader IDs
|
# Start the shader IDs
|
||||||
set(SHADER_COUNT 1)
|
|
||||||
set(SHADERS_DIR "${CMAKE_CURRENT_BINARY_DIR}/shaders")
|
set(SHADERS_DIR "${CMAKE_CURRENT_BINARY_DIR}/shaders")
|
||||||
set(SHADER_ENUMS "")
|
|
||||||
file(MAKE_DIRECTORY ${SHADERS_DIR})
|
file(MAKE_DIRECTORY ${SHADERS_DIR})
|
||||||
|
set(SHADER_ENUMS "")
|
||||||
|
set(SHADER_COUNT 1)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Scribe generation & program defintiion
|
# Scribe generation & program defintiion
|
||||||
#
|
#
|
||||||
foreach(SHADER_LIB ${ARGN})
|
foreach(SHADER_LIB ${ARGN})
|
||||||
|
list(APPEND AUTOSCRIBE_SHADER_SEEN_LIBS ${SHADER_LIB})
|
||||||
AUTOSCRIBE_SHADER_LIB(${SHADER_LIB})
|
AUTOSCRIBE_SHADER_LIB(${SHADER_LIB})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# Generate the library files
|
# Generate the library files
|
||||||
configure_file(
|
configure_file(
|
||||||
ShaderEnums.cpp.in
|
ShaderEnums.cpp.in
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.cpp)
|
${CMAKE_CURRENT_BINARY_DIR}/ShaderEnums.cpp)
|
||||||
configure_file(
|
configure_file(
|
||||||
ShaderEnums.h.in
|
ShaderEnums.h.in
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.h)
|
${CMAKE_CURRENT_BINARY_DIR}/ShaderEnums.h)
|
||||||
configure_file(
|
|
||||||
shaders.qrc.in
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/shaders.qrc)
|
|
||||||
|
|
||||||
set(AUTOSCRIBE_SHADER_LIB_SRC "${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.h;${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.cpp")
|
configure_file(shaders.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/shaders.qrc)
|
||||||
set(QT_RESOURCES_FILE ${CMAKE_CURRENT_BINARY_DIR}/shaders.qrc)
|
list(APPEND QT_RESOURCES_FILE ${CMAKE_CURRENT_BINARY_DIR}/shaders.qrc)
|
||||||
|
|
||||||
|
list(APPEND AUTOSCRIBE_SHADER_HEADERS ${AUTOSCRIBE_HEADER_DIR}/mono.glsl ${AUTOSCRIBE_HEADER_DIR}/stereo.glsl)
|
||||||
|
list(APPEND AUTOSCRIBE_SHADER_HEADERS ${AUTOSCRIBE_HEADER_DIR}/450/header.glsl ${AUTOSCRIBE_HEADER_DIR}/410/header.glsl ${AUTOSCRIBE_HEADER_DIR}/310es/header.glsl)
|
||||||
|
source_group("Shader Headers" FILES ${AUTOSCRIBE_HEADER_DIR}/mono.glsl ${AUTOSCRIBE_HEADER_DIR}/stereo.glsl)
|
||||||
|
source_group("Shader Headers\\450" FILES ${AUTOSCRIBE_HEADER_DIR}/450/header.glsl)
|
||||||
|
source_group("Shader Headers\\410" FILES ${AUTOSCRIBE_HEADER_DIR}/410/header.glsl)
|
||||||
|
source_group("Shader Headers\\310es" FILES ${AUTOSCRIBE_HEADER_DIR}/310es/header.glsl)
|
||||||
|
|
||||||
|
list(APPEND AUTOSCRIBE_SHADER_LIB_SRC ${AUTOSCRIBE_SHADER_HEADERS})
|
||||||
|
list(APPEND AUTOSCRIBE_SHADER_LIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/ShaderEnums.h ${CMAKE_CURRENT_BINARY_DIR}/ShaderEnums.cpp)
|
||||||
|
|
||||||
|
# Write the shadergen command list
|
||||||
|
set(AUTOSCRIBE_SHADERGEN_COMMANDS_FILE ${CMAKE_CURRENT_BINARY_DIR}/shadergen.txt)
|
||||||
|
file(WRITE ${AUTOSCRIBE_SHADERGEN_COMMANDS_FILE} "${AUTOSCRIBE_SHADERGEN_COMMANDS}")
|
||||||
|
|
||||||
|
# grab the SPIRV binaries we require
|
||||||
|
# note we don't use the normal ADD_DEPENDENCY_EXTERNAL_PROJECTS macro because only a custom command
|
||||||
|
# depends on these, not any of our build artifacts, so there's no valid target for the add_dependencies
|
||||||
|
# call in ADD_DEPENDENCY_EXTERNAL_PROJECTS to use
|
||||||
|
add_subdirectory(${EXTERNAL_PROJECT_DIR}/spirv_binaries ${EXTERNALS_BINARY_DIR}/spirv_binaries)
|
||||||
|
|
||||||
|
target_python()
|
||||||
|
|
||||||
|
# A custom python script which will generate
|
||||||
|
if (ANDROID)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${SCRIBED_SHADERS} ${SPIRV_SHADERS} ${REFLECTED_SHADERS}
|
||||||
|
COMMENT "Generating/updating shaders"
|
||||||
|
COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_SOURCE_DIR}/tools/shadergen.py
|
||||||
|
--commands ${AUTOSCRIBE_SHADERGEN_COMMANDS_FILE}
|
||||||
|
--spirv-binaries ${SPIRV_BINARIES_DIR}
|
||||||
|
--scribe ${NATIVE_SCRIBE}
|
||||||
|
--build-dir ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
--source-dir ${CMAKE_SOURCE_DIR}
|
||||||
|
DEPENDS ${AUTOSCRIBE_SHADER_HEADERS} spirv_binaries ${CMAKE_SOURCE_DIR}/tools/shadergen.py ${ALL_SCRIBE_SHADERS})
|
||||||
|
else()
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${SCRIBED_SHADERS} ${SPIRV_SHADERS} ${REFLECTED_SHADERS}
|
||||||
|
COMMENT "Generating/updating shaders"
|
||||||
|
COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_SOURCE_DIR}/tools/shadergen.py
|
||||||
|
--commands ${AUTOSCRIBE_SHADERGEN_COMMANDS_FILE}
|
||||||
|
--spirv-binaries ${SPIRV_BINARIES_DIR}
|
||||||
|
--scribe $<TARGET_FILE:scribe>
|
||||||
|
--build-dir ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
--source-dir ${CMAKE_SOURCE_DIR}
|
||||||
|
DEPENDS ${AUTOSCRIBE_SHADER_HEADERS} scribe spirv_binaries ${CMAKE_SOURCE_DIR}/tools/shadergen.py ${ALL_SCRIBE_SHADERS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_target(shadergen DEPENDS ${SCRIBED_SHADERS} ${SPIRV_SHADERS} ${REFLECTED_SHADERS})
|
||||||
|
set_target_properties(shadergen PROPERTIES FOLDER "Shaders")
|
||||||
|
|
||||||
# Custom targets required to force generation of the shaders via scribe
|
# Custom targets required to force generation of the shaders via scribe
|
||||||
add_custom_target(scribe_shaders SOURCES ${ALL_SCRIBE_SHADERS})
|
add_custom_target(scribe_shaders SOURCES ${ALL_SCRIBE_SHADERS} ${AUTOSCRIBE_SHADER_HEADERS})
|
||||||
add_custom_target(compiled_shaders SOURCES ${COMPILED_SHADERS})
|
|
||||||
add_custom_target(reflected_shaders SOURCES ${REFLECTED_SHADERS})
|
|
||||||
set_target_properties(scribe_shaders PROPERTIES FOLDER "Shaders")
|
set_target_properties(scribe_shaders PROPERTIES FOLDER "Shaders")
|
||||||
set_target_properties(compiled_shaders PROPERTIES FOLDER "Shaders")
|
|
||||||
|
add_custom_target(scribed_shaders SOURCES ${SCRIBED_SHADERS})
|
||||||
|
set_target_properties(scribed_shaders PROPERTIES FOLDER "Shaders")
|
||||||
|
add_dependencies(scribed_shaders shadergen)
|
||||||
|
|
||||||
|
add_custom_target(spirv_shaders SOURCES ${SPIRV_SHADERS})
|
||||||
|
set_target_properties(spirv_shaders PROPERTIES FOLDER "Shaders")
|
||||||
|
add_dependencies(spirv_shaders shadergen)
|
||||||
|
|
||||||
|
add_custom_target(reflected_shaders SOURCES ${REFLECTED_SHADERS})
|
||||||
set_target_properties(reflected_shaders PROPERTIES FOLDER "Shaders")
|
set_target_properties(reflected_shaders PROPERTIES FOLDER "Shaders")
|
||||||
|
add_dependencies(reflected_shaders shadergen)
|
||||||
|
|
||||||
|
message(STATUS "Shader processing end")
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
|
||||||
|
|
45
cmake/macros/ConfigureCCache.cmake
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#
|
||||||
|
# ConfigureCCache.cmake
|
||||||
|
# cmake/macros
|
||||||
|
#
|
||||||
|
# Created by Clement Brisset on 10/10/18.
|
||||||
|
# Copyright 2018 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
|
||||||
|
#
|
||||||
|
|
||||||
|
macro(configure_ccache)
|
||||||
|
find_program(CCACHE_PROGRAM ccache)
|
||||||
|
if(CCACHE_PROGRAM)
|
||||||
|
message(STATUS "Configuring ccache")
|
||||||
|
|
||||||
|
# Set up wrapper scripts
|
||||||
|
set(C_LAUNCHER "${CCACHE_PROGRAM}")
|
||||||
|
set(CXX_LAUNCHER "${CCACHE_PROGRAM}")
|
||||||
|
|
||||||
|
set(LAUNCH_C_IN "${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/launch-c.in")
|
||||||
|
set(LAUNCH_CXX_IN "${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/launch-cxx.in")
|
||||||
|
set(LAUNCH_C "${CMAKE_BINARY_DIR}/CMakeFiles/launch-c")
|
||||||
|
set(LAUNCH_CXX "${CMAKE_BINARY_DIR}/CMakeFiles/launch-cxx")
|
||||||
|
|
||||||
|
configure_file(${LAUNCH_C_IN} ${LAUNCH_C})
|
||||||
|
configure_file(${LAUNCH_CXX_IN} ${LAUNCH_CXX})
|
||||||
|
execute_process(COMMAND chmod a+rx ${LAUNCH_C} ${LAUNCH_CXX})
|
||||||
|
|
||||||
|
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||||
|
# Set Xcode project attributes to route compilation and linking
|
||||||
|
# through our scripts
|
||||||
|
set(CMAKE_XCODE_ATTRIBUTE_CC ${LAUNCH_C})
|
||||||
|
set(CMAKE_XCODE_ATTRIBUTE_CXX ${LAUNCH_CXX})
|
||||||
|
set(CMAKE_XCODE_ATTRIBUTE_LD ${LAUNCH_C})
|
||||||
|
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS ${LAUNCH_CXX})
|
||||||
|
else()
|
||||||
|
# Support Unix Makefiles and Ninja
|
||||||
|
set(CMAKE_C_COMPILER_LAUNCHER ${LAUNCH_C})
|
||||||
|
set(CMAKE_CXX_COMPILER_LAUNCHER ${LAUNCH_CXX})
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(WARNING "Could not find ccache")
|
||||||
|
endif()
|
||||||
|
endmacro()
|
22
cmake/macros/TargetPython.cmake
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
macro(TARGET_PYTHON)
|
||||||
|
if (NOT HIFI_PYTHON_EXEC)
|
||||||
|
# Find the python interpreter
|
||||||
|
if (CAME_VERSION VERSION_LESS 3.12)
|
||||||
|
# this logic is deprecated in CMake after 3.12
|
||||||
|
# FIXME eventually we should make 3.12 the min cmake verion and just use the Python3 find_package path
|
||||||
|
set(Python_ADDITIONAL_VERSIONS 3)
|
||||||
|
find_package(PythonInterp)
|
||||||
|
set(HIFI_PYTHON_VERSION ${PYTHON_VERSION_STRING})
|
||||||
|
set(HIFI_PYTHON_EXEC ${PYTHON_EXECUTABLE})
|
||||||
|
else()
|
||||||
|
# the new hotness
|
||||||
|
find_package(Python3)
|
||||||
|
set(HIFI_PYTHON_VERSION ${Python3_VERSION})
|
||||||
|
set(HIFI_PYTHON_EXEC ${Python3_EXECUTABLE})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if ((NOT HIFI_PYTHON_EXEC) OR (HIFI_PYTHON_VERSION VERSION_LESS 3.5))
|
||||||
|
message(FATAL_ERROR "Unable to locate Python interpreter 3.5 or higher")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endmacro()
|
15
cmake/macros/TargetSPIRV.cmake
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
macro(TARGET_SPIRV)
|
||||||
|
add_dependency_external_projects(spirv_cross)
|
||||||
|
target_link_libraries(${TARGET_NAME} ${SPIRV_CROSS_LIBRARIES})
|
||||||
|
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${SPIRV_CROSS_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
# spirv-tools requires spirv-headers
|
||||||
|
add_dependency_external_projects(spirv_headers)
|
||||||
|
add_dependency_external_projects(spirv_tools)
|
||||||
|
target_link_libraries(${TARGET_NAME} ${SPIRV_TOOLS_LIBRARIES})
|
||||||
|
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${SPIRV_TOOLS_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
add_dependency_external_projects(glslang)
|
||||||
|
target_link_libraries(${TARGET_NAME} ${GLSLANG_LIBRARIES})
|
||||||
|
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${GLSLANG_INCLUDE_DIRS})
|
||||||
|
endmacro()
|
10
cmake/macros/TargetSpirvBinaries.cmake
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#
|
||||||
|
# Created by Bradley Austin Davis on 2016/02/16
|
||||||
|
#
|
||||||
|
# Distributed under the Apache License, Version 2.0.
|
||||||
|
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
#
|
||||||
|
macro(TARGET_SPIRV_BINARIES)
|
||||||
|
add_dependency_external_projects(spirv_binaries)
|
||||||
|
endmacro()
|
||||||
|
|
19
cmake/macros/TargetVulkan.cmake
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#
|
||||||
|
# Created by Bradley Austin Davis on 2016/02/16
|
||||||
|
#
|
||||||
|
# Distributed under the Apache License, Version 2.0.
|
||||||
|
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
#
|
||||||
|
macro(TARGET_VULKAN)
|
||||||
|
find_package(Vulkan)
|
||||||
|
|
||||||
|
if (Vulkan_FOUND)
|
||||||
|
add_definitions(-DHAVE_VULKAN)
|
||||||
|
target_include_directories(${TARGET_NAME} PRIVATE ${Vulkan_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(${TARGET_NAME} ${Vulkan_LIBRARIES})
|
||||||
|
|
||||||
|
add_dependency_external_projects(glslang)
|
||||||
|
target_include_directories(${TARGET_NAME} PRIVATE ${GLSLANG_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(${TARGET_NAME} ${GLSLANG_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
endmacro()
|
12
cmake/templates/launch-c.in
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Xcode generator doesn't include the compiler as the
|
||||||
|
# first argument, Ninja and Makefiles do. Handle both cases.
|
||||||
|
if [[ "$1" = "${CMAKE_C_COMPILER}" ]] ; then
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
export CCACHE_CPP2=true
|
||||||
|
export CCACHE_HARDLINK=true
|
||||||
|
export CCACHE_SLOPPINESS=file_macro,time_macros,include_file_mtime,include_file_ctime,file_stat_matches
|
||||||
|
exec "${C_LAUNCHER}" "${CMAKE_C_COMPILER}" "$@"
|
12
cmake/templates/launch-cxx.in
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Xcode generator doesn't include the compiler as the
|
||||||
|
# first argument, Ninja and Makefiles do. Handle both cases.
|
||||||
|
if [[ "$1" = "${CMAKE_CXX_COMPILER}" ]] ; then
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
export CCACHE_CPP2=true
|
||||||
|
export CCACHE_HARDLINK=true
|
||||||
|
export CCACHE_SLOPPINESS=file_macro,time_macros,include_file_mtime,include_file_ctime,file_stat_matches
|
||||||
|
exec "${CXX_LAUNCHER}" "${CMAKE_CXX_COMPILER}" "$@"
|
140
interface/resources/avatar/network-animation.json
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
{
|
||||||
|
"version": "1.1",
|
||||||
|
"root": {
|
||||||
|
"id": "userAnimStateMachine",
|
||||||
|
"type": "stateMachine",
|
||||||
|
"data": {
|
||||||
|
"currentState": "idleAnim",
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"id": "idleAnim",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "postTransitAnim", "state": "postTransitAnim" },
|
||||||
|
{ "var": "preTransitAnim", "state": "preTransitAnim" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "preTransitAnim",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "idleAnim", "state": "idleAnim" },
|
||||||
|
{ "var": "transitAnim", "state": "transitAnim" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "transitAnim",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "preTransitAnim", "state": "preTransitAnim" },
|
||||||
|
{ "var": "postTransitAnim", "state": "postTransitAnim" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "postTransitAnim",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "transitAnim", "state": "transitAnim" },
|
||||||
|
{ "var": "idleAnim", "state": "idleAnim" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "userAnimA",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "idleAnim", "state": "idleAnim" },
|
||||||
|
{ "var": "userAnimB", "state": "userAnimB" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "userAnimB",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "idleAnim", "state": "idleAnim" },
|
||||||
|
{ "var": "userAnimA", "state": "userAnimA" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "idleAnim",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "qrc:///avatar/animations/idle.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 90.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "preTransitAnim",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-content.s3.amazonaws.com/luis/test_scripts/transitApp/animations/teleport01_warp.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 10.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": false
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "transitAnim",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-content.s3.amazonaws.com/luis/test_scripts/transitApp/animations/teleport01_warp.fbx",
|
||||||
|
"startFrame": 11.0,
|
||||||
|
"endFrame": 11.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "postTransitAnim",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-content.s3.amazonaws.com/luis/test_scripts/transitApp/animations/teleport01_warp.fbx",
|
||||||
|
"startFrame": 22.0,
|
||||||
|
"endFrame": 49.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": false
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "userAnimA",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "qrc:///avatar/animations/idle.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 90.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "userAnimB",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "qrc:///avatar/animations/idle.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 90.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -133,7 +133,7 @@
|
||||||
{ "from": "Keyboard.W", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_FORWARD" },
|
{ "from": "Keyboard.W", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_FORWARD" },
|
||||||
{ "from": "Keyboard.S", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_BACKWARD" },
|
{ "from": "Keyboard.S", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_BACKWARD" },
|
||||||
{ "from": "Keyboard.Shift", "when": ["!Keyboard.Left", "!Keyboard.Right"], "to": "Actions.SPRINT" },
|
{ "from": "Keyboard.Shift", "when": ["!Keyboard.Left", "!Keyboard.Right"], "to": "Actions.SPRINT" },
|
||||||
{ "from": "Keyboard.C", "to": "Actions.VERTICAL_DOWN" },
|
{ "from": "Keyboard.C", "when": "!Keyboard.Control", "to": "Actions.VERTICAL_DOWN" },
|
||||||
{ "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" },
|
||||||
|
|
|
@ -51,32 +51,34 @@
|
||||||
{ "from": "Vive.RSCenter", "to": "Standard.RightPrimaryThumb" },
|
{ "from": "Vive.RSCenter", "to": "Standard.RightPrimaryThumb" },
|
||||||
{ "from": "Vive.RightApplicationMenu", "to": "Standard.RightSecondaryThumb" },
|
{ "from": "Vive.RightApplicationMenu", "to": "Standard.RightSecondaryThumb" },
|
||||||
|
|
||||||
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand"},
|
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand" },
|
||||||
{ "from": "Vive.RightHand", "to": "Standard.RightHand"},
|
{ "from": "Vive.RightHand", "to": "Standard.RightHand" },
|
||||||
|
{ "from": "Vive.Head", "to" : "Standard.Head" },
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.LeftFoot", "to" : "Standard.LeftFoot",
|
"from": "Vive.LeftFoot", "to" : "Standard.LeftFoot",
|
||||||
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.RightFoot", "to" : "Standard.RightFoot",
|
"from": "Vive.RightFoot", "to" : "Standard.RightFoot",
|
||||||
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.Hips", "to" : "Standard.Hips",
|
"from": "Vive.Hips", "to" : "Standard.Hips",
|
||||||
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.Spine2", "to" : "Standard.Spine2",
|
"from": "Vive.Spine2", "to" : "Standard.Spine2",
|
||||||
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "Vive.RightArm", "to" : "Standard.RightArm",
|
||||||
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "Vive.LeftArm", "to" : "Standard.LeftArm",
|
||||||
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
|
||||||
},
|
},
|
||||||
|
|
||||||
{ "from": "Vive.Head", "to" : "Standard.Head"},
|
|
||||||
{ "from": "Vive.RightArm", "to" : "Standard.RightArm" },
|
|
||||||
{ "from": "Vive.LeftArm", "to" : "Standard.LeftArm" },
|
|
||||||
|
|
||||||
{ "from": "Vive.TrackedObject00", "to" : "Standard.TrackedObject00" },
|
{ "from": "Vive.TrackedObject00", "to" : "Standard.TrackedObject00" },
|
||||||
{ "from": "Vive.TrackedObject01", "to" : "Standard.TrackedObject01" },
|
{ "from": "Vive.TrackedObject01", "to" : "Standard.TrackedObject01" },
|
||||||
|
|
|
@ -10,6 +10,7 @@ Item {
|
||||||
property int modality: Qt.NonModal
|
property int modality: Qt.NonModal
|
||||||
implicitHeight: row.height
|
implicitHeight: row.height
|
||||||
implicitWidth: row.width
|
implicitWidth: row.width
|
||||||
|
visible: false
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
stats.parentChanged.connect(fill);
|
stats.parentChanged.connect(fill);
|
||||||
|
|
|
@ -136,7 +136,7 @@ Item {
|
||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: usernameField
|
id: usernameField
|
||||||
text: Settings.getValue("wallet/savedUsername", "");
|
text: Settings.getValue("keepMeLoggedIn/savedUsername", "");
|
||||||
width: parent.width
|
width: parent.width
|
||||||
focus: true
|
focus: true
|
||||||
placeholderText: "Username or Email"
|
placeholderText: "Username or Email"
|
||||||
|
@ -165,7 +165,7 @@ Item {
|
||||||
root.text = "";
|
root.text = "";
|
||||||
}
|
}
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
var savedUsername = Settings.getValue("wallet/savedUsername", "");
|
var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", "");
|
||||||
usernameField.text = savedUsername === "Unknown user" ? "" : savedUsername;
|
usernameField.text = savedUsername === "Unknown user" ? "" : savedUsername;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,7 +239,10 @@ Item {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onReturnPressed: linkAccountBody.login()
|
Keys.onReturnPressed: {
|
||||||
|
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||||
|
linkAccountBody.login();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InfoItem {
|
InfoItem {
|
||||||
|
@ -263,21 +266,21 @@ Item {
|
||||||
|
|
||||||
CheckBox {
|
CheckBox {
|
||||||
id: autoLogoutCheckbox
|
id: autoLogoutCheckbox
|
||||||
checked: !Settings.getValue("wallet/autoLogout", true)
|
checked: Settings.getValue("keepMeLoggedIn", false)
|
||||||
text: "Keep me signed in"
|
text: "Keep me logged in"
|
||||||
boxSize: 20;
|
boxSize: 20;
|
||||||
labelFontSize: 15
|
labelFontSize: 15
|
||||||
color: hifi.colors.black
|
color: hifi.colors.black
|
||||||
onCheckedChanged: {
|
onCheckedChanged: {
|
||||||
Settings.setValue("wallet/autoLogout", !checked);
|
Settings.setValue("keepMeLoggedIn", checked);
|
||||||
if (checked) {
|
if (checked) {
|
||||||
Settings.setValue("wallet/savedUsername", Account.username);
|
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||||
} else {
|
} else {
|
||||||
Settings.setValue("wallet/savedUsername", "");
|
Settings.setValue("keepMeLoggedIn/savedUsername", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
Settings.setValue("wallet/autoLogout", !checked);
|
Settings.setValue("keepMeLoggedIn", checked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,7 +292,10 @@ Item {
|
||||||
text: qsTr(loginDialog.isSteamRunning() ? "Link Account" : "Log in")
|
text: qsTr(loginDialog.isSteamRunning() ? "Link Account" : "Log in")
|
||||||
color: hifi.buttons.blue
|
color: hifi.buttons.blue
|
||||||
|
|
||||||
onClicked: linkAccountBody.login()
|
onClicked: {
|
||||||
|
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||||
|
linkAccountBody.login();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,6 +409,7 @@ Item {
|
||||||
case Qt.Key_Enter:
|
case Qt.Key_Enter:
|
||||||
case Qt.Key_Return:
|
case Qt.Key_Return:
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
|
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
|
||||||
linkAccountBody.login()
|
linkAccountBody.login()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ Rectangle {
|
||||||
|
|
||||||
scaleSlider.notify = false;
|
scaleSlider.notify = false;
|
||||||
scaleSlider.value = Math.round(avatarScale * 10);
|
scaleSlider.value = Math.round(avatarScale * 10);
|
||||||
scaleSlider.notify = true;;
|
scaleSlider.notify = true;
|
||||||
|
|
||||||
if (settings.dominantHand === 'left') {
|
if (settings.dominantHand === 'left') {
|
||||||
leftHandRadioButton.checked = true;
|
leftHandRadioButton.checked = true;
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
import Hifi 1.0 as Hifi
|
import Hifi 1.0 as Hifi
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
import "../../../styles-uit"
|
import "qrc:////qml//styles-uit"
|
||||||
import "../../../controls-uit" as HifiControlsUit
|
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||||
import "../../../controls" as HifiControls
|
import "qrc:////qml//controls" as HifiControls
|
||||||
|
|
||||||
// references XXX from root context
|
// references XXX from root context
|
||||||
|
|
||||||
|
@ -33,13 +33,15 @@ Rectangle {
|
||||||
property string buttonLayout: "leftright";
|
property string buttonLayout: "leftright";
|
||||||
|
|
||||||
readonly property string securityPicBodyText: "When you see your Security Pic, your actions and data are securely making use of your " +
|
readonly property string securityPicBodyText: "When you see your Security Pic, your actions and data are securely making use of your " +
|
||||||
"Wallet's private keys.<br><br>You can change your Security Pic in your Wallet.";
|
"private keys.<br><br>You can change your Security Pic via Settings > Security...";
|
||||||
|
|
||||||
id: root;
|
id: root;
|
||||||
visible: false;
|
visible: false;
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
color: Qt.rgba(0, 0, 0, 0.5);
|
color: Qt.rgba(0, 0, 0, 0.5);
|
||||||
z: 999;
|
z: 999;
|
||||||
|
|
||||||
|
HifiConstants { id: hifi; }
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
|
|
|
@ -0,0 +1,364 @@
|
||||||
|
//
|
||||||
|
// ItemUnderTest
|
||||||
|
// qml/hifi/commerce/marketplaceItemTester
|
||||||
|
//
|
||||||
|
// Load items not in the marketplace for testing purposes
|
||||||
|
//
|
||||||
|
// Created by Kerry Ivan Kurian on 2018-10-18
|
||||||
|
// Copyright 2018 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 Hifi 1.0 as Hifi
|
||||||
|
import "qrc:////qml//styles-uit" as HifiStylesUit
|
||||||
|
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: root;
|
||||||
|
color: hifi.colors.baseGray
|
||||||
|
width: parent.width - 16
|
||||||
|
height: childrenRect.height + itemHeaderContainer.anchors.topMargin + detailsContainer.anchors.topMargin
|
||||||
|
|
||||||
|
property var detailsExpanded: false
|
||||||
|
|
||||||
|
property var actions: {
|
||||||
|
"forward": function(resource, assetType, resourceObjectId){
|
||||||
|
switch(assetType) {
|
||||||
|
case "application":
|
||||||
|
Commerce.installApp(resource, true);
|
||||||
|
break;
|
||||||
|
case "avatar":
|
||||||
|
MyAvatar.useFullAvatarURL(resource);
|
||||||
|
break;
|
||||||
|
case "content set":
|
||||||
|
urlHandler.handleUrl("hifi://localhost/0,0,0");
|
||||||
|
Commerce.replaceContentSet(toUrl(resource), "");
|
||||||
|
break;
|
||||||
|
case "entity":
|
||||||
|
case "wearable":
|
||||||
|
rezEntity(resource, assetType, resourceObjectId);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
print("Marketplace item tester unsupported assetType " + assetType);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"trash": function(resource, assetType){
|
||||||
|
if ("application" === assetType) {
|
||||||
|
Commerce.uninstallApp(resource);
|
||||||
|
}
|
||||||
|
sendToScript({
|
||||||
|
method: "tester_deleteResourceObject",
|
||||||
|
objectId: resourceListModel.get(index).resourceObjectId});
|
||||||
|
resourceListModel.remove(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: itemHeaderContainer
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 8
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 8
|
||||||
|
width: parent.width - 16
|
||||||
|
height: childrenRect.height
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: itemNameContainer
|
||||||
|
width: parent.width * 0.5
|
||||||
|
height: childrenRect.height
|
||||||
|
|
||||||
|
HifiStylesUit.RalewaySemiBold {
|
||||||
|
id: resourceName
|
||||||
|
height: paintedHeight
|
||||||
|
width: parent.width
|
||||||
|
text: {
|
||||||
|
var match = resource.match(/\/([^/]*)$/);
|
||||||
|
return match ? match[1] : resource;
|
||||||
|
}
|
||||||
|
size: 14
|
||||||
|
color: hifi.colors.white
|
||||||
|
wrapMode: Text.WrapAnywhere
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiStylesUit.RalewayRegular {
|
||||||
|
id: resourceUrl
|
||||||
|
anchors.top: resourceName.bottom;
|
||||||
|
anchors.topMargin: 4;
|
||||||
|
height: paintedHeight
|
||||||
|
width: parent.width
|
||||||
|
text: resource
|
||||||
|
size: 12
|
||||||
|
color: hifi.colors.faintGray;
|
||||||
|
wrapMode: Text.WrapAnywhere
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.ComboBox {
|
||||||
|
id: comboBox
|
||||||
|
anchors.left: itemNameContainer.right
|
||||||
|
anchors.leftMargin: 4
|
||||||
|
anchors.verticalCenter: itemNameContainer.verticalCenter
|
||||||
|
height: 30
|
||||||
|
width: parent.width * 0.3 - anchors.leftMargin
|
||||||
|
|
||||||
|
model: [
|
||||||
|
"application",
|
||||||
|
"avatar",
|
||||||
|
"content set",
|
||||||
|
"entity",
|
||||||
|
"wearable",
|
||||||
|
"unknown"
|
||||||
|
]
|
||||||
|
|
||||||
|
currentIndex: (("entity or wearable" === assetType) ?
|
||||||
|
model.indexOf("unknown") : model.indexOf(assetType))
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
onCurrentIndexChanged.connect(function() {
|
||||||
|
assetType = model[currentIndex];
|
||||||
|
sendToScript({
|
||||||
|
method: "tester_updateResourceObjectAssetType",
|
||||||
|
objectId: resourceListModel.get(index)["resourceObjectId"],
|
||||||
|
assetType: assetType });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: actionButton
|
||||||
|
property var glyphs: {
|
||||||
|
"application": hifi.glyphs.install,
|
||||||
|
"avatar": hifi.glyphs.avatar,
|
||||||
|
"content set": hifi.glyphs.globe,
|
||||||
|
"entity": hifi.glyphs.wand,
|
||||||
|
"trash": hifi.glyphs.trash,
|
||||||
|
"unknown": hifi.glyphs.circleSlash,
|
||||||
|
"wearable": hifi.glyphs.hat
|
||||||
|
}
|
||||||
|
property int color: hifi.buttons.blue;
|
||||||
|
property int colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.left: comboBox.right
|
||||||
|
anchors.leftMargin: 4
|
||||||
|
anchors.verticalCenter: itemNameContainer.verticalCenter
|
||||||
|
width: parent.width * 0.10 - anchors.leftMargin
|
||||||
|
height: width
|
||||||
|
enabled: comboBox.model[comboBox.currentIndex] !== "unknown"
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (model.currentlyRecordingResources) {
|
||||||
|
model.currentlyRecordingResources = false;
|
||||||
|
} else {
|
||||||
|
model.resourceAccessEventText = "";
|
||||||
|
model.currentlyRecordingResources = true;
|
||||||
|
root.actions["forward"](resource, comboBox.currentText, resourceObjectId);
|
||||||
|
}
|
||||||
|
sendToScript({
|
||||||
|
method: "tester_updateResourceRecordingStatus",
|
||||||
|
objectId: resourceListModel.get(index).resourceObjectId,
|
||||||
|
status: model.currentlyRecordingResources
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
radius: 4;
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop {
|
||||||
|
position: 0.2
|
||||||
|
color: {
|
||||||
|
if (!actionButton.enabled) {
|
||||||
|
hifi.buttons.disabledColorStart[actionButton.colorScheme]
|
||||||
|
} else if (actionButton.pressed) {
|
||||||
|
hifi.buttons.pressedColor[actionButton.color]
|
||||||
|
} else if (actionButton.hovered) {
|
||||||
|
hifi.buttons.hoveredColor[actionButton.color]
|
||||||
|
} else {
|
||||||
|
hifi.buttons.colorStart[actionButton.color]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 1.0
|
||||||
|
color: {
|
||||||
|
if (!actionButton.enabled) {
|
||||||
|
hifi.buttons.disabledColorFinish[actionButton.colorScheme]
|
||||||
|
} else if (actionButton.pressed) {
|
||||||
|
hifi.buttons.pressedColor[actionButton.color]
|
||||||
|
} else if (actionButton.hovered) {
|
||||||
|
hifi.buttons.hoveredColor[actionButton.color]
|
||||||
|
} else {
|
||||||
|
hifi.buttons.colorFinish[actionButton.color]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Item {
|
||||||
|
HifiStylesUit.HiFiGlyphs {
|
||||||
|
id: rezIcon;
|
||||||
|
text: model.currentlyRecordingResources ? hifi.glyphs.scriptStop : actionButton.glyphs[comboBox.model[comboBox.currentIndex]];
|
||||||
|
anchors.fill: parent
|
||||||
|
size: 30;
|
||||||
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
color: enabled ? hifi.buttons.textColor[actionButton.color]
|
||||||
|
: hifi.buttons.disabledTextColor[actionButton.colorScheme]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: trashButton
|
||||||
|
property int color: hifi.buttons.red;
|
||||||
|
property int colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.left: actionButton.right
|
||||||
|
anchors.verticalCenter: itemNameContainer.verticalCenter
|
||||||
|
anchors.leftMargin: 4
|
||||||
|
width: parent.width * 0.10 - anchors.leftMargin
|
||||||
|
height: width
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
root.actions["trash"](resource, comboBox.currentText, resourceObjectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
radius: 4;
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop {
|
||||||
|
position: 0.2
|
||||||
|
color: {
|
||||||
|
if (!trashButton.enabled) {
|
||||||
|
hifi.buttons.disabledColorStart[trashButton.colorScheme]
|
||||||
|
} else if (trashButton.pressed) {
|
||||||
|
hifi.buttons.pressedColor[trashButton.color]
|
||||||
|
} else if (trashButton.hovered) {
|
||||||
|
hifi.buttons.hoveredColor[trashButton.color]
|
||||||
|
} else {
|
||||||
|
hifi.buttons.colorStart[trashButton.color]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GradientStop {
|
||||||
|
position: 1.0
|
||||||
|
color: {
|
||||||
|
if (!trashButton.enabled) {
|
||||||
|
hifi.buttons.disabledColorFinish[trashButton.colorScheme]
|
||||||
|
} else if (trashButton.pressed) {
|
||||||
|
hifi.buttons.pressedColor[trashButton.color]
|
||||||
|
} else if (trashButton.hovered) {
|
||||||
|
hifi.buttons.hoveredColor[trashButton.color]
|
||||||
|
} else {
|
||||||
|
hifi.buttons.colorFinish[trashButton.color]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Item {
|
||||||
|
HifiStylesUit.HiFiGlyphs {
|
||||||
|
id: trashIcon;
|
||||||
|
text: hifi.glyphs.trash
|
||||||
|
anchors.fill: parent
|
||||||
|
size: 22;
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
color: enabled ? hifi.buttons.textColor[trashButton.color]
|
||||||
|
: hifi.buttons.disabledTextColor[trashButton.colorScheme]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: detailsContainer
|
||||||
|
|
||||||
|
width: parent.width - 16
|
||||||
|
height: root.detailsExpanded ? 300 : 26
|
||||||
|
anchors.top: itemHeaderContainer.bottom
|
||||||
|
anchors.topMargin: 12
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 8
|
||||||
|
|
||||||
|
HifiStylesUit.HiFiGlyphs {
|
||||||
|
id: detailsToggle
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: -4
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: -2
|
||||||
|
width: 22
|
||||||
|
text: root.detailsExpanded ? hifi.glyphs.minimize : hifi.glyphs.maximize
|
||||||
|
color: hifi.colors.white
|
||||||
|
size: 22
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: root.detailsExpanded = !root.detailsExpanded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollView {
|
||||||
|
id: detailsTextContainer
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: detailsToggle.right
|
||||||
|
anchors.leftMargin: 4
|
||||||
|
anchors.right: parent.right
|
||||||
|
height: detailsContainer.height - (root.detailsExpanded ? (copyToClipboardButton.height + copyToClipboardButton.anchors.topMargin) : 0)
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
TextArea {
|
||||||
|
id: detailsText
|
||||||
|
readOnly: true
|
||||||
|
color: hifi.colors.white
|
||||||
|
text: {
|
||||||
|
var numUniqueResources = (model.resourceAccessEventText.split("\n").length - 1);
|
||||||
|
if (root.detailsExpanded && numUniqueResources > 0) {
|
||||||
|
return model.resourceAccessEventText
|
||||||
|
} else {
|
||||||
|
return numUniqueResources.toString() + " unique source/resource url pair" + (numUniqueResources === 1 ? "" : "s") + " recorded"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
font: Qt.font({ family: "Courier", pointSize: 8, weight: Font.Normal })
|
||||||
|
wrapMode: TextEdit.NoWrap
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
anchors.fill: parent;
|
||||||
|
color: hifi.colors.baseGrayShadow;
|
||||||
|
border.width: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
if (root.detailsExpanded) {
|
||||||
|
detailsText.selectAll();
|
||||||
|
} else {
|
||||||
|
root.detailsExpanded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: copyToClipboardButton;
|
||||||
|
visible: root.detailsExpanded
|
||||||
|
color: hifi.buttons.noneBorderlessWhite
|
||||||
|
colorScheme: hifi.colorSchemes.dark
|
||||||
|
|
||||||
|
anchors.top: detailsTextContainer.bottom
|
||||||
|
anchors.topMargin: 8
|
||||||
|
anchors.right: parent.right
|
||||||
|
width: 160
|
||||||
|
height: 30
|
||||||
|
text: "Copy to Clipboard"
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
Window.copyToClipboard(detailsText.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,21 +4,19 @@
|
||||||
//
|
//
|
||||||
// Load items not in the marketplace for testing purposes
|
// Load items not in the marketplace for testing purposes
|
||||||
//
|
//
|
||||||
// Created by Zach Fox on 2018-09-05
|
// Created by Kerry Ivan Kurian on 2018-09-05
|
||||||
// Copyright 2018 High Fidelity, Inc.
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
import QtQuick 2.5
|
import QtQuick 2.10
|
||||||
import QtQuick.Controls 1.4
|
|
||||||
import QtQuick.Controls.Styles 1.4
|
|
||||||
import QtQuick.Dialogs 1.0
|
|
||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
import Hifi 1.0 as Hifi
|
import Hifi 1.0 as Hifi
|
||||||
import "../../../styles-uit" as HifiStylesUit
|
import "qrc:////qml//styles-uit" as HifiStylesUit
|
||||||
import "../../../controls-uit" as HifiControlsUit
|
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,33 +25,223 @@ Rectangle {
|
||||||
|
|
||||||
property string installedApps
|
property string installedApps
|
||||||
property var nextResourceObjectId: 0
|
property var nextResourceObjectId: 0
|
||||||
signal sendToScript(var message)
|
|
||||||
|
|
||||||
HifiStylesUit.HifiConstants { id: hifi }
|
HifiStylesUit.HifiConstants { id: hifi }
|
||||||
ListModel { id: resourceListModel }
|
ListModel { id: resourceListModel }
|
||||||
|
|
||||||
color: hifi.colors.white
|
color: hifi.colors.darkGray
|
||||||
|
|
||||||
AnimatedImage {
|
//
|
||||||
id: spinner;
|
// TITLE BAR START
|
||||||
source: "spinner.gif"
|
//
|
||||||
width: 74;
|
Item {
|
||||||
height: width;
|
id: titleBarContainer
|
||||||
anchors.verticalCenter: parent.verticalCenter;
|
// Size
|
||||||
anchors.horizontalCenter: parent.horizontalCenter;
|
width: root.width
|
||||||
|
height: 50
|
||||||
|
// Anchors
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
|
||||||
|
// Title bar text
|
||||||
|
HifiStylesUit.RalewaySemiBold {
|
||||||
|
id: titleBarText
|
||||||
|
text: "Marketplace Item Tester"
|
||||||
|
// Text size
|
||||||
|
size: 24
|
||||||
|
// Anchors
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 16
|
||||||
|
width: paintedWidth
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.lightGrayText
|
||||||
|
// Alignment
|
||||||
|
horizontalAlignment: Text.AlignHLeft
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator
|
||||||
|
HifiControlsUit.Separator {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// TITLE BAR END
|
||||||
|
//
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: spinner
|
||||||
|
z: 999
|
||||||
|
anchors.top: titleBarContainer.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: buttonContainer.top
|
||||||
|
color: hifi.colors.darkGray
|
||||||
|
|
||||||
|
AnimatedImage {
|
||||||
|
source: "spinner.gif"
|
||||||
|
width: 74
|
||||||
|
height: width
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: instructionsContainer
|
||||||
|
z: 998
|
||||||
|
color: hifi.colors.darkGray
|
||||||
|
visible: resourceListModel.count === 0 && !spinner.visible
|
||||||
|
anchors.top: titleBarContainer.bottom
|
||||||
|
anchors.topMargin: 20
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 20
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 20
|
||||||
|
anchors.bottom: buttonContainer.top
|
||||||
|
anchors.bottomMargin: 20
|
||||||
|
|
||||||
|
HifiStylesUit.RalewayRegular {
|
||||||
|
text: "Use Marketplace Item Tester to test out your items before submitting them to the Marketplace." +
|
||||||
|
"\n\nUse one of the buttons below to load your item."
|
||||||
|
// Text size
|
||||||
|
size: 20
|
||||||
|
// Anchors
|
||||||
|
anchors.fill: parent
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.lightGrayText
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
// Alignment
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: itemList
|
||||||
|
visible: !instructionsContainer.visible
|
||||||
|
anchors.top: titleBarContainer.bottom
|
||||||
|
anchors.topMargin: 20
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: buttonContainer.top
|
||||||
|
anchors.bottomMargin: 20
|
||||||
|
ScrollBar.vertical: ScrollBar {
|
||||||
|
visible: !instructionsContainer.visible
|
||||||
|
policy: ScrollBar.AlwaysOn
|
||||||
|
parent: itemList.parent
|
||||||
|
anchors.top: itemList.top
|
||||||
|
anchors.right: itemList.right
|
||||||
|
anchors.bottom: itemList.bottom
|
||||||
|
width: 16
|
||||||
|
}
|
||||||
|
clip: true
|
||||||
|
model: resourceListModel
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
delegate: ItemUnderTest { }
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: buttonContainer
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 12
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 12
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: 12
|
||||||
|
height: 40
|
||||||
|
|
||||||
|
property string currentAction
|
||||||
|
property var actions: {
|
||||||
|
"Load File": function() {
|
||||||
|
buttonContainer.currentAction = "load file";
|
||||||
|
Window.browseChanged.connect(onResourceSelected);
|
||||||
|
Window.browseAsync("Please select a file (*.app.json *.json *.fst *.json.gz)", "", "Assets (*.app.json *.json *.fst *.json.gz)");
|
||||||
|
},
|
||||||
|
"Load URL": function() {
|
||||||
|
buttonContainer.currentAction = "load url";
|
||||||
|
Window.promptTextChanged.connect(onResourceSelected);
|
||||||
|
Window.promptAsync("Please enter a URL", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onResourceSelected(resource) {
|
||||||
|
// It is possible that we received the present signal
|
||||||
|
// from something other than our browserAsync window.
|
||||||
|
// Alas, there is nothing we can do about that so charge
|
||||||
|
// ahead as though we are sure the present signal is one
|
||||||
|
// we expect.
|
||||||
|
print("!!!! resource selected");
|
||||||
|
switch(currentAction) {
|
||||||
|
case "load file":
|
||||||
|
Window.browseChanged.disconnect(onResourceSelected);
|
||||||
|
break
|
||||||
|
case "load url":
|
||||||
|
Window.promptTextChanged.disconnect(onResourceSelected);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (resource) {
|
||||||
|
print("!!!! building resource object");
|
||||||
|
var resourceObj = buildResourceObj(resource);
|
||||||
|
print("!!!! notifying script of resource object");
|
||||||
|
sendToScript({
|
||||||
|
method: 'tester_newResourceObject',
|
||||||
|
resourceObject: resourceObj
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
enabled: !spinner.visible
|
||||||
|
anchors.right: parent.horizontalCenter
|
||||||
|
anchors.rightMargin: width/4
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
color: hifi.buttons.blue
|
||||||
|
fontSize: 20
|
||||||
|
text: "Load File"
|
||||||
|
width: parent.width / 3
|
||||||
|
height: parent.height
|
||||||
|
onClicked: buttonContainer.actions[text]()
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
enabled: !spinner.visible
|
||||||
|
anchors.left: parent.horizontalCenter
|
||||||
|
anchors.leftMargin: width/4
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
color: hifi.buttons.blue
|
||||||
|
fontSize: 20
|
||||||
|
text: "Load URL"
|
||||||
|
width: parent.width / 3
|
||||||
|
height: parent.height
|
||||||
|
onClicked: buttonContainer.actions[text]()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function fromScript(message) {
|
function fromScript(message) {
|
||||||
switch (message.method) {
|
switch (message.method) {
|
||||||
case "newResourceObjectInTest":
|
case "newResourceObjectInTest":
|
||||||
var resourceObject = message.resourceObject;
|
var resourceObject = message.resourceObject;
|
||||||
|
resourceListModel.clear(); // REMOVE THIS once we support specific referrers
|
||||||
resourceListModel.append(resourceObject);
|
resourceListModel.append(resourceObject);
|
||||||
spinner.visible = false;
|
spinner.visible = false;
|
||||||
break;
|
break;
|
||||||
case "nextObjectIdInTest":
|
case "nextObjectIdInTest":
|
||||||
|
print("!!!! message from script! " + JSON.stringify(message));
|
||||||
nextResourceObjectId = message.id;
|
nextResourceObjectId = message.id;
|
||||||
spinner.visible = false;
|
spinner.visible = false;
|
||||||
break;
|
break;
|
||||||
|
case "resourceRequestEvent":
|
||||||
|
// When we support multiple items under test simultaneously,
|
||||||
|
// we'll have to replace "0" with the correct index.
|
||||||
|
resourceListModel.setProperty(0, "resourceAccessEventText", message.resourceAccessEventText);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,227 +252,26 @@ Rectangle {
|
||||||
resource.match(/\.json\.gz$/) ? "content set" :
|
resource.match(/\.json\.gz$/) ? "content set" :
|
||||||
resource.match(/\.json$/) ? "entity or wearable" :
|
resource.match(/\.json$/) ? "entity or wearable" :
|
||||||
"unknown");
|
"unknown");
|
||||||
return { "id": nextResourceObjectId++,
|
// Uncomment this once we support more than one item in test at the same time
|
||||||
|
//nextResourceObjectId++;
|
||||||
|
return { "resourceObjectId": nextResourceObjectId,
|
||||||
"resource": resource,
|
"resource": resource,
|
||||||
"assetType": assetType };
|
"assetType": assetType };
|
||||||
}
|
}
|
||||||
|
|
||||||
function installResourceObj(resourceObj) {
|
|
||||||
if ("application" === resourceObj.assetType) {
|
|
||||||
Commerce.installApp(resourceObj.resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addAllInstalledAppsToList() {
|
|
||||||
var i, apps = Commerce.getInstalledApps().split(","), len = apps.length;
|
|
||||||
for(i = 0; i < len - 1; ++i) {
|
|
||||||
if (i in apps) {
|
|
||||||
resourceListModel.append(buildResourceObj(apps[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function toUrl(resource) {
|
function toUrl(resource) {
|
||||||
var httpPattern = /^http/i;
|
var httpPattern = /^http/i;
|
||||||
return httpPattern.test(resource) ? resource : "file:///" + resource;
|
return httpPattern.test(resource) ? resource : "file:///" + resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
function rezEntity(resource, entityType) {
|
function rezEntity(resource, entityType, resourceObjectId) {
|
||||||
|
print("!!!! tester_rezClicked");
|
||||||
sendToScript({
|
sendToScript({
|
||||||
method: 'tester_rezClicked',
|
method: 'tester_rezClicked',
|
||||||
itemHref: toUrl(resource),
|
itemHref: toUrl(resource),
|
||||||
itemType: entityType});
|
itemType: entityType,
|
||||||
|
itemId: resourceObjectId });
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView {
|
signal sendToScript(var message)
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: 12
|
|
||||||
anchors.bottomMargin: 40
|
|
||||||
anchors.rightMargin: 12
|
|
||||||
model: resourceListModel
|
|
||||||
spacing: 5
|
|
||||||
interactive: false
|
|
||||||
|
|
||||||
delegate: RowLayout {
|
|
||||||
anchors.left: parent.left
|
|
||||||
width: parent.width
|
|
||||||
spacing: 5
|
|
||||||
|
|
||||||
property var actions: {
|
|
||||||
"forward": function(resource, assetType){
|
|
||||||
switch(assetType) {
|
|
||||||
case "application":
|
|
||||||
Commerce.openApp(resource);
|
|
||||||
break;
|
|
||||||
case "avatar":
|
|
||||||
MyAvatar.useFullAvatarURL(resource);
|
|
||||||
break;
|
|
||||||
case "content set":
|
|
||||||
urlHandler.handleUrl("hifi://localhost/0,0,0");
|
|
||||||
Commerce.replaceContentSet(toUrl(resource), "");
|
|
||||||
break;
|
|
||||||
case "entity":
|
|
||||||
case "wearable":
|
|
||||||
rezEntity(resource, assetType);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
print("Marketplace item tester unsupported assetType " + assetType);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"trash": function(resource, assetType){
|
|
||||||
if ("application" === assetType) {
|
|
||||||
Commerce.uninstallApp(resource);
|
|
||||||
}
|
|
||||||
sendToScript({
|
|
||||||
method: "tester_deleteResourceObject",
|
|
||||||
objectId: resourceListModel.get(index).id});
|
|
||||||
resourceListModel.remove(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
Layout.preferredWidth: root.width * .6
|
|
||||||
spacing: 5
|
|
||||||
Text {
|
|
||||||
text: {
|
|
||||||
var match = resource.match(/\/([^/]*)$/);
|
|
||||||
return match ? match[1] : resource;
|
|
||||||
}
|
|
||||||
font.pointSize: 12
|
|
||||||
horizontalAlignment: Text.AlignBottom
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
text: resource
|
|
||||||
font.pointSize: 8
|
|
||||||
width: root.width * .6
|
|
||||||
horizontalAlignment: Text.AlignBottom
|
|
||||||
wrapMode: Text.WrapAnywhere
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ComboBox {
|
|
||||||
id: comboBox
|
|
||||||
|
|
||||||
Layout.preferredWidth: root.width * .2
|
|
||||||
|
|
||||||
model: [
|
|
||||||
"application",
|
|
||||||
"avatar",
|
|
||||||
"content set",
|
|
||||||
"entity",
|
|
||||||
"wearable",
|
|
||||||
"unknown"
|
|
||||||
]
|
|
||||||
|
|
||||||
currentIndex: (("entity or wearable" === assetType) ?
|
|
||||||
model.indexOf("unknown") : model.indexOf(assetType))
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
onCurrentIndexChanged.connect(function() {
|
|
||||||
assetType = model[currentIndex];
|
|
||||||
sendToScript({
|
|
||||||
method: "tester_updateResourceObjectAssetType",
|
|
||||||
objectId: resourceListModel.get(index)["id"],
|
|
||||||
assetType: assetType });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: [ "forward", "trash" ]
|
|
||||||
|
|
||||||
HifiStylesUit.HiFiGlyphs {
|
|
||||||
property var glyphs: {
|
|
||||||
"application": hifi.glyphs.install,
|
|
||||||
"avatar": hifi.glyphs.avatar,
|
|
||||||
"content set": hifi.glyphs.globe,
|
|
||||||
"entity": hifi.glyphs.wand,
|
|
||||||
"trash": hifi.glyphs.trash,
|
|
||||||
"unknown": hifi.glyphs.circleSlash,
|
|
||||||
"wearable": hifi.glyphs.hat,
|
|
||||||
}
|
|
||||||
text: (("trash" === modelData) ?
|
|
||||||
glyphs.trash :
|
|
||||||
glyphs[comboBox.model[comboBox.currentIndex]])
|
|
||||||
size: ("trash" === modelData) ? 22 : 30
|
|
||||||
color: hifi.colors.black
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: {
|
|
||||||
actions[modelData](resource, comboBox.currentText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
headerPositioning: ListView.OverlayHeader
|
|
||||||
header: HifiStylesUit.RalewayRegular {
|
|
||||||
id: rootHeader
|
|
||||||
text: "Marketplace Item Tester"
|
|
||||||
height: 80
|
|
||||||
width: paintedWidth
|
|
||||||
size: 22
|
|
||||||
color: hifi.colors.black
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: 12
|
|
||||||
}
|
|
||||||
|
|
||||||
footerPositioning: ListView.OverlayFooter
|
|
||||||
footer: Row {
|
|
||||||
id: rootActions
|
|
||||||
spacing: 20
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
|
|
||||||
property string currentAction
|
|
||||||
property var actions: {
|
|
||||||
"Load File": function(){
|
|
||||||
rootActions.currentAction = "load file";
|
|
||||||
Window.browseChanged.connect(onResourceSelected);
|
|
||||||
Window.browseAsync("Please select a file (*.app.json *.json *.fst *.json.gz)", "", "Assets (*.app.json *.json *.fst *.json.gz)");
|
|
||||||
},
|
|
||||||
"Load URL": function(){
|
|
||||||
rootActions.currentAction = "load url";
|
|
||||||
Window.promptTextChanged.connect(onResourceSelected);
|
|
||||||
Window.promptAsync("Please enter a URL", "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onResourceSelected(resource) {
|
|
||||||
// It is possible that we received the present signal
|
|
||||||
// from something other than our browserAsync window.
|
|
||||||
// Alas, there is nothing we can do about that so charge
|
|
||||||
// ahead as though we are sure the present signal is one
|
|
||||||
// we expect.
|
|
||||||
switch(currentAction) {
|
|
||||||
case "load file":
|
|
||||||
Window.browseChanged.disconnect(onResourceSelected);
|
|
||||||
break
|
|
||||||
case "load url":
|
|
||||||
Window.promptTextChanged.disconnect(onResourceSelected);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (resource) {
|
|
||||||
var resourceObj = buildResourceObj(resource);
|
|
||||||
installResourceObj(resourceObj);
|
|
||||||
sendToScript({
|
|
||||||
method: 'tester_newResourceObject',
|
|
||||||
resourceObject: resourceObj });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: [ "Load File", "Load URL" ]
|
|
||||||
HifiControlsUit.Button {
|
|
||||||
color: hifi.buttons.blue
|
|
||||||
fontSize: 20
|
|
||||||
text: modelData
|
|
||||||
width: root.width / 3
|
|
||||||
height: 40
|
|
||||||
onClicked: actions[text]()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 58 KiB |
|
@ -74,8 +74,7 @@ In your Wallet's Send Money tab, choose from your list of connections, or choose
|
||||||
isExpanded: false;
|
isExpanded: false;
|
||||||
question: "What is a Security Pic?"
|
question: "What is a Security Pic?"
|
||||||
answer: "Your Security Pic acts as an extra layer of Wallet security. \
|
answer: "Your Security Pic acts as an extra layer of Wallet security. \
|
||||||
When you see your Security Pic, you know that your actions and data are securely making use of your account. \
|
When you see your Security Pic, you know that your actions and data are securely making use of your account.";
|
||||||
<br><br><b><font color='#0093C5'><a href='#securitypic'>Tap here to change your Security Pic.</a></font></b>";
|
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
isExpanded: false;
|
isExpanded: false;
|
||||||
|
@ -137,7 +136,7 @@ At the moment, there is currently no way to convert HFC to other currencies. Sta
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
width: parent.width;
|
width: parent.width;
|
||||||
height: questionText.paintedHeight + 50;
|
height: questionText.paintedHeight + 50;
|
||||||
|
|
||||||
RalewaySemiBold {
|
RalewaySemiBold {
|
||||||
id: plusMinusButton;
|
id: plusMinusButton;
|
||||||
text: model.isExpanded ? "-" : "+";
|
text: model.isExpanded ? "-" : "+";
|
||||||
|
@ -217,8 +216,6 @@ At the moment, there is currently no way to convert HFC to other currencies. Sta
|
||||||
}
|
}
|
||||||
} else if (link === "#support") {
|
} else if (link === "#support") {
|
||||||
Qt.openUrlExternally("mailto:support@highfidelity.com");
|
Qt.openUrlExternally("mailto:support@highfidelity.com");
|
||||||
} else if (link === "#securitypic") {
|
|
||||||
sendSignalToWallet({method: 'walletSecurity_changeSecurityImage'});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,246 +0,0 @@
|
||||||
//
|
|
||||||
// Security.qml
|
|
||||||
// qml/hifi/commerce/wallet
|
|
||||||
//
|
|
||||||
// Security
|
|
||||||
//
|
|
||||||
// Created by Zach Fox on 2017-08-18
|
|
||||||
// Copyright 2017 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 Hifi 1.0 as Hifi
|
|
||||||
import QtQuick 2.5
|
|
||||||
import QtGraphicalEffects 1.0
|
|
||||||
import "../../../styles-uit"
|
|
||||||
import "../../../controls-uit" as HifiControlsUit
|
|
||||||
import "../../../controls" as HifiControls
|
|
||||||
|
|
||||||
// references XXX from root context
|
|
||||||
|
|
||||||
Item {
|
|
||||||
HifiConstants { id: hifi; }
|
|
||||||
|
|
||||||
id: root;
|
|
||||||
property string keyFilePath;
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: Commerce;
|
|
||||||
|
|
||||||
onKeyFilePathIfExistsResult: {
|
|
||||||
root.keyFilePath = path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Username Text
|
|
||||||
RalewayRegular {
|
|
||||||
id: usernameText;
|
|
||||||
text: Account.username;
|
|
||||||
// Text size
|
|
||||||
size: 24;
|
|
||||||
// Style
|
|
||||||
color: hifi.colors.white;
|
|
||||||
elide: Text.ElideRight;
|
|
||||||
// Anchors
|
|
||||||
anchors.top: parent.top;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.leftMargin: 20;
|
|
||||||
width: parent.width/2;
|
|
||||||
height: 80;
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: securityContainer;
|
|
||||||
anchors.top: usernameText.bottom;
|
|
||||||
anchors.topMargin: 20;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.bottom: parent.bottom;
|
|
||||||
|
|
||||||
RalewaySemiBold {
|
|
||||||
id: securityText;
|
|
||||||
text: "Security";
|
|
||||||
// Anchors
|
|
||||||
anchors.top: parent.top;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.leftMargin: 20;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
height: 30;
|
|
||||||
// Text size
|
|
||||||
size: 18;
|
|
||||||
// Style
|
|
||||||
color: hifi.colors.blueHighlight;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: securityTextSeparator;
|
|
||||||
// Size
|
|
||||||
width: parent.width;
|
|
||||||
height: 1;
|
|
||||||
// Anchors
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.top: securityText.bottom;
|
|
||||||
anchors.topMargin: 8;
|
|
||||||
// Style
|
|
||||||
color: hifi.colors.faintGray;
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: changeSecurityImageContainer;
|
|
||||||
anchors.top: securityTextSeparator.bottom;
|
|
||||||
anchors.topMargin: 8;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.leftMargin: 40;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.rightMargin: 55;
|
|
||||||
height: 75;
|
|
||||||
|
|
||||||
HiFiGlyphs {
|
|
||||||
id: changeSecurityImageImage;
|
|
||||||
text: hifi.glyphs.securityImage;
|
|
||||||
// Size
|
|
||||||
size: 80;
|
|
||||||
// Anchors
|
|
||||||
anchors.top: parent.top;
|
|
||||||
anchors.bottom: parent.bottom;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
// Style
|
|
||||||
color: hifi.colors.white;
|
|
||||||
}
|
|
||||||
|
|
||||||
RalewaySemiBold {
|
|
||||||
text: "Security Pic";
|
|
||||||
// Anchors
|
|
||||||
anchors.top: parent.top;
|
|
||||||
anchors.bottom: parent.bottom;
|
|
||||||
anchors.left: changeSecurityImageImage.right;
|
|
||||||
anchors.leftMargin: 30;
|
|
||||||
width: 50;
|
|
||||||
// Text size
|
|
||||||
size: 18;
|
|
||||||
// Style
|
|
||||||
color: hifi.colors.white;
|
|
||||||
}
|
|
||||||
|
|
||||||
// "Change Security Pic" button
|
|
||||||
HifiControlsUit.Button {
|
|
||||||
id: changeSecurityImageButton;
|
|
||||||
color: hifi.buttons.blue;
|
|
||||||
colorScheme: hifi.colorSchemes.dark;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.verticalCenter: parent.verticalCenter;
|
|
||||||
width: 140;
|
|
||||||
height: 40;
|
|
||||||
text: "Change";
|
|
||||||
onClicked: {
|
|
||||||
sendSignalToWallet({method: 'walletSecurity_changeSecurityImage'});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: autoLogoutContainer;
|
|
||||||
anchors.top: changeSecurityImageContainer.bottom;
|
|
||||||
anchors.topMargin: 8;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.leftMargin: 40;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.rightMargin: 55;
|
|
||||||
height: 75;
|
|
||||||
|
|
||||||
HiFiGlyphs {
|
|
||||||
id: autoLogoutImage;
|
|
||||||
text: hifi.glyphs.walletKey;
|
|
||||||
// Size
|
|
||||||
size: 80;
|
|
||||||
// Anchors
|
|
||||||
anchors.top: parent.top;
|
|
||||||
anchors.topMargin: 20;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
// Style
|
|
||||||
color: hifi.colors.white;
|
|
||||||
}
|
|
||||||
|
|
||||||
HifiControlsUit.CheckBox {
|
|
||||||
id: autoLogoutCheckbox;
|
|
||||||
checked: Settings.getValue("wallet/autoLogout", false);
|
|
||||||
text: "Automatically Log Out when Exiting Interface"
|
|
||||||
// Anchors
|
|
||||||
anchors.verticalCenter: autoLogoutImage.verticalCenter;
|
|
||||||
anchors.left: autoLogoutImage.right;
|
|
||||||
anchors.leftMargin: 20;
|
|
||||||
anchors.right: autoLogoutHelp.left;
|
|
||||||
anchors.rightMargin: 12;
|
|
||||||
boxSize: 28;
|
|
||||||
labelFontSize: 18;
|
|
||||||
color: hifi.colors.white;
|
|
||||||
onCheckedChanged: {
|
|
||||||
Settings.setValue("wallet/autoLogout", checked);
|
|
||||||
if (checked) {
|
|
||||||
Settings.setValue("wallet/savedUsername", Account.username);
|
|
||||||
} else {
|
|
||||||
Settings.setValue("wallet/savedUsername", "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RalewaySemiBold {
|
|
||||||
id: autoLogoutHelp;
|
|
||||||
text: '[?]';
|
|
||||||
// Anchors
|
|
||||||
anchors.verticalCenter: autoLogoutImage.verticalCenter;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
width: 30;
|
|
||||||
height: 30;
|
|
||||||
// Text size
|
|
||||||
size: 18;
|
|
||||||
// Style
|
|
||||||
color: hifi.colors.blueHighlight;
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent;
|
|
||||||
hoverEnabled: true;
|
|
||||||
onEntered: {
|
|
||||||
parent.color = hifi.colors.blueAccent;
|
|
||||||
}
|
|
||||||
onExited: {
|
|
||||||
parent.color = hifi.colors.blueHighlight;
|
|
||||||
}
|
|
||||||
onClicked: {
|
|
||||||
sendSignalToWallet({method: 'walletSecurity_autoLogoutHelp'});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// FUNCTION DEFINITIONS START
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Function Name: fromScript()
|
|
||||||
//
|
|
||||||
// Relevant Variables:
|
|
||||||
// None
|
|
||||||
//
|
|
||||||
// Arguments:
|
|
||||||
// message: The message sent from the JavaScript.
|
|
||||||
// Messages are in format "{method, params}", like json-rpc.
|
|
||||||
//
|
|
||||||
// Description:
|
|
||||||
// Called when a message is received from a script.
|
|
||||||
//
|
|
||||||
function fromScript(message) {
|
|
||||||
switch (message.method) {
|
|
||||||
default:
|
|
||||||
console.log('Unrecognized message from wallet.js:', JSON.stringify(message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
signal sendSignalToWallet(var msg);
|
|
||||||
//
|
|
||||||
// FUNCTION DEFINITIONS END
|
|
||||||
//
|
|
||||||
}
|
|
|
@ -142,7 +142,7 @@ Rectangle {
|
||||||
Image {
|
Image {
|
||||||
id: titleBarSecurityImage;
|
id: titleBarSecurityImage;
|
||||||
source: "";
|
source: "";
|
||||||
visible: titleBarSecurityImage.source !== "" && !securityImageChange.visible;
|
visible: titleBarSecurityImage.source !== "";
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
anchors.rightMargin: 6;
|
anchors.rightMargin: 6;
|
||||||
anchors.top: parent.top;
|
anchors.top: parent.top;
|
||||||
|
@ -232,10 +232,6 @@ Rectangle {
|
||||||
root.isPassword = msg.isPasswordField;
|
root.isPassword = msg.isPasswordField;
|
||||||
} else if (msg.method === 'walletSetup_lowerKeyboard') {
|
} else if (msg.method === 'walletSetup_lowerKeyboard') {
|
||||||
root.keyboardRaised = false;
|
root.keyboardRaised = false;
|
||||||
} else if (msg.method === 'walletSecurity_changePassphraseCancelled') {
|
|
||||||
root.activeView = "security";
|
|
||||||
} else if (msg.method === 'walletSecurity_changePassphraseSuccess') {
|
|
||||||
root.activeView = "security";
|
|
||||||
} else {
|
} else {
|
||||||
sendToScript(msg);
|
sendToScript(msg);
|
||||||
}
|
}
|
||||||
|
@ -245,27 +241,6 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SecurityImageChange {
|
|
||||||
id: securityImageChange;
|
|
||||||
visible: root.activeView === "securityImageChange";
|
|
||||||
z: 997;
|
|
||||||
anchors.top: titleBarContainer.bottom;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.bottom: parent.bottom;
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
onSendSignalToWallet: {
|
|
||||||
if (msg.method === 'walletSecurity_changeSecurityImageCancelled') {
|
|
||||||
root.activeView = "security";
|
|
||||||
} else if (msg.method === 'walletSecurity_changeSecurityImageSuccess') {
|
|
||||||
root.activeView = "security";
|
|
||||||
} else {
|
|
||||||
sendToScript(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// TAB CONTENTS START
|
// TAB CONTENTS START
|
||||||
|
@ -366,39 +341,6 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Security {
|
|
||||||
id: security;
|
|
||||||
visible: root.activeView === "security";
|
|
||||||
anchors.top: titleBarContainer.bottom;
|
|
||||||
anchors.bottom: tabButtonsContainer.top;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
onSendSignalToWallet: {
|
|
||||||
if (msg.method === 'walletSecurity_changePassphrase') {
|
|
||||||
root.activeView = "passphraseChange";
|
|
||||||
passphraseChange.clearPassphraseFields();
|
|
||||||
passphraseChange.resetSubmitButton();
|
|
||||||
} else if (msg.method === 'walletSecurity_changeSecurityImage') {
|
|
||||||
securityImageChange.initModel();
|
|
||||||
root.activeView = "securityImageChange";
|
|
||||||
} else if (msg.method === 'walletSecurity_autoLogoutHelp') {
|
|
||||||
lightboxPopup.titleText = "Automatically Log Out";
|
|
||||||
lightboxPopup.bodyText = "By default, after you log in to High Fidelity, you will stay logged in to your High Fidelity " +
|
|
||||||
"account even after you close and re-open Interface. This means anyone who opens Interface on your computer " +
|
|
||||||
"could make purchases with your Wallet.\n\n" +
|
|
||||||
"If you do not want to stay logged in across Interface sessions, check this box.";
|
|
||||||
lightboxPopup.button1text = "CLOSE";
|
|
||||||
lightboxPopup.button1method = function() {
|
|
||||||
lightboxPopup.visible = false;
|
|
||||||
}
|
|
||||||
lightboxPopup.visible = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Help {
|
Help {
|
||||||
id: help;
|
id: help;
|
||||||
visible: root.activeView === "help";
|
visible: root.activeView === "help";
|
||||||
|
@ -407,14 +349,6 @@ Rectangle {
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
|
|
||||||
Connections {
|
|
||||||
onSendSignalToWallet: {
|
|
||||||
if (msg.method === 'walletSecurity_changeSecurityImage') {
|
|
||||||
securityImageChange.initModel();
|
|
||||||
root.activeView = "securityImageChange";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -427,8 +361,8 @@ Rectangle {
|
||||||
//
|
//
|
||||||
Item {
|
Item {
|
||||||
id: tabButtonsContainer;
|
id: tabButtonsContainer;
|
||||||
visible: !needsLogIn.visible && root.activeView !== "passphraseChange" && root.activeView !== "securityImageChange" && sendMoney.currentActiveView !== "sendAssetStep";
|
visible: !needsLogIn.visible && root.activeView !== "passphraseChange" && sendMoney.currentActiveView !== "sendAssetStep";
|
||||||
property int numTabs: 5;
|
property int numTabs: 4;
|
||||||
// Size
|
// Size
|
||||||
width: root.width;
|
width: root.width;
|
||||||
height: 90;
|
height: 90;
|
||||||
|
@ -452,7 +386,7 @@ Rectangle {
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
width: parent.width / tabButtonsContainer.numTabs;
|
width: parent.width / tabButtonsContainer.numTabs;
|
||||||
|
|
||||||
HiFiGlyphs {
|
HiFiGlyphs {
|
||||||
id: homeTabIcon;
|
id: homeTabIcon;
|
||||||
text: hifi.glyphs.home2;
|
text: hifi.glyphs.home2;
|
||||||
|
@ -506,7 +440,7 @@ Rectangle {
|
||||||
anchors.left: walletHomeButtonContainer.right;
|
anchors.left: walletHomeButtonContainer.right;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
width: parent.width / tabButtonsContainer.numTabs;
|
width: parent.width / tabButtonsContainer.numTabs;
|
||||||
|
|
||||||
HiFiGlyphs {
|
HiFiGlyphs {
|
||||||
id: exchangeMoneyTabIcon;
|
id: exchangeMoneyTabIcon;
|
||||||
text: hifi.glyphs.leftRightArrows;
|
text: hifi.glyphs.leftRightArrows;
|
||||||
|
@ -550,7 +484,7 @@ Rectangle {
|
||||||
anchors.left: exchangeMoneyButtonContainer.right;
|
anchors.left: exchangeMoneyButtonContainer.right;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
width: parent.width / tabButtonsContainer.numTabs;
|
width: parent.width / tabButtonsContainer.numTabs;
|
||||||
|
|
||||||
HiFiGlyphs {
|
HiFiGlyphs {
|
||||||
id: sendMoneyTabIcon;
|
id: sendMoneyTabIcon;
|
||||||
text: hifi.glyphs.paperPlane;
|
text: hifi.glyphs.paperPlane;
|
||||||
|
@ -596,70 +530,16 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// "SECURITY" tab button
|
|
||||||
Rectangle {
|
|
||||||
id: securityButtonContainer;
|
|
||||||
visible: !walletSetup.visible;
|
|
||||||
color: root.activeView === "security" ? hifi.colors.blueAccent : hifi.colors.black;
|
|
||||||
anchors.top: parent.top;
|
|
||||||
anchors.left: sendMoneyButtonContainer.right;
|
|
||||||
anchors.bottom: parent.bottom;
|
|
||||||
width: parent.width / tabButtonsContainer.numTabs;
|
|
||||||
|
|
||||||
HiFiGlyphs {
|
|
||||||
id: securityTabIcon;
|
|
||||||
text: hifi.glyphs.lock;
|
|
||||||
// Size
|
|
||||||
size: 38;
|
|
||||||
// Anchors
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter;
|
|
||||||
anchors.top: parent.top;
|
|
||||||
anchors.topMargin: 2;
|
|
||||||
// Style
|
|
||||||
color: root.activeView === "security" || securityTabMouseArea.containsMouse ? hifi.colors.white : hifi.colors.blueHighlight;
|
|
||||||
}
|
|
||||||
|
|
||||||
RalewaySemiBold {
|
|
||||||
text: "SECURITY";
|
|
||||||
// Text size
|
|
||||||
size: 16;
|
|
||||||
// Anchors
|
|
||||||
anchors.bottom: parent.bottom;
|
|
||||||
height: parent.height/2;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.leftMargin: 4;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.rightMargin: 4;
|
|
||||||
// Style
|
|
||||||
color: root.activeView === "security" || securityTabMouseArea.containsMouse ? hifi.colors.white : hifi.colors.blueHighlight;
|
|
||||||
wrapMode: Text.WordWrap;
|
|
||||||
// Alignment
|
|
||||||
horizontalAlignment: Text.AlignHCenter;
|
|
||||||
verticalAlignment: Text.AlignTop;
|
|
||||||
}
|
|
||||||
MouseArea {
|
|
||||||
id: securityTabMouseArea;
|
|
||||||
anchors.fill: parent;
|
|
||||||
hoverEnabled: enabled;
|
|
||||||
onClicked: {
|
|
||||||
root.activeView = "security";
|
|
||||||
tabButtonsContainer.resetTabButtonColors();
|
|
||||||
}
|
|
||||||
onEntered: parent.color = hifi.colors.blueHighlight;
|
|
||||||
onExited: parent.color = root.activeView === "security" ? hifi.colors.blueAccent : hifi.colors.black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// "HELP" tab button
|
// "HELP" tab button
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: helpButtonContainer;
|
id: helpButtonContainer;
|
||||||
visible: !walletSetup.visible;
|
visible: !walletSetup.visible;
|
||||||
color: root.activeView === "help" ? hifi.colors.blueAccent : hifi.colors.black;
|
color: root.activeView === "help" ? hifi.colors.blueAccent : hifi.colors.black;
|
||||||
anchors.top: parent.top;
|
anchors.top: parent.top;
|
||||||
anchors.left: securityButtonContainer.right;
|
anchors.left: sendMoneyButtonContainer.right;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
width: parent.width / tabButtonsContainer.numTabs;
|
width: parent.width / tabButtonsContainer.numTabs;
|
||||||
|
|
||||||
HiFiGlyphs {
|
HiFiGlyphs {
|
||||||
id: helpTabIcon;
|
id: helpTabIcon;
|
||||||
text: hifi.glyphs.question;
|
text: hifi.glyphs.question;
|
||||||
|
|
|
@ -243,7 +243,6 @@ Item {
|
||||||
height: 50;
|
height: 50;
|
||||||
text: "Set Up Wallet";
|
text: "Set Up Wallet";
|
||||||
onClicked: {
|
onClicked: {
|
||||||
securityImageSelection.initModel();
|
|
||||||
root.activeView = "step_2";
|
root.activeView = "step_2";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,124 +266,6 @@ Item {
|
||||||
// FIRST PAGE END
|
// FIRST PAGE END
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
|
||||||
// SECURITY IMAGE SELECTION START
|
|
||||||
//
|
|
||||||
Item {
|
|
||||||
id: securityImageContainer;
|
|
||||||
visible: root.activeView === "step_2";
|
|
||||||
// Anchors
|
|
||||||
anchors.top: titleBarContainer.bottom;
|
|
||||||
anchors.topMargin: 30;
|
|
||||||
anchors.bottom: parent.bottom;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.leftMargin: 16;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.rightMargin: 16;
|
|
||||||
|
|
||||||
// Text below title bar
|
|
||||||
RalewayRegular {
|
|
||||||
id: securityImageTitleHelper;
|
|
||||||
text: "Choose a Security Pic:";
|
|
||||||
// Text size
|
|
||||||
size: 24;
|
|
||||||
// Anchors
|
|
||||||
anchors.top: parent.top;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
height: 50;
|
|
||||||
width: paintedWidth;
|
|
||||||
// Style
|
|
||||||
color: hifi.colors.white;
|
|
||||||
// Alignment
|
|
||||||
horizontalAlignment: Text.AlignHLeft;
|
|
||||||
verticalAlignment: Text.AlignVCenter;
|
|
||||||
}
|
|
||||||
|
|
||||||
SecurityImageSelection {
|
|
||||||
id: securityImageSelection;
|
|
||||||
// Anchors
|
|
||||||
anchors.top: securityImageTitleHelper.bottom;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
height: 300;
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
onSendSignalToWallet: {
|
|
||||||
sendSignalToWallet(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Text below security images
|
|
||||||
RalewayRegular {
|
|
||||||
text: "<b>Your security picture shows you that the service asking for your passphrase is authorized.</b> You can change your secure picture at any time.";
|
|
||||||
// Text size
|
|
||||||
size: 18;
|
|
||||||
// Anchors
|
|
||||||
anchors.top: securityImageSelection.bottom;
|
|
||||||
anchors.topMargin: 40;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
height: paintedHeight;
|
|
||||||
// Style
|
|
||||||
color: hifi.colors.white;
|
|
||||||
wrapMode: Text.WordWrap;
|
|
||||||
// Alignment
|
|
||||||
horizontalAlignment: Text.AlignHLeft;
|
|
||||||
verticalAlignment: Text.AlignVCenter;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Navigation Bar
|
|
||||||
Item {
|
|
||||||
// Size
|
|
||||||
width: parent.width;
|
|
||||||
height: 50;
|
|
||||||
// Anchors:
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.bottom: parent.bottom;
|
|
||||||
anchors.bottomMargin: 50;
|
|
||||||
|
|
||||||
// "Back" button
|
|
||||||
HifiControlsUit.Button {
|
|
||||||
color: hifi.buttons.noneBorderlessWhite;
|
|
||||||
colorScheme: hifi.colorSchemes.dark;
|
|
||||||
anchors.top: parent.top;
|
|
||||||
anchors.bottom: parent.bottom;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.leftMargin: 20;
|
|
||||||
width: 200;
|
|
||||||
text: "Back"
|
|
||||||
onClicked: {
|
|
||||||
securityImageSelection.resetSelection();
|
|
||||||
root.activeView = "step_1";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// "Next" button
|
|
||||||
HifiControlsUit.Button {
|
|
||||||
enabled: securityImageSelection.currentIndex !== -1;
|
|
||||||
color: hifi.buttons.blue;
|
|
||||||
colorScheme: hifi.colorSchemes.dark;
|
|
||||||
anchors.top: parent.top;
|
|
||||||
anchors.bottom: parent.bottom;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.rightMargin: 20;
|
|
||||||
width: 200;
|
|
||||||
text: "Next";
|
|
||||||
onClicked: {
|
|
||||||
root.lastPage = "step_2";
|
|
||||||
var securityImagePath = securityImageSelection.getImagePathFromImageID(securityImageSelection.getSelectedImageIndex())
|
|
||||||
Commerce.chooseSecurityImage(securityImagePath);
|
|
||||||
root.activeView = "step_3";
|
|
||||||
passphraseSelection.clearPassphraseFields();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// SECURITY IMAGE SELECTION END
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// SECURE PASSPHRASE SELECTION START
|
// SECURE PASSPHRASE SELECTION START
|
||||||
//
|
//
|
||||||
|
@ -525,7 +406,6 @@ Item {
|
||||||
width: 200;
|
width: 200;
|
||||||
text: "Back"
|
text: "Back"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
securityImageSelection.resetSelection();
|
|
||||||
root.lastPage = "step_3";
|
root.lastPage = "step_3";
|
||||||
root.activeView = "step_2";
|
root.activeView = "step_2";
|
||||||
}
|
}
|
||||||
|
|
344
interface/resources/qml/hifi/dialogs/security/Security.qml
Normal file
|
@ -0,0 +1,344 @@
|
||||||
|
//
|
||||||
|
// Security.qml
|
||||||
|
// qml\hifi\dialogs\security
|
||||||
|
//
|
||||||
|
// Security
|
||||||
|
//
|
||||||
|
// Created by Zach Fox on 2018-10-31
|
||||||
|
// Copyright 2018 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 Hifi 1.0 as Hifi
|
||||||
|
import QtQuick 2.5
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
import "qrc:////qml//styles-uit" as HifiStylesUit
|
||||||
|
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||||
|
import "qrc:////qml//controls" as HifiControls
|
||||||
|
import "qrc:////qml//hifi//commerce//common" as HifiCommerceCommon
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
HifiStylesUit.HifiConstants { id: hifi; }
|
||||||
|
|
||||||
|
id: root;
|
||||||
|
color: hifi.colors.baseGray;
|
||||||
|
|
||||||
|
property string title: "Security Settings";
|
||||||
|
property bool walletSetUp;
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: margins
|
||||||
|
property real paddings: root.width / 20.25
|
||||||
|
|
||||||
|
property real sizeCheckBox: root.width / 13.5
|
||||||
|
property real sizeText: root.width / 2.5
|
||||||
|
property real sizeLevel: root.width / 5.8
|
||||||
|
property real sizeDesktop: root.width / 5.8
|
||||||
|
property real sizeVR: root.width / 13.5
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: Commerce;
|
||||||
|
|
||||||
|
onWalletStatusResult: {
|
||||||
|
if (walletStatus === 5) {
|
||||||
|
Commerce.getSecurityImage();
|
||||||
|
root.walletSetUp = true;
|
||||||
|
} else {
|
||||||
|
root.walletSetUp = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSecurityImageResult: {
|
||||||
|
if (exists) {
|
||||||
|
currentSecurityPicture.source = "";
|
||||||
|
currentSecurityPicture.source = "image://security/securityImage";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
Commerce.getWalletStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiCommerceCommon.CommerceLightbox {
|
||||||
|
z: 996;
|
||||||
|
id: lightboxPopup;
|
||||||
|
visible: false;
|
||||||
|
anchors.fill: parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
SecurityImageChange {
|
||||||
|
id: securityImageChange;
|
||||||
|
visible: false;
|
||||||
|
z: 997;
|
||||||
|
anchors.top: usernameText.bottom;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
onSendSignalToParent: {
|
||||||
|
securityImageChange.visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Username Text
|
||||||
|
HifiStylesUit.RalewayRegular {
|
||||||
|
id: usernameText;
|
||||||
|
text: Account.username === "Unknown user" ? "Please Log In" : Account.username;
|
||||||
|
// Text size
|
||||||
|
size: 24;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.white;
|
||||||
|
elide: Text.ElideRight;
|
||||||
|
// Anchors
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.leftMargin: 20;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.rightMargin: 20;
|
||||||
|
height: 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: pleaseLogInContainer;
|
||||||
|
visible: Account.username === "Unknown user";
|
||||||
|
anchors.top: usernameText.bottom;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
|
||||||
|
HifiStylesUit.RalewayRegular {
|
||||||
|
text: "Please log in for security settings."
|
||||||
|
// Text size
|
||||||
|
size: 24;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.white;
|
||||||
|
// Anchors
|
||||||
|
anchors.bottom: openLoginButton.top;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
height: 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: openLoginButton;
|
||||||
|
color: hifi.buttons.white;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.centerIn: parent;
|
||||||
|
width: 140;
|
||||||
|
height: 40;
|
||||||
|
text: "Log In";
|
||||||
|
onClicked: {
|
||||||
|
DialogsManager.showLoginDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: securitySettingsContainer;
|
||||||
|
visible: !pleaseLogInContainer.visible;
|
||||||
|
anchors.top: usernameText.bottom;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: accountContainer;
|
||||||
|
anchors.top: securitySettingsContainer.top;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
height: childrenRect.height;
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: accountHeaderContainer;
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
height: 55;
|
||||||
|
color: hifi.colors.baseGrayHighlight;
|
||||||
|
|
||||||
|
HifiStylesUit.RalewaySemiBold {
|
||||||
|
text: "Account";
|
||||||
|
anchors.fill: parent;
|
||||||
|
anchors.leftMargin: 20;
|
||||||
|
color: hifi.colors.white;
|
||||||
|
size: 18;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: keepMeLoggedInContainer;
|
||||||
|
anchors.top: accountHeaderContainer.bottom;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
height: 80;
|
||||||
|
|
||||||
|
HifiControlsUit.CheckBox {
|
||||||
|
id: autoLogoutCheckbox;
|
||||||
|
checked: Settings.getValue("keepMeLoggedIn", false);
|
||||||
|
text: "Keep Me Logged In"
|
||||||
|
// Anchors
|
||||||
|
anchors.verticalCenter: parent.verticalCenter;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.leftMargin: 20;
|
||||||
|
boxSize: 24;
|
||||||
|
labelFontSize: 18;
|
||||||
|
colorScheme: hifi.colorSchemes.dark
|
||||||
|
color: hifi.colors.white;
|
||||||
|
width: 240;
|
||||||
|
onCheckedChanged: {
|
||||||
|
Settings.setValue("keepMeLoggedIn", checked);
|
||||||
|
if (checked) {
|
||||||
|
Settings.setValue("keepMeLoggedIn/savedUsername", Account.username);
|
||||||
|
} else {
|
||||||
|
Settings.setValue("keepMeLoggedIn/savedUsername", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiStylesUit.RalewaySemiBold {
|
||||||
|
id: autoLogoutHelp;
|
||||||
|
text: '[?]';
|
||||||
|
// Anchors
|
||||||
|
anchors.verticalCenter: parent.verticalCenter;
|
||||||
|
anchors.right: autoLogoutCheckbox.right;
|
||||||
|
width: 30;
|
||||||
|
height: 30;
|
||||||
|
// Text size
|
||||||
|
size: 18;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.blueHighlight;
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent;
|
||||||
|
hoverEnabled: true;
|
||||||
|
onEntered: {
|
||||||
|
parent.color = hifi.colors.blueAccent;
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
parent.color = hifi.colors.blueHighlight;
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
lightboxPopup.titleText = "Keep Me Logged In";
|
||||||
|
lightboxPopup.bodyText = "If you choose to stay logged in, ensure that this is a trusted device.\n\n" +
|
||||||
|
"Also, remember that logging out may not disconnect you from a domain.";
|
||||||
|
lightboxPopup.button1text = "OK";
|
||||||
|
lightboxPopup.button1method = function() {
|
||||||
|
lightboxPopup.visible = false;
|
||||||
|
}
|
||||||
|
lightboxPopup.visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: walletContainer;
|
||||||
|
anchors.top: accountContainer.bottom;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
height: childrenRect.height;
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: walletHeaderContainer;
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
height: 55;
|
||||||
|
color: hifi.colors.baseGrayHighlight;
|
||||||
|
|
||||||
|
HifiStylesUit.RalewaySemiBold {
|
||||||
|
text: "Wallet";
|
||||||
|
anchors.fill: parent;
|
||||||
|
anchors.leftMargin: 20;
|
||||||
|
color: hifi.colors.white;
|
||||||
|
size: 18;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: walletSecurityPictureContainer;
|
||||||
|
visible: root.walletSetUp;
|
||||||
|
anchors.top: walletHeaderContainer.bottom;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
height: 80;
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: currentSecurityPicture;
|
||||||
|
source: "";
|
||||||
|
visible: true;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.leftMargin: 20;
|
||||||
|
anchors.verticalCenter: parent.verticalCenter;
|
||||||
|
height: 40;
|
||||||
|
width: height;
|
||||||
|
mipmap: true;
|
||||||
|
cache: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiStylesUit.RalewaySemiBold {
|
||||||
|
id: securityPictureText;
|
||||||
|
text: "Wallet Security Picture";
|
||||||
|
// Anchors
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
anchors.left: currentSecurityPicture.right;
|
||||||
|
anchors.leftMargin: 12;
|
||||||
|
width: paintedWidth;
|
||||||
|
// Text size
|
||||||
|
size: 18;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.white;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Change Security Pic" button
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: changeSecurityImageButton;
|
||||||
|
color: hifi.buttons.white;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.left: securityPictureText.right;
|
||||||
|
anchors.leftMargin: 12;
|
||||||
|
anchors.verticalCenter: parent.verticalCenter;
|
||||||
|
width: 140;
|
||||||
|
height: 40;
|
||||||
|
text: "Change";
|
||||||
|
onClicked: {
|
||||||
|
securityImageChange.visible = true;
|
||||||
|
securityImageChange.initModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: walletNotSetUpContainer;
|
||||||
|
visible: !root.walletSetUp;
|
||||||
|
anchors.top: walletHeaderContainer.bottom;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
height: 60;
|
||||||
|
|
||||||
|
HifiStylesUit.RalewayRegular {
|
||||||
|
text: "Your wallet is not set up.\n" +
|
||||||
|
"Open the WALLET app to get started.";
|
||||||
|
// Anchors
|
||||||
|
anchors.fill: parent;
|
||||||
|
// Text size
|
||||||
|
size: 18;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.white;
|
||||||
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
//
|
//
|
||||||
// SecurityImageChange.qml
|
// SecurityImageChange.qml
|
||||||
// qml/hifi/commerce/wallet
|
// qml\hifi\dialogs\security
|
||||||
//
|
//
|
||||||
// SecurityImageChange
|
// Security
|
||||||
//
|
//
|
||||||
// Created by Zach Fox on 2017-08-18
|
// Created by Zach Fox on 2018-10-31
|
||||||
// Copyright 2017 High Fidelity, Inc.
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
@ -13,16 +13,17 @@
|
||||||
|
|
||||||
import Hifi 1.0 as Hifi
|
import Hifi 1.0 as Hifi
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import "../../../styles-uit"
|
import "qrc:////qml//styles-uit" as HifiStylesUit
|
||||||
import "../../../controls-uit" as HifiControlsUit
|
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||||
import "../../../controls" as HifiControls
|
import "qrc:////qml//controls" as HifiControls
|
||||||
|
|
||||||
// references XXX from root context
|
// references XXX from root context
|
||||||
|
|
||||||
Item {
|
Rectangle {
|
||||||
HifiConstants { id: hifi; }
|
HifiStylesUit.HifiConstants { id: hifi; }
|
||||||
|
|
||||||
id: root;
|
id: root;
|
||||||
|
color: hifi.colors.baseGray;
|
||||||
property bool justSubmitted: false;
|
property bool justSubmitted: false;
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
@ -33,7 +34,7 @@ Item {
|
||||||
securityImageChangePageSecurityImage.source = "image://security/securityImage";
|
securityImageChangePageSecurityImage.source = "image://security/securityImage";
|
||||||
if (exists) { // Success submitting new security image
|
if (exists) { // Success submitting new security image
|
||||||
if (root.justSubmitted) {
|
if (root.justSubmitted) {
|
||||||
sendSignalToWallet({method: "walletSecurity_changeSecurityImageSuccess"});
|
sendSignalToParent({method: "walletSecurity_changeSecurityImageSuccess"});
|
||||||
root.justSubmitted = false;
|
root.justSubmitted = false;
|
||||||
}
|
}
|
||||||
} else if (root.justSubmitted) {
|
} else if (root.justSubmitted) {
|
||||||
|
@ -72,7 +73,7 @@ Item {
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
height: 22;
|
height: 22;
|
||||||
// Lock icon
|
// Lock icon
|
||||||
HiFiGlyphs {
|
HifiStylesUit.HiFiGlyphs {
|
||||||
id: lockIcon;
|
id: lockIcon;
|
||||||
text: hifi.glyphs.lock;
|
text: hifi.glyphs.lock;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
|
@ -83,8 +84,8 @@ Item {
|
||||||
verticalAlignment: Text.AlignBottom;
|
verticalAlignment: Text.AlignBottom;
|
||||||
color: hifi.colors.white;
|
color: hifi.colors.white;
|
||||||
}
|
}
|
||||||
// "Security image" text below pic
|
// "Security image" text below image
|
||||||
RalewayRegular {
|
HifiStylesUit.RalewayRegular {
|
||||||
id: securityImageText;
|
id: securityImageText;
|
||||||
text: "SECURITY PIC";
|
text: "SECURITY PIC";
|
||||||
// Text size
|
// Text size
|
||||||
|
@ -116,9 +117,9 @@ Item {
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
|
|
||||||
// "Change Security Image" text
|
// "Change Security Image" text
|
||||||
RalewaySemiBold {
|
HifiStylesUit.RalewaySemiBold {
|
||||||
id: securityImageTitle;
|
id: securityImageTitle;
|
||||||
text: "Change Security Pic:";
|
text: "Change Security Image:";
|
||||||
// Text size
|
// Text size
|
||||||
size: 18;
|
size: 18;
|
||||||
anchors.top: parent.top;
|
anchors.top: parent.top;
|
||||||
|
@ -139,12 +140,6 @@ Item {
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
anchors.rightMargin: 16;
|
anchors.rightMargin: 16;
|
||||||
height: 300;
|
height: 300;
|
||||||
|
|
||||||
Connections {
|
|
||||||
onSendSignalToWallet: {
|
|
||||||
sendSignalToWallet(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Navigation Bar
|
// Navigation Bar
|
||||||
|
@ -169,7 +164,7 @@ Item {
|
||||||
width: 150;
|
width: 150;
|
||||||
text: "Cancel"
|
text: "Cancel"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
sendSignalToWallet({method: "walletSecurity_changeSecurityImageCancelled"});
|
sendSignalToParent({method: "walletSecurity_changeSecurityImageCancelled"});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +192,7 @@ Item {
|
||||||
// SECURITY IMAGE SELECTION END
|
// SECURITY IMAGE SELECTION END
|
||||||
//
|
//
|
||||||
|
|
||||||
signal sendSignalToWallet(var msg);
|
signal sendSignalToParent(var msg);
|
||||||
|
|
||||||
function initModel() {
|
function initModel() {
|
||||||
securityImageSelection.initModel();
|
securityImageSelection.initModel();
|
|
@ -1,11 +1,11 @@
|
||||||
//
|
//
|
||||||
// SecurityImageModel.qml
|
// SecurityImageModel.qml
|
||||||
// qml/hifi/commerce
|
// qml\hifi\dialogs\security
|
||||||
//
|
//
|
||||||
// SecurityImageModel
|
// Security
|
||||||
//
|
//
|
||||||
// Created by Zach Fox on 2017-08-17
|
// Created by Zach Fox on 2018-10-31
|
||||||
// Copyright 2017 High Fidelity, Inc.
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
@ -1,11 +1,11 @@
|
||||||
//
|
//
|
||||||
// SecurityImageSelection.qml
|
// SecurityImageSelection.qml
|
||||||
// qml/hifi/commerce/wallet
|
// qml\hifi\dialogs\security
|
||||||
//
|
//
|
||||||
// SecurityImageSelection
|
// Security
|
||||||
//
|
//
|
||||||
// Created by Zach Fox on 2017-08-17
|
// Created by Zach Fox on 2018-10-31
|
||||||
// Copyright 2017 High Fidelity, Inc.
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
@ -13,14 +13,14 @@
|
||||||
|
|
||||||
import Hifi 1.0 as Hifi
|
import Hifi 1.0 as Hifi
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import "../../../styles-uit"
|
import "qrc:////qml//styles-uit" as HifiStylesUit
|
||||||
import "../../../controls-uit" as HifiControlsUit
|
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||||
import "../../../controls" as HifiControls
|
import "qrc:////qml//controls" as HifiControls
|
||||||
|
|
||||||
// references XXX from root context
|
// references XXX from root context
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
HifiConstants { id: hifi; }
|
HifiStylesUit.HifiConstants { id: hifi; }
|
||||||
|
|
||||||
id: root;
|
id: root;
|
||||||
property alias currentIndex: securityImageGrid.currentIndex;
|
property alias currentIndex: securityImageGrid.currentIndex;
|
||||||
|
@ -64,17 +64,15 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
highlight: Rectangle {
|
highlight: Rectangle {
|
||||||
width: securityImageGrid.cellWidth;
|
width: securityImageGrid.cellWidth;
|
||||||
height: securityImageGrid.cellHeight;
|
height: securityImageGrid.cellHeight;
|
||||||
color: hifi.colors.blueHighlight;
|
color: hifi.colors.blueHighlight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// FUNCTION DEFINITIONS START
|
// FUNCTION DEFINITIONS START
|
||||||
//
|
//
|
||||||
signal sendSignalToWallet(var msg);
|
|
||||||
|
|
||||||
function getImagePathFromImageID(imageID) {
|
function getImagePathFromImageID(imageID) {
|
||||||
return (imageID ? gridModel.getImagePathFromImageID(imageID) : "");
|
return (imageID ? gridModel.getImagePathFromImageID(imageID) : "");
|
||||||
}
|
}
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
@ -175,7 +175,7 @@ TabBar {
|
||||||
method: "newEntityButtonClicked",
|
method: "newEntityButtonClicked",
|
||||||
params: { buttonName: "newParticleButton" }
|
params: { buttonName: "newParticleButton" }
|
||||||
});
|
});
|
||||||
editTabView.currentIndex = 4
|
editTabView.currentIndex = 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,21 +279,6 @@ TabBar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EditTabButton {
|
|
||||||
title: "P"
|
|
||||||
active: true
|
|
||||||
enabled: true
|
|
||||||
property string originalUrl: ""
|
|
||||||
|
|
||||||
property Component visualItem: Component {
|
|
||||||
WebView {
|
|
||||||
id: particleExplorerWebView
|
|
||||||
url: Paths.defaultScripts + "/system/particle_explorer/particleExplorer.html"
|
|
||||||
enabled: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function fromScript(message) {
|
function fromScript(message) {
|
||||||
switch (message.method) {
|
switch (message.method) {
|
||||||
case 'selectTab':
|
case 'selectTab':
|
||||||
|
@ -326,9 +311,6 @@ TabBar {
|
||||||
case 'grid':
|
case 'grid':
|
||||||
editTabView.currentIndex = 3;
|
editTabView.currentIndex = 3;
|
||||||
break;
|
break;
|
||||||
case 'particle':
|
|
||||||
editTabView.currentIndex = 4;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
console.warn('Attempt to switch to invalid tab:', id);
|
console.warn('Attempt to switch to invalid tab:', id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ TabBar {
|
||||||
readonly property int create: 0
|
readonly property int create: 0
|
||||||
readonly property int properties: 1
|
readonly property int properties: 1
|
||||||
readonly property int grid: 2
|
readonly property int grid: 2
|
||||||
readonly property int particle: 3
|
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property HifiConstants hifi: HifiConstants {}
|
readonly property HifiConstants hifi: HifiConstants {}
|
||||||
|
@ -182,7 +181,7 @@ TabBar {
|
||||||
method: "newEntityButtonClicked",
|
method: "newEntityButtonClicked",
|
||||||
params: { buttonName: "newParticleButton" }
|
params: { buttonName: "newParticleButton" }
|
||||||
});
|
});
|
||||||
editTabView.currentIndex = tabIndex.particle
|
editTabView.currentIndex = tabIndex.properties
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,21 +270,6 @@ TabBar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EditTabButton {
|
|
||||||
title: "P"
|
|
||||||
active: true
|
|
||||||
enabled: true
|
|
||||||
property string originalUrl: ""
|
|
||||||
|
|
||||||
property Component visualItem: Component {
|
|
||||||
WebView {
|
|
||||||
id: particleExplorerWebView
|
|
||||||
url: Paths.defaultScripts + "/system/particle_explorer/particleExplorer.html"
|
|
||||||
enabled: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function fromScript(message) {
|
function fromScript(message) {
|
||||||
switch (message.method) {
|
switch (message.method) {
|
||||||
case 'selectTab':
|
case 'selectTab':
|
||||||
|
@ -299,7 +283,7 @@ TabBar {
|
||||||
// Changes the current tab based on tab index or title as input
|
// Changes the current tab based on tab index or title as input
|
||||||
function selectTab(id) {
|
function selectTab(id) {
|
||||||
if (typeof id === 'number') {
|
if (typeof id === 'number') {
|
||||||
if (id >= tabIndex.create && id <= tabIndex.particle) {
|
if (id >= tabIndex.create && id <= tabIndex.grid) {
|
||||||
editTabView.currentIndex = id;
|
editTabView.currentIndex = id;
|
||||||
} else {
|
} else {
|
||||||
console.warn('Attempt to switch to invalid tab:', id);
|
console.warn('Attempt to switch to invalid tab:', id);
|
||||||
|
@ -315,9 +299,6 @@ TabBar {
|
||||||
case 'grid':
|
case 'grid':
|
||||||
editTabView.currentIndex = tabIndex.grid;
|
editTabView.currentIndex = tabIndex.grid;
|
||||||
break;
|
break;
|
||||||
case 'particle':
|
|
||||||
editTabView.currentIndex = tabIndex.particle;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
console.warn('Attempt to switch to invalid tab:', id);
|
console.warn('Attempt to switch to invalid tab:', id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,9 +116,14 @@ Rectangle {
|
||||||
Column {
|
Column {
|
||||||
id: column2
|
id: column2
|
||||||
width: 200
|
width: 200
|
||||||
height: 400
|
height: 600
|
||||||
spacing: 10
|
spacing: 10
|
||||||
|
|
||||||
|
CheckBox {
|
||||||
|
id: grabbable
|
||||||
|
text: qsTr("Grabbable")
|
||||||
|
}
|
||||||
|
|
||||||
CheckBox {
|
CheckBox {
|
||||||
id: dynamic
|
id: dynamic
|
||||||
text: qsTr("Dynamic")
|
text: qsTr("Dynamic")
|
||||||
|
@ -217,9 +222,10 @@ Rectangle {
|
||||||
newModelDialog.sendToScript({
|
newModelDialog.sendToScript({
|
||||||
method: "newModelDialogAdd",
|
method: "newModelDialogAdd",
|
||||||
params: {
|
params: {
|
||||||
textInput: modelURL.text,
|
url: modelURL.text,
|
||||||
checkBox: dynamic.checked,
|
dynamic: dynamic.checked,
|
||||||
comboBox: collisionType.currentIndex
|
collisionShapeIndex: collisionType.currentIndex,
|
||||||
|
grabbable: grabbable.checked
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -822,11 +822,44 @@ Flickable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: outOfRangeDataStrategyRow
|
||||||
|
anchors.top: viveInDesktop.bottom
|
||||||
|
anchors.topMargin: 5
|
||||||
|
anchors.left: openVrConfiguration.left
|
||||||
|
anchors.leftMargin: leftMargin + 10
|
||||||
|
spacing: 15
|
||||||
|
|
||||||
|
RalewayRegular {
|
||||||
|
id: outOfRangeDataStrategyLabel
|
||||||
|
size: 12
|
||||||
|
text: "Out Of Range Data Strategy:"
|
||||||
|
color: hifi.colors.lightGrayText
|
||||||
|
topPadding: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControls.ComboBox {
|
||||||
|
id: outOfRangeDataStrategyComboBox
|
||||||
|
|
||||||
|
height: 25
|
||||||
|
width: 100
|
||||||
|
|
||||||
|
editable: true
|
||||||
|
colorScheme: hifi.colorSchemes.dark
|
||||||
|
model: ["None", "Freeze", "Drop"]
|
||||||
|
label: ""
|
||||||
|
|
||||||
|
onCurrentIndexChanged: {
|
||||||
|
sendConfigurationSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RalewayBold {
|
RalewayBold {
|
||||||
id: viveDesktopText
|
id: viveDesktopText
|
||||||
size: 10
|
size: 12
|
||||||
text: "Use " + stack.selectedPlugin + " devices in desktop mode"
|
text: "Use " + stack.selectedPlugin + " devices in desktop mode"
|
||||||
color: hifi.colors.white
|
color: hifi.colors.lightGrayText
|
||||||
|
|
||||||
anchors {
|
anchors {
|
||||||
left: viveInDesktop.right
|
left: viveInDesktop.right
|
||||||
|
@ -946,6 +979,7 @@ Flickable {
|
||||||
|
|
||||||
viveInDesktop.checked = desktopMode;
|
viveInDesktop.checked = desktopMode;
|
||||||
hmdInDesktop.checked = hmdDesktopPosition;
|
hmdInDesktop.checked = hmdDesktopPosition;
|
||||||
|
outOfRangeDataStrategyComboBox.currentIndex = outOfRangeDataStrategyComboBox.model.indexOf(settings.outOfRangeDataStrategy);
|
||||||
|
|
||||||
initializeButtonState();
|
initializeButtonState();
|
||||||
updateCalibrationText();
|
updateCalibrationText();
|
||||||
|
@ -1107,7 +1141,8 @@ Flickable {
|
||||||
"armCircumference": armCircumference.realValue,
|
"armCircumference": armCircumference.realValue,
|
||||||
"shoulderWidth": shoulderWidth.realValue,
|
"shoulderWidth": shoulderWidth.realValue,
|
||||||
"desktopMode": viveInDesktop.checked,
|
"desktopMode": viveInDesktop.checked,
|
||||||
"hmdDesktopTracking": hmdInDesktop.checked
|
"hmdDesktopTracking": hmdInDesktop.checked,
|
||||||
|
"outOfRangeDataStrategy": outOfRangeDataStrategyComboBox.model[outOfRangeDataStrategyComboBox.currentIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
return settingsObject;
|
return settingsObject;
|
||||||
|
|
|
@ -52,6 +52,8 @@
|
||||||
#include <QTemporaryDir>
|
#include <QTemporaryDir>
|
||||||
|
|
||||||
#include <gl/QOpenGLContextWrapper.h>
|
#include <gl/QOpenGLContextWrapper.h>
|
||||||
|
#include <gl/GLWindow.h>
|
||||||
|
#include <gl/GLHelpers.h>
|
||||||
|
|
||||||
#include <shared/FileUtils.h>
|
#include <shared/FileUtils.h>
|
||||||
#include <shared/QtHelpers.h>
|
#include <shared/QtHelpers.h>
|
||||||
|
@ -226,6 +228,7 @@
|
||||||
#include "commerce/Ledger.h"
|
#include "commerce/Ledger.h"
|
||||||
#include "commerce/Wallet.h"
|
#include "commerce/Wallet.h"
|
||||||
#include "commerce/QmlCommerce.h"
|
#include "commerce/QmlCommerce.h"
|
||||||
|
#include "ResourceRequestObserver.h"
|
||||||
|
|
||||||
#include "webbrowser/WebBrowserSuggestionsEngine.h"
|
#include "webbrowser/WebBrowserSuggestionsEngine.h"
|
||||||
#include <DesktopPreviewProvider.h>
|
#include <DesktopPreviewProvider.h>
|
||||||
|
@ -379,7 +382,7 @@ static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds
|
||||||
static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop";
|
static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop";
|
||||||
static const QString ACTIVE_DISPLAY_PLUGIN_SETTING_NAME = "activeDisplayPlugin";
|
static const QString ACTIVE_DISPLAY_PLUGIN_SETTING_NAME = "activeDisplayPlugin";
|
||||||
static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
|
static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
|
||||||
static const QString AUTO_LOGOUT_SETTING_NAME = "wallet/autoLogout";
|
static const QString KEEP_ME_LOGGED_IN_SETTING_NAME = "keepMeLoggedIn";
|
||||||
|
|
||||||
const std::vector<std::pair<QString, Application::AcceptURLMethod>> Application::_acceptedExtensions {
|
const std::vector<std::pair<QString, Application::AcceptURLMethod>> Application::_acceptedExtensions {
|
||||||
{ SVO_EXTENSION, &Application::importSVOFromURL },
|
{ SVO_EXTENSION, &Application::importSVOFromURL },
|
||||||
|
@ -947,6 +950,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
||||||
DependencyManager::set<WalletScriptingInterface>();
|
DependencyManager::set<WalletScriptingInterface>();
|
||||||
|
|
||||||
DependencyManager::set<FadeEffect>();
|
DependencyManager::set<FadeEffect>();
|
||||||
|
DependencyManager::set<ResourceRequestObserver>();
|
||||||
|
|
||||||
return previousSessionCrashed;
|
return previousSessionCrashed;
|
||||||
}
|
}
|
||||||
|
@ -969,9 +973,11 @@ OffscreenGLCanvas* _qmlShareContext { nullptr };
|
||||||
// and manually set THAT to be the shared context for the Chromium helper
|
// and manually set THAT to be the shared context for the Chromium helper
|
||||||
#if !defined(DISABLE_QML)
|
#if !defined(DISABLE_QML)
|
||||||
OffscreenGLCanvas* _chromiumShareContext { nullptr };
|
OffscreenGLCanvas* _chromiumShareContext { nullptr };
|
||||||
Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext *context);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext *context);
|
||||||
|
Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context();
|
||||||
|
|
||||||
Setting::Handle<int> sessionRunTime{ "sessionRunTime", 0 };
|
Setting::Handle<int> sessionRunTime{ "sessionRunTime", 0 };
|
||||||
|
|
||||||
const float DEFAULT_HMD_TABLET_SCALE_PERCENT = 60.0f;
|
const float DEFAULT_HMD_TABLET_SCALE_PERCENT = 60.0f;
|
||||||
|
@ -1368,7 +1374,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
_glWidget->setMouseTracking(true);
|
_glWidget->setMouseTracking(true);
|
||||||
// Make sure the window is set to the correct size by processing the pending events
|
// Make sure the window is set to the correct size by processing the pending events
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
_glWidget->createContext();
|
|
||||||
|
|
||||||
// Create the main thread context, the GPU backend
|
// Create the main thread context, the GPU backend
|
||||||
initializeGL();
|
initializeGL();
|
||||||
|
@ -2562,8 +2567,8 @@ void Application::cleanupBeforeQuit() {
|
||||||
}
|
}
|
||||||
DependencyManager::destroy<ScriptEngines>();
|
DependencyManager::destroy<ScriptEngines>();
|
||||||
|
|
||||||
bool autoLogout = Setting::Handle<bool>(AUTO_LOGOUT_SETTING_NAME, false).get();
|
bool keepMeLoggedIn = Setting::Handle<bool>(KEEP_ME_LOGGED_IN_SETTING_NAME, false).get();
|
||||||
if (autoLogout) {
|
if (!keepMeLoggedIn) {
|
||||||
DependencyManager::get<AccountManager>()->removeAccountFromFile();
|
DependencyManager::get<AccountManager>()->removeAccountFromFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2725,46 +2730,66 @@ void Application::initializeGL() {
|
||||||
_isGLInitialized = true;
|
_isGLInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_glWidget->makeCurrent()) {
|
_glWidget->windowHandle()->setFormat(getDefaultOpenGLSurfaceFormat());
|
||||||
qCWarning(interfaceapp, "Unable to make window context current");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// When loading QtWebEngineWidgets, it creates a global share context on startup.
|
||||||
|
// We have to account for this possibility by checking here for an existing
|
||||||
|
// global share context
|
||||||
|
auto globalShareContext = qt_gl_global_share_context();
|
||||||
|
|
||||||
#if !defined(DISABLE_QML)
|
#if !defined(DISABLE_QML)
|
||||||
// Build a shared canvas / context for the Chromium processes
|
// Build a shared canvas / context for the Chromium processes
|
||||||
{
|
if (!globalShareContext) {
|
||||||
// Disable signed distance field font rendering on ATI/AMD GPUs, due to
|
|
||||||
// https://highfidelity.manuscript.com/f/cases/13677/Text-showing-up-white-on-Marketplace-app
|
|
||||||
std::string vendor{ (const char*)glGetString(GL_VENDOR) };
|
|
||||||
if ((vendor.find("AMD") != std::string::npos) || (vendor.find("ATI") != std::string::npos)) {
|
|
||||||
qputenv("QTWEBENGINE_CHROMIUM_FLAGS", QByteArray("--disable-distance-field-text"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chromium rendering uses some GL functions that prevent nSight from capturing
|
// Chromium rendering uses some GL functions that prevent nSight from capturing
|
||||||
// frames, so we only create the shared context if nsight is NOT active.
|
// frames, so we only create the shared context if nsight is NOT active.
|
||||||
if (!nsightActive()) {
|
if (!nsightActive()) {
|
||||||
_chromiumShareContext = new OffscreenGLCanvas();
|
_chromiumShareContext = new OffscreenGLCanvas();
|
||||||
_chromiumShareContext->setObjectName("ChromiumShareContext");
|
_chromiumShareContext->setObjectName("ChromiumShareContext");
|
||||||
_chromiumShareContext->create(_glWidget->qglContext());
|
auto format =QSurfaceFormat::defaultFormat();
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
// On mac, the primary shared OpenGL context must be a 3.2 core context,
|
||||||
|
// or chromium flips out and spews error spam (but renders fine)
|
||||||
|
format.setMajorVersion(3);
|
||||||
|
format.setMinorVersion(2);
|
||||||
|
#endif
|
||||||
|
_chromiumShareContext->setFormat(format);
|
||||||
|
_chromiumShareContext->create();
|
||||||
if (!_chromiumShareContext->makeCurrent()) {
|
if (!_chromiumShareContext->makeCurrent()) {
|
||||||
qCWarning(interfaceapp, "Unable to make chromium shared context current");
|
qCWarning(interfaceapp, "Unable to make chromium shared context current");
|
||||||
}
|
}
|
||||||
qt_gl_set_global_share_context(_chromiumShareContext->getContext());
|
globalShareContext = _chromiumShareContext->getContext();
|
||||||
|
qt_gl_set_global_share_context(globalShareContext);
|
||||||
_chromiumShareContext->doneCurrent();
|
_chromiumShareContext->doneCurrent();
|
||||||
// Restore the GL widget context
|
|
||||||
if (!_glWidget->makeCurrent()) {
|
|
||||||
qCWarning(interfaceapp, "Unable to make window context current");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
qCWarning(interfaceapp) << "nSight detected, disabling chrome rendering";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
_glWidget->createContext(globalShareContext);
|
||||||
|
|
||||||
|
if (!_glWidget->makeCurrent()) {
|
||||||
|
qCWarning(interfaceapp, "Unable to make window context current");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(DISABLE_QML)
|
||||||
|
// Disable signed distance field font rendering on ATI/AMD GPUs, due to
|
||||||
|
// https://highfidelity.manuscript.com/f/cases/13677/Text-showing-up-white-on-Marketplace-app
|
||||||
|
std::string vendor{ (const char*)glGetString(GL_VENDOR) };
|
||||||
|
if ((vendor.find("AMD") != std::string::npos) || (vendor.find("ATI") != std::string::npos)) {
|
||||||
|
qputenv("QTWEBENGINE_CHROMIUM_FLAGS", QByteArray("--disable-distance-field-text"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!globalShareContext) {
|
||||||
|
globalShareContext = _glWidget->qglContext();
|
||||||
|
qt_gl_set_global_share_context(globalShareContext);
|
||||||
|
}
|
||||||
|
|
||||||
// Build a shared canvas / context for the QML rendering
|
// Build a shared canvas / context for the QML rendering
|
||||||
{
|
{
|
||||||
_qmlShareContext = new OffscreenGLCanvas();
|
_qmlShareContext = new OffscreenGLCanvas();
|
||||||
_qmlShareContext->setObjectName("QmlShareContext");
|
_qmlShareContext->setObjectName("QmlShareContext");
|
||||||
_qmlShareContext->create(_glWidget->qglContext());
|
_qmlShareContext->create(globalShareContext);
|
||||||
if (!_qmlShareContext->makeCurrent()) {
|
if (!_qmlShareContext->makeCurrent()) {
|
||||||
qCWarning(interfaceapp, "Unable to make QML shared context current");
|
qCWarning(interfaceapp, "Unable to make QML shared context current");
|
||||||
}
|
}
|
||||||
|
@ -2919,13 +2944,13 @@ void Application::initializeUi() {
|
||||||
QUrl{ "hifi/commerce/wallet/PassphraseChange.qml" },
|
QUrl{ "hifi/commerce/wallet/PassphraseChange.qml" },
|
||||||
QUrl{ "hifi/commerce/wallet/PassphraseModal.qml" },
|
QUrl{ "hifi/commerce/wallet/PassphraseModal.qml" },
|
||||||
QUrl{ "hifi/commerce/wallet/PassphraseSelection.qml" },
|
QUrl{ "hifi/commerce/wallet/PassphraseSelection.qml" },
|
||||||
QUrl{ "hifi/commerce/wallet/Security.qml" },
|
|
||||||
QUrl{ "hifi/commerce/wallet/SecurityImageChange.qml" },
|
|
||||||
QUrl{ "hifi/commerce/wallet/SecurityImageModel.qml" },
|
|
||||||
QUrl{ "hifi/commerce/wallet/SecurityImageSelection.qml" },
|
|
||||||
QUrl{ "hifi/commerce/wallet/Wallet.qml" },
|
QUrl{ "hifi/commerce/wallet/Wallet.qml" },
|
||||||
QUrl{ "hifi/commerce/wallet/WalletHome.qml" },
|
QUrl{ "hifi/commerce/wallet/WalletHome.qml" },
|
||||||
QUrl{ "hifi/commerce/wallet/WalletSetup.qml" },
|
QUrl{ "hifi/commerce/wallet/WalletSetup.qml" },
|
||||||
|
QUrl{ "hifi/dialogs/security/Security.qml" },
|
||||||
|
QUrl{ "hifi/dialogs/security/SecurityImageChange.qml" },
|
||||||
|
QUrl{ "hifi/dialogs/security/SecurityImageModel.qml" },
|
||||||
|
QUrl{ "hifi/dialogs/security/SecurityImageSelection.qml" },
|
||||||
}, callback);
|
}, callback);
|
||||||
qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem");
|
qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem");
|
||||||
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
|
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
|
||||||
|
@ -3129,6 +3154,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
|
||||||
surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
|
surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
|
||||||
surfaceContext->setContextProperty("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
surfaceContext->setContextProperty("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
||||||
surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance());
|
surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance());
|
||||||
|
surfaceContext->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||||
|
|
||||||
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
||||||
surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
|
surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
|
||||||
|
@ -5022,12 +5048,12 @@ void Application::saveSettings() const {
|
||||||
PluginManager::getInstance()->saveSettings();
|
PluginManager::getInstance()->saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::importEntities(const QString& urlOrFilename) {
|
bool Application::importEntities(const QString& urlOrFilename, const bool isObservable, const qint64 callerId) {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
_entityClipboard->withWriteLock([&] {
|
_entityClipboard->withWriteLock([&] {
|
||||||
_entityClipboard->eraseAllOctreeElements();
|
_entityClipboard->eraseAllOctreeElements();
|
||||||
|
|
||||||
success = _entityClipboard->readFromURL(urlOrFilename);
|
success = _entityClipboard->readFromURL(urlOrFilename, isObservable, callerId);
|
||||||
if (success) {
|
if (success) {
|
||||||
_entityClipboard->reaverageOctreeElements();
|
_entityClipboard->reaverageOctreeElements();
|
||||||
}
|
}
|
||||||
|
@ -5812,6 +5838,42 @@ void Application::update(float deltaTime) {
|
||||||
controller::Pose pose = userInputMapper->getPoseState(action);
|
controller::Pose pose = userInputMapper->getPoseState(action);
|
||||||
myAvatar->setControllerPoseInSensorFrame(action, pose.transform(avatarToSensorMatrix));
|
myAvatar->setControllerPoseInSensorFrame(action, pose.transform(avatarToSensorMatrix));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const std::vector<QString> trackedObjectStringLiterals = {
|
||||||
|
QStringLiteral("_TrackedObject00"), QStringLiteral("_TrackedObject01"), QStringLiteral("_TrackedObject02"), QStringLiteral("_TrackedObject03"),
|
||||||
|
QStringLiteral("_TrackedObject04"), QStringLiteral("_TrackedObject05"), QStringLiteral("_TrackedObject06"), QStringLiteral("_TrackedObject07"),
|
||||||
|
QStringLiteral("_TrackedObject08"), QStringLiteral("_TrackedObject09"), QStringLiteral("_TrackedObject10"), QStringLiteral("_TrackedObject11"),
|
||||||
|
QStringLiteral("_TrackedObject12"), QStringLiteral("_TrackedObject13"), QStringLiteral("_TrackedObject14"), QStringLiteral("_TrackedObject15")
|
||||||
|
};
|
||||||
|
|
||||||
|
// Controlled by the Developer > Avatar > Show Tracked Objects menu.
|
||||||
|
if (_showTrackedObjects) {
|
||||||
|
static const std::vector<controller::Action> trackedObjectActions = {
|
||||||
|
controller::Action::TRACKED_OBJECT_00, controller::Action::TRACKED_OBJECT_01, controller::Action::TRACKED_OBJECT_02, controller::Action::TRACKED_OBJECT_03,
|
||||||
|
controller::Action::TRACKED_OBJECT_04, controller::Action::TRACKED_OBJECT_05, controller::Action::TRACKED_OBJECT_06, controller::Action::TRACKED_OBJECT_07,
|
||||||
|
controller::Action::TRACKED_OBJECT_08, controller::Action::TRACKED_OBJECT_09, controller::Action::TRACKED_OBJECT_10, controller::Action::TRACKED_OBJECT_11,
|
||||||
|
controller::Action::TRACKED_OBJECT_12, controller::Action::TRACKED_OBJECT_13, controller::Action::TRACKED_OBJECT_14, controller::Action::TRACKED_OBJECT_15
|
||||||
|
};
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
glm::vec4 BLUE(0.0f, 0.0f, 1.0f, 1.0f);
|
||||||
|
for (auto& action : trackedObjectActions) {
|
||||||
|
controller::Pose pose = userInputMapper->getPoseState(action);
|
||||||
|
if (pose.valid) {
|
||||||
|
glm::vec3 pos = transformPoint(myAvatarMatrix, pose.translation);
|
||||||
|
glm::quat rot = glmExtractRotation(myAvatarMatrix) * pose.rotation;
|
||||||
|
DebugDraw::getInstance().addMarker(trackedObjectStringLiterals[i], rot, pos, BLUE);
|
||||||
|
} else {
|
||||||
|
DebugDraw::getInstance().removeMarker(trackedObjectStringLiterals[i]);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
} else if (_prevShowTrackedObjects) {
|
||||||
|
for (auto& key : trackedObjectStringLiterals) {
|
||||||
|
DebugDraw::getInstance().removeMarker(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_prevShowTrackedObjects = _showTrackedObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
||||||
|
@ -5978,7 +6040,9 @@ void Application::update(float deltaTime) {
|
||||||
{
|
{
|
||||||
PROFILE_RANGE_EX(app, "Overlays", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
PROFILE_RANGE_EX(app, "Overlays", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||||
PerformanceTimer perfTimer("overlays");
|
PerformanceTimer perfTimer("overlays");
|
||||||
_overlays.update(deltaTime);
|
if (qApp->shouldPaint()) {
|
||||||
|
_overlays.update(deltaTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update _viewFrustum with latest camera and view frustum data...
|
// Update _viewFrustum with latest camera and view frustum data...
|
||||||
|
@ -6063,8 +6127,10 @@ void Application::update(float deltaTime) {
|
||||||
PROFILE_RANGE_EX(app, "PostUpdateLambdas", 0xffff0000, (uint64_t)0);
|
PROFILE_RANGE_EX(app, "PostUpdateLambdas", 0xffff0000, (uint64_t)0);
|
||||||
PerformanceTimer perfTimer("postUpdateLambdas");
|
PerformanceTimer perfTimer("postUpdateLambdas");
|
||||||
std::unique_lock<std::mutex> guard(_postUpdateLambdasLock);
|
std::unique_lock<std::mutex> guard(_postUpdateLambdasLock);
|
||||||
for (auto& iter : _postUpdateLambdas) {
|
if (qApp->shouldPaint()) {
|
||||||
iter.second();
|
for (auto& iter : _postUpdateLambdas) {
|
||||||
|
iter.second();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_postUpdateLambdas.clear();
|
_postUpdateLambdas.clear();
|
||||||
}
|
}
|
||||||
|
@ -6811,6 +6877,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
||||||
scriptEngine->registerGlobalObject("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
scriptEngine->registerGlobalObject("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
||||||
scriptEngine->registerGlobalObject("AddressManager", DependencyManager::get<AddressManager>().data());
|
scriptEngine->registerGlobalObject("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||||
scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance());
|
scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance());
|
||||||
|
scriptEngine->registerGlobalObject("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||||
|
|
||||||
qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
|
qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
|
||||||
|
|
||||||
|
@ -7197,7 +7264,8 @@ void Application::addAssetToWorldFromURL(QString url) {
|
||||||
|
|
||||||
addAssetToWorldInfo(filename, "Downloading model file " + filename + ".");
|
addAssetToWorldInfo(filename, "Downloading model file " + filename + ".");
|
||||||
|
|
||||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(nullptr, QUrl(url));
|
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||||
|
nullptr, QUrl(url), true, -1, "Application::addAssetToWorldFromURL");
|
||||||
connect(request, &ResourceRequest::finished, this, &Application::addAssetToWorldFromURLRequestFinished);
|
connect(request, &ResourceRequest::finished, this, &Application::addAssetToWorldFromURLRequestFinished);
|
||||||
request->send();
|
request->send();
|
||||||
}
|
}
|
||||||
|
@ -8306,6 +8374,10 @@ void Application::setShowBulletConstraintLimits(bool value) {
|
||||||
_physicsEngine->setShowBulletConstraintLimits(value);
|
_physicsEngine->setShowBulletConstraintLimits(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::setShowTrackedObjects(bool value) {
|
||||||
|
_showTrackedObjects = value;
|
||||||
|
}
|
||||||
|
|
||||||
void Application::startHMDStandBySession() {
|
void Application::startHMDStandBySession() {
|
||||||
_autoSwitchDisplayModeSupportedHMDPlugin->startStandBySession();
|
_autoSwitchDisplayModeSupportedHMDPlugin->startStandBySession();
|
||||||
}
|
}
|
||||||
|
|
|
@ -342,7 +342,7 @@ public slots:
|
||||||
QVector<EntityItemID> pasteEntities(float x, float y, float z);
|
QVector<EntityItemID> pasteEntities(float x, float y, float z);
|
||||||
bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs, const glm::vec3* givenOffset = nullptr);
|
bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs, const glm::vec3* givenOffset = nullptr);
|
||||||
bool exportEntities(const QString& filename, float x, float y, float z, float scale);
|
bool exportEntities(const QString& filename, float x, float y, float z, float scale);
|
||||||
bool importEntities(const QString& url);
|
bool importEntities(const QString& url, const bool isObservable = true, const qint64 callerId = -1);
|
||||||
void updateThreadPoolCount() const;
|
void updateThreadPoolCount() const;
|
||||||
void updateSystemTabletMode();
|
void updateSystemTabletMode();
|
||||||
void goToErrorDomainURL(QUrl errorDomainURL);
|
void goToErrorDomainURL(QUrl errorDomainURL);
|
||||||
|
@ -498,6 +498,8 @@ private slots:
|
||||||
void setShowBulletConstraints(bool value);
|
void setShowBulletConstraints(bool value);
|
||||||
void setShowBulletConstraintLimits(bool value);
|
void setShowBulletConstraintLimits(bool value);
|
||||||
|
|
||||||
|
void setShowTrackedObjects(bool value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
bool handleKeyEventForFocusedEntityOrOverlay(QEvent* event);
|
bool handleKeyEventForFocusedEntityOrOverlay(QEvent* event);
|
||||||
|
@ -779,5 +781,8 @@ private:
|
||||||
std::atomic<bool> _pendingRenderEvent { true };
|
std::atomic<bool> _pendingRenderEvent { true };
|
||||||
|
|
||||||
bool quitWhenFinished { false };
|
bool quitWhenFinished { false };
|
||||||
|
|
||||||
|
bool _showTrackedObjects { false };
|
||||||
|
bool _prevShowTrackedObjects { false };
|
||||||
};
|
};
|
||||||
#endif // hifi_Application_h
|
#endif // hifi_Application_h
|
||||||
|
|
|
@ -265,6 +265,18 @@ Menu::Menu() {
|
||||||
QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog");
|
QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Settings > Security...
|
||||||
|
action = addActionToQMenuAndActionHash(settingsMenu, "Security...");
|
||||||
|
connect(action, &QAction::triggered, [] {
|
||||||
|
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||||
|
tablet->pushOntoStack("hifi/dialogs/security/Security.qml");
|
||||||
|
|
||||||
|
if (!hmd->getShouldShowTablet()) {
|
||||||
|
hmd->toggleShouldShowTablet();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Settings > Developer Menu
|
// Settings > Developer Menu
|
||||||
addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus()));
|
addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus()));
|
||||||
|
|
||||||
|
@ -273,15 +285,71 @@ Menu::Menu() {
|
||||||
|
|
||||||
// Developer menu ----------------------------------
|
// Developer menu ----------------------------------
|
||||||
MenuWrapper* developerMenu = addMenu("Developer", "Developer");
|
MenuWrapper* developerMenu = addMenu("Developer", "Developer");
|
||||||
|
|
||||||
|
// Developer > Scripting >>>
|
||||||
|
MenuWrapper* scriptingOptionsMenu = developerMenu->addMenu("Scripting");
|
||||||
|
|
||||||
|
// Developer > Scripting > Console...
|
||||||
|
addActionToQMenuAndActionHash(scriptingOptionsMenu, MenuOption::Console, Qt::CTRL | Qt::ALT | Qt::Key_J,
|
||||||
|
DependencyManager::get<StandAloneJSConsole>().data(),
|
||||||
|
SLOT(toggleConsole()),
|
||||||
|
QAction::NoRole,
|
||||||
|
UNSPECIFIED_POSITION);
|
||||||
|
|
||||||
|
// Developer > Scripting > API Debugger
|
||||||
|
action = addActionToQMenuAndActionHash(scriptingOptionsMenu, "API Debugger");
|
||||||
|
connect(action, &QAction::triggered, [] {
|
||||||
|
QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
|
||||||
|
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/utilities/tools/currentAPI.js");
|
||||||
|
DependencyManager::get<ScriptEngines>()->loadScript(defaultScriptsLoc.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
// Developer > Scripting > Entity Script Server Log
|
||||||
|
auto essLogAction = addActionToQMenuAndActionHash(scriptingOptionsMenu, MenuOption::EntityScriptServerLog, 0,
|
||||||
|
qApp, SLOT(toggleEntityScriptServerLogDialog()));
|
||||||
|
{
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
QObject::connect(nodeList.data(), &NodeList::canRezChanged, essLogAction, [essLogAction] {
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
essLogAction->setEnabled(nodeList->getThisNodeCanRez());
|
||||||
|
});
|
||||||
|
essLogAction->setEnabled(nodeList->getThisNodeCanRez());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Developer > Scripting > Script Log (HMD friendly)...
|
||||||
|
addActionToQMenuAndActionHash(scriptingOptionsMenu, "Script Log (HMD friendly)...", Qt::NoButton,
|
||||||
|
qApp, SLOT(showScriptLogs()));
|
||||||
|
|
||||||
|
// Developer > Scripting > Verbose Logging
|
||||||
|
addCheckableActionToQMenuAndActionHash(scriptingOptionsMenu, MenuOption::VerboseLogging, 0, false,
|
||||||
|
qApp, SLOT(updateVerboseLogging()));
|
||||||
|
|
||||||
|
// Developer > Scripting > Enable Speech Control API
|
||||||
|
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||||
|
auto speechRecognizer = DependencyManager::get<SpeechRecognizer>();
|
||||||
|
QAction* speechRecognizerAction = addCheckableActionToQMenuAndActionHash(scriptingOptionsMenu, MenuOption::ControlWithSpeech,
|
||||||
|
Qt::CTRL | Qt::SHIFT | Qt::Key_C,
|
||||||
|
speechRecognizer->getEnabled(),
|
||||||
|
speechRecognizer.data(),
|
||||||
|
SLOT(setEnabled(bool)),
|
||||||
|
UNSPECIFIED_POSITION);
|
||||||
|
connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool)));
|
||||||
|
#endif
|
||||||
|
|
||||||
// Developer > UI >>>
|
// Developer > UI >>>
|
||||||
MenuWrapper* uiOptionsMenu = developerMenu->addMenu("UI");
|
MenuWrapper* uiOptionsMenu = developerMenu->addMenu("UI");
|
||||||
action = addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::DesktopTabletToToolbar, 0,
|
action = addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::DesktopTabletToToolbar, 0,
|
||||||
qApp->getDesktopTabletBecomesToolbarSetting());
|
qApp->getDesktopTabletBecomesToolbarSetting());
|
||||||
|
|
||||||
|
// Developer > UI > Show Overlays
|
||||||
|
addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::Overlays, 0, true);
|
||||||
|
|
||||||
|
// Developer > UI > Desktop Tablet Becomes Toolbar
|
||||||
connect(action, &QAction::triggered, [action] {
|
connect(action, &QAction::triggered, [action] {
|
||||||
qApp->setDesktopTabletBecomesToolbarSetting(action->isChecked());
|
qApp->setDesktopTabletBecomesToolbarSetting(action->isChecked());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Developer > UI > HMD Tablet Becomes Toolbar
|
||||||
action = addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::HMDTabletToToolbar, 0,
|
action = addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::HMDTabletToToolbar, 0,
|
||||||
qApp->getHmdTabletBecomesToolbarSetting());
|
qApp->getHmdTabletBecomesToolbarSetting());
|
||||||
connect(action, &QAction::triggered, [action] {
|
connect(action, &QAction::triggered, [action] {
|
||||||
|
@ -570,6 +638,8 @@ Menu::Menu() {
|
||||||
avatar.get(), SLOT(updateMotionBehaviorFromMenu()),
|
avatar.get(), SLOT(updateMotionBehaviorFromMenu()),
|
||||||
UNSPECIFIED_POSITION, "Developer");
|
UNSPECIFIED_POSITION, "Developer");
|
||||||
|
|
||||||
|
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowTrackedObjects, 0, false, qApp, SLOT(setShowTrackedObjects(bool)));
|
||||||
|
|
||||||
// Developer > Hands >>>
|
// Developer > Hands >>>
|
||||||
MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands");
|
MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands");
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false,
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false,
|
||||||
|
@ -684,10 +754,11 @@ Menu::Menu() {
|
||||||
addCheckableActionToQMenuAndActionHash(pickingOptionsMenu, MenuOption::ForceCoarsePicking, 0, false,
|
addCheckableActionToQMenuAndActionHash(pickingOptionsMenu, MenuOption::ForceCoarsePicking, 0, false,
|
||||||
DependencyManager::get<PickManager>().data(), SLOT(setForceCoarsePicking(bool)));
|
DependencyManager::get<PickManager>().data(), SLOT(setForceCoarsePicking(bool)));
|
||||||
|
|
||||||
// Developer > Display Crash Options
|
|
||||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::DisplayCrashOptions, 0, true);
|
|
||||||
// Developer > Crash >>>
|
// Developer > Crash >>>
|
||||||
MenuWrapper* crashMenu = developerMenu->addMenu("Crash");
|
MenuWrapper* crashMenu = developerMenu->addMenu("Crash");
|
||||||
|
|
||||||
|
// Developer > Crash > Display Crash Options
|
||||||
|
addCheckableActionToQMenuAndActionHash(crashMenu, MenuOption::DisplayCrashOptions, 0, true);
|
||||||
|
|
||||||
addActionToQMenuAndActionHash(crashMenu, MenuOption::DeadlockInterface, 0, qApp, SLOT(deadlockApplication()));
|
addActionToQMenuAndActionHash(crashMenu, MenuOption::DeadlockInterface, 0, qApp, SLOT(deadlockApplication()));
|
||||||
addActionToQMenuAndActionHash(crashMenu, MenuOption::UnresponsiveInterface, 0, qApp, SLOT(unresponsiveApplication()));
|
addActionToQMenuAndActionHash(crashMenu, MenuOption::UnresponsiveInterface, 0, qApp, SLOT(unresponsiveApplication()));
|
||||||
|
@ -722,59 +793,15 @@ Menu::Menu() {
|
||||||
action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNewFaultThreaded);
|
action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNewFaultThreaded);
|
||||||
connect(action, &QAction::triggered, qApp, []() { std::thread(crash::newFault).join(); });
|
connect(action, &QAction::triggered, qApp, []() { std::thread(crash::newFault).join(); });
|
||||||
|
|
||||||
// Developer > Stats
|
// Developer > Show Statistics
|
||||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Stats);
|
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Stats);
|
||||||
|
|
||||||
|
// Developer > Show Animation Statistics
|
||||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::AnimStats);
|
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::AnimStats);
|
||||||
|
|
||||||
// Settings > Enable Speech Control API
|
// Developer > Log
|
||||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
|
||||||
auto speechRecognizer = DependencyManager::get<SpeechRecognizer>();
|
|
||||||
QAction* speechRecognizerAction = addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::ControlWithSpeech,
|
|
||||||
Qt::CTRL | Qt::SHIFT | Qt::Key_C,
|
|
||||||
speechRecognizer->getEnabled(),
|
|
||||||
speechRecognizer.data(),
|
|
||||||
SLOT(setEnabled(bool)),
|
|
||||||
UNSPECIFIED_POSITION);
|
|
||||||
connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool)));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// console
|
|
||||||
addActionToQMenuAndActionHash(developerMenu, MenuOption::Console, Qt::CTRL | Qt::ALT | Qt::Key_J,
|
|
||||||
DependencyManager::get<StandAloneJSConsole>().data(),
|
|
||||||
SLOT(toggleConsole()),
|
|
||||||
QAction::NoRole,
|
|
||||||
UNSPECIFIED_POSITION);
|
|
||||||
|
|
||||||
// Developer > API Debugger
|
|
||||||
action = addActionToQMenuAndActionHash(developerMenu, "API Debugger");
|
|
||||||
connect(action, &QAction::triggered, [] {
|
|
||||||
QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
|
|
||||||
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/utilities/tools/currentAPI.js");
|
|
||||||
DependencyManager::get<ScriptEngines>()->loadScript(defaultScriptsLoc.toString());
|
|
||||||
});
|
|
||||||
|
|
||||||
// Developer > Log...
|
|
||||||
addActionToQMenuAndActionHash(developerMenu, MenuOption::Log, Qt::CTRL | Qt::SHIFT | Qt::Key_L,
|
addActionToQMenuAndActionHash(developerMenu, MenuOption::Log, Qt::CTRL | Qt::SHIFT | Qt::Key_L,
|
||||||
qApp, SLOT(toggleLogDialog()));
|
qApp, SLOT(toggleLogDialog()));
|
||||||
auto essLogAction = addActionToQMenuAndActionHash(developerMenu, MenuOption::EntityScriptServerLog, 0,
|
|
||||||
qApp, SLOT(toggleEntityScriptServerLogDialog()));
|
|
||||||
{
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
|
||||||
QObject::connect(nodeList.data(), &NodeList::canRezChanged, essLogAction, [essLogAction] {
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
|
||||||
essLogAction->setEnabled(nodeList->getThisNodeCanRez());
|
|
||||||
});
|
|
||||||
essLogAction->setEnabled(nodeList->getThisNodeCanRez());
|
|
||||||
}
|
|
||||||
|
|
||||||
addActionToQMenuAndActionHash(developerMenu, "Script Log (HMD friendly)...", Qt::NoButton,
|
|
||||||
qApp, SLOT(showScriptLogs()));
|
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::VerboseLogging, 0, false,
|
|
||||||
qApp, SLOT(updateVerboseLogging()));
|
|
||||||
|
|
||||||
// Developer > Show Overlays
|
|
||||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Overlays, 0, true);
|
|
||||||
|
|
||||||
#if 0 /// -------------- REMOVED FOR NOW --------------
|
#if 0 /// -------------- REMOVED FOR NOW --------------
|
||||||
addDisabledActionAndSeparator(navigateMenu, "History");
|
addDisabledActionAndSeparator(navigateMenu, "History");
|
||||||
|
|
|
@ -183,6 +183,7 @@ namespace MenuOption {
|
||||||
const QString RunClientScriptTests = "Run Client Script Tests";
|
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 SendWrongDSConnectVersion = "Send wrong DS connect version";
|
const QString SendWrongDSConnectVersion = "Send wrong DS connect version";
|
||||||
const QString SendWrongProtocolVersion = "Send wrong protocol version";
|
const QString SendWrongProtocolVersion = "Send wrong protocol version";
|
||||||
const QString SetHomeLocation = "Set Home Location";
|
const QString SetHomeLocation = "Set Home Location";
|
||||||
|
|
|
@ -235,7 +235,7 @@ bool ModelPackager::zipModel() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename, const FBXGeometry& geometry) {
|
void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename, const HFMGeometry& geometry) {
|
||||||
|
|
||||||
bool isBodyType = _modelType == FSTReader::BODY_ONLY_MODEL || _modelType == FSTReader::HEAD_AND_BODY_MODEL;
|
bool isBodyType = _modelType == FSTReader::BODY_ONLY_MODEL || _modelType == FSTReader::HEAD_AND_BODY_MODEL;
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename
|
||||||
|
|
||||||
void ModelPackager::listTextures() {
|
void ModelPackager::listTextures() {
|
||||||
_textures.clear();
|
_textures.clear();
|
||||||
foreach (const FBXMaterial mat, _geometry->materials) {
|
foreach (const HFMMaterial mat, _geometry->materials) {
|
||||||
if (!mat.albedoTexture.filename.isEmpty() && mat.albedoTexture.content.isEmpty() &&
|
if (!mat.albedoTexture.filename.isEmpty() && mat.albedoTexture.content.isEmpty() &&
|
||||||
!_textures.contains(mat.albedoTexture.filename)) {
|
!_textures.contains(mat.albedoTexture.filename)) {
|
||||||
_textures << mat.albedoTexture.filename;
|
_textures << mat.albedoTexture.filename;
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include "ui/ModelsBrowser.h"
|
#include "ui/ModelsBrowser.h"
|
||||||
|
|
||||||
class FBXGeometry;
|
class HFMGeometry;
|
||||||
|
|
||||||
class ModelPackager : public QObject {
|
class ModelPackager : public QObject {
|
||||||
public:
|
public:
|
||||||
|
@ -32,7 +32,7 @@ private:
|
||||||
bool editProperties();
|
bool editProperties();
|
||||||
bool zipModel();
|
bool zipModel();
|
||||||
|
|
||||||
void populateBasicMapping(QVariantHash& mapping, QString filename, const FBXGeometry& geometry);
|
void populateBasicMapping(QVariantHash& mapping, QString filename, const HFMGeometry& geometry);
|
||||||
|
|
||||||
void listTextures();
|
void listTextures();
|
||||||
bool copyTextures(const QString& oldDir, const QDir& newDir);
|
bool copyTextures(const QString& oldDir, const QDir& newDir);
|
||||||
|
@ -44,7 +44,7 @@ private:
|
||||||
QString _scriptDir;
|
QString _scriptDir;
|
||||||
|
|
||||||
QVariantHash _mapping;
|
QVariantHash _mapping;
|
||||||
std::unique_ptr<FBXGeometry> _geometry;
|
std::unique_ptr<HFMGeometry> _geometry;
|
||||||
QStringList _textures;
|
QStringList _textures;
|
||||||
QStringList _scripts;
|
QStringList _scripts;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
|
|
||||||
ModelPropertiesDialog::ModelPropertiesDialog(FSTReader::ModelType modelType, const QVariantHash& originalMapping,
|
ModelPropertiesDialog::ModelPropertiesDialog(FSTReader::ModelType modelType, const QVariantHash& originalMapping,
|
||||||
const QString& basePath, const FBXGeometry& geometry) :
|
const QString& basePath, const HFMGeometry& geometry) :
|
||||||
_modelType(modelType),
|
_modelType(modelType),
|
||||||
_originalMapping(originalMapping),
|
_originalMapping(originalMapping),
|
||||||
_basePath(basePath),
|
_basePath(basePath),
|
||||||
|
@ -249,7 +249,7 @@ QComboBox* ModelPropertiesDialog::createJointBox(bool withNone) const {
|
||||||
if (withNone) {
|
if (withNone) {
|
||||||
box->addItem("(none)");
|
box->addItem("(none)");
|
||||||
}
|
}
|
||||||
foreach (const FBXJoint& joint, _geometry.joints) {
|
foreach (const HFMJoint& joint, _geometry.joints) {
|
||||||
if (joint.isSkeletonJoint || !_geometry.hasSkeletonJoints) {
|
if (joint.isSkeletonJoint || !_geometry.hasSkeletonJoints) {
|
||||||
box->addItem(joint.name);
|
box->addItem(joint.name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ class ModelPropertiesDialog : public QDialog {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ModelPropertiesDialog(FSTReader::ModelType modelType, const QVariantHash& originalMapping,
|
ModelPropertiesDialog(FSTReader::ModelType modelType, const QVariantHash& originalMapping,
|
||||||
const QString& basePath, const FBXGeometry& geometry);
|
const QString& basePath, const HFMGeometry& geometry);
|
||||||
|
|
||||||
QVariantHash getMapping() const;
|
QVariantHash getMapping() const;
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ private:
|
||||||
FSTReader::ModelType _modelType;
|
FSTReader::ModelType _modelType;
|
||||||
QVariantHash _originalMapping;
|
QVariantHash _originalMapping;
|
||||||
QString _basePath;
|
QString _basePath;
|
||||||
FBXGeometry _geometry;
|
HFMGeometry _geometry;
|
||||||
QLineEdit* _name = nullptr;
|
QLineEdit* _name = nullptr;
|
||||||
QPushButton* _textureDirectory = nullptr;
|
QPushButton* _textureDirectory = nullptr;
|
||||||
QPushButton* _scriptDirectory = nullptr;
|
QPushButton* _scriptDirectory = nullptr;
|
||||||
|
|
|
@ -53,7 +53,8 @@ void ATPAssetMigrator::loadEntityServerFile() {
|
||||||
|
|
||||||
auto migrateResources = [=](QUrl migrationURL, QJsonValueRef jsonValue, bool isModelURL) {
|
auto migrateResources = [=](QUrl migrationURL, QJsonValueRef jsonValue, bool isModelURL) {
|
||||||
auto request =
|
auto request =
|
||||||
DependencyManager::get<ResourceManager>()->createResourceRequest(this, migrationURL);
|
DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||||
|
this, migrationURL, true, -1, "ATPAssetMigrator::loadEntityServerFile");
|
||||||
|
|
||||||
if (request) {
|
if (request) {
|
||||||
qCDebug(asset_migrator) << "Requesting" << migrationURL << "for ATP asset migration";
|
qCDebug(asset_migrator) << "Requesting" << migrationURL << "for ATP asset migration";
|
||||||
|
|
|
@ -135,7 +135,7 @@ bool AvatarActionHold::getTarget(float deltaTimeStep, glm::quat& rotation, glm::
|
||||||
glm::vec3 palmPosition;
|
glm::vec3 palmPosition;
|
||||||
glm::quat palmRotation;
|
glm::quat palmRotation;
|
||||||
|
|
||||||
bool isTransitingWithAvatar = holdingAvatar->getTransit()->isTransiting();
|
bool isTransitingWithAvatar = holdingAvatar->getTransit()->isActive();
|
||||||
if (isTransitingWithAvatar != _isTransitingWithAvatar) {
|
if (isTransitingWithAvatar != _isTransitingWithAvatar) {
|
||||||
_isTransitingWithAvatar = isTransitingWithAvatar;
|
_isTransitingWithAvatar = isTransitingWithAvatar;
|
||||||
auto ownerEntity = _ownerEntity.lock();
|
auto ownerEntity = _ownerEntity.lock();
|
||||||
|
@ -424,7 +424,7 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
|
||||||
if (ownerEntity) {
|
if (ownerEntity) {
|
||||||
ownerEntity->setDynamicDataDirty(true);
|
ownerEntity->setDynamicDataDirty(true);
|
||||||
ownerEntity->setDynamicDataNeedsTransmit(true);
|
ownerEntity->setDynamicDataNeedsTransmit(true);
|
||||||
ownerEntity->setTransitingWithAvatar(myAvatar->getTransit()->isTransiting());
|
ownerEntity->setTransitingWithAvatar(myAvatar->getTransit()->isActive());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,14 +71,12 @@ AvatarManager::AvatarManager(QObject* parent) :
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const float AVATAR_TRANSIT_TRIGGER_DISTANCE = 1.0f;
|
|
||||||
const int AVATAR_TRANSIT_FRAME_COUNT = 11; // Based on testing
|
|
||||||
const int AVATAR_TRANSIT_FRAMES_PER_METER = 1; // Based on testing
|
|
||||||
|
|
||||||
_transitConfig._totalFrames = AVATAR_TRANSIT_FRAME_COUNT;
|
_transitConfig._totalFrames = AVATAR_TRANSIT_FRAME_COUNT;
|
||||||
_transitConfig._triggerDistance = AVATAR_TRANSIT_TRIGGER_DISTANCE;
|
_transitConfig._minTriggerDistance = AVATAR_TRANSIT_MIN_TRIGGER_DISTANCE;
|
||||||
|
_transitConfig._maxTriggerDistance = AVATAR_TRANSIT_MAX_TRIGGER_DISTANCE;
|
||||||
_transitConfig._framesPerMeter = AVATAR_TRANSIT_FRAMES_PER_METER;
|
_transitConfig._framesPerMeter = AVATAR_TRANSIT_FRAMES_PER_METER;
|
||||||
_transitConfig._isDistanceBased = true;
|
_transitConfig._isDistanceBased = AVATAR_TRANSIT_DISTANCE_BASED;
|
||||||
|
_transitConfig._abortDistance = AVATAR_TRANSIT_ABORT_DISTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||||
|
@ -126,13 +124,39 @@ void AvatarManager::setSpace(workload::SpacePointer& space ) {
|
||||||
_space = space;
|
_space = space;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AvatarManager::handleTransitAnimations(AvatarTransit::Status status) {
|
||||||
|
switch (status) {
|
||||||
|
case AvatarTransit::Status::STARTED:
|
||||||
|
_myAvatar->getSkeletonModel()->getRig().triggerNetworkAnimation("preTransitAnim");
|
||||||
|
break;
|
||||||
|
case AvatarTransit::Status::START_TRANSIT:
|
||||||
|
_myAvatar->getSkeletonModel()->getRig().triggerNetworkAnimation("transitAnim");
|
||||||
|
break;
|
||||||
|
case AvatarTransit::Status::END_TRANSIT:
|
||||||
|
_myAvatar->getSkeletonModel()->getRig().triggerNetworkAnimation("postTransitAnim");
|
||||||
|
break;
|
||||||
|
case AvatarTransit::Status::ENDED:
|
||||||
|
_myAvatar->getSkeletonModel()->getRig().triggerNetworkAnimation("idleAnim");
|
||||||
|
break;
|
||||||
|
case AvatarTransit::Status::PRE_TRANSIT:
|
||||||
|
break;
|
||||||
|
case AvatarTransit::Status::POST_TRANSIT:
|
||||||
|
break;
|
||||||
|
case AvatarTransit::Status::IDLE:
|
||||||
|
break;
|
||||||
|
case AvatarTransit::Status::TRANSITING:
|
||||||
|
break;
|
||||||
|
case AvatarTransit::Status::ABORT_TRANSIT:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AvatarManager::updateMyAvatar(float deltaTime) {
|
void AvatarManager::updateMyAvatar(float deltaTime) {
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "AvatarManager::updateMyAvatar()");
|
PerformanceWarning warn(showWarnings, "AvatarManager::updateMyAvatar()");
|
||||||
|
|
||||||
AvatarTransit::Status status = _myAvatar->updateTransit(deltaTime, _myAvatar->getNextPosition(), _transitConfig);
|
AvatarTransit::Status status = _myAvatar->updateTransit(deltaTime, _myAvatar->getNextPosition(), _myAvatar->getSensorToWorldScale(), _transitConfig);
|
||||||
bool sendFirstTransitPackage = (status == AvatarTransit::Status::START_TRANSIT);
|
handleTransitAnimations(status);
|
||||||
bool blockTransitData = (status == AvatarTransit::Status::TRANSITING);
|
|
||||||
|
|
||||||
_myAvatar->update(deltaTime);
|
_myAvatar->update(deltaTime);
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
|
@ -142,18 +166,13 @@ void AvatarManager::updateMyAvatar(float deltaTime) {
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
quint64 dt = now - _lastSendAvatarDataTime;
|
quint64 dt = now - _lastSendAvatarDataTime;
|
||||||
|
|
||||||
|
if (dt > MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS && !_myAvatarDataPacketsPaused) {
|
||||||
if (sendFirstTransitPackage || (dt > MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS && !_myAvatarDataPacketsPaused && !blockTransitData)) {
|
|
||||||
// send head/hand data to the avatar mixer and voxel server
|
// send head/hand data to the avatar mixer and voxel server
|
||||||
PerformanceTimer perfTimer("send");
|
PerformanceTimer perfTimer("send");
|
||||||
if (sendFirstTransitPackage) {
|
|
||||||
_myAvatar->overrideNextPackagePositionData(_myAvatar->getTransit()->getEndPosition());
|
|
||||||
}
|
|
||||||
_myAvatar->sendAvatarDataPacket();
|
_myAvatar->sendAvatarDataPacket();
|
||||||
_lastSendAvatarDataTime = now;
|
_lastSendAvatarDataTime = now;
|
||||||
_myAvatarSendRate.increment();
|
_myAvatarSendRate.increment();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -242,7 +261,9 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
for (auto it = sortedAvatarVector.begin(); it != sortedAvatarVector.end(); ++it) {
|
for (auto it = sortedAvatarVector.begin(); it != sortedAvatarVector.end(); ++it) {
|
||||||
const SortableAvatar& sortData = *it;
|
const SortableAvatar& sortData = *it;
|
||||||
const auto avatar = std::static_pointer_cast<OtherAvatar>(sortData.getAvatar());
|
const auto avatar = std::static_pointer_cast<OtherAvatar>(sortData.getAvatar());
|
||||||
|
if (!avatar->_isClientAvatar) {
|
||||||
|
avatar->setIsClientAvatar(true);
|
||||||
|
}
|
||||||
// TODO: to help us scale to more avatars it would be nice to not have to poll this stuff every update
|
// TODO: to help us scale to more avatars it would be nice to not have to poll this stuff every update
|
||||||
if (avatar->getSkeletonModel()->isLoaded()) {
|
if (avatar->getSkeletonModel()->isLoaded()) {
|
||||||
// remove the orb if it is there
|
// remove the orb if it is there
|
||||||
|
@ -267,7 +288,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
if (inView && avatar->hasNewJointData()) {
|
if (inView && avatar->hasNewJointData()) {
|
||||||
numAvatarsUpdated++;
|
numAvatarsUpdated++;
|
||||||
}
|
}
|
||||||
auto transitStatus = avatar->_transit.update(deltaTime, avatar->_globalPosition, _transitConfig);
|
auto transitStatus = avatar->_transit.update(deltaTime, avatar->_serverPosition, _transitConfig);
|
||||||
if (avatar->getIsNewAvatar() && (transitStatus == AvatarTransit::Status::START_TRANSIT || transitStatus == AvatarTransit::Status::ABORT_TRANSIT)) {
|
if (avatar->getIsNewAvatar() && (transitStatus == AvatarTransit::Status::START_TRANSIT || transitStatus == AvatarTransit::Status::ABORT_TRANSIT)) {
|
||||||
avatar->_transit.reset();
|
avatar->_transit.reset();
|
||||||
avatar->setIsNewAvatar(false);
|
avatar->setIsNewAvatar(false);
|
||||||
|
|