Merge remote-tracking branch 'upstream/master' into android_nov
4
.gitignore
vendored
|
@ -23,7 +23,7 @@ android/app/src/main/res/values/libs.xml
|
||||||
android/app/src/main/assets/bundled
|
android/app/src/main/assets/bundled
|
||||||
|
|
||||||
# VSCode
|
# VSCode
|
||||||
# List taken from Github Global Ignores master@435c4d92
|
# List taken from Github Global Ignores master@435c4d92
|
||||||
# https://github.com/github/gitignore/commits/master/Global/VisualStudioCode.gitignore
|
# https://github.com/github/gitignore/commits/master/Global/VisualStudioCode.gitignore
|
||||||
.vscode/*
|
.vscode/*
|
||||||
!.vscode/settings.json
|
!.vscode/settings.json
|
||||||
|
@ -69,7 +69,7 @@ gvr-interface/libs/*
|
||||||
# ignore files for various dev environments
|
# ignore files for various dev environments
|
||||||
TAGS
|
TAGS
|
||||||
*.sw[po]
|
*.sw[po]
|
||||||
*.qmlc
|
*.jsc
|
||||||
|
|
||||||
# ignore QML compilation output
|
# ignore QML compilation output
|
||||||
*.qmlc
|
*.qmlc
|
||||||
|
|
27
BUILD_LINUX_CHEATSHEET.md
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# this guide is specific to Ubuntu 16.04.
|
||||||
|
# deb packages of High Fidelity domain server and assignment client are stored on debian.highfidelity.com
|
||||||
|
sudo su -
|
||||||
|
apt-get -y update
|
||||||
|
apt-get install -y software-properties-common
|
||||||
|
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 15FF1AAE
|
||||||
|
add-apt-repository "deb http://debian.highfidelity.com stable main"
|
||||||
|
apt-get -y update
|
||||||
|
apt-get install -y hifi-domain-server
|
||||||
|
apt-get install -y hifi-assignment-client
|
||||||
|
|
||||||
|
# When installing master/dev builds, the packages are slightly different and you just need to change the last 2 steps to:
|
||||||
|
apt-get install -y hifi-dev-domain-server
|
||||||
|
apt-get install -y hifi-dev-assignment-client
|
||||||
|
|
||||||
|
# domain server and assignment clients should already be running. The processes are controlled via:
|
||||||
|
systemctl start hifi-domain-server
|
||||||
|
systemctl stop hifi-domain-server
|
||||||
|
|
||||||
|
# Once the machine is setup and processes are running you should ensure that your firewall exposes port 40100 on TCP and all UDP ports. This will get your domain up and running and you could connect to it (for now) by using High Fidelity Interface and typing in the IP for the place name. (further customizations can be done via http://IPAddress:40100).
|
||||||
|
|
||||||
|
# The server always depends on both hifi-domain-server and hifi-assignment-client running at the same time.
|
||||||
|
# As an additional step, you should ensure that your packages are automatically updated when a new version goes out. You could, for example, set the automatic update checks to happen every hour (though this could potentially result in the domain being unreachable for a whole hour by new clients when they are released - adjust the update checks accordingly).
|
||||||
|
To do this you can modify /etc/crontab by adding the following lines
|
||||||
|
0 */1 * * * root apt-get update
|
||||||
|
1 */1 * * * root apt-get install --only-upgrade -y hifi-domain-server
|
||||||
|
2 */1 * * * root apt-get install --only-upgrade -y hifi-assignment-client
|
|
@ -454,6 +454,8 @@ task cleanDependencies(type: Delete) {
|
||||||
delete 'app/src/main/res/values/libs.xml'
|
delete 'app/src/main/res/values/libs.xml'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME this code is prototyping the desired functionality for doing build time binary dependency resolution.
|
||||||
|
// See the comment on the qtBundle task above
|
||||||
/*
|
/*
|
||||||
// FIXME derive the path from the gradle environment
|
// FIXME derive the path from the gradle environment
|
||||||
def toolchain = [
|
def toolchain = [
|
||||||
|
|
|
@ -94,7 +94,6 @@ Agent::Agent(ReceivedMessage& message) :
|
||||||
packetReceiver.registerListenerForTypes(
|
packetReceiver.registerListenerForTypes(
|
||||||
{ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase },
|
{ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase },
|
||||||
this, "handleOctreePacket");
|
this, "handleOctreePacket");
|
||||||
packetReceiver.registerListener(PacketType::Jurisdiction, this, "handleJurisdictionPacket");
|
|
||||||
packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat");
|
packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat");
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,17 +148,6 @@ void Agent::handleOctreePacket(QSharedPointer<ReceivedMessage> message, SharedNo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Agent::handleJurisdictionPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
|
||||||
NodeType_t nodeType;
|
|
||||||
message->peekPrimitive(&nodeType);
|
|
||||||
|
|
||||||
// PacketType_JURISDICTION, first byte is the node type...
|
|
||||||
if (nodeType == NodeType::EntityServer) {
|
|
||||||
DependencyManager::get<EntityScriptingInterface>()->getJurisdictionListener()->
|
|
||||||
queueReceivedPacket(message, senderNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Agent::handleAudioPacket(QSharedPointer<ReceivedMessage> message) {
|
void Agent::handleAudioPacket(QSharedPointer<ReceivedMessage> message) {
|
||||||
_receivedAudioStream.parseData(*message);
|
_receivedAudioStream.parseData(*message);
|
||||||
_lastReceivedAudioLoudness = _receivedAudioStream.getNextOutputFrameLoudness();
|
_lastReceivedAudioLoudness = _receivedAudioStream.getNextOutputFrameLoudness();
|
||||||
|
@ -483,10 +471,7 @@ void Agent::executeScript() {
|
||||||
auto recordingInterface = DependencyManager::get<RecordingScriptingInterface>();
|
auto recordingInterface = DependencyManager::get<RecordingScriptingInterface>();
|
||||||
_scriptEngine->registerGlobalObject("Recording", recordingInterface.data());
|
_scriptEngine->registerGlobalObject("Recording", recordingInterface.data());
|
||||||
|
|
||||||
// we need to make sure that init has been called for our EntityScriptingInterface
|
|
||||||
// so that it actually has a jurisdiction listener when we ask it for it next
|
|
||||||
entityScriptingInterface->init();
|
entityScriptingInterface->init();
|
||||||
_entityViewer.setJurisdictionListener(entityScriptingInterface->getJurisdictionListener());
|
|
||||||
|
|
||||||
_entityViewer.init();
|
_entityViewer.init();
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,6 @@ private slots:
|
||||||
|
|
||||||
void handleAudioPacket(QSharedPointer<ReceivedMessage> message);
|
void handleAudioPacket(QSharedPointer<ReceivedMessage> message);
|
||||||
void handleOctreePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
void handleOctreePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
void handleJurisdictionPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
|
||||||
void handleSelectedAudioFormat(QSharedPointer<ReceivedMessage> message);
|
void handleSelectedAudioFormat(QSharedPointer<ReceivedMessage> message);
|
||||||
|
|
||||||
void nodeActivated(SharedNodePointer activatedNode);
|
void nodeActivated(SharedNodePointer activatedNode);
|
||||||
|
|
|
@ -46,8 +46,14 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
|
||||||
|
|
||||||
const QCommandLineOption helpOption = parser.addHelpOption();
|
const QCommandLineOption helpOption = parser.addHelpOption();
|
||||||
|
|
||||||
const QCommandLineOption clientTypeOption(ASSIGNMENT_TYPE_OVERRIDE_OPTION,
|
QString typeDescription = "run single assignment client of given type\n# | Type\n============================";
|
||||||
"run single assignment client of given type", "type");
|
for (Assignment::Type type = Assignment::FirstType;
|
||||||
|
type != Assignment::AllTypes;
|
||||||
|
type = static_cast<Assignment::Type>(static_cast<int>(type) + 1)) {
|
||||||
|
typeDescription.append(QStringLiteral("\n%1 | %2").arg(QString::number(type), Assignment::typeToString(type)));
|
||||||
|
}
|
||||||
|
const QCommandLineOption clientTypeOption(ASSIGNMENT_TYPE_OVERRIDE_OPTION, typeDescription, "type");
|
||||||
|
|
||||||
parser.addOption(clientTypeOption);
|
parser.addOption(clientTypeOption);
|
||||||
|
|
||||||
const QCommandLineOption poolOption(ASSIGNMENT_POOL_OPTION, "set assignment pool", "pool-name");
|
const QCommandLineOption poolOption(ASSIGNMENT_POOL_OPTION, "set assignment pool", "pool-name");
|
||||||
|
|
|
@ -214,7 +214,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
uint64_t getTimestamp() const override {
|
uint64_t getTimestamp() const override {
|
||||||
return _lastEncodeTime;
|
return _lastEncodeTime;
|
||||||
}
|
}
|
||||||
const AvatarSharedPointer& getAvatar() const { return _avatar; }
|
AvatarSharedPointer getAvatar() const { return _avatar; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AvatarSharedPointer _avatar;
|
AvatarSharedPointer _avatar;
|
||||||
|
@ -326,7 +326,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
|
|
||||||
int remainingAvatars = (int)sortedAvatars.size();
|
int remainingAvatars = (int)sortedAvatars.size();
|
||||||
while (!sortedAvatars.empty()) {
|
while (!sortedAvatars.empty()) {
|
||||||
const auto& avatarData = sortedAvatars.top().getAvatar();
|
const auto avatarData = sortedAvatars.top().getAvatar();
|
||||||
sortedAvatars.pop();
|
sortedAvatars.pop();
|
||||||
remainingAvatars--;
|
remainingAvatars--;
|
||||||
|
|
||||||
|
|
|
@ -23,23 +23,6 @@ void OctreeHeadlessViewer::queryOctree() {
|
||||||
char serverType = getMyNodeType();
|
char serverType = getMyNodeType();
|
||||||
PacketType packetType = getMyQueryMessageType();
|
PacketType packetType = getMyQueryMessageType();
|
||||||
|
|
||||||
NodeToJurisdictionMap& jurisdictions = *_jurisdictionListener->getJurisdictions();
|
|
||||||
|
|
||||||
bool wantExtraDebugging = false;
|
|
||||||
|
|
||||||
if (wantExtraDebugging) {
|
|
||||||
qCDebug(octree) << "OctreeHeadlessViewer::queryOctree() _jurisdictionListener=" << _jurisdictionListener;
|
|
||||||
qCDebug(octree) << "---------------";
|
|
||||||
qCDebug(octree) << "_jurisdictionListener=" << _jurisdictionListener;
|
|
||||||
qCDebug(octree) << "Jurisdictions...";
|
|
||||||
jurisdictions.withReadLock([&] {
|
|
||||||
for (NodeToJurisdictionMapIterator i = jurisdictions.begin(); i != jurisdictions.end(); ++i) {
|
|
||||||
qCDebug(octree) << i.key() << ": " << &i.value();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
qCDebug(octree) << "---------------";
|
|
||||||
}
|
|
||||||
|
|
||||||
_octreeQuery.setCameraPosition(_viewFrustum.getPosition());
|
_octreeQuery.setCameraPosition(_viewFrustum.getPosition());
|
||||||
_octreeQuery.setCameraOrientation(_viewFrustum.getOrientation());
|
_octreeQuery.setCameraOrientation(_viewFrustum.getOrientation());
|
||||||
_octreeQuery.setCameraFov(_viewFrustum.getFieldOfView());
|
_octreeQuery.setCameraFov(_viewFrustum.getFieldOfView());
|
||||||
|
@ -51,159 +34,22 @@ void OctreeHeadlessViewer::queryOctree() {
|
||||||
_octreeQuery.setOctreeSizeScale(_voxelSizeScale);
|
_octreeQuery.setOctreeSizeScale(_voxelSizeScale);
|
||||||
_octreeQuery.setBoundaryLevelAdjust(_boundaryLevelAdjust);
|
_octreeQuery.setBoundaryLevelAdjust(_boundaryLevelAdjust);
|
||||||
|
|
||||||
// Iterate all of the nodes, and get a count of how many voxel servers we have...
|
|
||||||
int totalServers = 0;
|
|
||||||
int inViewServers = 0;
|
|
||||||
int unknownJurisdictionServers = 0;
|
|
||||||
|
|
||||||
DependencyManager::get<NodeList>()->eachNode([&](const SharedNodePointer& node){
|
|
||||||
// only send to the NodeTypes that are serverType
|
|
||||||
if (node->getActiveSocket() && node->getType() == serverType) {
|
|
||||||
totalServers++;
|
|
||||||
|
|
||||||
// get the server bounds for this server
|
|
||||||
QUuid nodeUUID = node->getUUID();
|
|
||||||
|
|
||||||
// if we haven't heard from this voxel server, go ahead and send it a query, so we
|
|
||||||
// can get the jurisdiction...
|
|
||||||
VoxelPositionSize rootDetails;
|
|
||||||
bool foundRootDetails = false;
|
|
||||||
jurisdictions.withReadLock([&] {
|
|
||||||
if (jurisdictions.find(nodeUUID) == jurisdictions.end()) {
|
|
||||||
unknownJurisdictionServers++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const JurisdictionMap& map = (jurisdictions)[nodeUUID];
|
|
||||||
|
|
||||||
auto rootCode = map.getRootOctalCode();
|
|
||||||
if (!rootCode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
voxelDetailsForCode(rootCode.get(), rootDetails);
|
|
||||||
foundRootDetails = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (foundRootDetails) {
|
|
||||||
AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
|
|
||||||
if ((bool)(_viewFrustum.calculateCubeKeyholeIntersection(serverBounds))) {
|
|
||||||
inViewServers++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (wantExtraDebugging) {
|
|
||||||
qCDebug(octree, "Servers: total %d, in view %d, unknown jurisdiction %d",
|
|
||||||
totalServers, inViewServers, unknownJurisdictionServers);
|
|
||||||
}
|
|
||||||
|
|
||||||
int perServerPPS = 0;
|
|
||||||
const int SMALL_BUDGET = 10;
|
|
||||||
int perUnknownServer = SMALL_BUDGET;
|
|
||||||
int totalPPS = getMaxPacketsPerSecond();
|
|
||||||
|
|
||||||
// determine PPS based on number of servers
|
|
||||||
if (inViewServers >= 1) {
|
|
||||||
// set our preferred PPS to be exactly evenly divided among all of the voxel servers... and allocate 1 PPS
|
|
||||||
// for each unknown jurisdiction server
|
|
||||||
perServerPPS = (totalPPS / inViewServers) - (unknownJurisdictionServers * perUnknownServer);
|
|
||||||
} else {
|
|
||||||
if (unknownJurisdictionServers > 0) {
|
|
||||||
perUnknownServer = (totalPPS / unknownJurisdictionServers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wantExtraDebugging) {
|
|
||||||
qCDebug(octree, "perServerPPS: %d perUnknownServer: %d", perServerPPS, perUnknownServer);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
nodeList->eachNode([&](const SharedNodePointer& node){
|
|
||||||
// only send to the NodeTypes that are serverType
|
|
||||||
if (node->getActiveSocket() && node->getType() == serverType) {
|
|
||||||
|
|
||||||
// get the server bounds for this server
|
auto node = nodeList->soloNodeOfType(serverType);
|
||||||
QUuid nodeUUID = node->getUUID();
|
if (node && node->getActiveSocket()) {
|
||||||
|
_octreeQuery.setMaxQueryPacketsPerSecond(getMaxPacketsPerSecond());
|
||||||
|
|
||||||
bool inView = false;
|
auto queryPacket = NLPacket::create(packetType);
|
||||||
bool unknownView = false;
|
|
||||||
|
|
||||||
// if we haven't heard from this voxel server, go ahead and send it a query, so we
|
// encode the query data
|
||||||
// can get the jurisdiction...
|
auto packetData = reinterpret_cast<unsigned char*>(queryPacket->getPayload());
|
||||||
VoxelPositionSize rootDetails;
|
int packetSize = _octreeQuery.getBroadcastData(packetData);
|
||||||
bool foundRootDetails = false;
|
queryPacket->setPayloadSize(packetSize);
|
||||||
jurisdictions.withReadLock([&] {
|
|
||||||
if (jurisdictions.find(nodeUUID) == jurisdictions.end()) {
|
|
||||||
unknownView = true; // assume it's in view
|
|
||||||
if (wantExtraDebugging) {
|
|
||||||
qCDebug(octree) << "no known jurisdiction for node " << *node << ", assume it's visible.";
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const JurisdictionMap& map = (jurisdictions)[nodeUUID];
|
// make sure we still have an active socket
|
||||||
auto rootCode = map.getRootOctalCode();
|
nodeList->sendUnreliablePacket(*queryPacket, *node);
|
||||||
|
}
|
||||||
if (!rootCode) {
|
|
||||||
if (wantExtraDebugging) {
|
|
||||||
qCDebug(octree) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!";
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
voxelDetailsForCode(rootCode.get(), rootDetails);
|
|
||||||
foundRootDetails = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (foundRootDetails) {
|
|
||||||
AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
|
|
||||||
inView = (bool)(_viewFrustum.calculateCubeKeyholeIntersection(serverBounds));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inView) {
|
|
||||||
_octreeQuery.setMaxQueryPacketsPerSecond(perServerPPS);
|
|
||||||
if (wantExtraDebugging) {
|
|
||||||
qCDebug(octree) << "inView for node " << *node << ", give it budget of " << perServerPPS;
|
|
||||||
}
|
|
||||||
} else if (unknownView) {
|
|
||||||
if (wantExtraDebugging) {
|
|
||||||
qCDebug(octree) << "no known jurisdiction for node " << *node << ", give it budget of "
|
|
||||||
<< perUnknownServer << " to send us jurisdiction.";
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the query's position/orientation to be degenerate in a manner that will get the scene quickly
|
|
||||||
// If there's only one server, then don't do this, and just let the normal voxel query pass through
|
|
||||||
// as expected... this way, we will actually get a valid scene if there is one to be seen
|
|
||||||
if (totalServers > 1) {
|
|
||||||
_octreeQuery.setCameraPosition(glm::vec3(-0.1,-0.1,-0.1));
|
|
||||||
const glm::quat OFF_IN_NEGATIVE_SPACE = glm::quat(-0.5, 0, -0.5, 1.0);
|
|
||||||
_octreeQuery.setCameraOrientation(OFF_IN_NEGATIVE_SPACE);
|
|
||||||
_octreeQuery.setCameraNearClip(0.1f);
|
|
||||||
_octreeQuery.setCameraFarClip(0.1f);
|
|
||||||
if (wantExtraDebugging) {
|
|
||||||
qCDebug(octree) << "Using 'minimal' camera position for node" << *node;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (wantExtraDebugging) {
|
|
||||||
qCDebug(octree) << "Using regular camera position for node" << *node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_octreeQuery.setMaxQueryPacketsPerSecond(perUnknownServer);
|
|
||||||
} else {
|
|
||||||
_octreeQuery.setMaxQueryPacketsPerSecond(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup the query packet
|
|
||||||
auto queryPacket = NLPacket::create(packetType);
|
|
||||||
|
|
||||||
// read the data to our packet and set the payload size to fit the query
|
|
||||||
int querySize = _octreeQuery.getBroadcastData(reinterpret_cast<unsigned char*>(queryPacket->getPayload()));
|
|
||||||
queryPacket->setPayloadSize(querySize);
|
|
||||||
|
|
||||||
// ask the NodeList to send it
|
|
||||||
nodeList->sendPacket(std::move(queryPacket), *node);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#define hifi_OctreeHeadlessViewer_h
|
#define hifi_OctreeHeadlessViewer_h
|
||||||
|
|
||||||
#include <OctreeProcessor.h>
|
#include <OctreeProcessor.h>
|
||||||
#include <JurisdictionListener.h>
|
|
||||||
#include <OctreeQuery.h>
|
#include <OctreeQuery.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,8 +22,6 @@ class OctreeHeadlessViewer : public OctreeProcessor {
|
||||||
public:
|
public:
|
||||||
OctreeHeadlessViewer();
|
OctreeHeadlessViewer();
|
||||||
virtual ~OctreeHeadlessViewer() {};
|
virtual ~OctreeHeadlessViewer() {};
|
||||||
|
|
||||||
void setJurisdictionListener(JurisdictionListener* jurisdictionListener) { _jurisdictionListener = jurisdictionListener; }
|
|
||||||
|
|
||||||
OctreeQuery& getOctreeQuery() { return _octreeQuery; }
|
OctreeQuery& getOctreeQuery() { return _octreeQuery; }
|
||||||
|
|
||||||
|
@ -57,7 +54,6 @@ public slots:
|
||||||
unsigned getOctreeElementsCount() const { return _tree->getOctreeElementsCount(); }
|
unsigned getOctreeElementsCount() const { return _tree->getOctreeElementsCount(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JurisdictionListener* _jurisdictionListener = nullptr;
|
|
||||||
OctreeQuery _octreeQuery;
|
OctreeQuery _octreeQuery;
|
||||||
|
|
||||||
ViewFrustum _viewFrustum;
|
ViewFrustum _viewFrustum;
|
||||||
|
|
|
@ -391,8 +391,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
|
||||||
|
|
||||||
nodeData->sceneStart(usecTimestampNow() - CHANGE_FUDGE);
|
nodeData->sceneStart(usecTimestampNow() - CHANGE_FUDGE);
|
||||||
// start tracking our stats
|
// start tracking our stats
|
||||||
nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged,
|
nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, _myServer->getOctree()->getRoot());
|
||||||
_myServer->getOctree()->getRoot(), _myServer->getJurisdiction());
|
|
||||||
|
|
||||||
preStartNewScene(nodeData, isFullScene);
|
preStartNewScene(nodeData, isFullScene);
|
||||||
}
|
}
|
||||||
|
@ -507,7 +506,7 @@ void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, Octre
|
||||||
float octreeSizeScale = nodeData->getOctreeSizeScale();
|
float octreeSizeScale = nodeData->getOctreeSizeScale();
|
||||||
EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP,
|
EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP,
|
||||||
viewFrustumChanged, boundaryLevelAdjust, octreeSizeScale,
|
viewFrustumChanged, boundaryLevelAdjust, octreeSizeScale,
|
||||||
isFullScene, _myServer->getJurisdiction(), nodeData);
|
isFullScene, nodeData);
|
||||||
// Our trackSend() function is implemented by the server subclass, and will be called back as new entities/data elements are sent
|
// Our trackSend() function is implemented by the server subclass, and will be called back as new entities/data elements are sent
|
||||||
params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) {
|
params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) {
|
||||||
_myServer->trackSend(dataID, dataEdited, _nodeUuid);
|
_myServer->trackSend(dataID, dataEdited, _nodeUuid);
|
||||||
|
|
|
@ -237,8 +237,6 @@ OctreeServer::OctreeServer(ReceivedMessage& message) :
|
||||||
_debugSending(false),
|
_debugSending(false),
|
||||||
_debugReceiving(false),
|
_debugReceiving(false),
|
||||||
_verboseDebug(false),
|
_verboseDebug(false),
|
||||||
_jurisdiction(NULL),
|
|
||||||
_jurisdictionSender(NULL),
|
|
||||||
_octreeInboundPacketProcessor(NULL),
|
_octreeInboundPacketProcessor(NULL),
|
||||||
_persistThread(NULL),
|
_persistThread(NULL),
|
||||||
_started(time(0)),
|
_started(time(0)),
|
||||||
|
@ -257,12 +255,6 @@ OctreeServer::~OctreeServer() {
|
||||||
delete[] _parsedArgV;
|
delete[] _parsedArgV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_jurisdictionSender) {
|
|
||||||
_jurisdictionSender->terminating();
|
|
||||||
_jurisdictionSender->terminate();
|
|
||||||
_jurisdictionSender->deleteLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_octreeInboundPacketProcessor) {
|
if (_octreeInboundPacketProcessor) {
|
||||||
_octreeInboundPacketProcessor->terminating();
|
_octreeInboundPacketProcessor->terminating();
|
||||||
_octreeInboundPacketProcessor->terminate();
|
_octreeInboundPacketProcessor->terminate();
|
||||||
|
@ -275,9 +267,6 @@ OctreeServer::~OctreeServer() {
|
||||||
_persistThread->deleteLater();
|
_persistThread->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
delete _jurisdiction;
|
|
||||||
_jurisdiction = NULL;
|
|
||||||
|
|
||||||
// cleanup our tree here...
|
// cleanup our tree here...
|
||||||
qDebug() << qPrintable(_safeServerName) << "server START cleaning up octree... [" << this << "]";
|
qDebug() << qPrintable(_safeServerName) << "server START cleaning up octree... [" << this << "]";
|
||||||
_tree.reset();
|
_tree.reset();
|
||||||
|
@ -933,10 +922,6 @@ void OctreeServer::handleOctreeDataNackPacket(QSharedPointer<ReceivedMessage> me
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreeServer::handleJurisdictionRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
|
||||||
_jurisdictionSender->queueReceivedPacket(message, senderNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OctreeServer::handleOctreeFileReplacement(QSharedPointer<ReceivedMessage> message) {
|
void OctreeServer::handleOctreeFileReplacement(QSharedPointer<ReceivedMessage> message) {
|
||||||
if (!_isFinished && !_isShuttingDown) {
|
if (!_isFinished && !_isShuttingDown) {
|
||||||
// these messages are only allowed to come from the domain server, so make sure that is the case
|
// these messages are only allowed to come from the domain server, so make sure that is the case
|
||||||
|
@ -1111,23 +1096,6 @@ void OctreeServer::readConfiguration() {
|
||||||
qDebug() << "statusPort= DISABLED";
|
qDebug() << "statusPort= DISABLED";
|
||||||
}
|
}
|
||||||
|
|
||||||
QString jurisdictionFile;
|
|
||||||
if (readOptionString(QString("jurisdictionFile"), settingsSectionObject, jurisdictionFile)) {
|
|
||||||
qDebug("jurisdictionFile=%s", qPrintable(jurisdictionFile));
|
|
||||||
qDebug("about to readFromFile().... jurisdictionFile=%s", qPrintable(jurisdictionFile));
|
|
||||||
_jurisdiction = new JurisdictionMap(qPrintable(jurisdictionFile));
|
|
||||||
qDebug("after readFromFile().... jurisdictionFile=%s", qPrintable(jurisdictionFile));
|
|
||||||
} else {
|
|
||||||
QString jurisdictionRoot;
|
|
||||||
bool hasRoot = readOptionString(QString("jurisdictionRoot"), settingsSectionObject, jurisdictionRoot);
|
|
||||||
QString jurisdictionEndNodes;
|
|
||||||
bool hasEndNodes = readOptionString(QString("jurisdictionEndNodes"), settingsSectionObject, jurisdictionEndNodes);
|
|
||||||
|
|
||||||
if (hasRoot || hasEndNodes) {
|
|
||||||
_jurisdiction = new JurisdictionMap(qPrintable(jurisdictionRoot), qPrintable(jurisdictionEndNodes));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
readOptionBool(QString("verboseDebug"), settingsSectionObject, _verboseDebug);
|
readOptionBool(QString("verboseDebug"), settingsSectionObject, _verboseDebug);
|
||||||
qDebug("verboseDebug=%s", debug::valueOf(_verboseDebug));
|
qDebug("verboseDebug=%s", debug::valueOf(_verboseDebug));
|
||||||
|
|
||||||
|
@ -1241,7 +1209,6 @@ void OctreeServer::domainSettingsRequestComplete() {
|
||||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||||
packetReceiver.registerListener(getMyQueryMessageType(), this, "handleOctreeQueryPacket");
|
packetReceiver.registerListener(getMyQueryMessageType(), this, "handleOctreeQueryPacket");
|
||||||
packetReceiver.registerListener(PacketType::OctreeDataNack, this, "handleOctreeDataNackPacket");
|
packetReceiver.registerListener(PacketType::OctreeDataNack, this, "handleOctreeDataNackPacket");
|
||||||
packetReceiver.registerListener(PacketType::JurisdictionRequest, this, "handleJurisdictionRequestPacket");
|
|
||||||
packetReceiver.registerListener(PacketType::OctreeFileReplacement, this, "handleOctreeFileReplacement");
|
packetReceiver.registerListener(PacketType::OctreeFileReplacement, this, "handleOctreeFileReplacement");
|
||||||
packetReceiver.registerListener(PacketType::OctreeFileReplacementFromUrl, this, "handleOctreeFileReplacementFromURL");
|
packetReceiver.registerListener(PacketType::OctreeFileReplacementFromUrl, this, "handleOctreeFileReplacementFromURL");
|
||||||
|
|
||||||
|
@ -1365,13 +1332,6 @@ void OctreeServer::domainSettingsRequestComplete() {
|
||||||
_persistThread->initialize(true);
|
_persistThread->initialize(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up our jurisdiction broadcaster...
|
|
||||||
if (_jurisdiction) {
|
|
||||||
_jurisdiction->setNodeType(getMyNodeType());
|
|
||||||
}
|
|
||||||
_jurisdictionSender = new JurisdictionSender(_jurisdiction, getMyNodeType());
|
|
||||||
_jurisdictionSender->initialize(true);
|
|
||||||
|
|
||||||
// set up our OctreeServerPacketProcessor
|
// set up our OctreeServerPacketProcessor
|
||||||
_octreeInboundPacketProcessor = new OctreeInboundPacketProcessor(this);
|
_octreeInboundPacketProcessor = new OctreeInboundPacketProcessor(this);
|
||||||
_octreeInboundPacketProcessor->initialize(true);
|
_octreeInboundPacketProcessor->initialize(true);
|
||||||
|
@ -1441,10 +1401,6 @@ void OctreeServer::aboutToFinish() {
|
||||||
_octreeInboundPacketProcessor->terminating();
|
_octreeInboundPacketProcessor->terminating();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_jurisdictionSender) {
|
|
||||||
_jurisdictionSender->terminating();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shut down all the send threads
|
// Shut down all the send threads
|
||||||
for (auto& it : _sendThreads) {
|
for (auto& it : _sendThreads) {
|
||||||
auto& sendThread = *it.second;
|
auto& sendThread = *it.second;
|
||||||
|
|
|
@ -44,7 +44,6 @@ public:
|
||||||
bool wantsVerboseDebug() const { return _verboseDebug; }
|
bool wantsVerboseDebug() const { return _verboseDebug; }
|
||||||
|
|
||||||
OctreePointer getOctree() { return _tree; }
|
OctreePointer getOctree() { return _tree; }
|
||||||
JurisdictionMap* getJurisdiction() { return _jurisdiction; }
|
|
||||||
|
|
||||||
int getPacketsPerClientPerInterval() const { return std::min(_packetsPerClientPerInterval,
|
int getPacketsPerClientPerInterval() const { return std::min(_packetsPerClientPerInterval,
|
||||||
std::max(1, getPacketsTotalPerInterval() / std::max(1, getCurrentClientCount()))); }
|
std::max(1, getPacketsTotalPerInterval() / std::max(1, getCurrentClientCount()))); }
|
||||||
|
@ -138,7 +137,6 @@ private slots:
|
||||||
void domainSettingsRequestComplete();
|
void domainSettingsRequestComplete();
|
||||||
void handleOctreeQueryPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
void handleOctreeQueryPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
void handleOctreeDataNackPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
void handleOctreeDataNackPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
void handleJurisdictionRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
|
||||||
void handleOctreeFileReplacement(QSharedPointer<ReceivedMessage> message);
|
void handleOctreeFileReplacement(QSharedPointer<ReceivedMessage> message);
|
||||||
void handleOctreeFileReplacementFromURL(QSharedPointer<ReceivedMessage> message);
|
void handleOctreeFileReplacementFromURL(QSharedPointer<ReceivedMessage> message);
|
||||||
void removeSendThread();
|
void removeSendThread();
|
||||||
|
@ -190,8 +188,6 @@ protected:
|
||||||
bool _debugReceiving;
|
bool _debugReceiving;
|
||||||
bool _debugTimestampNow;
|
bool _debugTimestampNow;
|
||||||
bool _verboseDebug;
|
bool _verboseDebug;
|
||||||
JurisdictionMap* _jurisdiction;
|
|
||||||
JurisdictionSender* _jurisdictionSender;
|
|
||||||
OctreeInboundPacketProcessor* _octreeInboundPacketProcessor;
|
OctreeInboundPacketProcessor* _octreeInboundPacketProcessor;
|
||||||
OctreePersistThread* _persistThread;
|
OctreePersistThread* _persistThread;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <NodeList.h> // for MAX_PACKET_SIZE
|
#include <NodeList.h> // for MAX_PACKET_SIZE
|
||||||
#include <JurisdictionSender.h>
|
|
||||||
|
|
||||||
const int MAX_FILENAME_LENGTH = 1024;
|
const int MAX_FILENAME_LENGTH = 1024;
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,6 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig
|
||||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||||
packetReceiver.registerListenerForTypes({ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase },
|
packetReceiver.registerListenerForTypes({ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase },
|
||||||
this, "handleOctreePacket");
|
this, "handleOctreePacket");
|
||||||
packetReceiver.registerListener(PacketType::Jurisdiction, this, "handleJurisdictionPacket");
|
|
||||||
packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat");
|
packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat");
|
||||||
|
|
||||||
auto avatarHashMap = DependencyManager::set<AvatarHashMap>();
|
auto avatarHashMap = DependencyManager::set<AvatarHashMap>();
|
||||||
|
@ -283,11 +282,8 @@ void EntityScriptServer::run() {
|
||||||
// Setup Script Engine
|
// Setup Script Engine
|
||||||
resetEntitiesScriptEngine();
|
resetEntitiesScriptEngine();
|
||||||
|
|
||||||
// we need to make sure that init has been called for our EntityScriptingInterface
|
|
||||||
// so that it actually has a jurisdiction listener when we ask it for it next
|
|
||||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||||
entityScriptingInterface->init();
|
entityScriptingInterface->init();
|
||||||
_entityViewer.setJurisdictionListener(entityScriptingInterface->getJurisdictionListener());
|
|
||||||
|
|
||||||
_entityViewer.init();
|
_entityViewer.init();
|
||||||
|
|
||||||
|
@ -566,17 +562,6 @@ void EntityScriptServer::handleOctreePacket(QSharedPointer<ReceivedMessage> mess
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityScriptServer::handleJurisdictionPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
|
||||||
NodeType_t nodeType;
|
|
||||||
message->peekPrimitive(&nodeType);
|
|
||||||
|
|
||||||
// PacketType_JURISDICTION, first byte is the node type...
|
|
||||||
if (nodeType == NodeType::EntityServer) {
|
|
||||||
DependencyManager::get<EntityScriptingInterface>()->getJurisdictionListener()->
|
|
||||||
queueReceivedPacket(message, senderNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EntityScriptServer::aboutToFinish() {
|
void EntityScriptServer::aboutToFinish() {
|
||||||
shutdownScriptEngine();
|
shutdownScriptEngine();
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,6 @@ public slots:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleOctreePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
void handleOctreePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
void handleJurisdictionPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
|
||||||
void handleSelectedAudioFormat(QSharedPointer<ReceivedMessage> message);
|
void handleSelectedAudioFormat(QSharedPointer<ReceivedMessage> message);
|
||||||
|
|
||||||
void handleReloadEntityServerScriptPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
void handleReloadEntityServerScriptPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
|
|
|
@ -945,7 +945,7 @@ void DomainServer::createStaticAssignmentsForType(Assignment::Type type, const Q
|
||||||
|
|
||||||
void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet<Assignment::Type>& excludedTypes) {
|
void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet<Assignment::Type>& excludedTypes) {
|
||||||
// enumerate over all assignment types and see if we've already excluded it
|
// enumerate over all assignment types and see if we've already excluded it
|
||||||
for (Assignment::Type defaultedType = Assignment::AudioMixerType;
|
for (Assignment::Type defaultedType = Assignment::FirstType;
|
||||||
defaultedType != Assignment::AllTypes;
|
defaultedType != Assignment::AllTypes;
|
||||||
defaultedType = static_cast<Assignment::Type>(static_cast<int>(defaultedType) + 1)) {
|
defaultedType = static_cast<Assignment::Type>(static_cast<int>(defaultedType) + 1)) {
|
||||||
if (!excludedTypes.contains(defaultedType) && defaultedType != Assignment::AgentType) {
|
if (!excludedTypes.contains(defaultedType) && defaultedType != Assignment::AgentType) {
|
||||||
|
|
|
@ -12,8 +12,10 @@ function(JOIN VALUES GLUE OUTPUT)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
|
||||||
set(INTERFACE_QML_QRC ${CMAKE_CURRENT_BINARY_DIR}/qml.qrc)
|
if (NOT DEV_BUILD)
|
||||||
generate_qrc(OUTPUT ${INTERFACE_QML_QRC} PATH ${CMAKE_CURRENT_SOURCE_DIR}/resources GLOBS *.qml *.qss *.js *.html *.ttf *.gif *.svg *.png *.jpg)
|
set(INTERFACE_QML_QRC ${CMAKE_CURRENT_BINARY_DIR}/qml.qrc)
|
||||||
|
generate_qrc(OUTPUT ${INTERFACE_QML_QRC} PATH ${CMAKE_CURRENT_SOURCE_DIR}/resources GLOBS *.qml *.qss *.js *.html *.ttf *.gif *.svg *.png *.jpg)
|
||||||
|
endif()
|
||||||
|
|
||||||
# set a default root dir for each of our optional externals if it was not passed
|
# set a default root dir for each of our optional externals if it was not passed
|
||||||
set(OPTIONAL_EXTERNALS "LeapMotion")
|
set(OPTIONAL_EXTERNALS "LeapMotion")
|
||||||
|
@ -72,7 +74,9 @@ qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}")
|
||||||
# add them to the interface source files
|
# add them to the interface source files
|
||||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}")
|
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}")
|
||||||
|
|
||||||
|
if (NOT DEV_BUILD)
|
||||||
list(APPEND INTERFACE_SRCS ${INTERFACE_QML_QRC})
|
list(APPEND INTERFACE_SRCS ${INTERFACE_QML_QRC})
|
||||||
|
endif()
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
install(
|
install(
|
||||||
|
|
|
@ -56,29 +56,28 @@
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.LeftFoot", "to" : "Standard.LeftFoot",
|
"from": "Vive.LeftFoot", "to" : "Standard.LeftFoot",
|
||||||
"filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}]
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.RightFoot", "to" : "Standard.RightFoot",
|
"from": "Vive.RightFoot", "to" : "Standard.RightFoot",
|
||||||
"filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}]
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.Hips", "to" : "Standard.Hips",
|
"from": "Vive.Hips", "to" : "Standard.Hips",
|
||||||
"filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}]
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.Spine2", "to" : "Standard.Spine2",
|
"from": "Vive.Spine2", "to" : "Standard.Spine2",
|
||||||
"filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}]
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
|
||||||
},
|
},
|
||||||
|
|
||||||
{ "from": "Vive.Head", "to" : "Standard.Head"},
|
{ "from": "Vive.Head", "to" : "Standard.Head"},
|
||||||
|
|
||||||
{ "from": "Vive.RightArm", "to" : "Standard.RightArm" },
|
{ "from": "Vive.RightArm", "to" : "Standard.RightArm" },
|
||||||
{ "from": "Vive.LeftArm", "to" : "Standard.LeftArm" },
|
{ "from": "Vive.LeftArm", "to" : "Standard.LeftArm" },
|
||||||
|
|
||||||
{ "from": "Vive.TrackedObject00", "to" : "Standard.TrackedObject00" },
|
{ "from": "Vive.TrackedObject00", "to" : "Standard.TrackedObject00" },
|
||||||
{ "from": "Vive.TrackedObject01", "to" : "Standard.TrackedObject01" },
|
{ "from": "Vive.TrackedObject01", "to" : "Standard.TrackedObject01" },
|
||||||
{ "from": "Vive.TrackedObject02", "to" : "Standard.TrackedObject02" },
|
{ "from": "Vive.TrackedObject02", "to" : "Standard.TrackedObject02" },
|
||||||
|
|
|
@ -110,7 +110,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
function pullFreshValues() {
|
function pullFreshValues() {
|
||||||
if (Audio.getRecording()) {
|
if (AudioScriptingInterface.getRecording()) {
|
||||||
updateRecordingLabel();
|
updateRecordingLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,14 +129,14 @@ Item {
|
||||||
_wavFilePath = _wavFilePath.replace(/[\-:]|\.\d*Z$/g, "").replace("T", "-") + ".wav";
|
_wavFilePath = _wavFilePath.replace(/[\-:]|\.\d*Z$/g, "").replace("T", "-") + ".wav";
|
||||||
// Using controller recording default directory
|
// Using controller recording default directory
|
||||||
_wavFilePath = Recording.getDefaultRecordingSaveDirectory() + _wavFilePath;
|
_wavFilePath = Recording.getDefaultRecordingSaveDirectory() + _wavFilePath;
|
||||||
if (!Audio.startRecording(_wavFilePath)) {
|
if (!AudioScriptingInterface.startRecording(_wavFilePath)) {
|
||||||
Messages.sendMessage("Hifi-Notifications", JSON.stringify({message:"Error creating: "+_wavFilePath}));
|
Messages.sendMessage("Hifi-Notifications", JSON.stringify({message:"Error creating: "+_wavFilePath}));
|
||||||
updateRecordingUI(false);
|
updateRecordingUI(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopRecording() {
|
function stopRecording() {
|
||||||
Audio.stopRecording();
|
AudioScriptingInterface.stopRecording();
|
||||||
setRecordingLabelOpacity(0.0);
|
setRecordingLabelOpacity(0.0);
|
||||||
Messages.sendMessage("Hifi-Notifications", JSON.stringify({message:"Saved: "+_wavFilePath}));
|
Messages.sendMessage("Hifi-Notifications", JSON.stringify({message:"Saved: "+_wavFilePath}));
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleRecording() {
|
function toggleRecording() {
|
||||||
if (Audio.getRecording()) {
|
if (AudioScriptingInterface.getRecording()) {
|
||||||
updateRecordingUI(false);
|
updateRecordingUI(false);
|
||||||
stopRecording();
|
stopRecording();
|
||||||
} else {
|
} else {
|
||||||
|
|
18
interface/resources/qml/OverlayWindowTest.qml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 100
|
||||||
|
height: 100
|
||||||
|
color: "white"
|
||||||
|
Rectangle {
|
||||||
|
width: 10
|
||||||
|
height: 10
|
||||||
|
color: "red"
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: OverlayWindowTestString
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,6 @@ Windows.Window {
|
||||||
// Don't destroy on close... otherwise the JS/C++ will have a dangling pointer
|
// Don't destroy on close... otherwise the JS/C++ will have a dangling pointer
|
||||||
destroyOnCloseButton: false
|
destroyOnCloseButton: false
|
||||||
property var source;
|
property var source;
|
||||||
property var component;
|
|
||||||
property var dynamicContent;
|
property var dynamicContent;
|
||||||
|
|
||||||
// Keyboard control properties in case needed by QML content.
|
// Keyboard control properties in case needed by QML content.
|
||||||
|
@ -35,28 +34,9 @@ Windows.Window {
|
||||||
dynamicContent.destroy();
|
dynamicContent.destroy();
|
||||||
dynamicContent = null;
|
dynamicContent = null;
|
||||||
}
|
}
|
||||||
component = Qt.createComponent(source);
|
QmlSurface.load(source, contentHolder, function(newObject) {
|
||||||
console.log("Created component " + component + " from source " + source);
|
dynamicContent = newObject;
|
||||||
}
|
});
|
||||||
|
|
||||||
onComponentChanged: {
|
|
||||||
console.log("Component changed to " + component)
|
|
||||||
populate();
|
|
||||||
}
|
|
||||||
|
|
||||||
function populate() {
|
|
||||||
console.log("Populate called: dynamicContent " + dynamicContent + " component " + component);
|
|
||||||
if (!dynamicContent && component) {
|
|
||||||
if (component.status == Component.Error) {
|
|
||||||
console.log("Error loading component:", component.errorString());
|
|
||||||
} else if (component.status == Component.Ready) {
|
|
||||||
console.log("Building dynamic content");
|
|
||||||
dynamicContent = component.createObject(contentHolder);
|
|
||||||
} else {
|
|
||||||
console.log("Component not yet ready, connecting to status change");
|
|
||||||
component.statusChanged.connect(populate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle message traffic from the script that launched us to the loaded QML
|
// Handle message traffic from the script that launched us to the loaded QML
|
||||||
|
|
|
@ -29,12 +29,12 @@ Original.Button {
|
||||||
|
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
style: ButtonStyle {
|
style: ButtonStyle {
|
||||||
|
|
|
@ -31,12 +31,12 @@ Original.CheckBox {
|
||||||
activeFocusOnPress: true
|
activeFocusOnPress: true
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: doesnt works for QQC1. check with QQC2
|
// TODO: doesnt works for QQC1. check with QQC2
|
||||||
// onHovered: {
|
// onHovered: {
|
||||||
// tabletInterface.playSound(TabletEnums.ButtonHover);
|
// Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
style: CheckBoxStyle {
|
style: CheckBoxStyle {
|
||||||
|
|
|
@ -36,12 +36,12 @@ CheckBox {
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,12 +27,12 @@ Original.Button {
|
||||||
|
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
style: ButtonStyle {
|
style: ButtonStyle {
|
||||||
|
|
|
@ -41,13 +41,13 @@ Item {
|
||||||
|
|
||||||
onContainsMouseChanged: {
|
onContainsMouseChanged: {
|
||||||
if (containsMouse) {
|
if (containsMouse) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
mouse.accepted = true;
|
mouse.accepted = true;
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
|
|
||||||
webEntity.synthesizeKeyPress(glyph);
|
webEntity.synthesizeKeyPress(glyph);
|
||||||
webEntity.synthesizeKeyPress(glyph, mirrorText);
|
webEntity.synthesizeKeyPress(glyph, mirrorText);
|
||||||
|
|
|
@ -30,12 +30,12 @@ Original.RadioButton {
|
||||||
readonly property int checkRadius: 2
|
readonly property int checkRadius: 2
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: doesnt works for QQC1. check with QQC2
|
// TODO: doesnt works for QQC1. check with QQC2
|
||||||
// onHovered: {
|
// onHovered: {
|
||||||
// tabletInterface.playSound(TabletEnums.ButtonHover);
|
// Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
style: RadioButtonStyle {
|
style: RadioButtonStyle {
|
||||||
|
|
|
@ -49,7 +49,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WebEngineView.LoadFailedStatus === loadRequest.status) {
|
if (WebEngineView.LoadFailedStatus === loadRequest.status) {
|
||||||
console.log(" Tablet WebEngineView failed to load url: " + loadRequest.url.toString());
|
console.log("Tablet WebEngineView failed to load url: " + loadRequest.url.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WebEngineView.LoadSucceededStatus === loadRequest.status) {
|
if (WebEngineView.LoadSucceededStatus === loadRequest.status) {
|
||||||
|
|
|
@ -25,13 +25,13 @@ Preference {
|
||||||
id: button
|
id: button
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
preference.trigger();
|
preference.trigger();
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
width: 180
|
width: 180
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
|
|
|
@ -41,12 +41,12 @@ Preference {
|
||||||
id: checkBox
|
id: checkBox
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors {
|
anchors {
|
||||||
|
|
|
@ -246,12 +246,12 @@ Item {
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
acceptedButtons: Qt.LeftButton;
|
acceptedButtons: Qt.LeftButton;
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
goFunction("hifi://" + hifiUrl);
|
goFunction("hifi://" + hifiUrl);
|
||||||
}
|
}
|
||||||
hoverEnabled: true;
|
hoverEnabled: true;
|
||||||
onEntered: {
|
onEntered: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
hoverThunk();
|
hoverThunk();
|
||||||
}
|
}
|
||||||
onExited: unhoverThunk();
|
onExited: unhoverThunk();
|
||||||
|
@ -269,7 +269,7 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function go() {
|
function go() {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
goFunction(drillDownToPlace ? ("/places/" + placeName) : ("/user_stories/" + storyId));
|
goFunction(drillDownToPlace ? ("/places/" + placeName) : ("/user_stories/" + storyId));
|
||||||
}
|
}
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|
|
@ -45,11 +45,13 @@ OriginalDesktop.Desktop {
|
||||||
Toolbar {
|
Toolbar {
|
||||||
id: sysToolbar;
|
id: sysToolbar;
|
||||||
objectName: "com.highfidelity.interface.toolbar.system";
|
objectName: "com.highfidelity.interface.toolbar.system";
|
||||||
|
property var tablet: Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||||
anchors.horizontalCenter: settings.constrainToolbarToCenterX ? desktop.horizontalCenter : undefined;
|
anchors.horizontalCenter: settings.constrainToolbarToCenterX ? desktop.horizontalCenter : undefined;
|
||||||
// Literal 50 is overwritten by settings from previous session, and sysToolbar.x comes from settings when not constrained.
|
// Literal 50 is overwritten by settings from previous session, and sysToolbar.x comes from settings when not constrained.
|
||||||
x: sysToolbar.x
|
x: sysToolbar.x
|
||||||
y: 50
|
y: 50
|
||||||
shown: true
|
buttonModel: tablet.buttons;
|
||||||
|
shown: tablet.toolbarMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings {
|
Settings {
|
||||||
|
|
|
@ -597,18 +597,11 @@ Item {
|
||||||
// Function body by Howard Stearns 2017-01-08
|
// Function body by Howard Stearns 2017-01-08
|
||||||
function goToUserInDomain(avatarUuid) {
|
function goToUserInDomain(avatarUuid) {
|
||||||
var avatar = AvatarList.getAvatar(avatarUuid);
|
var avatar = AvatarList.getAvatar(avatarUuid);
|
||||||
if (!avatar) {
|
if (!avatar || !avatar.position || !avatar.orientation) {
|
||||||
console.log("This avatar is no longer present. goToUserInDomain() failed.");
|
console.log("This avatar is no longer present. goToUserInDomain() failed.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// FIXME: We would like the avatar to recompute the avatar's "maybe fly" test at the new position, so that if high enough up,
|
// This is the last step of what AddressManager.goToUser does, but we don't need to resolve the username.
|
||||||
// the avatar goes into fly mode rather than falling. However, that is not exposed to Javascript right now.
|
MyAvatar.goToLocation(avatar.position, true, Quat.cancelOutRollAndPitch(avatar.orientation), true);
|
||||||
// FIXME: it would be nice if this used the same teleport steps and smoothing as in the teleport.js script.
|
|
||||||
// Note, however, that this script allows teleporting to a person in the air, while teleport.js is going to a grounded target.
|
|
||||||
// Position avatar 2 metres from the target in the direction that target avatar was facing.
|
|
||||||
MyAvatar.position = Vec3.sum(avatar.position, Vec3.multiplyQbyV(avatar.orientation, {x: 0, y: 0, z: -2}));
|
|
||||||
|
|
||||||
// Rotate avatar on Y axis to face target avatar and cancel out any inherited roll and pitch.
|
|
||||||
MyAvatar.orientation = Quat.cancelOutRollAndPitch(Quat.multiply(avatar.orientation, {y: 1}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ Rectangle {
|
||||||
HifiConstants { id: hifi; }
|
HifiConstants { id: hifi; }
|
||||||
|
|
||||||
property var eventBridge;
|
property var eventBridge;
|
||||||
property string title: "Audio Settings - " + Audio.context;
|
property string title: "Audio Settings - " + AudioScriptingInterface.context;
|
||||||
signal sendToScript(var message);
|
signal sendToScript(var message);
|
||||||
|
|
||||||
color: hifi.colors.baseGray;
|
color: hifi.colors.baseGray;
|
||||||
|
@ -37,7 +37,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
property bool isVR: Audio.context === "VR"
|
property bool isVR: AudioScriptingInterface.context === "VR"
|
||||||
property real rightMostInputLevelPos: 0
|
property real rightMostInputLevelPos: 0
|
||||||
//placeholder for control sizes and paddings
|
//placeholder for control sizes and paddings
|
||||||
//recalculates dynamically in case of UI size is changed
|
//recalculates dynamically in case of UI size is changed
|
||||||
|
@ -72,17 +72,17 @@ Rectangle {
|
||||||
property bool showPeaks: true;
|
property bool showPeaks: true;
|
||||||
|
|
||||||
function enablePeakValues() {
|
function enablePeakValues() {
|
||||||
Audio.devices.input.peakValuesEnabled = true;
|
AudioScriptingInterface.devices.input.peakValuesEnabled = true;
|
||||||
Audio.devices.input.peakValuesEnabledChanged.connect(function(enabled) {
|
AudioScriptingInterface.devices.input.peakValuesEnabledChanged.connect(function(enabled) {
|
||||||
if (!enabled && root.showPeaks) {
|
if (!enabled && root.showPeaks) {
|
||||||
Audio.devices.input.peakValuesEnabled = true;
|
AudioScriptingInterface.devices.input.peakValuesEnabled = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function disablePeakValues() {
|
function disablePeakValues() {
|
||||||
root.showPeaks = false;
|
root.showPeaks = false;
|
||||||
Audio.devices.input.peakValuesEnabled = false;
|
AudioScriptingInterface.devices.input.peakValuesEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: enablePeakValues();
|
Component.onCompleted: enablePeakValues();
|
||||||
|
@ -117,10 +117,10 @@ Rectangle {
|
||||||
text: qsTr("Mute microphone");
|
text: qsTr("Mute microphone");
|
||||||
spacing: margins.sizeCheckBox - boxSize
|
spacing: margins.sizeCheckBox - boxSize
|
||||||
isRedCheck: true;
|
isRedCheck: true;
|
||||||
checked: Audio.muted;
|
checked: AudioScriptingInterface.muted;
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Audio.muted = checked;
|
AudioScriptingInterface.muted = checked;
|
||||||
checked = Qt.binding(function() { return Audio.muted; }); // restore binding
|
checked = Qt.binding(function() { return AudioScriptingInterface.muted; }); // restore binding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,10 +130,10 @@ Rectangle {
|
||||||
AudioControls.CheckBox {
|
AudioControls.CheckBox {
|
||||||
spacing: muteMic.spacing
|
spacing: muteMic.spacing
|
||||||
text: qsTr("Enable noise reduction");
|
text: qsTr("Enable noise reduction");
|
||||||
checked: Audio.noiseReduction;
|
checked: AudioScriptingInterface.noiseReduction;
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Audio.noiseReduction = checked;
|
AudioScriptingInterface.noiseReduction = checked;
|
||||||
checked = Qt.binding(function() { return Audio.noiseReduction; }); // restore binding
|
checked = Qt.binding(function() { return AudioScriptingInterface.noiseReduction; }); // restore binding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AudioControls.CheckBox {
|
AudioControls.CheckBox {
|
||||||
|
@ -184,7 +184,7 @@ Rectangle {
|
||||||
spacing: 4;
|
spacing: 4;
|
||||||
snapMode: ListView.SnapToItem;
|
snapMode: ListView.SnapToItem;
|
||||||
clip: true;
|
clip: true;
|
||||||
model: Audio.devices.input;
|
model: AudioScriptingInterface.devices.input;
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
width: rightMostInputLevelPos
|
width: rightMostInputLevelPos
|
||||||
height: margins.sizeCheckBox > checkBoxInput.implicitHeight ?
|
height: margins.sizeCheckBox > checkBoxInput.implicitHeight ?
|
||||||
|
@ -204,7 +204,7 @@ Rectangle {
|
||||||
text: devicename
|
text: devicename
|
||||||
onPressed: {
|
onPressed: {
|
||||||
if (!checked) {
|
if (!checked) {
|
||||||
Audio.setInputDevice(info, bar.currentIndex === 1);
|
AudioScriptingInterface.setInputDevice(info, bar.currentIndex === 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ Rectangle {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
visible: ((bar.currentIndex === 1 && isVR) ||
|
visible: ((bar.currentIndex === 1 && isVR) ||
|
||||||
(bar.currentIndex === 0 && !isVR)) &&
|
(bar.currentIndex === 0 && !isVR)) &&
|
||||||
Audio.devices.input.peakValuesAvailable;
|
AudioScriptingInterface.devices.input.peakValuesAvailable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,7 +256,7 @@ Rectangle {
|
||||||
spacing: 4;
|
spacing: 4;
|
||||||
snapMode: ListView.SnapToItem;
|
snapMode: ListView.SnapToItem;
|
||||||
clip: true;
|
clip: true;
|
||||||
model: Audio.devices.output;
|
model: AudioScriptingInterface.devices.output;
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
width: rightMostInputLevelPos
|
width: rightMostInputLevelPos
|
||||||
height: margins.sizeCheckBox > checkBoxOutput.implicitHeight ?
|
height: margins.sizeCheckBox > checkBoxOutput.implicitHeight ?
|
||||||
|
@ -273,7 +273,7 @@ Rectangle {
|
||||||
text: devicename
|
text: devicename
|
||||||
onPressed: {
|
onPressed: {
|
||||||
if (!checked) {
|
if (!checked) {
|
||||||
Audio.setOutputDevice(info, bar.currentIndex === 1);
|
AudioScriptingInterface.setOutputDevice(info, bar.currentIndex === 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ Rectangle {
|
||||||
verticalCenter: parent.verticalCenter;
|
verticalCenter: parent.verticalCenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
visible: Audio.muted;
|
visible: AudioScriptingInterface.muted;
|
||||||
color: colors.muted;
|
color: colors.muted;
|
||||||
|
|
||||||
text: "MUTED";
|
text: "MUTED";
|
||||||
|
|
|
@ -17,7 +17,7 @@ import QtGraphicalEffects 1.0
|
||||||
import TabletScriptingInterface 1.0
|
import TabletScriptingInterface 1.0
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
readonly property var level: Audio.inputLevel;
|
readonly property var level: AudioScriptingInterface.inputLevel;
|
||||||
|
|
||||||
property bool standalone: false;
|
property bool standalone: false;
|
||||||
property var dragTarget: null;
|
property var dragTarget: null;
|
||||||
|
@ -60,13 +60,13 @@ Rectangle {
|
||||||
hoverEnabled: true;
|
hoverEnabled: true;
|
||||||
scrollGestureEnabled: false;
|
scrollGestureEnabled: false;
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Audio.muted = !Audio.muted;
|
AudioScriptingInterface.muted = !AudioScriptingInterface.muted;
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
drag.target: dragTarget;
|
drag.target: dragTarget;
|
||||||
onContainsMouseChanged: {
|
onContainsMouseChanged: {
|
||||||
if (containsMouse) {
|
if (containsMouse) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ Rectangle {
|
||||||
readonly property string red: colors.muted;
|
readonly property string red: colors.muted;
|
||||||
readonly property string fill: "#55000000";
|
readonly property string fill: "#55000000";
|
||||||
readonly property string border: standalone ? "#80FFFFFF" : "#55FFFFFF";
|
readonly property string border: standalone ? "#80FFFFFF" : "#55FFFFFF";
|
||||||
readonly property string icon: Audio.muted ? muted : unmuted;
|
readonly property string icon: AudioScriptingInterface.muted ? muted : unmuted;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
@ -103,7 +103,7 @@ Rectangle {
|
||||||
readonly property string mutedIcon: "../../../icons/tablet-icons/mic-mute-i.svg";
|
readonly property string mutedIcon: "../../../icons/tablet-icons/mic-mute-i.svg";
|
||||||
|
|
||||||
id: image;
|
id: image;
|
||||||
source: Audio.muted ? mutedIcon : unmutedIcon;
|
source: AudioScriptingInterface.muted ? mutedIcon : unmutedIcon;
|
||||||
|
|
||||||
width: 30;
|
width: 30;
|
||||||
height: 30;
|
height: 30;
|
||||||
|
@ -126,9 +126,9 @@ Rectangle {
|
||||||
Item {
|
Item {
|
||||||
id: status;
|
id: status;
|
||||||
|
|
||||||
readonly property string color: Audio.muted ? colors.muted : colors.unmuted;
|
readonly property string color: AudioScriptingInterface.muted ? colors.muted : colors.unmuted;
|
||||||
|
|
||||||
visible: Audio.muted;
|
visible: AudioScriptingInterface.muted;
|
||||||
|
|
||||||
anchors {
|
anchors {
|
||||||
left: parent.left;
|
left: parent.left;
|
||||||
|
@ -147,7 +147,7 @@ Rectangle {
|
||||||
|
|
||||||
color: parent.color;
|
color: parent.color;
|
||||||
|
|
||||||
text: Audio.muted ? "MUTED" : "MUTE";
|
text: AudioScriptingInterface.muted ? "MUTED" : "MUTE";
|
||||||
font.pointSize: 12;
|
font.pointSize: 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,9 @@ RowLayout {
|
||||||
}
|
}
|
||||||
function playSound() {
|
function playSound() {
|
||||||
// FIXME: MyAvatar is not properly exposed to QML; MyAvatar.qmlPosition is a stopgap
|
// FIXME: MyAvatar is not properly exposed to QML; MyAvatar.qmlPosition is a stopgap
|
||||||
// FIXME: Audio.playSystemSound should not require position
|
// FIXME: AudioScriptingInterface.playSystemSound should not require position
|
||||||
if (sample === null && !isPlaying) {
|
if (sample === null && !isPlaying) {
|
||||||
sample = Audio.playSystemSound(sound, MyAvatar.qmlPosition);
|
sample = AudioScriptingInterface.playSystemSound(sound, MyAvatar.qmlPosition);
|
||||||
isPlaying = true;
|
isPlaying = true;
|
||||||
sample.finished.connect(reset);
|
sample.finished.connect(reset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ Rectangle {
|
||||||
property string itemName;
|
property string itemName;
|
||||||
property string itemId;
|
property string itemId;
|
||||||
property string itemHref;
|
property string itemHref;
|
||||||
|
property string itemAuthor;
|
||||||
property double balanceAfterPurchase;
|
property double balanceAfterPurchase;
|
||||||
property bool alreadyOwned: false;
|
property bool alreadyOwned: false;
|
||||||
property int itemPrice: -1;
|
property int itemPrice: -1;
|
||||||
|
@ -41,10 +42,11 @@ Rectangle {
|
||||||
property bool debugCheckoutSuccess: false;
|
property bool debugCheckoutSuccess: false;
|
||||||
property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified();
|
property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified();
|
||||||
property bool isWearable;
|
property bool isWearable;
|
||||||
|
property string referrer;
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.white;
|
color: hifi.colors.white;
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onWalletStatusResult: {
|
onWalletStatusResult: {
|
||||||
if (walletStatus === 0) {
|
if (walletStatus === 0) {
|
||||||
|
@ -59,6 +61,7 @@ Rectangle {
|
||||||
} else if (walletStatus === 2) {
|
} else if (walletStatus === 2) {
|
||||||
if (root.activeView !== "passphraseModal") {
|
if (root.activeView !== "passphraseModal") {
|
||||||
root.activeView = "passphraseModal";
|
root.activeView = "passphraseModal";
|
||||||
|
UserActivityLogger.commercePassphraseEntry("marketplace checkout");
|
||||||
}
|
}
|
||||||
} else if (walletStatus === 3) {
|
} else if (walletStatus === 3) {
|
||||||
authSuccessStep();
|
authSuccessStep();
|
||||||
|
@ -71,7 +74,7 @@ Rectangle {
|
||||||
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
||||||
root.activeView = "needsLogIn";
|
root.activeView = "needsLogIn";
|
||||||
} else {
|
} else {
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,12 +82,12 @@ Rectangle {
|
||||||
if (result.status !== 'success') {
|
if (result.status !== 'success') {
|
||||||
failureErrorText.text = result.message;
|
failureErrorText.text = result.message;
|
||||||
root.activeView = "checkoutFailure";
|
root.activeView = "checkoutFailure";
|
||||||
UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemPrice, !root.alreadyOwned, result.message);
|
UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned, result.message);
|
||||||
} else {
|
} else {
|
||||||
root.itemHref = result.data.download_url;
|
root.itemHref = result.data.download_url;
|
||||||
root.isWearable = result.data.categories.indexOf("Wearables") > -1;
|
root.isWearable = result.data.categories.indexOf("Wearables") > -1;
|
||||||
root.activeView = "checkoutSuccess";
|
root.activeView = "checkoutSuccess";
|
||||||
UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemPrice, !root.alreadyOwned);
|
UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +117,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemIdChanged: {
|
onItemIdChanged: {
|
||||||
commerce.inventory();
|
Commerce.inventory();
|
||||||
itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg";
|
itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,14 +126,14 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemPriceChanged: {
|
onItemPriceChanged: {
|
||||||
commerce.balance();
|
Commerce.balance();
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: notSetUpTimer;
|
id: notSetUpTimer;
|
||||||
interval: 200;
|
interval: 200;
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
sendToScript({method: 'checkout_walletNotSetUp', itemId: itemId});
|
sendToScript({method: 'checkout_walletNotSetUp', itemId: itemId, referrer: referrer});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +205,7 @@ Rectangle {
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
purchasesReceived = false;
|
purchasesReceived = false;
|
||||||
balanceReceived = false;
|
balanceReceived = false;
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +226,7 @@ Rectangle {
|
||||||
Connections {
|
Connections {
|
||||||
target: GlobalServices
|
target: GlobalServices
|
||||||
onMyUsernameChanged: {
|
onMyUsernameChanged: {
|
||||||
commerce.getLoginStatus();
|
Commerce.getLoginStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +411,8 @@ Rectangle {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: buyTextContainer;
|
id: buyTextContainer;
|
||||||
visible: buyText.text !== "";
|
visible: buyText.text !== "";
|
||||||
anchors.top: parent.top;
|
anchors.top: cancelPurchaseButton.bottom;
|
||||||
|
anchors.topMargin: 16;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
height: buyText.height + 30;
|
height: buyText.height + 30;
|
||||||
|
@ -463,8 +467,8 @@ Rectangle {
|
||||||
enabled: (root.balanceAfterPurchase >= 0 && purchasesReceived && balanceReceived) || !itemIsJson;
|
enabled: (root.balanceAfterPurchase >= 0 && purchasesReceived && balanceReceived) || !itemIsJson;
|
||||||
color: hifi.buttons.blue;
|
color: hifi.buttons.blue;
|
||||||
colorScheme: hifi.colorSchemes.light;
|
colorScheme: hifi.colorSchemes.light;
|
||||||
anchors.top: buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top;
|
anchors.top: checkoutActionButtonsContainer.top;
|
||||||
anchors.topMargin: buyTextContainer.visible ? 12 : 16;
|
anchors.topMargin: 16;
|
||||||
height: 40;
|
height: 40;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
|
@ -473,9 +477,9 @@ Rectangle {
|
||||||
if (itemIsJson) {
|
if (itemIsJson) {
|
||||||
buyButton.enabled = false;
|
buyButton.enabled = false;
|
||||||
if (!root.shouldBuyWithControlledFailure) {
|
if (!root.shouldBuyWithControlledFailure) {
|
||||||
commerce.buy(itemId, itemPrice);
|
Commerce.buy(itemId, itemPrice);
|
||||||
} else {
|
} else {
|
||||||
commerce.buy(itemId, itemPrice, true);
|
Commerce.buy(itemId, itemPrice, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (urlHandler.canHandleUrl(itemHref)) {
|
if (urlHandler.canHandleUrl(itemHref)) {
|
||||||
|
@ -876,6 +880,8 @@ Rectangle {
|
||||||
itemName = message.params.itemName;
|
itemName = message.params.itemName;
|
||||||
root.itemPrice = message.params.itemPrice;
|
root.itemPrice = message.params.itemPrice;
|
||||||
itemHref = message.params.itemHref;
|
itemHref = message.params.itemHref;
|
||||||
|
referrer = message.params.referrer;
|
||||||
|
itemAuthor = message.params.itemAuthor;
|
||||||
setBuyText();
|
setBuyText();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -923,11 +929,11 @@ Rectangle {
|
||||||
buyText.text = "";
|
buyText.text = "";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buyText.text = "This free item <b>will not</b> be added to your <b>Purchases</b>. Non-entities can't yet be purchased for HFC.";
|
buyText.text = '<i>This type of item cannot currently be certified, so it will not show up in "My Purchases". You can access it again for free from the Marketplace.</i>';
|
||||||
buyTextContainer.color = "#FFD6AD";
|
buyTextContainer.color = hifi.colors.white;
|
||||||
buyTextContainer.border.color = "#FAC07D";
|
buyTextContainer.border.color = hifi.colors.white;
|
||||||
buyGlyph.text = hifi.glyphs.alert;
|
buyGlyph.text = "";
|
||||||
buyGlyph.size = 46;
|
buyGlyph.size = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -939,8 +945,8 @@ Rectangle {
|
||||||
}
|
}
|
||||||
root.balanceReceived = false;
|
root.balanceReceived = false;
|
||||||
root.purchasesReceived = false;
|
root.purchasesReceived = false;
|
||||||
commerce.inventory();
|
Commerce.inventory();
|
||||||
commerce.balance();
|
Commerce.balance();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -31,14 +31,14 @@ Item {
|
||||||
|
|
||||||
height: mainContainer.height + additionalDropdownHeight;
|
height: mainContainer.height + additionalDropdownHeight;
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onWalletStatusResult: {
|
onWalletStatusResult: {
|
||||||
if (walletStatus === 0) {
|
if (walletStatus === 0) {
|
||||||
sendToParent({method: "needsLogIn"});
|
sendToParent({method: "needsLogIn"});
|
||||||
} else if (walletStatus === 3) {
|
} else if (walletStatus === 3) {
|
||||||
commerce.getSecurityImage();
|
Commerce.getSecurityImage();
|
||||||
} else if (walletStatus > 3) {
|
} else if (walletStatus > 3) {
|
||||||
console.log("ERROR in EmulatedMarketplaceHeader.qml: Unknown wallet status: " + walletStatus);
|
console.log("ERROR in EmulatedMarketplaceHeader.qml: Unknown wallet status: " + walletStatus);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ Item {
|
||||||
if (!isLoggedIn) {
|
if (!isLoggedIn) {
|
||||||
sendToParent({method: "needsLogIn"});
|
sendToParent({method: "needsLogIn"});
|
||||||
} else {
|
} else {
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,13 +61,13 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: GlobalServices
|
target: GlobalServices
|
||||||
onMyUsernameChanged: {
|
onMyUsernameChanged: {
|
||||||
commerce.getLoginStatus();
|
Commerce.getLoginStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,8 @@ Rectangle {
|
||||||
property bool isCertificateInvalid: false;
|
property bool isCertificateInvalid: false;
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.faintGray;
|
color: hifi.colors.faintGray;
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onCertificateInfoResult: {
|
onCertificateInfoResult: {
|
||||||
if (result.status !== 'success') {
|
if (result.status !== 'success') {
|
||||||
|
@ -109,7 +109,7 @@ Rectangle {
|
||||||
|
|
||||||
onCertificateIdChanged: {
|
onCertificateIdChanged: {
|
||||||
if (certificateId !== "") {
|
if (certificateId !== "") {
|
||||||
commerce.certificateInfo(certificateId);
|
Commerce.certificateInfo(certificateId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,8 @@ Rectangle {
|
||||||
property bool isDebuggingFirstUseTutorial: false;
|
property bool isDebuggingFirstUseTutorial: false;
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.white;
|
color: hifi.colors.white;
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onWalletStatusResult: {
|
onWalletStatusResult: {
|
||||||
if (walletStatus === 0) {
|
if (walletStatus === 0) {
|
||||||
|
@ -54,13 +54,14 @@ Rectangle {
|
||||||
} else if (walletStatus === 2) {
|
} else if (walletStatus === 2) {
|
||||||
if (root.activeView !== "passphraseModal") {
|
if (root.activeView !== "passphraseModal") {
|
||||||
root.activeView = "passphraseModal";
|
root.activeView = "passphraseModal";
|
||||||
|
UserActivityLogger.commercePassphraseEntry("marketplace purchases");
|
||||||
}
|
}
|
||||||
} else if (walletStatus === 3) {
|
} else if (walletStatus === 3) {
|
||||||
if ((Settings.getValue("isFirstUseOfPurchases", true) || root.isDebuggingFirstUseTutorial) && root.activeView !== "firstUseTutorial") {
|
if ((Settings.getValue("isFirstUseOfPurchases", true) || root.isDebuggingFirstUseTutorial) && root.activeView !== "firstUseTutorial") {
|
||||||
root.activeView = "firstUseTutorial";
|
root.activeView = "firstUseTutorial";
|
||||||
} else if (!Settings.getValue("isFirstUseOfPurchases", true) && root.activeView === "initialize") {
|
} else if (!Settings.getValue("isFirstUseOfPurchases", true) && root.activeView === "initialize") {
|
||||||
root.activeView = "purchasesMain";
|
root.activeView = "purchasesMain";
|
||||||
commerce.inventory();
|
Commerce.inventory();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("ERROR in Purchases.qml: Unknown wallet status: " + walletStatus);
|
console.log("ERROR in Purchases.qml: Unknown wallet status: " + walletStatus);
|
||||||
|
@ -71,7 +72,7 @@ Rectangle {
|
||||||
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
||||||
root.activeView = "needsLogIn";
|
root.activeView = "needsLogIn";
|
||||||
} else {
|
} else {
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +198,7 @@ Rectangle {
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
securityImageResultReceived = false;
|
securityImageResultReceived = false;
|
||||||
purchasesReceived = false;
|
purchasesReceived = false;
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +219,7 @@ Rectangle {
|
||||||
Connections {
|
Connections {
|
||||||
target: GlobalServices
|
target: GlobalServices
|
||||||
onMyUsernameChanged: {
|
onMyUsernameChanged: {
|
||||||
commerce.getLoginStatus();
|
Commerce.getLoginStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +234,7 @@ Rectangle {
|
||||||
onSendSignalToParent: {
|
onSendSignalToParent: {
|
||||||
if (msg.method === "authSuccess") {
|
if (msg.method === "authSuccess") {
|
||||||
root.activeView = "initialize";
|
root.activeView = "initialize";
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
} else {
|
} else {
|
||||||
sendToScript(msg);
|
sendToScript(msg);
|
||||||
}
|
}
|
||||||
|
@ -254,7 +255,7 @@ Rectangle {
|
||||||
case 'tutorial_finished':
|
case 'tutorial_finished':
|
||||||
Settings.setValue("isFirstUseOfPurchases", false);
|
Settings.setValue("isFirstUseOfPurchases", false);
|
||||||
root.activeView = "purchasesMain";
|
root.activeView = "purchasesMain";
|
||||||
commerce.inventory();
|
Commerce.inventory();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -594,7 +595,7 @@ Rectangle {
|
||||||
if (root.activeView === "purchasesMain" && !root.pendingInventoryReply) {
|
if (root.activeView === "purchasesMain" && !root.pendingInventoryReply) {
|
||||||
console.log("Refreshing Purchases...");
|
console.log("Refreshing Purchases...");
|
||||||
root.pendingInventoryReply = true;
|
root.pendingInventoryReply = true;
|
||||||
commerce.inventory();
|
Commerce.inventory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ Item {
|
||||||
property string keyFilePath;
|
property string keyFilePath;
|
||||||
property bool showDebugButtons: true;
|
property bool showDebugButtons: true;
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onKeyFilePathIfExistsResult: {
|
onKeyFilePathIfExistsResult: {
|
||||||
root.keyFilePath = path;
|
root.keyFilePath = path;
|
||||||
|
@ -37,7 +37,7 @@ Item {
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
commerce.getKeyFilePathIfExists();
|
Commerce.getKeyFilePathIfExists();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,37 @@ Item {
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.blueHighlight;
|
color: hifi.colors.blueHighlight;
|
||||||
}
|
}
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: clearCachedPassphraseButton;
|
||||||
|
visible: root.showDebugButtons;
|
||||||
|
color: hifi.buttons.black;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.left: helpTitleText.right;
|
||||||
|
anchors.leftMargin: 20;
|
||||||
|
height: 40;
|
||||||
|
width: 150;
|
||||||
|
text: "DBG: Clear Pass";
|
||||||
|
onClicked: {
|
||||||
|
Commerce.setPassphrase("");
|
||||||
|
sendSignalToWallet({method: 'passphraseReset'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: resetButton;
|
||||||
|
visible: root.showDebugButtons;
|
||||||
|
color: hifi.buttons.red;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.top: clearCachedPassphraseButton.top;
|
||||||
|
anchors.left: clearCachedPassphraseButton.right;
|
||||||
|
height: 40;
|
||||||
|
width: 150;
|
||||||
|
text: "DBG: RST Wallet";
|
||||||
|
onClicked: {
|
||||||
|
Commerce.reset();
|
||||||
|
sendSignalToWallet({method: 'walletReset'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ListModel {
|
ListModel {
|
||||||
id: helpModel;
|
id: helpModel;
|
||||||
|
|
|
@ -30,8 +30,8 @@ Item {
|
||||||
source: "images/wallet-bg.jpg";
|
source: "images/wallet-bg.jpg";
|
||||||
}
|
}
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -25,10 +25,6 @@ Item {
|
||||||
|
|
||||||
id: root;
|
id: root;
|
||||||
|
|
||||||
SecurityImageModel {
|
|
||||||
id: securityImageModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Username Text
|
// Username Text
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
id: usernameText;
|
id: usernameText;
|
||||||
|
|
|
@ -36,8 +36,8 @@ Item {
|
||||||
source: "images/wallet-bg.jpg";
|
source: "images/wallet-bg.jpg";
|
||||||
}
|
}
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onSecurityImageResult: {
|
onSecurityImageResult: {
|
||||||
titleBarSecurityImage.source = "";
|
titleBarSecurityImage.source = "";
|
||||||
|
@ -50,8 +50,12 @@ Item {
|
||||||
submitPassphraseInputButton.enabled = true;
|
submitPassphraseInputButton.enabled = true;
|
||||||
if (!isAuthenticated) {
|
if (!isAuthenticated) {
|
||||||
errorText.text = "Authentication failed - please try again.";
|
errorText.text = "Authentication failed - please try again.";
|
||||||
|
passphraseField.error = true;
|
||||||
|
UserActivityLogger.commercePassphraseAuthenticationStatus("auth failure");
|
||||||
} else {
|
} else {
|
||||||
sendSignalToParent({method: 'authSuccess'});;
|
sendSignalToParent({method: 'authSuccess'});
|
||||||
|
passphraseField.error = false;
|
||||||
|
UserActivityLogger.commercePassphraseAuthenticationStatus("auth success");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,6 +74,7 @@ Item {
|
||||||
// TODO: Fix this unlikely bug
|
// TODO: Fix this unlikely bug
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
passphraseField.error = false;
|
||||||
passphraseField.focus = true;
|
passphraseField.focus = true;
|
||||||
sendSignalToParent({method: 'disableHmdPreview'});
|
sendSignalToParent({method: 'disableHmdPreview'});
|
||||||
} else {
|
} else {
|
||||||
|
@ -208,7 +213,7 @@ Item {
|
||||||
|
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
submitPassphraseInputButton.enabled = false;
|
submitPassphraseInputButton.enabled = false;
|
||||||
commerce.setPassphrase(passphraseField.text);
|
Commerce.setPassphrase(passphraseField.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +253,7 @@ Item {
|
||||||
source: "image://security/securityImage";
|
source: "image://security/securityImage";
|
||||||
cache: false;
|
cache: false;
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
commerce.getSecurityImage();
|
Commerce.getSecurityImage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item {
|
Item {
|
||||||
|
@ -316,7 +321,7 @@ Item {
|
||||||
text: "Submit"
|
text: "Submit"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
submitPassphraseInputButton.enabled = false;
|
submitPassphraseInputButton.enabled = false;
|
||||||
commerce.setPassphrase(passphraseField.text);
|
Commerce.setPassphrase(passphraseField.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,6 +341,7 @@ Item {
|
||||||
text: "Cancel"
|
text: "Cancel"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
sendSignalToParent({method: 'passphrasePopup_cancelClicked'});
|
sendSignalToParent({method: 'passphrasePopup_cancelClicked'});
|
||||||
|
UserActivityLogger.commercePassphraseAuthenticationStatus("passphrase modal cancelled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,8 @@ Item {
|
||||||
propagateComposedEvents: false;
|
propagateComposedEvents: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
onSecurityImageResult: {
|
onSecurityImageResult: {
|
||||||
passphrasePageSecurityImage.source = "";
|
passphrasePageSecurityImage.source = "";
|
||||||
passphrasePageSecurityImage.source = "image://security/securityImage";
|
passphrasePageSecurityImage.source = "image://security/securityImage";
|
||||||
|
@ -54,6 +54,9 @@ Item {
|
||||||
// TODO: Fix this unlikely bug
|
// TODO: Fix this unlikely bug
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
passphraseField.error = false;
|
||||||
|
passphraseFieldAgain.error = false;
|
||||||
|
currentPassphraseField.error = false;
|
||||||
if (root.shouldImmediatelyFocus) {
|
if (root.shouldImmediatelyFocus) {
|
||||||
focusFirstTextField();
|
focusFirstTextField();
|
||||||
}
|
}
|
||||||
|
@ -160,7 +163,7 @@ Item {
|
||||||
source: "image://security/securityImage";
|
source: "image://security/securityImage";
|
||||||
cache: false;
|
cache: false;
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
commerce.getSecurityImage();
|
Commerce.getSecurityImage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item {
|
Item {
|
||||||
|
@ -283,7 +286,7 @@ Item {
|
||||||
passphraseFieldAgain.error = false;
|
passphraseFieldAgain.error = false;
|
||||||
currentPassphraseField.error = false;
|
currentPassphraseField.error = false;
|
||||||
setErrorText("");
|
setErrorText("");
|
||||||
commerce.changePassphrase(currentPassphraseField.text, passphraseField.text);
|
Commerce.changePassphrase(currentPassphraseField.text, passphraseField.text);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ Item {
|
||||||
id: root;
|
id: root;
|
||||||
property string keyFilePath;
|
property string keyFilePath;
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onKeyFilePathIfExistsResult: {
|
onKeyFilePathIfExistsResult: {
|
||||||
root.keyFilePath = path;
|
root.keyFilePath = path;
|
||||||
|
@ -234,7 +234,7 @@ Item {
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
commerce.getKeyFilePathIfExists();
|
Commerce.getKeyFilePathIfExists();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,12 +26,8 @@ Item {
|
||||||
id: root;
|
id: root;
|
||||||
property bool justSubmitted: false;
|
property bool justSubmitted: false;
|
||||||
|
|
||||||
SecurityImageModel {
|
Connections {
|
||||||
id: securityImageModel;
|
target: Commerce;
|
||||||
}
|
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
|
||||||
id: commerce;
|
|
||||||
|
|
||||||
onSecurityImageResult: {
|
onSecurityImageResult: {
|
||||||
securityImageChangePageSecurityImage.source = "";
|
securityImageChangePageSecurityImage.source = "";
|
||||||
|
@ -70,7 +66,7 @@ Item {
|
||||||
source: "image://security/securityImage";
|
source: "image://security/securityImage";
|
||||||
cache: false;
|
cache: false;
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
commerce.getSecurityImage();
|
Commerce.getSecurityImage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item {
|
Item {
|
||||||
|
@ -198,7 +194,7 @@ Item {
|
||||||
securityImageSubmitButton.text = "Submitting...";
|
securityImageSubmitButton.text = "Submitting...";
|
||||||
securityImageSubmitButton.enabled = false;
|
securityImageSubmitButton.enabled = false;
|
||||||
var securityImagePath = securityImageSelection.getImagePathFromImageID(securityImageSelection.getSelectedImageIndex())
|
var securityImagePath = securityImageSelection.getImagePathFromImageID(securityImageSelection.getSelectedImageIndex())
|
||||||
commerce.chooseSecurityImage(securityImagePath);
|
Commerce.chooseSecurityImage(securityImagePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,4 +209,8 @@ Item {
|
||||||
securityImageSubmitButton.enabled = true;
|
securityImageSubmitButton.enabled = true;
|
||||||
securityImageSubmitButton.text = "Submit";
|
securityImageSubmitButton.text = "Submit";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initModel() {
|
||||||
|
securityImageSelection.initModel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,29 +15,28 @@ import QtQuick 2.5
|
||||||
|
|
||||||
ListModel {
|
ListModel {
|
||||||
id: root;
|
id: root;
|
||||||
ListElement{
|
|
||||||
sourcePath: "images/01.jpg"
|
function initModel() {
|
||||||
securityImageEnumValue: 1;
|
var array = [];
|
||||||
|
while (array.length < 6) {
|
||||||
|
// We currently have 34 security images to choose from
|
||||||
|
var randomNumber = Math.floor(Math.random() * 34) + 1;
|
||||||
|
if (array.indexOf(randomNumber) > -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
array[array.length] = randomNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
var modelElement;
|
||||||
|
|
||||||
|
for (var i = 0; i < 6; i++) {
|
||||||
|
modelElement = { "sourcePath":"images/" + addLeadingZero(array[i]) + ".jpg", "securityImageEnumValue": (i + 1) }
|
||||||
|
root.insert(i, modelElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ListElement{
|
|
||||||
sourcePath: "images/02.jpg"
|
function addLeadingZero(n) {
|
||||||
securityImageEnumValue: 2;
|
return n < 10 ? '0' + n : '' + n;
|
||||||
}
|
|
||||||
ListElement{
|
|
||||||
sourcePath: "images/03.jpg"
|
|
||||||
securityImageEnumValue: 3;
|
|
||||||
}
|
|
||||||
ListElement{
|
|
||||||
sourcePath: "images/04.jpg"
|
|
||||||
securityImageEnumValue: 4;
|
|
||||||
}
|
|
||||||
ListElement{
|
|
||||||
sourcePath: "images/05.jpg"
|
|
||||||
securityImageEnumValue: 5;
|
|
||||||
}
|
|
||||||
ListElement{
|
|
||||||
sourcePath: "images/06.jpg"
|
|
||||||
securityImageEnumValue: 6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getImagePathFromImageID(imageID) {
|
function getImagePathFromImageID(imageID) {
|
||||||
|
|
|
@ -95,6 +95,10 @@ Item {
|
||||||
function getSelectedImageIndex() {
|
function getSelectedImageIndex() {
|
||||||
return gridModel.get(securityImageGrid.currentIndex).securityImageEnumValue;
|
return gridModel.get(securityImageGrid.currentIndex).securityImageEnumValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initModel() {
|
||||||
|
gridModel.initModel();
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// FUNCTION DEFINITIONS END
|
// FUNCTION DEFINITIONS END
|
||||||
//
|
//
|
||||||
|
|
|
@ -25,8 +25,8 @@ Item {
|
||||||
|
|
||||||
id: root;
|
id: root;
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Unavailable"
|
// "Unavailable"
|
||||||
|
|
|
@ -31,13 +31,15 @@ Rectangle {
|
||||||
property bool keyboardRaised: false;
|
property bool keyboardRaised: false;
|
||||||
property bool isPassword: false;
|
property bool isPassword: false;
|
||||||
|
|
||||||
|
anchors.fill: (typeof parent === undefined) ? undefined : parent;
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
source: "images/wallet-bg.jpg";
|
source: "images/wallet-bg.jpg";
|
||||||
}
|
}
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onWalletStatusResult: {
|
onWalletStatusResult: {
|
||||||
if (walletStatus === 0) {
|
if (walletStatus === 0) {
|
||||||
|
@ -47,7 +49,7 @@ Rectangle {
|
||||||
} else if (walletStatus === 1) {
|
} else if (walletStatus === 1) {
|
||||||
if (root.activeView !== "walletSetup") {
|
if (root.activeView !== "walletSetup") {
|
||||||
root.activeView = "walletSetup";
|
root.activeView = "walletSetup";
|
||||||
commerce.resetLocalWalletOnly();
|
Commerce.resetLocalWalletOnly();
|
||||||
var timestamp = new Date();
|
var timestamp = new Date();
|
||||||
walletSetup.startingTimestamp = timestamp;
|
walletSetup.startingTimestamp = timestamp;
|
||||||
walletSetup.setupAttemptID = generateUUID();
|
walletSetup.setupAttemptID = generateUUID();
|
||||||
|
@ -57,10 +59,13 @@ Rectangle {
|
||||||
} else if (walletStatus === 2) {
|
} else if (walletStatus === 2) {
|
||||||
if (root.activeView !== "passphraseModal") {
|
if (root.activeView !== "passphraseModal") {
|
||||||
root.activeView = "passphraseModal";
|
root.activeView = "passphraseModal";
|
||||||
|
UserActivityLogger.commercePassphraseEntry("wallet app");
|
||||||
}
|
}
|
||||||
} else if (walletStatus === 3) {
|
} else if (walletStatus === 3) {
|
||||||
root.activeView = "walletHome";
|
if (root.activeView !== "walletSetup") {
|
||||||
commerce.getSecurityImage();
|
root.activeView = "walletHome";
|
||||||
|
Commerce.getSecurityImage();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("ERROR in Wallet.qml: Unknown wallet status: " + walletStatus);
|
console.log("ERROR in Wallet.qml: Unknown wallet status: " + walletStatus);
|
||||||
}
|
}
|
||||||
|
@ -70,7 +75,7 @@ Rectangle {
|
||||||
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
||||||
root.activeView = "needsLogIn";
|
root.activeView = "needsLogIn";
|
||||||
} else if (isLoggedIn) {
|
} else if (isLoggedIn) {
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,10 +87,6 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SecurityImageModel {
|
|
||||||
id: securityImageModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
HifiCommerceCommon.CommerceLightbox {
|
HifiCommerceCommon.CommerceLightbox {
|
||||||
id: lightboxPopup;
|
id: lightboxPopup;
|
||||||
visible: false;
|
visible: false;
|
||||||
|
@ -180,7 +181,7 @@ Rectangle {
|
||||||
if (msg.method === 'walletSetup_finished') {
|
if (msg.method === 'walletSetup_finished') {
|
||||||
if (msg.referrer === '' || msg.referrer === 'marketplace cta') {
|
if (msg.referrer === '' || msg.referrer === 'marketplace cta') {
|
||||||
root.activeView = "initialize";
|
root.activeView = "initialize";
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
} else if (msg.referrer === 'purchases') {
|
} else if (msg.referrer === 'purchases') {
|
||||||
sendToScript({method: 'goToPurchases'});
|
sendToScript({method: 'goToPurchases'});
|
||||||
} else {
|
} else {
|
||||||
|
@ -209,17 +210,19 @@ Rectangle {
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
onSendSignalToWallet: {
|
onSendSignalToWallet: {
|
||||||
if (msg.method === 'walletSetup_raiseKeyboard') {
|
if (passphraseChange.visible) {
|
||||||
root.keyboardRaised = true;
|
if (msg.method === 'walletSetup_raiseKeyboard') {
|
||||||
root.isPassword = msg.isPasswordField;
|
root.keyboardRaised = true;
|
||||||
} else if (msg.method === 'walletSetup_lowerKeyboard') {
|
root.isPassword = msg.isPasswordField;
|
||||||
root.keyboardRaised = false;
|
} else if (msg.method === 'walletSetup_lowerKeyboard') {
|
||||||
} else if (msg.method === 'walletSecurity_changePassphraseCancelled') {
|
root.keyboardRaised = false;
|
||||||
root.activeView = "security";
|
} else if (msg.method === 'walletSecurity_changePassphraseCancelled') {
|
||||||
} else if (msg.method === 'walletSecurity_changePassphraseSuccess') {
|
root.activeView = "security";
|
||||||
root.activeView = "security";
|
} else if (msg.method === 'walletSecurity_changePassphraseSuccess') {
|
||||||
} else {
|
root.activeView = "security";
|
||||||
sendToScript(msg);
|
} else {
|
||||||
|
sendToScript(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,7 +263,7 @@ Rectangle {
|
||||||
color: hifi.colors.baseGray;
|
color: hifi.colors.baseGray;
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,7 +284,7 @@ Rectangle {
|
||||||
Connections {
|
Connections {
|
||||||
target: GlobalServices
|
target: GlobalServices
|
||||||
onMyUsernameChanged: {
|
onMyUsernameChanged: {
|
||||||
commerce.getLoginStatus();
|
Commerce.getLoginStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +298,7 @@ Rectangle {
|
||||||
Connections {
|
Connections {
|
||||||
onSendSignalToParent: {
|
onSendSignalToParent: {
|
||||||
if (msg.method === "authSuccess") {
|
if (msg.method === "authSuccess") {
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
} else {
|
} else {
|
||||||
sendToScript(msg);
|
sendToScript(msg);
|
||||||
}
|
}
|
||||||
|
@ -342,6 +345,7 @@ Rectangle {
|
||||||
passphraseChange.clearPassphraseFields();
|
passphraseChange.clearPassphraseFields();
|
||||||
passphraseChange.resetSubmitButton();
|
passphraseChange.resetSubmitButton();
|
||||||
} else if (msg.method === 'walletSecurity_changeSecurityImage') {
|
} else if (msg.method === 'walletSecurity_changeSecurityImage') {
|
||||||
|
securityImageChange.initModel();
|
||||||
root.activeView = "securityImageChange";
|
root.activeView = "securityImageChange";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,8 @@ Item {
|
||||||
property bool historyReceived: false;
|
property bool historyReceived: false;
|
||||||
property int pendingCount: 0;
|
property int pendingCount: 0;
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onBalanceResult : {
|
onBalanceResult : {
|
||||||
balanceText.text = result.data.balance;
|
balanceText.text = result.data.balance;
|
||||||
|
@ -135,8 +135,8 @@ Item {
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
historyReceived = false;
|
historyReceived = false;
|
||||||
commerce.balance();
|
Commerce.balance();
|
||||||
commerce.history();
|
Commerce.history();
|
||||||
} else {
|
} else {
|
||||||
refreshTimer.stop();
|
refreshTimer.stop();
|
||||||
}
|
}
|
||||||
|
@ -165,8 +165,8 @@ Item {
|
||||||
interval: 4000;
|
interval: 4000;
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
console.log("Refreshing Wallet Home...");
|
console.log("Refreshing Wallet Home...");
|
||||||
commerce.balance();
|
Commerce.balance();
|
||||||
commerce.history();
|
Commerce.history();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,14 +197,36 @@ Item {
|
||||||
anchors.topMargin: 26;
|
anchors.topMargin: 26;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.leftMargin: 20;
|
anchors.leftMargin: 20;
|
||||||
anchors.right: parent.right;
|
width: paintedWidth;
|
||||||
anchors.rightMargin: 30;
|
|
||||||
height: 30;
|
height: 30;
|
||||||
// Text size
|
// Text size
|
||||||
size: 22;
|
size: 22;
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.baseGrayHighlight;
|
color: hifi.colors.baseGrayHighlight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RalewaySemiBold {
|
||||||
|
id: myPurchasesLink;
|
||||||
|
text: '<font color="#0093C5"><a href="#myPurchases">My Purchases</a></font>';
|
||||||
|
// Anchors
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.topMargin: 26;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.rightMargin: 20;
|
||||||
|
width: paintedWidth;
|
||||||
|
height: 30;
|
||||||
|
y: 4;
|
||||||
|
// Text size
|
||||||
|
size: 18;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.baseGrayHighlight;
|
||||||
|
horizontalAlignment: Text.AlignRight;
|
||||||
|
|
||||||
|
onLinkActivated: {
|
||||||
|
sendSignalToWallet({method: 'goToPurchases_fromWalletHome'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ListModel {
|
ListModel {
|
||||||
id: tempTransactionHistoryModel;
|
id: tempTransactionHistoryModel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,8 @@ Item {
|
||||||
source: "images/wallet-bg.jpg";
|
source: "images/wallet-bg.jpg";
|
||||||
}
|
}
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onSecurityImageResult: {
|
onSecurityImageResult: {
|
||||||
if (!exists && root.lastPage === "step_2") {
|
if (!exists && root.lastPage === "step_2") {
|
||||||
|
@ -236,6 +236,7 @@ Item {
|
||||||
height: 50;
|
height: 50;
|
||||||
text: "Set Up Wallet";
|
text: "Set Up Wallet";
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
securityImageSelection.initModel();
|
||||||
root.activeView = "step_2";
|
root.activeView = "step_2";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,7 +252,7 @@ Item {
|
||||||
height: 50;
|
height: 50;
|
||||||
text: "Cancel";
|
text: "Cancel";
|
||||||
onClicked: {
|
onClicked: {
|
||||||
sendSignalToWallet({method: 'walletSetup_cancelClicked'});
|
sendSignalToWallet({method: 'walletSetup_cancelClicked', referrer: root.referrer });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,7 +366,7 @@ Item {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.lastPage = "step_2";
|
root.lastPage = "step_2";
|
||||||
var securityImagePath = securityImageSelection.getImagePathFromImageID(securityImageSelection.getSelectedImageIndex())
|
var securityImagePath = securityImageSelection.getImagePathFromImageID(securityImageSelection.getSelectedImageIndex())
|
||||||
commerce.chooseSecurityImage(securityImagePath);
|
Commerce.chooseSecurityImage(securityImagePath);
|
||||||
root.activeView = "step_3";
|
root.activeView = "step_3";
|
||||||
passphraseSelection.clearPassphraseFields();
|
passphraseSelection.clearPassphraseFields();
|
||||||
}
|
}
|
||||||
|
@ -448,7 +449,7 @@ Item {
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
commerce.getWalletAuthenticatedStatus();
|
Commerce.getWalletAuthenticatedStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,7 +535,7 @@ Item {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (passphraseSelection.validateAndSubmitPassphrase()) {
|
if (passphraseSelection.validateAndSubmitPassphrase()) {
|
||||||
root.lastPage = "step_3";
|
root.lastPage = "step_3";
|
||||||
commerce.generateKeyPair();
|
Commerce.generateKeyPair();
|
||||||
root.activeView = "step_4";
|
root.activeView = "step_4";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -667,7 +668,7 @@ Item {
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
commerce.getKeyFilePathIfExists();
|
Commerce.getKeyFilePathIfExists();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 35 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/07.jpg
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/08.jpg
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/09.jpg
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/10.jpg
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/11.jpg
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/12.jpg
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/13.jpg
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/14.jpg
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/15.jpg
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/16.jpg
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/17.jpg
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/18.jpg
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/19.jpg
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/20.jpg
Normal file
After Width: | Height: | Size: 79 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/21.jpg
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/22.jpg
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/23.jpg
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/24.jpg
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/25.jpg
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/26.jpg
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/27.jpg
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/28.jpg
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/29.jpg
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/30.jpg
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/31.jpg
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/32.jpg
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/33.jpg
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
interface/resources/qml/hifi/commerce/wallet/images/34.jpg
Normal file
After Width: | Height: | Size: 50 KiB |
|
@ -123,11 +123,11 @@ Item {
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
enabled: true
|
enabled: true
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
newEntityButton.clicked();
|
newEntityButton.clicked();
|
||||||
}
|
}
|
||||||
onEntered: {
|
onEntered: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
newEntityButton.state = "hover state";
|
newEntityButton.state = "hover state";
|
||||||
}
|
}
|
||||||
onExited: {
|
onExited: {
|
||||||
|
|
|
@ -1,261 +0,0 @@
|
||||||
import QtQuick 2.5
|
|
||||||
import QtGraphicalEffects 1.0
|
|
||||||
import QtQuick.Layouts 1.3
|
|
||||||
|
|
||||||
import "../../styles-uit"
|
|
||||||
import "../audio" as HifiAudio
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: tablet
|
|
||||||
objectName: "tablet"
|
|
||||||
property int rowIndex: 6 // by default
|
|
||||||
property int columnIndex: 1 // point to 'go to location'
|
|
||||||
property int count: (flowMain.children.length - 1)
|
|
||||||
|
|
||||||
// used to look up a button by its uuid
|
|
||||||
function findButtonIndex(uuid) {
|
|
||||||
if (!uuid) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i in flowMain.children) {
|
|
||||||
var child = flowMain.children[i];
|
|
||||||
if (child.uuid === uuid) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortButtons() {
|
|
||||||
var children = [];
|
|
||||||
for (var i = 0; i < flowMain.children.length; i++) {
|
|
||||||
children[i] = flowMain.children[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
children.sort(function (a, b) {
|
|
||||||
if (a.sortOrder === b.sortOrder) {
|
|
||||||
// subsort by stableOrder, because JS sort is not stable in qml.
|
|
||||||
return a.stableOrder - b.stableOrder;
|
|
||||||
} else {
|
|
||||||
return a.sortOrder - b.sortOrder;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
flowMain.children = children;
|
|
||||||
}
|
|
||||||
|
|
||||||
// called by C++ code when a button should be added to the tablet
|
|
||||||
function addButtonProxy(properties) {
|
|
||||||
var component = Qt.createComponent("TabletButton.qml");
|
|
||||||
var button = component.createObject(flowMain);
|
|
||||||
|
|
||||||
// copy all properites to button
|
|
||||||
var keys = Object.keys(properties).forEach(function (key) {
|
|
||||||
button[key] = properties[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
// pass a reference to the tabletRoot object to the button.
|
|
||||||
if (tabletRoot) {
|
|
||||||
button.tabletRoot = tabletRoot;
|
|
||||||
} else {
|
|
||||||
button.tabletRoot = parent.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
sortButtons();
|
|
||||||
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
// called by C++ code when a button should be removed from the tablet
|
|
||||||
function removeButtonProxy(properties) {
|
|
||||||
var index = findButtonIndex(properties.uuid);
|
|
||||||
if (index < 0) {
|
|
||||||
console.log("Warning: Tablet.qml could not find button with uuid = " + properties.uuid);
|
|
||||||
} else {
|
|
||||||
flowMain.children[index].destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: bgTopBar
|
|
||||||
height: 90
|
|
||||||
|
|
||||||
anchors {
|
|
||||||
top: parent.top
|
|
||||||
topMargin: 0
|
|
||||||
left: parent.left
|
|
||||||
leftMargin: 0
|
|
||||||
right: parent.right
|
|
||||||
rightMargin: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
gradient: Gradient {
|
|
||||||
GradientStop {
|
|
||||||
position: 0
|
|
||||||
color: "#2b2b2b"
|
|
||||||
}
|
|
||||||
|
|
||||||
GradientStop {
|
|
||||||
position: 1
|
|
||||||
color: "#1e1e1e"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HifiAudio.MicBar {
|
|
||||||
anchors {
|
|
||||||
left: parent.left
|
|
||||||
leftMargin: 30
|
|
||||||
verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
width: 150
|
|
||||||
height: 50
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: 30
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
RalewaySemiBold {
|
|
||||||
text: Account.loggedIn ? qsTr("Log out") : qsTr("Log in")
|
|
||||||
horizontalAlignment: Text.AlignRight
|
|
||||||
anchors.right: parent.right
|
|
||||||
font.pixelSize: 20
|
|
||||||
color: "#afafaf"
|
|
||||||
}
|
|
||||||
|
|
||||||
RalewaySemiBold {
|
|
||||||
visible: Account.loggedIn
|
|
||||||
height: Account.loggedIn ? parent.height/2 - parent.spacing/2 : 0
|
|
||||||
text: Account.loggedIn ? "[" + tabletRoot.usernameShort + "]" : ""
|
|
||||||
horizontalAlignment: Text.AlignRight
|
|
||||||
anchors.right: parent.right
|
|
||||||
font.pixelSize: 20
|
|
||||||
color: "#afafaf"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: {
|
|
||||||
if (!Account.loggedIn) {
|
|
||||||
DialogsManager.showLoginDialog()
|
|
||||||
} else {
|
|
||||||
Account.logOut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: bgMain
|
|
||||||
gradient: Gradient {
|
|
||||||
GradientStop {
|
|
||||||
position: 0
|
|
||||||
color: "#2b2b2b"
|
|
||||||
}
|
|
||||||
|
|
||||||
GradientStop {
|
|
||||||
position: 1
|
|
||||||
color: "#0f212e"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.bottomMargin: 0
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: 0
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: 0
|
|
||||||
anchors.top: bgTopBar.bottom
|
|
||||||
anchors.topMargin: 0
|
|
||||||
|
|
||||||
Flickable {
|
|
||||||
id: flickable
|
|
||||||
width: parent.width
|
|
||||||
height: parent.height
|
|
||||||
contentWidth: parent.width
|
|
||||||
contentHeight: flowMain.childrenRect.height + flowMain.anchors.topMargin + flowMain.anchors.bottomMargin + flowMain.spacing
|
|
||||||
clip: true
|
|
||||||
Flow {
|
|
||||||
id: flowMain
|
|
||||||
spacing: 16
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: 30
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: 30
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.bottomMargin: 30
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.topMargin: 30
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setCurrentItemState(state) {
|
|
||||||
var index = rowIndex + columnIndex;
|
|
||||||
|
|
||||||
if (index >= 0 && index <= count ) {
|
|
||||||
flowMain.children[index].state = state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function nextItem() {
|
|
||||||
setCurrentItemState("base state");
|
|
||||||
var nextColumnIndex = (columnIndex + 3 + 1) % 3;
|
|
||||||
var nextIndex = rowIndex + nextColumnIndex;
|
|
||||||
if(nextIndex <= count) {
|
|
||||||
columnIndex = nextColumnIndex;
|
|
||||||
};
|
|
||||||
setCurrentItemState("hover state");
|
|
||||||
}
|
|
||||||
|
|
||||||
function previousItem() {
|
|
||||||
setCurrentItemState("base state");
|
|
||||||
var prevIndex = (columnIndex + 3 - 1) % 3;
|
|
||||||
if((rowIndex + prevIndex) <= count){
|
|
||||||
columnIndex = prevIndex;
|
|
||||||
}
|
|
||||||
setCurrentItemState("hover state");
|
|
||||||
}
|
|
||||||
|
|
||||||
function upItem() {
|
|
||||||
setCurrentItemState("base state");
|
|
||||||
rowIndex = rowIndex - 3;
|
|
||||||
if (rowIndex < 0 ) {
|
|
||||||
rowIndex = (count - (count % 3));
|
|
||||||
var index = rowIndex + columnIndex;
|
|
||||||
if(index > count) {
|
|
||||||
rowIndex = rowIndex - 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCurrentItemState("hover state");
|
|
||||||
}
|
|
||||||
|
|
||||||
function downItem() {
|
|
||||||
setCurrentItemState("base state");
|
|
||||||
rowIndex = rowIndex + 3;
|
|
||||||
var index = rowIndex + columnIndex;
|
|
||||||
if (index > count ) {
|
|
||||||
rowIndex = 0;
|
|
||||||
}
|
|
||||||
setCurrentItemState("hover state");
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectItem() {
|
|
||||||
flowMain.children[rowIndex + columnIndex].clicked();
|
|
||||||
if (tabletRoot) {
|
|
||||||
tabletRoot.playButtonClickSound();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onRightPressed: nextItem();
|
|
||||||
Keys.onLeftPressed: previousItem();
|
|
||||||
Keys.onDownPressed: downItem();
|
|
||||||
Keys.onUpPressed: upItem();
|
|
||||||
Keys.onReturnPressed: selectItem();
|
|
||||||
}
|
|
|
@ -72,10 +72,14 @@ StackView {
|
||||||
Component { id: tabletWebView; TabletWebView {} }
|
Component { id: tabletWebView; TabletWebView {} }
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
updateLocationText(false);
|
updateLocationText(false);
|
||||||
addressLine.focus = !HMD.active;
|
|
||||||
root.parentChanged.connect(center);
|
root.parentChanged.connect(center);
|
||||||
center();
|
center();
|
||||||
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
|
||||||
|
Qt.callLater(function() {
|
||||||
|
addressBarDialog.keyboardEnabled = HMD.active;
|
||||||
|
addressLine.forceActiveFocus();
|
||||||
|
})
|
||||||
}
|
}
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
root.parentChanged.disconnect(center);
|
root.parentChanged.disconnect(center);
|
||||||
|
|
|
@ -23,11 +23,26 @@ Item {
|
||||||
property double sortOrder: 100
|
property double sortOrder: 100
|
||||||
property int stableOrder: 0
|
property int stableOrder: 0
|
||||||
property var tabletRoot;
|
property var tabletRoot;
|
||||||
|
property var flickable: null
|
||||||
|
property var gridView: null
|
||||||
|
|
||||||
|
property int buttonIndex: -1
|
||||||
|
|
||||||
width: 129
|
width: 129
|
||||||
height: 129
|
height: 129
|
||||||
|
|
||||||
signal clicked()
|
signal clicked()
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: flickable
|
||||||
|
onMovingChanged: {
|
||||||
|
//when flick/move started, and hover is on, clean hove state
|
||||||
|
if (flickable.moving && tabletButton.state.indexOf("hover") !== -1) {
|
||||||
|
tabletButton.state = (tabletButton.isActive) ? "active state" : "base state";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function changeProperty(key, value) {
|
function changeProperty(key, value) {
|
||||||
tabletButton[key] = value;
|
tabletButton[key] = value;
|
||||||
}
|
}
|
||||||
|
@ -121,9 +136,10 @@ Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
enabled: true
|
enabled: true
|
||||||
preventStealing: true
|
preventStealing: false
|
||||||
onClicked: {
|
onClicked: {
|
||||||
console.log("Tablet Button Clicked!");
|
gridView.currentIndex = buttonIndex
|
||||||
|
|
||||||
if (tabletButton.inDebugMode) {
|
if (tabletButton.inDebugMode) {
|
||||||
if (tabletButton.isActive) {
|
if (tabletButton.isActive) {
|
||||||
tabletButton.isActive = false;
|
tabletButton.isActive = false;
|
||||||
|
@ -131,14 +147,17 @@ Item {
|
||||||
tabletButton.isActive = true;
|
tabletButton.isActive = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tabletButton.clicked();
|
tabletButton.clicked();
|
||||||
if (tabletRoot) {
|
if (tabletRoot) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onEntered: {
|
onEntered: {
|
||||||
|
gridView.currentIndex = buttonIndex
|
||||||
tabletButton.isEntered = true;
|
tabletButton.isEntered = true;
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
|
|
||||||
if (tabletButton.isActive) {
|
if (tabletButton.isActive) {
|
||||||
tabletButton.state = "hover active state";
|
tabletButton.state = "hover active state";
|
||||||
|
|
296
interface/resources/qml/hifi/tablet/TabletHome.qml
Normal file
|
@ -0,0 +1,296 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
import TabletScriptingInterface 1.0
|
||||||
|
|
||||||
|
import "."
|
||||||
|
import "../../styles-uit"
|
||||||
|
import "../audio" as HifiAudio
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: tablet
|
||||||
|
objectName: "tablet"
|
||||||
|
property var tabletProxy: Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
|
||||||
|
property var currentGridItems: null
|
||||||
|
|
||||||
|
focus: true
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: bgTopBar
|
||||||
|
height: 90
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop {
|
||||||
|
position: 0
|
||||||
|
color: "#2b2b2b"
|
||||||
|
}
|
||||||
|
|
||||||
|
GradientStop {
|
||||||
|
position: 1
|
||||||
|
color: "#1e1e1e"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiAudio.MicBar {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: 30
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: 150
|
||||||
|
height: 50
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 30
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
RalewaySemiBold {
|
||||||
|
text: Account.loggedIn ? qsTr("Log out") : qsTr("Log in")
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
anchors.right: parent.right
|
||||||
|
font.pixelSize: 20
|
||||||
|
color: "#afafaf"
|
||||||
|
}
|
||||||
|
|
||||||
|
RalewaySemiBold {
|
||||||
|
visible: Account.loggedIn
|
||||||
|
height: Account.loggedIn ? parent.height/2 - parent.spacing/2 : 0
|
||||||
|
text: Account.loggedIn ? "[" + tabletRoot.usernameShort + "]" : ""
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
anchors.right: parent.right
|
||||||
|
font.pixelSize: 20
|
||||||
|
color: "#afafaf"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
if (!Account.loggedIn) {
|
||||||
|
DialogsManager.showLoginDialog()
|
||||||
|
} else {
|
||||||
|
Account.logOut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: bgMain
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop {
|
||||||
|
position: 0
|
||||||
|
color: "#2b2b2b"
|
||||||
|
}
|
||||||
|
|
||||||
|
GradientStop {
|
||||||
|
position: 1
|
||||||
|
color: "#0f212e"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: bgTopBar.bottom
|
||||||
|
|
||||||
|
SwipeView {
|
||||||
|
id: swipeView
|
||||||
|
clip: false
|
||||||
|
currentIndex: -1
|
||||||
|
property int previousIndex: -1
|
||||||
|
Repeater {
|
||||||
|
id: pageRepeater
|
||||||
|
model: Math.ceil(tabletProxy.buttons.rowCount() / TabletEnums.ButtonsOnPage)
|
||||||
|
onItemAdded: {
|
||||||
|
item.proxyModel.sourceModel = tabletProxy.buttons;
|
||||||
|
item.proxyModel.pageIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate: Item {
|
||||||
|
id: page
|
||||||
|
property TabletButtonsProxyModel proxyModel: TabletButtonsProxyModel {}
|
||||||
|
|
||||||
|
GridView {
|
||||||
|
id: gridView
|
||||||
|
keyNavigationEnabled: false
|
||||||
|
highlightFollowsCurrentItem: false
|
||||||
|
property int previousGridIndex: -1
|
||||||
|
anchors {
|
||||||
|
fill: parent
|
||||||
|
topMargin: 20
|
||||||
|
leftMargin: 30
|
||||||
|
rightMargin: 30
|
||||||
|
bottomMargin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function setButtonState(buttonIndex, buttonstate) {
|
||||||
|
if (buttonIndex < 0 || gridView.contentItem === undefined
|
||||||
|
|| gridView.contentItem.children.length - 1 < buttonIndex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var itemat = gridView.contentItem.children[buttonIndex].children[0];
|
||||||
|
if (itemat.isActive) {
|
||||||
|
itemat.state = "active state";
|
||||||
|
} else {
|
||||||
|
itemat.state = buttonstate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onCurrentIndexChanged: {
|
||||||
|
setButtonState(previousGridIndex, "base state");
|
||||||
|
setButtonState(currentIndex, "hover state");
|
||||||
|
previousGridIndex = currentIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
cellWidth: width/3
|
||||||
|
cellHeight: cellWidth
|
||||||
|
flow: GridView.LeftToRight
|
||||||
|
model: page.proxyModel
|
||||||
|
|
||||||
|
delegate: Item {
|
||||||
|
id: wrapper
|
||||||
|
width: gridView.cellWidth
|
||||||
|
height: gridView.cellHeight
|
||||||
|
|
||||||
|
property var proxy: modelData
|
||||||
|
|
||||||
|
TabletButton {
|
||||||
|
id: tabletButton
|
||||||
|
anchors.centerIn: parent
|
||||||
|
gridView: wrapper.GridView.view
|
||||||
|
buttonIndex: page.proxyModel.buttonIndex(uuid);
|
||||||
|
flickable: swipeView.contentItem;
|
||||||
|
onClicked: modelData.clicked()
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: modelData;
|
||||||
|
onPropertiesChanged: {
|
||||||
|
updateProperties();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: updateProperties()
|
||||||
|
|
||||||
|
function updateProperties() {
|
||||||
|
var keys = Object.keys(modelData.properties).forEach(function (key) {
|
||||||
|
if (tabletButton[key] !== modelData.properties[key]) {
|
||||||
|
tabletButton[key] = modelData.properties[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onCurrentIndexChanged: {
|
||||||
|
if (swipeView.currentIndex < 0
|
||||||
|
|| swipeView.itemAt(swipeView.currentIndex) === null
|
||||||
|
|| swipeView.itemAt(swipeView.currentIndex).children[0] === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentGridItems = swipeView.itemAt(swipeView.currentIndex).children[0];
|
||||||
|
|
||||||
|
currentGridItems.currentIndex = (previousIndex > swipeView.currentIndex ? currentGridItems.count - 1 : 0);
|
||||||
|
previousIndex = currentIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
hoverEnabled: true
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
top: parent.top
|
||||||
|
bottom: pageIndicator.top
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PageIndicator {
|
||||||
|
id: pageIndicator
|
||||||
|
currentIndex: swipeView.currentIndex
|
||||||
|
|
||||||
|
delegate: Item {
|
||||||
|
width: 15
|
||||||
|
height: 15
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
opacity: index === pageIndicator.currentIndex ? 0.95 : 0.45
|
||||||
|
implicitWidth: index === pageIndicator.currentIndex ? 15 : 10
|
||||||
|
implicitHeight: implicitWidth
|
||||||
|
radius: width/2
|
||||||
|
color: "white"
|
||||||
|
Behavior on opacity {
|
||||||
|
OpacityAnimator {
|
||||||
|
duration: 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interactive: false
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
count: swipeView.count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
focus = true;
|
||||||
|
forceActiveFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onRightPressed: {
|
||||||
|
if (!currentGridItems) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var index = currentGridItems.currentIndex;
|
||||||
|
currentGridItems.moveCurrentIndexRight();
|
||||||
|
if (index === currentGridItems.count - 1 && index === currentGridItems.currentIndex) {
|
||||||
|
if (swipeView.currentIndex < swipeView.count - 1) {
|
||||||
|
swipeView.incrementCurrentIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onLeftPressed: {
|
||||||
|
if (!currentGridItems) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var index = currentGridItems.currentIndex;
|
||||||
|
currentGridItems.moveCurrentIndexLeft();
|
||||||
|
if (index === 0 && index === currentGridItems.currentIndex) {
|
||||||
|
if (swipeView.currentIndex > 0) {
|
||||||
|
swipeView.decrementCurrentIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Keys.onDownPressed: currentGridItems.moveCurrentIndexDown();
|
||||||
|
Keys.onUpPressed: currentGridItems.moveCurrentIndexUp();
|
||||||
|
Keys.onReturnPressed: {
|
||||||
|
if (currentGridItems.currentItem) {
|
||||||
|
currentGridItems.currentItem.proxy.clicked();
|
||||||
|
if (tabletRoot) {
|
||||||
|
tabletRoot.playButtonClickSound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,11 +48,15 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
function pushSource(path) {
|
function pushSource(path) {
|
||||||
d.push(Qt.resolvedUrl(path));
|
d.push(Qt.resolvedUrl("../../" + path));
|
||||||
d.currentItem.sendToScript.connect(tabletMenu.sendToScript);
|
if (d.currentItem.sendToScript !== undefined) {
|
||||||
|
d.currentItem.sendToScript.connect(tabletMenu.sendToScript);
|
||||||
|
}
|
||||||
d.currentItem.focus = true;
|
d.currentItem.focus = true;
|
||||||
d.currentItem.forceActiveFocus();
|
d.currentItem.forceActiveFocus();
|
||||||
breadcrumbText.text = d.currentItem.title;
|
if (d.currentItem.title !== undefined) {
|
||||||
|
breadcrumbText.text = d.currentItem.title;
|
||||||
|
}
|
||||||
if (typeof bgNavBar !== "undefined") {
|
if (typeof bgNavBar !== "undefined") {
|
||||||
d.currentItem.y = bgNavBar.height;
|
d.currentItem.y = bgNavBar.height;
|
||||||
d.currentItem.height -= bgNavBar.height;
|
d.currentItem.height -= bgNavBar.height;
|
||||||
|
|
|
@ -77,12 +77,12 @@ FocusScope {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: {
|
onEntered: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
listView.currentIndex = index
|
listView.currentIndex = index
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
root.selected(item);
|
root.selected(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,37 +68,36 @@ Item {
|
||||||
|
|
||||||
function loadSource(url) {
|
function loadSource(url) {
|
||||||
tabletApps.clear();
|
tabletApps.clear();
|
||||||
loader.source = ""; // make sure we load the qml fresh each time.
|
|
||||||
loader.source = url;
|
|
||||||
tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""});
|
tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""});
|
||||||
|
loader.load(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadQMLOnTop(url) {
|
function loadQMLOnTop(url) {
|
||||||
tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""});
|
tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""});
|
||||||
loader.source = "";
|
loader.load(tabletApps.get(currentApp).appUrl, function(){
|
||||||
loader.source = tabletApps.get(currentApp).appUrl;
|
if (loader.item.hasOwnProperty("gotoPreviousApp")) {
|
||||||
if (loader.item.hasOwnProperty("gotoPreviousApp")) {
|
loader.item.gotoPreviousApp = true;
|
||||||
loader.item.gotoPreviousApp = true;
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadWebOnTop(url, injectJavaScriptUrl) {
|
function loadWebContent(source, url, injectJavaScriptUrl) {
|
||||||
tabletApps.append({"appUrl": loader.source, "isWebUrl": true, "scriptUrl": injectJavaScriptUrl, "appWebUrl": url});
|
tabletApps.append({"appUrl": source, "isWebUrl": true, "scriptUrl": injectJavaScriptUrl, "appWebUrl": url});
|
||||||
loader.item.url = tabletApps.get(currentApp).appWebUrl;
|
loader.load(source, function() {
|
||||||
loader.item.scriptUrl = tabletApps.get(currentApp).scriptUrl;
|
loader.item.scriptURL = injectJavaScriptUrl;
|
||||||
if (loader.item.hasOwnProperty("gotoPreviousApp")) {
|
loader.item.url = url;
|
||||||
loader.item.gotoPreviousApp = true;
|
if (loader.item.hasOwnProperty("gotoPreviousApp")) {
|
||||||
}
|
loader.item.gotoPreviousApp = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadWebBase() {
|
function loadWebBase(url, injectJavaScriptUrl) {
|
||||||
loader.source = "";
|
loadWebContent("hifi/tablet/TabletWebView.qml", url, injectJavaScriptUrl);
|
||||||
loader.source = "TabletWebView.qml";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadTabletWebBase() {
|
function loadTabletWebBase(url, injectJavaScriptUrl) {
|
||||||
loader.source = "";
|
loadWebContent("hifi/tablet/BlocksWebView.qml", url, injectJavaScriptUrl);
|
||||||
loader.source = "./BlocksWebView.qml";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function returnToPreviousApp() {
|
function returnToPreviousApp() {
|
||||||
|
@ -110,7 +109,7 @@ Item {
|
||||||
loadSource("TabletWebView.qml");
|
loadSource("TabletWebView.qml");
|
||||||
loadWebUrl(webUrl, scriptUrl);
|
loadWebUrl(webUrl, scriptUrl);
|
||||||
} else {
|
} else {
|
||||||
loader.source = tabletApps.get(currentApp).appUrl;
|
loader.load(tabletApps.get(currentApp).appUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,47 +172,79 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
// Hook up callback for clara.io download from the marketplace.
|
||||||
id: loader
|
Connections {
|
||||||
objectName: "loader"
|
id: eventBridgeConnection
|
||||||
asynchronous: false
|
target: eventBridge
|
||||||
|
onWebEventReceived: {
|
||||||
width: parent.width
|
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
|
||||||
height: parent.height
|
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
|
||||||
|
|
||||||
// Hook up callback for clara.io download from the marketplace.
|
|
||||||
Connections {
|
|
||||||
id: eventBridgeConnection
|
|
||||||
target: eventBridge
|
|
||||||
onWebEventReceived: {
|
|
||||||
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
|
|
||||||
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoaded: {
|
|
||||||
if (loader.item.hasOwnProperty("sendToScript")) {
|
|
||||||
loader.item.sendToScript.connect(tabletRoot.sendToScript);
|
|
||||||
}
|
|
||||||
if (loader.item.hasOwnProperty("setRootMenu")) {
|
|
||||||
loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu);
|
|
||||||
}
|
|
||||||
loader.item.forceActiveFocus();
|
|
||||||
|
|
||||||
if (openModal) {
|
|
||||||
openModal.canceled();
|
|
||||||
openModal.destroy();
|
|
||||||
openModal = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (openBrowser) {
|
|
||||||
openBrowser.destroy();
|
|
||||||
openBrowser = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: loader
|
||||||
|
objectName: "loader";
|
||||||
|
anchors.fill: parent;
|
||||||
|
property string source: "";
|
||||||
|
property var item: null;
|
||||||
|
signal loaded;
|
||||||
|
|
||||||
|
onWidthChanged: {
|
||||||
|
if (loader.item) {
|
||||||
|
loader.item.width = loader.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onHeightChanged: {
|
||||||
|
if (loader.item) {
|
||||||
|
loader.item.height = loader.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function load(newSource, callback) {
|
||||||
|
if (loader.source == newSource) {
|
||||||
|
loader.loaded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loader.item) {
|
||||||
|
loader.item.destroy();
|
||||||
|
loader.item = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlSurface.load(newSource, loader, function(newItem) {
|
||||||
|
loader.item = newItem;
|
||||||
|
loader.item.width = loader.width;
|
||||||
|
loader.item.height = loader.height;
|
||||||
|
loader.loaded();
|
||||||
|
if (loader.item.hasOwnProperty("sendToScript")) {
|
||||||
|
loader.item.sendToScript.connect(tabletRoot.sendToScript);
|
||||||
|
}
|
||||||
|
if (loader.item.hasOwnProperty("setRootMenu")) {
|
||||||
|
loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu);
|
||||||
|
}
|
||||||
|
loader.item.forceActiveFocus();
|
||||||
|
|
||||||
|
if (openModal) {
|
||||||
|
openModal.canceled();
|
||||||
|
openModal.destroy();
|
||||||
|
openModal = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openBrowser) {
|
||||||
|
openBrowser.destroy();
|
||||||
|
openBrowser = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
width: 480
|
width: 480
|
||||||
height: 706
|
height: 706
|
||||||
|
|
||||||
|
|
|
@ -59,26 +59,25 @@ Windows.ScrollingWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadSource(url) {
|
function loadSource(url) {
|
||||||
loader.source = ""; // make sure we load the qml fresh each time.
|
loader.load(url)
|
||||||
loader.source = url;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadWebBase() {
|
function loadWebContent(source, url, injectJavaScriptUrl) {
|
||||||
loader.source = "";
|
loader.load(source, function() {
|
||||||
loader.source = "WindowWebView.qml";
|
loader.item.scriptURL = injectJavaScriptUrl;
|
||||||
|
loader.item.url = url;
|
||||||
|
if (loader.item.hasOwnProperty("closeButtonVisible")) {
|
||||||
|
loader.item.closeButtonVisible = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadTabletWebBase() {
|
function loadWebBase(url, injectJavaScriptUrl) {
|
||||||
loader.source = "";
|
loadWebContent("hifi/tablet/TabletWebView.qml", url, injectJavaScriptUrl);
|
||||||
loader.source = "./BlocksWebView.qml";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadWebUrl(url, injectedJavaScriptUrl) {
|
function loadTabletWebBase(url, injectJavaScriptUrl) {
|
||||||
loader.item.url = url;
|
loadWebContent("hifi/tablet/BlocksWebView.qml", url, injectJavaScriptUrl);
|
||||||
loader.item.scriptURL = injectedJavaScriptUrl;
|
|
||||||
if (loader.item.hasOwnProperty("closeButtonVisible")) {
|
|
||||||
loader.item.closeButtonVisible = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// used to send a message from qml to interface script.
|
// used to send a message from qml to interface script.
|
||||||
|
@ -111,38 +110,68 @@ Windows.ScrollingWindow {
|
||||||
username = newUsername;
|
username = newUsername;
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
// Hook up callback for clara.io download from the marketplace.
|
||||||
|
Connections {
|
||||||
|
id: eventBridgeConnection
|
||||||
|
target: eventBridge
|
||||||
|
onWebEventReceived: {
|
||||||
|
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
|
||||||
|
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
id: loader
|
id: loader
|
||||||
objectName: "loader"
|
objectName: "loader";
|
||||||
asynchronous: false
|
property string source: "";
|
||||||
|
property var item: null;
|
||||||
|
|
||||||
height: pane.scrollHeight
|
height: pane.scrollHeight
|
||||||
width: pane.contentWidth
|
width: pane.contentWidth
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
signal loaded;
|
||||||
// Hook up callback for clara.io download from the marketplace.
|
|
||||||
Connections {
|
onWidthChanged: {
|
||||||
id: eventBridgeConnection
|
if (loader.item) {
|
||||||
target: eventBridge
|
loader.item.width = loader.width;
|
||||||
onWebEventReceived: {
|
|
||||||
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
|
|
||||||
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoaded: {
|
onHeightChanged: {
|
||||||
if (loader.item.hasOwnProperty("sendToScript")) {
|
if (loader.item) {
|
||||||
loader.item.sendToScript.connect(tabletRoot.sendToScript);
|
loader.item.height = loader.height;
|
||||||
}
|
}
|
||||||
if (loader.item.hasOwnProperty("setRootMenu")) {
|
}
|
||||||
loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu);
|
|
||||||
|
function load(newSource, callback) {
|
||||||
|
if (loader.item) {
|
||||||
|
loader.item.destroy();
|
||||||
|
loader.item = null;
|
||||||
}
|
}
|
||||||
loader.item.forceActiveFocus();
|
|
||||||
|
QmlSurface.load(newSource, loader, function(newItem) {
|
||||||
|
loader.item = newItem;
|
||||||
|
loader.item.width = loader.width;
|
||||||
|
loader.item.height = loader.height;
|
||||||
|
loader.loaded();
|
||||||
|
if (loader.item.hasOwnProperty("sendToScript")) {
|
||||||
|
loader.item.sendToScript.connect(tabletRoot.sendToScript);
|
||||||
|
}
|
||||||
|
if (loader.item.hasOwnProperty("setRootMenu")) {
|
||||||
|
loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu);
|
||||||
|
}
|
||||||
|
loader.item.forceActiveFocus();
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
implicitWidth: 480
|
implicitWidth: 480
|
||||||
implicitHeight: 706
|
implicitHeight: 706
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ Window {
|
||||||
horizontalSpacers: horizontal
|
horizontalSpacers: horizontal
|
||||||
verticalSpacers: !horizontal
|
verticalSpacers: !horizontal
|
||||||
}
|
}
|
||||||
|
property var tabletProxy;
|
||||||
|
property var buttonModel: ListModel {}
|
||||||
hideBackground: true
|
hideBackground: true
|
||||||
resizable: false
|
resizable: false
|
||||||
destroyOnCloseButton: false
|
destroyOnCloseButton: false
|
||||||
|
@ -23,24 +25,32 @@ Window {
|
||||||
activator: Item {}
|
activator: Item {}
|
||||||
property bool horizontal: true
|
property bool horizontal: true
|
||||||
property real buttonSize: 50;
|
property real buttonSize: 50;
|
||||||
property var buttons: []
|
|
||||||
property var container: horizontal ? row : column
|
|
||||||
|
|
||||||
Settings {
|
Settings {
|
||||||
category: "toolbar/" + window.objectName
|
category: "toolbar/" + window.objectName
|
||||||
property alias x: window.x
|
property alias x: window.x
|
||||||
property alias y: window.y
|
property alias y: window.y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: buttonComponent
|
||||||
|
ToolbarButton {
|
||||||
|
id: toolbarButton
|
||||||
|
property var proxy: modelData;
|
||||||
|
onClicked: proxy.clicked()
|
||||||
|
Component.onCompleted: updateProperties()
|
||||||
|
|
||||||
onHorizontalChanged: {
|
Connections {
|
||||||
var newParent = horizontal ? row : column;
|
target: proxy;
|
||||||
for (var i in buttons) {
|
onPropertiesChanged: updateProperties();
|
||||||
var child = buttons[i];
|
}
|
||||||
child.parent = newParent;
|
|
||||||
if (horizontal) {
|
function updateProperties() {
|
||||||
child.y = 0
|
Object.keys(proxy.properties).forEach(function (key) {
|
||||||
} else {
|
if (toolbarButton[key] !== proxy.properties[key]) {
|
||||||
child.x = 0
|
toolbarButton[key] = proxy.properties[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,97 +62,22 @@ Window {
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: row
|
id: row
|
||||||
|
visible: window.horizontal
|
||||||
spacing: 6
|
spacing: 6
|
||||||
|
Repeater {
|
||||||
|
model: buttonModel
|
||||||
|
delegate: buttonComponent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: column
|
id: column
|
||||||
|
visible: !window.horizontal
|
||||||
spacing: 6
|
spacing: 6
|
||||||
}
|
Repeater {
|
||||||
|
model: buttonModel
|
||||||
Component { id: toolbarButtonBuilder; ToolbarButton { } }
|
delegate: buttonComponent
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function findButtonIndex(name) {
|
|
||||||
if (!name) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i in buttons) {
|
|
||||||
var child = buttons[i];
|
|
||||||
if (child.objectName === name) {
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findButton(name) {
|
|
||||||
var index = findButtonIndex(name);
|
|
||||||
if (index < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return buttons[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortButtons() {
|
|
||||||
var children = [];
|
|
||||||
for (var i = 0; i < container.children.length; i++) {
|
|
||||||
children[i] = container.children[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
children.sort(function (a, b) {
|
|
||||||
if (a.sortOrder === b.sortOrder) {
|
|
||||||
// subsort by stableOrder, because JS sort is not stable in qml.
|
|
||||||
return a.stableOrder - b.stableOrder;
|
|
||||||
} else {
|
|
||||||
return a.sortOrder - b.sortOrder;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
container.children = children;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addButton(properties) {
|
|
||||||
properties = properties || {}
|
|
||||||
|
|
||||||
// If a name is specified, then check if there's an existing button with that name
|
|
||||||
// and return it if so. This will allow multiple clients to listen to a single button,
|
|
||||||
// and allow scripts to be idempotent so they don't duplicate buttons if they're reloaded
|
|
||||||
var result = findButton(properties.objectName);
|
|
||||||
if (result) {
|
|
||||||
for (var property in properties) {
|
|
||||||
result[property] = properties[property];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
properties.toolbar = this;
|
|
||||||
properties.opacity = 0;
|
|
||||||
result = toolbarButtonBuilder.createObject(container, properties);
|
|
||||||
buttons.push(result);
|
|
||||||
|
|
||||||
result.opacity = 1;
|
|
||||||
|
|
||||||
sortButtons();
|
|
||||||
|
|
||||||
fadeIn(null);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeButton(name) {
|
|
||||||
var index = findButtonIndex(name);
|
|
||||||
if (index < -1) {
|
|
||||||
console.warn("Tried to remove non-existent button " + name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
buttons[index].destroy();
|
|
||||||
buttons.splice(index, 1);
|
|
||||||
|
|
||||||
if (buttons.length === 0) {
|
|
||||||
fadeOut(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,8 @@ StateImage {
|
||||||
property string activeHoverIcon: button.activeIcon
|
property string activeHoverIcon: button.activeIcon
|
||||||
|
|
||||||
property int sortOrder: 100
|
property int sortOrder: 100
|
||||||
property int stableSortOrder: 0
|
property int stableOrder: 0
|
||||||
|
property var uuid;
|
||||||
|
|
||||||
signal clicked()
|
signal clicked()
|
||||||
|
|
||||||
|
|
BIN
interface/resources/styles/filter.png
Normal file
After Width: | Height: | Size: 244 B |
|
@ -67,8 +67,22 @@ QPushButton#revealLogButton {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPushButton#showAllButton {
|
||||||
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
|
background-color: #333333;
|
||||||
|
color: #BBBBBB;
|
||||||
|
border-width: 0;
|
||||||
|
border-radius: 9px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
QCheckBox {
|
QCheckBox {
|
||||||
font-family: Helvetica, Arial, sans-serif;
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
color: #3d3d3d;
|
||||||
|
border-width: 0;
|
||||||
|
border-radius: 9px;
|
||||||
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
QCheckBox::indicator:unchecked {
|
QCheckBox::indicator:unchecked {
|
||||||
|
@ -77,4 +91,25 @@ QCheckBox::indicator:unchecked {
|
||||||
|
|
||||||
QCheckBox::indicator:checked {
|
QCheckBox::indicator:checked {
|
||||||
image: url(styles/checked.svg);
|
image: url(styles/checked.svg);
|
||||||
|
}
|
||||||
|
|
||||||
|
QComboBox {
|
||||||
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #CCCCCC;
|
||||||
|
color: #3d3d3d;
|
||||||
|
border-width: 0;
|
||||||
|
border-radius: 9px;
|
||||||
|
font-size: 11px;
|
||||||
|
padding-left: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QComboBox::drop-down {
|
||||||
|
border-width: 0px;
|
||||||
|
padding-right: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QComboBox::down-arrow {
|
||||||
|
image: url(styles/filter.png);
|
||||||
|
border-width: 0px;
|
||||||
}
|
}
|