mirror of
https://github.com/overte-org/overte.git
synced 2025-04-07 14:12:26 +02:00
Merge branch 'master' into short-id
This commit is contained in:
commit
9d06890aea
534 changed files with 14515 additions and 7511 deletions
8
BUILD.md
8
BUILD.md
|
@ -1,7 +1,7 @@
|
|||
### Dependencies
|
||||
|
||||
- [cmake](https://cmake.org/download/): 3.9
|
||||
- [Qt](https://www.qt.io/download-open-source): 5.9.1
|
||||
- [Qt](https://www.qt.io/download-open-source): 5.10.1
|
||||
- [OpenSSL](https://www.openssl.org/): Use the latest available 1.0 version (**NOT** 1.1) of OpenSSL to avoid security vulnerabilities.
|
||||
- [VHACD](https://github.com/virneo/v-hacd)(clone this repository)(Optional)
|
||||
|
||||
|
@ -46,8 +46,8 @@ This can either be entered directly into your shell session before you build or
|
|||
|
||||
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.6.2/clang_64/lib/cmake/
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.6.2/lib/cmake
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.10.1/clang_64/lib/cmake/
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.10.1/lib/cmake
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake
|
||||
|
||||
#### Generating build files
|
||||
|
@ -66,7 +66,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.6.2/lib/cmake
|
||||
cmake .. -DQT_CMAKE_PREFIX_PATH=/usr/local/qt/5.10.1/lib/cmake
|
||||
|
||||
#### Finding Dependencies
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ Should you choose not to install Qt5 via a package manager that handles dependen
|
|||
|
||||
Install qt:
|
||||
```bash
|
||||
wget http://debian.highfidelity.com/pool/h/hi/hifi-qt5.6.1_5.6.1_amd64.deb
|
||||
sudo dpkg -i hifi-qt5.6.1_5.6.1_amd64.deb
|
||||
wget http://debian.highfidelity.com/pool/h/hi/hifiqt5.10.1_5.10.1_amd64.deb
|
||||
sudo dpkg -i hifiqt5.10.1_5.10.1_amd64.deb
|
||||
```
|
||||
|
||||
Install build dependencies:
|
||||
|
@ -66,7 +66,7 @@ cd hifi/build
|
|||
|
||||
Prepare makefiles:
|
||||
```bash
|
||||
cmake -DQT_CMAKE_PREFIX_PATH=/usr/local/Qt5.6.1/5.6/gcc_64/lib/cmake ..
|
||||
cmake -DQT_CMAKE_PREFIX_PATH=/usr/local/Qt5.10.1/5.10/gcc_64/lib/cmake ..
|
||||
```
|
||||
|
||||
Start compilation and get a cup of coffee:
|
||||
|
@ -74,7 +74,7 @@ Start compilation and get a cup of coffee:
|
|||
make domain-server assignment-client interface
|
||||
```
|
||||
|
||||
In a server does not make sense to compile interface
|
||||
In a server does not make sense to compile interface
|
||||
|
||||
### Running the software
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ Note that this uses the version from the homebrew formula at the time of this wr
|
|||
Assuming you've installed Qt using the homebrew instructions above, you'll need to set QT_CMAKE_PREFIX_PATH so CMake can find your installations.
|
||||
For Qt installed via homebrew, set QT_CMAKE_PREFIX_PATH:
|
||||
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt/5.9.1/lib/cmake
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt/5.10.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.
|
||||
|
||||
|
|
20
BUILD_WIN.md
20
BUILD_WIN.md
|
@ -1,13 +1,13 @@
|
|||
This is a stand-alone guide for creating your first High Fidelity build for Windows 64-bit.
|
||||
|
||||
## Building High Fidelity
|
||||
Note: We are now using Visual Studio 2017 and Qt 5.9.1. If you are upgrading from Visual Studio 2013 and Qt 5.6.2, do a clean uninstall of those versions before going through this guide.
|
||||
Note: We are now using Visual Studio 2017 and Qt 5.10.1. If you are upgrading from Visual Studio 2013 and Qt 5.6.2, do a clean uninstall of those versions before going through this guide.
|
||||
|
||||
Note: The prerequisites will require about 10 GB of space on your drive. You will also need a system with at least 8GB of main memory.
|
||||
|
||||
### Step 1. Visual Studio 2017
|
||||
|
||||
If you don’t have Community or Professional edition of Visual Studio 2017, download [Visual Studio Community 2017](https://www.visualstudio.com/downloads/).
|
||||
If you don’t have Community or Professional edition of Visual Studio 2017, download [Visual Studio Community 2017](https://www.visualstudio.com/downloads/).
|
||||
|
||||
When selecting components, check "Desktop development with C++." Also check "Windows 8.1 SDK and UCRT SDK" and "VC++ 2015.3 v140 toolset (x86,x64)" on the Summary toolbar on the right.
|
||||
|
||||
|
@ -17,15 +17,15 @@ Download and install the latest version of CMake 3.9. Download the file named w
|
|||
|
||||
### Step 3. Installing Qt
|
||||
|
||||
Download and install the [Qt Online Installer](https://www.qt.io/download-open-source/?hsCtaTracking=f977210e-de67-475f-a32b-65cec207fd03%7Cd62710cd-e1db-46aa-8d4d-2f1c1ffdacea). While installing, you only need to have the following components checked under Qt 5.9.1: "msvc2017 64-bit", "Qt WebEngine", and "Qt Script (Deprecated)".
|
||||
Download and install the [Qt Online Installer](https://www.qt.io/download-open-source/?hsCtaTracking=f977210e-de67-475f-a32b-65cec207fd03%7Cd62710cd-e1db-46aa-8d4d-2f1c1ffdacea). While installing, you only need to have the following components checked under Qt 5.10.1: "msvc2017 64-bit", "Qt WebEngine", and "Qt Script (Deprecated)".
|
||||
|
||||
Note: Installing the Sources is optional but recommended if you have room for them (~2GB).
|
||||
Note: Installing the Sources is optional but recommended if you have room for them (~2GB).
|
||||
|
||||
### Step 4. Setting Qt Environment Variable
|
||||
|
||||
Go to `Control Panel > System > Advanced System Settings > Environment Variables > New...` (or search “Environment Variables” in Start Search).
|
||||
* Set "Variable name": `QT_CMAKE_PREFIX_PATH`
|
||||
* Set "Variable value": `C:\Qt\5.9.1\msvc2017_64\lib\cmake`
|
||||
* Set "Variable value": `C:\Qt\5.10.1\msvc2017_64\lib\cmake`
|
||||
|
||||
### Step 5. Installing [vcpkg](https://github.com/Microsoft/vcpkg)
|
||||
|
||||
|
@ -39,7 +39,7 @@ Go to `Control Panel > System > Advanced System Settings > Environment Variables
|
|||
|
||||
* In the vcpkg directory, install the 64 bit OpenSSL package with the command `vcpkg install openssl:x64-windows`
|
||||
* Once the build completes you should have a file `ssl.h` in `${VCPKG_ROOT}/installed/x64-windows/include/openssl`
|
||||
|
||||
|
||||
### Step 7. Running CMake to Generate Build Files
|
||||
|
||||
Run Command Prompt from Start and run the following commands:
|
||||
|
@ -49,7 +49,7 @@ mkdir build
|
|||
cd build
|
||||
cmake .. -G "Visual Studio 15 Win64"
|
||||
```
|
||||
|
||||
|
||||
Where `%HIFI_DIR%` is the directory for the highfidelity repository.
|
||||
|
||||
### Step 8. Making a Build
|
||||
|
@ -74,10 +74,10 @@ Note: You can also run Interface by launching it from command line or File Explo
|
|||
|
||||
## Troubleshooting
|
||||
|
||||
For any problems after Step #7, first try this:
|
||||
For any problems after Step #7, first try this:
|
||||
* Delete your locally cloned copy of the highfidelity repository
|
||||
* Restart your computer
|
||||
* Redownload the [repository](https://github.com/highfidelity/hifi)
|
||||
* Redownload the [repository](https://github.com/highfidelity/hifi)
|
||||
* Restart directions from Step #7
|
||||
|
||||
#### CMake gives you the same error message repeatedly after the build fails
|
||||
|
@ -90,4 +90,4 @@ Remove `CMakeCache.txt` found in the `%HIFI_DIR%\build` directory. Verify that
|
|||
|
||||
#### Qt is throwing an error
|
||||
|
||||
Make sure you have the correct version (5.9.1) installed and `QT_CMAKE_PREFIX_PATH` environment variable is set correctly.
|
||||
Make sure you have the correct version (5.10.1) installed and `QT_CMAKE_PREFIX_PATH` environment variable is set correctly.
|
||||
|
|
|
@ -39,6 +39,7 @@ set(BUILD_TOOLS_OPTION ON)
|
|||
set(BUILD_INSTALLER_OPTION ON)
|
||||
set(GLES_OPTION OFF)
|
||||
set(DISABLE_QML_OPTION OFF)
|
||||
set(DOWNLOAD_SERVERLESS_CONTENT_OPTION OFF)
|
||||
|
||||
if (ANDROID OR UWP)
|
||||
set(BUILD_SERVER_OPTION OFF)
|
||||
|
@ -74,6 +75,11 @@ option(BUILD_INSTALLER "Build installer" ${BUILD_INSTALLER_OPTION})
|
|||
option(USE_GLES "Use OpenGL ES" ${GLES_OPTION})
|
||||
option(DISABLE_QML "Disable QML" ${DISABLE_QML_OPTION})
|
||||
option(DISABLE_KTX_CACHE "Disable KTX Cache" OFF)
|
||||
option(
|
||||
DOWNLOAD_SERVERLESS_CONTENT
|
||||
"Download and setup default serverless content beside Interface"
|
||||
${DOWNLOAD_SERVERLESS_CONTENT_OPTION}
|
||||
)
|
||||
|
||||
set(PLATFORM_QT_GL OpenGL)
|
||||
|
||||
|
@ -88,12 +94,13 @@ foreach(PLATFORM_QT_COMPONENT ${PLATFORM_QT_COMPONENTS})
|
|||
list(APPEND PLATFORM_QT_LIBRARIES "Qt5::${PLATFORM_QT_COMPONENT}")
|
||||
endforeach()
|
||||
|
||||
MESSAGE(STATUS "Build server: " ${BUILD_SERVER})
|
||||
MESSAGE(STATUS "Build client: " ${BUILD_CLIENT})
|
||||
MESSAGE(STATUS "Build tests: " ${BUILD_TESTS})
|
||||
MESSAGE(STATUS "Build tools: " ${BUILD_TOOLS})
|
||||
MESSAGE(STATUS "Build installer: " ${BUILD_INSTALLER})
|
||||
MESSAGE(STATUS "GL ES: " ${USE_GLES})
|
||||
MESSAGE(STATUS "Build server: " ${BUILD_SERVER})
|
||||
MESSAGE(STATUS "Build client: " ${BUILD_CLIENT})
|
||||
MESSAGE(STATUS "Build tests: " ${BUILD_TESTS})
|
||||
MESSAGE(STATUS "Build tools: " ${BUILD_TOOLS})
|
||||
MESSAGE(STATUS "Build installer: " ${BUILD_INSTALLER})
|
||||
MESSAGE(STATUS "GL ES: " ${USE_GLES})
|
||||
MESSAGE(STATUS "DL serverless content: " ${DOWNLOAD_SERVERLESS_CONTENT})
|
||||
|
||||
if (DISABLE_QML)
|
||||
MESSAGE(STATUS "QML disabled!")
|
||||
|
|
|
@ -46,15 +46,68 @@ static const uint8_t CPU_AFFINITY_COUNT_LOW = 1;
|
|||
static const int INTERFACE_RUNNING_CHECK_FREQUENCY_MS = 1000;
|
||||
#endif
|
||||
|
||||
const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server";
|
||||
|
||||
static const QStringList BAKEABLE_MODEL_EXTENSIONS = { "fbx" };
|
||||
static QStringList BAKEABLE_TEXTURE_EXTENSIONS;
|
||||
static const QStringList BAKEABLE_SCRIPT_EXTENSIONS = {};
|
||||
static const QStringList BAKEABLE_SCRIPT_EXTENSIONS = { };
|
||||
|
||||
static const QString BAKED_MODEL_SIMPLE_NAME = "asset.fbx";
|
||||
static const QString BAKED_TEXTURE_SIMPLE_NAME = "texture.ktx";
|
||||
static const QString BAKED_SCRIPT_SIMPLE_NAME = "asset.js";
|
||||
|
||||
static const ModelBakeVersion CURRENT_MODEL_BAKE_VERSION = (ModelBakeVersion)((BakeVersion)ModelBakeVersion::COUNT - 1);
|
||||
static const TextureBakeVersion CURRENT_TEXTURE_BAKE_VERSION = (TextureBakeVersion)((BakeVersion)TextureBakeVersion::COUNT - 1);
|
||||
static const ScriptBakeVersion CURRENT_SCRIPT_BAKE_VERSION = (ScriptBakeVersion)((BakeVersion)ScriptBakeVersion::COUNT - 1);
|
||||
|
||||
BakedAssetType assetTypeForExtension(const QString& extension) {
|
||||
auto extensionLower = extension.toLower();
|
||||
if (BAKEABLE_MODEL_EXTENSIONS.contains(extensionLower)) {
|
||||
return BakedAssetType::Model;
|
||||
} else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(extensionLower.toLocal8Bit())) {
|
||||
return BakedAssetType::Texture;
|
||||
} else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extensionLower)) {
|
||||
return BakedAssetType::Script;
|
||||
}
|
||||
return BakedAssetType::Undefined;
|
||||
}
|
||||
|
||||
BakedAssetType assetTypeForFilename(const QString& filename) {
|
||||
auto dotIndex = filename.lastIndexOf(".");
|
||||
if (dotIndex == -1) {
|
||||
return BakedAssetType::Undefined;
|
||||
}
|
||||
|
||||
auto extension = filename.mid(dotIndex + 1);
|
||||
return assetTypeForExtension(extension);
|
||||
}
|
||||
|
||||
QString bakedFilenameForAssetType(BakedAssetType type) {
|
||||
switch (type) {
|
||||
case BakedAssetType::Model:
|
||||
return BAKED_MODEL_SIMPLE_NAME;
|
||||
case BakedAssetType::Texture:
|
||||
return BAKED_TEXTURE_SIMPLE_NAME;
|
||||
case BakedAssetType::Script:
|
||||
return BAKED_SCRIPT_SIMPLE_NAME;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
BakeVersion currentBakeVersionForAssetType(BakedAssetType type) {
|
||||
switch (type) {
|
||||
case BakedAssetType::Model:
|
||||
return (BakeVersion)CURRENT_MODEL_BAKE_VERSION;
|
||||
case BakedAssetType::Texture:
|
||||
return (BakeVersion)CURRENT_TEXTURE_BAKE_VERSION;
|
||||
case BakedAssetType::Script:
|
||||
return (BakeVersion)CURRENT_SCRIPT_BAKE_VERSION;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server";
|
||||
|
||||
void AssetServer::bakeAsset(const AssetUtils::AssetHash& assetHash, const AssetUtils::AssetPath& assetPath, const QString& filePath) {
|
||||
qDebug() << "Starting bake for: " << assetPath << assetHash;
|
||||
auto it = _pendingBakes.find(assetHash);
|
||||
|
@ -167,36 +220,38 @@ bool AssetServer::needsToBeBaked(const AssetUtils::AssetPath& path, const AssetU
|
|||
return false;
|
||||
}
|
||||
|
||||
auto dotIndex = path.lastIndexOf(".");
|
||||
if (dotIndex == -1) {
|
||||
BakedAssetType type = assetTypeForFilename(path);
|
||||
|
||||
if (type == BakedAssetType::Undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto extension = path.mid(dotIndex + 1);
|
||||
QString bakedFilename = bakedFilenameForAssetType(type);
|
||||
auto bakedPath = AssetUtils::HIDDEN_BAKED_CONTENT_FOLDER + assetHash + "/" + bakedFilename;
|
||||
auto mappingIt = _fileMappings.find(bakedPath);
|
||||
bool bakedMappingExists = mappingIt != _fileMappings.end();
|
||||
|
||||
QString bakedFilename;
|
||||
// If the path is mapped to the original file's hash, baking has been disabled for this
|
||||
// asset
|
||||
if (bakedMappingExists && mappingIt->second == assetHash) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool loaded;
|
||||
AssetMeta meta;
|
||||
std::tie(loaded, meta) = readMetaFile(assetHash);
|
||||
|
||||
// TODO: Allow failed bakes that happened on old versions to be re-baked
|
||||
if (loaded && meta.failedLastBake) {
|
||||
if (type == BakedAssetType::Texture && !loaded) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (BAKEABLE_MODEL_EXTENSIONS.contains(extension)) {
|
||||
bakedFilename = BAKED_MODEL_SIMPLE_NAME;
|
||||
} else if (loaded && BAKEABLE_TEXTURE_EXTENSIONS.contains(extension.toLocal8Bit())) {
|
||||
bakedFilename = BAKED_TEXTURE_SIMPLE_NAME;
|
||||
} else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extension)) {
|
||||
bakedFilename = BAKED_SCRIPT_SIMPLE_NAME;
|
||||
} else {
|
||||
auto currentVersion = currentBakeVersionForAssetType(type);
|
||||
|
||||
if (loaded && (meta.failedLastBake && meta.bakeVersion >= currentVersion)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto bakedPath = AssetUtils::HIDDEN_BAKED_CONTENT_FOLDER + assetHash + "/" + bakedFilename;
|
||||
return _fileMappings.find(bakedPath) == _fileMappings.end();
|
||||
return !bakedMappingExists || (meta.bakeVersion < currentVersion);
|
||||
}
|
||||
|
||||
bool interfaceRunning() {
|
||||
|
@ -598,15 +653,9 @@ void AssetServer::handleGetMappingOperation(ReceivedMessage& message, NLPacketLi
|
|||
|
||||
// first, figure out from the mapping extension what type of file this is
|
||||
auto assetPathExtension = assetPath.mid(assetPath.lastIndexOf('.') + 1).toLower();
|
||||
QString bakedRootFile;
|
||||
|
||||
if (BAKEABLE_MODEL_EXTENSIONS.contains(assetPathExtension)) {
|
||||
bakedRootFile = BAKED_MODEL_SIMPLE_NAME;
|
||||
} else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(assetPathExtension.toLocal8Bit())) {
|
||||
bakedRootFile = BAKED_TEXTURE_SIMPLE_NAME;
|
||||
} else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(assetPathExtension)) {
|
||||
bakedRootFile = BAKED_SCRIPT_SIMPLE_NAME;
|
||||
}
|
||||
auto type = assetTypeForFilename(assetPath);
|
||||
QString bakedRootFile = bakedFilenameForAssetType(type);
|
||||
|
||||
auto originalAssetHash = it->second;
|
||||
QString redirectedAssetHash;
|
||||
|
@ -653,9 +702,19 @@ void AssetServer::handleGetMappingOperation(ReceivedMessage& message, NLPacketLi
|
|||
auto query = QUrlQuery(url.query());
|
||||
bool isSkybox = query.hasQueryItem("skybox");
|
||||
if (isSkybox) {
|
||||
writeMetaFile(originalAssetHash);
|
||||
if (!bakingDisabled) {
|
||||
maybeBake(assetPath, originalAssetHash);
|
||||
bool loaded;
|
||||
AssetMeta meta;
|
||||
std::tie(loaded, meta) = readMetaFile(originalAssetHash);
|
||||
|
||||
if (!loaded) {
|
||||
AssetMeta needsBakingMeta;
|
||||
needsBakingMeta.bakeVersion = NEEDS_BAKING_BAKE_VERSION;
|
||||
|
||||
writeMetaFile(originalAssetHash, needsBakingMeta);
|
||||
if (!bakingDisabled) {
|
||||
maybeBake(assetPath, originalAssetHash);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1275,15 +1334,19 @@ QString getBakeMapping(const AssetUtils::AssetHash& hash, const QString& relativ
|
|||
}
|
||||
|
||||
void AssetServer::handleFailedBake(QString originalAssetHash, QString assetPath, QString errors) {
|
||||
qDebug() << "Failed: " << originalAssetHash << assetPath << errors;
|
||||
qDebug() << "Failed to bake: " << originalAssetHash << assetPath << "(" << errors << ")";
|
||||
|
||||
bool loaded;
|
||||
AssetMeta meta;
|
||||
|
||||
std::tie(loaded, meta) = readMetaFile(originalAssetHash);
|
||||
|
||||
auto type = assetTypeForFilename(assetPath);
|
||||
auto currentTypeVersion = currentBakeVersionForAssetType(type);
|
||||
|
||||
meta.failedLastBake = true;
|
||||
meta.lastBakeErrors = errors;
|
||||
meta.bakeVersion = currentTypeVersion;
|
||||
|
||||
writeMetaFile(originalAssetHash, meta);
|
||||
|
||||
|
@ -1373,17 +1436,20 @@ void AssetServer::handleCompletedBake(QString originalAssetHash, QString origina
|
|||
qWarning() << "Failed to remove temporary directory:" << bakedTempOutputDir;
|
||||
}
|
||||
|
||||
if (!errorCompletingBake) {
|
||||
// create the meta file to store which version of the baking process we just completed
|
||||
writeMetaFile(originalAssetHash);
|
||||
} else {
|
||||
auto type = assetTypeForFilename(originalAssetPath);
|
||||
auto currentTypeVersion = currentBakeVersionForAssetType(type);
|
||||
|
||||
AssetMeta meta;
|
||||
meta.bakeVersion = currentTypeVersion;
|
||||
meta.failedLastBake = errorCompletingBake;
|
||||
|
||||
if (errorCompletingBake) {
|
||||
qWarning() << "Could not complete bake for" << originalAssetHash;
|
||||
AssetMeta meta;
|
||||
meta.failedLastBake = true;
|
||||
meta.lastBakeErrors = errorReason;
|
||||
writeMetaFile(originalAssetHash, meta);
|
||||
}
|
||||
|
||||
writeMetaFile(originalAssetHash, meta);
|
||||
|
||||
_pendingBakes.remove(originalAssetHash);
|
||||
}
|
||||
|
||||
|
@ -1420,16 +1486,16 @@ std::pair<bool, AssetMeta> AssetServer::readMetaFile(AssetUtils::AssetHash hash)
|
|||
if (error.error == QJsonParseError::NoError && doc.isObject()) {
|
||||
auto root = doc.object();
|
||||
|
||||
auto bakeVersion = root[BAKE_VERSION_KEY].toInt(-1);
|
||||
auto bakeVersion = root[BAKE_VERSION_KEY];
|
||||
auto failedLastBake = root[FAILED_LAST_BAKE_KEY];
|
||||
auto lastBakeErrors = root[LAST_BAKE_ERRORS_KEY];
|
||||
|
||||
if (bakeVersion != -1
|
||||
if (bakeVersion.isDouble()
|
||||
&& failedLastBake.isBool()
|
||||
&& lastBakeErrors.isString()) {
|
||||
|
||||
AssetMeta meta;
|
||||
meta.bakeVersion = bakeVersion;
|
||||
meta.bakeVersion = bakeVersion.toInt();
|
||||
meta.failedLastBake = failedLastBake.toBool();
|
||||
meta.lastBakeErrors = lastBakeErrors.toString();
|
||||
|
||||
|
@ -1447,7 +1513,7 @@ bool AssetServer::writeMetaFile(AssetUtils::AssetHash originalAssetHash, const A
|
|||
// construct the JSON that will be in the meta file
|
||||
QJsonObject metaFileObject;
|
||||
|
||||
metaFileObject[BAKE_VERSION_KEY] = meta.bakeVersion;
|
||||
metaFileObject[BAKE_VERSION_KEY] = (int)meta.bakeVersion;
|
||||
metaFileObject[FAILED_LAST_BAKE_KEY] = meta.failedLastBake;
|
||||
metaFileObject[LAST_BAKE_ERRORS_KEY] = meta.lastBakeErrors;
|
||||
|
||||
|
@ -1479,27 +1545,13 @@ bool AssetServer::setBakingEnabled(const AssetUtils::AssetPathList& paths, bool
|
|||
for (const auto& path : paths) {
|
||||
auto it = _fileMappings.find(path);
|
||||
if (it != _fileMappings.end()) {
|
||||
auto type = assetTypeForFilename(path);
|
||||
if (type == BakedAssetType::Undefined) {
|
||||
continue;
|
||||
}
|
||||
QString bakedFilename = bakedFilenameForAssetType(type);
|
||||
|
||||
auto hash = it->second;
|
||||
|
||||
auto dotIndex = path.lastIndexOf(".");
|
||||
if (dotIndex == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto extension = path.mid(dotIndex + 1);
|
||||
|
||||
QString bakedFilename;
|
||||
|
||||
if (BAKEABLE_MODEL_EXTENSIONS.contains(extension)) {
|
||||
bakedFilename = BAKED_MODEL_SIMPLE_NAME;
|
||||
} else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(extension.toLocal8Bit()) && hasMetaFile(hash)) {
|
||||
bakedFilename = BAKED_TEXTURE_SIMPLE_NAME;
|
||||
} else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extension)) {
|
||||
bakedFilename = BAKED_SCRIPT_SIMPLE_NAME;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto bakedMapping = getBakeMapping(hash, bakedFilename);
|
||||
|
||||
auto it = _fileMappings.find(bakedMapping);
|
||||
|
|
|
@ -23,8 +23,47 @@
|
|||
|
||||
#include "RegisteredMetaTypes.h"
|
||||
|
||||
using BakeVersion = int;
|
||||
static const BakeVersion INITIAL_BAKE_VERSION = 0;
|
||||
static const BakeVersion NEEDS_BAKING_BAKE_VERSION = -1;
|
||||
|
||||
enum class BakedAssetType : int {
|
||||
Model = 0,
|
||||
Texture,
|
||||
Script,
|
||||
|
||||
NUM_ASSET_TYPES,
|
||||
Undefined
|
||||
};
|
||||
|
||||
// ATTENTION! If you change the current version for an asset type, you will also
|
||||
// need to update the function currentBakeVersionForAssetType() inside of AssetServer.cpp.
|
||||
enum class ModelBakeVersion : BakeVersion {
|
||||
Initial = INITIAL_BAKE_VERSION,
|
||||
|
||||
COUNT
|
||||
};
|
||||
|
||||
// ATTENTION! See above.
|
||||
enum class TextureBakeVersion : BakeVersion {
|
||||
Initial = INITIAL_BAKE_VERSION,
|
||||
|
||||
COUNT
|
||||
};
|
||||
|
||||
// ATTENTION! See above.
|
||||
enum class ScriptBakeVersion : BakeVersion {
|
||||
Initial = INITIAL_BAKE_VERSION,
|
||||
FixEmptyScripts,
|
||||
|
||||
COUNT
|
||||
};
|
||||
|
||||
struct AssetMeta {
|
||||
int bakeVersion { 0 };
|
||||
AssetMeta() {
|
||||
}
|
||||
|
||||
BakeVersion bakeVersion;
|
||||
bool failedLastBake { false };
|
||||
QString lastBakeErrors;
|
||||
};
|
||||
|
|
|
@ -322,8 +322,16 @@ void AudioMixerSlave::addStream(AudioMixerClientData& listenerNodeData, const QU
|
|||
|
||||
// stereo sources are not passed through HRTF
|
||||
if (streamToAdd.isStereo()) {
|
||||
for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; ++i) {
|
||||
_mixSamples[i] += float(streamPopOutput[i] * gain / AudioConstants::MAX_SAMPLE_VALUE);
|
||||
|
||||
// apply the avatar gain adjustment
|
||||
auto& hrtf = listenerNodeData.hrtfForStream(sourceNodeID, streamToAdd.getStreamIdentifier());
|
||||
gain *= hrtf.getGainAdjustment();
|
||||
|
||||
const float scale = 1/32768.0f; // int16_t to float
|
||||
|
||||
for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL; i++) {
|
||||
_mixSamples[2*i+0] += (float)streamPopOutput[2*i+0] * gain * scale;
|
||||
_mixSamples[2*i+1] += (float)streamPopOutput[2*i+1] * gain * scale;
|
||||
}
|
||||
|
||||
++stats.manualStereoMixes;
|
||||
|
@ -332,10 +340,13 @@ void AudioMixerSlave::addStream(AudioMixerClientData& listenerNodeData, const QU
|
|||
|
||||
// echo sources are not passed through HRTF
|
||||
if (isEcho) {
|
||||
for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; i += 2) {
|
||||
auto monoSample = float(streamPopOutput[i / 2] * gain / AudioConstants::MAX_SAMPLE_VALUE);
|
||||
_mixSamples[i] += monoSample;
|
||||
_mixSamples[i + 1] += monoSample;
|
||||
|
||||
const float scale = 1/32768.0f; // int16_t to float
|
||||
|
||||
for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL; i++) {
|
||||
float sample = (float)streamPopOutput[i] * gain * scale;
|
||||
_mixSamples[2*i+0] += sample;
|
||||
_mixSamples[2*i+1] += sample;
|
||||
}
|
||||
|
||||
++stats.manualEchoMixes;
|
||||
|
|
|
@ -33,7 +33,7 @@ uint64_t AvatarMixerClientData::getLastOtherAvatarEncodeTime(QUuid otherAvatar)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void AvatarMixerClientData::setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, const uint64_t& time) {
|
||||
void AvatarMixerClientData::setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time) {
|
||||
std::unordered_map<QUuid, uint64_t>::iterator itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
|
||||
if (itr != _lastOtherAvatarEncodeTime.end()) {
|
||||
itr->second = time;
|
||||
|
|
|
@ -113,7 +113,7 @@ public:
|
|||
ViewFrustum getViewFrustum() const { return _currentViewFrustum; }
|
||||
|
||||
uint64_t getLastOtherAvatarEncodeTime(QUuid otherAvatar) const;
|
||||
void setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, const uint64_t& time);
|
||||
void setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time);
|
||||
|
||||
QVector<JointData>& getLastOtherAvatarSentJoints(QUuid otherAvatar) {
|
||||
auto& lastOtherAvatarSentJoints = _lastOtherAvatarSentJoints[otherAvatar];
|
||||
|
|
|
@ -363,7 +363,9 @@ void EntityServer::nodeAdded(SharedNodePointer node) {
|
|||
|
||||
void EntityServer::nodeKilled(SharedNodePointer node) {
|
||||
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
|
||||
tree->deleteDescendantsOfAvatar(node->getUUID());
|
||||
tree->withWriteLock([&] {
|
||||
tree->deleteDescendantsOfAvatar(node->getUUID());
|
||||
});
|
||||
tree->forgetAvatarID(node->getUUID());
|
||||
OctreeServer::nodeKilled(node);
|
||||
}
|
||||
|
@ -451,8 +453,6 @@ void EntityServer::domainSettingsRequestFailed() {
|
|||
void EntityServer::startDynamicDomainVerification() {
|
||||
qCDebug(entities) << "Starting Dynamic Domain Verification...";
|
||||
|
||||
QString thisDomainID = DependencyManager::get<AddressManager>()->getDomainID().remove(QRegExp("\\{|\\}"));
|
||||
|
||||
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
|
||||
QHash<QString, EntityItemID> localMap(tree->getEntityCertificateIDMap());
|
||||
|
||||
|
@ -460,17 +460,20 @@ void EntityServer::startDynamicDomainVerification() {
|
|||
qCDebug(entities) << localMap.size() << "entities in _entityCertificateIDMap";
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
const auto& certificateID = i.key();
|
||||
const auto& entityID = i.value();
|
||||
|
||||
EntityItemPointer entity = tree->findEntityByEntityItemID(i.value());
|
||||
EntityItemPointer entity = tree->findEntityByEntityItemID(entityID);
|
||||
|
||||
if (entity) {
|
||||
if (!entity->getProperties().verifyStaticCertificateProperties()) {
|
||||
qCDebug(entities) << "During Dynamic Domain Verification, a certified entity with ID" << i.value() << "failed"
|
||||
qCDebug(entities) << "During Dynamic Domain Verification, a certified entity with ID" << entityID << "failed"
|
||||
<< "static certificate verification.";
|
||||
// Delete the entity if it doesn't pass static certificate verification
|
||||
tree->deleteEntity(i.value(), true);
|
||||
tree->withWriteLock([&] {
|
||||
tree->deleteEntity(entityID, true);
|
||||
});
|
||||
} else {
|
||||
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkRequest networkRequest;
|
||||
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
|
@ -478,35 +481,46 @@ void EntityServer::startDynamicDomainVerification() {
|
|||
QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL();
|
||||
requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/location");
|
||||
QJsonObject request;
|
||||
request["certificate_id"] = i.key();
|
||||
request["certificate_id"] = certificateID;
|
||||
networkRequest.setUrl(requestURL);
|
||||
|
||||
QNetworkReply* networkReply = NULL;
|
||||
networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson());
|
||||
QNetworkReply* networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson());
|
||||
|
||||
connect(networkReply, &QNetworkReply::finished, this, [this, entityID, networkReply] {
|
||||
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
|
||||
|
||||
connect(networkReply, &QNetworkReply::finished, [=]() {
|
||||
QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object();
|
||||
jsonObject = jsonObject["data"].toObject();
|
||||
|
||||
if (networkReply->error() == QNetworkReply::NoError) {
|
||||
QString thisDomainID = DependencyManager::get<AddressManager>()->getDomainID().remove(QRegExp("\\{|\\}"));
|
||||
if (jsonObject["domain_id"].toString() != thisDomainID) {
|
||||
qCDebug(entities) << "Entity's cert's domain ID" << jsonObject["domain_id"].toString()
|
||||
<< "doesn't match the current Domain ID" << thisDomainID << "; deleting entity" << i.value();
|
||||
tree->deleteEntity(i.value(), true);
|
||||
EntityItemPointer entity = tree->findEntityByEntityItemID(entityID);
|
||||
if (entity->getAge() > (_MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS/MSECS_PER_SECOND)) {
|
||||
qCDebug(entities) << "Entity's cert's domain ID" << jsonObject["domain_id"].toString()
|
||||
<< "doesn't match the current Domain ID" << thisDomainID << "; deleting entity" << entityID;
|
||||
tree->withWriteLock([&] {
|
||||
tree->deleteEntity(entityID, true);
|
||||
});
|
||||
} else {
|
||||
qCDebug(entities) << "Entity failed dynamic domain verification, but was created too recently to necessitate deletion:" << entityID;
|
||||
}
|
||||
} else {
|
||||
qCDebug(entities) << "Entity passed dynamic domain verification:" << i.value();
|
||||
qCDebug(entities) << "Entity passed dynamic domain verification:" << entityID;
|
||||
}
|
||||
} else {
|
||||
qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << "; deleting entity" << i.value()
|
||||
qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << "; deleting entity" << entityID
|
||||
<< "More info:" << jsonObject;
|
||||
tree->deleteEntity(i.value(), true);
|
||||
tree->withWriteLock([&] {
|
||||
tree->deleteEntity(entityID, true);
|
||||
});
|
||||
}
|
||||
|
||||
networkReply->deleteLater();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
qCWarning(entities) << "During DDV, an entity with ID" << i.value() << "was NOT found in the Entity Tree!";
|
||||
qCWarning(entities) << "During DDV, an entity with ID" << entityID << "was NOT found in the Entity Tree!";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -311,7 +311,8 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
|
|||
_sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
|
||||
_entitiesInQueue.insert(entity.get());
|
||||
}
|
||||
} else if (entity->getLastEdited() > knownTimestamp->second) {
|
||||
} else if (entity->getLastEdited() > knownTimestamp->second
|
||||
|| entity->getLastChangedOnServer() > knownTimestamp->second) {
|
||||
// it is known and it changed --> put it on the queue with any priority
|
||||
// TODO: sort these correctly
|
||||
_sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
|
||||
|
@ -330,7 +331,9 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
|
|||
return;
|
||||
}
|
||||
auto knownTimestamp = _knownState.find(entity.get());
|
||||
if (knownTimestamp == _knownState.end() || entity->getLastEdited() > knownTimestamp->second) {
|
||||
if (knownTimestamp == _knownState.end()
|
||||
|| entity->getLastEdited() > knownTimestamp->second
|
||||
|| entity->getLastChangedOnServer() > knownTimestamp->second) {
|
||||
_sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
|
||||
_entitiesInQueue.insert(entity.get());
|
||||
}
|
||||
|
@ -382,7 +385,8 @@ void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTree
|
|||
_sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
|
||||
_entitiesInQueue.insert(entity.get());
|
||||
}
|
||||
} else if (entity->getLastEdited() > knownTimestamp->second) {
|
||||
} else if (entity->getLastEdited() > knownTimestamp->second
|
||||
|| entity->getLastChangedOnServer() > knownTimestamp->second) {
|
||||
// it is known and it changed --> put it on the queue with any priority
|
||||
// TODO: sort these correctly
|
||||
_sendQueue.push(PrioritizedEntity(entity, PrioritizedEntity::WHEN_IN_DOUBT_PRIORITY));
|
||||
|
|
|
@ -48,8 +48,6 @@ private:
|
|||
void preDistributionProcessing() override;
|
||||
bool hasSomethingToSend(OctreeQueryNode* nodeData) override { return !_sendQueue.empty(); }
|
||||
bool shouldStartNewTraversal(OctreeQueryNode* nodeData, bool viewFrustumChanged) override { return viewFrustumChanged || _traversal.finished(); }
|
||||
void preStartNewScene(OctreeQueryNode* nodeData, bool isFullScene) override {};
|
||||
bool shouldTraverseAndSend(OctreeQueryNode* nodeData) override { return true; }
|
||||
|
||||
DiffTraversal _traversal;
|
||||
EntityPriorityQueue _sendQueue;
|
||||
|
|
|
@ -304,23 +304,6 @@ int OctreeSendThread::handlePacketSend(SharedNodePointer node, OctreeQueryNode*
|
|||
return numPackets;
|
||||
}
|
||||
|
||||
void OctreeSendThread::preStartNewScene(OctreeQueryNode* nodeData, bool isFullScene) {
|
||||
// If we're starting a full scene, then definitely we want to empty the elementBag
|
||||
if (isFullScene) {
|
||||
nodeData->elementBag.deleteAll();
|
||||
}
|
||||
|
||||
// This is the start of "resending" the scene.
|
||||
bool dontRestartSceneOnMove = false; // this is experimental
|
||||
if (dontRestartSceneOnMove) {
|
||||
if (nodeData->elementBag.isEmpty()) {
|
||||
nodeData->elementBag.insert(_myServer->getOctree()->getRoot());
|
||||
}
|
||||
} else {
|
||||
nodeData->elementBag.insert(_myServer->getOctree()->getRoot());
|
||||
}
|
||||
}
|
||||
|
||||
/// Version of octree element distributor that sends the deepest LOD level at once
|
||||
int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged) {
|
||||
OctreeServer::didPacketDistributor(this);
|
||||
|
@ -366,16 +349,8 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
|
|||
// the current view frustum for things to send.
|
||||
if (shouldStartNewTraversal(nodeData, viewFrustumChanged)) {
|
||||
|
||||
// if our view has changed, we need to reset these things...
|
||||
if (viewFrustumChanged) {
|
||||
if (nodeData->moveShouldDump() || nodeData->hasLodChanged()) {
|
||||
nodeData->dumpOutOfView();
|
||||
}
|
||||
}
|
||||
|
||||
// track completed scenes and send out the stats packet accordingly
|
||||
nodeData->stats.sceneCompleted();
|
||||
nodeData->setLastRootTimestamp(_myServer->getOctree()->getRoot()->getLastChanged());
|
||||
_myServer->getOctree()->releaseSceneEncodeData(&nodeData->extraEncodeData);
|
||||
|
||||
// TODO: add these to stats page
|
||||
|
@ -389,109 +364,74 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
|
|||
// TODO: add these to stats page
|
||||
//::startSceneSleepTime = _usleepTime;
|
||||
|
||||
nodeData->sceneStart(usecTimestampNow() - CHANGE_FUDGE);
|
||||
// start tracking our stats
|
||||
nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, _myServer->getOctree()->getRoot());
|
||||
|
||||
preStartNewScene(nodeData, isFullScene);
|
||||
}
|
||||
|
||||
// If we have something in our elementBag, then turn them into packets and send them out...
|
||||
if (shouldTraverseAndSend(nodeData)) {
|
||||
quint64 start = usecTimestampNow();
|
||||
quint64 start = usecTimestampNow();
|
||||
|
||||
_myServer->getOctree()->withReadLock([&]{
|
||||
traverseTreeAndSendContents(node, nodeData, viewFrustumChanged, isFullScene);
|
||||
});
|
||||
|
||||
// Here's where we can/should allow the server to send other data...
|
||||
// send the environment packet
|
||||
// TODO: should we turn this into a while loop to better handle sending multiple special packets
|
||||
if (_myServer->hasSpecialPacketsToSend(node) && !nodeData->isShuttingDown()) {
|
||||
int specialPacketsSent = 0;
|
||||
int specialBytesSent = _myServer->sendSpecialPackets(node, nodeData, specialPacketsSent);
|
||||
nodeData->resetOctreePacket(); // because nodeData's _sequenceNumber has changed
|
||||
_truePacketsSent += specialPacketsSent;
|
||||
_trueBytesSent += specialBytesSent;
|
||||
_packetsSentThisInterval += specialPacketsSent;
|
||||
// Here's where we can/should allow the server to send other data...
|
||||
// send the environment packet
|
||||
// TODO: should we turn this into a while loop to better handle sending multiple special packets
|
||||
if (_myServer->hasSpecialPacketsToSend(node) && !nodeData->isShuttingDown()) {
|
||||
int specialPacketsSent = 0;
|
||||
int specialBytesSent = _myServer->sendSpecialPackets(node, nodeData, specialPacketsSent);
|
||||
nodeData->resetOctreePacket(); // because nodeData's _sequenceNumber has changed
|
||||
_truePacketsSent += specialPacketsSent;
|
||||
_trueBytesSent += specialBytesSent;
|
||||
_packetsSentThisInterval += specialPacketsSent;
|
||||
|
||||
_totalPackets += specialPacketsSent;
|
||||
_totalBytes += specialBytesSent;
|
||||
_totalPackets += specialPacketsSent;
|
||||
_totalBytes += specialBytesSent;
|
||||
|
||||
_totalSpecialPackets += specialPacketsSent;
|
||||
_totalSpecialBytes += specialBytesSent;
|
||||
_totalSpecialPackets += specialPacketsSent;
|
||||
_totalSpecialBytes += specialBytesSent;
|
||||
}
|
||||
|
||||
// calculate max number of packets that can be sent during this interval
|
||||
int clientMaxPacketsPerInterval = std::max(1, (nodeData->getMaxQueryPacketsPerSecond() / INTERVALS_PER_SECOND));
|
||||
int maxPacketsPerInterval = std::min(clientMaxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval());
|
||||
|
||||
// Re-send packets that were nacked by the client
|
||||
while (nodeData->hasNextNackedPacket() && _packetsSentThisInterval < maxPacketsPerInterval) {
|
||||
const NLPacket* packet = nodeData->getNextNackedPacket();
|
||||
if (packet) {
|
||||
DependencyManager::get<NodeList>()->sendUnreliablePacket(*packet, *node);
|
||||
int numBytes = packet->getDataSize();
|
||||
_truePacketsSent++;
|
||||
_trueBytesSent += numBytes;
|
||||
_packetsSentThisInterval++;
|
||||
|
||||
_totalPackets++;
|
||||
_totalBytes += numBytes;
|
||||
_totalWastedBytes += udt::MAX_PACKET_SIZE - packet->getDataSize();
|
||||
}
|
||||
}
|
||||
|
||||
// calculate max number of packets that can be sent during this interval
|
||||
int clientMaxPacketsPerInterval = std::max(1, (nodeData->getMaxQueryPacketsPerSecond() / INTERVALS_PER_SECOND));
|
||||
int maxPacketsPerInterval = std::min(clientMaxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval());
|
||||
quint64 end = usecTimestampNow();
|
||||
int elapsedmsec = (end - start) / USECS_PER_MSEC;
|
||||
OctreeServer::trackLoopTime(elapsedmsec);
|
||||
|
||||
// Re-send packets that were nacked by the client
|
||||
while (nodeData->hasNextNackedPacket() && _packetsSentThisInterval < maxPacketsPerInterval) {
|
||||
const NLPacket* packet = nodeData->getNextNackedPacket();
|
||||
if (packet) {
|
||||
DependencyManager::get<NodeList>()->sendUnreliablePacket(*packet, *node);
|
||||
int numBytes = packet->getDataSize();
|
||||
_truePacketsSent++;
|
||||
_trueBytesSent += numBytes;
|
||||
_packetsSentThisInterval++;
|
||||
// if we've sent everything, then we want to remember that we've sent all
|
||||
// the octree elements from the current view frustum
|
||||
if (!hasSomethingToSend(nodeData)) {
|
||||
nodeData->setViewSent(true);
|
||||
|
||||
_totalPackets++;
|
||||
_totalBytes += numBytes;
|
||||
_totalWastedBytes += udt::MAX_PACKET_SIZE - packet->getDataSize();
|
||||
}
|
||||
// If this was a full scene then make sure we really send out a stats packet at this point so that
|
||||
// the clients will know the scene is stable
|
||||
if (isFullScene) {
|
||||
nodeData->stats.sceneCompleted();
|
||||
handlePacketSend(node, nodeData, true);
|
||||
}
|
||||
|
||||
quint64 end = usecTimestampNow();
|
||||
int elapsedmsec = (end - start) / USECS_PER_MSEC;
|
||||
OctreeServer::trackLoopTime(elapsedmsec);
|
||||
|
||||
// if after sending packets we've emptied our bag, then we want to remember that we've sent all
|
||||
// the octree elements from the current view frustum
|
||||
if (!hasSomethingToSend(nodeData)) {
|
||||
nodeData->updateLastKnownViewFrustum();
|
||||
nodeData->setViewSent(true);
|
||||
|
||||
// If this was a full scene then make sure we really send out a stats packet at this point so that
|
||||
// the clients will know the scene is stable
|
||||
if (isFullScene) {
|
||||
nodeData->stats.sceneCompleted();
|
||||
handlePacketSend(node, nodeData, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // end if bag wasn't empty, and so we sent stuff...
|
||||
}
|
||||
|
||||
return _truePacketsSent;
|
||||
}
|
||||
|
||||
bool OctreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) {
|
||||
bool somethingToSend = false;
|
||||
OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(params.nodeData);
|
||||
if (!nodeData->elementBag.isEmpty()) {
|
||||
quint64 encodeStart = usecTimestampNow();
|
||||
quint64 lockWaitStart = encodeStart;
|
||||
|
||||
_myServer->getOctree()->withReadLock([&]{
|
||||
OctreeServer::trackTreeWaitTime((float)(usecTimestampNow() - lockWaitStart));
|
||||
|
||||
OctreeElementPointer subTree = nodeData->elementBag.extract();
|
||||
if (subTree) {
|
||||
// NOTE: this is where the tree "contents" are actually packed
|
||||
nodeData->stats.encodeStarted();
|
||||
_myServer->getOctree()->encodeTreeBitstream(subTree, &_packetData, nodeData->elementBag, params);
|
||||
nodeData->stats.encodeStopped();
|
||||
|
||||
somethingToSend = true;
|
||||
}
|
||||
});
|
||||
|
||||
OctreeServer::trackEncodeTime((float)(usecTimestampNow() - encodeStart));
|
||||
} else {
|
||||
OctreeServer::trackTreeWaitTime(OctreeServer::SKIP_TIME);
|
||||
OctreeServer::trackEncodeTime(OctreeServer::SKIP_TIME);
|
||||
}
|
||||
return somethingToSend;
|
||||
}
|
||||
|
||||
void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged, bool isFullScene) {
|
||||
// calculate max number of packets that can be sent during this interval
|
||||
int clientMaxPacketsPerInterval = std::max(1, (nodeData->getMaxQueryPacketsPerSecond() / INTERVALS_PER_SECOND));
|
||||
|
@ -500,21 +440,12 @@ void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, Octre
|
|||
int extraPackingAttempts = 0;
|
||||
|
||||
// init params once outside the while loop
|
||||
int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust();
|
||||
int boundaryLevelAdjust = boundaryLevelAdjustClient +
|
||||
(viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
|
||||
float octreeSizeScale = nodeData->getOctreeSizeScale();
|
||||
EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP,
|
||||
viewFrustumChanged, boundaryLevelAdjust, octreeSizeScale,
|
||||
isFullScene, nodeData);
|
||||
EncodeBitstreamParams params(WANT_EXISTS_BITS, nodeData);
|
||||
// Our trackSend() function is implemented by the server subclass, and will be called back as new entities/data elements are sent
|
||||
params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) {
|
||||
_myServer->trackSend(dataID, dataEdited, _nodeUuid);
|
||||
};
|
||||
nodeData->copyCurrentViewFrustum(params.viewFrustum);
|
||||
if (viewFrustumChanged) {
|
||||
nodeData->copyLastKnownViewFrustum(params.lastViewFrustum);
|
||||
}
|
||||
|
||||
bool somethingToSend = true; // assume we have something
|
||||
bool hadSomething = hasSomethingToSend(nodeData);
|
||||
|
@ -534,8 +465,8 @@ void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, Octre
|
|||
extraPackingAttempts++;
|
||||
}
|
||||
|
||||
// If the bag had contents but is now empty then we know we've sent the entire scene.
|
||||
bool completedScene = hadSomething && nodeData->elementBag.isEmpty();
|
||||
// If we had something to send, but now we don't, then we know we've sent the entire scene.
|
||||
bool completedScene = hadSomething;
|
||||
if (completedScene || lastNodeDidntFit) {
|
||||
// we probably want to flush what has accumulated in nodeData but:
|
||||
// do we have more data to send? and is there room?
|
||||
|
|
|
@ -54,7 +54,7 @@ protected:
|
|||
|
||||
virtual void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,
|
||||
bool viewFrustumChanged, bool isFullScene);
|
||||
virtual bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters);
|
||||
virtual bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) = 0;
|
||||
|
||||
OctreePacketData _packetData;
|
||||
QWeakPointer<Node> _node;
|
||||
|
@ -63,14 +63,12 @@ protected:
|
|||
|
||||
private:
|
||||
/// Called before a packetDistributor pass to allow for pre-distribution processing
|
||||
virtual void preDistributionProcessing() {};
|
||||
virtual void preDistributionProcessing() = 0;
|
||||
int handlePacketSend(SharedNodePointer node, OctreeQueryNode* nodeData, bool dontSuppressDuplicate = false);
|
||||
int packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged);
|
||||
|
||||
virtual bool hasSomethingToSend(OctreeQueryNode* nodeData) { return !nodeData->elementBag.isEmpty(); }
|
||||
virtual bool shouldStartNewTraversal(OctreeQueryNode* nodeData, bool viewFrustumChanged) { return viewFrustumChanged || !hasSomethingToSend(nodeData); }
|
||||
virtual void preStartNewScene(OctreeQueryNode* nodeData, bool isFullScene);
|
||||
virtual bool shouldTraverseAndSend(OctreeQueryNode* nodeData) { return hasSomethingToSend(nodeData); }
|
||||
virtual bool hasSomethingToSend(OctreeQueryNode* nodeData) = 0;
|
||||
virtual bool shouldStartNewTraversal(OctreeQueryNode* nodeData, bool viewFrustumChanged) = 0;
|
||||
|
||||
int _truePacketsSent { 0 }; // available for debug stats
|
||||
int _trueBytesSent { 0 }; // available for debug stats
|
||||
|
|
|
@ -876,10 +876,6 @@ void OctreeServer::parsePayload() {
|
|||
}
|
||||
}
|
||||
|
||||
OctreeServer::UniqueSendThread OctreeServer::newSendThread(const SharedNodePointer& node) {
|
||||
return std::unique_ptr<OctreeSendThread>(new OctreeSendThread(this, node));
|
||||
}
|
||||
|
||||
OctreeServer::UniqueSendThread OctreeServer::createSendThread(const SharedNodePointer& node) {
|
||||
auto sendThread = newSendThread(node);
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ protected:
|
|||
void beginRunning(QByteArray replaceData);
|
||||
|
||||
UniqueSendThread createSendThread(const SharedNodePointer& node);
|
||||
virtual UniqueSendThread newSendThread(const SharedNodePointer& node);
|
||||
virtual UniqueSendThread newSendThread(const SharedNodePointer& node) = 0;
|
||||
|
||||
int _argc;
|
||||
const char** _argv;
|
||||
|
|
|
@ -105,8 +105,6 @@ EntityScriptServer::~EntityScriptServer() {
|
|||
static const QString ENTITY_SCRIPT_SERVER_LOGGING_NAME = "entity-script-server";
|
||||
|
||||
void EntityScriptServer::handleReloadEntityServerScriptPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
||||
// These are temporary checks until we can ensure that nodes eventually disconnect if the Domain Server stops telling them
|
||||
// about each other.
|
||||
if (senderNode->getCanRez() || senderNode->getCanRezTmp() || senderNode->getCanRezCertified() || senderNode->getCanRezTmpCertified()) {
|
||||
auto entityID = QUuid::fromRfc4122(message->read(NUM_BYTES_RFC4122_UUID));
|
||||
|
||||
|
@ -119,8 +117,6 @@ void EntityScriptServer::handleReloadEntityServerScriptPacket(QSharedPointer<Rec
|
|||
}
|
||||
|
||||
void EntityScriptServer::handleEntityScriptGetStatusPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
||||
// These are temporary checks until we can ensure that nodes eventually disconnect if the Domain Server stops telling them
|
||||
// about each other.
|
||||
if (senderNode->getCanRez() || senderNode->getCanRezTmp() || senderNode->getCanRezCertified() || senderNode->getCanRezTmpCertified()) {
|
||||
MessageID messageID;
|
||||
message->readPrimitive(&messageID);
|
||||
|
@ -190,15 +186,14 @@ void EntityScriptServer::updateEntityPPS() {
|
|||
}
|
||||
|
||||
void EntityScriptServer::handleEntityServerScriptLogPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
||||
// These are temporary checks until we can ensure that nodes eventually disconnect if the Domain Server stops telling them
|
||||
// about each other.
|
||||
bool canRezAny = senderNode->getCanRez() || senderNode->getCanRezTmp() || senderNode->getCanRezCertified() || senderNode->getCanRezTmpCertified();
|
||||
bool enable = false;
|
||||
message->readPrimitive(&enable);
|
||||
|
||||
auto senderUUID = senderNode->getUUID();
|
||||
auto it = _logListeners.find(senderUUID);
|
||||
|
||||
if (enable && senderNode->getCanRez()) {
|
||||
if (enable && canRezAny) {
|
||||
if (it == std::end(_logListeners)) {
|
||||
_logListeners.insert(senderUUID);
|
||||
qCInfo(entity_script_server) << "Node" << senderUUID << "subscribed to log stream";
|
||||
|
|
4
cmake/externals/crashpad/CMakeLists.txt
vendored
4
cmake/externals/crashpad/CMakeLists.txt
vendored
|
@ -6,8 +6,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
|||
if (WIN32)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL https://backtrace.io/download/crashpad_062317.zip
|
||||
URL_MD5 65817e564b3628492abfc1dbd2a1e98b
|
||||
URL http://public.highfidelity.com/dependencies/crashpad_062317.1.zip
|
||||
URL_MD5 9c84b77f5f23daf939da1371825ed2b1
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
|
|
16
cmake/externals/serverless-content/CMakeLists.txt
vendored
Normal file
16
cmake/externals/serverless-content/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
include(ExternalProject)
|
||||
|
||||
set(EXTERNAL_NAME serverless-content)
|
||||
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC66-v4.zip
|
||||
URL_MD5 d4f42f630986c83427ff39e1fe9908c6
|
||||
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")
|
|
@ -14,12 +14,24 @@ macro(GENERATE_INSTALLERS)
|
|||
|
||||
set(CPACK_MODULE_PATH ${CPACK_MODULE_PATH} "${HF_CMAKE_DIR}/templates")
|
||||
|
||||
set(_DISPLAY_NAME ${BUILD_ORGANIZATION})
|
||||
|
||||
if (CLIENT_ONLY)
|
||||
set(_PACKAGE_NAME_EXTRA "-Interface")
|
||||
set(INSTALLER_TYPE "client_only")
|
||||
string(REGEX REPLACE "High Fidelity" "High Fidelity Interface" _DISPLAY_NAME ${BUILD_ORGANIZATION})
|
||||
elseif (SERVER_ONLY)
|
||||
set(_PACKAGE_NAME_EXTRA "-Sandbox")
|
||||
set(INSTALLER_TYPE "server_only")
|
||||
string(REGEX REPLACE "High Fidelity" "High Fidelity Sandbox" _DISPLAY_NAME ${BUILD_ORGANIZATION})
|
||||
else ()
|
||||
set(_DISPLAY_NAME ${BUILD_ORGANIZATION})
|
||||
set(INSTALLER_TYPE "full")
|
||||
endif ()
|
||||
|
||||
set(CPACK_PACKAGE_NAME ${_DISPLAY_NAME})
|
||||
set(CPACK_PACKAGE_VENDOR "High Fidelity")
|
||||
set(CPACK_PACKAGE_VERSION ${BUILD_VERSION})
|
||||
set(CPACK_PACKAGE_FILE_NAME "HighFidelity-Beta-${BUILD_VERSION}")
|
||||
set(CPACK_PACKAGE_FILE_NAME "HighFidelity-Beta${_PACKAGE_NAME_EXTRA}-${BUILD_VERSION}")
|
||||
set(CPACK_NSIS_DISPLAY_NAME ${_DISPLAY_NAME})
|
||||
set(CPACK_NSIS_PACKAGE_NAME ${_DISPLAY_NAME})
|
||||
if (PR_BUILD)
|
||||
|
|
|
@ -73,6 +73,11 @@ macro(SET_PACKAGING_PARAMETERS)
|
|||
add_definitions(-DDEV_BUILD)
|
||||
endif ()
|
||||
|
||||
if (DEPLOY_PACKAGE)
|
||||
# for deployed packages always grab the serverless content
|
||||
set(DOWNLOAD_SERVERLESS_CONTENT ON)
|
||||
endif ()
|
||||
|
||||
if (APPLE)
|
||||
set(DMG_SUBFOLDER_NAME "${BUILD_ORGANIZATION}")
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#
|
||||
#
|
||||
# Created by Bradley Austin Davis on 2017/09/02
|
||||
# Copyright 2013-2017 High Fidelity, Inc.
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
#
|
||||
|
||||
# Construct a default QT location from a root path, a version and an architecture
|
||||
function(calculate_default_qt_dir _RESULT_NAME)
|
||||
|
@ -27,7 +27,7 @@ function(calculate_default_qt_dir _RESULT_NAME)
|
|||
endif()
|
||||
|
||||
set_from_env(QT_ROOT QT_ROOT ${QT_DEFAULT_ROOT})
|
||||
set_from_env(QT_VERSION QT_VERSION "5.9.1")
|
||||
set_from_env(QT_VERSION QT_VERSION "5.10.1")
|
||||
set_from_env(QT_ARCH QT_ARCH ${QT_DEFAULT_ARCH})
|
||||
|
||||
set(${_RESULT_NAME} "${QT_ROOT}/${QT_VERSION}/${QT_ARCH}" PARENT_SCOPE)
|
||||
|
@ -60,11 +60,11 @@ macro(setup_qt)
|
|||
#if (NOT EXISTS "${QT_DIR}/include/QtCore/QtGlobal")
|
||||
# message(FATAL_ERROR "Unable to locate Qt includes in ${QT_DIR}")
|
||||
#endif()
|
||||
|
||||
|
||||
if (NOT EXISTS "${QT_CMAKE_PREFIX_PATH}/Qt5Core/Qt5CoreConfig.cmake")
|
||||
message(FATAL_ERROR "Unable to locate Qt cmake config in ${QT_CMAKE_PREFIX_PATH}")
|
||||
endif()
|
||||
|
||||
|
||||
message(STATUS "The Qt build in use is: \"${QT_DIR}\"")
|
||||
|
||||
# Instruct CMake to run moc automatically when needed.
|
||||
|
@ -72,7 +72,7 @@ macro(setup_qt)
|
|||
|
||||
# Instruct CMake to run rcc automatically when needed
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
|
||||
if (WIN32)
|
||||
add_paths_to_fixup_libs("${QT_DIR}/bin")
|
||||
endif ()
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
# FindGVerb.cmake
|
||||
#
|
||||
# Try to find the Gverb library.
|
||||
#
|
||||
# You must provide a GVERB_ROOT_DIR which contains src and include directories
|
||||
#
|
||||
# Once done this will define
|
||||
#
|
||||
# GVERB_FOUND - system found Gverb
|
||||
# GVERB_INCLUDE_DIRS - the Gverb include directory
|
||||
#
|
||||
# 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("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
||||
hifi_library_search_hints("gverb")
|
||||
|
||||
find_path(GVERB_INCLUDE_DIRS gverb.h PATH_SUFFIXES include HINTS ${GVERB_SEARCH_DIRS})
|
||||
find_library(GVERB_LIBRARIES gverb PATH_SUFFIXES lib HINTS ${GVERB_SEARCH_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Gverb DEFAULT_MSG GVERB_INCLUDE_DIRS GVERB_LIBRARIES)
|
|
@ -48,3 +48,4 @@ set(UNINSTALLER_HEADER_IMAGE "@UNINSTALLER_HEADER_IMAGE@")
|
|||
set(ADD_REMOVE_ICON_PATH "@ADD_REMOVE_ICON_PATH@")
|
||||
set(SERVER_COMPONENT_CONDITIONAL "@SERVER_COMPONENT_CONDITIONAL@")
|
||||
set(CLIENT_COMPONENT_CONDITIONAL "@CLIENT_COMPONENT_CONDITIONAL@")
|
||||
set(INSTALLER_TYPE "@INSTALLER_TYPE@")
|
||||
|
|
|
@ -710,11 +710,9 @@ Function PostInstallOptionsPage
|
|||
!insertmacro SetInstallOption $ServerStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_CHECKED}
|
||||
${EndIf}
|
||||
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Perform a clean install (Delete older settings and content)"
|
||||
Pop $CleanInstallCheckbox
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
${EndIf}
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Perform a clean install (Delete older settings and content)"
|
||||
Pop $CleanInstallCheckbox
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
|
||||
${If} @PR_BUILD@ == 1
|
||||
; a PR build defaults all install options expect LaunchServerNowCheckbox, LaunchClientNowCheckbox and the settings copy to unchecked
|
||||
|
@ -809,10 +807,8 @@ Function ReadPostInstallOptions
|
|||
${NSD_GetState} $LaunchClientNowCheckbox $LaunchClientNowState
|
||||
${EndIf}
|
||||
|
||||
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||
; check if the user asked for a clean install
|
||||
${NSD_GetState} $CleanInstallCheckbox $CleanInstallState
|
||||
${EndIf}
|
||||
; check if the user asked for a clean install
|
||||
${NSD_GetState} $CleanInstallCheckbox $CleanInstallState
|
||||
FunctionEnd
|
||||
|
||||
Function HandlePostInstallOptions
|
||||
|
@ -856,13 +852,23 @@ Function HandlePostInstallOptions
|
|||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||
; check if the user asked for a clean install
|
||||
${If} $CleanInstallState == ${BST_CHECKED}
|
||||
SetShellVarContext current
|
||||
RMDir /r "$APPDATA\@BUILD_ORGANIZATION@"
|
||||
RMDir /r "$LOCALAPPDATA\@BUILD_ORGANIZATION@"
|
||||
; check if the user asked for a clean install
|
||||
${If} $CleanInstallState == ${BST_CHECKED}
|
||||
SetShellVarContext current
|
||||
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
RMDir /r "$APPDATA\@BUILD_ORGANIZATION@\Server Console"
|
||||
RMDir /r "$APPDATA\@BUILD_ORGANIZATION@\assignment-client"
|
||||
RMDir /r "$APPDATA\@BUILD_ORGANIZATION@\domain-server"
|
||||
Delete "$APPDATA\@BUILD_ORGANIZATION@\domain-server.json"
|
||||
${EndIf}
|
||||
|
||||
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||
Delete "$APPDATA\@BUILD_ORGANIZATION@\Interface\AccountInfo.bin"
|
||||
Delete "$APPDATA\@BUILD_ORGANIZATION@\Interface.json"
|
||||
${EndIf}
|
||||
|
||||
RMDir /r "$LOCALAPPDATA\@BUILD_ORGANIZATION@"
|
||||
${EndIf}
|
||||
|
||||
${If} @PR_BUILD@ == 1
|
||||
|
@ -976,6 +982,13 @@ Section "-Core installation"
|
|||
;Store installation folder
|
||||
WriteRegStr HKLM "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR
|
||||
|
||||
;Write some information about this install to the installation folder
|
||||
FileOpen $0 "$INSTDIR\installer.ini" w
|
||||
FileWrite $0 "type=@INSTALLER_TYPE@$\r$\n"
|
||||
FileWrite $0 "campaign=$CampaignName$\r$\n"
|
||||
FileWrite $0 "exepath=$EXEPATH$\r$\n"
|
||||
FileClose $0
|
||||
|
||||
;Package the signed uninstaller produced by the inner loop
|
||||
!ifndef INNER
|
||||
; this packages the signed uninstaller
|
||||
|
@ -1221,6 +1234,9 @@ Section "Uninstall"
|
|||
|
||||
@CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@
|
||||
|
||||
;Remove the installer information file
|
||||
Delete "$INSTDIR\installer.ini"
|
||||
|
||||
;Remove files we installed.
|
||||
;Keep the list of directories here in sync with the File commands above.
|
||||
@CPACK_NSIS_DELETE_FILES@
|
||||
|
|
|
@ -611,23 +611,13 @@ bool DomainServer::isPacketVerified(const udt::Packet& packet) {
|
|||
// let the NodeList do its checks now (but pass it the sourceNode so it doesn't need to look it up again)
|
||||
return nodeList->isPacketVerifiedWithSource(packet, sourceNode.data());
|
||||
} else {
|
||||
static const QString UNKNOWN_REGEX = "Packet of type \\d+ \\([\\sa-zA-Z:]+\\) received from unmatched IP for UUID";
|
||||
static QString repeatedMessage
|
||||
= LogHandler::getInstance().addRepeatedMessageRegex(UNKNOWN_REGEX);
|
||||
|
||||
qDebug() << "Packet of type" << headerType
|
||||
<< "received from unmatched IP for UUID" << uuidStringWithoutCurlyBraces(sourceNode->getUUID());
|
||||
|
||||
HIFI_FDEBUG("Packet of type" << headerType
|
||||
<< "received from unmatched IP for UUID" << uuidStringWithoutCurlyBraces(sourceNode->getUUID()));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
static const QString UNKNOWN_REGEX = "Packet of type \\d+ \\([\\sa-zA-Z:]+\\) received from unknown node with Local ID";
|
||||
static QString repeatedMessage
|
||||
= LogHandler::getInstance().addRepeatedMessageRegex(UNKNOWN_REGEX);
|
||||
|
||||
qDebug() << "Packet of type" << headerType
|
||||
<< "received from unknown node with Local ID" << localSourceID;
|
||||
|
||||
HIFI_FDEBUG("Packet of type" << headerType
|
||||
<< "received from unknown node with Local ID" << localSourceID);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1046,41 +1036,7 @@ void DomainServer::processListRequestPacket(QSharedPointer<ReceivedMessage> mess
|
|||
|
||||
bool DomainServer::isInInterestSet(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB) {
|
||||
auto nodeAData = static_cast<DomainServerNodeData*>(nodeA->getLinkedData());
|
||||
auto nodeBData = static_cast<DomainServerNodeData*>(nodeB->getLinkedData());
|
||||
|
||||
// if we have no linked data for node A then B can't possibly be in the interest set
|
||||
if (!nodeAData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// first check if the general interest set A contains the type for B
|
||||
if (nodeAData->getNodeInterestSet().contains(nodeB->getType())) {
|
||||
// given that there is a match in the general interest set, do any special checks
|
||||
|
||||
// (1/19/17) Agents only need to connect to Entity Script Servers to perform administrative tasks
|
||||
// related to entity server scripts. Only agents with rez permissions should be doing that, so
|
||||
// if the agent does not have those permissions, we do not want them and the server to incur the
|
||||
// overhead of connecting to one another. Additionally we exclude agents that do not care about the
|
||||
// Entity Script Server and won't attempt to connect to it.
|
||||
|
||||
bool isAgentWithoutRights = nodeA->getType() == NodeType::Agent
|
||||
&& nodeB->getType() == NodeType::EntityScriptServer
|
||||
&& !nodeA->getCanRez() && !nodeA->getCanRezTmp()
|
||||
&& !nodeA->getCanRezCertified() && !nodeA->getCanRezTmpCertified();
|
||||
|
||||
if (isAgentWithoutRights) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isScriptServerForIneffectiveAgent =
|
||||
(nodeA->getType() == NodeType::EntityScriptServer && nodeB->getType() == NodeType::Agent)
|
||||
&& ((nodeBData && !nodeBData->getNodeInterestSet().contains(NodeType::EntityScriptServer))
|
||||
|| (!nodeB->getCanRez() && !nodeB->getCanRezTmp() && !nodeB->getCanRezCertified() && !nodeB->getCanRezTmpCertified()));
|
||||
|
||||
return !isScriptServerForIneffectiveAgent;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return nodeAData && nodeAData->getNodeInterestSet().contains(nodeB->getType());
|
||||
}
|
||||
|
||||
unsigned int DomainServer::countConnectedUsers() {
|
||||
|
@ -1283,31 +1239,16 @@ void DomainServer::processRequestAssignmentPacket(QSharedPointer<ReceivedMessage
|
|||
|
||||
auto it = find_if(_acSubnetWhitelist.begin(), _acSubnetWhitelist.end(), isHostAddressInSubnet);
|
||||
if (it == _acSubnetWhitelist.end()) {
|
||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex(
|
||||
"Received an assignment connect request from a disallowed ip address: [^ ]+");
|
||||
qDebug() << "Received an assignment connect request from a disallowed ip address:"
|
||||
<< senderAddr.toString();
|
||||
HIFI_FDEBUG("Received an assignment connect request from a disallowed ip address:"
|
||||
<< senderAddr.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
// Suppress these for Assignment::AgentType to once per 5 seconds
|
||||
static QElapsedTimer noisyMessageTimer;
|
||||
static bool wasNoisyTimerStarted = false;
|
||||
|
||||
if (!wasNoisyTimerStarted) {
|
||||
noisyMessageTimer.start();
|
||||
wasNoisyTimerStarted = true;
|
||||
}
|
||||
|
||||
const qint64 NOISY_MESSAGE_INTERVAL_MSECS = 5 * 1000;
|
||||
|
||||
if (requestAssignment.getType() != Assignment::AgentType
|
||||
|| noisyMessageTimer.elapsed() > NOISY_MESSAGE_INTERVAL_MSECS) {
|
||||
static QString repeatedMessage = LogHandler::getInstance().addOnlyOnceMessageRegex
|
||||
("Received a request for assignment type [^ ]+ from [^ ]+");
|
||||
static bool printedAssignmentTypeMessage = false;
|
||||
if (!printedAssignmentTypeMessage && requestAssignment.getType() != Assignment::AgentType) {
|
||||
printedAssignmentTypeMessage = true;
|
||||
qDebug() << "Received a request for assignment type" << requestAssignment.getType()
|
||||
<< "from" << message->getSenderSockAddr();
|
||||
noisyMessageTimer.restart();
|
||||
}
|
||||
|
||||
SharedAssignmentPointer assignmentToDeploy = deployableAssignmentForRequest(requestAssignment);
|
||||
|
@ -1341,13 +1282,11 @@ void DomainServer::processRequestAssignmentPacket(QSharedPointer<ReceivedMessage
|
|||
_gatekeeper.addPendingAssignedNode(uniqueAssignment.getUUID(), assignmentToDeploy->getUUID(),
|
||||
requestAssignment.getWalletUUID(), requestAssignment.getNodeVersion());
|
||||
} else {
|
||||
if (requestAssignment.getType() != Assignment::AgentType
|
||||
|| noisyMessageTimer.elapsed() > NOISY_MESSAGE_INTERVAL_MSECS) {
|
||||
static QString repeatedMessage = LogHandler::getInstance().addOnlyOnceMessageRegex
|
||||
("Unable to fulfill assignment request of type [^ ]+ from [^ ]+");
|
||||
static bool printedAssignmentRequestMessage = false;
|
||||
if (!printedAssignmentRequestMessage && requestAssignment.getType() != Assignment::AgentType) {
|
||||
printedAssignmentRequestMessage = true;
|
||||
qDebug() << "Unable to fulfill assignment request of type" << requestAssignment.getType()
|
||||
<< "from" << message->getSenderSockAddr();
|
||||
noisyMessageTimer.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1593,10 +1532,12 @@ void DomainServer::sendICEServerAddressToMetaverseAPI() {
|
|||
callbackParameters.jsonCallbackReceiver = this;
|
||||
callbackParameters.jsonCallbackMethod = "handleSuccessfulICEServerAddressUpdate";
|
||||
|
||||
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 bool printedIceServerMessage = false;
|
||||
if (!printedIceServerMessage) {
|
||||
printedIceServerMessage = true;
|
||||
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";
|
||||
|
||||
|
@ -3482,4 +3423,4 @@ void DomainServer::handleOctreeFileReplacementRequest(QSharedPointer<ReceivedMes
|
|||
if (node->getCanReplaceContent()) {
|
||||
handleOctreeFileReplacement(message->readAll());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ endif()
|
|||
list(APPEND GENERATE_QRC_DEPENDS ${RESOURCES_RCC})
|
||||
add_custom_target(resources ALL DEPENDS ${GENERATE_QRC_DEPENDS})
|
||||
|
||||
|
||||
# set a default root dir for each of our optional externals if it was not passed
|
||||
set(OPTIONAL_EXTERNALS "LeapMotion")
|
||||
|
||||
|
@ -181,8 +180,9 @@ else ()
|
|||
add_executable(${TARGET_NAME} ${INTERFACE_SRCS} ${QM})
|
||||
endif ()
|
||||
|
||||
|
||||
if (BUILD_TOOLS AND NPM_EXECUTABLE)
|
||||
# require JSDoc to be build before interface is deployed (Console Auto-complete)
|
||||
# require JSDoc to be build before interface is deployed
|
||||
add_dependencies(resources jsdoc)
|
||||
endif()
|
||||
|
||||
|
@ -314,35 +314,55 @@ if (APPLE)
|
|||
)
|
||||
|
||||
set(SCRIPTS_INSTALL_DIR "${INTERFACE_INSTALL_APP_PATH}/Contents/Resources")
|
||||
|
||||
set(RESOURCES_DEV_DIR "$<TARGET_FILE_DIR:${TARGET_NAME}>/../Resources")
|
||||
|
||||
# copy script files beside the executable
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||
"${CMAKE_SOURCE_DIR}/scripts"
|
||||
"$<TARGET_FILE_DIR:${TARGET_NAME}>/../Resources/scripts"
|
||||
"${RESOURCES_DEV_DIR}/scripts"
|
||||
)
|
||||
|
||||
# copy JSDoc files beside the executable
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||
"${CMAKE_SOURCE_DIR}/tools/jsdoc/out"
|
||||
"${RESOURCES_DEV_DIR}/jsdoc"
|
||||
)
|
||||
|
||||
# call the fixup_interface macro to add required bundling commands for installation
|
||||
fixup_interface()
|
||||
|
||||
else()
|
||||
set(INTERFACE_EXEC_DIR "$<TARGET_FILE_DIR:${TARGET_NAME}>")
|
||||
set(RESOURCES_DEV_DIR "${INTERFACE_EXEC_DIR}/resources")
|
||||
|
||||
# copy the resources files beside the executable
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||
"${RESOURCES_RCC}"
|
||||
"$<TARGET_FILE_DIR:interface>"
|
||||
"${RESOURCES_RCC}"
|
||||
"${INTERFACE_EXEC_DIR}"
|
||||
# FIXME, the edit script code loads HTML from the scripts folder
|
||||
# which in turn relies on CSS that refers to the fonts. In theory
|
||||
# we should be able to modify the CSS to reference the QRC path to
|
||||
# the ttf files, but doing so generates a CORS policy violation,
|
||||
# so we have to retain a copy of the fonts outside of the resources binary
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||
"${PROJECT_SOURCE_DIR}/resources/fonts"
|
||||
"$<TARGET_FILE_DIR:${TARGET_NAME}>/resources/fonts"
|
||||
"${PROJECT_SOURCE_DIR}/resources/fonts"
|
||||
"${RESOURCES_DEV_DIR}/fonts"
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||
"${CMAKE_SOURCE_DIR}/scripts"
|
||||
"$<TARGET_FILE_DIR:${TARGET_NAME}>/scripts"
|
||||
"${CMAKE_SOURCE_DIR}/scripts"
|
||||
"${INTERFACE_EXEC_DIR}/scripts"
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||
"${PROJECT_SOURCE_DIR}/resources/serverless/tutorial.json"
|
||||
"${RESOURCES_DEV_DIR}/serverless/tutorial.json"
|
||||
)
|
||||
|
||||
# copy JSDoc files beside the executable
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||
"${CMAKE_SOURCE_DIR}/tools/jsdoc/out"
|
||||
"${INTERFACE_EXEC_DIR}/jsdoc"
|
||||
)
|
||||
|
||||
# link target to external libraries
|
||||
|
@ -368,7 +388,6 @@ else()
|
|||
endif()
|
||||
|
||||
if (SCRIPTS_INSTALL_DIR)
|
||||
|
||||
# setup install of scripts beside interface executable
|
||||
install(
|
||||
DIRECTORY "${CMAKE_SOURCE_DIR}/scripts/"
|
||||
|
@ -377,6 +396,19 @@ if (SCRIPTS_INSTALL_DIR)
|
|||
)
|
||||
endif()
|
||||
|
||||
if (DOWNLOAD_SERVERLESS_CONTENT)
|
||||
add_dependency_external_projects(serverless-content)
|
||||
|
||||
ExternalProject_Get_Property(serverless-content SOURCE_DIR)
|
||||
|
||||
# for dev builds, copy the serverless content to the resources folder
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||
"${SOURCE_DIR}"
|
||||
"${RESOURCES_DEV_DIR}/serverless"
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (WIN32)
|
||||
set(EXTRA_DEPLOY_OPTIONS "--qmldir \"${PROJECT_SOURCE_DIR}/resources/qml\"")
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Layouts 1.0
|
||||
|
||||
import "../../qml/dialogs"
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import QtQuick 2.4
|
||||
import QtQuick.Dialogs 1.1
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
import "../../qml/dialogs"
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Controls
|
||||
|
||||
import "../../qml/controls-uit"
|
||||
import "../../qml/styles-uit"
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Controls
|
||||
|
||||
import "../../qml/controls-uit"
|
||||
import "../../qml/styles-uit"
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Layouts 1.0
|
||||
|
||||
import "../../qml/controls-uit"
|
||||
import "../../qml/styles-uit"
|
||||
|
|
|
@ -1,15 +1,10 @@
|
|||
{
|
||||
"name": "Keyboard/Mouse to Actions",
|
||||
"channels": [
|
||||
|
||||
{ "from": "Keyboard.A", "when": "Keyboard.Shift", "to": "Actions.LATERAL_LEFT" },
|
||||
{ "from": "Keyboard.D", "when": "Keyboard.Shift", "to": "Actions.LATERAL_RIGHT" },
|
||||
{ "from": "Keyboard.A", "when": "Keyboard.RightMouseButton", "to": "Actions.LATERAL_LEFT" },
|
||||
{ "from": "Keyboard.D", "when": "Keyboard.RightMouseButton", "to": "Actions.LATERAL_RIGHT" },
|
||||
{ "from": "Keyboard.E", "when": "Keyboard.Shift", "to": "Actions.BOOM_IN", "filters": [ { "type": "scale", "scale": 0.05 } ] },
|
||||
{ "from": "Keyboard.C", "when": "Keyboard.Shift", "to": "Actions.BOOM_OUT", "filters": [ { "type": "scale", "scale": 0.05 } ] },
|
||||
{ "from": "Keyboard.S", "when": "Keyboard.Shift", "to": "Actions.PITCH_DOWN" },
|
||||
{ "from": "Keyboard.W", "when": "Keyboard.Shift", "to": "Actions.PITCH_UP" },
|
||||
{ "from": "Keyboard.E", "to": "Actions.LATERAL_RIGHT" },
|
||||
{ "from": "Keyboard.Q", "to": "Actions.LATERAL_LEFT" },
|
||||
|
||||
|
||||
{ "comment" : "Mouse turn need to be small continuous increments",
|
||||
|
@ -44,9 +39,24 @@
|
|||
]
|
||||
},
|
||||
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.A", "Keyboard.Left" ],
|
||||
["Keyboard.D", "Keyboard.Right"]
|
||||
["Keyboard.Left" ],
|
||||
["Keyboard.Right"]
|
||||
]
|
||||
},
|
||||
"when": ["Application.InHMD", "Application.SnapTurn", "!Keyboard.Shift"],
|
||||
"to": "Actions.StepYaw",
|
||||
"filters":
|
||||
[
|
||||
{ "type": "pulse", "interval": 0.5, "resetOnZero": true },
|
||||
{ "type": "scale", "scale": 22.5 }
|
||||
]
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.A"],
|
||||
["Keyboard.D"]
|
||||
]
|
||||
},
|
||||
"when": [ "Application.InHMD", "Application.SnapTurn" ],
|
||||
|
@ -59,26 +69,39 @@
|
|||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.A", "Keyboard.Left", "Keyboard.TouchpadLeft"],
|
||||
["Keyboard.D", "Keyboard.Right", "Keyboard.TouchpadRight"]
|
||||
["Keyboard.Left"],
|
||||
["Keyboard.Right"]
|
||||
]
|
||||
},
|
||||
"when": ["Application.CameraFirstPerson", "!Keyboard.Shift"],
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.Left"],
|
||||
["Keyboard.Right"]
|
||||
]
|
||||
},
|
||||
"when": ["Application.CameraThirdPerson", "!Keyboard.Shift"],
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.A", "Keyboard.TouchpadLeft"],
|
||||
["Keyboard.D", "Keyboard.TouchpadRight"]
|
||||
]
|
||||
},
|
||||
"when": "Application.CameraFirstPerson",
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.A", "Keyboard.Left", "Keyboard.TouchpadLeft"],
|
||||
["Keyboard.D", "Keyboard.Right", "Keyboard.TouchpadRight"]
|
||||
["Keyboard.A", "Keyboard.TouchpadLeft"],
|
||||
["Keyboard.D", "Keyboard.TouchpadRight"]
|
||||
]
|
||||
},
|
||||
"when": "Application.CameraThirdPerson",
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
{ "from": { "makeAxis" : [ ["Keyboard.A"], ["Keyboard.D"] ] },
|
||||
"when": "Application.CameraFSM",
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : ["Keyboard.MouseMoveLeft", "Keyboard.MouseMoveRight"] },
|
||||
"when": "Keyboard.RightMouseButton",
|
||||
"to": "Actions.Yaw",
|
||||
|
@ -90,14 +113,10 @@
|
|||
|
||||
{ "from": "Keyboard.W", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_FORWARD" },
|
||||
{ "from": "Keyboard.S", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_BACKWARD" },
|
||||
{ "from": "Keyboard.Shift", "when": ["!Keyboard.Left", "!Keyboard.Right"], "to": "Actions.SPRINT" },
|
||||
{ "from": "Keyboard.C", "to": "Actions.VERTICAL_DOWN" },
|
||||
{ "from": "Keyboard.E", "to": "Actions.VERTICAL_UP" },
|
||||
{ "from": "Keyboard.Left", "when": "Keyboard.RightMouseButton", "to": "Actions.LATERAL_LEFT" },
|
||||
{ "from": "Keyboard.Right", "when": "Keyboard.RightMouseButton", "to": "Actions.LATERAL_RIGHT" },
|
||||
{ "from": "Keyboard.Left", "when": "Keyboard.Shift", "to": "Actions.LATERAL_LEFT" },
|
||||
{ "from": "Keyboard.Right", "when": "Keyboard.Shift", "to": "Actions.LATERAL_RIGHT" },
|
||||
{ "from": "Keyboard.Down", "when": "Keyboard.Shift", "to": "Actions.PITCH_DOWN" },
|
||||
{ "from": "Keyboard.Up", "when": "Keyboard.Shift", "to": "Actions.PITCH_UP" },
|
||||
{ "from": "Keyboard.Up", "when": "Application.CameraFirstPerson", "to": "Actions.LONGITUDINAL_FORWARD" },
|
||||
{ "from": "Keyboard.Up", "when": "Application.CameraThirdPerson", "to": "Actions.LONGITUDINAL_FORWARD" },
|
||||
{ "from": "Keyboard.Down", "when": "Application.CameraFirstPerson", "to": "Actions.LONGITUDINAL_BACKWARD" },
|
||||
|
@ -128,7 +147,7 @@
|
|||
{ "from": "Keyboard.MouseWheelLeft", "to": "Actions.BOOM_OUT", "filters": [ { "type": "scale", "scale": 0.02 } ]},
|
||||
{ "from": "Keyboard.MouseWheelRight", "to": "Actions.BOOM_IN", "filters": [ { "type": "scale", "scale": 0.02 } ]},
|
||||
|
||||
{ "from": "Keyboard.Space", "to": "Actions.SHIFT" },
|
||||
{ "from": "Keyboard.Space", "to": "Actions.VERTICAL_UP" },
|
||||
{ "from": "Keyboard.R", "to": "Actions.ACTION1" },
|
||||
{ "from": "Keyboard.T", "to": "Actions.ACTION2" },
|
||||
{ "from": "Keyboard.Tab", "to": "Actions.ContextMenu" }
|
||||
|
|
|
@ -5,8 +5,25 @@
|
|||
|
||||
{ "from": "TouchscreenVirtualPad.LX", "when": "!Application.CameraIndependent", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Actions.TranslateX" },
|
||||
|
||||
{ "from": "TouchscreenVirtualPad.RX", "when": "!Application.CameraIndependent", "filters": [ {"type": "deadZone", "min": 0.05} , "invert" ], "to": "Actions.Yaw" },
|
||||
{ "from": "TouchscreenVirtualPad.JUMP_BUTTON_PRESS", "when": "!Application.CameraIndependent", "to": "Actions.VERTICAL_UP" },
|
||||
|
||||
{ "from": "TouchscreenVirtualPad.RX", "when": "!Application.CameraIndependent",
|
||||
"filters": [
|
||||
{ "type": "deadZone", "min": 0.000 },
|
||||
{ "type": "scale", "scale": 0.06 },
|
||||
"invert"
|
||||
],
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": "TouchscreenVirtualPad.RY", "when": "!Application.CameraIndependent",
|
||||
"filters": [
|
||||
{ "type": "deadZone", "min": 0.000 },
|
||||
{ "type": "scale", "scale": 0.06 },
|
||||
"invert"
|
||||
],
|
||||
"to": "Actions.Pitch"
|
||||
}
|
||||
|
||||
{ "from": "TouchscreenVirtualPad.RY", "when": "!Application.CameraIndependent", "filters": [ {"type": "deadZone", "min": 0.05}, "invert" ], "to": "Actions.Pitch" }
|
||||
]
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -25,7 +25,6 @@
|
|||
<glyph glyph-name="web" unicode="q" d="M438 390c0 8-6 15-14 15l-333 0c-8 0-15-7-15-15l0-298c0-8 7-14 15-14l333 0c8 0 14 6 14 14z m-219-8l172 0c8 0 15-7 15-16 0-9-7-16-15-16l-172 0c-8 0-15 7-15 16 0 9 7 16 15 16z m-47 1c9 0 16-7 16-16 0-10-7-17-16-17-10 0-17 7-17 17 0 9 7 16 17 16z m-51 0c9 0 17-7 17-16 0-10-8-17-17-17-9 0-17 7-17 17 0 9 8 16 17 16z m291-276l-308 0 0 219 308 0z m-250 84l-15 0-20 60 13 0 14-45 15 45 13 0 15-45 14 45 13 0-20-60-14 0-14 41z m137 25l-46 0c0-5 2-8 6-11 3-2 8-4 12-4 8 0 13 3 17 7l7-8c-6-6-14-9-25-9-8 0-15 2-21 8-6 5-9 13-9 22 0 9 3 17 9 22 6 6 13 9 21 9 8 0 15-3 21-8 6-5 8-11 8-20z m-46 9l34 0c0 5-2 9-5 12-3 3-7 4-11 4-5 0-9-1-13-4-3-3-5-7-5-12z m101 27c8 0 14-3 20-9 6-5 9-12 9-22 0-9-3-16-9-22-5-6-12-8-19-8-8 0-15 3-21 9l0-9-12 0 0 83 12 0 0-34c5 8 12 12 20 12z m-20-31c0-6 2-10 5-14 4-4 8-5 13-5 5 0 9 1 13 5 3 4 5 8 5 14 0 6-2 10-5 14-4 4-8 6-13 6-5 0-9-2-13-6-3-4-5-8-5-14z"/>
|
||||
<glyph glyph-name="web-2" unicode="r" d="M438 390c0 8-6 15-14 15l-333 0c-8 0-15-7-15-15l0-298c0-8 7-14 15-14l333 0c8 0 14 6 14 14z m-219-8l172 0c8 0 15-7 15-16 0-9-7-16-15-16l-172 0c-8 0-15 7-15 16 0 9 7 16 15 16z m-47 1c9 0 16-7 16-16 0-10-7-17-16-17-10 0-17 7-17 17 0 9 7 16 17 16z m-51 0c9 0 17-7 17-16 0-10-8-17-17-17-9 0-17 7-17 17 0 9 8 16 17 16z m291-276l-308 0 0 219 308 0z"/>
|
||||
<glyph glyph-name="edit" unicode="s" d="M196 214c-27-27-54-54-81-81-6 6-13 13-19 19 27 27 54 54 81 81l-22 21c-31-31-61-62-92-92-7-7-11-13-12-22-3-25-7-50-11-76 3 0 4 0 6 0 24 5 48 10 72 15 5 1 10 4 13 7 32 32 64 64 96 96z m126 207c10 10 21 21 33 32 4 4 10 4 14 0 19-19 38-38 57-57 4-5 4-10 0-15-11-11-22-22-34-33-23 24-46 48-70 73z m23-181c-5-1-8 0-11 3-8 8-15 15-23 23 18 18 37 37 55 55 2 2 4 4 4 4-24 25-47 49-71 74-2-2-3-4-5-6-18-18-37-37-55-55-34 34-67 67-101 101-2 2-5 5-8 7-18 14-42 12-57-5-15-17-14-42 2-58 50-51 101-101 151-151 17-16 33-33 50-49 2-3 3-5 2-8-2-8-4-15-4-23-4-48 27-90 73-102 20-5 39-4 58 4-1 2-3 3-5 4-14 14-28 28-42 42-10 11-11 26-2 36 8 8 16 16 24 24 11 10 24 10 35 0 2-1 4-4 6-6 15-14 29-28 43-42 0 0 1 0 2 1 1 8 3 16 4 24 7 69-59 123-125 103z m-243 162c-7 0-14 6-14 14 0 8 6 14 14 14 8 0 15-6 15-14 0-7-7-14-15-14z m198-46c6-6 13-12 19-19-13-13-26-26-39-39-7 6-13 12-20 19 14 13 27 26 40 39z"/>
|
||||
<glyph glyph-name="market" unicode="t" d="M88 370c3 0 7 0 10 0 6 0 11-1 15-2 9-2 16-8 20-16 3-5 4-10 6-15 2-6 3-13 5-19 3-10 5-19 8-27 2-6 3-13 5-19 3-7 5-15 7-23 3-9 6-19 9-30 0-2 1-4 1-6 2-8 5-17 9-24 3-7 8-12 13-15 6-3 13-5 22-6 2 0 5 0 7 0l21 0 57 0c25 0 50 0 75 0 12 0 25 0 37 0 1 0 1 0 2 0 6 0 13 0 17 2 5 3 7 9 9 16l3 10c0 0 0 0 0 0 0 2 1 3 1 3 5 20 11 40 17 60 1 4 2 9 4 13 2 8 4 16 7 24 2 7 4 16 0 22-3 4-9 5-14 5-6 0-188-2-284-4l-4 0-5 22c0 3-1 6-2 9 0 3-1 5-1 7-1 2-1 3-1 4-1 4-2 7-3 11-2 6-6 12-11 17-5 5-11 8-17 9-3 1-6 1-10 1-5 1-9 1-14 1-19 0-38 0-59 0-1 0-3 0-4 0-3 0-7 0-10-1-3 0-6-2-8-4-3-5-4-11-2-17 2-5 6-6 9-7 4-1 8-1 13-1 5 0 10 0 16 0l16 0c3 0 5 0 8 0z m353-78l-26-92-6-4-2 0c-2 0-21 0-55 0-50 0-118-1-125-1l-1-1 0 0c-6 0-12 2-16 6-4 4-6 10-8 16-3 12-6 25-10 39-1 4-2 8-3 12-2 4-3 8-4 13l-4 12z m-194-164c-9 0-15-2-20-7-5-5-8-11-8-20 0-8 3-16 8-21 5-5 13-8 20-8 17 0 30 12 30 28 0 8-3 15-9 20-5 6-12 8-21 8z m139 0c-9 0-16-2-21-6-5-6-8-13-8-21 0-9 3-16 8-21 5-6 12-8 21-8 16 0 29 13 29 29 0 8-3 14-8 20-5 5-13 7-21 7z"/>
|
||||
<glyph glyph-name="directory" unicode="u" d="M432 451l-99-38c-2 0-3-1-4-1-3 1-5 2-8 2l-116 38c-8 3-15 6-30-1l-91-35c-17-5-32-16-32-31l0-303c0-15 14-27 32-27l99 38c3 1 6 2 9 4 1-1 3-2 4-2 3-1 5-2 7-3 0 0 1 0 1-1 0 0 1 0 1 0l116-38 0 0c8-1 12-1 21 3l90 34c13 6 32 16 32 31l0 304c0 14-14 26-32 26z m-351-371c-1 0-1 1-1 2l0 303c0 2 5 6 14 9l1 0 1 1 89 34c1-1 0-1 0-2l0-303c0-1-3-4-16-10z m356 42c-1-2-5-5-17-11l-90-34c0 1-1 1-1 2l0 304c0 1 5 5 14 8l1 0 1 1 91 34c0 0 1-1 1-1z"/>
|
||||
<glyph glyph-name="menu" unicode="v" d="M257 22c-60 0-119 22-164 67-44 44-68 102-68 164 0 62 24 120 68 163 90 91 237 91 327 0 44-43 68-101 68-163 0-62-24-120-68-164-45-45-104-67-163-67z m0 431c-52 0-103-20-142-59-38-38-58-88-58-141 0-54 20-104 58-142 78-78 205-78 283 0 38 38 59 88 59 142 0 53-21 103-59 141-39 39-90 59-141 59z m101-133l-203 0c-8 0-15 7-15 15 0 8 7 15 15 15l203 0c8 0 14-7 14-15 0-8-6-15-14-15z m0-84l-203 0c-8 0-15 7-15 15 0 8 7 15 15 15l203 0c8 0 14-7 14-15 0-8-6-15-14-15z m0-81l-203 0c-8 0-15 7-15 15 0 8 7 14 15 14l203 0c8 0 14-6 14-14 0-8-6-15-14-15z"/>
|
||||
<glyph glyph-name="close" unicode="w" d="M258 19c-59 0-118 23-163 68-44 43-68 101-68 163 0 62 24 120 68 164 90 90 237 90 327 0 44-44 68-102 68-164 0-62-24-120-68-163-45-45-104-68-164-68z m0 431c-51 0-102-19-141-58-38-38-59-88-59-142 0-53 21-103 59-141 78-78 205-78 283 0 38 38 58 88 58 141 0 54-20 104-58 142-39 39-90 58-142 58z m25-200l67 67c7 7 7 18 0 25-7 7-18 7-25 0l-67-67-66 67c-7 7-18 7-25 0-7-7-7-18 0-25l66-67-66-66c-7-7-7-18 0-25 7-7 18-7 25 0l66 66 67-66c7-7 18-7 25 0 7 7 7 18 0 25z"/>
|
||||
|
@ -145,4 +144,14 @@
|
|||
<glyph glyph-name="rez" unicode="" d="M373 321c-2 5-6 8-11 8l-49 8 55 61c4 4 5 9 3 14-2 5-7 8-12 8 0 0 0 0 0 0l-114-1c-5-1-10-4-12-9l-54-136c-1-4-1-8 1-11 2-4 6-6 9-7l38-5-54-136c-2-6 0-13 6-16 2-1 4-2 7-2 3 0 7 2 10 5l175 206c3 4 3 9 2 13z"/>
|
||||
<glyph glyph-name="keyboard-collapse" unicode="" d="M373 249l-26 0 0 25 26 0z m-35 0l-27 0 0 25 27 0z m-36 0l-27 0 0 25 27 0z m-36 0l-26 0 0 25 26 0z m-35 0l-27 0 0 25 27 0z m-36 0l-27 0 0 25 27 0z m-36 0l-26 0 0 25 26 0z m224-1l18 0c7 0 13 6 13 13 0 7-6 13-13 13l-18 0m-262 0l-17 0c-7 0-13-6-13-13 0-7 6-13 13-13l17 0m252 39l-31 0 0 25 31 0z m-42 0l-31 0 0 25 31 0z m-41 0l-32 0 0 25 32 0z m-42 0l-32 0 0 25 32 0z m-42 0l-32 0 0 25 32 0z m-41 0l-32 0 0 25 32 0z m218-1l18 0c7 0 13 6 13 13 0 8-6 14-13 14l-18 0m-262 0l-17 0c-7 0-13-6-13-14 0-7 6-13 13-13l17 0m288-124l-315 0c-33 0-59 28-59 61l0 76c0 34 26 61 59 61l315 0c33 0 59-27 59-61l0-76c1-33-26-61-59-61z m-315 172c-18 0-33-16-33-34l0-77c0-19 15-34 33-34l315 0c18 0 33 15 33 34l0 77c0 19-15 34-33 34z m248-99l32 0 0-25-32 0z m-41 0l31 0 0-25-31 0z m-42 0l31 0 0-25-31 0z m-43 0l32 0 0-25-32 0z m-42 0l32 0 0-25-32 0z m-41 0l31 0 0-25-31 0z m250-26l18 0c7 0 13 6 13 14 0 7-6 13-13 13l-18 0m-262 0l-17 0c-7 0-13-6-13-13 0-8 6-13 13-13l17 0m81-82l50-50 53 54-107 0"/>
|
||||
<glyph glyph-name="image" unicode="" d="M257 428c52 0 104 0 156 0 24 0 37-13 37-37 1-90 1-179 0-269 0-25-13-38-39-38-103 0-207 0-311 0-26 0-39 13-39 40 0 88 0 176 0 263 0 28 13 41 41 41 51 0 103 0 155 0z m167-263c0 7 0 10 0 14 0 69 0 138 0 206 0 17 0 17-17 17-101 0-202 0-303 0-16 0-17-1-17-17 0-58 0-115 0-173 0-3 0-7 0-12 8 3 14 6 19 9 17 8 30 7 44-6 5-5 10-10 15-15 5-7 11-8 19-4 40 21 81 41 121 61 19 10 31 8 46-7 9-9 18-18 27-27 15-15 29-29 46-46z m-328-54c7 0 11-1 15-1 98 0 197 0 296 0 6 0 14 2 16 6 5 7 0 14-6 20-27 26-54 53-80 80-8 9-15 9-26 4-67-35-135-68-203-102-3-2-6-4-12-7z m-8 26c21 10 40 20 63 31-8 7-14 12-20 17-2 2-7 3-10 3-30-9-36-17-34-48 0 0 0-1 1-3z m134 169c1-25-21-46-46-46-25-1-46 20-47 46 0 25 21 46 47 47 25 0 46-21 46-47z m-46 22c-12 0-22-9-22-21 0-13 9-22 21-23 13 0 23 9 23 22 0 13-10 22-22 22z"/>
|
||||
<glyph glyph-name="environments" unicode="" d="M256 454c-110 0-199-89-199-199 0-110 89-199 199-199 0 0 0 0 0 0l2-1 0 1c109 1 197 90 197 199 0 110-89 199-199 199z m114-204l0 0 0 5c0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 2l0 4 0 0c-1 22-4 43-10 63 21 5 36 11 46 15 15-26 24-56 24-87 0-30-8-59-23-85-8 4-23 11-47 16 6 21 9 42 10 64z m-19 102c-13 30-30 53-46 69 34-10 64-30 86-57-9-4-22-8-40-12z m-6-95c0-23-4-45-11-66-20 4-42 6-65 6l0 120c23 1 45 3 66 6 6-21 10-43 10-66z m-46-170c17 17 37 41 52 75 20-5 34-10 42-13-24-31-57-53-94-62z m-30 256l0 77c17-14 40-37 56-73-17-2-36-4-56-4z m0-248l0 77c20-1 39-3 56-5-16-35-40-59-56-72z m-83 252c17 35 40 59 56 73l0-77c-19 0-38 1-56 4z m-19-90c0 23 4 45 10 65 20-3 42-5 65-5l0-120c-23 0-45-1-65-4-6 20-10 42-10 64z m-47 106c22 28 52 48 86 58-15-16-33-39-46-70-18 4-31 8-40 12z m40-199c15-36 37-61 53-77-38 10-72 32-96 64 9 4 24 9 43 13z m82 8l0-77c-16 13-39 37-56 73 18 2 37 3 56 4z m-100 92l-1 0 0-4c0-1 0-1 0-2 0 0 0 0 0-1 0 0 0 0 0-1 0 0 0-1 0-1l0-5 1 0c0-21 4-42 10-62-23-5-39-10-49-15-14 25-21 53-21 82 0 30 8 60 23 86 10-4 25-10 47-14-6-20-10-41-10-63z"/>
|
||||
<glyph glyph-name="wand" unicode="" d="M438 107l-80 78c-5 5-12 7-18 6l-77 78c-5 5-14 5-19 0-5-5-6-14 0-19l77-79c0-6 2-12 7-17l80-78c5-4 10-6 15-6 6 0 12 2 16 6 8 9 8 22-1 31z m-185 209l-28 0 0 27c0 6-5 11-12 11-6 0-11-5-11-11l0-27-27 0c-6 0-11-5-11-12 0-6 5-11 11-11l27 0 0-28c0-6 5-11 11-11 7 0 12 5 12 11l0 28 28 0c6 0 11 5 11 11 0 7-5 12-11 12z m51-22c-6 0-10 4-10 10 0 5 4 10 10 10 15 0 31 0 45 0 6 0 10-5 10-10 0-6-4-10-10-10-14 0-30 0-45 0 0 0 0 0 0 0z m-184 0c0 0 0 0 0 0-12 0-26 0-40 0 0 0 0 0 0 0-5 0-10 4-10 10 0 5 5 10 10 10 14 0 28 0 41 0 5 0 10-5 10-10-1-6-5-10-11-10z m94-129c-5 0-10 4-10 9 0 14 0 26 0 40 0 5 5 9 10 9 0 0 0 0 0 0 6 0 10-5 10-10 0-13 0-25 0-38 0-6-4-10-10-10 0 0 0 0 0 0z m0 223c-5 0-10 4-10 9 0 14 0 26 0 40 0 5 5 9 10 9 6 0 10-5 10-10 0-13 0-25 0-38 0-6-4-10-10-10 0 0 0 0 0 0z m-68-26c-2 0-4 0-6 2-6 5-11 10-16 15-4 5-8 9-12 13-4 4-5 10-1 14 4 4 10 4 14 1 5-5 9-9 14-14 4-5 9-10 14-14 4-4 4-10 1-14-2-2-5-3-8-3z m-24-159c-3 0-5 1-7 3-4 3-4 10-1 14 5 5 9 10 14 14 5 4 9 8 12 12 4 4 10 5 14 1 4-4 5-10 1-14-4-5-9-10-13-14-5-4-9-8-13-12-2-2-4-4-7-4z m157 157c-3 0-5 1-6 2-5 3-6 10-2 14 4 6 10 11 15 16 5 4 10 8 13 12 3 5 10 6 14 2 4-3 5-9 2-14-5-6-10-10-15-15-5-4-10-8-13-13-2-2-5-4-8-4z"/>
|
||||
<glyph glyph-name="market" unicode="t" d="M428 332c-2 4-7 7-12 7-5 1-10 1-14 1-5 0-10 1-15 1-27 1-51 2-75 3-23 1-47 2-74 3-10 0-18 1-27 1-9 0-18 1-27 1l-1 0 0 1c-2 8-8 26-12 39-2 5-3 9-4 12-2 8-7 12-16 12l-48 0c-9 0-16-6-16-15 0-8 7-14 16-14l32 0c5 0 7-3 8-7l0 0c6-25 13-51 19-76 7-24 13-50 19-75 2-9 3-16 0-24-1-4-2-9-3-14-1-4-2-9-3-14-2-8-2-14 1-17 3-4 8-6 16-6l190 0c4 1 7 3 9 6 3 3 4 8 3 12-1 8-7 12-17 12l-170 0 1 1c0 1 1 4 1 6 2 7 5 17 4 20l0 1c1 6 5 10 12 10 8 0 16 0 24 0 43 2 87 3 128 5 8 1 12 4 15 10 8 15 29 65 36 86l0 0c3 4 3 8 0 12z m-45-224c0-16-13-30-29-30-16 0-29 13-29 30 0 15 13 30 29 30 16-1 29-15 29-30z m-177 1c0-16-14-29-29-29-16 0-29 14-29 29 0 17 13 30 29 30 16-1 29-14 29-30z"/>
|
||||
<glyph glyph-name="wear" unicode="" d="M451 180c3 1 5 4 6 7 1 3 1 7-1 10-2 3-4 5-8 6-3 1-6 1-10-1-6-4-13-5-19-6-3-1-6-1-7-1-1 0-1 0-1 0l-1 0-26 0 0 66c0 9-3 43-27 73-24 29-58 44-101 44-54 0-84-24-100-44-24-30-26-64-27-73l0-66-17 0c-2 0-4 0-8 1-8 1-17 3-27 7-7 3-14-1-17-7-2-7 1-14 8-17 14-6 27-8 33-9 3 0 6 0 8-1 1 0 1 0 2 0l299 0c1 0 2 0 3 0l0 0c2 1 6 1 10 2 6 1 18 3 28 9z m-295 80c0 15 6 39 20 58 18 22 45 34 80 34 35 0 62-12 80-34 15-19 21-43 22-58l0-6-202 0z m202-65l-202 0 0 33 202 0z"/>
|
||||
<glyph glyph-name="certificate" unicode="" d="M168 320l172 0c7 0 14 6 14 14 0 7-7 13-14 13l-172 0c-8 0-14-6-14-13 0-8 6-14 14-14z m0-55l63 0c7 0 13 6 13 13 0 8-6 13-13 13l-63 0c-8 0-14-5-14-13 0-7 6-13 14-13z m0-57l46 0c8 0 14 6 14 14 0 7-6 14-14 14l-46 0c-8 0-14-7-14-14 0-8 6-14 14-14z m-65 210l0-283 139 0c7 0 12 6 12 13 0 6-5 12-12 12l-114 0 0 233 256 0 0-83c0-7 6-12 13-12 6 0 12 5 12 12l0 108z m304-200c0 43-35 78-78 78-43 0-78-35-78-78 0-27 14-52 37-66l-3-69c0-5 2-9 6-11 5-3 10-2 13 1l27 20 26-21c2-2 5-3 8-3 2 0 4 0 5 1 4 2 7 7 7 12l-4 72c21 14 34 38 34 64z m-68-101c-4 4-10 4-14 1l-15-11 1 36c6-2 12-2 18-2 7 0 14 1 20 2l2-36z"/>
|
||||
<glyph glyph-name="gift" unicode="" d="M342 330c1 1 3 2 4 3 19 17 21 47 4 66-9 10-22 16-35 16-6 0-12-1-17-3-6 19-24 33-45 33-22 0-41-15-46-35-5 2-11 3-17 3-13 0-26-6-35-16-17-20-15-50 5-66 0 0 0 0 0-1l-82 0 0-84 27 0 0-166 298 0 0 166 27 0 0 84z m-45 50l0 1c1 1 2 2 4 3 5 5 10 6 14 6 6 0 12-3 16-8 4-4 6-9 5-15 0-6-3-11-7-15-2-2-3-3-4-3l0 0 0 0c-5-1-27-10-52-18 10 22 22 44 24 49z m-44 40c12 0 21-9 21-21 0-3 0-4 0-5l0 0 0 0c-2-5-11-24-21-48-10 23-19 42-21 47l0 1c0 1-1 3-1 5 0 12 10 21 22 21z m-79-40c4 5 10 8 16 8 4 0 9-1 14-5 2-2 3-3 4-4l0 0 0 0c2-5 11-23 22-47-24 7-44 13-49 15l-1 0c-1 1-2 2-4 3-9 8-10 21-2 30z m67-274l-110 0 0 140 110 0z m0 166l-137 0 0 32 137 0z m136-166l-111 0 0 140 111 0z m27 166l-138 0 0 32 138 0z"/>
|
||||
<glyph glyph-name="update" unicode="" d="M380 170c-7 0-13-6-13-13l0-12c0-5-4-9-9-9l-203 0c-5 0-9 4-9 9l0 114 33-27c6-4 14-4 19 2 4 5 4 13-2 18l-54 47c-3 2-5 3-8 3-4 0-7-1-9-3l-54-47c-6-5-6-13-1-18 4-6 13-6 18-1l32 26 0-114c0-19 16-35 35-35l203 0c19 0 35 16 35 35l0 12c0 7-6 13-13 13z m-248 153c7 0 13 5 13 13l0 12c0 5 4 8 9 8l203 0c5 0 9-4 9-8l0-115-33 27c-5 5-14 4-18-1-5-6-5-14 1-19l54-47c3-2 5-3 9-3 3 0 6 1 8 3l54 47c6 5 6 13 2 19-5 5-13 6-19 1l-32-27 0 115c0 19-16 34-35 34l-203 0c-19 0-35-15-35-34l0-12c0-8 6-13 13-13z"/>
|
||||
<glyph glyph-name="uninstall" unicode="" d="M83 227c-7 0-13-6-13-13l0-78c0-19 16-35 35-35l297 0c19 0 35 16 35 35l0 78c0 7-6 13-13 13-7 0-13-6-13-13l0-78c0-5-4-9-9-9l-297 0c-5 0-9 4-9 9l0 78c0 7-6 13-13 13z m191 47l50 50c5 5 5 14 0 19-5 5-13 5-19 0l-50-50-50 50c-5 5-13 5-19 0-5-5-5-14 0-19l50-50-50-50c-5-5-5-14 0-19 5-5 14-5 19 0l50 50 50-50c5-5 14-5 19 0 5 5 5 14 0 19z"/>
|
||||
<glyph glyph-name="install" unicode="" d="M83 227c-7 0-13-6-13-13l0-78c0-19 16-35 35-35l297 0c19 0 35 16 35 35l0 78c0 7-6 13-13 13-7 0-13-6-13-13l0-78c0-5-4-9-9-9l-297 0c-5 0-9 4-9 9l0 78c0 7-6 13-13 13z m170 171l0-155-33 27c-6 5-14 5-19-1-4-5-4-14 2-18l54-48c3-2 5-3 8-3 3 0 7 1 9 3l54 48c5 4 6 13 1 18-4 5-13 6-18 1l-32-27 0 154c0 8-6 13-13 13-7 0-13-5-13-12z"/>
|
||||
<glyph glyph-name="ellipsis-vertical" unicode="" d="M276 178c0-14-11-24-24-24-14 0-25 10-25 24 0 13 11 24 25 24 13 0 24-11 24-24z m0 78c0-14-11-24-24-24-14 0-25 10-25 24 0 13 11 24 25 24 13 0 24-11 24-24z m0 78c0-14-11-24-24-24-14 0-25 10-25 24 0 13 11 24 25 24 13 0 24-11 24-24z"/>
|
||||
</font></defs></svg>
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 83 KiB |
Binary file not shown.
Binary file not shown.
|
@ -12,7 +12,7 @@
|
|||
<body>
|
||||
<div class="container">
|
||||
<h1>HiFi Glyphs</h1>
|
||||
<p class="small">This font was created for use in<a href="http://highfidelity.io/">High Fidelity</a></p>
|
||||
<p class="small">This font was created for use in <a href="http://highfidelity.io/">High Fidelity</a></p>
|
||||
<h2>CSS mapping</h2>
|
||||
<ul class="glyphs css-mapping">
|
||||
<li>
|
||||
|
@ -87,10 +87,6 @@
|
|||
<div class="icon icon-edit"></div>
|
||||
<input type="text" readonly="readonly" value="edit">
|
||||
</li>
|
||||
<li>
|
||||
<div class="icon icon-market"></div>
|
||||
<input type="text" readonly="readonly" value="market">
|
||||
</li>
|
||||
<li>
|
||||
<div class="icon icon-directory"></div>
|
||||
<input type="text" readonly="readonly" value="directory">
|
||||
|
@ -567,6 +563,46 @@
|
|||
<div class="icon icon-image"></div>
|
||||
<input type="text" readonly="readonly" value="image">
|
||||
</li>
|
||||
<li>
|
||||
<div class="icon icon-environments"></div>
|
||||
<input type="text" readonly="readonly" value="environments">
|
||||
</li>
|
||||
<li>
|
||||
<div class="icon icon-wand"></div>
|
||||
<input type="text" readonly="readonly" value="wand">
|
||||
</li>
|
||||
<li>
|
||||
<div class="icon icon-market"></div>
|
||||
<input type="text" readonly="readonly" value="market">
|
||||
</li>
|
||||
<li>
|
||||
<div class="icon icon-wear"></div>
|
||||
<input type="text" readonly="readonly" value="wear">
|
||||
</li>
|
||||
<li>
|
||||
<div class="icon icon-certificate"></div>
|
||||
<input type="text" readonly="readonly" value="certificate">
|
||||
</li>
|
||||
<li>
|
||||
<div class="icon icon-gift"></div>
|
||||
<input type="text" readonly="readonly" value="gift">
|
||||
</li>
|
||||
<li>
|
||||
<div class="icon icon-update"></div>
|
||||
<input type="text" readonly="readonly" value="update">
|
||||
</li>
|
||||
<li>
|
||||
<div class="icon icon-uninstall"></div>
|
||||
<input type="text" readonly="readonly" value="uninstall">
|
||||
</li>
|
||||
<li>
|
||||
<div class="icon icon-install"></div>
|
||||
<input type="text" readonly="readonly" value="install">
|
||||
</li>
|
||||
<li>
|
||||
<div class="icon icon-ellipsis-vertical"></div>
|
||||
<input type="text" readonly="readonly" value="ellipsis-vertical">
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Character mapping</h2>
|
||||
<ul class="glyphs character-mapping">
|
||||
|
@ -642,10 +678,6 @@
|
|||
<div data-icon="s" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="s">
|
||||
</li>
|
||||
<li>
|
||||
<div data-icon="t" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="t">
|
||||
</li>
|
||||
<li>
|
||||
<div data-icon="u" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="u">
|
||||
|
@ -1122,6 +1154,46 @@
|
|||
<div data-icon="" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="&#xe02a;">
|
||||
</li>
|
||||
<li>
|
||||
<div data-icon="" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="&#xe02c;">
|
||||
</li>
|
||||
<li>
|
||||
<div data-icon="" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="&#xe02d;">
|
||||
</li>
|
||||
<li>
|
||||
<div data-icon="t" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="t">
|
||||
</li>
|
||||
<li>
|
||||
<div data-icon="" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="&#xe02e;">
|
||||
</li>
|
||||
<li>
|
||||
<div data-icon="" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="&#xe030;">
|
||||
</li>
|
||||
<li>
|
||||
<div data-icon="" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="&#xe031;">
|
||||
</li>
|
||||
<li>
|
||||
<div data-icon="" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="&#xe032;">
|
||||
</li>
|
||||
<li>
|
||||
<div data-icon="" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="&#xe033;">
|
||||
</li>
|
||||
<li>
|
||||
<div data-icon="" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="&#xe02f;">
|
||||
</li>
|
||||
<li>
|
||||
<div data-icon="" class="icon"></div>
|
||||
<input type="text" readonly="readonly" value="&#xe034;">
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<script>(function() {
|
|
@ -92,9 +92,6 @@
|
|||
.icon-edit:before {
|
||||
content: "\73";
|
||||
}
|
||||
.icon-market:before {
|
||||
content: "\74";
|
||||
}
|
||||
.icon-directory:before {
|
||||
content: "\75";
|
||||
}
|
||||
|
@ -452,3 +449,33 @@
|
|||
.icon-image:before {
|
||||
content: "\e02a";
|
||||
}
|
||||
.icon-environments:before {
|
||||
content: "\e02c";
|
||||
}
|
||||
.icon-wand:before {
|
||||
content: "\e02d";
|
||||
}
|
||||
.icon-market:before {
|
||||
content: "\74";
|
||||
}
|
||||
.icon-wear:before {
|
||||
content: "\e02e";
|
||||
}
|
||||
.icon-certificate:before {
|
||||
content: "\e030";
|
||||
}
|
||||
.icon-gift:before {
|
||||
content: "\e031";
|
||||
}
|
||||
.icon-update:before {
|
||||
content: "\e032";
|
||||
}
|
||||
.icon-uninstall:before {
|
||||
content: "\e033";
|
||||
}
|
||||
.icon-install:before {
|
||||
content: "\e02f";
|
||||
}
|
||||
.icon-ellipsis-vertical:before {
|
||||
content: "\e034";
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 215 KiB After Width: | Height: | Size: 241 KiB |
16
interface/resources/icons/+android/stats.svg
Normal file
16
interface/resources/icons/+android/stats.svg
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, 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 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
|
||||
<path d="M45,40.3l-7.1-6.3c-0.7-0.7-1.7-0.9-2.6-0.8c2.3-2.9,3.6-6.4,3.6-10.3c0-9.9-7.9-17-16.9-17.1c-9.3,0-16.7,7.4-17,16.3
|
||||
C4.7,32,12.6,39.6,21.9,39.7c4.2,0,8.1-1.5,11-4.1c-0.2,0.9,0.1,1.9,0.9,2.6l7.1,6.3c1.2,1.1,3,1.1,4.1-0.1c0.5-0.6,0.8-1.3,0.8-2
|
||||
C45.9,41.6,45.6,40.8,45,40.3z M22.5,35.4c-7.3,0.3-13.2-5.5-13.2-12.8C9.2,15.8,14.9,10.1,21.9,10c7-0.1,12.8,5.6,12.8,12.7
|
||||
C34.7,29.7,29.2,35.2,22.5,35.4z"/>
|
||||
<path d="M26.2,19.9c-0.5,1.2-0.9,2.4-1.3,3.5c-0.6,1.6-1.2,3.2-1.8,4.8c-0.3,0.8-0.8,1.2-1.6,1.2c-0.8,0-1.2-0.3-1.6-1.2
|
||||
c-0.9-2.1-1.8-4.2-2.6-6.2c0-0.1-0.1-0.2-0.2-0.5c-0.3,0.5-0.6,0.9-0.8,1.4c-0.4,0.9-1.1,1.3-2.1,1.2c-0.6,0-1.2,0-1.8,0
|
||||
c-0.9,0-1.5-0.6-1.5-1.4c-0.1-0.7,0.5-1.4,1.3-1.5c0.2,0,0.4-0.1,0.5-0.1c0.7,0.1,1.1-0.2,1.5-0.9c0.5-1,1.1-2,1.6-3
|
||||
c0.3-0.6,0.8-1,1.6-1c0.7,0,1.2,0.5,1.5,1.1c0.8,1.8,1.6,3.7,2.3,5.5c0.1,0.2,0.1,0.3,0.3,0.6c0.2-0.6,0.4-1.1,0.6-1.6
|
||||
c0.9-2.4,1.8-4.8,2.7-7.2c0.3-0.9,0.8-1.2,1.5-1.2c0.8,0,1.3,0.4,1.6,1.2c0.7,1.8,1.3,3.6,1.9,5.5c0.4,1,0.1,0.8,1.1,0.8
|
||||
c0.4,0,0.8,0,1.1,0.1c0.7,0.2,1.2,0.8,1.1,1.6c-0.1,0.7-0.6,1.3-1.4,1.3c-1,0-2,0-3,0c-0.7,0-1.1-0.4-1.4-1.1
|
||||
C27,22.1,26.6,21.1,26.2,19.9z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
BIN
interface/resources/images/fly.png
Normal file
BIN
interface/resources/images/fly.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
|
@ -67,6 +67,10 @@ Item {
|
|||
fill: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
QmlHifi.WindowHeader {
|
||||
id: header
|
||||
iconSource: "../../../icons/goto-i.svg"
|
||||
|
|
9
interface/resources/qml/+android/StatText.qml
Normal file
9
interface/resources/qml/+android/StatText.qml
Normal file
|
@ -0,0 +1,9 @@
|
|||
import QtQuick 2.3
|
||||
import QtQuick.Controls 1.2
|
||||
|
||||
Text {
|
||||
color: "white";
|
||||
style: Text.Outline;
|
||||
styleColor: "black";
|
||||
font.pixelSize: 15;
|
||||
}
|
|
@ -8,9 +8,6 @@
|
|||
|
||||
import Hifi 1.0 as Hifi
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.3
|
||||
import QtGraphicalEffects 1.0
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
import "./hifi/audio" as HifiAudio
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.2
|
||||
import QtWebChannel 1.0
|
||||
import QtWebEngine 1.5
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
CheckBoxQQC2 {
|
||||
CheckBox {
|
||||
id: showPassword
|
||||
text: "Show password"
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
import Hifi 1.0
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4 as OriginalStyles
|
||||
|
||||
import "../controls-uit"
|
||||
import "../styles-uit"
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
import Hifi 1.0
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4 as OriginalStyles
|
||||
|
||||
import "../controls-uit"
|
||||
import "../styles-uit"
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtWebEngine 1.1
|
||||
import QtWebChannel 1.0
|
||||
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Controls 1.4
|
||||
import QtWebChannel 1.0
|
||||
import QtWebEngine 1.2
|
||||
import QtWebSockets 1.0
|
||||
|
||||
import "windows" as Windows
|
||||
import "controls"
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import QtQuick 2.3
|
||||
import QtQuick.Controls 1.2
|
||||
|
||||
Text {
|
||||
color: "white";
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import Hifi 1.0 as Hifi
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Controls 1.2
|
||||
import '.'
|
||||
|
||||
Item {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtWebChannel 1.0
|
||||
import QtWebEngine 1.5
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
import "controls" as Controls
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Dialogs 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Dialogs 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Dialogs 1.0
|
||||
|
||||
import "hydra"
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Dialogs 1.0
|
||||
|
||||
import "xbox"
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Dialogs 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Dialogs 1.0
|
||||
|
||||
import "xbox"
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Dialogs 1.0
|
||||
|
||||
import ".."
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Dialogs 1.0
|
||||
|
||||
import ".."
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Dialogs 1.0
|
||||
|
||||
import ".."
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Dialogs 1.0
|
||||
|
||||
import ".."
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Dialogs 1.0
|
||||
|
||||
import ".."
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
import QtQuick 2.1
|
||||
import QtQuick.Controls 1.0
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Dialogs 1.0
|
||||
|
||||
import ".."
|
||||
|
||||
|
|
125
interface/resources/qml/controls-uit/+android/Button.qml
Normal file
125
interface/resources/qml/controls-uit/+android/Button.qml
Normal file
|
@ -0,0 +1,125 @@
|
|||
//
|
||||
// Button.qml
|
||||
//
|
||||
// Created by David Rowe on 16 Feb 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
Original.Button {
|
||||
id: root;
|
||||
|
||||
property int color: 0
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
property string buttonGlyph: "";
|
||||
|
||||
width: hifi.dimensions.buttonWidth
|
||||
height: hifi.dimensions.controlLineHeight
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
Tablet.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
if (focus) {
|
||||
Tablet.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
style: ButtonStyle {
|
||||
|
||||
background: Rectangle {
|
||||
radius: hifi.buttons.radius
|
||||
|
||||
border.width: (control.color === hifi.buttons.none ||
|
||||
(control.color === hifi.buttons.noneBorderless && control.hovered) ||
|
||||
(control.color === hifi.buttons.noneBorderlessWhite && control.hovered) ||
|
||||
(control.color === hifi.buttons.noneBorderlessGray && control.hovered)) ? 1 : 0;
|
||||
border.color: control.color === hifi.buttons.noneBorderless ? hifi.colors.blueHighlight :
|
||||
(control.color === hifi.buttons.noneBorderlessGray ? hifi.colors.baseGray : hifi.colors.white);
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: {
|
||||
if (!control.enabled) {
|
||||
hifi.buttons.disabledColorStart[control.colorScheme]
|
||||
} else if (control.pressed) {
|
||||
hifi.buttons.pressedColor[control.color]
|
||||
} else if (control.hovered) {
|
||||
hifi.buttons.hoveredColor[control.color]
|
||||
} else if (!control.hovered && control.focus) {
|
||||
hifi.buttons.focusedColor[control.color]
|
||||
} else {
|
||||
hifi.buttons.colorStart[control.color]
|
||||
}
|
||||
}
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: {
|
||||
if (!control.enabled) {
|
||||
hifi.buttons.disabledColorFinish[control.colorScheme]
|
||||
} else if (control.pressed) {
|
||||
hifi.buttons.pressedColor[control.color]
|
||||
} else if (control.hovered) {
|
||||
hifi.buttons.hoveredColor[control.color]
|
||||
} else if (!control.hovered && control.focus) {
|
||||
hifi.buttons.focusedColor[control.color]
|
||||
} else {
|
||||
hifi.buttons.colorFinish[control.color]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
label: Item {
|
||||
HiFiGlyphs {
|
||||
id: buttonGlyph;
|
||||
visible: root.buttonGlyph !== "";
|
||||
text: root.buttonGlyph === "" ? hifi.glyphs.question : root.buttonGlyph;
|
||||
// Size
|
||||
size: 34;
|
||||
// Anchors
|
||||
anchors.right: buttonText.left;
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
// Style
|
||||
color: enabled ? hifi.buttons.textColor[control.color]
|
||||
: hifi.buttons.disabledTextColor[control.colorScheme];
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
RalewayBold {
|
||||
id: buttonText;
|
||||
anchors.centerIn: parent;
|
||||
font.capitalization: Font.AllUppercase
|
||||
color: enabled ? hifi.buttons.textColor[control.color]
|
||||
: hifi.buttons.disabledTextColor[control.colorScheme]
|
||||
size: hifi.fontSizes.buttonLabel
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: control.text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
165
interface/resources/qml/controls-uit/+android/Table.qml
Normal file
165
interface/resources/qml/controls-uit/+android/Table.qml
Normal file
|
@ -0,0 +1,165 @@
|
|||
//
|
||||
// Table.qml
|
||||
//
|
||||
// Created by David Rowe on 18 Feb 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick.Controls 2.2 as QQC2
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
TableView {
|
||||
id: tableView
|
||||
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||
property bool expandSelectedRow: false
|
||||
property bool centerHeaderText: false
|
||||
readonly property real headerSpacing: 3 //spacing between sort indicator and table header title
|
||||
property var titlePaintedPos: [] // storing extra data position behind painted
|
||||
// title text and sort indicatorin table's header
|
||||
signal titlePaintedPosSignal(int column) //signal that extradata position gets changed
|
||||
|
||||
model: ListModel { }
|
||||
|
||||
Component.onCompleted: {
|
||||
if (flickableItem !== null && flickableItem !== undefined) {
|
||||
tableView.flickableItem.QQC2.ScrollBar.vertical = scrollbar
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.ScrollBar {
|
||||
id: scrollbar
|
||||
parent: tableView.flickableItem
|
||||
policy: QQC2.ScrollBar.AsNeeded
|
||||
orientation: Qt.Vertical
|
||||
visible: size < 1.0
|
||||
topPadding: tableView.headerVisible ? hifi.dimensions.tableHeaderHeight + 1 : 1
|
||||
anchors.top: tableView.top
|
||||
anchors.left: tableView.right
|
||||
anchors.bottom: tableView.bottom
|
||||
|
||||
background: Item {
|
||||
implicitWidth: hifi.dimensions.scrollbarBackgroundWidth
|
||||
Rectangle {
|
||||
anchors {
|
||||
fill: parent;
|
||||
topMargin: tableView.headerVisible ? hifi.dimensions.tableHeaderHeight : 0
|
||||
}
|
||||
color: isLightColorScheme ? hifi.colors.tableScrollBackgroundLight
|
||||
: hifi.colors.tableScrollBackgroundDark
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: hifi.dimensions.scrollbarHandleWidth
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: (width - 4)/2
|
||||
color: isLightColorScheme ? hifi.colors.tableScrollHandleLight : hifi.colors.tableScrollHandleDark
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
headerVisible: false
|
||||
headerDelegate: Rectangle {
|
||||
height: hifi.dimensions.tableHeaderHeight
|
||||
color: isLightColorScheme ? hifi.colors.tableBackgroundLight : hifi.colors.tableBackgroundDark
|
||||
|
||||
|
||||
RalewayRegular {
|
||||
id: titleText
|
||||
x: centerHeaderText ? (parent.width - paintedWidth -
|
||||
((sortIndicatorVisible &&
|
||||
sortIndicatorColumn === styleData.column) ?
|
||||
(titleSort.paintedWidth / 5 + tableView.headerSpacing) : 0)) / 2 :
|
||||
hifi.dimensions.tablePadding
|
||||
text: styleData.value
|
||||
size: hifi.fontSizes.tableHeading
|
||||
font.capitalization: Font.AllUppercase
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
horizontalAlignment: (centerHeaderText ? Text.AlignHCenter : Text.AlignLeft)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
//actual image of sort indicator in glyph font only 20% of real font size
|
||||
//i.e. if the charachter size set to 60 pixels, actual image is 12 pixels
|
||||
HiFiGlyphs {
|
||||
id: titleSort
|
||||
text: sortIndicatorOrder == Qt.AscendingOrder ? hifi.glyphs.caratUp : hifi.glyphs.caratDn
|
||||
color: hifi.colors.darkGray
|
||||
opacity: 0.6;
|
||||
size: hifi.fontSizes.tableHeadingIcon
|
||||
anchors.verticalCenter: titleText.verticalCenter
|
||||
anchors.left: titleText.right
|
||||
anchors.leftMargin: -(hifi.fontSizes.tableHeadingIcon / 2.5) + tableView.headerSpacing
|
||||
visible: sortIndicatorVisible && sortIndicatorColumn === styleData.column
|
||||
onXChanged: {
|
||||
titlePaintedPos[styleData.column] = titleText.x + titleText.paintedWidth +
|
||||
paintedWidth / 5 + tableView.headerSpacing*2
|
||||
titlePaintedPosSignal(styleData.column)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 1
|
||||
anchors {
|
||||
left: parent.left
|
||||
top: parent.top
|
||||
topMargin: 1
|
||||
bottom: parent.bottom
|
||||
bottomMargin: 2
|
||||
}
|
||||
color: isLightColorScheme ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight
|
||||
visible: styleData.column > 0
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
height: 1
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
color: isLightColorScheme ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight
|
||||
}
|
||||
}
|
||||
|
||||
// Use rectangle to draw border with rounded corners.
|
||||
frameVisible: false
|
||||
Rectangle {
|
||||
color: "#00000000"
|
||||
anchors { fill: parent; margins: -2 }
|
||||
border.color: isLightColorScheme ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight
|
||||
border.width: 2
|
||||
}
|
||||
anchors.margins: 2 // Shrink TableView to lie within border.
|
||||
|
||||
backgroundVisible: true
|
||||
|
||||
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
|
||||
verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff
|
||||
|
||||
style: TableViewStyle {
|
||||
// Needed in order for rows to keep displaying rows after end of table entries.
|
||||
backgroundColor: tableView.isLightColorScheme ? hifi.colors.tableBackgroundLight : hifi.colors.tableBackgroundDark
|
||||
alternateBackgroundColor: tableView.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd
|
||||
padding.top: headerVisible ? hifi.dimensions.tableHeaderHeight: 0
|
||||
}
|
||||
|
||||
rowDelegate: Rectangle {
|
||||
height: (styleData.selected && expandSelectedRow ? 1.8 : 1) * hifi.dimensions.tableRowHeight
|
||||
color: styleData.selected
|
||||
? hifi.colors.primaryHighlight
|
||||
: tableView.isLightColorScheme
|
||||
? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd)
|
||||
: (styleData.alternate ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd)
|
||||
}
|
||||
}
|
|
@ -8,15 +8,14 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.3 as Original
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
Original.Button {
|
||||
id: root;
|
||||
id: control;
|
||||
|
||||
property int color: 0
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
|
@ -38,88 +37,86 @@ Original.Button {
|
|||
Tablet.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
style: ButtonStyle {
|
||||
background: Rectangle {
|
||||
radius: hifi.buttons.radius
|
||||
|
||||
background: Rectangle {
|
||||
radius: hifi.buttons.radius
|
||||
border.width: (control.color === hifi.buttons.none ||
|
||||
(control.color === hifi.buttons.noneBorderless && control.hovered) ||
|
||||
(control.color === hifi.buttons.noneBorderlessWhite && control.hovered) ||
|
||||
(control.color === hifi.buttons.noneBorderlessGray && control.hovered)) ? 1 : 0;
|
||||
border.color: control.color === hifi.buttons.noneBorderless ? hifi.colors.blueHighlight :
|
||||
(control.color === hifi.buttons.noneBorderlessGray ? hifi.colors.baseGray : hifi.colors.white);
|
||||
|
||||
border.width: (control.color === hifi.buttons.none ||
|
||||
(control.color === hifi.buttons.noneBorderless && control.hovered) ||
|
||||
(control.color === hifi.buttons.noneBorderlessWhite && control.hovered) ||
|
||||
(control.color === hifi.buttons.noneBorderlessGray && control.hovered)) ? 1 : 0;
|
||||
border.color: control.color === hifi.buttons.noneBorderless ? hifi.colors.blueHighlight :
|
||||
(control.color === hifi.buttons.noneBorderlessGray ? hifi.colors.baseGray : hifi.colors.white);
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: {
|
||||
if (!control.enabled) {
|
||||
hifi.buttons.disabledColorStart[control.colorScheme]
|
||||
} else if (control.pressed) {
|
||||
hifi.buttons.pressedColor[control.color]
|
||||
} else if (control.hovered) {
|
||||
hifi.buttons.hoveredColor[control.color]
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: {
|
||||
if (!control.enabled) {
|
||||
hifi.buttons.disabledColorStart[control.colorScheme]
|
||||
} else if (control.pressed) {
|
||||
hifi.buttons.pressedColor[control.color]
|
||||
} else if (control.hovered) {
|
||||
hifi.buttons.hoveredColor[control.color]
|
||||
} else if (!control.hovered && control.focus) {
|
||||
hifi.buttons.focusedColor[control.color]
|
||||
} else {
|
||||
hifi.buttons.colorStart[control.color]
|
||||
}
|
||||
} else {
|
||||
hifi.buttons.colorStart[control.color]
|
||||
}
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: {
|
||||
if (!control.enabled) {
|
||||
hifi.buttons.disabledColorFinish[control.colorScheme]
|
||||
} else if (control.pressed) {
|
||||
hifi.buttons.pressedColor[control.color]
|
||||
} else if (control.hovered) {
|
||||
hifi.buttons.hoveredColor[control.color]
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: {
|
||||
if (!control.enabled) {
|
||||
hifi.buttons.disabledColorFinish[control.colorScheme]
|
||||
} else if (control.pressed) {
|
||||
hifi.buttons.pressedColor[control.color]
|
||||
} else if (control.hovered) {
|
||||
hifi.buttons.hoveredColor[control.color]
|
||||
} else if (!control.hovered && control.focus) {
|
||||
hifi.buttons.focusedColor[control.color]
|
||||
} else {
|
||||
hifi.buttons.colorFinish[control.color]
|
||||
}
|
||||
} else {
|
||||
hifi.buttons.colorFinish[control.color]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
label: Item {
|
||||
HiFiGlyphs {
|
||||
id: buttonGlyph;
|
||||
visible: root.buttonGlyph !== "";
|
||||
text: root.buttonGlyph === "" ? hifi.glyphs.question : root.buttonGlyph;
|
||||
// Size
|
||||
size: 34;
|
||||
// Anchors
|
||||
anchors.right: buttonText.left;
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
// Style
|
||||
color: enabled ? hifi.buttons.textColor[control.color]
|
||||
: hifi.buttons.disabledTextColor[control.colorScheme];
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
RalewayBold {
|
||||
id: buttonText;
|
||||
anchors.centerIn: parent;
|
||||
font.capitalization: Font.AllUppercase
|
||||
color: enabled ? hifi.buttons.textColor[control.color]
|
||||
: hifi.buttons.disabledTextColor[control.colorScheme]
|
||||
size: hifi.fontSizes.buttonLabel
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: control.text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
HiFiGlyphs {
|
||||
id: buttonGlyph;
|
||||
visible: control.buttonGlyph !== "";
|
||||
text: control.buttonGlyph === "" ? hifi.glyphs.question : control.buttonGlyph;
|
||||
// Size
|
||||
size: 34;
|
||||
// Anchors
|
||||
anchors.right: buttonText.left;
|
||||
anchors.top: parent.top;
|
||||
anchors.bottom: parent.bottom;
|
||||
// Style
|
||||
color: enabled ? hifi.buttons.textColor[control.color]
|
||||
: hifi.buttons.disabledTextColor[control.colorScheme];
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
RalewayBold {
|
||||
id: buttonText;
|
||||
anchors.centerIn: parent;
|
||||
font.capitalization: Font.AllUppercase
|
||||
color: enabled ? hifi.buttons.textColor[control.color]
|
||||
: hifi.buttons.disabledTextColor[control.colorScheme]
|
||||
size: hifi.fontSizes.buttonLabel
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: control.text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,9 +8,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick 2.2
|
||||
import QtQuick.Controls 2.2 as Original
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
|
@ -28,85 +27,89 @@ Original.CheckBox {
|
|||
property bool wrap: true;
|
||||
readonly property int checkSize: Math.max(boxSize - 8, 10)
|
||||
readonly property int checkRadius: 2
|
||||
activeFocusOnPress: true
|
||||
focusPolicy: Qt.ClickFocus
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
// TODO: doesnt works for QQC1. check with QQC2
|
||||
// onHovered: {
|
||||
// Tablet.playSound(TabletEnums.ButtonHover);
|
||||
// }
|
||||
|
||||
style: CheckBoxStyle {
|
||||
indicator: Rectangle {
|
||||
id: box
|
||||
implicitWidth: boxSize
|
||||
implicitHeight: boxSize
|
||||
radius: boxRadius
|
||||
border.width: 1
|
||||
border.color: pressed || hovered
|
||||
? hifi.colors.checkboxCheckedBorder
|
||||
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: pressed || hovered
|
||||
? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightStart)
|
||||
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightStart : hifi.colors.checkboxDarkStart)
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: pressed || hovered
|
||||
? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightFinish)
|
||||
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: pressed || hovered
|
||||
anchors.centerIn: parent
|
||||
id: innerBox
|
||||
width: checkSize - 4
|
||||
height: width
|
||||
radius: checkRadius
|
||||
color: hifi.colors.checkboxCheckedBorder
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: check
|
||||
width: checkSize
|
||||
height: checkSize
|
||||
radius: checkRadius
|
||||
anchors.centerIn: parent
|
||||
color: isRedCheck ? hifi.colors.checkboxCheckedRed : hifi.colors.checkboxChecked
|
||||
border.width: 2
|
||||
border.color: isRedCheck? hifi.colors.checkboxCheckedBorderRed : hifi.colors.checkboxCheckedBorder
|
||||
visible: checked && !pressed || !checked && pressed
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: disabledOverlay
|
||||
visible: !enabled
|
||||
width: boxSize
|
||||
height: boxSize
|
||||
radius: boxRadius
|
||||
border.width: 1
|
||||
border.color: hifi.colors.baseGrayHighlight
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
opacity: 0.5
|
||||
}
|
||||
}
|
||||
|
||||
label: Label {
|
||||
text: checkBox.text
|
||||
color: checkBox.color
|
||||
x: 2
|
||||
wrapMode: checkBox.wrap ? Text.Wrap : Text.NoWrap
|
||||
elide: checkBox.wrap ? Text.ElideNone : Text.ElideRight
|
||||
enabled: checkBox.enabled
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
Tablet.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
indicator: Rectangle {
|
||||
id: box
|
||||
implicitWidth: boxSize
|
||||
implicitHeight: boxSize
|
||||
radius: boxRadius
|
||||
y: parent.height / 2 - height / 2
|
||||
border.width: 1
|
||||
border.color: pressed || hovered
|
||||
? hifi.colors.checkboxCheckedBorder
|
||||
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: pressed || hovered
|
||||
? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightStart)
|
||||
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightStart : hifi.colors.checkboxDarkStart)
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: pressed || hovered
|
||||
? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightFinish)
|
||||
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: pressed || hovered
|
||||
anchors.centerIn: parent
|
||||
id: innerBox
|
||||
width: checkSize - 4
|
||||
height: width
|
||||
radius: checkRadius
|
||||
color: hifi.colors.checkboxCheckedBorder
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: check
|
||||
width: checkSize
|
||||
height: checkSize
|
||||
radius: checkRadius
|
||||
anchors.centerIn: parent
|
||||
color: isRedCheck ? hifi.colors.checkboxCheckedRed : hifi.colors.checkboxChecked
|
||||
border.width: 2
|
||||
border.color: isRedCheck? hifi.colors.checkboxCheckedBorderRed : hifi.colors.checkboxCheckedBorder
|
||||
visible: checked && !pressed || !checked && pressed
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: disabledOverlay
|
||||
visible: !enabled
|
||||
width: boxSize
|
||||
height: boxSize
|
||||
radius: boxRadius
|
||||
border.width: 1
|
||||
border.color: hifi.colors.baseGrayHighlight
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
opacity: 0.5
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Label {
|
||||
text: checkBox.text
|
||||
color: checkBox.color
|
||||
x: 2
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
wrapMode: checkBox.wrap ? Text.Wrap : Text.NoWrap
|
||||
elide: checkBox.wrap ? Text.ElideNone : Text.ElideRight
|
||||
enabled: checkBox.enabled
|
||||
leftPadding: checkBox.indicator.width + checkBox.spacing
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
|
@ -24,6 +23,7 @@ FocusScope {
|
|||
property alias comboBox: comboBox
|
||||
readonly property alias currentText: comboBox.currentText;
|
||||
property alias currentIndex: comboBox.currentIndex;
|
||||
property int currentHighLightedIndex: comboBox.currentIndex;
|
||||
|
||||
property int dropdownHeight: 480
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
|
@ -40,196 +40,134 @@ FocusScope {
|
|||
implicitHeight: comboBox.height;
|
||||
focus: true
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: popup.visible
|
||||
? (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
|
||||
: (isLightColorScheme ? hifi.colors.dropDownLightStart : hifi.colors.dropDownDarkStart)
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: popup.visible
|
||||
? (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
|
||||
: (isLightColorScheme ? hifi.colors.dropDownLightFinish : hifi.colors.dropDownDarkFinish)
|
||||
}
|
||||
}
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
SystemPalette { id: palette }
|
||||
|
||||
ComboBox {
|
||||
id: comboBox
|
||||
anchors.fill: parent
|
||||
visible: false
|
||||
height: hifi.fontSizes.textFieldInput + 13 // Match height of TextField control.
|
||||
}
|
||||
|
||||
FiraSansSemiBold {
|
||||
id: textField
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: hifi.dimensions.textPadding
|
||||
right: dropIcon.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
size: hifi.fontSizes.textFieldInput
|
||||
text: comboBox.currentText
|
||||
elide: Text.ElideRight
|
||||
color: controlHover.containsMouse || popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText )
|
||||
}
|
||||
|
||||
Item {
|
||||
id: dropIcon
|
||||
anchors { right: parent.right; verticalCenter: parent.verticalCenter }
|
||||
height: background.height
|
||||
width: height
|
||||
Rectangle {
|
||||
width: 1
|
||||
height: parent.height
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
color: isLightColorScheme ? hifi.colors.faintGray : hifi.colors.baseGray
|
||||
}
|
||||
HiFiGlyphs {
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: -11
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
size: hifi.dimensions.spinnerSize
|
||||
text: hifi.glyphs.caratDn
|
||||
color: controlHover.containsMouse || popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText)
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: controlHover
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
onClicked: toggleList();
|
||||
}
|
||||
visible: true
|
||||
height: hifi.fontSizes.textFieldInput + 13 // Match height of TextField control.
|
||||
|
||||
function toggleList() {
|
||||
if (popup.visible) {
|
||||
hideList();
|
||||
} else {
|
||||
showList();
|
||||
}
|
||||
}
|
||||
|
||||
function showList() {
|
||||
var r;
|
||||
if (isDesktop) {
|
||||
r = desktop.mapFromItem(root, 0, 0, root.width, root.height);
|
||||
} else {
|
||||
r = mapFromItem(root, 0, 0, root.width, root.height);
|
||||
}
|
||||
var y = r.y + r.height;
|
||||
var bottom = y + scrollView.height;
|
||||
var height = isDesktop ? desktop.height : tabletRoot.height;
|
||||
if (bottom > height) {
|
||||
y -= bottom - height + 8;
|
||||
}
|
||||
scrollView.x = r.x;
|
||||
scrollView.y = y;
|
||||
popup.visible = true;
|
||||
popup.forceActiveFocus();
|
||||
listView.currentIndex = root.currentIndex;
|
||||
scrollView.hoverEnabled = true;
|
||||
}
|
||||
|
||||
function hideList() {
|
||||
popup.visible = false;
|
||||
scrollView.hoverEnabled = false;
|
||||
root.accepted();
|
||||
}
|
||||
|
||||
FocusScope {
|
||||
id: popup
|
||||
parent: isDesktop ? desktop : root
|
||||
anchors.fill: parent
|
||||
z: isDesktop ? desktop.zLevels.menu : 12
|
||||
visible: false
|
||||
focus: true
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: hideList();
|
||||
}
|
||||
|
||||
function previousItem() { listView.currentIndex = (listView.currentIndex + listView.count - 1) % listView.count; }
|
||||
function nextItem() { listView.currentIndex = (listView.currentIndex + listView.count + 1) % listView.count; }
|
||||
function selectCurrentItem() { root.currentIndex = listView.currentIndex; hideList(); }
|
||||
function selectSpecificItem(index) { root.currentIndex = index; hideList(); }
|
||||
function previousItem() { root.currentHighLightedIndex = (root.currentHighLightedIndex + comboBox.count - 1) % comboBox.count; }
|
||||
function nextItem() { root.currentHighLightedIndex = (root.currentHighLightedIndex + comboBox.count + 1) % comboBox.count; }
|
||||
function selectCurrentItem() { root.currentIndex = root.currentHighLightedIndex; close(); /*hideList();*/ }
|
||||
function selectSpecificItem(index) { root.currentIndex = index; close();/*hideList();*/ }
|
||||
|
||||
Keys.onUpPressed: previousItem();
|
||||
Keys.onDownPressed: nextItem();
|
||||
Keys.onSpacePressed: selectCurrentItem();
|
||||
Keys.onRightPressed: selectCurrentItem();
|
||||
Keys.onReturnPressed: selectCurrentItem();
|
||||
Keys.onEscapePressed: hideList();
|
||||
|
||||
ScrollView {
|
||||
id: scrollView
|
||||
height: root.dropdownHeight
|
||||
background: Rectangle {
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: comboBox.popup.visible
|
||||
? (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
|
||||
: (isLightColorScheme ? hifi.colors.dropDownLightStart : hifi.colors.dropDownDarkStart)
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: comboBox.popup.visible
|
||||
? (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
|
||||
: (isLightColorScheme ? hifi.colors.dropDownLightFinish : hifi.colors.dropDownDarkFinish)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
indicator: Item {
|
||||
id: dropIcon
|
||||
anchors { right: parent.right; verticalCenter: parent.verticalCenter }
|
||||
height: root.height
|
||||
width: height
|
||||
Rectangle {
|
||||
width: 1
|
||||
height: parent.height
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
color: isLightColorScheme ? hifi.colors.faintGray : hifi.colors.baseGray
|
||||
}
|
||||
HiFiGlyphs {
|
||||
anchors { top: parent.top; topMargin: -11; horizontalCenter: parent.horizontalCenter }
|
||||
size: hifi.dimensions.spinnerSize
|
||||
text: hifi.glyphs.caratDn
|
||||
color: comboBox.hovered || comboBox.popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText)
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: FiraSansSemiBold {
|
||||
id: textField
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: hifi.dimensions.textPadding
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
size: hifi.fontSizes.textFieldInput
|
||||
text: comboBox.currentText
|
||||
elide: Text.ElideRight
|
||||
color: comboBox.hovered || comboBox.popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText )
|
||||
}
|
||||
|
||||
delegate: ItemDelegate {
|
||||
id: itemDelegate
|
||||
hoverEnabled: true
|
||||
width: root.width + 4
|
||||
property bool hoverEnabled: false;
|
||||
height: popupText.implicitHeight * 1.4
|
||||
highlighted: root.currentHighLightedIndex == index
|
||||
|
||||
style: ScrollViewStyle {
|
||||
decrementControl: Item {
|
||||
visible: false
|
||||
}
|
||||
incrementControl: Item {
|
||||
visible: false
|
||||
}
|
||||
scrollBarBackground: Rectangle{
|
||||
implicitWidth: 20
|
||||
color: hifi.colors.baseGray
|
||||
}
|
||||
|
||||
handle:
|
||||
Rectangle {
|
||||
implicitWidth: 16
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 3
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
radius: 6
|
||||
color: hifi.colors.lightGrayText
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
root.currentHighLightedIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
background: Rectangle {
|
||||
color: itemDelegate.highlighted ? hifi.colors.primaryHighlight
|
||||
: (isLightColorScheme ? hifi.colors.dropDownPressedLight
|
||||
: hifi.colors.dropDownPressedDark)
|
||||
}
|
||||
|
||||
contentItem: FiraSansSemiBold {
|
||||
id: popupText
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: hifi.dimensions.textPadding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: comboBox.model[index] ? comboBox.model[index]
|
||||
: (comboBox.model.get && comboBox.model.get(index).text ?
|
||||
comboBox.model.get(index).text : "")
|
||||
size: hifi.fontSizes.textFieldInput
|
||||
color: hifi.colors.baseGray
|
||||
}
|
||||
}
|
||||
popup: Popup {
|
||||
y: comboBox.height - 1
|
||||
width: comboBox.width
|
||||
implicitHeight: listView.contentHeight > dropdownHeight ? dropdownHeight
|
||||
: listView.contentHeight
|
||||
padding: 0
|
||||
topPadding: 1
|
||||
|
||||
onClosed: {
|
||||
root.accepted()
|
||||
}
|
||||
|
||||
contentItem: ListView {
|
||||
id: listView
|
||||
height: textField.height * count * 1.4
|
||||
model: root.model
|
||||
delegate: Rectangle {
|
||||
width: root.width + 4
|
||||
height: popupText.implicitHeight * 1.4
|
||||
color: (listView.currentIndex === index) ? hifi.colors.primaryHighlight :
|
||||
(isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
|
||||
FiraSansSemiBold {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: hifi.dimensions.textPadding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
id: popupText
|
||||
text: listView.model[index] ? listView.model[index] : (listView.model.get && listView.model.get(index).text ? listView.model.get(index).text : "")
|
||||
size: hifi.fontSizes.textFieldInput
|
||||
color: hifi.colors.baseGray
|
||||
}
|
||||
MouseArea {
|
||||
id: popupHover
|
||||
anchors.fill: parent;
|
||||
hoverEnabled: scrollView.hoverEnabled;
|
||||
onEntered: listView.currentIndex = index;
|
||||
onClicked: popup.selectSpecificItem(index);
|
||||
}
|
||||
clip: true
|
||||
model: comboBox.popup.visible ? comboBox.delegateModel : null
|
||||
currentIndex: root.currentHighLightedIndex
|
||||
delegate: comboBox.delegate
|
||||
ScrollBar.vertical: HifiControls.ScrollBar {
|
||||
id: scrollbar
|
||||
parent: listView
|
||||
policy: ScrollBar.AsNeeded
|
||||
visible: size < 1.0
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: hifi.colors.baseGray
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,15 +8,14 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2 as Original
|
||||
import TabletScriptingInterface 1.0
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
Original.Button {
|
||||
id: control
|
||||
property int color: 0
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
property string glyph: ""
|
||||
|
@ -41,59 +40,52 @@ Original.Button {
|
|||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
style: ButtonStyle {
|
||||
background: Rectangle {
|
||||
radius: hifi.buttons.radius
|
||||
|
||||
background: Rectangle {
|
||||
radius: hifi.buttons.radius
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: {
|
||||
if (!control.enabled) {
|
||||
hifi.buttons.disabledColorStart[control.colorScheme]
|
||||
} else if (control.pressed) {
|
||||
hifi.buttons.pressedColor[control.color]
|
||||
} else if (control.hovered) {
|
||||
hifi.buttons.hoveredColor[control.color]
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: {
|
||||
if (!control.enabled) {
|
||||
hifi.buttons.disabledColorStart[control.colorScheme]
|
||||
} else if (control.pressed) {
|
||||
hifi.buttons.pressedColor[control.color]
|
||||
} else if (control.hovered) {
|
||||
hifi.buttons.hoveredColor[control.color]
|
||||
} else if (!control.hovered && control.focus) {
|
||||
hifi.buttons.focusedColor[control.color]
|
||||
} else {
|
||||
hifi.buttons.colorStart[control.color]
|
||||
}
|
||||
}
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: {
|
||||
if (!control.enabled) {
|
||||
hifi.buttons.disabledColorFinish[control.colorScheme]
|
||||
} else if (control.pressed) {
|
||||
hifi.buttons.pressedColor[control.color]
|
||||
} else if (control.hovered) {
|
||||
hifi.buttons.hoveredColor[control.color]
|
||||
} else if (!control.hovered && control.focus) {
|
||||
hifi.buttons.focusedColor[control.color]
|
||||
} else {
|
||||
hifi.buttons.colorFinish[control.color]
|
||||
}
|
||||
} else {
|
||||
hifi.buttons.colorStart[control.color]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
label: HiFiGlyphs {
|
||||
color: enabled ? hifi.buttons.textColor[control.color]
|
||||
: hifi.buttons.disabledTextColor[control.colorScheme]
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors {
|
||||
// Tweak horizontal alignment so that it looks right.
|
||||
left: parent.left
|
||||
leftMargin: -0.5
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: {
|
||||
if (!control.enabled) {
|
||||
hifi.buttons.disabledColorFinish[control.colorScheme]
|
||||
} else if (control.pressed) {
|
||||
hifi.buttons.pressedColor[control.color]
|
||||
} else if (control.hovered) {
|
||||
hifi.buttons.hoveredColor[control.color]
|
||||
} else if (!control.hovered && control.focus) {
|
||||
hifi.buttons.focusedColor[control.color]
|
||||
} else {
|
||||
hifi.buttons.colorFinish[control.color]
|
||||
}
|
||||
}
|
||||
}
|
||||
text: control.glyph
|
||||
size: control.size
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: HiFiGlyphs {
|
||||
color: enabled ? hifi.buttons.textColor[control.color]
|
||||
: hifi.buttons.disabledTextColor[control.colorScheme]
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: control.glyph
|
||||
size: control.size
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import "../styles-uit"
|
||||
|
||||
Item {
|
||||
|
|
|
@ -26,15 +26,17 @@ Rectangle {
|
|||
|
||||
readonly property int keyboardRowHeight: 50
|
||||
readonly property int keyboardWidth: 480
|
||||
readonly property int keyboardHeight: 200
|
||||
|
||||
readonly property int mirrorTextHeight: keyboardRowHeight
|
||||
|
||||
property bool password: false
|
||||
property alias mirroredText: mirrorText.text
|
||||
property bool showMirrorText: true
|
||||
readonly property int raisedHeight: 200
|
||||
|
||||
height: enabled && raised ? raisedHeight + (showMirrorText ? keyboardRowHeight : 0) : 0
|
||||
readonly property int raisedHeight: keyboardHeight + (showMirrorText ? keyboardRowHeight : 0)
|
||||
|
||||
height: enabled && raised ? raisedHeight : 0
|
||||
visible: enabled && raised
|
||||
|
||||
property bool shiftMode: false
|
||||
|
@ -158,7 +160,7 @@ Rectangle {
|
|||
id: keyboardRect
|
||||
y: showMirrorText ? mirrorTextHeight : 0
|
||||
width: keyboardWidth
|
||||
height: raisedHeight
|
||||
height: keyboardHeight
|
||||
color: "#252525"
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
|
@ -167,7 +169,7 @@ Rectangle {
|
|||
Column {
|
||||
id: columnAlpha
|
||||
width: keyboardWidth
|
||||
height: raisedHeight
|
||||
height: keyboardHeight
|
||||
visible: !numeric
|
||||
|
||||
Row {
|
||||
|
@ -259,7 +261,7 @@ Rectangle {
|
|||
Column {
|
||||
id: columnNumeric
|
||||
width: keyboardWidth
|
||||
height: raisedHeight
|
||||
height: keyboardHeight
|
||||
visible: numeric
|
||||
|
||||
Row {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick 2.7
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
import "../styles-uit"
|
||||
import "." as HifiControls
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick.Controls 2.2 as Original
|
||||
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
|
@ -21,6 +20,8 @@ Original.RadioButton {
|
|||
id: radioButton
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
hoverEnabled: true
|
||||
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||
|
||||
|
@ -33,50 +34,53 @@ Original.RadioButton {
|
|||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
}
|
||||
|
||||
// TODO: doesnt works for QQC1. check with QQC2
|
||||
// onHovered: {
|
||||
// Tablet.playSound(TabletEnums.ButtonHover);
|
||||
// }
|
||||
|
||||
style: RadioButtonStyle {
|
||||
indicator: Rectangle {
|
||||
id: box
|
||||
width: boxSize
|
||||
height: boxSize
|
||||
radius: 7
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: pressed || hovered
|
||||
? (radioButton.isLightColorScheme ? hifi.colors.checkboxDarkStart : hifi.colors.checkboxLightStart)
|
||||
: (radioButton.isLightColorScheme ? hifi.colors.checkboxLightStart : hifi.colors.checkboxDarkStart)
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: pressed || hovered
|
||||
? (radioButton.isLightColorScheme ? hifi.colors.checkboxDarkFinish : hifi.colors.checkboxLightFinish)
|
||||
: (radioButton.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: check
|
||||
width: checkSize
|
||||
height: checkSize
|
||||
radius: 7
|
||||
anchors.centerIn: parent
|
||||
color: "#00B4EF"
|
||||
border.width: 1
|
||||
border.color: "#36CDFF"
|
||||
visible: checked && !pressed || !checked && pressed
|
||||
}
|
||||
}
|
||||
|
||||
label: RalewaySemiBold {
|
||||
text: control.text
|
||||
size: hifi.fontSizes.inputLabel
|
||||
color: isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText
|
||||
x: radioButton.boxSize / 2
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
Tablet.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
}
|
||||
|
||||
indicator: Rectangle {
|
||||
id: box
|
||||
width: boxSize
|
||||
height: boxSize
|
||||
radius: 7
|
||||
x: radioButton.leftPadding
|
||||
y: parent.height / 2 - height / 2
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: pressed || hovered
|
||||
? (radioButton.isLightColorScheme ? hifi.colors.checkboxDarkStart : hifi.colors.checkboxLightStart)
|
||||
: (radioButton.isLightColorScheme ? hifi.colors.checkboxLightStart : hifi.colors.checkboxDarkStart)
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: pressed || hovered
|
||||
? (radioButton.isLightColorScheme ? hifi.colors.checkboxDarkFinish : hifi.colors.checkboxLightFinish)
|
||||
: (radioButton.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: check
|
||||
width: checkSize
|
||||
height: checkSize
|
||||
radius: 7
|
||||
anchors.centerIn: parent
|
||||
color: "#00B4EF"
|
||||
border.width: 1
|
||||
border.color: "#36CDFF"
|
||||
visible: checked && !pressed || !checked && pressed
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: RalewaySemiBold {
|
||||
text: radioButton.text
|
||||
size: hifi.fontSizes.inputLabel
|
||||
color: isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
leftPadding: radioButton.indicator.width + radioButton.spacing
|
||||
}
|
||||
}
|
||||
|
|
41
interface/resources/qml/controls-uit/ScrollBar.qml
Normal file
41
interface/resources/qml/controls-uit/ScrollBar.qml
Normal file
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// ScrollBar.qml
|
||||
//
|
||||
// Created by Vlad Stelmahovsky on 27 Nov 2017
|
||||
// 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.7
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
ScrollBar {
|
||||
visible: size < 1.0
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||
|
||||
background: Item {
|
||||
implicitWidth: hifi.dimensions.scrollbarBackgroundWidth
|
||||
Rectangle {
|
||||
anchors { fill: parent; topMargin: 3; bottomMargin: 3 }
|
||||
radius: hifi.dimensions.scrollbarHandleWidth/2
|
||||
color: isLightColorScheme ? hifi.colors.tableScrollBackgroundLight
|
||||
: hifi.colors.tableScrollBackgroundDark
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: hifi.dimensions.scrollbarHandleWidth
|
||||
Rectangle {
|
||||
anchors { fill: parent; topMargin: 1; bottomMargin: 1 }
|
||||
radius: hifi.dimensions.scrollbarHandleWidth/2
|
||||
color: isLightColorScheme ? hifi.colors.tableScrollHandleLight : hifi.colors.tableScrollHandleDark
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,9 +8,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
|
@ -23,66 +22,65 @@ Slider {
|
|||
property string label: ""
|
||||
property real controlHeight: height + (sliderLabel.visible ? sliderLabel.height + sliderLabel.anchors.bottomMargin : 0)
|
||||
|
||||
property alias minimumValue: slider.from
|
||||
property alias maximumValue: slider.to
|
||||
|
||||
height: hifi.fontSizes.textFieldInput + 14 // Match height of TextField control.
|
||||
y: sliderLabel.visible ? sliderLabel.height + sliderLabel.anchors.bottomMargin : 0
|
||||
|
||||
style: SliderStyle {
|
||||
background: Rectangle {
|
||||
x: slider.leftPadding
|
||||
y: slider.topPadding + slider.availableHeight / 2 - height / 2
|
||||
|
||||
groove: Rectangle {
|
||||
implicitWidth: 50
|
||||
implicitHeight: hifi.dimensions.sliderGrooveHeight
|
||||
implicitWidth: 50
|
||||
implicitHeight: hifi.dimensions.sliderGrooveHeight
|
||||
width: slider.availableWidth
|
||||
height: implicitHeight
|
||||
radius: height / 2
|
||||
color: isLightColorScheme ? hifi.colors.sliderGutterLight : hifi.colors.sliderGutterDark
|
||||
|
||||
Rectangle {
|
||||
width: slider.visualPosition * parent.width
|
||||
height: parent.height
|
||||
radius: height / 2
|
||||
color: isLightColorScheme ? hifi.colors.sliderGutterLight : hifi.colors.sliderGutterDark
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: hifi.colors.blueAccent }
|
||||
GradientStop { position: 1.0; color: hifi.colors.primaryHighlight }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.height - 2
|
||||
height: slider.width * (slider.value - slider.minimumValue) / (slider.maximumValue - slider.minimumValue) - 1
|
||||
radius: height / 2
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: width + 1
|
||||
left: parent.left
|
||||
leftMargin: 1
|
||||
}
|
||||
transformOrigin: Item.TopLeft
|
||||
rotation: -90
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: hifi.colors.blueAccent }
|
||||
GradientStop { position: 1.0; color: hifi.colors.primaryHighlight }
|
||||
}
|
||||
handle: Rectangle {
|
||||
x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width)
|
||||
y: slider.topPadding + slider.availableHeight / 2 - height / 2
|
||||
implicitWidth: hifi.dimensions.sliderHandleSize
|
||||
implicitHeight: hifi.dimensions.sliderHandleSize
|
||||
radius: height / 2
|
||||
border.width: 1
|
||||
border.color: isLightColorScheme ? hifi.colors.sliderBorderLight : hifi.colors.sliderBorderDark
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.0
|
||||
color: pressed || hovered
|
||||
? (isLightColorScheme ? hifi.colors.sliderDarkStart : hifi.colors.sliderLightStart )
|
||||
: (isLightColorScheme ? hifi.colors.sliderLightStart : hifi.colors.sliderDarkStart )
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: pressed || hovered
|
||||
? (isLightColorScheme ? hifi.colors.sliderDarkFinish : hifi.colors.sliderLightFinish )
|
||||
: (isLightColorScheme ? hifi.colors.sliderLightFinish : hifi.colors.sliderDarkFinish )
|
||||
}
|
||||
}
|
||||
|
||||
handle: Rectangle {
|
||||
implicitWidth: hifi.dimensions.sliderHandleSize
|
||||
implicitHeight: hifi.dimensions.sliderHandleSize
|
||||
Rectangle {
|
||||
height: parent.height - 2
|
||||
width: height
|
||||
radius: height / 2
|
||||
anchors.centerIn: parent
|
||||
color: hifi.colors.transparent
|
||||
border.width: 1
|
||||
border.color: isLightColorScheme ? hifi.colors.sliderBorderLight : hifi.colors.sliderBorderDark
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.0
|
||||
color: pressed || hovered
|
||||
? (isLightColorScheme ? hifi.colors.sliderDarkStart : hifi.colors.sliderLightStart )
|
||||
: (isLightColorScheme ? hifi.colors.sliderLightStart : hifi.colors.sliderDarkStart )
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: pressed || hovered
|
||||
? (isLightColorScheme ? hifi.colors.sliderDarkFinish : hifi.colors.sliderLightFinish )
|
||||
: (isLightColorScheme ? hifi.colors.sliderLightFinish : hifi.colors.sliderDarkFinish )
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
height: parent.height - 2
|
||||
width: height
|
||||
radius: height / 2
|
||||
anchors.centerIn: parent
|
||||
color: hifi.colors.transparent
|
||||
border.width: 1
|
||||
border.color: hifi.colors.black
|
||||
}
|
||||
border.color: hifi.colors.black
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,9 +8,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
|
@ -19,11 +18,40 @@ SpinBox {
|
|||
id: spinBox
|
||||
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||
readonly property bool isLightColorScheme: colorScheme === hifi.colorSchemes.light
|
||||
property string label: ""
|
||||
property string labelInside: ""
|
||||
property color colorLabelInside: hifi.colors.white
|
||||
property real controlHeight: height + (spinBoxLabel.visible ? spinBoxLabel.height + spinBoxLabel.anchors.bottomMargin : 0)
|
||||
property int decimals: 2;
|
||||
property real factor: Math.pow(10, decimals)
|
||||
|
||||
property real minimumValue: 0.0
|
||||
property real maximumValue: 0.0
|
||||
|
||||
property real realValue: 0.0
|
||||
property real realFrom: 0.0
|
||||
property real realTo: 100.0
|
||||
property real realStepSize: 1.0
|
||||
|
||||
implicitHeight: height
|
||||
implicitWidth: width
|
||||
|
||||
padding: 0
|
||||
leftPadding: 0
|
||||
rightPadding: padding + (up.indicator ? up.indicator.width : 0)
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
locale: Qt.locale("en_US")
|
||||
|
||||
onValueModified: realValue = value/factor
|
||||
onValueChanged: realValue = value/factor
|
||||
|
||||
stepSize: realStepSize*factor
|
||||
value: realValue*factor
|
||||
to : realTo*factor
|
||||
from : realFrom*factor
|
||||
|
||||
font.family: "Fira Sans SemiBold"
|
||||
font.pixelSize: hifi.fontSizes.textFieldInput
|
||||
|
@ -31,43 +59,67 @@ SpinBox {
|
|||
|
||||
y: spinBoxLabel.visible ? spinBoxLabel.height + spinBoxLabel.anchors.bottomMargin : 0
|
||||
|
||||
style: SpinBoxStyle {
|
||||
id: spinStyle
|
||||
background: Rectangle {
|
||||
color: isLightColorScheme
|
||||
? (spinBox.activeFocus ? hifi.colors.white : hifi.colors.lightGray)
|
||||
: (spinBox.activeFocus ? hifi.colors.black : hifi.colors.baseGrayShadow)
|
||||
border.color: spinBoxLabelInside.visible ? spinBoxLabelInside.color : hifi.colors.primaryHighlight
|
||||
border.width: spinBox.activeFocus ? spinBoxLabelInside.visible ? 2 : 1 : 0
|
||||
}
|
||||
background: Rectangle {
|
||||
color: isLightColorScheme
|
||||
? (spinBox.activeFocus ? hifi.colors.white : hifi.colors.lightGray)
|
||||
: (spinBox.activeFocus ? hifi.colors.black : hifi.colors.baseGrayShadow)
|
||||
border.color: spinBoxLabelInside.visible ? spinBoxLabelInside.color : hifi.colors.primaryHighlight
|
||||
border.width: spinBox.activeFocus ? spinBoxLabelInside.visible ? 2 : 1 : 0
|
||||
}
|
||||
|
||||
textColor: isLightColorScheme
|
||||
? (spinBox.activeFocus ? hifi.colors.black : hifi.colors.lightGray)
|
||||
: (spinBox.activeFocus ? hifi.colors.white : hifi.colors.lightGrayText)
|
||||
validator: DoubleValidator {
|
||||
bottom: Math.min(spinBox.from, spinBox.to)*spinBox.factor
|
||||
top: Math.max(spinBox.from, spinBox.to)*spinBox.factor
|
||||
}
|
||||
|
||||
textFromValue: function(value, locale) {
|
||||
return parseFloat(value*1.0/factor).toFixed(decimals);
|
||||
}
|
||||
|
||||
valueFromText: function(text, locale) {
|
||||
return Number.fromLocaleString(locale, text);
|
||||
}
|
||||
|
||||
|
||||
contentItem: TextInput {
|
||||
z: 2
|
||||
color: isLightColorScheme
|
||||
? (spinBox.activeFocus ? hifi.colors.black : hifi.colors.lightGray)
|
||||
: (spinBox.activeFocus ? hifi.colors.white : hifi.colors.lightGrayText)
|
||||
selectedTextColor: hifi.colors.black
|
||||
selectionColor: hifi.colors.primaryHighlight
|
||||
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
padding.left: spinBoxLabelInside.visible ? 30 : hifi.dimensions.textPadding
|
||||
padding.right: hifi.dimensions.spinnerSize
|
||||
padding.top: 0
|
||||
|
||||
incrementControl: HiFiGlyphs {
|
||||
id: incrementButton
|
||||
text: spinBox.textFromValue(spinBox.value, spinBox.locale)
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
leftPadding: spinBoxLabelInside.visible ? 30 : hifi.dimensions.textPadding
|
||||
//rightPadding: hifi.dimensions.spinnerSize
|
||||
width: spinBox.width - hifi.dimensions.spinnerSize
|
||||
}
|
||||
up.indicator: Item {
|
||||
x: spinBox.width - implicitWidth - 5
|
||||
y: 1
|
||||
clip: true
|
||||
implicitHeight: spinBox.implicitHeight/2
|
||||
implicitWidth: spinBox.implicitHeight/2
|
||||
HiFiGlyphs {
|
||||
anchors.centerIn: parent
|
||||
text: hifi.glyphs.caratUp
|
||||
x: 10
|
||||
y: 1
|
||||
size: hifi.dimensions.spinnerSize
|
||||
color: styleData.upPressed ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
|
||||
color: spinBox.down.pressed || spinBox.up.hovered ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
|
||||
}
|
||||
}
|
||||
|
||||
decrementControl: HiFiGlyphs {
|
||||
text: hifi.glyphs.caratDn
|
||||
x: 10
|
||||
y: -1
|
||||
size: hifi.dimensions.spinnerSize
|
||||
color: styleData.downPressed ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
|
||||
}
|
||||
down.indicator: Item {
|
||||
x: spinBox.width - implicitWidth - 5
|
||||
y: spinBox.implicitHeight/2
|
||||
clip: true
|
||||
implicitHeight: spinBox.implicitHeight/2
|
||||
implicitWidth: spinBox.implicitHeight/2
|
||||
HiFiGlyphs {
|
||||
anchors.centerIn: parent
|
||||
text: hifi.glyphs.caratDn
|
||||
size: hifi.dimensions.spinnerSize
|
||||
color: spinBox.down.pressed || spinBox.down.hovered ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Label {
|
||||
|
@ -91,26 +143,26 @@ SpinBox {
|
|||
visible: spinBox.labelInside != ""
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
propagateComposedEvents: true
|
||||
onWheel: {
|
||||
if(spinBox.activeFocus)
|
||||
wheel.accepted = false
|
||||
else
|
||||
wheel.accepted = true
|
||||
}
|
||||
onPressed: {
|
||||
mouse.accepted = false
|
||||
}
|
||||
onReleased: {
|
||||
mouse.accepted = false
|
||||
}
|
||||
onClicked: {
|
||||
mouse.accepted = false
|
||||
}
|
||||
onDoubleClicked: {
|
||||
mouse.accepted = false
|
||||
}
|
||||
}
|
||||
// MouseArea {
|
||||
// anchors.fill: parent
|
||||
// propagateComposedEvents: true
|
||||
// onWheel: {
|
||||
// if(spinBox.activeFocus)
|
||||
// wheel.accepted = false
|
||||
// else
|
||||
// wheel.accepted = true
|
||||
// }
|
||||
// onPressed: {
|
||||
// mouse.accepted = false
|
||||
// }
|
||||
// onReleased: {
|
||||
// mouse.accepted = false
|
||||
// }
|
||||
// onClicked: {
|
||||
// mouse.accepted = false
|
||||
// }
|
||||
// onDoubleClicked: {
|
||||
// mouse.accepted = false
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -8,9 +8,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2 as Original
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
|
@ -33,44 +32,49 @@ Item {
|
|||
|
||||
Original.Switch {
|
||||
id: originalSwitch;
|
||||
activeFocusOnPress: true;
|
||||
focusPolicy: Qt.ClickFocus
|
||||
anchors.top: rootSwitch.top;
|
||||
anchors.left: rootSwitch.left;
|
||||
anchors.leftMargin: rootSwitch.width/2 - rootSwitch.switchWidth/2;
|
||||
onCheckedChanged: rootSwitch.onCheckedChanged();
|
||||
onClicked: rootSwitch.clicked();
|
||||
hoverEnabled: true
|
||||
|
||||
style: SwitchStyle {
|
||||
topPadding: 3;
|
||||
leftPadding: 3;
|
||||
rightPadding: 3;
|
||||
bottomPadding: 3;
|
||||
|
||||
padding {
|
||||
top: 3;
|
||||
left: 3;
|
||||
right: 3;
|
||||
bottom: 3;
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
switchHandle.color = hifi.colors.blueHighlight;
|
||||
} else {
|
||||
switchHandle.color = hifi.colors.lightGray;
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: "#252525";
|
||||
implicitWidth: rootSwitch.switchWidth;
|
||||
implicitHeight: rootSwitch.height;
|
||||
radius: rootSwitch.switchRadius;
|
||||
}
|
||||
|
||||
indicator: Rectangle {
|
||||
id: switchHandle;
|
||||
implicitWidth: rootSwitch.height - originalSwitch.topPadding - originalSwitch.bottomPadding;
|
||||
implicitHeight: implicitWidth;
|
||||
radius: implicitWidth/2;
|
||||
border.color: hifi.colors.lightGrayText;
|
||||
color: hifi.colors.lightGray;
|
||||
//x: originalSwitch.leftPadding
|
||||
x: Math.max(0, Math.min(parent.width - width, originalSwitch.visualPosition * parent.width - (width / 2)))
|
||||
y: parent.height / 2 - height / 2
|
||||
Behavior on x {
|
||||
enabled: !originalSwitch.down
|
||||
SmoothedAnimation { velocity: 200 }
|
||||
}
|
||||
|
||||
groove: Rectangle {
|
||||
color: "#252525";
|
||||
implicitWidth: rootSwitch.switchWidth;
|
||||
implicitHeight: rootSwitch.height;
|
||||
radius: rootSwitch.switchRadius;
|
||||
}
|
||||
|
||||
handle: Rectangle {
|
||||
id: switchHandle;
|
||||
implicitWidth: rootSwitch.height - padding.top - padding.bottom;
|
||||
implicitHeight: implicitWidth;
|
||||
radius: implicitWidth/2;
|
||||
border.color: hifi.colors.lightGrayText;
|
||||
color: hifi.colors.lightGray;
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
hoverEnabled: true;
|
||||
onEntered: parent.color = hifi.colors.blueHighlight;
|
||||
onExited: parent.color = hifi.colors.lightGray;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick.Controls 2.2 as QQC2
|
||||
import QtQuick.Controls 2.3 as QQC2
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import "../styles-uit"
|
||||
|
||||
TextEdit {
|
||||
|
|
|
@ -163,8 +163,10 @@ TextField {
|
|||
text: textField.label
|
||||
colorScheme: textField.colorScheme
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: 3
|
||||
wrapMode: Text.WordWrap
|
||||
visible: label != ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick.Controls 2.2 as Original
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
|
@ -26,23 +25,16 @@ Original.Button {
|
|||
readonly property color clickedColor: "#FFFFFF"
|
||||
readonly property color disabledColor: "#575757"
|
||||
|
||||
style: ButtonStyle {
|
||||
background: Item {}
|
||||
background: Item {}
|
||||
|
||||
|
||||
label: HiFiGlyphs {
|
||||
color: control.enabled ? (control.pressed ? control.clickedColor :
|
||||
(control.hovered ? control.hoverColor : control.normalColor)) :
|
||||
control.disabledColor
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors {
|
||||
// Tweak horizontal alignment so that it looks right.
|
||||
left: parent.left
|
||||
leftMargin: -0.5
|
||||
}
|
||||
text: control.glyph
|
||||
size: control.size
|
||||
}
|
||||
contentItem: HiFiGlyphs {
|
||||
color: control.enabled ? (control.pressed ? control.clickedColor :
|
||||
(control.hovered ? control.hoverColor : control.normalColor)) :
|
||||
control.disabledColor
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: control.glyph
|
||||
size: control.size
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,27 +1,35 @@
|
|||
import QtQuick 2.3
|
||||
import QtQuick.Controls 1.3 as Original
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
import QtQuick.Controls 2.2 as Original
|
||||
|
||||
import "."
|
||||
import "../styles"
|
||||
import "../controls-uit"
|
||||
|
||||
Original.Button {
|
||||
style: ButtonStyle {
|
||||
HifiConstants { id: hifi }
|
||||
padding {
|
||||
top: 8
|
||||
left: 12
|
||||
right: 12
|
||||
bottom: 8
|
||||
}
|
||||
background: Border {
|
||||
anchors.fill: parent
|
||||
}
|
||||
label: Text {
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: control.text
|
||||
color: control.enabled ? hifi.colors.text : hifi.colors.disabledText
|
||||
id: control
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
property Action action: null
|
||||
|
||||
onActionChanged: {
|
||||
if (action !== null && action.text !== "") {
|
||||
control.text = action.text
|
||||
}
|
||||
}
|
||||
|
||||
padding {
|
||||
top: 8
|
||||
left: 12
|
||||
right: 12
|
||||
bottom: 8
|
||||
}
|
||||
background: Border {
|
||||
anchors.fill: parent
|
||||
}
|
||||
contentItem: Text {
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: control.text
|
||||
color: control.enabled ? hifi.colors.text : hifi.colors.disabledText
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,9 +122,21 @@ Item {
|
|||
newViewRequestedCallback(request)
|
||||
}
|
||||
|
||||
// Prior to 5.10, the WebEngineView loading property is true during initial page loading and then stays false
|
||||
// as in-page javascript adds more html content. However, in 5.10 there is a bug such that adding html turns
|
||||
// loading true, and never turns it false again. safeLoading provides a workaround, but it should be removed
|
||||
// when QT fixes this.
|
||||
property bool safeLoading: false
|
||||
property bool loadingLatched: false
|
||||
property var loadingRequest: null
|
||||
onLoadingChanged: {
|
||||
flick.onLoadingChanged(loadRequest)
|
||||
loadingChangedCallback(loadRequest)
|
||||
webViewCore.loadingRequest = loadRequest;
|
||||
webViewCore.safeLoading = webViewCore.loading && !loadingLatched;
|
||||
webViewCore.loadingLatched |= webViewCore.loading;
|
||||
}
|
||||
onSafeLoadingChanged: {
|
||||
flick.onLoadingChanged(webViewCore.loadingRequest)
|
||||
loadingChangedCallback(webViewCore.loadingRequest)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,7 +145,7 @@ Item {
|
|||
x: flick.width/2 - width/2
|
||||
y: flick.height/2 - height/2
|
||||
source: "../../icons/loader-snake-64-w.gif"
|
||||
visible: webViewCore.loading && /^(http.*|)$/i.test(webViewCore.url.toString())
|
||||
visible: webViewCore.safeLoading && /^(http.*|)$/i.test(webViewCore.url.toString())
|
||||
playing: visible
|
||||
z: 10000
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import QtQuick 2.3
|
||||
import QtQuick.Controls 1.3
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
|
||||
Text {
|
||||
id: root
|
||||
|
|
575
interface/resources/qml/desktop/+android/Desktop.qml
Normal file
575
interface/resources/qml/desktop/+android/Desktop.qml
Normal file
|
@ -0,0 +1,575 @@
|
|||
//
|
||||
// Desktop.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 15 Apr 2015
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
import "../dialogs"
|
||||
import "../js/Utils.js" as Utils
|
||||
|
||||
// This is our primary 'desktop' object to which all VR dialogs and windows are childed.
|
||||
FocusScope {
|
||||
id: desktop
|
||||
objectName: "desktop"
|
||||
anchors.fill: parent
|
||||
|
||||
readonly property int invalid_position: -9999;
|
||||
property rect recommendedRect: Qt.rect(0,0,0,0);
|
||||
property var expectedChildren;
|
||||
property bool repositionLocked: true
|
||||
property bool hmdHandMouseActive: false
|
||||
|
||||
onRepositionLockedChanged: {
|
||||
if (!repositionLocked) {
|
||||
d.handleSizeChanged();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onHeightChanged: d.handleSizeChanged();
|
||||
|
||||
onWidthChanged: d.handleSizeChanged();
|
||||
|
||||
// Controls and windows can trigger this signal to ensure the desktop becomes visible
|
||||
// when they're opened.
|
||||
signal showDesktop();
|
||||
|
||||
// This is for JS/QML communication, which is unused in the Desktop,
|
||||
// but not having this here results in spurious warnings about a
|
||||
// missing signal
|
||||
signal sendToScript(var message);
|
||||
|
||||
// Allows QML/JS to find the desktop through the parent chain
|
||||
property bool desktopRoot: true
|
||||
|
||||
// The VR version of the primary menu
|
||||
property var rootMenu: Menu {
|
||||
id: rootMenuId
|
||||
objectName: "rootMenu"
|
||||
|
||||
property var exclusionGroups: ({});
|
||||
property Component exclusiveGroupMaker: Component {
|
||||
ExclusiveGroup {
|
||||
}
|
||||
}
|
||||
|
||||
function addExclusionGroup(qmlAction, exclusionGroup) {
|
||||
|
||||
var exclusionGroupId = exclusionGroup.toString();
|
||||
if(!exclusionGroups[exclusionGroupId]) {
|
||||
exclusionGroups[exclusionGroupId] = exclusiveGroupMaker.createObject(rootMenuId);
|
||||
}
|
||||
|
||||
qmlAction.exclusiveGroup = exclusionGroups[exclusionGroupId]
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Alpha gradients display as fuschia under QtQuick 2.5 on OSX/AMD
|
||||
// because shaders are 4.2, and do not include #version declarations.
|
||||
property bool gradientsSupported: Qt.platform.os != "osx" && !~GL.vendor.indexOf("ATI")
|
||||
|
||||
readonly property alias zLevels: zLevels
|
||||
QtObject {
|
||||
id: zLevels;
|
||||
readonly property real normal: 1 // make windows always appear higher than QML overlays and other non-window controls.
|
||||
readonly property real top: 2000
|
||||
readonly property real modal: 4000
|
||||
readonly property real menu: 8000
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
function handleSizeChanged() {
|
||||
if (desktop.repositionLocked) {
|
||||
return;
|
||||
}
|
||||
var oldRecommendedRect = recommendedRect;
|
||||
var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedHUDRect();
|
||||
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
|
||||
newRecommendedRectJS.width,
|
||||
newRecommendedRectJS.height);
|
||||
|
||||
var oldChildren = expectedChildren;
|
||||
var newChildren = d.getRepositionChildren();
|
||||
if (oldRecommendedRect != Qt.rect(0,0,0,0) && oldRecommendedRect != Qt.rect(0,0,1,1)
|
||||
&& (oldRecommendedRect != newRecommendedRect
|
||||
|| oldChildren != newChildren)
|
||||
) {
|
||||
expectedChildren = newChildren;
|
||||
d.repositionAll();
|
||||
}
|
||||
recommendedRect = newRecommendedRect;
|
||||
}
|
||||
|
||||
function findChild(item, name) {
|
||||
for (var i = 0; i < item.children.length; ++i) {
|
||||
if (item.children[i].objectName === name) {
|
||||
return item.children[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function findParentMatching(item, predicate) {
|
||||
while (item) {
|
||||
if (predicate(item)) {
|
||||
break;
|
||||
}
|
||||
item = item.parent;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
function findMatchingChildren(item, predicate) {
|
||||
var results = [];
|
||||
for (var i in item.children) {
|
||||
var child = item.children[i];
|
||||
if (predicate(child)) {
|
||||
results.push(child);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
function isTopLevelWindow(item) {
|
||||
return item.topLevelWindow;
|
||||
}
|
||||
|
||||
function isAlwaysOnTopWindow(window) {
|
||||
return window.alwaysOnTop;
|
||||
}
|
||||
|
||||
function isModalWindow(window) {
|
||||
return window.modality !== Qt.NonModal;
|
||||
}
|
||||
|
||||
function getTopLevelWindows(predicate) {
|
||||
return findMatchingChildren(desktop, function(child) {
|
||||
return (isTopLevelWindow(child) && (!predicate || predicate(child)));
|
||||
});
|
||||
}
|
||||
|
||||
function getDesktopWindow(item) {
|
||||
return findParentMatching(item, isTopLevelWindow)
|
||||
}
|
||||
|
||||
function fixupZOrder(windows, basis, topWindow) {
|
||||
windows.sort(function(a, b){ return a.z - b.z; });
|
||||
|
||||
if ((topWindow.z >= basis) && (windows[windows.length - 1] === topWindow)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var lastZ = -1;
|
||||
var lastTargetZ = basis - 1;
|
||||
for (var i = 0; i < windows.length; ++i) {
|
||||
var window = windows[i];
|
||||
if (!window.visible) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (topWindow && (topWindow === window)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (window.z > lastZ) {
|
||||
lastZ = window.z;
|
||||
++lastTargetZ;
|
||||
}
|
||||
if (DebugQML) {
|
||||
console.log("Assigning z order " + lastTargetZ + " to " + window)
|
||||
}
|
||||
|
||||
window.z = lastTargetZ;
|
||||
}
|
||||
if (topWindow) {
|
||||
++lastTargetZ;
|
||||
if (DebugQML) {
|
||||
console.log("Assigning z order " + lastTargetZ + " to " + topWindow)
|
||||
}
|
||||
topWindow.z = lastTargetZ;
|
||||
}
|
||||
|
||||
return lastTargetZ;
|
||||
}
|
||||
|
||||
function raiseWindow(targetWindow) {
|
||||
var predicate;
|
||||
var zBasis;
|
||||
if (isModalWindow(targetWindow)) {
|
||||
predicate = isModalWindow;
|
||||
zBasis = zLevels.modal
|
||||
} else if (isAlwaysOnTopWindow(targetWindow)) {
|
||||
predicate = function(window) {
|
||||
return (isAlwaysOnTopWindow(window) && !isModalWindow(window));
|
||||
}
|
||||
zBasis = zLevels.top
|
||||
} else {
|
||||
predicate = function(window) {
|
||||
return (!isAlwaysOnTopWindow(window) && !isModalWindow(window));
|
||||
}
|
||||
zBasis = zLevels.normal
|
||||
}
|
||||
|
||||
var windows = getTopLevelWindows(predicate);
|
||||
fixupZOrder(windows, zBasis, targetWindow);
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
//offscreenWindow.activeFocusItemChanged.connect(onWindowFocusChanged);
|
||||
focusHack.start();
|
||||
}
|
||||
|
||||
function onWindowFocusChanged() {
|
||||
//console.log("Focus item is " + offscreenWindow.activeFocusItem);
|
||||
|
||||
// FIXME this needs more testing before it can go into production
|
||||
// and I already cant produce any way to have a modal dialog lose focus
|
||||
// to a non-modal one.
|
||||
/*
|
||||
var focusedWindow = getDesktopWindow(offscreenWindow.activeFocusItem);
|
||||
|
||||
if (isModalWindow(focusedWindow)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// new focused window is not modal... check if there are any modal windows
|
||||
var windows = getTopLevelWindows(isModalWindow);
|
||||
if (0 === windows.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// There are modal windows present, force focus back to the top-most modal window
|
||||
windows.sort(function(a, b){ return a.z - b.z; });
|
||||
windows[windows.length - 1].focus = true;
|
||||
*/
|
||||
|
||||
// var focusedItem = offscreenWindow.activeFocusItem ;
|
||||
// if (DebugQML && focusedItem) {
|
||||
// var rect = desktop.mapFromItem(focusedItem, 0, 0, focusedItem.width, focusedItem.height);
|
||||
// focusDebugger.x = rect.x;
|
||||
// focusDebugger.y = rect.y;
|
||||
// focusDebugger.width = rect.width
|
||||
// focusDebugger.height = rect.height
|
||||
// }
|
||||
}
|
||||
|
||||
function getRepositionChildren(predicate) {
|
||||
return findMatchingChildren(desktop, function(child) {
|
||||
return (child.shouldReposition === true && (!predicate || predicate(child)));
|
||||
});
|
||||
}
|
||||
|
||||
function repositionAll() {
|
||||
if (desktop.repositionLocked) {
|
||||
return;
|
||||
}
|
||||
|
||||
var oldRecommendedRect = recommendedRect;
|
||||
var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
|
||||
var newRecommendedRect = Controller.getRecommendedHUDRect();
|
||||
var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
|
||||
var windows = d.getTopLevelWindows();
|
||||
for (var i = 0; i < windows.length; ++i) {
|
||||
var targetWindow = windows[i];
|
||||
if (targetWindow.visible) {
|
||||
repositionWindow(targetWindow, true, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
|
||||
}
|
||||
}
|
||||
|
||||
// also reposition the other children that aren't top level windows but want to be repositioned
|
||||
var otherChildren = d.getRepositionChildren();
|
||||
for (var i = 0; i < otherChildren.length; ++i) {
|
||||
var child = otherChildren[i];
|
||||
repositionWindow(child, true, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
property bool pinned: false
|
||||
property var hiddenChildren: []
|
||||
|
||||
function togglePinned() {
|
||||
pinned = !pinned
|
||||
}
|
||||
|
||||
function isPointOnWindow(point) {
|
||||
for (var i = 0; i < desktop.visibleChildren.length; i++) {
|
||||
var child = desktop.visibleChildren[i];
|
||||
if (child.hasOwnProperty("modality")) {
|
||||
var mappedPoint = mapToItem(child, point.x, point.y);
|
||||
if (child.hasOwnProperty("frame")) {
|
||||
var outLine = child.frame.children[2];
|
||||
var framePoint = outLine.mapFromGlobal(point.x, point.y);
|
||||
if (outLine.contains(framePoint)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (child.contains(mappedPoint)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function setPinned(newPinned) {
|
||||
pinned = newPinned
|
||||
}
|
||||
|
||||
property real unpinnedAlpha: 1.0;
|
||||
|
||||
Behavior on unpinnedAlpha {
|
||||
NumberAnimation {
|
||||
easing.type: Easing.Linear;
|
||||
duration: 300
|
||||
}
|
||||
}
|
||||
|
||||
state: "NORMAL"
|
||||
states: [
|
||||
State {
|
||||
name: "NORMAL"
|
||||
PropertyChanges { target: desktop; unpinnedAlpha: 1.0 }
|
||||
},
|
||||
State {
|
||||
name: "PINNED"
|
||||
PropertyChanges { target: desktop; unpinnedAlpha: 0.0 }
|
||||
}
|
||||
]
|
||||
|
||||
transitions: [
|
||||
Transition {
|
||||
NumberAnimation { properties: "unpinnedAlpha"; duration: 300 }
|
||||
}
|
||||
]
|
||||
|
||||
onPinnedChanged: {
|
||||
if (pinned) {
|
||||
d.raiseWindow(desktop);
|
||||
desktop.focus = true;
|
||||
desktop.forceActiveFocus();
|
||||
|
||||
// recalculate our non-pinned children
|
||||
hiddenChildren = d.findMatchingChildren(desktop, function(child){
|
||||
return !d.isTopLevelWindow(child) && child.visible && !child.pinned;
|
||||
});
|
||||
|
||||
hiddenChildren.forEach(function(child){
|
||||
child.opacity = Qt.binding(function(){ return desktop.unpinnedAlpha });
|
||||
});
|
||||
}
|
||||
state = pinned ? "PINNED" : "NORMAL"
|
||||
}
|
||||
|
||||
onShowDesktop: pinned = false
|
||||
|
||||
function raise(item) {
|
||||
var targetWindow = d.getDesktopWindow(item);
|
||||
if (!targetWindow) {
|
||||
console.warn("Could not find top level window for " + item);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fix up the Z-order (takes into account if this is a modal window)
|
||||
d.raiseWindow(targetWindow);
|
||||
var setFocus = true;
|
||||
if (!d.isModalWindow(targetWindow)) {
|
||||
var modalWindows = d.getTopLevelWindows(d.isModalWindow);
|
||||
if (modalWindows.length) {
|
||||
setFocus = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (setFocus) {
|
||||
targetWindow.focus = true;
|
||||
}
|
||||
|
||||
showDesktop();
|
||||
}
|
||||
|
||||
function ensureTitleBarVisible(targetWindow) {
|
||||
// Reposition window to ensure that title bar is vertically inside window.
|
||||
if (targetWindow.frame && targetWindow.frame.decoration) {
|
||||
var topMargin = -targetWindow.frame.decoration.anchors.topMargin; // Frame's topMargin is a negative value.
|
||||
targetWindow.y = Math.max(targetWindow.y, topMargin);
|
||||
}
|
||||
}
|
||||
|
||||
function centerOnVisible(item) {
|
||||
var targetWindow = d.getDesktopWindow(item);
|
||||
if (!targetWindow) {
|
||||
console.warn("Could not find top level window for " + item);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof Controller === "undefined") {
|
||||
console.warn("Controller not yet available... can't center");
|
||||
return;
|
||||
}
|
||||
|
||||
var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedHUDRect();
|
||||
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
|
||||
newRecommendedRectJS.width,
|
||||
newRecommendedRectJS.height);
|
||||
var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
|
||||
var newX = newRecommendedRect.x + ((newRecommendedRect.width - targetWindow.width) / 2);
|
||||
var newY = newRecommendedRect.y + ((newRecommendedRect.height - targetWindow.height) / 2);
|
||||
targetWindow.x = newX;
|
||||
targetWindow.y = newY;
|
||||
|
||||
ensureTitleBarVisible(targetWindow);
|
||||
|
||||
// If we've noticed that our recommended desktop rect has changed, record that change here.
|
||||
if (recommendedRect != newRecommendedRect) {
|
||||
recommendedRect = newRecommendedRect;
|
||||
}
|
||||
}
|
||||
|
||||
function repositionOnVisible(item) {
|
||||
var targetWindow = d.getDesktopWindow(item);
|
||||
if (!targetWindow) {
|
||||
console.warn("Could not find top level window for " + item);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof Controller === "undefined") {
|
||||
console.warn("Controller not yet available... can't reposition targetWindow:" + targetWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
var oldRecommendedRect = recommendedRect;
|
||||
var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
|
||||
var newRecommendedRect = Controller.getRecommendedHUDRect();
|
||||
var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
|
||||
repositionWindow(targetWindow, false, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
|
||||
}
|
||||
|
||||
function repositionWindow(targetWindow, forceReposition,
|
||||
oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions) {
|
||||
|
||||
if (desktop.width === 0 || desktop.height === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!targetWindow) {
|
||||
console.warn("Could not find top level window for " + item);
|
||||
return;
|
||||
}
|
||||
|
||||
var recommended = Controller.getRecommendedHUDRect();
|
||||
var maxX = recommended.x + recommended.width;
|
||||
var maxY = recommended.y + recommended.height;
|
||||
var newPosition = Qt.vector2d(targetWindow.x, targetWindow.y);
|
||||
|
||||
// if we asked to force reposition, or if the window is completely outside of the recommended rectangle, reposition it
|
||||
if (forceReposition || (targetWindow.x > maxX || (targetWindow.x + targetWindow.width) < recommended.x) ||
|
||||
(targetWindow.y > maxY || (targetWindow.y + targetWindow.height) < recommended.y)) {
|
||||
newPosition.x = -1
|
||||
newPosition.y = -1
|
||||
}
|
||||
|
||||
if (newPosition.x === -1 && newPosition.y === -1) {
|
||||
var originRelativeX = (targetWindow.x - oldRecommendedRect.x);
|
||||
var originRelativeY = (targetWindow.y - oldRecommendedRect.y);
|
||||
if (isNaN(originRelativeX)) {
|
||||
originRelativeX = 0;
|
||||
}
|
||||
if (isNaN(originRelativeY)) {
|
||||
originRelativeY = 0;
|
||||
}
|
||||
var fractionX = Utils.clamp(originRelativeX / oldRecommendedDimmensions.x, 0, 1);
|
||||
var fractionY = Utils.clamp(originRelativeY / oldRecommendedDimmensions.y, 0, 1);
|
||||
var newX = (fractionX * newRecommendedDimmensions.x) + newRecommendedRect.x;
|
||||
var newY = (fractionY * newRecommendedDimmensions.y) + newRecommendedRect.y;
|
||||
newPosition = Qt.vector2d(newX, newY);
|
||||
}
|
||||
targetWindow.x = newPosition.x;
|
||||
targetWindow.y = newPosition.y;
|
||||
|
||||
ensureTitleBarVisible(targetWindow);
|
||||
}
|
||||
|
||||
Component { id: messageDialogBuilder; MessageDialog { } }
|
||||
function messageBox(properties) {
|
||||
return messageDialogBuilder.createObject(desktop, properties);
|
||||
}
|
||||
|
||||
Component { id: inputDialogBuilder; QueryDialog { } }
|
||||
function inputDialog(properties) {
|
||||
return inputDialogBuilder.createObject(desktop, properties);
|
||||
}
|
||||
|
||||
Component { id: customInputDialogBuilder; CustomQueryDialog { } }
|
||||
function customInputDialog(properties) {
|
||||
return customInputDialogBuilder.createObject(desktop, properties);
|
||||
}
|
||||
|
||||
Component { id: fileDialogBuilder; FileDialog { } }
|
||||
function fileDialog(properties) {
|
||||
return fileDialogBuilder.createObject(desktop, properties);
|
||||
}
|
||||
|
||||
Component { id: assetDialogBuilder; AssetDialog { } }
|
||||
function assetDialog(properties) {
|
||||
return assetDialogBuilder.createObject(desktop, properties);
|
||||
}
|
||||
|
||||
function unfocusWindows() {
|
||||
// First find the active focus item, and unfocus it, all the way
|
||||
// up the parent chain to the window
|
||||
var currentFocus = offscreenWindow.activeFocusItem;
|
||||
var targetWindow = d.getDesktopWindow(currentFocus);
|
||||
while (currentFocus) {
|
||||
if (currentFocus === targetWindow) {
|
||||
break;
|
||||
}
|
||||
currentFocus.focus = false;
|
||||
currentFocus = currentFocus.parent;
|
||||
}
|
||||
|
||||
// Unfocus all windows
|
||||
var windows = d.getTopLevelWindows();
|
||||
for (var i = 0; i < windows.length; ++i) {
|
||||
windows[i].focus = false;
|
||||
}
|
||||
|
||||
// For the desktop to have active focus
|
||||
desktop.focus = true;
|
||||
desktop.forceActiveFocus();
|
||||
}
|
||||
|
||||
function openBrowserWindow(request, profile) {
|
||||
var component = Qt.createComponent("../Browser.qml");
|
||||
var newWindow = component.createObject(desktop);
|
||||
newWindow.webView.profile = profile;
|
||||
request.openIn(newWindow.webView);
|
||||
}
|
||||
|
||||
FocusHack { id: focusHack; }
|
||||
|
||||
Rectangle {
|
||||
id: focusDebugger;
|
||||
objectName: "focusDebugger"
|
||||
z: 9999; visible: false; color: "red"
|
||||
ColorAnimation on color { from: "#7fffff00"; to: "#7f0000ff"; duration: 1000; loops: 9999 }
|
||||
}
|
||||
|
||||
Action {
|
||||
text: "Toggle Focus Debugger"
|
||||
shortcut: "Ctrl+Shift+F"
|
||||
enabled: DebugQML
|
||||
onTriggered: focusDebugger.visible = !focusDebugger.visible
|
||||
}
|
||||
|
||||
}
|
|
@ -8,8 +8,9 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls 2.3 as QQC2
|
||||
|
||||
import "../dialogs"
|
||||
import "../js/Utils.js" as Utils
|
||||
|
@ -323,6 +324,18 @@ FocusScope {
|
|||
return false;
|
||||
}
|
||||
|
||||
function hideDesktopWindows() {
|
||||
for (var index = 0; index < desktop.visibleChildren.length; index++) {
|
||||
var child = desktop.visibleChildren[index];
|
||||
if (child.topLevelWindow && child.hasOwnProperty("modality")) {
|
||||
var TOOLBAR_NAME = "com.highfidelity.interface.toolbar.system"
|
||||
if (child.objectName !== TOOLBAR_NAME) {
|
||||
child.setShown(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setPinned(newPinned) {
|
||||
pinned = newPinned
|
||||
}
|
||||
|
@ -565,7 +578,7 @@ FocusScope {
|
|||
ColorAnimation on color { from: "#7fffff00"; to: "#7f0000ff"; duration: 1000; loops: 9999 }
|
||||
}
|
||||
|
||||
Action {
|
||||
QQC2.Action {
|
||||
text: "Toggle Focus Debugger"
|
||||
shortcut: "Ctrl+Shift+F"
|
||||
enabled: DebugQML
|
||||
|
|
338
interface/resources/qml/dialogs/+android/CustomQueryDialog.qml
Normal file
338
interface/resources/qml/dialogs/+android/CustomQueryDialog.qml
Normal file
|
@ -0,0 +1,338 @@
|
|||
//
|
||||
// CustomQueryDialog.qml
|
||||
//
|
||||
// Created by Zander Otavka on 7/14/16
|
||||
// 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.7;
|
||||
import QtQuick.Dialogs 1.2 as OriginalDialogs;
|
||||
import QtQuick.Controls 1.4;
|
||||
|
||||
import "../controls-uit";
|
||||
import "../styles-uit";
|
||||
import "../windows";
|
||||
|
||||
ModalWindow {
|
||||
id: root;
|
||||
HifiConstants { id: hifi; }
|
||||
implicitWidth: 640;
|
||||
implicitHeight: 320;
|
||||
visible: true;
|
||||
keyboardOverride: true // Disable ModalWindow's keyboard.
|
||||
|
||||
signal selected(var result);
|
||||
signal canceled();
|
||||
|
||||
property int icon: hifi.icons.none;
|
||||
property string iconText: "";
|
||||
property int iconSize: 35;
|
||||
onIconChanged: updateIcon();
|
||||
|
||||
property var textInput;
|
||||
property var comboBox;
|
||||
property var checkBox;
|
||||
onTextInputChanged: {
|
||||
if (textInput && textInput.text !== undefined) {
|
||||
textField.text = textInput.text;
|
||||
}
|
||||
}
|
||||
onComboBoxChanged: {
|
||||
if (comboBox && comboBox.index !== undefined) {
|
||||
comboBoxField.currentIndex = comboBox.index;
|
||||
}
|
||||
}
|
||||
onCheckBoxChanged: {
|
||||
if (checkBox && checkBox.checked !== undefined) {
|
||||
checkBoxField.checked = checkBox.checked;
|
||||
}
|
||||
}
|
||||
|
||||
property bool keyboardEnabled: false
|
||||
property bool keyboardRaised: false
|
||||
property bool punctuationMode: false
|
||||
onKeyboardRaisedChanged: d.resize();
|
||||
|
||||
property var warning: "";
|
||||
property var result;
|
||||
|
||||
property var implicitCheckState: null;
|
||||
|
||||
property int titleWidth: 0;
|
||||
onTitleWidthChanged: d.resize();
|
||||
|
||||
function updateIcon() {
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
iconText = hifi.glyphForIcon(root.icon);
|
||||
}
|
||||
|
||||
function updateCheckbox() {
|
||||
if (checkBox.disableForItems) {
|
||||
var currentItemInDisableList = false;
|
||||
for (var i in checkBox.disableForItems) {
|
||||
if (comboBoxField.currentIndex === checkBox.disableForItems[i]) {
|
||||
currentItemInDisableList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentItemInDisableList) {
|
||||
checkBoxField.enabled = false;
|
||||
if (checkBox.checkStateOnDisable !== null && checkBox.checkStateOnDisable !== undefined) {
|
||||
root.implicitCheckState = checkBoxField.checked;
|
||||
checkBoxField.checked = checkBox.checkStateOnDisable;
|
||||
}
|
||||
root.warning = checkBox.warningOnDisable;
|
||||
} else {
|
||||
checkBoxField.enabled = true;
|
||||
if (root.implicitCheckState !== null) {
|
||||
checkBoxField.checked = root.implicitCheckState;
|
||||
root.implicitCheckState = null;
|
||||
}
|
||||
root.warning = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
clip: true;
|
||||
width: pane.width;
|
||||
height: pane.height;
|
||||
anchors.margins: 0;
|
||||
|
||||
QtObject {
|
||||
id: d;
|
||||
readonly property int minWidth: 480
|
||||
readonly property int maxWdith: 1280
|
||||
readonly property int minHeight: 120
|
||||
readonly property int maxHeight: 720
|
||||
|
||||
function resize() {
|
||||
var targetWidth = Math.max(titleWidth, pane.width);
|
||||
var targetHeight = (textField.visible ? textField.controlHeight + hifi.dimensions.contentSpacing.y : 0) +
|
||||
(extraInputs.visible ? extraInputs.height + hifi.dimensions.contentSpacing.y : 0) +
|
||||
(buttons.height + 3 * hifi.dimensions.contentSpacing.y) +
|
||||
((keyboardEnabled && keyboardRaised) ? (keyboard.raisedHeight + hifi.dimensions.contentSpacing.y) : 0);
|
||||
|
||||
root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth);
|
||||
root.height = (targetHeight < d.minHeight) ? d.minHeight : ((targetHeight > d.maxHeight) ?
|
||||
d.maxHeight : targetHeight);
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors {
|
||||
top: parent.top;
|
||||
bottom: extraInputs.visible ? extraInputs.top : buttons.top;
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
margins: 0;
|
||||
}
|
||||
|
||||
// FIXME make a text field type that can be bound to a history for autocompletion
|
||||
TextField {
|
||||
id: textField;
|
||||
label: root.textInput.label;
|
||||
focus: root.textInput ? true : false;
|
||||
visible: root.textInput ? true : false;
|
||||
anchors {
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
bottom: keyboard.top;
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y;
|
||||
}
|
||||
}
|
||||
|
||||
Keyboard {
|
||||
id: keyboard
|
||||
raised: keyboardEnabled && keyboardRaised
|
||||
numeric: punctuationMode
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
bottomMargin: raised ? hifi.dimensions.contentSpacing.y : 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: extraInputs;
|
||||
visible: Boolean(root.checkBox || root.comboBox);
|
||||
anchors {
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
bottom: buttons.top;
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y;
|
||||
}
|
||||
height: comboBoxField.controlHeight;
|
||||
onHeightChanged: d.resize();
|
||||
onWidthChanged: d.resize();
|
||||
|
||||
CheckBox {
|
||||
id: checkBoxField;
|
||||
text: root.checkBox.label;
|
||||
focus: Boolean(root.checkBox);
|
||||
visible: Boolean(root.checkBox);
|
||||
anchors {
|
||||
left: parent.left;
|
||||
bottom: parent.bottom;
|
||||
leftMargin: 6; // Magic number to align with warning icon
|
||||
bottomMargin: 6;
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: comboBoxField;
|
||||
label: root.comboBox.label;
|
||||
focus: Boolean(root.comboBox);
|
||||
visible: Boolean(root.comboBox);
|
||||
Binding on x {
|
||||
when: comboBoxField.visible
|
||||
value: !checkBoxField.visible ? buttons.x : acceptButton.x
|
||||
}
|
||||
|
||||
Binding on width {
|
||||
when: comboBoxField.visible
|
||||
value: !checkBoxField.visible ? buttons.width : buttons.width - acceptButton.x
|
||||
}
|
||||
anchors {
|
||||
right: parent.right;
|
||||
bottom: parent.bottom;
|
||||
}
|
||||
model: root.comboBox ? root.comboBox.items : [];
|
||||
onAccepted: {
|
||||
updateCheckbox();
|
||||
focus = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: buttons;
|
||||
focus: true;
|
||||
spacing: hifi.dimensions.contentSpacing.x;
|
||||
layoutDirection: Qt.RightToLeft;
|
||||
onHeightChanged: d.resize();
|
||||
onWidthChanged: {
|
||||
d.resize();
|
||||
resizeWarningText();
|
||||
}
|
||||
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
left: parent.left;
|
||||
right: parent.right;
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y;
|
||||
}
|
||||
|
||||
function resizeWarningText() {
|
||||
var rowWidth = buttons.width;
|
||||
var buttonsWidth = acceptButton.width + cancelButton.width + hifi.dimensions.contentSpacing.x * 2;
|
||||
var warningIconWidth = warningIcon.width + hifi.dimensions.contentSpacing.x;
|
||||
warningText.width = rowWidth - buttonsWidth - warningIconWidth;
|
||||
}
|
||||
|
||||
Button {
|
||||
id: cancelButton;
|
||||
action: cancelAction;
|
||||
}
|
||||
|
||||
Button {
|
||||
id: acceptButton;
|
||||
action: acceptAction;
|
||||
}
|
||||
|
||||
Text {
|
||||
id: warningText;
|
||||
visible: Boolean(root.warning);
|
||||
text: root.warning;
|
||||
wrapMode: Text.WordWrap;
|
||||
font.italic: true;
|
||||
maximumLineCount: 2;
|
||||
}
|
||||
|
||||
HiFiGlyphs {
|
||||
id: warningIcon;
|
||||
visible: Boolean(root.warning);
|
||||
text: hifi.glyphs.alert;
|
||||
size: hifi.dimensions.controlLineHeight;
|
||||
width: 20 // Line up with checkbox.
|
||||
}
|
||||
}
|
||||
|
||||
Action {
|
||||
id: cancelAction;
|
||||
text: qsTr("Cancel");
|
||||
shortcut: "Esc";
|
||||
onTriggered: {
|
||||
root.result = null;
|
||||
root.canceled();
|
||||
// FIXME we are leaking memory to avoid a crash
|
||||
// root.destroy();
|
||||
|
||||
root.disableFade = true
|
||||
visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
Action {
|
||||
id: acceptAction;
|
||||
text: qsTr("Add");
|
||||
shortcut: "Return"
|
||||
onTriggered: {
|
||||
var result = {};
|
||||
if (textInput) {
|
||||
result.textInput = textField.text;
|
||||
}
|
||||
if (comboBox) {
|
||||
result.comboBox = comboBoxField.currentIndex;
|
||||
result.comboBoxText = comboBoxField.currentText;
|
||||
}
|
||||
if (checkBox) {
|
||||
result.checkBox = checkBoxField.enabled ? checkBoxField.checked : null;
|
||||
}
|
||||
root.result = JSON.stringify(result);
|
||||
root.selected(root.result);
|
||||
// FIXME we are leaking memory to avoid a crash
|
||||
// root.destroy();
|
||||
|
||||
root.disableFade = true
|
||||
visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (!visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.key) {
|
||||
case Qt.Key_Escape:
|
||||
case Qt.Key_Back:
|
||||
cancelAction.trigger();
|
||||
event.accepted = true;
|
||||
break;
|
||||
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
acceptAction.trigger();
|
||||
event.accepted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
keyboardEnabled = HMD.active;
|
||||
updateIcon();
|
||||
updateCheckbox();
|
||||
d.resize();
|
||||
textField.forceActiveFocus();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue