mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 04:03:59 +02:00
Merge branch 'black' of https://github.com/samcake/hifi into black
This commit is contained in:
commit
278b954d98
60 changed files with 1314 additions and 753 deletions
27
BUILD_WIN.md
27
BUILD_WIN.md
|
@ -27,11 +27,20 @@ Go to `Control Panel > System > Advanced System Settings > Environment Variables
|
|||
* Set "Variable name": `QT_CMAKE_PREFIX_PATH`
|
||||
* Set "Variable value": `C:\Qt\5.9.1\msvc2017_64\lib\cmake`
|
||||
|
||||
### Step 5. Installing OpenSSL
|
||||
### Step 5. Installing [vcpkg](https://github.com/Microsoft/vcpkg)
|
||||
|
||||
Download and install the Win64 OpenSSL v1.0.2 Installer[https://slproweb.com/products/Win32OpenSSL.html].
|
||||
* Clone the VCPKG [repository](https://github.com/Microsoft/vcpkg)
|
||||
* Follow the instructions in the [readme](https://github.com/Microsoft/vcpkg/blob/master/README.md) to bootstrap vcpkg
|
||||
* Note, you may need to do these in a _Developer Command Prompt_
|
||||
* Set an environment variable VCPKG_ROOT to the location of the cloned repository
|
||||
* Close and re-open any command prompts after setting the environment variable so that they will pick up the change
|
||||
|
||||
### Step 6. Running CMake to Generate Build Files
|
||||
### Step 6. Installing OpenSSL via vcpkg
|
||||
|
||||
* In the vcpkg directory, install the 64 bit OpenSSL package with the command `vcpkg install openssl:x64-windows`
|
||||
* Once the build completes you should have a file `ssl.h` in `${VCPKG_ROOT}/installed/x64-windows/include/openssl`
|
||||
|
||||
### Step 7. Running CMake to Generate Build Files
|
||||
|
||||
Run Command Prompt from Start and run the following commands:
|
||||
```
|
||||
|
@ -43,7 +52,7 @@ cmake .. -G "Visual Studio 15 Win64"
|
|||
|
||||
Where `%HIFI_DIR%` is the directory for the highfidelity repository.
|
||||
|
||||
### Step 7. Making a Build
|
||||
### Step 8. Making a Build
|
||||
|
||||
Open `%HIFI_DIR%\build\hifi.sln` using Visual Studio.
|
||||
|
||||
|
@ -51,7 +60,7 @@ Change the Solution Configuration (next to the green play button) from "Debug" t
|
|||
|
||||
Run `Build > Build Solution`.
|
||||
|
||||
### Step 8. Testing Interface
|
||||
### Step 9. Testing Interface
|
||||
|
||||
Create another environment variable (see Step #4)
|
||||
* Set "Variable name": `_NO_DEBUG_HEAP`
|
||||
|
@ -65,16 +74,20 @@ Note: You can also run Interface by launching it from command line or File Explo
|
|||
|
||||
## Troubleshooting
|
||||
|
||||
For any problems after Step #6, first try this:
|
||||
For any problems after Step #7, first try this:
|
||||
* Delete your locally cloned copy of the highfidelity repository
|
||||
* Restart your computer
|
||||
* Redownload the [repository](https://github.com/highfidelity/hifi)
|
||||
* Restart directions from Step #6
|
||||
* Restart directions from Step #7
|
||||
|
||||
#### CMake gives you the same error message repeatedly after the build fails
|
||||
|
||||
Remove `CMakeCache.txt` found in the `%HIFI_DIR%\build` directory.
|
||||
|
||||
#### CMake can't find OpenSSL
|
||||
|
||||
Remove `CMakeCache.txt` found in the `%HIFI_DIR%\build` directory. Verify that your VCPKG_ROOT environment variable is set and pointing to the correct location. Verify that the file `${VCPKG_ROOT}/installed/x64-windows/include/openssl/ssl.h` exists.
|
||||
|
||||
#### Qt is throwing an error
|
||||
|
||||
Make sure you have the correct version (5.9.1) installed and `QT_CMAKE_PREFIX_PATH` environment variable is set correctly.
|
||||
|
|
BIN
Test Plan 2.docx
BIN
Test Plan 2.docx
Binary file not shown.
|
@ -558,7 +558,7 @@ float computeAzimuth(const AvatarAudioStream& listeningNodeStream, const Positio
|
|||
|
||||
// produce an oriented angle about the y-axis
|
||||
glm::vec3 direction = rotatedSourcePosition * (1.0f / fastSqrtf(rotatedSourcePositionLength2));
|
||||
float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward"
|
||||
float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward"
|
||||
return (direction.x < 0.0f) ? -angle : angle;
|
||||
|
||||
} else {
|
||||
|
|
|
@ -458,84 +458,80 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
|
|||
return _truePacketsSent;
|
||||
}
|
||||
|
||||
bool OctreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params) {
|
||||
bool somethingToSend = false;
|
||||
OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(params.nodeData);
|
||||
if (!nodeData->elementBag.isEmpty()) {
|
||||
quint64 encodeStart = usecTimestampNow();
|
||||
quint64 lockWaitStart = encodeStart;
|
||||
|
||||
_myServer->getOctree()->withReadLock([&]{
|
||||
OctreeServer::trackTreeWaitTime((float)(usecTimestampNow() - lockWaitStart));
|
||||
|
||||
OctreeElementPointer subTree = nodeData->elementBag.extract();
|
||||
if (subTree) {
|
||||
// NOTE: this is where the tree "contents" are actually packed
|
||||
nodeData->stats.encodeStarted();
|
||||
_myServer->getOctree()->encodeTreeBitstream(subTree, &_packetData, nodeData->elementBag, params);
|
||||
nodeData->stats.encodeStopped();
|
||||
|
||||
somethingToSend = true;
|
||||
}
|
||||
});
|
||||
|
||||
OctreeServer::trackEncodeTime((float)(usecTimestampNow() - encodeStart));
|
||||
} else {
|
||||
OctreeServer::trackTreeWaitTime(OctreeServer::SKIP_TIME);
|
||||
OctreeServer::trackEncodeTime(OctreeServer::SKIP_TIME);
|
||||
}
|
||||
return somethingToSend;
|
||||
}
|
||||
|
||||
void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged, bool isFullScene) {
|
||||
// calculate max number of packets that can be sent during this interval
|
||||
int clientMaxPacketsPerInterval = std::max(1, (nodeData->getMaxQueryPacketsPerSecond() / INTERVALS_PER_SECOND));
|
||||
int maxPacketsPerInterval = std::min(clientMaxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval());
|
||||
|
||||
int extraPackingAttempts = 0;
|
||||
bool completedScene = false;
|
||||
|
||||
// init params once outside the while loop
|
||||
int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust();
|
||||
int boundaryLevelAdjust = boundaryLevelAdjustClient +
|
||||
(viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
|
||||
float octreeSizeScale = nodeData->getOctreeSizeScale();
|
||||
EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP,
|
||||
viewFrustumChanged, boundaryLevelAdjust, octreeSizeScale,
|
||||
isFullScene, _myServer->getJurisdiction(), nodeData);
|
||||
// Our trackSend() function is implemented by the server subclass, and will be called back
|
||||
// during the encodeTreeBitstream() as new entities/data elements are sent
|
||||
params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) {
|
||||
_myServer->trackSend(dataID, dataEdited, _nodeUuid);
|
||||
};
|
||||
nodeData->copyCurrentViewFrustum(params.viewFrustum);
|
||||
if (viewFrustumChanged) {
|
||||
nodeData->copyLastKnownViewFrustum(params.lastViewFrustum);
|
||||
}
|
||||
|
||||
bool somethingToSend = true; // assume we have something
|
||||
bool bagHadSomething = !nodeData->elementBag.isEmpty();
|
||||
while (somethingToSend && _packetsSentThisInterval < maxPacketsPerInterval && !nodeData->isShuttingDown()) {
|
||||
float lockWaitElapsedUsec = OctreeServer::SKIP_TIME;
|
||||
float encodeElapsedUsec = OctreeServer::SKIP_TIME;
|
||||
float compressAndWriteElapsedUsec = OctreeServer::SKIP_TIME;
|
||||
float packetSendingElapsedUsec = OctreeServer::SKIP_TIME;
|
||||
|
||||
quint64 startInside = usecTimestampNow();
|
||||
|
||||
bool lastNodeDidntFit = false; // assume each node fits
|
||||
if (!nodeData->elementBag.isEmpty()) {
|
||||
params.stopReason = EncodeBitstreamParams::UNKNOWN; // reset params.stopReason before traversal
|
||||
|
||||
quint64 lockWaitStart = usecTimestampNow();
|
||||
_myServer->getOctree()->withReadLock([&]{
|
||||
quint64 lockWaitEnd = usecTimestampNow();
|
||||
lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart);
|
||||
quint64 encodeStart = usecTimestampNow();
|
||||
somethingToSend = traverseTreeAndBuildNextPacketPayload(params);
|
||||
|
||||
OctreeElementPointer subTree = nodeData->elementBag.extract();
|
||||
if (!subTree) {
|
||||
return;
|
||||
}
|
||||
|
||||
float octreeSizeScale = nodeData->getOctreeSizeScale();
|
||||
int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust();
|
||||
|
||||
int boundaryLevelAdjust = boundaryLevelAdjustClient +
|
||||
(viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
|
||||
|
||||
EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP,
|
||||
viewFrustumChanged, boundaryLevelAdjust, octreeSizeScale,
|
||||
isFullScene, _myServer->getJurisdiction(), nodeData);
|
||||
nodeData->copyCurrentViewFrustum(params.viewFrustum);
|
||||
if (viewFrustumChanged) {
|
||||
nodeData->copyLastKnownViewFrustum(params.lastViewFrustum);
|
||||
}
|
||||
|
||||
// Our trackSend() function is implemented by the server subclass, and will be called back
|
||||
// during the encodeTreeBitstream() as new entities/data elements are sent
|
||||
params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) {
|
||||
_myServer->trackSend(dataID, dataEdited, _nodeUuid);
|
||||
};
|
||||
|
||||
// TODO: should this include the lock time or not? This stat is sent down to the client,
|
||||
// it seems like it may be a good idea to include the lock time as part of the encode time
|
||||
// are reported to client. Since you can encode without the lock
|
||||
nodeData->stats.encodeStarted();
|
||||
|
||||
// NOTE: this is where the tree "contents" are actaully packed
|
||||
_myServer->getOctree()->encodeTreeBitstream(subTree, &_packetData, nodeData->elementBag, params);
|
||||
|
||||
quint64 encodeEnd = usecTimestampNow();
|
||||
encodeElapsedUsec = (float)(encodeEnd - encodeStart);
|
||||
|
||||
// If after calling encodeTreeBitstream() there are no nodes left to send, then we know we've
|
||||
// sent the entire scene. We want to know this below so we'll actually write this content into
|
||||
// the packet and send it
|
||||
completedScene = nodeData->elementBag.isEmpty();
|
||||
|
||||
if (params.stopReason == EncodeBitstreamParams::DIDNT_FIT) {
|
||||
lastNodeDidntFit = true;
|
||||
extraPackingAttempts++;
|
||||
}
|
||||
|
||||
nodeData->stats.encodeStopped();
|
||||
});
|
||||
} else {
|
||||
somethingToSend = false; // this will cause us to drop out of the loop...
|
||||
if (params.stopReason == EncodeBitstreamParams::DIDNT_FIT) {
|
||||
lastNodeDidntFit = true;
|
||||
extraPackingAttempts++;
|
||||
}
|
||||
|
||||
// If the bag had contents but is now empty then we know we've sent the entire scene.
|
||||
bool completedScene = bagHadSomething && nodeData->elementBag.isEmpty();
|
||||
if (completedScene || lastNodeDidntFit) {
|
||||
// we probably want to flush what has accumulated in nodeData but:
|
||||
// do we have more data to send? and is there room?
|
||||
|
@ -562,8 +558,7 @@ void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, Octre
|
|||
if (sendNow) {
|
||||
quint64 packetSendingStart = usecTimestampNow();
|
||||
_packetsSentThisInterval += handlePacketSend(node, nodeData);
|
||||
quint64 packetSendingEnd = usecTimestampNow();
|
||||
packetSendingElapsedUsec = (float)(packetSendingEnd - packetSendingStart);
|
||||
packetSendingElapsedUsec = (float)(usecTimestampNow() - packetSendingStart);
|
||||
|
||||
targetSize = nodeData->getAvailable() - sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE);
|
||||
extraPackingAttempts = 0;
|
||||
|
@ -576,14 +571,9 @@ void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, Octre
|
|||
}
|
||||
_packetData.changeSettings(true, targetSize); // will do reset - NOTE: Always compressed
|
||||
}
|
||||
OctreeServer::trackTreeWaitTime(lockWaitElapsedUsec);
|
||||
OctreeServer::trackEncodeTime(encodeElapsedUsec);
|
||||
OctreeServer::trackCompressAndWriteTime(compressAndWriteElapsedUsec);
|
||||
OctreeServer::trackPacketSendingTime(packetSendingElapsedUsec);
|
||||
|
||||
quint64 endInside = usecTimestampNow();
|
||||
quint64 elapsedInsideUsecs = endInside - startInside;
|
||||
OctreeServer::trackInsideTime((float)elapsedInsideUsecs);
|
||||
OctreeServer::trackInsideTime((float)(usecTimestampNow() - startInside));
|
||||
}
|
||||
|
||||
if (somethingToSend && _myServer->wantsVerboseDebug()) {
|
||||
|
|
|
@ -53,7 +53,9 @@ protected:
|
|||
|
||||
/// Called before a packetDistributor pass to allow for pre-distribution processing
|
||||
virtual void preDistributionProcessing() {};
|
||||
virtual void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged, bool isFullScene);
|
||||
virtual void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,
|
||||
bool viewFrustumChanged, bool isFullScene);
|
||||
virtual bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params);
|
||||
|
||||
OctreeServer* _myServer { nullptr };
|
||||
QWeakPointer<Node> _node;
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include <QtCore/QDir>
|
||||
|
||||
int OctreeServer::_clientCount = 0;
|
||||
const int MOVING_AVERAGE_SAMPLE_COUNTS = 1000000;
|
||||
const int MOVING_AVERAGE_SAMPLE_COUNTS = 1000;
|
||||
|
||||
float OctreeServer::SKIP_TIME = -1.0f; // use this for trackXXXTime() calls for non-times
|
||||
|
||||
|
@ -136,18 +136,19 @@ void OctreeServer::trackEncodeTime(float time) {
|
|||
|
||||
if (time == SKIP_TIME) {
|
||||
_noEncode++;
|
||||
time = 0.0f;
|
||||
} else if (time <= MAX_SHORT_TIME) {
|
||||
_shortEncode++;
|
||||
_averageShortEncodeTime.updateAverage(time);
|
||||
} else if (time <= MAX_LONG_TIME) {
|
||||
_longEncode++;
|
||||
_averageLongEncodeTime.updateAverage(time);
|
||||
} else {
|
||||
_extraLongEncode++;
|
||||
_averageExtraLongEncodeTime.updateAverage(time);
|
||||
if (time <= MAX_SHORT_TIME) {
|
||||
_shortEncode++;
|
||||
_averageShortEncodeTime.updateAverage(time);
|
||||
} else if (time <= MAX_LONG_TIME) {
|
||||
_longEncode++;
|
||||
_averageLongEncodeTime.updateAverage(time);
|
||||
} else {
|
||||
_extraLongEncode++;
|
||||
_averageExtraLongEncodeTime.updateAverage(time);
|
||||
}
|
||||
_averageEncodeTime.updateAverage(time);
|
||||
}
|
||||
_averageEncodeTime.updateAverage(time);
|
||||
}
|
||||
|
||||
void OctreeServer::trackTreeWaitTime(float time) {
|
||||
|
@ -155,18 +156,19 @@ void OctreeServer::trackTreeWaitTime(float time) {
|
|||
const float MAX_LONG_TIME = 100.0f;
|
||||
if (time == SKIP_TIME) {
|
||||
_noTreeWait++;
|
||||
time = 0.0f;
|
||||
} else if (time <= MAX_SHORT_TIME) {
|
||||
_shortTreeWait++;
|
||||
_averageTreeShortWaitTime.updateAverage(time);
|
||||
} else if (time <= MAX_LONG_TIME) {
|
||||
_longTreeWait++;
|
||||
_averageTreeLongWaitTime.updateAverage(time);
|
||||
} else {
|
||||
_extraLongTreeWait++;
|
||||
_averageTreeExtraLongWaitTime.updateAverage(time);
|
||||
if (time <= MAX_SHORT_TIME) {
|
||||
_shortTreeWait++;
|
||||
_averageTreeShortWaitTime.updateAverage(time);
|
||||
} else if (time <= MAX_LONG_TIME) {
|
||||
_longTreeWait++;
|
||||
_averageTreeLongWaitTime.updateAverage(time);
|
||||
} else {
|
||||
_extraLongTreeWait++;
|
||||
_averageTreeExtraLongWaitTime.updateAverage(time);
|
||||
}
|
||||
_averageTreeWaitTime.updateAverage(time);
|
||||
}
|
||||
_averageTreeWaitTime.updateAverage(time);
|
||||
}
|
||||
|
||||
void OctreeServer::trackCompressAndWriteTime(float time) {
|
||||
|
@ -174,26 +176,27 @@ void OctreeServer::trackCompressAndWriteTime(float time) {
|
|||
const float MAX_LONG_TIME = 100.0f;
|
||||
if (time == SKIP_TIME) {
|
||||
_noCompress++;
|
||||
time = 0.0f;
|
||||
} else if (time <= MAX_SHORT_TIME) {
|
||||
_shortCompress++;
|
||||
_averageShortCompressTime.updateAverage(time);
|
||||
} else if (time <= MAX_LONG_TIME) {
|
||||
_longCompress++;
|
||||
_averageLongCompressTime.updateAverage(time);
|
||||
} else {
|
||||
_extraLongCompress++;
|
||||
_averageExtraLongCompressTime.updateAverage(time);
|
||||
if (time <= MAX_SHORT_TIME) {
|
||||
_shortCompress++;
|
||||
_averageShortCompressTime.updateAverage(time);
|
||||
} else if (time <= MAX_LONG_TIME) {
|
||||
_longCompress++;
|
||||
_averageLongCompressTime.updateAverage(time);
|
||||
} else {
|
||||
_extraLongCompress++;
|
||||
_averageExtraLongCompressTime.updateAverage(time);
|
||||
}
|
||||
_averageCompressAndWriteTime.updateAverage(time);
|
||||
}
|
||||
_averageCompressAndWriteTime.updateAverage(time);
|
||||
}
|
||||
|
||||
void OctreeServer::trackPacketSendingTime(float time) {
|
||||
if (time == SKIP_TIME) {
|
||||
_noSend++;
|
||||
time = 0.0f;
|
||||
} else {
|
||||
_averagePacketSendingTime.updateAverage(time);
|
||||
}
|
||||
_averagePacketSendingTime.updateAverage(time);
|
||||
}
|
||||
|
||||
|
||||
|
@ -202,18 +205,19 @@ void OctreeServer::trackProcessWaitTime(float time) {
|
|||
const float MAX_LONG_TIME = 100.0f;
|
||||
if (time == SKIP_TIME) {
|
||||
_noProcessWait++;
|
||||
time = 0.0f;
|
||||
} else if (time <= MAX_SHORT_TIME) {
|
||||
_shortProcessWait++;
|
||||
_averageProcessShortWaitTime.updateAverage(time);
|
||||
} else if (time <= MAX_LONG_TIME) {
|
||||
_longProcessWait++;
|
||||
_averageProcessLongWaitTime.updateAverage(time);
|
||||
} else {
|
||||
_extraLongProcessWait++;
|
||||
_averageProcessExtraLongWaitTime.updateAverage(time);
|
||||
if (time <= MAX_SHORT_TIME) {
|
||||
_shortProcessWait++;
|
||||
_averageProcessShortWaitTime.updateAverage(time);
|
||||
} else if (time <= MAX_LONG_TIME) {
|
||||
_longProcessWait++;
|
||||
_averageProcessLongWaitTime.updateAverage(time);
|
||||
} else {
|
||||
_extraLongProcessWait++;
|
||||
_averageProcessExtraLongWaitTime.updateAverage(time);
|
||||
}
|
||||
_averageProcessWaitTime.updateAverage(time);
|
||||
}
|
||||
_averageProcessWaitTime.updateAverage(time);
|
||||
}
|
||||
|
||||
OctreeServer::OctreeServer(ReceivedMessage& message) :
|
||||
|
|
|
@ -133,7 +133,7 @@ macro(SET_PACKAGING_PARAMETERS)
|
|||
else()
|
||||
message( FATAL_ERROR "Visual Studio 2013 or higher required." )
|
||||
endif()
|
||||
|
||||
|
||||
if (NOT SIGNTOOL_EXECUTABLE)
|
||||
message(FATAL_ERROR "Code signing of executables was requested but signtool.exe could not be found.")
|
||||
endif ()
|
||||
|
@ -147,6 +147,7 @@ macro(SET_PACKAGING_PARAMETERS)
|
|||
set(CONSOLE_STARTUP_REG_KEY "ConsoleStartupShortcut")
|
||||
set(CLIENT_LAUNCH_NOW_REG_KEY "ClientLaunchAfterInstall")
|
||||
set(SERVER_LAUNCH_NOW_REG_KEY "ServerLaunchAfterInstall")
|
||||
set(CUSTOM_INSTALL_REG_KEY "CustomInstall")
|
||||
endif ()
|
||||
|
||||
# setup component categories for installer
|
||||
|
|
|
@ -34,26 +34,11 @@ if (UNIX)
|
|||
endif ()
|
||||
|
||||
if (WIN32)
|
||||
|
||||
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
||||
|
||||
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||
# http://www.slproweb.com/products/Win32OpenSSL.html
|
||||
set(_OPENSSL_ROOT_HINTS ${OPENSSL_ROOT_DIR} $ENV{OPENSSL_ROOT_DIR} $ENV{HIFI_LIB_DIR}/openssl
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
|
||||
)
|
||||
set(_OPENSSL_ROOT_PATHS "${_programfiles}/OpenSSL" "${_programfiles}/OpenSSL-Win64" "C:/OpenSSL/" "C:/OpenSSL-Win64/")
|
||||
if (("${CMAKE_SIZEOF_VOID_P}" EQUAL "8"))
|
||||
set(_OPENSSL_ROOT_HINTS_AND_PATHS $ENV{VCPKG_ROOT}/installed/x64-windows)
|
||||
else()
|
||||
# http://www.slproweb.com/products/Win32OpenSSL.html
|
||||
set(_OPENSSL_ROOT_HINTS ${OPENSSL_ROOT_DIR} $ENV{OPENSSL_ROOT_DIR} $ENV{HIFI_LIB_DIR}/openssl
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
|
||||
)
|
||||
set(_OPENSSL_ROOT_PATHS "${_programfiles}/OpenSSL" "${_programfiles}/OpenSSL-Win32" "C:/OpenSSL/" "C:/OpenSSL-Win32/")
|
||||
set(_OPENSSL_ROOT_HINTS_AND_PATHS $ENV{VCPKG_ROOT}/installed/x86-windows)
|
||||
endif()
|
||||
|
||||
unset(_programfiles)
|
||||
set(_OPENSSL_ROOT_HINTS_AND_PATHS HINTS ${_OPENSSL_ROOT_HINTS} PATHS ${_OPENSSL_ROOT_PATHS})
|
||||
|
||||
else ()
|
||||
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
||||
hifi_library_search_hints("openssl")
|
||||
|
@ -67,47 +52,14 @@ find_path(OPENSSL_INCLUDE_DIR NAMES openssl/ssl.h HINTS ${_OPENSSL_ROOT_HINTS_AN
|
|||
|
||||
if (WIN32 AND NOT CYGWIN)
|
||||
if (MSVC)
|
||||
|
||||
# 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
|
||||
# * MT for static-release
|
||||
# * MTd for static-debug
|
||||
|
||||
# Implementation details:
|
||||
# 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
|
||||
|
||||
# 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 libeay32MT
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib/VC/static"
|
||||
)
|
||||
|
||||
find_library(SSL_EAY_DEBUG NAMES ssleay32MTd
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib/VC/static"
|
||||
)
|
||||
|
||||
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}")
|
||||
set(LIB_EAY_LIBRARY_RELEASE "${LIB_EAY_RELEASE}")
|
||||
set(SSL_EAY_LIBRARY_DEBUG "${SSL_EAY_DEBUG}")
|
||||
set(SSL_EAY_LIBRARY_RELEASE "${SSL_EAY_RELEASE}")
|
||||
# Using vcpkg builds of openssl
|
||||
find_library(LIB_EAY_LIBRARY_RELEASE NAMES libeay32 HINTS ${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib")
|
||||
find_library(SSL_EAY_LIBRARY_RELEASE NAMES ssleay32 HINTS ${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES "lib")
|
||||
|
||||
include(SelectLibraryConfigurations)
|
||||
select_library_configurations(LIB_EAY)
|
||||
select_library_configurations(SSL_EAY)
|
||||
|
||||
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})
|
||||
endif()
|
||||
else()
|
||||
|
|
|
@ -40,6 +40,7 @@ set(CONSOLE_DESKTOP_SHORTCUT_REG_KEY "@CONSOLE_DESKTOP_SHORTCUT_REG_KEY@")
|
|||
set(CONSOLE_STARTUP_REG_KEY "@CONSOLE_STARTUP_REG_KEY@")
|
||||
set(SERVER_LAUNCH_NOW_REG_KEY "@SERVER_LAUNCH_NOW_REG_KEY@")
|
||||
set(CLIENT_LAUNCH_NOW_REG_KEY "@CLIENT_LAUNCH_NOW_REG_KEY@")
|
||||
set(CUSTOM_INSTALL_REG_KEY "@CUSTOM_INSTALL_REG_KEY@")
|
||||
set(INSTALLER_HEADER_IMAGE "@INSTALLER_HEADER_IMAGE@")
|
||||
set(UNINSTALLER_HEADER_IMAGE "@UNINSTALLER_HEADER_IMAGE@")
|
||||
set(ADD_REMOVE_ICON_PATH "@ADD_REMOVE_ICON_PATH@")
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
Var STR_CONTAINS_VAR_3
|
||||
Var STR_CONTAINS_VAR_4
|
||||
Var STR_RETURN_VAR
|
||||
|
||||
|
||||
Function StrContains
|
||||
Exch $STR_NEEDLE
|
||||
Exch 1
|
||||
|
@ -343,29 +343,29 @@ SectionEnd
|
|||
;--------------------------------
|
||||
;Pages
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
|
||||
|
||||
!insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@"
|
||||
|
||||
|
||||
Page custom InstallTypesPage ReadInstallTypes
|
||||
|
||||
|
||||
!define MUI_PAGE_CUSTOMFUNCTION_PRE AbortFunction
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
|
||||
|
||||
;Start Menu Folder Page Configuration
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM"
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
|
||||
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
|
||||
|
||||
|
||||
!define MUI_PAGE_CUSTOMFUNCTION_PRE AbortFunction
|
||||
!insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER
|
||||
|
||||
|
||||
!define MUI_PAGE_CUSTOMFUNCTION_PRE AbortFunction
|
||||
@CPACK_NSIS_PAGE_COMPONENTS@
|
||||
|
||||
|
||||
Page custom PostInstallOptionsPage ReadPostInstallOptions
|
||||
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
|
||||
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
|
||||
|
@ -453,9 +453,10 @@ Var ExpressInstallRadioButton
|
|||
Var CustomInstallRadioButton
|
||||
Var InstallTypeDialog
|
||||
Var Express
|
||||
Var CustomInstallTemporaryState
|
||||
|
||||
!macro SetPostInstallOption Checkbox OptionName Default
|
||||
; reads the value for the given post install option to the registry
|
||||
!macro SetInstallOption Checkbox OptionName Default
|
||||
; reads the value for the given install option to the registry
|
||||
ReadRegStr $0 HKLM "@REGISTRY_HKLM_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\@POST_INSTALL_OPTIONS_REG_GROUP@" "${OptionName}"
|
||||
|
||||
${If} $0 == "NO"
|
||||
|
@ -472,31 +473,39 @@ Var Express
|
|||
|
||||
Function InstallTypesPage
|
||||
!insertmacro MUI_HEADER_TEXT "Choose Installation Type" "Express or Custom Install"
|
||||
|
||||
|
||||
nsDialogs::Create 1018
|
||||
Pop $InstallTypeDialog
|
||||
|
||||
|
||||
${If} $InstallTypeDialog == error
|
||||
Abort
|
||||
${EndIf}
|
||||
|
||||
|
||||
StrCpy $CurrentOffset 0
|
||||
StrCpy $OffsetUnits u
|
||||
StrCpy $Express "0"
|
||||
|
||||
StrCpy $Express "0"
|
||||
|
||||
${NSD_CreateRadioButton} 30% $CurrentOffset$OffsetUnits 100% 10u "Express Install (Recommended)"; $\nInstalls High Fidelity Interface and High Fidelity Sandbox"
|
||||
pop $ExpressInstallRadioButton
|
||||
${NSD_OnClick} $ExpressInstallRadioButton ChangeExpressLabel
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
|
||||
|
||||
${NSD_CreateRadiobutton} 30% $CurrentOffset$OffsetUnits 100% 10u "Custom Install (Advanced)"
|
||||
pop $CustomInstallRadioButton
|
||||
${NSD_OnClick} $CustomInstallRadioButton ChangeCustomLabel
|
||||
|
||||
; Express Install selected by default
|
||||
${NSD_Check} $ExpressInstallRadioButton
|
||||
${NSD_OnClick} $CustomInstallRadioButton ChangeCustomLabel
|
||||
|
||||
; check install type from the registry, express install by default
|
||||
!insertmacro SetInstallOption $CustomInstallRadioButton @CUSTOM_INSTALL_REG_KEY@ ${BST_UNCHECKED}
|
||||
|
||||
; set the express install value based on the custom install value from registry
|
||||
${NSD_GetState} $CustomInstallRadioButton $CustomInstallTemporaryState
|
||||
|
||||
${If} $CustomInstallTemporaryState == ${BST_UNCHECKED}
|
||||
${NSD_Check} $ExpressInstallRadioButton
|
||||
${EndIf}
|
||||
|
||||
Call ChangeExpressLabel
|
||||
|
||||
|
||||
nsDialogs::Show
|
||||
FunctionEnd
|
||||
|
||||
|
@ -519,18 +528,18 @@ Function AbortFunction
|
|||
StrCmp $Express "1" 0 end
|
||||
Abort
|
||||
end:
|
||||
FunctionEnd
|
||||
FunctionEnd
|
||||
|
||||
Function PostInstallOptionsPage
|
||||
!insertmacro MUI_HEADER_TEXT "Setup Options" ""
|
||||
|
||||
nsDialogs::Create 1018
|
||||
Pop $PostInstallDialog
|
||||
|
||||
|
||||
${If} $PostInstallDialog == error
|
||||
Abort
|
||||
${EndIf}
|
||||
|
||||
|
||||
; Check if Express is set, if so, abort the post install options page
|
||||
StrCmp $Express "1" 0 end
|
||||
Abort
|
||||
|
@ -543,18 +552,18 @@ Function PostInstallOptionsPage
|
|||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @INTERFACE_HF_SHORTCUT_NAME@"
|
||||
Pop $DesktopClientCheckbox
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
|
||||
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetPostInstallOption $DesktopClientCheckbox @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ ${BST_CHECKED}
|
||||
!insertmacro SetInstallOption $DesktopClientCheckbox @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ ${BST_CHECKED}
|
||||
${EndIf}
|
||||
|
||||
|
||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @CONSOLE_HF_SHORTCUT_NAME@"
|
||||
Pop $DesktopServerCheckbox
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
|
||||
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetPostInstallOption $DesktopServerCheckbox @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ ${BST_UNCHECKED}
|
||||
!insertmacro SetInstallOption $DesktopServerCheckbox @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ ${BST_UNCHECKED}
|
||||
${EndIf}
|
||||
|
||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
||||
|
@ -562,7 +571,7 @@ Function PostInstallOptionsPage
|
|||
Pop $LaunchServerNowCheckbox
|
||||
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetPostInstallOption $LaunchServerNowCheckbox @SERVER_LAUNCH_NOW_REG_KEY@ ${BST_CHECKED}
|
||||
!insertmacro SetInstallOption $LaunchServerNowCheckbox @SERVER_LAUNCH_NOW_REG_KEY@ ${BST_CHECKED}
|
||||
${StrContains} $substringResult "/forceNoLaunchServer" $CMDLINE
|
||||
${IfNot} $substringResult == ""
|
||||
${NSD_SetState} $LaunchServerNowCheckbox ${BST_UNCHECKED}
|
||||
|
@ -570,29 +579,29 @@ Function PostInstallOptionsPage
|
|||
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
${EndIf}
|
||||
|
||||
|
||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @INTERFACE_HF_SHORTCUT_NAME@ after install"
|
||||
Pop $LaunchClientNowCheckbox
|
||||
IntOp $CurrentOffset $CurrentOffset + 30
|
||||
|
||||
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetPostInstallOption $LaunchClientNowCheckbox @CLIENT_LAUNCH_NOW_REG_KEY@ ${BST_CHECKED}
|
||||
!insertmacro SetInstallOption $LaunchClientNowCheckbox @CLIENT_LAUNCH_NOW_REG_KEY@ ${BST_CHECKED}
|
||||
${StrContains} $substringResult "/forceNoLaunchClient" $CMDLINE
|
||||
${IfNot} $substringResult == ""
|
||||
${NSD_SetState} $LaunchClientNowCheckbox ${BST_UNCHECKED}
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
|
||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ on startup"
|
||||
Pop $ServerStartupCheckbox
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
|
||||
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetPostInstallOption $ServerStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_CHECKED}
|
||||
!insertmacro SetInstallOption $ServerStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_CHECKED}
|
||||
${EndIf}
|
||||
|
||||
|
||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Perform a clean install (Delete older settings and content)"
|
||||
Pop $CleanInstallCheckbox
|
||||
|
@ -618,12 +627,12 @@ Function PostInstallOptionsPage
|
|||
|
||||
${NSD_SetState} $CopyFromProductionCheckbox ${BST_UNCHECKED}
|
||||
${EndIf}
|
||||
|
||||
|
||||
nsDialogs::Show
|
||||
FunctionEnd
|
||||
|
||||
!macro WritePostInstallOption OptionName Option
|
||||
; writes the value for the given post install option to the registry
|
||||
!macro WriteInstallOption OptionName Option
|
||||
; writes the value for the given install option to the registry
|
||||
WriteRegStr HKLM "@REGISTRY_HKLM_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\@POST_INSTALL_OPTIONS_REG_GROUP@" "${OptionName}" ${Option}
|
||||
!macroend
|
||||
|
||||
|
@ -641,12 +650,12 @@ Function ReadInstallTypes
|
|||
; check if the user asked for express/custom install
|
||||
${NSD_GetState} $ExpressInstallRadioButton $ExpressInstallState
|
||||
${NSD_GetState} $CustomInstallRadioButton $CustomInstallState
|
||||
|
||||
|
||||
${If} $ExpressInstallState == ${BST_CHECKED}
|
||||
StrCpy $Express "1"
|
||||
|
||||
StrCpy $DesktopClientState ${BST_CHECKED}
|
||||
StrCpy $ServerStartupState ${BST_CHECKED}
|
||||
|
||||
StrCpy $DesktopClientState ${BST_CHECKED}
|
||||
StrCpy $ServerStartupState ${BST_CHECKED}
|
||||
StrCpy $LaunchServerNowState ${BST_CHECKED}
|
||||
StrCpy $LaunchClientNowState ${BST_CHECKED}
|
||||
StrCpy $CleanInstallState ${BST_UNCHECKED}
|
||||
|
@ -655,9 +664,12 @@ Function ReadInstallTypes
|
|||
${If} @PR_BUILD@ == 1
|
||||
StrCpy $CopyFromProductionState ${BST_UNCHECKED}
|
||||
${EndIf}
|
||||
|
||||
|
||||
!insertmacro WriteInstallOption "@CUSTOM_INSTALL_REG_KEY@" NO
|
||||
${Else}
|
||||
!insertmacro WriteInstallOption "@CUSTOM_INSTALL_REG_KEY@" YES
|
||||
${EndIf}
|
||||
|
||||
|
||||
FunctionEnd
|
||||
|
||||
Function ReadPostInstallOptions
|
||||
|
@ -683,12 +695,12 @@ Function ReadPostInstallOptions
|
|||
; check if we need to launch the server post-install
|
||||
${NSD_GetState} $LaunchServerNowCheckbox $LaunchServerNowState
|
||||
${EndIf}
|
||||
|
||||
|
||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
||||
; check if we need to launch the client post-install
|
||||
${NSD_GetState} $LaunchClientNowCheckbox $LaunchClientNowState
|
||||
${EndIf}
|
||||
|
||||
|
||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
||||
; check if the user asked for a clean install
|
||||
${NSD_GetState} $CleanInstallCheckbox $CleanInstallState
|
||||
|
@ -700,9 +712,9 @@ Function HandlePostInstallOptions
|
|||
; check if the user asked for a desktop shortcut to High Fidelity
|
||||
${If} $DesktopClientState == ${BST_CHECKED}
|
||||
CreateShortCut "$DESKTOP\@INTERFACE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"
|
||||
!insertmacro WritePostInstallOption "@CLIENT_DESKTOP_SHORTCUT_REG_KEY@" YES
|
||||
!insertmacro WriteInstallOption "@CLIENT_DESKTOP_SHORTCUT_REG_KEY@" YES
|
||||
${Else}
|
||||
!insertmacro WritePostInstallOption @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ NO
|
||||
!insertmacro WriteInstallOption @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ NO
|
||||
${EndIf}
|
||||
|
||||
${EndIf}
|
||||
|
@ -711,12 +723,12 @@ Function HandlePostInstallOptions
|
|||
; check if the user asked for a desktop shortcut to Sandbox
|
||||
${If} $DesktopServerState == ${BST_CHECKED}
|
||||
CreateShortCut "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
||||
!insertmacro WritePostInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ YES
|
||||
!insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ YES
|
||||
${Else}
|
||||
!insertmacro WritePostInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO
|
||||
!insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO
|
||||
${EndIf}
|
||||
|
||||
|
||||
|
||||
; check if the user asked to have Sandbox launched every startup
|
||||
${If} $ServerStartupState == ${BST_CHECKED}
|
||||
; in case we added a shortcut in the global context, pull that now
|
||||
|
@ -730,12 +742,12 @@ Function HandlePostInstallOptions
|
|||
; reset the shell var context back
|
||||
SetShellVarContext all
|
||||
|
||||
!insertmacro WritePostInstallOption @CONSOLE_STARTUP_REG_KEY@ YES
|
||||
!insertmacro WriteInstallOption @CONSOLE_STARTUP_REG_KEY@ YES
|
||||
${Else}
|
||||
!insertmacro WritePostInstallOption @CONSOLE_STARTUP_REG_KEY@ NO
|
||||
!insertmacro WriteInstallOption @CONSOLE_STARTUP_REG_KEY@ NO
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
|
||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
||||
; check if the user asked for a clean install
|
||||
${If} $CleanInstallState == ${BST_CHECKED}
|
||||
|
@ -774,28 +786,28 @@ Function HandlePostInstallOptions
|
|||
${EndIf}
|
||||
|
||||
${If} $LaunchServerNowState == ${BST_CHECKED}
|
||||
!insertmacro WritePostInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ YES
|
||||
!insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ YES
|
||||
|
||||
; both launches use the explorer trick in case the user has elevated permissions for the installer
|
||||
${If} $LaunchClientNowState == ${BST_CHECKED}
|
||||
!insertmacro WritePostInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ YES
|
||||
!insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ YES
|
||||
; create shortcut with ARGUMENTS
|
||||
CreateShortCut "$TEMP\SandboxShortcut.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" "-- --launchInterface"
|
||||
Exec '"$WINDIR\explorer.exe" "$TEMP\SandboxShortcut.lnk"'
|
||||
${Else}
|
||||
!insertmacro WritePostInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ NO
|
||||
!insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ NO
|
||||
Exec '"$WINDIR\explorer.exe" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"'
|
||||
${EndIf}
|
||||
|
||||
${Else}
|
||||
!insertmacro WritePostInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ NO
|
||||
!insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ NO
|
||||
|
||||
; launch uses the explorer trick in case the user has elevated permissions for the installer
|
||||
${If} $LaunchClientNowState == ${BST_CHECKED}
|
||||
!insertmacro WritePostInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ YES
|
||||
!insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ YES
|
||||
Exec '"$WINDIR\explorer.exe" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"'
|
||||
${Else}
|
||||
!insertmacro WritePostInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ NO
|
||||
!insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ NO
|
||||
${EndIf}
|
||||
|
||||
${EndIf}
|
||||
|
@ -843,7 +855,7 @@ Section "-Core installation"
|
|||
Rename "$INSTDIR\resources\qml\styles-uit\RalewaySemibold.qml" "$INSTDIR\resources\qml\styles-uit\RalewaySemiBold.qml"
|
||||
|
||||
ExecWait "$INSTDIR\vcredist_x64.exe /install /q /norestart"
|
||||
|
||||
|
||||
; Remove the Old Interface directory and vcredist_x64.exe (from installs prior to Server Console)
|
||||
RMDir /r "$INSTDIR\Interface"
|
||||
Delete "$INSTDIR\vcredist_x64.exe"
|
||||
|
@ -943,9 +955,9 @@ Section "-Core installation"
|
|||
Call ConditionalAddToRegisty
|
||||
|
||||
!insertmacro MUI_STARTMENU_WRITE_END
|
||||
|
||||
|
||||
@CPACK_NSIS_EXTRA_INSTALL_COMMANDS@
|
||||
|
||||
|
||||
; Handle whichever post install options were set
|
||||
Call HandlePostInstallOptions
|
||||
|
||||
|
@ -963,9 +975,18 @@ SectionEnd
|
|||
${If} $R0 == 0
|
||||
|
||||
; the process is running, ask the user to close it
|
||||
|
||||
${If} "${displayName}" == "@CONSOLE_DISPLAY_NAME@"
|
||||
MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION \
|
||||
"${displayName} cannot be ${action} while ${displayName} is running.$\r$\nPlease close it and click Retry to continue." \
|
||||
"${displayName} cannot be ${action} while ${displayName} is running.$\r$\nPlease close it in the system tray and click Retry to continue." \
|
||||
/SD IDCANCEL IDRETRY Prompt_${UniqueID} IDCANCEL 0
|
||||
${EndIf}
|
||||
|
||||
${If} "${displayName}" == "@INTERFACE_DISPLAY_NAME@"
|
||||
MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION \
|
||||
"${displayName} cannot be ${action} while ${displayName} is running.$\r$\nPlease close it in the task bar and click Retry to continue." \
|
||||
/SD IDCANCEL IDRETRY Prompt_${UniqueID} IDCANCEL 0
|
||||
${EndIf}
|
||||
|
||||
; If the user decided to cancel, stop the current installer/uninstaller
|
||||
Abort
|
||||
|
|
|
@ -752,8 +752,28 @@ void DomainServer::setupICEHeartbeatForFullNetworking() {
|
|||
}
|
||||
|
||||
void DomainServer::updateICEServerAddresses() {
|
||||
if (_iceAddressLookupID == -1) {
|
||||
if (_iceAddressLookupID == INVALID_ICE_LOOKUP_ID) {
|
||||
_iceAddressLookupID = QHostInfo::lookupHost(_iceServerAddr, this, SLOT(handleICEHostInfo(QHostInfo)));
|
||||
|
||||
// there seems to be a 5.9 bug where lookupHost never calls our slot
|
||||
// so we add a single shot manual "timeout" to fire it off again if it hasn't called back yet
|
||||
static const int ICE_ADDRESS_LOOKUP_TIMEOUT_MS = 5000;
|
||||
QTimer::singleShot(ICE_ADDRESS_LOOKUP_TIMEOUT_MS, this, &DomainServer::timeoutICEAddressLookup);
|
||||
}
|
||||
}
|
||||
|
||||
void DomainServer::timeoutICEAddressLookup() {
|
||||
if (_iceAddressLookupID != INVALID_ICE_LOOKUP_ID) {
|
||||
// we waited 5s and didn't hear back for our ICE DNS lookup
|
||||
// so time that one out and kick off another
|
||||
|
||||
qDebug() << "IP address lookup timed out for" << _iceServerAddr << "- retrying";
|
||||
|
||||
QHostInfo::abortHostLookup(_iceAddressLookupID);
|
||||
|
||||
_iceAddressLookupID = INVALID_ICE_LOOKUP_ID;
|
||||
|
||||
updateICEServerAddresses();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ typedef QMultiHash<QUuid, WalletTransaction*> TransactionHash;
|
|||
using Subnet = QPair<QHostAddress, int>;
|
||||
using SubnetList = std::vector<Subnet>;
|
||||
|
||||
const int INVALID_ICE_LOOKUP_ID = -1;
|
||||
|
||||
enum ReplicationServerDirection {
|
||||
Upstream,
|
||||
Downstream
|
||||
|
@ -114,6 +116,8 @@ private slots:
|
|||
void tokenGrantFinished();
|
||||
void profileRequestFinished();
|
||||
|
||||
void timeoutICEAddressLookup();
|
||||
|
||||
signals:
|
||||
void iceServerChanged();
|
||||
void userConnected();
|
||||
|
@ -223,7 +227,7 @@ private:
|
|||
|
||||
QList<QHostAddress> _iceServerAddresses;
|
||||
QSet<QHostAddress> _failedIceServerAddresses;
|
||||
int _iceAddressLookupID { -1 };
|
||||
int _iceAddressLookupID { INVALID_ICE_LOOKUP_ID };
|
||||
int _noReplyICEHeartbeats { 0 };
|
||||
int _numHeartbeatDenials { 0 };
|
||||
bool _connectedToICEServer { false };
|
||||
|
|
|
@ -6,7 +6,14 @@
|
|||
<title>Welcome to Interface</title>
|
||||
|
||||
<style>
|
||||
body {
|
||||
@font-face {
|
||||
font-family: 'Raleway Light';
|
||||
src: url('../fonts/Raleway-Light.ttf') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
background: black;
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
|
@ -15,6 +22,14 @@
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
a:link {color:inherit}
|
||||
a:active {color:inherit}
|
||||
a:visited {color:inherit}
|
||||
a:hover {
|
||||
color:inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#left_button {
|
||||
position: absolute;
|
||||
left: 70;
|
||||
|
@ -38,6 +53,15 @@
|
|||
position: absolute;
|
||||
top: 0; left: 0; bottom: 0; right: 0;
|
||||
}
|
||||
|
||||
#report_problem {
|
||||
position: fixed;
|
||||
top: 10;
|
||||
right: 10;
|
||||
font-family: "Raleway Light", sans-serif;
|
||||
text-decoration: none;
|
||||
color: #ddd;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
var handControllerImageURL = null;
|
||||
|
@ -152,6 +176,7 @@
|
|||
<a href="#" id="left_button" onmousedown="cycleLeft()"></a>
|
||||
<a href="#" id="right_button" onmousedown="cycleRight()"></a>
|
||||
</div>
|
||||
<a href="mailto:support@highfidelity.com" id="report_problem">Report Problem</a>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtWebChannel 1.0
|
||||
import QtWebEngine 1.2
|
||||
import QtWebEngine 1.5
|
||||
|
||||
import "controls"
|
||||
import "controls-uit" as HifiControls
|
||||
|
@ -13,11 +13,11 @@ Item {
|
|||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
HifiStyles.HifiConstants { id: hifistyles }
|
||||
//width: parent.width
|
||||
|
||||
height: 600
|
||||
property variant permissionsBar: {'securityOrigin':'none','feature':'none'}
|
||||
property alias url: webview.url
|
||||
property WebEngineView webView: webview
|
||||
|
||||
property bool canGoBack: webview.canGoBack
|
||||
property bool canGoForward: webview.canGoForward
|
||||
|
||||
|
@ -123,5 +123,4 @@ Item {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtWebEngine 1.2
|
||||
import QtWebEngine 1.5
|
||||
|
||||
WebEngineView {
|
||||
id: root
|
||||
|
|
|
@ -9,10 +9,13 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtWebEngine 1.5
|
||||
|
||||
AnimatedImage {
|
||||
property WebEngineView webview: parent
|
||||
source: "../../icons/loader-snake-64-w.gif"
|
||||
visible: parent.loading && /^(http.*|)$/i.test(parent.url.toString())
|
||||
visible: webview.loading && /^(http.*|)$/i.test(webview.url.toString())
|
||||
playing: visible
|
||||
z: 10000
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
|
|
170
interface/resources/qml/controls/FlickableWebViewCore.qml
Normal file
170
interface/resources/qml/controls/FlickableWebViewCore.qml
Normal file
|
@ -0,0 +1,170 @@
|
|||
import QtQuick 2.7
|
||||
import QtWebEngine 1.5
|
||||
import QtWebChannel 1.0
|
||||
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
import "../styles-uit" as StylesUIt
|
||||
|
||||
Flickable {
|
||||
id: flick
|
||||
|
||||
property alias url: _webview.url
|
||||
property alias canGoBack: _webview.canGoBack
|
||||
property alias webViewCore: _webview
|
||||
property alias webViewCoreProfile: _webview.profile
|
||||
|
||||
property string userScriptUrl: ""
|
||||
property string urlTag: "noDownload=false";
|
||||
|
||||
signal newViewRequestedCallback(var request)
|
||||
signal loadingChangedCallback(var loadRequest)
|
||||
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
|
||||
StylesUIt.HifiConstants {
|
||||
id: hifi
|
||||
}
|
||||
|
||||
onHeightChanged: {
|
||||
if (height > 0) {
|
||||
//reload page since window dimentions changed,
|
||||
//so web engine should recalculate page render dimentions
|
||||
reloadTimer.start()
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
id: scrollBar
|
||||
visible: flick.contentHeight > flick.height
|
||||
|
||||
contentItem: Rectangle {
|
||||
opacity: 0.75
|
||||
implicitWidth: hifi.dimensions.scrollbarHandleWidth
|
||||
radius: height / 2
|
||||
color: hifi.colors.tableScrollHandleDark
|
||||
}
|
||||
}
|
||||
|
||||
function onLoadingChanged(loadRequest) {
|
||||
if (WebEngineView.LoadStartedStatus === loadRequest.status) {
|
||||
flick.contentWidth = flick.width
|
||||
flick.contentHeight = flick.height
|
||||
|
||||
// Required to support clicking on "hifi://" links
|
||||
var url = loadRequest.url.toString();
|
||||
if (urlHandler.canHandleUrl(url)) {
|
||||
if (urlHandler.handleUrl(url)) {
|
||||
_webview.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (WebEngineView.LoadFailedStatus === loadRequest.status) {
|
||||
console.log(" Tablet WebEngineView failed to load url: " + loadRequest.url.toString());
|
||||
}
|
||||
|
||||
if (WebEngineView.LoadSucceededStatus === loadRequest.status) {
|
||||
//disable Chromium's scroll bars
|
||||
_webview.runJavaScript("document.body.style.overflow = 'hidden';");
|
||||
//calculate page height
|
||||
_webview.runJavaScript("document.body.scrollHeight;", function (i_actualPageHeight) {
|
||||
if (i_actualPageHeight !== undefined) {
|
||||
flick.contentHeight = i_actualPageHeight
|
||||
} else {
|
||||
flick.contentHeight = flick.height;
|
||||
}
|
||||
})
|
||||
flick.contentWidth = flick.width
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: reloadTimer
|
||||
interval: 100
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
_webview.reload()
|
||||
}
|
||||
}
|
||||
|
||||
WebEngineView {
|
||||
id: _webview
|
||||
|
||||
height: parent.height
|
||||
|
||||
profile: HFWebEngineProfile;
|
||||
|
||||
// creates a global EventBridge object.
|
||||
WebEngineScript {
|
||||
id: createGlobalEventBridge
|
||||
sourceCode: eventBridgeJavaScriptToInject
|
||||
injectionPoint: WebEngineScript.DocumentCreation
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// detects when to raise and lower virtual keyboard
|
||||
WebEngineScript {
|
||||
id: raiseAndLowerKeyboard
|
||||
injectionPoint: WebEngineScript.Deferred
|
||||
sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js"
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// User script.
|
||||
WebEngineScript {
|
||||
id: userScript
|
||||
sourceUrl: flick.userScriptUrl
|
||||
injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
|
||||
|
||||
property string newUrl: ""
|
||||
|
||||
Component.onCompleted: {
|
||||
width = Qt.binding(function() { return flick.width; });
|
||||
webChannel.registerObject("eventBridge", eventBridge);
|
||||
webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper);
|
||||
// Ensure the JS from the web-engine makes it to our logging
|
||||
_webview.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
|
||||
console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message);
|
||||
});
|
||||
_webview.profile.httpUserAgent = "Mozilla/5.0 Chrome (HighFidelityInterface)";
|
||||
|
||||
}
|
||||
|
||||
onFeaturePermissionRequested: {
|
||||
grantFeaturePermission(securityOrigin, feature, true);
|
||||
}
|
||||
|
||||
onContentsSizeChanged: {
|
||||
flick.contentHeight = Math.max(contentsSize.height, flick.height);
|
||||
flick.contentWidth = flick.width
|
||||
}
|
||||
//disable popup
|
||||
onContextMenuRequested: {
|
||||
request.accepted = true;
|
||||
}
|
||||
|
||||
onNewViewRequested: {
|
||||
newViewRequestedCallback(request)
|
||||
}
|
||||
|
||||
onLoadingChanged: {
|
||||
flick.onLoadingChanged(loadRequest)
|
||||
loadingChangedCallback(loadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedImage {
|
||||
//anchoring doesnt works here when changing content size
|
||||
x: flick.width/2 - width/2
|
||||
y: flick.height/2 - height/2
|
||||
source: "../../icons/loader-snake-64-w.gif"
|
||||
visible: _webview.loading && /^(http.*|)$/i.test(_webview.url.toString())
|
||||
playing: visible
|
||||
z: 10000
|
||||
}
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
import QtQuick 2.5
|
||||
import QtWebEngine 1.1
|
||||
import QtWebChannel 1.0
|
||||
import QtQuick 2.7
|
||||
import "../controls-uit" as HiFiControls
|
||||
|
||||
Item {
|
||||
property alias url: root.url
|
||||
property alias scriptURL: root.userScriptUrl
|
||||
property alias canGoBack: root.canGoBack;
|
||||
property var goBack: root.goBack;
|
||||
property alias urlTag: root.urlTag
|
||||
id: root
|
||||
property alias url: webroot.url
|
||||
property alias scriptURL: webroot.userScriptUrl
|
||||
property alias canGoBack: webroot.canGoBack;
|
||||
property var goBack: webroot.webViewCore.goBack;
|
||||
property alias urlTag: webroot.urlTag
|
||||
property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
|
@ -21,84 +20,20 @@ Item {
|
|||
}
|
||||
*/
|
||||
|
||||
property alias viewProfile: root.profile
|
||||
property alias viewProfile: webroot.webViewCoreProfile
|
||||
|
||||
WebEngineView {
|
||||
id: root
|
||||
objectName: "webEngineView"
|
||||
x: 0
|
||||
y: 0
|
||||
FlickableWebViewCore {
|
||||
id: webroot
|
||||
width: parent.width
|
||||
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height
|
||||
|
||||
profile: HFWebEngineProfile;
|
||||
|
||||
property string userScriptUrl: ""
|
||||
|
||||
// creates a global EventBridge object.
|
||||
WebEngineScript {
|
||||
id: createGlobalEventBridge
|
||||
sourceCode: eventBridgeJavaScriptToInject
|
||||
injectionPoint: WebEngineScript.DocumentCreation
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// detects when to raise and lower virtual keyboard
|
||||
WebEngineScript {
|
||||
id: raiseAndLowerKeyboard
|
||||
injectionPoint: WebEngineScript.Deferred
|
||||
sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js"
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// User script.
|
||||
WebEngineScript {
|
||||
id: userScript
|
||||
sourceUrl: root.userScriptUrl
|
||||
injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
property string urlTag: "noDownload=false";
|
||||
|
||||
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
|
||||
|
||||
property string newUrl: ""
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
webChannel.registerObject("eventBridge", eventBridge);
|
||||
webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper);
|
||||
// Ensure the JS from the web-engine makes it to our logging
|
||||
root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
|
||||
console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message);
|
||||
});
|
||||
|
||||
root.profile.httpUserAgent = "Mozilla/5.0 Chrome (HighFidelityInterface)";
|
||||
}
|
||||
|
||||
onFeaturePermissionRequested: {
|
||||
grantFeaturePermission(securityOrigin, feature, true);
|
||||
}
|
||||
|
||||
onLoadingChanged: {
|
||||
onLoadingChangedCallback: {
|
||||
keyboardRaised = false;
|
||||
punctuationMode = false;
|
||||
keyboard.resetShiftMode(false);
|
||||
|
||||
// Required to support clicking on "hifi://" links
|
||||
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
|
||||
var url = loadRequest.url.toString();
|
||||
url = (url.indexOf("?") >= 0) ? url + urlTag : url + "?" + urlTag;
|
||||
if (urlHandler.canHandleUrl(url)) {
|
||||
if (urlHandler.handleUrl(url)) {
|
||||
root.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onNewViewRequested:{
|
||||
onNewViewRequestedCallback: {
|
||||
// desktop is not defined for web-entities or tablet
|
||||
if (typeof desktop !== "undefined") {
|
||||
desktop.openBrowserWindow(request, profile);
|
||||
|
@ -107,7 +42,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
HiFiControls.WebSpinner { }
|
||||
}
|
||||
|
||||
HiFiControls.Keyboard {
|
||||
|
@ -120,5 +54,4 @@ Item {
|
|||
bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtWebEngine 1.2
|
||||
import QtWebChannel 1.0
|
||||
import QtQuick 2.7
|
||||
import QtWebEngine 1.5
|
||||
import "../controls-uit" as HiFiControls
|
||||
import "../styles" as HifiStyles
|
||||
import "../styles-uit"
|
||||
import "../"
|
||||
import "."
|
||||
|
||||
Item {
|
||||
id: web
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
width: parent !== null ? parent.width : undefined
|
||||
height: parent !== null ? parent.height : undefined
|
||||
property var parentStackItem: null
|
||||
property int headerHeight: 70
|
||||
property string url
|
||||
|
@ -21,8 +17,8 @@ Item {
|
|||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
property bool isDesktop: false
|
||||
property alias webView: webview
|
||||
property alias profile: webview.profile
|
||||
property alias webView: web.webViewCore
|
||||
property alias profile: web.webViewCoreProfile
|
||||
property bool remove: false
|
||||
property bool closeButtonVisible: true
|
||||
|
||||
|
@ -79,7 +75,7 @@ Item {
|
|||
color: hifi.colors.baseGray
|
||||
font.pixelSize: 12
|
||||
verticalAlignment: Text.AlignLeft
|
||||
text: webview.url
|
||||
text: root.url
|
||||
anchors {
|
||||
top: nav.bottom
|
||||
horizontalCenter: parent.horizontalCenter;
|
||||
|
@ -104,13 +100,13 @@ Item {
|
|||
|
||||
function closeWebEngine() {
|
||||
if (remove) {
|
||||
web.destroy();
|
||||
root.destroy();
|
||||
return;
|
||||
}
|
||||
if (parentStackItem) {
|
||||
parentStackItem.pop();
|
||||
} else {
|
||||
web.visible = false;
|
||||
root.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,67 +124,19 @@ Item {
|
|||
}
|
||||
|
||||
function loadUrl(url) {
|
||||
webview.url = url
|
||||
web.url = webview.url;
|
||||
web.webViewCore.url = url
|
||||
root.url = web.webViewCore.url;
|
||||
}
|
||||
|
||||
onUrlChanged: {
|
||||
loadUrl(url);
|
||||
}
|
||||
|
||||
WebEngineView {
|
||||
id: webview
|
||||
objectName: "webEngineView"
|
||||
x: 0
|
||||
y: 0
|
||||
FlickableWebViewCore {
|
||||
id: web
|
||||
width: parent.width
|
||||
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height - web.headerHeight : parent.height - web.headerHeight
|
||||
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height - root.headerHeight : parent.height - root.headerHeight
|
||||
anchors.top: buttons.bottom
|
||||
profile: HFWebEngineProfile;
|
||||
|
||||
property string userScriptUrl: ""
|
||||
|
||||
// creates a global EventBridge object.
|
||||
WebEngineScript {
|
||||
id: createGlobalEventBridge
|
||||
sourceCode: eventBridgeJavaScriptToInject
|
||||
injectionPoint: WebEngineScript.DocumentCreation
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// detects when to raise and lower virtual keyboard
|
||||
WebEngineScript {
|
||||
id: raiseAndLowerKeyboard
|
||||
injectionPoint: WebEngineScript.Deferred
|
||||
sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js"
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// User script.
|
||||
WebEngineScript {
|
||||
id: userScript
|
||||
sourceUrl: webview.userScriptUrl
|
||||
injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
property string urlTag: "noDownload=false";
|
||||
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
|
||||
|
||||
property string newUrl: ""
|
||||
|
||||
Component.onCompleted: {
|
||||
webChannel.registerObject("eventBridge", eventBridge);
|
||||
webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper);
|
||||
// Ensure the JS from the web-engine makes it to our logging
|
||||
webview.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
|
||||
console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message);
|
||||
});
|
||||
}
|
||||
|
||||
onFeaturePermissionRequested: {
|
||||
grantFeaturePermission(securityOrigin, feature, true);
|
||||
}
|
||||
|
||||
onUrlChanged: {
|
||||
// Record history, skipping null and duplicate items.
|
||||
|
@ -201,34 +149,16 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
onLoadingChanged: {
|
||||
onLoadingChangedCallback: {
|
||||
keyboardRaised = false;
|
||||
punctuationMode = false;
|
||||
keyboard.resetShiftMode(false);
|
||||
// Required to support clicking on "hifi://" links
|
||||
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
|
||||
var url = loadRequest.url.toString();
|
||||
if (urlHandler.canHandleUrl(url)) {
|
||||
if (urlHandler.handleUrl(url)) {
|
||||
root.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (WebEngineView.LoadFailedStatus == loadRequest.status) {
|
||||
console.log(" Tablet WebEngineView failed to load url: " + loadRequest.url.toString());
|
||||
}
|
||||
|
||||
if (WebEngineView.LoadSucceededStatus == loadRequest.status) {
|
||||
webview.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
onNewViewRequested: {
|
||||
request.openIn(webview);
|
||||
webViewCore.forceActiveFocus();
|
||||
}
|
||||
|
||||
HiFiControls.WebSpinner { }
|
||||
onNewViewRequestedCallback: {
|
||||
request.openIn(webViewCore);
|
||||
}
|
||||
}
|
||||
|
||||
HiFiControls.Keyboard {
|
||||
|
@ -244,7 +174,7 @@ Item {
|
|||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
web.isDesktop = (typeof desktop !== "undefined");
|
||||
root.isDesktop = (typeof desktop !== "undefined");
|
||||
keyboardEnabled = HMD.active;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
import QtQuick 2.5
|
||||
import QtWebEngine 1.1
|
||||
import QtWebChannel 1.0
|
||||
import QtQuick 2.7
|
||||
import "../controls-uit" as HiFiControls
|
||||
|
||||
Item {
|
||||
property alias url: root.url
|
||||
property alias scriptURL: root.userScriptUrl
|
||||
property alias canGoBack: root.canGoBack;
|
||||
property var goBack: root.goBack;
|
||||
property alias urlTag: root.urlTag
|
||||
width: parent !== null ? parent.width : undefined
|
||||
height: parent !== null ? parent.height : undefined
|
||||
|
||||
property alias url: webroot.url
|
||||
property alias scriptURL: webroot.userScriptUrl
|
||||
property alias canGoBack: webroot.canGoBack;
|
||||
property var goBack: webroot.webViewCore.goBack;
|
||||
property alias urlTag: webroot.urlTag
|
||||
property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
property alias flickable: webroot.interactive
|
||||
|
||||
// FIXME - Keyboard HMD only: Make Interface either set keyboardRaised property directly in OffscreenQmlSurface
|
||||
// or provide HMDinfo object to QML in RenderableWebEntityItem and do the following.
|
||||
|
@ -21,82 +23,20 @@ Item {
|
|||
}
|
||||
*/
|
||||
|
||||
property alias viewProfile: root.profile
|
||||
property alias viewProfile: webroot.webViewCoreProfile
|
||||
|
||||
WebEngineView {
|
||||
id: root
|
||||
objectName: "webEngineView"
|
||||
x: 0
|
||||
y: 0
|
||||
FlickableWebViewCore {
|
||||
id: webroot
|
||||
width: parent.width
|
||||
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height
|
||||
|
||||
profile: HFWebEngineProfile;
|
||||
|
||||
property string userScriptUrl: ""
|
||||
|
||||
// creates a global EventBridge object.
|
||||
WebEngineScript {
|
||||
id: createGlobalEventBridge
|
||||
sourceCode: eventBridgeJavaScriptToInject
|
||||
injectionPoint: WebEngineScript.DocumentCreation
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// detects when to raise and lower virtual keyboard
|
||||
WebEngineScript {
|
||||
id: raiseAndLowerKeyboard
|
||||
injectionPoint: WebEngineScript.Deferred
|
||||
sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js"
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
// User script.
|
||||
WebEngineScript {
|
||||
id: userScript
|
||||
sourceUrl: root.userScriptUrl
|
||||
injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
property string urlTag: "noDownload=false";
|
||||
|
||||
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
|
||||
|
||||
property string newUrl: ""
|
||||
|
||||
Component.onCompleted: {
|
||||
webChannel.registerObject("eventBridge", eventBridge);
|
||||
webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper);
|
||||
// Ensure the JS from the web-engine makes it to our logging
|
||||
root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
|
||||
console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
onFeaturePermissionRequested: {
|
||||
grantFeaturePermission(securityOrigin, feature, true);
|
||||
}
|
||||
|
||||
onLoadingChanged: {
|
||||
onLoadingChangedCallback: {
|
||||
keyboardRaised = false;
|
||||
punctuationMode = false;
|
||||
keyboard.resetShiftMode(false);
|
||||
|
||||
// Required to support clicking on "hifi://" links
|
||||
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
|
||||
var url = loadRequest.url.toString();
|
||||
url = (url.indexOf("?") >= 0) ? url + urlTag : url + "?" + urlTag;
|
||||
if (urlHandler.canHandleUrl(url)) {
|
||||
if (urlHandler.handleUrl(url)) {
|
||||
root.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onNewViewRequested:{
|
||||
onNewViewRequestedCallback: {
|
||||
// desktop is not defined for web-entities or tablet
|
||||
if (typeof desktop !== "undefined") {
|
||||
desktop.openBrowserWindow(request, profile);
|
||||
|
@ -104,8 +44,6 @@ Item {
|
|||
tabletRoot.openBrowserWindow(request, profile);
|
||||
}
|
||||
}
|
||||
|
||||
HiFiControls.WebSpinner { }
|
||||
}
|
||||
|
||||
HiFiControls.Keyboard {
|
||||
|
@ -118,5 +56,4 @@ Item {
|
|||
bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,6 +36,24 @@ Rectangle {
|
|||
return (root.parent !== null) && root.parent.objectName == "loader";
|
||||
}
|
||||
|
||||
property bool showPeaks: true;
|
||||
function enablePeakValues() {
|
||||
Audio.devices.input.peakValuesEnabled = true;
|
||||
Audio.devices.input.peakValuesEnabledChanged.connect(function(enabled) {
|
||||
if (!enabled && root.showPeaks) {
|
||||
Audio.devices.input.peakValuesEnabled = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
function disablePeakValues() {
|
||||
root.showPeaks = false;
|
||||
Audio.devices.input.peakValuesEnabled = false;
|
||||
}
|
||||
|
||||
Component.onCompleted: enablePeakValues();
|
||||
Component.onDestruction: disablePeakValues();
|
||||
onVisibleChanged: visible ? enablePeakValues() : disablePeakValues();
|
||||
|
||||
Column {
|
||||
y: 16; // padding does not work
|
||||
spacing: 16;
|
||||
|
@ -133,12 +151,13 @@ Rectangle {
|
|||
onClicked: Audio.setInputDevice(info);
|
||||
}
|
||||
|
||||
InputLevel {
|
||||
id: level;
|
||||
InputPeak {
|
||||
id: inputPeak;
|
||||
visible: Audio.devices.input.peakValuesAvailable;
|
||||
peak: model.peak;
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 30
|
||||
visible: selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// InputLevel.qml
|
||||
// InputPeak.qml
|
||||
// qml/hifi/audio
|
||||
//
|
||||
// Created by Zach Pomerantz on 6/20/2017
|
||||
|
@ -15,7 +15,7 @@ import QtQuick.Layouts 1.3
|
|||
import QtGraphicalEffects 1.0
|
||||
|
||||
Rectangle {
|
||||
readonly property var level: Audio.inputLevel;
|
||||
property var peak;
|
||||
|
||||
width: 70;
|
||||
height: 8;
|
||||
|
@ -65,7 +65,7 @@ Rectangle {
|
|||
|
||||
Rectangle { // mask
|
||||
id: mask;
|
||||
width: parent.width * level;
|
||||
width: parent.width * peak;
|
||||
radius: 5;
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
|
@ -55,6 +55,7 @@ Item {
|
|||
text: "DEBUG: Clear Cached Passphrase";
|
||||
onClicked: {
|
||||
commerce.setPassphrase("");
|
||||
sendSignalToWallet({method: 'passphraseReset'});
|
||||
}
|
||||
}
|
||||
HifiControlsUit.Button {
|
||||
|
|
|
@ -33,12 +33,19 @@ Rectangle {
|
|||
Hifi.QmlCommerce {
|
||||
id: commerce;
|
||||
|
||||
onAccountResult: {
|
||||
if (result.status === "success") {
|
||||
commerce.getKeyFilePathIfExists();
|
||||
} else {
|
||||
// unsure how to handle a failure here. We definitely cannot proceed.
|
||||
}
|
||||
}
|
||||
onLoginStatusResult: {
|
||||
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
||||
root.activeView = "needsLogIn";
|
||||
} else if (isLoggedIn) {
|
||||
root.activeView = "initialize";
|
||||
commerce.getKeyFilePathIfExists();
|
||||
commerce.account();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,7 +325,7 @@ Rectangle {
|
|||
|
||||
Connections {
|
||||
onSendSignalToWallet: {
|
||||
if (msg.method === 'walletReset') {
|
||||
if (msg.method === 'walletReset' || msg.method === 'passphraseReset') {
|
||||
sendToScript(msg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -325,7 +325,7 @@ Rectangle {
|
|||
onClicked: {
|
||||
if (passphraseSelection.validateAndSubmitPassphrase()) {
|
||||
root.lastPage = "choosePassphrase";
|
||||
commerce.balance(); // Do this here so that keys are generated. Order might change as backend changes?
|
||||
commerce.generateKeyPair();
|
||||
choosePassphraseContainer.visible = false;
|
||||
privateKeysReadyContainer.visible = true;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.5
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import "../../styles-uit"
|
||||
import "../audio" as HifiAudio
|
||||
|
@ -109,15 +110,45 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
id: usernameText
|
||||
text: tabletRoot.username
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Item {
|
||||
width: 150
|
||||
height: 50
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 20
|
||||
horizontalAlignment: Text.AlignRight
|
||||
font.pixelSize: 20
|
||||
color: "#afafaf"
|
||||
anchors.rightMargin: 30
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
RalewaySemiBold {
|
||||
text: Account.loggedIn ? qsTr("Log out") : qsTr("Log in")
|
||||
horizontalAlignment: Text.AlignRight
|
||||
anchors.right: parent.right
|
||||
font.pixelSize: 20
|
||||
color: "#afafaf"
|
||||
}
|
||||
|
||||
RalewaySemiBold {
|
||||
visible: Account.loggedIn
|
||||
height: Account.loggedIn ? parent.height/2 - parent.spacing/2 : 0
|
||||
text: Account.loggedIn ? "[" + tabletRoot.usernameShort + "]" : ""
|
||||
horizontalAlignment: Text.AlignRight
|
||||
anchors.right: parent.right
|
||||
font.pixelSize: 20
|
||||
color: "#afafaf"
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
if (!Account.loggedIn) {
|
||||
DialogsManager.showLoginDialog()
|
||||
} else {
|
||||
Account.logOut()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@ import QtGraphicalEffects 1.0
|
|||
|
||||
Item {
|
||||
id: tabletButton
|
||||
|
||||
property string captionColorOverride: ""
|
||||
property var uuid;
|
||||
property string icon: "icons/tablet-icons/edit-i.svg"
|
||||
property string hoverIcon: tabletButton.icon
|
||||
|
@ -102,7 +104,7 @@ Item {
|
|||
|
||||
Text {
|
||||
id: text
|
||||
color: "#ffffff"
|
||||
color: captionColorOverride !== "" ? captionColorOverride: "#ffffff"
|
||||
text: tabletButton.text
|
||||
font.bold: true
|
||||
font.pixelSize: 18
|
||||
|
|
|
@ -8,6 +8,7 @@ Item {
|
|||
id: tabletRoot
|
||||
objectName: "tabletRoot"
|
||||
property string username: "Unknown user"
|
||||
property string usernameShort: "Unknown user"
|
||||
property var rootMenu;
|
||||
property var openModal: null;
|
||||
property var openMessage: null;
|
||||
|
@ -157,6 +158,11 @@ Item {
|
|||
|
||||
function setUsername(newUsername) {
|
||||
username = newUsername;
|
||||
usernameShort = newUsername.substring(0, 8);
|
||||
|
||||
if (newUsername.length > 8) {
|
||||
usernameShort = usernameShort + "..."
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
|
|
|
@ -604,6 +604,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
DependencyManager::registerInheritance<SpatialParentFinder, InterfaceParentFinder>();
|
||||
|
||||
// Set dependencies
|
||||
DependencyManager::set<Cursor::Manager>();
|
||||
DependencyManager::set<AccountManager>(std::bind(&Application::getUserAgent, qApp));
|
||||
DependencyManager::set<StatTracker>();
|
||||
DependencyManager::set<ScriptEngines>(ScriptEngine::CLIENT_SCRIPT);
|
||||
|
@ -2802,35 +2803,18 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
|
|||
|
||||
// Get controller availability
|
||||
bool hasHandControllers = false;
|
||||
HandControllerType handControllerType = Vive;
|
||||
if (PluginUtils::isViveControllerAvailable()) {
|
||||
if (PluginUtils::isViveControllerAvailable() || PluginUtils::isOculusTouchControllerAvailable()) {
|
||||
hasHandControllers = true;
|
||||
handControllerType = Vive;
|
||||
} else if (PluginUtils::isOculusTouchControllerAvailable()) {
|
||||
hasHandControllers = true;
|
||||
handControllerType = Oculus;
|
||||
}
|
||||
|
||||
// Check tutorial content versioning
|
||||
bool hasTutorialContent = contentVersion >= MIN_CONTENT_VERSION.at(handControllerType);
|
||||
|
||||
// Check HMD use (may be technically available without being in use)
|
||||
bool hasHMD = PluginUtils::isHMDAvailable();
|
||||
bool isUsingHMD = _displayPlugin->isHmd();
|
||||
bool isUsingHMDAndHandControllers = hasHMD && hasHandControllers && isUsingHMD;
|
||||
|
||||
Setting::Handle<bool> tutorialComplete{ "tutorialComplete", false };
|
||||
Setting::Handle<bool> firstRun{ Settings::firstRun, true };
|
||||
|
||||
const QString HIFI_SKIP_TUTORIAL_COMMAND_LINE_KEY = "--skipTutorial";
|
||||
// Skips tutorial/help behavior, and does NOT clear firstRun setting.
|
||||
bool skipTutorial = arguments().contains(HIFI_SKIP_TUTORIAL_COMMAND_LINE_KEY);
|
||||
bool isTutorialComplete = tutorialComplete.get();
|
||||
bool shouldGoToTutorial = isUsingHMDAndHandControllers && hasTutorialContent && !isTutorialComplete && !skipTutorial;
|
||||
|
||||
qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMDAndHandControllers;
|
||||
qCDebug(interfaceapp) << "Tutorial version:" << contentVersion << ", sufficient:" << hasTutorialContent <<
|
||||
", complete:" << isTutorialComplete << ", should go:" << shouldGoToTutorial;
|
||||
|
||||
// when --url in command line, teleport to location
|
||||
const QString HIFI_URL_COMMAND_LINE_KEY = "--url";
|
||||
|
@ -2840,58 +2824,31 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
|
|||
addressLookupString = arguments().value(urlIndex + 1);
|
||||
}
|
||||
|
||||
const QString TUTORIAL_PATH = "/tutorial_begin";
|
||||
|
||||
static const QString SENT_TO_TUTORIAL = "tutorial";
|
||||
static const QString SENT_TO_PREVIOUS_LOCATION = "previous_location";
|
||||
static const QString SENT_TO_ENTRY = "entry";
|
||||
static const QString SENT_TO_SANDBOX = "sandbox";
|
||||
|
||||
QString sentTo;
|
||||
|
||||
if (shouldGoToTutorial) {
|
||||
if (sandboxIsRunning) {
|
||||
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
|
||||
DependencyManager::get<AddressManager>()->goToLocalSandbox(TUTORIAL_PATH);
|
||||
sentTo = SENT_TO_TUTORIAL;
|
||||
} else {
|
||||
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
|
||||
if (firstRun.get()) {
|
||||
showHelp();
|
||||
}
|
||||
if (addressLookupString.isEmpty()) {
|
||||
DependencyManager::get<AddressManager>()->goToEntry();
|
||||
sentTo = SENT_TO_ENTRY;
|
||||
} else {
|
||||
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
|
||||
sentTo = SENT_TO_PREVIOUS_LOCATION;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// If this is a first run we short-circuit the address passed in
|
||||
if (firstRun.get() && !skipTutorial) {
|
||||
if (firstRun.get()) {
|
||||
showHelp();
|
||||
if (isUsingHMDAndHandControllers) {
|
||||
if (sandboxIsRunning) {
|
||||
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
|
||||
DependencyManager::get<AddressManager>()->goToLocalSandbox();
|
||||
sentTo = SENT_TO_SANDBOX;
|
||||
} else {
|
||||
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
|
||||
DependencyManager::get<AddressManager>()->goToEntry();
|
||||
sentTo = SENT_TO_ENTRY;
|
||||
}
|
||||
if (sandboxIsRunning) {
|
||||
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
|
||||
DependencyManager::get<AddressManager>()->goToLocalSandbox();
|
||||
sentTo = SENT_TO_SANDBOX;
|
||||
} else {
|
||||
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
|
||||
DependencyManager::get<AddressManager>()->goToEntry();
|
||||
sentTo = SENT_TO_ENTRY;
|
||||
}
|
||||
firstRun.set(false);
|
||||
|
||||
} else {
|
||||
qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
|
||||
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
|
||||
sentTo = SENT_TO_PREVIOUS_LOCATION;
|
||||
}
|
||||
}
|
||||
|
||||
UserActivityLogger::getInstance().logAction("startup_sent_to", {
|
||||
{ "sent_to", sentTo },
|
||||
|
@ -2900,18 +2857,10 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
|
|||
{ "has_hand_controllers", hasHandControllers },
|
||||
{ "is_using_hmd", isUsingHMD },
|
||||
{ "is_using_hmd_and_hand_controllers", isUsingHMDAndHandControllers },
|
||||
{ "content_version", contentVersion },
|
||||
{ "is_tutorial_complete", isTutorialComplete },
|
||||
{ "has_tutorial_content", hasTutorialContent },
|
||||
{ "should_go_to_tutorial", shouldGoToTutorial }
|
||||
{ "content_version", contentVersion }
|
||||
});
|
||||
|
||||
_connectionMonitor.init();
|
||||
|
||||
// After all of the constructor is completed, then set firstRun to false.
|
||||
if (!skipTutorial) {
|
||||
firstRun.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
bool Application::importJSONFromURL(const QString& urlString) {
|
||||
|
@ -6320,11 +6269,11 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) {
|
|||
|
||||
bool Application::askToReplaceDomainContent(const QString& url) {
|
||||
QString methodDetails;
|
||||
const int MAX_CHARACTERS_PER_LINE = 90;
|
||||
if (DependencyManager::get<NodeList>()->getThisNodeCanReplaceContent()) {
|
||||
QUrl originURL { url };
|
||||
if (originURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) {
|
||||
// Create a confirmation dialog when this call is made
|
||||
const int MAX_CHARACTERS_PER_LINE = 90;
|
||||
static const QString infoText = simpleWordWrap("Your domain's content will be replaced with a new content set. "
|
||||
"If you want to save what you have now, create a backup before proceeding. For more information about backing up "
|
||||
"and restoring content, visit the documentation page at: ", MAX_CHARACTERS_PER_LINE) +
|
||||
|
@ -6360,7 +6309,9 @@ bool Application::askToReplaceDomainContent(const QString& url) {
|
|||
}
|
||||
} else {
|
||||
methodDetails = "UserDoesNotHavePermissionToReplaceContent";
|
||||
OffscreenUi::warning("Unable to replace content", "You do not have permissions to replace domain content",
|
||||
static const QString warningMessage = simpleWordWrap("The domain owner must enable 'Replace Content' "
|
||||
"permissions for you in this domain's server settings before you can continue.", MAX_CHARACTERS_PER_LINE);
|
||||
OffscreenUi::warning("You do not have permissions to replace domain content", warningMessage,
|
||||
QMessageBox::Ok, QMessageBox::Ok);
|
||||
}
|
||||
QJsonObject messageProperties = {
|
||||
|
@ -7438,7 +7389,10 @@ void Application::updateDisplayMode() {
|
|||
getApplicationCompositor().setDisplayPlugin(newDisplayPlugin);
|
||||
_displayPlugin = newDisplayPlugin;
|
||||
connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent);
|
||||
offscreenUi->getDesktop()->setProperty("repositionLocked", wasRepositionLocked);
|
||||
auto desktop = offscreenUi->getDesktop();
|
||||
if (desktop) {
|
||||
desktop->setProperty("repositionLocked", wasRepositionLocked);
|
||||
}
|
||||
}
|
||||
|
||||
bool isHmd = _displayPlugin->isHmd();
|
||||
|
|
|
@ -1912,6 +1912,17 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) {
|
|||
const bool shouldDrawHead = shouldRenderHead(renderArgs);
|
||||
if (shouldDrawHead != _prevShouldDrawHead) {
|
||||
_skeletonModel->setEnableCauterization(!shouldDrawHead);
|
||||
|
||||
for (int i = 0; i < _attachmentData.size(); i++) {
|
||||
if (_attachmentData[i].jointName.compare("Head", Qt::CaseInsensitive) == 0 ||
|
||||
_attachmentData[i].jointName.compare("Neck", Qt::CaseInsensitive) == 0 ||
|
||||
_attachmentData[i].jointName.compare("LeftEye", Qt::CaseInsensitive) == 0 ||
|
||||
_attachmentData[i].jointName.compare("RightEye", Qt::CaseInsensitive) == 0 ||
|
||||
_attachmentData[i].jointName.compare("HeadTop_End", Qt::CaseInsensitive) == 0 ||
|
||||
_attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) {
|
||||
_attachmentModels[i]->setVisibleInScene(shouldDrawHead, qApp->getMain3DScene());
|
||||
}
|
||||
}
|
||||
}
|
||||
_prevShouldDrawHead = shouldDrawHead;
|
||||
}
|
||||
|
|
|
@ -176,3 +176,28 @@ void Ledger::resetFailure(QNetworkReply& reply) { failResponse("reset", reply);
|
|||
void Ledger::reset() {
|
||||
send("reset_user_hfc_account", "resetSuccess", "resetFailure", QNetworkAccessManager::PutOperation, QJsonObject());
|
||||
}
|
||||
|
||||
void Ledger::accountSuccess(QNetworkReply& reply) {
|
||||
// lets set the appropriate stuff in the wallet now
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
QByteArray response = reply.readAll();
|
||||
QJsonObject data = QJsonDocument::fromJson(response).object()["data"].toObject();
|
||||
|
||||
auto salt = QByteArray::fromBase64(data["salt"].toString().toUtf8());
|
||||
auto iv = QByteArray::fromBase64(data["iv"].toString().toUtf8());
|
||||
auto ckey = QByteArray::fromBase64(data["ckey"].toString().toUtf8());
|
||||
|
||||
wallet->setSalt(salt);
|
||||
wallet->setIv(iv);
|
||||
wallet->setCKey(ckey);
|
||||
|
||||
// none of the hfc account info should be emitted
|
||||
emit accountResult(QJsonObject{ {"status", "success"} });
|
||||
}
|
||||
|
||||
void Ledger::accountFailure(QNetworkReply& reply) {
|
||||
failResponse("account", reply);
|
||||
}
|
||||
void Ledger::account() {
|
||||
send("hfc_account", "accountSuccess", "accountFailure", QNetworkAccessManager::PutOperation, QJsonObject());
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ public:
|
|||
void balance(const QStringList& keys);
|
||||
void inventory(const QStringList& keys);
|
||||
void history(const QStringList& keys);
|
||||
void account();
|
||||
void reset();
|
||||
|
||||
signals:
|
||||
|
@ -37,6 +38,7 @@ signals:
|
|||
void balanceResult(QJsonObject result);
|
||||
void inventoryResult(QJsonObject result);
|
||||
void historyResult(QJsonObject result);
|
||||
void accountResult(QJsonObject result);
|
||||
|
||||
public slots:
|
||||
void buySuccess(QNetworkReply& reply);
|
||||
|
@ -51,6 +53,8 @@ public slots:
|
|||
void historyFailure(QNetworkReply& reply);
|
||||
void resetSuccess(QNetworkReply& reply);
|
||||
void resetFailure(QNetworkReply& reply);
|
||||
void accountSuccess(QNetworkReply& reply);
|
||||
void accountFailure(QNetworkReply& reply);
|
||||
|
||||
private:
|
||||
QJsonObject apiResponse(const QString& label, QNetworkReply& reply);
|
||||
|
|
|
@ -27,6 +27,7 @@ QmlCommerce::QmlCommerce(QQuickItem* parent) : OffscreenQmlDialog(parent) {
|
|||
connect(wallet.data(), &Wallet::securityImageResult, this, &QmlCommerce::securityImageResult);
|
||||
connect(ledger.data(), &Ledger::historyResult, this, &QmlCommerce::historyResult);
|
||||
connect(wallet.data(), &Wallet::keyFilePathIfExistsResult, this, &QmlCommerce::keyFilePathIfExistsResult);
|
||||
connect(ledger.data(), &Ledger::accountResult, this, &QmlCommerce::accountResult);
|
||||
}
|
||||
|
||||
void QmlCommerce::getLoginStatus() {
|
||||
|
@ -86,7 +87,7 @@ void QmlCommerce::history() {
|
|||
|
||||
void QmlCommerce::setPassphrase(const QString& passphrase) {
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
if (wallet->getPassphrase() && !wallet->getPassphrase()->isEmpty()) {
|
||||
if(wallet->getPassphrase() && !wallet->getPassphrase()->isEmpty() && !passphrase.isEmpty()) {
|
||||
wallet->changePassphrase(passphrase);
|
||||
} else {
|
||||
wallet->setPassphrase(passphrase);
|
||||
|
@ -94,9 +95,20 @@ void QmlCommerce::setPassphrase(const QString& passphrase) {
|
|||
getWalletAuthenticatedStatus();
|
||||
}
|
||||
|
||||
void QmlCommerce::generateKeyPair() {
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
wallet->generateKeyPair();
|
||||
getWalletAuthenticatedStatus();
|
||||
}
|
||||
|
||||
void QmlCommerce::reset() {
|
||||
auto ledger = DependencyManager::get<Ledger>();
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
ledger->reset();
|
||||
wallet->reset();
|
||||
}
|
||||
|
||||
void QmlCommerce::account() {
|
||||
auto ledger = DependencyManager::get<Ledger>();
|
||||
ledger->account();
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ signals:
|
|||
void balanceResult(QJsonObject result);
|
||||
void inventoryResult(QJsonObject result);
|
||||
void historyResult(QJsonObject result);
|
||||
void accountResult(QJsonObject result);
|
||||
|
||||
protected:
|
||||
Q_INVOKABLE void getLoginStatus();
|
||||
|
@ -53,8 +54,9 @@ protected:
|
|||
Q_INVOKABLE void balance();
|
||||
Q_INVOKABLE void inventory();
|
||||
Q_INVOKABLE void history();
|
||||
|
||||
Q_INVOKABLE void generateKeyPair();
|
||||
Q_INVOKABLE void reset();
|
||||
Q_INVOKABLE void account();
|
||||
};
|
||||
|
||||
#endif // hifi_QmlCommerce_h
|
||||
|
|
|
@ -55,9 +55,12 @@ QString imageFilePath() {
|
|||
// use the cached _passphrase if it exists, otherwise we need to prompt
|
||||
int passwordCallback(char* password, int maxPasswordSize, int rwFlag, void* u) {
|
||||
// just return a hardcoded pwd for now
|
||||
auto passphrase = DependencyManager::get<Wallet>()->getPassphrase();
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
auto passphrase = wallet->getPassphrase();
|
||||
if (passphrase && !passphrase->isEmpty()) {
|
||||
strcpy(password, passphrase->toLocal8Bit().constData());
|
||||
QString saltedPassphrase(*passphrase);
|
||||
saltedPassphrase.append(wallet->getSalt());
|
||||
strcpy(password, saltedPassphrase.toUtf8().constData());
|
||||
return static_cast<int>(passphrase->size());
|
||||
} else {
|
||||
// this shouldn't happen - so lets log it to tell us we have
|
||||
|
@ -245,6 +248,8 @@ RSA* readPrivateKey(const char* filename) {
|
|||
|
||||
} else {
|
||||
qCDebug(commerce) << "couldn't parse" << filename;
|
||||
// if the passphrase is wrong, then let's not cache it
|
||||
DependencyManager::get<Wallet>()->setPassphrase("");
|
||||
}
|
||||
fclose(fp);
|
||||
} else {
|
||||
|
@ -252,13 +257,12 @@ RSA* readPrivateKey(const char* filename) {
|
|||
}
|
||||
return key;
|
||||
}
|
||||
static const unsigned char IVEC[16] = "IAmAnIVecYay123";
|
||||
|
||||
void initializeAESKeys(unsigned char* ivec, unsigned char* ckey, const QByteArray& salt) {
|
||||
// first ivec
|
||||
memcpy(ivec, IVEC, 16);
|
||||
auto hash = QCryptographicHash::hash(salt, QCryptographicHash::Sha256);
|
||||
memcpy(ckey, hash.data(), 32);
|
||||
// use the ones in the wallet
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
memcpy(ivec, wallet->getIv(), 16);
|
||||
memcpy(ckey, wallet->getCKey(), 32);
|
||||
}
|
||||
|
||||
Wallet::~Wallet() {
|
||||
|
@ -273,8 +277,6 @@ void Wallet::setPassphrase(const QString& passphrase) {
|
|||
}
|
||||
_passphrase = new QString(passphrase);
|
||||
|
||||
// no matter what, we now need to clear the keys as they
|
||||
// need to be read using this passphrase
|
||||
_publicKeys.clear();
|
||||
}
|
||||
|
||||
|
@ -413,28 +415,10 @@ bool Wallet::walletIsAuthenticatedWithPassphrase() {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Wallet::createIfNeeded() {
|
||||
if (_publicKeys.count() > 0) return false;
|
||||
|
||||
bool Wallet::generateKeyPair() {
|
||||
// FIXME: initialize OpenSSL elsewhere soon
|
||||
initialize();
|
||||
|
||||
// try to read existing keys if they exist...
|
||||
auto publicKey = readPublicKey(keyFilePath().toStdString().c_str());
|
||||
if (publicKey.size() > 0) {
|
||||
if (auto key = readPrivateKey(keyFilePath().toStdString().c_str()) ) {
|
||||
qCDebug(commerce) << "read private key";
|
||||
RSA_free(key);
|
||||
// K -- add the public key since we have a legit private key associated with it
|
||||
_publicKeys.push_back(publicKey.toBase64());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
qCInfo(commerce) << "Creating wallet.";
|
||||
return generateKeyPair();
|
||||
}
|
||||
|
||||
bool Wallet::generateKeyPair() {
|
||||
qCInfo(commerce) << "Generating keypair.";
|
||||
auto keyPair = generateRSAKeypair();
|
||||
sendKeyFilePathIfExists();
|
||||
|
@ -453,7 +437,6 @@ bool Wallet::generateKeyPair() {
|
|||
|
||||
QStringList Wallet::listPublicKeys() {
|
||||
qCInfo(commerce) << "Enumerating public keys.";
|
||||
createIfNeeded();
|
||||
return _publicKeys;
|
||||
}
|
||||
|
||||
|
@ -572,12 +555,8 @@ void Wallet::reset() {
|
|||
|
||||
// tell the provider we got nothing
|
||||
updateImageProvider();
|
||||
delete _passphrase;
|
||||
_passphrase->clear();
|
||||
|
||||
// for now we need to maintain the hard-coded passphrase.
|
||||
// FIXME: remove this line as part of wiring up the passphrase
|
||||
// and probably set it to nullptr
|
||||
_passphrase = new QString("pwd");
|
||||
|
||||
QFile keyFile(keyFilePath());
|
||||
QFile imageFile(imageFilePath());
|
||||
|
@ -608,6 +587,7 @@ bool Wallet::changePassphrase(const QString& newPassphrase) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
qCDebug(commerce) << "couldn't read keys";
|
||||
qCDebug(commerce) << "couldn't decrypt keys with current passphrase, clearing";
|
||||
setPassphrase(QString(""));
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ public:
|
|||
|
||||
~Wallet();
|
||||
// These are currently blocking calls, although they might take a moment.
|
||||
bool createIfNeeded();
|
||||
bool generateKeyPair();
|
||||
QStringList listPublicKeys();
|
||||
QString signWithKey(const QByteArray& text, const QString& key);
|
||||
|
@ -36,6 +35,10 @@ public:
|
|||
|
||||
void setSalt(const QByteArray& salt) { _salt = salt; }
|
||||
QByteArray getSalt() { return _salt; }
|
||||
void setIv(const QByteArray& iv) { _iv = iv; }
|
||||
QByteArray getIv() { return _iv; }
|
||||
void setCKey(const QByteArray& ckey) { _ckey = ckey; }
|
||||
QByteArray getCKey() { return _ckey; }
|
||||
|
||||
void setPassphrase(const QString& passphrase);
|
||||
QString* getPassphrase() { return _passphrase; }
|
||||
|
@ -53,6 +56,8 @@ private:
|
|||
QStringList _publicKeys{};
|
||||
QPixmap* _securityImage { nullptr };
|
||||
QByteArray _salt {"iamsalt!"};
|
||||
QByteArray _iv;
|
||||
QByteArray _ckey;
|
||||
QString* _passphrase { new QString("") };
|
||||
|
||||
void updateImageProvider();
|
||||
|
|
|
@ -18,6 +18,8 @@ AccountScriptingInterface* AccountScriptingInterface::getInstance() {
|
|||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
QObject::connect(accountManager.data(), &AccountManager::profileChanged,
|
||||
&sharedInstance, &AccountScriptingInterface::usernameChanged);
|
||||
QObject::connect(accountManager.data(), &AccountManager::usernameChanged,
|
||||
&sharedInstance, &AccountScriptingInterface::onUsernameChanged);
|
||||
return &sharedInstance;
|
||||
}
|
||||
|
||||
|
@ -31,6 +33,21 @@ bool AccountScriptingInterface::checkAndSignalForAccessToken() {
|
|||
return accountManager->checkAndSignalForAccessToken();
|
||||
}
|
||||
|
||||
void AccountScriptingInterface::logOut() {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
return accountManager->logout();
|
||||
}
|
||||
|
||||
AccountScriptingInterface::AccountScriptingInterface(QObject *parent): QObject(parent) {
|
||||
m_loggedIn = isLoggedIn();
|
||||
emit loggedInChanged(m_loggedIn);
|
||||
}
|
||||
|
||||
void AccountScriptingInterface::onUsernameChanged(QString username) {
|
||||
m_loggedIn = (username != QString());
|
||||
emit loggedInChanged(m_loggedIn);
|
||||
}
|
||||
|
||||
QString AccountScriptingInterface::getUsername() {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
if (accountManager->isLoggedIn()) {
|
||||
|
|
|
@ -18,6 +18,7 @@ class AccountScriptingInterface : public QObject {
|
|||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString username READ getUsername NOTIFY usernameChanged)
|
||||
Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loggedInChanged)
|
||||
|
||||
/**jsdoc
|
||||
* @namespace Account
|
||||
|
@ -32,6 +33,7 @@ signals:
|
|||
* @return {Signal}
|
||||
*/
|
||||
void usernameChanged();
|
||||
void loggedInChanged(bool loggedIn);
|
||||
|
||||
public slots:
|
||||
static AccountScriptingInterface* getInstance();
|
||||
|
@ -50,6 +52,20 @@ public slots:
|
|||
*/
|
||||
bool isLoggedIn();
|
||||
bool checkAndSignalForAccessToken();
|
||||
void logOut();
|
||||
|
||||
public:
|
||||
AccountScriptingInterface(QObject* parent = nullptr);
|
||||
bool loggedIn() const {
|
||||
return m_loggedIn;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void onUsernameChanged(QString username);
|
||||
|
||||
private:
|
||||
bool m_loggedIn { false };
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_AccountScriptingInterface_h
|
||||
|
|
|
@ -37,6 +37,20 @@ Setting::Handle<QString>& getSetting(bool contextIsHMD, QAudio::Mode mode) {
|
|||
}
|
||||
}
|
||||
|
||||
enum AudioDeviceRole {
|
||||
DisplayRole = Qt::DisplayRole,
|
||||
CheckStateRole = Qt::CheckStateRole,
|
||||
PeakRole = Qt::UserRole,
|
||||
InfoRole = Qt::UserRole + 1
|
||||
};
|
||||
|
||||
QHash<int, QByteArray> AudioDeviceList::_roles {
|
||||
{ DisplayRole, "display" },
|
||||
{ CheckStateRole, "selected" },
|
||||
{ PeakRole, "peak" },
|
||||
{ InfoRole, "info" }
|
||||
};
|
||||
|
||||
static QString getTargetDevice(bool hmd, QAudio::Mode mode) {
|
||||
QString deviceName;
|
||||
auto& setting = getSetting(hmd, mode);
|
||||
|
@ -52,29 +66,36 @@ static QString getTargetDevice(bool hmd, QAudio::Mode mode) {
|
|||
return deviceName;
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> AudioDeviceList::_roles {
|
||||
{ Qt::DisplayRole, "display" },
|
||||
{ Qt::CheckStateRole, "selected" },
|
||||
{ Qt::UserRole, "info" }
|
||||
};
|
||||
Qt::ItemFlags AudioDeviceList::_flags { Qt::ItemIsSelectable | Qt::ItemIsEnabled };
|
||||
|
||||
QVariant AudioDeviceList::data(const QModelIndex& index, int role) const {
|
||||
if (!index.isValid() || index.row() >= _devices.size()) {
|
||||
if (!index.isValid() || index.row() >= rowCount()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
return _devices.at(index.row()).display;
|
||||
} else if (role == Qt::CheckStateRole) {
|
||||
return _devices.at(index.row()).selected;
|
||||
} else if (role == Qt::UserRole) {
|
||||
return QVariant::fromValue<QAudioDeviceInfo>(_devices.at(index.row()).info);
|
||||
if (role == DisplayRole) {
|
||||
return _devices.at(index.row())->display;
|
||||
} else if (role == CheckStateRole) {
|
||||
return _devices.at(index.row())->selected;
|
||||
} else if (role == InfoRole) {
|
||||
return QVariant::fromValue<QAudioDeviceInfo>(_devices.at(index.row())->info);
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant AudioInputDeviceList::data(const QModelIndex& index, int role) const {
|
||||
if (!index.isValid() || index.row() >= rowCount()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (role == PeakRole) {
|
||||
return std::static_pointer_cast<AudioInputDevice>(_devices.at(index.row()))->peak;
|
||||
} else {
|
||||
return AudioDeviceList::data(index, role);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioDeviceList::resetDevice(bool contextIsHMD) {
|
||||
auto client = DependencyManager::get<AudioClient>().data();
|
||||
QString deviceName = getTargetDevice(contextIsHMD, _mode);
|
||||
|
@ -113,8 +134,9 @@ void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device) {
|
|||
auto oldDevice = _selectedDevice;
|
||||
_selectedDevice = device;
|
||||
|
||||
for (auto i = 0; i < _devices.size(); ++i) {
|
||||
AudioDevice& device = _devices[i];
|
||||
for (auto i = 0; i < rowCount(); ++i) {
|
||||
AudioDevice& device = *_devices[i];
|
||||
|
||||
if (device.selected && device.info != _selectedDevice) {
|
||||
device.selected = false;
|
||||
} else if (device.info == _selectedDevice) {
|
||||
|
@ -139,17 +161,47 @@ void AudioDeviceList::onDevicesChanged(const QList<QAudioDeviceInfo>& devices) {
|
|||
.remove("Device")
|
||||
.replace(" )", ")");
|
||||
device.selected = (device.info == _selectedDevice);
|
||||
_devices.push_back(device);
|
||||
_devices.push_back(newDevice(device));
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
bool AudioInputDeviceList::peakValuesAvailable() {
|
||||
std::call_once(_peakFlag, [&] {
|
||||
_peakValuesAvailable = DependencyManager::get<AudioClient>()->peakValuesAvailable();
|
||||
});
|
||||
return _peakValuesAvailable;
|
||||
}
|
||||
|
||||
void AudioInputDeviceList::setPeakValuesEnabled(bool enable) {
|
||||
if (peakValuesAvailable() && (enable != _peakValuesEnabled)) {
|
||||
DependencyManager::get<AudioClient>()->enablePeakValues(enable);
|
||||
_peakValuesEnabled = enable;
|
||||
emit peakValuesEnabledChanged(_peakValuesEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioInputDeviceList::onPeakValueListChanged(const QList<float>& peakValueList) {
|
||||
assert(_mode == QAudio::AudioInput);
|
||||
|
||||
if (peakValueList.length() != rowCount()) {
|
||||
qWarning() << "AudioDeviceList" << __FUNCTION__ << "length mismatch";
|
||||
}
|
||||
|
||||
for (auto i = 0; i < rowCount(); ++i) {
|
||||
std::static_pointer_cast<AudioInputDevice>(_devices[i])->peak = peakValueList[i];
|
||||
}
|
||||
|
||||
emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0), { PeakRole });
|
||||
}
|
||||
|
||||
AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) {
|
||||
auto client = DependencyManager::get<AudioClient>();
|
||||
|
||||
connect(client.data(), &AudioClient::deviceChanged, this, &AudioDevices::onDeviceChanged, Qt::QueuedConnection);
|
||||
connect(client.data(), &AudioClient::devicesChanged, this, &AudioDevices::onDevicesChanged, Qt::QueuedConnection);
|
||||
connect(client.data(), &AudioClient::peakValueListChanged, &_inputs, &AudioInputDeviceList::onPeakValueListChanged, Qt::QueuedConnection);
|
||||
|
||||
// connections are made after client is initialized, so we must also fetch the devices
|
||||
_inputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioInput));
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#ifndef hifi_scripting_AudioDevices_h
|
||||
#define hifi_scripting_AudioDevices_h
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include <QObject>
|
||||
#include <QAbstractListModel>
|
||||
#include <QAudioDeviceInfo>
|
||||
|
@ -29,7 +32,11 @@ class AudioDeviceList : public QAbstractListModel {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AudioDeviceList(QAudio::Mode mode) : _mode(mode) {}
|
||||
AudioDeviceList(QAudio::Mode mode = QAudio::AudioOutput) : _mode(mode) {}
|
||||
~AudioDeviceList() = default;
|
||||
|
||||
virtual std::shared_ptr<AudioDevice> newDevice(const AudioDevice& device)
|
||||
{ return std::make_shared<AudioDevice>(device); }
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override { Q_UNUSED(parent); return _devices.size(); }
|
||||
QHash<int, QByteArray> roleNames() const override { return _roles; }
|
||||
|
@ -44,25 +51,63 @@ public:
|
|||
signals:
|
||||
void deviceChanged(const QAudioDeviceInfo& device);
|
||||
|
||||
private slots:
|
||||
protected slots:
|
||||
void onDeviceChanged(const QAudioDeviceInfo& device);
|
||||
void onDevicesChanged(const QList<QAudioDeviceInfo>& devices);
|
||||
|
||||
private:
|
||||
protected:
|
||||
friend class AudioDevices;
|
||||
|
||||
static QHash<int, QByteArray> _roles;
|
||||
static Qt::ItemFlags _flags;
|
||||
const QAudio::Mode _mode;
|
||||
QAudioDeviceInfo _selectedDevice;
|
||||
QList<AudioDevice> _devices;
|
||||
QList<std::shared_ptr<AudioDevice>> _devices;
|
||||
};
|
||||
|
||||
class AudioInputDevice : public AudioDevice {
|
||||
public:
|
||||
AudioInputDevice(const AudioDevice& device) : AudioDevice(device) {}
|
||||
float peak { 0.0f };
|
||||
};
|
||||
|
||||
class AudioInputDeviceList : public AudioDeviceList {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool peakValuesAvailable READ peakValuesAvailable)
|
||||
Q_PROPERTY(bool peakValuesEnabled READ peakValuesEnabled WRITE setPeakValuesEnabled NOTIFY peakValuesEnabledChanged)
|
||||
|
||||
public:
|
||||
AudioInputDeviceList() : AudioDeviceList(QAudio::AudioInput) {}
|
||||
virtual ~AudioInputDeviceList() = default;
|
||||
|
||||
virtual std::shared_ptr<AudioDevice> newDevice(const AudioDevice& device) override
|
||||
{ return std::make_shared<AudioInputDevice>(device); }
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
|
||||
signals:
|
||||
void peakValuesEnabledChanged(bool enabled);
|
||||
|
||||
protected slots:
|
||||
void onPeakValueListChanged(const QList<float>& peakValueList);
|
||||
|
||||
protected:
|
||||
friend class AudioDevices;
|
||||
|
||||
bool peakValuesAvailable();
|
||||
std::once_flag _peakFlag;
|
||||
bool _peakValuesAvailable;
|
||||
|
||||
bool peakValuesEnabled() const { return _peakValuesEnabled; }
|
||||
void setPeakValuesEnabled(bool enable);
|
||||
bool _peakValuesEnabled { false };
|
||||
};
|
||||
|
||||
class Audio;
|
||||
|
||||
class AudioDevices : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(AudioDeviceList* input READ getInputList NOTIFY nop)
|
||||
Q_PROPERTY(AudioInputDeviceList* input READ getInputList NOTIFY nop)
|
||||
Q_PROPERTY(AudioDeviceList* output READ getOutputList NOTIFY nop)
|
||||
|
||||
public:
|
||||
|
@ -82,10 +127,10 @@ private slots:
|
|||
private:
|
||||
friend class Audio;
|
||||
|
||||
AudioDeviceList* getInputList() { return &_inputs; }
|
||||
AudioInputDeviceList* getInputList() { return &_inputs; }
|
||||
AudioDeviceList* getOutputList() { return &_outputs; }
|
||||
|
||||
AudioDeviceList _inputs { QAudio::AudioInput };
|
||||
AudioInputDeviceList _inputs;
|
||||
AudioDeviceList _outputs { QAudio::AudioOutput };
|
||||
QAudioDeviceInfo _requestedOutputDevice;
|
||||
QAudioDeviceInfo _requestedInputDevice;
|
||||
|
|
|
@ -33,7 +33,12 @@ void DialogsManagerScriptingInterface::showAddressBar() {
|
|||
|
||||
void DialogsManagerScriptingInterface::hideAddressBar() {
|
||||
QMetaObject::invokeMethod(DependencyManager::get<DialogsManager>().data(),
|
||||
"hideAddressBar", Qt::QueuedConnection);
|
||||
"hideAddressBar", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void DialogsManagerScriptingInterface::showLoginDialog() {
|
||||
QMetaObject::invokeMethod(DependencyManager::get<DialogsManager>().data(),
|
||||
"showLoginDialog", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void DialogsManagerScriptingInterface::showFeed() {
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
public slots:
|
||||
void showAddressBar();
|
||||
void hideAddressBar();
|
||||
void showLoginDialog();
|
||||
|
||||
signals:
|
||||
void addressBarShown(bool visible);
|
||||
|
|
|
@ -169,12 +169,14 @@ void LoginDialog::openUrl(const QString& url) const {
|
|||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
|
||||
if (tablet->getToolbarMode()) {
|
||||
auto browser = offscreenUi->load("Browser.qml");
|
||||
browser->setProperty("url", url);
|
||||
offscreenUi->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) {
|
||||
newObject->setProperty("url", url);
|
||||
});
|
||||
} else {
|
||||
if (!hmd->getShouldShowTablet() && !qApp->isHMDMode()) {
|
||||
auto browser = offscreenUi->load("Browser.qml");
|
||||
browser->setProperty("url", url);
|
||||
offscreenUi->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) {
|
||||
newObject->setProperty("url", url);
|
||||
});
|
||||
} else {
|
||||
tablet->gotoWebScreen(url);
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ Setting::Handle<int> staticJitterBufferFrames("staticJitterBufferFrames",
|
|||
// protect the Qt internal device list
|
||||
using Mutex = std::mutex;
|
||||
using Lock = std::unique_lock<Mutex>;
|
||||
static Mutex _deviceMutex;
|
||||
Mutex _deviceMutex;
|
||||
|
||||
// thread-safe
|
||||
QList<QAudioDeviceInfo> getAvailableDevices(QAudio::Mode mode) {
|
||||
|
@ -227,13 +227,18 @@ AudioClient::AudioClient() :
|
|||
// start a thread to detect any device changes
|
||||
_checkDevicesTimer = new QTimer(this);
|
||||
connect(_checkDevicesTimer, &QTimer::timeout, [this] {
|
||||
QtConcurrent::run(QThreadPool::globalInstance(), [this] {
|
||||
checkDevices();
|
||||
});
|
||||
QtConcurrent::run(QThreadPool::globalInstance(), [this] { checkDevices(); });
|
||||
});
|
||||
const unsigned long DEVICE_CHECK_INTERVAL_MSECS = 2 * 1000;
|
||||
_checkDevicesTimer->start(DEVICE_CHECK_INTERVAL_MSECS);
|
||||
|
||||
// start a thread to detect peak value changes
|
||||
_checkPeakValuesTimer = new QTimer(this);
|
||||
connect(_checkPeakValuesTimer, &QTimer::timeout, [this] {
|
||||
QtConcurrent::run(QThreadPool::globalInstance(), [this] { checkPeakValues(); });
|
||||
});
|
||||
const unsigned long PEAK_VALUES_CHECK_INTERVAL_MSECS = 50;
|
||||
_checkPeakValuesTimer->start(PEAK_VALUES_CHECK_INTERVAL_MSECS);
|
||||
|
||||
configureReverb();
|
||||
|
||||
|
@ -275,6 +280,7 @@ void AudioClient::cleanupBeforeQuit() {
|
|||
|
||||
stop();
|
||||
_checkDevicesTimer->stop();
|
||||
_checkPeakValuesTimer->stop();
|
||||
guard.trigger();
|
||||
}
|
||||
|
||||
|
@ -316,8 +322,6 @@ QString getWinDeviceName(IMMDevice* pEndpoint) {
|
|||
QString deviceName;
|
||||
IPropertyStore* pPropertyStore;
|
||||
pEndpoint->OpenPropertyStore(STGM_READ, &pPropertyStore);
|
||||
pEndpoint->Release();
|
||||
pEndpoint = nullptr;
|
||||
PROPVARIANT pv;
|
||||
PropVariantInit(&pv);
|
||||
HRESULT hr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &pv);
|
||||
|
@ -346,6 +350,8 @@ QString AudioClient::getWinDeviceName(wchar_t* guid) {
|
|||
deviceName = QString("NONE");
|
||||
} else {
|
||||
deviceName = ::getWinDeviceName(pEndpoint);
|
||||
pEndpoint->Release();
|
||||
pEndpoint = nullptr;
|
||||
}
|
||||
pMMDeviceEnumerator->Release();
|
||||
pMMDeviceEnumerator = nullptr;
|
||||
|
@ -429,6 +435,8 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
|
|||
deviceName = QString("NONE");
|
||||
} else {
|
||||
deviceName = getWinDeviceName(pEndpoint);
|
||||
pEndpoint->Release();
|
||||
pEndpoint = nullptr;
|
||||
}
|
||||
pMMDeviceEnumerator->Release();
|
||||
pMMDeviceEnumerator = NULL;
|
||||
|
|
|
@ -148,6 +148,9 @@ public:
|
|||
QAudioDeviceInfo getActiveAudioDevice(QAudio::Mode mode) const;
|
||||
QList<QAudioDeviceInfo> getAudioDevices(QAudio::Mode mode) const;
|
||||
|
||||
void enablePeakValues(bool enable) { _enablePeakValues = enable; }
|
||||
bool peakValuesAvailable() const;
|
||||
|
||||
static const float CALLBACK_ACCELERATOR_RATIO;
|
||||
|
||||
bool getNamedAudioDeviceForModeExists(QAudio::Mode mode, const QString& deviceName);
|
||||
|
@ -224,6 +227,7 @@ signals:
|
|||
|
||||
void deviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device);
|
||||
void devicesChanged(QAudio::Mode mode, const QList<QAudioDeviceInfo>& devices);
|
||||
void peakValueListChanged(const QList<float> peakValueList);
|
||||
|
||||
void receivedFirstPacket();
|
||||
void disconnected();
|
||||
|
@ -242,9 +246,12 @@ private:
|
|||
friend class CheckDevicesThread;
|
||||
friend class LocalInjectorsThread;
|
||||
|
||||
// background tasks
|
||||
void checkDevices();
|
||||
void checkPeakValues();
|
||||
|
||||
void outputFormatChanged();
|
||||
void handleAudioInput(QByteArray& audioBuffer);
|
||||
void checkDevices();
|
||||
void prepareLocalAudioInjectors(std::unique_ptr<Lock> localAudioLock = nullptr);
|
||||
bool mixLocalAudioInjectors(float* mixBuffer);
|
||||
float azimuthForSource(const glm::vec3& relativePosition);
|
||||
|
@ -298,6 +305,7 @@ private:
|
|||
std::atomic<bool> _localInjectorsAvailable { false };
|
||||
MixedProcessedAudioStream _receivedAudioStream;
|
||||
bool _isStereoInput;
|
||||
std::atomic<bool> _enablePeakValues { false };
|
||||
|
||||
quint64 _outputStarveDetectionStartTimeMsec;
|
||||
int _outputStarveDetectionCount;
|
||||
|
@ -396,6 +404,7 @@ private:
|
|||
RateCounter<> _audioInbound;
|
||||
|
||||
QTimer* _checkDevicesTimer { nullptr };
|
||||
QTimer* _checkPeakValuesTimer { nullptr };
|
||||
};
|
||||
|
||||
|
||||
|
|
176
libraries/audio-client/src/AudioPeakValues.cpp
Normal file
176
libraries/audio-client/src/AudioPeakValues.cpp
Normal file
|
@ -0,0 +1,176 @@
|
|||
//
|
||||
// AudioPeakValues.cpp
|
||||
// interface/src
|
||||
//
|
||||
// Created by Zach Pomerantz on 6/26/2017
|
||||
// Copyright 2013 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
|
||||
//
|
||||
|
||||
#include "AudioClient.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmdeviceapi.h>
|
||||
#include <endpointvolume.h>
|
||||
#include <audioclient.h>
|
||||
|
||||
#include <QString>
|
||||
|
||||
#define RETURN_ON_FAIL(result) if (FAILED(result)) { return; }
|
||||
#define CONTINUE_ON_FAIL(result) if (FAILED(result)) { continue; }
|
||||
|
||||
extern QString getWinDeviceName(IMMDevice* pEndpoint);
|
||||
extern std::mutex _deviceMutex;
|
||||
|
||||
std::map<std::wstring, std::shared_ptr<IAudioClient>> activeClients;
|
||||
|
||||
template <class T>
|
||||
void release(T* t) {
|
||||
t->Release();
|
||||
}
|
||||
|
||||
template <>
|
||||
void release(IAudioClient* audioClient) {
|
||||
audioClient->Stop();
|
||||
audioClient->Release();
|
||||
}
|
||||
|
||||
void AudioClient::checkPeakValues() {
|
||||
// prepare the windows environment
|
||||
CoInitialize(NULL);
|
||||
|
||||
// if disabled, clean up active clients
|
||||
if (!_enablePeakValues) {
|
||||
activeClients.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// lock the devices so the _inputDevices list is static
|
||||
std::unique_lock<std::mutex> lock(_deviceMutex);
|
||||
HRESULT result;
|
||||
|
||||
// initialize the payload
|
||||
QList<float> peakValueList;
|
||||
for (int i = 0; i < _inputDevices.size(); ++i) {
|
||||
peakValueList.push_back(0.0f);
|
||||
}
|
||||
|
||||
std::shared_ptr<IMMDeviceEnumerator> enumerator;
|
||||
{
|
||||
IMMDeviceEnumerator* pEnumerator;
|
||||
result = CoCreateInstance(
|
||||
__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);
|
||||
RETURN_ON_FAIL(result);
|
||||
enumerator = std::shared_ptr<IMMDeviceEnumerator>(pEnumerator, &release<IMMDeviceEnumerator>);
|
||||
}
|
||||
|
||||
std::shared_ptr<IMMDeviceCollection> endpoints;
|
||||
{
|
||||
IMMDeviceCollection* pEndpoints;
|
||||
result = enumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, &pEndpoints);
|
||||
RETURN_ON_FAIL(result);
|
||||
endpoints = std::shared_ptr<IMMDeviceCollection>(pEndpoints, &release<IMMDeviceCollection>);
|
||||
}
|
||||
|
||||
UINT count;
|
||||
{
|
||||
result = endpoints->GetCount(&count);
|
||||
RETURN_ON_FAIL(result);
|
||||
}
|
||||
|
||||
IMMDevice* pDevice;
|
||||
std::shared_ptr<IMMDevice> device;
|
||||
IAudioMeterInformation* pMeterInfo;
|
||||
std::shared_ptr<IAudioMeterInformation> meterInfo;
|
||||
IAudioClient* pAudioClient;
|
||||
std::shared_ptr<IAudioClient> audioClient;
|
||||
DWORD hardwareSupport;
|
||||
LPWSTR pDeviceId = NULL;
|
||||
LPWAVEFORMATEX format;
|
||||
float peakValue;
|
||||
QString deviceName;
|
||||
int deviceIndex;
|
||||
for (UINT i = 0; i < count; ++i) {
|
||||
result = endpoints->Item(i, &pDevice);
|
||||
CONTINUE_ON_FAIL(result);
|
||||
device = std::shared_ptr<IMMDevice>(pDevice, &release<IMMDevice>);
|
||||
|
||||
// if the device isn't listed through Qt, skip it
|
||||
deviceName = ::getWinDeviceName(pDevice);
|
||||
deviceIndex = 0;
|
||||
for (; deviceIndex < _inputDevices.size(); ++deviceIndex) {
|
||||
if (deviceName == _inputDevices[deviceIndex].deviceName()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (deviceIndex >= _inputDevices.size()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//continue;
|
||||
|
||||
result = device->Activate(__uuidof(IAudioMeterInformation), CLSCTX_ALL, NULL, (void**)&pMeterInfo);
|
||||
CONTINUE_ON_FAIL(result);
|
||||
meterInfo = std::shared_ptr<IAudioMeterInformation>(pMeterInfo, &release<IAudioMeterInformation>);
|
||||
|
||||
//continue;
|
||||
|
||||
hardwareSupport;
|
||||
result = meterInfo->QueryHardwareSupport(&hardwareSupport);
|
||||
CONTINUE_ON_FAIL(result);
|
||||
|
||||
//continue;
|
||||
|
||||
// if the device has no hardware support (USB)...
|
||||
if (!(hardwareSupport & ENDPOINT_HARDWARE_SUPPORT_METER)) {
|
||||
result = device->GetId(&pDeviceId);
|
||||
CONTINUE_ON_FAIL(result);
|
||||
std::wstring deviceId(pDeviceId);
|
||||
CoTaskMemFree(pDeviceId);
|
||||
|
||||
//continue;
|
||||
|
||||
// ...and no active client...
|
||||
if (activeClients.find(deviceId) == activeClients.end()) {
|
||||
result = device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&pAudioClient);
|
||||
CONTINUE_ON_FAIL(result);
|
||||
audioClient = std::shared_ptr<IAudioClient>(pAudioClient, &release<IAudioClient>);
|
||||
|
||||
//continue;
|
||||
|
||||
// ...activate a client
|
||||
audioClient->GetMixFormat(&format);
|
||||
audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, 0, 0, format, NULL);
|
||||
audioClient->Start();
|
||||
|
||||
//continue;
|
||||
|
||||
activeClients[deviceId] = audioClient;
|
||||
}
|
||||
}
|
||||
|
||||
// get the peak value and put it in the payload
|
||||
meterInfo->GetPeakValue(&peakValue);
|
||||
peakValueList[deviceIndex] = peakValue;
|
||||
}
|
||||
|
||||
emit peakValueListChanged(peakValueList);
|
||||
}
|
||||
|
||||
bool AudioClient::peakValuesAvailable() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
void AudioClient::checkPeakValues() {
|
||||
}
|
||||
|
||||
bool AudioClient::peakValuesAvailable() const {
|
||||
return false;
|
||||
}
|
||||
#endif
|
|
@ -431,7 +431,7 @@ int Octree::readElementData(const OctreeElementPointer& destinationElement, cons
|
|||
return bytesRead;
|
||||
}
|
||||
|
||||
void Octree::readBitstreamToTree(const unsigned char * bitstream, unsigned long int bufferSizeBytes,
|
||||
void Octree::readBitstreamToTree(const unsigned char * bitstream, uint64_t bufferSizeBytes,
|
||||
ReadBitstreamToTreeParams& args) {
|
||||
int bytesRead = 0;
|
||||
const unsigned char* bitstreamAt = bitstream;
|
||||
|
@ -925,8 +925,8 @@ int Octree::encodeTreeBitstream(const OctreeElementPointer& element,
|
|||
roomForOctalCode = packetData->startSubTree(newCode);
|
||||
|
||||
if (newCode) {
|
||||
delete[] newCode;
|
||||
codeLength = numberOfThreeBitSectionsInCode(newCode);
|
||||
delete[] newCode;
|
||||
} else {
|
||||
codeLength = 1;
|
||||
}
|
||||
|
@ -1152,7 +1152,6 @@ int Octree::encodeTreeBitstreamRecursion(const OctreeElementPointer& element,
|
|||
OctreeElementPointer sortedChildren[NUMBER_OF_CHILDREN] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
||||
float distancesToChildren[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
int indexOfChildren[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
int currentCount = 0;
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
OctreeElementPointer childElement = element->getChildAtIndex(i);
|
||||
|
@ -1174,7 +1173,6 @@ int Octree::encodeTreeBitstreamRecursion(const OctreeElementPointer& element,
|
|||
sortedChildren[i] = childElement;
|
||||
indexOfChildren[i] = i;
|
||||
distancesToChildren[i] = 0.0f;
|
||||
currentCount++;
|
||||
|
||||
// track stats
|
||||
// must check childElement here, because it could be we got here with no childElement
|
||||
|
@ -1185,7 +1183,7 @@ int Octree::encodeTreeBitstreamRecursion(const OctreeElementPointer& element,
|
|||
|
||||
// for each child element in Distance sorted order..., check to see if they exist, are colored, and in view, and if so
|
||||
// add them to our distance ordered array of children
|
||||
for (int i = 0; i < currentCount; i++) {
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
OctreeElementPointer childElement = sortedChildren[i];
|
||||
int originalIndex = indexOfChildren[i];
|
||||
|
||||
|
@ -1276,7 +1274,7 @@ int Octree::encodeTreeBitstreamRecursion(const OctreeElementPointer& element,
|
|||
}
|
||||
|
||||
// NOTE: the childrenDataBits indicates that there is an array of child element data included in this packet.
|
||||
// We wil write this bit mask but we may come back later and update the bits that are actually included
|
||||
// We will write this bit mask but we may come back later and update the bits that are actually included
|
||||
packetData->releaseReservedBytes(sizeof(childrenDataBits));
|
||||
continueThisLevel = packetData->appendBitMask(childrenDataBits);
|
||||
|
||||
|
@ -1441,7 +1439,7 @@ int Octree::encodeTreeBitstreamRecursion(const OctreeElementPointer& element,
|
|||
|
||||
// for each child element in Distance sorted order..., check to see if they exist, are colored, and in view, and if so
|
||||
// add them to our distance ordered array of children
|
||||
for (int indexByDistance = 0; indexByDistance < currentCount; indexByDistance++) {
|
||||
for (int indexByDistance = 0; indexByDistance < NUMBER_OF_CHILDREN; indexByDistance++) {
|
||||
OctreeElementPointer childElement = sortedChildren[indexByDistance];
|
||||
int originalIndex = indexOfChildren[indexByDistance];
|
||||
|
||||
|
@ -1638,7 +1636,7 @@ bool Octree::readFromFile(const char* fileName) {
|
|||
|
||||
QDataStream fileInputStream(&file);
|
||||
QFileInfo fileInfo(qFileName);
|
||||
unsigned long fileLength = fileInfo.size();
|
||||
uint64_t fileLength = fileInfo.size();
|
||||
|
||||
emit importSize(1.0f, 1.0f, 1.0f);
|
||||
emit importProgress(0);
|
||||
|
@ -1715,7 +1713,7 @@ bool Octree::readFromURL(const QString& urlString) {
|
|||
}
|
||||
|
||||
|
||||
bool Octree::readFromStream(unsigned long streamLength, QDataStream& inputStream, const QString& marketplaceID) {
|
||||
bool Octree::readFromStream(uint64_t streamLength, QDataStream& inputStream, const QString& marketplaceID) {
|
||||
// decide if this is binary SVO or JSON-formatted SVO
|
||||
QIODevice *device = inputStream.device();
|
||||
char firstChar;
|
||||
|
@ -1732,14 +1730,14 @@ bool Octree::readFromStream(unsigned long streamLength, QDataStream& inputStream
|
|||
}
|
||||
|
||||
|
||||
bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStream) {
|
||||
bool Octree::readSVOFromStream(uint64_t streamLength, QDataStream& inputStream) {
|
||||
qWarning() << "SVO file format depricated. Support for reading SVO files is no longer support and will be removed soon.";
|
||||
|
||||
bool fileOk = false;
|
||||
|
||||
PacketVersion gotVersion = 0;
|
||||
|
||||
unsigned long headerLength = 0; // bytes in the header
|
||||
uint64_t headerLength = 0; // bytes in the header
|
||||
|
||||
bool wantImportProgress = true;
|
||||
|
||||
|
@ -1751,14 +1749,14 @@ bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStr
|
|||
if (getWantSVOfileVersions()) {
|
||||
|
||||
// read just enough of the file to parse the header...
|
||||
const unsigned long HEADER_LENGTH = sizeof(int) + sizeof(PacketVersion);
|
||||
const uint64_t HEADER_LENGTH = sizeof(int) + sizeof(PacketVersion);
|
||||
unsigned char fileHeader[HEADER_LENGTH];
|
||||
inputStream.readRawData((char*)&fileHeader, HEADER_LENGTH);
|
||||
|
||||
headerLength = HEADER_LENGTH; // we need this later to skip to the data
|
||||
|
||||
unsigned char* dataAt = (unsigned char*)&fileHeader;
|
||||
unsigned long dataLength = HEADER_LENGTH;
|
||||
uint64_t dataLength = HEADER_LENGTH;
|
||||
|
||||
// if so, read the first byte of the file and see if it matches the expected version code
|
||||
int intPacketType;
|
||||
|
@ -1804,7 +1802,7 @@ bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStr
|
|||
if (!hasBufferBreaks) {
|
||||
|
||||
// read the entire file into a buffer, WHAT!? Why not.
|
||||
unsigned long dataLength = streamLength - headerLength;
|
||||
uint64_t dataLength = streamLength - headerLength;
|
||||
unsigned char* entireFileDataSection = new unsigned char[dataLength];
|
||||
inputStream.readRawData((char*)entireFileDataSection, dataLength);
|
||||
|
||||
|
@ -1819,9 +1817,9 @@ bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStr
|
|||
} else {
|
||||
|
||||
|
||||
unsigned long dataLength = streamLength - headerLength;
|
||||
unsigned long remainingLength = dataLength;
|
||||
const unsigned long MAX_CHUNK_LENGTH = MAX_OCTREE_PACKET_SIZE * 2;
|
||||
uint64_t dataLength = streamLength - headerLength;
|
||||
uint64_t remainingLength = dataLength;
|
||||
const uint64_t MAX_CHUNK_LENGTH = MAX_OCTREE_PACKET_SIZE * 2;
|
||||
unsigned char* fileChunk = new unsigned char[MAX_CHUNK_LENGTH];
|
||||
|
||||
while (remainingLength > 0) {
|
||||
|
@ -1847,7 +1845,7 @@ bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStr
|
|||
remainingLength -= chunkLength;
|
||||
|
||||
unsigned char* dataAt = fileChunk;
|
||||
unsigned long dataLength = chunkLength;
|
||||
uint64_t dataLength = chunkLength;
|
||||
|
||||
ReadBitstreamToTreeParams args(NO_EXISTS_BITS, NULL, 0,
|
||||
SharedNodePointer(), wantImportProgress, gotVersion);
|
||||
|
@ -1887,7 +1885,7 @@ QJsonDocument addMarketplaceIDToDocumentEntities(QJsonDocument& doc, const QStri
|
|||
|
||||
const int READ_JSON_BUFFER_SIZE = 2048;
|
||||
|
||||
bool Octree::readJSONFromStream(unsigned long streamLength, QDataStream& inputStream, const QString& marketplaceID /*=""*/) {
|
||||
bool Octree::readJSONFromStream(uint64_t streamLength, QDataStream& inputStream, const QString& marketplaceID /*=""*/) {
|
||||
// if the data is gzipped we may not have a useful bytesAvailable() result, so just keep reading until
|
||||
// we get an eof. Leave streamLength parameter for consistency.
|
||||
|
||||
|
@ -1982,14 +1980,14 @@ bool Octree::writeToJSONFile(const char* fileName, const OctreeElementPointer& e
|
|||
return success;
|
||||
}
|
||||
|
||||
unsigned long Octree::getOctreeElementsCount() {
|
||||
unsigned long nodeCount = 0;
|
||||
uint64_t Octree::getOctreeElementsCount() {
|
||||
uint64_t nodeCount = 0;
|
||||
recurseTreeWithOperation(countOctreeElementsOperation, &nodeCount);
|
||||
return nodeCount;
|
||||
}
|
||||
|
||||
bool Octree::countOctreeElementsOperation(const OctreeElementPointer& element, void* extraData) {
|
||||
(*(unsigned long*)extraData)++;
|
||||
(*(uint64_t*)extraData)++;
|
||||
return true; // keep going
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
|
@ -231,7 +232,7 @@ public:
|
|||
|
||||
virtual void eraseAllOctreeElements(bool createNewRoot = true);
|
||||
|
||||
void readBitstreamToTree(const unsigned char* bitstream, unsigned long int bufferSizeBytes, ReadBitstreamToTreeParams& args);
|
||||
void readBitstreamToTree(const unsigned char* bitstream, uint64_t bufferSizeBytes, ReadBitstreamToTreeParams& args);
|
||||
void deleteOctalCodeFromTree(const unsigned char* codeBuffer, bool collapseEmptyTrees = DONT_COLLAPSE);
|
||||
void reaverageOctreeElements(OctreeElementPointer startElement = OctreeElementPointer());
|
||||
|
||||
|
@ -301,13 +302,13 @@ public:
|
|||
// Octree importers
|
||||
bool readFromFile(const char* filename);
|
||||
bool readFromURL(const QString& url); // will support file urls as well...
|
||||
bool readFromStream(unsigned long streamLength, QDataStream& inputStream, const QString& marketplaceID="");
|
||||
bool readSVOFromStream(unsigned long streamLength, QDataStream& inputStream);
|
||||
bool readJSONFromStream(unsigned long streamLength, QDataStream& inputStream, const QString& marketplaceID="");
|
||||
bool readFromStream(uint64_t streamLength, QDataStream& inputStream, const QString& marketplaceID="");
|
||||
bool readSVOFromStream(uint64_t streamLength, QDataStream& inputStream);
|
||||
bool readJSONFromStream(uint64_t streamLength, QDataStream& inputStream, const QString& marketplaceID="");
|
||||
bool readJSONFromGzippedFile(QString qFileName);
|
||||
virtual bool readFromMap(QVariantMap& entityDescription) = 0;
|
||||
|
||||
unsigned long getOctreeElementsCount();
|
||||
uint64_t getOctreeElementsCount();
|
||||
|
||||
bool getShouldReaverage() const { return _shouldReaverage; }
|
||||
|
||||
|
|
|
@ -24,13 +24,6 @@ namespace Cursor {
|
|||
return _icon;
|
||||
}
|
||||
|
||||
|
||||
class MouseInstance : public Instance {
|
||||
Source getType() const override {
|
||||
return Source::MOUSE;
|
||||
}
|
||||
};
|
||||
|
||||
QMap<uint16_t, QString> Manager::ICON_NAMES {
|
||||
{ Icon::SYSTEM, "SYSTEM", },
|
||||
{ Icon::DEFAULT, "DEFAULT", },
|
||||
|
@ -38,7 +31,7 @@ namespace Cursor {
|
|||
{ Icon::ARROW, "ARROW", },
|
||||
{ Icon::RETICLE, "RETICLE", },
|
||||
};
|
||||
QMap<uint16_t, QString> Manager::ICONS;
|
||||
|
||||
static uint16_t _customIconId = Icon::USER_BASE;
|
||||
|
||||
Manager::Manager() {
|
||||
|
@ -62,8 +55,8 @@ namespace Cursor {
|
|||
}
|
||||
|
||||
Manager& Manager::instance() {
|
||||
static Manager instance;
|
||||
return instance;
|
||||
static QSharedPointer<Manager> instance = DependencyManager::get<Cursor::Manager>();
|
||||
return *instance;
|
||||
}
|
||||
|
||||
QList<uint16_t> Manager::registeredIcons() const {
|
||||
|
@ -76,7 +69,6 @@ namespace Cursor {
|
|||
|
||||
Instance* Manager::getCursor(uint8_t index) {
|
||||
Q_ASSERT(index < getCount());
|
||||
static MouseInstance mouseInstance;
|
||||
if (index == 0) {
|
||||
return &mouseInstance;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <DependencyManager.h>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
|
@ -39,7 +40,15 @@ namespace Cursor {
|
|||
uint16_t _icon;
|
||||
};
|
||||
|
||||
class Manager {
|
||||
class MouseInstance : public Instance {
|
||||
Source getType() const override {
|
||||
return Source::MOUSE;
|
||||
}
|
||||
};
|
||||
|
||||
class Manager : public QObject, public Dependency {
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
Manager();
|
||||
Manager(const Manager& other) = delete;
|
||||
public:
|
||||
|
@ -52,12 +61,13 @@ namespace Cursor {
|
|||
QList<uint16_t> registeredIcons() const;
|
||||
const QString& getIconImage(uint16_t icon);
|
||||
|
||||
static QMap<uint16_t, QString> ICONS;
|
||||
static QMap<uint16_t, QString> ICON_NAMES;
|
||||
static Icon lookupIcon(const QString& name);
|
||||
static const QString& getIconName(const Icon& icon);
|
||||
private:
|
||||
MouseInstance mouseInstance;
|
||||
float _scale{ 1.0f };
|
||||
QMap<uint16_t, QString> ICONS;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -554,20 +554,19 @@ void OffscreenUi::createDesktop(const QUrl& url) {
|
|||
getSurfaceContext()->setContextProperty("DebugQML", QVariant(false));
|
||||
#endif
|
||||
|
||||
_desktop = dynamic_cast<QQuickItem*>(load(url));
|
||||
Q_ASSERT(_desktop);
|
||||
getSurfaceContext()->setContextProperty("desktop", _desktop);
|
||||
load(url, [=](QQmlContext* context, QObject* newObject) {
|
||||
_desktop = static_cast<QQuickItem*>(newObject);
|
||||
getSurfaceContext()->setContextProperty("desktop", _desktop);
|
||||
_toolWindow = _desktop->findChild<QQuickItem*>("ToolWindow");
|
||||
|
||||
_toolWindow = _desktop->findChild<QQuickItem*>("ToolWindow");
|
||||
_vrMenu = new VrMenu(this);
|
||||
for (const auto& menuInitializer : _queuedMenuInitializers) {
|
||||
menuInitializer(_vrMenu);
|
||||
}
|
||||
|
||||
_vrMenu = new VrMenu(this);
|
||||
for (const auto& menuInitializer : _queuedMenuInitializers) {
|
||||
menuInitializer(_vrMenu);
|
||||
}
|
||||
|
||||
new KeyboardFocusHack();
|
||||
|
||||
connect(_desktop, SIGNAL(showDesktop()), this, SIGNAL(showDesktop()));
|
||||
new KeyboardFocusHack();
|
||||
connect(_desktop, SIGNAL(showDesktop()), this, SIGNAL(showDesktop()));
|
||||
});
|
||||
}
|
||||
|
||||
QQuickItem* OffscreenUi::getDesktop() {
|
||||
|
|
|
@ -639,7 +639,7 @@ void OffscreenQmlSurface::setBaseUrl(const QUrl& baseUrl) {
|
|||
_qmlContext->setBaseUrl(baseUrl);
|
||||
}
|
||||
|
||||
QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
qCWarning(uiLogging) << "Called load on a non-surface thread";
|
||||
}
|
||||
|
@ -662,32 +662,32 @@ QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext,
|
|||
[this, qmlComponent, targetContext, f](QQmlComponent::Status) {
|
||||
finishQmlLoad(qmlComponent, targetContext, f);
|
||||
});
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
return finishQmlLoad(qmlComponent, targetContext, f);
|
||||
finishQmlLoad(qmlComponent, targetContext, f);
|
||||
}
|
||||
|
||||
QObject* OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
return load(qmlSource, true, f);
|
||||
void OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
load(qmlSource, true, f);
|
||||
}
|
||||
|
||||
QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
return load(qmlSource, false, f);
|
||||
void OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
load(qmlSource, false, f);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::clearCache() {
|
||||
_qmlContext->engine()->clearComponentCache();
|
||||
}
|
||||
|
||||
QObject* OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
disconnect(qmlComponent, &QQmlComponent::statusChanged, this, 0);
|
||||
if (qmlComponent->isError()) {
|
||||
for (const auto& error : qmlComponent->errors()) {
|
||||
qCWarning(uiLogging) << error.url() << error.line() << error;
|
||||
}
|
||||
qmlComponent->deleteLater();
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -700,7 +700,7 @@ QObject* OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlCon
|
|||
qFatal("Unable to finish loading QML root");
|
||||
}
|
||||
qmlComponent->deleteLater();
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
qmlContext->engine()->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
||||
|
@ -726,19 +726,19 @@ QObject* OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlCon
|
|||
}
|
||||
|
||||
// If we already have a root, just set a couple of flags and the ancestry
|
||||
if (_rootItem) {
|
||||
if (newItem && _rootItem) {
|
||||
// Allow child windows to be destroyed from JS
|
||||
QQmlEngine::setObjectOwnership(newObject, QQmlEngine::JavaScriptOwnership);
|
||||
newObject->setParent(_rootItem);
|
||||
if (newItem) {
|
||||
newItem->setParentItem(_rootItem);
|
||||
}
|
||||
return newObject;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!newItem) {
|
||||
qFatal("Could not load object as root item");
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant)));
|
||||
|
@ -747,7 +747,6 @@ QObject* OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlCon
|
|||
_rootItem = newItem;
|
||||
_rootItem->setParentItem(_quickWindow->contentItem());
|
||||
_rootItem->setSize(_quickWindow->renderTargetSize());
|
||||
return _rootItem;
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::updateQuick() {
|
||||
|
|
|
@ -50,10 +50,10 @@ public:
|
|||
void resize(const QSize& size, bool forceResize = false);
|
||||
QSize size() const;
|
||||
|
||||
Q_INVOKABLE QObject* load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE QObject* loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE QObject* load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE QObject* load(const QString& qmlSourceFile, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}) {
|
||||
Q_INVOKABLE void load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
Q_INVOKABLE void load(const QString& qmlSourceFile, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}) {
|
||||
return load(QUrl(qmlSourceFile), f);
|
||||
}
|
||||
void clearCache();
|
||||
|
@ -120,7 +120,7 @@ protected:
|
|||
private:
|
||||
static QOpenGLContext* getSharedContext();
|
||||
|
||||
QObject* finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> f);
|
||||
void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> f);
|
||||
QPointF mapWindowToUi(const QPointF& sourcePosition, QObject* sourceObject);
|
||||
void setupFbo();
|
||||
bool allowNewFrame(uint8_t fps);
|
||||
|
|
Binary file not shown.
|
@ -8,7 +8,7 @@
|
|||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
|
@ -28,6 +28,7 @@ Rectangle {
|
|||
Column {
|
||||
id: antialiasing
|
||||
spacing: 20
|
||||
padding: 10
|
||||
|
||||
Column{
|
||||
spacing: 10
|
||||
|
@ -125,16 +126,17 @@ Rectangle {
|
|||
checked: Render.getConfig("RenderMainView.Antialiasing")["clipExactColor"]
|
||||
onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["clipExactColor"] = checked }
|
||||
}
|
||||
HifiControls.ConfigSlider {
|
||||
label: qsTr("Covariance gamma")
|
||||
integral: false
|
||||
config: Render.getConfig("RenderMainView.Antialiasing")
|
||||
property: "covarianceGamma"
|
||||
max: 1.5
|
||||
min: 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HifiControls.ConfigSlider {
|
||||
label: qsTr("Covariance gamma")
|
||||
integral: false
|
||||
config: Render.getConfig("RenderMainView.Antialiasing")
|
||||
property: "covarianceGamma"
|
||||
max: 1.5
|
||||
min: 0.5
|
||||
}
|
||||
Separator {}
|
||||
HifiControls.CheckBox {
|
||||
boxSize: 20
|
||||
text: "Feedback history color"
|
||||
|
@ -152,6 +154,7 @@ Rectangle {
|
|||
}
|
||||
|
||||
}
|
||||
Separator {}
|
||||
Row {
|
||||
|
||||
spacing: 10
|
||||
|
@ -176,23 +179,12 @@ Rectangle {
|
|||
max: 1.0
|
||||
min: 0.0
|
||||
}
|
||||
HifiControls.ConfigSlider {
|
||||
label: qsTr("FXAA Region >")
|
||||
integral: false
|
||||
config: Render.getConfig("RenderMainView.Antialiasing")
|
||||
property: "debugFXAAX"
|
||||
max: 1.0
|
||||
min: 0.0
|
||||
}
|
||||
Row {
|
||||
|
||||
HifiControls.CheckBox {
|
||||
boxSize: 20
|
||||
text: "Closest Fragment"
|
||||
checked: Render.getConfig("RenderMainView.Antialiasing")["showClosestFragment"]
|
||||
onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["showClosestFragment"] = checked }
|
||||
}
|
||||
}
|
||||
HifiControls.CheckBox {
|
||||
boxSize: 20
|
||||
text: "Closest Fragment"
|
||||
checked: Render.getConfig("RenderMainView.Antialiasing")["showClosestFragment"]
|
||||
onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["showClosestFragment"] = checked }
|
||||
}
|
||||
HifiControls.ConfigSlider {
|
||||
label: qsTr("Debug Velocity Threshold [pix]")
|
||||
integral: false
|
||||
|
|
|
@ -71,6 +71,10 @@
|
|||
case 'maybeEnableHmdPreview':
|
||||
Menu.setIsOptionChecked("Disable Preview", isHmdPreviewDisabled);
|
||||
break;
|
||||
case 'passphraseReset':
|
||||
onButtonClicked();
|
||||
onButtonClicked();
|
||||
break;
|
||||
case 'walletReset':
|
||||
onButtonClicked();
|
||||
onButtonClicked();
|
||||
|
|
|
@ -539,7 +539,7 @@ clickMapping.from(Controller.Standard.Start).peek().to(function (clicked) {
|
|||
if (clicked) {
|
||||
activeHudPoint2dGamePad();
|
||||
var noHands = -1;
|
||||
Messages.sendLocalMessage("toggleHand", noHands);
|
||||
Messages.sendLocalMessage("toggleHand", Controller.Standard.LeftHand);
|
||||
}
|
||||
|
||||
wantsMenu = clicked;
|
||||
|
|
|
@ -68,6 +68,9 @@ function onHmdChanged(isHmd) {
|
|||
function onClicked() {
|
||||
var isDesktop = Menu.isOptionChecked(desktopMenuItemName);
|
||||
Menu.setIsOptionChecked(isDesktop ? headset : desktopMenuItemName, true);
|
||||
if (!isDesktop) {
|
||||
UserActivityLogger.logAction("exit_vr");
|
||||
}
|
||||
}
|
||||
|
||||
if (headset) {
|
||||
|
|
|
@ -134,7 +134,7 @@
|
|||
if (parseInt(cost) > 0) {
|
||||
var priceElement = $(this).find('.price')
|
||||
priceElement.css({ "width": "auto", "padding": "3px 5px", "height": "26px" });
|
||||
priceElement.text(parseFloat(cost / 100).toFixed(2) + ' HFC');
|
||||
priceElement.text(cost + ' HFC');
|
||||
priceElement.css({ "min-width": priceElement.width() + 10 });
|
||||
}
|
||||
});
|
||||
|
|
168
unpublishedScripts/marketplace/dodgeBall/dodgeBall.js
Normal file
168
unpublishedScripts/marketplace/dodgeBall/dodgeBall.js
Normal file
|
@ -0,0 +1,168 @@
|
|||
(function () {
|
||||
|
||||
var FORCE_DROP_CHANNEL = "Hifi-Hand-Drop";
|
||||
|
||||
var proxInterval,
|
||||
proxTimeout;
|
||||
|
||||
var _entityID;
|
||||
this.preload = function (entityID) {
|
||||
_entityID = entityID;
|
||||
|
||||
Entities.editEntity(_entityID, {
|
||||
userData: '{"grabbableKey": {"grabbable": true}'
|
||||
});
|
||||
};
|
||||
|
||||
var particleTrailEntity = null;
|
||||
|
||||
function particleTrail() {
|
||||
|
||||
var props = {
|
||||
type: 'ParticleEffect',
|
||||
name: 'Particle',
|
||||
parentID: _entityID,
|
||||
isEmitting: true,
|
||||
lifespan: 2.0,
|
||||
maxParticles: 100,
|
||||
textures: 'https://content.highfidelity.com/DomainContent/production/Particles/wispy-smoke.png',
|
||||
emitRate: 50,
|
||||
emitSpeed: 0,
|
||||
emitterShouldTrail: true,
|
||||
particleRadius: 0,
|
||||
radiusSpread: 0,
|
||||
radiusStart: .2,
|
||||
radiusFinish: 0.1,
|
||||
color: {
|
||||
red: 201,
|
||||
blue: 201,
|
||||
green: 34
|
||||
},
|
||||
accelerationSpread: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
alpha: 0,
|
||||
alphaSpread: 0,
|
||||
alphaStart: 1,
|
||||
alphaFinish: 0,
|
||||
polarStart: 0,
|
||||
polarFinish: 0,
|
||||
azimuthStart: -180,
|
||||
azimuthFinish: 180
|
||||
};
|
||||
|
||||
particleTrailEntity = Entities.addEntity(props);
|
||||
}
|
||||
|
||||
function particleExplode() {
|
||||
var entPos = Entities.getEntityProperties(_entityID, 'position').position;
|
||||
var props = {
|
||||
type: 'ParticleEffect',
|
||||
name: 'Particle',
|
||||
parentID: _entityID,
|
||||
isEmitting: true,
|
||||
lifespan: 2,
|
||||
maxParticles: 10,
|
||||
position: entPos,
|
||||
textures: 'https://content.highfidelity.com/DomainContent/production/Particles/wispy-smoke.png',
|
||||
emitRate: 1,
|
||||
emitSpeed: 0,
|
||||
emitterShouldTrail: false,
|
||||
particleRadius: 1,
|
||||
radiusSpread: 0,
|
||||
radiusStart: 0,
|
||||
radiusFinish: 1,
|
||||
color: {
|
||||
red: 232,
|
||||
blue: 232,
|
||||
green: 26
|
||||
},
|
||||
emitAcceleration: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
alpha: 0,
|
||||
alphaSpread: 0,
|
||||
alphaStart: 1,
|
||||
alphaFinish: .5,
|
||||
polarStart: 0,
|
||||
polarFinish: 0,
|
||||
azimuthStart: -180,
|
||||
azimuthFinish: 180
|
||||
};
|
||||
var explosionParticles = Entities.addEntity(props);
|
||||
Entities.editEntity(_entityID, {
|
||||
velocity: Vec3.ZERO,
|
||||
dynamic: false
|
||||
});
|
||||
Script.setTimeout(function () {
|
||||
Entities.deleteEntity(explosionParticles);
|
||||
Entities.editEntity(_entityID, {
|
||||
dynamic: true
|
||||
})
|
||||
}, 500);
|
||||
}
|
||||
|
||||
|
||||
function clearProxCheck() {
|
||||
if (proxInterval) {
|
||||
Script.clearInterval(proxInterval);
|
||||
Entities.deleteEntity(particleTrailEntity);
|
||||
particleTrailEntity = null;
|
||||
}
|
||||
|
||||
if (proxTimeout) {
|
||||
Script.clearTimeout(proxTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
function proxCheck() {
|
||||
var ballPos = Entities.getEntityProperties(_entityID, ['position']).position;
|
||||
var isAnyAvatarInRange = AvatarList.isAvatarInRange(ballPos, 1);
|
||||
|
||||
if (isAnyAvatarInRange) {
|
||||
clearProxCheck();
|
||||
particleExplode();
|
||||
}
|
||||
}
|
||||
|
||||
this.startDistanceGrab = function (thisEntityID, triggerHandAndAvatarUUIDArray) {
|
||||
clearProxCheck();
|
||||
var triggerHand = triggerHandAndAvatarUUIDArray[0];
|
||||
var avatarUUID = triggerHandAndAvatarUUIDArray[1];
|
||||
|
||||
var ballPos = Entities.getEntityProperties(_entityID, ['position']).position;
|
||||
var MAX_DISTANCE_GRAB = 2; //meter
|
||||
|
||||
if (Vec3.distance(ballPos, AvatarList.getAvatar(avatarUUID).position) > MAX_DISTANCE_GRAB) {
|
||||
Messages.sendMessage(FORCE_DROP_CHANNEL, triggerHand, true);
|
||||
}
|
||||
|
||||
};
|
||||
this.startNearGrab = function (thisEntityID, triggerHandAndAvatarUUIDArray) {
|
||||
clearProxCheck();
|
||||
};
|
||||
|
||||
this.releaseGrab = function (thisEntityID) {
|
||||
|
||||
if (particleTrailEntity === null) {
|
||||
particleTrail();
|
||||
}
|
||||
|
||||
Script.setTimeout(function () {
|
||||
proxInterval = Script.setInterval(proxCheck, 50);
|
||||
}, 200); // Setting a delay to give it time to leave initial avatar without proc.
|
||||
|
||||
proxTimeout = Script.setTimeout(function () {
|
||||
clearProxCheck();
|
||||
}, 10000)
|
||||
};
|
||||
|
||||
this.collisionWithEntity = function (thisEntityID, collisionEntityID, collisionInfo) {
|
||||
clearProxCheck();
|
||||
};
|
||||
|
||||
});
|
Loading…
Reference in a new issue