Merge remote-tracking branch 'upstream/master' into enable_aec_by_default

This commit is contained in:
Gabriel Calero 2018-11-05 11:25:09 -03:00
commit 58c135a74d
456 changed files with 14815 additions and 10827 deletions

View file

@ -36,6 +36,7 @@ module.exports = {
"GlobalServices": false,
"GooglePoly": false,
"Graphics": false,
"HifiAbout": false,
"HMD": false,
"LaserPointers": false,
"location": true,

View file

@ -9,6 +9,7 @@
- [cmake](https://cmake.org/download/): 3.9
- [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.
- [VHACD](https://github.com/virneo/v-hacd)(clone this repository)(Optional)

View file

@ -40,6 +40,11 @@ Install build tools:
sudo apt-get install cmake
```
Install Python 3:
```bash
sudo apt-get install python3.6
```
### Get code and checkout the tag you need

View file

@ -6,6 +6,10 @@ Please read the [general build guide](BUILD.md) for information on dependencies
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
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.
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.

View file

@ -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.
### Step 1. Visual Studio 2017
### Step 1. Visual Studio 2017 & Python
If you dont 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

View file

@ -66,7 +66,7 @@ if (ANDROID)
set(GLES_OPTION ON)
set(PLATFORM_QT_COMPONENTS AndroidExtras WebView)
else ()
set(PLATFORM_QT_COMPONENTS WebEngine WebEngineWidgets)
set(PLATFORM_QT_COMPONENTS WebEngine)
endif ()
if (USE_GLES AND (NOT ANDROID))

View file

@ -24,7 +24,6 @@ android {
'-DANDROID_STL=c++_shared',
'-DQT_CMAKE_PREFIX_PATH=' + HIFI_ANDROID_PRECOMPILED + '/qt/lib/cmake',
'-DNATIVE_SCRIBE=' + HIFI_ANDROID_PRECOMPILED + '/scribe' + EXEC_SUFFIX,
'-DNATIVE_SHREFLECT=' + HIFI_ANDROID_PRECOMPILED + '/shreflect' + EXEC_SUFFIX,
'-DHIFI_ANDROID_PRECOMPILED=' + HIFI_ANDROID_PRECOMPILED,
'-DRELEASE_NUMBER=' + RELEASE_NUMBER,
'-DRELEASE_TYPE=' + RELEASE_TYPE,

View file

@ -161,31 +161,19 @@ def packages = [
]
]
def scribeLocalFile='scribe' + EXEC_SUFFIX
def scribeFile='scribe_linux_x86_64'
def scribeChecksum='ca4b904f52f4f993c29175ba96798fa6'
def scribeVersion='u_iTrJDaE95i2abTPXOpPZckGBIim53G'
def shreflectLocalFile='shreflect' + EXEC_SUFFIX
def shreflectFile='shreflect_linux_x86_64'
def shreflectChecksum='d6094a8580066c0b6f4e80b5adfb1d98'
def shreflectVersion='jnrpudh6fptIg6T2.Z6fgKP2ultAdKmE'
def scribeChecksum='4635c28192724281d2367ce9e94380ab'
def scribeVersion='mPAY_N846oZH1tPY1bwChB_hzqkiYyoC'
if (Os.isFamily(Os.FAMILY_MAC)) {
scribeFile = 'scribe_osx_x86_64'
scribeChecksum='72db9d32d4e1e50add755570ac5eb749'
scribeVersion='DAW0DmnjCRib4MD8x93bgc2Z2MpPojZC'
shreflectFile='shreflect_osx_x86_64'
shreflectChecksum='d613ef0703c21371fee93fd2e54b964f'
shreflectVersion='.rYNzjSFq6WtWDnE5KIKRIAGyJtr__ad'
scribeChecksum='1ead61c285d265eba9a5ef91ae3b7c26'
scribeVersion='4TAXWdo9fviw60N2wUA8HNyQ9TabjZa3'
} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
scribeFile = 'scribe_win32_x86_64.exe'
scribeChecksum='678e43d290c90fda670c6fefe038a06d'
scribeVersion='PuullrA_bPlO9kXZRt8rLe536X1UI.m7'
shreflectFile='shreflect_win32_x86_64.exe'
shreflectChecksum='6f4a77b8cceb3f1bbc655132c3665060'
shreflectVersion='iIyCyza1nelkbI7ihybF59bBlwrfAC3D'
scribeChecksum='9c29a62595daf4844f95f6744d568c15'
scribeVersion='DUoxjufeX8ZAIVRBKRczWTuZwT13enTv'
}
def options = [
@ -461,27 +449,11 @@ task fixScribePermissions(type: Exec, dependsOn: verifyScribe) {
commandLine 'chmod', 'a+x', HIFI_ANDROID_PRECOMPILED + '/' + scribeLocalFile
}
task downloadShreflect(type: Download) {
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]) { }
task setupScribe(dependsOn: [verifyScribe]) { }
// On Windows, we don't need to set the executable bit, but on OSX and Unix we do
if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
setupScribe.dependsOn fixScribePermissions
setupScribe.dependsOn fixShreflectPermissions
}
task extractGvrBinaries(dependsOn: extractDependencies) {

View file

@ -222,7 +222,8 @@ void Agent::requestScript() {
return;
}
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(this, scriptURL);
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
this, scriptURL, true, -1, "Agent::requestScript");
if (!request) {
qWarning() << "Could not create ResourceRequest for Agent script at" << scriptURL.toString();

View file

@ -21,7 +21,6 @@
#include <QtCore/QTimer>
#include <QUuid>
#include <ClientTraitsHandler.h>
#include <EntityEditPacketSender.h>
#include <EntityTree.h>
#include <ScriptEngine.h>

View file

@ -35,6 +35,7 @@
#include "AssignmentClientLogging.h"
#include "AssignmentFactory.h"
#include "ResourceRequestObserver.h"
const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client";
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<StatTracker>();
DependencyManager::set<AccountManager>();
DependencyManager::set<ResourceRequestObserver>();
auto addressManager = DependencyManager::set<AddressManager>();

View file

@ -541,7 +541,7 @@ void AvatarMixer::handleRequestsDomainListDataPacket(QSharedPointer<ReceivedMess
// ...For those nodes, reset the lastBroadcastTime to 0
// so that the AvatarMixer will send Identity data to us
[&](const SharedNodePointer& node) {
nodeData->setLastBroadcastTime(node->getUUID(), 0);
nodeData->setLastBroadcastTime(node->getLocalID(), 0);
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
bool identityChanged = false;
bool displayNameChanged = false;
avatar.processAvatarIdentity(message->getMessage(), identityChanged, displayNameChanged);
QDataStream avatarIdentityStream(message->getMessage());
avatar.processAvatarIdentity(avatarIdentityStream, identityChanged, displayNameChanged);
if (identityChanged) {
QMutexLocker nodeDataLocker(&nodeData->getMutex());
@ -637,7 +638,7 @@ void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage>
// Reset the lastBroadcastTime for the ignored avatar to 0
// so the AvatarMixer knows it'll have to send identity data about the ignored avatar
// to the ignorer if the ignorer unignores.
nodeData->setLastBroadcastTime(ignoredUUID, 0);
nodeData->setLastBroadcastTime(ignoredNode->getLocalID(), 0);
nodeData->resetSentTraitData(ignoredNode->getLocalID());
}
@ -647,7 +648,7 @@ void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage>
// to the ignored if the ignorer unignores.
AvatarMixerClientData* ignoredNodeData = reinterpret_cast<AvatarMixerClientData*>(ignoredNode->getLinkedData());
if (ignoredNodeData) {
ignoredNodeData->setLastBroadcastTime(senderNode->getUUID(), 0);
ignoredNodeData->setLastBroadcastTime(senderNode->getLocalID(), 0);
ignoredNodeData->resetSentTraitData(senderNode->getLocalID());
}
}

View file

@ -26,20 +26,20 @@ AvatarMixerClientData::AvatarMixerClientData(const QUuid& nodeID, Node::LocalID
_avatar->setID(nodeID);
}
uint64_t AvatarMixerClientData::getLastOtherAvatarEncodeTime(QUuid otherAvatar) const {
std::unordered_map<QUuid, uint64_t>::const_iterator itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
uint64_t AvatarMixerClientData::getLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar) const {
const auto itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
if (itr != _lastOtherAvatarEncodeTime.end()) {
return itr->second;
}
return 0;
}
void AvatarMixerClientData::setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time) {
std::unordered_map<QUuid, uint64_t>::iterator itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
void AvatarMixerClientData::setLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar, uint64_t time) {
auto itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
if (itr != _lastOtherAvatarEncodeTime.end()) {
itr->second = time;
} 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
auto nodeMatch = _lastBroadcastTimes.find(nodeUUID);
if (nodeMatch != _lastBroadcastTimes.end()) {
@ -229,9 +229,9 @@ uint64_t AvatarMixerClientData::getLastBroadcastTime(const QUuid& nodeUUID) cons
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
auto nodeMatch = _lastBroadcastSequenceNumbers.find(nodeUUID);
auto nodeMatch = _lastBroadcastSequenceNumbers.find(nodeID);
if (nodeMatch != _lastBroadcastSequenceNumbers.end()) {
return nodeMatch->second;
}
@ -252,7 +252,7 @@ void AvatarMixerClientData::ignoreOther(const Node* self, const Node* other) {
} else {
killPacket->writePrimitive(KillAvatarReason::YourAvatarEnteredTheirBubble);
}
setLastBroadcastTime(other->getUUID(), 0);
setLastBroadcastTime(other->getLocalID(), 0);
resetSentTraitData(other->getLocalID());
@ -331,9 +331,9 @@ AvatarMixerClientData::TraitsCheckTimestamp AvatarMixerClientData::getLastOtherA
}
}
void AvatarMixerClientData::cleanupKilledNode(const QUuid& nodeUUID, Node::LocalID nodeLocalID) {
removeLastBroadcastSequenceNumber(nodeUUID);
removeLastBroadcastTime(nodeUUID);
void AvatarMixerClientData::cleanupKilledNode(const QUuid&, Node::LocalID nodeLocalID) {
removeLastBroadcastSequenceNumber(nodeLocalID);
removeLastBroadcastTime(nodeLocalID);
_lastSentTraitsTimestamps.erase(nodeLocalID);
_sentTraitVersions.erase(nodeLocalID);
}

View file

@ -49,17 +49,16 @@ public:
const AvatarData* getConstAvatarData() const { return _avatar.get(); }
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; }
void setIsIgnoreRadiusEnabled(bool enabled) { _isIgnoreRadiusEnabled = enabled; }
uint16_t getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const;
void setLastBroadcastSequenceNumber(const QUuid& nodeUUID, uint16_t sequenceNumber)
{ _lastBroadcastSequenceNumbers[nodeUUID] = sequenceNumber; }
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); }
uint64_t getLastBroadcastTime(NLPacket::LocalID nodeUUID) const;
void setLastBroadcastTime(NLPacket::LocalID nodeUUID, uint64_t broadcastTime) { _lastBroadcastTimes[nodeUUID] = broadcastTime; }
Q_INVOKABLE void removeLastBroadcastTime(NLPacket::LocalID nodeUUID) { _lastBroadcastTimes.erase(nodeUUID); }
Q_INVOKABLE void cleanupKilledNode(const QUuid& nodeUUID, Node::LocalID nodeLocalID);
@ -93,7 +92,7 @@ public:
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;
void addToRadiusIgnoringSet(const QUuid& other);
void removeFromRadiusIgnoringSet(const QUuid& other);
@ -114,10 +113,10 @@ public:
const ConicalViewFrustums& getViewFrustums() const { return _currentViewFrustums; }
uint64_t getLastOtherAvatarEncodeTime(QUuid otherAvatar) const;
void setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time);
uint64_t getLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar) const;
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);
int processPackets(const SlaveSharedData& slaveSharedData); // returns number of packets processed
@ -150,13 +149,13 @@ private:
AvatarSharedPointer _avatar { new AvatarData() };
uint16_t _lastReceivedSequenceNumber { 0 };
std::unordered_map<QUuid, uint16_t> _lastBroadcastSequenceNumbers;
std::unordered_map<QUuid, uint64_t> _lastBroadcastTimes;
std::unordered_map<NLPacket::LocalID, uint16_t> _lastBroadcastSequenceNumbers;
std::unordered_map<NLPacket::LocalID, uint64_t> _lastBroadcastTimes;
// this is a map of the last time we encoded an "other" avatar for
// sending to "this" node
std::unordered_map<QUuid, uint64_t> _lastOtherAvatarEncodeTime;
std::unordered_map<QUuid, QVector<JointData>> _lastOtherAvatarSentJoints;
std::unordered_map<NLPacket::LocalID, uint64_t> _lastOtherAvatarEncodeTime;
std::unordered_map<NLPacket::LocalID, QVector<JointData>> _lastOtherAvatarSentJoints;
uint64_t _identityChangeTimestamp;
bool _avatarSessionDisplayNameMustChange{ true };

View file

@ -68,13 +68,11 @@ void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) {
_stats.processIncomingPacketsElapsedTime += (end - start);
}
int AvatarMixerSlave::sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode) {
if (destinationNode->getType() == NodeType::Agent && !destinationNode->isUpstream()) {
int AvatarMixerSlave::sendIdentityPacket(NLPacketList& packetList, const AvatarMixerClientData* nodeData, const Node& destinationNode) {
if (destinationNode.getType() == NodeType::Agent && !destinationNode.isUpstream()) {
QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray();
individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious
auto identityPackets = NLPacketList::create(PacketType::AvatarIdentity, QByteArray(), true, true);
identityPackets->write(individualData);
DependencyManager::get<NodeList>()->sendPacketList(std::move(identityPackets), *destinationNode);
packetList.write(individualData);
_stats.numIdentityPackets++;
return individualData.size();
} else {
@ -247,12 +245,12 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
// reset the internal state for correct random number distribution
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
nodeData->resetNumAvatarsSentLastFrame();
// keep a counter of the number of considered avatars
int numOtherAvatars = 0;
// keep track of outbound data rate specifically for avatar data
int numAvatarDataBytes = 0;
int identityBytesSent = 0;
@ -261,7 +259,6 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
// max number of avatarBytes per frame
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
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 +
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
const float MY_AVATAR_BUBBLE_EXPANSION_FACTOR = 4.0f; // magic number determined emperically
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
if (nodeData->isIgnoreRadiusEnabled() || (avatarClientNodeData->isIgnoreRadiusEnabled() && !getsAnyIgnored)) {
// Perform the collision check between the two bounding boxes
const float OTHER_AVATAR_BUBBLE_EXPANSION_FACTOR = 2.4f; // magic number determined empirically
AABox otherNodeBox = computeBubbleBox(avatarClientNodeData->getAvatar(), OTHER_AVATAR_BUBBLE_EXPANSION_FACTOR);
AABox otherNodeBox = avatarClientNodeData->getAvatar().getDefaultBubbleBox();
if (nodeBox.touches(otherNodeBox)) {
nodeData->ignoreOther(destinationNode, avatarNode);
shouldIgnore = !getsAnyIgnored;
@ -364,7 +356,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
}
if (!shouldIgnore) {
AvatarDataSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(avatarNode->getUUID());
AvatarDataSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(avatarNode->getLocalID());
AvatarDataSequenceNumber lastSeqFromSender = avatarClientNodeData->getLastReceivedSequenceNumber();
// FIXME - This code does appear to be working. But it seems brittle.
@ -396,7 +388,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
if (!shouldIgnore) {
// sort this one for later
const AvatarData* avatarNodeData = avatarClientNodeData->getConstAvatarData();
auto lastEncodeTime = nodeData->getLastOtherAvatarEncodeTime(avatarNodeData->getSessionUUID());
auto lastEncodeTime = nodeData->getLastOtherAvatarEncodeTime(avatarNode->getLocalID());
sortedAvatars.push(SortableAvatar(avatarNodeData, avatarNode, lastEncodeTime));
}
@ -406,8 +398,13 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
int remainingAvatars = (int)sortedAvatars.size();
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) {
const Node* otherNode = sortedAvatar.getNode();
auto lastEncodeForOther = sortedAvatar.getTimestamp();
@ -432,21 +429,9 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
auto startAvatarDataPacking = chrono::high_resolution_clock::now();
++numOtherAvatars;
const AvatarMixerClientData* otherNodeData = reinterpret_cast<const AvatarMixerClientData*>(otherNode->getLinkedData());
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:
bool isLowerPriority = sortedAvatar.getPriority() <= OUT_OF_VIEW_THRESHOLD;
@ -456,71 +441,56 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
} else if (!overBudget) {
detail = distribution(generator) < AVATAR_SEND_FULL_UPDATE_RATIO ? AvatarData::SendAllData : AvatarData::CullSmallData;
nodeData->incrementAvatarInView();
}
bool includeThisAvatar = true;
QVector<JointData>& lastSentJointsForOther = nodeData->getLastOtherAvatarSentJoints(otherNode->getUUID());
// 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->getLocalID()) <= otherNodeData->getIdentityChangeTimestamp()) {
identityBytesSent += sendIdentityPacket(*identityPacketList, otherNodeData, *destinationNode);
lastSentJointsForOther.resize(otherAvatar->getJointCount());
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;
}
// remember the last time we sent identity details about this other node to the receiver
nodeData->setLastBroadcastTime(otherNode->getLocalID(), usecTimestampNow());
}
}
if (includeThisAvatar) {
// start a new segment in the PacketList for this avatar
avatarPacketList->startSegment();
numAvatarDataBytes += avatarPacketList->write(otherNode->getUUID().toRfc4122());
numAvatarDataBytes += avatarPacketList->write(bytes);
avatarPacketList->endSegment();
QVector<JointData>& lastSentJointsForOther = nodeData->getLastOtherAvatarSentJoints(otherNode->getLocalID());
if (detail != AvatarData::NoData) {
_stats.numOthersIncluded++;
const bool distanceAdjust = true;
const bool dropFaceTracking = false;
AvatarDataPacket::SendStatus sendStatus;
sendStatus.sendUUID = true;
// increment the number of avatars sent to this reciever
nodeData->incrementNumAvatarsSentLastFrame();
do {
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
nodeData->setLastBroadcastSequenceNumber(otherNode->getUUID(),
otherNodeData->getLastReceivedSequenceNumber());
nodeData->setLastOtherAvatarEncodeTime(otherNode->getUUID(), usecTimestampNow());
avatarPacket->write(bytes);
avatarSpaceAvailable -= bytes.size();
numAvatarDataBytes += bytes.size();
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 {
// 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.
} while (!sendStatus);
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();
@ -532,17 +502,21 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
remainingAvatars--;
}
if (nodeData->getNumAvatarsSentLastFrame() > numToSendEst) {
qCWarning(avatars) << "More avatars sent than upper estimate" << nodeData->getNumAvatarsSentLastFrame()
<< " / " << numToSendEst;
}
quint64 startPacketSending = usecTimestampNow();
// close the current packet so that we're always sending something
avatarPacketList->closeCurrentPacket(true);
if (avatarPacket->getPayloadSize() != 0) {
nodeList->sendPacket(std::move(avatarPacket), *destinationNode);
++numPacketsSent;
}
_stats.numPacketsSent += (int)avatarPacketList->getNumPackets();
_stats.numPacketsSent += numPacketsSent;
_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
nodeData->recordSentAvatarData(numAvatarDataBytes);
@ -554,6 +528,12 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
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
nodeData->recordNumOtherAvatarStarves(numAvatarsHeldBack);
nodeData->recordNumOtherAvatarSkips(numAvatarsWithSkippedFrames);
@ -599,20 +579,20 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
// so we always send a full update for this avatar
quint64 start = usecTimestampNow();
AvatarDataPacket::HasFlags flagsOut;
AvatarDataPacket::SendStatus sendStatus;
QVector<JointData> emptyLastJointSendData { otherAvatar->getJointCount() };
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();
_stats.toByteArrayElapsedTime += (end - start);
auto lastBroadcastTime = nodeData->getLastBroadcastTime(agentNode->getUUID());
auto lastBroadcastTime = nodeData->getLastBroadcastTime(agentNode->getLocalID());
if (lastBroadcastTime <= agentNodeData->getIdentityChangeTimestamp()
|| (start - lastBroadcastTime) >= REBROADCAST_IDENTITY_TO_DOWNSTREAM_EVERY_US) {
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
@ -630,14 +610,14 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
<< "-" << avatarByteArray.size() << "bytes";
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) {
qCWarning(avatars) << "Replicated avatar data without facial data still too large for"
<< otherAvatar->getSessionUUID() << "-" << avatarByteArray.size() << "bytes";
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();
// set the last sent sequence number for this sender on the receiver
nodeData->setLastBroadcastSequenceNumber(agentNode->getUUID(),
nodeData->setLastBroadcastSequenceNumber(agentNode->getLocalID(),
agentNodeData->getLastReceivedSequenceNumber());
// increment the number of avatars sent to this reciever

View file

@ -101,7 +101,7 @@ public:
void harvestStats(AvatarMixerSlaveStats& stats);
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);
qint64 addChangedTraitsToBulkPacket(AvatarMixerClientData* listeningNodeData,

View file

@ -69,10 +69,10 @@ void ScriptableAvatar::setSkeletonModelURL(const QUrl& 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 rotationMat = glm::mat4_cast(fbxJoint.preRotation * rotation * fbxJoint.postRotation);
glm::mat4 finalMat = translationMat * fbxJoint.preTransform * rotationMat * fbxJoint.postTransform;
glm::mat4 rotationMat = glm::mat4_cast(joint.preRotation * rotation * joint.postRotation);
glm::mat4 finalMat = translationMat * joint.preTransform * rotationMat * joint.postTransform;
return AnimPose(finalMat);
}
@ -93,7 +93,7 @@ void ScriptableAvatar::update(float deltatime) {
}
_animationDetails.currentFrame = currentFrame;
const QVector<FBXJoint>& modelJoints = _bind->getGeometry().joints;
const QVector<HFMJoint>& modelJoints = _bind->getGeometry().joints;
QStringList animationJointNames = _animation->getJointNames();
const int nJoints = modelJoints.size();
@ -102,8 +102,8 @@ void ScriptableAvatar::update(float deltatime) {
}
const int frameCount = _animation->getFrames().size();
const FBXAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
const FBXAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
const HFMAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
const HFMAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
const float frameFraction = glm::fract(currentFrame);
std::vector<AnimPose> poses = _animSkeleton->getRelativeDefaultPoses();

View file

@ -6,6 +6,10 @@ if (NOT "${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
message( FATAL_ERROR "Only 64 bit builds supported." )
endif()
if (USE_CCACHE OR "$ENV{USE_CCACHE}")
configure_ccache()
endif()
if (WIN32)
add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)

42
cmake/externals/glslang/CMakeLists.txt vendored Normal file
View 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")

View file

@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC73.zip
URL_MD5 0c5edfb63cafb042311d3cf25261fbf2
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC75.zip
URL_MD5 b4225d058952e17976ac228330ce8d51
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""

View 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")

View 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")

View 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")

View 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")

View file

@ -10,6 +10,10 @@ if (POLICY CMP0042)
cmake_policy(SET CMP0042 NEW)
endif ()
if (POLICY CMP0074)
cmake_policy(SET CMP0074 OLD)
endif ()
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets")
# Hide automoc folders (for IDEs)

View file

@ -8,34 +8,132 @@
# 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)
#
# 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)
# Grab include files
foreach(includeFile ${ARGN})
list(APPEND SHADER_INCLUDE_FILES ${includeFile})
endforeach()
foreach(SHADER_INCLUDE ${SHADER_INCLUDE_FILES})
get_filename_component(INCLUDE_DIR ${SHADER_INCLUDE} PATH)
list(APPEND SHADER_INCLUDES_PATHS ${INCLUDE_DIR})
endforeach()
list(REMOVE_DUPLICATES SHADER_INCLUDES_PATHS)
#Extract the unique include shader paths
set(INCLUDES ${HIFI_LIBRARIES_SHADER_INCLUDE_FILES})
foreach(EXTRA_SHADER_INCLUDE ${INCLUDES})
list(APPEND SHADER_INCLUDES_PATHS ${EXTRA_SHADER_INCLUDE})
endforeach()
list(REMOVE_DUPLICATES SHADER_INCLUDES_PATHS)
#message(ready for includes ${SHADER_INCLUDES_PATHS})
# make the scribe include arguments
set(SCRIBE_INCLUDES)
unset(SCRIBE_INCLUDES)
foreach(INCLUDE_PATH ${SHADER_INCLUDES_PATHS})
set(SCRIBE_INCLUDES ${SCRIBE_INCLUDES} -I ${INCLUDE_PATH}/)
endforeach()
#
# Figure out the various output names
#
# Define the final name of the generated shader file
get_filename_component(SHADER_NAME ${SHADER_FILE} NAME_WE)
get_filename_component(SHADER_EXT ${SHADER_FILE} EXT)
@ -46,38 +144,36 @@ macro(AUTOSCRIBE_SHADER)
elseif(${SHADER_EXT} STREQUAL .slg)
set(SHADER_TYPE geom)
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
add_custom_command(
OUTPUT ${SHADER_TARGET}
COMMAND ${SCRIBE_COMMAND} ${SCRIBE_ARGS}
DEPENDS ${SHADER_FILE} ${SCRIBE_COMMAND} ${SHADER_INCLUDE_FILES})
# SHADER_SCRIBED -> the output of scribe
set(SHADER_SCRIBED "${SHADERS_DIR}/${SHADER_LIB}/${SHADER_NAME}.${SHADER_TYPE}")
# Generate the json reflection
# FIXME move to spirv-cross for this task after we have spirv compatible shaders
add_custom_command(
OUTPUT ${REFLECTED_SHADER}
COMMAND ${SHREFLECT_COMMAND} ${COMPILED_SHADER}
DEPENDS ${SHREFLECT_DEPENDENCY} ${COMPILED_SHADER})
# SHADER_NAME_FILE -> a file containing the shader name and extension (useful for debugging and for
# determining the type of shader from the filename)
set(SHADER_NAME_FILE "${SHADER_SCRIBED}.name")
file(TO_CMAKE_PATH "${SHADER_SCRIBED}" SHADER_SCRIBED)
file(WRITE "${SHADER_SCRIBED}.name" "${SHADER_NAME}.${SHADER_TYPE}")
AUTOSCRIBE_APPEND_QRC("${SHADER_COUNT}/name" "${SHADER_NAME_FILE}")
#output the generated file name
source_group("Compiled/${SHADER_LIB}" FILES ${COMPILED_SHADER})
set_property(SOURCE ${COMPILED_SHADER} PROPERTY SKIP_AUTOMOC ON)
list(APPEND COMPILED_SHADERS ${COMPILED_SHADER})
if (USE_GLES)
set(SPIRV_CROSS_ARGS --version 310es)
AUTOSCRIBE_PLATFORM_SHADER("310es")
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_SHADERS_ARRAY "${SHADER_SHADERS_ARRAY}" "${SHADER_COUNT},\n")
MATH(EXPR SHADER_COUNT "${SHADER_COUNT}+1")
endmacro()
@ -86,6 +182,8 @@ macro(AUTOSCRIBE_SHADER_LIB)
message(FATAL_ERROR "AUTOSCRIBE_SHADER_LIB can only be used by the shaders library")
endif()
file(MAKE_DIRECTORY "${SHADERS_DIR}/${SHADER_LIB}")
list(APPEND HIFI_LIBRARIES_SHADER_INCLUDE_FILES "${CMAKE_SOURCE_DIR}/libraries/${SHADER_LIB}/src")
string(REGEX REPLACE "[-]" "_" SHADER_NAMESPACE ${SHADER_LIB})
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "namespace ${SHADER_NAMESPACE} {\n")
@ -165,66 +263,103 @@ macro(AUTOSCRIBE_SHADER_LIB)
# Finish the shader enums
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()
macro(AUTOSCRIBE_SHADER_LIBS)
set(SCRIBE_COMMAND scribe)
set(SHREFLECT_COMMAND shreflect)
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()
message(STATUS "Shader processing start")
set(AUTOSCRIBE_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/headers)
# Start the shader IDs
set(SHADER_COUNT 1)
set(SHADERS_DIR "${CMAKE_CURRENT_BINARY_DIR}/shaders")
set(SHADER_ENUMS "")
file(MAKE_DIRECTORY ${SHADERS_DIR})
set(SHADER_ENUMS "")
set(SHADER_COUNT 1)
#
# Scribe generation & program defintiion
#
foreach(SHADER_LIB ${ARGN})
list(APPEND AUTOSCRIBE_SHADER_SEEN_LIBS ${SHADER_LIB})
AUTOSCRIBE_SHADER_LIB(${SHADER_LIB})
endforeach()
# Generate the library files
configure_file(
ShaderEnums.cpp.in
${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.cpp)
${CMAKE_CURRENT_BINARY_DIR}/ShaderEnums.cpp)
configure_file(
ShaderEnums.h.in
${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.h)
configure_file(
shaders.qrc.in
${CMAKE_CURRENT_BINARY_DIR}/shaders.qrc)
${CMAKE_CURRENT_BINARY_DIR}/ShaderEnums.h)
set(AUTOSCRIBE_SHADER_LIB_SRC "${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.h;${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.cpp")
set(QT_RESOURCES_FILE ${CMAKE_CURRENT_BINARY_DIR}/shaders.qrc)
configure_file(shaders.qrc.in ${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
add_custom_target(scribe_shaders SOURCES ${ALL_SCRIBE_SHADERS})
add_custom_target(compiled_shaders SOURCES ${COMPILED_SHADERS})
add_custom_target(reflected_shaders SOURCES ${REFLECTED_SHADERS})
add_custom_target(scribe_shaders SOURCES ${ALL_SCRIBE_SHADERS} ${AUTOSCRIBE_SHADER_HEADERS})
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")
add_dependencies(reflected_shaders shadergen)
message(STATUS "Shader processing end")
endmacro()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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}" "$@"

View 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}" "$@"

View 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": []
}
]
}
}

View file

@ -133,7 +133,7 @@
{ "from": "Keyboard.W", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_FORWARD" },
{ "from": "Keyboard.S", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_BACKWARD" },
{ "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.Right", "when": "Keyboard.Shift", "to": "Actions.LATERAL_RIGHT" },
{ "from": "Keyboard.Up", "when": "Application.CameraFirstPerson", "to": "Actions.LONGITUDINAL_FORWARD" },

View file

@ -51,32 +51,34 @@
{ "from": "Vive.RSCenter", "to": "Standard.RightPrimaryThumb" },
{ "from": "Vive.RightApplicationMenu", "to": "Standard.RightSecondaryThumb" },
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand"},
{ "from": "Vive.RightHand", "to": "Standard.RightHand"},
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand" },
{ "from": "Vive.RightHand", "to": "Standard.RightHand" },
{ "from": "Vive.Head", "to" : "Standard.Head" },
{
"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",
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
},
{
"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",
"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.TrackedObject01", "to" : "Standard.TrackedObject01" },

View file

@ -10,6 +10,7 @@ Item {
property int modality: Qt.NonModal
implicitHeight: row.height
implicitWidth: row.width
visible: false
Component.onCompleted: {
stats.parentChanged.connect(fill);

View file

@ -136,7 +136,7 @@ Item {
TextField {
id: usernameField
text: Settings.getValue("wallet/savedUsername", "");
text: Settings.getValue("keepMeLoggedIn/savedUsername", "");
width: parent.width
focus: true
placeholderText: "Username or Email"
@ -165,7 +165,7 @@ Item {
root.text = "";
}
Component.onCompleted: {
var savedUsername = Settings.getValue("wallet/savedUsername", "");
var savedUsername = Settings.getValue("keepMeLoggedIn/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 {
@ -263,21 +266,21 @@ Item {
CheckBox {
id: autoLogoutCheckbox
checked: !Settings.getValue("wallet/autoLogout", true)
text: "Keep me signed in"
checked: Settings.getValue("keepMeLoggedIn", false)
text: "Keep me logged in"
boxSize: 20;
labelFontSize: 15
color: hifi.colors.black
onCheckedChanged: {
Settings.setValue("wallet/autoLogout", !checked);
Settings.setValue("keepMeLoggedIn", checked);
if (checked) {
Settings.setValue("wallet/savedUsername", Account.username);
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
} else {
Settings.setValue("wallet/savedUsername", "");
Settings.setValue("keepMeLoggedIn/savedUsername", "");
}
}
Component.onDestruction: {
Settings.setValue("wallet/autoLogout", !checked);
Settings.setValue("keepMeLoggedIn", checked);
}
}
@ -289,7 +292,10 @@ Item {
text: qsTr(loginDialog.isSteamRunning() ? "Link Account" : "Log in")
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_Return:
event.accepted = true
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
linkAccountBody.login()
break
}

View file

@ -31,7 +31,7 @@ Rectangle {
scaleSlider.notify = false;
scaleSlider.value = Math.round(avatarScale * 10);
scaleSlider.notify = true;;
scaleSlider.notify = true;
if (settings.dominantHand === 'left') {
leftHandRadioButton.checked = true;

View file

@ -14,9 +14,9 @@
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
import "qrc:////qml//styles-uit"
import "qrc:////qml//controls-uit" as HifiControlsUit
import "qrc:////qml//controls" as HifiControls
// references XXX from root context
@ -33,13 +33,15 @@ Rectangle {
property string buttonLayout: "leftright";
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;
visible: false;
anchors.fill: parent;
color: Qt.rgba(0, 0, 0, 0.5);
z: 999;
HifiConstants { id: hifi; }
onVisibleChanged: {
if (!visible) {

View file

@ -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);
}
}
}
}

View file

@ -4,21 +4,19 @@
//
// 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.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.0
import QtQuick 2.10
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.3
import Hifi 1.0 as Hifi
import "../../../styles-uit" as HifiStylesUit
import "../../../controls-uit" as HifiControlsUit
import "qrc:////qml//styles-uit" as HifiStylesUit
import "qrc:////qml//controls-uit" as HifiControlsUit
@ -27,33 +25,223 @@ Rectangle {
property string installedApps
property var nextResourceObjectId: 0
signal sendToScript(var message)
HifiStylesUit.HifiConstants { id: hifi }
ListModel { id: resourceListModel }
color: hifi.colors.white
color: hifi.colors.darkGray
AnimatedImage {
id: spinner;
source: "spinner.gif"
width: 74;
height: width;
anchors.verticalCenter: parent.verticalCenter;
anchors.horizontalCenter: parent.horizontalCenter;
//
// TITLE BAR START
//
Item {
id: titleBarContainer
// Size
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) {
switch (message.method) {
case "newResourceObjectInTest":
var resourceObject = message.resourceObject;
resourceListModel.clear(); // REMOVE THIS once we support specific referrers
resourceListModel.append(resourceObject);
spinner.visible = false;
break;
case "nextObjectIdInTest":
print("!!!! message from script! " + JSON.stringify(message));
nextResourceObjectId = message.id;
spinner.visible = false;
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$/) ? "entity or wearable" :
"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,
"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) {
var httpPattern = /^http/i;
return httpPattern.test(resource) ? resource : "file:///" + resource;
}
function rezEntity(resource, entityType) {
function rezEntity(resource, entityType, resourceObjectId) {
print("!!!! tester_rezClicked");
sendToScript({
method: 'tester_rezClicked',
itemHref: toUrl(resource),
itemType: entityType});
itemType: entityType,
itemId: resourceObjectId });
}
ListView {
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]()
}
}
}
}
signal sendToScript(var message)
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View file

@ -74,8 +74,7 @@ In your Wallet's Send Money tab, choose from your list of connections, or choose
isExpanded: false;
question: "What is a Security Pic?"
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. \
<br><br><b><font color='#0093C5'><a href='#securitypic'>Tap here to change your Security Pic.</a></font></b>";
When you see your Security Pic, you know that your actions and data are securely making use of your account.";
}
ListElement {
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;
width: parent.width;
height: questionText.paintedHeight + 50;
RalewaySemiBold {
id: plusMinusButton;
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") {
Qt.openUrlExternally("mailto:support@highfidelity.com");
} else if (link === "#securitypic") {
sendSignalToWallet({method: 'walletSecurity_changeSecurityImage'});
}
}
}

View file

@ -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
//
}

View file

@ -142,7 +142,7 @@ Rectangle {
Image {
id: titleBarSecurityImage;
source: "";
visible: titleBarSecurityImage.source !== "" && !securityImageChange.visible;
visible: titleBarSecurityImage.source !== "";
anchors.right: parent.right;
anchors.rightMargin: 6;
anchors.top: parent.top;
@ -232,10 +232,6 @@ Rectangle {
root.isPassword = msg.isPasswordField;
} else if (msg.method === 'walletSetup_lowerKeyboard') {
root.keyboardRaised = false;
} else if (msg.method === 'walletSecurity_changePassphraseCancelled') {
root.activeView = "security";
} else if (msg.method === 'walletSecurity_changePassphraseSuccess') {
root.activeView = "security";
} else {
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
@ -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 {
id: help;
visible: root.activeView === "help";
@ -407,14 +349,6 @@ Rectangle {
anchors.left: parent.left;
anchors.right: parent.right;
Connections {
onSendSignalToWallet: {
if (msg.method === 'walletSecurity_changeSecurityImage') {
securityImageChange.initModel();
root.activeView = "securityImageChange";
}
}
}
}
@ -427,8 +361,8 @@ Rectangle {
//
Item {
id: tabButtonsContainer;
visible: !needsLogIn.visible && root.activeView !== "passphraseChange" && root.activeView !== "securityImageChange" && sendMoney.currentActiveView !== "sendAssetStep";
property int numTabs: 5;
visible: !needsLogIn.visible && root.activeView !== "passphraseChange" && sendMoney.currentActiveView !== "sendAssetStep";
property int numTabs: 4;
// Size
width: root.width;
height: 90;
@ -452,7 +386,7 @@ Rectangle {
anchors.left: parent.left;
anchors.bottom: parent.bottom;
width: parent.width / tabButtonsContainer.numTabs;
HiFiGlyphs {
id: homeTabIcon;
text: hifi.glyphs.home2;
@ -506,7 +440,7 @@ Rectangle {
anchors.left: walletHomeButtonContainer.right;
anchors.bottom: parent.bottom;
width: parent.width / tabButtonsContainer.numTabs;
HiFiGlyphs {
id: exchangeMoneyTabIcon;
text: hifi.glyphs.leftRightArrows;
@ -550,7 +484,7 @@ Rectangle {
anchors.left: exchangeMoneyButtonContainer.right;
anchors.bottom: parent.bottom;
width: parent.width / tabButtonsContainer.numTabs;
HiFiGlyphs {
id: sendMoneyTabIcon;
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
Rectangle {
id: helpButtonContainer;
visible: !walletSetup.visible;
color: root.activeView === "help" ? hifi.colors.blueAccent : hifi.colors.black;
anchors.top: parent.top;
anchors.left: securityButtonContainer.right;
anchors.left: sendMoneyButtonContainer.right;
anchors.bottom: parent.bottom;
width: parent.width / tabButtonsContainer.numTabs;
HiFiGlyphs {
id: helpTabIcon;
text: hifi.glyphs.question;

View file

@ -243,7 +243,6 @@ Item {
height: 50;
text: "Set Up Wallet";
onClicked: {
securityImageSelection.initModel();
root.activeView = "step_2";
}
}
@ -267,124 +266,6 @@ Item {
// 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
//
@ -525,7 +406,6 @@ Item {
width: 200;
text: "Back"
onClicked: {
securityImageSelection.resetSelection();
root.lastPage = "step_3";
root.activeView = "step_2";
}

View 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;
}
}
}
}
}

View file

@ -1,11 +1,11 @@
//
// SecurityImageChange.qml
// qml/hifi/commerce/wallet
// qml\hifi\dialogs\security
//
// SecurityImageChange
// Security
//
// Created by Zach Fox on 2017-08-18
// Copyright 2017 High Fidelity, Inc.
// 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
@ -13,16 +13,17 @@
import Hifi 1.0 as Hifi
import QtQuick 2.5
import "../../../styles-uit"
import "../../../controls-uit" as HifiControlsUit
import "../../../controls" as HifiControls
import "qrc:////qml//styles-uit" as HifiStylesUit
import "qrc:////qml//controls-uit" as HifiControlsUit
import "qrc:////qml//controls" as HifiControls
// references XXX from root context
Item {
HifiConstants { id: hifi; }
Rectangle {
HifiStylesUit.HifiConstants { id: hifi; }
id: root;
color: hifi.colors.baseGray;
property bool justSubmitted: false;
Connections {
@ -33,7 +34,7 @@ Item {
securityImageChangePageSecurityImage.source = "image://security/securityImage";
if (exists) { // Success submitting new security image
if (root.justSubmitted) {
sendSignalToWallet({method: "walletSecurity_changeSecurityImageSuccess"});
sendSignalToParent({method: "walletSecurity_changeSecurityImageSuccess"});
root.justSubmitted = false;
}
} else if (root.justSubmitted) {
@ -72,7 +73,7 @@ Item {
anchors.bottom: parent.bottom;
height: 22;
// Lock icon
HiFiGlyphs {
HifiStylesUit.HiFiGlyphs {
id: lockIcon;
text: hifi.glyphs.lock;
anchors.bottom: parent.bottom;
@ -83,8 +84,8 @@ Item {
verticalAlignment: Text.AlignBottom;
color: hifi.colors.white;
}
// "Security image" text below pic
RalewayRegular {
// "Security image" text below image
HifiStylesUit.RalewayRegular {
id: securityImageText;
text: "SECURITY PIC";
// Text size
@ -116,9 +117,9 @@ Item {
anchors.bottom: parent.bottom;
// "Change Security Image" text
RalewaySemiBold {
HifiStylesUit.RalewaySemiBold {
id: securityImageTitle;
text: "Change Security Pic:";
text: "Change Security Image:";
// Text size
size: 18;
anchors.top: parent.top;
@ -139,12 +140,6 @@ Item {
anchors.right: parent.right;
anchors.rightMargin: 16;
height: 300;
Connections {
onSendSignalToWallet: {
sendSignalToWallet(msg);
}
}
}
// Navigation Bar
@ -169,7 +164,7 @@ Item {
width: 150;
text: "Cancel"
onClicked: {
sendSignalToWallet({method: "walletSecurity_changeSecurityImageCancelled"});
sendSignalToParent({method: "walletSecurity_changeSecurityImageCancelled"});
}
}
@ -197,7 +192,7 @@ Item {
// SECURITY IMAGE SELECTION END
//
signal sendSignalToWallet(var msg);
signal sendSignalToParent(var msg);
function initModel() {
securityImageSelection.initModel();

View file

@ -1,11 +1,11 @@
//
// SecurityImageModel.qml
// qml/hifi/commerce
// qml\hifi\dialogs\security
//
// SecurityImageModel
// Security
//
// Created by Zach Fox on 2017-08-17
// Copyright 2017 High Fidelity, Inc.
// 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

View file

@ -1,11 +1,11 @@
//
// SecurityImageSelection.qml
// qml/hifi/commerce/wallet
// qml\hifi\dialogs\security
//
// SecurityImageSelection
// Security
//
// Created by Zach Fox on 2017-08-17
// Copyright 2017 High Fidelity, Inc.
// 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
@ -13,14 +13,14 @@
import Hifi 1.0 as Hifi
import QtQuick 2.5
import "../../../styles-uit"
import "../../../controls-uit" as HifiControlsUit
import "../../../controls" as HifiControls
import "qrc:////qml//styles-uit" as HifiStylesUit
import "qrc:////qml//controls-uit" as HifiControlsUit
import "qrc:////qml//controls" as HifiControls
// references XXX from root context
Item {
HifiConstants { id: hifi; }
HifiStylesUit.HifiConstants { id: hifi; }
id: root;
property alias currentIndex: securityImageGrid.currentIndex;
@ -64,17 +64,15 @@ Item {
}
}
highlight: Rectangle {
width: securityImageGrid.cellWidth;
height: securityImageGrid.cellHeight;
color: hifi.colors.blueHighlight;
}
width: securityImageGrid.cellWidth;
height: securityImageGrid.cellHeight;
color: hifi.colors.blueHighlight;
}
}
//
// FUNCTION DEFINITIONS START
//
signal sendSignalToWallet(var msg);
function getImagePathFromImageID(imageID) {
return (imageID ? gridModel.getImagePathFromImageID(imageID) : "");
}

View file

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

View file

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View file

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View file

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View file

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View file

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View file

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View file

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View file

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View file

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View file

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View file

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View file

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View file

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View file

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View file

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View file

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View file

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View file

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View file

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View file

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View file

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View file

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View file

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View file

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View file

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -175,7 +175,7 @@ TabBar {
method: "newEntityButtonClicked",
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) {
switch (message.method) {
case 'selectTab':
@ -326,9 +311,6 @@ TabBar {
case 'grid':
editTabView.currentIndex = 3;
break;
case 'particle':
editTabView.currentIndex = 4;
break;
default:
console.warn('Attempt to switch to invalid tab:', id);
}

View file

@ -18,7 +18,6 @@ TabBar {
readonly property int create: 0
readonly property int properties: 1
readonly property int grid: 2
readonly property int particle: 3
}
readonly property HifiConstants hifi: HifiConstants {}
@ -182,7 +181,7 @@ TabBar {
method: "newEntityButtonClicked",
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) {
switch (message.method) {
case 'selectTab':
@ -299,7 +283,7 @@ TabBar {
// Changes the current tab based on tab index or title as input
function selectTab(id) {
if (typeof id === 'number') {
if (id >= tabIndex.create && id <= tabIndex.particle) {
if (id >= tabIndex.create && id <= tabIndex.grid) {
editTabView.currentIndex = id;
} else {
console.warn('Attempt to switch to invalid tab:', id);
@ -315,9 +299,6 @@ TabBar {
case 'grid':
editTabView.currentIndex = tabIndex.grid;
break;
case 'particle':
editTabView.currentIndex = tabIndex.particle;
break;
default:
console.warn('Attempt to switch to invalid tab:', id);
}

View file

@ -116,9 +116,14 @@ Rectangle {
Column {
id: column2
width: 200
height: 400
height: 600
spacing: 10
CheckBox {
id: grabbable
text: qsTr("Grabbable")
}
CheckBox {
id: dynamic
text: qsTr("Dynamic")
@ -217,9 +222,10 @@ Rectangle {
newModelDialog.sendToScript({
method: "newModelDialogAdd",
params: {
textInput: modelURL.text,
checkBox: dynamic.checked,
comboBox: collisionType.currentIndex
url: modelURL.text,
dynamic: dynamic.checked,
collisionShapeIndex: collisionType.currentIndex,
grabbable: grabbable.checked
}
});
}

View file

@ -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 {
id: viveDesktopText
size: 10
size: 12
text: "Use " + stack.selectedPlugin + " devices in desktop mode"
color: hifi.colors.white
color: hifi.colors.lightGrayText
anchors {
left: viveInDesktop.right
@ -946,6 +979,7 @@ Flickable {
viveInDesktop.checked = desktopMode;
hmdInDesktop.checked = hmdDesktopPosition;
outOfRangeDataStrategyComboBox.currentIndex = outOfRangeDataStrategyComboBox.model.indexOf(settings.outOfRangeDataStrategy);
initializeButtonState();
updateCalibrationText();
@ -1107,7 +1141,8 @@ Flickable {
"armCircumference": armCircumference.realValue,
"shoulderWidth": shoulderWidth.realValue,
"desktopMode": viveInDesktop.checked,
"hmdDesktopTracking": hmdInDesktop.checked
"hmdDesktopTracking": hmdInDesktop.checked,
"outOfRangeDataStrategy": outOfRangeDataStrategyComboBox.model[outOfRangeDataStrategyComboBox.currentIndex]
}
return settingsObject;

View file

@ -52,6 +52,8 @@
#include <QTemporaryDir>
#include <gl/QOpenGLContextWrapper.h>
#include <gl/GLWindow.h>
#include <gl/GLHelpers.h>
#include <shared/FileUtils.h>
#include <shared/QtHelpers.h>
@ -226,6 +228,7 @@
#include "commerce/Ledger.h"
#include "commerce/Wallet.h"
#include "commerce/QmlCommerce.h"
#include "ResourceRequestObserver.h"
#include "webbrowser/WebBrowserSuggestionsEngine.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 ACTIVE_DISPLAY_PLUGIN_SETTING_NAME = "activeDisplayPlugin";
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 {
{ SVO_EXTENSION, &Application::importSVOFromURL },
@ -947,6 +950,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
DependencyManager::set<WalletScriptingInterface>();
DependencyManager::set<FadeEffect>();
DependencyManager::set<ResourceRequestObserver>();
return previousSessionCrashed;
}
@ -969,9 +973,11 @@ OffscreenGLCanvas* _qmlShareContext { nullptr };
// and manually set THAT to be the shared context for the Chromium helper
#if !defined(DISABLE_QML)
OffscreenGLCanvas* _chromiumShareContext { nullptr };
Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext *context);
#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 };
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);
// Make sure the window is set to the correct size by processing the pending events
QCoreApplication::processEvents();
_glWidget->createContext();
// Create the main thread context, the GPU backend
initializeGL();
@ -2562,8 +2567,8 @@ void Application::cleanupBeforeQuit() {
}
DependencyManager::destroy<ScriptEngines>();
bool autoLogout = Setting::Handle<bool>(AUTO_LOGOUT_SETTING_NAME, false).get();
if (autoLogout) {
bool keepMeLoggedIn = Setting::Handle<bool>(KEEP_ME_LOGGED_IN_SETTING_NAME, false).get();
if (!keepMeLoggedIn) {
DependencyManager::get<AccountManager>()->removeAccountFromFile();
}
@ -2725,46 +2730,66 @@ void Application::initializeGL() {
_isGLInitialized = true;
}
if (!_glWidget->makeCurrent()) {
qCWarning(interfaceapp, "Unable to make window context current");
}
_glWidget->windowHandle()->setFormat(getDefaultOpenGLSurfaceFormat());
// 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)
// Build a shared canvas / context for the Chromium processes
{
// 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"));
}
if (!globalShareContext) {
// Chromium rendering uses some GL functions that prevent nSight from capturing
// frames, so we only create the shared context if nsight is NOT active.
if (!nsightActive()) {
_chromiumShareContext = new OffscreenGLCanvas();
_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()) {
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();
// 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
_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
{
_qmlShareContext = new OffscreenGLCanvas();
_qmlShareContext->setObjectName("QmlShareContext");
_qmlShareContext->create(_glWidget->qglContext());
_qmlShareContext->create(globalShareContext);
if (!_qmlShareContext->makeCurrent()) {
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/PassphraseModal.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/WalletHome.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);
qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem");
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
@ -3129,6 +3154,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
surfaceContext->setContextProperty("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance());
surfaceContext->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
@ -5022,12 +5048,12 @@ void Application::saveSettings() const {
PluginManager::getInstance()->saveSettings();
}
bool Application::importEntities(const QString& urlOrFilename) {
bool Application::importEntities(const QString& urlOrFilename, const bool isObservable, const qint64 callerId) {
bool success = false;
_entityClipboard->withWriteLock([&] {
_entityClipboard->eraseAllOctreeElements();
success = _entityClipboard->readFromURL(urlOrFilename);
success = _entityClipboard->readFromURL(urlOrFilename, isObservable, callerId);
if (success) {
_entityClipboard->reaverageOctreeElements();
}
@ -5812,6 +5838,42 @@ void Application::update(float deltaTime) {
controller::Pose pose = userInputMapper->getPoseState(action);
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...
@ -5978,7 +6040,9 @@ void Application::update(float deltaTime) {
{
PROFILE_RANGE_EX(app, "Overlays", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount());
PerformanceTimer perfTimer("overlays");
_overlays.update(deltaTime);
if (qApp->shouldPaint()) {
_overlays.update(deltaTime);
}
}
// 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);
PerformanceTimer perfTimer("postUpdateLambdas");
std::unique_lock<std::mutex> guard(_postUpdateLambdasLock);
for (auto& iter : _postUpdateLambdas) {
iter.second();
if (qApp->shouldPaint()) {
for (auto& iter : _postUpdateLambdas) {
iter.second();
}
}
_postUpdateLambdas.clear();
}
@ -6811,6 +6877,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
scriptEngine->registerGlobalObject("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
scriptEngine->registerGlobalObject("AddressManager", DependencyManager::get<AddressManager>().data());
scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance());
scriptEngine->registerGlobalObject("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
@ -7197,7 +7264,8 @@ void Application::addAssetToWorldFromURL(QString url) {
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);
request->send();
}
@ -8306,6 +8374,10 @@ void Application::setShowBulletConstraintLimits(bool value) {
_physicsEngine->setShowBulletConstraintLimits(value);
}
void Application::setShowTrackedObjects(bool value) {
_showTrackedObjects = value;
}
void Application::startHMDStandBySession() {
_autoSwitchDisplayModeSupportedHMDPlugin->startStandBySession();
}

View file

@ -342,7 +342,7 @@ public slots:
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, 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 updateSystemTabletMode();
void goToErrorDomainURL(QUrl errorDomainURL);
@ -498,6 +498,8 @@ private slots:
void setShowBulletConstraints(bool value);
void setShowBulletConstraintLimits(bool value);
void setShowTrackedObjects(bool value);
private:
void init();
bool handleKeyEventForFocusedEntityOrOverlay(QEvent* event);
@ -779,5 +781,8 @@ private:
std::atomic<bool> _pendingRenderEvent { true };
bool quitWhenFinished { false };
bool _showTrackedObjects { false };
bool _prevShowTrackedObjects { false };
};
#endif // hifi_Application_h

View file

@ -265,6 +265,18 @@ Menu::Menu() {
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
addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus()));
@ -273,15 +285,71 @@ Menu::Menu() {
// Developer menu ----------------------------------
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 >>>
MenuWrapper* uiOptionsMenu = developerMenu->addMenu("UI");
action = addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::DesktopTabletToToolbar, 0,
qApp->getDesktopTabletBecomesToolbarSetting());
// Developer > UI > Show Overlays
addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::Overlays, 0, true);
// Developer > UI > Desktop Tablet Becomes Toolbar
connect(action, &QAction::triggered, [action] {
qApp->setDesktopTabletBecomesToolbarSetting(action->isChecked());
});
// Developer > UI > HMD Tablet Becomes Toolbar
action = addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::HMDTabletToToolbar, 0,
qApp->getHmdTabletBecomesToolbarSetting());
connect(action, &QAction::triggered, [action] {
@ -570,6 +638,8 @@ Menu::Menu() {
avatar.get(), SLOT(updateMotionBehaviorFromMenu()),
UNSPECIFIED_POSITION, "Developer");
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowTrackedObjects, 0, false, qApp, SLOT(setShowTrackedObjects(bool)));
// Developer > Hands >>>
MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands");
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false,
@ -684,10 +754,11 @@ Menu::Menu() {
addCheckableActionToQMenuAndActionHash(pickingOptionsMenu, MenuOption::ForceCoarsePicking, 0, false,
DependencyManager::get<PickManager>().data(), SLOT(setForceCoarsePicking(bool)));
// Developer > Display Crash Options
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::DisplayCrashOptions, 0, true);
// Developer > 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::UnresponsiveInterface, 0, qApp, SLOT(unresponsiveApplication()));
@ -722,59 +793,15 @@ Menu::Menu() {
action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNewFaultThreaded);
connect(action, &QAction::triggered, qApp, []() { std::thread(crash::newFault).join(); });
// Developer > Stats
// Developer > Show Statistics
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Stats);
// Developer > Show Animation Statistics
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::AnimStats);
// Settings > Enable Speech Control API
#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...
// Developer > Log
addActionToQMenuAndActionHash(developerMenu, MenuOption::Log, Qt::CTRL | Qt::SHIFT | Qt::Key_L,
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 --------------
addDisabledActionAndSeparator(navigateMenu, "History");

View file

@ -183,6 +183,7 @@ namespace MenuOption {
const QString RunClientScriptTests = "Run Client Script Tests";
const QString RunTimingTests = "Run Timing Tests";
const QString ScriptedMotorControl = "Enable Scripted Motor Control";
const QString ShowTrackedObjects = "Show Tracked Objects";
const QString SendWrongDSConnectVersion = "Send wrong DS connect version";
const QString SendWrongProtocolVersion = "Send wrong protocol version";
const QString SetHomeLocation = "Set Home Location";

View file

@ -235,7 +235,7 @@ bool ModelPackager::zipModel() {
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;
@ -370,7 +370,7 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename
void ModelPackager::listTextures() {
_textures.clear();
foreach (const FBXMaterial mat, _geometry->materials) {
foreach (const HFMMaterial mat, _geometry->materials) {
if (!mat.albedoTexture.filename.isEmpty() && mat.albedoTexture.content.isEmpty() &&
!_textures.contains(mat.albedoTexture.filename)) {
_textures << mat.albedoTexture.filename;

View file

@ -19,7 +19,7 @@
#include "ui/ModelsBrowser.h"
class FBXGeometry;
class HFMGeometry;
class ModelPackager : public QObject {
public:
@ -32,7 +32,7 @@ private:
bool editProperties();
bool zipModel();
void populateBasicMapping(QVariantHash& mapping, QString filename, const FBXGeometry& geometry);
void populateBasicMapping(QVariantHash& mapping, QString filename, const HFMGeometry& geometry);
void listTextures();
bool copyTextures(const QString& oldDir, const QDir& newDir);
@ -44,7 +44,7 @@ private:
QString _scriptDir;
QVariantHash _mapping;
std::unique_ptr<FBXGeometry> _geometry;
std::unique_ptr<HFMGeometry> _geometry;
QStringList _textures;
QStringList _scripts;
};

View file

@ -27,7 +27,7 @@
ModelPropertiesDialog::ModelPropertiesDialog(FSTReader::ModelType modelType, const QVariantHash& originalMapping,
const QString& basePath, const FBXGeometry& geometry) :
const QString& basePath, const HFMGeometry& geometry) :
_modelType(modelType),
_originalMapping(originalMapping),
_basePath(basePath),
@ -249,7 +249,7 @@ QComboBox* ModelPropertiesDialog::createJointBox(bool withNone) const {
if (withNone) {
box->addItem("(none)");
}
foreach (const FBXJoint& joint, _geometry.joints) {
foreach (const HFMJoint& joint, _geometry.joints) {
if (joint.isSkeletonJoint || !_geometry.hasSkeletonJoints) {
box->addItem(joint.name);
}

View file

@ -30,7 +30,7 @@ class ModelPropertiesDialog : public QDialog {
public:
ModelPropertiesDialog(FSTReader::ModelType modelType, const QVariantHash& originalMapping,
const QString& basePath, const FBXGeometry& geometry);
const QString& basePath, const HFMGeometry& geometry);
QVariantHash getMapping() const;
@ -50,7 +50,7 @@ private:
FSTReader::ModelType _modelType;
QVariantHash _originalMapping;
QString _basePath;
FBXGeometry _geometry;
HFMGeometry _geometry;
QLineEdit* _name = nullptr;
QPushButton* _textureDirectory = nullptr;
QPushButton* _scriptDirectory = nullptr;

View file

@ -53,7 +53,8 @@ void ATPAssetMigrator::loadEntityServerFile() {
auto migrateResources = [=](QUrl migrationURL, QJsonValueRef jsonValue, bool isModelURL) {
auto request =
DependencyManager::get<ResourceManager>()->createResourceRequest(this, migrationURL);
DependencyManager::get<ResourceManager>()->createResourceRequest(
this, migrationURL, true, -1, "ATPAssetMigrator::loadEntityServerFile");
if (request) {
qCDebug(asset_migrator) << "Requesting" << migrationURL << "for ATP asset migration";

View file

@ -135,7 +135,7 @@ bool AvatarActionHold::getTarget(float deltaTimeStep, glm::quat& rotation, glm::
glm::vec3 palmPosition;
glm::quat palmRotation;
bool isTransitingWithAvatar = holdingAvatar->getTransit()->isTransiting();
bool isTransitingWithAvatar = holdingAvatar->getTransit()->isActive();
if (isTransitingWithAvatar != _isTransitingWithAvatar) {
_isTransitingWithAvatar = isTransitingWithAvatar;
auto ownerEntity = _ownerEntity.lock();
@ -424,7 +424,7 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
if (ownerEntity) {
ownerEntity->setDynamicDataDirty(true);
ownerEntity->setDynamicDataNeedsTransmit(true);
ownerEntity->setTransitingWithAvatar(myAvatar->getTransit()->isTransiting());
ownerEntity->setTransitingWithAvatar(myAvatar->getTransit()->isActive());
}
});
}

View file

@ -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._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._isDistanceBased = true;
_transitConfig._isDistanceBased = AVATAR_TRANSIT_DISTANCE_BASED;
_transitConfig._abortDistance = AVATAR_TRANSIT_ABORT_DISTANCE;
}
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
@ -126,13 +124,39 @@ void AvatarManager::setSpace(workload::SpacePointer& 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) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "AvatarManager::updateMyAvatar()");
AvatarTransit::Status status = _myAvatar->updateTransit(deltaTime, _myAvatar->getNextPosition(), _transitConfig);
bool sendFirstTransitPackage = (status == AvatarTransit::Status::START_TRANSIT);
bool blockTransitData = (status == AvatarTransit::Status::TRANSITING);
AvatarTransit::Status status = _myAvatar->updateTransit(deltaTime, _myAvatar->getNextPosition(), _myAvatar->getSensorToWorldScale(), _transitConfig);
handleTransitAnimations(status);
_myAvatar->update(deltaTime);
render::Transaction transaction;
@ -142,18 +166,13 @@ void AvatarManager::updateMyAvatar(float deltaTime) {
quint64 now = usecTimestampNow();
quint64 dt = now - _lastSendAvatarDataTime;
if (sendFirstTransitPackage || (dt > MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS && !_myAvatarDataPacketsPaused && !blockTransitData)) {
if (dt > MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS && !_myAvatarDataPacketsPaused) {
// send head/hand data to the avatar mixer and voxel server
PerformanceTimer perfTimer("send");
if (sendFirstTransitPackage) {
_myAvatar->overrideNextPackagePositionData(_myAvatar->getTransit()->getEndPosition());
}
PerformanceTimer perfTimer("send");
_myAvatar->sendAvatarDataPacket();
_lastSendAvatarDataTime = now;
_myAvatarSendRate.increment();
}
}
@ -242,7 +261,9 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
for (auto it = sortedAvatarVector.begin(); it != sortedAvatarVector.end(); ++it) {
const SortableAvatar& sortData = *it;
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
if (avatar->getSkeletonModel()->isLoaded()) {
// remove the orb if it is there
@ -267,7 +288,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
if (inView && avatar->hasNewJointData()) {
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)) {
avatar->_transit.reset();
avatar->setIsNewAvatar(false);

Some files were not shown because too many files have changed in this diff Show more