mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-29 18:22:55 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into hackathonLightening
This commit is contained in:
commit
3f85daf276
205 changed files with 5029 additions and 2081 deletions
assignment-client/src/octree
cmake
macros
modules
domain-server
resources/web/settings/js
src
examples
ice-server
interface
CMakeLists.txt
resources
fonts
qml
controls-uit
Button.qmlCheckBox.qmlComboBox.qmlContentSection.qmlLabel.qmlSlider.qmlSpinBox.qmlStaticSection.qmlTextField.qmlTree.qmlVerticalSpacer.qml
dialogs
PreferencesDialog.qml
preferences
hifi/dialogs
AudioPreferencesDialog.qmlAvatarPreferencesDialog.qmlGeneralPreferencesDialog.qmlGraphicsPreferencesDialog.qmlLodPreferencesDialog.qmlRunningScripts.qml
styles-uit
windows-uit
src
Application.cppApplication.hCrashHandler.cppCrashHandler.hMainWindow.cppMainWindow.hModelPackager.cpp
scripting
ui
PreferencesDialog.cpp
overlays
Base3DOverlay.cppBase3DOverlay.hBillboard3DOverlay.cppBillboard3DOverlay.hBillboardable.cppBillboardable.hCircle3DOverlay.cppCircle3DOverlay.hCube3DOverlay.cppCube3DOverlay.hGrid3DOverlay.cppGrid3DOverlay.hImage3DOverlay.cppImage3DOverlay.hLine3DOverlay.cppLine3DOverlay.hModelOverlay.cppModelOverlay.hOverlay.cppOverlay.hOverlay2D.cppOverlay2D.hOverlayPanel.cppOverlayPanel.hOverlays.cppOverlays.hOverlaysPayload.cppPanelAttachable.cppPanelAttachable.hPlanar3DOverlay.cppPlanar3DOverlay.hQmlOverlay.cppQmlOverlay.hRectangle3DOverlay.cppRectangle3DOverlay.hText3DOverlay.cppText3DOverlay.hVolume3DOverlay.cppVolume3DOverlay.h
|
@ -236,10 +236,6 @@ OctreeServer::OctreeServer(ReceivedMessage& message) :
|
|||
{
|
||||
_averageLoopTime.updateAverage(0);
|
||||
qDebug() << "Octree server starting... [" << this << "]";
|
||||
|
||||
// make sure the AccountManager has an Auth URL for payment redemptions
|
||||
|
||||
AccountManager::getInstance().setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL);
|
||||
}
|
||||
|
||||
OctreeServer::~OctreeServer() {
|
||||
|
|
|
@ -64,11 +64,10 @@ macro(install_beside_console)
|
|||
)
|
||||
endif()
|
||||
|
||||
# set variables used by manual ssleay library copy
|
||||
set(TARGET_INSTALL_DIR ${COMPONENT_INSTALL_DIR})
|
||||
set(TARGET_INSTALL_COMPONENT ${SERVER_COMPONENT})
|
||||
manually_install_openssl_for_qt()
|
||||
|
||||
endif ()
|
||||
|
||||
# set variables used by manual ssleay library copy
|
||||
set(TARGET_INSTALL_DIR ${COMPONENT_INSTALL_DIR})
|
||||
set(TARGET_INSTALL_COMPONENT ${SERVER_COMPONENT})
|
||||
manually_install_ssl_eay()
|
||||
|
||||
endmacro()
|
||||
|
|
34
cmake/macros/ManuallyInstallOpenSSLForQt.cmake
Normal file
34
cmake/macros/ManuallyInstallOpenSSLForQt.cmake
Normal file
|
@ -0,0 +1,34 @@
|
|||
#
|
||||
# ManuallyInstallOpenSSLforQt.cmake
|
||||
#
|
||||
# Created by Stephen Birarda on 1/15/16.
|
||||
# Copyright 2014 High Fidelity, Inc.
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
macro(manually_install_openssl_for_qt)
|
||||
|
||||
# Qt dynamically links OpenSSL if it can find it on the user's machine
|
||||
# We want to avoid it being found somewhere random and have it not being a compatible version
|
||||
# So even though we don't need the dynamic version of OpenSSL for our direct-use purposes
|
||||
# we use this macro to include the two SSL DLLs with the targets using QtNetwork
|
||||
if (WIN32)
|
||||
# we have to call find_package(OpenSSL) here even though this target may not directly need it
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
install(
|
||||
FILES "${OPENSSL_DLL_PATH}/ssleay32.dll"
|
||||
DESTINATION ${TARGET_INSTALL_DIR}
|
||||
COMPONENT ${TARGET_INSTALL_COMPONENT}
|
||||
)
|
||||
|
||||
install(
|
||||
FILES "${OPENSSL_DLL_PATH}/libeay32.dll"
|
||||
DESTINATION ${TARGET_INSTALL_DIR}
|
||||
COMPONENT ${TARGET_INSTALL_COMPONENT}
|
||||
)
|
||||
endif()
|
||||
|
||||
endmacro()
|
|
@ -1,28 +0,0 @@
|
|||
#
|
||||
# ManuallyInstallSSLEay.cmake
|
||||
#
|
||||
# Created by Stephen Birarda on 1/15/16.
|
||||
# Copyright 2014 High Fidelity, Inc.
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
macro(manually_install_ssl_eay)
|
||||
|
||||
# on windows we have had issues with targets missing ssleay library
|
||||
# not convinced we actually need it (I assume it would show up in the dependency tree)
|
||||
# but to be safe we install it manually beside the current target
|
||||
if (WIN32)
|
||||
# we need to find SSL_EAY_LIBRARY_* so we can install it beside this target
|
||||
# so we have to call find_package(OpenSSL) here even though this target may not specifically need it
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
install(
|
||||
FILES "${OPENSSL_DLL_PATH}/ssleay32.dll"
|
||||
DESTINATION ${TARGET_INSTALL_DIR}
|
||||
COMPONENT ${TARGET_INSTALL_COMPONENT}
|
||||
)
|
||||
endif()
|
||||
|
||||
endmacro()
|
|
@ -67,10 +67,7 @@ find_path(OPENSSL_INCLUDE_DIR NAMES openssl/ssl.h HINTS ${_OPENSSL_ROOT_HINTS_AN
|
|||
|
||||
if (WIN32 AND NOT CYGWIN)
|
||||
if (MSVC)
|
||||
# /MD and /MDd are the standard values - if someone wants to use
|
||||
# others, the libnames have to change here too
|
||||
# use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b
|
||||
# TODO: handle /MT and static lib
|
||||
|
||||
# In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix:
|
||||
# * MD for dynamic-release
|
||||
# * MDd for dynamic-debug
|
||||
|
@ -81,20 +78,23 @@ if (WIN32 AND NOT CYGWIN)
|
|||
# We are using the libraries located in the VC subdir instead of the parent directory eventhough :
|
||||
# libeay32MD.lib is identical to ../libeay32.lib, and
|
||||
# ssleay32MD.lib is identical to ../ssleay32.lib
|
||||
find_library(LIB_EAY_DEBUG NAMES libeay32MDd libeay32d
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib" "VC" "lib/VC"
|
||||
|
||||
# The Kitware FindOpenSSL module has been modified here by High Fidelity to look specifically for static libraries
|
||||
|
||||
find_library(LIB_EAY_DEBUG NAMES libeay32MTd
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib/VC/static"
|
||||
)
|
||||
|
||||
find_library(LIB_EAY_RELEASE NAMES libeay32MD libeay32
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib" "VC" "lib/VC"
|
||||
find_library(LIB_EAY_RELEASE NAMES libeay32MT
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib/VC/static"
|
||||
)
|
||||
|
||||
find_library(SSL_EAY_DEBUG NAMES ssleay32MDd ssleay32d
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib" "VC" "lib/VC"
|
||||
find_library(SSL_EAY_DEBUG NAMES ssleay32MTd
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib/VC/static"
|
||||
)
|
||||
|
||||
find_library(SSL_EAY_RELEASE NAMES ssleay32MD ssleay32 ssl
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib" "VC" "lib/VC"
|
||||
find_library(SSL_EAY_RELEASE NAMES ssleay32MT
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib/VC/static"
|
||||
)
|
||||
|
||||
set(LIB_EAY_LIBRARY_DEBUG "${LIB_EAY_DEBUG}")
|
||||
|
@ -109,37 +109,6 @@ if (WIN32 AND NOT CYGWIN)
|
|||
set(OPENSSL_LIBRARIES ${SSL_EAY_LIBRARY} ${LIB_EAY_LIBRARY})
|
||||
|
||||
find_path(OPENSSL_DLL_PATH NAMES ssleay32.dll PATH_SUFFIXES "bin" ${_OPENSSL_ROOT_HINTS_AND_PATHS})
|
||||
|
||||
elseif (MINGW)
|
||||
# same player, for MinGW
|
||||
set(LIB_EAY_NAMES libeay32)
|
||||
set(SSL_EAY_NAMES ssleay32)
|
||||
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
list(APPEND LIB_EAY_NAMES crypto)
|
||||
list(APPEND SSL_EAY_NAMES ssl)
|
||||
endif ()
|
||||
|
||||
find_library(LIB_EAY NAMES ${LIB_EAY_NAMES}
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib" "lib/MinGW"
|
||||
)
|
||||
|
||||
find_library(SSL_EAY NAMES ${SSL_EAY_NAMES}
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib" "lib/MinGW"
|
||||
)
|
||||
|
||||
mark_as_advanced(SSL_EAY LIB_EAY)
|
||||
set(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY})
|
||||
unset(LIB_EAY_NAMES)
|
||||
unset(SSL_EAY_NAMES)
|
||||
else ()
|
||||
# Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
|
||||
find_library(LIB_EAY NAMES libeay32 HINTS ${_OPENSSL_ROOT_HINTS_AND_PATHS} ${_OPENSSL_LIBDIR} PATH_SUFFIXES lib)
|
||||
|
||||
find_library(SSL_EAY NAMES ssleay32 HINTS ${_OPENSSL_ROOT_HINTS_AND_PATHS} ${_OPENSSL_LIBDIR} PATH_SUFFIXES lib)
|
||||
|
||||
mark_as_advanced(SSL_EAY LIB_EAY)
|
||||
set(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY})
|
||||
endif()
|
||||
else()
|
||||
|
||||
|
@ -250,8 +219,4 @@ else ()
|
|||
)
|
||||
endif ()
|
||||
|
||||
if (WIN32)
|
||||
add_paths_to_fixup_libs(${OPENSSL_DLL_PATH})
|
||||
endif ()
|
||||
|
||||
mark_as_advanced(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES OPENSSL_SEARCH_DIRS)
|
||||
|
|
|
@ -778,7 +778,7 @@ function chooseFromHighFidelityDomains(clickedButton) {
|
|||
function createTemporaryDomain() {
|
||||
swal({
|
||||
title: 'Create temporary place name',
|
||||
text: "This will create a temporary place name and domain ID (valid for 30 days)"
|
||||
text: "This will create a temporary place name and domain ID"
|
||||
+ " so other users can easily connect to your domain.</br></br>"
|
||||
+ "In order to make your domain reachable, this will also enable full automatic networking.",
|
||||
showCancelButton: true,
|
||||
|
|
|
@ -258,9 +258,26 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
|
|||
if (onlyEditorsAreRezzers) {
|
||||
canRez = isAllowedEditor;
|
||||
}
|
||||
|
||||
QUuid hintNodeID;
|
||||
|
||||
// in case this is a node that's failing to connect
|
||||
// double check we don't have a node whose sockets match exactly already in the list
|
||||
limitedNodeList->eachNodeBreakable([&nodeConnection, &hintNodeID](const SharedNodePointer& node){
|
||||
if (node->getPublicSocket() == nodeConnection.publicSockAddr
|
||||
&& node->getLocalSocket() == nodeConnection.localSockAddr) {
|
||||
// we have a node that already has these exact sockets - this occurs if a node
|
||||
// is unable to connect to the domain
|
||||
hintNodeID = node->getUUID();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// add the new node
|
||||
SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection);
|
||||
// add the connecting node (or re-use the matched one from eachNodeBreakable above)
|
||||
SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection, hintNodeID);
|
||||
|
||||
// set the edit rights for this user
|
||||
newNode->setIsAllowedEditor(isAllowedEditor);
|
||||
|
@ -279,28 +296,29 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
|
|||
return newNode;
|
||||
}
|
||||
|
||||
SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection) {
|
||||
SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection,
|
||||
QUuid nodeID) {
|
||||
HifiSockAddr discoveredSocket = nodeConnection.senderSockAddr;
|
||||
SharedNetworkPeer connectedPeer = _icePeers.value(nodeConnection.connectUUID);
|
||||
|
||||
QUuid nodeUUID;
|
||||
|
||||
if (connectedPeer) {
|
||||
// this user negotiated a connection with us via ICE, so re-use their ICE client ID
|
||||
nodeUUID = nodeConnection.connectUUID;
|
||||
nodeID = nodeConnection.connectUUID;
|
||||
|
||||
if (connectedPeer->getActiveSocket()) {
|
||||
// set their discovered socket to whatever the activated socket on the network peer object was
|
||||
discoveredSocket = *connectedPeer->getActiveSocket();
|
||||
}
|
||||
} else {
|
||||
// we got a connectUUID we didn't recognize, just add the node with a new UUID
|
||||
nodeUUID = QUuid::createUuid();
|
||||
// we got a connectUUID we didn't recognize, either use the hinted node ID or randomly generate a new one
|
||||
if (nodeID.isNull()) {
|
||||
nodeID = QUuid::createUuid();
|
||||
}
|
||||
}
|
||||
|
||||
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
|
||||
|
||||
SharedNodePointer newNode = limitedNodeList->addOrUpdateNode(nodeUUID, nodeConnection.nodeType,
|
||||
SharedNodePointer newNode = limitedNodeList->addOrUpdateNode(nodeID, nodeConnection.nodeType,
|
||||
nodeConnection.publicSockAddr, nodeConnection.localSockAddr);
|
||||
|
||||
// So that we can send messages to this node at will - we need to activate the correct socket on this node now
|
||||
|
@ -331,7 +349,6 @@ bool DomainGatekeeper::verifyUserSignature(const QString& username,
|
|||
QCryptographicHash::Sha256);
|
||||
|
||||
if (rsaPublicKey) {
|
||||
QByteArray decryptedArray(RSA_size(rsaPublicKey), 0);
|
||||
int decryptResult = RSA_verify(NID_sha256,
|
||||
reinterpret_cast<const unsigned char*>(usernameWithToken.constData()),
|
||||
usernameWithToken.size(),
|
||||
|
|
|
@ -59,7 +59,8 @@ private:
|
|||
SharedNodePointer processAgentConnectRequest(const NodeConnectionData& nodeConnection,
|
||||
const QString& username,
|
||||
const QByteArray& usernameSignature);
|
||||
SharedNodePointer addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection);
|
||||
SharedNodePointer addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection,
|
||||
QUuid nodeID = QUuid());
|
||||
|
||||
bool verifyUserSignature(const QString& username, const QByteArray& usernameSignature,
|
||||
const HifiSockAddr& senderSockAddr);
|
||||
|
|
|
@ -96,7 +96,7 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
// make sure we hear about newly connected nodes from our gatekeeper
|
||||
connect(&_gatekeeper, &DomainGatekeeper::connectedNode, this, &DomainServer::handleConnectedNode);
|
||||
|
||||
if (optionallyReadX509KeyAndCertificate() && optionallySetupOAuth() && optionallySetupAssignmentPayment()) {
|
||||
if (optionallyReadX509KeyAndCertificate() && optionallySetupOAuth()) {
|
||||
// we either read a certificate and private key or were not passed one
|
||||
// and completed login or did not need to
|
||||
|
||||
|
@ -198,7 +198,6 @@ bool DomainServer::optionallySetupOAuth() {
|
|||
}
|
||||
|
||||
AccountManager& accountManager = AccountManager::getInstance();
|
||||
accountManager.disableSettingsFilePersistence();
|
||||
accountManager.setAuthURL(_oauthProviderURL);
|
||||
|
||||
_oauthClientID = settingsMap.value(OAUTH_CLIENT_ID_OPTION).toString();
|
||||
|
@ -372,20 +371,12 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) {
|
|||
packetReceiver.registerListener(PacketType::ICEPing, &_gatekeeper, "processICEPingPacket");
|
||||
packetReceiver.registerListener(PacketType::ICEPingReply, &_gatekeeper, "processICEPingReplyPacket");
|
||||
packetReceiver.registerListener(PacketType::ICEServerPeerInformation, &_gatekeeper, "processICEPeerInformationPacket");
|
||||
packetReceiver.registerListener(PacketType::ICEServerHeartbeatDenied, this, "processICEServerHeartbeatDenialPacket");
|
||||
|
||||
// add whatever static assignments that have been parsed to the queue
|
||||
addStaticAssignmentsToQueue();
|
||||
}
|
||||
|
||||
bool DomainServer::didSetupAccountManagerWithAccessToken() {
|
||||
if (AccountManager::getInstance().hasValidAccessToken()) {
|
||||
// we already gave the account manager a valid access token
|
||||
return true;
|
||||
}
|
||||
|
||||
return resetAccountManagerAccessToken();
|
||||
}
|
||||
|
||||
const QString ACCESS_TOKEN_KEY_PATH = "metaverse.access_token";
|
||||
|
||||
bool DomainServer::resetAccountManagerAccessToken() {
|
||||
|
@ -401,9 +392,13 @@ bool DomainServer::resetAccountManagerAccessToken() {
|
|||
if (accessTokenVariant && accessTokenVariant->canConvert(QMetaType::QString)) {
|
||||
accessToken = accessTokenVariant->toString();
|
||||
} else {
|
||||
qDebug() << "A domain-server feature that requires authentication is enabled but no access token is present."
|
||||
<< "Set an access token via the web interface, in your user or master config"
|
||||
qDebug() << "A domain-server feature that requires authentication is enabled but no access token is present.";
|
||||
qDebug() << "Set an access token via the web interface, in your user or master config"
|
||||
<< "at keypath metaverse.access_token or in your ENV at key DOMAIN_SERVER_ACCESS_TOKEN";
|
||||
|
||||
// clear any existing access token from AccountManager
|
||||
AccountManager::getInstance().setAccessTokenForCurrentAuthURL(QString());
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
@ -429,34 +424,6 @@ bool DomainServer::resetAccountManagerAccessToken() {
|
|||
}
|
||||
}
|
||||
|
||||
bool DomainServer::optionallySetupAssignmentPayment() {
|
||||
const QString PAY_FOR_ASSIGNMENTS_OPTION = "pay-for-assignments";
|
||||
const QVariantMap& settingsMap = _settingsManager.getSettingsMap();
|
||||
|
||||
if (settingsMap.contains(PAY_FOR_ASSIGNMENTS_OPTION) &&
|
||||
settingsMap.value(PAY_FOR_ASSIGNMENTS_OPTION).toBool() &&
|
||||
didSetupAccountManagerWithAccessToken()) {
|
||||
|
||||
qDebug() << "Assignments will be paid for via" << qPrintable(_oauthProviderURL.toString());
|
||||
|
||||
// assume that the fact we are authing against HF data server means we will pay for assignments
|
||||
// setup a timer to send transactions to pay assigned nodes every 30 seconds
|
||||
QTimer* creditSetupTimer = new QTimer(this);
|
||||
connect(creditSetupTimer, &QTimer::timeout, this, &DomainServer::setupPendingAssignmentCredits);
|
||||
|
||||
const qint64 CREDIT_CHECK_INTERVAL_MSECS = 5 * 1000;
|
||||
creditSetupTimer->start(CREDIT_CHECK_INTERVAL_MSECS);
|
||||
|
||||
QTimer* nodePaymentTimer = new QTimer(this);
|
||||
connect(nodePaymentTimer, &QTimer::timeout, this, &DomainServer::sendPendingTransactionsToServer);
|
||||
|
||||
const qint64 TRANSACTION_SEND_INTERVAL_MSECS = 30 * 1000;
|
||||
nodePaymentTimer->start(TRANSACTION_SEND_INTERVAL_MSECS);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DomainServer::setupAutomaticNetworking() {
|
||||
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
||||
|
||||
|
@ -467,9 +434,9 @@ void DomainServer::setupAutomaticNetworking() {
|
|||
setupICEHeartbeatForFullNetworking();
|
||||
}
|
||||
|
||||
if (!didSetupAccountManagerWithAccessToken()) {
|
||||
qDebug() << "Cannot send heartbeat to data server without an access token.";
|
||||
qDebug() << "Add an access token to your config file or via the web interface.";
|
||||
if (!resetAccountManagerAccessToken()) {
|
||||
qDebug() << "Will not send heartbeat to Metaverse API without an access token.";
|
||||
qDebug() << "If this is not a temporary domain add an access token to your config file or via the web interface.";
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -526,6 +493,19 @@ void DomainServer::setupICEHeartbeatForFullNetworking() {
|
|||
// we need this DS to know what our public IP is - start trying to figure that out now
|
||||
limitedNodeList->startSTUNPublicSocketUpdate();
|
||||
|
||||
// to send ICE heartbeats we'd better have a private key locally with an uploaded public key
|
||||
auto& accountManager = AccountManager::getInstance();
|
||||
auto domainID = accountManager.getAccountInfo().getDomainID();
|
||||
|
||||
// if we have an access token and we don't have a private key or the current domain ID has changed
|
||||
// we should generate a new keypair
|
||||
if (!accountManager.getAccountInfo().hasPrivateKey() || domainID != limitedNodeList->getSessionUUID()) {
|
||||
accountManager.generateNewDomainKeypair(limitedNodeList->getSessionUUID());
|
||||
}
|
||||
|
||||
// hookup to the signal from account manager that tells us when keypair is available
|
||||
connect(&accountManager, &AccountManager::newKeypair, this, &DomainServer::handleKeypairChange);
|
||||
|
||||
if (!_iceHeartbeatTimer) {
|
||||
// setup a timer to heartbeat with the ice-server every so often
|
||||
_iceHeartbeatTimer = new QTimer { this };
|
||||
|
@ -1082,11 +1062,76 @@ void DomainServer::sendHeartbeatToDataServer(const QString& networkAddress) {
|
|||
domainUpdateJSON.toUtf8());
|
||||
}
|
||||
|
||||
// TODO: have data-web respond with ice-server hostname to use
|
||||
|
||||
void DomainServer::sendHeartbeatToIceServer() {
|
||||
if (!_iceServerSocket.getAddress().isNull()) {
|
||||
DependencyManager::get<LimitedNodeList>()->sendHeartbeatToIceServer(_iceServerSocket);
|
||||
|
||||
auto& accountManager = AccountManager::getInstance();
|
||||
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
|
||||
|
||||
if (!accountManager.getAccountInfo().hasPrivateKey()) {
|
||||
qWarning() << "Cannot send an ice-server heartbeat without a private key for signature.";
|
||||
qWarning() << "Waiting for keypair generation to complete before sending ICE heartbeat.";
|
||||
|
||||
if (!limitedNodeList->getSessionUUID().isNull()) {
|
||||
accountManager.generateNewDomainKeypair(limitedNodeList->getSessionUUID());
|
||||
} else {
|
||||
qWarning() << "Attempting to send ICE server heartbeat with no domain ID. This is not supported";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: I'd love to specify the correct size for the packet here, but it's a little trickey with
|
||||
// QDataStream and the possibility of IPv6 address for the sockets.
|
||||
if (!_iceServerHeartbeatPacket) {
|
||||
_iceServerHeartbeatPacket = NLPacket::create(PacketType::ICEServerHeartbeat);
|
||||
}
|
||||
|
||||
bool shouldRecreatePacket = false;
|
||||
|
||||
if (_iceServerHeartbeatPacket->getPayloadSize() > 0) {
|
||||
// if either of our sockets have changed we need to re-sign the heartbeat
|
||||
// first read the sockets out from the current packet
|
||||
_iceServerHeartbeatPacket->seek(0);
|
||||
QDataStream heartbeatStream(_iceServerHeartbeatPacket.get());
|
||||
|
||||
QUuid senderUUID;
|
||||
HifiSockAddr publicSocket, localSocket;
|
||||
heartbeatStream >> senderUUID >> publicSocket >> localSocket;
|
||||
|
||||
if (senderUUID != limitedNodeList->getSessionUUID()
|
||||
|| publicSocket != limitedNodeList->getPublicSockAddr()
|
||||
|| localSocket != limitedNodeList->getLocalSockAddr()) {
|
||||
shouldRecreatePacket = true;
|
||||
}
|
||||
} else {
|
||||
shouldRecreatePacket = true;
|
||||
}
|
||||
|
||||
if (shouldRecreatePacket) {
|
||||
// either we don't have a heartbeat packet yet or some combination of sockets, ID and keypair have changed
|
||||
// and we need to make a new one
|
||||
|
||||
// reset the position in the packet before writing
|
||||
_iceServerHeartbeatPacket->reset();
|
||||
|
||||
// write our plaintext data to the packet
|
||||
QDataStream heartbeatDataStream(_iceServerHeartbeatPacket.get());
|
||||
heartbeatDataStream << limitedNodeList->getSessionUUID()
|
||||
<< limitedNodeList->getPublicSockAddr() << limitedNodeList->getLocalSockAddr();
|
||||
|
||||
// setup a QByteArray that points to the plaintext data
|
||||
auto plaintext = QByteArray::fromRawData(_iceServerHeartbeatPacket->getPayload(), _iceServerHeartbeatPacket->getPayloadSize());
|
||||
|
||||
// generate a signature for the plaintext data in the packet
|
||||
auto signature = accountManager.getAccountInfo().signPlaintext(plaintext);
|
||||
|
||||
// pack the signature with the data
|
||||
heartbeatDataStream << signature;
|
||||
}
|
||||
|
||||
// send the heartbeat packet to the ice server now
|
||||
limitedNodeList->sendUnreliablePacket(*_iceServerHeartbeatPacket, _iceServerSocket);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1970,3 +2015,31 @@ void DomainServer::processNodeDisconnectRequestPacket(QSharedPointer<ReceivedMes
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
void DomainServer::processICEServerHeartbeatDenialPacket(QSharedPointer<ReceivedMessage> message) {
|
||||
static const int NUM_HEARTBEAT_DENIALS_FOR_KEYPAIR_REGEN = 3;
|
||||
|
||||
static int numHeartbeatDenials = 0;
|
||||
if (++numHeartbeatDenials > NUM_HEARTBEAT_DENIALS_FOR_KEYPAIR_REGEN) {
|
||||
qDebug() << "Received" << NUM_HEARTBEAT_DENIALS_FOR_KEYPAIR_REGEN << "heartbeat denials from ice-server"
|
||||
<< "- re-generating keypair now";
|
||||
|
||||
// we've hit our threshold of heartbeat denials, trigger a keypair re-generation
|
||||
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
|
||||
AccountManager::getInstance().generateNewDomainKeypair(limitedNodeList->getSessionUUID());
|
||||
|
||||
// reset our number of heartbeat denials
|
||||
numHeartbeatDenials = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DomainServer::handleKeypairChange() {
|
||||
if (_iceServerHeartbeatPacket) {
|
||||
// reset the payload size of the ice-server heartbeat packet - this causes the packet to be re-generated
|
||||
// the next time we go to send an ice-server heartbeat
|
||||
_iceServerHeartbeatPacket->setPayloadSize(0);
|
||||
|
||||
// send a heartbeat to the ice server immediately
|
||||
sendHeartbeatToIceServer();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ public slots:
|
|||
void processNodeJSONStatsPacket(QSharedPointer<ReceivedMessage> packetList, SharedNodePointer sendingNode);
|
||||
void processPathQueryPacket(QSharedPointer<ReceivedMessage> packet);
|
||||
void processNodeDisconnectRequestPacket(QSharedPointer<ReceivedMessage> message);
|
||||
void processICEServerHeartbeatDenialPacket(QSharedPointer<ReceivedMessage> message);
|
||||
|
||||
private slots:
|
||||
void aboutToQuit();
|
||||
|
@ -78,16 +79,16 @@ private slots:
|
|||
void handleTempDomainError(QNetworkReply& requestReply);
|
||||
|
||||
void queuedQuit(QString quitMessage, int exitCode);
|
||||
|
||||
void handleKeypairChange();
|
||||
|
||||
private:
|
||||
void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid());
|
||||
bool optionallySetupOAuth();
|
||||
bool optionallyReadX509KeyAndCertificate();
|
||||
bool optionallySetupAssignmentPayment();
|
||||
|
||||
void optionallyGetTemporaryName(const QStringList& arguments);
|
||||
|
||||
bool didSetupAccountManagerWithAccessToken();
|
||||
bool resetAccountManagerAccessToken();
|
||||
|
||||
void setupAutomaticNetworking();
|
||||
|
@ -153,6 +154,7 @@ private:
|
|||
DomainServerSettingsManager _settingsManager;
|
||||
|
||||
HifiSockAddr _iceServerSocket;
|
||||
std::unique_ptr<NLPacket> _iceServerHeartbeatPacket;
|
||||
|
||||
QTimer* _iceHeartbeatTimer { nullptr }; // this looks like it dangles when created but it's parented to the DomainServer
|
||||
|
||||
|
|
|
@ -206,8 +206,9 @@ function maybeGoActive(event) {
|
|||
goActive();
|
||||
}
|
||||
}
|
||||
var wasHmdActive = false;
|
||||
var wasMouseCaptured = false;
|
||||
var wasHmdActive = HMD.active;
|
||||
var wasMouseCaptured = Reticle.mouseCaptured;
|
||||
|
||||
function maybeGoAway() {
|
||||
if (HMD.active !== wasHmdActive) {
|
||||
wasHmdActive = !wasHmdActive;
|
||||
|
|
|
@ -46,7 +46,7 @@ function emitter(jointName) {
|
|||
x:0,
|
||||
y: 0,
|
||||
z: 0,
|
||||
w: Math.PI
|
||||
w: 1
|
||||
},
|
||||
emitRadiusStart: 0,
|
||||
polarStart: 0,
|
||||
|
@ -84,7 +84,7 @@ function emitter(jointName) {
|
|||
alpha: 1,
|
||||
alphaSpread: 0,
|
||||
alphaStart: 1,
|
||||
alphaFinish: 1
|
||||
alphaFinish: 1
|
||||
});
|
||||
return newEmitter;
|
||||
}
|
||||
|
|
689
examples/toybox/flappyAvatars/flappyAvatars.js
Normal file
689
examples/toybox/flappyAvatars/flappyAvatars.js
Normal file
|
@ -0,0 +1,689 @@
|
|||
//
|
||||
// flappyAvatars.js
|
||||
// examples/toybox
|
||||
//
|
||||
// Created by Clement 3/2/16
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
(function() {
|
||||
// Constants
|
||||
var TRIGGER_CONTROLS = [
|
||||
Controller.Standard.LT,
|
||||
Controller.Standard.RT,
|
||||
];
|
||||
|
||||
var G = 4.0;
|
||||
|
||||
Number.prototype.clamp = function(min, max) {
|
||||
return Math.min(Math.max(this, min), max);
|
||||
};
|
||||
|
||||
var entityManager = new EntityManager();
|
||||
|
||||
// Class definitions
|
||||
function Avatar(DEFAULT_X, DEFAULT_Y, rotation, to3DPosition) {
|
||||
var DIMENSION = 0.15;
|
||||
var JUMP_VELOCITY = 1.0;
|
||||
var xPosition = DEFAULT_X;
|
||||
var color = { red: 0, green: 0, blue: 255 };
|
||||
|
||||
var dimensionsSet = false;
|
||||
var dimensions = { x: DIMENSION, y: DIMENSION, z: DIMENSION };
|
||||
var yPosition = DEFAULT_Y;
|
||||
var yVelocity = 0.0;
|
||||
var yAcceleration = -G;
|
||||
|
||||
var airSwipeSound = SoundCache.getSound("https://s3-us-west-1.amazonaws.com/hifi-content/clement/production/Air Swipe 05.wav");
|
||||
var injector = null;
|
||||
|
||||
this.position = function() {
|
||||
return { x: xPosition, y: yPosition };
|
||||
}
|
||||
this.dimensions = function() {
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
var id = entityManager.add({
|
||||
type: "Model",
|
||||
modelURL: MyAvatar.skeletonModelURL,
|
||||
animation: {
|
||||
url: "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/fly.fbx",
|
||||
running: true,
|
||||
fps: 30,
|
||||
firstFrame: 1.0,
|
||||
lastFrame: 80.0,
|
||||
currentFrame: 1.0,
|
||||
loop: true,
|
||||
hold: false
|
||||
},
|
||||
position: to3DPosition(this.position()),
|
||||
rotation: rotation,
|
||||
dimensions: dimensions
|
||||
});
|
||||
|
||||
this.changeModel = function(modelURL) {
|
||||
dimensionsSet = false;
|
||||
dimensions = { x: 0.10, y: 0.10, z: 0.01 };
|
||||
|
||||
Entities.editEntity(id, {
|
||||
modelURL: modelURL,
|
||||
rotation: Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(0, -90, 0)),
|
||||
dimensions: dimensions,
|
||||
animation: {running: false}
|
||||
});
|
||||
|
||||
airSwipeSound = SoundCache.getSound("https://s3-us-west-1.amazonaws.com/hifi-content/clement/production/8bit Jump 03.wav");
|
||||
injector = null;
|
||||
}
|
||||
|
||||
this.jump = function() {
|
||||
yVelocity = JUMP_VELOCITY;
|
||||
|
||||
if (airSwipeSound.downloaded && !injector) {
|
||||
injector = Audio.playSound(airSwipeSound, { position: to3DPosition(this.position()), volume: 0.05 });
|
||||
} else if (injector) {
|
||||
injector.restart();
|
||||
}
|
||||
}
|
||||
this.update = function(deltaTime) {
|
||||
if (!dimensionsSet) {
|
||||
var properties = Entities.getEntityProperties(id, ["naturalDimensions"]);
|
||||
var naturalDimensions = properties.naturalDimensions;
|
||||
if (naturalDimensions.x != 1 || naturalDimensions.y != 1 || naturalDimensions.z != 1) {
|
||||
var max = Math.max(naturalDimensions.x, Math.max(naturalDimensions.y, naturalDimensions.z));
|
||||
dimensions.x = naturalDimensions.x / max * dimensions.x;
|
||||
dimensions.y = naturalDimensions.y / max * dimensions.y;
|
||||
dimensions.z = naturalDimensions.z / max * dimensions.z;
|
||||
dimensionsSet = true;
|
||||
|
||||
Entities.editEntity(id, {
|
||||
dimensions: dimensions
|
||||
});
|
||||
}
|
||||
} else {
|
||||
dimensions = Entities.getEntityProperties(id, ["dimensions"]).dimensions;
|
||||
}
|
||||
|
||||
yPosition += deltaTime * (yVelocity + deltaTime * yAcceleration / 2.0);
|
||||
yVelocity += deltaTime * yAcceleration;
|
||||
}
|
||||
this.draw = function() {
|
||||
Entities.editEntity(id, {
|
||||
position: to3DPosition(this.position())
|
||||
});
|
||||
}
|
||||
this.reset = function() {
|
||||
yPosition = DEFAULT_Y;
|
||||
yVelocity = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
function Coin(xPosition, yPosition, to3DPosition) {
|
||||
var velocity = 0.4;
|
||||
var dimensions = { x: 0.0625, y: 0.0625, z: 0.0088 };
|
||||
|
||||
this.position = function() {
|
||||
return { x: xPosition, y: yPosition };
|
||||
}
|
||||
|
||||
var id = entityManager.add({
|
||||
type: "Model",
|
||||
modelURL: "https://s3-us-west-1.amazonaws.com/hifi-content/clement/production/coin.fbx",
|
||||
angularVelocity: { x: 0, y: 20, z: 0 },
|
||||
position: to3DPosition(this.position()),
|
||||
dimensions:dimensions
|
||||
});
|
||||
|
||||
this.update = function(deltaTime) {
|
||||
xPosition -= deltaTime * velocity;
|
||||
}
|
||||
this.isColliding = function(avatar) {
|
||||
var deltaX = Math.abs(this.position().x - avatar.position().x);
|
||||
var deltaY = Math.abs(this.position().Y - avatar.position().Y);
|
||||
if (deltaX < (avatar.dimensions().x + dimensions.x) / 2.0 &&
|
||||
deltaX < (avatar.dimensions().y + dimensions.y) / 2.0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
this.draw = function() {
|
||||
Entities.editEntity(id, { position: to3DPosition({ x: xPosition, y: yPosition }) });
|
||||
}
|
||||
this.clear = function() {
|
||||
entityManager.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
function Pipe(xPosition, yPosition, height, gap, to3DPosition) {
|
||||
var velocity = 0.4;
|
||||
var width = 0.1;
|
||||
|
||||
this.position = function() {
|
||||
return xPosition;
|
||||
}
|
||||
|
||||
var upHeight = yPosition - (height + gap);
|
||||
var upYPosition = height + gap + upHeight / 2.0;
|
||||
|
||||
var idUp = entityManager.add({
|
||||
type: "Model",
|
||||
modelURL: "https://s3-us-west-1.amazonaws.com/hifi-content/clement/production/greenPipe.fbx",
|
||||
rotation: Quat.fromPitchYawRollDegrees(180, 0, 0),
|
||||
position: to3DPosition({ x: xPosition, y: upYPosition }),
|
||||
dimensions: { x: width, y: upHeight, z: width }
|
||||
});
|
||||
var idDown = entityManager.add({
|
||||
type: "Model",
|
||||
modelURL: "https://s3-us-west-1.amazonaws.com/hifi-content/clement/production/greenPipe.fbx",
|
||||
position: to3DPosition({ x: xPosition, y: height / 2.0 }),
|
||||
dimensions: { x: width, y: height, z: width }
|
||||
});
|
||||
|
||||
this.update = function(deltaTime) {
|
||||
xPosition -= deltaTime * velocity;
|
||||
}
|
||||
this.isColliding = function(avatar) {
|
||||
var deltaX = Math.abs(this.position() - avatar.position().x);
|
||||
if (deltaX < (avatar.dimensions().z + width) / 2.0) {
|
||||
var factor = 0.8;
|
||||
var upDistance = (yPosition - upHeight) - (avatar.position().y + avatar.dimensions().y * factor);
|
||||
var downDistance = (avatar.position().y - avatar.dimensions().y * factor) - height;
|
||||
if (upDistance <= 0 || downDistance <= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
this.draw = function() {
|
||||
Entities.editEntity(idUp, { position: to3DPosition({ x: xPosition, y: upYPosition }) });
|
||||
Entities.editEntity(idDown, { position: to3DPosition({ x: xPosition, y: height / 2.0 }) });
|
||||
}
|
||||
this.clear = function() {
|
||||
entityManager.remove(idUp);
|
||||
entityManager.remove(idDown);
|
||||
}
|
||||
}
|
||||
|
||||
function Pipes(newPipesPosition, newPipesHeight, to3DPosition, moveScore) {
|
||||
var lastPipe = 0;
|
||||
var pipesInterval = 2.0;
|
||||
|
||||
var pipes = new Array();
|
||||
var coins = new Array();
|
||||
|
||||
var coinsSound = SoundCache.getSound("https://s3-us-west-1.amazonaws.com/hifi-content/clement/production/Coin.wav");
|
||||
var injector = null;
|
||||
|
||||
this.update = function(deltaTime, gameTime, startedPlaying) {
|
||||
// Move pipes forward
|
||||
pipes.forEach(function(element) {
|
||||
element.update(deltaTime);
|
||||
});
|
||||
// Move coins forward
|
||||
coins.forEach(function(element) {
|
||||
element.update(deltaTime);
|
||||
});
|
||||
// Delete pipes over the end
|
||||
var count = 0;
|
||||
while(count < pipes.length && pipes[count].position() <= 0.0) {
|
||||
pipes[count].clear();
|
||||
count++;
|
||||
}
|
||||
if (count > 0) {
|
||||
pipes = pipes.splice(count);
|
||||
}
|
||||
// Delete coins over the end
|
||||
count = 0;
|
||||
while(count < coins.length && coins[count].position() <= 0.0) {
|
||||
coins[count].clear();
|
||||
count++;
|
||||
}
|
||||
if (count > 0) {
|
||||
coins = coins.splice(count);
|
||||
}
|
||||
// Make new pipes and coins
|
||||
if (startedPlaying && gameTime - lastPipe > pipesInterval) {
|
||||
var min = 0.4;
|
||||
var max = 0.7;
|
||||
var height = Math.random() * (max - min) + min;
|
||||
pipes.push(new Pipe(newPipesPosition, newPipesHeight, height, 0.5, to3DPosition));
|
||||
coins.push(new Coin(newPipesPosition, height + 0.5 / 2.0, to3DPosition));
|
||||
lastPipe = gameTime;
|
||||
}
|
||||
}
|
||||
this.isColliding = function(avatar) {
|
||||
// Check coin collection
|
||||
var collected = -1;
|
||||
coins.forEach(function(element, index) {
|
||||
if (element.isColliding(avatar)) {
|
||||
element.clear();
|
||||
collected = index;
|
||||
moveScore(1);
|
||||
|
||||
if (coinsSound.downloaded && !injector) {
|
||||
injector = Audio.playSound(coinsSound, { position: to3DPosition({ x: newPipesPosition, y: newPipesHeight }), volume: 0.1 });
|
||||
} else if (injector) {
|
||||
injector.restart();
|
||||
}
|
||||
}
|
||||
});
|
||||
if (collected > -1) {
|
||||
coins.splice(collected, 1);
|
||||
}
|
||||
|
||||
|
||||
// Check collisions
|
||||
var isColliding = false;
|
||||
|
||||
pipes.forEach(function(element) {
|
||||
isColliding |= element.isColliding(avatar);
|
||||
});
|
||||
|
||||
return isColliding;
|
||||
}
|
||||
this.draw = function() {
|
||||
// Drawing pipes
|
||||
pipes.forEach(function(element) {
|
||||
element.draw();
|
||||
});
|
||||
// Drawing coins
|
||||
coins.forEach(function(element) {
|
||||
element.draw();
|
||||
});
|
||||
}
|
||||
this.clear = function() {
|
||||
// Clearing pipes
|
||||
pipes.forEach(function(element) {
|
||||
element.clear();
|
||||
});
|
||||
pipes = new Array();
|
||||
|
||||
// Clearing coins
|
||||
coins.forEach(function(element) {
|
||||
element.clear();
|
||||
});
|
||||
coins = new Array();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Score(space, bestScore) {
|
||||
var score = 0;
|
||||
var highScore = bestScore;
|
||||
|
||||
var topOffset = Vec3.multiplyQbyV(space.orientation, { x: -0.1, y: 0.2, z: -0.2 });
|
||||
var topLeft = Vec3.sum(space.position, topOffset);
|
||||
var bottomOffset = Vec3.multiplyQbyV(space.orientation, { x: -0.1, y: 0.0, z: -0.2 });
|
||||
var bottomLeft = Vec3.sum(space.position, bottomOffset);
|
||||
|
||||
var numberDimensions = { x: 0.0660, y: 0.1050, z: 0.0048 };
|
||||
|
||||
function numberUrl(number) {
|
||||
return "https://s3-us-west-1.amazonaws.com/hifi-content/clement/production/" + number + ".fbx"
|
||||
}
|
||||
function digitPosition(digit) {
|
||||
return Vec3.multiplyQbyV(space.orientation, { x: 0.3778 + digit * (numberDimensions.x + 0.01), y: 0.0, z: 0.0 });
|
||||
}
|
||||
this.score = function() {
|
||||
return score;
|
||||
}
|
||||
this.highScore = function() {
|
||||
return highScore;
|
||||
}
|
||||
|
||||
var numDigits = 3;
|
||||
|
||||
var bestId = entityManager.add({
|
||||
type: "Model",
|
||||
modelURL: "https://s3-us-west-1.amazonaws.com/hifi-content/clement/production/best.fbx",
|
||||
position: topLeft,
|
||||
rotation: Quat.multiply(space.orientation, Quat.fromPitchYawRollDegrees(90, 0, 0)),
|
||||
dimensions: { x: 0.2781, y: 0.0063, z: 0.1037 }
|
||||
});
|
||||
var bestDigitsId = []
|
||||
for (var i = 0; i < numDigits; i++) {
|
||||
bestDigitsId[i] = entityManager.add({
|
||||
type: "Model",
|
||||
modelURL: numberUrl(0),
|
||||
position: Vec3.sum(topLeft, digitPosition(i)),
|
||||
rotation: space.orientation,
|
||||
dimensions: numberDimensions
|
||||
});
|
||||
}
|
||||
|
||||
var scoreId = entityManager.add({
|
||||
type: "Model",
|
||||
modelURL: "https://s3-us-west-1.amazonaws.com/hifi-content/clement/production/score.fbx",
|
||||
position: bottomLeft,
|
||||
rotation: Quat.multiply(space.orientation, Quat.fromPitchYawRollDegrees(90, 0, 0)),
|
||||
dimensions: { x: 0.3678, y: 0.0063, z: 0.1037 }
|
||||
});
|
||||
var scoreDigitsId = []
|
||||
for (var i = 0; i < numDigits; i++) {
|
||||
scoreDigitsId[i] = entityManager.add({
|
||||
type: "Model",
|
||||
modelURL: numberUrl(0),
|
||||
position: Vec3.sum(bottomLeft, digitPosition(i)),
|
||||
rotation: space.orientation,
|
||||
dimensions: numberDimensions
|
||||
});
|
||||
}
|
||||
|
||||
this.moveScore = function(delta) {
|
||||
score += delta;
|
||||
if (score > highScore) {
|
||||
highScore = score;
|
||||
}
|
||||
}
|
||||
this.resetScore = function() {
|
||||
score = 0;
|
||||
}
|
||||
|
||||
this.draw = function() {
|
||||
for (var i = 0; i < numDigits; i++) {
|
||||
Entities.editEntity(bestDigitsId[i], { modelURL: numberUrl(Math.floor((highScore / Math.pow(10, numDigits- i - 1)) % 10)) });
|
||||
}
|
||||
|
||||
for (var i = 0; i < numDigits; i++) {
|
||||
Entities.editEntity(scoreDigitsId[i], { modelURL: numberUrl(Math.floor(score / Math.pow(10, numDigits - i - 1)) % 10) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Game(bestScore) {
|
||||
// public methods
|
||||
this.start = function() {
|
||||
if (!isRunning) {
|
||||
isRunning = true;
|
||||
setup();
|
||||
}
|
||||
}
|
||||
|
||||
this.stop = function() {
|
||||
if (isRunning) {
|
||||
cleanup();
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Game loop setup
|
||||
var timestamp = 0;
|
||||
this.idle = function(triggerValue) {
|
||||
var now = Date.now();
|
||||
var deltaTime = (now - timestamp) / 1000.0;
|
||||
if (timestamp === 0) {
|
||||
deltaTime = 0;
|
||||
}
|
||||
gameTime += deltaTime;
|
||||
|
||||
inputs(triggerValue);
|
||||
update(deltaTime);
|
||||
draw();
|
||||
timestamp = now;
|
||||
}
|
||||
|
||||
// Constants
|
||||
var spaceDimensions = { x: 2.0, y: 1.5, z: 0.01 };
|
||||
var spaceDistance = 1.5;
|
||||
var spaceYOffset = 0.6;
|
||||
|
||||
// Private game state
|
||||
var that = this;
|
||||
var isRunning = false;
|
||||
var startedPlaying = false;
|
||||
|
||||
var coolDown = 1.5;
|
||||
var lastLost = -coolDown;
|
||||
|
||||
var gameTime = 0;
|
||||
|
||||
var isJumping = false;
|
||||
var lastJumpValue = 0.0;
|
||||
var lastTriggerValue = 0.0;
|
||||
var TRIGGER_THRESHOLD = 0.9;
|
||||
|
||||
var space = null;
|
||||
var avatar = null;
|
||||
var pipes = null;
|
||||
var score = null;
|
||||
|
||||
var gameOverSound = SoundCache.getSound("https://s3-us-west-1.amazonaws.com/hifi-content/clement/production/Game Over.wav");
|
||||
var injector = null;
|
||||
|
||||
var directions = ["UP", "DOWN", "LEFT", "RIGHT"];
|
||||
var sequence = [directions[0], directions[0], directions[1], directions[1], directions[2], directions[3], directions[2], directions[3], "b", "a"];
|
||||
var current = 0;
|
||||
function keyPress(event) {
|
||||
if (event.text === sequence[current]) {
|
||||
++current;
|
||||
} else {
|
||||
current = 0;
|
||||
}
|
||||
if (current === sequence.length) {
|
||||
avatar.changeModel("https://s3-us-west-1.amazonaws.com/hifi-content/clement/production/mario.fbx");
|
||||
current = 0;
|
||||
}
|
||||
}
|
||||
|
||||
var isBoardReset = true;
|
||||
|
||||
function moveScore(delta) {
|
||||
score.moveScore(delta);
|
||||
}
|
||||
|
||||
this.score = function() {
|
||||
return score.score();
|
||||
}
|
||||
this.highScore = function() {
|
||||
return score.highScore();
|
||||
}
|
||||
|
||||
function setup() {
|
||||
space = {
|
||||
position: getSpacePosition(),
|
||||
orientation: getSpaceOrientation(),
|
||||
dimensions: getSpaceDimensions()
|
||||
}
|
||||
|
||||
var rotation = Quat.multiply(space.orientation, Quat.fromPitchYawRollDegrees(0, 90, 0));
|
||||
avatar = new Avatar(space.dimensions.x / 2.0, space.dimensions.y / 2.0, rotation, to3DPosition);
|
||||
pipes = new Pipes(space.dimensions.x, space.dimensions.y, to3DPosition, moveScore);
|
||||
score = new Score(space, bestScore);
|
||||
|
||||
Controller.keyPressEvent.connect(keyPress);
|
||||
}
|
||||
function inputs(triggerValue) {
|
||||
if (!startedPlaying && !isBoardReset && (gameTime - lastLost) > coolDown) {
|
||||
score.resetScore();
|
||||
avatar.reset();
|
||||
pipes.clear();
|
||||
|
||||
isBoardReset = true;
|
||||
}
|
||||
|
||||
if (triggerValue > TRIGGER_THRESHOLD &&
|
||||
lastTriggerValue < TRIGGER_THRESHOLD &&
|
||||
(gameTime - lastLost) > coolDown) {
|
||||
isJumping = true;
|
||||
startedPlaying = true;
|
||||
}
|
||||
lastTriggerValue = triggerValue;
|
||||
}
|
||||
function update(deltaTime) {
|
||||
// Keep entities alive
|
||||
entityManager.update(deltaTime);
|
||||
|
||||
if (!startedPlaying && (gameTime - lastLost) < coolDown && !isBoardReset) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update Avatar
|
||||
if (!startedPlaying && avatar.position().y < spaceDimensions.y / 2.0) {
|
||||
isJumping = true;
|
||||
}
|
||||
// Apply jumps
|
||||
if (isJumping) {
|
||||
avatar.jump();
|
||||
isJumping = false;
|
||||
}
|
||||
avatar.update(deltaTime);
|
||||
|
||||
pipes.update(deltaTime, gameTime, startedPlaying);
|
||||
|
||||
// Check lost
|
||||
var hasLost = avatar.position().y < 0.0 ||
|
||||
avatar.position().y > space.dimensions.y ||
|
||||
pipes.isColliding(avatar);
|
||||
|
||||
|
||||
// Cleanup
|
||||
if (hasLost) {
|
||||
if (gameOverSound.downloaded && !injector) {
|
||||
injector = Audio.playSound(gameOverSound, { position: space.position, volume: 0.4 });
|
||||
} else if (injector) {
|
||||
injector.restart();
|
||||
}
|
||||
|
||||
isBoardReset = false;
|
||||
startedPlaying = false;
|
||||
lastLost = gameTime;
|
||||
}
|
||||
}
|
||||
function draw() {
|
||||
avatar.draw();
|
||||
pipes.draw();
|
||||
score.draw();
|
||||
}
|
||||
function cleanup() {
|
||||
entityManager.removeAll();
|
||||
|
||||
Controller.keyPressEvent.disconnect(keyPress);
|
||||
}
|
||||
|
||||
// Private methods
|
||||
function getSpacePosition() {
|
||||
var forward = Vec3.multiplyQbyV(MyAvatar.orientation, Vec3.FRONT);
|
||||
var spacePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(spaceDistance, forward));
|
||||
return Vec3.sum(spacePosition, Vec3.multiply(spaceYOffset, Vec3.UP));
|
||||
}
|
||||
function getSpaceOrientation() {
|
||||
return MyAvatar.orientation;
|
||||
}
|
||||
function getSpaceDimensions() {
|
||||
return spaceDimensions;
|
||||
}
|
||||
|
||||
function to3DPosition(position) {
|
||||
var position2D = {
|
||||
x: position.x - space.dimensions.x / 2.0,
|
||||
y: position.y - space.dimensions.y / 2.0,
|
||||
z: 0.0
|
||||
}
|
||||
return Vec3.sum(space.position, Vec3.multiplyQbyV(space.orientation, position2D));
|
||||
}
|
||||
}
|
||||
|
||||
function EntityManager() {
|
||||
var OBJECTS_LIFETIME = 1;
|
||||
var entities = new Array();
|
||||
var lifetime = OBJECTS_LIFETIME;
|
||||
|
||||
this.setLifetime = function(newLifetime) {
|
||||
lifetime = newLifetime;
|
||||
this.update();
|
||||
}
|
||||
this.add = function(properties) {
|
||||
// Add to scene
|
||||
properties.lifetime = lifetime;
|
||||
var entityID = Entities.addEntity(properties);
|
||||
// Add to array
|
||||
entities.push({ id: entityID, properties: properties });
|
||||
|
||||
return entityID;
|
||||
}
|
||||
this.update = function(deltaTime) {
|
||||
entities.forEach(function(element) {
|
||||
// Get entity's age
|
||||
var properties = Entities.getEntityProperties(element.id, ["age"]);
|
||||
// Update entity's lifetime
|
||||
Entities.editEntity(element.id, { lifetime: properties.age + lifetime });
|
||||
});
|
||||
}
|
||||
this.remove = function(entityID) {
|
||||
// Remove from scene
|
||||
Entities.deleteEntity(entityID);
|
||||
|
||||
// Remove from array
|
||||
entities = entities.filter(function(element) {
|
||||
return element.id !== entityID;
|
||||
});
|
||||
}
|
||||
this.removeAll = function() {
|
||||
// Remove all from scene
|
||||
entities.forEach(function(element) {
|
||||
Entities.deleteEntity(element.id);
|
||||
});
|
||||
// Remove all from array
|
||||
entities = new Array();
|
||||
}
|
||||
}
|
||||
|
||||
PartableGame = function() {
|
||||
this.entityID = null;
|
||||
this.equipped = false;
|
||||
this.triggerValue = 0.0;
|
||||
this.hand = 0;
|
||||
this.game = null;
|
||||
};
|
||||
|
||||
PartableGame.prototype = {
|
||||
preload: function(entityID) {
|
||||
this.entityID = entityID;
|
||||
},
|
||||
unload: function() {
|
||||
},
|
||||
startEquip: function(id, params) {
|
||||
this.equipped = true;
|
||||
this.hand = params[0] == "left" ? 0 : 1;
|
||||
|
||||
|
||||
var bestScore = 0;
|
||||
var properties = Entities.getEntityProperties(this.entityID, ["userData"]);
|
||||
var userData = JSON.parse(properties.userData);
|
||||
if (userData.highScore) {
|
||||
bestScore = userData.highScore;
|
||||
}
|
||||
|
||||
this.game = new Game(bestScore);
|
||||
this.game.start();
|
||||
},
|
||||
releaseEquip: function(id, params) {
|
||||
this.equipped = false;
|
||||
|
||||
var properties = Entities.getEntityProperties(this.entityID, ["userData"]);
|
||||
var userData = JSON.parse(properties.userData);
|
||||
userData.highScore = this.game.highScore();
|
||||
properties.userData = JSON.stringify(userData);
|
||||
Entities.editEntity(this.entityID, properties);
|
||||
|
||||
this.game.stop();
|
||||
delete this.game;
|
||||
},
|
||||
continueEquip: function(id, params) {
|
||||
if (!this.equipped) {
|
||||
return;
|
||||
}
|
||||
this.triggerValue = Controller.getValue(TRIGGER_CONTROLS[this.hand]);
|
||||
this.game.idle(this.triggerValue);
|
||||
},
|
||||
};
|
||||
|
||||
// entity scripts always need to return a newly constructed object of our type
|
||||
return new PartableGame();
|
||||
});
|
34
examples/toybox/flappyAvatars/flappyAvatars.json
Normal file
34
examples/toybox/flappyAvatars/flappyAvatars.json
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"Entities": [
|
||||
{
|
||||
"collisionsWillMove": 1,
|
||||
"created": "2016-03-03T19:00:10Z",
|
||||
"dimensions": {
|
||||
"x": 0.11497055739164352,
|
||||
"y": 0.11497056484222412,
|
||||
"z": 0.11497056484222412
|
||||
},
|
||||
"dynamic": 1,
|
||||
"id": "{ee5b25e6-aca2-4dc7-9462-51537d89c126}",
|
||||
"modelURL": "https://s3-us-west-1.amazonaws.com/hifi-content/clement/production/cube.fbx",
|
||||
"queryAACube": {
|
||||
"scale": 0.5974045991897583,
|
||||
"x": -5.1575918197631836,
|
||||
"y": 23.078603744506836,
|
||||
"z": 16.521066665649414
|
||||
},
|
||||
"rotation": {
|
||||
"w": 0.92288088798522949,
|
||||
"x": -0.10148775577545166,
|
||||
"y": -0.13279926776885986,
|
||||
"z": 0.34688329696655273
|
||||
},
|
||||
"script": "https://raw.githubusercontent.com/Atlante45/hifi/feat/hackaton/examples/toybox/flappyAvatars/flappyAvatars.js",
|
||||
"scriptTimestamp": 1457031937425,
|
||||
"shapeType": "box",
|
||||
"type": "Model",
|
||||
"userData": "{\"wearable\":{\"joints\":{\"RightHand\":[{\"x\":0.07079616189002991,\"y\":0.20177987217903137,\"z\":0.06374628841876984},{\"x\":-0.5863648653030396,\"y\":-0.46007341146469116,\"z\":0.46949487924575806,\"w\":-0.4733745753765106}],\"LeftHand\":[{\"x\":-0.018704339861869812,\"y\":0.20499876141548157,\"z\":0.08445858210325241},{\"x\":0.2061777561903,\"y\":-0.6629757881164551,\"z\":0.5865269303321838,\"w\":0.41706138849258423}]}},\"grabbableKey\":{\"invertSolidWhileHeld\":true},\"resetMe\":{\"resetMe\":true},\"highScore\":0}"
|
||||
}
|
||||
],
|
||||
"Version": 57
|
||||
}
|
51
examples/utilities/tools/render/debugFramebuffer.js
Normal file
51
examples/utilities/tools/render/debugFramebuffer.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// ddebugFramBuffer.js
|
||||
// examples/utilities/tools/render
|
||||
//
|
||||
// Sam Gateau created on 2/18/2016.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var DDB = Render.RenderDeferredTask.DebugDeferredBuffer;
|
||||
oldConfig = DDB.toJSON();
|
||||
DDB.enabled = true;
|
||||
|
||||
|
||||
// Set up the qml ui
|
||||
var qml = Script.resolvePath('framebuffer.qml');
|
||||
var window = new OverlayWindow({
|
||||
title: 'Framebuffer Debug',
|
||||
source: qml,
|
||||
width: 400, height: 400,
|
||||
});
|
||||
window.setPosition(25, 50);
|
||||
window.closed.connect(function() { Script.stop(); });
|
||||
|
||||
// Debug buffer sizing
|
||||
var resizing = false;
|
||||
|
||||
Controller.mousePressEvent.connect(function (e) {
|
||||
if (shouldStartResizing(e.x)) {
|
||||
resizing = true;
|
||||
}
|
||||
});
|
||||
Controller.mouseReleaseEvent.connect(function() { resizing = false; });
|
||||
Controller.mouseMoveEvent.connect(function (e) { resizing && setDebugBufferSize(e.x); });
|
||||
|
||||
|
||||
function shouldStartResizing(eventX) {
|
||||
var x = Math.abs(eventX - Window.innerWidth * (1.0 + DDB.size.x) / 2.0);
|
||||
var mode = DDB.mode;
|
||||
return mode !== -1 && x < 20;
|
||||
}
|
||||
|
||||
function setDebugBufferSize(x) {
|
||||
x = (2.0 * (x / Window.innerWidth) - 1.0); // scale
|
||||
x = Math.min(Math.max(-1, x), 1); // clamp
|
||||
DDB.size = { x: x, y: -1, z: 1, w: 1 };
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(function () { DDB.fromJSON(oldConfig); });
|
52
examples/utilities/tools/render/framebuffer.qml
Normal file
52
examples/utilities/tools/render/framebuffer.qml
Normal file
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// main.qml
|
||||
// examples/utilities/tools/render
|
||||
//
|
||||
// Created by Zach Pomerantz on 2/8/2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
Column {
|
||||
id: debug
|
||||
property var config: Render.getConfig("DebugDeferredBuffer")
|
||||
|
||||
function setDebugMode(mode) {
|
||||
debug.config.enabled = (mode != -1);
|
||||
debug.config.mode = mode;
|
||||
}
|
||||
|
||||
Label { text: qsTr("Debug Buffer") }
|
||||
ExclusiveGroup { id: bufferGroup }
|
||||
Repeater {
|
||||
model: [
|
||||
"Off",
|
||||
"Depth",
|
||||
"Albedo",
|
||||
"Normal",
|
||||
"Roughness",
|
||||
"Metallic",
|
||||
"Emissive",
|
||||
"Occlusion",
|
||||
"Lightmap",
|
||||
"Lighting",
|
||||
"Shadow",
|
||||
"Pyramid Depth",
|
||||
"Ambient Occlusion",
|
||||
"Custom Shader"
|
||||
]
|
||||
RadioButton {
|
||||
text: qsTr(modelData)
|
||||
exclusiveGroup: bufferGroup
|
||||
checked: index == 0
|
||||
onCheckedChanged: if (checked) debug.setDebugMode(index - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,3 +6,17 @@ setup_hifi_project(Network)
|
|||
# link the shared hifi libraries
|
||||
link_hifi_libraries(embedded-webserver networking shared)
|
||||
package_libraries_for_deployment()
|
||||
|
||||
# find OpenSSL
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
if (APPLE AND ${OPENSSL_INCLUDE_DIR} STREQUAL "/usr/include")
|
||||
# this is a user on OS X using system OpenSSL, which is going to throw warnings since they're deprecating for their common crypto
|
||||
message(WARNING "The found version of OpenSSL is the OS X system version. This will produce deprecation warnings."
|
||||
"\nWe recommend you install a newer version (at least 1.0.1h) in a different directory and set OPENSSL_ROOT_DIR in your env so Cmake can find it.")
|
||||
endif ()
|
||||
|
||||
include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}")
|
||||
|
||||
# append OpenSSL to our list of libraries to link
|
||||
target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES})
|
||||
|
|
|
@ -9,14 +9,21 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QTimer>
|
||||
#include "IceServer.h"
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
|
||||
#include <LimitedNodeList.h>
|
||||
#include <NetworkingConstants.h>
|
||||
#include <udt/PacketHeaders.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "IceServer.h"
|
||||
|
||||
const int CLEAR_INACTIVE_PEERS_INTERVAL_MSECS = 1 * 1000;
|
||||
const int PEER_SILENCE_THRESHOLD_MSECS = 5 * 1000;
|
||||
|
||||
|
@ -45,7 +52,6 @@ IceServer::IceServer(int argc, char* argv[]) :
|
|||
QTimer* inactivePeerTimer = new QTimer(this);
|
||||
connect(inactivePeerTimer, &QTimer::timeout, this, &IceServer::clearInactivePeers);
|
||||
inactivePeerTimer->start(CLEAR_INACTIVE_PEERS_INTERVAL_MSECS);
|
||||
|
||||
}
|
||||
|
||||
bool IceServer::packetVersionMatch(const udt::Packet& packet) {
|
||||
|
@ -70,9 +76,14 @@ void IceServer::processPacket(std::unique_ptr<udt::Packet> packet) {
|
|||
|
||||
if (nlPacket->getType() == PacketType::ICEServerHeartbeat) {
|
||||
SharedNetworkPeer peer = addOrUpdateHeartbeatingPeer(*nlPacket);
|
||||
|
||||
// so that we can send packets to the heartbeating peer when we need, we need to activate a socket now
|
||||
peer->activateMatchingOrNewSymmetricSocket(nlPacket->getSenderSockAddr());
|
||||
if (peer) {
|
||||
// so that we can send packets to the heartbeating peer when we need, we need to activate a socket now
|
||||
peer->activateMatchingOrNewSymmetricSocket(nlPacket->getSenderSockAddr());
|
||||
} else {
|
||||
// we couldn't verify this peer - respond back to them so they know they may need to perform keypair re-generation
|
||||
static auto deniedPacket = NLPacket::create(PacketType::ICEServerHeartbeatDenied);
|
||||
_serverSocket.writePacket(*deniedPacket, nlPacket->getSenderSockAddr());
|
||||
}
|
||||
} else if (nlPacket->getType() == PacketType::ICEServerQuery) {
|
||||
QDataStream heartbeatStream(nlPacket.get());
|
||||
|
||||
|
@ -114,31 +125,135 @@ SharedNetworkPeer IceServer::addOrUpdateHeartbeatingPeer(NLPacket& packet) {
|
|||
// pull the UUID, public and private sock addrs for this peer
|
||||
QUuid senderUUID;
|
||||
HifiSockAddr publicSocket, localSocket;
|
||||
QByteArray signature;
|
||||
|
||||
QDataStream heartbeatStream(&packet);
|
||||
|
||||
heartbeatStream >> senderUUID;
|
||||
heartbeatStream >> publicSocket >> localSocket;
|
||||
heartbeatStream >> senderUUID >> publicSocket >> localSocket;
|
||||
|
||||
// make sure we have this sender in our peer hash
|
||||
SharedNetworkPeer matchingPeer = _activePeers.value(senderUUID);
|
||||
auto signedPlaintext = QByteArray::fromRawData(packet.getPayload(), heartbeatStream.device()->pos());
|
||||
heartbeatStream >> signature;
|
||||
|
||||
if (!matchingPeer) {
|
||||
// if we don't have this sender we need to create them now
|
||||
matchingPeer = QSharedPointer<NetworkPeer>::create(senderUUID, publicSocket, localSocket);
|
||||
_activePeers.insert(senderUUID, matchingPeer);
|
||||
// make sure this is a verified heartbeat before performing any more processing
|
||||
if (isVerifiedHeartbeat(senderUUID, signedPlaintext, signature)) {
|
||||
// make sure we have this sender in our peer hash
|
||||
SharedNetworkPeer matchingPeer = _activePeers.value(senderUUID);
|
||||
|
||||
qDebug() << "Added a new network peer" << *matchingPeer;
|
||||
if (!matchingPeer) {
|
||||
// if we don't have this sender we need to create them now
|
||||
matchingPeer = QSharedPointer<NetworkPeer>::create(senderUUID, publicSocket, localSocket);
|
||||
_activePeers.insert(senderUUID, matchingPeer);
|
||||
|
||||
qDebug() << "Added a new network peer" << *matchingPeer;
|
||||
} else {
|
||||
// we already had the peer so just potentially update their sockets
|
||||
matchingPeer->setPublicSocket(publicSocket);
|
||||
matchingPeer->setLocalSocket(localSocket);
|
||||
}
|
||||
|
||||
// update our last heard microstamp for this network peer to now
|
||||
matchingPeer->setLastHeardMicrostamp(usecTimestampNow());
|
||||
|
||||
return matchingPeer;
|
||||
} else {
|
||||
// we already had the peer so just potentially update their sockets
|
||||
matchingPeer->setPublicSocket(publicSocket);
|
||||
matchingPeer->setLocalSocket(localSocket);
|
||||
// not verified, return the empty peer object
|
||||
return SharedNetworkPeer();
|
||||
}
|
||||
}
|
||||
|
||||
bool IceServer::isVerifiedHeartbeat(const QUuid& domainID, const QByteArray& plaintext, const QByteArray& signature) {
|
||||
// check if we have a private key for this domain ID - if we do not then fire off the request for it
|
||||
auto it = _domainPublicKeys.find(domainID);
|
||||
if (it != _domainPublicKeys.end()) {
|
||||
|
||||
// attempt to verify the signature for this heartbeat
|
||||
const unsigned char* publicKeyData = reinterpret_cast<const unsigned char*>(it->second.constData());
|
||||
|
||||
// first load up the public key into an RSA struct
|
||||
RSA* rsaPublicKey = d2i_RSA_PUBKEY(NULL, &publicKeyData, it->second.size());
|
||||
|
||||
if (rsaPublicKey) {
|
||||
auto hashedPlaintext = QCryptographicHash::hash(plaintext, QCryptographicHash::Sha256);
|
||||
int verificationResult = RSA_verify(NID_sha256,
|
||||
reinterpret_cast<const unsigned char*>(hashedPlaintext.constData()),
|
||||
hashedPlaintext.size(),
|
||||
reinterpret_cast<const unsigned char*>(signature.constData()),
|
||||
signature.size(),
|
||||
rsaPublicKey);
|
||||
|
||||
// free up the public key and remove connection token before we return
|
||||
RSA_free(rsaPublicKey);
|
||||
|
||||
if (verificationResult == 1) {
|
||||
// this is the only success case - we return true here to indicate that the heartbeat is verified
|
||||
return true;
|
||||
} else {
|
||||
qDebug() << "Failed to verify heartbeat for" << domainID << "- re-requesting public key from API.";
|
||||
}
|
||||
|
||||
} else {
|
||||
// we can't let this user in since we couldn't convert their public key to an RSA key we could use
|
||||
qWarning() << "Could not convert in-memory public key for" << domainID << "to usable RSA public key.";
|
||||
qWarning() << "Re-requesting public key from API";
|
||||
}
|
||||
}
|
||||
|
||||
// update our last heard microstamp for this network peer to now
|
||||
matchingPeer->setLastHeardMicrostamp(usecTimestampNow());
|
||||
// we could not verify this heartbeat (missing public key, could not load public key, bad actor)
|
||||
// ask the metaverse API for the right public key and return false to indicate that this is not verified
|
||||
requestDomainPublicKey(domainID);
|
||||
|
||||
return matchingPeer;
|
||||
return false;
|
||||
}
|
||||
|
||||
void IceServer::requestDomainPublicKey(const QUuid& domainID) {
|
||||
// send a request to the metaverse API for the public key for this domain
|
||||
QNetworkAccessManager* manager = new QNetworkAccessManager { this };
|
||||
connect(manager, &QNetworkAccessManager::finished, this, &IceServer::publicKeyReplyFinished);
|
||||
|
||||
QUrl publicKeyURL { NetworkingConstants::METAVERSE_SERVER_URL };
|
||||
QString publicKeyPath = QString("/api/v1/domains/%1/public_key").arg(uuidStringWithoutCurlyBraces(domainID));
|
||||
publicKeyURL.setPath(publicKeyPath);
|
||||
|
||||
QNetworkRequest publicKeyRequest { publicKeyURL };
|
||||
publicKeyRequest.setAttribute(QNetworkRequest::User, domainID);
|
||||
|
||||
qDebug() << "Requesting public key for domain with ID" << domainID;
|
||||
|
||||
manager->get(publicKeyRequest);
|
||||
}
|
||||
|
||||
void IceServer::publicKeyReplyFinished(QNetworkReply* reply) {
|
||||
// get the domain ID from the QNetworkReply attribute
|
||||
QUuid domainID = reply->request().attribute(QNetworkRequest::User).toUuid();
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError) {
|
||||
// pull out the public key and store it for this domain
|
||||
|
||||
// the response should be JSON
|
||||
QJsonDocument responseDocument = QJsonDocument::fromJson(reply->readAll());
|
||||
|
||||
static const QString DATA_KEY = "data";
|
||||
static const QString PUBLIC_KEY_KEY = "public_key";
|
||||
static const QString STATUS_KEY = "status";
|
||||
static const QString SUCCESS_VALUE = "success";
|
||||
|
||||
auto responseObject = responseDocument.object();
|
||||
if (responseObject[STATUS_KEY].toString() == SUCCESS_VALUE) {
|
||||
auto dataObject = responseObject[DATA_KEY].toObject();
|
||||
if (dataObject.contains(PUBLIC_KEY_KEY)) {
|
||||
_domainPublicKeys[domainID] = QByteArray::fromBase64(dataObject[PUBLIC_KEY_KEY].toString().toUtf8());
|
||||
} else {
|
||||
qWarning() << "There was no public key present in response for domain with ID" << domainID;
|
||||
}
|
||||
} else {
|
||||
qWarning() << "The metaverse API did not return success for public key request for domain with ID" << domainID;
|
||||
}
|
||||
|
||||
} else {
|
||||
// there was a problem getting the public key for the domain
|
||||
// log it since it will be re-requested on the next heartbeat
|
||||
|
||||
qWarning() << "Error retreiving public key for domain with ID" << domainID << "-" << reply->errorString();
|
||||
}
|
||||
}
|
||||
|
||||
void IceServer::sendPeerInformationPacket(const NetworkPeer& peer, const HifiSockAddr* destinationSockAddr) {
|
||||
|
|
|
@ -16,13 +16,15 @@
|
|||
#include <QtCore/QSharedPointer>
|
||||
#include <QUdpSocket>
|
||||
|
||||
#include <UUIDHasher.h>
|
||||
|
||||
#include <NetworkPeer.h>
|
||||
#include <HTTPConnection.h>
|
||||
#include <HTTPManager.h>
|
||||
#include <NLPacket.h>
|
||||
#include <udt/Socket.h>
|
||||
|
||||
typedef QHash<QUuid, SharedNetworkPeer> NetworkPeerHash;
|
||||
class QNetworkReply;
|
||||
|
||||
class IceServer : public QCoreApplication, public HTTPRequestHandler {
|
||||
Q_OBJECT
|
||||
|
@ -31,6 +33,7 @@ public:
|
|||
bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler = false);
|
||||
private slots:
|
||||
void clearInactivePeers();
|
||||
void publicKeyReplyFinished(QNetworkReply* reply);
|
||||
private:
|
||||
bool packetVersionMatch(const udt::Packet& packet);
|
||||
void processPacket(std::unique_ptr<udt::Packet> packet);
|
||||
|
@ -38,10 +41,19 @@ private:
|
|||
SharedNetworkPeer addOrUpdateHeartbeatingPeer(NLPacket& incomingPacket);
|
||||
void sendPeerInformationPacket(const NetworkPeer& peer, const HifiSockAddr* destinationSockAddr);
|
||||
|
||||
bool isVerifiedHeartbeat(const QUuid& domainID, const QByteArray& plaintext, const QByteArray& signature);
|
||||
void requestDomainPublicKey(const QUuid& domainID);
|
||||
|
||||
QUuid _id;
|
||||
udt::Socket _serverSocket;
|
||||
|
||||
using NetworkPeerHash = QHash<QUuid, SharedNetworkPeer>;
|
||||
NetworkPeerHash _activePeers;
|
||||
|
||||
HTTPManager _httpManager;
|
||||
|
||||
using DomainPublicKeyHash = std::unordered_map<QUuid, QByteArray>;
|
||||
DomainPublicKeyHash _domainPublicKeys;
|
||||
};
|
||||
|
||||
#endif // hifi_IceServer_h
|
||||
|
|
|
@ -268,7 +268,7 @@ if (WIN32)
|
|||
|
||||
set(TARGET_INSTALL_DIR ${INTERFACE_INSTALL_DIR})
|
||||
set(TARGET_INSTALL_COMPONENT ${CLIENT_COMPONENT})
|
||||
manually_install_ssl_eay()
|
||||
manually_install_openssl_for_qt()
|
||||
|
||||
package_libraries_for_deployment()
|
||||
endif()
|
||||
|
|
Binary file not shown.
|
@ -18,7 +18,7 @@ Original.Button {
|
|||
id: button
|
||||
property int color: 0
|
||||
width: 120
|
||||
height: 30
|
||||
height: 28
|
||||
|
||||
style: ButtonStyle {
|
||||
|
||||
|
|
70
interface/resources/qml/controls-uit/CheckBox.qml
Normal file
70
interface/resources/qml/controls-uit/CheckBox.qml
Normal file
|
@ -0,0 +1,70 @@
|
|||
//
|
||||
// CheckBox.qml
|
||||
//
|
||||
// Created by David Rowe on 26 Feb 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
Original.CheckBox {
|
||||
id: checkBox
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||
|
||||
readonly property int boxSize: 14
|
||||
readonly property int boxRadius: 3
|
||||
readonly property int checkSize: 10
|
||||
readonly property int checkRadius: 2
|
||||
|
||||
style: CheckBoxStyle {
|
||||
indicator: Rectangle {
|
||||
id: box
|
||||
width: boxSize
|
||||
height: boxSize
|
||||
radius: boxRadius
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: pressed || hovered
|
||||
? (checkBox.isLightColorScheme ? hifi.colors.checkboxDarkStart : hifi.colors.checkboxLightStart)
|
||||
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightStart : hifi.colors.checkboxDarkStart)
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: pressed || hovered
|
||||
? (checkBox.isLightColorScheme ? hifi.colors.checkboxDarkFinish : hifi.colors.checkboxLightFinish)
|
||||
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: check
|
||||
width: checkSize
|
||||
height: checkSize
|
||||
radius: checkRadius
|
||||
anchors.centerIn: parent
|
||||
color: hifi.colors.checkboxChecked
|
||||
border.width: 1
|
||||
border.color: hifi.colors.checkboxCheckedBorder
|
||||
visible: checked && !pressed || !checked && pressed
|
||||
}
|
||||
}
|
||||
|
||||
label: Label {
|
||||
text: control.text
|
||||
colorScheme: checkBox.colorScheme
|
||||
x: checkBox.boxSize / 2
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
}
|
202
interface/resources/qml/controls-uit/ComboBox.qml
Normal file
202
interface/resources/qml/controls-uit/ComboBox.qml
Normal file
|
@ -0,0 +1,202 @@
|
|||
//
|
||||
// ComboBox.qml
|
||||
//
|
||||
// Created by Bradley Austin David on 27 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
import "." as VrControls
|
||||
|
||||
FocusScope {
|
||||
id: root
|
||||
|
||||
property alias model: comboBox.model;
|
||||
property alias comboBox: comboBox
|
||||
readonly property alias currentText: comboBox.currentText;
|
||||
property alias currentIndex: comboBox.currentIndex;
|
||||
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||
property string label: ""
|
||||
property real controlHeight: height + (comboBoxLabel.visible ? comboBoxLabel.height + comboBoxLabel.anchors.bottomMargin : 0)
|
||||
|
||||
readonly property ComboBox control: comboBox
|
||||
|
||||
implicitHeight: comboBox.height;
|
||||
focus: true
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: popup.visible
|
||||
? (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
|
||||
: (isLightColorScheme ? hifi.colors.dropDownLightStart : hifi.colors.dropDownDarkStart)
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: popup.visible
|
||||
? (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
|
||||
: (isLightColorScheme ? hifi.colors.dropDownLightFinish : hifi.colors.dropDownDarkFinish)
|
||||
}
|
||||
}
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
SystemPalette { id: palette }
|
||||
|
||||
ComboBox {
|
||||
id: comboBox
|
||||
anchors.fill: parent
|
||||
visible: false
|
||||
height: hifi.fontSizes.textFieldInput + 14 // Match height of TextField control.
|
||||
}
|
||||
|
||||
FiraSansSemiBold {
|
||||
id: textField
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: hifi.dimensions.textPadding
|
||||
right: dropIcon.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
size: hifi.fontSizes.textFieldInput
|
||||
text: comboBox.currentText
|
||||
elide: Text.ElideRight
|
||||
color: controlHover.containsMouse || popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText )
|
||||
}
|
||||
|
||||
Item {
|
||||
id: dropIcon
|
||||
anchors { right: parent.right; verticalCenter: parent.verticalCenter }
|
||||
height: background.height
|
||||
width: height
|
||||
Rectangle {
|
||||
width: 1
|
||||
height: parent.height
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
color: isLightColorScheme ? hifi.colors.faintGray : hifi.colors.baseGray
|
||||
}
|
||||
HiFiGlyphs {
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: -8
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
size: hifi.dimensions.spinnerSize
|
||||
text: hifi.glyphs.caratDn
|
||||
color: controlHover.containsMouse || popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText)
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: controlHover
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
onClicked: toggleList();
|
||||
}
|
||||
|
||||
function toggleList() {
|
||||
if (popup.visible) {
|
||||
hideList();
|
||||
} else {
|
||||
showList();
|
||||
}
|
||||
}
|
||||
|
||||
function showList() {
|
||||
var r = desktop.mapFromItem(root, 0, 0, root.width, root.height);
|
||||
listView.currentIndex = root.currentIndex
|
||||
scrollView.x = r.x;
|
||||
scrollView.y = r.y + r.height;
|
||||
var bottom = scrollView.y + scrollView.height;
|
||||
if (bottom > desktop.height) {
|
||||
scrollView.y -= bottom - desktop.height + 8;
|
||||
}
|
||||
popup.visible = true;
|
||||
popup.forceActiveFocus();
|
||||
}
|
||||
|
||||
function hideList() {
|
||||
popup.visible = false;
|
||||
}
|
||||
|
||||
FocusScope {
|
||||
id: popup
|
||||
parent: desktop
|
||||
anchors.fill: parent
|
||||
z: desktop.zLevels.menu
|
||||
visible: false
|
||||
focus: true
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: hideList();
|
||||
}
|
||||
|
||||
function previousItem() { listView.currentIndex = (listView.currentIndex + listView.count - 1) % listView.count; }
|
||||
function nextItem() { listView.currentIndex = (listView.currentIndex + listView.count + 1) % listView.count; }
|
||||
function selectCurrentItem() { root.currentIndex = listView.currentIndex; hideList(); }
|
||||
function selectSpecificItem(index) { root.currentIndex = index; hideList(); }
|
||||
|
||||
Keys.onUpPressed: previousItem();
|
||||
Keys.onDownPressed: nextItem();
|
||||
Keys.onSpacePressed: selectCurrentItem();
|
||||
Keys.onRightPressed: selectCurrentItem();
|
||||
Keys.onReturnPressed: selectCurrentItem();
|
||||
Keys.onEscapePressed: hideList();
|
||||
|
||||
ScrollView {
|
||||
id: scrollView
|
||||
height: 480
|
||||
|
||||
ListView {
|
||||
id: listView
|
||||
height: textField.height * count * 1.4
|
||||
model: root.model
|
||||
delegate: Rectangle {
|
||||
width: root.width + 4
|
||||
height: popupText.implicitHeight * 1.4
|
||||
color: popupHover.containsMouse ? hifi.colors.primaryHighlight : (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
|
||||
FiraSansSemiBold {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: hifi.dimensions.textPadding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
id: popupText
|
||||
text: listView.model[index]
|
||||
size: hifi.fontSizes.textFieldInput
|
||||
color: hifi.colors.baseGray
|
||||
}
|
||||
MouseArea {
|
||||
id: popupHover
|
||||
anchors.fill: parent;
|
||||
hoverEnabled: true
|
||||
onEntered: listView.currentIndex = index;
|
||||
onClicked: popup.selectSpecificItem(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Label {
|
||||
id: comboBoxLabel
|
||||
text: root.label
|
||||
colorScheme: root.colorScheme
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: 4
|
||||
visible: label != ""
|
||||
}
|
||||
}
|
133
interface/resources/qml/controls-uit/ContentSection.qml
Normal file
133
interface/resources/qml/controls-uit/ContentSection.qml
Normal file
|
@ -0,0 +1,133 @@
|
|||
//
|
||||
// ContentSection.qml
|
||||
//
|
||||
// Created by David Rowe on 16 Feb 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
Column {
|
||||
property string name: "Static Section"
|
||||
property bool isFirst: false
|
||||
property bool isCollapsible: false // Set at creation.
|
||||
property bool isCollapsed: false
|
||||
|
||||
spacing: 0 // Defer spacing decisions to individual controls.
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: hifi.dimensions.contentMargin.x
|
||||
right: parent.right
|
||||
rightMargin: hifi.dimensions.contentMargin.x
|
||||
}
|
||||
|
||||
function toggleCollapsed() {
|
||||
if (isCollapsible) {
|
||||
isCollapsed = !isCollapsed;
|
||||
for (var i = 1; i < children.length; i++) {
|
||||
children[i].visible = !isCollapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: sectionName
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: leadingSpace.height + topBar.height + heading.height + bottomBar.height
|
||||
|
||||
Item {
|
||||
id: leadingSpace
|
||||
width: 1
|
||||
height: isFirst ? hifi.dimensions.contentSpacing.y : hifi.dimensions.controlInterlineHeight
|
||||
anchors.top: parent.top
|
||||
}
|
||||
|
||||
Item {
|
||||
id: topBar
|
||||
visible: !isFirst
|
||||
height: visible ? 2 : 0
|
||||
anchors.top: leadingSpace.bottom
|
||||
|
||||
Rectangle {
|
||||
id: shadow
|
||||
width: frame.width
|
||||
height: 1
|
||||
color: hifi.colors.baseGrayShadow
|
||||
x: -hifi.dimensions.contentMargin.x
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: frame.width
|
||||
height: 1
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
x: -hifi.dimensions.contentMargin.x
|
||||
anchors.top: shadow.bottom
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: heading
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: topBar.bottom
|
||||
}
|
||||
height: (isCollapsible ? 3 : 2) * hifi.dimensions.contentSpacing.y
|
||||
|
||||
RalewayRegular {
|
||||
id: title
|
||||
anchors {
|
||||
left: parent.left
|
||||
top: parent.top
|
||||
topMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
size: hifi.fontSizes.sectionName
|
||||
font.capitalization: Font.AllUppercase
|
||||
text: name
|
||||
color: hifi.colors.lightGrayText
|
||||
}
|
||||
|
||||
HiFiGlyphs {
|
||||
anchors {
|
||||
verticalCenter: title.verticalCenter
|
||||
right: parent.right
|
||||
rightMargin: -4
|
||||
}
|
||||
y: -2
|
||||
size: hifi.fontSizes.disclosureButton
|
||||
text: isCollapsed ? hifi.glyphs.disclosureButtonExpand : hifi.glyphs.disclosureButtonCollapse
|
||||
color: hifi.colors.lightGrayText
|
||||
visible: isCollapsible
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: toggleCollapsed()
|
||||
}
|
||||
}
|
||||
|
||||
LinearGradient {
|
||||
id: bottomBar
|
||||
visible: isCollapsible
|
||||
width: frame.width
|
||||
height: visible ? 4 : 0
|
||||
x: -hifi.dimensions.contentMargin.x
|
||||
anchors.top: heading.bottom
|
||||
start: Qt.point(0, 0)
|
||||
end: Qt.point(0, 4)
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: hifi.colors.darkGray }
|
||||
GradientStop { position: 1.0; color: hifi.colors.baseGray } // Equivalent of darkGray0 over baseGray background.
|
||||
}
|
||||
cached: true
|
||||
}
|
||||
}
|
||||
}
|
20
interface/resources/qml/controls-uit/Label.qml
Normal file
20
interface/resources/qml/controls-uit/Label.qml
Normal file
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// Label.qml
|
||||
//
|
||||
// Created by David Rowe on 26 Feb 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
RalewaySemibold {
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
|
||||
size: hifi.fontSizes.inputLabel
|
||||
color: colorScheme == hifi.colorSchemes.light ? hifi.colors.lightGray : hifi.colors.lightGrayText
|
||||
}
|
98
interface/resources/qml/controls-uit/Slider.qml
Normal file
98
interface/resources/qml/controls-uit/Slider.qml
Normal file
|
@ -0,0 +1,98 @@
|
|||
//
|
||||
// Slider.qml
|
||||
//
|
||||
// Created by David Rowe on 27 Feb 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
|
||||
Slider {
|
||||
id: slider
|
||||
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||
property string label: ""
|
||||
property real controlHeight: height + (sliderLabel.visible ? sliderLabel.height + sliderLabel.anchors.bottomMargin : 0)
|
||||
|
||||
height: hifi.fontSizes.textFieldInput + 14 // Match height of TextField control.
|
||||
y: sliderLabel.visible ? sliderLabel.height + sliderLabel.anchors.bottomMargin : 0
|
||||
|
||||
style: SliderStyle {
|
||||
|
||||
groove: Rectangle {
|
||||
implicitWidth: 50
|
||||
implicitHeight: hifi.dimensions.sliderGrooveHeight
|
||||
radius: height / 2
|
||||
color: isLightColorScheme ? hifi.colors.sliderGutterLight : hifi.colors.sliderGutterDark
|
||||
|
||||
Rectangle {
|
||||
width: parent.height - 2
|
||||
height: slider.value * slider.width - 1
|
||||
radius: height / 2
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: width + 1
|
||||
left: parent.left
|
||||
leftMargin: 1
|
||||
}
|
||||
transformOrigin: Item.TopLeft
|
||||
rotation: -90
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: hifi.colors.blueAccent }
|
||||
GradientStop { position: 1.0; color: hifi.colors.primaryHighlight }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handle: Rectangle {
|
||||
implicitWidth: hifi.dimensions.sliderHandleSize
|
||||
implicitHeight: hifi.dimensions.sliderHandleSize
|
||||
radius: height / 2
|
||||
border.width: 1
|
||||
border.color: isLightColorScheme ? hifi.colors.sliderBorderLight : hifi.colors.sliderBorderDark
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.0
|
||||
color: pressed || hovered
|
||||
? (isLightColorScheme ? hifi.colors.sliderDarkStart : hifi.colors.sliderLightStart )
|
||||
: (isLightColorScheme ? hifi.colors.sliderLightStart : hifi.colors.sliderDarkStart )
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: pressed || hovered
|
||||
? (isLightColorScheme ? hifi.colors.sliderDarkFinish : hifi.colors.sliderLightFinish )
|
||||
: (isLightColorScheme ? hifi.colors.sliderLightFinish : hifi.colors.sliderDarkFinish )
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
height: parent.height - 2
|
||||
width: height
|
||||
radius: height / 2
|
||||
anchors.centerIn: parent
|
||||
color: hifi.colors.transparent
|
||||
border.width: 1
|
||||
border.color: hifi.colors.black
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Label {
|
||||
id: sliderLabel
|
||||
text: slider.label
|
||||
colorScheme: slider.colorScheme
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: 2
|
||||
visible: label != ""
|
||||
}
|
||||
}
|
79
interface/resources/qml/controls-uit/SpinBox.qml
Normal file
79
interface/resources/qml/controls-uit/SpinBox.qml
Normal file
|
@ -0,0 +1,79 @@
|
|||
//
|
||||
// SpinBox.qml
|
||||
//
|
||||
// Created by David Rowe on 26 Feb 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
|
||||
SpinBox {
|
||||
id: spinBox
|
||||
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||
property string label: ""
|
||||
property real controlHeight: height + (spinBoxLabel.visible ? spinBoxLabel.height + spinBoxLabel.anchors.bottomMargin : 0)
|
||||
|
||||
FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; }
|
||||
font.family: firaSansSemiBold.name
|
||||
font.pixelSize: hifi.fontSizes.textFieldInput
|
||||
height: hifi.fontSizes.textFieldInput + 14 // Match height of TextField control.
|
||||
|
||||
y: spinBoxLabel.visible ? spinBoxLabel.height + spinBoxLabel.anchors.bottomMargin : 0
|
||||
|
||||
style: SpinBoxStyle {
|
||||
background: Rectangle {
|
||||
color: isLightColorScheme
|
||||
? (spinBox.focus ? hifi.colors.white : hifi.colors.lightGray)
|
||||
: (spinBox.focus ? hifi.colors.black : hifi.colors.baseGrayShadow)
|
||||
border.color: hifi.colors.primaryHighlight
|
||||
border.width: spinBox.focus ? 1 : 0
|
||||
}
|
||||
|
||||
textColor: isLightColorScheme
|
||||
? (spinBox.focus ? hifi.colors.black : hifi.colors.lightGray)
|
||||
: (spinBox.focus ? hifi.colors.white : hifi.colors.lightGrayText)
|
||||
selectedTextColor: hifi.colors.black
|
||||
selectionColor: hifi.colors.primaryHighlight
|
||||
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
padding.left: hifi.dimensions.textPadding
|
||||
padding.right: hifi.dimensions.spinnerSize
|
||||
|
||||
incrementControl: HiFiGlyphs {
|
||||
id: incrementButton
|
||||
text: hifi.glyphs.caratUp
|
||||
x: 6
|
||||
y: 2
|
||||
size: hifi.dimensions.spinnerSize
|
||||
color: styleData.upPressed ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
|
||||
}
|
||||
|
||||
decrementControl: HiFiGlyphs {
|
||||
text: hifi.glyphs.caratDn
|
||||
x: 6
|
||||
y: -3
|
||||
size: hifi.dimensions.spinnerSize
|
||||
color: styleData.downPressed ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Label {
|
||||
id: spinBoxLabel
|
||||
text: spinBox.label
|
||||
colorScheme: spinBox.colorScheme
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: 4
|
||||
visible: label != ""
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
//
|
||||
// StaticSection.qml
|
||||
//
|
||||
// Created by David Rowe on 16 Feb 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
Column {
|
||||
property string name: "Static Section"
|
||||
property bool hasSeparator: false
|
||||
|
||||
spacing: hifi.dimensions.contentSpacing.y
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: hifi.dimensions.contentMargin.x
|
||||
right: parent.right
|
||||
rightMargin: hifi.dimensions.contentMargin.x
|
||||
}
|
||||
|
||||
VerticalSpacer { }
|
||||
|
||||
Item {
|
||||
visible: hasSeparator
|
||||
anchors.top: sectionName.top
|
||||
|
||||
Rectangle {
|
||||
width: frame.width
|
||||
height: 1
|
||||
color: hifi.colors.baseGrayShadow
|
||||
x: -hifi.dimensions.contentMargin.x
|
||||
anchors.bottom: highlight.top
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: highlight
|
||||
width: frame.width
|
||||
height: 1
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
x: -hifi.dimensions.contentMargin.x
|
||||
anchors.bottom: parent.top
|
||||
}
|
||||
}
|
||||
|
||||
RalewayRegular {
|
||||
id: sectionName
|
||||
text: parent.name
|
||||
size: hifi.fontSizes.sectionName
|
||||
font.capitalization: Font.AllUppercase
|
||||
color: hifi.colors.lightGrayText
|
||||
verticalAlignment: Text.AlignBottom
|
||||
height: {
|
||||
if (hasSeparator) {
|
||||
hifi.dimensions.contentMargin.y
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,25 +13,31 @@ import QtQuick.Controls 1.4
|
|||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
|
||||
TextField {
|
||||
id: textField
|
||||
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||
property string label: ""
|
||||
property real controlHeight: height + (textFieldLabel.visible ? textFieldLabel.height : 0)
|
||||
|
||||
placeholderText: textField.placeholderText
|
||||
|
||||
FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; }
|
||||
font.family: firaSansSemiBold.name
|
||||
font.pixelSize: hifi.fontSizes.textFieldInput
|
||||
height: implicitHeight + 4 // Make surrounding box higher so that highlight is vertically centered.
|
||||
placeholderText: textField.label // Instead of separate label (see below).
|
||||
|
||||
y: textFieldLabel.visible ? textFieldLabel.height + textFieldLabel.anchors.bottomMargin : 0
|
||||
|
||||
style: TextFieldStyle {
|
||||
textColor: textField.colorScheme == hifi.colorSchemes.light
|
||||
textColor: isLightColorScheme
|
||||
? (textField.focus ? hifi.colors.black : hifi.colors.lightGray)
|
||||
: (textField.focus ? hifi.colors.white : hifi.colors.lightGrayText)
|
||||
background: Rectangle {
|
||||
color: textField.colorScheme == hifi.colorSchemes.light
|
||||
color: isLightColorScheme
|
||||
? (textField.focus ? hifi.colors.white : hifi.colors.lightGray)
|
||||
: (textField.focus ? hifi.colors.black : hifi.colors.baseGrayShadow)
|
||||
border.color: hifi.colors.primaryHighlight
|
||||
|
@ -44,16 +50,13 @@ TextField {
|
|||
padding.right: hifi.dimensions.textPadding
|
||||
}
|
||||
|
||||
/*
|
||||
// Separate label instead of placeholderText.
|
||||
RalewaySemibold {
|
||||
HifiControls.Label {
|
||||
id: textFieldLabel
|
||||
text: textField.label
|
||||
size: hifi.fontSizes.inputLabel
|
||||
color: hifi.colors.lightGrayText
|
||||
colorScheme: textField.colorScheme
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: 4
|
||||
visible: label != ""
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -55,8 +55,8 @@ TreeView {
|
|||
alternateBackgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd
|
||||
|
||||
branchDelegate: HiFiGlyphs {
|
||||
text: styleData.isExpanded ? hifi.glyphs.disclosureCollapse : hifi.glyphs.disclosureExpand
|
||||
size: hifi.fontSizes.tableText * 2.5
|
||||
text: styleData.isExpanded ? hifi.glyphs.caratDn : hifi.glyphs.caratR
|
||||
size: hifi.fontSizes.carat
|
||||
color: colorScheme == hifi.colorSchemes.light
|
||||
? (styleData.selected
|
||||
? hifi.colors.black
|
||||
|
|
|
@ -14,5 +14,5 @@ import "../styles-uit"
|
|||
|
||||
Item {
|
||||
width: 1 // Must be non-zero
|
||||
height: hifi.dimensions.contentSpacing.y
|
||||
height: hifi.dimensions.controlInterlineHeight
|
||||
}
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
//
|
||||
// PreferencesDialog.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 24 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Dialogs 1.2 as OriginalDialogs
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
import "../controls" as HifiControls
|
||||
import "../windows"
|
||||
import "../controls-uit" as HifiControls
|
||||
import "../styles-uit"
|
||||
import "../windows-uit"
|
||||
import "preferences"
|
||||
|
||||
Window {
|
||||
|
@ -16,6 +25,9 @@ Window {
|
|||
height: 577
|
||||
property var sections: []
|
||||
property var showCategories: []
|
||||
minSize: Qt.vector2d(400, 500)
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
function saveAll() {
|
||||
for (var i = 0; i < sections.length; ++i) {
|
||||
|
@ -33,10 +45,8 @@ Window {
|
|||
destroy();
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
color: "white"
|
||||
Column {
|
||||
width: pane.contentWidth
|
||||
|
||||
Component {
|
||||
id: sectionBuilder
|
||||
|
@ -64,45 +74,45 @@ Window {
|
|||
}
|
||||
|
||||
if (sections.length) {
|
||||
sections[0].expanded = true;
|
||||
// Default sections to expanded/collapsed as appropriate for dialog.
|
||||
if (sections.length === 1) {
|
||||
sections[0].collapsable = false
|
||||
sections[0].expanded = true
|
||||
} else {
|
||||
for (i = 0; i < sections.length; i++) {
|
||||
sections[i].collapsable = true;
|
||||
sections[i].expanded = true;
|
||||
}
|
||||
}
|
||||
sections[0].isFirst = true;
|
||||
sections[sections.length - 1].isLast = true;
|
||||
}
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: flickable
|
||||
clip: true
|
||||
interactive: true
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: dialogButtons.top
|
||||
anchors.bottomMargin: 8
|
||||
contentHeight: prefControls.height
|
||||
contentWidth: parent.width
|
||||
|
||||
Column {
|
||||
id: prefControls
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
}
|
||||
Column {
|
||||
id: prefControls
|
||||
width: pane.contentWidth
|
||||
}
|
||||
Row {
|
||||
id: dialogButtons
|
||||
anchors { bottom: parent.bottom; right: parent.right; margins: 8 }
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Cancel";
|
||||
onClicked: root.restoreAll();
|
||||
}
|
||||
footer: Row {
|
||||
anchors {
|
||||
right: parent.right;
|
||||
rightMargin: hifi.dimensions.contentMargin.x
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
|
||||
Button {
|
||||
text: "Save all changes"
|
||||
onClicked: root.saveAll();
|
||||
}
|
||||
HifiControls.Button {
|
||||
text: "Save changes"
|
||||
color: hifi.buttons.blue
|
||||
onClicked: root.saveAll()
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
text: "Cancel"
|
||||
color: hifi.buttons.white
|
||||
onClicked: root.restoreAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,25 @@
|
|||
//
|
||||
// AvatarPreference.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 22 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
import "../../dialogs"
|
||||
import "../../controls-uit"
|
||||
|
||||
Preference {
|
||||
id: root
|
||||
property alias buttonText: button.text
|
||||
property alias text: dataTextField.text
|
||||
property alias buttonText: button.text
|
||||
property alias placeholderText: dataTextField.placeholderText
|
||||
property real spacing: 8
|
||||
property var browser;
|
||||
height: labelText.height + Math.max(dataTextField.height, button.height) + spacing
|
||||
height: control.height + hifi.dimensions.controlInterlineHeight
|
||||
|
||||
Component.onCompleted: {
|
||||
dataTextField.text = preference.value;
|
||||
|
@ -41,40 +51,48 @@ Preference {
|
|||
preference.save();
|
||||
}
|
||||
|
||||
Text {
|
||||
id: labelText
|
||||
color: enabled ? "black" : "gray"
|
||||
text: root.label
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: dataTextField
|
||||
placeholderText: root.placeholderText
|
||||
text: preference.value
|
||||
style: TextFieldStyle { renderType: Text.QtRendering }
|
||||
Item {
|
||||
id: control
|
||||
anchors {
|
||||
top: labelText.bottom
|
||||
left: parent.left
|
||||
right: button.left
|
||||
topMargin: root.spacing
|
||||
rightMargin: root.spacing
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
height: Math.max(dataTextField.controlHeight, button.height)
|
||||
|
||||
Component {
|
||||
id: avatarBrowserBuilder;
|
||||
AvatarBrowser { }
|
||||
}
|
||||
|
||||
Button {
|
||||
id: button
|
||||
anchors { right: parent.right; verticalCenter: dataTextField.verticalCenter }
|
||||
text: "Browse"
|
||||
onClicked: {
|
||||
root.browser = avatarBrowserBuilder.createObject(desktop);
|
||||
root.browser.windowDestroyed.connect(function(){
|
||||
root.browser = null;
|
||||
})
|
||||
TextField {
|
||||
id: dataTextField
|
||||
placeholderText: root.placeholderText
|
||||
text: preference.value
|
||||
label: root.label
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: button.left
|
||||
rightMargin: hifi.dimensions.contentSpacing.x
|
||||
bottom: parent.bottom
|
||||
}
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
}
|
||||
|
||||
Component {
|
||||
id: avatarBrowserBuilder;
|
||||
AvatarBrowser { }
|
||||
}
|
||||
|
||||
Button {
|
||||
id: button
|
||||
text: "Browse"
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: dataTextField.verticalCenter
|
||||
}
|
||||
onClicked: {
|
||||
root.browser = avatarBrowserBuilder.createObject(desktop);
|
||||
root.browser.windowDestroyed.connect(function(){
|
||||
root.browser = null;
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
//
|
||||
// BrowsablePreference.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 18 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
import "../../dialogs"
|
||||
import "../../controls-uit"
|
||||
|
||||
Preference {
|
||||
id: root
|
||||
property alias buttonText: button.text
|
||||
property alias text: dataTextField.text
|
||||
property alias placeholderText: dataTextField.placeholderText
|
||||
property real spacing: 8
|
||||
height: labelText.height + Math.max(dataTextField.height, button.height) + spacing
|
||||
height: control.height + hifi.dimensions.controlInterlineHeight
|
||||
|
||||
Component.onCompleted: {
|
||||
dataTextField.text = preference.value;
|
||||
|
@ -21,42 +28,49 @@ Preference {
|
|||
preference.save();
|
||||
}
|
||||
|
||||
Text {
|
||||
id: labelText
|
||||
color: enabled ? "black" : "gray"
|
||||
text: root.label
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: dataTextField
|
||||
placeholderText: root.placeholderText
|
||||
text: preference.value
|
||||
style: TextFieldStyle { renderType: Text.QtRendering }
|
||||
Item {
|
||||
id: control
|
||||
anchors {
|
||||
top: labelText.bottom
|
||||
left: parent.left
|
||||
right: button.left
|
||||
topMargin: root.spacing
|
||||
rightMargin: root.spacing
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
height: Math.max(dataTextField.controlHeight, button.height)
|
||||
|
||||
Component {
|
||||
id: fileBrowserBuilder;
|
||||
FileDialog { selectDirectory: true }
|
||||
}
|
||||
TextField {
|
||||
id: dataTextField
|
||||
|
||||
Button {
|
||||
id: button
|
||||
anchors { right: parent.right; verticalCenter: dataTextField.verticalCenter }
|
||||
text: preference.browseLabel
|
||||
onClicked: {
|
||||
var browser = fileBrowserBuilder.createObject(desktop, { selectDirectory: true, folder: fileDialogHelper.pathToUrl(preference.value) });
|
||||
browser.selectedFile.connect(function(fileUrl){
|
||||
console.log(fileUrl);
|
||||
dataTextField.text = fileDialogHelper.urlToPath(fileUrl);
|
||||
});
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: button.left
|
||||
rightMargin: hifi.dimensions.contentSpacing.x
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
label: root.label
|
||||
placeholderText: root.placeholderText
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
}
|
||||
|
||||
Component {
|
||||
id: fileBrowserBuilder;
|
||||
FileDialog { selectDirectory: true }
|
||||
}
|
||||
|
||||
Button {
|
||||
id: button
|
||||
text: preference.browseLabel
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: dataTextField.verticalCenter
|
||||
}
|
||||
onClicked: {
|
||||
var browser = fileBrowserBuilder.createObject(desktop, { selectDirectory: true, folder: fileDialogHelper.pathToUrl(preference.value) });
|
||||
browser.selectedFile.connect(function(fileUrl){
|
||||
console.log(fileUrl);
|
||||
dataTextField.text = fileDialogHelper.urlToPath(fileUrl);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,29 @@
|
|||
//
|
||||
// ButtonPreference.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 18 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
|
||||
import "../../controls-uit"
|
||||
|
||||
Preference {
|
||||
id: root
|
||||
height: button.height
|
||||
height: button.height + hifi.dimensions.controlInterlineHeight
|
||||
|
||||
Component.onCompleted: button.text = preference.name;
|
||||
|
||||
function save() { }
|
||||
|
||||
Original.Button {
|
||||
Button {
|
||||
id: button
|
||||
onClicked: preference.trigger()
|
||||
width: 180
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
//
|
||||
// CheckBoxPreference.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 18 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import "../../controls"
|
||||
|
||||
import "../../controls-uit"
|
||||
|
||||
Preference {
|
||||
id: root
|
||||
height: checkBox.implicitHeight
|
||||
height: spacer.height + Math.max(hifi.dimensions.controlLineHeight, checkBox.implicitHeight)
|
||||
|
||||
Component.onCompleted: {
|
||||
checkBox.checked = preference.value;
|
||||
|
@ -16,9 +26,25 @@ Preference {
|
|||
preference.save();
|
||||
}
|
||||
|
||||
Item {
|
||||
id: spacer
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
height: isFirstCheckBox ? hifi.dimensions.controlInterlineHeight : 0
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: checkBox
|
||||
anchors.fill: parent
|
||||
anchors {
|
||||
top: spacer.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
text: root.label
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,26 @@
|
|||
//
|
||||
// ComboBoxPreference.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 18 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import "../../controls-uit" as HiFiControls
|
||||
import "../../styles-uit"
|
||||
|
||||
Preference {
|
||||
id: root
|
||||
property real spacing: 8
|
||||
height: labelText.height + dataComboBox.height + spacing
|
||||
height: control.height + hifi.dimensions.controlInterlineHeight
|
||||
|
||||
Component.onCompleted: {
|
||||
dataComboBox.currentIndex = dataComboBox.find(preference.value);
|
||||
dataComboBox.currentIndex = dataComboBox.comboBox.find(preference.value);
|
||||
}
|
||||
|
||||
function save() {
|
||||
|
@ -16,22 +28,38 @@ Preference {
|
|||
preference.save();
|
||||
}
|
||||
|
||||
Text {
|
||||
id: labelText
|
||||
color: enabled ? "black" : "gray"
|
||||
text: root.label
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: dataComboBox
|
||||
model: preference.items
|
||||
style: ComboBoxStyle { renderType: Text.QtRendering }
|
||||
Item {
|
||||
id: control
|
||||
anchors {
|
||||
top: labelText.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
topMargin: root.spacing
|
||||
rightMargin: root.spacing
|
||||
bottom: parent.bottom
|
||||
}
|
||||
height: Math.max(labelText.height, dataComboBox.controlHeight)
|
||||
|
||||
HiFiControls.Label {
|
||||
id: labelText
|
||||
text: root.label + ":"
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: dataComboBox.left
|
||||
rightMargin: hifi.dimensions.labelPadding
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
horizontalAlignment: Text.AlignRight
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
HiFiControls.ComboBox {
|
||||
id: dataComboBox
|
||||
model: preference.items
|
||||
width: 150
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
//
|
||||
// EditablePreference.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 18 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
import "../../dialogs"
|
||||
import "../../controls-uit"
|
||||
|
||||
Preference {
|
||||
id: root
|
||||
property real spacing: 8
|
||||
height: labelText.height + dataTextField.height + spacing
|
||||
height: dataTextField.controlHeight + hifi.dimensions.controlInterlineHeight
|
||||
|
||||
Component.onCompleted: {
|
||||
dataTextField.text = preference.value;
|
||||
|
@ -16,22 +26,16 @@ Preference {
|
|||
preference.save();
|
||||
}
|
||||
|
||||
Text {
|
||||
id: labelText
|
||||
color: enabled ? "black" : "gray"
|
||||
text: root.label
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: dataTextField
|
||||
placeholderText: preference.placeholderText
|
||||
style: TextFieldStyle { renderType: Text.QtRendering }
|
||||
label: root.label
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
|
||||
anchors {
|
||||
top: labelText.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
topMargin: root.spacing
|
||||
rightMargin: root.spacing
|
||||
bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
//
|
||||
// Preference.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 18 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
|
@ -6,6 +16,7 @@ Item {
|
|||
anchors { left: parent.left; right: parent.right }
|
||||
property var preference;
|
||||
property string label: preference ? preference.name : "";
|
||||
property bool isFirstCheckBox;
|
||||
Component.onCompleted: {
|
||||
if (preference) {
|
||||
preference.load();
|
||||
|
|
|
@ -1,20 +1,33 @@
|
|||
//
|
||||
// Section.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 18 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import Hifi 1.0
|
||||
|
||||
import "../../controls" as VrControls
|
||||
import "../../controls-uit" as HiFiControls
|
||||
import "../../styles-uit"
|
||||
import "."
|
||||
|
||||
Preference {
|
||||
id: root
|
||||
property bool collapsable: true
|
||||
property bool expanded: false
|
||||
property bool isFirst: false
|
||||
property bool isLast: false
|
||||
property string name: "Header"
|
||||
property real spacing: 8
|
||||
readonly property alias toggle: toggle
|
||||
readonly property alias header: header
|
||||
default property alias preferences: contentContainer.children
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
function saveAll() {
|
||||
for (var i = 0; i < d.preferences.length; ++i) {
|
||||
var preference = d.preferences[i];
|
||||
|
@ -29,47 +42,24 @@ Preference {
|
|||
}
|
||||
}
|
||||
|
||||
clip: true
|
||||
children: [ toggle, header, contentContainer ]
|
||||
height: expanded ? header.height + contentContainer.height + root.spacing * 3
|
||||
: Math.max(toggle.height, header.height) + root.spacing * 2
|
||||
Behavior on height { PropertyAnimation {} }
|
||||
children: [ contentContainer ]
|
||||
|
||||
height: contentContainer.height + (root.isLast ? 2 * hifi.dimensions.contentSpacing.y : 0)
|
||||
|
||||
Component.onCompleted: d.buildPreferences();
|
||||
|
||||
function toggleExpanded() {
|
||||
root.expanded = !root.expanded;
|
||||
}
|
||||
|
||||
VrControls.FontAwesome {
|
||||
id: toggle
|
||||
width: root.collapsable ? height : 0
|
||||
anchors { left: parent.left; top: parent.top; margins: root.spacing }
|
||||
visible: root.collapsable
|
||||
enabled: root.collapsable
|
||||
rotation: root.expanded ? 0 : -90
|
||||
text: "\uf078"
|
||||
Behavior on rotation { PropertyAnimation {} }
|
||||
MouseArea { anchors.fill: parent; onClicked: root.toggleExpanded() }
|
||||
}
|
||||
|
||||
Text {
|
||||
id: header
|
||||
anchors { left: toggle.right; top: parent.top; leftMargin: root.spacing * 2; margins: root.spacing }
|
||||
font.bold: true
|
||||
font.pointSize: 16
|
||||
color: "#0e7077"
|
||||
text: root.name
|
||||
MouseArea { anchors.fill: parent; onClicked: root.toggleExpanded() }
|
||||
}
|
||||
|
||||
Column {
|
||||
HiFiControls.ContentSection {
|
||||
id: contentContainer
|
||||
spacing: root.spacing
|
||||
anchors { left: toggle.right; top: header.bottom; topMargin: root.spacing; right: parent.right; margins: root.spacing }
|
||||
enabled: root.expanded
|
||||
visible: root.expanded
|
||||
clip: true
|
||||
name: root.name
|
||||
isFirst: root.isFirst
|
||||
isCollapsible: root.collapsable
|
||||
isCollapsed: !root.expanded
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
margins: 0
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
|
@ -83,6 +73,7 @@ Preference {
|
|||
property var buttonBuilder: Component { ButtonPreference { } }
|
||||
property var comboBoxBuilder: Component { ComboBoxPreference { } }
|
||||
property var preferences: []
|
||||
property int checkBoxCount: 0
|
||||
|
||||
function buildPreferences() {
|
||||
var categoryPreferences = Preferences.preferencesByCategory[root.name];
|
||||
|
@ -99,40 +90,49 @@ Preference {
|
|||
var builder;
|
||||
switch (preference.type) {
|
||||
case Preference.Editable:
|
||||
checkBoxCount = 0;
|
||||
builder = editableBuilder;
|
||||
break;
|
||||
|
||||
case Preference.Browsable:
|
||||
checkBoxCount = 0;
|
||||
builder = browsableBuilder;
|
||||
break;
|
||||
|
||||
case Preference.Spinner:
|
||||
checkBoxCount = 0;
|
||||
builder = spinnerBuilder;
|
||||
break;
|
||||
|
||||
case Preference.Slider:
|
||||
checkBoxCount = 0;
|
||||
builder = sliderBuilder;
|
||||
break;
|
||||
|
||||
case Preference.Checkbox:
|
||||
checkBoxCount++;
|
||||
console.log("####### checkBoxCount = " + checkBoxCount);
|
||||
builder = checkboxBuilder;
|
||||
break;
|
||||
|
||||
case Preference.Avatar:
|
||||
checkBoxCount = 0;
|
||||
builder = avatarBuilder;
|
||||
break;
|
||||
|
||||
case Preference.Button:
|
||||
checkBoxCount = 0;
|
||||
builder = buttonBuilder;
|
||||
break;
|
||||
|
||||
case Preference.ComboBox:
|
||||
checkBoxCount = 0;
|
||||
builder = comboBoxBuilder;
|
||||
break;
|
||||
};
|
||||
|
||||
if (builder) {
|
||||
preferences.push(builder.createObject(contentContainer, { preference: preference }));
|
||||
preferences.push(builder.createObject(contentContainer, { preference: preference, isFirstCheckBox: (checkBoxCount === 1) }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
//
|
||||
// SpinBoxPreference.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 18 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
import "../../dialogs"
|
||||
import "../../controls-uit"
|
||||
|
||||
Preference {
|
||||
id: root
|
||||
property alias slider: slider
|
||||
height: slider.height
|
||||
height: control.height + hifi.dimensions.controlInterlineHeight
|
||||
|
||||
Component.onCompleted: {
|
||||
slider.value = preference.value;
|
||||
|
@ -15,16 +27,38 @@ Preference {
|
|||
preference.save();
|
||||
}
|
||||
|
||||
Text {
|
||||
text: root.label
|
||||
color: enabled ? "black" : "gray"
|
||||
anchors.verticalCenter: slider.verticalCenter
|
||||
}
|
||||
Item {
|
||||
id: control
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
height: Math.max(labelText.height, slider.height)
|
||||
|
||||
Slider {
|
||||
id: slider
|
||||
value: preference.value
|
||||
width: 130
|
||||
anchors { right: parent.right }
|
||||
Label {
|
||||
id: labelText
|
||||
text: root.label + ":"
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: slider.left
|
||||
rightMargin: hifi.dimensions.labelPadding
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
horizontalAlignment: Text.AlignRight
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: slider
|
||||
value: preference.value
|
||||
width: 130
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,21 @@
|
|||
//
|
||||
// SpinBoxPreference.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 18 Jan 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
import "../../controls-uit"
|
||||
|
||||
Preference {
|
||||
id: root
|
||||
property alias spinner: spinner
|
||||
height: spinner.height
|
||||
height: control.height + hifi.dimensions.controlInterlineHeight
|
||||
|
||||
Component.onCompleted: {
|
||||
spinner.value = preference.value;
|
||||
|
@ -15,18 +26,40 @@ Preference {
|
|||
preference.save();
|
||||
}
|
||||
|
||||
Text {
|
||||
text: root.label
|
||||
color: root.enabled ? "black" : "gray"
|
||||
anchors.verticalCenter: spinner.verticalCenter
|
||||
}
|
||||
Item {
|
||||
id: control
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
height: Math.max(spinnerLabel.height, spinner.controlHeight)
|
||||
|
||||
SpinBox {
|
||||
id: spinner
|
||||
decimals: preference.decimals
|
||||
minimumValue: preference.min
|
||||
maximumValue: preference.max
|
||||
width: 100
|
||||
anchors { right: parent.right }
|
||||
Label {
|
||||
id: spinnerLabel
|
||||
text: root.label + ":"
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: spinner.left
|
||||
rightMargin: hifi.dimensions.labelPadding
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
horizontalAlignment: Text.AlignRight
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
SpinBox {
|
||||
id: spinner
|
||||
decimals: preference.decimals
|
||||
minimumValue: preference.min
|
||||
maximumValue: preference.max
|
||||
width: 100
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import "../../dialogs"
|
|||
PreferencesDialog {
|
||||
id: root
|
||||
objectName: "AudioPreferencesDialog"
|
||||
title: "Audio Preferences"
|
||||
title: "Audio Settings"
|
||||
showCategories: ["Audio"]
|
||||
property var settings: Settings {
|
||||
category: root.objectName
|
||||
|
|
|
@ -6,7 +6,7 @@ import "../../dialogs"
|
|||
PreferencesDialog {
|
||||
id: root
|
||||
objectName: "AvatarPreferencesDialog"
|
||||
title: "Avatar Preferences"
|
||||
title: "Avatar Settings"
|
||||
showCategories: [ "Avatar Basics", "Avatar Tuning", "Avatar Camera" ]
|
||||
property var settings: Settings {
|
||||
category: root.objectName
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
//
|
||||
// PreferencesDialog.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 24 Jan 2016
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
|
@ -6,7 +16,7 @@ import "../../dialogs"
|
|||
PreferencesDialog {
|
||||
id: root
|
||||
objectName: "GeneralPreferencesDialog"
|
||||
title: "General Preferences"
|
||||
title: "General Settings"
|
||||
showCategories: ["Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers"]
|
||||
property var settings: Settings {
|
||||
category: root.objectName
|
||||
|
|
|
@ -6,7 +6,7 @@ import "../../dialogs"
|
|||
PreferencesDialog {
|
||||
id: root
|
||||
objectName: "GraphicsPreferencesDialog"
|
||||
title: "Graphics Preferences"
|
||||
title: "Graphics Settings"
|
||||
showCategories: ["Graphics"]
|
||||
property var settings: Settings {
|
||||
category: root.objectName
|
||||
|
|
|
@ -6,7 +6,7 @@ import "../../dialogs"
|
|||
PreferencesDialog {
|
||||
id: root
|
||||
objectName: "LodPreferencesDialog"
|
||||
title: "Level of Detail preferences"
|
||||
title: "LOD Settings"
|
||||
showCategories: ["Level of Detail Tuning"]
|
||||
property var settings: Settings {
|
||||
category: root.objectName
|
||||
|
|
|
@ -24,7 +24,7 @@ Window {
|
|||
resizable: true
|
||||
destroyOnInvisible: true
|
||||
x: 40; y: 40
|
||||
implicitWidth: 384; implicitHeight: 640
|
||||
implicitWidth: 400; implicitHeight: 695
|
||||
minSize: Qt.vector2d(200, 300)
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
@ -87,8 +87,11 @@ Window {
|
|||
Column {
|
||||
width: pane.contentWidth
|
||||
|
||||
HifiControls.StaticSection {
|
||||
HifiControls.ContentSection {
|
||||
name: "Currently Running"
|
||||
isFirst: true
|
||||
|
||||
HifiControls.VerticalSpacer {}
|
||||
|
||||
Row {
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
|
@ -106,6 +109,8 @@ Window {
|
|||
}
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {}
|
||||
|
||||
HifiControls.Table {
|
||||
tableModel: runningScriptsModel
|
||||
height: 185
|
||||
|
@ -113,11 +118,16 @@ Window {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {
|
||||
height: 2 // Table view draws a little taller than it's height.
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.StaticSection {
|
||||
HifiControls.ContentSection {
|
||||
name: "Load Scripts"
|
||||
hasSeparator: true
|
||||
|
||||
HifiControls.VerticalSpacer {}
|
||||
|
||||
Row {
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
|
@ -161,18 +171,21 @@ Window {
|
|||
}
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {}
|
||||
|
||||
HifiControls.TextField {
|
||||
id: filterEdit
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
focus: true
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
//placeholderText: "filter"
|
||||
label: "Filter"
|
||||
placeholderText: "filter"
|
||||
onTextChanged: scriptsModel.filterRegExp = new RegExp("^.*" + text + ".*$", "i")
|
||||
Component.onCompleted: scriptsModel.filterRegExp = new RegExp("^.*$", "i")
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {}
|
||||
|
||||
HifiControls.Tree {
|
||||
id: treeView
|
||||
height: 155
|
||||
|
@ -182,6 +195,8 @@ Window {
|
|||
anchors.right: parent.right
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {}
|
||||
|
||||
HifiControls.TextField {
|
||||
id: selectedScript
|
||||
anchors.left: parent.left
|
||||
|
|
|
@ -48,11 +48,13 @@ Item {
|
|||
|
||||
// Other colors
|
||||
readonly property color white: "#ffffff"
|
||||
readonly property color gray: "#808080"
|
||||
readonly property color black: "#000000"
|
||||
// Semitransparent
|
||||
readonly property color white50: "#80ffffff"
|
||||
readonly property color white30: "#4dffffff"
|
||||
readonly property color white25: "#40ffffff"
|
||||
readonly property color transparent: "#00ffffff"
|
||||
|
||||
// Control specific colors
|
||||
readonly property color tableRowLightOdd: white50
|
||||
|
@ -61,6 +63,26 @@ Item {
|
|||
readonly property color tableRowDarkEven: "#a6181818"
|
||||
readonly property color tableScrollHandle: "#707070"
|
||||
readonly property color tableScrollBackground: "#323232"
|
||||
readonly property color checkboxLightStart: "#ffffff"
|
||||
readonly property color checkboxLightFinish: "#afafaf"
|
||||
readonly property color checkboxDarkStart: "#7d7d7d"
|
||||
readonly property color checkboxDarkFinish: "#6b6a6b"
|
||||
readonly property color checkboxChecked: primaryHighlight
|
||||
readonly property color checkboxCheckedBorder: "#36cdff"
|
||||
readonly property color sliderGutterLight: "#d4d4d4"
|
||||
readonly property color sliderGutterDark: "#252525"
|
||||
readonly property color sliderBorderLight: "#afafaf"
|
||||
readonly property color sliderBorderDark: "#7d7d7d"
|
||||
readonly property color sliderLightStart: "#ffffff"
|
||||
readonly property color sliderLightFinish: "#afafaf"
|
||||
readonly property color sliderDarkStart: "#7d7d7d"
|
||||
readonly property color sliderDarkFinish: "#6b6a6b"
|
||||
readonly property color dropDownPressedLight: "#d4d4d4"
|
||||
readonly property color dropDownPressedDark: "#afafaf"
|
||||
readonly property color dropDownLightStart: "#ffffff"
|
||||
readonly property color dropDownLightFinish: "#afafaf"
|
||||
readonly property color dropDownDarkStart: "#7d7d7d"
|
||||
readonly property color dropDownDarkFinish: "#6b6a6b"
|
||||
}
|
||||
|
||||
Item {
|
||||
|
@ -76,39 +98,54 @@ Item {
|
|||
readonly property real borderWidth: largeScreen ? 2 : 1
|
||||
readonly property vector2d contentMargin: Qt.vector2d(12, 24)
|
||||
readonly property vector2d contentSpacing: Qt.vector2d(8, 12)
|
||||
readonly property real labelPadding: 40
|
||||
readonly property real textPadding: 8
|
||||
readonly property real sliderHandleSize: 18
|
||||
readonly property real sliderGrooveHeight: 8
|
||||
readonly property real spinnerSize: 42
|
||||
readonly property real tablePadding: 12
|
||||
readonly property real tableRowHeight: largeScreen ? 26 : 23
|
||||
readonly property vector2d modalDialogMargin: Qt.vector2d(50, 30)
|
||||
readonly property real modalDialogTitleHeight: 40
|
||||
readonly property real controlLineHeight: 29 // Height of spinbox control on 1920 x 1080 monitor
|
||||
readonly property real controlInterlineHeight: 22 // 75% of controlLineHeight
|
||||
}
|
||||
|
||||
Item {
|
||||
id: fontSizes // In pixels
|
||||
readonly property real overlayTitle: dimensions.largeScreen? 18 : 14
|
||||
readonly property real tabName: dimensions.largeScreen? 12 : 10
|
||||
readonly property real sectionName: dimensions.largeScreen? 12 : 10
|
||||
readonly property real inputLabel: dimensions.largeScreen? 14 : 10
|
||||
readonly property real textFieldInput: dimensions.largeScreen? 15 : 12
|
||||
readonly property real tableText: dimensions.largeScreen? 15 : 12
|
||||
readonly property real buttonLabel: dimensions.largeScreen? 13 : 9
|
||||
readonly property real iconButton: dimensions.largeScreen? 13 : 9
|
||||
readonly property real listItem: dimensions.largeScreen? 15 : 11
|
||||
readonly property real tabularData: dimensions.largeScreen? 15 : 11
|
||||
readonly property real logs: dimensions.largeScreen? 16 : 12
|
||||
readonly property real code: dimensions.largeScreen? 16 : 12
|
||||
readonly property real rootMenu: dimensions.largeScreen? 15 : 11
|
||||
readonly property real menuItem: dimensions.largeScreen? 15 : 11
|
||||
readonly property real shortcutText: dimensions.largeScreen? 13 : 9
|
||||
readonly property real overlayTitle: dimensions.largeScreen ? 18 : 14
|
||||
readonly property real tabName: dimensions.largeScreen ? 12 : 10
|
||||
readonly property real sectionName: dimensions.largeScreen ? 12 : 10
|
||||
readonly property real inputLabel: dimensions.largeScreen ? 14 : 10
|
||||
readonly property real textFieldInput: dimensions.largeScreen ? 15 : 12
|
||||
readonly property real tableText: dimensions.largeScreen ? 15 : 12
|
||||
readonly property real buttonLabel: dimensions.largeScreen ? 13 : 9
|
||||
readonly property real iconButton: dimensions.largeScreen ? 13 : 9
|
||||
readonly property real listItem: dimensions.largeScreen ? 15 : 11
|
||||
readonly property real tabularData: dimensions.largeScreen ? 15 : 11
|
||||
readonly property real logs: dimensions.largeScreen ? 16 : 12
|
||||
readonly property real code: dimensions.largeScreen ? 16 : 12
|
||||
readonly property real rootMenu: dimensions.largeScreen ? 15 : 11
|
||||
readonly property real menuItem: dimensions.largeScreen ? 15 : 11
|
||||
readonly property real shortcutText: dimensions.largeScreen ? 13 : 9
|
||||
readonly property real carat: dimensions.largeScreen ? 38 : 30
|
||||
readonly property real disclosureButton: dimensions.largeScreen ? 20 : 15
|
||||
}
|
||||
|
||||
Item {
|
||||
id: glyphs
|
||||
readonly property string backward: "E"
|
||||
readonly property string caratDn: "5"
|
||||
readonly property string caratR: "3"
|
||||
readonly property string caratUp: "6"
|
||||
readonly property string close: "w"
|
||||
readonly property string closeInverted: "x"
|
||||
readonly property string closeSmall: "C"
|
||||
readonly property string disclosureButtonCollapse: "M"
|
||||
readonly property string disclosureButtonExpand: "L"
|
||||
readonly property string disclosureCollapse: "Z"
|
||||
readonly property string disclosureExpand: "B"
|
||||
readonly property string forward: "D"
|
||||
readonly property string pin: "y"
|
||||
readonly property string pinInverted: "z"
|
||||
readonly property string reloadSmall: "a"
|
||||
|
|
|
@ -99,8 +99,8 @@ Frame {
|
|||
DropShadow {
|
||||
source: titleText
|
||||
anchors.fill: titleText
|
||||
horizontalOffset: 1
|
||||
verticalOffset: 1
|
||||
horizontalOffset: 2
|
||||
verticalOffset: 2
|
||||
samples: 2
|
||||
color: hifi.colors.baseGrayShadow60
|
||||
visible: (window && window.focus)
|
||||
|
|
|
@ -58,6 +58,8 @@ Fadable {
|
|||
// The content to place inside the window, determined by the client
|
||||
default property var content
|
||||
|
||||
property var footer: Item { } // Optional static footer at the bottom of the dialog.
|
||||
|
||||
function setDefaultFocus() {} // Default function; can be overridden by dialogs.
|
||||
|
||||
property var rectifier: Timer {
|
||||
|
@ -125,7 +127,8 @@ Fadable {
|
|||
// Scrollable window content.
|
||||
property var pane: Item {
|
||||
property bool isScrolling: scrollView.height < scrollView.contentItem.height
|
||||
property int contentWidth: scrollView.width - (isScrolling ? 11 : 0)
|
||||
property int contentWidth: scrollView.width - (isScrolling ? 10 : 0)
|
||||
property int scrollHeight: scrollView.height
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: isScrolling ? 11 : 0
|
||||
|
@ -162,6 +165,7 @@ Fadable {
|
|||
verticalScrollBarPolicy: Qt.ScrollBarAsNeeded
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: parent.isScrolling ? 1 : 0
|
||||
anchors.bottomMargin: footer.height > 0 ? footerPane.height : 0
|
||||
|
||||
style: ScrollViewStyle {
|
||||
|
||||
|
@ -203,7 +207,46 @@ Fadable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
// Optional non-scrolling footer.
|
||||
id: footerPane
|
||||
anchors {
|
||||
left: parent.left
|
||||
bottom: parent.bottom
|
||||
}
|
||||
width: parent.contentWidth
|
||||
height: footer.height + 2 * hifi.dimensions.contentSpacing.y
|
||||
color: hifi.colors.baseGray
|
||||
visible: footer.height > 0
|
||||
|
||||
Item {
|
||||
// Horizontal rule.
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 1
|
||||
y: 1 // Stop displaying content just above horizontal rule/=.
|
||||
color: hifi.colors.baseGrayShadow
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 1
|
||||
y: 2
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 3 // Horizontal rule.
|
||||
children: [ footer ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
children: [ swallower, frame, pane, activator ]
|
||||
|
||||
Component.onCompleted: { raise(); setDefaultFocus(); }
|
||||
|
|
|
@ -544,7 +544,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
connect(&domainHandler, SIGNAL(connectedToDomain(const QString&)), SLOT(updateWindowTitle()));
|
||||
connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle()));
|
||||
connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(clearDomainOctreeDetails()));
|
||||
connect(&domainHandler, &DomainHandler::settingsReceived, this, &Application::domainSettingsReceived);
|
||||
|
||||
// update our location every 5 seconds in the metaverse server, assuming that we are authenticated with one
|
||||
const qint64 DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS = 5 * 1000;
|
||||
|
@ -581,6 +580,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle);
|
||||
|
||||
// set the account manager's root URL and trigger a login request if we don't have the access token
|
||||
accountManager.setIsAgent(true);
|
||||
accountManager.setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL);
|
||||
UserActivityLogger::getInstance().launch(applicationVersion());
|
||||
|
||||
|
@ -889,9 +889,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
SpacemouseManager::getInstance().init();
|
||||
#endif
|
||||
|
||||
auto& packetReceiver = nodeList->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::DomainConnectionDenied, this, "handleDomainConnectionDeniedPacket");
|
||||
|
||||
// If the user clicks an an entity, we will check that it's an unlocked web entity, and if so, set the focus to it
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickDownOnEntity,
|
||||
|
@ -3819,7 +3816,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
|||
// Setup the current Zone Entity lighting
|
||||
{
|
||||
auto stage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
||||
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(stage->getSunLight(), stage->getSkybox()->getCubemap());
|
||||
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(stage->getSunLight());
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -3955,29 +3952,10 @@ void Application::clearDomainOctreeDetails() {
|
|||
void Application::domainChanged(const QString& domainHostname) {
|
||||
updateWindowTitle();
|
||||
clearDomainOctreeDetails();
|
||||
_domainConnectionRefusals.clear();
|
||||
// disable physics until we have enough information about our new location to not cause craziness.
|
||||
_physicsEnabled = false;
|
||||
}
|
||||
|
||||
void Application::handleDomainConnectionDeniedPacket(QSharedPointer<ReceivedMessage> message) {
|
||||
// Read deny reason from packet
|
||||
quint16 reasonSize;
|
||||
message->readPrimitive(&reasonSize);
|
||||
QString reason = QString::fromUtf8(message->readWithoutCopy(reasonSize));
|
||||
|
||||
// output to the log so the user knows they got a denied connection request
|
||||
// and check and signal for an access token so that we can make sure they are logged in
|
||||
qCDebug(interfaceapp) << "The domain-server denied a connection request: " << reason;
|
||||
qCDebug(interfaceapp) << "You may need to re-log to generate a keypair so you can provide a username signature.";
|
||||
|
||||
if (!_domainConnectionRefusals.contains(reason)) {
|
||||
_domainConnectionRefusals.append(reason);
|
||||
emit domainConnectionRefused(reason);
|
||||
}
|
||||
|
||||
AccountManager::getInstance().checkAndSignalForAccessToken();
|
||||
}
|
||||
|
||||
void Application::resettingDomain() {
|
||||
_notifiedPacketVersionMismatchThisDomain = false;
|
||||
|
@ -4517,33 +4495,6 @@ void Application::openUrl(const QUrl& url) {
|
|||
}
|
||||
}
|
||||
|
||||
void Application::domainSettingsReceived(const QJsonObject& domainSettingsObject) {
|
||||
// from the domain-handler, figure out the satoshi cost per voxel and per meter cubed
|
||||
const QString VOXEL_SETTINGS_KEY = "voxels";
|
||||
const QString PER_VOXEL_COST_KEY = "per-voxel-credits";
|
||||
const QString PER_METER_CUBED_COST_KEY = "per-meter-cubed-credits";
|
||||
const QString VOXEL_WALLET_UUID = "voxel-wallet";
|
||||
|
||||
const QJsonObject& voxelObject = domainSettingsObject[VOXEL_SETTINGS_KEY].toObject();
|
||||
|
||||
qint64 satoshisPerVoxel = 0;
|
||||
qint64 satoshisPerMeterCubed = 0;
|
||||
QUuid voxelWalletUUID;
|
||||
|
||||
if (!domainSettingsObject.isEmpty()) {
|
||||
float perVoxelCredits = (float) voxelObject[PER_VOXEL_COST_KEY].toDouble();
|
||||
float perMeterCubedCredits = (float) voxelObject[PER_METER_CUBED_COST_KEY].toDouble();
|
||||
|
||||
satoshisPerVoxel = (qint64) floorf(perVoxelCredits * SATOSHIS_PER_CREDIT);
|
||||
satoshisPerMeterCubed = (qint64) floorf(perMeterCubedCredits * SATOSHIS_PER_CREDIT);
|
||||
|
||||
voxelWalletUUID = QUuid(voxelObject[VOXEL_WALLET_UUID].toString());
|
||||
}
|
||||
|
||||
qCDebug(interfaceapp) << "Octree edits costs are" << satoshisPerVoxel << "per octree cell and" << satoshisPerMeterCubed << "per meter cubed";
|
||||
qCDebug(interfaceapp) << "Destination wallet UUID for edit payments is" << voxelWalletUUID;
|
||||
}
|
||||
|
||||
void Application::loadDialog() {
|
||||
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||
QString fileNameString = OffscreenUi::getOpenFileName(
|
||||
|
|
|
@ -227,7 +227,6 @@ signals:
|
|||
void svoImportRequested(const QString& url);
|
||||
|
||||
void checkBackgroundDownloads();
|
||||
void domainConnectionRefused(const QString& reason);
|
||||
|
||||
void fullAvatarURLChanged(const QString& newValue, const QString& modelName);
|
||||
|
||||
|
@ -297,9 +296,6 @@ private slots:
|
|||
|
||||
void activeChanged(Qt::ApplicationState state);
|
||||
|
||||
void domainSettingsReceived(const QJsonObject& domainSettingsObject);
|
||||
void handleDomainConnectionDeniedPacket(QSharedPointer<ReceivedMessage> message);
|
||||
|
||||
void notifyPacketVersionMismatch();
|
||||
|
||||
void loadSettings();
|
||||
|
@ -476,7 +472,6 @@ private:
|
|||
typedef bool (Application::* AcceptURLMethod)(const QString &);
|
||||
static const QHash<QString, AcceptURLMethod> _acceptedExtensions;
|
||||
|
||||
QList<QString> _domainConnectionRefusals;
|
||||
glm::uvec2 _renderResolution;
|
||||
|
||||
int _maxOctreePPS = DEFAULT_MAX_OCTREE_PPS;
|
||||
|
|
|
@ -22,11 +22,8 @@
|
|||
#include <QStandardPaths>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "DataServerAccountInfo.h"
|
||||
#include "Menu.h"
|
||||
|
||||
Q_DECLARE_METATYPE(DataServerAccountInfo)
|
||||
|
||||
static const QString RUNNING_MARKER_FILENAME = "Interface.running";
|
||||
|
||||
void CrashHandler::checkForAndHandleCrash() {
|
||||
|
@ -57,7 +54,7 @@ CrashHandler::Action CrashHandler::promptUserForAction() {
|
|||
layout->addWidget(label);
|
||||
|
||||
QRadioButton* option1 = new QRadioButton("Reset all my settings");
|
||||
QRadioButton* option2 = new QRadioButton("Reset my settings but retain login and avatar info.");
|
||||
QRadioButton* option2 = new QRadioButton("Reset my settings but retain avatar info.");
|
||||
QRadioButton* option3 = new QRadioButton("Continue with my current settings");
|
||||
option3->setChecked(true);
|
||||
layout->addWidget(option1);
|
||||
|
@ -79,7 +76,7 @@ CrashHandler::Action CrashHandler::promptUserForAction() {
|
|||
return CrashHandler::DELETE_INTERFACE_INI;
|
||||
}
|
||||
if (option2->isChecked()) {
|
||||
return CrashHandler::RETAIN_LOGIN_AND_AVATAR_INFO;
|
||||
return CrashHandler::RETAIN_AVATAR_INFO;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,7 +85,7 @@ CrashHandler::Action CrashHandler::promptUserForAction() {
|
|||
}
|
||||
|
||||
void CrashHandler::handleCrash(CrashHandler::Action action) {
|
||||
if (action != CrashHandler::DELETE_INTERFACE_INI && action != CrashHandler::RETAIN_LOGIN_AND_AVATAR_INFO) {
|
||||
if (action != CrashHandler::DELETE_INTERFACE_INI && action != CrashHandler::RETAIN_AVATAR_INFO) {
|
||||
// CrashHandler::DO_NOTHING or unexpected value
|
||||
return;
|
||||
}
|
||||
|
@ -101,18 +98,13 @@ void CrashHandler::handleCrash(CrashHandler::Action action) {
|
|||
const QString DISPLAY_NAME_KEY = "displayName";
|
||||
const QString FULL_AVATAR_URL_KEY = "fullAvatarURL";
|
||||
const QString FULL_AVATAR_MODEL_NAME_KEY = "fullAvatarModelName";
|
||||
const QString ACCOUNTS_GROUP = "accounts";
|
||||
QString displayName;
|
||||
QUrl fullAvatarURL;
|
||||
QString fullAvatarModelName;
|
||||
QUrl address;
|
||||
QMap<QString, DataServerAccountInfo> accounts;
|
||||
|
||||
if (action == CrashHandler::RETAIN_LOGIN_AND_AVATAR_INFO) {
|
||||
// Read login and avatar info
|
||||
|
||||
qRegisterMetaType<DataServerAccountInfo>("DataServerAccountInfo");
|
||||
qRegisterMetaTypeStreamOperators<DataServerAccountInfo>("DataServerAccountInfo");
|
||||
if (action == CrashHandler::RETAIN_AVATAR_INFO) {
|
||||
// Read avatar info
|
||||
|
||||
// Location and orientation
|
||||
settings.beginGroup(ADDRESS_MANAGER_GROUP);
|
||||
|
@ -125,13 +117,6 @@ void CrashHandler::handleCrash(CrashHandler::Action action) {
|
|||
fullAvatarURL = settings.value(FULL_AVATAR_URL_KEY).toUrl();
|
||||
fullAvatarModelName = settings.value(FULL_AVATAR_MODEL_NAME_KEY).toString();
|
||||
settings.endGroup();
|
||||
|
||||
// Accounts
|
||||
settings.beginGroup(ACCOUNTS_GROUP);
|
||||
foreach(const QString& key, settings.allKeys()) {
|
||||
accounts.insert(key, settings.value(key).value<DataServerAccountInfo>());
|
||||
}
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
// Delete Interface.ini
|
||||
|
@ -140,8 +125,8 @@ void CrashHandler::handleCrash(CrashHandler::Action action) {
|
|||
settingsFile.remove();
|
||||
}
|
||||
|
||||
if (action == CrashHandler::RETAIN_LOGIN_AND_AVATAR_INFO) {
|
||||
// Write login and avatar info
|
||||
if (action == CrashHandler::RETAIN_AVATAR_INFO) {
|
||||
// Write avatar info
|
||||
|
||||
// Location and orientation
|
||||
settings.beginGroup(ADDRESS_MANAGER_GROUP);
|
||||
|
@ -154,13 +139,6 @@ void CrashHandler::handleCrash(CrashHandler::Action action) {
|
|||
settings.setValue(FULL_AVATAR_URL_KEY, fullAvatarURL);
|
||||
settings.setValue(FULL_AVATAR_MODEL_NAME_KEY, fullAvatarModelName);
|
||||
settings.endGroup();
|
||||
|
||||
// Accounts
|
||||
settings.beginGroup(ACCOUNTS_GROUP);
|
||||
foreach(const QString& key, accounts.keys()) {
|
||||
settings.setValue(key, QVariant::fromValue(accounts.value(key)));
|
||||
}
|
||||
settings.endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
private:
|
||||
enum Action {
|
||||
DELETE_INTERFACE_INI,
|
||||
RETAIN_LOGIN_AND_AVATAR_INFO,
|
||||
RETAIN_AVATAR_INFO,
|
||||
DO_NOTHING
|
||||
};
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ MainWindow::MainWindow(QWidget* parent) :
|
|||
_windowState("WindowState", 0)
|
||||
{
|
||||
setAcceptDrops(true);
|
||||
_trayIcon.show();
|
||||
}
|
||||
|
||||
void MainWindow::restoreGeometry() {
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#define __hifi__MainWindow__
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QSystemTrayIcon>
|
||||
|
||||
#include <SettingHandle.h>
|
||||
|
||||
|
@ -43,7 +42,6 @@ protected:
|
|||
private:
|
||||
Setting::Handle<QRect> _windowGeometry;
|
||||
Setting::Handle<int> _windowState;
|
||||
QSystemTrayIcon _trayIcon;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__MainWindow__) */
|
||||
|
|
|
@ -342,9 +342,9 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename
|
|||
void ModelPackager::listTextures() {
|
||||
_textures.clear();
|
||||
foreach (const FBXMaterial mat, _geometry->materials) {
|
||||
if (!mat.diffuseTexture.filename.isEmpty() && mat.diffuseTexture.content.isEmpty() &&
|
||||
!_textures.contains(mat.diffuseTexture.filename)) {
|
||||
_textures << mat.diffuseTexture.filename;
|
||||
if (!mat.albedoTexture.filename.isEmpty() && mat.albedoTexture.content.isEmpty() &&
|
||||
!_textures.contains(mat.albedoTexture.filename)) {
|
||||
_textures << mat.albedoTexture.filename;
|
||||
}
|
||||
if (!mat.normalTexture.filename.isEmpty() && mat.normalTexture.content.isEmpty() &&
|
||||
!_textures.contains(mat.normalTexture.filename)) {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
WindowScriptingInterface::WindowScriptingInterface() {
|
||||
const DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();
|
||||
connect(&domainHandler, &DomainHandler::connectedToDomain, this, &WindowScriptingInterface::domainChanged);
|
||||
connect(qApp, &Application::domainConnectionRefused, this, &WindowScriptingInterface::domainConnectionRefused);
|
||||
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &WindowScriptingInterface::domainConnectionRefused);
|
||||
|
||||
connect(qApp, &Application::svoImportRequested, [this](const QString& urlString) {
|
||||
static const QMetaMethod svoImportRequestedSignal =
|
||||
|
|
|
@ -36,8 +36,7 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = [=]()->QString {return myAvatar->getDisplayName(); };
|
||||
auto setter = [=](const QString& value) { myAvatar->setDisplayName(value); };
|
||||
const QString label = "Avatar display name <font color=\"#909090\">(optional)</font>";
|
||||
auto preference = new EditPreference(AVATAR_BASICS, label, getter, setter);
|
||||
auto preference = new EditPreference(AVATAR_BASICS, "Avatar display name (optional)", getter, setter);
|
||||
preference->setPlaceholderText("Not showing a name");
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
|
@ -45,8 +44,7 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = [=]()->QString {return myAvatar->getCollisionSoundURL(); };
|
||||
auto setter = [=](const QString& value) { myAvatar->setCollisionSoundURL(value); };
|
||||
const QString label = "Avatar collision sound URL <font color=\"#909090\">(optional)</font>";
|
||||
auto preference = new EditPreference(AVATAR_BASICS, label, getter, setter);
|
||||
auto preference = new EditPreference(AVATAR_BASICS, "Avatar collision sound URL (optional)", getter, setter);
|
||||
preference->setPlaceholderText("Enter the URL of a sound to play when you bump into something");
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
|
@ -54,18 +52,18 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = [=]()->QString { return myAvatar->getFullAvatarURLFromPreferences().toString(); };
|
||||
auto setter = [=](const QString& value) { myAvatar->useFullAvatarURL(value, ""); };
|
||||
auto preference = new AvatarPreference(AVATAR_BASICS, "Appearance: ", getter, setter);
|
||||
auto preference = new AvatarPreference(AVATAR_BASICS, "Appearance", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = [=]()->bool {return myAvatar->getSnapTurn(); };
|
||||
auto setter = [=](bool value) { myAvatar->setSnapTurn(value); };
|
||||
preferences->addPreference(new CheckPreference(AVATAR_BASICS, "Snap Turn when in HMD", getter, setter));
|
||||
preferences->addPreference(new CheckPreference(AVATAR_BASICS, "Snap turn when in HMD", getter, setter));
|
||||
}
|
||||
{
|
||||
auto getter = []()->QString { return Snapshot::snapshotsLocation.get(); };
|
||||
auto setter = [](const QString& value) { Snapshot::snapshotsLocation.set(value); };
|
||||
auto preference = new BrowsePreference("Snapshots", "Place my Snapshots here:", getter, setter);
|
||||
auto preference = new BrowsePreference("Snapshots", "Put my snapshots here", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
|
||||
|
@ -73,7 +71,7 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = []()->QString { return DependencyManager::get<ScriptEngines>()->getScriptsLocation(); };
|
||||
auto setter = [](const QString& value) { DependencyManager::get<ScriptEngines>()->setScriptsLocation(value); };
|
||||
preferences->addPreference(new BrowsePreference("Scripts", "Load scripts from this directory:", getter, setter));
|
||||
preferences->addPreference(new BrowsePreference("Scripts", "Load scripts from this directory", getter, setter));
|
||||
}
|
||||
|
||||
preferences->addPreference(new ButtonPreference("Scripts", "Load Default Scripts", [] {
|
||||
|
@ -83,14 +81,14 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = []()->bool {return !Menu::getInstance()->isOptionChecked(MenuOption::DisableActivityLogger); };
|
||||
auto setter = [](bool value) { Menu::getInstance()->setIsOptionChecked(MenuOption::DisableActivityLogger, !value); };
|
||||
preferences->addPreference(new CheckPreference("Privacy", "Send Data", getter, setter));
|
||||
preferences->addPreference(new CheckPreference("Privacy", "Send data", getter, setter));
|
||||
}
|
||||
|
||||
static const QString LOD_TUNING("Level of Detail Tuning");
|
||||
{
|
||||
auto getter = []()->float { return DependencyManager::get<LODManager>()->getDesktopLODDecreaseFPS(); };
|
||||
auto setter = [](float value) { DependencyManager::get<LODManager>()->setDesktopLODDecreaseFPS(value); };
|
||||
auto preference = new SpinnerPreference(LOD_TUNING, "Minimum Desktop FPS", getter, setter);
|
||||
auto preference = new SpinnerPreference(LOD_TUNING, "Minimum desktop FPS", getter, setter);
|
||||
preference->setMin(0);
|
||||
preference->setMax(120);
|
||||
preference->setStep(1);
|
||||
|
@ -138,7 +136,7 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = [=]()->float { return myAvatar->getUniformScale(); };
|
||||
auto setter = [=](float value) { myAvatar->setTargetScaleVerbose(value); }; // The hell?
|
||||
auto preference = new SpinnerPreference(AVATAR_TUNING, "Avatar scale <font color=\"#909090\">(default is 1.0)</font>", getter, setter);
|
||||
auto preference = new SpinnerPreference(AVATAR_TUNING, "Avatar scale (default is 1.0)", getter, setter);
|
||||
preference->setMin(0.01f);
|
||||
preference->setMax(99.9f);
|
||||
preference->setDecimals(2);
|
||||
|
@ -170,7 +168,7 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = [=]()->QString { return myAvatar->getAnimGraphUrl().toString(); };
|
||||
auto setter = [=](const QString& value) { myAvatar->setAnimGraphUrl(value); };
|
||||
auto preference = new EditPreference(AVATAR_TUNING, "Avatar Animation JSON", getter, setter);
|
||||
auto preference = new EditPreference(AVATAR_TUNING, "Avatar animation JSON", getter, setter);
|
||||
preference->setPlaceholderText("default");
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
|
@ -179,7 +177,7 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = [=]()->float { return myAvatar->getPitchSpeed(); };
|
||||
auto setter = [=](float value) { myAvatar->setPitchSpeed(value); };
|
||||
auto preference = new SpinnerPreference(AVATAR_CAMERA, "Camera Pitch Speed (degrees/second)", getter, setter);
|
||||
auto preference = new SpinnerPreference(AVATAR_CAMERA, "Camera pitch speed (degrees/second)", getter, setter);
|
||||
preference->setMin(1.0f);
|
||||
preference->setMax(360.0f);
|
||||
preferences->addPreference(preference);
|
||||
|
@ -187,7 +185,7 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = [=]()->float { return myAvatar->getYawSpeed(); };
|
||||
auto setter = [=](float value) { myAvatar->setYawSpeed(value); };
|
||||
auto preference = new SpinnerPreference(AVATAR_CAMERA, "Camera Yaw Speed (degrees/second)", getter, setter);
|
||||
auto preference = new SpinnerPreference(AVATAR_CAMERA, "Camera yaw speed (degrees/second)", getter, setter);
|
||||
preference->setMin(1.0f);
|
||||
preference->setMax(360.0f);
|
||||
preferences->addPreference(preference);
|
||||
|
@ -197,13 +195,13 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = []()->bool {return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getDynamicJitterBuffers(); };
|
||||
auto setter = [](bool value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setDynamicJitterBuffers(value); };
|
||||
preferences->addPreference(new CheckPreference(AUDIO, "Enable Dynamic Jitter Buffers", getter, setter));
|
||||
preferences->addPreference(new CheckPreference(AUDIO, "Enable dynamic jitter buffers", getter, setter));
|
||||
}
|
||||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getDesiredJitterBufferFrames(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setStaticDesiredJitterBufferFrames(value); };
|
||||
|
||||
auto preference = new SpinnerPreference(AUDIO, "Static Jitter Buffer Frames", getter, setter);
|
||||
auto preference = new SpinnerPreference(AUDIO, "Static jitter buffer frames", getter, setter);
|
||||
preference->setMin(0);
|
||||
preference->setMax(10000);
|
||||
preference->setStep(1);
|
||||
|
@ -212,7 +210,7 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getMaxFramesOverDesired(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setMaxFramesOverDesired(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Max Frames Over Desired", getter, setter);
|
||||
auto preference = new SpinnerPreference(AUDIO, "Max frames over desired", getter, setter);
|
||||
preference->setMax(10000);
|
||||
preference->setStep(1);
|
||||
preferences->addPreference(preference);
|
||||
|
@ -220,12 +218,12 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = []()->bool {return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getUseStDevForJitterCalc(); };
|
||||
auto setter = [](bool value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setUseStDevForJitterCalc(value); };
|
||||
preferences->addPreference(new CheckPreference(AUDIO, "Use Stddev for Dynamic Jitter Calc", getter, setter));
|
||||
preferences->addPreference(new CheckPreference(AUDIO, "Use standard deviation for dynamic jitter calc", getter, setter));
|
||||
}
|
||||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getWindowStarveThreshold(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setWindowStarveThreshold(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Window A Starve Threshold", getter, setter);
|
||||
auto preference = new SpinnerPreference(AUDIO, "Window A starve threshold", getter, setter);
|
||||
preference->setMax(10000);
|
||||
preference->setStep(1);
|
||||
preferences->addPreference(preference);
|
||||
|
@ -233,7 +231,7 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getWindowSecondsForDesiredCalcOnTooManyStarves(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setWindowSecondsForDesiredCalcOnTooManyStarves(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Window A (raise desired on N starves) Seconds)", getter, setter);
|
||||
auto preference = new SpinnerPreference(AUDIO, "Window A (raise desired on N starves) seconds", getter, setter);
|
||||
preference->setMax(10000);
|
||||
preference->setStep(1);
|
||||
preferences->addPreference(preference);
|
||||
|
@ -241,7 +239,7 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getWindowSecondsForDesiredReduction(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setWindowSecondsForDesiredReduction(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Window B (desired ceiling) Seconds", getter, setter);
|
||||
auto preference = new SpinnerPreference(AUDIO, "Window B (desired ceiling) seconds", getter, setter);
|
||||
preference->setMax(10000);
|
||||
preference->setStep(1);
|
||||
preferences->addPreference(preference);
|
||||
|
@ -249,12 +247,12 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = []()->bool {return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getRepetitionWithFade(); };
|
||||
auto setter = [](bool value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setRepetitionWithFade(value); };
|
||||
preferences->addPreference(new CheckPreference(AUDIO, "Repetition with Fade", getter, setter));
|
||||
preferences->addPreference(new CheckPreference(AUDIO, "Repetition with fade", getter, setter));
|
||||
}
|
||||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getOutputBufferSize(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->setOutputBufferSize(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Output Buffer Initial Size (frames)", getter, setter);
|
||||
auto preference = new SpinnerPreference(AUDIO, "Output buffer initial size (frames)", getter, setter);
|
||||
preference->setMin(1);
|
||||
preference->setMax(20);
|
||||
preference->setStep(1);
|
||||
|
@ -263,13 +261,13 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = []()->bool {return DependencyManager::get<AudioClient>()->getOutputStarveDetectionEnabled(); };
|
||||
auto setter = [](bool value) { DependencyManager::get<AudioClient>()->setOutputStarveDetectionEnabled(value); };
|
||||
auto preference = new CheckPreference(AUDIO, "Output Starve Detection (Automatic Buffer Size Increase)", getter, setter);
|
||||
auto preference = new CheckPreference(AUDIO, "Output starve detection (automatic buffer size increase)", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getOutputStarveDetectionThreshold(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->setOutputStarveDetectionThreshold(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Output Starve Detection Threshold", getter, setter);
|
||||
auto preference = new SpinnerPreference(AUDIO, "Output starve detection threshold", getter, setter);
|
||||
preference->setMin(1);
|
||||
preference->setMax(500);
|
||||
preference->setStep(1);
|
||||
|
@ -278,7 +276,7 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getOutputStarveDetectionPeriod(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->setOutputStarveDetectionPeriod(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Output Starve Detection Period (ms)", getter, setter);
|
||||
auto preference = new SpinnerPreference(AUDIO, "Output starve detection period (ms)", getter, setter);
|
||||
preference->setMin(1);
|
||||
preference->setMax((float)999999999);
|
||||
preference->setStep(1);
|
||||
|
@ -299,7 +297,7 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = []()->float { return qApp->getApplicationCompositor().getHmdUIAngularSize(); };
|
||||
auto setter = [](float value) { qApp->getApplicationCompositor().setHmdUIAngularSize(value); };
|
||||
auto preference = new SpinnerPreference("HMD", "User Interface Horizontal Angular Size (degrees)", getter, setter);
|
||||
auto preference = new SpinnerPreference("HMD", "UI horizontal angular size (degrees)", getter, setter);
|
||||
preference->setMin(30);
|
||||
preference->setMax(160);
|
||||
preference->setStep(1);
|
||||
|
@ -310,7 +308,7 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = []()->float { return controller::InputDevice::getReticleMoveSpeed(); };
|
||||
auto setter = [](float value) { controller::InputDevice::setReticleMoveSpeed(value); };
|
||||
auto preference = new SpinnerPreference("Sixense Controllers", "Reticle Movement Speed", getter, setter);
|
||||
auto preference = new SpinnerPreference("Sixense Controllers", "Reticle movement speed", getter, setter);
|
||||
preference->setMin(0);
|
||||
preference->setMax(100);
|
||||
preference->setStep(1);
|
||||
|
@ -325,7 +323,7 @@ void setupPreferences() {
|
|||
{
|
||||
auto getter = [ambientOcclusionConfig]()->QString { return ambientOcclusionConfig->getPreset(); };
|
||||
auto setter = [ambientOcclusionConfig](QString preset) { ambientOcclusionConfig->setPreset(preset); };
|
||||
auto preference = new ComboBoxPreference(RENDER, "Ambient Occlusion", getter, setter);
|
||||
auto preference = new ComboBoxPreference(RENDER, "Ambient occlusion", getter, setter);
|
||||
preference->setItems(ambientOcclusionConfig->getPresetList());
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
|
||||
#include "Base3DOverlay.h"
|
||||
|
||||
#include <QScriptValue>
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
|
@ -41,103 +39,78 @@ Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) :
|
|||
{
|
||||
}
|
||||
|
||||
void Base3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
void Base3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Overlay::setProperties(properties);
|
||||
|
||||
QScriptValue drawInFront = properties.property("drawInFront");
|
||||
auto drawInFront = properties["drawInFront"];
|
||||
|
||||
if (drawInFront.isValid()) {
|
||||
bool value = drawInFront.toVariant().toBool();
|
||||
bool value = drawInFront.toBool();
|
||||
setDrawInFront(value);
|
||||
}
|
||||
|
||||
QScriptValue position = properties.property("position");
|
||||
auto position = properties["position"];
|
||||
|
||||
// if "position" property was not there, check to see if they included aliases: point, p1
|
||||
if (!position.isValid()) {
|
||||
position = properties.property("p1");
|
||||
position = properties["p1"];
|
||||
if (!position.isValid()) {
|
||||
position = properties.property("point");
|
||||
position = properties["point"];
|
||||
}
|
||||
}
|
||||
|
||||
if (position.isValid()) {
|
||||
QScriptValue x = position.property("x");
|
||||
QScriptValue y = position.property("y");
|
||||
QScriptValue z = position.property("z");
|
||||
if (x.isValid() && y.isValid() && z.isValid()) {
|
||||
glm::vec3 newPosition;
|
||||
newPosition.x = x.toVariant().toFloat();
|
||||
newPosition.y = y.toVariant().toFloat();
|
||||
newPosition.z = z.toVariant().toFloat();
|
||||
setPosition(newPosition);
|
||||
}
|
||||
setPosition(vec3FromVariant(position));
|
||||
}
|
||||
|
||||
if (properties.property("lineWidth").isValid()) {
|
||||
setLineWidth(properties.property("lineWidth").toVariant().toFloat());
|
||||
if (properties["lineWidth"].isValid()) {
|
||||
setLineWidth(properties["lineWidth"].toFloat());
|
||||
}
|
||||
|
||||
QScriptValue rotation = properties.property("rotation");
|
||||
auto rotation = properties["rotation"];
|
||||
|
||||
if (rotation.isValid()) {
|
||||
glm::quat newRotation;
|
||||
|
||||
// size, scale, dimensions is special, it might just be a single scalar, or it might be a vector, check that here
|
||||
QScriptValue x = rotation.property("x");
|
||||
QScriptValue y = rotation.property("y");
|
||||
QScriptValue z = rotation.property("z");
|
||||
QScriptValue w = rotation.property("w");
|
||||
|
||||
|
||||
if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) {
|
||||
newRotation.x = x.toVariant().toFloat();
|
||||
newRotation.y = y.toVariant().toFloat();
|
||||
newRotation.z = z.toVariant().toFloat();
|
||||
newRotation.w = w.toVariant().toFloat();
|
||||
setRotation(newRotation);
|
||||
}
|
||||
setRotation(quatFromVariant(rotation));
|
||||
}
|
||||
|
||||
if (properties.property("isSolid").isValid()) {
|
||||
setIsSolid(properties.property("isSolid").toVariant().toBool());
|
||||
if (properties["isSolid"].isValid()) {
|
||||
setIsSolid(properties["isSolid"].toBool());
|
||||
}
|
||||
if (properties.property("isFilled").isValid()) {
|
||||
setIsSolid(properties.property("isSolid").toVariant().toBool());
|
||||
if (properties["isFilled"].isValid()) {
|
||||
setIsSolid(properties["isSolid"].toBool());
|
||||
}
|
||||
if (properties.property("isWire").isValid()) {
|
||||
setIsSolid(!properties.property("isWire").toVariant().toBool());
|
||||
if (properties["isWire"].isValid()) {
|
||||
setIsSolid(!properties["isWire"].toBool());
|
||||
}
|
||||
if (properties.property("solid").isValid()) {
|
||||
setIsSolid(properties.property("solid").toVariant().toBool());
|
||||
if (properties["solid"].isValid()) {
|
||||
setIsSolid(properties["solid"].toBool());
|
||||
}
|
||||
if (properties.property("filled").isValid()) {
|
||||
setIsSolid(properties.property("filled").toVariant().toBool());
|
||||
if (properties["filled"].isValid()) {
|
||||
setIsSolid(properties["filled"].toBool());
|
||||
}
|
||||
if (properties.property("wire").isValid()) {
|
||||
setIsSolid(!properties.property("wire").toVariant().toBool());
|
||||
if (properties["wire"].isValid()) {
|
||||
setIsSolid(!properties["wire"].toBool());
|
||||
}
|
||||
|
||||
if (properties.property("isDashedLine").isValid()) {
|
||||
setIsDashedLine(properties.property("isDashedLine").toVariant().toBool());
|
||||
if (properties["isDashedLine"].isValid()) {
|
||||
setIsDashedLine(properties["isDashedLine"].toBool());
|
||||
}
|
||||
if (properties.property("dashed").isValid()) {
|
||||
setIsDashedLine(properties.property("dashed").toVariant().toBool());
|
||||
if (properties["dashed"].isValid()) {
|
||||
setIsDashedLine(properties["dashed"].toBool());
|
||||
}
|
||||
if (properties.property("ignoreRayIntersection").isValid()) {
|
||||
setIgnoreRayIntersection(properties.property("ignoreRayIntersection").toVariant().toBool());
|
||||
if (properties["ignoreRayIntersection"].isValid()) {
|
||||
setIgnoreRayIntersection(properties["ignoreRayIntersection"].toBool());
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue Base3DOverlay::getProperty(const QString& property) {
|
||||
QVariant Base3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "position" || property == "start" || property == "p1" || property == "point") {
|
||||
return vec3toScriptValue(_scriptEngine, getPosition());
|
||||
return vec3toVariant(getPosition());
|
||||
}
|
||||
if (property == "lineWidth") {
|
||||
return _lineWidth;
|
||||
}
|
||||
if (property == "rotation") {
|
||||
return quatToScriptValue(_scriptEngine, getRotation());
|
||||
return quatToVariant(getRotation());
|
||||
}
|
||||
if (property == "isSolid" || property == "isFilled" || property == "solid" || property == "filed") {
|
||||
return _isSolid;
|
||||
|
|
|
@ -52,8 +52,8 @@ public:
|
|||
|
||||
virtual AABox getBounds() const = 0;
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal);
|
||||
|
|
|
@ -18,19 +18,19 @@ Billboard3DOverlay::Billboard3DOverlay(const Billboard3DOverlay* billboard3DOver
|
|||
{
|
||||
}
|
||||
|
||||
void Billboard3DOverlay::setProperties(const QScriptValue &properties) {
|
||||
void Billboard3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Planar3DOverlay::setProperties(properties);
|
||||
PanelAttachable::setProperties(properties);
|
||||
Billboardable::setProperties(properties);
|
||||
}
|
||||
|
||||
QScriptValue Billboard3DOverlay::getProperty(const QString &property) {
|
||||
QScriptValue value;
|
||||
value = Billboardable::getProperty(_scriptEngine, property);
|
||||
QVariant Billboard3DOverlay::getProperty(const QString &property) {
|
||||
QVariant value;
|
||||
value = Billboardable::getProperty(property);
|
||||
if (value.isValid()) {
|
||||
return value;
|
||||
}
|
||||
value = PanelAttachable::getProperty(_scriptEngine, property);
|
||||
value = PanelAttachable::getProperty(property);
|
||||
if (value.isValid()) {
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ public:
|
|||
Billboard3DOverlay() {}
|
||||
Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay);
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
protected:
|
||||
virtual void applyTransformTo(Transform& transform, bool force = false);
|
||||
|
|
|
@ -14,18 +14,18 @@
|
|||
#include <Application.h>
|
||||
#include <Transform.h>
|
||||
|
||||
void Billboardable::setProperties(const QScriptValue &properties) {
|
||||
QScriptValue isFacingAvatar = properties.property("isFacingAvatar");
|
||||
void Billboardable::setProperties(const QVariantMap& properties) {
|
||||
auto isFacingAvatar = properties["isFacingAvatar"];
|
||||
if (isFacingAvatar.isValid()) {
|
||||
setIsFacingAvatar(isFacingAvatar.toVariant().toBool());
|
||||
setIsFacingAvatar(isFacingAvatar.toBool());
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue Billboardable::getProperty(QScriptEngine* scriptEngine, const QString &property) {
|
||||
QVariant Billboardable::getProperty(const QString &property) {
|
||||
if (property == "isFacingAvatar") {
|
||||
return isFacingAvatar();
|
||||
}
|
||||
return QScriptValue();
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void Billboardable::pointTransformAtCamera(Transform& transform, glm::quat offsetRotation) {
|
||||
|
|
|
@ -12,11 +12,9 @@
|
|||
#ifndef hifi_Billboardable_h
|
||||
#define hifi_Billboardable_h
|
||||
|
||||
#include <QScriptValue>
|
||||
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <QVariant>
|
||||
|
||||
class QScriptEngine;
|
||||
class QString;
|
||||
class Transform;
|
||||
|
||||
|
@ -26,8 +24,8 @@ public:
|
|||
void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; }
|
||||
|
||||
protected:
|
||||
void setProperties(const QScriptValue& properties);
|
||||
QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property);
|
||||
void setProperties(const QVariantMap& properties);
|
||||
QVariant getProperty(const QString& property);
|
||||
|
||||
void pointTransformAtCamera(Transform& transform, glm::quat offsetRotation = {1, 0, 0, 0});
|
||||
|
||||
|
|
|
@ -286,83 +286,76 @@ const render::ShapeKey Circle3DOverlay::getShapeKey() {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
void Circle3DOverlay::setProperties(const QScriptValue &properties) {
|
||||
void Circle3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Planar3DOverlay::setProperties(properties);
|
||||
|
||||
QScriptValue startAt = properties.property("startAt");
|
||||
QVariant startAt = properties["startAt"];
|
||||
if (startAt.isValid()) {
|
||||
setStartAt(startAt.toVariant().toFloat());
|
||||
setStartAt(startAt.toFloat());
|
||||
}
|
||||
|
||||
QScriptValue endAt = properties.property("endAt");
|
||||
QVariant endAt = properties["endAt"];
|
||||
if (endAt.isValid()) {
|
||||
setEndAt(endAt.toVariant().toFloat());
|
||||
setEndAt(endAt.toFloat());
|
||||
}
|
||||
|
||||
QScriptValue outerRadius = properties.property("radius");
|
||||
QVariant outerRadius = properties["radius"];
|
||||
if (!outerRadius.isValid()) {
|
||||
outerRadius = properties.property("outerRadius");
|
||||
outerRadius = properties["outerRadius"];
|
||||
}
|
||||
if (outerRadius.isValid()) {
|
||||
setOuterRadius(outerRadius.toVariant().toFloat());
|
||||
setOuterRadius(outerRadius.toFloat());
|
||||
}
|
||||
|
||||
QScriptValue innerRadius = properties.property("innerRadius");
|
||||
QVariant innerRadius = properties["innerRadius"];
|
||||
if (innerRadius.isValid()) {
|
||||
setInnerRadius(innerRadius.toVariant().toFloat());
|
||||
setInnerRadius(innerRadius.toFloat());
|
||||
}
|
||||
|
||||
QScriptValue hasTickMarks = properties.property("hasTickMarks");
|
||||
QVariant hasTickMarks = properties["hasTickMarks"];
|
||||
if (hasTickMarks.isValid()) {
|
||||
setHasTickMarks(hasTickMarks.toVariant().toBool());
|
||||
setHasTickMarks(hasTickMarks.toBool());
|
||||
}
|
||||
|
||||
QScriptValue majorTickMarksAngle = properties.property("majorTickMarksAngle");
|
||||
QVariant majorTickMarksAngle = properties["majorTickMarksAngle"];
|
||||
if (majorTickMarksAngle.isValid()) {
|
||||
setMajorTickMarksAngle(majorTickMarksAngle.toVariant().toFloat());
|
||||
setMajorTickMarksAngle(majorTickMarksAngle.toFloat());
|
||||
}
|
||||
|
||||
QScriptValue minorTickMarksAngle = properties.property("minorTickMarksAngle");
|
||||
QVariant minorTickMarksAngle = properties["minorTickMarksAngle"];
|
||||
if (minorTickMarksAngle.isValid()) {
|
||||
setMinorTickMarksAngle(minorTickMarksAngle.toVariant().toFloat());
|
||||
setMinorTickMarksAngle(minorTickMarksAngle.toFloat());
|
||||
}
|
||||
|
||||
QScriptValue majorTickMarksLength = properties.property("majorTickMarksLength");
|
||||
QVariant majorTickMarksLength = properties["majorTickMarksLength"];
|
||||
if (majorTickMarksLength.isValid()) {
|
||||
setMajorTickMarksLength(majorTickMarksLength.toVariant().toFloat());
|
||||
setMajorTickMarksLength(majorTickMarksLength.toFloat());
|
||||
}
|
||||
|
||||
QScriptValue minorTickMarksLength = properties.property("minorTickMarksLength");
|
||||
QVariant minorTickMarksLength = properties["minorTickMarksLength"];
|
||||
if (minorTickMarksLength.isValid()) {
|
||||
setMinorTickMarksLength(minorTickMarksLength.toVariant().toFloat());
|
||||
setMinorTickMarksLength(minorTickMarksLength.toFloat());
|
||||
}
|
||||
|
||||
QScriptValue majorTickMarksColor = properties.property("majorTickMarksColor");
|
||||
bool valid;
|
||||
auto majorTickMarksColor = properties["majorTickMarksColor"];
|
||||
if (majorTickMarksColor.isValid()) {
|
||||
QScriptValue red = majorTickMarksColor.property("red");
|
||||
QScriptValue green = majorTickMarksColor.property("green");
|
||||
QScriptValue blue = majorTickMarksColor.property("blue");
|
||||
if (red.isValid() && green.isValid() && blue.isValid()) {
|
||||
_majorTickMarksColor.red = red.toVariant().toInt();
|
||||
_majorTickMarksColor.green = green.toVariant().toInt();
|
||||
_majorTickMarksColor.blue = blue.toVariant().toInt();
|
||||
auto color = xColorFromVariant(majorTickMarksColor, valid);
|
||||
if (valid) {
|
||||
_majorTickMarksColor = color;
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue minorTickMarksColor = properties.property("minorTickMarksColor");
|
||||
auto minorTickMarksColor = properties["minorTickMarksColor"];
|
||||
if (minorTickMarksColor.isValid()) {
|
||||
QScriptValue red = minorTickMarksColor.property("red");
|
||||
QScriptValue green = minorTickMarksColor.property("green");
|
||||
QScriptValue blue = minorTickMarksColor.property("blue");
|
||||
if (red.isValid() && green.isValid() && blue.isValid()) {
|
||||
_minorTickMarksColor.red = red.toVariant().toInt();
|
||||
_minorTickMarksColor.green = green.toVariant().toInt();
|
||||
_minorTickMarksColor.blue = blue.toVariant().toInt();
|
||||
auto color = xColorFromVariant(majorTickMarksColor, valid);
|
||||
if (valid) {
|
||||
_minorTickMarksColor = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue Circle3DOverlay::getProperty(const QString& property) {
|
||||
QVariant Circle3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "startAt") {
|
||||
return _startAt;
|
||||
}
|
||||
|
@ -394,10 +387,10 @@ QScriptValue Circle3DOverlay::getProperty(const QString& property) {
|
|||
return _minorTickMarksLength;
|
||||
}
|
||||
if (property == "majorTickMarksColor") {
|
||||
return xColorToScriptValue(_scriptEngine, _majorTickMarksColor);
|
||||
return xColorToVariant(_majorTickMarksColor);
|
||||
}
|
||||
if (property == "minorTickMarksColor") {
|
||||
return xColorToScriptValue(_scriptEngine, _minorTickMarksColor);
|
||||
return xColorToVariant(_minorTickMarksColor);
|
||||
}
|
||||
|
||||
return Planar3DOverlay::getProperty(property);
|
||||
|
|
|
@ -26,8 +26,8 @@ public:
|
|||
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
float getStartAt() const { return _startAt; }
|
||||
float getEndAt() const { return _endAt; }
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "Cube3DOverlay.h"
|
||||
|
||||
#include <QScriptValue>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <StreamUtils.h>
|
||||
#include <GeometryCache.h>
|
||||
|
@ -110,18 +108,18 @@ Cube3DOverlay* Cube3DOverlay::createClone() const {
|
|||
return new Cube3DOverlay(this);
|
||||
}
|
||||
|
||||
void Cube3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
void Cube3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Volume3DOverlay::setProperties(properties);
|
||||
|
||||
QScriptValue borderSize = properties.property("borderSize");
|
||||
auto borderSize = properties["borderSize"];
|
||||
|
||||
if (borderSize.isValid()) {
|
||||
float value = borderSize.toVariant().toFloat();
|
||||
float value = borderSize.toFloat();
|
||||
setBorderSize(value);
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue Cube3DOverlay::getProperty(const QString& property) {
|
||||
QVariant Cube3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "borderSize") {
|
||||
return _borderSize;
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ public:
|
|||
|
||||
void setBorderSize(float value) { _borderSize = value; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
private:
|
||||
float _borderSize;
|
||||
|
|
|
@ -11,10 +11,7 @@
|
|||
|
||||
#include "Grid3DOverlay.h"
|
||||
|
||||
#include <QScriptValue>
|
||||
|
||||
#include <OctreeConstants.h>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <PathUtils.h>
|
||||
|
@ -92,24 +89,24 @@ const render::ShapeKey Grid3DOverlay::getShapeKey() {
|
|||
return render::ShapeKey::Builder().withOwnPipeline();
|
||||
}
|
||||
|
||||
void Grid3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
void Grid3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Planar3DOverlay::setProperties(properties);
|
||||
if (properties.property("followCamera").isValid()) {
|
||||
_followCamera = properties.property("followCamera").toVariant().toBool();
|
||||
if (properties["followCamera"].isValid()) {
|
||||
_followCamera = properties["followCamera"].toBool();
|
||||
}
|
||||
|
||||
if (properties.property("majorGridEvery").isValid()) {
|
||||
_majorGridEvery = properties.property("majorGridEvery").toVariant().toInt();
|
||||
if (properties["majorGridEvery"].isValid()) {
|
||||
_majorGridEvery = properties["majorGridEvery"].toInt();
|
||||
}
|
||||
|
||||
if (properties.property("minorGridEvery").isValid()) {
|
||||
_minorGridEvery = properties.property("minorGridEvery").toVariant().toFloat();
|
||||
if (properties["minorGridEvery"].isValid()) {
|
||||
_minorGridEvery = properties["minorGridEvery"].toFloat();
|
||||
}
|
||||
|
||||
updateGrid();
|
||||
}
|
||||
|
||||
QScriptValue Grid3DOverlay::getProperty(const QString& property) {
|
||||
QVariant Grid3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "followCamera") {
|
||||
return _followCamera;
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ public:
|
|||
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
virtual Grid3DOverlay* createClone() const;
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
|
||||
#include "Image3DOverlay.h"
|
||||
|
||||
#include <QScriptValue>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <gpu/Batch.h>
|
||||
|
@ -114,41 +112,42 @@ const render::ShapeKey Image3DOverlay::getShapeKey() {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
void Image3DOverlay::setProperties(const QScriptValue &properties) {
|
||||
void Image3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Billboard3DOverlay::setProperties(properties);
|
||||
|
||||
QScriptValue urlValue = properties.property("url");
|
||||
auto urlValue = properties["url"];
|
||||
if (urlValue.isValid()) {
|
||||
QString newURL = urlValue.toVariant().toString();
|
||||
QString newURL = urlValue.toString();
|
||||
if (newURL != _url) {
|
||||
setURL(newURL);
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue subImageBounds = properties.property("subImage");
|
||||
if (subImageBounds.isValid()) {
|
||||
if (subImageBounds.isNull()) {
|
||||
auto subImageBoundsVar = properties["subImage"];
|
||||
if (subImageBoundsVar.isValid()) {
|
||||
if (subImageBoundsVar.isNull()) {
|
||||
_fromImage = QRect();
|
||||
} else {
|
||||
QRect oldSubImageRect = _fromImage;
|
||||
QRect subImageRect = _fromImage;
|
||||
if (subImageBounds.property("x").isValid()) {
|
||||
subImageRect.setX(subImageBounds.property("x").toVariant().toInt());
|
||||
auto subImageBounds = subImageBoundsVar.toMap();
|
||||
if (subImageBounds["x"].isValid()) {
|
||||
subImageRect.setX(subImageBounds["x"].toInt());
|
||||
} else {
|
||||
subImageRect.setX(oldSubImageRect.x());
|
||||
}
|
||||
if (subImageBounds.property("y").isValid()) {
|
||||
subImageRect.setY(subImageBounds.property("y").toVariant().toInt());
|
||||
if (subImageBounds["y"].isValid()) {
|
||||
subImageRect.setY(subImageBounds["y"].toInt());
|
||||
} else {
|
||||
subImageRect.setY(oldSubImageRect.y());
|
||||
}
|
||||
if (subImageBounds.property("width").isValid()) {
|
||||
subImageRect.setWidth(subImageBounds.property("width").toVariant().toInt());
|
||||
if (subImageBounds["width"].isValid()) {
|
||||
subImageRect.setWidth(subImageBounds["width"].toInt());
|
||||
} else {
|
||||
subImageRect.setWidth(oldSubImageRect.width());
|
||||
}
|
||||
if (subImageBounds.property("height").isValid()) {
|
||||
subImageRect.setHeight(subImageBounds.property("height").toVariant().toInt());
|
||||
if (subImageBounds["height"].isValid()) {
|
||||
subImageRect.setHeight(subImageBounds["height"].toInt());
|
||||
} else {
|
||||
subImageRect.setHeight(oldSubImageRect.height());
|
||||
}
|
||||
|
@ -156,21 +155,21 @@ void Image3DOverlay::setProperties(const QScriptValue &properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue emissiveValue = properties.property("emissive");
|
||||
auto emissiveValue = properties["emissive"];
|
||||
if (emissiveValue.isValid()) {
|
||||
_emissive = emissiveValue.toBool();
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue Image3DOverlay::getProperty(const QString& property) {
|
||||
QVariant Image3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "url") {
|
||||
return _url;
|
||||
}
|
||||
if (property == "subImage") {
|
||||
return qRectToScriptValue(_scriptEngine, _fromImage);
|
||||
return _fromImage;
|
||||
}
|
||||
if (property == "offsetPosition") {
|
||||
return vec3toScriptValue(_scriptEngine, getOffsetPosition());
|
||||
return vec3toVariant(getOffsetPosition());
|
||||
}
|
||||
if (property == "emissive") {
|
||||
return _emissive;
|
||||
|
|
|
@ -37,8 +37,8 @@ public:
|
|||
void setURL(const QString& url);
|
||||
void setClipFromSource(const QRect& bounds) { _fromImage = bounds; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal);
|
||||
|
|
|
@ -64,56 +64,41 @@ void Line3DOverlay::render(RenderArgs* args) {
|
|||
}
|
||||
|
||||
const render::ShapeKey Line3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder();
|
||||
auto builder = render::ShapeKey::Builder().withoutCullFace();
|
||||
if (getAlpha() != 1.0f) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
void Line3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
void Line3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Base3DOverlay::setProperties(properties);
|
||||
|
||||
QScriptValue start = properties.property("start");
|
||||
auto start = properties["start"];
|
||||
// if "start" property was not there, check to see if they included aliases: startPoint
|
||||
if (!start.isValid()) {
|
||||
start = properties.property("startPoint");
|
||||
start = properties["startPoint"];
|
||||
}
|
||||
if (start.isValid()) {
|
||||
QScriptValue x = start.property("x");
|
||||
QScriptValue y = start.property("y");
|
||||
QScriptValue z = start.property("z");
|
||||
if (x.isValid() && y.isValid() && z.isValid()) {
|
||||
glm::vec3 newStart;
|
||||
newStart.x = x.toVariant().toFloat();
|
||||
newStart.y = y.toVariant().toFloat();
|
||||
newStart.z = z.toVariant().toFloat();
|
||||
setStart(newStart);
|
||||
}
|
||||
setStart(vec3FromVariant(start));
|
||||
}
|
||||
|
||||
QScriptValue end = properties.property("end");
|
||||
auto end = properties["end"];
|
||||
// if "end" property was not there, check to see if they included aliases: endPoint
|
||||
if (!end.isValid()) {
|
||||
end = properties.property("endPoint");
|
||||
end = properties["endPoint"];
|
||||
}
|
||||
if (end.isValid()) {
|
||||
QScriptValue x = end.property("x");
|
||||
QScriptValue y = end.property("y");
|
||||
QScriptValue z = end.property("z");
|
||||
if (x.isValid() && y.isValid() && z.isValid()) {
|
||||
glm::vec3 newEnd;
|
||||
newEnd.x = x.toVariant().toFloat();
|
||||
newEnd.y = y.toVariant().toFloat();
|
||||
newEnd.z = z.toVariant().toFloat();
|
||||
setEnd(newEnd);
|
||||
}
|
||||
setEnd(vec3FromVariant(end));
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue Line3DOverlay::getProperty(const QString& property) {
|
||||
QVariant Line3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "start" || property == "startPoint" || property == "p1") {
|
||||
return vec3toVariant(_start);
|
||||
}
|
||||
if (property == "end" || property == "endPoint" || property == "p2") {
|
||||
return vec3toScriptValue(_scriptEngine, _end);
|
||||
return vec3toVariant(_end);
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
|
|
|
@ -35,8 +35,8 @@ public:
|
|||
void setStart(const glm::vec3& start) { _start = start; }
|
||||
void setEnd(const glm::vec3& end) { _end = end; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
virtual Line3DOverlay* createClone() const;
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ void ModelOverlay::render(RenderArgs* args) {
|
|||
}
|
||||
}
|
||||
|
||||
void ModelOverlay::setProperties(const QScriptValue &properties) {
|
||||
void ModelOverlay::setProperties(const QVariantMap& properties) {
|
||||
auto position = getPosition();
|
||||
auto rotation = getRotation();
|
||||
auto scale = getDimensions();
|
||||
|
@ -105,16 +105,16 @@ void ModelOverlay::setProperties(const QScriptValue &properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue urlValue = properties.property("url");
|
||||
if (urlValue.isValid() && urlValue.isString()) {
|
||||
auto urlValue = properties["url"];
|
||||
if (urlValue.isValid() && urlValue.canConvert<QString>()) {
|
||||
_url = urlValue.toString();
|
||||
_updateModel = true;
|
||||
_isLoaded = false;
|
||||
}
|
||||
|
||||
QScriptValue texturesValue = properties.property("textures");
|
||||
if (texturesValue.isValid() && texturesValue.toVariant().canConvert(QVariant::Map)) {
|
||||
QVariantMap textureMap = texturesValue.toVariant().toMap();
|
||||
auto texturesValue = properties["textures"];
|
||||
if (texturesValue.isValid() && texturesValue.canConvert(QVariant::Map)) {
|
||||
QVariantMap textureMap = texturesValue.toMap();
|
||||
foreach(const QString& key, textureMap.keys()) {
|
||||
|
||||
QUrl newTextureURL = textureMap[key].toUrl();
|
||||
|
@ -129,22 +129,22 @@ void ModelOverlay::setProperties(const QScriptValue &properties) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue ModelOverlay::getProperty(const QString& property) {
|
||||
QVariant ModelOverlay::getProperty(const QString& property) {
|
||||
if (property == "url") {
|
||||
return _url.toString();
|
||||
}
|
||||
if (property == "dimensions" || property == "scale" || property == "size") {
|
||||
return vec3toScriptValue(_scriptEngine, _model.getScaleToFitDimensions());
|
||||
return vec3toVariant(_model.getScaleToFitDimensions());
|
||||
}
|
||||
if (property == "textures") {
|
||||
if (_modelTextures.size() > 0) {
|
||||
QScriptValue textures = _scriptEngine->newObject();
|
||||
QVariantMap textures;
|
||||
foreach(const QString& key, _modelTextures.keys()) {
|
||||
textures.setProperty(key, _modelTextures[key].toString());
|
||||
textures[key] = _modelTextures[key].toString();
|
||||
}
|
||||
return textures;
|
||||
} else {
|
||||
return QScriptValue();
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@ public:
|
|||
|
||||
virtual void update(float deltatime);
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal);
|
||||
virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, glm::vec3& surfaceNormal, QString& extraInfo);
|
||||
|
|
|
@ -52,70 +52,68 @@ Overlay::Overlay(const Overlay* overlay) :
|
|||
_colorPulse(overlay->_colorPulse),
|
||||
_color(overlay->_color),
|
||||
_visible(overlay->_visible),
|
||||
_anchor(overlay->_anchor),
|
||||
_scriptEngine(NULL)
|
||||
_anchor(overlay->_anchor)
|
||||
{
|
||||
}
|
||||
|
||||
void Overlay::init(QScriptEngine* scriptEngine) {
|
||||
_scriptEngine = scriptEngine;
|
||||
}
|
||||
|
||||
Overlay::~Overlay() {
|
||||
}
|
||||
|
||||
void Overlay::setProperties(const QScriptValue& properties) {
|
||||
QScriptValue color = properties.property("color");
|
||||
xColorFromScriptValue(properties.property("color"), _color);
|
||||
void Overlay::setProperties(const QVariantMap& properties) {
|
||||
bool valid;
|
||||
auto color = xColorFromVariant(properties["color"], valid);
|
||||
if (valid) {
|
||||
_color = color;
|
||||
}
|
||||
|
||||
if (properties.property("alpha").isValid()) {
|
||||
setAlpha(properties.property("alpha").toVariant().toFloat());
|
||||
if (properties["alpha"].isValid()) {
|
||||
setAlpha(properties["alpha"].toFloat());
|
||||
}
|
||||
|
||||
if (properties.property("glowLevel").isValid()) {
|
||||
setGlowLevel(properties.property("glowLevel").toVariant().toFloat());
|
||||
if (properties["glowLevel"].isValid()) {
|
||||
setGlowLevel(properties["glowLevel"].toFloat());
|
||||
}
|
||||
|
||||
if (properties.property("pulseMax").isValid()) {
|
||||
setPulseMax(properties.property("pulseMax").toVariant().toFloat());
|
||||
if (properties["pulseMax"].isValid()) {
|
||||
setPulseMax(properties["pulseMax"].toFloat());
|
||||
}
|
||||
|
||||
if (properties.property("pulseMin").isValid()) {
|
||||
setPulseMin(properties.property("pulseMin").toVariant().toFloat());
|
||||
if (properties["pulseMin"].isValid()) {
|
||||
setPulseMin(properties["pulseMin"].toFloat());
|
||||
}
|
||||
|
||||
if (properties.property("pulsePeriod").isValid()) {
|
||||
setPulsePeriod(properties.property("pulsePeriod").toVariant().toFloat());
|
||||
if (properties["pulsePeriod"].isValid()) {
|
||||
setPulsePeriod(properties["pulsePeriod"].toFloat());
|
||||
}
|
||||
|
||||
if (properties.property("glowLevelPulse").isValid()) {
|
||||
setGlowLevelPulse(properties.property("glowLevelPulse").toVariant().toFloat());
|
||||
if (properties["glowLevelPulse"].isValid()) {
|
||||
setGlowLevelPulse(properties["glowLevelPulse"].toFloat());
|
||||
}
|
||||
|
||||
if (properties.property("alphaPulse").isValid()) {
|
||||
setAlphaPulse(properties.property("alphaPulse").toVariant().toFloat());
|
||||
if (properties["alphaPulse"].isValid()) {
|
||||
setAlphaPulse(properties["alphaPulse"].toFloat());
|
||||
}
|
||||
|
||||
if (properties.property("colorPulse").isValid()) {
|
||||
setColorPulse(properties.property("colorPulse").toVariant().toFloat());
|
||||
if (properties["colorPulse"].isValid()) {
|
||||
setColorPulse(properties["colorPulse"].toFloat());
|
||||
}
|
||||
|
||||
if (properties.property("visible").isValid()) {
|
||||
bool visible = properties.property("visible").toVariant().toBool();
|
||||
if (properties["visible"].isValid()) {
|
||||
bool visible = properties["visible"].toBool();
|
||||
setVisible(visible);
|
||||
}
|
||||
|
||||
if (properties.property("anchor").isValid()) {
|
||||
QString property = properties.property("anchor").toVariant().toString();
|
||||
if (properties["anchor"].isValid()) {
|
||||
QString property = properties["anchor"].toString();
|
||||
if (property == "MyAvatar") {
|
||||
setAnchor(MY_AVATAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue Overlay::getProperty(const QString& property) {
|
||||
QVariant Overlay::getProperty(const QString& property) {
|
||||
if (property == "color") {
|
||||
return xColorToScriptValue(_scriptEngine, _color);
|
||||
return xColorToVariant(_color);
|
||||
}
|
||||
if (property == "alpha") {
|
||||
return _alpha;
|
||||
|
@ -148,7 +146,7 @@ QScriptValue Overlay::getProperty(const QString& property) {
|
|||
return _anchor == MY_AVATAR ? "MyAvatar" : "";
|
||||
}
|
||||
|
||||
return QScriptValue();
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
xColor Overlay::getColor() {
|
||||
|
|
|
@ -15,9 +15,6 @@
|
|||
#include <SharedUtil.h> // for xColor
|
||||
#include <render/Scene.h>
|
||||
|
||||
class QScriptEngine;
|
||||
class QScriptValue;
|
||||
|
||||
class Overlay : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -34,7 +31,6 @@ public:
|
|||
Overlay();
|
||||
Overlay(const Overlay* overlay);
|
||||
~Overlay();
|
||||
void init(QScriptEngine* scriptEngine);
|
||||
virtual void update(float deltatime) {}
|
||||
virtual void render(RenderArgs* args) = 0;
|
||||
|
||||
|
@ -82,9 +78,9 @@ public:
|
|||
void setColorPulse(float value) { _colorPulse = value; }
|
||||
void setAlphaPulse(float value) { _alphaPulse = value; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual void setProperties(const QVariantMap& properties);
|
||||
virtual Overlay* createClone() const = 0;
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
virtual QVariant getProperty(const QString& property);
|
||||
|
||||
render::ItemID getRenderItemID() const { return _renderItemID; }
|
||||
void setRenderItemID(render::ItemID renderItemID) { _renderItemID = renderItemID; }
|
||||
|
@ -112,8 +108,6 @@ protected:
|
|||
xColor _color;
|
||||
bool _visible; // should the overlay be drawn at all
|
||||
Anchor _anchor;
|
||||
|
||||
QScriptEngine* _scriptEngine;
|
||||
};
|
||||
|
||||
namespace render {
|
||||
|
|
|
@ -23,49 +23,44 @@ AABox Overlay2D::getBounds() const {
|
|||
glm::vec3(_bounds.width(), _bounds.height(), 0.01f));
|
||||
}
|
||||
|
||||
void Overlay2D::setProperties(const QScriptValue& properties) {
|
||||
void Overlay2D::setProperties(const QVariantMap& properties) {
|
||||
Overlay::setProperties(properties);
|
||||
|
||||
QScriptValue bounds = properties.property("bounds");
|
||||
auto bounds = properties["bounds"];
|
||||
if (bounds.isValid()) {
|
||||
QRect boundsRect;
|
||||
boundsRect.setX(bounds.property("x").toVariant().toInt());
|
||||
boundsRect.setY(bounds.property("y").toVariant().toInt());
|
||||
boundsRect.setWidth(bounds.property("width").toVariant().toInt());
|
||||
boundsRect.setHeight(bounds.property("height").toVariant().toInt());
|
||||
setBounds(boundsRect);
|
||||
bool valid;
|
||||
auto rect = qRectFromVariant(bounds, valid);
|
||||
setBounds(rect);
|
||||
} else {
|
||||
QRect oldBounds = _bounds;
|
||||
QRect newBounds = oldBounds;
|
||||
|
||||
if (properties.property("x").isValid()) {
|
||||
newBounds.setX(properties.property("x").toVariant().toInt());
|
||||
if (properties["x"].isValid()) {
|
||||
newBounds.setX(properties["x"].toInt());
|
||||
} else {
|
||||
newBounds.setX(oldBounds.x());
|
||||
}
|
||||
if (properties.property("y").isValid()) {
|
||||
newBounds.setY(properties.property("y").toVariant().toInt());
|
||||
if (properties["y"].isValid()) {
|
||||
newBounds.setY(properties["y"].toInt());
|
||||
} else {
|
||||
newBounds.setY(oldBounds.y());
|
||||
}
|
||||
if (properties.property("width").isValid()) {
|
||||
newBounds.setWidth(properties.property("width").toVariant().toInt());
|
||||
if (properties["width"].isValid()) {
|
||||
newBounds.setWidth(properties["width"].toInt());
|
||||
} else {
|
||||
newBounds.setWidth(oldBounds.width());
|
||||
}
|
||||
if (properties.property("height").isValid()) {
|
||||
newBounds.setHeight(properties.property("height").toVariant().toInt());
|
||||
if (properties["height"].isValid()) {
|
||||
newBounds.setHeight(properties["height"].toInt());
|
||||
} else {
|
||||
newBounds.setHeight(oldBounds.height());
|
||||
}
|
||||
setBounds(newBounds);
|
||||
//qDebug() << "set bounds to " << getBounds();
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue Overlay2D::getProperty(const QString& property) {
|
||||
QVariant Overlay2D::getProperty(const QString& property) {
|
||||
if (property == "bounds") {
|
||||
return qRectToScriptValue(_scriptEngine, _bounds);
|
||||
return qRectToVariant(_bounds);
|
||||
}
|
||||
if (property == "x") {
|
||||
return _bounds.x();
|
||||
|
|
|
@ -40,8 +40,8 @@ public:
|
|||
void setHeight(int height) { _bounds.setHeight(height); }
|
||||
void setBounds(const QRect& bounds) { _bounds = bounds; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
protected:
|
||||
QRect _bounds; // where on the screen to draw
|
||||
|
|
|
@ -26,26 +26,27 @@ PropertyBinding::PropertyBinding(QString avatar, QUuid entity) :
|
|||
{
|
||||
}
|
||||
|
||||
QScriptValue propertyBindingToScriptValue(QScriptEngine* engine, const PropertyBinding& value) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
QVariant propertyBindingToVariant(const PropertyBinding& value) {
|
||||
QVariantMap obj;
|
||||
|
||||
if (value.avatar == "MyAvatar") {
|
||||
obj.setProperty("avatar", "MyAvatar");
|
||||
obj["avatar"] = "MyAvatar";
|
||||
} else if (!value.entity.isNull()) {
|
||||
obj.setProperty("entity", engine->newVariant(value.entity));
|
||||
obj["entity"] = value.entity;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void propertyBindingFromScriptValue(const QScriptValue& object, PropertyBinding& value) {
|
||||
QScriptValue avatar = object.property("avatar");
|
||||
QScriptValue entity = object.property("entity");
|
||||
void propertyBindingFromVariant(const QVariant& objectVar, PropertyBinding& value) {
|
||||
auto object = objectVar.toMap();
|
||||
auto avatar = object["avatar"];
|
||||
auto entity = object["entity"];
|
||||
|
||||
if (avatar.isValid() && !avatar.isNull()) {
|
||||
value.avatar = avatar.toVariant().toString();
|
||||
value.avatar = avatar.toString();
|
||||
} else if (entity.isValid() && !entity.isNull()) {
|
||||
value.entity = entity.toVariant().toUuid();
|
||||
value.entity = entity.toUuid();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,103 +63,82 @@ void OverlayPanel::removeChild(unsigned int childId) {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue OverlayPanel::getProperty(const QString &property) {
|
||||
QVariant OverlayPanel::getProperty(const QString &property) {
|
||||
if (property == "anchorPosition") {
|
||||
return vec3toScriptValue(_scriptEngine, getAnchorPosition());
|
||||
return vec3toVariant(getAnchorPosition());
|
||||
}
|
||||
if (property == "anchorPositionBinding") {
|
||||
return propertyBindingToScriptValue(_scriptEngine,
|
||||
PropertyBinding(_anchorPositionBindMyAvatar ?
|
||||
return propertyBindingToVariant(PropertyBinding(_anchorPositionBindMyAvatar ?
|
||||
"MyAvatar" : "",
|
||||
_anchorPositionBindEntity));
|
||||
}
|
||||
if (property == "anchorRotation") {
|
||||
return quatToScriptValue(_scriptEngine, getAnchorRotation());
|
||||
return quatToVariant(getAnchorRotation());
|
||||
}
|
||||
if (property == "anchorRotationBinding") {
|
||||
return propertyBindingToScriptValue(_scriptEngine,
|
||||
PropertyBinding(_anchorRotationBindMyAvatar ?
|
||||
return propertyBindingToVariant(PropertyBinding(_anchorRotationBindMyAvatar ?
|
||||
"MyAvatar" : "",
|
||||
_anchorRotationBindEntity));
|
||||
}
|
||||
if (property == "anchorScale") {
|
||||
return vec3toScriptValue(_scriptEngine, getAnchorScale());
|
||||
return vec3toVariant(getAnchorScale());
|
||||
}
|
||||
if (property == "visible") {
|
||||
return getVisible();
|
||||
}
|
||||
if (property == "children") {
|
||||
QScriptValue array = _scriptEngine->newArray(_children.length());
|
||||
QVariantList array;
|
||||
for (int i = 0; i < _children.length(); i++) {
|
||||
array.setProperty(i, _children[i]);
|
||||
array.append(_children[i]);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
QScriptValue value = Billboardable::getProperty(_scriptEngine, property);
|
||||
auto value = Billboardable::getProperty(property);
|
||||
if (value.isValid()) {
|
||||
return value;
|
||||
}
|
||||
return PanelAttachable::getProperty(_scriptEngine, property);
|
||||
return PanelAttachable::getProperty(property);
|
||||
}
|
||||
|
||||
void OverlayPanel::setProperties(const QScriptValue &properties) {
|
||||
void OverlayPanel::setProperties(const QVariantMap& properties) {
|
||||
PanelAttachable::setProperties(properties);
|
||||
Billboardable::setProperties(properties);
|
||||
|
||||
QScriptValue anchorPosition = properties.property("anchorPosition");
|
||||
if (anchorPosition.isValid() &&
|
||||
anchorPosition.property("x").isValid() &&
|
||||
anchorPosition.property("y").isValid() &&
|
||||
anchorPosition.property("z").isValid()) {
|
||||
glm::vec3 newPosition;
|
||||
vec3FromScriptValue(anchorPosition, newPosition);
|
||||
setAnchorPosition(newPosition);
|
||||
auto anchorPosition = properties["anchorPosition"];
|
||||
if (anchorPosition.isValid()) {
|
||||
setAnchorPosition(vec3FromVariant(anchorPosition));
|
||||
}
|
||||
|
||||
QScriptValue anchorPositionBinding = properties.property("anchorPositionBinding");
|
||||
auto anchorPositionBinding = properties["anchorPositionBinding"];
|
||||
if (anchorPositionBinding.isValid()) {
|
||||
PropertyBinding binding = {};
|
||||
propertyBindingFromScriptValue(anchorPositionBinding, binding);
|
||||
propertyBindingFromVariant(anchorPositionBinding, binding);
|
||||
_anchorPositionBindMyAvatar = binding.avatar == "MyAvatar";
|
||||
_anchorPositionBindEntity = binding.entity;
|
||||
}
|
||||
|
||||
QScriptValue anchorRotation = properties.property("anchorRotation");
|
||||
if (anchorRotation.isValid() &&
|
||||
anchorRotation.property("x").isValid() &&
|
||||
anchorRotation.property("y").isValid() &&
|
||||
anchorRotation.property("z").isValid() &&
|
||||
anchorRotation.property("w").isValid()) {
|
||||
glm::quat newRotation;
|
||||
quatFromScriptValue(anchorRotation, newRotation);
|
||||
setAnchorRotation(newRotation);
|
||||
auto anchorRotation = properties["anchorRotation"];
|
||||
if (anchorRotation.isValid()) {
|
||||
setAnchorRotation(quatFromVariant(anchorRotation));
|
||||
}
|
||||
|
||||
QScriptValue anchorRotationBinding = properties.property("anchorRotationBinding");
|
||||
auto anchorRotationBinding = properties["anchorRotationBinding"];
|
||||
if (anchorRotationBinding.isValid()) {
|
||||
PropertyBinding binding = {};
|
||||
propertyBindingFromScriptValue(anchorPositionBinding, binding);
|
||||
propertyBindingFromVariant(anchorPositionBinding, binding);
|
||||
_anchorRotationBindMyAvatar = binding.avatar == "MyAvatar";
|
||||
_anchorRotationBindEntity = binding.entity;
|
||||
}
|
||||
|
||||
QScriptValue anchorScale = properties.property("anchorScale");
|
||||
auto anchorScale = properties["anchorScale"];
|
||||
if (anchorScale.isValid()) {
|
||||
if (anchorScale.property("x").isValid() &&
|
||||
anchorScale.property("y").isValid() &&
|
||||
anchorScale.property("z").isValid()) {
|
||||
glm::vec3 newScale;
|
||||
vec3FromScriptValue(anchorScale, newScale);
|
||||
setAnchorScale(newScale);
|
||||
} else {
|
||||
setAnchorScale(anchorScale.toVariant().toFloat());
|
||||
}
|
||||
setAnchorScale(vec3FromVariant(anchorScale));
|
||||
}
|
||||
|
||||
QScriptValue visible = properties.property("visible");
|
||||
auto visible = properties["visible"];
|
||||
if (visible.isValid()) {
|
||||
setVisible(visible.toVariant().toBool());
|
||||
setVisible(visible.toBool());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <QScriptValue>
|
||||
#include <QUuid>
|
||||
|
||||
#include "PanelAttachable.h"
|
||||
|
@ -30,8 +29,8 @@ public:
|
|||
QUuid entity;
|
||||
};
|
||||
|
||||
QScriptValue propertyBindingToScriptValue(QScriptEngine* engine, const PropertyBinding& value);
|
||||
void propertyBindingFromScriptValue(const QScriptValue& object, PropertyBinding& value);
|
||||
QVariant propertyBindingToVariant(const PropertyBinding& value);
|
||||
void propertyBindingFromVariant(const QVariant& object, PropertyBinding& value);
|
||||
|
||||
|
||||
class OverlayPanel : public QObject, public PanelAttachable, public Billboardable {
|
||||
|
@ -60,8 +59,8 @@ public:
|
|||
void removeChild(unsigned int childId);
|
||||
unsigned int popLastChild() { return _children.takeLast(); }
|
||||
|
||||
QScriptValue getProperty(const QString& property);
|
||||
void setProperties(const QScriptValue& properties);
|
||||
void setProperties(const QVariantMap& properties);
|
||||
QVariant getProperty(const QString& property);
|
||||
|
||||
virtual void applyTransformTo(Transform& transform, bool force = false);
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ Overlay::Pointer Overlays::getOverlay(unsigned int id) const {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) {
|
||||
unsigned int Overlays::addOverlay(const QString& type, const QVariant& properties) {
|
||||
Overlay::Pointer thisOverlay = nullptr;
|
||||
|
||||
if (type == ImageOverlay::TYPE) {
|
||||
|
@ -187,15 +187,13 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope
|
|||
}
|
||||
|
||||
if (thisOverlay) {
|
||||
thisOverlay->setProperties(properties);
|
||||
thisOverlay->setProperties(properties.toMap());
|
||||
return addOverlay(thisOverlay);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int Overlays::addOverlay(Overlay::Pointer overlay) {
|
||||
overlay->init(_scriptEngine);
|
||||
|
||||
QWriteLocker lock(&_lock);
|
||||
unsigned int thisID = _nextOverlayID;
|
||||
_nextOverlayID++;
|
||||
|
@ -228,7 +226,7 @@ unsigned int Overlays::cloneOverlay(unsigned int id) {
|
|||
return 0; // Not found
|
||||
}
|
||||
|
||||
bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) {
|
||||
bool Overlays::editOverlay(unsigned int id, const QVariant& properties) {
|
||||
QWriteLocker lock(&_lock);
|
||||
|
||||
Overlay::Pointer thisOverlay = getOverlay(id);
|
||||
|
@ -236,7 +234,7 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) {
|
|||
if (thisOverlay->is3D()) {
|
||||
render::ItemKey oldItemKey = render::payloadGetKey(thisOverlay);
|
||||
|
||||
thisOverlay->setProperties(properties);
|
||||
thisOverlay->setProperties(properties.toMap());
|
||||
|
||||
render::ItemKey itemKey = render::payloadGetKey(thisOverlay);
|
||||
if (itemKey != oldItemKey) {
|
||||
|
@ -249,7 +247,7 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
thisOverlay->setProperties(properties);
|
||||
thisOverlay->setProperties(properties.toMap());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -380,36 +378,21 @@ OverlayPropertyResult Overlays::getProperty(unsigned int id, const QString& prop
|
|||
return result;
|
||||
}
|
||||
|
||||
OverlayPropertyResult::OverlayPropertyResult() :
|
||||
value(QScriptValue())
|
||||
{
|
||||
OverlayPropertyResult::OverlayPropertyResult() {
|
||||
}
|
||||
|
||||
QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& result)
|
||||
{
|
||||
if (!result.value.isValid()) {
|
||||
QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& value) {
|
||||
if (!value.value.isValid()) {
|
||||
return QScriptValue::UndefinedValue;
|
||||
}
|
||||
|
||||
QScriptValue object = engine->newObject();
|
||||
if (result.value.isObject()) {
|
||||
QScriptValueIterator it(result.value);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
object.setProperty(it.name(), QScriptValue(it.value().toString()));
|
||||
}
|
||||
|
||||
} else {
|
||||
object = result.value;
|
||||
}
|
||||
return object;
|
||||
return engine->newVariant(value.value);
|
||||
}
|
||||
|
||||
void OverlayPropertyResultFromScriptValue(const QScriptValue& value, OverlayPropertyResult& result)
|
||||
{
|
||||
result.value = value;
|
||||
void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPropertyResult& value) {
|
||||
value.value = object.toVariant();
|
||||
}
|
||||
|
||||
|
||||
RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) {
|
||||
float bestDistance = std::numeric_limits<float>::max();
|
||||
bool bestIsFront = false;
|
||||
|
@ -456,7 +439,7 @@ RayToOverlayIntersectionResult::RayToOverlayIntersectionResult() :
|
|||
}
|
||||
|
||||
QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value) {
|
||||
QScriptValue obj = engine->newObject();
|
||||
auto obj = engine->newObject();
|
||||
obj.setProperty("intersects", value.intersects);
|
||||
obj.setProperty("overlayID", value.overlayID);
|
||||
obj.setProperty("distance", value.distance);
|
||||
|
@ -488,18 +471,19 @@ QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine,
|
|||
break;
|
||||
}
|
||||
obj.setProperty("face", faceName);
|
||||
QScriptValue intersection = vec3toScriptValue(engine, value.intersection);
|
||||
auto intersection = vec3toScriptValue(engine, value.intersection);
|
||||
obj.setProperty("intersection", intersection);
|
||||
obj.setProperty("extraInfo", value.extraInfo);
|
||||
return obj;
|
||||
}
|
||||
|
||||
void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, RayToOverlayIntersectionResult& value) {
|
||||
value.intersects = object.property("intersects").toVariant().toBool();
|
||||
value.overlayID = object.property("overlayID").toVariant().toInt();
|
||||
value.distance = object.property("distance").toVariant().toFloat();
|
||||
void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& objectVar, RayToOverlayIntersectionResult& value) {
|
||||
QVariantMap object = objectVar.toVariant().toMap();
|
||||
value.intersects = object["intersects"].toBool();
|
||||
value.overlayID = object["overlayID"].toInt();
|
||||
value.distance = object["distance"].toFloat();
|
||||
|
||||
QString faceName = object.property("face").toVariant().toString();
|
||||
QString faceName = object["face"].toString();
|
||||
if (faceName == "MIN_X_FACE") {
|
||||
value.face = MIN_X_FACE;
|
||||
} else if (faceName == "MAX_X_FACE") {
|
||||
|
@ -515,11 +499,15 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R
|
|||
} else {
|
||||
value.face = UNKNOWN_FACE;
|
||||
};
|
||||
QScriptValue intersection = object.property("intersection");
|
||||
auto intersection = object["intersection"];
|
||||
if (intersection.isValid()) {
|
||||
vec3FromScriptValue(intersection, value.intersection);
|
||||
bool valid;
|
||||
auto newIntersection = vec3FromVariant(intersection, valid);
|
||||
if (valid) {
|
||||
value.intersection = newIntersection;
|
||||
}
|
||||
}
|
||||
value.extraInfo = object.property("extraInfo").toVariant().toString();
|
||||
value.extraInfo = object["extraInfo"].toString();
|
||||
}
|
||||
|
||||
bool Overlays::isLoaded(unsigned int id) {
|
||||
|
@ -556,16 +544,16 @@ unsigned int Overlays::addPanel(OverlayPanel::Pointer panel) {
|
|||
return thisID;
|
||||
}
|
||||
|
||||
unsigned int Overlays::addPanel(const QScriptValue& properties) {
|
||||
unsigned int Overlays::addPanel(const QVariant& properties) {
|
||||
OverlayPanel::Pointer panel = std::make_shared<OverlayPanel>();
|
||||
panel->init(_scriptEngine);
|
||||
panel->setProperties(properties);
|
||||
panel->setProperties(properties.toMap());
|
||||
return addPanel(panel);
|
||||
}
|
||||
|
||||
void Overlays::editPanel(unsigned int panelId, const QScriptValue& properties) {
|
||||
void Overlays::editPanel(unsigned int panelId, const QVariant& properties) {
|
||||
if (_panels.contains(panelId)) {
|
||||
_panels[panelId]->setProperties(properties);
|
||||
_panels[panelId]->setProperties(properties.toMap());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ class PickRay;
|
|||
class OverlayPropertyResult {
|
||||
public:
|
||||
OverlayPropertyResult();
|
||||
QScriptValue value;
|
||||
QVariant value;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(OverlayPropertyResult);
|
||||
|
@ -75,7 +75,7 @@ public:
|
|||
|
||||
public slots:
|
||||
/// adds an overlay with the specific properties
|
||||
unsigned int addOverlay(const QString& type, const QScriptValue& properties);
|
||||
unsigned int addOverlay(const QString& type, const QVariant& properties);
|
||||
|
||||
/// adds an overlay that's already been created
|
||||
unsigned int addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); }
|
||||
|
@ -86,7 +86,7 @@ public slots:
|
|||
|
||||
/// edits an overlay updating only the included properties, will return the identified OverlayID in case of
|
||||
/// successful edit, if the input id is for an unknown overlay this function will have no effect
|
||||
bool editOverlay(unsigned int id, const QScriptValue& properties);
|
||||
bool editOverlay(unsigned int id, const QVariant& properties);
|
||||
|
||||
/// deletes a particle
|
||||
void deleteOverlay(unsigned int id);
|
||||
|
@ -122,10 +122,10 @@ public slots:
|
|||
unsigned int addPanel(OverlayPanel::Pointer panel);
|
||||
|
||||
/// creates and adds a panel based on a set of properties
|
||||
unsigned int addPanel(const QScriptValue& properties);
|
||||
unsigned int addPanel(const QVariant& properties);
|
||||
|
||||
/// edit the properties of a panel
|
||||
void editPanel(unsigned int panelId, const QScriptValue& properties);
|
||||
void editPanel(unsigned int panelId, const QVariant& properties);
|
||||
|
||||
/// get a property of a panel
|
||||
OverlayPropertyResult getPanelProperty(unsigned int panelId, const QString& property);
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QScriptValueIterator>
|
||||
|
||||
#include <limits>
|
||||
#include <typeinfo>
|
||||
|
||||
|
|
|
@ -23,53 +23,38 @@ bool PanelAttachable::getParentVisible() const {
|
|||
}
|
||||
}
|
||||
|
||||
QScriptValue PanelAttachable::getProperty(QScriptEngine* scriptEngine, const QString &property) {
|
||||
QVariant PanelAttachable::getProperty(const QString& property) {
|
||||
if (property == "offsetPosition") {
|
||||
return vec3toScriptValue(scriptEngine, getOffsetPosition());
|
||||
return vec3toVariant(getOffsetPosition());
|
||||
}
|
||||
if (property == "offsetRotation") {
|
||||
return quatToScriptValue(scriptEngine, getOffsetRotation());
|
||||
return quatToVariant(getOffsetRotation());
|
||||
}
|
||||
if (property == "offsetScale") {
|
||||
return vec3toScriptValue(scriptEngine, getOffsetScale());
|
||||
return vec3toVariant(getOffsetScale());
|
||||
}
|
||||
return QScriptValue();
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void PanelAttachable::setProperties(const QScriptValue &properties) {
|
||||
QScriptValue offsetPosition = properties.property("offsetPosition");
|
||||
if (offsetPosition.isValid() &&
|
||||
offsetPosition.property("x").isValid() &&
|
||||
offsetPosition.property("y").isValid() &&
|
||||
offsetPosition.property("z").isValid()) {
|
||||
glm::vec3 newPosition;
|
||||
vec3FromScriptValue(offsetPosition, newPosition);
|
||||
setOffsetPosition(newPosition);
|
||||
}
|
||||
|
||||
QScriptValue offsetRotation = properties.property("offsetRotation");
|
||||
if (offsetRotation.isValid() &&
|
||||
offsetRotation.property("x").isValid() &&
|
||||
offsetRotation.property("y").isValid() &&
|
||||
offsetRotation.property("z").isValid() &&
|
||||
offsetRotation.property("w").isValid()) {
|
||||
glm::quat newRotation;
|
||||
quatFromScriptValue(offsetRotation, newRotation);
|
||||
setOffsetRotation(newRotation);
|
||||
}
|
||||
|
||||
QScriptValue offsetScale = properties.property("offsetScale");
|
||||
if (offsetScale.isValid()) {
|
||||
if (offsetScale.property("x").isValid() &&
|
||||
offsetScale.property("y").isValid() &&
|
||||
offsetScale.property("z").isValid()) {
|
||||
glm::vec3 newScale;
|
||||
vec3FromScriptValue(offsetScale, newScale);
|
||||
setOffsetScale(newScale);
|
||||
} else {
|
||||
setOffsetScale(offsetScale.toVariant().toFloat());
|
||||
void PanelAttachable::setProperties(const QVariantMap& properties) {
|
||||
auto offsetPosition = properties["offsetPosition"];
|
||||
bool valid;
|
||||
if (offsetPosition.isValid()) {
|
||||
glm::vec3 newPosition = vec3FromVariant(offsetPosition, valid);
|
||||
if (valid) {
|
||||
setOffsetPosition(newPosition);
|
||||
}
|
||||
}
|
||||
|
||||
auto offsetRotation = properties["offsetRotation"];
|
||||
if (offsetRotation.isValid()) {
|
||||
setOffsetRotation(quatFromVariant(offsetRotation));
|
||||
}
|
||||
|
||||
auto offsetScale = properties["offsetScale"];
|
||||
if (offsetScale.isValid()) {
|
||||
setOffsetScale(vec3FromVariant(offsetScale));
|
||||
}
|
||||
}
|
||||
|
||||
void PanelAttachable::applyTransformTo(Transform& transform, bool force) {
|
||||
|
|
|
@ -57,8 +57,8 @@ public:
|
|||
void setOffsetScale(const glm::vec3& scale) { _offset.setScale(scale); }
|
||||
|
||||
protected:
|
||||
QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property);
|
||||
void setProperties(const QScriptValue& properties);
|
||||
void setProperties(const QVariantMap& properties);
|
||||
QVariant getProperty(const QString& property);
|
||||
|
||||
/// set position, rotation and scale on transform based on offsets, and parent panel offsets
|
||||
/// if force is false, only apply transform if it hasn't been applied in the last .1 seconds
|
||||
|
|
|
@ -35,57 +35,27 @@ AABox Planar3DOverlay::getBounds() const {
|
|||
return AABox(extents);
|
||||
}
|
||||
|
||||
void Planar3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
void Planar3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Base3DOverlay::setProperties(properties);
|
||||
|
||||
QScriptValue dimensions = properties.property("dimensions");
|
||||
auto dimensions = properties["dimensions"];
|
||||
|
||||
// if "dimensions" property was not there, check to see if they included aliases: scale
|
||||
if (!dimensions.isValid()) {
|
||||
dimensions = properties.property("scale");
|
||||
dimensions = properties["scale"];
|
||||
if (!dimensions.isValid()) {
|
||||
dimensions = properties.property("size");
|
||||
dimensions = properties["size"];
|
||||
}
|
||||
}
|
||||
|
||||
if (dimensions.isValid()) {
|
||||
bool validDimensions = false;
|
||||
glm::vec2 newDimensions;
|
||||
|
||||
QScriptValue x = dimensions.property("x");
|
||||
QScriptValue y = dimensions.property("y");
|
||||
|
||||
if (x.isValid() && y.isValid()) {
|
||||
newDimensions.x = x.toVariant().toFloat();
|
||||
newDimensions.y = y.toVariant().toFloat();
|
||||
validDimensions = true;
|
||||
} else {
|
||||
QScriptValue width = dimensions.property("width");
|
||||
QScriptValue height = dimensions.property("height");
|
||||
if (width.isValid() && height.isValid()) {
|
||||
newDimensions.x = width.toVariant().toFloat();
|
||||
newDimensions.y = height.toVariant().toFloat();
|
||||
validDimensions = true;
|
||||
}
|
||||
}
|
||||
|
||||
// size, scale, dimensions is special, it might just be a single scalar, check that here
|
||||
if (!validDimensions && dimensions.isNumber()) {
|
||||
float size = dimensions.toVariant().toFloat();
|
||||
newDimensions.x = size;
|
||||
newDimensions.y = size;
|
||||
validDimensions = true;
|
||||
}
|
||||
|
||||
if (validDimensions) {
|
||||
setDimensions(newDimensions);
|
||||
}
|
||||
setDimensions(vec2FromVariant(dimensions));
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue Planar3DOverlay::getProperty(const QString& property) {
|
||||
QVariant Planar3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "dimensions" || property == "scale" || property == "size") {
|
||||
return vec2toScriptValue(_scriptEngine, getDimensions());
|
||||
return vec2toVariant(getDimensions());
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
|
|
|
@ -26,8 +26,8 @@ public:
|
|||
void setDimensions(float value) { _dimensions = glm::vec2(value); }
|
||||
void setDimensions(const glm::vec2& value) { _dimensions = value; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal);
|
||||
|
|
|
@ -57,7 +57,7 @@ QmlOverlay::~QmlOverlay() {
|
|||
}
|
||||
}
|
||||
|
||||
void QmlOverlay::setProperties(const QScriptValue& properties) {
|
||||
void QmlOverlay::setProperties(const QVariantMap& properties) {
|
||||
Overlay2D::setProperties(properties);
|
||||
auto bounds = _bounds;
|
||||
std::weak_ptr<QQuickItem> weakQmlElement;
|
||||
|
@ -71,7 +71,7 @@ void QmlOverlay::setProperties(const QScriptValue& properties) {
|
|||
_qmlElement->setHeight(bounds.height());
|
||||
}
|
||||
});
|
||||
QMetaObject::invokeMethod(_qmlElement.get(), "updatePropertiesFromScript", Q_ARG(QVariant, properties.toVariant()));
|
||||
QMetaObject::invokeMethod(_qmlElement.get(), "updatePropertiesFromScript", Q_ARG(QVariant, properties));
|
||||
}
|
||||
|
||||
void QmlOverlay::render(RenderArgs* args) {
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
// Cannot fetch properties from QML based overlays due to race conditions
|
||||
bool supportsGetProperty() const override { return false; }
|
||||
|
||||
void setProperties(const QScriptValue& properties) override;
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
void render(RenderArgs* args) override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -96,7 +96,7 @@ const render::ShapeKey Rectangle3DOverlay::getShapeKey() {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
void Rectangle3DOverlay::setProperties(const QScriptValue &properties) {
|
||||
void Rectangle3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Planar3DOverlay::setProperties(properties);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
~Rectangle3DOverlay();
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
|
||||
virtual Rectangle3DOverlay* createClone() const;
|
||||
private:
|
||||
|
|
|
@ -121,57 +121,54 @@ const render::ShapeKey Text3DOverlay::getShapeKey() {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
void Text3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
void Text3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Billboard3DOverlay::setProperties(properties);
|
||||
|
||||
QScriptValue text = properties.property("text");
|
||||
auto text = properties["text"];
|
||||
if (text.isValid()) {
|
||||
setText(text.toVariant().toString());
|
||||
setText(text.toString());
|
||||
}
|
||||
|
||||
QScriptValue textAlpha = properties.property("textAlpha");
|
||||
auto textAlpha = properties["textAlpha"];
|
||||
if (textAlpha.isValid()) {
|
||||
setTextAlpha(textAlpha.toVariant().toFloat());
|
||||
setTextAlpha(textAlpha.toFloat());
|
||||
}
|
||||
|
||||
QScriptValue backgroundColor = properties.property("backgroundColor");
|
||||
bool valid;
|
||||
auto backgroundColor = properties["backgroundColor"];
|
||||
if (backgroundColor.isValid()) {
|
||||
QScriptValue red = backgroundColor.property("red");
|
||||
QScriptValue green = backgroundColor.property("green");
|
||||
QScriptValue blue = backgroundColor.property("blue");
|
||||
if (red.isValid() && green.isValid() && blue.isValid()) {
|
||||
_backgroundColor.red = red.toVariant().toInt();
|
||||
_backgroundColor.green = green.toVariant().toInt();
|
||||
_backgroundColor.blue = blue.toVariant().toInt();
|
||||
auto color = xColorFromVariant(backgroundColor, valid);
|
||||
if (valid) {
|
||||
_backgroundColor = color;
|
||||
}
|
||||
}
|
||||
|
||||
if (properties.property("backgroundAlpha").isValid()) {
|
||||
setAlpha(properties.property("backgroundAlpha").toVariant().toFloat());
|
||||
if (properties["backgroundAlpha"].isValid()) {
|
||||
setAlpha(properties["backgroundAlpha"].toFloat());
|
||||
}
|
||||
|
||||
if (properties.property("lineHeight").isValid()) {
|
||||
setLineHeight(properties.property("lineHeight").toVariant().toFloat());
|
||||
if (properties["lineHeight"].isValid()) {
|
||||
setLineHeight(properties["lineHeight"].toFloat());
|
||||
}
|
||||
|
||||
if (properties.property("leftMargin").isValid()) {
|
||||
setLeftMargin(properties.property("leftMargin").toVariant().toFloat());
|
||||
if (properties["leftMargin"].isValid()) {
|
||||
setLeftMargin(properties["leftMargin"].toFloat());
|
||||
}
|
||||
|
||||
if (properties.property("topMargin").isValid()) {
|
||||
setTopMargin(properties.property("topMargin").toVariant().toFloat());
|
||||
if (properties["topMargin"].isValid()) {
|
||||
setTopMargin(properties["topMargin"].toFloat());
|
||||
}
|
||||
|
||||
if (properties.property("rightMargin").isValid()) {
|
||||
setRightMargin(properties.property("rightMargin").toVariant().toFloat());
|
||||
if (properties["rightMargin"].isValid()) {
|
||||
setRightMargin(properties["rightMargin"].toFloat());
|
||||
}
|
||||
|
||||
if (properties.property("bottomMargin").isValid()) {
|
||||
setBottomMargin(properties.property("bottomMargin").toVariant().toFloat());
|
||||
if (properties["bottomMargin"].isValid()) {
|
||||
setBottomMargin(properties["bottomMargin"].toFloat());
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue Text3DOverlay::getProperty(const QString& property) {
|
||||
QVariant Text3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "text") {
|
||||
return _text;
|
||||
}
|
||||
|
@ -179,7 +176,7 @@ QScriptValue Text3DOverlay::getProperty(const QString& property) {
|
|||
return _textAlpha;
|
||||
}
|
||||
if (property == "backgroundColor") {
|
||||
return xColorToScriptValue(_scriptEngine, _backgroundColor);
|
||||
return xColorToVariant(_backgroundColor);
|
||||
}
|
||||
if (property == "backgroundAlpha") {
|
||||
return Billboard3DOverlay::getProperty("alpha");
|
||||
|
|
|
@ -53,8 +53,8 @@ public:
|
|||
void setRightMargin(float margin) { _rightMargin = margin; }
|
||||
void setBottomMargin(float margin) { _bottomMargin = margin; }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
QSizeF textSize(const QString& test) const; // Meters
|
||||
|
||||
|
|
|
@ -26,67 +26,27 @@ AABox Volume3DOverlay::getBounds() const {
|
|||
return AABox(extents);
|
||||
}
|
||||
|
||||
void Volume3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
void Volume3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Base3DOverlay::setProperties(properties);
|
||||
|
||||
QScriptValue dimensions = properties.property("dimensions");
|
||||
auto dimensions = properties["dimensions"];
|
||||
|
||||
// if "dimensions" property was not there, check to see if they included aliases: scale
|
||||
if (!dimensions.isValid()) {
|
||||
dimensions = properties.property("scale");
|
||||
dimensions = properties["scale"];
|
||||
if (!dimensions.isValid()) {
|
||||
dimensions = properties.property("size");
|
||||
dimensions = properties["size"];
|
||||
}
|
||||
}
|
||||
|
||||
if (dimensions.isValid()) {
|
||||
bool validDimensions = false;
|
||||
glm::vec3 newDimensions;
|
||||
|
||||
QScriptValue x = dimensions.property("x");
|
||||
QScriptValue y = dimensions.property("y");
|
||||
QScriptValue z = dimensions.property("z");
|
||||
|
||||
|
||||
if (x.isValid() && x.isNumber() &&
|
||||
y.isValid() && y.isNumber() &&
|
||||
z.isValid() && z.isNumber()) {
|
||||
newDimensions.x = x.toNumber();
|
||||
newDimensions.y = y.toNumber();
|
||||
newDimensions.z = z.toNumber();
|
||||
validDimensions = true;
|
||||
} else {
|
||||
QScriptValue width = dimensions.property("width");
|
||||
QScriptValue height = dimensions.property("height");
|
||||
QScriptValue depth = dimensions.property("depth");
|
||||
if (width.isValid() && width.isNumber() &&
|
||||
height.isValid() && height.isNumber() &&
|
||||
depth.isValid() && depth.isNumber()) {
|
||||
newDimensions.x = width.toNumber();
|
||||
newDimensions.y = height.toNumber();
|
||||
newDimensions.z = depth.toNumber();
|
||||
validDimensions = true;
|
||||
}
|
||||
}
|
||||
|
||||
// size, scale, dimensions is special, it might just be a single scalar, check that here
|
||||
if (!validDimensions && dimensions.isNumber()) {
|
||||
float size = dimensions.toNumber();
|
||||
newDimensions.x = size;
|
||||
newDimensions.y = size;
|
||||
newDimensions.z = size;
|
||||
validDimensions = true;
|
||||
}
|
||||
|
||||
if (validDimensions) {
|
||||
setDimensions(newDimensions);
|
||||
}
|
||||
setDimensions(vec3FromVariant(dimensions));
|
||||
}
|
||||
}
|
||||
|
||||
QScriptValue Volume3DOverlay::getProperty(const QString& property) {
|
||||
QVariant Volume3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "dimensions" || property == "scale" || property == "size") {
|
||||
return vec3toScriptValue(_scriptEngine, getDimensions());
|
||||
return vec3toVariant(getDimensions());
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
|
|
|
@ -26,8 +26,8 @@ public:
|
|||
void setDimensions(float value) { _localBoundingBox.setBox(glm::vec3(-value / 2.0f), value); }
|
||||
void setDimensions(const glm::vec3& value) { _localBoundingBox.setBox(-value / 2.0f, value); }
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual QScriptValue getProperty(const QString& property);
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue