Merge pull request #8655 from highfidelity/RC-21
Beta Release 21 - Includes up to Developer Release 5396
12
BUILD.md
|
@ -1,7 +1,7 @@
|
|||
###Dependencies
|
||||
|
||||
* [cmake](http://www.cmake.org/cmake/resources/software.html) ~> 3.3.2
|
||||
* [Qt](http://www.qt.io/download-open-source) ~> 5.5.1
|
||||
* [Qt](http://www.qt.io/download-open-source) ~> 5.6.1
|
||||
* [OpenSSL](https://www.openssl.org/community/binaries.html) ~> 1.0.1m
|
||||
* IMPORTANT: Using the recommended version of OpenSSL is critical to avoid security vulnerabilities.
|
||||
* [VHACD](https://github.com/virneo/v-hacd)(clone this repository)(Optional)
|
||||
|
@ -41,14 +41,14 @@ If you would like to use a specific install of a dependency instead of the versi
|
|||
Hifi uses CMake to generate build files and project files for your platform.
|
||||
|
||||
####Qt
|
||||
In order for CMake to find the Qt5 find modules, you will need to set an ENV variable pointing to your Qt installation.
|
||||
In order for CMake to find the Qt5 find modules, you will need to set a QT_CMAKE_PREFIX_PATH environment variable pointing to your Qt installation.
|
||||
|
||||
For example, a Qt5 5.5.1 installation to /usr/local/qt5 would require that QT_CMAKE_PREFIX_PATH be set with the following command. This can either be entered directly into your shell session before you build or in your shell profile (e.g.: ~/.bash_profile, ~/.bashrc, ~/.zshrc - this depends on your shell and environment).
|
||||
This can either be entered directly into your shell session before you build or in your shell profile (e.g.: ~/.bash_profile, ~/.bashrc, ~/.zshrc - this depends on your shell and environment).
|
||||
|
||||
The path it needs to be set to will depend on where and how Qt5 was installed. e.g.
|
||||
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.5.1/clang_64/lib/cmake/
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.5.1/lib/cmake
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.6.1/clang_64/lib/cmake/
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.6.1-1/lib/cmake
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake
|
||||
|
||||
####Generating build files
|
||||
|
@ -65,7 +65,7 @@ Any variables that need to be set for CMake to find dependencies can be set as E
|
|||
|
||||
For example, to pass the QT_CMAKE_PREFIX_PATH variable during build file generation:
|
||||
|
||||
cmake .. -DQT_CMAKE_PREFIX_PATH=/usr/local/qt/5.5.1/lib/cmake
|
||||
cmake .. -DQT_CMAKE_PREFIX_PATH=/usr/local/qt/5.6.1/lib/cmake
|
||||
|
||||
####Finding Dependencies
|
||||
|
||||
|
|
|
@ -4,13 +4,11 @@ Please read the [general build guide](BUILD.md) for information on dependencies
|
|||
|
||||
You will need the following tools to build our Android targets.
|
||||
|
||||
* [cmake](http://www.cmake.org/download/) ~> 3.1.0
|
||||
* Note that this is a newer version required than the minimum for hifi desktop targets.
|
||||
* [Qt](http://www.qt.io/download-open-source/#) ~> 5.4.0
|
||||
* Note that this is a newer version required than the minimum for hifi desktop targets.
|
||||
* [cmake](http://www.cmake.org/download/) ~> 3.5.1
|
||||
* [Qt](http://www.qt.io/download-open-source/#) ~> 5.5.1
|
||||
* [ant](http://ant.apache.org/bindownload.cgi) ~> 1.9.4
|
||||
* [Android NDK](https://developer.android.com/tools/sdk/ndk/index.html) = r10c
|
||||
* [Android SDK](http://developer.android.com/sdk/installing/index.html) ~> 24.0.2
|
||||
* [Android NDK](https://developer.android.com/tools/sdk/ndk/index.html) ~> r10d
|
||||
* [Android SDK](http://developer.android.com/sdk/installing/index.html) ~> 24.4.1.1
|
||||
* Install the latest Platform-tools
|
||||
* Install the latest Build-tools
|
||||
* Install the SDK Platform for API Level 19
|
||||
|
@ -19,6 +17,12 @@ You will need the following tools to build our Android targets.
|
|||
|
||||
You will also need to cross-compile the dependencies required for all platforms for Android, and help CMake find these compiled libraries on your machine.
|
||||
|
||||
####Scribe
|
||||
|
||||
High Fidelity has a shader pre-processing tool called `scribe` that various libraries will call on during the build process. You must compile scribe using your native toolchain (following the build instructions for your platform) and then pass a CMake variable or set an ENV variable `SCRIBE_PATH` that is a path to the scribe executable.
|
||||
|
||||
CMake will fatally error if it does not find the scribe executable while using the android toolchain.
|
||||
|
||||
####Optional Components
|
||||
|
||||
* [Oculus Mobile SDK](https://developer.oculus.com/downloads/#sdk=mobile) ~> 0.4.2
|
||||
|
@ -31,11 +35,11 @@ This is most easily accomplished by installing all Android dependencies in the s
|
|||
|
||||
####Qt
|
||||
|
||||
Install Qt 5.4 for Android for your host environment from the [Qt downloads page](http://www.qt.io/download/). Install Qt to ``$ANDROID_LIB_DIR/Qt``. This is required so that our root CMakeLists file can help CMake find your Android Qt installation.
|
||||
Install Qt 5.5.1 for Android for your host environment from the [Qt downloads page](http://www.qt.io/download/). Install Qt to ``$ANDROID_LIB_DIR/Qt``. This is required so that our root CMakeLists file can help CMake find your Android Qt installation.
|
||||
|
||||
The component required for the Android build is the `Android armv7` component.
|
||||
|
||||
If you would like to install Qt to a different location, or attempt to build with a different Qt version, you can pass `ANDROID_QT_CMAKE_PREFIX_PATH` to CMake. Point to the `cmake` folder inside `$VERSION_NUMBER/android_armv7/lib`. Otherwise, our root CMakeLists will set it to `$ANDROID_LIB_DIR/Qt/5.3/android_armv7/lib/cmake`.
|
||||
If you would like to install Qt to a different location, or attempt to build with a different Qt version, you can pass `ANDROID_QT_CMAKE_PREFIX_PATH` to CMake. Point to the `cmake` folder inside `$VERSION_NUMBER/android_armv7/lib`. Otherwise, our root CMakeLists will set it to `$ANDROID_LIB_DIR/Qt/5.5/android_armv7/lib/cmake`.
|
||||
|
||||
####OpenSSL
|
||||
|
||||
|
|
26
BUILD_OSX.md
|
@ -1,25 +1,31 @@
|
|||
Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only OS X specific instructions are found in this file.
|
||||
|
||||
###Homebrew
|
||||
[Homebrew](http://brew.sh/) is an excellent package manager for OS X. It makes install of all High Fidelity dependencies very simple.
|
||||
[Homebrew](http://brew.sh/) is an excellent package manager for OS X. It makes install of some High Fidelity dependencies very simple.
|
||||
|
||||
brew tap homebrew/versions
|
||||
brew install cmake openssl qt55
|
||||
brew install cmake openssl
|
||||
|
||||
We no longer require install of qt5 via our [homebrew formulas repository](https://github.com/highfidelity/homebrew-formulas). Versions of Qt that are 5.5.x provide a mechanism to disable the wireless scanning we previously had a custom patch for.
|
||||
###OpenSSL
|
||||
|
||||
###OpenSSL and Qt
|
||||
|
||||
Assuming you've installed OpenSSL or Qt 5 using the homebrew instructions above, you'll need to set OPENSSL_ROOT_DIR and QT_CMAKE_PREFIX_PATH so CMake can find your installations.
|
||||
Assuming you've installed OpenSSL using the homebrew instructions above, you'll need to set OPENSSL_ROOT_DIR so CMake can find your installations.
|
||||
For OpenSSL installed via homebrew, set OPENSSL_ROOT_DIR:
|
||||
|
||||
export OPENSSL_ROOT_DIR=/usr/local/Cellar/openssl/1.0.2h_1/
|
||||
|
||||
For Qt 5.5.1 installed via homebrew, set QT_CMAKE_PREFIX_PATH as follows.
|
||||
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt55/5.5.1/lib/cmake
|
||||
Note that this uses the version from the homebrew formula at the time of this writing, and the version in the path will likely change.
|
||||
|
||||
Note that these use the versions from homebrew formulae at the time of this writing, and the version in the path will likely change.
|
||||
###Qt
|
||||
You can use the online installer or the offline installer.
|
||||
|
||||
* [Download the online installer](http://www.qt.io/download-open-source/#section-2)
|
||||
* When it asks you to select components, select the following:
|
||||
* Qt > Qt 5.6
|
||||
|
||||
* [Download the offline installer](http://download.qt.io/official_releases/qt/5.6/5.6.1-1/qt-opensource-mac-x64-clang-5.6.1-1.dmg)
|
||||
|
||||
Once Qt is installed, you need to manually configure the following:
|
||||
* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt5.6.1/5.6/clang_64/lib/cmake/` directory.
|
||||
|
||||
###Xcode
|
||||
If Xcode is your editor of choice, you can ask CMake to generate Xcode project files instead of Unix Makefiles.
|
||||
|
|
12
BUILD_WIN.md
|
@ -27,17 +27,17 @@ We expect nmake.exe to be located at the following path.
|
|||
###Qt
|
||||
You can use the online installer or the offline installer. If you use the offline installer, be sure to select the "OpenGL" version.
|
||||
|
||||
* [Download the online installer](http://qt-project.org/downloads)
|
||||
* [Download the online installer](http://www.qt.io/download-open-source/#section-2)
|
||||
* When it asks you to select components, ONLY select one of the following, 32- or 64-bit to match your build preference:
|
||||
* Qt > Qt 5.5.1 > **msvc2013 32-bit**
|
||||
* Qt > Qt 5.5.1 > **msvc2013 64-bit**
|
||||
* Qt > Qt 5.6.1 > **msvc2013 32-bit**
|
||||
* Qt > Qt 5.6.1 > **msvc2013 64-bit**
|
||||
|
||||
* Download the offline installer, 32- or 64-bit to match your build preference:
|
||||
* [32-bit](http://download.qt.io/official_releases/qt/5.5/5.5.1/qt-opensource-windows-x86-msvc2013-5.5.1.exe)
|
||||
* [64-bit](http://download.qt.io/official_releases/qt/5.5/5.5.1/qt-opensource-windows-x86-msvc2013_64-5.5.1.exe)
|
||||
* [32-bit](http://download.qt.io/official_releases/qt/5.6/5.6.1-1/qt-opensource-windows-x86-msvc2013-5.6.1-1.exe)
|
||||
* [64-bit](http://download.qt.io/official_releases/qt/5.6/5.6.1-1/qt-opensource-windows-x86-msvc2013_64-5.6.1-1.exe)
|
||||
|
||||
Once Qt is installed, you need to manually configure the following:
|
||||
* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.5.1\msvc2013\lib\cmake` or `Qt\5.5.1\msvc2013_64\lib\cmake` directory.
|
||||
* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.6.1\msvc2013\lib\cmake` or `Qt\5.6.1\msvc2013_64\lib\cmake` directory.
|
||||
* You can set an environment variable from Control Panel > System > Advanced System Settings > Environment Variables > New
|
||||
|
||||
###External Libraries
|
||||
|
|
|
@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.2)
|
|||
if (USE_ANDROID_TOOLCHAIN)
|
||||
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/android/android.toolchain.cmake")
|
||||
set(ANDROID_NATIVE_API_LEVEL 19)
|
||||
set(ANDROID_TOOLCHAIN_NAME arm-linux-androideabi-clang3.5)
|
||||
set(ANDROID_STL c++_shared)
|
||||
endif ()
|
||||
|
||||
if (WIN32)
|
||||
|
@ -64,7 +66,7 @@ if (WIN32)
|
|||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG /OPT:REF /OPT:ICF")
|
||||
else ()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -fno-strict-aliasing -Wno-unused-parameter")
|
||||
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb -Woverloaded-virtual -Wdouble-promotion")
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "5.1") # gcc 5.1 and on have suggest-override
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override")
|
||||
|
@ -72,18 +74,30 @@ else ()
|
|||
endif ()
|
||||
endif(WIN32)
|
||||
|
||||
if ((NOT MSVC12) AND (NOT MSVC14))
|
||||
include(CheckCXXCompilerFlag)
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
|
||||
|
||||
if (COMPILER_SUPPORTS_CXX11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
elseif(COMPILER_SUPPORTS_CXX0X)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
else()
|
||||
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.3")
|
||||
# GLM 0.9.8 on Ubuntu 14 (gcc 4.4) has issues with the simd declarations
|
||||
add_definitions(-DGLM_FORCE_PURE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT ANDROID)
|
||||
if ((NOT MSVC12) AND (NOT MSVC14))
|
||||
include(CheckCXXCompilerFlag)
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
|
||||
|
||||
if (COMPILER_SUPPORTS_CXX11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
elseif(COMPILER_SUPPORTS_CXX0X)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
else()
|
||||
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
|
||||
endif()
|
||||
endif ()
|
||||
else ()
|
||||
# assume that the toolchain selected for android has C++11 support
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
endif ()
|
||||
|
||||
if (APPLE)
|
||||
|
@ -98,7 +112,7 @@ endif ()
|
|||
|
||||
if (ANDROID)
|
||||
if (NOT ANDROID_QT_CMAKE_PREFIX_PATH)
|
||||
set(QT_CMAKE_PREFIX_PATH ${ANDROID_LIB_DIR}/Qt/5.4/android_armv7/lib/cmake)
|
||||
set(QT_CMAKE_PREFIX_PATH ${ANDROID_LIB_DIR}/Qt/5.5/android_armv7/lib/cmake)
|
||||
else ()
|
||||
set(QT_CMAKE_PREFIX_PATH ${ANDROID_QT_CMAKE_PREFIX_PATH})
|
||||
endif ()
|
||||
|
@ -236,7 +250,9 @@ if (NOT ANDROID)
|
|||
endif()
|
||||
|
||||
if (ANDROID OR DESKTOP_GVR)
|
||||
add_subdirectory(interface)
|
||||
add_subdirectory(gvr-interface)
|
||||
add_subdirectory(plugins)
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{HIFI_MEMORY_DEBUGGING})
|
||||
|
|
|
@ -2,6 +2,11 @@ set(TARGET_NAME assignment-client)
|
|||
|
||||
setup_hifi_project(Core Gui Network Script Quick Widgets WebSockets)
|
||||
|
||||
# Fix up the rpath so macdeployqt works
|
||||
if (APPLE)
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES INSTALL_RPATH "@executable_path/../Frameworks")
|
||||
endif ()
|
||||
|
||||
# link in the shared libraries
|
||||
link_hifi_libraries(
|
||||
audio avatars octree gpu model fbx entities
|
||||
|
|
|
@ -48,11 +48,8 @@ static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10;
|
|||
Agent::Agent(ReceivedMessage& message) :
|
||||
ThreadedAssignment(message),
|
||||
_entityEditSender(),
|
||||
_receivedAudioStream(AudioConstants::NETWORK_FRAME_SAMPLES_STEREO, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES,
|
||||
InboundAudioStream::Settings(0, false, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, false,
|
||||
DEFAULT_WINDOW_STARVE_THRESHOLD, DEFAULT_WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES,
|
||||
DEFAULT_WINDOW_SECONDS_FOR_DESIRED_REDUCTION, false))
|
||||
{
|
||||
_receivedAudioStream(AudioConstants::NETWORK_FRAME_SAMPLES_STEREO,
|
||||
RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES) {
|
||||
DependencyManager::get<EntityScriptingInterface>()->setPacketSender(&_entityEditSender);
|
||||
|
||||
ResourceManager::init();
|
||||
|
|
|
@ -61,15 +61,14 @@
|
|||
|
||||
#include "AudioMixer.h"
|
||||
|
||||
const float LOUDNESS_TO_DISTANCE_RATIO = 0.00001f;
|
||||
const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.5f; // attenuation = -6dB * log2(distance)
|
||||
const float DEFAULT_NOISE_MUTING_THRESHOLD = 0.003f;
|
||||
const QString AUDIO_MIXER_LOGGING_TARGET_NAME = "audio-mixer";
|
||||
const QString AUDIO_ENV_GROUP_KEY = "audio_env";
|
||||
const QString AUDIO_BUFFER_GROUP_KEY = "audio_buffer";
|
||||
|
||||
InboundAudioStream::Settings AudioMixer::_streamSettings;
|
||||
static const float LOUDNESS_TO_DISTANCE_RATIO = 0.00001f;
|
||||
static const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.5f; // attenuation = -6dB * log2(distance)
|
||||
static const float DEFAULT_NOISE_MUTING_THRESHOLD = 0.003f;
|
||||
static const QString AUDIO_MIXER_LOGGING_TARGET_NAME = "audio-mixer";
|
||||
static const QString AUDIO_ENV_GROUP_KEY = "audio_env";
|
||||
static const QString AUDIO_BUFFER_GROUP_KEY = "audio_buffer";
|
||||
|
||||
int AudioMixer::_numStaticJitterFrames{ -1 };
|
||||
bool AudioMixer::_enableFilter = true;
|
||||
|
||||
bool AudioMixer::shouldMute(float quietestFrame) {
|
||||
|
@ -269,20 +268,18 @@ void AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData&
|
|||
if (!streamToAdd.lastPopSucceeded()) {
|
||||
bool forceSilentBlock = true;
|
||||
|
||||
if (_streamSettings._repetitionWithFade && !streamToAdd.getLastPopOutput().isNull()) {
|
||||
if (!streamToAdd.getLastPopOutput().isNull()) {
|
||||
bool isInjector = dynamic_cast<const InjectedAudioStream*>(&streamToAdd);
|
||||
|
||||
// reptition with fade is enabled, and we do have a valid previous frame to repeat
|
||||
// so we mix the previously-mixed block
|
||||
|
||||
// this is preferable to not mixing it at all to avoid the harsh jump to silence
|
||||
// in an injector, just go silent - the injector has likely ended
|
||||
// in other inputs (microphone, &c.), repeat with fade to avoid the harsh jump to silence
|
||||
|
||||
// we'll repeat the last block until it has a block to mix
|
||||
// and we'll gradually fade that repeated block into silence.
|
||||
|
||||
// calculate its fade factor, which depends on how many times it's already been repeated.
|
||||
|
||||
repeatedFrameFadeFactor = calculateRepeatedFrameFadeFactor(streamToAdd.getConsecutiveNotMixedCount() - 1);
|
||||
if (repeatedFrameFadeFactor > 0.0f) {
|
||||
if (!isInjector && repeatedFrameFadeFactor > 0.0f) {
|
||||
// apply the repeatedFrameFadeFactor to the gain
|
||||
gain *= repeatedFrameFadeFactor;
|
||||
|
||||
|
@ -641,7 +638,7 @@ QString AudioMixer::percentageForMixStats(int counter) {
|
|||
void AudioMixer::sendStatsPacket() {
|
||||
static QJsonObject statsObject;
|
||||
|
||||
statsObject["useDynamicJitterBuffers"] = _streamSettings._dynamicJitterBuffers;
|
||||
statsObject["useDynamicJitterBuffers"] = _numStaticJitterFrames == -1;
|
||||
statsObject["trailing_sleep_percentage"] = _trailingSleepRatio * 100.0f;
|
||||
statsObject["performance_throttling_ratio"] = _performanceThrottlingRatio;
|
||||
|
||||
|
@ -902,63 +899,62 @@ void AudioMixer::parseSettingsObject(const QJsonObject &settingsObject) {
|
|||
|
||||
// check the payload to see if we have asked for dynamicJitterBuffer support
|
||||
const QString DYNAMIC_JITTER_BUFFER_JSON_KEY = "dynamic_jitter_buffer";
|
||||
_streamSettings._dynamicJitterBuffers = audioBufferGroupObject[DYNAMIC_JITTER_BUFFER_JSON_KEY].toBool();
|
||||
if (_streamSettings._dynamicJitterBuffers) {
|
||||
qDebug() << "Enable dynamic jitter buffers.";
|
||||
bool enableDynamicJitterBuffer = audioBufferGroupObject[DYNAMIC_JITTER_BUFFER_JSON_KEY].toBool();
|
||||
if (enableDynamicJitterBuffer) {
|
||||
qDebug() << "Enabling dynamic jitter buffers.";
|
||||
|
||||
bool ok;
|
||||
const QString DESIRED_JITTER_BUFFER_FRAMES_KEY = "static_desired_jitter_buffer_frames";
|
||||
_numStaticJitterFrames = audioBufferGroupObject[DESIRED_JITTER_BUFFER_FRAMES_KEY].toString().toInt(&ok);
|
||||
if (!ok) {
|
||||
_numStaticJitterFrames = InboundAudioStream::DEFAULT_STATIC_JITTER_FRAMES;
|
||||
}
|
||||
qDebug() << "Static desired jitter buffer frames:" << _numStaticJitterFrames;
|
||||
} else {
|
||||
qDebug() << "Dynamic jitter buffers disabled.";
|
||||
qDebug() << "Disabling dynamic jitter buffers.";
|
||||
_numStaticJitterFrames = -1;
|
||||
}
|
||||
|
||||
// check for deprecated audio settings
|
||||
auto deprecationNotice = [](const QString& setting, const QString& value) {
|
||||
qInfo().nospace() << "[DEPRECATION NOTICE] " << setting << "(" << value << ") has been deprecated, and has no effect";
|
||||
};
|
||||
bool ok;
|
||||
const QString DESIRED_JITTER_BUFFER_FRAMES_KEY = "static_desired_jitter_buffer_frames";
|
||||
_streamSettings._staticDesiredJitterBufferFrames = audioBufferGroupObject[DESIRED_JITTER_BUFFER_FRAMES_KEY].toString().toInt(&ok);
|
||||
if (!ok) {
|
||||
_streamSettings._staticDesiredJitterBufferFrames = DEFAULT_STATIC_DESIRED_JITTER_BUFFER_FRAMES;
|
||||
}
|
||||
qDebug() << "Static desired jitter buffer frames:" << _streamSettings._staticDesiredJitterBufferFrames;
|
||||
|
||||
const QString MAX_FRAMES_OVER_DESIRED_JSON_KEY = "max_frames_over_desired";
|
||||
_streamSettings._maxFramesOverDesired = audioBufferGroupObject[MAX_FRAMES_OVER_DESIRED_JSON_KEY].toString().toInt(&ok);
|
||||
if (!ok) {
|
||||
_streamSettings._maxFramesOverDesired = DEFAULT_MAX_FRAMES_OVER_DESIRED;
|
||||
}
|
||||
qDebug() << "Max frames over desired:" << _streamSettings._maxFramesOverDesired;
|
||||
|
||||
const QString USE_STDEV_FOR_DESIRED_CALC_JSON_KEY = "use_stdev_for_desired_calc";
|
||||
_streamSettings._useStDevForJitterCalc = audioBufferGroupObject[USE_STDEV_FOR_DESIRED_CALC_JSON_KEY].toBool();
|
||||
if (_streamSettings._useStDevForJitterCalc) {
|
||||
qDebug() << "Using stdev method for jitter calc if dynamic jitter buffers enabled";
|
||||
} else {
|
||||
qDebug() << "Using max-gap method for jitter calc if dynamic jitter buffers enabled";
|
||||
int maxFramesOverDesired = audioBufferGroupObject[MAX_FRAMES_OVER_DESIRED_JSON_KEY].toString().toInt(&ok);
|
||||
if (ok && maxFramesOverDesired != InboundAudioStream::MAX_FRAMES_OVER_DESIRED) {
|
||||
deprecationNotice(MAX_FRAMES_OVER_DESIRED_JSON_KEY, QString::number(maxFramesOverDesired));
|
||||
}
|
||||
|
||||
const QString WINDOW_STARVE_THRESHOLD_JSON_KEY = "window_starve_threshold";
|
||||
_streamSettings._windowStarveThreshold = audioBufferGroupObject[WINDOW_STARVE_THRESHOLD_JSON_KEY].toString().toInt(&ok);
|
||||
if (!ok) {
|
||||
_streamSettings._windowStarveThreshold = DEFAULT_WINDOW_STARVE_THRESHOLD;
|
||||
int windowStarveThreshold = audioBufferGroupObject[WINDOW_STARVE_THRESHOLD_JSON_KEY].toString().toInt(&ok);
|
||||
if (ok && windowStarveThreshold != InboundAudioStream::WINDOW_STARVE_THRESHOLD) {
|
||||
deprecationNotice(WINDOW_STARVE_THRESHOLD_JSON_KEY, QString::number(windowStarveThreshold));
|
||||
}
|
||||
qDebug() << "Window A starve threshold:" << _streamSettings._windowStarveThreshold;
|
||||
|
||||
const QString WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES_JSON_KEY = "window_seconds_for_desired_calc_on_too_many_starves";
|
||||
_streamSettings._windowSecondsForDesiredCalcOnTooManyStarves = audioBufferGroupObject[WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES_JSON_KEY].toString().toInt(&ok);
|
||||
if (!ok) {
|
||||
_streamSettings._windowSecondsForDesiredCalcOnTooManyStarves = DEFAULT_WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES;
|
||||
int windowSecondsForDesiredCalcOnTooManyStarves = audioBufferGroupObject[WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES_JSON_KEY].toString().toInt(&ok);
|
||||
if (ok && windowSecondsForDesiredCalcOnTooManyStarves != InboundAudioStream::WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES) {
|
||||
deprecationNotice(WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES_JSON_KEY, QString::number(windowSecondsForDesiredCalcOnTooManyStarves));
|
||||
}
|
||||
qDebug() << "Window A length:" << _streamSettings._windowSecondsForDesiredCalcOnTooManyStarves << "seconds";
|
||||
|
||||
const QString WINDOW_SECONDS_FOR_DESIRED_REDUCTION_JSON_KEY = "window_seconds_for_desired_reduction";
|
||||
_streamSettings._windowSecondsForDesiredReduction = audioBufferGroupObject[WINDOW_SECONDS_FOR_DESIRED_REDUCTION_JSON_KEY].toString().toInt(&ok);
|
||||
if (!ok) {
|
||||
_streamSettings._windowSecondsForDesiredReduction = DEFAULT_WINDOW_SECONDS_FOR_DESIRED_REDUCTION;
|
||||
int windowSecondsForDesiredReduction = audioBufferGroupObject[WINDOW_SECONDS_FOR_DESIRED_REDUCTION_JSON_KEY].toString().toInt(&ok);
|
||||
if (ok && windowSecondsForDesiredReduction != InboundAudioStream::WINDOW_SECONDS_FOR_DESIRED_REDUCTION) {
|
||||
deprecationNotice(WINDOW_SECONDS_FOR_DESIRED_REDUCTION_JSON_KEY, QString::number(windowSecondsForDesiredReduction));
|
||||
}
|
||||
|
||||
const QString USE_STDEV_FOR_JITTER_JSON_KEY = "use_stdev_for_desired_calc";
|
||||
bool useStDevForJitterCalc = audioBufferGroupObject[USE_STDEV_FOR_JITTER_JSON_KEY].toBool();
|
||||
if (useStDevForJitterCalc != InboundAudioStream::USE_STDEV_FOR_JITTER) {
|
||||
deprecationNotice(USE_STDEV_FOR_JITTER_JSON_KEY, useStDevForJitterCalc ? "true" : "false");
|
||||
}
|
||||
qDebug() << "Window B length:" << _streamSettings._windowSecondsForDesiredReduction << "seconds";
|
||||
|
||||
const QString REPETITION_WITH_FADE_JSON_KEY = "repetition_with_fade";
|
||||
_streamSettings._repetitionWithFade = audioBufferGroupObject[REPETITION_WITH_FADE_JSON_KEY].toBool();
|
||||
if (_streamSettings._repetitionWithFade) {
|
||||
qDebug() << "Repetition with fade enabled";
|
||||
} else {
|
||||
qDebug() << "Repetition with fade disabled";
|
||||
bool repetitionWithFade = audioBufferGroupObject[REPETITION_WITH_FADE_JSON_KEY].toBool();
|
||||
if (repetitionWithFade != InboundAudioStream::REPETITION_WITH_FADE) {
|
||||
deprecationNotice(REPETITION_WITH_FADE_JSON_KEY, repetitionWithFade ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ public slots:
|
|||
|
||||
void sendStatsPacket() override;
|
||||
|
||||
static const InboundAudioStream::Settings& getStreamSettings() { return _streamSettings; }
|
||||
static int getStaticJitterFrames() { return _numStaticJitterFrames; }
|
||||
|
||||
private slots:
|
||||
void broadcastMixes();
|
||||
|
@ -112,7 +112,7 @@ private:
|
|||
};
|
||||
QVector<ReverbSettings> _zoneReverbSettings;
|
||||
|
||||
static InboundAudioStream::Settings _streamSettings;
|
||||
static int _numStaticJitterFrames; // -1 denotes dynamic jitter buffering
|
||||
|
||||
static bool _enableFilter;
|
||||
};
|
||||
|
|
|
@ -109,7 +109,7 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) {
|
|||
|
||||
bool isStereo = channelFlag == 1;
|
||||
|
||||
auto avatarAudioStream = new AvatarAudioStream(isStereo, AudioMixer::getStreamSettings());
|
||||
auto avatarAudioStream = new AvatarAudioStream(isStereo, AudioMixer::getStaticJitterFrames());
|
||||
avatarAudioStream->setupCodec(_codec, _selectedCodecName, AudioConstants::MONO);
|
||||
qDebug() << "creating new AvatarAudioStream... codec:" << _selectedCodecName;
|
||||
|
||||
|
@ -143,7 +143,7 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) {
|
|||
|
||||
if (streamIt == _audioStreams.end()) {
|
||||
// we don't have this injected stream yet, so add it
|
||||
auto injectorStream = new InjectedAudioStream(streamIdentifier, isStereo, AudioMixer::getStreamSettings());
|
||||
auto injectorStream = new InjectedAudioStream(streamIdentifier, isStereo, AudioMixer::getStaticJitterFrames());
|
||||
|
||||
#if INJECTORS_SUPPORT_CODECS
|
||||
injectorStream->setupCodec(_codec, _selectedCodecName, isStereo ? AudioConstants::STEREO : AudioConstants::MONO);
|
||||
|
@ -270,6 +270,7 @@ QJsonObject AudioMixerClientData::getAudioStreamStats() {
|
|||
downstreamStats["desired"] = streamStats._desiredJitterBufferFrames;
|
||||
downstreamStats["available_avg_10s"] = streamStats._framesAvailableAverage;
|
||||
downstreamStats["available"] = (double) streamStats._framesAvailable;
|
||||
downstreamStats["unplayed"] = (double) streamStats._unplayedMs;
|
||||
downstreamStats["starves"] = (double) streamStats._starveCount;
|
||||
downstreamStats["not_mixed"] = (double) streamStats._consecutiveNotMixedCount;
|
||||
downstreamStats["overflows"] = (double) streamStats._overflowCount;
|
||||
|
@ -294,6 +295,7 @@ QJsonObject AudioMixerClientData::getAudioStreamStats() {
|
|||
upstreamStats["desired_calc"] = avatarAudioStream->getCalculatedJitterBufferFrames();
|
||||
upstreamStats["available_avg_10s"] = streamStats._framesAvailableAverage;
|
||||
upstreamStats["available"] = (double) streamStats._framesAvailable;
|
||||
upstreamStats["unplayed"] = (double) streamStats._unplayedMs;
|
||||
upstreamStats["starves"] = (double) streamStats._starveCount;
|
||||
upstreamStats["not_mixed"] = (double) streamStats._consecutiveNotMixedCount;
|
||||
upstreamStats["overflows"] = (double) streamStats._overflowCount;
|
||||
|
@ -323,6 +325,7 @@ QJsonObject AudioMixerClientData::getAudioStreamStats() {
|
|||
upstreamStats["desired_calc"] = injectorPair.second->getCalculatedJitterBufferFrames();
|
||||
upstreamStats["available_avg_10s"] = streamStats._framesAvailableAverage;
|
||||
upstreamStats["available"] = (double) streamStats._framesAvailable;
|
||||
upstreamStats["unplayed"] = (double) streamStats._unplayedMs;
|
||||
upstreamStats["starves"] = (double) streamStats._starveCount;
|
||||
upstreamStats["not_mixed"] = (double) streamStats._consecutiveNotMixedCount;
|
||||
upstreamStats["overflows"] = (double) streamStats._overflowCount;
|
||||
|
|
|
@ -13,10 +13,8 @@
|
|||
|
||||
#include "AvatarAudioStream.h"
|
||||
|
||||
AvatarAudioStream::AvatarAudioStream(bool isStereo, const InboundAudioStream::Settings& settings) :
|
||||
PositionalAudioStream(PositionalAudioStream::Microphone, isStereo, settings)
|
||||
{
|
||||
}
|
||||
AvatarAudioStream::AvatarAudioStream(bool isStereo, int numStaticJitterFrames) :
|
||||
PositionalAudioStream(PositionalAudioStream::Microphone, isStereo, numStaticJitterFrames) {}
|
||||
|
||||
int AvatarAudioStream::parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& numAudioSamples) {
|
||||
int readBytes = 0;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
class AvatarAudioStream : public PositionalAudioStream {
|
||||
public:
|
||||
AvatarAudioStream(bool isStereo, const InboundAudioStream::Settings& settings);
|
||||
AvatarAudioStream(bool isStereo, int numStaticJitterFrames = -1);
|
||||
|
||||
private:
|
||||
// disallow copying of AvatarAudioStream objects
|
||||
|
|
|
@ -413,6 +413,9 @@ void AvatarMixer::handleAvatarDataPacket(QSharedPointer<ReceivedMessage> message
|
|||
}
|
||||
|
||||
void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
nodeList->getOrCreateLinkedData(senderNode);
|
||||
|
||||
if (senderNode->getLinkedData()) {
|
||||
AvatarMixerClientData* nodeData = dynamic_cast<AvatarMixerClientData*>(senderNode->getLinkedData());
|
||||
if (nodeData != nullptr) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <AccountManager.h>
|
||||
#include <HTTPConnection.h>
|
||||
#include <LogHandler.h>
|
||||
#include <shared/NetworkUtils.h>
|
||||
#include <NetworkingConstants.h>
|
||||
#include <NumericalConstants.h>
|
||||
#include <UUID.h>
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Android CMake toolchain file, for use with the Android NDK r5-r10c
|
||||
# Requires cmake 2.6.3 or newer (2.8.5 or newer is recommended).
|
||||
# Android CMake toolchain file, for use with the Android NDK r5-r10d
|
||||
# Requires cmake 2.6.3 or newer (2.8.9 or newer is recommended).
|
||||
# See home page: https://github.com/taka-no-me/android-cmake
|
||||
#
|
||||
# Usage Linux:
|
||||
|
@ -39,12 +39,6 @@
|
|||
# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake ..
|
||||
# $ make -j8
|
||||
#
|
||||
# Usage Linux (using standalone toolchain):
|
||||
# $ export ANDROID_STANDALONE_TOOLCHAIN=/absolute/path/to/android-toolchain
|
||||
# $ mkdir build && cd build
|
||||
# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake ..
|
||||
# $ make -j8
|
||||
#
|
||||
# Usage Windows:
|
||||
# You need native port of make to build your project.
|
||||
# Android NDK r7 (and newer) already has make.exe on board.
|
||||
|
@ -63,11 +57,6 @@
|
|||
# ANDROID_NDK=/opt/android-ndk - path to the NDK root.
|
||||
# Can be set as environment variable. Can be set only at first cmake run.
|
||||
#
|
||||
# ANDROID_STANDALONE_TOOLCHAIN=/opt/android-toolchain - path to the
|
||||
# standalone toolchain. This option is not used if full NDK is found
|
||||
# (ignored if ANDROID_NDK is set).
|
||||
# Can be set as environment variable. Can be set only at first cmake run.
|
||||
#
|
||||
# ANDROID_ABI=armeabi-v7a - specifies the target Application Binary
|
||||
# Interface (ABI). This option nearly matches to the APP_ABI variable
|
||||
# used by ndk-build tool from Android NDK.
|
||||
|
@ -123,8 +112,8 @@
|
|||
# * x86_64-clang3.5
|
||||
#
|
||||
# ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions
|
||||
# instead of Thumb. Is not available for "x86" (inapplicable) and
|
||||
# "armeabi-v6 with VFP" (is forced to be ON) ABIs.
|
||||
# instead of Thumb. Is not available for "armeabi-v6 with VFP"
|
||||
# (is forced to be ON) ABI.
|
||||
#
|
||||
# ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker
|
||||
# errors even if they are not used.
|
||||
|
@ -133,13 +122,6 @@
|
|||
# libraries. Automatically turned for NDK r5x and r6x due to GLESv2
|
||||
# problems.
|
||||
#
|
||||
# LIBRARY_OUTPUT_PATH_ROOT=${CMAKE_SOURCE_DIR} - where to output binary
|
||||
# files. See additional details below.
|
||||
#
|
||||
# ANDROID_SET_OBSOLETE_VARIABLES=ON - if set, then toolchain defines some
|
||||
# obsolete variables which were used by previous versions of this file for
|
||||
# backward compatibility.
|
||||
#
|
||||
# ANDROID_STL=gnustl_static - specify the runtime to use.
|
||||
#
|
||||
# Possible values are:
|
||||
|
@ -172,6 +154,8 @@
|
|||
# Implies -frtti -fno-exceptions.
|
||||
# Available for NDK r7b and newer.
|
||||
# Silently degrades to gnustl_static if not available.
|
||||
# c++_static -> Use the LLVM libc++ runtime as a static library.
|
||||
# c++_shared -> Use the LLVM libc++ runtime as a shared library.
|
||||
#
|
||||
# ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on
|
||||
# chosen runtime. If disabled, then the user is responsible for settings
|
||||
|
@ -200,12 +184,6 @@
|
|||
# will be set true, mutually exclusive. NEON option will be set true
|
||||
# if VFP is set to NEON.
|
||||
#
|
||||
# LIBRARY_OUTPUT_PATH_ROOT should be set in cache to determine where Android
|
||||
# libraries will be installed.
|
||||
# Default is ${CMAKE_SOURCE_DIR}, and the android libs will always be
|
||||
# under the ${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}
|
||||
# (depending on the target ABI). This is convenient for Android packaging.
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
cmake_minimum_required( VERSION 2.6.3 )
|
||||
|
@ -235,22 +213,22 @@ endif()
|
|||
# this one not so much
|
||||
set( CMAKE_SYSTEM_VERSION 1 )
|
||||
|
||||
# rpath makes low sence for Android
|
||||
# rpath makes low sense for Android
|
||||
set( CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "" )
|
||||
set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." )
|
||||
|
||||
# NDK search paths
|
||||
set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r10c -r10b -r10 -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
|
||||
if(NOT DEFINED ANDROID_NDK_SEARCH_PATHS)
|
||||
set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r10d -r10c -r10b -r10 -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
|
||||
if( NOT DEFINED ANDROID_NDK_SEARCH_PATHS )
|
||||
if( CMAKE_HOST_WIN32 )
|
||||
file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS )
|
||||
set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}/android-ndk" "$ENV{SystemDrive}/NVPACK/android-ndk" )
|
||||
set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}" "$ENV{SystemDrive}/NVPACK" )
|
||||
else()
|
||||
file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS )
|
||||
set( ANDROID_NDK_SEARCH_PATHS /opt/android-ndk "${ANDROID_NDK_SEARCH_PATHS}/NVPACK/android-ndk" )
|
||||
set( ANDROID_NDK_SEARCH_PATHS /opt "${ANDROID_NDK_SEARCH_PATHS}/NVPACK" )
|
||||
endif()
|
||||
endif()
|
||||
if(NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH)
|
||||
if( NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH )
|
||||
set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain )
|
||||
endif()
|
||||
|
||||
|
@ -272,106 +250,90 @@ set( ANDROID_DEFAULT_NDK_API_LEVEL_mips64 21 )
|
|||
|
||||
|
||||
macro( __LIST_FILTER listvar regex )
|
||||
if( ${listvar} )
|
||||
foreach( __val ${${listvar}} )
|
||||
if( __val MATCHES "${regex}" )
|
||||
list( REMOVE_ITEM ${listvar} "${__val}" )
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
if( ${listvar} )
|
||||
foreach( __val ${${listvar}} )
|
||||
if( __val MATCHES "${regex}" )
|
||||
list( REMOVE_ITEM ${listvar} "${__val}" )
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro( __INIT_VARIABLE var_name )
|
||||
set( __test_path 0 )
|
||||
foreach( __var ${ARGN} )
|
||||
if( __var STREQUAL "PATH" )
|
||||
set( __test_path 1 )
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
if( __test_path AND NOT EXISTS "${${var_name}}" )
|
||||
unset( ${var_name} CACHE )
|
||||
endif()
|
||||
if( "${${var_name}}" STREQUAL "" )
|
||||
set( __values 0 )
|
||||
set( __test_path 0 )
|
||||
foreach( __var ${ARGN} )
|
||||
if( __var STREQUAL "VALUES" )
|
||||
set( __values 1 )
|
||||
elseif( NOT __var STREQUAL "PATH" )
|
||||
set( __obsolete 0 )
|
||||
if( __var MATCHES "^OBSOLETE_.*$" )
|
||||
string( REPLACE "OBSOLETE_" "" __var "${__var}" )
|
||||
set( __obsolete 1 )
|
||||
endif()
|
||||
if( __var MATCHES "^ENV_.*$" )
|
||||
string( REPLACE "ENV_" "" __var "${__var}" )
|
||||
set( __value "$ENV{${__var}}" )
|
||||
elseif( DEFINED ${__var} )
|
||||
set( __value "${${__var}}" )
|
||||
else()
|
||||
if( __values )
|
||||
set( __value "${__var}" )
|
||||
else()
|
||||
set( __value "" )
|
||||
endif()
|
||||
endif()
|
||||
if( NOT "${__value}" STREQUAL "" )
|
||||
if( __test_path )
|
||||
if( EXISTS "${__value}" )
|
||||
file( TO_CMAKE_PATH "${__value}" ${var_name} )
|
||||
if( __obsolete AND NOT _CMAKE_IN_TRY_COMPILE )
|
||||
message( WARNING "Using value of obsolete variable ${__var} as initial value for ${var_name}. Please note, that ${__var} can be completely removed in future versions of the toolchain." )
|
||||
endif()
|
||||
break()
|
||||
endif()
|
||||
else()
|
||||
set( ${var_name} "${__value}" )
|
||||
if( __obsolete AND NOT _CMAKE_IN_TRY_COMPILE )
|
||||
message( WARNING "Using value of obsolete variable ${__var} as initial value for ${var_name}. Please note, that ${__var} can be completely removed in future versions of the toolchain." )
|
||||
endif()
|
||||
if( __var STREQUAL "PATH" )
|
||||
set( __test_path 1 )
|
||||
break()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
unset( __value )
|
||||
unset( __values )
|
||||
unset( __obsolete )
|
||||
elseif( __test_path )
|
||||
file( TO_CMAKE_PATH "${${var_name}}" ${var_name} )
|
||||
endif()
|
||||
unset( __test_path )
|
||||
|
||||
if( __test_path AND NOT EXISTS "${${var_name}}" )
|
||||
unset( ${var_name} CACHE )
|
||||
endif()
|
||||
|
||||
if( " ${${var_name}}" STREQUAL " " )
|
||||
set( __values 0 )
|
||||
foreach( __var ${ARGN} )
|
||||
if( __var STREQUAL "VALUES" )
|
||||
set( __values 1 )
|
||||
elseif( NOT __var STREQUAL "PATH" )
|
||||
if( __var MATCHES "^ENV_.*$" )
|
||||
string( REPLACE "ENV_" "" __var "${__var}" )
|
||||
set( __value "$ENV{${__var}}" )
|
||||
elseif( DEFINED ${__var} )
|
||||
set( __value "${${__var}}" )
|
||||
elseif( __values )
|
||||
set( __value "${__var}" )
|
||||
else()
|
||||
set( __value "" )
|
||||
endif()
|
||||
|
||||
if( NOT " ${__value}" STREQUAL " " AND (NOT __test_path OR EXISTS "${__value}") )
|
||||
set( ${var_name} "${__value}" )
|
||||
break()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
unset( __value )
|
||||
unset( __values )
|
||||
endif()
|
||||
|
||||
if( __test_path )
|
||||
file( TO_CMAKE_PATH "${${var_name}}" ${var_name} )
|
||||
endif()
|
||||
unset( __test_path )
|
||||
endmacro()
|
||||
|
||||
macro( __DETECT_NATIVE_API_LEVEL _var _path )
|
||||
SET( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*.*$" )
|
||||
FILE( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" )
|
||||
if( NOT __apiFileContent )
|
||||
message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." )
|
||||
endif()
|
||||
string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" )
|
||||
unset( __apiFileContent )
|
||||
unset( __ndkApiLevelRegex )
|
||||
set( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*.*$" )
|
||||
file( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" )
|
||||
if( NOT __apiFileContent )
|
||||
message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." )
|
||||
endif()
|
||||
string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" )
|
||||
unset( __apiFileContent )
|
||||
unset( __ndkApiLevelRegex )
|
||||
endmacro()
|
||||
|
||||
macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root )
|
||||
if( EXISTS "${_root}" )
|
||||
file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" )
|
||||
__LIST_FILTER( __gccExePath "^[.].*" )
|
||||
list( LENGTH __gccExePath __gccExePathsCount )
|
||||
if( NOT __gccExePathsCount EQUAL 1 AND NOT _CMAKE_IN_TRY_COMPILE )
|
||||
message( WARNING "Could not determine machine name for compiler from ${_root}" )
|
||||
set( ${_var} "" )
|
||||
file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" )
|
||||
__LIST_FILTER( __gccExePath "^[.].*" )
|
||||
list( LENGTH __gccExePath __gccExePathsCount )
|
||||
if( NOT __gccExePathsCount EQUAL 1 AND NOT _CMAKE_IN_TRY_COMPILE )
|
||||
message( WARNING "Could not determine machine name for compiler from ${_root}" )
|
||||
set( ${_var} "" )
|
||||
else()
|
||||
get_filename_component( __gccExeName "${__gccExePath}" NAME_WE )
|
||||
string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" )
|
||||
endif()
|
||||
unset( __gccExePath )
|
||||
unset( __gccExePathsCount )
|
||||
unset( __gccExeName )
|
||||
else()
|
||||
get_filename_component( __gccExeName "${__gccExePath}" NAME_WE )
|
||||
string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" )
|
||||
set( ${_var} "" )
|
||||
endif()
|
||||
unset( __gccExePath )
|
||||
unset( __gccExePathsCount )
|
||||
unset( __gccExeName )
|
||||
else()
|
||||
set( ${_var} "" )
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
||||
|
@ -419,17 +381,19 @@ if( NOT ANDROID_NDK_HOST_X64 )
|
|||
endif()
|
||||
|
||||
# see if we have path to Android NDK
|
||||
__INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK )
|
||||
if( NOT ANDROID_NDK AND NOT ANDROID_STANDALONE_TOOLCHAIN )
|
||||
__INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK )
|
||||
endif()
|
||||
if( NOT ANDROID_NDK )
|
||||
# see if we have path to Android standalone toolchain
|
||||
__INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN OBSOLETE_ANDROID_NDK_TOOLCHAIN_ROOT OBSOLETE_ENV_ANDROID_NDK_TOOLCHAIN_ROOT )
|
||||
__INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN )
|
||||
|
||||
if( NOT ANDROID_STANDALONE_TOOLCHAIN )
|
||||
#try to find Android NDK in one of the the default locations
|
||||
set( __ndkSearchPaths )
|
||||
foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} )
|
||||
foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} )
|
||||
list( APPEND __ndkSearchPaths "${__ndkSearchPath}${suffix}" )
|
||||
list( APPEND __ndkSearchPaths "${__ndkSearchPath}/android-ndk${suffix}" )
|
||||
endforeach()
|
||||
endforeach()
|
||||
__INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} )
|
||||
|
@ -487,7 +451,7 @@ else()
|
|||
or
|
||||
export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain
|
||||
or put the toolchain or NDK in the default path:
|
||||
sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}
|
||||
sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}/android-ndk
|
||||
sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" )
|
||||
endif()
|
||||
|
||||
|
@ -636,7 +600,7 @@ if( BUILD_WITH_ANDROID_NDK )
|
|||
endif()
|
||||
if( NOT __availableToolchains )
|
||||
file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" )
|
||||
if( __availableToolchains )
|
||||
if( __availableToolchainsLst )
|
||||
list(SORT __availableToolchainsLst) # we need clang to go after gcc
|
||||
endif()
|
||||
__LIST_FILTER( __availableToolchainsLst "^[.]" )
|
||||
|
@ -669,7 +633,7 @@ if( NOT ANDROID_SUPPORTED_ABIS )
|
|||
endif()
|
||||
|
||||
# choose target ABI
|
||||
__INIT_VARIABLE( ANDROID_ABI OBSOLETE_ARM_TARGET OBSOLETE_ARM_TARGETS VALUES ${ANDROID_SUPPORTED_ABIS} )
|
||||
__INIT_VARIABLE( ANDROID_ABI VALUES ${ANDROID_SUPPORTED_ABIS} )
|
||||
# verify that target ABI is supported
|
||||
list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx )
|
||||
if( __androidAbiIdx EQUAL -1 )
|
||||
|
@ -760,7 +724,7 @@ if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMa
|
|||
endif()
|
||||
|
||||
if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 )
|
||||
__INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD OBSOLETE_FORCE_ARM VALUES OFF )
|
||||
__INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD VALUES OFF )
|
||||
set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE )
|
||||
mark_as_advanced( ANDROID_FORCE_ARM_BUILD )
|
||||
else()
|
||||
|
@ -845,6 +809,7 @@ else()
|
|||
unset( __realApiLevel )
|
||||
endif()
|
||||
set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE )
|
||||
set( CMAKE_ANDROID_API ${ANDROID_NATIVE_API_LEVEL} )
|
||||
if( CMAKE_VERSION VERSION_GREATER "2.8" )
|
||||
list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS )
|
||||
set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
|
||||
|
@ -863,23 +828,14 @@ endif()
|
|||
|
||||
# runtime choice (STL, rtti, exceptions)
|
||||
if( NOT ANDROID_STL )
|
||||
# honor legacy ANDROID_USE_STLPORT
|
||||
if( DEFINED ANDROID_USE_STLPORT )
|
||||
if( ANDROID_USE_STLPORT )
|
||||
set( ANDROID_STL stlport_static )
|
||||
endif()
|
||||
message( WARNING "You are using an obsolete variable ANDROID_USE_STLPORT to select the STL variant. Use -DANDROID_STL=stlport_static instead." )
|
||||
endif()
|
||||
if( NOT ANDROID_STL )
|
||||
set( ANDROID_STL gnustl_static )
|
||||
endif()
|
||||
endif()
|
||||
set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" )
|
||||
set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" )
|
||||
mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES )
|
||||
|
||||
if( BUILD_WITH_ANDROID_NDK )
|
||||
if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared)$")
|
||||
if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared|c\\+\\+_static|c\\+\\+_shared)$")
|
||||
message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\".
|
||||
The possible values are:
|
||||
none -> Do not configure the runtime.
|
||||
|
@ -891,6 +847,8 @@ The possible values are:
|
|||
stlport_shared -> Use the STLport runtime as a shared library.
|
||||
gnustl_static -> (default) Use the GNU STL as a static library.
|
||||
gnustl_shared -> Use the GNU STL as a shared library.
|
||||
c++_static -> Use the LLVM libc++ runtime as a static library.
|
||||
c++_shared -> Use the LLVM libc++ runtime as a shared library.
|
||||
" )
|
||||
endif()
|
||||
elseif( BUILD_WITH_STANDALONE_TOOLCHAIN )
|
||||
|
@ -1033,7 +991,7 @@ if( BUILD_WITH_ANDROID_NDK )
|
|||
set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" )
|
||||
elseif( ANDROID_STL MATCHES "gabi" )
|
||||
if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
|
||||
message( FATAL_ERROR "gabi++ is not awailable in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.")
|
||||
message( FATAL_ERROR "gabi++ is not available in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.")
|
||||
endif()
|
||||
set( ANDROID_RTTI ON )
|
||||
set( ANDROID_EXCEPTIONS OFF )
|
||||
|
@ -1066,12 +1024,40 @@ if( BUILD_WITH_ANDROID_NDK )
|
|||
else()
|
||||
set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" )
|
||||
endif()
|
||||
set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" )
|
||||
set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" "${__libstl}/include/backward" )
|
||||
if( EXISTS "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" )
|
||||
set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" )
|
||||
else()
|
||||
set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" )
|
||||
endif()
|
||||
elseif( ANDROID_STL MATCHES "c\\+\\+_shared" OR ANDROID_STL MATCHES "c\\+\\+_static" )
|
||||
set( ANDROID_EXCEPTIONS ON )
|
||||
set( ANDROID_RTTI ON )
|
||||
set( ANDROID_CXX_ROOT "${ANDROID_NDK}/sources/cxx-stl/" )
|
||||
set( ANDROID_LLVM_ROOT "${ANDROID_CXX_ROOT}/llvm-libc++" )
|
||||
|
||||
if( X86 )
|
||||
set( ANDROID_ABI_INCLUDE_DIRS "${ANDROID_CXX_ROOT}/gabi++/include" )
|
||||
else()
|
||||
set( ANDROID_ABI_INCLUDE_DIRS "${ANDROID_CXX_ROOT}/llvm-libc++abi/include" )
|
||||
endif()
|
||||
|
||||
set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_LLVM_ROOT}/libcxx/include" "${ANDROID_ABI_INCLUDE_DIRS}" )
|
||||
|
||||
# android support sfiles
|
||||
include_directories ( SYSTEM ${ANDROID_NDK}/sources/android/support/include )
|
||||
|
||||
if(ANDROID_STL MATCHES "c\\+\\+_shared")
|
||||
set ( LLVM_LIBRARY_NAME "libc++_shared.so")
|
||||
else()
|
||||
set ( LLVM_LIBRARY_NAME "libc++_static.a" )
|
||||
endif ()
|
||||
|
||||
if( EXISTS "${ANDROID_LLVM_ROOT}/libs/${ANDROID_NDK_ABI_NAME}/${LLVM_LIBRARY_NAME}" )
|
||||
set( __libstl "${ANDROID_LLVM_ROOT}/libs/${ANDROID_NDK_ABI_NAME}/${LLVM_LIBRARY_NAME}" )
|
||||
else()
|
||||
message( FATAL_ERROR "Could not find libc++ library" )
|
||||
endif()
|
||||
else()
|
||||
message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" )
|
||||
endif()
|
||||
|
@ -1144,7 +1130,12 @@ if( NOT CMAKE_C_COMPILER )
|
|||
endif()
|
||||
set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "assembler" )
|
||||
set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" )
|
||||
set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" )
|
||||
if( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" )
|
||||
# Use gcc-ar if we have it for better LTO support.
|
||||
set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" )
|
||||
else()
|
||||
set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" )
|
||||
endif()
|
||||
set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" )
|
||||
set( CMAKE_NM "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" )
|
||||
set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" )
|
||||
|
@ -1168,7 +1159,7 @@ endif()
|
|||
include( CMakeForceCompiler )
|
||||
CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU )
|
||||
if( ANDROID_COMPILER_IS_CLANG )
|
||||
set( CMAKE_C_COMPILER_ID Clang)
|
||||
set( CMAKE_C_COMPILER_ID Clang )
|
||||
endif()
|
||||
set( CMAKE_C_PLATFORM_ID Linux )
|
||||
if( X86_64 OR MIPS64 OR ARM64_V8A )
|
||||
|
@ -1195,6 +1186,14 @@ set( CMAKE_ASM_COMPILER_FORCED TRUE )
|
|||
set( CMAKE_COMPILER_IS_GNUASM 1)
|
||||
set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm )
|
||||
|
||||
foreach( lang C CXX ASM )
|
||||
if( ANDROID_COMPILER_IS_CLANG )
|
||||
set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_CLANG_VERSION} )
|
||||
else()
|
||||
set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_COMPILER_VERSION} )
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# flags and definitions
|
||||
remove_definitions( -DANDROID )
|
||||
add_definitions( -DANDROID )
|
||||
|
@ -1225,14 +1224,14 @@ endif()
|
|||
|
||||
# NDK flags
|
||||
if (ARM64_V8A )
|
||||
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fpic -ffunction-sections -funwind-tables" )
|
||||
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
|
||||
set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" )
|
||||
set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" )
|
||||
if( NOT ANDROID_COMPILER_IS_CLANG )
|
||||
set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" )
|
||||
endif()
|
||||
elseif( ARMEABI OR ARMEABI_V7A)
|
||||
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fpic -funwind-tables" )
|
||||
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
|
||||
if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 )
|
||||
set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" )
|
||||
set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" )
|
||||
|
@ -1251,13 +1250,11 @@ elseif( X86 OR X86_64 )
|
|||
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
|
||||
if( NOT ANDROID_COMPILER_IS_CLANG )
|
||||
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" )
|
||||
else()
|
||||
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fPIC" )
|
||||
endif()
|
||||
set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" )
|
||||
set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" )
|
||||
elseif( MIPS OR MIPS64 )
|
||||
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fpic -fno-strict-aliasing -finline-functions -ffunction-sections -funwind-tables -fmessage-length=0" )
|
||||
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-strict-aliasing -finline-functions -funwind-tables -fmessage-length=0" )
|
||||
set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" )
|
||||
set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer" )
|
||||
if( NOT ANDROID_COMPILER_IS_CLANG )
|
||||
|
@ -1342,7 +1339,7 @@ if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
|
|||
else()
|
||||
__INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES OFF )
|
||||
endif()
|
||||
__INIT_VARIABLE( ANDROID_NO_UNDEFINED OBSOLETE_NO_UNDEFINED VALUES ON )
|
||||
__INIT_VARIABLE( ANDROID_NO_UNDEFINED VALUES ON )
|
||||
__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON )
|
||||
__INIT_VARIABLE( ANDROID_GOLD_LINKER VALUES ON )
|
||||
__INIT_VARIABLE( ANDROID_NOEXECSTACK VALUES ON )
|
||||
|
@ -1350,7 +1347,7 @@ __INIT_VARIABLE( ANDROID_RELRO VALUES ON )
|
|||
|
||||
set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" )
|
||||
set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
|
||||
set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
|
||||
set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Put each function in separate section and enable garbage collection of unused input sections at link time" )
|
||||
set( ANDROID_GOLD_LINKER ${ANDROID_GOLD_LINKER} CACHE BOOL "Enables gold linker" )
|
||||
set( ANDROID_NOEXECSTACK ${ANDROID_NOEXECSTACK} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
|
||||
set( ANDROID_RELRO ${ANDROID_RELRO} CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" )
|
||||
|
@ -1452,6 +1449,16 @@ if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" )
|
|||
set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" )
|
||||
endif()
|
||||
|
||||
# pie/pic
|
||||
if( NOT (ANDROID_NATIVE_API_LEVEL LESS 16) AND (NOT DEFINED ANDROID_APP_PIE OR ANDROID_APP_PIE) AND (CMAKE_VERSION VERSION_GREATER 2.8.8) )
|
||||
set( CMAKE_POSITION_INDEPENDENT_CODE TRUE )
|
||||
set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie")
|
||||
else()
|
||||
set( CMAKE_POSITION_INDEPENDENT_CODE FALSE )
|
||||
set( CMAKE_CXX_FLAGS "-fpic ${CMAKE_CXX_FLAGS}" )
|
||||
set( CMAKE_C_FLAGS "-fpic ${CMAKE_C_FLAGS}" )
|
||||
endif()
|
||||
|
||||
# configure rtti
|
||||
if( DEFINED ANDROID_RTTI AND ANDROID_STL_FORCE_FEATURES )
|
||||
if( ANDROID_RTTI )
|
||||
|
@ -1515,27 +1522,31 @@ if( ANDROID_EXPLICIT_CRT_LINK )
|
|||
endif()
|
||||
|
||||
# setup output directories
|
||||
set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "root for library output, set this to change where android libs are installed to" )
|
||||
set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" )
|
||||
|
||||
if(NOT _CMAKE_IN_TRY_COMPILE)
|
||||
if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" )
|
||||
set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" )
|
||||
else()
|
||||
set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" )
|
||||
endif()
|
||||
set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "path for android libs" )
|
||||
if( DEFINED LIBRARY_OUTPUT_PATH_ROOT
|
||||
OR EXISTS "${CMAKE_SOURCE_DIR}/AndroidManifest.xml"
|
||||
OR (EXISTS "${CMAKE_SOURCE_DIR}/../AndroidManifest.xml" AND EXISTS "${CMAKE_SOURCE_DIR}/../jni/") )
|
||||
set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "Root for binaries output, set this to change where Android libs are installed to" )
|
||||
if( NOT _CMAKE_IN_TRY_COMPILE )
|
||||
if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" )
|
||||
set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" )
|
||||
else()
|
||||
set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" )
|
||||
endif()
|
||||
set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for Android libs" )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# copy shaed stl library to build directory
|
||||
if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" )
|
||||
get_filename_component( __libstlname "${__libstl}" NAME )
|
||||
execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess )
|
||||
if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}")
|
||||
message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" )
|
||||
endif()
|
||||
unset( __fileCopyProcess )
|
||||
unset( __libstlname )
|
||||
if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" AND DEFINED LIBRARY_OUTPUT_PATH )
|
||||
get_filename_component( __libstlname "${__libstl}" NAME )
|
||||
execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess )
|
||||
if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}")
|
||||
message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" )
|
||||
endif()
|
||||
unset( __fileCopyProcess )
|
||||
unset( __libstlname )
|
||||
endif()
|
||||
|
||||
|
||||
|
@ -1596,28 +1607,10 @@ macro( find_host_program )
|
|||
endmacro()
|
||||
|
||||
|
||||
macro( ANDROID_GET_ABI_RAWNAME TOOLCHAIN_FLAG VAR )
|
||||
if( "${TOOLCHAIN_FLAG}" STREQUAL "ARMEABI" )
|
||||
set( ${VAR} "armeabi" )
|
||||
elseif( "${TOOLCHAIN_FLAG}" STREQUAL "ARMEABI_V7A" )
|
||||
set( ${VAR} "armeabi-v7a" )
|
||||
elseif( "${TOOLCHAIN_FLAG}" STREQUAL "X86" )
|
||||
set( ${VAR} "x86" )
|
||||
elseif( "${TOOLCHAIN_FLAG}" STREQUAL "MIPS" )
|
||||
set( ${VAR} "mips" )
|
||||
else()
|
||||
set( ${VAR} "unknown" )
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
if (POLICY CMP0054)
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
endif ()
|
||||
|
||||
# export toolchain settings for the try_compile() command
|
||||
if( NOT PROJECT_NAME STREQUAL "CMAKE_TRY_COMPILE" )
|
||||
if( NOT _CMAKE_IN_TRY_COMPILE )
|
||||
set( __toolchain_config "")
|
||||
foreach( __var NDK_CCACHE LIBRARY_OUTPUT_PATH_ROOT ANDROID_FORBID_SYGWIN ANDROID_SET_OBSOLETE_VARIABLES
|
||||
foreach( __var NDK_CCACHE LIBRARY_OUTPUT_PATH_ROOT ANDROID_FORBID_SYGWIN
|
||||
ANDROID_NDK_HOST_X64
|
||||
ANDROID_NDK
|
||||
ANDROID_NDK_LAYOUT
|
||||
|
@ -1636,9 +1629,10 @@ if( NOT PROJECT_NAME STREQUAL "CMAKE_TRY_COMPILE" )
|
|||
ANDROID_RELRO
|
||||
ANDROID_LIBM_PATH
|
||||
ANDROID_EXPLICIT_CRT_LINK
|
||||
ANDROID_APP_PIE
|
||||
)
|
||||
if( DEFINED ${__var} )
|
||||
if( "${__var}" MATCHES " ")
|
||||
if( ${__var} MATCHES " ")
|
||||
set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" )
|
||||
else()
|
||||
set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" )
|
||||
|
@ -1663,16 +1657,6 @@ if( CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_HOST_WIN32 )
|
|||
endif()
|
||||
|
||||
|
||||
# set some obsolete variables for backward compatibility
|
||||
set( ANDROID_SET_OBSOLETE_VARIABLES ON CACHE BOOL "Define obsolete Andrid-specific cmake variables" )
|
||||
mark_as_advanced( ANDROID_SET_OBSOLETE_VARIABLES )
|
||||
if( ANDROID_SET_OBSOLETE_VARIABLES )
|
||||
set( ANDROID_API_LEVEL ${ANDROID_NATIVE_API_LEVEL} )
|
||||
set( ARM_TARGET "${ANDROID_ABI}" )
|
||||
set( ARMEABI_NDK_NAME "${ANDROID_NDK_ABI_NAME}" )
|
||||
endif()
|
||||
|
||||
|
||||
# Variables controlling behavior or set by cmake toolchain:
|
||||
# ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips", "arm64-v8a", "x86_64", "mips64"
|
||||
# ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14,15,16,17,18,19,21 (depends on NDK version)
|
||||
|
@ -1686,22 +1670,15 @@ endif()
|
|||
# ANDROID_RELRO : ON/OFF
|
||||
# ANDROID_FORCE_ARM_BUILD : ON/OFF
|
||||
# ANDROID_STL_FORCE_FEATURES : ON/OFF
|
||||
# ANDROID_SET_OBSOLETE_VARIABLES : ON/OFF
|
||||
# ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product/<product_name>/obj/lib/libm.so) to workaround unresolved `sincos`
|
||||
# Can be set only at the first run:
|
||||
# ANDROID_NDK
|
||||
# ANDROID_STANDALONE_TOOLCHAIN
|
||||
# ANDROID_NDK : path to your NDK install
|
||||
# NDK_CCACHE : path to your ccache executable
|
||||
# ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain
|
||||
# ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems)
|
||||
# ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID)
|
||||
# LIBRARY_OUTPUT_PATH_ROOT : <any valid path>
|
||||
# NDK_CCACHE : <path to your ccache executable>
|
||||
# Obsolete:
|
||||
# ANDROID_API_LEVEL : superseded by ANDROID_NATIVE_API_LEVEL
|
||||
# ARM_TARGET : superseded by ANDROID_ABI
|
||||
# ARM_TARGETS : superseded by ANDROID_ABI (can be set only)
|
||||
# ANDROID_NDK_TOOLCHAIN_ROOT : superseded by ANDROID_STANDALONE_TOOLCHAIN (can be set only)
|
||||
# ANDROID_USE_STLPORT : superseded by ANDROID_STL=stlport_static
|
||||
# ANDROID_LEVEL : superseded by ANDROID_NATIVE_API_LEVEL (completely removed)
|
||||
# ANDROID_STANDALONE_TOOLCHAIN
|
||||
#
|
||||
# Primary read-only variables:
|
||||
# ANDROID : always TRUE
|
||||
|
@ -1715,19 +1692,16 @@ endif()
|
|||
# X86_64 : TRUE if configured for x86_64
|
||||
# MIPS : TRUE if configured for mips
|
||||
# MIPS64 : TRUE if configured for mips64
|
||||
# BUILD_ANDROID : always TRUE
|
||||
# BUILD_WITH_ANDROID_NDK : TRUE if NDK is used
|
||||
# BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used
|
||||
# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform
|
||||
# ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86", "mips", "arm64-v8a", "x86_64", "mips64" depending on ANDROID_ABI
|
||||
# ANDROID_NDK_RELEASE : from r5 to r10c; set only for NDK
|
||||
# ANDROID_NDK_RELEASE : from r5 to r10d; set only for NDK
|
||||
# ANDROID_NDK_RELEASE_NUM : numeric ANDROID_NDK_RELEASE version (1000*major+minor)
|
||||
# ANDROID_ARCH_NAME : "arm", "x86", "mips", "arm64", "x86_64", "mips64" depending on ANDROID_ABI
|
||||
# ANDROID_SYSROOT : path to the compiler sysroot
|
||||
# TOOL_OS_SUFFIX : "" or ".exe" depending on host platform
|
||||
# ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used
|
||||
# Obsolete:
|
||||
# ARMEABI_NDK_NAME : superseded by ANDROID_NDK_ABI_NAME
|
||||
#
|
||||
# Secondary (less stable) read-only variables:
|
||||
# ANDROID_COMPILER_VERSION : GCC version used (not Clang version)
|
||||
|
@ -1742,12 +1716,10 @@ endif()
|
|||
# ANDROID_RTTI : if rtti is enabled by the runtime
|
||||
# ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime
|
||||
# ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used
|
||||
# ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product/<product_name>/obj/lib/libm.so) to workaround unresolved `sincos`
|
||||
#
|
||||
# Defaults:
|
||||
# ANDROID_DEFAULT_NDK_API_LEVEL
|
||||
# ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH}
|
||||
# ANDROID_NDK_SEARCH_PATHS
|
||||
# ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH
|
||||
# ANDROID_SUPPORTED_ABIS_${ARCH}
|
||||
# ANDROID_SUPPORTED_NDK_VERSIONS
|
||||
# ANDROID_SUPPORTED_NDK_VERSIONS
|
||||
|
|
9
cmake/externals/LibOVR/CMakeLists.txt
vendored
|
@ -20,8 +20,8 @@ if (WIN32)
|
|||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.3.0_public.zip
|
||||
URL_MD5 a2dcf695e0f03a70fdd1ed7480585e82
|
||||
URL https://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.8.0_public.zip
|
||||
URL_MD5 bea17e04acc1dd8cf7cabefa1b28cc3c
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
|
@ -29,8 +29,8 @@ if (WIN32)
|
|||
)
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||
|
||||
set(LIBOVR_DIR ${SOURCE_DIR}/OculusSDK/LibOVR)
|
||||
message("LIBOVR dir ${SOURCE_DIR}")
|
||||
set(LIBOVR_DIR ${SOURCE_DIR}/LibOVR)
|
||||
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||
set(LIBOVR_LIB_DIR ${LIBOVR_DIR}/Lib/Windows/x64/Release/VS2013 CACHE TYPE INTERNAL)
|
||||
else()
|
||||
|
@ -38,6 +38,7 @@ if (WIN32)
|
|||
endif()
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${LIBOVR_DIR}/Include CACHE TYPE INTERNAL)
|
||||
message("LIBOVR include dir ${${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS}")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${LIBOVR_LIB_DIR}/LibOVR.lib CACHE TYPE INTERNAL)
|
||||
|
||||
elseif(APPLE)
|
||||
|
|
3
cmake/externals/glew/CMakeLists.txt
vendored
|
@ -15,7 +15,6 @@ ExternalProject_Add(
|
|||
LOG_BUILD 1
|
||||
)
|
||||
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
||||
|
@ -32,4 +31,4 @@ elseif (WIN32)
|
|||
endif ()
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/${LIB_PREFIX}glew_d.${LIB_EXT} CACHE FILEPATH "Path to glew debug library")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/${LIB_PREFIX}glew.${LIB_EXT} CACHE FILEPATH "Path to glew release library")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/${LIB_PREFIX}glew.${LIB_EXT} CACHE FILEPATH "Path to glew release library")
|
||||
|
|
21
cmake/externals/gli/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
set(EXTERNAL_NAME gli)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL https://hifi-public.s3.amazonaws.com/dependencies/gli-0.8.1.0.zip
|
||||
URL_MD5 00c990f59c12bbf367956ef399d6f798
|
||||
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
LOG_DOWNLOAD 1
|
||||
)
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR} CACHE PATH "List of gli include directories")
|
4
cmake/externals/glm/CMakeLists.txt
vendored
|
@ -3,8 +3,8 @@ set(EXTERNAL_NAME glm)
|
|||
include(ExternalProject)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://hifi-public.s3.amazonaws.com/dependencies/glm-0.9.5.4.zip
|
||||
URL_MD5 fab76fc982b256b46208e5c750ed456a
|
||||
URL https://hifi-public.s3.amazonaws.com/dependencies/glm-0.9.8.zip
|
||||
URL_MD5 579ac77a3110befa3244d68c0ceb7281
|
||||
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
||||
LOG_DOWNLOAD 1
|
||||
|
|
74
cmake/externals/hifiAudioCodec/CMakeLists.txt
vendored
|
@ -5,39 +5,43 @@ set(EXTERNAL_NAME hifiAudioCodec)
|
|||
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
|
||||
if (WIN32 OR APPLE)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-1.zip
|
||||
URL_MD5 23ec3fe51eaa155ea159a4971856fc13
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
LOG_DOWNLOAD 1
|
||||
)
|
||||
elseif(NOT ANDROID)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-linux.zip
|
||||
URL_MD5 7d37914a18aa4de971d2f45dd3043bde
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
LOG_DOWNLOAD 1
|
||||
)
|
||||
endif()
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL)
|
||||
|
||||
if (WIN32)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/audio.lib CACHE TYPE INTERNAL)
|
||||
elseif(APPLE)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL)
|
||||
elseif(NOT ANDROID)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL)
|
||||
if (NOT ANDROID)
|
||||
|
||||
if (WIN32 OR APPLE)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-1.zip
|
||||
URL_MD5 23ec3fe51eaa155ea159a4971856fc13
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
LOG_DOWNLOAD 1
|
||||
)
|
||||
else ()
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-linux.zip
|
||||
URL_MD5 7d37914a18aa4de971d2f45dd3043bde
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
LOG_DOWNLOAD 1
|
||||
)
|
||||
endif()
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL)
|
||||
|
||||
if (WIN32)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/audio.lib CACHE TYPE INTERNAL)
|
||||
elseif(APPLE)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL)
|
||||
elseif(NOT ANDROID)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
|
7
cmake/externals/sdl2/CMakeLists.txt
vendored
|
@ -46,7 +46,7 @@ else ()
|
|||
if (ANDROID)
|
||||
set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19")
|
||||
endif ()
|
||||
|
||||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://www.libsdl.org/release/SDL2-2.0.3.tar.gz
|
||||
|
@ -61,7 +61,6 @@ endif ()
|
|||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
||||
|
||||
if (APPLE)
|
||||
|
||||
# NOOP
|
||||
|
@ -78,9 +77,9 @@ elseif (WIN32)
|
|||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${SOURCE_DIR}/lib/x86/SDL2.lib CACHE FILEPATH "Path to SDL2 library")
|
||||
set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/lib/x86 CACHE PATH "Location of SDL2 DLL")
|
||||
endif()
|
||||
|
||||
|
||||
add_paths_to_fixup_libs(${${EXTERNAL_NAME_UPPER}_DLL_PATH})
|
||||
|
||||
|
||||
else ()
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
|
||||
|
|
28
cmake/externals/tbb/CMakeLists.txt
vendored
|
@ -3,9 +3,9 @@ set(EXTERNAL_NAME tbb)
|
|||
include(ExternalProject)
|
||||
|
||||
if (ANDROID)
|
||||
|
||||
|
||||
find_program(NDK_BUILD_COMMAND NAMES ndk-build DOC "Path to the ndk-build command")
|
||||
|
||||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://hifi-public.s3.amazonaws.com/dependencies/tbb43_20150316oss_src.tgz
|
||||
|
@ -20,7 +20,7 @@ if (ANDROID)
|
|||
)
|
||||
elseif (APPLE)
|
||||
find_program(MAKE_COMMAND NAMES make DOC "Path to the make command")
|
||||
|
||||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://hifi-public.s3.amazonaws.com/dependencies/tbb43_20150316oss_src.tgz
|
||||
|
@ -37,11 +37,11 @@ else ()
|
|||
if (WIN32)
|
||||
set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150316oss_win.zip)
|
||||
set(DOWNLOAD_MD5 d250d40bb93b255f75bcbb19e976a440)
|
||||
else ()
|
||||
else ()
|
||||
set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150316oss_lin.tgz)
|
||||
set(DOWNLOAD_MD5 7830ba2bc62438325fba2ec0c95367a5)
|
||||
endif ()
|
||||
|
||||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL ${DOWNLOAD_URL}
|
||||
|
@ -60,11 +60,11 @@ ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
|||
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
|
||||
if (APPLE)
|
||||
if (APPLE)
|
||||
set(_TBB_LIB_DIR "${SOURCE_DIR}/lib")
|
||||
set(_LIB_PREFIX "lib")
|
||||
set(_LIB_EXT "dylib")
|
||||
|
||||
|
||||
ExternalProject_Add_Step(
|
||||
${EXTERNAL_NAME}
|
||||
change-install-name
|
||||
|
@ -74,7 +74,7 @@ if (APPLE)
|
|||
WORKING_DIRECTORY <SOURCE_DIR>
|
||||
LOG 1
|
||||
)
|
||||
|
||||
|
||||
elseif (WIN32)
|
||||
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||
set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/intel64/vc12")
|
||||
|
@ -91,18 +91,18 @@ elseif (ANDROID)
|
|||
elseif (UNIX)
|
||||
set(_LIB_PREFIX "lib")
|
||||
set(_LIB_EXT "so")
|
||||
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(_TBB_ARCH_DIR "intel64")
|
||||
else()
|
||||
set(_TBB_ARCH_DIR "ia32")
|
||||
endif()
|
||||
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_C_COMPILER} -dumpversion
|
||||
OUTPUT_VARIABLE GCC_VERSION
|
||||
)
|
||||
|
||||
|
||||
if (GCC_VERSION VERSION_GREATER 4.4 OR GCC_VERSION VERSION_EQUAL 4.4)
|
||||
set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/${_TBB_ARCH_DIR}/gcc4.4")
|
||||
elseif (GCC_VERSION VERSION_GREATER 4.1 OR GCC_VERSION VERSION_EQUAL 4.1)
|
||||
|
@ -110,9 +110,9 @@ elseif (UNIX)
|
|||
else ()
|
||||
message(STATUS "Could not find a compatible version of Threading Building Blocks library for your compiler.")
|
||||
endif ()
|
||||
|
||||
|
||||
endif ()
|
||||
|
||||
|
||||
endif ()
|
||||
|
||||
if (DEFINED _TBB_LIB_DIR)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbb_debug.${_LIB_EXT} CACHE FILEPATH "TBB debug library location")
|
||||
|
|
24
cmake/externals/wasapi/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
if (WIN32)
|
||||
|
||||
set(EXTERNAL_NAME wasapi)
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://hifi-public.s3.amazonaws.com/dependencies/qtaudio_wasapi.zip
|
||||
URL_MD5 11c8a7728d6eda7223df800e10b70723
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
LOG_DOWNLOAD 1
|
||||
)
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||
|
||||
set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR} CACHE FILEPATH "Location of wasapi DLL")
|
||||
|
||||
endif()
|
|
@ -1,23 +0,0 @@
|
|||
#
|
||||
# AutoMTC.cmake
|
||||
#
|
||||
# Created by Andrzej Kapolka on 12/31/13.
|
||||
# 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
|
||||
#
|
||||
|
||||
macro(AUTO_MTC)
|
||||
set(AUTOMTC_SRC ${TARGET_NAME}_automtc.cpp)
|
||||
|
||||
file(GLOB INCLUDE_FILES src/*.h)
|
||||
|
||||
if (NOT ANDROID)
|
||||
set(MTC_EXECUTABLE mtc)
|
||||
else ()
|
||||
set(MTC_EXECUTABLE $ENV{MTC_PATH}/mtc)
|
||||
endif ()
|
||||
|
||||
add_custom_command(OUTPUT ${AUTOMTC_SRC} COMMAND ${MTC_EXECUTABLE} -o ${AUTOMTC_SRC} ${INCLUDE_FILES} DEPENDS ${MTC_EXECUTABLE} ${INCLUDE_FILES})
|
||||
endmacro()
|
|
@ -1,77 +1,92 @@
|
|||
#
|
||||
#
|
||||
# AutoScribeShader.cmake
|
||||
#
|
||||
#
|
||||
# Created by Sam Gateau on 12/17/14.
|
||||
# Copyright 2014 High Fidelity, Inc.
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
#
|
||||
|
||||
function(AUTOSCRIBE_SHADER SHADER_FILE)
|
||||
|
||||
# Grab include files
|
||||
foreach(includeFile ${ARGN})
|
||||
list(APPEND SHADER_INCLUDE_FILES ${includeFile})
|
||||
endforeach()
|
||||
# Grab include files
|
||||
foreach(includeFile ${ARGN})
|
||||
list(APPEND SHADER_INCLUDE_FILES ${includeFile})
|
||||
endforeach()
|
||||
|
||||
foreach(SHADER_INCLUDE ${SHADER_INCLUDE_FILES})
|
||||
get_filename_component(INCLUDE_DIR ${SHADER_INCLUDE} PATH)
|
||||
list(APPEND SHADER_INCLUDES_PATHS ${INCLUDE_DIR})
|
||||
endforeach()
|
||||
foreach(SHADER_INCLUDE ${SHADER_INCLUDE_FILES})
|
||||
get_filename_component(INCLUDE_DIR ${SHADER_INCLUDE} PATH)
|
||||
list(APPEND SHADER_INCLUDES_PATHS ${INCLUDE_DIR})
|
||||
endforeach()
|
||||
|
||||
#Extract the unique include shader paths
|
||||
set(INCLUDES ${HIFI_LIBRARIES_SHADER_INCLUDE_FILES})
|
||||
#message(${TARGET_NAME} Hifi for includes ${INCLUDES})
|
||||
foreach(EXTRA_SHADER_INCLUDE ${INCLUDES})
|
||||
list(APPEND SHADER_INCLUDES_PATHS ${EXTRA_SHADER_INCLUDE})
|
||||
endforeach()
|
||||
|
||||
#Extract the unique include shader paths
|
||||
set(INCLUDES ${HIFI_LIBRARIES_SHADER_INCLUDE_FILES})
|
||||
#message(${TARGET_NAME} Hifi for includes ${INCLUDES})
|
||||
foreach(EXTRA_SHADER_INCLUDE ${INCLUDES})
|
||||
list(APPEND SHADER_INCLUDES_PATHS ${EXTRA_SHADER_INCLUDE})
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES SHADER_INCLUDES_PATHS)
|
||||
#message(ready for includes ${SHADER_INCLUDES_PATHS})
|
||||
|
||||
list(REMOVE_DUPLICATES SHADER_INCLUDES_PATHS)
|
||||
#message(ready for includes ${SHADER_INCLUDES_PATHS})
|
||||
# make the scribe include arguments
|
||||
set(SCRIBE_INCLUDES)
|
||||
foreach(INCLUDE_PATH ${SHADER_INCLUDES_PATHS})
|
||||
set(SCRIBE_INCLUDES ${SCRIBE_INCLUDES} -I ${INCLUDE_PATH}/)
|
||||
endforeach()
|
||||
|
||||
# make the scribe include arguments
|
||||
set(SCRIBE_INCLUDES)
|
||||
foreach(INCLUDE_PATH ${SHADER_INCLUDES_PATHS})
|
||||
set(SCRIBE_INCLUDES ${SCRIBE_INCLUDES} -I ${INCLUDE_PATH}/)
|
||||
endforeach()
|
||||
# Define the final name of the generated shader file
|
||||
get_filename_component(SHADER_TARGET ${SHADER_FILE} NAME_WE)
|
||||
get_filename_component(SHADER_EXT ${SHADER_FILE} EXT)
|
||||
if(SHADER_EXT STREQUAL .slv)
|
||||
set(SHADER_TARGET ${SHADER_TARGET}_vert.h)
|
||||
elseif(${SHADER_EXT} STREQUAL .slf)
|
||||
set(SHADER_TARGET ${SHADER_TARGET}_frag.h)
|
||||
elseif(${SHADER_EXT} STREQUAL .slg)
|
||||
set(SHADER_TARGET ${SHADER_TARGET}_geom.h)
|
||||
endif()
|
||||
|
||||
# Define the final name of the generated shader file
|
||||
get_filename_component(SHADER_TARGET ${SHADER_FILE} NAME_WE)
|
||||
get_filename_component(SHADER_EXT ${SHADER_FILE} EXT)
|
||||
if(SHADER_EXT STREQUAL .slv)
|
||||
set(SHADER_TARGET ${SHADER_TARGET}_vert.h)
|
||||
elseif(${SHADER_EXT} STREQUAL .slf)
|
||||
set(SHADER_TARGET ${SHADER_TARGET}_frag.h)
|
||||
elseif(${SHADER_EXT} STREQUAL .slg)
|
||||
set(SHADER_TARGET ${SHADER_TARGET}_geom.h)
|
||||
endif()
|
||||
set(SHADER_TARGET "${SHADERS_DIR}/${SHADER_TARGET}")
|
||||
|
||||
set(SHADER_TARGET "${SHADERS_DIR}/${SHADER_TARGET}")
|
||||
# Target dependant Custom rule on the SHADER_FILE
|
||||
if (APPLE)
|
||||
set(GLPROFILE MAC_GL)
|
||||
set(SCRIBE_ARGS -c++ -D GLPROFILE ${GLPROFILE} ${SCRIBE_INCLUDES} -o ${SHADER_TARGET} ${SHADER_FILE})
|
||||
|
||||
# Target dependant Custom rule on the SHADER_FILE
|
||||
if (APPLE)
|
||||
set(GLPROFILE MAC_GL)
|
||||
set(SCRIBE_ARGS -c++ -D GLPROFILE ${GLPROFILE} ${SCRIBE_INCLUDES} -o ${SHADER_TARGET} ${SHADER_FILE})
|
||||
add_custom_command(OUTPUT ${SHADER_TARGET} COMMAND scribe ${SCRIBE_ARGS} DEPENDS scribe ${SHADER_INCLUDE_FILES} ${SHADER_FILE})
|
||||
elseif (ANDROID)
|
||||
set(GLPROFILE LINUX_GL)
|
||||
set(SCRIBE_ARGS -c++ -D GLPROFILE ${GLPROFILE} ${SCRIBE_INCLUDES} -o ${SHADER_TARGET} ${SHADER_FILE})
|
||||
|
||||
add_custom_command(OUTPUT ${SHADER_TARGET} COMMAND scribe ${SCRIBE_ARGS} DEPENDS scribe ${SHADER_INCLUDE_FILES} ${SHADER_FILE})
|
||||
elseif (UNIX)
|
||||
set(GLPROFILE LINUX_GL)
|
||||
set(SCRIBE_ARGS -c++ -D GLPROFILE ${GLPROFILE} ${SCRIBE_INCLUDES} -o ${SHADER_TARGET} ${SHADER_FILE})
|
||||
# for an android build, we can't use the scribe that cmake would normally produce as a target,
|
||||
# since it's unrunnable by the cross-compiling build machine
|
||||
|
||||
add_custom_command(OUTPUT ${SHADER_TARGET} COMMAND scribe ${SCRIBE_ARGS} DEPENDS scribe ${SHADER_INCLUDE_FILES} ${SHADER_FILE})
|
||||
else ()
|
||||
set(GLPROFILE PC_GL)
|
||||
set(SCRIBE_ARGS -c++ -D GLPROFILE ${GLPROFILE} ${SCRIBE_INCLUDES} -o ${SHADER_TARGET} ${SHADER_FILE})
|
||||
# so, we require the compiling user to point us at a compiled executable version for their native toolchain
|
||||
find_program(NATIVE_SCRIBE scribe PATHS ${SCRIBE_PATH} ENV SCRIBE_PATH)
|
||||
|
||||
add_custom_command(OUTPUT ${SHADER_TARGET} COMMAND scribe ${SCRIBE_ARGS} DEPENDS scribe ${SHADER_INCLUDE_FILES} ${SHADER_FILE})
|
||||
endif()
|
||||
if (NOT NATIVE_SCRIBE)
|
||||
message(FATAL_ERROR "The High Fidelity scribe tool is required for shader pre-processing. \
|
||||
Please compile scribe using your native toolchain and set SCRIBE_PATH to the path containing the scribe executable in your ENV.\
|
||||
")
|
||||
endif ()
|
||||
|
||||
#output the generated file name
|
||||
set(AUTOSCRIBE_SHADER_RETURN ${SHADER_TARGET} PARENT_SCOPE)
|
||||
add_custom_command(OUTPUT ${SHADER_TARGET} COMMAND ${NATIVE_SCRIBE} ${SCRIBE_ARGS} DEPENDS ${SHADER_INCLUDE_FILES} ${SHADER_FILE})
|
||||
elseif (UNIX)
|
||||
set(GLPROFILE LINUX_GL)
|
||||
set(SCRIBE_ARGS -c++ -D GLPROFILE ${GLPROFILE} ${SCRIBE_INCLUDES} -o ${SHADER_TARGET} ${SHADER_FILE})
|
||||
|
||||
file(GLOB INCLUDE_FILES ${SHADER_TARGET})
|
||||
add_custom_command(OUTPUT ${SHADER_TARGET} COMMAND scribe ${SCRIBE_ARGS} DEPENDS scribe ${SHADER_INCLUDE_FILES} ${SHADER_FILE})
|
||||
else ()
|
||||
set(GLPROFILE PC_GL)
|
||||
set(SCRIBE_ARGS -c++ -D GLPROFILE ${GLPROFILE} ${SCRIBE_INCLUDES} -o ${SHADER_TARGET} ${SHADER_FILE})
|
||||
|
||||
add_custom_command(OUTPUT ${SHADER_TARGET} COMMAND scribe ${SCRIBE_ARGS} DEPENDS scribe ${SHADER_INCLUDE_FILES} ${SHADER_FILE})
|
||||
endif()
|
||||
|
||||
#output the generated file name
|
||||
set(AUTOSCRIBE_SHADER_RETURN ${SHADER_TARGET} PARENT_SCOPE)
|
||||
|
||||
file(GLOB INCLUDE_FILES ${SHADER_TARGET})
|
||||
|
||||
endfunction()
|
||||
|
||||
|
@ -79,11 +94,11 @@ endfunction()
|
|||
macro(AUTOSCRIBE_SHADER_LIB)
|
||||
set(HIFI_LIBRARIES_SHADER_INCLUDE_FILES "")
|
||||
file(RELATIVE_PATH RELATIVE_LIBRARY_DIR_PATH ${CMAKE_CURRENT_SOURCE_DIR} "${HIFI_LIBRARY_DIR}")
|
||||
foreach(HIFI_LIBRARY ${ARGN})
|
||||
foreach(HIFI_LIBRARY ${ARGN})
|
||||
#if (NOT TARGET ${HIFI_LIBRARY})
|
||||
# file(GLOB_RECURSE HIFI_LIBRARIES_SHADER_INCLUDE_FILES ${RELATIVE_LIBRARY_DIR_PATH}/${HIFI_LIBRARY}/src/)
|
||||
#endif ()
|
||||
|
||||
|
||||
#file(GLOB_RECURSE HIFI_LIBRARIES_SHADER_INCLUDE_FILES ${HIFI_LIBRARY_DIR}/${HIFI_LIBRARY}/src/*.slh)
|
||||
list(APPEND HIFI_LIBRARIES_SHADER_INCLUDE_FILES ${HIFI_LIBRARY_DIR}/${HIFI_LIBRARY}/src)
|
||||
endforeach()
|
||||
|
@ -99,9 +114,9 @@ macro(AUTOSCRIBE_SHADER_LIB)
|
|||
#message("${TARGET_NAME} ${SHADER_INCLUDE_FILES}")
|
||||
set(AUTOSCRIBE_SHADER_SRC "")
|
||||
foreach(SHADER_FILE ${SHADER_SOURCE_FILES})
|
||||
AUTOSCRIBE_SHADER(${SHADER_FILE} ${SHADER_INCLUDE_FILES})
|
||||
file(TO_CMAKE_PATH "${AUTOSCRIBE_SHADER_RETURN}" AUTOSCRIBE_GENERATED_FILE)
|
||||
list(APPEND AUTOSCRIBE_SHADER_SRC ${AUTOSCRIBE_GENERATED_FILE})
|
||||
AUTOSCRIBE_SHADER(${SHADER_FILE} ${SHADER_INCLUDE_FILES})
|
||||
file(TO_CMAKE_PATH "${AUTOSCRIBE_SHADER_RETURN}" AUTOSCRIBE_GENERATED_FILE)
|
||||
list(APPEND AUTOSCRIBE_SHADER_SRC ${AUTOSCRIBE_GENERATED_FILE})
|
||||
endforeach()
|
||||
#message(${TARGET_NAME} ${AUTOSCRIBE_SHADER_SRC})
|
||||
|
||||
|
@ -118,4 +133,4 @@ macro(AUTOSCRIBE_SHADER_LIB)
|
|||
# Link library shaders, if they exist
|
||||
include_directories("${SHADERS_DIR}")
|
||||
|
||||
endmacro()
|
||||
endmacro()
|
||||
|
|
|
@ -16,26 +16,6 @@ macro(fixup_interface)
|
|||
string(REPLACE " " "\\ " ESCAPED_INSTALL_PATH ${INTERFACE_INSTALL_DIR})
|
||||
set(_INTERFACE_INSTALL_PATH "${ESCAPED_INSTALL_PATH}/${ESCAPED_BUNDLE_NAME}.app")
|
||||
|
||||
# install QtWebProcess from Qt to the application bundle
|
||||
# since it is missed by macdeployqt
|
||||
# https://bugreports.qt.io/browse/QTBUG-35211
|
||||
set(LIBEXEC_PATH "${_INTERFACE_INSTALL_PATH}/Contents/libexec")
|
||||
install(
|
||||
PROGRAMS "${QT_DIR}/libexec/QtWebProcess"
|
||||
DESTINATION ${LIBEXEC_PATH}
|
||||
COMPONENT ${CLIENT_COMPONENT}
|
||||
)
|
||||
|
||||
set(QTWEBPROCESS_PATH "\${CMAKE_INSTALL_PREFIX}/${LIBEXEC_PATH}")
|
||||
|
||||
# we also need a qt.conf in the directory of QtWebProcess
|
||||
install(CODE "
|
||||
file(WRITE ${QTWEBPROCESS_PATH}/qt.conf
|
||||
\"[Paths]\nPlugins = ../PlugIns\nImports = ../Resources/qml\nQml2Imports = ../Resources/qml\"
|
||||
)"
|
||||
COMPONENT ${CLIENT_COMPONENT}
|
||||
)
|
||||
|
||||
find_program(MACDEPLOYQT_COMMAND macdeployqt PATHS "${QT_DIR}/bin" NO_DEFAULT_PATH)
|
||||
|
||||
if (NOT MACDEPLOYQT_COMMAND AND (PRODUCTION_BUILD OR PR_BUILD))
|
||||
|
@ -49,7 +29,6 @@ macro(fixup_interface)
|
|||
execute_process(COMMAND ${MACDEPLOYQT_COMMAND}\
|
||||
\${CMAKE_INSTALL_PREFIX}/${_INTERFACE_INSTALL_PATH}/\
|
||||
-verbose=2 -qmldir=${CMAKE_SOURCE_DIR}/interface/resources/qml/\
|
||||
-executable=\${CMAKE_INSTALL_PREFIX}/${_INTERFACE_INSTALL_PATH}/Contents/libexec/QtWebProcess\
|
||||
)"
|
||||
COMPONENT ${CLIENT_COMPONENT}
|
||||
)
|
||||
|
|
|
@ -59,7 +59,12 @@ macro(install_beside_console)
|
|||
set(EXECUTABLE_NEEDING_FIXUP "\${CMAKE_INSTALL_PREFIX}/${COMPONENT_INSTALL_DIR}/${TARGET_NAME}")
|
||||
string(REPLACE " " "\\ " ESCAPED_EXECUTABLE_NAME ${EXECUTABLE_NEEDING_FIXUP})
|
||||
|
||||
# configure Info.plist for COMPONENT_APP
|
||||
install(CODE "
|
||||
set(MACOSX_BUNDLE_EXECUTABLE_NAME domain-server)
|
||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER com.highfidelity.server-components)
|
||||
set(MACOSX_BUNDLE_BUNDLE_NAME Sandbox\\ Components)
|
||||
configure_file(${HF_CMAKE_DIR}/templates/MacOSXBundleSandboxComponentsInfo.plist.in ${ESCAPED_BUNDLE_NAME}/Contents/Info.plist)
|
||||
execute_process(COMMAND ${MACDEPLOYQT_COMMAND} ${ESCAPED_BUNDLE_NAME} -verbose=2 -executable=${ESCAPED_EXECUTABLE_NAME})"
|
||||
COMPONENT ${SERVER_COMPONENT}
|
||||
)
|
||||
|
|
|
@ -41,5 +41,15 @@ macro(PACKAGE_LIBRARIES_FOR_DEPLOYMENT)
|
|||
POST_BUILD
|
||||
COMMAND CMD /C "SET PATH=%PATH%;${QT_DIR}/bin && ${WINDEPLOYQT_COMMAND} ${EXTRA_DEPLOY_OPTIONS} $<$<OR:$<CONFIG:Release>,$<CONFIG:MinSizeRel>,$<CONFIG:RelWithDebInfo>>:--release> $<TARGET_FILE:${TARGET_NAME}>"
|
||||
)
|
||||
|
||||
set(QTAUDIO_PATH $<TARGET_FILE_DIR:${TARGET_NAME}>/audio)
|
||||
|
||||
# if present, replace qtaudio_windows.dll with qtaudio_wasapi.dll
|
||||
add_custom_command(
|
||||
TARGET ${TARGET_NAME}
|
||||
POST_BUILD
|
||||
COMMAND if exist ${QTAUDIO_PATH}/qtaudio_windows.dll ( ${CMAKE_COMMAND} -E remove ${QTAUDIO_PATH}/qtaudio_windows.dll && ${CMAKE_COMMAND} -E copy ${WASAPI_DLL_PATH}/qtaudio_wasapi.dll ${QTAUDIO_PATH} && ${CMAKE_COMMAND} -E copy ${WASAPI_DLL_PATH}/qtaudio_wasapi.pdb ${QTAUDIO_PATH} )
|
||||
)
|
||||
|
||||
endif ()
|
||||
endmacro()
|
||||
|
|
|
@ -18,6 +18,13 @@ macro(SET_PACKAGING_PARAMETERS)
|
|||
|
||||
set(RELEASE_TYPE $ENV{RELEASE_TYPE})
|
||||
set(RELEASE_NUMBER $ENV{RELEASE_NUMBER})
|
||||
string(TOLOWER "$ENV{BRANCH}" BUILD_BRANCH)
|
||||
set(BUILD_GLOBAL_SERVICES "DEVELOPMENT")
|
||||
set(USE_STABLE_GLOBAL_SERVICES FALSE)
|
||||
|
||||
message(STATUS "The BUILD_BRANCH variable is: ${BUILD_BRANCH}")
|
||||
message(STATUS "The BRANCH environment variable is: $ENV{BRANCH}")
|
||||
message(STATUS "The RELEASE_TYPE variable is: ${RELEASE_TYPE}")
|
||||
|
||||
if (RELEASE_TYPE STREQUAL "PRODUCTION")
|
||||
set(DEPLOY_PACKAGE TRUE)
|
||||
|
@ -31,6 +38,14 @@ macro(SET_PACKAGING_PARAMETERS)
|
|||
# add definition for this release type
|
||||
add_definitions(-DPRODUCTION_BUILD)
|
||||
|
||||
# if the build is a PRODUCTION_BUILD from the "stable" branch
|
||||
# then use the STABLE gobal services
|
||||
if (BUILD_BRANCH STREQUAL "stable")
|
||||
message(STATUS "The RELEASE_TYPE is PRODUCTION and the BUILD_BRANCH is stable...")
|
||||
set(BUILD_GLOBAL_SERVICES "STABLE")
|
||||
set(USE_STABLE_GLOBAL_SERVICES TRUE)
|
||||
endif()
|
||||
|
||||
elseif (RELEASE_TYPE STREQUAL "PR")
|
||||
set(DEPLOY_PACKAGE TRUE)
|
||||
set(PR_BUILD 1)
|
||||
|
@ -132,6 +147,10 @@ macro(SET_PACKAGING_PARAMETERS)
|
|||
set(CLIENT_COMPONENT client)
|
||||
set(SERVER_COMPONENT server)
|
||||
|
||||
# print out some results for testing this new build feature
|
||||
message(STATUS "The BUILD_GLOBAL_SERVICES variable is: ${BUILD_GLOBAL_SERVICES}")
|
||||
message(STATUS "The USE_STABLE_GLOBAL_SERVICES variable is: ${USE_STABLE_GLOBAL_SERVICES}")
|
||||
|
||||
# create a header file our targets can use to find out the application version
|
||||
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/includes")
|
||||
configure_file("${HF_CMAKE_DIR}/templates/BuildInfo.h.in" "${CMAKE_BINARY_DIR}/includes/BuildInfo.h")
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
#
|
||||
#
|
||||
# SetupHifiLibrary.cmake
|
||||
#
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#
|
||||
|
||||
macro(SETUP_HIFI_LIBRARY)
|
||||
|
||||
|
||||
project(${TARGET_NAME})
|
||||
|
||||
|
||||
# grab the implementation and header files
|
||||
file(GLOB_RECURSE LIB_SRCS "src/*.h" "src/*.cpp" "src/*.c")
|
||||
list(APPEND ${TARGET_NAME}_SRCS ${LIB_SRCS})
|
||||
|
@ -34,19 +34,19 @@ macro(SETUP_HIFI_LIBRARY)
|
|||
set_source_files_properties(${SRC} PROPERTIES COMPILE_FLAGS "-mavx2 -mfma")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
|
||||
setup_memory_debugger()
|
||||
|
||||
# create a library and set the property so it can be referenced later
|
||||
if (${${TARGET_NAME}_SHARED})
|
||||
add_library(${TARGET_NAME} SHARED ${LIB_SRCS} ${AUTOMTC_SRC} ${AUTOSCRIBE_SHADER_LIB_SRC} ${QT_RESOURCES_FILE})
|
||||
add_library(${TARGET_NAME} SHARED ${LIB_SRCS} ${AUTOSCRIBE_SHADER_LIB_SRC} ${QT_RESOURCES_FILE})
|
||||
else ()
|
||||
add_library(${TARGET_NAME} ${LIB_SRCS} ${AUTOMTC_SRC} ${AUTOSCRIBE_SHADER_LIB_SRC} ${QT_RESOURCES_FILE})
|
||||
add_library(${TARGET_NAME} ${LIB_SRCS} ${AUTOSCRIBE_SHADER_LIB_SRC} ${QT_RESOURCES_FILE})
|
||||
endif ()
|
||||
|
||||
|
||||
set(${TARGET_NAME}_DEPENDENCY_QT_MODULES ${ARGN})
|
||||
list(APPEND ${TARGET_NAME}_DEPENDENCY_QT_MODULES Core)
|
||||
|
||||
|
||||
# find these Qt modules and link them to our own target
|
||||
find_package(Qt5 COMPONENTS ${${TARGET_NAME}_DEPENDENCY_QT_MODULES} REQUIRED)
|
||||
|
||||
|
@ -59,7 +59,7 @@ macro(SETUP_HIFI_LIBRARY)
|
|||
set(QT_RESOURCES_FILE "")
|
||||
|
||||
target_glm()
|
||||
|
||||
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Libraries")
|
||||
|
||||
endmacro(SETUP_HIFI_LIBRARY)
|
||||
|
||||
endmacro(SETUP_HIFI_LIBRARY)
|
||||
|
|
|
@ -22,7 +22,7 @@ macro(SETUP_HIFI_PROJECT)
|
|||
endif ()
|
||||
endforeach()
|
||||
|
||||
add_executable(${TARGET_NAME} ${TARGET_SRCS} ${AUTOMTC_SRC} ${AUTOSCRIBE_SHADER_LIB_SRC})
|
||||
add_executable(${TARGET_NAME} ${TARGET_SRCS} ${AUTOSCRIBE_SHADER_LIB_SRC})
|
||||
|
||||
# include the generated application version header
|
||||
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/includes")
|
||||
|
|
12
cmake/macros/TargetGli.cmake
Normal file
|
@ -0,0 +1,12 @@
|
|||
#
|
||||
# Copyright 2015 High Fidelity, Inc.
|
||||
# Created by Bradley Austin Davis on 2015/10/10
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
macro(TARGET_GLI)
|
||||
add_dependency_external_projects(gli)
|
||||
find_package(GLI REQUIRED)
|
||||
target_include_directories(${TARGET_NAME} PUBLIC ${GLI_INCLUDE_DIRS})
|
||||
endmacro()
|
26
cmake/modules/FindGLI.cmake
Normal file
|
@ -0,0 +1,26 @@
|
|||
#
|
||||
# FindGLI.cmake
|
||||
#
|
||||
# Try to find GLI include path.
|
||||
# Once done this will define
|
||||
#
|
||||
# GLI_INCLUDE_DIRS
|
||||
#
|
||||
# Created on 2016/09/03 by Bradley Austin Davis
|
||||
# Copyright 2013-2016 High Fidelity, Inc.
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
# setup hints for GLI search
|
||||
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
||||
hifi_library_search_hints("gli")
|
||||
|
||||
# locate header
|
||||
find_path(GLI_INCLUDE_DIRS "gli/gli.hpp" HINTS ${GLI_SEARCH_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(GLI DEFAULT_MSG GLI_INCLUDE_DIRS)
|
||||
|
||||
mark_as_advanced(GLI_INCLUDE_DIRS GLI_SEARCH_DIRS)
|
|
@ -9,7 +9,12 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#define USE_STABLE_GLOBAL_SERVICES @USE_STABLE_GLOBAL_SERVICES@
|
||||
|
||||
namespace BuildInfo {
|
||||
const QString MODIFIED_ORGANIZATION = "@BUILD_ORGANIZATION@";
|
||||
const QString VERSION = "@BUILD_VERSION@";
|
||||
const QString BUILD_BRANCH = "@BUILD_BRANCH@";
|
||||
const QString BUILD_GLOBAL_SERVICES = "@BUILD_GLOBAL_SERVICES@";
|
||||
}
|
||||
|
||||
|
|
36
cmake/templates/MacOSXBundleSandboxComponentsInfo.plist.in
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleLongVersionString</key>
|
||||
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
<key>LSRequiresCarbon</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -130,6 +130,11 @@ Var AR_RegFlags
|
|||
SectionSetFlags ${${SecName}} $AR_SecFlags
|
||||
|
||||
"default_${SecName}:"
|
||||
; The client is always selected by default
|
||||
${If} ${SecName} == @CLIENT_COMPONENT_NAME@
|
||||
SectionSetFlags ${${SecName}} 17
|
||||
${EndIf}
|
||||
|
||||
!insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected
|
||||
!macroend
|
||||
|
||||
|
@ -243,6 +248,12 @@ FunctionEnd
|
|||
|
||||
;--------------------------------
|
||||
; Installation types
|
||||
|
||||
Section "-Previous Install Cleanup"
|
||||
; Remove the resources folder so we don't end up including removed QML files
|
||||
RMDir /r "$INSTDIR\resources"
|
||||
SectionEnd
|
||||
|
||||
@CPACK_NSIS_INSTALLATION_TYPES@
|
||||
|
||||
;--------------------------------
|
||||
|
@ -589,6 +600,9 @@ Section "-Core installation"
|
|||
Delete "$INSTDIR\version"
|
||||
Delete "$INSTDIR\xinput1_3.dll"
|
||||
|
||||
;Delete old Qt files
|
||||
Delete "$INSTDIR\audio\qtaudio_windows.dll"
|
||||
|
||||
; Delete old desktop shortcuts before they were renamed during Sandbox rename
|
||||
Delete "$DESKTOP\@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@.lnk"
|
||||
Delete "$DESKTOP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
|
||||
|
|
|
@ -9,6 +9,11 @@ endif ()
|
|||
# setup the project and link required Qt modules
|
||||
setup_hifi_project(Network)
|
||||
|
||||
# Fix up the rpath so macdeployqt works
|
||||
if (APPLE)
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES INSTALL_RPATH "@executable_path/../Frameworks")
|
||||
endif ()
|
||||
|
||||
# TODO: find a solution that will handle web file changes in resources on windows without a re-build.
|
||||
# Currently the resources are only copied on post-build. If one is changed but the domain-server is not, they will
|
||||
# not be re-copied. This is worked-around on OS X/UNIX by using a symlink.
|
||||
|
|
|
@ -380,6 +380,14 @@
|
|||
"default": "0",
|
||||
"advanced": false
|
||||
},
|
||||
{
|
||||
"name": "maximum_user_capacity_redirect_location",
|
||||
"label": "Redirect to Location on Maximum Capacity",
|
||||
"help": "Is there another domain, you'd like to redirect clients to when the maximum number of avatars are connected.",
|
||||
"placeholder": "",
|
||||
"default": "",
|
||||
"advanced": false
|
||||
},
|
||||
{
|
||||
"name": "standard_permissions",
|
||||
"type": "table",
|
||||
|
@ -1025,65 +1033,41 @@
|
|||
"name": "dynamic_jitter_buffer",
|
||||
"type": "checkbox",
|
||||
"label": "Dynamic Jitter Buffers",
|
||||
"help": "Dynamically buffer client audio based on perceived jitter in packet receipt timing",
|
||||
"help": "Dynamically buffer inbound audio streams based on perceived jitter in packet receipt timing.",
|
||||
"default": true,
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "static_desired_jitter_buffer_frames",
|
||||
"label": "Static Desired Jitter Buffer Frames",
|
||||
"help": "If dynamic jitter buffers is disabled, this determines the target number of frames maintained by the AudioMixer's jitter buffers",
|
||||
"help": "If dynamic jitter buffers is disabled, this determines the size of the jitter buffers of inbound audio streams in the mixer. Higher numbers introduce more latency.",
|
||||
"placeholder": "1",
|
||||
"default": "1",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "max_frames_over_desired",
|
||||
"label": "Max Frames Over Desired",
|
||||
"help": "The highest number of frames an AudioMixer's ringbuffer can exceed the desired jitter buffer frames by",
|
||||
"placeholder": "10",
|
||||
"default": "10",
|
||||
"advanced": true
|
||||
"name": "max_frames_over_desired",
|
||||
"deprecated": true
|
||||
},
|
||||
{
|
||||
"name": "use_stdev_for_desired_calc",
|
||||
"type": "checkbox",
|
||||
"label": "Stdev for Desired Jitter Frames Calc",
|
||||
"help": "Use Philip's method (stdev of timegaps) to calculate desired jitter frames (otherwise Fred's max timegap method is used)",
|
||||
"default": false,
|
||||
"advanced": true
|
||||
"name": "window_starve_threshold",
|
||||
"deprecated": true
|
||||
},
|
||||
{
|
||||
"name": "window_starve_threshold",
|
||||
"label": "Window Starve Threshold",
|
||||
"help": "If this many starves occur in an N-second window (N is the number in the next field), then the desired jitter frames will be re-evaluated using Window A.",
|
||||
"placeholder": "3",
|
||||
"default": "3",
|
||||
"advanced": true
|
||||
"name": "window_seconds_for_desired_calc_on_too_many_starves",
|
||||
"deprecated": true
|
||||
},
|
||||
{
|
||||
"name": "window_seconds_for_desired_calc_on_too_many_starves",
|
||||
"label": "Timegaps Window (A) Seconds",
|
||||
"help": "Window A contains a history of timegaps. Its max timegap is used to re-evaluate the desired jitter frames when too many starves occur within it.",
|
||||
"placeholder": "50",
|
||||
"default": "50",
|
||||
"advanced": true
|
||||
"name": "window_seconds_for_desired_reduction",
|
||||
"deprecated": true
|
||||
},
|
||||
{
|
||||
"name": "window_seconds_for_desired_reduction",
|
||||
"label": "Timegaps Window (B) Seconds",
|
||||
"help": "Window B contains a history of timegaps. Its max timegap is used as a ceiling for the desired jitter frames value.",
|
||||
"placeholder": "10",
|
||||
"default": "10",
|
||||
"advanced": true
|
||||
"name": "use_stdev_for_desired_calc",
|
||||
"deprecated": true
|
||||
},
|
||||
{
|
||||
"name": "repetition_with_fade",
|
||||
"type": "checkbox",
|
||||
"label": "Repetition with Fade",
|
||||
"help": "Dropped frames and mixing during starves repeat the last frame, eventually fading to silence",
|
||||
"default": false,
|
||||
"advanced": true
|
||||
"name": "repetition_with_fade",
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -75,7 +75,7 @@ span.port {
|
|||
color: #666666;
|
||||
}
|
||||
|
||||
.advanced-setting {
|
||||
.advanced-setting, .deprecated-setting {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,8 @@
|
|||
|
||||
<script id="panels-template" type="text/template">
|
||||
<% _.each(descriptions, function(group){ %>
|
||||
<% split_settings = _.partition(group.settings, function(value, index) { return !value.advanced }) %>
|
||||
<% var settings = _.partition(group.settings, function(value, index) { return !value.deprecated })[0] %>
|
||||
<% split_settings = _.partition(settings, function(value, index) { return !value.advanced }) %>
|
||||
<% isAdvanced = _.isEmpty(split_settings[0]) %>
|
||||
<% if (isAdvanced) { %>
|
||||
<% $("a[href=#" + group.name + "]").addClass('advanced-setting').hide() %>
|
||||
|
|
|
@ -2,6 +2,7 @@ var Settings = {
|
|||
showAdvanced: false,
|
||||
METAVERSE_URL: 'https://metaverse.highfidelity.com',
|
||||
ADVANCED_CLASS: 'advanced-setting',
|
||||
DEPRECATED_CLASS: 'deprecated-setting',
|
||||
TRIGGER_CHANGE_CLASS: 'trigger-change',
|
||||
DATA_ROW_CLASS: 'value-row',
|
||||
DATA_COL_CLASS: 'value-col',
|
||||
|
@ -42,7 +43,10 @@ var Settings = {
|
|||
|
||||
var viewHelpers = {
|
||||
getFormGroup: function(keypath, setting, values, isAdvanced) {
|
||||
form_group = "<div class='form-group " + (isAdvanced ? Settings.ADVANCED_CLASS : "") + "' data-keypath='" + keypath + "'>";
|
||||
form_group = "<div class='form-group " +
|
||||
(isAdvanced ? Settings.ADVANCED_CLASS : "") + " " +
|
||||
(setting.deprecated ? Settings.DEPRECATED_CLASS : "" ) + "' " +
|
||||
"data-keypath='" + keypath + "'>";
|
||||
setting_value = _(values).valueForKeyPath(keypath);
|
||||
|
||||
if (_.isUndefined(setting_value) || _.isNull(setting_value)) {
|
||||
|
@ -454,7 +458,7 @@ function setupHFAccountButton() {
|
|||
}
|
||||
|
||||
// use the existing getFormGroup helper to ask for a button
|
||||
var buttonGroup = viewHelpers.getFormGroup('', buttonSetting, Settings.data.values, false);
|
||||
var buttonGroup = viewHelpers.getFormGroup('', buttonSetting, Settings.data.values);
|
||||
|
||||
// add the button group to the top of the metaverse panel
|
||||
$('#metaverse .panel-body').prepend(buttonGroup);
|
||||
|
@ -665,7 +669,7 @@ function setupPlacesTable() {
|
|||
}
|
||||
|
||||
// get a table for the places
|
||||
var placesTableGroup = viewHelpers.getFormGroup('', placesTableSetting, Settings.data.values, false);
|
||||
var placesTableGroup = viewHelpers.getFormGroup('', placesTableSetting, Settings.data.values);
|
||||
|
||||
// append the places table in the right place
|
||||
$('#places_paths .panel-body').prepend(placesTableGroup);
|
||||
|
|
|
@ -317,6 +317,7 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo
|
|||
}
|
||||
|
||||
const QString MAXIMUM_USER_CAPACITY = "security.maximum_user_capacity";
|
||||
const QString MAXIMUM_USER_CAPACITY_REDIRECT_LOCATION = "security.maximum_user_capacity_redirect_location";
|
||||
|
||||
SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnectionData& nodeConnection,
|
||||
const QString& username,
|
||||
|
@ -363,7 +364,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
|
|||
|
||||
if (!userPerms.can(NodePermissions::Permission::canConnectToDomain)) {
|
||||
sendConnectionDeniedPacket("You lack the required permissions to connect to this domain.",
|
||||
nodeConnection.senderSockAddr, DomainHandler::ConnectionRefusedReason::TooManyUsers);
|
||||
nodeConnection.senderSockAddr, DomainHandler::ConnectionRefusedReason::NotAuthorized);
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "stalling login due to permissions:" << username;
|
||||
#endif
|
||||
|
@ -372,8 +373,16 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
|
|||
|
||||
if (!userPerms.can(NodePermissions::Permission::canConnectPastMaxCapacity) && !isWithinMaxCapacity()) {
|
||||
// we can't allow this user to connect because we are at max capacity
|
||||
QString redirectOnMaxCapacity;
|
||||
const QVariant* redirectOnMaxCapacityVariant =
|
||||
valueForKeyPath(_server->_settingsManager.getSettingsMap(), MAXIMUM_USER_CAPACITY_REDIRECT_LOCATION);
|
||||
if (redirectOnMaxCapacityVariant && redirectOnMaxCapacityVariant->canConvert<QString>()) {
|
||||
redirectOnMaxCapacity = redirectOnMaxCapacityVariant->toString();
|
||||
qDebug() << "Redirection domain:" << redirectOnMaxCapacity;
|
||||
}
|
||||
|
||||
sendConnectionDeniedPacket("Too many connected users.", nodeConnection.senderSockAddr,
|
||||
DomainHandler::ConnectionRefusedReason::TooManyUsers);
|
||||
DomainHandler::ConnectionRefusedReason::TooManyUsers, redirectOnMaxCapacity);
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "stalling login due to max capacity:" << username;
|
||||
#endif
|
||||
|
@ -623,22 +632,30 @@ void DomainGatekeeper::sendProtocolMismatchConnectionDenial(const HifiSockAddr&
|
|||
}
|
||||
|
||||
void DomainGatekeeper::sendConnectionDeniedPacket(const QString& reason, const HifiSockAddr& senderSockAddr,
|
||||
DomainHandler::ConnectionRefusedReason reasonCode) {
|
||||
DomainHandler::ConnectionRefusedReason reasonCode,
|
||||
QString extraInfo) {
|
||||
// this is an agent and we've decided we won't let them connect - send them a packet to deny connection
|
||||
QByteArray utfString = reason.toUtf8();
|
||||
quint16 payloadSize = utfString.size();
|
||||
QByteArray utfReasonString = reason.toUtf8();
|
||||
quint16 reasonSize = utfReasonString.size();
|
||||
|
||||
QByteArray utfExtraInfo = extraInfo.toUtf8();
|
||||
quint16 extraInfoSize = utfExtraInfo.size();
|
||||
|
||||
// setup the DomainConnectionDenied packet
|
||||
auto connectionDeniedPacket = NLPacket::create(PacketType::DomainConnectionDenied,
|
||||
payloadSize + sizeof(payloadSize) + sizeof(uint8_t));
|
||||
sizeof(uint8_t) + // reasonCode
|
||||
reasonSize + sizeof(reasonSize) +
|
||||
extraInfoSize + sizeof(extraInfoSize));
|
||||
|
||||
// pack in the reason the connection was denied (the client displays this)
|
||||
if (payloadSize > 0) {
|
||||
uint8_t reasonCodeWire = (uint8_t)reasonCode;
|
||||
connectionDeniedPacket->writePrimitive(reasonCodeWire);
|
||||
connectionDeniedPacket->writePrimitive(payloadSize);
|
||||
connectionDeniedPacket->write(utfString);
|
||||
}
|
||||
uint8_t reasonCodeWire = (uint8_t)reasonCode;
|
||||
connectionDeniedPacket->writePrimitive(reasonCodeWire);
|
||||
connectionDeniedPacket->writePrimitive(reasonSize);
|
||||
connectionDeniedPacket->write(utfReasonString);
|
||||
|
||||
// write the extra info as well
|
||||
connectionDeniedPacket->writePrimitive(extraInfoSize);
|
||||
connectionDeniedPacket->write(utfExtraInfo);
|
||||
|
||||
// send the packet off
|
||||
DependencyManager::get<LimitedNodeList>()->sendPacket(std::move(connectionDeniedPacket), senderSockAddr);
|
||||
|
|
|
@ -88,7 +88,8 @@ private:
|
|||
|
||||
void sendConnectionTokenPacket(const QString& username, const HifiSockAddr& senderSockAddr);
|
||||
static void sendConnectionDeniedPacket(const QString& reason, const HifiSockAddr& senderSockAddr,
|
||||
DomainHandler::ConnectionRefusedReason reasonCode = DomainHandler::ConnectionRefusedReason::Unknown);
|
||||
DomainHandler::ConnectionRefusedReason reasonCode = DomainHandler::ConnectionRefusedReason::Unknown,
|
||||
QString extraInfo = QString());
|
||||
|
||||
void pingPunchForConnectingPeer(const SharedNetworkPeer& peer);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <QStandardPaths>
|
||||
#include <QTimer>
|
||||
#include <QUrlQuery>
|
||||
#include <QCommandLineParser>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <BuildInfo.h>
|
||||
|
@ -45,7 +46,11 @@
|
|||
|
||||
int const DomainServer::EXIT_CODE_REBOOT = 234923;
|
||||
|
||||
#if USE_STABLE_GLOBAL_SERVICES
|
||||
const QString ICE_SERVER_DEFAULT_HOSTNAME = "ice.highfidelity.com";
|
||||
#else
|
||||
const QString ICE_SERVER_DEFAULT_HOSTNAME = "dev-ice.highfidelity.com";
|
||||
#endif
|
||||
|
||||
DomainServer::DomainServer(int argc, char* argv[]) :
|
||||
QCoreApplication(argc, argv),
|
||||
|
@ -62,8 +67,11 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
_webAuthenticationStateSet(),
|
||||
_cookieSessionHash(),
|
||||
_automaticNetworkingSetting(),
|
||||
_settingsManager()
|
||||
_settingsManager(),
|
||||
_iceServerAddr(ICE_SERVER_DEFAULT_HOSTNAME),
|
||||
_iceServerPort(ICE_SERVER_DEFAULT_PORT)
|
||||
{
|
||||
parseCommandLine();
|
||||
qInstallMessageHandler(LogHandler::verboseMessageHandler);
|
||||
|
||||
LogUtils::init();
|
||||
|
@ -79,6 +87,14 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
|
||||
qDebug() << "Setting up domain-server";
|
||||
|
||||
qDebug() << "[VERSION] Build sequence:" << qPrintable(applicationVersion());
|
||||
qDebug() << "[VERSION] MODIFIED_ORGANIZATION:" << BuildInfo::MODIFIED_ORGANIZATION;
|
||||
qDebug() << "[VERSION] VERSION:" << BuildInfo::VERSION;
|
||||
qDebug() << "[VERSION] BUILD_BRANCH:" << BuildInfo::BUILD_BRANCH;
|
||||
qDebug() << "[VERSION] BUILD_GLOBAL_SERVICES:" << BuildInfo::BUILD_GLOBAL_SERVICES;
|
||||
qDebug() << "[VERSION] We will be using this default ICE server:" << ICE_SERVER_DEFAULT_HOSTNAME;
|
||||
|
||||
|
||||
// make sure we have a fresh AccountManager instance
|
||||
// (need this since domain-server can restart itself and maintain static variables)
|
||||
DependencyManager::set<AccountManager>();
|
||||
|
@ -147,6 +163,53 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
qDebug() << "domain-server is running";
|
||||
}
|
||||
|
||||
void DomainServer::parseCommandLine() {
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("High Fidelity Domain Server");
|
||||
parser.addHelpOption();
|
||||
|
||||
const QCommandLineOption iceServerAddressOption("i", "ice-server address", "IP:PORT or HOSTNAME:PORT");
|
||||
parser.addOption(iceServerAddressOption);
|
||||
|
||||
const QCommandLineOption domainIDOption("d", "domain-server uuid");
|
||||
parser.addOption(domainIDOption);
|
||||
|
||||
const QCommandLineOption getTempNameOption("get-temp-name", "Request a temporary domain-name");
|
||||
parser.addOption(getTempNameOption);
|
||||
|
||||
const QCommandLineOption masterConfigOption("master-config", "Deprecated config-file option");
|
||||
parser.addOption(masterConfigOption);
|
||||
|
||||
|
||||
if (!parser.parse(QCoreApplication::arguments())) {
|
||||
qWarning() << parser.errorText() << endl;
|
||||
parser.showHelp();
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
if (parser.isSet(iceServerAddressOption)) {
|
||||
// parse the IP and port combination for this target
|
||||
QString hostnamePortString = parser.value(iceServerAddressOption);
|
||||
|
||||
_iceServerAddr = hostnamePortString.left(hostnamePortString.indexOf(':'));
|
||||
_iceServerPort = (quint16) hostnamePortString.mid(hostnamePortString.indexOf(':') + 1).toUInt();
|
||||
if (_iceServerPort == 0) {
|
||||
_iceServerPort = ICE_SERVER_DEFAULT_PORT;
|
||||
}
|
||||
|
||||
if (_iceServerAddr.isEmpty()) {
|
||||
qWarning() << "Could not parse an IP address and port combination from" << hostnamePortString;
|
||||
QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
if (parser.isSet(domainIDOption)) {
|
||||
_overridingDomainID = QUuid(parser.value(domainIDOption));
|
||||
_overrideDomainID = true;
|
||||
qDebug() << "domain-server ID is" << _overridingDomainID;
|
||||
}
|
||||
}
|
||||
|
||||
DomainServer::~DomainServer() {
|
||||
// destroy the LimitedNodeList before the DomainServer QCoreApplication is down
|
||||
DependencyManager::destroy<LimitedNodeList>();
|
||||
|
@ -154,7 +217,7 @@ DomainServer::~DomainServer() {
|
|||
|
||||
void DomainServer::queuedQuit(QString quitMessage, int exitCode) {
|
||||
if (!quitMessage.isEmpty()) {
|
||||
qCritical() << qPrintable(quitMessage);
|
||||
qWarning() << qPrintable(quitMessage);
|
||||
}
|
||||
|
||||
QCoreApplication::exit(exitCode);
|
||||
|
@ -295,7 +358,7 @@ void DomainServer::handleTempDomainSuccess(QNetworkReply& requestReply) {
|
|||
|
||||
auto domainObject = jsonObject[DATA_KEY].toObject()[DOMAIN_KEY].toObject();
|
||||
if (!domainObject.isEmpty()) {
|
||||
auto id = domainObject[ID_KEY].toString();
|
||||
auto id = _overrideDomainID ? _overridingDomainID.toString() : domainObject[ID_KEY].toString();
|
||||
auto name = domainObject[NAME_KEY].toString();
|
||||
auto key = domainObject[KEY_KEY].toString();
|
||||
|
||||
|
@ -368,11 +431,11 @@ void DomainServer::setupNodeListAndAssignments() {
|
|||
const QString CUSTOM_LOCAL_PORT_OPTION = "metaverse.local_port";
|
||||
|
||||
QVariant localPortValue = _settingsManager.valueOrDefaultValueForKeyPath(CUSTOM_LOCAL_PORT_OPTION);
|
||||
unsigned short domainServerPort = (unsigned short) localPortValue.toUInt();
|
||||
int domainServerPort = localPortValue.toInt();
|
||||
|
||||
QVariantMap& settingsMap = _settingsManager.getSettingsMap();
|
||||
|
||||
unsigned short domainServerDTLSPort = 0;
|
||||
int domainServerDTLSPort = INVALID_PORT;
|
||||
|
||||
if (_isUsingDTLS) {
|
||||
domainServerDTLSPort = DEFAULT_DOMAIN_SERVER_DTLS_PORT;
|
||||
|
@ -403,24 +466,30 @@ void DomainServer::setupNodeListAndAssignments() {
|
|||
quint16 localHttpsPort = DOMAIN_SERVER_HTTPS_PORT;
|
||||
nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_HTTPS_PORT_SMEM_KEY, this, localHttpsPort);
|
||||
|
||||
|
||||
// set our LimitedNodeList UUID to match the UUID from our config
|
||||
// nodes will currently use this to add resources to data-web that relate to our domain
|
||||
const QVariant* idValueVariant = valueForKeyPath(settingsMap, METAVERSE_DOMAIN_ID_KEY_PATH);
|
||||
if (idValueVariant) {
|
||||
nodeList->setSessionUUID(idValueVariant->toString());
|
||||
bool isMetaverseDomain = false;
|
||||
if (_overrideDomainID) {
|
||||
nodeList->setSessionUUID(_overridingDomainID);
|
||||
isMetaverseDomain = true; // assume metaverse domain
|
||||
} else {
|
||||
const QVariant* idValueVariant = valueForKeyPath(settingsMap, METAVERSE_DOMAIN_ID_KEY_PATH);
|
||||
if (idValueVariant) {
|
||||
nodeList->setSessionUUID(idValueVariant->toString());
|
||||
isMetaverseDomain = true; // if we have an ID, we'll assume we're a metaverse domain
|
||||
} else {
|
||||
nodeList->setSessionUUID(QUuid::createUuid()); // Use random UUID
|
||||
}
|
||||
}
|
||||
|
||||
// if we have an ID, we'll assume we're a metaverse domain
|
||||
// now see if we think we're a temp domain (we have an API key) or a full domain
|
||||
if (isMetaverseDomain) {
|
||||
// see if we think we're a temp domain (we have an API key) or a full domain
|
||||
const auto& temporaryDomainKey = DependencyManager::get<AccountManager>()->getTemporaryDomainKey(getID());
|
||||
if (temporaryDomainKey.isEmpty()) {
|
||||
_type = MetaverseDomain;
|
||||
} else {
|
||||
_type = MetaverseTemporaryDomain;
|
||||
}
|
||||
|
||||
} else {
|
||||
nodeList->setSessionUUID(QUuid::createUuid()); // Use random UUID
|
||||
}
|
||||
|
||||
connect(nodeList.data(), &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded);
|
||||
|
@ -536,7 +605,6 @@ void DomainServer::setupAutomaticNetworking() {
|
|||
} else {
|
||||
qDebug() << "Cannot enable domain-server automatic networking without a domain ID."
|
||||
<< "Please add an ID to your config file or via the web interface.";
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -594,12 +662,11 @@ void DomainServer::setupICEHeartbeatForFullNetworking() {
|
|||
|
||||
void DomainServer::updateICEServerAddresses() {
|
||||
if (_iceAddressLookupID == -1) {
|
||||
_iceAddressLookupID = QHostInfo::lookupHost(ICE_SERVER_DEFAULT_HOSTNAME, this, SLOT(handleICEHostInfo(QHostInfo)));
|
||||
_iceAddressLookupID = QHostInfo::lookupHost(_iceServerAddr, this, SLOT(handleICEHostInfo(QHostInfo)));
|
||||
}
|
||||
}
|
||||
|
||||
void DomainServer::parseAssignmentConfigs(QSet<Assignment::Type>& excludedTypes) {
|
||||
// check for configs from the command line, these take precedence
|
||||
const QString ASSIGNMENT_CONFIG_REGEX_STRING = "config-([\\d]+)";
|
||||
QRegExp assignmentConfigRegex(ASSIGNMENT_CONFIG_REGEX_STRING);
|
||||
|
||||
|
@ -1211,41 +1278,43 @@ void DomainServer::handleMetaverseHeartbeatError(QNetworkReply& requestReply) {
|
|||
}
|
||||
|
||||
void DomainServer::sendICEServerAddressToMetaverseAPI() {
|
||||
if (!_iceServerSocket.isNull()) {
|
||||
const QString ICE_SERVER_ADDRESS = "ice_server_address";
|
||||
const QString ICE_SERVER_ADDRESS = "ice_server_address";
|
||||
|
||||
QJsonObject domainObject;
|
||||
QJsonObject domainObject;
|
||||
|
||||
if (!_connectedToICEServer || _iceServerSocket.isNull()) {
|
||||
domainObject[ICE_SERVER_ADDRESS] = "0.0.0.0";
|
||||
} else {
|
||||
// we're using full automatic networking and we have a current ice-server socket, use that now
|
||||
domainObject[ICE_SERVER_ADDRESS] = _iceServerSocket.getAddress().toString();
|
||||
|
||||
const auto& temporaryDomainKey = DependencyManager::get<AccountManager>()->getTemporaryDomainKey(getID());
|
||||
if (!temporaryDomainKey.isEmpty()) {
|
||||
// add the temporary domain token
|
||||
const QString KEY_KEY = "api_key";
|
||||
domainObject[KEY_KEY] = temporaryDomainKey;
|
||||
}
|
||||
|
||||
QString domainUpdateJSON = QString("{\"domain\": %1 }").arg(QString(QJsonDocument(domainObject).toJson()));
|
||||
|
||||
// make sure we hear about failure so we can retry
|
||||
JSONCallbackParameters callbackParameters;
|
||||
callbackParameters.errorCallbackReceiver = this;
|
||||
callbackParameters.errorCallbackMethod = "handleFailedICEServerAddressUpdate";
|
||||
|
||||
static QString repeatedMessage = LogHandler::getInstance().addOnlyOnceMessageRegex
|
||||
("Updating ice-server address in High Fidelity Metaverse API to [^ \n]+");
|
||||
qDebug() << "Updating ice-server address in High Fidelity Metaverse API to"
|
||||
<< _iceServerSocket.getAddress().toString();
|
||||
|
||||
static const QString DOMAIN_ICE_ADDRESS_UPDATE = "/api/v1/domains/%1/ice_server_address";
|
||||
|
||||
DependencyManager::get<AccountManager>()->sendRequest(DOMAIN_ICE_ADDRESS_UPDATE.arg(uuidStringWithoutCurlyBraces(getID())),
|
||||
AccountManagerAuth::Optional,
|
||||
QNetworkAccessManager::PutOperation,
|
||||
callbackParameters,
|
||||
domainUpdateJSON.toUtf8());
|
||||
}
|
||||
|
||||
const auto& temporaryDomainKey = DependencyManager::get<AccountManager>()->getTemporaryDomainKey(getID());
|
||||
if (!temporaryDomainKey.isEmpty()) {
|
||||
// add the temporary domain token
|
||||
const QString KEY_KEY = "api_key";
|
||||
domainObject[KEY_KEY] = temporaryDomainKey;
|
||||
}
|
||||
|
||||
QString domainUpdateJSON = QString("{\"domain\": %1 }").arg(QString(QJsonDocument(domainObject).toJson()));
|
||||
|
||||
// make sure we hear about failure so we can retry
|
||||
JSONCallbackParameters callbackParameters;
|
||||
callbackParameters.errorCallbackReceiver = this;
|
||||
callbackParameters.errorCallbackMethod = "handleFailedICEServerAddressUpdate";
|
||||
|
||||
static QString repeatedMessage = LogHandler::getInstance().addOnlyOnceMessageRegex
|
||||
("Updating ice-server address in High Fidelity Metaverse API to [^ \n]+");
|
||||
qDebug() << "Updating ice-server address in High Fidelity Metaverse API to"
|
||||
<< (_iceServerSocket.isNull() ? "" : _iceServerSocket.getAddress().toString());
|
||||
|
||||
static const QString DOMAIN_ICE_ADDRESS_UPDATE = "/api/v1/domains/%1/ice_server_address";
|
||||
|
||||
DependencyManager::get<AccountManager>()->sendRequest(DOMAIN_ICE_ADDRESS_UPDATE.arg(uuidStringWithoutCurlyBraces(getID())),
|
||||
AccountManagerAuth::Optional,
|
||||
QNetworkAccessManager::PutOperation,
|
||||
callbackParameters,
|
||||
domainUpdateJSON.toUtf8());
|
||||
}
|
||||
|
||||
void DomainServer::handleFailedICEServerAddressUpdate(QNetworkReply& requestReply) {
|
||||
|
@ -1297,6 +1366,7 @@ void DomainServer::sendHeartbeatToIceServer() {
|
|||
|
||||
// reset the connection flag for ICE server
|
||||
_connectedToICEServer = false;
|
||||
sendICEServerAddressToMetaverseAPI();
|
||||
|
||||
// randomize our ice-server address (and simultaneously look up any new hostnames for available ice-servers)
|
||||
randomizeICEServerAddress(true);
|
||||
|
@ -1756,6 +1826,7 @@ bool DomainServer::handleHTTPSRequest(HTTPSConnection* connection, const QUrl &u
|
|||
.arg(authorizationCode, oauthRedirectURL().toString(), _oauthClientID, _oauthClientSecret);
|
||||
|
||||
QNetworkRequest tokenRequest(tokenRequestUrl);
|
||||
tokenRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
tokenRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||
tokenRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
|
||||
|
@ -1949,6 +2020,7 @@ QNetworkReply* DomainServer::profileRequestGivenTokenReply(QNetworkReply* tokenR
|
|||
profileURL.setQuery(QString("%1=%2").arg(OAUTH_JSON_ACCESS_TOKEN_KEY, accessToken));
|
||||
|
||||
QNetworkRequest profileRequest(profileURL);
|
||||
profileRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
profileRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||
return NetworkAccessManager::getInstance().get(profileRequest);
|
||||
}
|
||||
|
@ -2267,6 +2339,7 @@ void DomainServer::processICEServerHeartbeatACK(QSharedPointer<ReceivedMessage>
|
|||
|
||||
if (!_connectedToICEServer) {
|
||||
_connectedToICEServer = true;
|
||||
sendICEServerAddressToMetaverseAPI();
|
||||
qInfo() << "Connected to ice-server at" << _iceServerSocket;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,6 +105,7 @@ signals:
|
|||
|
||||
private:
|
||||
const QUuid& getID();
|
||||
void parseCommandLine();
|
||||
|
||||
void setupNodeListAndAssignments();
|
||||
bool optionallySetupOAuth();
|
||||
|
@ -205,6 +206,11 @@ private:
|
|||
|
||||
friend class DomainGatekeeper;
|
||||
friend class DomainMetadata;
|
||||
|
||||
QString _iceServerAddr;
|
||||
int _iceServerPort;
|
||||
bool _overrideDomainID { false }; // should we override the domain-id from settings?
|
||||
QUuid _overridingDomainID { QUuid() }; // what should we override it with?
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ set(TARGET_NAME gvr-interface)
|
|||
if (ANDROID)
|
||||
set(ANDROID_APK_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/apk-build")
|
||||
set(ANDROID_APK_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/apk")
|
||||
|
||||
|
||||
set(ANDROID_SDK_ROOT $ENV{ANDROID_HOME})
|
||||
set(ANDROID_APP_DISPLAY_NAME Interface)
|
||||
set(ANDROID_API_LEVEL 19)
|
||||
|
@ -13,10 +13,10 @@ if (ANDROID)
|
|||
set(ANDROID_APK_VERSION_CODE 1)
|
||||
set(ANDROID_APK_FULLSCREEN TRUE)
|
||||
set(ANDROID_DEPLOY_QT_INSTALL "--install")
|
||||
|
||||
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${ANDROID_APK_OUTPUT_DIR}/libs/${ANDROID_ABI}")
|
||||
|
||||
|
||||
setup_hifi_library(Gui Widgets AndroidExtras)
|
||||
else ()
|
||||
setup_hifi_project(Gui Widgets)
|
||||
|
@ -28,12 +28,12 @@ link_hifi_libraries(shared networking audio-client avatars)
|
|||
|
||||
if (ANDROID)
|
||||
find_package(LibOVR)
|
||||
|
||||
|
||||
if (LIBOVR_FOUND)
|
||||
add_definitions(-DHAVE_LIBOVR)
|
||||
target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES} ${LIBOVR_ANDROID_LIBRARIES} ${TURBOJPEG_LIBRARY})
|
||||
include_directories(SYSTEM ${LIBOVR_INCLUDE_DIRS})
|
||||
|
||||
|
||||
# we need VRLib, so add a project.properties to our apk build folder that says that
|
||||
file(RELATIVE_PATH RELATIVE_VRLIB_PATH ${ANDROID_APK_OUTPUT_DIR} "${LIBOVR_VRLIB_DIR}")
|
||||
file(WRITE "${ANDROID_APK_BUILD_DIR}/project.properties" "android.library.reference.1=${RELATIVE_VRLIB_PATH}")
|
||||
|
@ -50,7 +50,7 @@ if (ANDROID AND HOCKEY_APP_ID)
|
|||
set(ANDROID_ACTIVITY_NAME io.highfidelity.gvrinterface.InterfaceBetaActivity)
|
||||
set(ANDROID_DEPLOY_QT_INSTALL "")
|
||||
set(ANDROID_APK_CUSTOM_NAME "Interface-beta.apk")
|
||||
|
||||
|
||||
# set the ANDROID_APK_VERSION_CODE to the number of git commits
|
||||
execute_process(
|
||||
COMMAND git rev-list --first-parent --count HEAD
|
||||
|
@ -58,16 +58,16 @@ if (ANDROID AND HOCKEY_APP_ID)
|
|||
OUTPUT_VARIABLE GIT_COMMIT_COUNT
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
|
||||
set(ANDROID_APK_VERSION_CODE ${GIT_COMMIT_COUNT})
|
||||
|
||||
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/templates/InterfaceBetaActivity.java.in" "${ANDROID_APK_BUILD_DIR}/src/io/highfidelity/gvrinterface/InterfaceBetaActivity.java")
|
||||
elseif (ANDROID)
|
||||
set(HOCKEY_APP_ENABLED false)
|
||||
endif ()
|
||||
|
||||
if (ANDROID)
|
||||
|
||||
|
||||
set(HIFI_URL_INTENT "<intent-filter>\
|
||||
\n <action android:name='android.intent.action.VIEW' />\
|
||||
\n <category android:name='android.intent.category.DEFAULT' />\
|
||||
|
@ -75,13 +75,11 @@ if (ANDROID)
|
|||
\n <data android:scheme='hifi' />\
|
||||
\n </intent-filter>"
|
||||
)
|
||||
|
||||
|
||||
set(ANDROID_EXTRA_APPLICATION_XML "${HOCKEY_APP_ACTIVITY}")
|
||||
set(ANDROID_EXTRA_ACTIVITY_XML "${HIFI_URL_INTENT}")
|
||||
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/templates/hockeyapp.xml.in" "${ANDROID_APK_BUILD_DIR}/res/values/hockeyapp.xml")
|
||||
qt_create_apk()
|
||||
|
||||
endif (ANDROID)
|
||||
|
||||
copy_dlls_beside_windows_executable()
|
||||
endif (ANDROID)
|
||||
|
|
|
@ -213,6 +213,7 @@ void IceServer::requestDomainPublicKey(const QUuid& domainID) {
|
|||
publicKeyURL.setPath(publicKeyPath);
|
||||
|
||||
QNetworkRequest publicKeyRequest { publicKeyURL };
|
||||
publicKeyRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
publicKeyRequest.setAttribute(QNetworkRequest::User, domainID);
|
||||
|
||||
qDebug() << "Requesting public key for domain with ID" << domainID;
|
||||
|
|
|
@ -39,9 +39,18 @@ else ()
|
|||
list(REMOVE_ITEM INTERFACE_SRCS ${SPEECHRECOGNIZER_CPP})
|
||||
endif ()
|
||||
|
||||
find_package(Qt5 COMPONENTS
|
||||
Gui Multimedia Network OpenGL Qml Quick Script ScriptTools Svg
|
||||
WebChannel WebEngine WebEngineWidgets WebKitWidgets WebSockets)
|
||||
if (ANDROID)
|
||||
set(PLATFORM_QT_COMPONENTS AndroidExtras)
|
||||
else ()
|
||||
set(PLATFORM_QT_COMPONENTS WebEngine WebEngineWidgets)
|
||||
endif ()
|
||||
|
||||
find_package(
|
||||
Qt5 COMPONENTS
|
||||
Gui Multimedia Network OpenGL Qml Quick Script Svg
|
||||
${PLATFORM_QT_COMPONENTS}
|
||||
WebChannel WebSockets
|
||||
)
|
||||
|
||||
# grab the ui files in resources/ui
|
||||
file (GLOB_RECURSE QT_UI_FILES ui/*.ui)
|
||||
|
@ -57,6 +66,26 @@ set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}")
|
|||
# set(TS ${TARGET_NAME}_en.ts)
|
||||
# qt5_create_translation_custom(${QM} ${INTERFACE_SRCS} ${QT_UI_FILES} ${TS})
|
||||
|
||||
# setup the android parameters that will help us produce an APK
|
||||
if (ANDROID)
|
||||
set(ANDROID_APK_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/apk-build")
|
||||
set(ANDROID_APK_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/apk")
|
||||
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${ANDROID_APK_OUTPUT_DIR}/libs/${ANDROID_ABI}")
|
||||
|
||||
set(ANDROID_SDK_ROOT $ENV{ANDROID_HOME})
|
||||
set(ANDROID_APP_DISPLAY_NAME Interface)
|
||||
set(ANDROID_API_LEVEL 19)
|
||||
set(ANDROID_APK_PACKAGE io.highfidelity.interface)
|
||||
set(ANDROID_ACTIVITY_NAME io.highfidelity.interface.InterfaceActivity)
|
||||
set(ANDROID_APK_VERSION_NAME "0.1")
|
||||
set(ANDROID_APK_VERSION_CODE 1)
|
||||
set(ANDROID_APK_FULLSCREEN TRUE)
|
||||
set(ANDROID_DEPLOY_QT_INSTALL "--install")
|
||||
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
endif ()
|
||||
|
||||
if (APPLE)
|
||||
|
||||
# configure CMake to use a custom Info.plist
|
||||
|
@ -94,8 +123,9 @@ if (APPLE)
|
|||
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM})
|
||||
|
||||
# make sure the output name for the .app bundle is correct
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${INTERFACE_BUNDLE_NAME})
|
||||
elseif(WIN32)
|
||||
# Fix up the rpath so macdeployqt works
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES INSTALL_RPATH "@executable_path/../Frameworks")
|
||||
elseif (WIN32)
|
||||
# configure an rc file for the chosen icon
|
||||
set(CONFIGURE_ICON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/icon/${INTERFACE_ICON_FILENAME}")
|
||||
set(CONFIGURE_ICON_RC_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Icon.rc")
|
||||
|
@ -104,7 +134,7 @@ elseif(WIN32)
|
|||
# add an executable that also has the icon itself and the configured rc file as resources
|
||||
add_executable(${TARGET_NAME} WIN32 ${INTERFACE_SRCS} ${QM} ${CONFIGURE_ICON_RC_OUTPUT})
|
||||
|
||||
if ( NOT DEV_BUILD )
|
||||
if (NOT DEV_BUILD)
|
||||
add_custom_command(
|
||||
TARGET ${TARGET_NAME}
|
||||
POST_BUILD
|
||||
|
@ -113,9 +143,12 @@ elseif(WIN32)
|
|||
)
|
||||
endif()
|
||||
|
||||
else()
|
||||
elseif (ANDROID)
|
||||
# on android the Interface target is a library that gets linked/used by the APK shell that qtcreateapk produces
|
||||
add_library(${TARGET_NAME} ${INTERFACE_SRCS} ${QM})
|
||||
else ()
|
||||
add_executable(${TARGET_NAME} ${INTERFACE_SRCS} ${QM})
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/includes")
|
||||
|
||||
|
@ -126,6 +159,7 @@ if (WIN32)
|
|||
add_dependency_external_projects(sdl2)
|
||||
add_dependency_external_projects(OpenVR)
|
||||
add_dependency_external_projects(neuron)
|
||||
add_dependency_external_projects(wasapi)
|
||||
endif()
|
||||
|
||||
# disable /OPT:REF and /OPT:ICF for the Debug builds
|
||||
|
@ -135,21 +169,32 @@ if (WIN32)
|
|||
set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG "/OPT:NOREF /OPT:NOICF")
|
||||
endif()
|
||||
|
||||
if (NOT ANDROID)
|
||||
set(NON_ANDROID_LIBRARIES steamworks-wrapper)
|
||||
endif ()
|
||||
|
||||
# link required hifi libraries
|
||||
link_hifi_libraries(shared octree gpu gl gpu-gl procedural model render
|
||||
recording fbx networking model-networking entities avatars
|
||||
audio audio-client animation script-engine physics
|
||||
render-utils entities-renderer ui auto-updater
|
||||
controllers plugins ui-plugins display-plugins input-plugins steamworks-wrapper)
|
||||
link_hifi_libraries(
|
||||
shared octree gpu gl gpu-gl procedural model render
|
||||
recording fbx networking model-networking entities avatars
|
||||
audio audio-client animation script-engine physics
|
||||
render-utils entities-renderer ui auto-updater
|
||||
controllers plugins
|
||||
ui-plugins display-plugins input-plugins
|
||||
${NON_ANDROID_LIBRARIES}
|
||||
)
|
||||
|
||||
# include the binary directory of render-utils for shader includes
|
||||
target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/libraries/render-utils")
|
||||
|
||||
#fixme find a way to express faceshift as a plugin
|
||||
target_bullet()
|
||||
target_glew()
|
||||
target_opengl()
|
||||
|
||||
if (NOT ANDROID)
|
||||
target_glew()
|
||||
endif ()
|
||||
|
||||
if (WIN32 OR APPLE)
|
||||
target_faceshift()
|
||||
endif()
|
||||
|
@ -198,16 +243,10 @@ include_directories("${PROJECT_SOURCE_DIR}/src")
|
|||
target_link_libraries(
|
||||
${TARGET_NAME}
|
||||
Qt5::Gui Qt5::Network Qt5::Multimedia Qt5::OpenGL
|
||||
Qt5::Qml Qt5::Quick Qt5::Script Qt5::ScriptTools Qt5::Svg
|
||||
Qt5::WebChannel Qt5::WebEngine Qt5::WebEngineWidgets Qt5::WebKitWidgets
|
||||
Qt5::Qml Qt5::Quick Qt5::Script Qt5::Svg
|
||||
Qt5::WebChannel Qt5::WebEngine
|
||||
)
|
||||
|
||||
# Issue causes build failure unless we add this directory.
|
||||
# See https://bugreports.qt.io/browse/QTBUG-43351
|
||||
if (WIN32)
|
||||
add_paths_to_fixup_libs(${Qt5_DIR}/../../../plugins/qtwebengine)
|
||||
endif()
|
||||
|
||||
if (UNIX)
|
||||
target_link_libraries(${TARGET_NAME} pthread)
|
||||
endif(UNIX)
|
||||
|
@ -291,3 +330,17 @@ if (WIN32)
|
|||
|
||||
package_libraries_for_deployment()
|
||||
endif()
|
||||
|
||||
if (ANDROID)
|
||||
set(HIFI_URL_INTENT "<intent-filter>\
|
||||
\n <action android:name='android.intent.action.VIEW' />\
|
||||
\n <category android:name='android.intent.category.DEFAULT' />\
|
||||
\n <category android:name='android.intent.category.BROWSABLE' />\
|
||||
\n <data android:scheme='hifi' />\
|
||||
\n </intent-filter>"
|
||||
)
|
||||
|
||||
set(ANDROID_EXTRA_ACTIVITY_XML "${HIFI_URL_INTENT}")
|
||||
|
||||
qt_create_apk()
|
||||
endif ()
|
||||
|
|
43
interface/resources/html/createGlobalEventBridge.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// createGlobalEventBridge.js
|
||||
//
|
||||
// Created by Anthony J. Thibault on 9/7/2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// Stick a EventBridge object in the global namespace.
|
||||
var EventBridge;
|
||||
(function () {
|
||||
// the TempEventBridge class queues up emitWebEvent messages and executes them when the real EventBridge is ready.
|
||||
// Similarly, it holds all scriptEventReceived callbacks, and hooks them up to the real EventBridge.
|
||||
function TempEventBridge() {
|
||||
var self = this;
|
||||
this._callbacks = [];
|
||||
this._messages = [];
|
||||
this.scriptEventReceived = {
|
||||
connect: function (callback) {
|
||||
self._callbacks.push(callback);
|
||||
}
|
||||
};
|
||||
this.emitWebEvent = function (message) {
|
||||
self._messages.push(message);
|
||||
};
|
||||
};
|
||||
|
||||
EventBridge = new TempEventBridge();
|
||||
|
||||
var webChannel = new QWebChannel(qt.webChannelTransport, function (channel) {
|
||||
// replace the TempEventBridge with the real one.
|
||||
var tempEventBridge = EventBridge;
|
||||
EventBridge = channel.objects.eventBridgeWrapper.eventBridge;
|
||||
tempEventBridge._callbacks.forEach(function (callback) {
|
||||
EventBridge.scriptEventReceived.connect(callback);
|
||||
});
|
||||
tempEventBridge._messages.forEach(function (message) {
|
||||
EventBridge.emitWebEvent(message);
|
||||
});
|
||||
});
|
||||
})();
|
41
interface/resources/html/raiseAndLowerKeyboard.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// Created by Anthony Thibault on 2016-09-02
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
// Sends messages over the EventBridge when text input is required.
|
||||
//
|
||||
(function () {
|
||||
var POLL_FREQUENCY = 500; // ms
|
||||
var MAX_WARNINGS = 3;
|
||||
var numWarnings = 0;
|
||||
|
||||
function shouldRaiseKeyboard() {
|
||||
if (document.activeElement.nodeName == "INPUT" || document.activeElement.nodeName == "TEXTAREA") {
|
||||
return true;
|
||||
} else {
|
||||
// check for contenteditable attribute
|
||||
for (var i = 0; i < document.activeElement.attributes.length; i++) {
|
||||
if (document.activeElement.attributes[i].name === "contenteditable" &&
|
||||
document.activeElement.attributes[i].value === "true") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
setInterval(function () {
|
||||
var event = shouldRaiseKeyboard() ? "_RAISE_KEYBOARD" : "_LOWER_KEYBOARD";
|
||||
if (typeof EventBridge != "undefined") {
|
||||
EventBridge.emitWebEvent(event);
|
||||
} else {
|
||||
if (numWarnings < MAX_WARNINGS) {
|
||||
console.log("WARNING: no global EventBridge object found");
|
||||
numWarnings++;
|
||||
}
|
||||
}
|
||||
}, POLL_FREQUENCY);
|
||||
})();
|
|
@ -9,10 +9,10 @@
|
|||
.st1{fill:#E6E7E8;}
|
||||
.st2{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M1428.61,172H11.46c-6.27,0-11.39-5.13-11.39-11.39V49.58c0-6.27,5.13-11.39,11.39-11.39h1417.15
|
||||
c6.27,0,11.39,5.13,11.39,11.39v111.03C1440,166.87,1434.87,172,1428.61,172z"/>
|
||||
<path class="st1" d="M1428.61,165.81H11.46c-6.27,0-11.39-5.13-11.39-11.39V43.39c0-6.27,5.13-11.39,11.39-11.39h1417.15
|
||||
c6.27,0,11.39,5.13,11.39,11.39v111.03C1440,160.68,1434.87,165.81,1428.61,165.81z"/>
|
||||
<path class="st2" d="M1133.24,165.81H417.95c-4.47,0-8.12-3.65-8.12-8.12V40.11c0-4.47,3.65-8.12,8.12-8.12h715.28
|
||||
c4.47,0,8.12,3.65,8.12,8.12v117.57C1141.36,162.15,1137.7,165.81,1133.24,165.81z"/>
|
||||
<path class="st0" d="M1428.6,172H11.5c-6.3,0-11.4-5.1-11.4-11.4v-111c0-6.3,5.1-11.4,11.4-11.4h1417.2c6.3,0,11.4,5.1,11.4,11.4
|
||||
v111C1440,166.9,1434.9,172,1428.6,172z"/>
|
||||
<path class="st1" d="M1428.6,165.8H11.5c-6.3,0-11.4-5.1-11.4-11.4v-111C0.1,37.1,5.2,32,11.5,32h1417.2c6.3,0,11.4,5.1,11.4,11.4
|
||||
v111C1440,160.7,1434.9,165.8,1428.6,165.8z"/>
|
||||
<path class="st2" d="M1429.9,165.8H421.3c-6.3,0-11.5-3.6-11.5-8.1V40.1c0-4.5,5.1-8.1,11.5-8.1h1008.6c6.3,0,11.5,3.7,11.5,8.1
|
||||
v117.6C1441.4,162.1,1436.2,165.8,1429.9,165.8z"/>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
53
interface/resources/images/concurrency.svg
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 32 64" style="enable-background:new 0 0 32 64;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#168DB7;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
.st2{opacity:0.63;fill:#58595B;enable-background:new ;}
|
||||
</style>
|
||||
<circle cx="15.8" cy="48.2" r="14.7"/>
|
||||
<circle class="st0" cx="15.8" cy="47.6" r="14.7"/>
|
||||
<circle cx="16.1" cy="44.9" r="3"/>
|
||||
<path d="M18.2,50.2H14c-1.7,0-3.1,1.5-3.1,3.2V55c1.4,1.1,3.1,1.7,4.9,1.7c2.1,0,4-0.8,5.4-2.1v-1.2C21.3,51.7,19.9,50.2,18.2,50.2z
|
||||
"/>
|
||||
<circle cx="22.9" cy="44.9" r="1.6"/>
|
||||
<path d="M24,47.9h-1.8c-0.4,0-0.8,0.2-1,0.4c0.5,0.3,1,0.7,1.4,1.1c0.5,0.5,0.7,1.2,0.7,1.9c0.1,0.4,0.1,0.8,0.1,1.2v0.3
|
||||
c0.8-1,1.5-2.7,1.8-3.6v-0.1C25.2,48.8,24.6,47.9,24,47.9z"/>
|
||||
<circle cx="9.1" cy="45.2" r="1.6"/>
|
||||
<path d="M8.7,53.2c0-0.3,0-0.6,0-0.9v-0.1c0-0.1,0-0.2,0-0.3s0-0.1,0-0.2c0-0.1,0-0.1,0-0.2c0.1-0.9,0.7-2,1.4-2.5
|
||||
c0.2-0.2,0.4-0.3,0.6-0.4c-0.2-0.2-0.6-0.3-0.9-0.3H8c-0.6,0-1.2,0.8-1.1,1.2v0.1C7.2,50.6,7.9,52.3,8.7,53.2z"/>
|
||||
<circle class="st1" cx="16.1" cy="44.3" r="3"/>
|
||||
<path class="st1" d="M18.2,49.6H14c-1.7,0-3.1,1.5-3.1,3.2v1.6c1.4,1.1,3.1,1.7,4.9,1.7c2.1,0,4-0.8,5.4-2.1v-1.2
|
||||
C21.3,51.1,19.9,49.6,18.2,49.6z"/>
|
||||
<circle class="st1" cx="22.9" cy="44.4" r="1.6"/>
|
||||
<path class="st1" d="M24,47.4h-1.8c-0.4,0-0.8,0.2-1,0.4c0.5,0.3,1,0.7,1.4,1.1c0.5,0.5,0.7,1.2,0.7,1.9c0.1,0.4,0.1,0.8,0.1,1.2
|
||||
v0.3c0.8-1,1.5-2.7,1.8-3.6v-0.1C25.2,48.2,24.6,47.4,24,47.4z"/>
|
||||
<circle class="st1" cx="9.1" cy="44.6" r="1.6"/>
|
||||
<path class="st1" d="M8.7,52.7c0-0.3,0-0.6,0-0.9v-0.1c0-0.1,0-0.2,0-0.3s0-0.1,0-0.2c0-0.1,0-0.1,0-0.2c0.1-0.9,0.7-2,1.4-2.5
|
||||
c0.2-0.2,0.4-0.3,0.6-0.4c-0.2-0.2-0.6-0.3-0.9-0.3H8c-0.6,0-1.2,0.8-1.1,1.2v0.1C7.2,50,7.9,51.7,8.7,52.7z"/>
|
||||
<path d="M15.9,3.4c-7,0-12.7,5.7-12.7,12.7s5.7,12.7,12.7,12.7s12.7-5.7,12.7-12.7S22.9,3.4,15.9,3.4z M15.9,27.2
|
||||
c-6.1,0-11.1-5-11.1-11.1S9.8,5,15.9,5C22,4.9,27,9.9,27,16.1C27,22.2,22,27.2,15.9,27.2z"/>
|
||||
<circle class="st2" cx="15.9" cy="15.5" r="12.4"/>
|
||||
<path class="st1" d="M15.9,2.8c-7,0-12.7,5.7-12.7,12.7s5.7,12.7,12.7,12.7s12.7-5.7,12.7-12.7S22.9,2.8,15.9,2.8z M15.9,26.6
|
||||
c-6.1,0-11.1-5-11.1-11.1s5-11.1,11.1-11.1C22,4.4,27,9.4,27,15.5S22,26.6,15.9,26.6z"/>
|
||||
<circle cx="16.1" cy="12.9" r="3"/>
|
||||
<path d="M18.2,18.2H14c-1.7,0-3.1,1.5-3.1,3.2V23c1.4,1.1,3.1,1.7,4.9,1.7c2.1,0,4-0.8,5.4-2.1v-1.2C21.3,19.7,19.9,18.2,18.2,18.2z
|
||||
"/>
|
||||
<circle cx="22.9" cy="12.9" r="1.6"/>
|
||||
<path d="M24,15.9h-1.8c-0.4,0-0.8,0.2-1,0.4c0.5,0.3,1,0.7,1.4,1.1c0.5,0.5,0.7,1.2,0.7,1.9c0.1,0.4,0.1,0.8,0.1,1.2v0.3
|
||||
c0.8-1,1.5-2.7,1.8-3.6v-0.1C25.2,16.8,24.6,15.9,24,15.9z"/>
|
||||
<circle cx="9.1" cy="13.2" r="1.6"/>
|
||||
<path d="M8.7,21.2c0-0.3,0-0.6,0-0.9v-0.1c0-0.1,0-0.2,0-0.3c0-0.1,0-0.1,0-0.2s0-0.1,0-0.2c0.1-0.9,0.7-2,1.4-2.5
|
||||
c0.2-0.2,0.4-0.3,0.6-0.4c-0.2-0.2-0.6-0.3-0.9-0.3H8c-0.6,0-1.2,0.8-1.1,1.2v0.1C7.2,18.6,7.9,20.2,8.7,21.2z"/>
|
||||
<circle class="st1" cx="16.1" cy="12.3" r="3"/>
|
||||
<path class="st1" d="M18.2,17.6H14c-1.7,0-3.1,1.5-3.1,3.2v1.6c1.4,1.1,3.1,1.7,4.9,1.7c2.1,0,4-0.8,5.4-2.1v-1.2
|
||||
C21.3,19.1,19.9,17.6,18.2,17.6z"/>
|
||||
<circle class="st1" cx="22.9" cy="12.4" r="1.6"/>
|
||||
<path class="st1" d="M24,15.4h-1.8c-0.4,0-0.8,0.2-1,0.4c0.5,0.3,1,0.7,1.4,1.1c0.5,0.5,0.7,1.2,0.7,1.9c0.1,0.4,0.1,0.8,0.1,1.2
|
||||
v0.3c0.8-1,1.5-2.7,1.8-3.6v-0.1C25.2,16.2,24.6,15.4,24,15.4z"/>
|
||||
<circle class="st1" cx="9.1" cy="12.6" r="1.6"/>
|
||||
<path class="st1" d="M8.7,20.7c0-0.3,0-0.6,0-0.9v-0.1c0-0.1,0-0.2,0-0.3c0-0.1,0-0.1,0-0.2s0-0.1,0-0.2c0.1-0.9,0.7-2,1.4-2.5
|
||||
c0.2-0.2,0.4-0.3,0.6-0.4c-0.2-0.2-0.6-0.3-0.9-0.3H8c-0.6,0-1.2,0.8-1.1,1.2v0.1C7.2,18,7.9,19.7,8.7,20.7z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
BIN
interface/resources/images/preview-disabled.png
Normal file
After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 59 KiB |
33
interface/resources/images/snapshot.svg
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 32 64" style="enable-background:new 0 0 32 64;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{opacity:0.64;fill:#58595B;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
.st2{fill:#168DB7;}
|
||||
</style>
|
||||
<circle class="st0" cx="15.8" cy="15.5" r="12.5"/>
|
||||
<path d="M15.8,3.4c-7,0-12.7,5.7-12.7,12.7s5.7,12.7,12.7,12.7c7,0,12.7-5.7,12.7-12.7S22.8,3.4,15.8,3.4z M15.8,27.3
|
||||
c-6.2,0-11.2-5-11.2-11.2C4.6,10,9.7,5,15.8,5C22,5,27,10,27,16.1C27,22.3,22,27.3,15.8,27.3z"/>
|
||||
<path class="st1" d="M15.8,2.8c-7,0-12.7,5.7-12.7,12.7s5.7,12.7,12.7,12.7c7,0,12.7-5.7,12.7-12.7S22.8,2.8,15.8,2.8z M15.8,26.7
|
||||
c-6.2,0-11.2-5-11.2-11.2c0-6.2,5-11.2,11.2-11.2C22,4.4,27,9.4,27,15.6C27,21.7,22,26.7,15.8,26.7z"/>
|
||||
<path d="M21.5,11.6H20V11c0-1-0.6-1.2-1.6-1.2h-5c-1,0-1.5,0.2-1.5,1.2v0.6h-1.5c-1,0-1.9,0.4-1.9,1.4v6.6c0,1,0.8,1.9,1.9,1.9h11
|
||||
c1,0,1.7-1.1,1.7-2.1V13C23.3,12,22.5,11.6,21.5,11.6z M16.1,20.1c-2.3,0-4-1.8-4-4c0-2.3,1.8-4,4-4c2.3,0,4,1.8,4,4
|
||||
S18.4,20.1,16.1,20.1z"/>
|
||||
<circle cx="16.1" cy="16" r="2.4"/>
|
||||
<path class="st1" d="M21.5,11H20v-0.6c0-1-0.6-1.2-1.6-1.2h-5c-1,0-1.5,0.2-1.5,1.2V11h-1.5c-1,0-1.9,0.4-1.9,1.4v6.6
|
||||
c0,1,0.8,1.9,1.9,1.9h11c1,0,1.7-1.1,1.7-2.1v-6.4C23.3,11.5,22.5,11,21.5,11z M16.1,19.5c-2.3,0-4-1.8-4-4c0-2.3,1.8-4,4-4
|
||||
c2.3,0,4,1.8,4,4S18.4,19.5,16.1,19.5z"/>
|
||||
<circle class="st1" cx="16.1" cy="15.5" r="2.4"/>
|
||||
<circle cx="15.8" cy="48.2" r="14.8"/>
|
||||
<circle class="st2" cx="15.8" cy="47.6" r="14.8"/>
|
||||
<path d="M21.5,43.6H20V43c0-1-0.6-1.2-1.6-1.2h-5c-1,0-1.5,0.2-1.5,1.2v0.6h-1.5c-1,0-1.9,0.4-1.9,1.4v6.6c0,1,0.8,1.9,1.9,1.9h11
|
||||
c1,0,1.7-1.1,1.7-2.1V45C23.3,44.1,22.5,43.6,21.5,43.6z M16.1,52.1c-2.3,0-4-1.8-4-4c0-2.3,1.8-4,4-4c2.3,0,4,1.8,4,4
|
||||
C20.1,50.2,18.4,52.1,16.1,52.1z"/>
|
||||
<circle cx="16.1" cy="48" r="2.4"/>
|
||||
<path class="st1" d="M21.5,43.1H20v-0.6c0-1-0.6-1.2-1.6-1.2h-5c-1,0-1.5,0.2-1.5,1.2v0.6h-1.5c-1,0-1.9,0.4-1.9,1.4v6.6
|
||||
c0,1,0.8,1.9,1.9,1.9h11c1,0,1.7-1.1,1.7-2.1v-6.4C23.3,43.5,22.5,43.1,21.5,43.1z M16.1,51.5c-2.3,0-4-1.8-4-4c0-2.3,1.8-4,4-4
|
||||
c2.3,0,4,1.8,4,4C20.1,49.7,18.4,51.5,16.1,51.5z"/>
|
||||
<circle class="st1" cx="16.1" cy="47.5" r="2.4"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
|
@ -50,16 +50,15 @@ Window {
|
|||
function resetAfterTeleport() {
|
||||
storyCardFrame.shown = root.shown = false;
|
||||
}
|
||||
function goCard(card) {
|
||||
if (addressBarDialog.useFeed) {
|
||||
storyCardHTML.url = addressBarDialog.metaverseServerUrl + "/user_stories/" + card.storyId;
|
||||
function goCard(targetString) {
|
||||
if (0 !== targetString.indexOf('hifi://')) {
|
||||
storyCardHTML.url = addressBarDialog.metaverseServerUrl + targetString;
|
||||
storyCardFrame.shown = true;
|
||||
return;
|
||||
}
|
||||
addressLine.text = card.hifiUrl;
|
||||
addressLine.text = targetString;
|
||||
toggleOrGo(true);
|
||||
}
|
||||
property var allPlaces: [];
|
||||
property var allStories: [];
|
||||
property int cardWidth: 200;
|
||||
property int cardHeight: 152;
|
||||
|
@ -72,7 +71,6 @@ Window {
|
|||
// The buttons have their button state changed on hover, so we have to manually fix them up here
|
||||
onBackEnabledChanged: backArrow.buttonState = addressBarDialog.backEnabled ? 1 : 0;
|
||||
onForwardEnabledChanged: forwardArrow.buttonState = addressBarDialog.forwardEnabled ? 1 : 0;
|
||||
onUseFeedChanged: updateFeedState();
|
||||
onReceivedHifiSchemeURL: resetAfterTeleport();
|
||||
|
||||
ListModel { id: suggestions }
|
||||
|
@ -97,7 +95,6 @@ Window {
|
|||
userName: model.username;
|
||||
placeName: model.place_name;
|
||||
hifiUrl: model.place_name + model.path;
|
||||
imageUrl: model.image_url;
|
||||
thumbnail: model.thumbnail_url;
|
||||
action: model.action;
|
||||
timestamp: model.created_at;
|
||||
|
@ -135,7 +132,10 @@ Window {
|
|||
buttonState: 1
|
||||
defaultState: 1
|
||||
hoverState: 2
|
||||
onClicked: addressBarDialog.loadHome();
|
||||
onClicked: {
|
||||
addressBarDialog.loadHome();
|
||||
root.shown = false;
|
||||
}
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: homeButton.width / 2
|
||||
|
@ -176,9 +176,9 @@ Window {
|
|||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
left: forwardArrow.right
|
||||
right: placesButton.left
|
||||
right: parent.right
|
||||
leftMargin: forwardArrow.width
|
||||
rightMargin: placesButton.width
|
||||
rightMargin: forwardArrow.width / 2
|
||||
topMargin: parent.inputAreaStep + hifi.layout.spacing
|
||||
bottomMargin: parent.inputAreaStep + hifi.layout.spacing
|
||||
}
|
||||
|
@ -188,32 +188,6 @@ Window {
|
|||
helperItalic: true
|
||||
onTextChanged: filterChoicesByText()
|
||||
}
|
||||
// These two are radio buttons.
|
||||
ToolbarButton {
|
||||
id: placesButton
|
||||
imageURL: "../images/places.svg"
|
||||
buttonState: 1
|
||||
defaultState: addressBarDialog.useFeed ? 0 : 1;
|
||||
hoverState: addressBarDialog.useFeed ? 2 : -1;
|
||||
onClicked: addressBarDialog.useFeed ? toggleFeed() : identity()
|
||||
anchors {
|
||||
right: feedButton.left;
|
||||
bottom: addressLine.bottom;
|
||||
}
|
||||
}
|
||||
ToolbarButton {
|
||||
id: feedButton;
|
||||
imageURL: "../images/snap-feed.svg";
|
||||
buttonState: 0
|
||||
defaultState: addressBarDialog.useFeed ? 1 : 0;
|
||||
hoverState: addressBarDialog.useFeed ? -1 : 2;
|
||||
onClicked: addressBarDialog.useFeed ? identity() : toggleFeed();
|
||||
anchors {
|
||||
right: parent.right;
|
||||
bottom: addressLine.bottom;
|
||||
rightMargin: feedButton.width / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Window {
|
||||
|
@ -237,16 +211,6 @@ Window {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function toggleFeed() {
|
||||
addressBarDialog.useFeed = !addressBarDialog.useFeed;
|
||||
updateFeedState();
|
||||
}
|
||||
function updateFeedState() {
|
||||
placesButton.buttonState = addressBarDialog.useFeed ? 0 : 1;
|
||||
feedButton.buttonState = addressBarDialog.useFeed ? 1 : 0;
|
||||
filterChoicesByText();
|
||||
}
|
||||
function getRequest(url, cb) { // cb(error, responseOfCorrectContentType) of url. General for 'get' text/html/json, but without redirects.
|
||||
// TODO: make available to other .qml.
|
||||
var request = new XMLHttpRequest();
|
||||
|
@ -271,37 +235,6 @@ Window {
|
|||
request.open("GET", url, true);
|
||||
request.send();
|
||||
}
|
||||
function asyncMap(array, iterator, cb) {
|
||||
// call iterator(element, icb) once for each element of array, and then cb(error, mappedResult)
|
||||
// when icb(error, mappedElement) has been called by each iterator.
|
||||
// Calls to iterator are overlapped and may call icb in any order, but the mappedResults are collected in the same
|
||||
// order as the elements of the array.
|
||||
// Short-circuits if error. Note that iterator MUST be an asynchronous function. (Use setTimeout if necessary.)
|
||||
var count = array.length, results = [];
|
||||
if (!count) {
|
||||
return cb(null, results);
|
||||
}
|
||||
array.forEach(function (element, index) {
|
||||
if (count < 0) { // don't keep iterating after we short-circuit
|
||||
return;
|
||||
}
|
||||
iterator(element, function (error, mapped) {
|
||||
results[index] = mapped;
|
||||
if (error || !--count) {
|
||||
count = 0; // don't cb multiple times if error
|
||||
cb(error, results);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
// Example:
|
||||
/*asyncMap([0, 1, 2, 3, 4, 5, 6], function (elt, icb) {
|
||||
console.log('called', elt);
|
||||
setTimeout(function () {
|
||||
console.log('answering', elt);
|
||||
icb(null, elt);
|
||||
}, Math.random() * 1000);
|
||||
}, console.log); */
|
||||
|
||||
function identity(x) {
|
||||
return x;
|
||||
|
@ -321,131 +254,61 @@ Window {
|
|||
cb(error);
|
||||
return true;
|
||||
}
|
||||
|
||||
function getPlace(placeData, cb) { // cb(error, side-effected-placeData), after adding path, thumbnails, and description
|
||||
var url = metaverseBase + 'places/' + placeData.place_name;
|
||||
getRequest(url, function (error, data) {
|
||||
if (handleError(url, error, data, cb)) {
|
||||
return;
|
||||
}
|
||||
var place = data.data.place, previews = place.previews;
|
||||
placeData.path = place.path;
|
||||
if (previews && previews.thumbnail) {
|
||||
placeData.thumbnail_url = previews.thumbnail;
|
||||
}
|
||||
if (place.description) {
|
||||
placeData.description = place.description;
|
||||
placeData.searchText += ' ' + place.description.toUpperCase();
|
||||
}
|
||||
cb(error, placeData);
|
||||
});
|
||||
function resolveUrl(url) {
|
||||
return (url.indexOf('/') === 0) ? (addressBarDialog.metaverseServerUrl + url) : url;
|
||||
}
|
||||
function makeModelData(data, optionalPlaceName) { // create a new obj from data
|
||||
|
||||
function makeModelData(data) { // create a new obj from data
|
||||
// ListModel elements will only ever have those properties that are defined by the first obj that is added.
|
||||
// So here we make sure that we have all the properties we need, regardless of whether it is a place data or user story.
|
||||
var name = optionalPlaceName || data.place_name,
|
||||
var name = data.place_name,
|
||||
tags = data.tags || [data.action, data.username],
|
||||
description = data.description || "",
|
||||
thumbnail_url = data.thumbnail_url || "",
|
||||
image_url = thumbnail_url;
|
||||
if (data.details) {
|
||||
try {
|
||||
image_url = JSON.parse(data.details).image_url || thumbnail_url;
|
||||
} catch (e) {
|
||||
console.log(name, "has bad details", data.details);
|
||||
}
|
||||
}
|
||||
thumbnail_url = data.thumbnail_url || "";
|
||||
return {
|
||||
place_name: name,
|
||||
username: data.username || "",
|
||||
path: data.path || "",
|
||||
created_at: data.created_at || "",
|
||||
action: data.action || "",
|
||||
thumbnail_url: thumbnail_url,
|
||||
image_url: image_url,
|
||||
thumbnail_url: resolveUrl(thumbnail_url),
|
||||
|
||||
metaverseId: (data.id || "").toString(), // Some are strings from server while others are numbers. Model objects require uniformity.
|
||||
|
||||
tags: tags,
|
||||
description: description,
|
||||
online_users: data.online_users || 0,
|
||||
online_users: data.details.concurrency || 0,
|
||||
|
||||
searchText: [name].concat(tags, description || []).join(' ').toUpperCase()
|
||||
}
|
||||
}
|
||||
function mapDomainPlaces(domain, cb) { // cb(error, arrayOfDomainPlaceData)
|
||||
function addPlace(name, icb) {
|
||||
getPlace(makeModelData(domain, name), icb);
|
||||
}
|
||||
// IWBNI we could get these results in order with most-recent-entered first.
|
||||
// In any case, we don't really need to preserve the domain.names order in the results.
|
||||
asyncMap(domain.names || [], addPlace, cb);
|
||||
}
|
||||
|
||||
function suggestable(place) {
|
||||
if (addressBarDialog.useFeed) {
|
||||
if (place.action === 'snapshot') {
|
||||
return true;
|
||||
}
|
||||
return (place.place_name !== AddressManager.hostname) // Not our entry, but do show other entry points to current domain.
|
||||
&& place.thumbnail_url
|
||||
&& place.online_users // at least one present means it's actually online
|
||||
&& place.online_users <= 20;
|
||||
}
|
||||
function getDomainPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model
|
||||
// Each page of results is processed completely before we start on the next page.
|
||||
// For each page of domains, we process each domain in parallel, and for each domain, process each place name in parallel.
|
||||
// This gives us minimum latency within the page, but we do preserve the order within the page by using asyncMap and
|
||||
// only appending the collected results.
|
||||
var params = [
|
||||
'open', // published hours handle now
|
||||
// TBD: should determine if place is actually running?
|
||||
'restriction=open', // Not by whitelist, etc. TBD: If logged in, add hifi to the restriction options, in order to include places that require login?
|
||||
// TBD: add maturity?
|
||||
'protocol=' + encodeURIComponent(AddressManager.protocolVersion()),
|
||||
'sort_by=users',
|
||||
'sort_order=desc',
|
||||
'page=' + pageNumber
|
||||
];
|
||||
var url = metaverseBase + 'domains/all?' + params.join('&');
|
||||
getRequest(url, function (error, data) {
|
||||
if (handleError(url, error, data, cb)) {
|
||||
return;
|
||||
}
|
||||
asyncMap(data.data.domains, mapDomainPlaces, function (error, pageResults) {
|
||||
if (error) {
|
||||
return cb(error);
|
||||
}
|
||||
// pageResults is now [ [ placeDataOneForDomainOne, placeDataTwoForDomainOne, ...], [ placeDataTwoForDomainTwo...] ]
|
||||
pageResults.forEach(function (domainResults) {
|
||||
allPlaces = allPlaces.concat(domainResults);
|
||||
if (!addressLine.text && !addressBarDialog.useFeed) { // Don't add if the user is already filtering
|
||||
domainResults.forEach(function (place) {
|
||||
if (suggestable(place)) {
|
||||
suggestions.append(place);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (data.current_page < data.total_pages) {
|
||||
return getDomainPage(pageNumber + 1, cb);
|
||||
}
|
||||
cb();
|
||||
});
|
||||
});
|
||||
return (place.place_name !== AddressManager.hostname); // Not our entry, but do show other entry points to current domain.
|
||||
// could also require right protocolVersion
|
||||
}
|
||||
function getUserStoryPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model
|
||||
var url = metaverseBase + 'user_stories?page=' + pageNumber;
|
||||
var options = [
|
||||
'include_actions=snapshot,concurrency',
|
||||
'protocol=' + encodeURIComponent(AddressManager.protocolVersion()),
|
||||
'page=' + pageNumber
|
||||
];
|
||||
var url = metaverseBase + 'user_stories?' + options.join('&');
|
||||
getRequest(url, function (error, data) {
|
||||
if (handleError(url, error, data, cb)) {
|
||||
return;
|
||||
}
|
||||
var stories = data.user_stories.map(function (story) { // explicit single-argument function
|
||||
return makeModelData(story);
|
||||
return makeModelData(story, url);
|
||||
});
|
||||
allStories = allStories.concat(stories);
|
||||
if (!addressLine.text && addressBarDialog.useFeed) { // Don't add if the user is already filtering
|
||||
if (!addressLine.text) { // Don't add if the user is already filtering
|
||||
stories.forEach(function (story) {
|
||||
suggestions.append(story);
|
||||
if (suggestable(story)) {
|
||||
suggestions.append(story);
|
||||
}
|
||||
});
|
||||
}
|
||||
if ((data.current_page < data.total_pages) && (data.current_page <= 10)) { // just 10 pages = 100 stories for now
|
||||
|
@ -457,7 +320,7 @@ Window {
|
|||
function filterChoicesByText() {
|
||||
suggestions.clear();
|
||||
var words = addressLine.text.toUpperCase().split(/\s+/).filter(identity),
|
||||
data = addressBarDialog.useFeed ? allStories : allPlaces;
|
||||
data = allStories;
|
||||
function matches(place) {
|
||||
if (!words.length) {
|
||||
return suggestable(place);
|
||||
|
@ -474,12 +337,8 @@ Window {
|
|||
}
|
||||
|
||||
function fillDestinations() {
|
||||
allPlaces = [];
|
||||
allStories = [];
|
||||
suggestions.clear();
|
||||
getDomainPage(1, function (error) {
|
||||
console.log('domain query', error || 'ok', allPlaces.length);
|
||||
});
|
||||
getUserStoryPage(1, function (error) {
|
||||
console.log('user stories query', error || 'ok', allStories.length);
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.2
|
||||
import QtWebEngine 1.1
|
||||
import QtWebEngine 1.2
|
||||
|
||||
import "controls-uit"
|
||||
import "styles" as HifiStyles
|
||||
|
@ -223,12 +223,15 @@ ScrollingWindow {
|
|||
var newWindow = component.createObject(desktop);
|
||||
request.openIn(newWindow.webView)
|
||||
}
|
||||
Component.onCompleted: {
|
||||
desktop.initWebviewProfileHandlers(webview.profile)
|
||||
}
|
||||
|
||||
onWindowCloseRequested: {
|
||||
root.destroy();
|
||||
}
|
||||
|
||||
//profile: desktop.browserProfile
|
||||
Component.onCompleted: {
|
||||
desktop.initWebviewProfileHandlers(webview.profile)
|
||||
}
|
||||
|
||||
profile: desktop.browserProfile
|
||||
}
|
||||
|
||||
} // item
|
||||
|
@ -245,4 +248,4 @@ ScrollingWindow {
|
|||
break;
|
||||
}
|
||||
}
|
||||
} // dialog
|
||||
} // dialog
|
||||
|
|
|
@ -1,103 +0,0 @@
|
|||
//
|
||||
// MarketplaceComboBox.qml
|
||||
//
|
||||
// Created by Elisa Lupin-Jimenez on 3 Aug 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtWebChannel 1.0
|
||||
import QtWebEngine 1.1
|
||||
import QtWebSockets 1.0
|
||||
import "qrc:///qtwebchannel/qwebchannel.js" as WebChannel
|
||||
|
||||
import "controls"
|
||||
import "controls-uit" as Controls
|
||||
import "styles"
|
||||
import "styles-uit"
|
||||
|
||||
|
||||
Rectangle {
|
||||
HifiConstants { id: hifi }
|
||||
id: marketplaceComboBox
|
||||
anchors.fill: parent
|
||||
color: hifi.colors.baseGrayShadow
|
||||
property var currentUrl: "https://metaverse.highfidelity.com/marketplace"
|
||||
|
||||
Controls.BaseWebView {
|
||||
id: webview
|
||||
url: currentUrl
|
||||
anchors.top: switchMarketView.bottom
|
||||
width: parent.width
|
||||
height: parent.height - 40
|
||||
focus: true
|
||||
|
||||
Timer {
|
||||
id: zipTimer
|
||||
running: false
|
||||
repeat: false
|
||||
interval: 1500
|
||||
property var handler;
|
||||
onTriggered: handler();
|
||||
}
|
||||
|
||||
property var autoCancel: 'var element = $("a.btn.cancel");
|
||||
element.click();'
|
||||
|
||||
onNewViewRequested: {
|
||||
var component = Qt.createComponent("Browser.qml");
|
||||
var newWindow = component.createObject(desktop);
|
||||
request.openIn(newWindow.webView);
|
||||
if (File.isZippedFbx(desktop.currentUrl)) {
|
||||
zipTimer.handler = function() {
|
||||
newWindow.destroy();
|
||||
runJavaScript(autoCancel);
|
||||
}
|
||||
zipTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
property var simpleDownload: 'var element = $("a.download-file");
|
||||
element.removeClass("download-file");
|
||||
element.removeAttr("download");'
|
||||
|
||||
onLinkHovered: {
|
||||
desktop.currentUrl = hoveredUrl;
|
||||
// add an error message for non-fbx files
|
||||
if (File.isZippedFbx(desktop.currentUrl)) {
|
||||
runJavaScript(simpleDownload, function(){console.log("ran the JS");});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Controls.ComboBox {
|
||||
id: switchMarketView
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
width: 200
|
||||
height: 40
|
||||
visible: true
|
||||
model: ["Marketplace", "Clara.io"]
|
||||
onCurrentIndexChanged: {
|
||||
if (currentIndex === 0) { webview.url = "https://metaverse.highfidelity.com/marketplace"; }
|
||||
if (currentIndex === 1) { webview.url = "https://clara.io/library"; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Controls.Label {
|
||||
id: switchMarketLabel
|
||||
anchors.verticalCenter: switchMarketView.verticalCenter
|
||||
anchors.right: switchMarketView.left
|
||||
color: hifi.colors.white
|
||||
text: "Explore interesting content from: "
|
||||
}
|
||||
|
||||
}
|
167
interface/resources/qml/Marketplaces.qml
Normal file
|
@ -0,0 +1,167 @@
|
|||
//
|
||||
// Marketplaces.qml
|
||||
//
|
||||
// Created by Elisa Lupin-Jimenez on 3 Aug 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtWebChannel 1.0
|
||||
import QtWebEngine 1.1
|
||||
import QtWebSockets 1.0
|
||||
import "qrc:///qtwebchannel/qwebchannel.js" as WebChannel
|
||||
|
||||
import "controls"
|
||||
import "controls-uit" as Controls
|
||||
import "styles"
|
||||
import "styles-uit"
|
||||
|
||||
|
||||
Rectangle {
|
||||
HifiConstants { id: hifi }
|
||||
id: marketplace
|
||||
anchors.fill: parent
|
||||
property var marketplacesUrl: "../../scripts/system/html/marketplaces.html"
|
||||
property int statusBarHeight: 50
|
||||
property int statusMargin: 50
|
||||
property string standardMessage: "Check out other marketplaces."
|
||||
property string claraMessage: "Choose a model and click Download -> Autodesk FBX."
|
||||
property string claraError: "High Fidelity only supports Autodesk FBX models."
|
||||
|
||||
Controls.BaseWebView {
|
||||
id: webview
|
||||
url: marketplacesUrl
|
||||
anchors.top: marketplace.top
|
||||
width: parent.width
|
||||
height: parent.height - statusBarHeight
|
||||
focus: true
|
||||
|
||||
Timer {
|
||||
id: zipTimer
|
||||
running: false
|
||||
repeat: false
|
||||
interval: 1500
|
||||
property var handler;
|
||||
onTriggered: handler();
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: alertTimer
|
||||
running: false
|
||||
repeat: false
|
||||
interval: 9000
|
||||
property var handler;
|
||||
onTriggered: handler();
|
||||
}
|
||||
|
||||
property var autoCancel: 'var element = $("a.btn.cancel");
|
||||
element.click();'
|
||||
|
||||
property var simpleDownload: 'var element = $("a.download-file");
|
||||
element.removeClass("download-file");
|
||||
element.removeAttr("download");'
|
||||
|
||||
function displayErrorStatus() {
|
||||
alertTimer.handler = function() {
|
||||
statusLabel.text = claraMessage;
|
||||
statusBar.color = hifi.colors.blueHighlight;
|
||||
statusIcon.text = hifi.glyphs.info;
|
||||
}
|
||||
alertTimer.start();
|
||||
}
|
||||
|
||||
property var notFbxHandler: 'var element = $("a.btn.btn-primary.viewer-button.download-file")
|
||||
element.click();'
|
||||
|
||||
// this code is for removing other file types from Clara.io's download options
|
||||
//property var checkFileType: "$('[data-extension]:not([data-extension=\"fbx\"])').parent().remove()"
|
||||
|
||||
onLinkHovered: {
|
||||
desktop.currentUrl = hoveredUrl;
|
||||
//runJavaScript(checkFileType, function(){console.log("Remove filetypes JS injection");});
|
||||
if (File.isZippedFbx(desktop.currentUrl)) {
|
||||
runJavaScript(simpleDownload, function(){console.log("Download JS injection");});
|
||||
return;
|
||||
}
|
||||
|
||||
if (File.isZipped(desktop.currentUrl)) {
|
||||
statusLabel.text = claraError;
|
||||
statusBar.color = hifi.colors.redHighlight;
|
||||
statusIcon.text = hifi.glyphs.alert;
|
||||
runJavaScript(notFbxHandler, displayErrorStatus());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onLoadingChanged: {
|
||||
if (File.isClaraLink(webview.url)) {
|
||||
statusLabel.text = claraMessage;
|
||||
} else {
|
||||
statusLabel.text = standardMessage;
|
||||
}
|
||||
statusBar.color = hifi.colors.blueHighlight;
|
||||
statusIcon.text = hifi.glyphs.info;
|
||||
}
|
||||
|
||||
onNewViewRequested: {
|
||||
var component = Qt.createComponent("Browser.qml");
|
||||
var newWindow = component.createObject(desktop);
|
||||
request.openIn(newWindow.webView);
|
||||
if (File.isZippedFbx(desktop.currentUrl)) {
|
||||
runJavaScript(autoCancel);
|
||||
zipTimer.handler = function() {
|
||||
newWindow.destroy();
|
||||
}
|
||||
zipTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: statusBar
|
||||
anchors.top: webview.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
color: hifi.colors.blueHighlight
|
||||
|
||||
Controls.Button {
|
||||
id: switchMarketView
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: statusMargin
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 150
|
||||
text: "See all markets"
|
||||
onClicked: {
|
||||
webview.url = "../../scripts/system/html/marketplaces.html";
|
||||
statusLabel.text = standardMessage;
|
||||
}
|
||||
}
|
||||
|
||||
Controls.Label {
|
||||
id: statusLabel
|
||||
anchors.verticalCenter: switchMarketView.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: statusMargin
|
||||
color: hifi.colors.white
|
||||
text: standardMessage
|
||||
size: 18
|
||||
}
|
||||
|
||||
HiFiGlyphs {
|
||||
id: statusIcon
|
||||
anchors.right: statusLabel.left
|
||||
anchors.verticalCenter: statusLabel.verticalCenter
|
||||
text: hifi.glyphs.info
|
||||
color: hifi.colors.white
|
||||
size: hifi.fontSizes.tableHeadingIcon
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -59,6 +59,11 @@ Item {
|
|||
font.pixelSize: root.fontSize
|
||||
text: "Avatars: " + root.avatarCount
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Frame Rate: " + root.framerate.toFixed(2);
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
|
|
|
@ -154,7 +154,6 @@ ScrollingWindow {
|
|||
return i;
|
||||
}
|
||||
}
|
||||
console.warn("Could not find tab for " + source);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -189,7 +188,6 @@ ScrollingWindow {
|
|||
return i;
|
||||
}
|
||||
}
|
||||
console.warn("Could not find free tab");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -216,7 +214,6 @@ ScrollingWindow {
|
|||
|
||||
var existingTabIndex = findIndexForUrl(properties.source);
|
||||
if (existingTabIndex >= 0) {
|
||||
console.log("Existing tab " + existingTabIndex + " found with URL " + properties.source);
|
||||
var tab = tabView.getTab(existingTabIndex);
|
||||
return tab.item;
|
||||
}
|
||||
|
@ -239,16 +236,13 @@ ScrollingWindow {
|
|||
var tab = tabView.getTab(freeTabIndex);
|
||||
tab.title = properties.title || "Unknown";
|
||||
tab.enabled = true;
|
||||
console.log("New tab URL: " + properties.source)
|
||||
tab.originalUrl = properties.source;
|
||||
|
||||
var eventBridge = properties.eventBridge;
|
||||
console.log("Event bridge: " + eventBridge);
|
||||
|
||||
var result = tab.item;
|
||||
result.enabled = true;
|
||||
tabView.tabCount++;
|
||||
console.log("Setting event bridge: " + eventBridge);
|
||||
result.eventBridgeWrapper.eventBridge = eventBridge;
|
||||
result.url = properties.source;
|
||||
return result;
|
||||
|
|
|
@ -15,7 +15,7 @@ WebEngineView {
|
|||
id: root
|
||||
property var newUrl;
|
||||
|
||||
profile.httpUserAgent: "Mozilla/5.0 Chrome/38.0 (HighFidelityInterface)"
|
||||
profile: desktop.browserProfile
|
||||
|
||||
Component.onCompleted: {
|
||||
console.log("Connecting JS messaging to Hifi Logging")
|
||||
|
@ -60,9 +60,4 @@ WebEngineView {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This breaks the webchannel used for passing messages. Fixed in Qt 5.6
|
||||
// See https://bugreports.qt.io/browse/QTBUG-49521
|
||||
//profile: desktop.browserProfile
|
||||
}
|
||||
|
|
164
interface/resources/qml/controls/Key.qml
Normal file
|
@ -0,0 +1,164 @@
|
|||
import QtQuick 2.0
|
||||
|
||||
Item {
|
||||
id: keyItem
|
||||
width: 45
|
||||
height: 50
|
||||
property string glyph: "a"
|
||||
property bool toggle: false // does this button have the toggle behaivor?
|
||||
property bool toggled: false // is this button currently toggled?
|
||||
property alias mouseArea: mouseArea1
|
||||
|
||||
function resetToggledMode(mode) {
|
||||
toggled = mode;
|
||||
if (toggled) {
|
||||
state = "mouseDepressed";
|
||||
} else {
|
||||
state = "";
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea1
|
||||
width: 36
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
onCanceled: {
|
||||
if (toggled) {
|
||||
keyItem.state = "mouseDepressed";
|
||||
} else {
|
||||
keyItem.state = "";
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
mouse.accepted = true;
|
||||
webEntity.synthesizeKeyPress(glyph);
|
||||
if (toggle) {
|
||||
toggled = !toggled;
|
||||
}
|
||||
}
|
||||
|
||||
onDoubleClicked: {
|
||||
mouse.accepted = true;
|
||||
}
|
||||
|
||||
onEntered: {
|
||||
keyItem.state = "mouseOver";
|
||||
}
|
||||
|
||||
onExited: {
|
||||
if (toggled) {
|
||||
keyItem.state = "mouseDepressed";
|
||||
} else {
|
||||
keyItem.state = "";
|
||||
}
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
keyItem.state = "mouseClicked";
|
||||
mouse.accepted = true;
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
if (containsMouse) {
|
||||
keyItem.state = "mouseOver";
|
||||
} else {
|
||||
if (toggled) {
|
||||
keyItem.state = "mouseDepressed";
|
||||
} else {
|
||||
keyItem.state = "";
|
||||
}
|
||||
}
|
||||
mouse.accepted = true;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: roundedRect
|
||||
width: 30
|
||||
color: "#121212"
|
||||
radius: 2
|
||||
border.color: "#00000000"
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 4
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 4
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 4
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 4
|
||||
}
|
||||
|
||||
Text {
|
||||
id: letter
|
||||
y: 6
|
||||
width: 50
|
||||
color: "#ffffff"
|
||||
text: glyph
|
||||
style: Text.Normal
|
||||
font.family: "Tahoma"
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 0
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 28
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "mouseOver"
|
||||
|
||||
PropertyChanges {
|
||||
target: roundedRect
|
||||
color: "#121212"
|
||||
radius: 3
|
||||
border.width: 2
|
||||
border.color: "#00b4ef"
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: letter
|
||||
color: "#00b4ef"
|
||||
style: Text.Normal
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "mouseClicked"
|
||||
PropertyChanges {
|
||||
target: roundedRect
|
||||
color: "#1080b8"
|
||||
border.width: 2
|
||||
border.color: "#00b4ef"
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: letter
|
||||
color: "#121212"
|
||||
styleColor: "#00000000"
|
||||
style: Text.Normal
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "mouseDepressed"
|
||||
PropertyChanges {
|
||||
target: roundedRect
|
||||
color: "#0578b1"
|
||||
border.width: 0
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: letter
|
||||
color: "#121212"
|
||||
styleColor: "#00000000"
|
||||
style: Text.Normal
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
390
interface/resources/qml/controls/Keyboard.qml
Normal file
|
@ -0,0 +1,390 @@
|
|||
import QtQuick 2.0
|
||||
|
||||
Item {
|
||||
id: keyboardBase
|
||||
height: 200
|
||||
property alias shiftKey: key27
|
||||
property bool shiftMode: false
|
||||
|
||||
function resetShiftMode(mode) {
|
||||
shiftMode = mode;
|
||||
shiftKey.resetToggledMode(mode);
|
||||
}
|
||||
|
||||
function toUpper(str) {
|
||||
if (str === ",") {
|
||||
return "<";
|
||||
} else if (str === ".") {
|
||||
return ">";
|
||||
} else if (str === "/") {
|
||||
return "?";
|
||||
} else {
|
||||
return str.toUpperCase(str);
|
||||
}
|
||||
}
|
||||
|
||||
function toLower(str) {
|
||||
if (str === "<") {
|
||||
return ",";
|
||||
} else if (str === ">") {
|
||||
return ".";
|
||||
} else if (str === "?") {
|
||||
return "/";
|
||||
} else {
|
||||
return str.toLowerCase(str);
|
||||
}
|
||||
}
|
||||
|
||||
function forEachKey(func) {
|
||||
var i, j;
|
||||
for (i = 0; i < column1.children.length; i++) {
|
||||
var row = column1.children[i];
|
||||
for (j = 0; j < row.children.length; j++) {
|
||||
var key = row.children[j];
|
||||
func(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onShiftModeChanged: {
|
||||
forEachKey(function (key) {
|
||||
if (shiftMode) {
|
||||
key.glyph = keyboardBase.toUpper(key.glyph);
|
||||
} else {
|
||||
key.glyph = keyboardBase.toLower(key.glyph);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function alphaKeyClickedHandler(mouseArea) {
|
||||
// reset shift mode to false after first keypress
|
||||
if (shiftMode) {
|
||||
resetShiftMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
// hook up callbacks to every ascii key
|
||||
forEachKey(function (key) {
|
||||
if (/^[a-z]+$/i.test(key.glyph)) {
|
||||
key.mouseArea.onClicked.connect(alphaKeyClickedHandler);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: leftRect
|
||||
y: 0
|
||||
height: 200
|
||||
color: "#252525"
|
||||
anchors.right: keyboardRect.left
|
||||
anchors.rightMargin: 0
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: keyboardRect
|
||||
x: 206
|
||||
y: 0
|
||||
width: 480
|
||||
height: 200
|
||||
color: "#252525"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 0
|
||||
|
||||
Column {
|
||||
id: column1
|
||||
width: 480
|
||||
height: 200
|
||||
|
||||
Row {
|
||||
id: row1
|
||||
width: 480
|
||||
height: 50
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
|
||||
Key {
|
||||
id: key1
|
||||
width: 44
|
||||
glyph: "q"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key2
|
||||
width: 44
|
||||
glyph: "w"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key3
|
||||
width: 44
|
||||
glyph: "e"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key4
|
||||
width: 43
|
||||
glyph: "r"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key5
|
||||
width: 43
|
||||
glyph: "t"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key6
|
||||
width: 44
|
||||
glyph: "y"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key7
|
||||
width: 44
|
||||
glyph: "u"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key8
|
||||
width: 43
|
||||
glyph: "i"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key9
|
||||
width: 42
|
||||
glyph: "o"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key10
|
||||
width: 44
|
||||
glyph: "p"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key28
|
||||
width: 45
|
||||
glyph: "←"
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: row2
|
||||
width: 480
|
||||
height: 50
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 18
|
||||
|
||||
Key {
|
||||
id: key11
|
||||
width: 43
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key12
|
||||
width: 43
|
||||
glyph: "s"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key13
|
||||
width: 43
|
||||
glyph: "d"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key14
|
||||
width: 43
|
||||
glyph: "f"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key15
|
||||
width: 43
|
||||
glyph: "g"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key16
|
||||
width: 43
|
||||
glyph: "h"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key17
|
||||
width: 43
|
||||
glyph: "j"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key18
|
||||
width: 43
|
||||
glyph: "k"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key19
|
||||
width: 43
|
||||
glyph: "l"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key32
|
||||
width: 75
|
||||
glyph: "⏎"
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: row3
|
||||
width: 480
|
||||
height: 50
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
|
||||
Key {
|
||||
id: key27
|
||||
width: 46
|
||||
glyph: "⇪"
|
||||
toggle: true
|
||||
onToggledChanged: {
|
||||
shiftMode = toggled;
|
||||
}
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key20
|
||||
width: 43
|
||||
glyph: "z"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key21
|
||||
width: 43
|
||||
glyph: "x"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key22
|
||||
width: 43
|
||||
glyph: "c"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key23
|
||||
width: 43
|
||||
glyph: "v"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key24
|
||||
width: 43
|
||||
glyph: "b"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key25
|
||||
width: 43
|
||||
glyph: "n"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key26
|
||||
width: 44
|
||||
glyph: "m"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key31
|
||||
width: 43
|
||||
glyph: ","
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key33
|
||||
width: 43
|
||||
glyph: "."
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key36
|
||||
width: 46
|
||||
glyph: "/"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Row {
|
||||
id: row4
|
||||
width: 480
|
||||
height: 50
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 19
|
||||
|
||||
Key {
|
||||
id: key30
|
||||
width: 89
|
||||
glyph: "&123"
|
||||
mouseArea.onClicked: {
|
||||
keyboardBase.parent.punctuationMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key29
|
||||
width: 285
|
||||
glyph: " "
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key34
|
||||
width: 43
|
||||
glyph: "⇦"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key35
|
||||
x: 343
|
||||
width: 43
|
||||
glyph: "⇨"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: rightRect
|
||||
y: 280
|
||||
height: 200
|
||||
color: "#252525"
|
||||
border.width: 0
|
||||
anchors.left: keyboardRect.right
|
||||
anchors.leftMargin: 0
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 0
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: rectangle1
|
||||
color: "#ffffff"
|
||||
anchors.bottom: keyboardRect.top
|
||||
anchors.bottomMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
|
||||
}
|
324
interface/resources/qml/controls/KeyboardPunctuation.qml
Normal file
|
@ -0,0 +1,324 @@
|
|||
import QtQuick 2.0
|
||||
|
||||
Item {
|
||||
id: keyboardBase
|
||||
height: 200
|
||||
Rectangle {
|
||||
id: leftRect
|
||||
y: 0
|
||||
height: 200
|
||||
color: "#252525"
|
||||
anchors.right: keyboardRect.left
|
||||
anchors.rightMargin: 0
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: keyboardRect
|
||||
x: 206
|
||||
y: 0
|
||||
width: 480
|
||||
height: 200
|
||||
color: "#252525"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 0
|
||||
|
||||
Column {
|
||||
id: column1
|
||||
width: 480
|
||||
height: 200
|
||||
|
||||
Row {
|
||||
id: row1
|
||||
width: 480
|
||||
height: 50
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
|
||||
Key {
|
||||
id: key1
|
||||
width: 43
|
||||
glyph: "1"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key2
|
||||
width: 43
|
||||
glyph: "2"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key3
|
||||
width: 43
|
||||
glyph: "3"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key4
|
||||
width: 43
|
||||
glyph: "4"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key5
|
||||
width: 43
|
||||
glyph: "5"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key6
|
||||
width: 43
|
||||
glyph: "6"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key7
|
||||
width: 43
|
||||
glyph: "7"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key8
|
||||
width: 43
|
||||
glyph: "8"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key9
|
||||
width: 43
|
||||
glyph: "9"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key10
|
||||
width: 43
|
||||
glyph: "0"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key28
|
||||
width: 50
|
||||
glyph: "←"
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: row2
|
||||
width: 480
|
||||
height: 50
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
|
||||
Key {
|
||||
id: key11
|
||||
width: 43
|
||||
glyph: "!"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key12
|
||||
width: 43
|
||||
glyph: "@"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key13
|
||||
width: 43
|
||||
glyph: "#"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key14
|
||||
width: 43
|
||||
glyph: "$"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key15
|
||||
width: 43
|
||||
glyph: "%"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key16
|
||||
width: 43
|
||||
glyph: "^"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key17
|
||||
width: 43
|
||||
glyph: "&"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key18
|
||||
width: 43
|
||||
glyph: "*"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key19
|
||||
width: 43
|
||||
glyph: "("
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key32
|
||||
width: 43
|
||||
glyph: ")"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key37
|
||||
width: 50
|
||||
glyph: "⏎"
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: row3
|
||||
width: 480
|
||||
height: 50
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 4
|
||||
|
||||
Key {
|
||||
id: key27
|
||||
width: 43
|
||||
glyph: "="
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key20
|
||||
width: 43
|
||||
glyph: "+"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key21
|
||||
width: 43
|
||||
glyph: "-"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key22
|
||||
width: 43
|
||||
glyph: "_"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key23
|
||||
width: 43
|
||||
glyph: ";"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key24
|
||||
width: 43
|
||||
glyph: ":"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key25
|
||||
width: 43
|
||||
glyph: "'"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key26
|
||||
width: 43
|
||||
glyph: "\""
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key31
|
||||
width: 43
|
||||
glyph: "<"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key33
|
||||
width: 43
|
||||
glyph: ">"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key36
|
||||
width: 43
|
||||
glyph: "?"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Row {
|
||||
id: row4
|
||||
width: 480
|
||||
height: 50
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 19
|
||||
|
||||
Key {
|
||||
id: key30
|
||||
width: 65
|
||||
glyph: "abc"
|
||||
mouseArea.onClicked: {
|
||||
keyboardBase.parent.punctuationMode = false
|
||||
}
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key29
|
||||
width: 285
|
||||
glyph: " "
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key34
|
||||
width: 43
|
||||
glyph: "⇦"
|
||||
}
|
||||
|
||||
Key {
|
||||
id: key35
|
||||
x: 343
|
||||
width: 43
|
||||
glyph: "⇨"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: rightRect
|
||||
y: 280
|
||||
height: 200
|
||||
color: "#252525"
|
||||
border.width: 0
|
||||
anchors.left: keyboardRect.right
|
||||
anchors.leftMargin: 0
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 0
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: rectangle1
|
||||
color: "#ffffff"
|
||||
anchors.bottom: keyboardRect.top
|
||||
anchors.bottomMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 0
|
||||
}
|
||||
|
||||
}
|
|
@ -1,68 +1,135 @@
|
|||
import QtQuick 2.5
|
||||
import QtWebEngine 1.1
|
||||
import QtWebChannel 1.0
|
||||
|
||||
WebEngineView {
|
||||
id: root
|
||||
property var newUrl;
|
||||
|
||||
profile.httpUserAgent: "Mozilla/5.0 Chrome (HighFidelityInterface)"
|
||||
|
||||
Component.onCompleted: {
|
||||
console.log("Connecting JS messaging to Hifi Logging")
|
||||
// Ensure the JS from the web-engine makes it to our logging
|
||||
root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
|
||||
console.log("Web Window JS message: " + sourceID + " " + lineNumber + " " + message);
|
||||
});
|
||||
Item {
|
||||
property alias url: root.url
|
||||
property alias eventBridge: eventBridgeWrapper.eventBridge
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
|
||||
QtObject {
|
||||
id: eventBridgeWrapper
|
||||
WebChannel.id: "eventBridgeWrapper"
|
||||
property var eventBridge;
|
||||
}
|
||||
|
||||
// FIXME hack to get the URL with the auth token included. Remove when we move to Qt 5.6
|
||||
Timer {
|
||||
id: urlReplacementTimer
|
||||
running: false
|
||||
repeat: false
|
||||
interval: 50
|
||||
onTriggered: url = newUrl;
|
||||
}
|
||||
WebEngineView {
|
||||
id: root
|
||||
x: 0
|
||||
y: 0
|
||||
width: parent.width
|
||||
height: keyboardRaised ? parent.height - keyboard1.height : parent.height
|
||||
|
||||
onUrlChanged: {
|
||||
var originalUrl = url.toString();
|
||||
newUrl = urlHandler.fixupUrl(originalUrl).toString();
|
||||
if (newUrl !== originalUrl) {
|
||||
root.stop();
|
||||
if (urlReplacementTimer.running) {
|
||||
console.warn("Replacement timer already running");
|
||||
return;
|
||||
}
|
||||
urlReplacementTimer.start();
|
||||
// creates a global EventBridge object.
|
||||
WebEngineScript {
|
||||
id: createGlobalEventBridge
|
||||
sourceCode: eventBridgeJavaScriptToInject
|
||||
injectionPoint: WebEngineScript.DocumentCreation
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
}
|
||||
|
||||
onFeaturePermissionRequested: {
|
||||
grantFeaturePermission(securityOrigin, feature, true);
|
||||
}
|
||||
// detects when to raise and lower virtual keyboard
|
||||
WebEngineScript {
|
||||
id: raiseAndLowerKeyboard
|
||||
injectionPoint: WebEngineScript.Deferred
|
||||
sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js"
|
||||
worldId: WebEngineScript.MainWorld
|
||||
}
|
||||
|
||||
onLoadingChanged: {
|
||||
// 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();
|
||||
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard ]
|
||||
|
||||
property string newUrl: ""
|
||||
|
||||
webChannel.registeredObjects: [eventBridgeWrapper]
|
||||
|
||||
Component.onCompleted: {
|
||||
// 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)";
|
||||
}
|
||||
|
||||
// FIXME hack to get the URL with the auth token included. Remove when we move to Qt 5.6
|
||||
Timer {
|
||||
id: urlReplacementTimer
|
||||
running: false
|
||||
repeat: false
|
||||
interval: 50
|
||||
onTriggered: url = root.newUrl;
|
||||
}
|
||||
|
||||
onUrlChanged: {
|
||||
var originalUrl = url.toString();
|
||||
root.newUrl = urlHandler.fixupUrl(originalUrl).toString();
|
||||
if (root.newUrl !== originalUrl) {
|
||||
root.stop();
|
||||
if (urlReplacementTimer.running) {
|
||||
console.warn("Replacement timer already running");
|
||||
return;
|
||||
}
|
||||
urlReplacementTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
onFeaturePermissionRequested: {
|
||||
grantFeaturePermission(securityOrigin, feature, true);
|
||||
}
|
||||
|
||||
onLoadingChanged: {
|
||||
keyboardRaised = false;
|
||||
punctuationMode = false;
|
||||
keyboard1.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onNewViewRequested:{
|
||||
if (desktop) {
|
||||
var component = Qt.createComponent("../Browser.qml");
|
||||
var newWindow = component.createObject(desktop);
|
||||
request.openIn(newWindow.webView);
|
||||
onNewViewRequested:{
|
||||
// desktop is not defined for web-entities
|
||||
if (desktop) {
|
||||
var component = Qt.createComponent("../Browser.qml");
|
||||
var newWindow = component.createObject(desktop);
|
||||
request.openIn(newWindow.webView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This breaks the webchannel used for passing messages. Fixed in Qt 5.6
|
||||
// See https://bugreports.qt.io/browse/QTBUG-49521
|
||||
//profile: desktop.browserProfile
|
||||
// virtual keyboard, letters
|
||||
Keyboard {
|
||||
id: keyboard1
|
||||
y: keyboardRaised ? parent.height : 0
|
||||
height: keyboardRaised ? 200 : 0
|
||||
visible: keyboardRaised && !punctuationMode
|
||||
enabled: keyboardRaised && !punctuationMode
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 0
|
||||
}
|
||||
|
||||
KeyboardPunctuation {
|
||||
id: keyboard2
|
||||
y: keyboardRaised ? parent.height : 0
|
||||
height: keyboardRaised ? 200 : 0
|
||||
visible: keyboardRaised && punctuationMode
|
||||
enabled: keyboardRaised && punctuationMode
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ ModalWindow {
|
|||
// Set from OffscreenUi::getOpenFile()
|
||||
property int options; // <-- FIXME unused
|
||||
|
||||
property string iconText: text !== "" ? hifi.glyphs.scriptUpload : ""
|
||||
property string iconText: root.title !== "" ? hifi.glyphs.scriptUpload : ""
|
||||
property int iconSize: 40
|
||||
|
||||
property bool selectDirectory: false;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
import Hifi 1.0
|
||||
import QtQuick 2.5
|
||||
import QtGraphicalEffects 1.0
|
||||
import "toolbars"
|
||||
import "../styles-uit"
|
||||
|
||||
Rectangle {
|
||||
|
@ -23,16 +24,13 @@ Rectangle {
|
|||
property string timestamp: "";
|
||||
property string hifiUrl: "";
|
||||
property string thumbnail: defaultThumbnail;
|
||||
property string imageUrl: "";
|
||||
property var goFunction: null;
|
||||
property string storyId: "";
|
||||
|
||||
property string timePhrase: pastTime(timestamp);
|
||||
property string actionPhrase: makeActionPhrase(action);
|
||||
property int onlineUsers: 0;
|
||||
property bool isUserStory: userName && !onlineUsers;
|
||||
|
||||
property int textPadding: 20;
|
||||
property int textPadding: 10;
|
||||
property int textSize: 24;
|
||||
property int textSizeSmall: 18;
|
||||
property string defaultThumbnail: Qt.resolvedUrl("../../images/default-domain.gif");
|
||||
|
@ -58,14 +56,6 @@ Rectangle {
|
|||
}
|
||||
return 'about a minute ago';
|
||||
}
|
||||
function makeActionPhrase(actionLabel) {
|
||||
switch (actionLabel) {
|
||||
case "snapshot":
|
||||
return "took a snapshot";
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: lobby;
|
||||
|
@ -89,6 +79,7 @@ Rectangle {
|
|||
property int dropSamples: 9;
|
||||
property int dropSpread: 0;
|
||||
DropShadow {
|
||||
visible: desktop.gradientsSupported;
|
||||
source: place;
|
||||
anchors.fill: place;
|
||||
horizontalOffset: dropHorizontalOffset;
|
||||
|
@ -99,6 +90,7 @@ Rectangle {
|
|||
spread: dropSpread;
|
||||
}
|
||||
DropShadow {
|
||||
visible: users.visible && desktop.gradientsSupported;
|
||||
source: users;
|
||||
anchors.fill: users;
|
||||
horizontalOffset: dropHorizontalOffset;
|
||||
|
@ -110,7 +102,7 @@ Rectangle {
|
|||
}
|
||||
RalewaySemiBold {
|
||||
id: place;
|
||||
text: isUserStory ? "" : placeName;
|
||||
text: placeName;
|
||||
color: hifi.colors.white;
|
||||
size: textSize;
|
||||
anchors {
|
||||
|
@ -119,14 +111,15 @@ Rectangle {
|
|||
margins: textPadding;
|
||||
}
|
||||
}
|
||||
RalewayRegular {
|
||||
FiraSansRegular {
|
||||
id: users;
|
||||
text: isUserStory ? timePhrase : (onlineUsers + ((onlineUsers === 1) ? ' person' : ' people'));
|
||||
size: textSizeSmall;
|
||||
visible: action === 'concurrency';
|
||||
text: onlineUsers;
|
||||
size: textSize;
|
||||
color: hifi.colors.white;
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
right: parent.right;
|
||||
verticalCenter: usersImage.verticalCenter;
|
||||
right: usersImage.left;
|
||||
margins: textPadding;
|
||||
}
|
||||
}
|
||||
|
@ -139,9 +132,23 @@ Rectangle {
|
|||
id: zmouseArea;
|
||||
anchors.fill: parent;
|
||||
acceptedButtons: Qt.LeftButton;
|
||||
onClicked: goFunction(parent);
|
||||
onClicked: goFunction("hifi://" + hifiUrl);
|
||||
hoverEnabled: true;
|
||||
onEntered: hoverThunk();
|
||||
onExited: unhoverThunk();
|
||||
}
|
||||
ToolbarButton {
|
||||
id: usersImage;
|
||||
imageURL: "../../images/" + action + ".svg";
|
||||
size: 32;
|
||||
onClicked: goFunction("/user_stories/" + storyId);
|
||||
buttonState: 0;
|
||||
defaultState: 0;
|
||||
hoverState: 1;
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
right: parent.right;
|
||||
margins: textPadding;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,8 +46,20 @@ OriginalDesktop.Desktop {
|
|||
}
|
||||
}
|
||||
|
||||
property var toolbars: ({})
|
||||
Component { id: toolbarBuilder; Toolbar { } }
|
||||
// This used to create sysToolbar dynamically with a call to getToolbar() within onCompleted.
|
||||
// Beginning with QT 5.6, this stopped working, as anything added to toolbars too early got
|
||||
// wiped during startup.
|
||||
Toolbar {
|
||||
id: sysToolbar;
|
||||
objectName: "com.highfidelity.interface.toolbar.system";
|
||||
// Magic: sysToolbar.x and y come from settings, and are bound before the properties specified here are applied.
|
||||
x: sysToolbar.x;
|
||||
y: sysToolbar.y;
|
||||
}
|
||||
property var toolbars: (function (map) { // answer dictionary preloaded with sysToolbar
|
||||
map[sysToolbar.objectName] = sysToolbar;
|
||||
return map; })({});
|
||||
|
||||
Component.onCompleted: {
|
||||
WebEngine.settings.javascriptCanOpenWindows = true;
|
||||
|
@ -55,7 +67,6 @@ OriginalDesktop.Desktop {
|
|||
WebEngine.settings.spatialNavigationEnabled = false;
|
||||
WebEngine.settings.localContentCanAccessRemoteUrls = true;
|
||||
|
||||
var sysToolbar = desktop.getToolbar("com.highfidelity.interface.toolbar.system");
|
||||
var toggleHudButton = sysToolbar.addButton({
|
||||
objectName: "hudToggle",
|
||||
imageURL: "../../../icons/hud.svg",
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import QtQuick 2.5
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
import "../../dialogs"
|
||||
|
||||
PreferencesDialog {
|
||||
id: root
|
||||
objectName: "NetworkingPreferencesDialog"
|
||||
title: "Networking Settings"
|
||||
showCategories: ["Networking"]
|
||||
property var settings: Settings {
|
||||
category: root.objectName
|
||||
property alias x: root.x
|
||||
property alias y: root.y
|
||||
property alias width: root.width
|
||||
property alias height: root.height
|
||||
}
|
||||
}
|
||||
|
|
@ -109,7 +109,7 @@ Decoration {
|
|||
verticalOffset: 2
|
||||
samples: 2
|
||||
color: hifi.colors.baseGrayShadow60
|
||||
visible: (window && window.focus)
|
||||
visible: (desktop.gradientsSupported && window && window.focus)
|
||||
cached: true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,7 +133,6 @@
|
|||
#include "scripting/LocationScriptingInterface.h"
|
||||
#include "scripting/MenuScriptingInterface.h"
|
||||
#include "scripting/SettingsScriptingInterface.h"
|
||||
#include "scripting/WebWindowClass.h"
|
||||
#include "scripting/WindowScriptingInterface.h"
|
||||
#include "scripting/ControllerScriptingInterface.h"
|
||||
#include "scripting/ToolbarScriptingInterface.h"
|
||||
|
@ -176,8 +175,6 @@ static const int MAX_CONCURRENT_RESOURCE_DOWNLOADS = 16;
|
|||
// For processing on QThreadPool, target 2 less than the ideal number of threads, leaving
|
||||
// 2 logical cores available for time sensitive tasks.
|
||||
static const int MIN_PROCESSING_THREAD_POOL_SIZE = 2;
|
||||
static const int PROCESSING_THREAD_POOL_SIZE = std::max(MIN_PROCESSING_THREAD_POOL_SIZE,
|
||||
QThread::idealThreadCount() - 2);
|
||||
|
||||
static const QString SNAPSHOT_EXTENSION = ".jpg";
|
||||
static const QString SVO_EXTENSION = ".svo";
|
||||
|
@ -217,7 +214,6 @@ Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTRE
|
|||
static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com";
|
||||
|
||||
const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensions {
|
||||
{ SNAPSHOT_EXTENSION, &Application::acceptSnapshot },
|
||||
{ SVO_EXTENSION, &Application::importSVOFromURL },
|
||||
{ SVO_JSON_EXTENSION, &Application::importSVOFromURL },
|
||||
{ AVA_JSON_EXTENSION, &Application::askToWearAvatarAttachmentUrl },
|
||||
|
@ -268,7 +264,7 @@ public:
|
|||
auto elapsedMovingAverage = _movingAverage.getAverage();
|
||||
|
||||
if (elapsedMovingAverage > _maxElapsedAverage) {
|
||||
qDebug() << "DEADLOCK WATCHDOG WARNING:"
|
||||
qCDebug(interfaceapp_deadlock) << "DEADLOCK WATCHDOG WARNING:"
|
||||
<< "lastHeartbeatAge:" << lastHeartbeatAge
|
||||
<< "elapsedMovingAverage:" << elapsedMovingAverage
|
||||
<< "maxElapsed:" << _maxElapsed
|
||||
|
@ -278,7 +274,7 @@ public:
|
|||
_maxElapsedAverage = elapsedMovingAverage;
|
||||
}
|
||||
if (lastHeartbeatAge > _maxElapsed) {
|
||||
qDebug() << "DEADLOCK WATCHDOG WARNING:"
|
||||
qCDebug(interfaceapp_deadlock) << "DEADLOCK WATCHDOG WARNING:"
|
||||
<< "lastHeartbeatAge:" << lastHeartbeatAge
|
||||
<< "elapsedMovingAverage:" << elapsedMovingAverage
|
||||
<< "PREVIOUS maxElapsed:" << _maxElapsed
|
||||
|
@ -288,7 +284,7 @@ public:
|
|||
_maxElapsed = lastHeartbeatAge;
|
||||
}
|
||||
if (elapsedMovingAverage > WARNING_ELAPSED_HEARTBEAT) {
|
||||
qDebug() << "DEADLOCK WATCHDOG WARNING:"
|
||||
qCDebug(interfaceapp_deadlock) << "DEADLOCK WATCHDOG WARNING:"
|
||||
<< "lastHeartbeatAge:" << lastHeartbeatAge
|
||||
<< "elapsedMovingAverage:" << elapsedMovingAverage << "** OVER EXPECTED VALUE **"
|
||||
<< "maxElapsed:" << _maxElapsed
|
||||
|
@ -297,7 +293,7 @@ public:
|
|||
}
|
||||
|
||||
if (lastHeartbeatAge > MAX_HEARTBEAT_AGE_USECS) {
|
||||
qDebug() << "DEADLOCK DETECTED -- "
|
||||
qCDebug(interfaceapp_deadlock) << "DEADLOCK DETECTED -- "
|
||||
<< "lastHeartbeatAge:" << lastHeartbeatAge
|
||||
<< "[ lastHeartbeat :" << lastHeartbeat
|
||||
<< "now:" << now << " ]"
|
||||
|
@ -403,12 +399,10 @@ static const QString STATE_GROUNDED = "Grounded";
|
|||
static const QString STATE_NAV_FOCUSED = "NavigationFocused";
|
||||
|
||||
bool setupEssentials(int& argc, char** argv) {
|
||||
unsigned int listenPort = 0; // bind to an ephemeral port by default
|
||||
const char** constArgv = const_cast<const char**>(argv);
|
||||
const char* portStr = getCmdOption(argc, constArgv, "--listenPort");
|
||||
if (portStr) {
|
||||
listenPort = atoi(portStr);
|
||||
}
|
||||
const int listenPort = portStr ? atoi(portStr) : INVALID_PORT;
|
||||
|
||||
// Set build version
|
||||
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
|
||||
|
||||
|
@ -537,7 +531,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
PluginContainer* pluginContainer = dynamic_cast<PluginContainer*>(this); // set the container for any plugins that care
|
||||
PluginManager::getInstance()->setContainer(pluginContainer);
|
||||
|
||||
QThreadPool::globalInstance()->setMaxThreadCount(PROCESSING_THREAD_POOL_SIZE);
|
||||
QThreadPool::globalInstance()->setMaxThreadCount(MIN_PROCESSING_THREAD_POOL_SIZE);
|
||||
thread()->setPriority(QThread::HighPriority);
|
||||
thread()->setObjectName("Main Thread");
|
||||
|
||||
|
@ -568,6 +562,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
_deadlockWatchdogThread->start();
|
||||
|
||||
qCDebug(interfaceapp) << "[VERSION] Build sequence:" << qPrintable(applicationVersion());
|
||||
qCDebug(interfaceapp) << "[VERSION] MODIFIED_ORGANIZATION:" << BuildInfo::MODIFIED_ORGANIZATION;
|
||||
qCDebug(interfaceapp) << "[VERSION] VERSION:" << BuildInfo::VERSION;
|
||||
qCDebug(interfaceapp) << "[VERSION] BUILD_BRANCH:" << BuildInfo::BUILD_BRANCH;
|
||||
qCDebug(interfaceapp) << "[VERSION] BUILD_GLOBAL_SERVICES:" << BuildInfo::BUILD_GLOBAL_SERVICES;
|
||||
#if USE_STABLE_GLOBAL_SERVICES
|
||||
qCDebug(interfaceapp) << "[VERSION] We will use STABLE global services.";
|
||||
#else
|
||||
qCDebug(interfaceapp) << "[VERSION] We will use DEVELOPMENT global services.";
|
||||
#endif
|
||||
|
||||
|
||||
_bookmarks = new Bookmarks(); // Before setting up the menu
|
||||
|
||||
|
@ -707,6 +711,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle);
|
||||
connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress);
|
||||
|
||||
connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateThreadPoolCount);
|
||||
|
||||
// Save avatar location immediately after a teleport.
|
||||
connect(getMyAvatar(), &MyAvatar::positionGoneTo,
|
||||
DependencyManager::get<AddressManager>().data(), &AddressManager::storeCurrentAddress);
|
||||
|
@ -1033,7 +1039,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
cameraMenuChanged();
|
||||
}
|
||||
|
||||
// set the local loopback interface for local sounds from audio scripts
|
||||
// set the local loopback interface for local sounds
|
||||
AudioInjector::setLocalAudioInterface(audioIO.data());
|
||||
AudioScriptingInterface::getInstance().setLocalAudioInterface(audioIO.data());
|
||||
|
||||
this->installEventFilter(this);
|
||||
|
@ -1233,8 +1240,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
firstRun.set(false);
|
||||
}
|
||||
|
||||
void Application::domainConnectionRefused(const QString& reasonMessage, int reasonCode) {
|
||||
switch (static_cast<DomainHandler::ConnectionRefusedReason>(reasonCode)) {
|
||||
void Application::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) {
|
||||
DomainHandler::ConnectionRefusedReason reasonCode = static_cast<DomainHandler::ConnectionRefusedReason>(reasonCodeInt);
|
||||
|
||||
if (reasonCode == DomainHandler::ConnectionRefusedReason::TooManyUsers && !extraInfo.isEmpty()) {
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(extraInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (reasonCode) {
|
||||
case DomainHandler::ConnectionRefusedReason::ProtocolMismatch:
|
||||
case DomainHandler::ConnectionRefusedReason::TooManyUsers:
|
||||
case DomainHandler::ConnectionRefusedReason::Unknown: {
|
||||
|
@ -1685,7 +1699,6 @@ void Application::paintGL() {
|
|||
Finally clearFlag([this] { _inPaint = false; });
|
||||
|
||||
_frameCount++;
|
||||
_frameCounter.increment();
|
||||
|
||||
auto lastPaintBegin = usecTimestampNow();
|
||||
PROFILE_RANGE_EX(__FUNCTION__, 0xff0000ff, (uint64_t)_frameCount);
|
||||
|
@ -1922,6 +1935,7 @@ void Application::paintGL() {
|
|||
{
|
||||
PROFILE_RANGE(__FUNCTION__ "/pluginOutput");
|
||||
PerformanceTimer perfTimer("pluginOutput");
|
||||
_frameCounter.increment();
|
||||
displayPlugin->submitFrame(frame);
|
||||
}
|
||||
|
||||
|
@ -2009,7 +2023,7 @@ void Application::resizeGL() {
|
|||
static qreal lastDevicePixelRatio = 0;
|
||||
qreal devicePixelRatio = _window->devicePixelRatio();
|
||||
if (offscreenUi->size() != fromGlm(uiSize) || devicePixelRatio != lastDevicePixelRatio) {
|
||||
qDebug() << "Device pixel ratio changed, triggering resize";
|
||||
qCDebug(interfaceapp) << "Device pixel ratio changed, triggering resize to " << uiSize;
|
||||
offscreenUi->resize(fromGlm(uiSize), true);
|
||||
_offscreenContext->makeCurrent();
|
||||
lastDevicePixelRatio = devicePixelRatio;
|
||||
|
@ -2860,6 +2874,8 @@ void Application::dragEnterEvent(QDragEnterEvent* event) {
|
|||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
// This is currently not used, but could be invoked if the user wants to go to the place embedded in an
|
||||
// Interface-taken snapshot. (It was developed for drag and drop, before we had asset-server loading or in-world browsers.)
|
||||
bool Application::acceptSnapshot(const QString& urlString) {
|
||||
QUrl url(urlString);
|
||||
QString snapshotPath = url.toLocalFile();
|
||||
|
@ -3262,17 +3278,17 @@ void Application::init() {
|
|||
|
||||
Setting::Handle<bool> firstRun { Settings::firstRun, true };
|
||||
if (addressLookupString.isEmpty() && firstRun.get()) {
|
||||
qDebug() << "First run and no URL passed... attempting to go to Home or Entry...";
|
||||
qCDebug(interfaceapp) << "First run and no URL passed... attempting to go to Home or Entry...";
|
||||
DependencyManager::get<AddressManager>()->ifLocalSandboxRunningElse([](){
|
||||
qDebug() << "Home sandbox appears to be running, going to Home.";
|
||||
qCDebug(interfaceapp) << "Home sandbox appears to be running, going to Home.";
|
||||
DependencyManager::get<AddressManager>()->goToLocalSandbox();
|
||||
},
|
||||
[](){
|
||||
qDebug() << "Home sandbox does not appear to be running, going to Entry.";
|
||||
qCDebug(interfaceapp) << "Home sandbox does not appear to be running, going to Entry.";
|
||||
DependencyManager::get<AddressManager>()->goToEntry();
|
||||
});
|
||||
} else {
|
||||
qDebug() << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
|
||||
qCDebug(interfaceapp) << "Not first run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("previous location") : addressLookupString);
|
||||
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
|
||||
}
|
||||
|
||||
|
@ -3291,7 +3307,7 @@ void Application::init() {
|
|||
|
||||
getEntities()->setEntityLoadingPriorityFunction([this](const EntityItem& item) {
|
||||
auto dims = item.getDimensions();
|
||||
auto maxSize = glm::max(dims.x, dims.y, dims.z);
|
||||
auto maxSize = glm::compMax(dims);
|
||||
|
||||
if (maxSize <= 0.0f) {
|
||||
return 0.0f;
|
||||
|
@ -4858,7 +4874,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter,
|
||||
LocationScriptingInterface::locationSetter);
|
||||
|
||||
scriptEngine->registerFunction("WebWindow", WebWindowClass::constructor, 1);
|
||||
scriptEngine->registerFunction("OverlayWebWindow", QmlWebWindowClass::constructor);
|
||||
scriptEngine->registerFunction("OverlayWindow", QmlWindowClass::constructor);
|
||||
|
||||
|
@ -5034,6 +5049,7 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
|
|||
bool Application::askToWearAvatarAttachmentUrl(const QString& url) {
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkRequest networkRequest = QNetworkRequest(url);
|
||||
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||
QNetworkReply* reply = networkAccessManager.get(networkRequest);
|
||||
int requestNumber = ++_avatarAttachmentRequest;
|
||||
|
@ -5619,7 +5635,7 @@ void Application::setActiveDisplayPlugin(const QString& pluginName) {
|
|||
void Application::handleLocalServerConnection() const {
|
||||
auto server = qobject_cast<QLocalServer*>(sender());
|
||||
|
||||
qDebug() << "Got connection on local server from additional instance - waiting for parameters";
|
||||
qCDebug(interfaceapp) << "Got connection on local server from additional instance - waiting for parameters";
|
||||
|
||||
auto socket = server->nextPendingConnection();
|
||||
|
||||
|
@ -5635,7 +5651,7 @@ void Application::readArgumentsFromLocalSocket() const {
|
|||
auto message = socket->readAll();
|
||||
socket->deleteLater();
|
||||
|
||||
qDebug() << "Read from connection: " << message;
|
||||
qCDebug(interfaceapp) << "Read from connection: " << message;
|
||||
|
||||
// If we received a message, try to open it as a URL
|
||||
if (message.length() > 0) {
|
||||
|
@ -5727,3 +5743,18 @@ void Application::sendHoverLeaveEntity(QUuid id, PointerEvent event) {
|
|||
EntityItemID entityItemID(id);
|
||||
emit getEntities()->hoverLeaveEntity(entityItemID, event);
|
||||
}
|
||||
|
||||
// FIXME? perhaps two, one for the main thread and one for the offscreen UI rendering thread?
|
||||
static const int UI_RESERVED_THREADS = 1;
|
||||
// Windows won't let you have all the cores
|
||||
static const int OS_RESERVED_THREADS = 1;
|
||||
|
||||
void Application::updateThreadPoolCount() const {
|
||||
auto reservedThreads = UI_RESERVED_THREADS + OS_RESERVED_THREADS + _displayPlugin->getRequiredThreadCount();
|
||||
auto availableThreads = QThread::idealThreadCount() - reservedThreads;
|
||||
auto threadPoolSize = std::max(MIN_PROCESSING_THREAD_POOL_SIZE, availableThreads);
|
||||
qCDebug(interfaceapp) << "Ideal Thread Count " << QThread::idealThreadCount();
|
||||
qCDebug(interfaceapp) << "Reserved threads " << reservedThreads;
|
||||
qCDebug(interfaceapp) << "Setting thread pool size to " << threadPoolSize;
|
||||
QThreadPool::globalInstance()->setMaxThreadCount(threadPoolSize);
|
||||
}
|
||||
|
|
|
@ -44,12 +44,12 @@
|
|||
#include <AbstractUriHandler.h>
|
||||
#include <shared/RateCounter.h>
|
||||
#include <ThreadSafeValueCache.h>
|
||||
#include <shared/FileLogger.h>
|
||||
|
||||
#include "avatar/MyAvatar.h"
|
||||
#include "Bookmarks.h"
|
||||
#include "Camera.h"
|
||||
#include "ConnectionMonitor.h"
|
||||
#include "FileLogger.h"
|
||||
#include "gpu/Context.h"
|
||||
#include "Menu.h"
|
||||
#include "octree/OctreePacketProcessor.h"
|
||||
|
@ -223,7 +223,7 @@ public:
|
|||
// the isHMDMode is true whenever we use the interface from an HMD and not a standard flat display
|
||||
// rendering of several elements depend on that
|
||||
// TODO: carry that information on the Camera as a setting
|
||||
bool isHMDMode() const;
|
||||
virtual bool isHMDMode() const override;
|
||||
glm::mat4 getHMDSensorPose() const;
|
||||
glm::mat4 getEyeOffset(int eye) const;
|
||||
glm::mat4 getEyeProjection(int eye) const;
|
||||
|
@ -286,6 +286,7 @@ public slots:
|
|||
bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs, const glm::vec3* givenOffset = nullptr);
|
||||
bool exportEntities(const QString& filename, float x, float y, float z, float scale);
|
||||
bool importEntities(const QString& url);
|
||||
void updateThreadPoolCount() const;
|
||||
|
||||
static void setLowVelocityFilter(bool lowVelocityFilter);
|
||||
Q_INVOKABLE void loadDialog();
|
||||
|
@ -374,7 +375,7 @@ private slots:
|
|||
void nodeKilled(SharedNodePointer node);
|
||||
static void packetSent(quint64 length);
|
||||
void updateDisplayMode();
|
||||
void domainConnectionRefused(const QString& reasonMessage, int reason);
|
||||
void domainConnectionRefused(const QString& reasonMessage, int reason, const QString& extraInfo);
|
||||
|
||||
private:
|
||||
static void initDisplay();
|
||||
|
|
|
@ -182,3 +182,16 @@ ViewFrustum Camera::toViewFrustum() const {
|
|||
loadViewFrustum(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariantMap Camera::getViewFrustum() {
|
||||
ViewFrustum frustum;
|
||||
loadViewFrustum(frustum);
|
||||
|
||||
QVariantMap result;
|
||||
result["position"].setValue(frustum.getPosition());
|
||||
result["orientation"].setValue(frustum.getOrientation());
|
||||
result["projection"].setValue(frustum.getProjection());
|
||||
result["centerRadius"].setValue(frustum.getCenterRadius());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ class Camera : public QObject {
|
|||
Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation)
|
||||
Q_PROPERTY(QString mode READ getModeString WRITE setModeString)
|
||||
Q_PROPERTY(QUuid cameraEntity READ getCameraEntity WRITE setCameraEntity)
|
||||
Q_PROPERTY(QVariantMap frustum READ getViewFrustum CONSTANT)
|
||||
|
||||
public:
|
||||
Camera();
|
||||
|
||||
|
@ -63,6 +65,8 @@ public:
|
|||
const glm::mat4& getProjection() const { return _projection; }
|
||||
void setProjection(const glm::mat4& projection);
|
||||
|
||||
QVariantMap getViewFrustum();
|
||||
|
||||
public slots:
|
||||
QString getModeString() const;
|
||||
void setModeString(const QString& mode);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <avatar/AvatarActionHold.h>
|
||||
#include <ObjectActionOffset.h>
|
||||
#include <ObjectActionSpring.h>
|
||||
#include <ObjectActionTravelOriented.h>
|
||||
#include <LogHandler.h>
|
||||
|
||||
#include "InterfaceActionFactory.h"
|
||||
|
@ -29,6 +30,8 @@ EntityActionPointer interfaceActionFactory(EntityActionType type, const QUuid& i
|
|||
return std::make_shared<ObjectActionSpring>(id, ownerEntity);
|
||||
case ACTION_TYPE_HOLD:
|
||||
return std::make_shared<AvatarActionHold>(id, ownerEntity);
|
||||
case ACTION_TYPE_TRAVEL_ORIENTED:
|
||||
return std::make_shared<ObjectActionTravelOriented>(id, ownerEntity);
|
||||
}
|
||||
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown entity action type");
|
||||
|
|
|
@ -13,3 +13,4 @@
|
|||
|
||||
Q_LOGGING_CATEGORY(interfaceapp, "hifi.interface")
|
||||
Q_LOGGING_CATEGORY(interfaceapp_timing, "hifi.interface.timing")
|
||||
Q_LOGGING_CATEGORY(interfaceapp_deadlock, "hifi.interface.deadlock")
|
||||
|
|
|
@ -16,5 +16,6 @@
|
|||
|
||||
Q_DECLARE_LOGGING_CATEGORY(interfaceapp)
|
||||
Q_DECLARE_LOGGING_CATEGORY(interfaceapp_timing)
|
||||
Q_DECLARE_LOGGING_CATEGORY(interfaceapp_deadlock)
|
||||
|
||||
#endif // hifi_InterfaceLogging_h
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
|
||||
#include "Menu.h"
|
||||
|
||||
extern bool DEV_DECIMATE_TEXTURES;
|
||||
|
||||
Menu* Menu::getInstance() {
|
||||
return dynamic_cast<Menu*>(qApp->getWindow()->menuBar());
|
||||
}
|
||||
|
@ -301,12 +303,6 @@ Menu::Menu() {
|
|||
DependencyManager::get<OffscreenUi>()->toggle(QString("hifi/dialogs/AvatarPreferencesDialog.qml"), "AvatarPreferencesDialog");
|
||||
});
|
||||
|
||||
// Settings > Audio...
|
||||
action = addActionToQMenuAndActionHash(settingsMenu, "Audio...");
|
||||
connect(action, &QAction::triggered, [] {
|
||||
DependencyManager::get<OffscreenUi>()->toggle(QString("hifi/dialogs/AudioPreferencesDialog.qml"), "AudioPreferencesDialog");
|
||||
});
|
||||
|
||||
// Settings > LOD...
|
||||
action = addActionToQMenuAndActionHash(settingsMenu, "LOD...");
|
||||
connect(action, &QAction::triggered, [] {
|
||||
|
@ -359,7 +355,7 @@ Menu::Menu() {
|
|||
//const QString = "1024 MB";
|
||||
//const QString = "2048 MB";
|
||||
|
||||
// Developer > Render > Resolution
|
||||
// Developer > Render > Maximum Texture Memory
|
||||
MenuWrapper* textureMenu = renderOptionsMenu->addMenu(MenuOption::RenderMaxTextureMemory);
|
||||
QActionGroup* textureGroup = new QActionGroup(textureMenu);
|
||||
textureGroup->setExclusive(true);
|
||||
|
@ -387,9 +383,54 @@ Menu::Menu() {
|
|||
gpu::Texture::setAllowedGPUMemoryUsage(newMaxTextureMemory);
|
||||
});
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#define MIN_CORES_FOR_INCREMENTAL_TEXTURES 5
|
||||
bool recommendedIncrementalTransfers = (QThread::idealThreadCount() >= MIN_CORES_FOR_INCREMENTAL_TEXTURES);
|
||||
bool recommendedSparseTextures = recommendedIncrementalTransfers;
|
||||
|
||||
qDebug() << "[TEXTURE TRANSFER SUPPORT]"
|
||||
<< "\n\tidealThreadCount:" << QThread::idealThreadCount()
|
||||
<< "\n\tRECOMMENDED enableSparseTextures:" << recommendedSparseTextures
|
||||
<< "\n\tRECOMMENDED enableIncrementalTextures:" << recommendedIncrementalTransfers;
|
||||
|
||||
gpu::Texture::setEnableIncrementalTextureTransfers(recommendedIncrementalTransfers);
|
||||
gpu::Texture::setEnableSparseTextures(recommendedSparseTextures);
|
||||
|
||||
// Developer > Render > Enable Dynamic Texture Management
|
||||
{
|
||||
auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableDynamicTextureManagement, 0, recommendedSparseTextures);
|
||||
connect(action, &QAction::triggered, [&](bool checked) {
|
||||
qDebug() << "[TEXTURE TRANSFER SUPPORT] --- Enable Dynamic Texture Management menu option:" << checked;
|
||||
gpu::Texture::setEnableSparseTextures(checked);
|
||||
});
|
||||
}
|
||||
|
||||
// Developer > Render > Enable Incremental Texture Transfer
|
||||
{
|
||||
auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableIncrementalTextureTransfer, 0, recommendedIncrementalTransfers);
|
||||
connect(action, &QAction::triggered, [&](bool checked) {
|
||||
qDebug() << "[TEXTURE TRANSFER SUPPORT] --- Enable Incremental Texture Transfer menu option:" << checked;
|
||||
gpu::Texture::setEnableIncrementalTextureTransfers(checked);
|
||||
});
|
||||
}
|
||||
|
||||
#else
|
||||
qDebug() << "[TEXTURE TRANSFER SUPPORT] Incremental Texture Transfer and Dynamic Texture Management not supported on this platform.";
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Developer > Render > LOD Tools
|
||||
addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, 0, dialogsManager.data(), SLOT(lodTools()));
|
||||
|
||||
// HACK enable texture decimation
|
||||
{
|
||||
auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, "Decimate Textures");
|
||||
connect(action, &QAction::triggered, [&](bool checked) {
|
||||
DEV_DECIMATE_TEXTURES = checked;
|
||||
});
|
||||
}
|
||||
|
||||
// Developer > Assets >>>
|
||||
MenuWrapper* assetDeveloperMenu = developerMenu->addMenu("Assets");
|
||||
auto& atpMigrator = ATPAssetMigrator::getInstance();
|
||||
|
@ -522,6 +563,11 @@ Menu::Menu() {
|
|||
|
||||
// Developer > Network >>>
|
||||
MenuWrapper* networkMenu = developerMenu->addMenu("Network");
|
||||
action = addActionToQMenuAndActionHash(networkMenu, MenuOption::Networking);
|
||||
connect(action, &QAction::triggered, [] {
|
||||
DependencyManager::get<OffscreenUi>()->toggle(QUrl("hifi/dialogs/NetworkingPreferencesDialog.qml"),
|
||||
"NetworkingPreferencesDialog");
|
||||
});
|
||||
addActionToQMenuAndActionHash(networkMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches()));
|
||||
addCheckableActionToQMenuAndActionHash(networkMenu,
|
||||
MenuOption::DisableActivityLogger,
|
||||
|
@ -569,6 +615,12 @@ Menu::Menu() {
|
|||
|
||||
// Developer > Audio >>>
|
||||
MenuWrapper* audioDebugMenu = developerMenu->addMenu("Audio");
|
||||
|
||||
action = addActionToQMenuAndActionHash(audioDebugMenu, "Buffers...");
|
||||
connect(action, &QAction::triggered, [] {
|
||||
DependencyManager::get<OffscreenUi>()->toggle(QString("hifi/dialogs/AudioPreferencesDialog.qml"), "AudioPreferencesDialog");
|
||||
});
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioNoiseReduction, 0, true,
|
||||
audioIO.data(), SLOT(toggleAudioNoiseReduction()));
|
||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoServerAudio, 0, false,
|
||||
|
|
|
@ -98,6 +98,8 @@ namespace MenuOption {
|
|||
const QString EchoLocalAudio = "Echo Local Audio";
|
||||
const QString EchoServerAudio = "Echo Server Audio";
|
||||
const QString EnableCharacterController = "Enable avatar collisions";
|
||||
const QString EnableIncrementalTextureTransfer = "Enable Incremental Texture Transfer";
|
||||
const QString EnableDynamicTextureManagement = "Enable Dynamic Texture Management";
|
||||
const QString EnableInverseKinematics = "Enable Inverse Kinematics";
|
||||
const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation";
|
||||
const QString ExpandMyAvatarTiming = "Expand /myAvatar";
|
||||
|
@ -129,6 +131,7 @@ namespace MenuOption {
|
|||
const QString MuteEnvironment = "Mute Environment";
|
||||
const QString MuteFaceTracking = "Mute Face Tracking";
|
||||
const QString NamesAboveHeads = "Names Above Heads";
|
||||
const QString Networking = "Networking...";
|
||||
const QString NoFaceTracking = "None";
|
||||
const QString OctreeStats = "Entity Statistics";
|
||||
const QString OnePointCalibration = "1 Point Calibration";
|
||||
|
|
|
@ -59,8 +59,6 @@ const float DISPLAYNAME_ALPHA = 1.0f;
|
|||
const float DISPLAYNAME_BACKGROUND_ALPHA = 0.4f;
|
||||
const glm::vec3 HAND_TO_PALM_OFFSET(0.0f, 0.12f, 0.08f);
|
||||
|
||||
const int SENSOR_TO_WORLD_MATRIX_INDEX = 65534;
|
||||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar) {
|
||||
return ItemKey::Builder::opaqueShape();
|
||||
|
@ -853,32 +851,54 @@ glm::vec3 Avatar::getDefaultJointTranslation(int index) const {
|
|||
}
|
||||
|
||||
glm::quat Avatar::getAbsoluteJointRotationInObjectFrame(int index) const {
|
||||
if (index == SENSOR_TO_WORLD_MATRIX_INDEX) {
|
||||
glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix();
|
||||
bool success;
|
||||
Transform avatarTransform;
|
||||
Transform::mult(avatarTransform, getParentTransform(success), getLocalTransform());
|
||||
glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix();
|
||||
return glmExtractRotation(invAvatarMat * sensorToWorldMatrix);
|
||||
} else {
|
||||
glm::quat rotation;
|
||||
_skeletonModel->getAbsoluteJointRotationInRigFrame(index, rotation);
|
||||
return Quaternions::Y_180 * rotation;
|
||||
switch(index) {
|
||||
case SENSOR_TO_WORLD_MATRIX_INDEX: {
|
||||
glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix();
|
||||
bool success;
|
||||
Transform avatarTransform;
|
||||
Transform::mult(avatarTransform, getParentTransform(success), getLocalTransform());
|
||||
glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix();
|
||||
return glmExtractRotation(invAvatarMat * sensorToWorldMatrix);
|
||||
}
|
||||
case CONTROLLER_LEFTHAND_INDEX: {
|
||||
Transform controllerLeftHandTransform = Transform(getControllerLeftHandMatrix());
|
||||
return controllerLeftHandTransform.getRotation();
|
||||
}
|
||||
case CONTROLLER_RIGHTHAND_INDEX: {
|
||||
Transform controllerRightHandTransform = Transform(getControllerRightHandMatrix());
|
||||
return controllerRightHandTransform.getRotation();
|
||||
}
|
||||
default: {
|
||||
glm::quat rotation;
|
||||
_skeletonModel->getAbsoluteJointRotationInRigFrame(index, rotation);
|
||||
return Quaternions::Y_180 * rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const {
|
||||
if (index == SENSOR_TO_WORLD_MATRIX_INDEX) {
|
||||
glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix();
|
||||
bool success;
|
||||
Transform avatarTransform;
|
||||
Transform::mult(avatarTransform, getParentTransform(success), getLocalTransform());
|
||||
glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix();
|
||||
return extractTranslation(invAvatarMat * sensorToWorldMatrix);
|
||||
} else {
|
||||
glm::vec3 translation;
|
||||
_skeletonModel->getAbsoluteJointTranslationInRigFrame(index, translation);
|
||||
return Quaternions::Y_180 * translation;
|
||||
switch(index) {
|
||||
case SENSOR_TO_WORLD_MATRIX_INDEX: {
|
||||
glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix();
|
||||
bool success;
|
||||
Transform avatarTransform;
|
||||
Transform::mult(avatarTransform, getParentTransform(success), getLocalTransform());
|
||||
glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix();
|
||||
return extractTranslation(invAvatarMat * sensorToWorldMatrix);
|
||||
}
|
||||
case CONTROLLER_LEFTHAND_INDEX: {
|
||||
Transform controllerLeftHandTransform = Transform(getControllerLeftHandMatrix());
|
||||
return controllerLeftHandTransform.getTranslation();
|
||||
}
|
||||
case CONTROLLER_RIGHTHAND_INDEX: {
|
||||
Transform controllerRightHandTransform = Transform(getControllerRightHandMatrix());
|
||||
return controllerRightHandTransform.getTranslation();
|
||||
}
|
||||
default: {
|
||||
glm::vec3 translation;
|
||||
_skeletonModel->getAbsoluteJointTranslationInRigFrame(index, translation);
|
||||
return Quaternions::Y_180 * translation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -889,6 +909,10 @@ int Avatar::getJointIndex(const QString& name) const {
|
|||
Q_RETURN_ARG(int, result), Q_ARG(const QString&, name));
|
||||
return result;
|
||||
}
|
||||
int result = getFauxJointIndex(name);
|
||||
if (result != -1) {
|
||||
return result;
|
||||
}
|
||||
return _skeletonModel->isActive() ? _skeletonModel->getFBXGeometry().getJointIndex(name) : -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,10 @@ void AvatarActionHold::prepareForPhysicsSimulation() {
|
|||
}
|
||||
|
||||
withWriteLock([&]{
|
||||
glm::vec3 avatarRigidBodyPosition;
|
||||
glm::quat avatarRigidBodyRotation;
|
||||
getAvatarRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation);
|
||||
|
||||
if (_ignoreIK) {
|
||||
return;
|
||||
}
|
||||
|
@ -70,9 +74,6 @@ void AvatarActionHold::prepareForPhysicsSimulation() {
|
|||
palmRotation = holdingAvatar->getUncachedLeftPalmRotation();
|
||||
}
|
||||
|
||||
glm::vec3 avatarRigidBodyPosition;
|
||||
glm::quat avatarRigidBodyRotation;
|
||||
getAvatarRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation);
|
||||
|
||||
// determine the difference in translation and rotation between the avatar's
|
||||
// rigid body and the palm position. The avatar's rigid body will be moved by bullet
|
||||
|
@ -124,13 +125,20 @@ bool AvatarActionHold::getTarget(float deltaTimeStep, glm::quat& rotation, glm::
|
|||
if (pose.isValid()) {
|
||||
linearVelocity = pose.getVelocity();
|
||||
angularVelocity = pose.getAngularVelocity();
|
||||
|
||||
if (isRightHand) {
|
||||
pose = avatarManager->getMyAvatar()->getRightHandControllerPoseInAvatarFrame();
|
||||
} else {
|
||||
pose = avatarManager->getMyAvatar()->getLeftHandControllerPoseInAvatarFrame();
|
||||
}
|
||||
}
|
||||
|
||||
if (_ignoreIK && pose.isValid()) {
|
||||
// We cannot ignore other avatars IK and this is not the point of this option
|
||||
// This is meant to make the grabbing behavior more reactive.
|
||||
palmPosition = pose.getTranslation();
|
||||
palmRotation = pose.getRotation();
|
||||
Transform avatarTransform;
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
avatarTransform = myAvatar->getTransform();
|
||||
palmPosition = avatarTransform.transform(pose.getTranslation() / myAvatar->getTargetScale());
|
||||
palmRotation = avatarTransform.getRotation() * pose.getRotation();
|
||||
} else {
|
||||
glm::vec3 avatarRigidBodyPosition;
|
||||
glm::quat avatarRigidBodyRotation;
|
||||
|
@ -159,11 +167,17 @@ bool AvatarActionHold::getTarget(float deltaTimeStep, glm::quat& rotation, glm::
|
|||
}
|
||||
} else { // regular avatar
|
||||
if (isRightHand) {
|
||||
palmPosition = holdingAvatar->getRightPalmPosition();
|
||||
palmRotation = holdingAvatar->getRightPalmRotation();
|
||||
Transform controllerRightTransform = Transform(holdingAvatar->getControllerRightHandMatrix());
|
||||
Transform avatarTransform = holdingAvatar->getTransform();
|
||||
palmRotation = avatarTransform.getRotation() * controllerRightTransform.getRotation();
|
||||
palmPosition = avatarTransform.getTranslation() +
|
||||
(avatarTransform.getRotation() * controllerRightTransform.getTranslation());
|
||||
} else {
|
||||
palmPosition = holdingAvatar->getLeftPalmPosition();
|
||||
palmRotation = holdingAvatar->getLeftPalmRotation();
|
||||
Transform controllerLeftTransform = Transform(holdingAvatar->getControllerLeftHandMatrix());
|
||||
Transform avatarTransform = holdingAvatar->getTransform();
|
||||
palmRotation = avatarTransform.getRotation() * controllerLeftTransform.getRotation();
|
||||
palmPosition = avatarTransform.getTranslation() +
|
||||
(avatarTransform.getRotation() * controllerLeftTransform.getTranslation());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,14 +244,19 @@ void AvatarActionHold::doKinematicUpdate(float deltaTimeStep) {
|
|||
// 3 -- ignore i of 0 1 2
|
||||
// 4 -- ignore i of 1 2 3
|
||||
// 5 -- ignore i of 2 3 4
|
||||
if ((i + 1) % AvatarActionHold::velocitySmoothFrames == _measuredLinearVelocitiesIndex ||
|
||||
(i + 2) % AvatarActionHold::velocitySmoothFrames == _measuredLinearVelocitiesIndex ||
|
||||
(i + 3) % AvatarActionHold::velocitySmoothFrames == _measuredLinearVelocitiesIndex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// This code is now disabled, but I'm leaving it commented-out because I suspect it will come back.
|
||||
// if ((i + 1) % AvatarActionHold::velocitySmoothFrames == _measuredLinearVelocitiesIndex ||
|
||||
// (i + 2) % AvatarActionHold::velocitySmoothFrames == _measuredLinearVelocitiesIndex ||
|
||||
// (i + 3) % AvatarActionHold::velocitySmoothFrames == _measuredLinearVelocitiesIndex) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
measuredLinearVelocity += _measuredLinearVelocities[i];
|
||||
}
|
||||
measuredLinearVelocity /= (float)(AvatarActionHold::velocitySmoothFrames - 3); // 3 because of the 3 we skipped, above
|
||||
measuredLinearVelocity /= (float)(AvatarActionHold::velocitySmoothFrames
|
||||
// - 3 // 3 because of the 3 we skipped, above
|
||||
);
|
||||
|
||||
if (_kinematicSetVelocity) {
|
||||
rigidBody->setLinearVelocity(glmToBullet(measuredLinearVelocity));
|
||||
|
|
|
@ -532,11 +532,21 @@ void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
|
|||
_hmdSensorFacing = getFacingDir2D(_hmdSensorOrientation);
|
||||
}
|
||||
|
||||
void MyAvatar::updateJointFromController(controller::Action poseKey, ThreadSafeValueCache<glm::mat4>& matrixCache) {
|
||||
assert(QThread::currentThread() == thread());
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
controller::Pose controllerPose = userInputMapper->getPoseState(poseKey);
|
||||
Transform transform;
|
||||
transform.setTranslation(controllerPose.getTranslation());
|
||||
transform.setRotation(controllerPose.getRotation());
|
||||
glm::mat4 controllerMatrix = transform.getMatrix();
|
||||
matrixCache.set(controllerMatrix);
|
||||
}
|
||||
|
||||
// best called at end of main loop, after physics.
|
||||
// update sensor to world matrix from current body position and hmd sensor.
|
||||
// This is so the correct camera can be used for rendering.
|
||||
void MyAvatar::updateSensorToWorldMatrix() {
|
||||
|
||||
// update the sensor mat so that the body position will end up in the desired
|
||||
// position when driven from the head.
|
||||
glm::mat4 desiredMat = createMatFromQuatAndPos(getOrientation(), getPosition());
|
||||
|
@ -545,10 +555,14 @@ void MyAvatar::updateSensorToWorldMatrix() {
|
|||
lateUpdatePalms();
|
||||
|
||||
if (_enableDebugDrawSensorToWorldMatrix) {
|
||||
DebugDraw::getInstance().addMarker("sensorToWorldMatrix", glmExtractRotation(_sensorToWorldMatrix), extractTranslation(_sensorToWorldMatrix), glm::vec4(1));
|
||||
DebugDraw::getInstance().addMarker("sensorToWorldMatrix", glmExtractRotation(_sensorToWorldMatrix),
|
||||
extractTranslation(_sensorToWorldMatrix), glm::vec4(1));
|
||||
}
|
||||
|
||||
_sensorToWorldMatrixCache.set(_sensorToWorldMatrix);
|
||||
|
||||
updateJointFromController(controller::Action::LEFT_HAND, _controllerLeftHandMatrixCache);
|
||||
updateJointFromController(controller::Action::RIGHT_HAND, _controllerRightHandMatrixCache);
|
||||
}
|
||||
|
||||
// Update avatar head rotation with sensor data
|
||||
|
@ -2215,3 +2229,31 @@ bool MyAvatar::didTeleport() {
|
|||
bool MyAvatar::hasDriveInput() const {
|
||||
return fabsf(_driveKeys[TRANSLATE_X]) > 0.0f || fabsf(_driveKeys[TRANSLATE_Y]) > 0.0f || fabsf(_driveKeys[TRANSLATE_Z]) > 0.0f;
|
||||
}
|
||||
|
||||
glm::quat MyAvatar::getAbsoluteJointRotationInObjectFrame(int index) const {
|
||||
switch(index) {
|
||||
case CONTROLLER_LEFTHAND_INDEX: {
|
||||
return getLeftHandControllerPoseInAvatarFrame().getRotation();
|
||||
}
|
||||
case CONTROLLER_RIGHTHAND_INDEX: {
|
||||
return getRightHandControllerPoseInAvatarFrame().getRotation();
|
||||
}
|
||||
default: {
|
||||
return Avatar::getAbsoluteJointRotationInObjectFrame(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 MyAvatar::getAbsoluteJointTranslationInObjectFrame(int index) const {
|
||||
switch(index) {
|
||||
case CONTROLLER_LEFTHAND_INDEX: {
|
||||
return getLeftHandControllerPoseInAvatarFrame().getTranslation();
|
||||
}
|
||||
case CONTROLLER_RIGHTHAND_INDEX: {
|
||||
return getRightHandControllerPoseInAvatarFrame().getTranslation();
|
||||
}
|
||||
default: {
|
||||
return Avatar::getAbsoluteJointTranslationInObjectFrame(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <Sound.h>
|
||||
|
||||
#include <controllers/Pose.h>
|
||||
#include <controllers/Actions.h>
|
||||
|
||||
#include "Avatar.h"
|
||||
#include "AtRestDetector.h"
|
||||
|
@ -117,6 +118,9 @@ public:
|
|||
// as it moves through the world.
|
||||
void updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix);
|
||||
|
||||
// read the location of a hand controller and save the transform
|
||||
void updateJointFromController(controller::Action poseKey, ThreadSafeValueCache<glm::mat4>& matrixCache);
|
||||
|
||||
// best called at end of main loop, just before rendering.
|
||||
// update sensor to world matrix from current body position and hmd sensor.
|
||||
// This is so the correct camera can be used for rendering.
|
||||
|
@ -270,6 +274,9 @@ public:
|
|||
Q_INVOKABLE void setCharacterControllerEnabled(bool enabled);
|
||||
Q_INVOKABLE bool getCharacterControllerEnabled();
|
||||
|
||||
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
|
||||
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
|
||||
|
||||
public slots:
|
||||
void increaseSize();
|
||||
void decreaseSize();
|
||||
|
@ -410,9 +417,8 @@ private:
|
|||
bool _useSnapTurn { true };
|
||||
bool _clearOverlayWhenMoving { true };
|
||||
|
||||
// working copy of sensorToWorldMatrix.
|
||||
// See AvatarData for thread-safe _sensorToWorldMatrixCache, used for outward facing access
|
||||
glm::mat4 _sensorToWorldMatrix;
|
||||
// working copies -- see AvatarData for thread-safe _sensorToWorldMatrixCache, used for outward facing access
|
||||
glm::mat4 _sensorToWorldMatrix { glm::mat4() };
|
||||
|
||||
// cache of the current HMD sensor position and orientation
|
||||
// in sensor space.
|
||||
|
|
|
@ -55,7 +55,7 @@ void SoftAttachmentModel::updateClusterMatrices(glm::vec3 modelPosition, glm::qu
|
|||
|
||||
// TODO: cache these look ups as an optimization
|
||||
int jointIndexOverride = getJointIndexOverride(cluster.jointIndex);
|
||||
glm::mat4 jointMatrix(glm::mat4::_null);
|
||||
glm::mat4 jointMatrix;
|
||||
if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride->getJointStateCount()) {
|
||||
jointMatrix = _rigOverride->getJointTransform(jointIndexOverride);
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// InterfaceActivity.java
|
||||
// gvr-interface/java
|
||||
//
|
||||
// Created by Stephen Birarda on 1/26/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
package io.highfidelity.gvrinterface;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.WindowManager;
|
||||
import android.util.Log;
|
||||
import org.qtproject.qt5.android.bindings.QtActivity;
|
||||
|
||||
public class InterfaceActivity extends QtActivity {
|
||||
|
||||
public static native void handleHifiURL(String hifiURLString);
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
|
||||
// Get the intent that started this activity in case we have a hifi:// URL to parse
|
||||
Intent intent = getIntent();
|
||||
if (intent.getAction() == Intent.ACTION_VIEW) {
|
||||
Uri data = intent.getData();
|
||||
|
||||
if (data.getScheme().equals("hifi")) {
|
||||
handleHifiURL(data.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,182 +0,0 @@
|
|||
//
|
||||
// WebWindowClass.cpp
|
||||
// interface/src/scripting
|
||||
//
|
||||
// Created by Ryan Huffman on 11/06/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QDockWidget>
|
||||
#include <QWebFrame>
|
||||
#include <QWebView>
|
||||
#include <QListWidget>
|
||||
#include <QStyleFactory>
|
||||
|
||||
#include "Application.h"
|
||||
#include "ui/DataWebPage.h"
|
||||
#include "MainWindow.h"
|
||||
#include "WebWindowClass.h"
|
||||
#include "WindowScriptingInterface.h"
|
||||
|
||||
ScriptEventBridge::ScriptEventBridge(QObject* parent) : QObject(parent) {
|
||||
}
|
||||
|
||||
void ScriptEventBridge::emitWebEvent(const QString& data) {
|
||||
emit webEventReceived(data);
|
||||
}
|
||||
|
||||
void ScriptEventBridge::emitScriptEvent(const QString& data) {
|
||||
emit scriptEventReceived(data);
|
||||
}
|
||||
|
||||
WebWindowClass::WebWindowClass(const QString& title, const QString& url, int width, int height)
|
||||
: QObject(NULL), _eventBridge(new ScriptEventBridge(this)) {
|
||||
auto dialogWidget = new QDialog(qApp->getWindow(), Qt::Window);
|
||||
dialogWidget->setWindowTitle(title);
|
||||
dialogWidget->resize(width, height);
|
||||
dialogWidget->installEventFilter(this);
|
||||
connect(dialogWidget, &QDialog::finished, this, &WebWindowClass::hasClosed);
|
||||
|
||||
auto layout = new QVBoxLayout(dialogWidget);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
dialogWidget->setLayout(layout);
|
||||
|
||||
_webView = new QWebView(dialogWidget);
|
||||
|
||||
layout->addWidget(_webView);
|
||||
|
||||
addEventBridgeToWindowObject();
|
||||
|
||||
_windowWidget = dialogWidget;
|
||||
|
||||
auto style = QStyleFactory::create("fusion");
|
||||
if (style) {
|
||||
_webView->setStyle(style);
|
||||
}
|
||||
|
||||
_webView->setPage(new DataWebPage());
|
||||
if (!url.startsWith("http") && !url.startsWith("file://")) {
|
||||
_webView->setUrl(QUrl::fromLocalFile(url));
|
||||
} else {
|
||||
_webView->setUrl(url);
|
||||
}
|
||||
|
||||
connect(this, &WebWindowClass::destroyed, _windowWidget, &QWidget::deleteLater);
|
||||
connect(_webView->page()->mainFrame(), &QWebFrame::javaScriptWindowObjectCleared,
|
||||
this, &WebWindowClass::addEventBridgeToWindowObject);
|
||||
}
|
||||
|
||||
WebWindowClass::~WebWindowClass() {
|
||||
}
|
||||
|
||||
bool WebWindowClass::eventFilter(QObject* sender, QEvent* event) {
|
||||
if (sender == _windowWidget) {
|
||||
if (event->type() == QEvent::Move) {
|
||||
emit moved(getPosition());
|
||||
}
|
||||
if (event->type() == QEvent::Resize) {
|
||||
emit resized(getSize());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void WebWindowClass::hasClosed() {
|
||||
emit closed();
|
||||
}
|
||||
|
||||
void WebWindowClass::addEventBridgeToWindowObject() {
|
||||
_webView->page()->mainFrame()->addToJavaScriptWindowObject("EventBridge", _eventBridge);
|
||||
}
|
||||
|
||||
void WebWindowClass::setVisible(bool visible) {
|
||||
if (visible) {
|
||||
QMetaObject::invokeMethod(_windowWidget, "showNormal", Qt::AutoConnection);
|
||||
QMetaObject::invokeMethod(_windowWidget, "raise", Qt::AutoConnection);
|
||||
}
|
||||
QMetaObject::invokeMethod(_windowWidget, "setVisible", Qt::AutoConnection, Q_ARG(bool, visible));
|
||||
}
|
||||
|
||||
void WebWindowClass::setURL(const QString& url) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setURL", Qt::AutoConnection, Q_ARG(QString, url));
|
||||
return;
|
||||
}
|
||||
_webView->setUrl(url);
|
||||
}
|
||||
|
||||
QSizeF WebWindowClass::getSize() const {
|
||||
QSizeF size = _windowWidget->size();
|
||||
return size;
|
||||
}
|
||||
|
||||
void WebWindowClass::setSize(QSizeF size) {
|
||||
setSize(size.width(), size.height());
|
||||
}
|
||||
|
||||
void WebWindowClass::setSize(int width, int height) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setSize", Qt::AutoConnection, Q_ARG(int, width), Q_ARG(int, height));
|
||||
return;
|
||||
}
|
||||
_windowWidget->resize(width, height);
|
||||
}
|
||||
|
||||
glm::vec2 WebWindowClass::getPosition() const {
|
||||
QPoint position = _windowWidget->pos();
|
||||
return glm::vec2(position.x(), position.y());
|
||||
}
|
||||
|
||||
void WebWindowClass::setPosition(glm::vec2 position) {
|
||||
setPosition(position.x, position.y);
|
||||
}
|
||||
|
||||
void WebWindowClass::setPosition(int x, int y) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setPosition", Qt::AutoConnection, Q_ARG(int, x), Q_ARG(int, y));
|
||||
return;
|
||||
}
|
||||
_windowWidget->move(x, y);
|
||||
}
|
||||
|
||||
void WebWindowClass::raise() {
|
||||
QMetaObject::invokeMethod(_windowWidget, "showNormal", Qt::AutoConnection);
|
||||
QMetaObject::invokeMethod(_windowWidget, "raise", Qt::AutoConnection);
|
||||
}
|
||||
|
||||
QScriptValue WebWindowClass::constructor(QScriptContext* context, QScriptEngine* engine) {
|
||||
WebWindowClass* retVal;
|
||||
QString file = context->argument(0).toString();
|
||||
if (context->argument(4).toBool()) {
|
||||
qWarning() << "ToolWindow views with WebWindow are no longer supported. Use OverlayWebWindow instead";
|
||||
return QScriptValue();
|
||||
} else {
|
||||
qWarning() << "WebWindow views are deprecated. Use OverlayWebWindow instead";
|
||||
}
|
||||
QMetaObject::invokeMethod(DependencyManager::get<WindowScriptingInterface>().data(), "doCreateWebWindow", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(WebWindowClass*, retVal),
|
||||
Q_ARG(const QString&, file),
|
||||
Q_ARG(QString, context->argument(1).toString()),
|
||||
Q_ARG(int, context->argument(2).toInteger()),
|
||||
Q_ARG(int, context->argument(3).toInteger()));
|
||||
|
||||
connect(engine, &QScriptEngine::destroyed, retVal, &WebWindowClass::deleteLater);
|
||||
|
||||
return engine->newQObject(retVal);
|
||||
}
|
||||
|
||||
void WebWindowClass::setTitle(const QString& title) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setTitle", Qt::AutoConnection, Q_ARG(QString, title));
|
||||
return;
|
||||
}
|
||||
_windowWidget->setWindowTitle(title);
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
//
|
||||
// WebWindowClass.h
|
||||
// interface/src/scripting
|
||||
//
|
||||
// Created by Ryan Huffman on 11/06/14.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_WebWindowClass_h
|
||||
#define hifi_WebWindowClass_h
|
||||
|
||||
#include <QScriptContext>
|
||||
#include <QScriptEngine>
|
||||
#include <QWebView>
|
||||
|
||||
class ScriptEventBridge : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScriptEventBridge(QObject* parent = NULL);
|
||||
|
||||
public slots:
|
||||
void emitWebEvent(const QString& data);
|
||||
void emitScriptEvent(const QString& data);
|
||||
|
||||
signals:
|
||||
void webEventReceived(const QString& data);
|
||||
void scriptEventReceived(const QString& data);
|
||||
|
||||
};
|
||||
|
||||
class WebWindowClass : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QObject* eventBridge READ getEventBridge)
|
||||
Q_PROPERTY(QString url READ getURL)
|
||||
Q_PROPERTY(glm::vec2 position READ getPosition WRITE setPosition);
|
||||
Q_PROPERTY(QSizeF size READ getSize WRITE setSize);
|
||||
|
||||
public:
|
||||
WebWindowClass(const QString& title, const QString& url, int width, int height);
|
||||
~WebWindowClass();
|
||||
|
||||
static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine);
|
||||
|
||||
public slots:
|
||||
void setVisible(bool visible);
|
||||
glm::vec2 getPosition() const;
|
||||
void setPosition(int x, int y);
|
||||
void setPosition(glm::vec2 position);
|
||||
QSizeF getSize() const;
|
||||
void setSize(QSizeF size);
|
||||
void setSize(int width, int height);
|
||||
QString getURL() const { return _webView->url().url(); }
|
||||
void setURL(const QString& url);
|
||||
void raise();
|
||||
ScriptEventBridge* getEventBridge() const { return _eventBridge; }
|
||||
void addEventBridgeToWindowObject();
|
||||
void setTitle(const QString& title);
|
||||
|
||||
signals:
|
||||
void visibilityChanged(bool visible); // Tool window
|
||||
void moved(glm::vec2 position);
|
||||
void resized(QSizeF size);
|
||||
void closed();
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject* sender, QEvent* event) override;
|
||||
|
||||
private slots:
|
||||
void hasClosed();
|
||||
|
||||
private:
|
||||
QWidget* _windowWidget;
|
||||
QWebView* _webView;
|
||||
ScriptEventBridge* _eventBridge;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -21,7 +21,6 @@
|
|||
#include "MainWindow.h"
|
||||
#include "Menu.h"
|
||||
#include "OffscreenUi.h"
|
||||
#include "WebWindowClass.h"
|
||||
|
||||
#include "WindowScriptingInterface.h"
|
||||
|
||||
|
@ -61,10 +60,6 @@ WindowScriptingInterface::WindowScriptingInterface() {
|
|||
});
|
||||
}
|
||||
|
||||
WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title, const QString& url, int width, int height) {
|
||||
return new WebWindowClass(title, url, width, height);
|
||||
}
|
||||
|
||||
QScriptValue WindowScriptingInterface::hasFocus() {
|
||||
return qApp->hasFocus();
|
||||
}
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
#include <QtCore/QString>
|
||||
#include <QtScript/QScriptValue>
|
||||
|
||||
class WebWindowClass;
|
||||
|
||||
|
||||
class CustomPromptResult {
|
||||
public:
|
||||
QVariant value;
|
||||
|
@ -61,13 +58,10 @@ public slots:
|
|||
signals:
|
||||
void domainChanged(const QString& domainHostname);
|
||||
void svoImportRequested(const QString& url);
|
||||
void domainConnectionRefused(const QString& reasonMessage, int reasonCode);
|
||||
void domainConnectionRefused(const QString& reasonMessage, int reasonCode, const QString& extraInfo);
|
||||
void snapshotTaken(const QString& path, bool notify);
|
||||
void snapshotShared(const QString& error);
|
||||
|
||||
private slots:
|
||||
WebWindowClass* doCreateWebWindow(const QString& title, const QString& url, int width, int height);
|
||||
|
||||
private:
|
||||
QString getPreviousBrowseLocation() const;
|
||||
void setPreviousBrowseLocation(const QString& location);
|
||||
|
|
|
@ -58,21 +58,19 @@ void AudioStatsDisplay::updatedDisplay(QString str) {
|
|||
AudioStatsDialog::AudioStatsDialog(QWidget* parent) :
|
||||
QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) {
|
||||
|
||||
_shouldShowInjectedStreams = false;
|
||||
|
||||
setWindowTitle("Audio Network Statistics");
|
||||
|
||||
|
||||
// Get statistics from the Audio Client
|
||||
_stats = &DependencyManager::get<AudioClient>()->getStats();
|
||||
|
||||
// Create layout
|
||||
_form = new QFormLayout();
|
||||
_form->setSizeConstraint(QLayout::SetFixedSize);
|
||||
QDialog::setLayout(_form);
|
||||
|
||||
// Load and initialize all channels
|
||||
renderStats();
|
||||
// Initialize channels' content (needed to correctly size channels)
|
||||
updateStats();
|
||||
|
||||
// Create channels
|
||||
_audioDisplayChannels = QVector<QVector<AudioStatsDisplay*>>(1);
|
||||
|
||||
_audioMixerID = addChannel(_form, _audioMixerStats, COLOR0);
|
||||
|
@ -80,9 +78,16 @@ AudioStatsDialog::AudioStatsDialog(QWidget* parent) :
|
|||
_upstreamMixerID = addChannel(_form, _upstreamMixerStats, COLOR2);
|
||||
_downstreamID = addChannel(_form, _downstreamStats, COLOR3);
|
||||
_upstreamInjectedID = addChannel(_form, _upstreamInjectedStats, COLOR0);
|
||||
|
||||
connect(averageUpdateTimer, SIGNAL(timeout()), this, SLOT(updateTimerTimeout()));
|
||||
averageUpdateTimer->start(1000);
|
||||
|
||||
// Initialize channels
|
||||
updateChannels();
|
||||
|
||||
// Future renders
|
||||
connect(averageUpdateTimer, SIGNAL(timeout()), this, SLOT(renderStats()));
|
||||
averageUpdateTimer->start(200);
|
||||
|
||||
// Initial render
|
||||
QDialog::setLayout(_form);
|
||||
}
|
||||
|
||||
int AudioStatsDialog::addChannel(QFormLayout* form, QVector<QString>& stats, const unsigned color) {
|
||||
|
@ -99,148 +104,152 @@ int AudioStatsDialog::addChannel(QFormLayout* form, QVector<QString>& stats, con
|
|||
return channelID;
|
||||
}
|
||||
|
||||
void AudioStatsDialog::updateStats(QVector<QString>& stats, int channelID) {
|
||||
void AudioStatsDialog::renderStats() {
|
||||
updateStats();
|
||||
updateChannels();
|
||||
}
|
||||
|
||||
void AudioStatsDialog::updateChannels() {
|
||||
updateChannel(_audioMixerStats, _audioMixerID);
|
||||
updateChannel(_upstreamClientStats, _upstreamClientID);
|
||||
updateChannel(_upstreamMixerStats, _upstreamMixerID);
|
||||
updateChannel(_downstreamStats, _downstreamID);
|
||||
updateChannel(_upstreamInjectedStats, _upstreamInjectedID);
|
||||
}
|
||||
|
||||
void AudioStatsDialog::updateChannel(QVector<QString>& stats, int channelID) {
|
||||
// Update all stat displays at specified channel
|
||||
for (int i = 0; i < stats.size(); i++)
|
||||
_audioDisplayChannels[channelID].at(i)->updatedDisplay(stats.at(i));
|
||||
}
|
||||
|
||||
void AudioStatsDialog::renderStats() {
|
||||
void AudioStatsDialog::updateStats() {
|
||||
|
||||
// Clear current stats from all vectors
|
||||
clearAllChannels();
|
||||
|
||||
double audioInputBufferLatency = 0.0,
|
||||
inputRingBufferLatency = 0.0,
|
||||
networkRoundtripLatency = 0.0,
|
||||
mixerRingBufferLatency = 0.0,
|
||||
outputRingBufferLatency = 0.0,
|
||||
audioOutputBufferLatency = 0.0;
|
||||
double audioInputBufferLatency{ 0.0 };
|
||||
double inputRingBufferLatency{ 0.0 };
|
||||
double networkRoundtripLatency{ 0.0 };
|
||||
double mixerRingBufferLatency{ 0.0 };
|
||||
double outputRingBufferLatency{ 0.0 };
|
||||
double audioOutputBufferLatency{ 0.0 };
|
||||
|
||||
AudioStreamStats downstreamAudioStreamStats = _stats->getMixerDownstreamStats();
|
||||
SharedNodePointer audioMixerNodePointer = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::AudioMixer);
|
||||
|
||||
if (!audioMixerNodePointer.isNull()) {
|
||||
audioInputBufferLatency = (double)_stats->getAudioInputMsecsReadStats().getWindowAverage();
|
||||
inputRingBufferLatency = (double)_stats->getInputRungBufferMsecsAvailableStats().getWindowAverage();
|
||||
networkRoundtripLatency = (double) audioMixerNodePointer->getPingMs();
|
||||
mixerRingBufferLatency = (double)_stats->getMixerAvatarStreamStats()._framesAvailableAverage *
|
||||
(double)AudioConstants::NETWORK_FRAME_MSECS;
|
||||
outputRingBufferLatency = (double)downstreamAudioStreamStats._framesAvailableAverage *
|
||||
(double)AudioConstants::NETWORK_FRAME_MSECS;
|
||||
audioOutputBufferLatency = (double)_stats->getAudioOutputMsecsUnplayedStats().getWindowAverage();
|
||||
if (SharedNodePointer audioMixerNodePointer = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::AudioMixer)) {
|
||||
audioInputBufferLatency = (double)_stats->getInputMsRead().getWindowMax();
|
||||
inputRingBufferLatency = (double)_stats->getInputMsUnplayed().getWindowMax();
|
||||
networkRoundtripLatency = (double)audioMixerNodePointer->getPingMs();
|
||||
mixerRingBufferLatency = (double)_stats->getMixerAvatarStreamStats()._unplayedMs;
|
||||
outputRingBufferLatency = (double)_stats->getMixerDownstreamStats()._unplayedMs;
|
||||
audioOutputBufferLatency = (double)_stats->getOutputMsUnplayed().getWindowMax();
|
||||
}
|
||||
|
||||
double totalLatency = audioInputBufferLatency + inputRingBufferLatency + networkRoundtripLatency + mixerRingBufferLatency
|
||||
+ outputRingBufferLatency + audioOutputBufferLatency;
|
||||
|
||||
QString stats = "Audio input buffer: %1ms - avg msecs of samples read to the audio input buffer in last 10s";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number(audioInputBufferLatency, 'f', 2)));
|
||||
double totalLatency = audioInputBufferLatency + inputRingBufferLatency + mixerRingBufferLatency
|
||||
+ outputRingBufferLatency + audioOutputBufferLatency + networkRoundtripLatency;
|
||||
|
||||
stats = "Input ring buffer: %1ms - avg msecs of samples read to the input ring buffer in last 10s";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number(inputRingBufferLatency, 'f', 2)));
|
||||
stats = "Network to mixer: %1ms - half of last ping value calculated by the node list";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number((networkRoundtripLatency / 2.0), 'f', 2)));
|
||||
stats = "Network to client: %1ms - half of last ping value calculated by the node list";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number((mixerRingBufferLatency / 2.0),'f', 2)));
|
||||
stats = "Output ring buffer: %1ms - avg msecs of samples in output ring buffer in last 10s";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number(outputRingBufferLatency,'f', 2)));
|
||||
stats = "Audio output buffer: %1ms - avg msecs of samples in audio output buffer in last 10s";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number(mixerRingBufferLatency,'f', 2)));
|
||||
stats = "TOTAL: %1ms - avg msecs of samples in audio output buffer in last 10s";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number(totalLatency, 'f', 2)));
|
||||
QString stats;
|
||||
_audioMixerStats.push_back("PIPELINE (averaged over the past 10s)");
|
||||
stats = "Input Read:\t%1 ms";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number(audioInputBufferLatency, 'f', 0)));
|
||||
stats = "Input Ring:\t%1 ms";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number(inputRingBufferLatency, 'f', 0)));
|
||||
stats = "Network (client->mixer):\t%1 ms";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number(networkRoundtripLatency / 2, 'f', 0)));
|
||||
stats = "Mixer Ring:\t%1 ms";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number(mixerRingBufferLatency, 'f', 0)));
|
||||
stats = "Network (mixer->client):\t%1 ms";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number(networkRoundtripLatency / 2, 'f', 0)));
|
||||
stats = "Output Ring:\t%1 ms";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number(outputRingBufferLatency, 'f', 0)));
|
||||
stats = "Output Read:\t%1 ms";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number(audioOutputBufferLatency, 'f', 0)));
|
||||
stats = "TOTAL:\t%1 ms";
|
||||
_audioMixerStats.push_back(stats.arg(QString::number(totalLatency, 'f', 0)));
|
||||
|
||||
|
||||
const MovingMinMaxAvg<quint64>& packetSentTimeGaps = _stats->getPacketSentTimeGaps();
|
||||
const MovingMinMaxAvg<quint64>& packetSentTimeGaps = _stats->getPacketTimegaps();
|
||||
|
||||
_upstreamClientStats.push_back("\nUpstream Mic Audio Packets Sent Gaps (by client):");
|
||||
|
||||
stats = "Inter-packet timegaps (overall) | min: %1, max: %2, avg: %3";
|
||||
stats = "Inter-packet timegaps";
|
||||
_upstreamClientStats.push_back(stats);
|
||||
stats = "overall min:\t%1, max:\t%2, avg:\t%3";
|
||||
stats = stats.arg(formatUsecTime(packetSentTimeGaps.getMin()),
|
||||
formatUsecTime(packetSentTimeGaps.getMax()),
|
||||
formatUsecTime(packetSentTimeGaps.getAverage()));
|
||||
_upstreamClientStats.push_back(stats);
|
||||
|
||||
stats = "Inter-packet timegaps (last 30s) | min: %1, max: %2, avg: %3";
|
||||
stats = "last window min:\t%1, max:\t%2, avg:\t%3";
|
||||
stats = stats.arg(formatUsecTime(packetSentTimeGaps.getWindowMin()),
|
||||
formatUsecTime(packetSentTimeGaps.getWindowMax()),
|
||||
formatUsecTime(packetSentTimeGaps.getWindowAverage()));
|
||||
_upstreamClientStats.push_back(stats);
|
||||
|
||||
_upstreamMixerStats.push_back("\nUpstream mic audio stats (received and reported by audio-mixer):");
|
||||
_upstreamMixerStats.push_back("\nMIXER STREAM");
|
||||
_upstreamMixerStats.push_back("(this client's remote mixer stream performance)");
|
||||
|
||||
renderAudioStreamStats(&_stats->getMixerAvatarStreamStats(), &_upstreamMixerStats, true);
|
||||
renderAudioStreamStats(&_stats->getMixerAvatarStreamStats(), &_upstreamMixerStats);
|
||||
|
||||
_downstreamStats.push_back("\nDownstream mixed audio stats:");
|
||||
_downstreamStats.push_back("\nCLIENT STREAM");
|
||||
|
||||
AudioStreamStats downstreamStats = _stats->getMixerDownstreamStats();
|
||||
|
||||
renderAudioStreamStats(&downstreamStats, &_downstreamStats, true);
|
||||
renderAudioStreamStats(&downstreamStats, &_downstreamStats);
|
||||
|
||||
|
||||
if (_shouldShowInjectedStreams) {
|
||||
|
||||
foreach(const AudioStreamStats& injectedStreamAudioStats, _stats->getMixerInjectedStreamStatsMap()) {
|
||||
stats = "\nUpstream injected audio stats: stream ID: %1";
|
||||
stats = "\nINJECTED STREAM (ID: %1)";
|
||||
stats = stats.arg(injectedStreamAudioStats._streamIdentifier.toString());
|
||||
_upstreamInjectedStats.push_back(stats);
|
||||
|
||||
renderAudioStreamStats(&injectedStreamAudioStats, &_upstreamInjectedStats, true);
|
||||
renderAudioStreamStats(&injectedStreamAudioStats, &_upstreamInjectedStats);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AudioStatsDialog::renderAudioStreamStats(const AudioStreamStats* streamStats, QVector<QString>* audioStreamStats, bool isDownstreamStats) {
|
||||
void AudioStatsDialog::renderAudioStreamStats(const AudioStreamStats* streamStats, QVector<QString>* audioStreamStats) {
|
||||
|
||||
QString stats = "Packet loss | overall: %1% (%2 lost), last_30s: %3% (%4 lost)";
|
||||
QString stats = "Packet Loss";
|
||||
audioStreamStats->push_back(stats);
|
||||
stats = "overall:\t%1%\t(%2 lost), window:\t%3%\t(%4 lost)";
|
||||
stats = stats.arg(QString::number((int)(streamStats->_packetStreamStats.getLostRate() * 100.0f)),
|
||||
QString::number((int)(streamStats->_packetStreamStats._lost)),
|
||||
QString::number((int)(streamStats->_packetStreamWindowStats.getLostRate() * 100.0f)),
|
||||
QString::number((int)(streamStats->_packetStreamWindowStats._lost)));
|
||||
QString::number((int)(streamStats->_packetStreamStats._lost)),
|
||||
QString::number((int)(streamStats->_packetStreamWindowStats.getLostRate() * 100.0f)),
|
||||
QString::number((int)(streamStats->_packetStreamWindowStats._lost)));
|
||||
audioStreamStats->push_back(stats);
|
||||
|
||||
if (isDownstreamStats) {
|
||||
stats = "Ringbuffer frames | desired: %1, avg_available(10s): %2 + %3, available: %4 + %5";
|
||||
stats = stats.arg(QString::number(streamStats->_desiredJitterBufferFrames),
|
||||
QString::number(streamStats->_framesAvailableAverage),
|
||||
QString::number((int)((float)_stats->getAudioInputMsecsReadStats().getWindowAverage() /
|
||||
AudioConstants::NETWORK_FRAME_MSECS)),
|
||||
QString::number(streamStats->_framesAvailable),
|
||||
QString::number((int)(_stats->getAudioOutputMsecsUnplayedStats().getCurrentIntervalLastSample() /
|
||||
AudioConstants::NETWORK_FRAME_MSECS)));
|
||||
audioStreamStats->push_back(stats);
|
||||
} else {
|
||||
stats = "Ringbuffer frames | desired: %1, avg_available(10s): %2, available: %3";
|
||||
stats = stats.arg(QString::number(streamStats->_desiredJitterBufferFrames),
|
||||
QString::number(streamStats->_framesAvailableAverage),
|
||||
QString::number(streamStats->_framesAvailable));
|
||||
audioStreamStats->push_back(stats);
|
||||
}
|
||||
|
||||
|
||||
stats = "Ringbuffer stats | starves: %1, prev_starve_lasted: %2, frames_dropped: %3, overflows: %4";
|
||||
stats = "Ringbuffer";
|
||||
audioStreamStats->push_back(stats);
|
||||
stats = "available frames (avg):\t%1\t(%2), desired:\t%3";
|
||||
stats = stats.arg(QString::number(streamStats->_framesAvailable),
|
||||
QString::number(streamStats->_framesAvailableAverage),
|
||||
QString::number(streamStats->_desiredJitterBufferFrames));
|
||||
audioStreamStats->push_back(stats);
|
||||
stats = "starves:\t%1, last starve duration:\t%2, drops:\t%3, overflows:\t%4";
|
||||
stats = stats.arg(QString::number(streamStats->_starveCount),
|
||||
QString::number(streamStats->_consecutiveNotMixedCount),
|
||||
QString::number(streamStats->_framesDropped),
|
||||
QString::number(streamStats->_overflowCount));
|
||||
QString::number(streamStats->_consecutiveNotMixedCount),
|
||||
QString::number(streamStats->_framesDropped),
|
||||
QString::number(streamStats->_overflowCount));
|
||||
audioStreamStats->push_back(stats);
|
||||
|
||||
stats = "Inter-packet timegaps";
|
||||
audioStreamStats->push_back(stats);
|
||||
|
||||
stats = "Inter-packet timegaps (overall) | min: %1, max: %2, avg: %3";
|
||||
stats = "overall min:\t%1, max:\t%2, avg:\t%3";
|
||||
stats = stats.arg(formatUsecTime(streamStats->_timeGapMin),
|
||||
formatUsecTime(streamStats->_timeGapMax),
|
||||
formatUsecTime(streamStats->_timeGapAverage));
|
||||
formatUsecTime(streamStats->_timeGapMax),
|
||||
formatUsecTime(streamStats->_timeGapAverage));
|
||||
audioStreamStats->push_back(stats);
|
||||
|
||||
|
||||
stats = "Inter-packet timegaps (last 30s) | min: %1, max: %2, avg: %3";
|
||||
stats = "last window min:\t%1, max:\t%2, avg:\t%3";
|
||||
stats = stats.arg(formatUsecTime(streamStats->_timeGapWindowMin),
|
||||
formatUsecTime(streamStats->_timeGapWindowMax),
|
||||
formatUsecTime(streamStats->_timeGapWindowAverage));
|
||||
formatUsecTime(streamStats->_timeGapWindowMax),
|
||||
formatUsecTime(streamStats->_timeGapWindowAverage));
|
||||
audioStreamStats->push_back(stats);
|
||||
|
||||
}
|
||||
|
||||
void AudioStatsDialog::clearAllChannels() {
|
||||
|
@ -251,21 +260,6 @@ void AudioStatsDialog::clearAllChannels() {
|
|||
_upstreamInjectedStats.clear();
|
||||
}
|
||||
|
||||
|
||||
void AudioStatsDialog::updateTimerTimeout() {
|
||||
|
||||
renderStats();
|
||||
|
||||
// Update all audio stats
|
||||
updateStats(_audioMixerStats, _audioMixerID);
|
||||
updateStats(_upstreamClientStats, _upstreamClientID);
|
||||
updateStats(_upstreamMixerStats, _upstreamMixerID);
|
||||
updateStats(_downstreamStats, _downstreamID);
|
||||
updateStats(_upstreamInjectedStats, _upstreamInjectedID);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void AudioStatsDialog::paintEvent(QPaintEvent* event) {
|
||||
|
||||
// Repaint each stat in each channel
|
||||
|
|
|
@ -70,18 +70,18 @@ private:
|
|||
|
||||
QVector<QVector<AudioStatsDisplay*>> _audioDisplayChannels;
|
||||
|
||||
void updateStats();
|
||||
int addChannel(QFormLayout* form, QVector<QString>& stats, const unsigned color);
|
||||
void updateStats(QVector<QString>& stats, const int channelID);
|
||||
void renderStats();
|
||||
void updateChannel(QVector<QString>& stats, const int channelID);
|
||||
void updateChannels();
|
||||
void clearAllChannels();
|
||||
void renderAudioStreamStats(const AudioStreamStats* streamStats, QVector<QString>* audioStreamstats, bool isDownstreamStats);
|
||||
void renderAudioStreamStats(const AudioStreamStats* streamStats, QVector<QString>* audioStreamstats);
|
||||
|
||||
|
||||
const AudioIOStats* _stats;
|
||||
QFormLayout* _form;
|
||||
|
||||
bool _isEnabled;
|
||||
bool _shouldShowInjectedStreams;
|
||||
bool _shouldShowInjectedStreams{ false };
|
||||
|
||||
|
||||
signals:
|
||||
|
@ -93,7 +93,7 @@ signals:
|
|||
|
||||
|
||||
void reject() override;
|
||||
void updateTimerTimeout();
|
||||
void renderStats();
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -58,7 +58,10 @@ void CachesSizeDialog::confirmClicked(bool checked) {
|
|||
DependencyManager::get<AnimationCache>()->setUnusedResourceCacheSize(_animations->value() * BYTES_PER_MEGABYTES);
|
||||
DependencyManager::get<ModelCache>()->setUnusedResourceCacheSize(_geometries->value() * BYTES_PER_MEGABYTES);
|
||||
DependencyManager::get<SoundCache>()->setUnusedResourceCacheSize(_sounds->value() * BYTES_PER_MEGABYTES);
|
||||
// Disabling the texture cache because it's a liability in cases where we're overcommiting GPU memory
|
||||
#if 0
|
||||
DependencyManager::get<TextureCache>()->setUnusedResourceCacheSize(_textures->value() * BYTES_PER_MEGABYTES);
|
||||
#endif
|
||||
|
||||
QDialog::close();
|
||||
}
|
||||
|
@ -78,4 +81,4 @@ void CachesSizeDialog::reject() {
|
|||
void CachesSizeDialog::closeEvent(QCloseEvent* event) {
|
||||
QDialog::closeEvent(event);
|
||||
emit closed();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
//
|
||||
// DataWebPage.cpp
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-09-22.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <qnetworkrequest.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include <AddressManager.h>
|
||||
#include <OAuthNetworkAccessManager.h>
|
||||
|
||||
#include "DataWebPage.h"
|
||||
|
||||
DataWebPage::DataWebPage(QObject* parent) :
|
||||
QWebPage(parent)
|
||||
{
|
||||
// use an OAuthNetworkAccessManager instead of regular QNetworkAccessManager so our requests are authed
|
||||
setNetworkAccessManager(OAuthNetworkAccessManager::getInstance());
|
||||
|
||||
// give the page an empty stylesheet
|
||||
settings()->setUserStyleSheetUrl(QUrl());
|
||||
}
|
||||
|
||||
void DataWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID) {
|
||||
qDebug() << "JS console message at line" << lineNumber << "from" << sourceID << "-" << message;
|
||||
}
|
||||
|
||||
bool DataWebPage::acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, QWebPage::NavigationType type) {
|
||||
// Handle hifi:// links and links to files with particular extensions
|
||||
QString urlString = request.url().toString();
|
||||
if (qApp->canAcceptURL(urlString)) {
|
||||
if (qApp->acceptURL(urlString)) {
|
||||
return false; // we handled it, so QWebPage doesn't need to handle it
|
||||
}
|
||||
}
|
||||
|
||||
// Make hyperlinks with target="_blank" open in user's Web browser
|
||||
if (type == QWebPage::NavigationTypeLinkClicked && frame == nullptr) {
|
||||
qApp->openUrl(request.url());
|
||||
return false; // We handled it.
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString DataWebPage::userAgentForUrl(const QUrl& url) const {
|
||||
return HIGH_FIDELITY_USER_AGENT;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
//
|
||||
// DataWebPage.h
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Stephen Birarda on 2014-09-22.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_DataWebPage_h
|
||||
#define hifi_DataWebPage_h
|
||||
|
||||
#include <qwebpage.h>
|
||||
|
||||
class DataWebPage : public QWebPage {
|
||||
public:
|
||||
DataWebPage(QObject* parent = 0);
|
||||
protected:
|
||||
void javaScriptConsoleMessage(const QString & message, int lineNumber, const QString & sourceID) override;
|
||||
bool acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, QWebPage::NavigationType type) override;
|
||||
virtual QString userAgentForUrl(const QUrl& url) const override;
|
||||
};
|
||||
|
||||
#endif // hifi_DataWebPage_h
|
|
@ -20,7 +20,7 @@
|
|||
#include <QCheckBox>
|
||||
#include <QSyntaxHighlighter>
|
||||
|
||||
#include "AbstractLoggerInterface.h"
|
||||
#include <shared/AbstractLoggerInterface.h>
|
||||
|
||||
class KeywordHighlighter : public QSyntaxHighlighter {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -228,6 +228,7 @@ void ModelHandler::update() {
|
|||
QUrl url(_model.item(i,0)->data(Qt::UserRole).toString());
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkRequest request(url);
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||
QNetworkReply* reply = networkAccessManager.head(request);
|
||||
connect(reply, SIGNAL(finished()), SLOT(downloadFinished()));
|
||||
|
@ -280,6 +281,7 @@ void ModelHandler::queryNewFiles(QString marker) {
|
|||
url.setQuery(query);
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkRequest request(url);
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||
QNetworkReply* reply = networkAccessManager.get(request);
|
||||
connect(reply, SIGNAL(finished()), SLOT(downloadFinished()));
|
||||
|
|
|
@ -188,95 +188,52 @@ void setupPreferences() {
|
|||
|
||||
static const QString AUDIO("Audio");
|
||||
{
|
||||
auto getter = []()->bool { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getDynamicJitterBuffers(); };
|
||||
auto setter = [](bool value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setDynamicJitterBuffers(value); };
|
||||
preferences->addPreference(new CheckPreference(AUDIO, "Enable dynamic jitter buffers", getter, setter));
|
||||
auto getter = []()->bool { return !DependencyManager::get<AudioClient>()->getReceivedAudioStream().dynamicJitterBufferEnabled(); };
|
||||
auto setter = [](bool value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setDynamicJitterBufferEnabled(!value); };
|
||||
auto preference = new CheckPreference(AUDIO, "Disable dynamic jitter buffer", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getDesiredJitterBufferFrames(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setStaticDesiredJitterBufferFrames(value); };
|
||||
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getStaticJitterBufferFrames(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setStaticJitterBufferFrames(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Static jitter buffer frames", getter, setter);
|
||||
preference->setMin(0);
|
||||
preference->setMax(10000);
|
||||
preference->setMax(2000);
|
||||
preference->setStep(1);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getMaxFramesOverDesired(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setMaxFramesOverDesired(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Max frames over desired", getter, setter);
|
||||
preference->setMax(10000);
|
||||
preference->setStep(1);
|
||||
auto getter = []()->bool { return !DependencyManager::get<AudioClient>()->getOutputStarveDetectionEnabled(); };
|
||||
auto setter = [](bool value) { DependencyManager::get<AudioClient>()->setOutputStarveDetectionEnabled(!value); };
|
||||
auto preference = new CheckPreference(AUDIO, "Disable output starve detection", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = []()->bool { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getUseStDevForJitterCalc(); };
|
||||
auto setter = [](bool value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setUseStDevForJitterCalc(value); };
|
||||
preferences->addPreference(new CheckPreference(AUDIO, "Use standard deviation for dynamic jitter calc", getter, setter));
|
||||
}
|
||||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getWindowStarveThreshold(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setWindowStarveThreshold(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Window A starve threshold", getter, setter);
|
||||
preference->setMax(10000);
|
||||
preference->setStep(1);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getWindowSecondsForDesiredCalcOnTooManyStarves(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setWindowSecondsForDesiredCalcOnTooManyStarves(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Window A (raise desired on N starves) seconds", getter, setter);
|
||||
preference->setMax(10000);
|
||||
preference->setStep(1);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getWindowSecondsForDesiredReduction(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setWindowSecondsForDesiredReduction(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Window B (desired ceiling) seconds", getter, setter);
|
||||
preference->setMax(10000);
|
||||
preference->setStep(1);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = []()->bool { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getRepetitionWithFade(); };
|
||||
auto setter = [](bool value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setRepetitionWithFade(value); };
|
||||
preferences->addPreference(new CheckPreference(AUDIO, "Repetition with fade", getter, setter));
|
||||
}
|
||||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getOutputBufferSize(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->setOutputBufferSize(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Output buffer initial size (frames)", getter, setter);
|
||||
preference->setMin(1);
|
||||
preference->setMax(20);
|
||||
auto preference = new SpinnerPreference(AUDIO, "Output buffer initial frames", getter, setter);
|
||||
preference->setMin(AudioClient::MIN_BUFFER_FRAMES);
|
||||
preference->setMax(AudioClient::MAX_BUFFER_FRAMES);
|
||||
preference->setStep(1);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
#if DEV_BUILD || PR_BUILD
|
||||
{
|
||||
auto getter = []()->bool { return DependencyManager::get<AudioClient>()->getOutputStarveDetectionEnabled(); };
|
||||
auto setter = [](bool value) { DependencyManager::get<AudioClient>()->setOutputStarveDetectionEnabled(value); };
|
||||
auto preference = new CheckPreference(AUDIO, "Output starve detection (automatic buffer size increase)", getter, setter);
|
||||
auto getter = []()->bool { return DependencyManager::get<AudioClient>()->isSimulatingJitter(); };
|
||||
auto setter = [](bool value) { return DependencyManager::get<AudioClient>()->setIsSimulatingJitter(value); };
|
||||
auto preference = new CheckPreference(AUDIO, "Packet jitter simulator", getter, setter);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getOutputStarveDetectionThreshold(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->setOutputStarveDetectionThreshold(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Output starve detection threshold", getter, setter);
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getGateThreshold(); };
|
||||
auto setter = [](float value) { return DependencyManager::get<AudioClient>()->setGateThreshold(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Packet throttle threshold", getter, setter);
|
||||
preference->setMin(1);
|
||||
preference->setMax(500);
|
||||
preference->setStep(1);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = []()->float { return DependencyManager::get<AudioClient>()->getOutputStarveDetectionPeriod(); };
|
||||
auto setter = [](float value) { DependencyManager::get<AudioClient>()->setOutputStarveDetectionPeriod(value); };
|
||||
auto preference = new SpinnerPreference(AUDIO, "Output starve detection period (ms)", getter, setter);
|
||||
preference->setMin(1);
|
||||
preference->setMax((float)999999999);
|
||||
preference->setMax(200);
|
||||
preference->setStep(1);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
auto getter = []()->float { return qApp->getMaxOctreePacketsPerSecond(); };
|
||||
|
@ -332,4 +289,19 @@ void setupPreferences() {
|
|||
preferences->addPreference(preference);
|
||||
}
|
||||
}
|
||||
{
|
||||
static const QString RENDER("Networking");
|
||||
|
||||
auto nodelist = DependencyManager::get<NodeList>();
|
||||
{
|
||||
static const int MIN_PORT_NUMBER { 0 };
|
||||
static const int MAX_PORT_NUMBER { 65535 };
|
||||
auto getter = [nodelist] { return static_cast<int>(nodelist->getSocketLocalPort()); };
|
||||
auto setter = [nodelist](int preset) { nodelist->setSocketLocalPort(static_cast<quint16>(preset)); };
|
||||
auto preference = new IntSpinnerPreference(RENDER, "Listening Port", getter, setter);
|
||||
preference->setMin(MIN_PORT_NUMBER);
|
||||
preference->setMax(MAX_PORT_NUMBER);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,6 +161,7 @@ void ScriptEditorWidget::loadFile(const QString& scriptPath) {
|
|||
} else {
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkRequest networkRequest = QNetworkRequest(url);
|
||||
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||
QNetworkReply* reply = networkAccessManager.get(networkRequest);
|
||||
qDebug() << "Downloading included script at" << scriptPath;
|
||||
|
|