mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge remote-tracking branch 'upstream/master' into scriptEngine
This commit is contained in:
commit
b3e9c1e8f8
505 changed files with 332553 additions and 13191 deletions
|
@ -5,6 +5,7 @@ module.exports = {
|
|||
"ecmaVersion": 5
|
||||
},
|
||||
"globals": {
|
||||
"About": false,
|
||||
"Account": false,
|
||||
"Agent": false,
|
||||
"AnimationCache": false,
|
||||
|
|
308
.github/workflows/master_build.yml
vendored
308
.github/workflows/master_build.yml
vendored
|
@ -3,114 +3,60 @@ name: Master CI Build
|
|||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- gha-master-ci
|
||||
# FIXME: Change target branch to "master" before merging into "master" branch.
|
||||
|
||||
env:
|
||||
#APP_NAME: gpu-frame-player
|
||||
APP_NAME: interface
|
||||
BUILD_TYPE: Release
|
||||
BUCKET_NAME: hifi-gh-builds
|
||||
BUILD_NUMBER: ${{ github.run_number }}
|
||||
CI_BUILD: Github
|
||||
CMAKE_BACKTRACE_URL: https://highfidelity.sp.backtrace.io:6098
|
||||
CMAKE_BACKTRACE_TOKEN: ${{ secrets.backtrace_token }}
|
||||
CMAKE_BACKTRACE_SYMBOLS_TOKEN: ${{ secrets.backtrace_symbols_token }}
|
||||
GIT_COMMIT: ${{ github.sha }}
|
||||
HIFI_VCPKG_BOOTSTRAP: true
|
||||
LAUNCHER_HMAC_SECRET: ${{ secrets.launcher_hmac_secret }}
|
||||
OCULUS_APP_ID: '${{ secrets.oculus_app_id }}'
|
||||
# VCPKG did not build well on OSX disabling HIFI_VCPKG_BOOTSTRAP, which invokes a download to a working version of vcpkg
|
||||
# HIFI_VCPKG_BOOTSTRAP: true
|
||||
RELEASE_TYPE: PRODUCTION
|
||||
RELEASE_DYNAMODB_V2: ReleaseManager2-ReleaseQueue-prod
|
||||
RELEASE_NUMBER: ${{ github.run_number }}
|
||||
STABLE_BUILD: 0
|
||||
UPLOAD_BUCKET: athena-public
|
||||
|
||||
|
||||
# OSX specific variables
|
||||
# OSX-specific variables
|
||||
DEVELOPER_DIR: /Applications/Xcode_11.2.app/Contents/Developer
|
||||
MACOSX_DEPLOYMENT_TARGET: '10.11'
|
||||
|
||||
# WIN32 specific variables
|
||||
# WIN-specific variables
|
||||
PreferredToolArchitecture: X64
|
||||
|
||||
# Mac OS
|
||||
#PLATFORM_CMAKE_GENERATOR=Xcode
|
||||
#PLATFORM_BUILD_ARGUMENTS=--config Release --target package
|
||||
#ARTIFACT_EXPRESSION=build/*.dmg,build/*.zip
|
||||
|
||||
# Windows
|
||||
#PLATFORM_CMAKE_GENERATOR=Visual Studio 15 2017 Win64
|
||||
#PLATFORM_BUILD_ARGUMENTS=--target package --config release
|
||||
#ARTIFACT_EXPRESSION=build/*.exe,build/*.zip,*-symbols.zip
|
||||
|
||||
# Ubuntu
|
||||
#PLATFORM_CMAKE_GENERATOR=Unix Makefiles
|
||||
#PLATFORM_BUILD_ARGUMENTS=--target all -- -j4
|
||||
#ARTIFACT_EXPRESSION=build/assignment-client/**,build/domain-server/**,build/ice-server/ice-server,build/tools/ice-client/ice-client,build/tools/ac-client/ac-client,build/tools/oven,build/ext/makefiles/nvtt/project/lib/**,build/ext/makefiles/quazip/project/lib/**
|
||||
|
||||
# Android
|
||||
# branch: master
|
||||
# GA_TRACKING_ID: ${{ secrets.ga_tracking_id }}
|
||||
# ANDROID_OAUTH_CLIENT_SECRET=${MASKED_ANDROID_OAUTH_CLIENT_SECRET_NIGHTLY}
|
||||
# ANDROID_OAUTH_CLIENT_ID=6c7d2349c0614640150db37457a1f75dce98a28ffe8f14d47f6cfae4de5b262a
|
||||
# ANDROID_OAUTH_REDIRECT_URI=https://dev-android-interface.highfidelity.com/auth
|
||||
# branch: !master
|
||||
# GA_TRACKING_ID=UA-39558647-11
|
||||
# ANDROID_OAUTH_CLIENT_SECRET=${MASKED_ANDROID_OAUTH_CLIENT_SECRET_RELEASE}
|
||||
# ANDROID_OAUTH_CLIENT_ID= c1063ea5d0b0c405e0c9cd77351328e211a91496a3f25985a99e861f1661db1d
|
||||
# ANDROID_OAUTH_REDIRECT_URI=https://android-interface.highfidelity.com/auth
|
||||
# ARTIFACT_EXPRESSION=android/*.apk
|
||||
# ANDROID_APK_NAME=HighFidelity-Beta-PR${RELEASE_NUMBER}-${GIT_COMMIT_SHORT}.apk
|
||||
# ANDROID_BUILT_APK_NAME=interface-debug.apk
|
||||
# ANDROID_APP=interface
|
||||
# ANDROID_BUILD_DIR=debug
|
||||
# ANDROID_BUILD_TARGET=assembleDebug
|
||||
# STABLE_BUILD=0
|
||||
|
||||
|
||||
|
||||
jobs:
|
||||
generate_build_number:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Generate build number
|
||||
id: buildnumber
|
||||
uses: highfidelity/build-number@v3
|
||||
with:
|
||||
token: ${{secrets.github_token}}
|
||||
- name: Upload build number
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: BUILD_NUMBER
|
||||
path: BUILD_NUMBER
|
||||
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, macOS-latest]
|
||||
build_type: [full, client]
|
||||
#os: [windows-latest, macOS-latest, ubuntu-latest]
|
||||
# exclude:
|
||||
# - os: ubuntu-latest
|
||||
# build_type: client
|
||||
os: [windows-latest, macOS-latest, ubuntu-18.04]
|
||||
# build_type: [full, client]
|
||||
build_type: [full]
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
build_type: full
|
||||
apt-dependencies: mesa-common-dev libegl1 libglvnd-dev libdouble-conversion1 libpulse0
|
||||
fail-fast: false
|
||||
runs-on: ${{matrix.os}}
|
||||
needs: generate_build_number
|
||||
steps:
|
||||
- name: Download build number
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
name: BUILD_NUMBER
|
||||
- name: Restore build number
|
||||
id: buildnumber
|
||||
uses: highfidelity/build-number@v3
|
||||
with:
|
||||
output_name: RELEASE_NUMBER
|
||||
- name: Configure Build Environment 1
|
||||
- name: Report Build Number
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Build number: $BUILD_NUMBER"
|
||||
- name: Configure build environment 1
|
||||
shell: bash
|
||||
id: buildenv1
|
||||
run: |
|
||||
echo ::set-env name=UPLOAD_PREFIX::master
|
||||
echo ::set-env name=GIT_COMMIT_SHORT::`echo $GIT_COMMIT | cut -c1-7`
|
||||
echo ::set-env name=JOB_NAME::"build (${{matrix.os}}, ${{matrix.build_type}})"
|
||||
# Linux build variables
|
||||
if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then
|
||||
if [[ "${{ matrix.os }}" = "ubuntu-"* ]]; then
|
||||
echo ::set-env name=PYTHON_EXEC::python3
|
||||
echo ::set-env name=INSTALLER_EXT::tgz
|
||||
echo ::set-env name=CMAKE_BUILD_EXTRA::"-- -j3"
|
||||
echo ::set-env name=CMAKE_EXTRA::"-DBUILD_TOOLS:BOOLEAN=FALSE -DHIFI_PYTHON_EXEC:FILEPATH=$(which python3)"
|
||||
fi
|
||||
# Mac build variables
|
||||
if [ "${{ matrix.os }}" = "macOS-latest" ]; then
|
||||
|
@ -118,8 +64,8 @@ jobs:
|
|||
echo ::set-env name=ZIP_COMMAND::zip
|
||||
echo ::set-env name=ZIP_ARGS::-r
|
||||
echo ::set-env name=INSTALLER_EXT::dmg
|
||||
echo ::set-env name=SYMBOL_REGEX::dSYM
|
||||
echo "::set-output name=symbols_archive::${{ steps.buildnumber.outputs.build_number }}-${{ matrix.build_type }}-mac-symbols.zip"
|
||||
echo ::set-env name=CMAKE_EXTRA::"-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=OFF -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -G Xcode"
|
||||
echo "::set-output name=symbols_archive::${BUILD_NUMBER}-${{ matrix.build_type }}-mac-symbols.zip"
|
||||
fi
|
||||
# Windows build variables
|
||||
if [ "${{ matrix.os }}" = "windows-latest" ]; then
|
||||
|
@ -127,40 +73,28 @@ jobs:
|
|||
echo ::set-env name=ZIP_COMMAND::7z
|
||||
echo ::set-env name=ZIP_ARGS::a
|
||||
echo ::set-env name=INSTALLER_EXT::exe
|
||||
echo ::set-env name=CMAKE_EXTRA::"-A x64"
|
||||
echo "::set-env name=SYMBOL_REGEX::\(exe\|dll\|pdb\)"
|
||||
echo "::set-output name=symbols_archive::${{ steps.buildnumber.outputs.build_number }}-${{ matrix.build_type }}-win-symbols.zip"
|
||||
echo "::set-output name=symbols_archive::${BUILD_NUMBER}-${{ matrix.build_type }}-win-symbols.zip"
|
||||
# echo ::set-env name=HF_PFX_PASSPHRASE::${{secrets.pfx_key}}
|
||||
# echo "::set-env name=HF_PFX_FILE::${{runner.workspace}}\build\codesign.pfx"
|
||||
fi
|
||||
# Configuration is broken into two steps because you can't set an env var and also reference it in the same step
|
||||
- name: Configure Build Environment 2
|
||||
- name: Configure build environment 2
|
||||
shell: bash
|
||||
run: |
|
||||
echo "${{ steps.buildenv1.outputs.symbols_archive }}"
|
||||
echo ::set-env name=ARTIFACT_PATTERN::HighFidelity-Beta-*.$INSTALLER_EXT
|
||||
echo ::set-env name=ARTIFACT_PATTERN::Vircadia-Alpha-*.$INSTALLER_EXT
|
||||
# Build type variables
|
||||
if [ "${{ matrix.build_type }}" = "full" ]; then
|
||||
echo ::set-env name=CLIENT_ONLY::FALSE
|
||||
echo ::set-env name=INSTALLER::HighFidelity-Beta-$RELEASE_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT
|
||||
echo ::set-env name=INSTALLER::Vircadia-Alpha-$BUILD_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT
|
||||
else
|
||||
echo ::set-env name=CLIENT_ONLY::TRUE
|
||||
echo ::set-env name=INSTALLER::HighFidelity-Beta-Interface-$RELEASE_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT
|
||||
echo ::set-env name=INSTALLER::Vircadia-Alpha-Interface-$BUILD_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT
|
||||
fi
|
||||
# Linux build variables
|
||||
if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then
|
||||
echo ::set-env name=PYTHON_EXEC::python3
|
||||
echo ::set-env name=CMAKE_EXTRA::""
|
||||
fi
|
||||
# Mac build variables
|
||||
if [ "${{ matrix.os }}" = "macOS-latest" ]; then
|
||||
echo ::set-env name=CMAKE_EXTRA::"-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=OFF -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -G Xcode"
|
||||
fi
|
||||
# Windows build variables
|
||||
if [ "${{ matrix.os }}" = "windows-latest" ]; then
|
||||
echo ::set-env name=CMAKE_EXTRA::"-A x64"
|
||||
echo ::set-env name=HF_PFX_PASSPHRASE::${{secrets.pfx_key}}
|
||||
echo "::set-env name=HF_PFX_FILE::${{runner.workspace}}\build\codesign.pfx"
|
||||
fi
|
||||
- name: Clear Working Directory
|
||||
if: matrix.os == 'windows-latest'
|
||||
- name: Clear working directory
|
||||
if: startsWith(matrix.os, 'windows')
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}
|
||||
run: rm -rf ./*
|
||||
|
@ -168,89 +102,119 @@ jobs:
|
|||
with:
|
||||
submodules: true
|
||||
fetch-depth: 1
|
||||
- name: Create Build Directory
|
||||
run: cmake -E make_directory ${{runner.workspace}}/build
|
||||
- name: Decrypt Signing Key (Windows)
|
||||
if: matrix.os == 'windows-latest'
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
- name: Install dependencies
|
||||
if: startsWith(matrix.os, 'ubuntu')
|
||||
shell: bash
|
||||
run: gpg --batch --yes -o codesign.pfx --passphrase "${{secrets.gpg_symmetric_key}}" --decrypt $GITHUB_WORKSPACE/tools/ci-scripts/codesign.pfx.gpg
|
||||
- name: Import Signing Key (Windows)
|
||||
if: matrix.os == 'windows-latest'
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: powershell
|
||||
run: |
|
||||
$mypwd=ConvertTo-SecureString -String ${{ secrets.pfx_key }} -Force -AsPlainText
|
||||
Import-PfxCertificate -Password $mypwd -CertStoreLocation Cert:\CurrentUser\My -FilePath ${{runner.workspace}}\build\codesign.pfx
|
||||
Import-PfxCertificate -Password $mypwd -CertStoreLocation Cert:\LocalMachine\My -FilePath ${{runner.workspace}}\build\codesign.pfx
|
||||
run: |
|
||||
echo "Installing Python Modules:"
|
||||
pip3 install distro || exit 1
|
||||
echo "Updating apt repository index"
|
||||
sudo apt update || exit 1
|
||||
echo "Installing apt packages"
|
||||
sudo apt install -y ${{ matrix.apt-dependencies }} || exit 1
|
||||
- name: Install Python modules
|
||||
if: matrix.os != 'ubuntu-latest'
|
||||
if: startsWith(matrix.os, 'windows') || startsWith(matrix.os, 'macOS')
|
||||
shell: bash
|
||||
run: $PYTHON_EXEC -m pip install boto3 PyGithub
|
||||
- name: Create build environment
|
||||
shell: bash
|
||||
run: cmake -E make_directory "${{runner.workspace}}/build"
|
||||
- name: Configure CMake
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCLIENT_ONLY:BOOLEAN=$CLIENT_ONLY $CMAKE_EXTRA
|
||||
- name: Build Application
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DVCPKG_BUILD_TYPE=release -DCLIENT_ONLY:BOOLEAN=$CLIENT_ONLY -DBYPASS_SIGNING:BOOLEAN=TRUE $CMAKE_EXTRA
|
||||
- name: Build application
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: cmake --build . --config $BUILD_TYPE --target $APP_NAME
|
||||
- name: Build Console
|
||||
run: cmake --build . --config $BUILD_TYPE --target $APP_NAME $CMAKE_BUILD_EXTRA
|
||||
- name: Build domain server
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: cmake --build . --config $BUILD_TYPE --target packaged-server-console
|
||||
- name: Build Domain Server (FullBuild)
|
||||
if: matrix.build_type == 'full'
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: cmake --build . --config $BUILD_TYPE --target domain-server
|
||||
- name: Build Assignment Client (FullBuild)
|
||||
if: matrix.build_type == 'full'
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: cmake --build . --config $BUILD_TYPE --target assignment-client
|
||||
- name: Build Installer
|
||||
run: cmake --build . --config $BUILD_TYPE --target domain-server $CMAKE_BUILD_EXTRA
|
||||
- name: Build assignment client
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: cmake --build . --config $BUILD_TYPE --target package
|
||||
- name: Sign Installer (Windows)
|
||||
if: matrix.os == 'windows-latest'
|
||||
shell: powershell
|
||||
working-directory: C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64
|
||||
run: .\signtool.exe sign /fd sha256 /f ${{runner.workspace}}\build\codesign.pfx /p ${{secrets.pfx_key}} /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /td SHA256 ${{runner.workspace}}\build\${env:INSTALLER}
|
||||
- name: Upload Artifact
|
||||
if: matrix.os != 'ubuntu-latest'
|
||||
run: cmake --build . --config $BUILD_TYPE --target assignment-client $CMAKE_BUILD_EXTRA
|
||||
- name: Build console
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: cmake --build . --config $BUILD_TYPE --target packaged-server-console $CMAKE_BUILD_EXTRA
|
||||
- name: Build installer
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Retry code from https://unix.stackexchange.com/a/137639"
|
||||
function fail {
|
||||
echo $1 >&2
|
||||
exit 1
|
||||
}
|
||||
function retry {
|
||||
local n=1
|
||||
local max=5
|
||||
local delay=15
|
||||
while true; do
|
||||
"$@" && break || {
|
||||
if [[ $n -lt $max ]]; then
|
||||
((n++))
|
||||
echo "Command failed. Attempt $n/$max:"
|
||||
sleep $delay;
|
||||
else
|
||||
fail "The command has failed after $n attempts."
|
||||
fi
|
||||
}
|
||||
done
|
||||
}
|
||||
retry cmake --build . --config $BUILD_TYPE --target package $CMAKE_BUILD_EXTRA
|
||||
#- name: Sign installer (Windows)
|
||||
# if: startsWith(matrix.os, 'windows')
|
||||
# shell: powershell
|
||||
# working-directory: C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64
|
||||
# run: .\signtool.exe sign /fd sha256 /f ${{runner.workspace}}\build\codesign.pfx /p ${{secrets.pfx_key}} /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /td SHA256 ${{runner.workspace}}\build\${env:INSTALLER}
|
||||
- name: Output system stats
|
||||
if: ${{ always() }}
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Disk usage:"
|
||||
df -h
|
||||
- name: Output installer logs
|
||||
if: failure() && startsWith(matrix.os, 'windows')
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: cat ./_CPack_Packages/win64/NSIS/NSISOutput.log
|
||||
- name: Upload artifact
|
||||
if: startsWith(matrix.os, 'windows') || startsWith(matrix.os, 'macOS')
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.aws_access_key_id }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.aws_secret_access_key }}
|
||||
run: $PYTHON_EXEC $GITHUB_WORKSPACE/tools/ci-scripts/upload.py
|
||||
- name: Archive Symbols
|
||||
if: (matrix.os == 'windows-latest') || (matrix.os == 'macOS-latest')
|
||||
working-directory: ${{runner.workspace}}
|
||||
shell: bash
|
||||
run: |
|
||||
SYMBOLS_TEMP="symbols-temp"
|
||||
mkdir $SYMBOLS_TEMP
|
||||
find "./build" \( -path '*/tools/gpu-frame-player/*' -or -path '*/interface/*' -or -path '*/plugins/*' \) -regex ".*\.$SYMBOL_REGEX" -exec cp -r {} $SYMBOLS_TEMP \;
|
||||
cd $SYMBOLS_TEMP
|
||||
$ZIP_COMMAND $ZIP_ARGS ../${{ steps.buildenv1.outputs.symbols_archive }} .
|
||||
- name: Upload Symbols
|
||||
if: (matrix.os == 'windows-latest') || (matrix.os == 'macOS-latest')
|
||||
working-directory: ${{runner.workspace}}
|
||||
shell: bash
|
||||
run: |
|
||||
curl --data-binary @${{ steps.buildenv1.outputs.symbols_archive }} "$CMAKE_BACKTRACE_URL/post?format=symbols&token=$CMAKE_BACKTRACE_SYMBOLS_TOKEN&upload_file=${{steps.buildenv1.outputs.symbols_archive}}&tag=$RELEASE_NUMBER"
|
||||
# - name: Debug List Symbols
|
||||
# if: (matrix.os == 'windows-latest') || (matrix.os == 'macOS-latest')
|
||||
# working-directory: ${{runner.workspace}}
|
||||
# shell: bash
|
||||
# run: |
|
||||
# unzip -v "${{runner.workspace}}/${{ steps.buildenv1.outputs.symbols_archive }}"
|
||||
# - name: Debug Upload Symbols Artifact
|
||||
# if: (matrix.os == 'windows-latest') || (matrix.os == 'macOS-latest')
|
||||
# uses: actions/upload-artifact@v1
|
||||
# with:
|
||||
# name: symbols
|
||||
# path: ${{runner.workspace}}/${{ steps.buildenv1.outputs.symbols_archive }}
|
||||
#- name: Archive symbols
|
||||
# if: startsWith(matrix.os, 'windows') || startsWith(matrix.os, 'macOS')
|
||||
# working-directory: ${{runner.workspace}}
|
||||
# shell: bash
|
||||
# run: |
|
||||
# SYMBOLS_TEMP="symbols-temp"
|
||||
# mkdir $SYMBOLS_TEMP
|
||||
# find "./build" \( -path '*/tools/gpu-frame-player/*' -or -path '*/interface/*' -or -path '*/plugins/*' \) -regex ".*\.$SYMBOL_REGEX" -exec cp -r {} $SYMBOLS_TEMP \;
|
||||
# cd $SYMBOLS_TEMP
|
||||
# $ZIP_COMMAND $ZIP_ARGS ../${{ steps.buildenv1.outputs.symbols_archive }} .
|
||||
#- name: Upload symbols
|
||||
# if: startsWith(matrix.os, 'windows') || startsWith(matrix.os, 'macOS')
|
||||
# working-directory: ${{runner.workspace}}
|
||||
# shell: bash
|
||||
# run: |
|
||||
# curl --data-binary @${{ steps.buildenv1.outputs.symbols_archive }} "$CMAKE_BACKTRACE_URL/post?format=symbols&token=$CMAKE_BACKTRACE_SYMBOLS_TOKEN&upload_file=${{steps.buildenv1.outputs.symbols_archive}}&tag=$BUILD_NUMBER"
|
||||
#- name: Debug list symbols
|
||||
# if: startsWith(matrix.os, 'windows') || startsWith(matrix.os, 'macOS')
|
||||
# working-directory: ${{runner.workspace}}
|
||||
# shell: bash
|
||||
# run: |
|
||||
# unzip -v "${{runner.workspace}}/${{ steps.buildenv1.outputs.symbols_archive }}"
|
||||
#- name: Upload debug list symbols
|
||||
# if: startsWith(matrix.os, 'windows') || startsWith(matrix.os, 'macOS')
|
||||
# uses: actions/upload-artifact@v1
|
||||
# with:
|
||||
# name: symbols
|
||||
# path: ${{runner.workspace}}/${{ steps.buildenv1.outputs.symbols_archive }}
|
||||
|
|
15
BUILD.md
15
BUILD.md
|
@ -1,6 +1,6 @@
|
|||
# General Build Information
|
||||
|
||||
*Last Updated on June 27, 2020*
|
||||
*Last Updated on August 26, 2020*
|
||||
|
||||
### OS Specific Build Guides
|
||||
|
||||
|
@ -80,12 +80,19 @@ Where /path/to/directory is the path to a directory where you wish the build fil
|
|||
// The type of release.
|
||||
RELEASE_TYPE=PRODUCTION|PR|DEV
|
||||
|
||||
// TODO: What do these do?
|
||||
// The Interface will have a custom default home and startup location.
|
||||
INITIAL_STARTUP_LOCATION=Location/IP/URL
|
||||
|
||||
// Code-signing environment variables must be set during runtime of CMake AND globally when the signing takes place.
|
||||
HF_PFX_FILE=Path to certificate
|
||||
HF_PFX_PASSPHRASE=Passphrase for certificate
|
||||
|
||||
// Determine the build type
|
||||
PRODUCTION_BUILD=0|1
|
||||
PR_BUILD=0|1
|
||||
STABLE_BUILD=0|1
|
||||
|
||||
// TODO: What do these do?
|
||||
// Determine if to utilize testing or stable Metaverse URLs
|
||||
USE_STABLE_GLOBAL_SERVICES=1
|
||||
BUILD_GLOBAL_SERVICES=STABLE
|
||||
|
||||
|
@ -141,6 +148,8 @@ The following build options can be used when running CMake
|
|||
* BUILD_SERVER
|
||||
* BUILD_TESTS
|
||||
* BUILD_TOOLS
|
||||
* CLIENT_ONLY // Will package only the Interface
|
||||
* SERVER_ONLY // Will package only the Server
|
||||
|
||||
#### Developer Build Options
|
||||
|
||||
|
|
24
BUILD_OSX.md
24
BUILD_OSX.md
|
@ -1,6 +1,6 @@
|
|||
# Build OSX
|
||||
|
||||
*Last Updated on July 13, 2020*
|
||||
*Last Updated on August 26, 2020*
|
||||
|
||||
Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only macOS specific instructions are found in this document.
|
||||
|
||||
|
@ -17,7 +17,9 @@ Execute the `Update Shell Profile.command` script that is provided with the inst
|
|||
|
||||
### OSX SDK
|
||||
|
||||
You will need the OSX SDK for building. The easiest way to get this is to install Xcode from the App Store.
|
||||
You will need version `10.12` of the OSX SDK for building, otherwise you may have crashing or other unintended issues due to the deprecation of OpenGL on OSX. You can get that SDK from [here](https://github.com/phracker/MacOSX-SDKs). You must copy it in to your Xcode SDK directory, e.g.
|
||||
|
||||
cp -rp ~/Downloads/MacOSX10.12.sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
|
||||
|
||||
### OpenSSL
|
||||
|
||||
|
@ -28,18 +30,26 @@ For OpenSSL installed via homebrew, set OPENSSL_ROOT_DIR via
|
|||
|
||||
### Xcode
|
||||
|
||||
If Xcode is your editor of choice, you can ask CMake to generate Xcode project files instead of Unix Makefiles. You will need to select the Xcode installation in the terminal first if you have not done so already.
|
||||
You can ask CMake to generate Xcode project files instead of Unix Makefiles using the `-G Xcode` parameter after CMake. You will need to select the Xcode installation in the terminal first if you have not done so already.
|
||||
|
||||
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
|
||||
|
||||
cmake .. -G Xcode
|
||||
|
||||
cmake ../ -DCMAKE_OSX_SYSROOT="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DOSX_SDK=10.12 ..
|
||||
|
||||
If `cmake` complains about Python 3 being missing, you may need to update your CMake binary with command `brew upgrade cmake`, or by downloading and running the latest CMake installer, depending on how you originally instaled CMake
|
||||
|
||||
After running cmake, you will have the make files or Xcode project file necessary to build all of the components. Open the hifi.xcodeproj file, choose ALL_BUILD from the Product > Scheme menu (or target drop down), and click Run.
|
||||
After running CMake, you will have the make files or Xcode project file necessary to build all of the components. Open the hifi.xcodeproj file, choose ALL_BUILD from the Product > Scheme menu (or target drop down), and click Run.
|
||||
|
||||
If the build completes successfully, you will have built targets for all components located in the `build/${target_name}/Debug` directories.
|
||||
|
||||
### make
|
||||
|
||||
If you build with make rather than Xcode, you can append `-j4`for assigning more threads. The number indicates the number of threads, e.g. 4.
|
||||
If you build with make rather than Xcode, you can append `-j4` for assigning more threads. The number indicates the number of threads, e.g. 4.
|
||||
|
||||
To package the installation, you can simply run `make package` afterwards.
|
||||
|
||||
### FAQ
|
||||
|
||||
1. **Problem:** Running the scheme `interface.app` from Xcode causes a crash for Interface related to `libgl`
|
||||
1. **Cause:** The target `gl` generates a binary called `libgl`. A macOS `libGL.framework` item gets loaded instead by Xcode.
|
||||
1. **Solution:** In the Xcode target settings for `libgl`, set the version to 1.0.0
|
||||
|
|
|
@ -120,7 +120,7 @@ else()
|
|||
endif()
|
||||
|
||||
# Use default time server if none defined in environment
|
||||
set_from_env(TIMESERVER_URL TIMESERVER_URL "http://sha256timestamp.ws.symantec.com/sha256/timestamp")
|
||||
set_from_env(TIMESERVER_URL TIMESERVER_URL "http://timestamp.comodoca.com?td=sha256")
|
||||
|
||||
set(HIFI_USE_OPTIMIZED_IK_OPTION OFF)
|
||||
set(BUILD_CLIENT_OPTION ON)
|
||||
|
|
10
INSTALL.md
10
INSTALL.md
|
@ -1,5 +1,7 @@
|
|||
# Creating an Installer
|
||||
|
||||
*Last Updated on August 24, 2020*
|
||||
|
||||
Follow the [build guide](BUILD.md) to figure out how to build Vircadia for your platform.
|
||||
|
||||
During generation, CMake should produce an `install` target and a `package` target.
|
||||
|
@ -13,6 +15,8 @@ To produce an installer, run the `package` target. However you will want to foll
|
|||
|
||||
#### Windows
|
||||
|
||||
##### Prerequisites
|
||||
|
||||
To produce an executable installer on Windows, the following are required:
|
||||
|
||||
1. [7-zip](<https://www.7-zip.org/download.html>)
|
||||
|
@ -59,6 +63,12 @@ To produce an executable installer on Windows, the following are required:
|
|||
1. [Node.JS and NPM](<https://www.npmjs.com/get-npm>)
|
||||
1. Install version 10.15.0 LTS
|
||||
|
||||
##### Code Signing (optional)
|
||||
|
||||
For code signing to work, you will need to set the `HF_PFX_FILE` and `HF_PFX_PASSPHRASE` environment variables to be present during CMake runtime and globally as we proceed to package the installer.
|
||||
|
||||
##### Creating the Installer
|
||||
|
||||
1. Perform a clean cmake from a new terminal.
|
||||
1. Open the `vircadia.sln` solution with elevated (administrator) permissions on Visual Studio and select the **Release** configuration.
|
||||
1. Build the solution.
|
||||
|
|
|
@ -9,7 +9,7 @@ import java.net.URISyntaxException;
|
|||
|
||||
public class HifiUtils {
|
||||
|
||||
public static final String METAVERSE_BASE_URL = "https://metaverse.highfidelity.com";
|
||||
public static final String METAVERSE_BASE_URL = "https://metaverse.vircadia.com/live";
|
||||
|
||||
private static HifiUtils instance;
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ public class LoginFragment extends Fragment
|
|||
|
||||
private final String OAUTH_CLIENT_ID = BuildConfig.OAUTH_CLIENT_ID;
|
||||
private final String OAUTH_REDIRECT_URI = BuildConfig.OAUTH_REDIRECT_URI;
|
||||
private final String OAUTH_AUTHORIZE_BASE_URL = "https://highfidelity.com/oauth/authorize";
|
||||
private final String OAUTH_AUTHORIZE_BASE_URL = "https://metaverse.vircadia.com/live/oauth/authorize";
|
||||
private static final int OAUTH_AUTHORIZE_REQUEST = 1;
|
||||
|
||||
private EditText mUsername;
|
||||
|
@ -222,7 +222,7 @@ public class LoginFragment extends Fragment
|
|||
}
|
||||
|
||||
private void onForgotPasswordClicked() {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://highfidelity.com/users/password/new"));
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://metaverse.vircadia.com/live/users/password/new"));
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import retrofit2.http.Query;
|
|||
|
||||
public class EndpointUsersProvider implements UsersProvider {
|
||||
|
||||
public static final String BASE_URL = "https://metaverse.highfidelity.com/";
|
||||
public static final String BASE_URL = "https://metaverse.vircadia.com/live/";
|
||||
private final Retrofit mRetrofit;
|
||||
private final EndpointUsersProviderService mEndpointUsersProviderService;
|
||||
|
||||
|
@ -154,18 +154,18 @@ public class EndpointUsersProvider implements UsersProvider {
|
|||
}
|
||||
|
||||
public interface EndpointUsersProviderService {
|
||||
@GET("api/v1/users")
|
||||
@GET("/api/v1/users")
|
||||
Call<UsersResponse> getUsers(@Query("filter") String filter,
|
||||
@Query("per_page") int perPage,
|
||||
@Query("online") Boolean online);
|
||||
|
||||
@DELETE("api/v1/user/connections/{connectionUserName}")
|
||||
@DELETE("/api/v1/user/connections/{connectionUserName}")
|
||||
Call<UsersResponse> removeConnection(@Path("connectionUserName") String connectionUserName);
|
||||
|
||||
@DELETE("api/v1/user/friends/{friendUserName}")
|
||||
@DELETE("/api/v1/user/friends/{friendUserName}")
|
||||
Call<UsersResponse> removeFriend(@Path("friendUserName") String friendUserName);
|
||||
|
||||
@POST("api/v1/user/friends")
|
||||
@POST("/api/v1/user/friends")
|
||||
Call<UsersResponse> addFriend(@Body BodyAddFriend friendUserName);
|
||||
|
||||
/* response
|
||||
|
|
|
@ -22,7 +22,7 @@ import retrofit2.http.Query;
|
|||
|
||||
public class UserStoryDomainProvider implements DomainProvider {
|
||||
|
||||
public static final String BASE_URL = "https://metaverse.highfidelity.com/";
|
||||
public static final String BASE_URL = "https://metaverse.vircadia.com/live/";
|
||||
|
||||
private static final String INCLUDE_ACTIONS_FOR_PLACES = "concurrency";
|
||||
private static final String INCLUDE_ACTIONS_FOR_FULL_SEARCH = "concurrency,announcements,snapshot";
|
||||
|
@ -169,7 +169,7 @@ public class UserStoryDomainProvider implements DomainProvider {
|
|||
}
|
||||
|
||||
public interface UserStoryDomainProviderService {
|
||||
@GET("api/v1/user_stories")
|
||||
@GET("/api/v1/user_stories")
|
||||
Call<UserStories> getUserStories(@Query("include_actions") String includeActions,
|
||||
@Query("restriction") String restriction,
|
||||
@Query("require_online") boolean requireOnline,
|
||||
|
|
|
@ -15,8 +15,8 @@ import io.highfidelity.hifiinterface.HifiUtils;
|
|||
* available in an API
|
||||
*/
|
||||
public class DownloadProfileImageTask extends AsyncTask<String, Void, String> {
|
||||
|
||||
private static final String BASE_PROFILE_URL = "https://highfidelity.com";
|
||||
// Note: This should now be available in the API, correct?
|
||||
private static final String BASE_PROFILE_URL = "https://metaverse.vircadia.com/live";
|
||||
private static final String TAG = "Interface";
|
||||
|
||||
private final DownloadProfileImageResultProcessor mResultProcessor;
|
||||
|
|
|
@ -48,7 +48,7 @@ ext {
|
|||
|
||||
def appDir = new File(projectDir, 'apps/interface')
|
||||
def jniFolder = new File(appDir, 'src/main/jniLibs/arm64-v8a')
|
||||
def baseUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/android/'
|
||||
def baseUrl = 'https://cdn-1.vircadia.com/eu-c-1/vircadia-public/dependencies/android/'
|
||||
def breakpadDumpSymsDir = new File("${appDir}/build/tmp/breakpadDumpSyms")
|
||||
|
||||
task extractGvrBinaries() {
|
||||
|
|
|
@ -11,7 +11,7 @@ buildscript {
|
|||
|
||||
|
||||
def file='gvrsdk_v1.101.0.tgz'
|
||||
def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file
|
||||
def url='https://cdn-1.vircadia.com/eu-c-1/vircadia-public/austin/android/' + file
|
||||
def destFile = new File(HIFI_ANDROID_PRECOMPILED, file)
|
||||
|
||||
// FIXME find a way to only download if the file doesn't exist
|
||||
|
|
|
@ -112,11 +112,12 @@ Agent::Agent(ReceivedMessage& message) :
|
|||
|
||||
packetReceiver.registerListenerForTypes(
|
||||
{ PacketType::MixedAudio, PacketType::SilentAudioFrame },
|
||||
this, "handleAudioPacket");
|
||||
PacketReceiver::makeUnsourcedListenerReference<Agent>(this, &Agent::handleAudioPacket));
|
||||
packetReceiver.registerListenerForTypes(
|
||||
{ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase },
|
||||
this, "handleOctreePacket");
|
||||
packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat");
|
||||
PacketReceiver::makeSourcedListenerReference<Agent>(this, &Agent::handleOctreePacket));
|
||||
packetReceiver.registerListener(PacketType::SelectedAudioFormat,
|
||||
PacketReceiver::makeUnsourcedListenerReference<Agent>(this, &Agent::handleSelectedAudioFormat));
|
||||
|
||||
// 100Hz timer for audio
|
||||
const int TARGET_INTERVAL_MSEC = 10; // 10ms
|
||||
|
|
|
@ -118,8 +118,10 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
|
|||
setUpStatusToMonitor();
|
||||
}
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::CreateAssignment, this, "handleCreateAssignmentPacket");
|
||||
packetReceiver.registerListener(PacketType::StopNode, this, "handleStopNodePacket");
|
||||
packetReceiver.registerListener(PacketType::CreateAssignment,
|
||||
PacketReceiver::makeUnsourcedListenerReference<AssignmentClient>(this, &AssignmentClient::handleCreateAssignmentPacket));
|
||||
packetReceiver.registerListener(PacketType::StopNode,
|
||||
PacketReceiver::makeUnsourcedListenerReference<AssignmentClient>(this, &AssignmentClient::handleStopNodePacket));
|
||||
}
|
||||
|
||||
void AssignmentClient::stopAssignmentClient() {
|
||||
|
|
|
@ -183,7 +183,7 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
|
|||
}
|
||||
|
||||
QString assignmentServerHostname;
|
||||
if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) {
|
||||
if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION)) {
|
||||
assignmentServerHostname = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION).toString();
|
||||
}
|
||||
if (parser.isSet(assignmentServerHostnameOption)) {
|
||||
|
@ -192,7 +192,7 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
|
|||
|
||||
// check for an overriden assignment server port
|
||||
quint16 assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT;
|
||||
if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) {
|
||||
if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION)) {
|
||||
assignmentServerPort = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION).toUInt();
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,8 @@ AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmen
|
|||
auto nodeList = DependencyManager::set<LimitedNodeList>(listenPort);
|
||||
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::AssignmentClientStatus, this, "handleChildStatusPacket");
|
||||
packetReceiver.registerListener(PacketType::AssignmentClientStatus,
|
||||
PacketReceiver::makeUnsourcedListenerReference<AssignmentClientMonitor>(this, &AssignmentClientMonitor::handleChildStatusPacket));
|
||||
|
||||
adjustOSResources(std::max(_numAssignmentClientForks, _maxAssignmentClientForks));
|
||||
// use QProcess to fork off a process for each of the child assignment clients
|
||||
|
|
|
@ -308,7 +308,8 @@ AssetServer::AssetServer(ReceivedMessage& message) :
|
|||
|
||||
// Queue all requests until the Asset Server is fully setup
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
packetReceiver.registerListenerForTypes({ PacketType::AssetGet, PacketType::AssetGetInfo, PacketType::AssetUpload, PacketType::AssetMappingOperation }, this, "queueRequests");
|
||||
packetReceiver.registerListenerForTypes({ PacketType::AssetGet, PacketType::AssetGetInfo, PacketType::AssetUpload, PacketType::AssetMappingOperation },
|
||||
PacketReceiver::makeSourcedListenerReference<AssetServer>(this, &AssetServer::queueRequests));
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
updateConsumedCores();
|
||||
|
@ -464,10 +465,14 @@ void AssetServer::completeSetup() {
|
|||
qCDebug(asset_server) << "Overriding temporary queuing packet handler.";
|
||||
// We're fully setup, override the request queueing handler and replay all requests
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::AssetGet, this, "handleAssetGet");
|
||||
packetReceiver.registerListener(PacketType::AssetGetInfo, this, "handleAssetGetInfo");
|
||||
packetReceiver.registerListener(PacketType::AssetUpload, this, "handleAssetUpload");
|
||||
packetReceiver.registerListener(PacketType::AssetMappingOperation, this, "handleAssetMappingOperation");
|
||||
packetReceiver.registerListener(PacketType::AssetGet,
|
||||
PacketReceiver::makeSourcedListenerReference<AssetServer>(this, &AssetServer::handleAssetGet));
|
||||
packetReceiver.registerListener(PacketType::AssetGetInfo,
|
||||
PacketReceiver::makeSourcedListenerReference<AssetServer>(this, &AssetServer::handleAssetGetInfo));
|
||||
packetReceiver.registerListener(PacketType::AssetUpload,
|
||||
PacketReceiver::makeSourcedListenerReference<AssetServer>(this, &AssetServer::handleAssetUpload));
|
||||
packetReceiver.registerListener(PacketType::AssetMappingOperation,
|
||||
PacketReceiver::makeSourcedListenerReference<AssetServer>(this, &AssetServer::handleAssetMappingOperation));
|
||||
|
||||
replayRequests();
|
||||
}
|
||||
|
|
|
@ -101,20 +101,23 @@ AudioMixer::AudioMixer(ReceivedMessage& message) :
|
|||
PacketType::InjectorGainSet,
|
||||
PacketType::AudioSoloRequest,
|
||||
PacketType::StopInjector },
|
||||
this, "queueAudioPacket");
|
||||
PacketReceiver::makeSourcedListenerReference<AudioMixer>(this, &AudioMixer::queueAudioPacket)
|
||||
);
|
||||
|
||||
// packets whose consequences are global should be processed on the main thread
|
||||
packetReceiver.registerListener(PacketType::MuteEnvironment, this, "handleMuteEnvironmentPacket");
|
||||
packetReceiver.registerListener(PacketType::NodeMuteRequest, this, "handleNodeMuteRequestPacket");
|
||||
packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
|
||||
packetReceiver.registerListener(PacketType::MuteEnvironment,
|
||||
PacketReceiver::makeSourcedListenerReference<AudioMixer>(this, &AudioMixer::handleMuteEnvironmentPacket));
|
||||
packetReceiver.registerListener(PacketType::NodeMuteRequest,
|
||||
PacketReceiver::makeSourcedListenerReference<AudioMixer>(this, &AudioMixer::handleNodeMuteRequestPacket));
|
||||
packetReceiver.registerListener(PacketType::KillAvatar,
|
||||
PacketReceiver::makeSourcedListenerReference<AudioMixer>(this, &AudioMixer::handleKillAvatarPacket));
|
||||
|
||||
packetReceiver.registerListenerForTypes({
|
||||
PacketType::ReplicatedMicrophoneAudioNoEcho,
|
||||
PacketType::ReplicatedMicrophoneAudioWithEcho,
|
||||
PacketType::ReplicatedInjectAudio,
|
||||
PacketType::ReplicatedSilentAudioFrame
|
||||
},
|
||||
this, "queueReplicatedAudioPacket"
|
||||
PacketType::ReplicatedSilentAudioFrame },
|
||||
PacketReceiver::makeUnsourcedListenerReference<AudioMixer>(this, &AudioMixer::queueReplicatedAudioPacket)
|
||||
);
|
||||
|
||||
connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled);
|
||||
|
|
|
@ -14,7 +14,10 @@
|
|||
|
||||
#include <queue>
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
// Work around https://bugreports.qt.io/browse/QTBUG-80990
|
||||
#include <tbb/concurrent_vector.h>
|
||||
#endif
|
||||
|
||||
#include <QtCore/QJsonObject>
|
||||
|
||||
|
|
|
@ -12,7 +12,10 @@
|
|||
#ifndef hifi_AudioMixerSlave_h
|
||||
#define hifi_AudioMixerSlave_h
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
// Work around https://bugreports.qt.io/browse/QTBUG-80990
|
||||
#include <tbb/concurrent_vector.h>
|
||||
#endif
|
||||
|
||||
#include <AABox.h>
|
||||
#include <AudioHRTF.h>
|
||||
|
|
|
@ -71,26 +71,38 @@ AvatarMixer::AvatarMixer(ReceivedMessage& message) :
|
|||
connect(DependencyManager::get<NodeList>().data(), &NodeList::nodeKilled, this, &AvatarMixer::handleAvatarKilled);
|
||||
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::AvatarData, this, "queueIncomingPacket");
|
||||
packetReceiver.registerListener(PacketType::AdjustAvatarSorting, this, "handleAdjustAvatarSorting");
|
||||
packetReceiver.registerListener(PacketType::AvatarQuery, this, "handleAvatarQueryPacket");
|
||||
packetReceiver.registerListener(PacketType::AvatarIdentity, this, "handleAvatarIdentityPacket");
|
||||
packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
|
||||
packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket");
|
||||
packetReceiver.registerListener(PacketType::RadiusIgnoreRequest, this, "handleRadiusIgnoreRequestPacket");
|
||||
packetReceiver.registerListener(PacketType::RequestsDomainListData, this, "handleRequestsDomainListDataPacket");
|
||||
packetReceiver.registerListener(PacketType::SetAvatarTraits, this, "queueIncomingPacket");
|
||||
packetReceiver.registerListener(PacketType::BulkAvatarTraitsAck, this, "queueIncomingPacket");
|
||||
packetReceiver.registerListener(PacketType::AvatarData,
|
||||
PacketReceiver::makeSourcedListenerReference<AvatarMixer>(this, &AvatarMixer::queueIncomingPacket));
|
||||
packetReceiver.registerListener(PacketType::AdjustAvatarSorting,
|
||||
PacketReceiver::makeSourcedListenerReference<AvatarMixer>(this, &AvatarMixer::handleAdjustAvatarSorting));
|
||||
packetReceiver.registerListener(PacketType::AvatarQuery,
|
||||
PacketReceiver::makeSourcedListenerReference<AvatarMixer>(this, &AvatarMixer::handleAvatarQueryPacket));
|
||||
packetReceiver.registerListener(PacketType::AvatarIdentity,
|
||||
PacketReceiver::makeSourcedListenerReference<AvatarMixer>(this, &AvatarMixer::handleAvatarIdentityPacket));
|
||||
packetReceiver.registerListener(PacketType::KillAvatar,
|
||||
PacketReceiver::makeSourcedListenerReference<AvatarMixer>(this, &AvatarMixer::handleKillAvatarPacket));
|
||||
packetReceiver.registerListener(PacketType::NodeIgnoreRequest,
|
||||
PacketReceiver::makeSourcedListenerReference<AvatarMixer>(this, &AvatarMixer::handleNodeIgnoreRequestPacket));
|
||||
packetReceiver.registerListener(PacketType::RadiusIgnoreRequest,
|
||||
PacketReceiver::makeSourcedListenerReference<AvatarMixer>(this, &AvatarMixer::handleRadiusIgnoreRequestPacket));
|
||||
packetReceiver.registerListener(PacketType::RequestsDomainListData,
|
||||
PacketReceiver::makeSourcedListenerReference<AvatarMixer>(this, &AvatarMixer::handleRequestsDomainListDataPacket));
|
||||
packetReceiver.registerListener(PacketType::SetAvatarTraits,
|
||||
PacketReceiver::makeSourcedListenerReference<AvatarMixer>(this, &AvatarMixer::queueIncomingPacket));
|
||||
packetReceiver.registerListener(PacketType::BulkAvatarTraitsAck,
|
||||
PacketReceiver::makeSourcedListenerReference<AvatarMixer>(this, &AvatarMixer::queueIncomingPacket));
|
||||
packetReceiver.registerListenerForTypes({ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase },
|
||||
this, "handleOctreePacket");
|
||||
packetReceiver.registerListener(PacketType::ChallengeOwnership, this, "queueIncomingPacket");
|
||||
PacketReceiver::makeSourcedListenerReference<AvatarMixer>(this, &AvatarMixer::handleOctreePacket));
|
||||
packetReceiver.registerListener(PacketType::ChallengeOwnership,
|
||||
PacketReceiver::makeSourcedListenerReference<AvatarMixer>(this, &AvatarMixer::queueIncomingPacket));
|
||||
|
||||
packetReceiver.registerListenerForTypes({
|
||||
PacketType::ReplicatedAvatarIdentity,
|
||||
PacketType::ReplicatedKillAvatar
|
||||
}, this, "handleReplicatedPacket");
|
||||
}, PacketReceiver::makeUnsourcedListenerReference<AvatarMixer>(this, &AvatarMixer::handleReplicatedPacket));
|
||||
|
||||
packetReceiver.registerListener(PacketType::ReplicatedBulkAvatarData, this, "handleReplicatedBulkAvatarPacket");
|
||||
packetReceiver.registerListener(PacketType::ReplicatedBulkAvatarData,
|
||||
PacketReceiver::makeUnsourcedListenerReference<AvatarMixer>(this, &AvatarMixer::handleReplicatedBulkAvatarPacket));
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &AvatarMixer::handlePacketVersionMismatch);
|
||||
|
|
|
@ -59,8 +59,7 @@ EntityServer::EntityServer(ReceivedMessage& message) :
|
|||
PacketType::ChallengeOwnership,
|
||||
PacketType::ChallengeOwnershipRequest,
|
||||
PacketType::ChallengeOwnershipReply },
|
||||
this,
|
||||
"handleEntityPacket");
|
||||
PacketReceiver::makeSourcedListenerReference<EntityServer>(this, &EntityServer::handleEntityPacket));
|
||||
|
||||
connect(&_dynamicDomainVerificationTimer, &QTimer::timeout, this, &EntityServer::startDynamicDomainVerification);
|
||||
_dynamicDomainVerificationTimer.setSingleShot(true);
|
||||
|
|
|
@ -25,9 +25,12 @@ MessagesMixer::MessagesMixer(ReceivedMessage& message) : ThreadedAssignment(mess
|
|||
{
|
||||
connect(DependencyManager::get<NodeList>().data(), &NodeList::nodeKilled, this, &MessagesMixer::nodeKilled);
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::MessagesData, this, "handleMessages");
|
||||
packetReceiver.registerListener(PacketType::MessagesSubscribe, this, "handleMessagesSubscribe");
|
||||
packetReceiver.registerListener(PacketType::MessagesUnsubscribe, this, "handleMessagesUnsubscribe");
|
||||
packetReceiver.registerListener(PacketType::MessagesData,
|
||||
PacketReceiver::makeSourcedListenerReference<MessagesMixer>(this, &MessagesMixer::handleMessages));
|
||||
packetReceiver.registerListener(PacketType::MessagesSubscribe,
|
||||
PacketReceiver::makeSourcedListenerReference<MessagesMixer>(this, &MessagesMixer::handleMessagesSubscribe));
|
||||
packetReceiver.registerListener(PacketType::MessagesUnsubscribe,
|
||||
PacketReceiver::makeSourcedListenerReference<MessagesMixer>(this, &MessagesMixer::handleMessagesUnsubscribe));
|
||||
}
|
||||
|
||||
void MessagesMixer::nodeKilled(SharedNodePointer killedNode) {
|
||||
|
|
|
@ -1122,8 +1122,10 @@ void OctreeServer::run() {
|
|||
|
||||
void OctreeServer::domainSettingsRequestComplete() {
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::OctreeDataNack, this, "handleOctreeDataNackPacket");
|
||||
packetReceiver.registerListener(getMyQueryMessageType(), this, "handleOctreeQueryPacket");
|
||||
packetReceiver.registerListener(PacketType::OctreeDataNack,
|
||||
PacketReceiver::makeSourcedListenerReference<OctreeServer>(this, &OctreeServer::handleOctreeDataNackPacket));
|
||||
packetReceiver.registerListener(getMyQueryMessageType(),
|
||||
PacketReceiver::makeSourcedListenerReference<OctreeServer>(this, &OctreeServer::handleOctreeQueryPacket));
|
||||
|
||||
qDebug(octree_server) << "Received domain settings";
|
||||
|
||||
|
|
|
@ -83,13 +83,18 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig
|
|||
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
packetReceiver.registerListenerForTypes({ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase },
|
||||
this, "handleOctreePacket");
|
||||
packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat");
|
||||
PacketReceiver::makeSourcedListenerReference<EntityScriptServer>(this, &EntityScriptServer::handleOctreePacket));
|
||||
packetReceiver.registerListener(PacketType::SelectedAudioFormat,
|
||||
PacketReceiver::makeUnsourcedListenerReference<EntityScriptServer>(this, &EntityScriptServer::handleSelectedAudioFormat));
|
||||
|
||||
packetReceiver.registerListener(PacketType::ReloadEntityServerScript, this, "handleReloadEntityServerScriptPacket");
|
||||
packetReceiver.registerListener(PacketType::EntityScriptGetStatus, this, "handleEntityScriptGetStatusPacket");
|
||||
packetReceiver.registerListener(PacketType::EntityServerScriptLog, this, "handleEntityServerScriptLogPacket");
|
||||
packetReceiver.registerListener(PacketType::EntityScriptCallMethod, this, "handleEntityScriptCallMethodPacket");
|
||||
packetReceiver.registerListener(PacketType::ReloadEntityServerScript,
|
||||
PacketReceiver::makeSourcedListenerReference<EntityScriptServer>(this, &EntityScriptServer::handleReloadEntityServerScriptPacket));
|
||||
packetReceiver.registerListener(PacketType::EntityScriptGetStatus,
|
||||
PacketReceiver::makeSourcedListenerReference<EntityScriptServer>(this, &EntityScriptServer::handleEntityScriptGetStatusPacket));
|
||||
packetReceiver.registerListener(PacketType::EntityServerScriptLog,
|
||||
PacketReceiver::makeSourcedListenerReference<EntityScriptServer>(this, &EntityScriptServer::handleEntityServerScriptLogPacket));
|
||||
packetReceiver.registerListener(PacketType::EntityScriptCallMethod,
|
||||
PacketReceiver::makeSourcedListenerReference<EntityScriptServer>(this, &EntityScriptServer::handleEntityScriptCallMethodPacket));
|
||||
|
||||
static const int LOG_INTERVAL = MSECS_PER_SECOND / 10;
|
||||
auto timer = new QTimer(this);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,6 +4,7 @@
|
|||
#
|
||||
# Created by Leonardo Murillo on 07/14/2015.
|
||||
# Copyright 2015 High Fidelity, Inc.
|
||||
# Copyright 2020 Vircadia contributors.
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -23,6 +24,7 @@ macro(SET_PACKAGING_PARAMETERS)
|
|||
set_from_env(RELEASE_TYPE RELEASE_TYPE "DEV")
|
||||
set_from_env(RELEASE_NUMBER RELEASE_NUMBER "")
|
||||
set_from_env(STABLE_BUILD STABLE_BUILD 0)
|
||||
set_from_env(INITIAL_STARTUP_LOCATION INITIAL_STARTUP_LOCATION "")
|
||||
|
||||
message(STATUS "The RELEASE_TYPE variable is: ${RELEASE_TYPE}")
|
||||
|
||||
|
@ -174,7 +176,7 @@ macro(SET_PACKAGING_PARAMETERS)
|
|||
set(INTERFACE_SHORTCUT_NAME "Vircadia")
|
||||
set(CONSOLE_SHORTCUT_NAME "Console")
|
||||
set(SANDBOX_SHORTCUT_NAME "Sandbox")
|
||||
set(APP_USER_MODEL_ID "com.highfidelity.console")
|
||||
set(APP_USER_MODEL_ID "com.vircadia.console")
|
||||
else ()
|
||||
set(INTERFACE_SHORTCUT_NAME "Vircadia - ${BUILD_VERSION_NO_SHA}")
|
||||
set(CONSOLE_SHORTCUT_NAME "Console - ${BUILD_VERSION_NO_SHA}")
|
||||
|
|
|
@ -22,11 +22,12 @@ namespace BuildInfo {
|
|||
const QString DOMAIN_SERVER_NAME = "domain-server";
|
||||
const QString AC_CLIENT_SERVER_NAME = "ac-client";
|
||||
const QString MODIFIED_ORGANIZATION = "@BUILD_ORGANIZATION@";
|
||||
const QString ORGANIZATION_DOMAIN = "highfidelity.io";
|
||||
const QString ORGANIZATION_DOMAIN = "vircadia.com";
|
||||
const QString VERSION = "@BUILD_VERSION@";
|
||||
const QString BUILD_NUMBER = "@BUILD_NUMBER@";
|
||||
const QString BUILD_GLOBAL_SERVICES = "@BUILD_GLOBAL_SERVICES@";
|
||||
const QString BUILD_TIME = "@BUILD_TIME@";
|
||||
const QString INITIAL_STARTUP_LOCATION = "@INITIAL_STARTUP_LOCATION@";
|
||||
|
||||
enum BuildType {
|
||||
Dev,
|
||||
|
|
|
@ -2,18 +2,19 @@
|
|||
# CPackProperties.cmake.in
|
||||
# cmake/templates
|
||||
#
|
||||
# Copyright 2016 High Fidelity, Inc.
|
||||
# Created by Stephen Birarda on January 11, 2016
|
||||
# Copyright 2016 High Fidelity, Inc.
|
||||
# Copyright 2020 Vircadia contributors.
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
set(INTERFACE_DISPLAY_NAME "Interface")
|
||||
set(INTERFACE_DISPLAY_NAME "Vircadia")
|
||||
set(INTERFACE_SHORTCUT_NAME "@INTERFACE_SHORTCUT_NAME@")
|
||||
set(INTERFACE_HF_SHORTCUT_NAME "@INTERFACE_HF_SHORTCUT_NAME@")
|
||||
set(INTERFACE_WIN_EXEC_NAME "@INTERFACE_EXEC_PREFIX@.exe")
|
||||
set(CONSOLE_DISPLAY_NAME "Console")
|
||||
set(CONSOLE_DISPLAY_NAME "Vircadia Server Console")
|
||||
set(CONSOLE_INSTALL_SUBDIR "@CONSOLE_INSTALL_DIR@")
|
||||
set(CONSOLE_SHORTCUT_NAME "@CONSOLE_SHORTCUT_NAME@")
|
||||
set(CONSOLE_HF_SHORTCUT_NAME "@CONSOLE_HF_SHORTCUT_NAME@")
|
||||
|
@ -22,9 +23,9 @@ set(SANDBOX_HF_SHORTCUT_NAME "@SANDBOX_HF_SHORTCUT_NAME@")
|
|||
set(CONSOLE_WIN_EXEC_NAME "@CONSOLE_EXEC_NAME@")
|
||||
set(PRE_SANDBOX_INTERFACE_SHORTCUT_NAME "@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@")
|
||||
set(PRE_SANDBOX_CONSOLE_SHORTCUT_NAME "@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@")
|
||||
set(DS_DISPLAY_NAME "Domain Server")
|
||||
set(DS_DISPLAY_NAME "Vircadia Domain Server")
|
||||
set(DS_EXEC_NAME "@DS_EXEC_NAME@")
|
||||
set(AC_DISPLAY_NAME "Assignment Client")
|
||||
set(AC_DISPLAY_NAME "Vircadia Assignment Client")
|
||||
set(AC_EXEC_NAME "@AC_EXEC_NAME@")
|
||||
set(HIGH_FIDELITY_PROTOCOL "@HIGH_FIDELITY_PROTOCOL@")
|
||||
set(HIGH_FIDELITY_APP_PROTOCOL "@HIGH_FIDELITY_APP_PROTOCOL@")
|
||||
|
|
|
@ -199,18 +199,15 @@
|
|||
|
||||
!system "$%TEMP%\tempinstaller.exe" = 2
|
||||
|
||||
; NOTE: We're not code signing right now, so we're going to disable that.
|
||||
; TODO: Get a code signing certificate so we can re-enable code signing.
|
||||
|
||||
; The Inner invocation has written an uninstaller binary for us.
|
||||
; We need to sign it if it's a production or PR build.
|
||||
; !if @PRODUCTION_BUILD@ == 1
|
||||
; !if @BYPASS_SIGNING@ == 1
|
||||
; !warning "BYPASS_SIGNING set - installer will not be signed"
|
||||
; !else
|
||||
; !system '"@SIGNTOOL_EXECUTABLE@" sign /fd sha256 /f %HF_PFX_FILE% /p %HF_PFX_PASSPHRASE% /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /td SHA256 $%TEMP%\@UNINSTALLER_NAME@' = 0
|
||||
; !endif
|
||||
; !endif
|
||||
!if @PRODUCTION_BUILD@ == 1
|
||||
!if @BYPASS_SIGNING@ == TRUE
|
||||
!warning "BYPASS_SIGNING set - installer will not be signed"
|
||||
!else
|
||||
!system '"@SIGNTOOL_EXECUTABLE@" sign /fd sha256 /f %HF_PFX_FILE% /p %HF_PFX_PASSPHRASE% /tr http://timestamp.comodoca.com?td=sha256 /td SHA256 $%TEMP%\@UNINSTALLER_NAME@' = 0
|
||||
!endif
|
||||
!endif
|
||||
|
||||
; Good. Now we can carry on writing the real installer.
|
||||
|
||||
|
@ -639,6 +636,7 @@ Var Express
|
|||
|
||||
; figure out where to download installer slideshow images from
|
||||
StrCpy $0 "http://cdn.highfidelity.com/installer/slideshow"
|
||||
; Is this in use anymore?
|
||||
|
||||
${If} $CampaignName == ""
|
||||
StrCpy $0 "$0/default"
|
||||
|
@ -1303,13 +1301,13 @@ Section "-Core installation"
|
|||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
; handling for server console shortcut
|
||||
Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk"
|
||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_SHORTCUT_NAME@.lnk" \
|
||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_HF_SHORTCUT_NAME@.lnk" \
|
||||
"$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
||||
; Set appUserModelId
|
||||
ApplicationID::Set "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@"
|
||||
ApplicationID::Set "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_HF_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@"
|
||||
${Else}
|
||||
; handling for interface only console shortcut
|
||||
Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_SHORTCUT_NAME@.lnk"
|
||||
Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_HF_SHORTCUT_NAME@.lnk"
|
||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" \
|
||||
"$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
||||
; Set appUserModelId
|
||||
|
@ -1520,7 +1518,7 @@ Section "Uninstall"
|
|||
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\@INTERFACE_SHORTCUT_NAME@.lnk"
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\@CONSOLE_SHORTCUT_NAME@.lnk"
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\@SANDBOX_SHORTCUT_NAME@.lnk"
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\@SANDBOX_HF_SHORTCUT_NAME@.lnk"
|
||||
Delete "$DESKTOP\@INTERFACE_HF_SHORTCUT_NAME@.lnk"
|
||||
Delete "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk"
|
||||
Delete "$DESKTOP\@SANDBOX_HF_SHORTCUT_NAME@.lnk"
|
||||
|
@ -1561,7 +1559,7 @@ Section "Uninstall"
|
|||
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\@INTERFACE_SHORTCUT_NAME@.lnk"
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\@CONSOLE_SHORTCUT_NAME@.lnk"
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\@SANDBOX_SHORTCUT_NAME@.lnk"
|
||||
Delete "$SMPROGRAMS\$MUI_TEMP\@SANDBOX_HF_SHORTCUT_NAME@.lnk"
|
||||
@CPACK_NSIS_DELETE_ICONS_EXTRA@
|
||||
|
||||
;Delete empty start menu parent diretories
|
||||
|
|
2
debian/rules
vendored
2
debian/rules
vendored
|
@ -6,7 +6,7 @@
|
|||
|
||||
override_dh_auto_configure:
|
||||
mkdir obj-$(DEB_TARGET_MULTIARCH)
|
||||
(cd obj-$(DEB_TARGET_MULTIARCH) && cmake .. -DCMAKE_INSTALL_PREFIX=/opt/hifi -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=ON "-GUnix Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCLIENT_ONLY=ON -DDOWNLOAD_SERVERLESS_CONTENT=ON -DCMAKE_CXX_COMPILER=/usr/lib/llvm-7/bin/clang\+\+ -DOpenGL_GL_PREFERENCE=GLVND)
|
||||
(cd obj-$(DEB_TARGET_MULTIARCH) && cmake .. -DCMAKE_INSTALL_PREFIX=/opt/hifi -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=ON "-GUnix Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCLIENT_ONLY=ON -DDOWNLOAD_SERVERLESS_CONTENT=ON -DCMAKE_CXX_COMPILER=/usr/lib/llvm-7/bin/clang\+\+ -DOpenGL_GL_PREFERENCE=LEGACY)
|
||||
|
||||
override_dh_auto_build:
|
||||
(cd obj-$(DEB_TARGET_MULTIARCH) && make -j4)
|
||||
|
|
|
@ -8,20 +8,20 @@
|
|||
{
|
||||
"name": "access_token",
|
||||
"label": "Access Token",
|
||||
"help": "This is your OAuth access token to connect this domain-server with your High Fidelity account. <br/>It can be generated by clicking the 'Connect Account' button above.<br/>You can also go to the <a href='https://metaverse.highfidelity.com/user/security' target='_blank'>My Security</a> page of your account and generate a token with the 'domains' scope and paste it here.",
|
||||
"help": "This is your OAuth access token to connect this domain-server with your Metaverse account. <br/>It can be generated by clicking the 'Connect Account' button above.<br/>You can also go to the Security page of your account on your Metaverse Server and generate a token with the 'domains' scope and paste it here.",
|
||||
"advanced": true,
|
||||
"backup": false
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
"label": "Domain ID",
|
||||
"help": "This is your High Fidelity domain ID. If you do not want your domain to be registered in the High Fidelity metaverse you can leave this blank.",
|
||||
"help": "This is your Metaverse domain ID. If you do not want your domain to be registered in the Metaverse you can leave this blank.",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "automatic_networking",
|
||||
"label": "Automatic Networking",
|
||||
"help": "This defines how other nodes in the High Fidelity metaverse will be able to reach your domain-server.<br/>If you don't want to deal with any network settings, use full automatic networking.",
|
||||
"help": "This defines how other nodes in the Metaverse will be able to reach your domain-server.<br/>If you don't want to deal with any network settings, use full automatic networking.",
|
||||
"default": "disabled",
|
||||
"type": "select",
|
||||
"options": [
|
||||
|
@ -35,7 +35,7 @@
|
|||
},
|
||||
{
|
||||
"value": "disabled",
|
||||
"label": "None: use the network information I have entered for this domain at metaverse.highfidelity.com"
|
||||
"label": "None: use the network information I have entered for this domain at in the Metaverse Server."
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -50,10 +50,26 @@
|
|||
{
|
||||
"name": "enable_packet_verification",
|
||||
"label": "Enable Packet Verification",
|
||||
"help": "Enable secure checksums on communication that uses the High Fidelity protocol. Increases security with possibly a small performance penalty.",
|
||||
"help": "Enable secure checksums on communication that uses the Metaverse protocol. Increases security with possibly a small performance penalty.",
|
||||
"default": true,
|
||||
"type": "checkbox",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "enable_metadata_exporter",
|
||||
"label": "Enable Metadata HTTP Availability",
|
||||
"help": "Allows your domain's metadata to be accessible on the public internet via direct HTTP connection to the domain server.",
|
||||
"default": true,
|
||||
"type": "checkbox",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
"name": "metadata_exporter_port",
|
||||
"label": "Metadata Exporter HTTP Port",
|
||||
"help": "This is the port where the Metaverse exporter accepts connections. It listens both on IPv4 and IPv6 and can be accessed remotely, so you should make sure to restrict access with a firewall as needed.",
|
||||
"default": "9704",
|
||||
"type": "int",
|
||||
"advanced": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -98,7 +114,7 @@
|
|||
{
|
||||
"name": "enable_prometheus_exporter",
|
||||
"label": "Enable Prometheus Exporter",
|
||||
"help": "Enable a Prometheus exporter to make it possible to gather the stats that are available at <a href='/'>Nodes</a> tab with a <a href='https://prometheus.io/'>Prometheus</a> server. This makes it possible to keep track of long-term domain statistics for graphing, troubleshooting, and performance monitoring.",
|
||||
"help": "Enable a Prometheus exporter to make it possible to gather stats about the mixers that are available in the <a href='/'>Nodes</a> tab with a <a href='https://prometheus.io/'>Prometheus</a> server. This makes it possible to keep track of long-term domain statistics for graphing, troubleshooting, and performance monitoring.",
|
||||
"default": false,
|
||||
"type": "checkbox",
|
||||
"advanced": true
|
||||
|
@ -144,14 +160,42 @@
|
|||
"name": "descriptors",
|
||||
"label": "Description",
|
||||
"restart": false,
|
||||
"help": "This data will be queryable from your server. It may be collected by High Fidelity and used to share your domain with others.",
|
||||
"help": "This data will be queryable from your server. It may be collected by the Metaverse and used to share your domain with others.",
|
||||
"settings": [
|
||||
{
|
||||
"name": "world_name",
|
||||
"label": "Name",
|
||||
"advanced": true,
|
||||
"help": "The name of your domain (256 character limit)."
|
||||
},
|
||||
{
|
||||
"name": "description",
|
||||
"label": "Description",
|
||||
"advanced": true,
|
||||
"help": "A description of your domain (256 character limit)."
|
||||
},
|
||||
{
|
||||
"name": "thumbnail",
|
||||
"label": "World Thumbnail",
|
||||
"advanced": true,
|
||||
"help": "A link to the thumbnail that is publicly accessible from the internet."
|
||||
},
|
||||
{
|
||||
"name": "images",
|
||||
"label": "World Images",
|
||||
"advanced": true,
|
||||
"type": "table",
|
||||
"can_add_new_rows": true,
|
||||
"help": "URLs to images that visually describe your world to potential visitors.",
|
||||
"numbered": false,
|
||||
"columns": [
|
||||
{
|
||||
"name": "image",
|
||||
"label": "Image URL",
|
||||
"can_set": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "maturity",
|
||||
"label": "Maturity",
|
||||
|
@ -183,16 +227,22 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"name": "hosts",
|
||||
"label": "Hosts",
|
||||
"name": "contact_info",
|
||||
"label": "World Administrative Contact",
|
||||
"advanced": true,
|
||||
"help": "Contact information to reach server administrators for assistance (256 character limit)."
|
||||
},
|
||||
{
|
||||
"name": "managers",
|
||||
"label": "World Managers / Administrators",
|
||||
"advanced": true,
|
||||
"type": "table",
|
||||
"can_add_new_rows": true,
|
||||
"help": "Usernames of hosts who can reliably show your domain to new visitors.",
|
||||
"help": "Usernames of managers that administrate the domain.",
|
||||
"numbered": false,
|
||||
"columns": [
|
||||
{
|
||||
"name": "host",
|
||||
"name": "manager",
|
||||
"label": "Username",
|
||||
"can_set": true
|
||||
}
|
||||
|
@ -243,6 +293,14 @@
|
|||
"help": "Must match the password entered above for change to be saved.",
|
||||
"value-hidden": true
|
||||
},
|
||||
{
|
||||
"name": "approved_safe_urls",
|
||||
"label": "Approved Script and QML URLs",
|
||||
"help": "These URLs will be sent to the Interface as safe URLs to allow through the whitelist if the Interface has this security option enabled.",
|
||||
"placeholder": "0",
|
||||
"default": "1",
|
||||
"advanced": false
|
||||
},
|
||||
{
|
||||
"name": "maximum_user_capacity",
|
||||
"label": "Maximum User Capacity",
|
||||
|
@ -1830,7 +1888,7 @@
|
|||
"name": "provider",
|
||||
"label": "Provider",
|
||||
"help": "OAuth provider URL.",
|
||||
"default": "https://metaverse.highfidelity.com",
|
||||
"default": "https://metaverse.vircadia.com/live",
|
||||
"advanced": true,
|
||||
"backup": false
|
||||
},
|
||||
|
|
26
domain-server/resources/metadata_exporter/index.html
Normal file
26
domain-server/resources/metadata_exporter/index.html
Normal file
|
@ -0,0 +1,26 @@
|
|||
<!--
|
||||
//
|
||||
// index.html
|
||||
//
|
||||
// Created by kasenvr@gmail.com on 21 Jul 2020
|
||||
// Copyright 2020 Vircadia and contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Vircadia Metadata Exporter</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Vircadia Metadata Exporter</h1>
|
||||
|
||||
<p>If you can see this page, this means that your domain's metadata is available to be exported.</p>
|
||||
<p>
|
||||
<a href="/metadata">Metadata</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
|
@ -1,3 +1,3 @@
|
|||
// Here you can put a script that will be run by an assignment-client (AC)
|
||||
// For examples, please go to https://github.com/highfidelity/hifi/tree/master/script-archive/acScripts
|
||||
// For examples, please go to https://github.com/kasenvr/project-athena/tree/master/script-archive/acScripts
|
||||
// The directory named acScripts contains assignment-client specific scripts you can try.
|
||||
|
|
|
@ -51,9 +51,9 @@ $.extend(Settings, {
|
|||
var URLs = {
|
||||
// STABLE METAVERSE_URL: https://metaverse.highfidelity.com
|
||||
// STAGING METAVERSE_URL: https://staging.highfidelity.com
|
||||
METAVERSE_URL: 'https://metaverse.highfidelity.com',
|
||||
CDN_URL: 'https://cdn.highfidelity.com',
|
||||
PLACE_URL: 'https://hifi.place',
|
||||
DEFAULT_METAVERSE_URL: "https://metaverse.vircadia.com/live",
|
||||
CDN_URL: 'https://cdn-1.vircadia.com/eu-c-1',
|
||||
PLACE_URL: 'https://xr.place'
|
||||
};
|
||||
|
||||
var Strings = {
|
||||
|
@ -61,7 +61,7 @@ var Strings = {
|
|||
|
||||
CHOOSE_DOMAIN_BUTTON: "Choose from my domains",
|
||||
CREATE_DOMAIN_BUTTON: "Create new domain ID",
|
||||
CREATE_DOMAIN_SUCCESS_JUST_CONNECTED: "We connnected your High Fidelity account and created a new domain ID for this machine.",
|
||||
CREATE_DOMAIN_SUCCESS_JUST_CONNECTED: "We connnected your Metaverse account and created a new domain ID for this machine.",
|
||||
CREATE_DOMAIN_SUCCESS: "We created a new domain ID for this machine.",
|
||||
|
||||
// When a place modification fails, they will be brought back to the previous
|
||||
|
@ -92,7 +92,7 @@ var Strings = {
|
|||
ADD_PLACE_LOADING_DIALOG: "Loading your places...",
|
||||
|
||||
ADD_PLACE_NOT_CONNECTED_TITLE: "Access token required",
|
||||
ADD_PLACE_NOT_CONNECTED_MESSAGE: "You must have an access token to query your High Fidelity places.<br><br>Please follow the instructions on the settings page to add an access token.",
|
||||
ADD_PLACE_NOT_CONNECTED_MESSAGE: "You must have an access token to query your Metaverse places.<br><br>Please follow the instructions on the settings page to add an access token.",
|
||||
};
|
||||
|
||||
var DOMAIN_ID_TYPE_NONE = 0;
|
||||
|
@ -228,215 +228,214 @@ function getDomainFromAPI(callback) {
|
|||
return pendingDomainRequest;
|
||||
}
|
||||
|
||||
function chooseFromHighFidelityPlaces(accessToken, forcePathTo, onSuccessfullyAdded) {
|
||||
function chooseFromMetaversePlaces(accessToken, forcePathTo, onSuccessfullyAdded) {
|
||||
if (accessToken) {
|
||||
getMetaverseUrl(function(metaverse_url) {
|
||||
|
||||
var loadingDialog = showLoadingDialog(Strings.ADD_PLACE_LOADING_DIALOG);
|
||||
var loadingDialog = showLoadingDialog(Strings.ADD_PLACE_LOADING_DIALOG);
|
||||
|
||||
function loadPlaces() {
|
||||
$.ajax("/api/places", {
|
||||
dataType: 'json',
|
||||
jsonp: false,
|
||||
success: function(data) {
|
||||
if (data.status == 'success') {
|
||||
var modal_buttons = {
|
||||
cancel: {
|
||||
label: Strings.ADD_PLACE_CANCEL_BUTTON,
|
||||
className: 'add-place-cancel-button btn-default'
|
||||
}
|
||||
};
|
||||
|
||||
var dialog;
|
||||
var modal_body;
|
||||
|
||||
if (data.data.places.length) {
|
||||
var places_by_id = {};
|
||||
|
||||
modal_body = $('<div>');
|
||||
|
||||
modal_body.append($("<p>Choose a place name that you own or <a href='" + URLs.METAVERSE_URL + "/user/places' target='_blank'>register a new place name</a></p>"));
|
||||
|
||||
var currentDomainIDType = getCurrentDomainIDType();
|
||||
if (currentDomainIDType === DOMAIN_ID_TYPE_TEMP) {
|
||||
var warning = "<div class='domain-loading-error alert alert-warning'>";
|
||||
warning += "If you choose a place name it will replace your current temporary place name.";
|
||||
warning += "</div>";
|
||||
modal_body.append(warning);
|
||||
}
|
||||
|
||||
// setup a select box for the returned places
|
||||
modal_body.append($("<label for='place-name-select'>Places</label>"));
|
||||
place_select = $("<select id='place-name-select' class='form-control'></select>");
|
||||
_.each(data.data.places, function(place) {
|
||||
places_by_id[place.id] = place;
|
||||
place_select.append("<option value='" + place.id + "'>" + place.name + "</option>");
|
||||
})
|
||||
modal_body.append(place_select);
|
||||
modal_body.append($("<p id='place-name-warning' class='warning-text' style='display: none'>This place name already points to a place or path. Saving this would overwrite the previous settings associated with it.</p>"));
|
||||
|
||||
if (forcePathTo === undefined || forcePathTo === null) {
|
||||
var path = "<div class='form-group'>";
|
||||
path += "<label for='place-path-input' class='control-label'>Path or Viewpoint</label>";
|
||||
path += "<input type='text' id='place-path-input' class='form-control' value='/'>";
|
||||
path += "</div>";
|
||||
modal_body.append($(path));
|
||||
}
|
||||
|
||||
var place_select = modal_body.find("#place-name-select")
|
||||
place_select.change(function(ev) {
|
||||
var warning = modal_body.find("#place-name-warning");
|
||||
var place = places_by_id[$(this).val()];
|
||||
if (place === undefined || place.pointee === null) {
|
||||
warning.hide();
|
||||
} else {
|
||||
warning.show();
|
||||
function loadPlaces() {
|
||||
$.ajax("/api/places", {
|
||||
dataType: 'json',
|
||||
jsonp: false,
|
||||
success: function(data) {
|
||||
if (data.status == 'success') {
|
||||
var modal_buttons = {
|
||||
cancel: {
|
||||
label: Strings.ADD_PLACE_CANCEL_BUTTON,
|
||||
className: 'add-place-cancel-button btn-default'
|
||||
}
|
||||
});
|
||||
place_select.trigger('change');
|
||||
};
|
||||
|
||||
modal_buttons["success"] = {
|
||||
label: Strings.ADD_PLACE_CONFIRM_BUTTON,
|
||||
className: 'add-place-confirm-button btn btn-primary',
|
||||
callback: function() {
|
||||
var placeID = $('#place-name-select').val();
|
||||
// set the place ID on the form
|
||||
$(Settings.place_ID_SELECTOR).val(placeID).change();
|
||||
var dialog;
|
||||
var modal_body;
|
||||
if (data.data.places.length) {
|
||||
var places_by_id = {};
|
||||
|
||||
if (forcePathTo === undefined || forcePathTo === null) {
|
||||
var placePath = $('#place-path-input').val();
|
||||
modal_body = $('<div>');
|
||||
|
||||
modal_body.append($("<p>Choose a place name that you own or <a href='" + metaverse_url + "/user/places' target='_blank'>register a new place name</a></p>"));
|
||||
|
||||
var currentDomainIDType = getCurrentDomainIDType();
|
||||
if (currentDomainIDType === DOMAIN_ID_TYPE_TEMP) {
|
||||
var warning = "<div class='domain-loading-error alert alert-warning'>";
|
||||
warning += "If you choose a place name it will replace your current temporary place name.";
|
||||
warning += "</div>";
|
||||
modal_body.append(warning);
|
||||
}
|
||||
|
||||
// setup a select box for the returned places
|
||||
modal_body.append($("<label for='place-name-select'>Places</label>"));
|
||||
place_select = $("<select id='place-name-select' class='form-control'></select>");
|
||||
_.each(data.data.places, function(place) {
|
||||
places_by_id[place.id] = place;
|
||||
place_select.append("<option value='" + place.id + "'>" + place.name + "</option>");
|
||||
})
|
||||
modal_body.append(place_select);
|
||||
modal_body.append($("<p id='place-name-warning' class='warning-text' style='display: none'>This place name already points to a place or path. Saving this would overwrite the previous settings associated with it.</p>"));
|
||||
|
||||
if (forcePathTo === undefined || forcePathTo === null) {
|
||||
var path = "<div class='form-group'>";
|
||||
path += "<label for='place-path-input' class='control-label'>Path or Viewpoint</label>";
|
||||
path += "<input type='text' id='place-path-input' class='form-control' value='/'>";
|
||||
path += "</div>";
|
||||
modal_body.append($(path));
|
||||
}
|
||||
|
||||
var place_select = modal_body.find("#place-name-select")
|
||||
place_select.change(function(ev) {
|
||||
var warning = modal_body.find("#place-name-warning");
|
||||
var place = places_by_id[$(this).val()];
|
||||
if (place === undefined || place.pointee === null) {
|
||||
warning.hide();
|
||||
} else {
|
||||
var placePath = forcePathTo;
|
||||
warning.show();
|
||||
}
|
||||
});
|
||||
place_select.trigger('change');
|
||||
|
||||
$('.add-place-confirm-button').attr('disabled', 'disabled');
|
||||
$('.add-place-confirm-button').html(Strings.ADD_PLACE_CONFIRM_BUTTON_PENDING);
|
||||
$('.add-place-cancel-button').attr('disabled', 'disabled');
|
||||
modal_buttons["success"] = {
|
||||
label: Strings.ADD_PLACE_CONFIRM_BUTTON,
|
||||
className: 'add-place-confirm-button btn btn-primary',
|
||||
callback: function() {
|
||||
var placeID = $('#place-name-select').val();
|
||||
// set the place ID on the form
|
||||
$(Settings.place_ID_SELECTOR).val(placeID).change();
|
||||
|
||||
function finalizeSaveDomainID(domainID) {
|
||||
var jsonSettings = {
|
||||
metaverse: {
|
||||
id: domainID
|
||||
}
|
||||
}
|
||||
var dialog = showLoadingDialog("Waiting for Domain Server to restart...");
|
||||
$.ajax('/settings.json', {
|
||||
data: JSON.stringify(jsonSettings),
|
||||
contentType: 'application/json',
|
||||
type: 'POST'
|
||||
}).done(function(data) {
|
||||
if (data.status == "success") {
|
||||
waitForDomainServerRestart(function() {
|
||||
dialog.modal('hide');
|
||||
if (onSuccessfullyAdded) {
|
||||
onSuccessfullyAdded(places_by_id[placeID].name, domainID);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
bootbox.alert("Failed to add place");
|
||||
}
|
||||
}).fail(function() {
|
||||
bootbox.alert("Failed to add place");
|
||||
});
|
||||
}
|
||||
|
||||
// If domainID is not specified, the current domain id will be used.
|
||||
function finishSettingUpPlace(domainID) {
|
||||
sendUpdatePlaceRequest(
|
||||
placeID,
|
||||
placePath,
|
||||
domainID,
|
||||
false,
|
||||
function(data) {
|
||||
dialog.modal('hide')
|
||||
if (domainID) {
|
||||
$(Settings.DOMAIN_ID_SELECTOR).val(domainID).change();
|
||||
finalizeSaveDomainID(domainID);
|
||||
} else {
|
||||
if (onSuccessfullyAdded) {
|
||||
onSuccessfullyAdded(places_by_id[placeID].name);
|
||||
}
|
||||
}
|
||||
},
|
||||
function(data) {
|
||||
$('.add-place-confirm-button').removeAttr('disabled');
|
||||
$('.add-place-confirm-button').html(Strings.ADD_PLACE_CONFIRM_BUTTON);
|
||||
$('.add-place-cancel-button').removeAttr('disabled');
|
||||
bootbox.alert(Strings.ADD_PLACE_UNKNOWN_ERROR);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function maybeCreateNewDomainID() {
|
||||
console.log("Maybe creating domain id", currentDomainIDType)
|
||||
if (currentDomainIDType === DOMAIN_ID_TYPE_FULL) {
|
||||
finishSettingUpPlace();
|
||||
if (forcePathTo === undefined || forcePathTo === null) {
|
||||
var placePath = $('#place-path-input').val();
|
||||
} else {
|
||||
sendCreateDomainRequest(function(domainID) {
|
||||
console.log("Created domain", domainID);
|
||||
finishSettingUpPlace(domainID);
|
||||
}, function() {
|
||||
$('.add-place-confirm-button').removeAttr('disabled');
|
||||
$('.add-place-confirm-button').html(Strings.ADD_PLACE_CONFIRM_BUTTON);
|
||||
$('.add-place-cancel-button').removeAttr('disabled');
|
||||
bootbox.alert(Strings.ADD_PLACE_UNKNOWN_ERROR);
|
||||
var placePath = forcePathTo;
|
||||
}
|
||||
|
||||
$('.add-place-confirm-button').attr('disabled', 'disabled');
|
||||
$('.add-place-confirm-button').html(Strings.ADD_PLACE_CONFIRM_BUTTON_PENDING);
|
||||
$('.add-place-cancel-button').attr('disabled', 'disabled');
|
||||
|
||||
function finalizeSaveDomainID(domainID) {
|
||||
var jsonSettings = {
|
||||
metaverse: {
|
||||
id: domainID
|
||||
}
|
||||
}
|
||||
var dialog = showLoadingDialog("Waiting for Domain Server to restart...");
|
||||
$.ajax('/settings.json', {
|
||||
data: JSON.stringify(jsonSettings),
|
||||
contentType: 'application/json',
|
||||
type: 'POST'
|
||||
}).done(function(data) {
|
||||
if (data.status == "success") {
|
||||
waitForDomainServerRestart(function() {
|
||||
dialog.modal('hide');
|
||||
if (onSuccessfullyAdded) {
|
||||
onSuccessfullyAdded(places_by_id[placeID].name, domainID);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
bootbox.alert("Failed to add place");
|
||||
}
|
||||
}).fail(function() {
|
||||
bootbox.alert("Failed to add place");
|
||||
});
|
||||
}
|
||||
|
||||
// If domainID is not specified, the current domain id will be used.
|
||||
function finishSettingUpPlace(domainID) {
|
||||
sendUpdatePlaceRequest(
|
||||
placeID,
|
||||
placePath,
|
||||
domainID,
|
||||
false,
|
||||
function(data) {
|
||||
dialog.modal('hide')
|
||||
if (domainID) {
|
||||
$(Settings.DOMAIN_ID_SELECTOR).val(domainID).change();
|
||||
finalizeSaveDomainID(domainID);
|
||||
} else {
|
||||
if (onSuccessfullyAdded) {
|
||||
onSuccessfullyAdded(places_by_id[placeID].name);
|
||||
}
|
||||
}
|
||||
},
|
||||
function(data) {
|
||||
$('.add-place-confirm-button').removeAttr('disabled');
|
||||
$('.add-place-confirm-button').html(Strings.ADD_PLACE_CONFIRM_BUTTON);
|
||||
$('.add-place-cancel-button').removeAttr('disabled');
|
||||
bootbox.alert(Strings.ADD_PLACE_UNKNOWN_ERROR);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function maybeCreateNewDomainID() {
|
||||
console.log("Maybe creating domain id", currentDomainIDType)
|
||||
if (currentDomainIDType === DOMAIN_ID_TYPE_FULL) {
|
||||
finishSettingUpPlace();
|
||||
} else {
|
||||
sendCreateDomainRequest(function(domainID) {
|
||||
console.log("Created domain", domainID);
|
||||
finishSettingUpPlace(domainID);
|
||||
}, function() {
|
||||
$('.add-place-confirm-button').removeAttr('disabled');
|
||||
$('.add-place-confirm-button').html(Strings.ADD_PLACE_CONFIRM_BUTTON);
|
||||
$('.add-place-cancel-button').removeAttr('disabled');
|
||||
bootbox.alert(Strings.ADD_PLACE_UNKNOWN_ERROR);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
maybeCreateNewDomainID();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
maybeCreateNewDomainID();
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
modal_buttons["success"] = {
|
||||
label: Strings.ADD_PLACE_NO_PLACES_BUTTON,
|
||||
callback: function() {
|
||||
window.open(metaverse_url + "/user/places", '_blank');
|
||||
}
|
||||
}
|
||||
modal_body = Strings.ADD_PLACE_NO_PLACES_MESSAGE;
|
||||
}
|
||||
dialog = bootbox.dialog({
|
||||
title: Strings.ADD_PLACE_TITLE,
|
||||
message: modal_body,
|
||||
closeButton: false,
|
||||
buttons: modal_buttons,
|
||||
onEscape: true
|
||||
});
|
||||
} else {
|
||||
modal_buttons["success"] = {
|
||||
label: Strings.ADD_PLACE_NO_PLACES_BUTTON,
|
||||
callback: function() {
|
||||
window.open(URLs.METAVERSE_URL + "/user/places", '_blank');
|
||||
}
|
||||
}
|
||||
modal_body = Strings.ADD_PLACE_NO_PLACES_MESSAGE;
|
||||
bootbox.alert(Strings.ADD_PLACE_UNABLE_TO_LOAD_ERROR);
|
||||
}
|
||||
|
||||
dialog = bootbox.dialog({
|
||||
title: Strings.ADD_PLACE_TITLE,
|
||||
message: modal_body,
|
||||
closeButton: false,
|
||||
buttons: modal_buttons,
|
||||
onEscape: true
|
||||
});
|
||||
} else {
|
||||
},
|
||||
error: function() {
|
||||
bootbox.alert(Strings.ADD_PLACE_UNABLE_TO_LOAD_ERROR);
|
||||
},
|
||||
complete: function() {
|
||||
loadingDialog.modal('hide');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
bootbox.alert(Strings.ADD_PLACE_UNABLE_TO_LOAD_ERROR);
|
||||
},
|
||||
complete: function() {
|
||||
loadingDialog.modal('hide');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var domainType = getCurrentDomainIDType();
|
||||
if (domainType !== DOMAIN_ID_TYPE_UNKNOWN) {
|
||||
loadPlaces();
|
||||
} else {
|
||||
getDomainFromAPI(function(data) {
|
||||
if (data.status === 'success') {
|
||||
var domainType = getCurrentDomainIDType();
|
||||
loadPlaces();
|
||||
} else {
|
||||
loadingDialog.modal('hide');
|
||||
bootbox.confirm("We were not able to load your domain information from the Metaverse. Would you like to retry?", function(response) {
|
||||
if (response) {
|
||||
chooseFromHighFidelityPlaces(accessToken, forcePathTo, onSuccessfullyAdded);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var domainType = getCurrentDomainIDType();
|
||||
if (domainType !== DOMAIN_ID_TYPE_UNKNOWN) {
|
||||
loadPlaces();
|
||||
} else {
|
||||
getDomainFromAPI(function(data) {
|
||||
if (data.status === 'success') {
|
||||
var domainType = getCurrentDomainIDType();
|
||||
loadPlaces();
|
||||
} else {
|
||||
loadingDialog.modal('hide');
|
||||
bootbox.confirm("We were not able to load your domain information from the Metaverse. Would you like to retry?", function(response) {
|
||||
if (response) {
|
||||
chooseFromMetaversePlaces(accessToken, forcePathTo, onSuccessfullyAdded);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
} else {
|
||||
bootbox.alert({
|
||||
title: Strings.ADD_PLACE_NOT_CONNECTED_TITLE,
|
||||
|
@ -501,14 +500,38 @@ function prepareAccessTokenPrompt(callback) {
|
|||
});
|
||||
}
|
||||
|
||||
function createDomainIDPrompt(callback) {
|
||||
swal({
|
||||
title: 'Finish Registering Domain',
|
||||
type: 'input',
|
||||
text: 'Enter a label for this machine.</br></br>This will help you identify which domain ID belongs to which machine.</br></br>This is a required step for registration.</br></br>',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "Create",
|
||||
closeOnConfirm: false,
|
||||
html: true
|
||||
}, function (inputValue) {
|
||||
if (inputValue === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inputValue === "") {
|
||||
swal.showInputError("Please enter a valid label for your machine.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback(inputValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getMetaverseUrl(callback) {
|
||||
$.ajax('/api/metaverse_info', {
|
||||
success: function(data) {
|
||||
callback(data.metaverse_url);
|
||||
},
|
||||
error: function() {
|
||||
callback(URLs.METAVERSE_URL);
|
||||
callback(URLs.DEFAULT_METAVERSE_URL);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ $(document).ready(function(){
|
|||
|
||||
Settings.extraGroupsAtEnd = Settings.extraDomainGroupsAtEnd;
|
||||
Settings.extraGroupsAtIndex = Settings.extraDomainGroupsAtIndex;
|
||||
var METAVERSE_URL = URLs.METAVERSE_URL;
|
||||
var METAVERSE_URL = URLs.DEFAULT_METAVERSE_URL;
|
||||
|
||||
var SSL_PRIVATE_KEY_FILE_ID = 'ssl-private-key-file';
|
||||
var SSL_PRIVATE_KEY_CONTENTS_ID = 'key-contents';
|
||||
|
@ -40,6 +40,8 @@ $(document).ready(function(){
|
|||
|
||||
// call our method to setup the place names table
|
||||
setupPlacesTable();
|
||||
// hide the places table for now because we do not want that interacted with from the domain-server
|
||||
$('#' + Settings.PLACES_TABLE_ID).hide();
|
||||
|
||||
setupDomainNetworkingSettings();
|
||||
// setupDomainLabelSetting();
|
||||
|
@ -277,7 +279,7 @@ $(document).ready(function(){
|
|||
swal({
|
||||
title: '',
|
||||
type: 'error',
|
||||
text: "There was a problem retrieving domain information from High Fidelity API.",
|
||||
text: "There was a problem retrieving domain information from the Metaverse API.",
|
||||
confirmButtonText: 'Try again',
|
||||
showCancelButton: true,
|
||||
closeOnConfirm: false
|
||||
|
@ -306,7 +308,7 @@ $(document).ready(function(){
|
|||
|
||||
if (hasAccessToken) {
|
||||
el = "<p>";
|
||||
el += "<span class='account-connected-header'>High Fidelity Account Connected</span>";
|
||||
el += "<span class='account-connected-header'>Metaverse Account Connected</span>";
|
||||
el += "<button id='" + Settings.DISCONNECT_ACCOUNT_BTN_ID + "' class='btn'>Disconnect</button>";
|
||||
el += "</p>";
|
||||
el = $(el);
|
||||
|
@ -319,7 +321,7 @@ $(document).ready(function(){
|
|||
}
|
||||
buttonSetting.help = "";
|
||||
buttonSetting.classes = "btn-primary";
|
||||
buttonSetting.button_label = "Connect High Fidelity Account";
|
||||
buttonSetting.button_label = "Connect Metaverse Account";
|
||||
buttonSetting.html_id = Settings.CONNECT_ACCOUNT_BTN_ID;
|
||||
|
||||
buttonSetting.href = METAVERSE_URL + "/user/tokens/new?for_domain_server=true";
|
||||
|
@ -363,7 +365,7 @@ $(document).ready(function(){
|
|||
confirmButtonText: "Create",
|
||||
closeOnConfirm: false,
|
||||
html: true
|
||||
}, function(inputValue){
|
||||
}, function (inputValue) {
|
||||
if (inputValue === false) {
|
||||
swal.close();
|
||||
|
||||
|
@ -373,7 +375,7 @@ $(document).ready(function(){
|
|||
}
|
||||
} else {
|
||||
// we're going to change the alert to a new one with a spinner while we create this domain
|
||||
showSpinnerAlert('Creating domain ID');
|
||||
// showSpinnerAlert('Creating domain ID');
|
||||
createNewDomainID(inputValue, justConnected);
|
||||
}
|
||||
});
|
||||
|
@ -385,9 +387,14 @@ $(document).ready(function(){
|
|||
"label": label
|
||||
}
|
||||
|
||||
$.post("/api/domains", domainJSON, function(data){
|
||||
$.post("/api/domains", domainJSON, function(data) {
|
||||
if (data.status === "failure") {
|
||||
failedToCreateDomainID(data, justConnected);
|
||||
return;
|
||||
}
|
||||
|
||||
// we successfully created a domain ID, set it on that field
|
||||
var domainID = data.domain.id;
|
||||
var domainID = data.domain.domainId;
|
||||
console.log("Setting domain id to ", data, domainID);
|
||||
$(Settings.DOMAIN_ID_SELECTOR).val(domainID).change();
|
||||
|
||||
|
@ -406,40 +413,50 @@ $(document).ready(function(){
|
|||
text: successText,
|
||||
html: true,
|
||||
confirmButtonText: 'Save'
|
||||
}, function(){
|
||||
}, function () {
|
||||
saveSettings();
|
||||
});
|
||||
}, 'json').fail(function(){
|
||||
}, 'json').fail(function (data) {
|
||||
failedToCreateDomainID(data, justConnected);
|
||||
});
|
||||
}
|
||||
|
||||
function failedToCreateDomainID(data, justConnected) {
|
||||
var errorText = "There was a problem creating your new domain ID. Do you want to try again or";
|
||||
|
||||
var errorText = "There was a problem creating your new domain ID. Do you want to try again or";
|
||||
if (data && data.status === "failure") {
|
||||
errorText = "Error: " + data.error + "</br>Do you want to try again or";
|
||||
console.log("Error: " + data.error);
|
||||
} else {
|
||||
console.log("Error: Failed to post to metaverse.");
|
||||
}
|
||||
|
||||
if (justConnected) {
|
||||
errorText += " just save your new access token?</br></br>You can always create a new domain ID later.";
|
||||
if (justConnected) {
|
||||
errorText += " just save your new access token?</br></br>You can always create a new domain ID later.";
|
||||
} else {
|
||||
errorText += " cancel?"
|
||||
}
|
||||
|
||||
// we failed to create the new domain ID, show a sweet-alert that lets them try again or cancel
|
||||
swal({
|
||||
title: '',
|
||||
type: 'error',
|
||||
text: errorText,
|
||||
html: true,
|
||||
confirmButtonText: 'Try again',
|
||||
showCancelButton: true,
|
||||
closeOnConfirm: false
|
||||
}, function (isConfirm) {
|
||||
if (isConfirm) {
|
||||
// they want to try creating a domain ID again
|
||||
showDomainCreationAlert(justConnected);
|
||||
} else {
|
||||
errorText += " cancel?"
|
||||
}
|
||||
|
||||
// we failed to create the new domain ID, show a sweet-alert that lets them try again or cancel
|
||||
swal({
|
||||
title: '',
|
||||
type: 'error',
|
||||
text: errorText,
|
||||
html: true,
|
||||
confirmButtonText: 'Try again',
|
||||
showCancelButton: true,
|
||||
closeOnConfirm: false
|
||||
}, function(isConfirm){
|
||||
if (isConfirm) {
|
||||
// they want to try creating a domain ID again
|
||||
showDomainCreationAlert(justConnected);
|
||||
} else {
|
||||
// they want to cancel
|
||||
if (justConnected) {
|
||||
// since they just connected we need to save the access token here
|
||||
saveSettings();
|
||||
}
|
||||
// they want to cancel
|
||||
if (justConnected) {
|
||||
// since they just connected we need to save the access token here
|
||||
saveSettings();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -711,9 +728,9 @@ $(document).ready(function(){
|
|||
name: 'places',
|
||||
label: 'Places',
|
||||
html_id: Settings.PLACES_TABLE_ID,
|
||||
help: "The following places currently point to this domain.</br>To point places to this domain, "
|
||||
+ " go to the <a href='" + METAVERSE_URL + "/user/places'>My Places</a> "
|
||||
+ "page in your High Fidelity Metaverse account.",
|
||||
help: "To point places to this domain, "
|
||||
+ " go to the <a href='" + METAVERSE_URL + "/user/places'>Places</a> "
|
||||
+ "page in your Metaverse account.",
|
||||
read_only: true,
|
||||
can_add_new_rows: false,
|
||||
columns: [
|
||||
|
@ -745,9 +762,10 @@ $(document).ready(function(){
|
|||
var errorEl = createDomainLoadingError("There was an error retrieving your places.");
|
||||
$("#" + Settings.PLACES_TABLE_ID).after(errorEl);
|
||||
|
||||
var temporaryPlaceButton = dynamicButton(Settings.GET_TEMPORARY_NAME_BTN_ID, 'Get a temporary place name');
|
||||
temporaryPlaceButton.hide();
|
||||
$('#' + Settings.PLACES_TABLE_ID).after(temporaryPlaceButton);
|
||||
// DISABLE TEMP PLACE NAME BUTTON...
|
||||
// var temporaryPlaceButton = dynamicButton(Settings.GET_TEMPORARY_NAME_BTN_ID, 'Get a temporary place name');
|
||||
// temporaryPlaceButton.hide();
|
||||
// $('#' + Settings.PLACES_TABLE_ID).after(temporaryPlaceButton);
|
||||
if (accessTokenIsSet()) {
|
||||
appendAddButtonToPlacesTable();
|
||||
}
|
||||
|
@ -853,7 +871,7 @@ $(document).ready(function(){
|
|||
}
|
||||
// Update label
|
||||
if (showOrHideLabel()) {
|
||||
var label = data.domain.label;
|
||||
var label = data.domain.name;
|
||||
label = label === null ? '' : label;
|
||||
$('#network-label').val(label);
|
||||
}
|
||||
|
@ -959,7 +977,7 @@ $(document).ready(function(){
|
|||
var addRow = $("<tr> <td></td> <td></td> <td class='buttons'><a href='#' class='place-add glyphicon glyphicon-plus'></a></td> </tr>");
|
||||
addRow.find(".place-add").click(function(ev) {
|
||||
ev.preventDefault();
|
||||
chooseFromHighFidelityPlaces(Settings.initialValues.metaverse.access_token, null, function(placeName, newDomainID) {
|
||||
chooseFromMetaversePlaces(Settings.initialValues.metaverse.access_token, null, function(placeName, newDomainID) {
|
||||
if (newDomainID) {
|
||||
Settings.data.values.metaverse.id = newDomainID;
|
||||
var domainIDEl = $("[data-keypath='metaverse.id']");
|
||||
|
@ -997,18 +1015,18 @@ $(document).ready(function(){
|
|||
|
||||
if (data.data.domains.length) {
|
||||
// setup a select box for the returned domains
|
||||
modal_body = "<p>Choose the High Fidelity domain you want this domain-server to represent.<br/>This will set your domain ID on the settings page.</p>";
|
||||
modal_body = "<p>Choose the Metaverse domain you want this domain-server to represent.<br/>This will set your domain ID on the settings page.</p>";
|
||||
domain_select = $("<select id='domain-name-select' class='form-control'></select>");
|
||||
_.each(data.data.domains, function(domain){
|
||||
var domainString = "";
|
||||
|
||||
if (domain.label) {
|
||||
domainString += '"' + domain.label+ '" - ';
|
||||
if (domain.name) {
|
||||
domainString += '"' + domain.name+ '" - ';
|
||||
}
|
||||
|
||||
domainString += domain.id;
|
||||
domainString += domain.domainId;
|
||||
|
||||
domain_select.append("<option value='" + domain.id + "'>" + domainString + "</option>");
|
||||
domain_select.append("<option value='" + domain.domainId + "'>" + domainString + "</option>");
|
||||
})
|
||||
modal_body += "<label for='domain-name-select'>Domains</label>" + domain_select[0].outerHTML
|
||||
modal_buttons["success"] = {
|
||||
|
@ -1026,7 +1044,7 @@ $(document).ready(function(){
|
|||
window.open(METAVERSE_URL + "/user/domains", '_blank');
|
||||
}
|
||||
}
|
||||
modal_body = "<p>You do not have any domains in your High Fidelity account." +
|
||||
modal_body = "<p>You do not have any domains in your Metaverse account." +
|
||||
"<br/><br/>Go to your domains page to create a new one. Once your domain is created re-open this dialog to select it.</p>"
|
||||
}
|
||||
|
||||
|
@ -1038,7 +1056,7 @@ $(document).ready(function(){
|
|||
})
|
||||
},
|
||||
error: function() {
|
||||
bootbox.alert("Failed to retrieve your domains from the High Fidelity Metaverse");
|
||||
bootbox.alert("Failed to retrieve your domains from the Metaverse");
|
||||
},
|
||||
complete: function() {
|
||||
// remove the spinner from the choose button
|
||||
|
@ -1049,7 +1067,7 @@ $(document).ready(function(){
|
|||
|
||||
} else {
|
||||
bootbox.alert({
|
||||
message: "You must have an access token to query your High Fidelity domains.<br><br>" +
|
||||
message: "You must have an access token to query your Metaverse domains.<br><br>" +
|
||||
"Please follow the instructions on the settings page to add an access token.",
|
||||
title: "Access token required"
|
||||
})
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
<h4 class="step-title"></h4>
|
||||
<dl class="row">
|
||||
<dd class="col-md-12">
|
||||
<span class='step-description'>By connecting your High Fidelity Account you will be granting access to your account information.</span>
|
||||
<span class='step-description'>By connecting your Metaverse Account you will be granting access to your account information.</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="row">
|
||||
<dd class="col-md-12">
|
||||
<a id="connect-account-btn" role="button" class="btn btn-primary btn-md btn-block" target="_blank">Connect your High Fidelity account</a>
|
||||
<a id="connect-account-btn" role="button" class="btn btn-primary btn-md btn-block" target="_blank">Connect your Metaverse account</a>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
@ -19,13 +19,13 @@
|
|||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="wizard-step col-md-8 col-centered" style="display: none;">
|
||||
<!-- <div class="wizard-step col-md-8 col-centered" style="display: none;">
|
||||
<h4 class="step-title"></h4>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class='step-description'>
|
||||
<a target='_blank' href='https://docs.vircadia.dev/create-and-explore/start-working-in-your-sandbox/place-names'>Place names</a> are similar to web addresses. Users who want to visit your domain can
|
||||
enter its Place Name in High Fidelity's Interface. You can choose a Place Name for your domain.</br>
|
||||
enter its Place Name in Vircadia's Interface. You can choose a Place Name for your domain.</br>
|
||||
Your domain may also be reachable by <b>IP address</b>.
|
||||
</span>
|
||||
</div>
|
||||
|
@ -51,16 +51,16 @@
|
|||
<button type="button" class="btn btn-md btn-block btn-primary next-button">Next</button>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="wizard-step col-md-9 col-centered" style="display: none;">
|
||||
<h4 class="step-title"></h4>
|
||||
<div class="row">
|
||||
<p id="permissions-description" class="col-md-12 step-info"><b>Localhost</b> has been granted administrator privileges to this domain. (Localhost is any</br>user on the same machine as the High Fidelity Server)</p>
|
||||
<p id="permissions-description" class="col-md-12 step-info"><b>Localhost</b> has been granted administrator privileges to this domain. (Localhost is any</br>user on the same machine as the Vircadia server)</p>
|
||||
</div>
|
||||
<div id="admin-row" class="row">
|
||||
<p class="col-md-6">
|
||||
<span class="step-info"><span id="admin-description"><b>Add your High Fidelity username</b> and any other usernames</span> to grant <span class='wizard-link' data-toggle="tooltip" title="Users who will have all the permissions for this domain.">administrator privileges</span></span>
|
||||
<span class="step-info"><span id="admin-description"><b>Add your Metaverse username</b> and any other usernames</span> to grant <span class='wizard-link' data-toggle="tooltip" title="Users who will have all the permissions for this domain.">administrator privileges</span></span>
|
||||
</p>
|
||||
<div class="col-md-6">
|
||||
<input id="admin-usernames" type="text" class="form-control">
|
||||
|
@ -95,7 +95,7 @@
|
|||
</p>
|
||||
<p class="col-md-5">
|
||||
<label>
|
||||
<input id="connect-logged-in" name="connect-radio" type="radio" value="logged-in"> Users logged into High Fidelity
|
||||
<input id="connect-logged-in" name="connect-radio" type="radio" value="logged-in"> Users logged into the Metaverse
|
||||
</label>
|
||||
</p>
|
||||
<p class="col-md-2">
|
||||
|
@ -126,7 +126,7 @@
|
|||
</p>
|
||||
<p class="col-md-5">
|
||||
<label>
|
||||
<input id="rez-logged-in" name="rez-radio" type="radio" value="logged-in" disabled> Users logged into High Fidelity
|
||||
<input id="rez-logged-in" name="rez-radio" type="radio" value="logged-in" disabled> Users logged into the Metaverse
|
||||
</label>
|
||||
</p>
|
||||
<p class="col-md-2">
|
||||
|
@ -164,14 +164,14 @@
|
|||
<dt class="col-md-4 step-info">Username</dt>
|
||||
<dd class="col-md-8">
|
||||
<input id="http_username" type="text" class="form-control">
|
||||
<span class='help-block'>This does not have to be your High Fidelity username</span>
|
||||
<span class='help-block'>This does not have to be your Metaverse username</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="row">
|
||||
<dt class="col-md-4 step-info">Enter password</dt>
|
||||
<dd class="col-md-8">
|
||||
<input id="http_password" type="password" class="form-control">
|
||||
<span class='help-block'>This should not be the same as your High Fidelity password</span>
|
||||
<span class='help-block'>This should not be the same as your Metaverse password</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl id="verify-password-row" class="row">
|
||||
|
@ -186,7 +186,37 @@
|
|||
<button type="button" class="btn btn-md btn-block btn-default back-button">Back</button>
|
||||
</dd>
|
||||
<dd class="col-md-3 col-md-offset-6">
|
||||
<button id="save-username-password" type="button" class="btn btn-md btn-block btn-primary">Finish</button>
|
||||
<button id="save-username-password" type="button" class="btn btn-md btn-block btn-primary next-button">Next</button>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="wizard-step col-md-8 col-centered" style="display: none;">
|
||||
<h4 class="step-title"></h4>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<span class='step-description'>
|
||||
Would you like use automatic threading for your server's avatars and audio?
|
||||
If you are hosting this server on your local computer and it is not very powerful, then consider leaving this off because the server will use more resources if it is being utilized extensively, thereby slowing down your computer.
|
||||
If you are running this server on a powerful system and intend to have a large audience, then turn this setting on.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div id="automatic-threading-options-row" class="row">
|
||||
<p class="col-md-12">
|
||||
<label>
|
||||
<input id="enable-automatic-threading" name="threading-checkbox" type="checkbox" value="true"> Enable Automatic Threading
|
||||
</label>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<dl class="row">
|
||||
<dd class="col-md-3">
|
||||
<button type="button" class="btn btn-md btn-block btn-default back-button">Back</button>
|
||||
</dd>
|
||||
<dd class="col-md-3 col-md-offset-6">
|
||||
<button id="save-threading-settings" type="button" class="btn btn-md btn-block btn-primary">Finish</button>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
@ -201,7 +231,7 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-xs-10 col-xs-offset-1">
|
||||
<p id="main-description" class="step-info">You have successfully setup and configured your cloud hosted domain.</p>
|
||||
<p id="main-description" class="step-info">You have successfully setup and configured your Vircadia domain.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -262,4 +292,5 @@
|
|||
<script src='/js/bootbox.min.js'></script>
|
||||
<script src='/js/sha256.js'></script>
|
||||
<script src='js/wizard.js'></script>
|
||||
<script src='../js/shared.js'></script>
|
||||
<!--#include virtual="page-end.html"-->
|
||||
|
|
|
@ -2,121 +2,132 @@ var Metaverse = {
|
|||
accessToken: null
|
||||
}
|
||||
|
||||
var CURRENT_METAVERSE_URL;
|
||||
|
||||
var currentStepNumber;
|
||||
|
||||
$(document).ready(function(){
|
||||
Strings.ADD_PLACE_NOT_CONNECTED_MESSAGE = "You must have an access token to query your High Fidelity places.<br><br>" +
|
||||
"Please go back and connect your account.";
|
||||
getMetaverseUrl(function(metaverse_url) {
|
||||
CURRENT_METAVERSE_URL = metaverse_url;
|
||||
|
||||
$('#connect-account-btn').attr('href', URLs.METAVERSE_URL + "/user/tokens/new?for_domain_server=true");
|
||||
Strings.ADD_PLACE_NOT_CONNECTED_MESSAGE = "You must have an access token to query your Metaverse places.<br><br>" +
|
||||
"Please go back and connect your account.";
|
||||
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
$('#connect-account-btn').attr('href', CURRENT_METAVERSE_URL + "/user/tokens/new?for_domain_server=true");
|
||||
|
||||
$('.perms-link').on('click', function() {
|
||||
var modal_body = '<div>';
|
||||
modal_body += '<b>None</b> - No one will have permissions. Only you and the users your have given administrator privileges to will have permissions.</br></br>';
|
||||
modal_body += '<b>Friends</b> - Users who are your Friends in High Fidelity.</br></br>';
|
||||
modal_body += '<b>Users logged into High Fidelity</b> - Users who are currently logged into High Fidelity.</br></br>';
|
||||
modal_body += '<b>Everyone</b> - Anyone who uses High Fidelity.';
|
||||
modal_body += '</div>';
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
dialog = bootbox.dialog({
|
||||
title: "User definition",
|
||||
message: modal_body,
|
||||
closeButton: true
|
||||
$('.perms-link').on('click', function() {
|
||||
var modal_body = '<div>';
|
||||
modal_body += '<b>None</b> - No one will have permissions. Only you and the users your have given administrator privileges to will have permissions.</br></br>';
|
||||
modal_body += '<b>Friends</b> - Users who are your Friends in the Metaverse.</br></br>';
|
||||
modal_body += '<b>Users logged into the Metaverse</b> - Users who are currently logged into the Metaverse.</br></br>';
|
||||
modal_body += '<b>Everyone</b> - Anyone who uses the Metaverse.';
|
||||
modal_body += '</div>';
|
||||
|
||||
dialog = bootbox.dialog({
|
||||
title: "User definition",
|
||||
message: modal_body,
|
||||
closeButton: true
|
||||
});
|
||||
return false;
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
$('body').on('click', '.next-button', function() {
|
||||
goToNextStep();
|
||||
});
|
||||
|
||||
$('body').on('click', '.back-button', function() {
|
||||
goToPreviousStep();
|
||||
});
|
||||
|
||||
$('body').on('click', '#skip-wizard-button', function() {
|
||||
skipWizard();
|
||||
})
|
||||
|
||||
$('body').on('click', '#connect-account-btn', function() {
|
||||
$(this).blur();
|
||||
prepareAccessTokenPrompt(function(accessToken) {
|
||||
Metaverse.accessToken = accessToken;
|
||||
saveAccessToken();
|
||||
$('body').on('click', '.next-button', function() {
|
||||
goToNextStep();
|
||||
});
|
||||
});
|
||||
|
||||
$('body').on('click', '.back-button', function() {
|
||||
goToPreviousStep();
|
||||
});
|
||||
|
||||
$('body').on('click', '#skip-wizard-button', function() {
|
||||
skipWizard();
|
||||
})
|
||||
|
||||
$('body').on('click', '#connect-account-btn', function() {
|
||||
$(this).blur();
|
||||
prepareAccessTokenPrompt(function(accessToken) {
|
||||
Metaverse.accessToken = accessToken;
|
||||
saveAccessToken();
|
||||
promptToCreateDomainID();
|
||||
});
|
||||
});
|
||||
|
||||
$('body').on('click', '#save-permissions', function() {
|
||||
savePermissions();
|
||||
});
|
||||
|
||||
function triggerSaveUsernamePassword(event) {
|
||||
if (event.keyCode === 13) {
|
||||
$("#save-username-password").click();
|
||||
}
|
||||
}
|
||||
$("#http_username").keyup(triggerSaveUsernamePassword);
|
||||
$("#http_password").keyup(triggerSaveUsernamePassword);
|
||||
$("#verify_http_password").keyup(triggerSaveUsernamePassword);
|
||||
$('body').on('click', '#save-username-password', function() {
|
||||
saveUsernamePassword();
|
||||
|
||||
$('body').on('click', '#save-threading-settings', function() {
|
||||
saveThreadingSettings();
|
||||
});
|
||||
|
||||
$('body').on('click', '#change-place-name', function() {
|
||||
chooseFromHighFidelityPlaces(Settings.data.values.metaverse.access_token, "/0,-10,0", function(placeName) {
|
||||
updatePlaceNameLink(placeName);
|
||||
});
|
||||
});
|
||||
|
||||
$('body').on('click', '#visit-domain', function() {
|
||||
$('#share-link')[0].click();
|
||||
});
|
||||
|
||||
$('input[type=radio][name=connect-radio]').change(function() {
|
||||
var inputs = $('input[type=radio][name=rez-radio]');
|
||||
var disabled = [];
|
||||
|
||||
switch (this.value) {
|
||||
case 'none':
|
||||
disabled = inputs.splice(1);
|
||||
break;
|
||||
case 'friends':
|
||||
disabled = inputs.splice(2);
|
||||
break;
|
||||
case 'logged-in':
|
||||
disabled = inputs.splice(3);
|
||||
break;
|
||||
case 'everyone':
|
||||
disabled = inputs.splice(4);
|
||||
break;
|
||||
function triggerSaveUsernamePassword(event) {
|
||||
if (event.keyCode === 13) {
|
||||
$("#save-username-password").click();
|
||||
}
|
||||
}
|
||||
|
||||
$.each(inputs, function() {
|
||||
$(this).prop('disabled', false);
|
||||
$("#http_username").keyup(triggerSaveUsernamePassword);
|
||||
$("#http_password").keyup(triggerSaveUsernamePassword);
|
||||
$("#verify_http_password").keyup(triggerSaveUsernamePassword);
|
||||
$('body').on('click', '#save-username-password', function() {
|
||||
saveUsernamePassword();
|
||||
});
|
||||
$.each(disabled, function() {
|
||||
if ($(this).prop('checked')) {
|
||||
$(inputs.last()).prop('checked', true);
|
||||
}
|
||||
$(this).prop('disabled', true);
|
||||
});
|
||||
});
|
||||
|
||||
reloadSettings(function(success) {
|
||||
if (success) {
|
||||
getDomainFromAPI();
|
||||
setupWizardSteps();
|
||||
updatePlaceNameDisplay();
|
||||
updateUsernameDisplay();
|
||||
} else {
|
||||
swal({
|
||||
title: '',
|
||||
type: 'error',
|
||||
text: "There was a problem loading the domain settings.\nPlease refresh the page to try again.",
|
||||
$('body').on('click', '#change-place-name', function() {
|
||||
chooseFromMetaversePlaces(Settings.data.values.metaverse.access_token, "/0,-10,0", function(placeName) {
|
||||
updatePlaceNameLink(placeName);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('body').on('click', '#visit-domain', function() {
|
||||
$('#share-link')[0].click();
|
||||
});
|
||||
|
||||
$('input[type=radio][name=connect-radio]').change(function() {
|
||||
var inputs = $('input[type=radio][name=rez-radio]');
|
||||
var disabled = [];
|
||||
|
||||
switch (this.value) {
|
||||
case 'none':
|
||||
disabled = inputs.splice(1);
|
||||
break;
|
||||
case 'friends':
|
||||
disabled = inputs.splice(2);
|
||||
break;
|
||||
case 'logged-in':
|
||||
disabled = inputs.splice(3);
|
||||
break;
|
||||
case 'everyone':
|
||||
disabled = inputs.splice(4);
|
||||
break;
|
||||
}
|
||||
|
||||
$.each(inputs, function() {
|
||||
$(this).prop('disabled', false);
|
||||
});
|
||||
$.each(disabled, function() {
|
||||
if ($(this).prop('checked')) {
|
||||
$(inputs.last()).prop('checked', true);
|
||||
}
|
||||
$(this).prop('disabled', true);
|
||||
});
|
||||
});
|
||||
|
||||
reloadSettings(function(success) {
|
||||
if (success) {
|
||||
getDomainFromAPI();
|
||||
setupWizardSteps();
|
||||
updatePlaceNameDisplay();
|
||||
updateUsernameDisplay();
|
||||
} else {
|
||||
swal({
|
||||
title: '',
|
||||
type: 'error',
|
||||
text: "There was a problem loading the domain settings.\nPlease refresh the page to try again.",
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -142,10 +153,10 @@ function setupWizardSteps() {
|
|||
});
|
||||
|
||||
$('#permissions-description').html('You <span id="username-display"></span>have been assigned administrator privileges to this domain.');
|
||||
$('#admin-description').html('Add more High Fidelity usernames');
|
||||
$('#admin-description').html('Add more Metaverse usernames');
|
||||
} else {
|
||||
$('.cloud-only').remove();
|
||||
$('#save-permissions').text("Finish");
|
||||
$('#save-threading-settings').text("Finish");
|
||||
|
||||
steps = $('.wizard-step');
|
||||
$(steps).each(function(i) {
|
||||
|
@ -161,6 +172,45 @@ function setupWizardSteps() {
|
|||
$(currentStep).show();
|
||||
}
|
||||
|
||||
function promptToCreateDomainID() {
|
||||
setTimeout(function () {
|
||||
createDomainIDPrompt(function (label) {
|
||||
var domainJSON = {
|
||||
"label": label
|
||||
};
|
||||
|
||||
$.post("/api/domains", domainJSON, function (data) {
|
||||
if (data.status === "failure") {
|
||||
swal.showInputError("Error: " + data.error);
|
||||
return;
|
||||
}
|
||||
|
||||
swal.close();
|
||||
|
||||
// we successfully created a domain ID, set it on that field
|
||||
var domainID = data.domain.domainId;
|
||||
console.log("Setting domain ID to ", data, domainID);
|
||||
|
||||
var formJSON = {
|
||||
"metaverse": {
|
||||
"id": domainID
|
||||
}
|
||||
};
|
||||
|
||||
// POST the form JSON to the domain-server settings.json endpoint so the settings are saved
|
||||
postSettings(formJSON, goToNextStep);
|
||||
}, 'json').fail(function (data) {
|
||||
if (data && data.status === "failure") {
|
||||
swal.showInputError("Error: " + data.error);
|
||||
} else {
|
||||
swal.showInputError("Error: Failed to post to metaverse.");
|
||||
}
|
||||
console.log("Failed to create domain ID...");
|
||||
});
|
||||
});
|
||||
}, 500); // Apparently swal needs time before opening another prompt.
|
||||
}
|
||||
|
||||
function updatePlaceNameLink(address) {
|
||||
if (address) {
|
||||
var url = URLs.PLACE_URL + '/' + address;
|
||||
|
@ -171,7 +221,7 @@ function updatePlaceNameLink(address) {
|
|||
|
||||
function updatePlaceNameDisplay() {
|
||||
if (Settings.data.values.metaverse.id) {
|
||||
$.getJSON(URLs.METAVERSE_URL + '/api/v1/domains/' + Settings.data.values.metaverse.id, function(data) {
|
||||
$.getJSON(CURRENT_METAVERSE_URL + '/api/v1/domains/' + Settings.data.values.metaverse.id, function(data) {
|
||||
|
||||
if (data.status === 'success') {
|
||||
if (data.domain.default_place_name) {
|
||||
|
@ -254,10 +304,6 @@ function goToNextStep() {
|
|||
var currentStep = $('body').find('.wizard-step:visible');
|
||||
var nextStep = currentStep.next('.wizard-step');
|
||||
|
||||
var formJSON = {
|
||||
"wizard": {}
|
||||
}
|
||||
|
||||
if (nextStep.length > 0) {
|
||||
currentStep.hide();
|
||||
nextStep.show();
|
||||
|
@ -335,7 +381,7 @@ function saveAccessToken() {
|
|||
$(this).blur();
|
||||
|
||||
// POST the form JSON to the domain-server settings.json endpoint so the settings are saved
|
||||
postSettings(formJSON, goToNextStep);
|
||||
postSettings(formJSON);
|
||||
}
|
||||
|
||||
function getSettingDescriptionForKey(groupKey, settingKey) {
|
||||
|
@ -515,7 +561,29 @@ function saveUsernamePassword() {
|
|||
$(this).blur();
|
||||
|
||||
// POST the form JSON to the domain-server settings.json endpoint so the settings are saved
|
||||
postSettings(formJSON, function() {
|
||||
location.reload();
|
||||
});
|
||||
postSettings(formJSON, goToNextStep);
|
||||
}
|
||||
|
||||
function saveThreadingSettings() {
|
||||
var enable_automatic_threading = $("#enable-automatic-threading").prop("checked");
|
||||
|
||||
currentStepNumber += 1;
|
||||
|
||||
var formJSON = {
|
||||
"audio_threading": {
|
||||
"auto_threads": enable_automatic_threading
|
||||
},
|
||||
"avatar_mixer": {
|
||||
"auto_threads": enable_automatic_threading
|
||||
},
|
||||
"wizard": {
|
||||
"steps_completed": currentStepNumber.toString()
|
||||
}
|
||||
}
|
||||
|
||||
// remove focus from the button
|
||||
$(this).blur();
|
||||
|
||||
// POST the form JSON to the domain-server settings.json endpoint so the settings are saved
|
||||
postSettings(formJSON, goToNextStep);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
#include <openssl/x509.h>
|
||||
#include <random>
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QtCore/QDataStream>
|
||||
#include <QtCore/QMetaMethod>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <Assignment.h>
|
||||
|
@ -821,7 +822,7 @@ void DomainGatekeeper::requestUserPublicKey(const QString& username, bool isOpti
|
|||
callbackParams.errorCallbackMethod = "publicKeyJSONErrorCallback";
|
||||
|
||||
|
||||
const QString USER_PUBLIC_KEY_PATH = "api/v1/users/%1/public_key";
|
||||
const QString USER_PUBLIC_KEY_PATH = "/api/v1/users/%1/public_key";
|
||||
|
||||
qDebug().nospace() << "Requesting " << (isOptimistic ? "optimistic " : " ") << "public key for user " << username;
|
||||
|
||||
|
@ -1048,7 +1049,7 @@ void DomainGatekeeper::getGroupMemberships(const QString& username) {
|
|||
callbackParams.jsonCallbackMethod = "getIsGroupMemberJSONCallback";
|
||||
callbackParams.errorCallbackMethod = "getIsGroupMemberErrorCallback";
|
||||
|
||||
const QString GET_IS_GROUP_MEMBER_PATH = "api/v1/groups/members/%2";
|
||||
const QString GET_IS_GROUP_MEMBER_PATH = "/api/v1/groups/members/%2";
|
||||
DependencyManager::get<AccountManager>()->sendRequest(GET_IS_GROUP_MEMBER_PATH.arg(username),
|
||||
AccountManagerAuth::Required,
|
||||
QNetworkAccessManager::PostOperation, callbackParams,
|
||||
|
@ -1114,7 +1115,7 @@ void DomainGatekeeper::getDomainOwnerFriendsList() {
|
|||
callbackParams.jsonCallbackMethod = "getDomainOwnerFriendsListJSONCallback";
|
||||
callbackParams.errorCallbackMethod = "getDomainOwnerFriendsListErrorCallback";
|
||||
|
||||
const QString GET_FRIENDS_LIST_PATH = "api/v1/user/friends";
|
||||
const QString GET_FRIENDS_LIST_PATH = "/api/v1/user/friends";
|
||||
if (DependencyManager::get<AccountManager>()->hasValidAccessToken()) {
|
||||
DependencyManager::get<AccountManager>()->sendRequest(GET_FRIENDS_LIST_PATH, AccountManagerAuth::Required,
|
||||
QNetworkAccessManager::GetOperation, callbackParams, QByteArray(),
|
||||
|
@ -1196,7 +1197,7 @@ Node::LocalID DomainGatekeeper::findOrCreateLocalID(const QUuid& uuid) {
|
|||
return existingLocalIDIt->second;
|
||||
}
|
||||
|
||||
assert(_localIDs.size() < std::numeric_limits<LocalIDs::value_type>::max() - 2);
|
||||
assert(_localIDs.size() < (size_t)(std::numeric_limits<LocalIDs::value_type>::max() - 2));
|
||||
|
||||
Node::LocalID newLocalID;
|
||||
do {
|
||||
|
|
|
@ -4,20 +4,25 @@
|
|||
//
|
||||
// Created by Zach Pomerantz on 5/25/2016.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
#include "DomainMetadata.h"
|
||||
#include "HTTPConnection.h"
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <HifiConfigVariantMap.h>
|
||||
#include <LimitedNodeList.h>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
#include "DomainServer.h"
|
||||
#include "DomainServerNodeData.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(domain_metadata_exporter, "hifi.domain_server.metadata_exporter")
|
||||
|
||||
const QString DomainMetadata::USERS = "users";
|
||||
const QString DomainMetadata::Users::NUM_TOTAL = "num_users";
|
||||
const QString DomainMetadata::Users::NUM_ANON = "num_anon_users";
|
||||
|
@ -29,18 +34,28 @@ const QString DomainMetadata::Users::HOSTNAMES = "user_hostnames";
|
|||
// }
|
||||
|
||||
const QString DomainMetadata::DESCRIPTORS = "descriptors";
|
||||
const QString DomainMetadata::Descriptors::NAME = "world_name";
|
||||
const QString DomainMetadata::Descriptors::DESCRIPTION = "description";
|
||||
const QString DomainMetadata::Descriptors::THUMBNAIL = "thumbnail";
|
||||
const QString DomainMetadata::Descriptors::IMAGES = "images";
|
||||
const QString DomainMetadata::Descriptors::CAPACITY = "capacity"; // parsed from security
|
||||
const QString DomainMetadata::Descriptors::RESTRICTION = "restriction"; // parsed from ACL
|
||||
const QString DomainMetadata::Descriptors::MATURITY = "maturity";
|
||||
const QString DomainMetadata::Descriptors::HOSTS = "hosts";
|
||||
const QString DomainMetadata::Descriptors::CONTACT = "contact_info";
|
||||
const QString DomainMetadata::Descriptors::MANAGERS = "managers";
|
||||
const QString DomainMetadata::Descriptors::TAGS = "tags";
|
||||
|
||||
// descriptors metadata will appear as (JSON):
|
||||
// { "description": String, // capped description
|
||||
// {
|
||||
// "world_name": String, // capped name
|
||||
// "description": String, // capped description
|
||||
// "thumbnail": String, // capped thumbnail URL
|
||||
// "images": [ String ], // capped list of image URLs
|
||||
// "capacity": Number,
|
||||
// "restriction": String, // enum of either open, hifi, or acl
|
||||
// "maturity": String, // enum corresponding to ESRB ratings
|
||||
// "hosts": [ String ], // capped list of usernames
|
||||
// "contact_info": [ String ], // capped list of usernames
|
||||
// "managers": [ String ], // capped list of usernames
|
||||
// "tags": [ String ], // capped list of tags
|
||||
// }
|
||||
|
||||
|
@ -54,17 +69,6 @@ DomainMetadata::DomainMetadata(QObject* domainServer) : QObject(domainServer) {
|
|||
_metadata[USERS] = QVariantMap {};
|
||||
_metadata[DESCRIPTORS] = QVariantMap {};
|
||||
|
||||
assert(dynamic_cast<DomainServer*>(domainServer));
|
||||
DomainServer* server = static_cast<DomainServer*>(domainServer);
|
||||
|
||||
// update the metadata when a user (dis)connects
|
||||
connect(server, &DomainServer::userConnected, this, &DomainMetadata::usersChanged);
|
||||
connect(server, &DomainServer::userDisconnected, this, &DomainMetadata::usersChanged);
|
||||
|
||||
// update the metadata when security changes
|
||||
connect(&server->_settingsManager, &DomainServerSettingsManager::updateNodePermissions,
|
||||
this, static_cast<void(DomainMetadata::*)()>(&DomainMetadata::securityChanged));
|
||||
|
||||
// initialize the descriptors
|
||||
securityChanged(false);
|
||||
descriptorsChanged();
|
||||
|
@ -88,12 +92,40 @@ void DomainMetadata::descriptorsChanged() {
|
|||
static const QString DESCRIPTORS_GROUP_KEYPATH = "descriptors";
|
||||
auto descriptorsMap = static_cast<DomainServer*>(parent())->_settingsManager.valueForKeyPath(DESCRIPTORS).toMap();
|
||||
|
||||
// copy simple descriptors (description/maturity)
|
||||
state[Descriptors::DESCRIPTION] = descriptorsMap[Descriptors::DESCRIPTION];
|
||||
state[Descriptors::MATURITY] = descriptorsMap[Descriptors::MATURITY];
|
||||
// copy simple descriptors
|
||||
if (!descriptorsMap[Descriptors::NAME].isNull()) {
|
||||
state[Descriptors::NAME] = descriptorsMap[Descriptors::NAME];
|
||||
} else {
|
||||
state[Descriptors::NAME] = "";
|
||||
}
|
||||
|
||||
// copy array descriptors (hosts/tags)
|
||||
state[Descriptors::HOSTS] = descriptorsMap[Descriptors::HOSTS].toList();
|
||||
if (!descriptorsMap[Descriptors::DESCRIPTION].isNull()) {
|
||||
state[Descriptors::DESCRIPTION] = descriptorsMap[Descriptors::DESCRIPTION];
|
||||
} else {
|
||||
state[Descriptors::DESCRIPTION] = "";
|
||||
}
|
||||
|
||||
if (!descriptorsMap[Descriptors::THUMBNAIL].isNull()) {
|
||||
state[Descriptors::THUMBNAIL] = descriptorsMap[Descriptors::THUMBNAIL];
|
||||
} else {
|
||||
state[Descriptors::THUMBNAIL] = "";
|
||||
}
|
||||
|
||||
if (!descriptorsMap[Descriptors::MATURITY].isNull()) {
|
||||
state[Descriptors::MATURITY] = descriptorsMap[Descriptors::MATURITY];
|
||||
} else {
|
||||
state[Descriptors::MATURITY] = "";
|
||||
}
|
||||
|
||||
if (!descriptorsMap[Descriptors::CONTACT].isNull()) {
|
||||
state[Descriptors::CONTACT] = descriptorsMap[Descriptors::CONTACT];
|
||||
} else {
|
||||
state[Descriptors::CONTACT] = "";
|
||||
}
|
||||
|
||||
// copy array descriptors
|
||||
state[Descriptors::IMAGES] = descriptorsMap[Descriptors::IMAGES].toList();
|
||||
state[Descriptors::MANAGERS] = descriptorsMap[Descriptors::MANAGERS].toList();
|
||||
state[Descriptors::TAGS] = descriptorsMap[Descriptors::TAGS].toList();
|
||||
|
||||
// parse capacity
|
||||
|
@ -198,7 +230,7 @@ void DomainMetadata::maybeUpdateUsers() {
|
|||
}
|
||||
|
||||
void DomainMetadata::sendDescriptors() {
|
||||
QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(get(DESCRIPTORS)).toJson(QJsonDocument::Compact)));
|
||||
QString domainUpdateJSON = QString("{\"domain\":{\"meta\":%1}}").arg(QString(QJsonDocument(get(DESCRIPTORS)).toJson(QJsonDocument::Compact)));
|
||||
const QUuid& domainID = DependencyManager::get<LimitedNodeList>()->getSessionUUID();
|
||||
if (!domainID.isNull()) {
|
||||
static const QString DOMAIN_UPDATE = "/api/v1/domains/%1";
|
||||
|
@ -215,3 +247,22 @@ void DomainMetadata::sendDescriptors() {
|
|||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool DomainMetadata::handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler) {
|
||||
QString domainMetadataJSON = QString("{\"domain\":{\"meta\":%1}, \"users\":%2}")
|
||||
.arg(QString(QJsonDocument(get(DESCRIPTORS)).toJson(QJsonDocument::Compact)))
|
||||
.arg(QString(QJsonDocument(get(USERS)).toJson(QJsonDocument::Compact)));
|
||||
const QString URI_METADATA = "/metadata";
|
||||
const QString EXPORTER_MIME_TYPE = "application/json";
|
||||
|
||||
if (url.path() == URI_METADATA) {
|
||||
connection->respond(HTTPConnection::StatusCode200, domainMetadataJSON.toUtf8(), qPrintable(EXPORTER_MIME_TYPE));
|
||||
return true;
|
||||
}
|
||||
|
||||
#if DEV_BUILD || PR_BUILD
|
||||
qCDebug(domain_metadata_exporter) << "Metadata request on URL " << url;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Zach Pomerantz on 5/25/2016.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -15,8 +16,9 @@
|
|||
|
||||
#include <QVariantMap>
|
||||
#include <QJsonObject>
|
||||
#include "HTTPManager.h"
|
||||
|
||||
class DomainMetadata : public QObject {
|
||||
class DomainMetadata : public QObject, public HTTPRequestHandler {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -33,25 +35,29 @@ public:
|
|||
static const QString DESCRIPTORS;
|
||||
class Descriptors {
|
||||
public:
|
||||
static const QString NAME;
|
||||
static const QString DESCRIPTION;
|
||||
static const QString THUMBNAIL;
|
||||
static const QString IMAGES;
|
||||
static const QString CAPACITY;
|
||||
static const QString RESTRICTION;
|
||||
static const QString MATURITY;
|
||||
static const QString HOSTS;
|
||||
static const QString CONTACT;
|
||||
static const QString MANAGERS;
|
||||
static const QString TAGS;
|
||||
};
|
||||
|
||||
DomainMetadata(QObject* domainServer);
|
||||
DomainMetadata() = delete;
|
||||
|
||||
~DomainMetadata() = default;
|
||||
// Get cached metadata
|
||||
QJsonObject get();
|
||||
QJsonObject get(const QString& group);
|
||||
|
||||
bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler = false) override;
|
||||
|
||||
public slots:
|
||||
void descriptorsChanged();
|
||||
void securityChanged(bool send);
|
||||
void securityChanged() { securityChanged(true); }
|
||||
void usersChanged();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Stephen Birarda on 9/26/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -70,7 +71,6 @@ const QString DomainServer::REPLACEMENT_FILE_EXTENSION = ".replace";
|
|||
const int MIN_PORT = 1;
|
||||
const int MAX_PORT = 65535;
|
||||
|
||||
|
||||
int const DomainServer::EXIT_CODE_REBOOT = 234923;
|
||||
|
||||
QString DomainServer::_iceServerAddr { NetworkingConstants::ICE_SERVER_DEFAULT_HOSTNAME };
|
||||
|
@ -119,7 +119,7 @@ bool DomainServer::forwardMetaverseAPIRequest(HTTPConnection* connection,
|
|||
root.insert(requestSubobjectKey, subobject);
|
||||
QJsonDocument doc { root };
|
||||
|
||||
QUrl url{ MetaverseAPI::getCurrentMetaverseServerURL().toString() + metaversePath };
|
||||
QUrl url { MetaverseAPI::getCurrentMetaverseServerURL().toString() + metaversePath };
|
||||
|
||||
QNetworkRequest req(url);
|
||||
req.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
|
||||
|
@ -267,6 +267,13 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
connect(&_settingsManager, &DomainServerSettingsManager::settingsUpdated,
|
||||
_metadata, &DomainMetadata::descriptorsChanged);
|
||||
|
||||
// update the metadata when a user (dis)connects
|
||||
connect(this, &DomainServer::userConnected, _metadata, &DomainMetadata::usersChanged);
|
||||
connect(this, &DomainServer::userDisconnected, _metadata, &DomainMetadata::usersChanged);
|
||||
|
||||
// update the metadata when security changes
|
||||
connect(&_settingsManager, &DomainServerSettingsManager::updateNodePermissions, [this] { _metadata->securityChanged(true); });
|
||||
|
||||
qDebug() << "domain-server is running";
|
||||
static const QString AC_SUBNET_WHITELIST_SETTING_PATH = "security.ac_subnet_whitelist";
|
||||
|
||||
|
@ -328,11 +335,12 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
_nodePingMonitorTimer->start(NODE_PING_MONITOR_INTERVAL_MSECS);
|
||||
|
||||
initializeExporter();
|
||||
initializeMetadataExporter();
|
||||
}
|
||||
|
||||
void DomainServer::parseCommandLine(int argc, char* argv[]) {
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("High Fidelity Domain Server");
|
||||
parser.setApplicationDescription("Vircadia Domain Server");
|
||||
const QCommandLineOption versionOption = parser.addVersionOption();
|
||||
const QCommandLineOption helpOption = parser.addHelpOption();
|
||||
|
||||
|
@ -421,6 +429,11 @@ DomainServer::~DomainServer() {
|
|||
_contentManager->aboutToFinish();
|
||||
_contentManager->terminate();
|
||||
}
|
||||
|
||||
if (_httpMetadataExporterManager) {
|
||||
_httpMetadataExporterManager->close();
|
||||
delete _httpMetadataExporterManager;
|
||||
}
|
||||
|
||||
if (_httpExporterManager) {
|
||||
_httpExporterManager->close();
|
||||
|
@ -765,32 +778,51 @@ void DomainServer::setupNodeListAndAssignments() {
|
|||
|
||||
// register as the packet receiver for the types we want
|
||||
PacketReceiver& packetReceiver = nodeList->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::RequestAssignment, this, "processRequestAssignmentPacket");
|
||||
packetReceiver.registerListener(PacketType::DomainListRequest, this, "processListRequestPacket");
|
||||
packetReceiver.registerListener(PacketType::DomainServerPathQuery, this, "processPathQueryPacket");
|
||||
packetReceiver.registerListener(PacketType::NodeJsonStats, this, "processNodeJSONStatsPacket");
|
||||
packetReceiver.registerListener(PacketType::DomainDisconnectRequest, this, "processNodeDisconnectRequestPacket");
|
||||
packetReceiver.registerListener(PacketType::AvatarZonePresence, this, "processAvatarZonePresencePacket");
|
||||
packetReceiver.registerListener(PacketType::RequestAssignment,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainServer>(this, &DomainServer::processRequestAssignmentPacket));
|
||||
packetReceiver.registerListener(PacketType::DomainListRequest,
|
||||
PacketReceiver::makeSourcedListenerReference<DomainServer>(this, &DomainServer::processListRequestPacket));
|
||||
packetReceiver.registerListener(PacketType::DomainServerPathQuery,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainServer>(this, &DomainServer::processPathQueryPacket));
|
||||
packetReceiver.registerListener(PacketType::NodeJsonStats,
|
||||
PacketReceiver::makeSourcedListenerReference<DomainServer>(this, &DomainServer::processNodeJSONStatsPacket));
|
||||
packetReceiver.registerListener(PacketType::DomainDisconnectRequest,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainServer>(this, &DomainServer::processNodeDisconnectRequestPacket));
|
||||
packetReceiver.registerListener(PacketType::AvatarZonePresence,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainServer>(this, &DomainServer::processAvatarZonePresencePacket));
|
||||
|
||||
// NodeList won't be available to the settings manager when it is created, so call registerListener here
|
||||
packetReceiver.registerListener(PacketType::DomainSettingsRequest, &_settingsManager, "processSettingsRequestPacket");
|
||||
packetReceiver.registerListener(PacketType::NodeKickRequest, &_settingsManager, "processNodeKickRequestPacket");
|
||||
packetReceiver.registerListener(PacketType::UsernameFromIDRequest, &_settingsManager, "processUsernameFromIDRequestPacket");
|
||||
packetReceiver.registerListener(PacketType::DomainSettingsRequest,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainServerSettingsManager>(&_settingsManager, &DomainServerSettingsManager::processSettingsRequestPacket));
|
||||
packetReceiver.registerListener(PacketType::NodeKickRequest,
|
||||
PacketReceiver::makeSourcedListenerReference<DomainServerSettingsManager>(&_settingsManager, &DomainServerSettingsManager::processNodeKickRequestPacket));
|
||||
packetReceiver.registerListener(PacketType::UsernameFromIDRequest,
|
||||
PacketReceiver::makeSourcedListenerReference<DomainServerSettingsManager>(&_settingsManager, &DomainServerSettingsManager::processUsernameFromIDRequestPacket));
|
||||
|
||||
// register the gatekeeper for the packets it needs to receive
|
||||
packetReceiver.registerListener(PacketType::DomainConnectRequest, &_gatekeeper, "processConnectRequestPacket");
|
||||
packetReceiver.registerListener(PacketType::ICEPing, &_gatekeeper, "processICEPingPacket");
|
||||
packetReceiver.registerListener(PacketType::ICEPingReply, &_gatekeeper, "processICEPingReplyPacket");
|
||||
packetReceiver.registerListener(PacketType::ICEServerPeerInformation, &_gatekeeper, "processICEPeerInformationPacket");
|
||||
packetReceiver.registerListener(PacketType::DomainConnectRequest,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainGatekeeper>(&_gatekeeper, &DomainGatekeeper::processConnectRequestPacket));
|
||||
packetReceiver.registerListener(PacketType::ICEPing,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainGatekeeper>(&_gatekeeper, &DomainGatekeeper::processICEPingPacket));
|
||||
packetReceiver.registerListener(PacketType::ICEPingReply,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainGatekeeper>(&_gatekeeper, &DomainGatekeeper::processICEPingReplyPacket));
|
||||
packetReceiver.registerListener(PacketType::ICEServerPeerInformation,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainGatekeeper>(&_gatekeeper, &DomainGatekeeper::processICEPeerInformationPacket));
|
||||
|
||||
packetReceiver.registerListener(PacketType::ICEServerHeartbeatDenied, this, "processICEServerHeartbeatDenialPacket");
|
||||
packetReceiver.registerListener(PacketType::ICEServerHeartbeatACK, this, "processICEServerHeartbeatACK");
|
||||
packetReceiver.registerListener(PacketType::ICEServerHeartbeatDenied,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainServer>(this, &DomainServer::processICEServerHeartbeatDenialPacket));
|
||||
packetReceiver.registerListener(PacketType::ICEServerHeartbeatACK,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainServer>(this, &DomainServer::processICEServerHeartbeatACK));
|
||||
|
||||
packetReceiver.registerListener(PacketType::OctreeDataFileRequest, this, "processOctreeDataRequestMessage");
|
||||
packetReceiver.registerListener(PacketType::OctreeDataPersist, this, "processOctreeDataPersistMessage");
|
||||
packetReceiver.registerListener(PacketType::OctreeDataFileRequest,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainServer>(this, &DomainServer::processOctreeDataRequestMessage));
|
||||
packetReceiver.registerListener(PacketType::OctreeDataPersist,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainServer>(this, &DomainServer::processOctreeDataPersistMessage));
|
||||
|
||||
packetReceiver.registerListener(PacketType::OctreeFileReplacement, this, "handleOctreeFileReplacementRequest");
|
||||
packetReceiver.registerListener(PacketType::DomainContentReplacementFromUrl, this, "handleDomainContentReplacementFromURLRequest");
|
||||
packetReceiver.registerListener(PacketType::OctreeFileReplacement,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainServer>(this, &DomainServer::handleOctreeFileReplacementRequest));
|
||||
packetReceiver.registerListener(PacketType::DomainContentReplacementFromUrl,
|
||||
PacketReceiver::makeUnsourcedListenerReference<DomainServer>(this, &DomainServer::handleDomainContentReplacementFromURLRequest));
|
||||
|
||||
// set a custom packetVersionMatch as the verify packet operator for the udt::Socket
|
||||
nodeList->setPacketFilterOperator(&DomainServer::isPacketVerified);
|
||||
|
@ -1144,7 +1176,7 @@ QUrl DomainServer::oauthAuthorizationURL(const QUuid& stateUUID) {
|
|||
QUrl authorizationURL = _oauthProviderURL;
|
||||
|
||||
const QString OAUTH_AUTHORIZATION_PATH = "/oauth/authorize";
|
||||
authorizationURL.setPath(OAUTH_AUTHORIZATION_PATH);
|
||||
authorizationURL.setPath(MetaverseAPI::getCurrentMetaverseServerURLPath() + OAUTH_AUTHORIZATION_PATH);
|
||||
|
||||
QUrlQuery authorizationQuery;
|
||||
|
||||
|
@ -1422,7 +1454,7 @@ void DomainServer::sendPendingTransactionsToServer() {
|
|||
transactionCallbackParams.jsonCallbackMethod = "transactionJSONCallback";
|
||||
|
||||
while (i != _pendingAssignmentCredits.end()) {
|
||||
accountManager->sendRequest("api/v1/transactions",
|
||||
accountManager->sendRequest("/api/v1/transactions",
|
||||
AccountManagerAuth::Required,
|
||||
QNetworkAccessManager::PostOperation,
|
||||
transactionCallbackParams, i.value()->postJson().toJson());
|
||||
|
@ -1608,7 +1640,7 @@ void DomainServer::sendICEServerAddressToMetaverseAPI() {
|
|||
callbackParameters.errorCallbackMethod = "handleFailedICEServerAddressUpdate";
|
||||
callbackParameters.jsonCallbackMethod = "handleSuccessfulICEServerAddressUpdate";
|
||||
|
||||
qCDebug(domain_server_ice) << "Updating ice-server address in High Fidelity Metaverse API to"
|
||||
qCDebug(domain_server_ice) << "Updating ice-server address in Metaverse API to"
|
||||
<< (_iceServerSocket.isNull() ? "" : _iceServerSocket.getAddress().toString());
|
||||
|
||||
static const QString DOMAIN_ICE_ADDRESS_UPDATE = "/api/v1/domains/%1/ice_server_address";
|
||||
|
@ -1967,6 +1999,7 @@ const QString URI_OAUTH = "/oauth";
|
|||
bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler) {
|
||||
const QString JSON_MIME_TYPE = "application/json";
|
||||
|
||||
const QString URI_ID = "/id";
|
||||
const QString URI_ASSIGNMENT = "/assignment";
|
||||
const QString URI_NODES = "/nodes";
|
||||
const QString URI_SETTINGS = "/settings";
|
||||
|
@ -2043,7 +2076,6 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
|||
}
|
||||
|
||||
// check if this is a request for our domain ID
|
||||
const QString URI_ID = "/id";
|
||||
if (connection->requestOperation() == QNetworkAccessManager::GetOperation
|
||||
&& url.path() == URI_ID) {
|
||||
QUuid domainID = nodeList->getSessionUUID();
|
||||
|
@ -2550,7 +2582,7 @@ bool DomainServer::handleHTTPSRequest(HTTPSConnection* connection, const QUrl &u
|
|||
|
||||
const QString OAUTH_TOKEN_REQUEST_PATH = "/oauth/token";
|
||||
QUrl tokenRequestUrl = _oauthProviderURL;
|
||||
tokenRequestUrl.setPath(OAUTH_TOKEN_REQUEST_PATH);
|
||||
tokenRequestUrl.setPath(MetaverseAPI::getCurrentMetaverseServerURLPath() + OAUTH_TOKEN_REQUEST_PATH);
|
||||
|
||||
const QString OAUTH_GRANT_TYPE_POST_STRING = "grant_type=authorization_code";
|
||||
QString tokenPostBody = OAUTH_GRANT_TYPE_POST_STRING;
|
||||
|
@ -2864,7 +2896,7 @@ QNetworkReply* DomainServer::profileRequestGivenTokenReply(QNetworkReply* tokenR
|
|||
|
||||
// fire off a request to get this user's identity so we can see if we will let them in
|
||||
QUrl profileURL = _oauthProviderURL;
|
||||
profileURL.setPath("/api/v1/user/profile");
|
||||
profileURL.setPath(MetaverseAPI::getCurrentMetaverseServerURLPath() + "/api/v1/user/profile");
|
||||
profileURL.setQuery(QString("%1=%2").arg(OAUTH_JSON_ACCESS_TOKEN_KEY, accessToken));
|
||||
|
||||
qDebug() << "Sending profile request to: " << profileURL;
|
||||
|
@ -3039,8 +3071,7 @@ void DomainServer::updateUpstreamNodes() {
|
|||
updateReplicationNodes(Upstream);
|
||||
}
|
||||
|
||||
void DomainServer::initializeExporter()
|
||||
{
|
||||
void DomainServer::initializeExporter() {
|
||||
static const QString ENABLE_EXPORTER = "monitoring.enable_prometheus_exporter";
|
||||
static const QString EXPORTER_PORT = "monitoring.prometheus_exporter_port";
|
||||
|
||||
|
@ -3056,7 +3087,39 @@ void DomainServer::initializeExporter()
|
|||
|
||||
if (isExporterEnabled && !_httpExporterManager) {
|
||||
qCInfo(domain_server) << "Starting Prometheus exporter on port " << exporterPort;
|
||||
_httpExporterManager = new HTTPManager(QHostAddress::Any, (quint16)exporterPort, QString("%1/resources/prometheus_exporter/").arg(QCoreApplication::applicationDirPath()), &_exporter);
|
||||
_httpExporterManager = new HTTPManager
|
||||
(
|
||||
QHostAddress::Any,
|
||||
(quint16)exporterPort,
|
||||
QString("%1/resources/prometheus_exporter/").arg(QCoreApplication::applicationDirPath()),
|
||||
&_exporter
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void DomainServer::initializeMetadataExporter() {
|
||||
static const QString ENABLE_EXPORTER = "metaverse.enable_metadata_exporter";
|
||||
static const QString EXPORTER_PORT = "metaverse.metadata_exporter_port";
|
||||
|
||||
bool isMetadataExporterEnabled = _settingsManager.valueOrDefaultValueForKeyPath(ENABLE_EXPORTER).toBool();
|
||||
int metadataExporterPort = _settingsManager.valueOrDefaultValueForKeyPath(EXPORTER_PORT).toInt();
|
||||
|
||||
if (metadataExporterPort < MIN_PORT || metadataExporterPort > MAX_PORT) {
|
||||
qCWarning(domain_server) << "Metadata exporter port" << metadataExporterPort << "is out of range.";
|
||||
isMetadataExporterEnabled = false;
|
||||
}
|
||||
|
||||
qCDebug(domain_server) << "Setting up Metadata exporter.";
|
||||
|
||||
if (isMetadataExporterEnabled && !_httpMetadataExporterManager) {
|
||||
qCInfo(domain_server) << "Starting Metadata exporter on port" << metadataExporterPort;
|
||||
_httpMetadataExporterManager = new HTTPManager
|
||||
(
|
||||
QHostAddress::Any,
|
||||
(quint16)metadataExporterPort,
|
||||
QString("%1/resources/metadata_exporter/").arg(QCoreApplication::applicationDirPath()),
|
||||
_metadata
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3682,7 +3745,7 @@ void DomainServer::screensharePresence(QString roomname, QUuid avatarID, int exp
|
|||
callbackData.insert("roomname", roomname);
|
||||
callbackData.insert("avatarID", avatarID.toString());
|
||||
callbackParams.callbackData = callbackData;
|
||||
const QString PATH = "api/v1/domains/%1/screenshare";
|
||||
const QString PATH = "/api/v1/domains/%1/screenshare";
|
||||
QString domain_id = uuidStringWithoutCurlyBraces(getID());
|
||||
QJsonObject json, screenshare;
|
||||
screenshare["username"] = verifiedUsername;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Stephen Birarda on 9/26/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -140,6 +141,7 @@ private slots:
|
|||
void updateDownstreamNodes();
|
||||
void updateUpstreamNodes();
|
||||
void initializeExporter();
|
||||
void initializeMetadataExporter();
|
||||
|
||||
void tokenGrantFinished();
|
||||
void profileRequestFinished();
|
||||
|
@ -240,6 +242,8 @@ private:
|
|||
|
||||
HTTPManager _httpManager;
|
||||
HTTPManager* _httpExporterManager { nullptr };
|
||||
HTTPManager* _httpMetadataExporterManager { nullptr };
|
||||
|
||||
std::unique_ptr<HTTPSManager> _httpsManager;
|
||||
|
||||
QHash<QUuid, SharedAssignmentPointer> _allAssignments;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Stephen Birarda on 2014-06-24.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -1998,7 +1999,7 @@ void DomainServerSettingsManager::apiGetGroupID(const QString& groupName) {
|
|||
callbackParams.jsonCallbackMethod = "apiGetGroupIDJSONCallback";
|
||||
callbackParams.errorCallbackMethod = "apiGetGroupIDErrorCallback";
|
||||
|
||||
const QString GET_GROUP_ID_PATH = "api/v1/groups/names/%1";
|
||||
const QString GET_GROUP_ID_PATH = "/api/v1/groups/names/%1";
|
||||
DependencyManager::get<AccountManager>()->sendRequest(GET_GROUP_ID_PATH.arg(groupName),
|
||||
AccountManagerAuth::Required,
|
||||
QNetworkAccessManager::GetOperation, callbackParams);
|
||||
|
@ -2064,7 +2065,7 @@ void DomainServerSettingsManager::apiGetGroupRanks(const QUuid& groupID) {
|
|||
callbackParams.jsonCallbackMethod = "apiGetGroupRanksJSONCallback";
|
||||
callbackParams.errorCallbackMethod = "apiGetGroupRanksErrorCallback";
|
||||
|
||||
const QString GET_GROUP_RANKS_PATH = "api/v1/groups/%1/ranks";
|
||||
const QString GET_GROUP_RANKS_PATH = "/api/v1/groups/%1/ranks";
|
||||
DependencyManager::get<AccountManager>()->sendRequest(GET_GROUP_RANKS_PATH.arg(groupID.toString().mid(1,36)),
|
||||
AccountManagerAuth::Required,
|
||||
QNetworkAccessManager::GetOperation, callbackParams);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Stephen Birarda on 2014-06-24.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -108,7 +109,7 @@ public:
|
|||
QStringList getDomainServerGroupNames();
|
||||
QStringList getDomainServerBlacklistGroupNames();
|
||||
|
||||
// these are used to locally cache the result of calling "api/v1/groups/.../is_member/..." on metaverse's api
|
||||
// these are used to locally cache the result of calling "/api/v1/groups/.../is_member/..." on metaverse's api
|
||||
void clearGroupMemberships(const QString& name) { _groupMembership[name.toLower()].clear(); }
|
||||
void recordGroupMembership(const QString& name, const QUuid groupID, QUuid rankID);
|
||||
QUuid isGroupMember(const QString& name, const QUuid& groupID); // returns rank or -1 if not a member
|
||||
|
@ -211,6 +212,8 @@ private:
|
|||
|
||||
/// guard read/write access from multiple threads to settings
|
||||
QReadWriteLock _settingsLock { QReadWriteLock::Recursive };
|
||||
|
||||
friend class DomainServer;
|
||||
};
|
||||
|
||||
#endif // hifi_DomainServerSettingsManager_h
|
||||
|
|
|
@ -10,7 +10,7 @@ import zipfile
|
|||
|
||||
print = functools.partial(print, flush=True)
|
||||
|
||||
ANDROID_PACKAGE_URL = 'https://content.vircadia.com/eu-c-1/vircadia-public/dependencies/android/'
|
||||
ANDROID_PACKAGE_URL = 'https://cdn-1.vircadia.com/eu-c-1/vircadia-public/dependencies/android/'
|
||||
|
||||
ANDROID_PACKAGES = {
|
||||
'qt' : {
|
||||
|
@ -68,7 +68,7 @@ ANDROID_PACKAGES = {
|
|||
'includeLibs': ['libtbb.so', 'libtbbmalloc.so'],
|
||||
},
|
||||
'hifiAC': {
|
||||
'baseUrl': 'https://content.vircadia.com/eu-c-1/vircadia-public/dependencies/',
|
||||
'baseUrl': 'https://cdn-1.vircadia.com/eu-c-1/vircadia-public/dependencies/',
|
||||
'file': 'codecSDK-android_armv8-2.0.zip',
|
||||
'checksum': '1cbef929675818fc64c4101b72f84a6a'
|
||||
},
|
||||
|
|
|
@ -211,8 +211,15 @@ void IceServer::requestDomainPublicKey(const QUuid& domainID) {
|
|||
auto& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
|
||||
QUrl publicKeyURL{ MetaverseAPI::getCurrentMetaverseServerURL() };
|
||||
// qDebug() << "publicKeyURL" << publicKeyURL;
|
||||
// qDebug() << "MetaverseAPI::getCurrentMetaverseServerURLPath()" << MetaverseAPI::getCurrentMetaverseServerURLPath();
|
||||
QString publicKeyPath = QString("/api/v1/domains/%1/public_key").arg(uuidStringWithoutCurlyBraces(domainID));
|
||||
publicKeyURL.setPath(publicKeyPath);
|
||||
publicKeyURL.setPath("/" + MetaverseAPI::getCurrentMetaverseServerURLPath() + publicKeyPath);
|
||||
// qDebug() << "publicKeyPath" << publicKeyPath;
|
||||
// qDebug() << "publicKeyURL.setPath" << "/" + MetaverseAPI::getCurrentMetaverseServerURLPath() + publicKeyPath;
|
||||
// qDebug() << "publicKeyURL" << publicKeyURL;
|
||||
// qDebug() << "publicKeyURL.isValid()" << publicKeyURL.isValid();
|
||||
// qDebug() << "publicKeyURL.errorString()" << publicKeyURL.errorString();
|
||||
|
||||
QNetworkRequest publicKeyRequest { publicKeyURL };
|
||||
publicKeyRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
|
|
|
@ -238,6 +238,8 @@ target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/libraries
|
|||
target_openssl()
|
||||
|
||||
target_bullet()
|
||||
|
||||
set(OpenGL_GL_PREFERENCE "LEGACY")
|
||||
target_opengl()
|
||||
add_crashpad()
|
||||
target_breakpad()
|
||||
|
|
|
@ -1,861 +1,71 @@
|
|||
{
|
||||
"Anime boy": {
|
||||
"attachments": [
|
||||
],
|
||||
"avatarEntites": [
|
||||
{
|
||||
"properties": {
|
||||
"acceleration": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"actionData": "",
|
||||
"age": 6.915350914001465,
|
||||
"ageAsText": "0 hours 0 minutes 6 seconds",
|
||||
"angularDamping": 0.39346998929977417,
|
||||
"angularVelocity": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"animation": {
|
||||
"allowTranslation": true,
|
||||
"currentFrame": 0,
|
||||
"firstFrame": 0,
|
||||
"fps": 30,
|
||||
"hold": false,
|
||||
"lastFrame": 100000,
|
||||
"loop": true,
|
||||
"running": false,
|
||||
"url": ""
|
||||
},
|
||||
"boundingBox": {
|
||||
"brn": {
|
||||
"x": -0.10961885005235672,
|
||||
"y": -0.19444090127944946,
|
||||
"z": -0.15760529041290283
|
||||
},
|
||||
"center": {
|
||||
"x": 2.6226043701171875e-06,
|
||||
"y": -0.13999652862548828,
|
||||
"z": -0.04999971389770508
|
||||
},
|
||||
"dimensions": {
|
||||
"x": 0.21924294531345367,
|
||||
"y": 0.10888873785734177,
|
||||
"z": 0.2152111530303955
|
||||
},
|
||||
"tfl": {
|
||||
"x": 0.10962409526109695,
|
||||
"y": -0.0855521634221077,
|
||||
"z": 0.057605862617492676
|
||||
}
|
||||
},
|
||||
"canCastShadow": true,
|
||||
"certificateID": "",
|
||||
"clientOnly": true,
|
||||
"cloneAvatarEntity": false,
|
||||
"cloneDynamic": false,
|
||||
"cloneLifetime": 300,
|
||||
"cloneLimit": 0,
|
||||
"cloneOriginID": "{00000000-0000-0000-0000-000000000000}",
|
||||
"cloneable": false,
|
||||
"collidesWith": "",
|
||||
"collisionMask": 0,
|
||||
"collisionSoundURL": "",
|
||||
"collisionless": false,
|
||||
"collisionsWillMove": false,
|
||||
"compoundShapeURL": "",
|
||||
"created": "2018-06-06T17:27:53Z",
|
||||
"damping": 0.39346998929977417,
|
||||
"density": 1000,
|
||||
"description": "",
|
||||
"dimensions": {
|
||||
"x": 0.21924294531345367,
|
||||
"y": 0.07768379896879196,
|
||||
"z": 0.2055898904800415
|
||||
},
|
||||
"dynamic": false,
|
||||
"editionNumber": 15,
|
||||
"entityInstanceNumber": 0,
|
||||
"friction": 0.5,
|
||||
"gravity": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"href": "",
|
||||
"id": "{5d20c775-a0d7-4163-b158-4e0a784a4625}",
|
||||
"ignoreForCollisions": false,
|
||||
"itemArtist": "jyoum",
|
||||
"itemCategories": "Wearables",
|
||||
"itemDescription": "Wear these, and others will respect your authoritah.",
|
||||
"itemLicense": "",
|
||||
"itemName": "Aviators",
|
||||
"jointRotations": [
|
||||
],
|
||||
"jointRotationsSet": [
|
||||
],
|
||||
"jointTranslations": [
|
||||
],
|
||||
"jointTranslationsSet": [
|
||||
],
|
||||
"lastEdited": 1528306178314655,
|
||||
"lastEditedBy": "{439a2669-4626-487f-9dcf-2d15e77c69a2}",
|
||||
"lifetime": -1,
|
||||
"limitedRun": 4294967295,
|
||||
"localPosition": {
|
||||
"x": 2.6226043701171875e-06,
|
||||
"y": -0.13999652862548828,
|
||||
"z": -0.04999971389770508
|
||||
},
|
||||
"localRotation": {
|
||||
"w": 0.9969173073768616,
|
||||
"x": -0.07845909893512726,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"locked": false,
|
||||
"marketplaceID": "40d879ec-93f0-4b4a-8c58-dd6349bdb058",
|
||||
"modelURL": "http://mpassets.highfidelity.com/40d879ec-93f0-4b4a-8c58-dd6349bdb058-v1/Aviator.fbx",
|
||||
"name": "",
|
||||
"naturalDimensions": {
|
||||
"x": 0.1660931408405304,
|
||||
"y": 0.05885136127471924,
|
||||
"z": 0.15574991703033447
|
||||
},
|
||||
"naturalPosition": {
|
||||
"x": 0,
|
||||
"y": 1.6633577346801758,
|
||||
"z": 0.048884183168411255
|
||||
},
|
||||
"originalTextures": "{\n \"aviator:Eyewear2F\": \"http://mpassets.highfidelity.com/40d879ec-93f0-4b4a-8c58-dd6349bdb058-v1/Aviator.fbx/Aviator.fbm/aviator_Eyewear_Diffuse.png\",\n \"aviator:Eyewear2F1\": \"http://mpassets.highfidelity.com/40d879ec-93f0-4b4a-8c58-dd6349bdb058-v1/Aviator.fbx/Aviator.fbm/aviator_Eyewear_Specular.png\"\n}\n",
|
||||
"owningAvatarID": "{439a2669-4626-487f-9dcf-2d15e77c69a2}",
|
||||
"parentID": "{439a2669-4626-487f-9dcf-2d15e77c69a2}",
|
||||
"parentJointIndex": 66,
|
||||
"position": {
|
||||
"x": 2.6226043701171875e-06,
|
||||
"y": -0.13999652862548828,
|
||||
"z": -0.04999971389770508
|
||||
},
|
||||
"queryAACube": {
|
||||
"scale": 0.9313028454780579,
|
||||
"x": -1.4091639518737793,
|
||||
"y": -10.133878707885742,
|
||||
"z": 1.9983724355697632
|
||||
},
|
||||
"registrationPoint": {
|
||||
"x": 0.5,
|
||||
"y": 0.5,
|
||||
"z": 0.5
|
||||
},
|
||||
"relayParentJoints": false,
|
||||
"renderInfo": {
|
||||
"drawCalls": 1,
|
||||
"hasTransparent": false,
|
||||
"texturesCount": 2,
|
||||
"texturesSize": 1310720,
|
||||
"verticesCount": 982
|
||||
},
|
||||
"restitution": 0.5,
|
||||
"rotation": {
|
||||
"w": 0.9969173073768616,
|
||||
"x": -0.07845909893512726,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"script": "",
|
||||
"scriptTimestamp": 0,
|
||||
"serverScripts": "",
|
||||
"shapeType": "box",
|
||||
"staticCertificateVersion": 0,
|
||||
"textures": "",
|
||||
"type": "Model",
|
||||
"userData": "{\"Attachment\":{\"action\":\"attach\",\"joint\":\"HeadTop_End\",\"attached\":false,\"options\":{\"translation\":{\"x\":0,\"y\":0,\"z\":0},\"scale\":1}},\"grabbableKey\":{\"cloneable\":false,\"grabbable\":true}}",
|
||||
"velocity": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"visible": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"avatarScale": 1,
|
||||
"avatarUrl": "http://mpassets.highfidelity.com/46e0fd52-3cff-462f-ba97-927338d88295-v1/AnimeBoy2.fst",
|
||||
"version": 3
|
||||
},
|
||||
"Anime girl": {
|
||||
"attachments": [
|
||||
],
|
||||
"avatarEntites": [
|
||||
{
|
||||
"properties": {
|
||||
"acceleration": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"actionData": "",
|
||||
"age": 19.66267967224121,
|
||||
"ageAsText": "0 hours 0 minutes 19 seconds",
|
||||
"angularDamping": 0.39346998929977417,
|
||||
"angularVelocity": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"animation": {
|
||||
"allowTranslation": true,
|
||||
"currentFrame": 0,
|
||||
"firstFrame": 0,
|
||||
"fps": 30,
|
||||
"hold": false,
|
||||
"lastFrame": 100000,
|
||||
"loop": true,
|
||||
"running": false,
|
||||
"url": ""
|
||||
},
|
||||
"boundingBox": {
|
||||
"brn": {
|
||||
"x": -0.10536206513643265,
|
||||
"y": -0.16647332906723022,
|
||||
"z": -0.12632352113723755
|
||||
},
|
||||
"center": {
|
||||
"x": 0,
|
||||
"y": -0.12999999523162842,
|
||||
"z": -0.030000001192092896
|
||||
},
|
||||
"dimensions": {
|
||||
"x": 0.2107241302728653,
|
||||
"y": 0.07294666767120361,
|
||||
"z": 0.1926470398902893
|
||||
},
|
||||
"tfl": {
|
||||
"x": 0.10536206513643265,
|
||||
"y": -0.09352666139602661,
|
||||
"z": 0.06632351875305176
|
||||
}
|
||||
},
|
||||
"canCastShadow": true,
|
||||
"certificateID": "",
|
||||
"clientOnly": true,
|
||||
"cloneAvatarEntity": false,
|
||||
"cloneDynamic": false,
|
||||
"cloneLifetime": 300,
|
||||
"cloneLimit": 0,
|
||||
"cloneOriginID": "{00000000-0000-0000-0000-000000000000}",
|
||||
"cloneable": false,
|
||||
"collidesWith": "",
|
||||
"collisionMask": 0,
|
||||
"collisionSoundURL": "",
|
||||
"collisionless": false,
|
||||
"collisionsWillMove": false,
|
||||
"compoundShapeURL": "",
|
||||
"created": "2018-06-05T00:10:37Z",
|
||||
"damping": 0.39346998929977417,
|
||||
"density": 1000,
|
||||
"description": "",
|
||||
"dimensions": {
|
||||
"x": 0.2107241302728653,
|
||||
"y": 0.07294666767120361,
|
||||
"z": 0.1926470398902893
|
||||
},
|
||||
"dynamic": false,
|
||||
"editionNumber": 5,
|
||||
"entityInstanceNumber": 0,
|
||||
"friction": 0.5,
|
||||
"gravity": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"href": "",
|
||||
"id": "{1586b83a-2af7-4532-9bfb-82fe3f5d5ce9}",
|
||||
"ignoreForCollisions": false,
|
||||
"itemArtist": "moam_00",
|
||||
"itemCategories": "Wearables",
|
||||
"itemDescription": "Perfect for side-glancin'.",
|
||||
"itemLicense": "",
|
||||
"itemName": "Blacker Fem Glasses",
|
||||
"jointRotations": [
|
||||
],
|
||||
"jointRotationsSet": [
|
||||
],
|
||||
"jointTranslations": [
|
||||
],
|
||||
"jointTranslationsSet": [
|
||||
],
|
||||
"lastEdited": 1528157470041658,
|
||||
"lastEditedBy": "{425df1a8-289b-42fc-819c-c3b2a12d7165}",
|
||||
"lifetime": -1,
|
||||
"limitedRun": 4294967295,
|
||||
"localPosition": {
|
||||
"x": 0,
|
||||
"y": -0.12999999523162842,
|
||||
"z": -0.029999999329447746
|
||||
},
|
||||
"localRotation": {
|
||||
"w": 1,
|
||||
"x": -2.2351741790771484e-08,
|
||||
"y": 3.4924596548080444e-10,
|
||||
"z": 3.725290298461914e-09
|
||||
},
|
||||
"locked": false,
|
||||
"marketplaceID": "06781d12-9139-48f4-ac2a-417dde090981",
|
||||
"modelURL": "http://mpassets.highfidelity.com/06781d12-9139-48f4-ac2a-417dde090981-v1/FemGlasses03.fbx",
|
||||
"name": "Female Glasses 3 by Mario Andrade",
|
||||
"naturalDimensions": {
|
||||
"x": 0.16209548711776733,
|
||||
"y": 0.05611282214522362,
|
||||
"z": 0.14819003641605377
|
||||
},
|
||||
"naturalPosition": {
|
||||
"x": 0,
|
||||
"y": -7.636845111846924e-08,
|
||||
"z": 0
|
||||
},
|
||||
"originalTextures": "{\n \"file49\": \"http://mpassets.highfidelity.com/06781d12-9139-48f4-ac2a-417dde090981-v1/FemGlasses03.fbx/FemGlasses03.fbm/FemGlasses03Mat_Mixed_AO.jpg\",\n \"file81\": \"http://mpassets.highfidelity.com/06781d12-9139-48f4-ac2a-417dde090981-v1/FemGlasses03.fbx/FemGlasses03.fbm/FemGlasses03Mat_Metallic.jpg\",\n \"file84\": \"http://mpassets.highfidelity.com/06781d12-9139-48f4-ac2a-417dde090981-v1/FemGlasses03.fbx/FemGlasses03.fbm/FemGlasses03Mat_Roughness.jpg\",\n \"file86\": \"http://mpassets.highfidelity.com/06781d12-9139-48f4-ac2a-417dde090981-v1/FemGlasses03.fbx/FemGlasses03.fbm/FemGlasses03Mat_Base_Color.jpg\",\n \"file87\": \"http://mpassets.highfidelity.com/06781d12-9139-48f4-ac2a-417dde090981-v1/FemGlasses03.fbx/FemGlasses03.fbm/FemGlasses03Mat_Normal_DirectX.jpg\"\n}\n",
|
||||
"owningAvatarID": "{1277f725-fbb4-478b-ae79-1241fd90e508}",
|
||||
"parentID": "{1277f725-fbb4-478b-ae79-1241fd90e508}",
|
||||
"parentJointIndex": 66,
|
||||
"position": {
|
||||
"x": 0,
|
||||
"y": -0.12999999523162842,
|
||||
"z": -0.029999999329447746
|
||||
},
|
||||
"queryAACube": {
|
||||
"scale": 0.8840523958206177,
|
||||
"x": -2.6587564945220947,
|
||||
"y": -10.162277221679688,
|
||||
"z": -0.9548344016075134
|
||||
},
|
||||
"registrationPoint": {
|
||||
"x": 0.5,
|
||||
"y": 0.5,
|
||||
"z": 0.5
|
||||
},
|
||||
"relayParentJoints": false,
|
||||
"renderInfo": {
|
||||
"drawCalls": 1,
|
||||
"hasTransparent": false,
|
||||
"texturesCount": 5,
|
||||
"texturesSize": 0,
|
||||
"verticesCount": 1156
|
||||
},
|
||||
"restitution": 0.5,
|
||||
"rotation": {
|
||||
"w": 1,
|
||||
"x": -2.2351741790771484e-08,
|
||||
"y": 3.4924596548080444e-10,
|
||||
"z": 3.725290298461914e-09
|
||||
},
|
||||
"script": "",
|
||||
"scriptTimestamp": 0,
|
||||
"serverScripts": "",
|
||||
"shapeType": "box",
|
||||
"staticCertificateVersion": 0,
|
||||
"textures": "",
|
||||
"type": "Model",
|
||||
"userData": "{\"Attachment\":{\"action\":\"attach\",\"joint\":\"HeadTop_End\",\"attached\":false,\"options\":{\"translation\":{\"x\":0,\"y\":0,\"z\":0},\"scale\":1}},\"grabbableKey\":{\"cloneable\":false,\"grabbable\":true}}",
|
||||
"velocity": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"visible": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"avatarScale": 1,
|
||||
"avatarUrl": "http://mpassets.highfidelity.com/0dce3426-55c8-4641-8dd5-d76eb575b64a-v1/Anime_F_Outfit.fst",
|
||||
"version": 3
|
||||
},
|
||||
"Last Legends: Male": {
|
||||
"attachments": [
|
||||
],
|
||||
"avatarEntites": [
|
||||
{
|
||||
"properties": {
|
||||
"acceleration": {
|
||||
"blue": 0,
|
||||
"green": 0,
|
||||
"red": 0,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"actionData": "",
|
||||
"age": 321.8835144042969,
|
||||
"ageAsText": "0 hours 5 minutes 21 seconds",
|
||||
"angularDamping": 0.39346998929977417,
|
||||
"angularVelocity": {
|
||||
"blue": 0,
|
||||
"green": 0,
|
||||
"red": 0,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"animation": {
|
||||
"allowTranslation": true,
|
||||
"currentFrame": 0,
|
||||
"firstFrame": 0,
|
||||
"fps": 30,
|
||||
"hold": false,
|
||||
"lastFrame": 100000,
|
||||
"loop": true,
|
||||
"running": false,
|
||||
"url": ""
|
||||
},
|
||||
"boundingBox": {
|
||||
"brn": {
|
||||
"blue": -0.03950843587517738,
|
||||
"green": 0.20785385370254517,
|
||||
"red": -0.04381325840950012,
|
||||
"x": -0.04381325840950012,
|
||||
"y": 0.20785385370254517,
|
||||
"z": -0.03950843587517738
|
||||
},
|
||||
"center": {
|
||||
"blue": 0,
|
||||
"green": 0.23000000417232513,
|
||||
"red": 0,
|
||||
"x": 0,
|
||||
"y": 0.23000000417232513,
|
||||
"z": 0
|
||||
},
|
||||
"dimensions": {
|
||||
"blue": 0.07901687175035477,
|
||||
"green": 0.044292300939559937,
|
||||
"red": 0.08762651681900024,
|
||||
"x": 0.08762651681900024,
|
||||
"y": 0.044292300939559937,
|
||||
"z": 0.07901687175035477
|
||||
},
|
||||
"tfl": {
|
||||
"blue": 0.03950843587517738,
|
||||
"green": 0.2521461546421051,
|
||||
"red": 0.04381325840950012,
|
||||
"x": 0.04381325840950012,
|
||||
"y": 0.2521461546421051,
|
||||
"z": 0.03950843587517738
|
||||
}
|
||||
},
|
||||
"canCastShadow": true,
|
||||
"certificateID": "",
|
||||
"clientOnly": true,
|
||||
"cloneAvatarEntity": false,
|
||||
"cloneDynamic": false,
|
||||
"cloneLifetime": 300,
|
||||
"cloneLimit": 0,
|
||||
"cloneOriginID": "{00000000-0000-0000-0000-000000000000}",
|
||||
"cloneable": false,
|
||||
"collidesWith": "",
|
||||
"collisionMask": 0,
|
||||
"collisionSoundURL": "",
|
||||
"collisionless": false,
|
||||
"collisionsWillMove": false,
|
||||
"compoundShapeURL": "",
|
||||
"created": "2018-07-26T23:56:46Z",
|
||||
"damping": 0.39346998929977417,
|
||||
"density": 1000,
|
||||
"description": "",
|
||||
"dimensions": {
|
||||
"blue": 0.07229919731616974,
|
||||
"green": 0.06644226610660553,
|
||||
"red": 0.03022606298327446,
|
||||
"x": 0.03022606298327446,
|
||||
"y": 0.06644226610660553,
|
||||
"z": 0.07229919731616974
|
||||
},
|
||||
"dynamic": false,
|
||||
"editionNumber": 58,
|
||||
"entityInstanceNumber": 0,
|
||||
"friction": 0.5,
|
||||
"gravity": {
|
||||
"blue": 0,
|
||||
"green": 0,
|
||||
"red": 0,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"href": "",
|
||||
"id": "{03053239-bb37-4c51-a013-a1772baaeed5}",
|
||||
"ignoreForCollisions": false,
|
||||
"itemArtist": "jyoum",
|
||||
"itemCategories": "Wearables",
|
||||
"itemDescription": "A cool scifi watch for your avatar!",
|
||||
"itemLicense": "",
|
||||
"itemName": "Scifi Watch",
|
||||
"jointRotations": [
|
||||
],
|
||||
"jointRotationsSet": [
|
||||
],
|
||||
"jointTranslations": [
|
||||
],
|
||||
"jointTranslationsSet": [
|
||||
],
|
||||
"lastEdited": 1532649569894305,
|
||||
"lastEditedBy": "{042ac463-7879-40f0-8126-e2e56c4345ca}",
|
||||
"lifetime": -1,
|
||||
"limitedRun": 4294967295,
|
||||
"localPosition": {
|
||||
"blue": 0,
|
||||
"green": 0.23000000417232513,
|
||||
"red": 0,
|
||||
"x": 0,
|
||||
"y": 0.23000000417232513,
|
||||
"z": 0
|
||||
},
|
||||
"localRotation": {
|
||||
"w": 0.5910986065864563,
|
||||
"x": -0.48726415634155273,
|
||||
"y": -0.4088630974292755,
|
||||
"z": 0.49599072337150574
|
||||
},
|
||||
"locked": false,
|
||||
"marketplaceID": "0685794d-fddb-4bad-a608-6d7789ceda90",
|
||||
"modelURL": "http://mpassets.highfidelity.com/0685794d-fddb-4bad-a608-6d7789ceda90-v1/ScifiWatch.fbx",
|
||||
"name": "Scifi Watch by Jimi",
|
||||
"naturalDimensions": {
|
||||
"blue": 0.055614765733480453,
|
||||
"green": 0.0511094331741333,
|
||||
"red": 0.023250818252563477,
|
||||
"x": 0.023250818252563477,
|
||||
"y": 0.0511094331741333,
|
||||
"z": 0.055614765733480453
|
||||
},
|
||||
"naturalPosition": {
|
||||
"blue": -0.06031447649002075,
|
||||
"green": 1.4500460624694824,
|
||||
"red": 0.6493338942527771,
|
||||
"x": 0.6493338942527771,
|
||||
"y": 1.4500460624694824,
|
||||
"z": -0.06031447649002075
|
||||
},
|
||||
"originalTextures": "{\n \"file4\": \"http://mpassets.highfidelity.com/0685794d-fddb-4bad-a608-6d7789ceda90-v1/ScifiWatch.fbx/ScifiWatch/texture/lambert1_Base_Color.png\",\n \"file5\": \"http://mpassets.highfidelity.com/0685794d-fddb-4bad-a608-6d7789ceda90-v1/ScifiWatch.fbx/ScifiWatch/texture/lambert1_Normal_OpenGL.png\",\n \"file6\": \"http://mpassets.highfidelity.com/0685794d-fddb-4bad-a608-6d7789ceda90-v1/ScifiWatch.fbx/ScifiWatch/texture/lambert1_Metallic.png\",\n \"file7\": \"http://mpassets.highfidelity.com/0685794d-fddb-4bad-a608-6d7789ceda90-v1/ScifiWatch.fbx/ScifiWatch/texture/lambert1_Roughness.png\",\n \"file8\": \"http://mpassets.highfidelity.com/0685794d-fddb-4bad-a608-6d7789ceda90-v1/ScifiWatch.fbx/ScifiWatch/texture/lambert1_Emissive.png\"\n}\n",
|
||||
"owningAvatarID": "{042ac463-7879-40f0-8126-e2e56c4345ca}",
|
||||
"parentID": "{042ac463-7879-40f0-8126-e2e56c4345ca}",
|
||||
"parentJointIndex": 16,
|
||||
"position": {
|
||||
"blue": 0,
|
||||
"green": 0.23000000417232513,
|
||||
"red": 0,
|
||||
"x": 0,
|
||||
"y": 0.23000000417232513,
|
||||
"z": 0
|
||||
},
|
||||
"queryAACube": {
|
||||
"scale": 0.3082179129123688,
|
||||
"x": 495.7716979980469,
|
||||
"y": 498.345703125,
|
||||
"z": 498.52044677734375
|
||||
},
|
||||
"registrationPoint": {
|
||||
"blue": 0.5,
|
||||
"green": 0.5,
|
||||
"red": 0.5,
|
||||
"x": 0.5,
|
||||
"y": 0.5,
|
||||
"z": 0.5
|
||||
},
|
||||
"relayParentJoints": false,
|
||||
"renderInfo": {
|
||||
"drawCalls": 1,
|
||||
"hasTransparent": false,
|
||||
"texturesCount": 5,
|
||||
"texturesSize": 786432,
|
||||
"verticesCount": 273
|
||||
},
|
||||
"restitution": 0.5,
|
||||
"rotation": {
|
||||
"w": 0.5910986065864563,
|
||||
"x": -0.48726415634155273,
|
||||
"y": -0.4088630974292755,
|
||||
"z": 0.49599072337150574
|
||||
},
|
||||
"script": "",
|
||||
"scriptTimestamp": 0,
|
||||
"serverScripts": "",
|
||||
"shapeType": "box",
|
||||
"staticCertificateVersion": 0,
|
||||
"textures": "",
|
||||
"type": "Model",
|
||||
"userData": "{\"Attachment\":{\"action\":\"attach\",\"joint\":\"[LR]ForeArm\",\"attached\":false,\"options\":{\"translation\":{\"x\":0,\"y\":0,\"z\":0},\"scale\":1}},\"grabbableKey\":{\"cloneable\":false,\"grabbable\":true}}",
|
||||
"velocity": {
|
||||
"blue": 0,
|
||||
"green": 0,
|
||||
"red": 0,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"visible": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"acceleration": {
|
||||
"blue": 0,
|
||||
"green": 0,
|
||||
"red": 0,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"actionData": "",
|
||||
"age": 308.8044128417969,
|
||||
"ageAsText": "0 hours 5 minutes 8 seconds",
|
||||
"angularDamping": 0.39346998929977417,
|
||||
"angularVelocity": {
|
||||
"blue": 0,
|
||||
"green": 0,
|
||||
"red": 0,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"animation": {
|
||||
"allowTranslation": true,
|
||||
"currentFrame": 0,
|
||||
"firstFrame": 0,
|
||||
"fps": 30,
|
||||
"hold": false,
|
||||
"lastFrame": 100000,
|
||||
"loop": true,
|
||||
"running": false,
|
||||
"url": ""
|
||||
},
|
||||
"boundingBox": {
|
||||
"brn": {
|
||||
"blue": -0.2340194433927536,
|
||||
"green": -0.07067721337080002,
|
||||
"red": -0.17002610862255096,
|
||||
"x": -0.17002610862255096,
|
||||
"y": -0.07067721337080002,
|
||||
"z": -0.2340194433927536
|
||||
},
|
||||
"center": {
|
||||
"blue": -0.039825439453125,
|
||||
"green": 0.02001953125,
|
||||
"red": 0.0001678466796875,
|
||||
"x": 0.0001678466796875,
|
||||
"y": 0.02001953125,
|
||||
"z": -0.039825439453125
|
||||
},
|
||||
"dimensions": {
|
||||
"blue": 0.3883880078792572,
|
||||
"green": 0.18139348924160004,
|
||||
"red": 0.34038791060447693,
|
||||
"x": 0.34038791060447693,
|
||||
"y": 0.18139348924160004,
|
||||
"z": 0.3883880078792572
|
||||
},
|
||||
"tfl": {
|
||||
"blue": 0.1543685644865036,
|
||||
"green": 0.11071627587080002,
|
||||
"red": 0.17036180198192596,
|
||||
"x": 0.17036180198192596,
|
||||
"y": 0.11071627587080002,
|
||||
"z": 0.1543685644865036
|
||||
}
|
||||
},
|
||||
"canCastShadow": true,
|
||||
"certificateID": "",
|
||||
"clientOnly": true,
|
||||
"cloneAvatarEntity": false,
|
||||
"cloneDynamic": false,
|
||||
"cloneLifetime": 300,
|
||||
"cloneLimit": 0,
|
||||
"cloneOriginID": "{00000000-0000-0000-0000-000000000000}",
|
||||
"cloneable": false,
|
||||
"collidesWith": "",
|
||||
"collisionMask": 0,
|
||||
"collisionSoundURL": "",
|
||||
"collisionless": false,
|
||||
"collisionsWillMove": false,
|
||||
"compoundShapeURL": "",
|
||||
"created": "2018-07-26T23:56:46Z",
|
||||
"damping": 0.39346998929977417,
|
||||
"density": 1000,
|
||||
"description": "",
|
||||
"dimensions": {
|
||||
"blue": 0.38838762044906616,
|
||||
"green": 0.16981728374958038,
|
||||
"red": 0.33466479182243347,
|
||||
"x": 0.33466479182243347,
|
||||
"y": 0.16981728374958038,
|
||||
"z": 0.38838762044906616
|
||||
},
|
||||
"dynamic": false,
|
||||
"editionNumber": 18,
|
||||
"entityInstanceNumber": 0,
|
||||
"friction": 0.5,
|
||||
"gravity": {
|
||||
"blue": 0,
|
||||
"green": 0,
|
||||
"red": 0,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"href": "",
|
||||
"id": "{1bf231ce-3913-4c53-be3c-b1f4094dac51}",
|
||||
"ignoreForCollisions": false,
|
||||
"itemArtist": "jyoum",
|
||||
"itemCategories": "Wearables",
|
||||
"itemDescription": "A stylish and classic piece of headwear for your avatar.",
|
||||
"itemLicense": "",
|
||||
"itemName": "Fedora",
|
||||
"jointRotations": [
|
||||
],
|
||||
"jointRotationsSet": [
|
||||
],
|
||||
"jointTranslations": [
|
||||
],
|
||||
"jointTranslationsSet": [
|
||||
],
|
||||
"lastEdited": 1532649698129709,
|
||||
"lastEditedBy": "{042ac463-7879-40f0-8126-e2e56c4345ca}",
|
||||
"lifetime": -1,
|
||||
"limitedRun": 4294967295,
|
||||
"localPosition": {
|
||||
"blue": -0.039825439453125,
|
||||
"green": 0.02001953125,
|
||||
"red": 0.0001678466796875,
|
||||
"x": 0.0001678466796875,
|
||||
"y": 0.02001953125,
|
||||
"z": -0.039825439453125
|
||||
},
|
||||
"localRotation": {
|
||||
"w": 0.9998477101325989,
|
||||
"x": -9.898545982878204e-09,
|
||||
"y": 5.670873406415922e-07,
|
||||
"z": 0.017452405765652657
|
||||
},
|
||||
"locked": false,
|
||||
"marketplaceID": "11c4208d-15d7-4449-9758-a08da6dbd3dc",
|
||||
"modelURL": "http://mpassets.highfidelity.com/11c4208d-15d7-4449-9758-a08da6dbd3dc-v1/Fedora.fbx",
|
||||
"name": "",
|
||||
"naturalDimensions": {
|
||||
"blue": 0.320981502532959,
|
||||
"green": 0.14034485816955566,
|
||||
"red": 0.2765824794769287,
|
||||
"x": 0.2765824794769287,
|
||||
"y": 0.14034485816955566,
|
||||
"z": 0.320981502532959
|
||||
},
|
||||
"naturalPosition": {
|
||||
"blue": 0.022502630949020386,
|
||||
"green": 1.7460365295410156,
|
||||
"red": 0.000143393874168396,
|
||||
"x": 0.000143393874168396,
|
||||
"y": 1.7460365295410156,
|
||||
"z": 0.022502630949020386
|
||||
},
|
||||
"originalTextures": "{\n \"file5\": \"http://mpassets.highfidelity.com/11c4208d-15d7-4449-9758-a08da6dbd3dc-v1/Fedora.fbx/Texture/Fedora_Hat1_Base_Color.png\",\n \"file7\": \"http://mpassets.highfidelity.com/11c4208d-15d7-4449-9758-a08da6dbd3dc-v1/Fedora.fbx/Texture/Fedora_Hat1_Roughness.png\"\n}\n",
|
||||
"owningAvatarID": "{042ac463-7879-40f0-8126-e2e56c4345ca}",
|
||||
"parentID": "{042ac463-7879-40f0-8126-e2e56c4345ca}",
|
||||
"parentJointIndex": 66,
|
||||
"position": {
|
||||
"blue": -0.039825439453125,
|
||||
"green": 0.02001953125,
|
||||
"red": 0.0001678466796875,
|
||||
"x": 0.0001678466796875,
|
||||
"y": 0.02001953125,
|
||||
"z": -0.039825439453125
|
||||
},
|
||||
"queryAACube": {
|
||||
"scale": 1.6202316284179688,
|
||||
"x": 495.21051025390625,
|
||||
"y": 498.5577697753906,
|
||||
"z": 497.6370849609375
|
||||
},
|
||||
"registrationPoint": {
|
||||
"blue": 0.5,
|
||||
"green": 0.5,
|
||||
"red": 0.5,
|
||||
"x": 0.5,
|
||||
"y": 0.5,
|
||||
"z": 0.5
|
||||
},
|
||||
"relayParentJoints": false,
|
||||
"renderInfo": {
|
||||
"drawCalls": 1,
|
||||
"hasTransparent": false,
|
||||
"texturesCount": 2,
|
||||
"texturesSize": 327680,
|
||||
"verticesCount": 719
|
||||
},
|
||||
"restitution": 0.5,
|
||||
"rotation": {
|
||||
"w": 0.9998477101325989,
|
||||
"x": -9.898545982878204e-09,
|
||||
"y": 5.670873406415922e-07,
|
||||
"z": 0.017452405765652657
|
||||
},
|
||||
"script": "",
|
||||
"scriptTimestamp": 0,
|
||||
"serverScripts": "",
|
||||
"shapeType": "box",
|
||||
"staticCertificateVersion": 0,
|
||||
"textures": "",
|
||||
"type": "Model",
|
||||
"userData": "{\"Attachment\":{\"action\":\"attach\",\"joint\":\"HeadTop_End\",\"attached\":false,\"options\":{\"translation\":{\"x\":0,\"y\":0,\"z\":0},\"scale\":1}},\"grabbableKey\":{\"cloneable\":false,\"grabbable\":true}}",
|
||||
"velocity": {
|
||||
"blue": 0,
|
||||
"green": 0,
|
||||
"red": 0,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"visible": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"avatarScale": 1,
|
||||
"avatarUrl": "http://mpassets.highfidelity.com/28569047-6f1a-4100-af67-8054ec397cc3-v1/LLMale2.fst",
|
||||
"version": 3
|
||||
},
|
||||
"Last legends Female": {
|
||||
"attachments": [
|
||||
],
|
||||
"avatarEntites": [
|
||||
],
|
||||
"avatarScale": 1,
|
||||
"avatarUrl": "http://mpassets.highfidelity.com/8d823be5-6197-4418-b984-eb94160ed956-v1/LLFemale_Clothes.fst",
|
||||
"version": 3
|
||||
},
|
||||
"Matthew": {
|
||||
"attachments": [
|
||||
],
|
||||
"avatarEntites": [
|
||||
],
|
||||
"avatarScale": 1,
|
||||
"avatarUrl": "http://mpassets.highfidelity.com/b652081b-a199-425e-ae5c-7815721bdc09-v1/matthew.fst",
|
||||
"version": 3
|
||||
},
|
||||
"Priscilla": {
|
||||
"attachments": [
|
||||
],
|
||||
"avatarEntites": [
|
||||
],
|
||||
"avatarScale": 1,
|
||||
"avatarUrl": "http://mpassets.highfidelity.com/e7565f93-8bc5-47c2-b6eb-b3b31d4a1339-v1/priscilla.fst",
|
||||
"version": 3
|
||||
},
|
||||
"Woody": {
|
||||
"attachments": [
|
||||
],
|
||||
"avatarEntites": [
|
||||
],
|
||||
"avatarScale": 1,
|
||||
"avatarUrl": "http://mpassets.highfidelity.com/ad348528-de38-420c-82bb-054cb22163f5-v1/mannequin.fst",
|
||||
"avatarUrl": "https://cdn-1.vircadia.com/us-e-1/Bazaar/Avatars/Woody/mannequin.fst",
|
||||
"version": 3
|
||||
},
|
||||
"Kim": {
|
||||
"attachments": [
|
||||
],
|
||||
"avatarEntites": [
|
||||
],
|
||||
"avatarScale": 1,
|
||||
"avatarUrl": "https://cdn-1.vircadia.com/us-e-1/Bazaar/Avatars/Kim/fbx/Kim.fst",
|
||||
"avatarIcon": "https://cdn-1.vircadia.com/us-e-1/Bazaar/Avatars/Kim/img/icon.png",
|
||||
"version": 3
|
||||
},
|
||||
"Mason": {
|
||||
"attachments": [
|
||||
],
|
||||
"avatarEntites": [
|
||||
],
|
||||
"avatarScale": 1,
|
||||
"avatarUrl": "https://cdn-1.vircadia.com/us-e-1/Bazaar/Avatars/Mason/fbx/Mason.fst",
|
||||
"avatarIcon": "https://cdn-1.vircadia.com/us-e-1/Bazaar/Avatars/Mason/img/icon.png",
|
||||
"version": 3
|
||||
},
|
||||
"Mike": {
|
||||
"attachments": [
|
||||
],
|
||||
"avatarEntites": [
|
||||
],
|
||||
"avatarScale": 1,
|
||||
"avatarUrl": "https://cdn-1.vircadia.com/us-e-1/Bazaar/Avatars/Mike/fbx/Mike.fst",
|
||||
"avatarIcon": "https://cdn-1.vircadia.com/us-e-1/Bazaar/Avatars/Mike/img/icon.png",
|
||||
"version": 3
|
||||
},
|
||||
"Sean": {
|
||||
"attachments": [
|
||||
],
|
||||
"avatarEntites": [
|
||||
],
|
||||
"avatarScale": 1,
|
||||
"avatarUrl": "https://cdn-1.vircadia.com/us-e-1/Bazaar/Avatars/Sean/fbx/Sean.fst",
|
||||
"avatarIcon": "https://cdn-1.vircadia.com/us-e-1/Bazaar/Avatars/Sean/img/icon.png",
|
||||
"version": 3
|
||||
},
|
||||
"Summer": {
|
||||
"attachments": [
|
||||
],
|
||||
"avatarEntites": [
|
||||
],
|
||||
"avatarScale": 1,
|
||||
"avatarUrl": "https://cdn-1.vircadia.com/us-e-1/Bazaar/Avatars/Summer/fbx/Summer.fst",
|
||||
"avatarIcon": "https://cdn-1.vircadia.com/us-e-1/Bazaar/Avatars/Summer/img/icon.png",
|
||||
"version": 3
|
||||
},
|
||||
"Tanya": {
|
||||
"attachments": [
|
||||
],
|
||||
"avatarEntites": [
|
||||
],
|
||||
"avatarScale": 1,
|
||||
"avatarUrl": "https://cdn-1.vircadia.com/us-e-1/Bazaar/Avatars/Tanya/fbx/Tanya.fst",
|
||||
"avatarIcon": "https://cdn-1.vircadia.com/us-e-1/Bazaar/Avatars/Tanya/img/icon.png",
|
||||
"version": 3
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,9 +3,9 @@
|
|||
"channels": [
|
||||
{ "from": "Keyboard.A", "when": ["Keyboard.RightMouseButton", "!Keyboard.Control"], "to": "Actions.LATERAL_LEFT" },
|
||||
{ "from": "Keyboard.D", "when": ["Keyboard.RightMouseButton", "!Keyboard.Control"], "to": "Actions.LATERAL_RIGHT" },
|
||||
{ "from": "Keyboard.E", "when": ["!Application.CameraSelfie", "!Keyboard.Control"], "to": "Actions.LATERAL_RIGHT" },
|
||||
{ "from": "Keyboard.Q", "when": ["!Application.CameraSelfie", "!Keyboard.Control"], "to": "Actions.LATERAL_LEFT" },
|
||||
{ "from": "Keyboard.Q", "when": ["!Application.CameraSelfie", "!Keyboard.Control", "!Application.CaptureMouse"], "to": "Actions.LATERAL_LEFT" },
|
||||
{ "from": "Keyboard.Q", "when": ["Application.CameraSelfie", "!Keyboard.Control"], "to": "Actions.LATERAL_RIGHT" },
|
||||
{ "from": "Keyboard.E", "when": ["!Application.CameraSelfie", "!Keyboard.Control", "!Application.CaptureMouse"], "to": "Actions.LATERAL_RIGHT" },
|
||||
{ "from": "Keyboard.E", "when": ["Application.CameraSelfie", "!Keyboard.Control"], "to": "Actions.LATERAL_LEFT" },
|
||||
{ "from": "Keyboard.T", "when": "!Keyboard.Control", "to": "Actions.TogglePushToTalk" },
|
||||
|
||||
|
@ -72,46 +72,20 @@
|
|||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.Left"],
|
||||
["Keyboard.Right"]
|
||||
]
|
||||
]
|
||||
},
|
||||
"when": ["Application.CameraFirstPerson", "!Keyboard.Shift"],
|
||||
"when": ["!Application.CameraFSM", "!Application.CameraIndependent", "!Application.CameraEntity", "!Application.CaptureMouse", "!Keyboard.Shift"],
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.Left"],
|
||||
["Keyboard.Right"]
|
||||
]
|
||||
},
|
||||
"when": ["Application.CameraFirstPersonLookat", "!Keyboard.Shift"],
|
||||
"to": "Actions.Yaw"
|
||||
{ "from": "Keyboard.Left",
|
||||
"when": ["!Application.CameraFSM", "!Application.CameraIndependent", "!Application.CameraEntity", "Application.CaptureMouse", "!Keyboard.Shift"],
|
||||
"to": "Actions.LATERAL_LEFT"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.Left"],
|
||||
["Keyboard.Right"]
|
||||
]
|
||||
},
|
||||
"when": ["Application.CameraThirdPerson", "!Keyboard.Shift"],
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.Left"],
|
||||
["Keyboard.Right"]
|
||||
]
|
||||
},
|
||||
"when": ["Application.CameraLookAt", "!Keyboard.Shift"],
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.Left"],
|
||||
["Keyboard.Right"]
|
||||
]
|
||||
},
|
||||
"when": ["Application.CameraSelfie", "!Keyboard.Shift"],
|
||||
"to": "Actions.Yaw"
|
||||
{ "from": "Keyboard.Right",
|
||||
"when": ["!Application.CameraFSM", "!Application.CameraIndependent", "!Application.CameraEntity", "Application.CaptureMouse", "!Keyboard.Shift"],
|
||||
"to": "Actions.LATERAL_RIGHT"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
|
@ -119,53 +93,18 @@
|
|||
["Keyboard.D"]
|
||||
]
|
||||
},
|
||||
"when": ["Application.CameraFirstPerson", "!Keyboard.Control"],
|
||||
"when": ["!Application.CameraFSM", "!Application.CameraIndependent", "!Application.CameraEntity", "!Application.CaptureMouse", "!Keyboard.Control"],
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.A"],
|
||||
["Keyboard.D"]
|
||||
]
|
||||
},
|
||||
"when": ["Application.CameraFirstPersonLookat", "!Keyboard.Control"],
|
||||
"to": "Actions.Yaw"
|
||||
{ "from": "Keyboard.A",
|
||||
"when": ["!Application.CameraFSM", "!Application.CameraIndependent", "!Application.CameraEntity", "Application.CaptureMouse", "!Keyboard.Control"],
|
||||
"to": "Actions.LATERAL_LEFT"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.A"],
|
||||
["Keyboard.D"]
|
||||
]
|
||||
},
|
||||
"when": ["Application.CameraThirdPerson", "!Keyboard.Control"],
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.A"],
|
||||
["Keyboard.D"]
|
||||
]
|
||||
},
|
||||
"when": ["Application.CameraLookAt", "!Keyboard.Control"],
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.A"],
|
||||
["Keyboard.D"]
|
||||
]
|
||||
},
|
||||
"when": ["Application.CameraSelfie", "!Keyboard.Control"],
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.TouchpadLeft"],
|
||||
["Keyboard.TouchpadRight"]
|
||||
]
|
||||
},
|
||||
"when": "Application.CameraFirstPerson",
|
||||
"to": "Actions.Yaw"
|
||||
{ "from": "Keyboard.D",
|
||||
"when": ["!Application.CameraFSM", "!Application.CameraIndependent", "!Application.CameraEntity", "Application.CaptureMouse", "!Keyboard.Control"],
|
||||
"to": "Actions.LATERAL_RIGHT"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
|
@ -173,39 +112,12 @@
|
|||
["Keyboard.TouchpadRight"]
|
||||
]
|
||||
},
|
||||
"when": "Application.CameraFirstPersonLookat",
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.TouchpadLeft"],
|
||||
["Keyboard.TouchpadRight"]
|
||||
]
|
||||
},
|
||||
"when": "Application.CameraThirdPerson",
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.TouchpadLeft"],
|
||||
["Keyboard.TouchpadRight"]
|
||||
]
|
||||
},
|
||||
"when": "Application.CameraLookAt",
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : [
|
||||
["Keyboard.TouchpadLeft"],
|
||||
["Keyboard.TouchpadRight"]
|
||||
]
|
||||
},
|
||||
"when": "Application.CameraSelfie",
|
||||
"when": ["!Application.CameraFSM", "!Application.CameraIndependent", "!Application.CameraEntity"],
|
||||
"to": "Actions.Yaw"
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : ["Keyboard.MouseMoveLeft", "Keyboard.MouseMoveRight"] },
|
||||
"when": "Keyboard.RightMouseButton",
|
||||
"when": ["Keyboard.RightMouseButton", "!Application.CaptureMouse"],
|
||||
"to": "Actions.DeltaYaw",
|
||||
"filters":
|
||||
[
|
||||
|
@ -213,8 +125,17 @@
|
|||
]
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : ["Keyboard.MouseMoveLeft", "Keyboard.MouseMoveRight"] },
|
||||
"to": "Actions.DeltaYaw",
|
||||
"when": "Application.CaptureMouse",
|
||||
"filters":
|
||||
[
|
||||
{ "type": "scale", "scale": 0.2 }
|
||||
]
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : ["Keyboard.MouseMoveUp", "Keyboard.MouseMoveDown"] },
|
||||
"when": ["!Application.CameraSelfie", "!Application.CameraLookAt", "Keyboard.RightMouseButton"],
|
||||
"when": ["!Application.CameraSelfie", "!Application.CameraLookAt", "!Application.CaptureMouse", "Keyboard.RightMouseButton"],
|
||||
"to": "Actions.DeltaPitch",
|
||||
"filters":
|
||||
[
|
||||
|
@ -222,6 +143,15 @@
|
|||
]
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : ["Keyboard.MouseMoveUp", "Keyboard.MouseMoveDown"] },
|
||||
"to": "Actions.DeltaPitch",
|
||||
"when": "Application.CaptureMouse",
|
||||
"filters":
|
||||
[
|
||||
{ "type": "scale", "scale": 0.2 }
|
||||
]
|
||||
},
|
||||
|
||||
{ "from": { "makeAxis" : ["Keyboard.MouseMoveUp", "Keyboard.MouseMoveDown"] },
|
||||
"when": ["Application.CameraLookAt", "Keyboard.RightMouseButton"],
|
||||
"to": "Actions.DeltaPitch",
|
||||
|
|
BIN
interface/resources/fonts/vircadia_glyphs.ttf
Normal file
BIN
interface/resources/fonts/vircadia_glyphs.ttf
Normal file
Binary file not shown.
|
@ -386,6 +386,10 @@ Item {
|
|||
visible: root.expanded
|
||||
text: "LOD: " + root.lodStatus;
|
||||
}
|
||||
StatText {
|
||||
visible: root.expanded
|
||||
text: "Entity Updates: " + root.numEntityUpdates + " / " + root.numNeededEntityUpdates;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ WebView {
|
|||
id: webview
|
||||
url: "https://vircadia.com/"
|
||||
profile: FileTypeProfile;
|
||||
|
||||
property var parentRoot: null
|
||||
|
||||
// Create a global EventBridge object for raiseAndLowerKeyboard.
|
||||
|
|
|
@ -49,6 +49,12 @@ ScrollingWindow {
|
|||
desktop.setAutoAdd(auto);
|
||||
}
|
||||
|
||||
function openExternalBrowser() {
|
||||
Qt.openUrlExternally(addressBar.text);
|
||||
root.shown = false;
|
||||
root.windowClosed();
|
||||
}
|
||||
|
||||
Item {
|
||||
id:item
|
||||
width: pane.contentWidth
|
||||
|
@ -58,34 +64,49 @@ ScrollingWindow {
|
|||
id: buttons
|
||||
spacing: 4
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.topMargin: 4
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
HiFiGlyphs {
|
||||
id: back;
|
||||
enabled: webview.canGoBack;
|
||||
id: back
|
||||
enabled: webview.canGoBack
|
||||
text: hifi.glyphs.backward
|
||||
color: enabled ? hifi.colors.text : hifi.colors.disabledText
|
||||
color: enabled ? (backMouseArea.containsMouse ? hifi.colors.blueHighlight : hifi.colors.faintGray) : hifi.colors.lightGray
|
||||
size: 48
|
||||
MouseArea { anchors.fill: parent; onClicked: webview.goBack() }
|
||||
MouseArea {
|
||||
id: backMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: webview.goBack();
|
||||
}
|
||||
}
|
||||
|
||||
HiFiGlyphs {
|
||||
id: forward;
|
||||
enabled: webview.canGoForward;
|
||||
id: forward
|
||||
enabled: webview.canGoForward
|
||||
text: hifi.glyphs.forward
|
||||
color: enabled ? hifi.colors.text : hifi.colors.disabledText
|
||||
color: enabled ? (forwardMouseArea.containsMouse ? hifi.colors.blueHighlight : hifi.colors.faintGray) : hifi.colors.lightGray
|
||||
size: 48
|
||||
MouseArea { anchors.fill: parent; onClicked: webview.goForward() }
|
||||
MouseArea {
|
||||
id: forwardMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: webview.goForward();
|
||||
}
|
||||
}
|
||||
|
||||
HiFiGlyphs {
|
||||
id: reload;
|
||||
enabled: webview.canGoForward;
|
||||
id: reload
|
||||
enabled: url !== ""
|
||||
text: webview.loading ? hifi.glyphs.close : hifi.glyphs.reload
|
||||
color: enabled ? hifi.colors.text : hifi.colors.disabledText
|
||||
color: enabled ? (reloadMouseArea.containsMouse ? hifi.colors.blueHighlight : hifi.colors.faintGray) : hifi.colors.lightGray
|
||||
size: 48
|
||||
MouseArea { anchors.fill: parent; onClicked: webview.goForward() }
|
||||
MouseArea {
|
||||
id: reloadMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: webview.loading ? webview.stop() : webview.reload();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -94,52 +115,82 @@ ScrollingWindow {
|
|||
id: border
|
||||
height: 48
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.topMargin: 4
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
anchors.left: buttons.right
|
||||
anchors.leftMargin: 8
|
||||
|
||||
HiFiGlyphs {
|
||||
id: externalBrowser
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 4
|
||||
enabled: !HMD.active && url !== ""
|
||||
font.family: "FontAwesome"
|
||||
text: "\uf24d"
|
||||
rotation: -90
|
||||
color: enabled ? (externalBrowserMouseArea.containsMouse ? hifi.colors.blueHighlight : hifi.colors.faintGray) : hifi.colors.lightGray
|
||||
size: 32
|
||||
MouseArea {
|
||||
id: externalBrowserMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: openExternalBrowser();
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: barIcon
|
||||
width: parent.height
|
||||
height: parent.height
|
||||
Image {
|
||||
source: webview.icon;
|
||||
source: webview.loading ? "" : webview.icon
|
||||
x: (parent.height - height) / 2
|
||||
y: (parent.width - width) / 2
|
||||
sourceSize: Qt.size(width, height);
|
||||
verticalAlignment: Image.AlignVCenter;
|
||||
width: 28
|
||||
height: 28
|
||||
verticalAlignment: Image.AlignVCenter
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: addressBar
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
anchors.right: externalBrowser.left
|
||||
anchors.rightMargin: 32
|
||||
anchors.left: barIcon.right
|
||||
anchors.leftMargin: 0
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
focus: true
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
placeholderText: "Enter URL"
|
||||
inputMethodHints: Qt.ImhUrlCharactersOnly
|
||||
Component.onCompleted: ScriptDiscoveryService.scriptsModelFilter.filterRegExp = new RegExp("^.*$", "i")
|
||||
Keys.onPressed: {
|
||||
switch(event.key) {
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
event.accepted = true
|
||||
if (text.indexOf("http") != 0) {
|
||||
if (text.indexOf("http") !== 0) {
|
||||
text = "http://" + text;
|
||||
}
|
||||
|
||||
// Setting webiew.url directly doesn't add the URL to the navigation history.
|
||||
//webview.url = text;
|
||||
// The following works around this bug.
|
||||
text = encodeURI(text);
|
||||
text = text.replace(/;/g, "%3b"); // Prevent script injection.
|
||||
text = text.replace(/'/g, "%25"); // ""
|
||||
webview.runJavaScript("window.location='" + text + "'");
|
||||
|
||||
root.hidePermissionsBar();
|
||||
root.keyboardRaised = false;
|
||||
webview.url = text;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
@ -204,7 +255,7 @@ ScrollingWindow {
|
|||
parentRoot: root
|
||||
|
||||
anchors.top: buttons.bottom
|
||||
anchors.topMargin: 8
|
||||
anchors.topMargin: 4
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
@ -216,7 +267,7 @@ ScrollingWindow {
|
|||
Keys.onPressed: {
|
||||
switch(event.key) {
|
||||
case Qt.Key_L:
|
||||
if (event.modifiers == Qt.ControlModifier) {
|
||||
if (event.modifiers === Qt.ControlModifier) {
|
||||
event.accepted = true
|
||||
addressBar.selectAll()
|
||||
addressBar.forceActiveFocus()
|
||||
|
@ -224,4 +275,5 @@ ScrollingWindow {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // dialog
|
||||
|
|
|
@ -437,6 +437,10 @@ Item {
|
|||
visible: root.expanded
|
||||
text: "LOD: " + root.lodStatus;
|
||||
}
|
||||
StatText {
|
||||
visible: root.expanded
|
||||
text: "Entity Updates: " + root.numEntityUpdates + " / " + root.numNeededEntityUpdates;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//
|
||||
// Created by David Rowe on 16 Dec 2016.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -17,22 +18,31 @@ Item {
|
|||
anchors.fill: parent
|
||||
property string url: ""
|
||||
property string scriptUrl: null
|
||||
property bool useBackground: true
|
||||
|
||||
onUrlChanged: {
|
||||
load(root.url, root.scriptUrl);
|
||||
load(root.url, root.scriptUrl, root.useBackground);
|
||||
}
|
||||
|
||||
onScriptUrlChanged: {
|
||||
if (root.item) {
|
||||
root.item.scriptUrl = root.scriptUrl;
|
||||
} else {
|
||||
load(root.url, root.scriptUrl);
|
||||
load(root.url, root.scriptUrl, root.useBackground);
|
||||
}
|
||||
}
|
||||
|
||||
onUseBackgroundChanged: {
|
||||
if (root.item) {
|
||||
root.item.useBackground = root.useBackground;
|
||||
} else {
|
||||
load(root.url, root.scriptUrl, root.useBackground);
|
||||
}
|
||||
}
|
||||
|
||||
property var item: null
|
||||
|
||||
function load(url, scriptUrl) {
|
||||
function load(url, scriptUrl, useBackground) {
|
||||
// Ensure we reset any existing item to "about:blank" to ensure web audio stops: DEV-2375
|
||||
if (root.item != null) {
|
||||
root.item.url = "about:blank"
|
||||
|
@ -43,11 +53,12 @@ Item {
|
|||
root.item = newItem
|
||||
root.item.url = url
|
||||
root.item.scriptUrl = scriptUrl
|
||||
root.item.useBackground = useBackground
|
||||
})
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
load(root.url, root.scriptUrl);
|
||||
load(root.url, root.scriptUrl, root.useBackground);
|
||||
}
|
||||
|
||||
signal sendToScript(var message);
|
||||
|
|
|
@ -16,6 +16,7 @@ Item {
|
|||
property alias webViewCoreProfile: webViewCore.profile
|
||||
property string webViewCoreUserAgent
|
||||
|
||||
property bool useBackground: webViewCore.useBackground
|
||||
property string userScriptUrl: ""
|
||||
property string urlTag: "noDownload=false";
|
||||
|
||||
|
@ -98,6 +99,7 @@ Item {
|
|||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
backgroundColor: (flick.useBackground) ? "white" : "transparent"
|
||||
|
||||
profile: HFWebEngineProfile;
|
||||
settings.pluginsEnabled: true
|
||||
|
|
|
@ -14,6 +14,7 @@ Item {
|
|||
property alias webViewCoreProfile: webViewCore.profile
|
||||
property string webViewCoreUserAgent
|
||||
|
||||
property bool useBackground: webViewCore.useBackground
|
||||
property string userScriptUrl: ""
|
||||
property string urlTag: "noDownload=false";
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ Item {
|
|||
property bool passwordField: false
|
||||
property alias flickable: webroot.interactive
|
||||
property alias blurOnCtrlShift: webroot.blurOnCtrlShift
|
||||
property alias useBackground: webroot.useBackground
|
||||
|
||||
function stop() {
|
||||
webroot.stop();
|
||||
|
|
|
@ -148,7 +148,7 @@ Windows.ScrollingWindow {
|
|||
}
|
||||
|
||||
function canAddToWorld(path) {
|
||||
var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i, /\.jpg\b/i, /\.png\b/i, /\.gltf\b/i];
|
||||
var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i, /\.jpg\b/i, /\.png\b/i, /\.gltf\b/i, /\.glb\b/i];
|
||||
|
||||
if (selectedItemCount > 1) {
|
||||
return false;
|
||||
|
|
|
@ -37,17 +37,6 @@ ListModel {
|
|||
return trimmedUrl;
|
||||
}
|
||||
|
||||
function imageExists(imageUrl) {
|
||||
|
||||
var http = new XMLHttpRequest();
|
||||
|
||||
http.open('HEAD', imageUrl, false);
|
||||
http.send();
|
||||
|
||||
return http.status !== 404;
|
||||
|
||||
}
|
||||
|
||||
function makeThumbnailUrl(avatarUrl) {
|
||||
var marketId = extractMarketId(avatarUrl);
|
||||
if (marketId !== '') {
|
||||
|
@ -55,17 +44,18 @@ ListModel {
|
|||
}
|
||||
|
||||
var avatarThumbnailFileUrl = trimFileExtension(avatarUrl) + ".jpg";
|
||||
var thumbnailExist = imageExists(avatarThumbnailFileUrl);
|
||||
|
||||
if (!thumbnailExist) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return avatarThumbnailFileUrl;
|
||||
}
|
||||
|
||||
function makeAvatarObject(avatar, avatarName) {
|
||||
var avatarThumbnailUrl = makeThumbnailUrl(avatar.avatarUrl);
|
||||
var avatarThumbnailUrl;
|
||||
|
||||
if (!avatar.avatarIcon) {
|
||||
avatarThumbnailUrl = makeThumbnailUrl(avatar.avatarUrl);
|
||||
} else {
|
||||
avatarThumbnailUrl = avatar.avatarIcon;
|
||||
}
|
||||
|
||||
return {
|
||||
'name' : avatarName,
|
||||
|
|
|
@ -456,7 +456,7 @@ Rectangle {
|
|||
id: avatarCollisionSoundUrlInputText
|
||||
font.pixelSize: 17
|
||||
Layout.fillWidth: true
|
||||
placeholderText: 'https://hifi-public.s3.amazonaws.com/sounds/Collisions-'
|
||||
placeholderText: "https://cdn-1.vircadia.com/eu-c-1/vircadia-public/sounds/Collisions-"
|
||||
|
||||
onFocusChanged: {
|
||||
keyboardRaised = (avatarAnimationUrlInputText.focus || avatarCollisionSoundUrlInputText.focus);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//
|
||||
// Created by David Rowe on 18 Apr 2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -33,12 +34,12 @@ Rectangle {
|
|||
anchors.left: parent.left
|
||||
anchors.leftMargin: 70
|
||||
RalewayRegular {
|
||||
text: "Build " + HiFiAbout.buildVersion
|
||||
text: "Build " + About.buildVersion
|
||||
size: 16
|
||||
color: "white"
|
||||
}
|
||||
RalewayRegular {
|
||||
text: "Released " + HiFiAbout.buildDate
|
||||
text: "Released " + About.buildDate
|
||||
size: 16
|
||||
color: "white"
|
||||
}
|
||||
|
@ -56,7 +57,7 @@ Rectangle {
|
|||
text: "<a href=\"https://github.com/kasenvr/project-athena\">Vircadia Github</a>."
|
||||
size: 20
|
||||
onLinkActivated: {
|
||||
HiFiAbout.openUrl("https:/github.com/kasenvr/project-athena");
|
||||
About.openUrl("https:/github.com/kasenvr/project-athena");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -70,13 +71,13 @@ Rectangle {
|
|||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
HiFiAbout.openUrl("https://www.qt.io/");
|
||||
About.openUrl("https://www.qt.io/");
|
||||
}
|
||||
}
|
||||
}
|
||||
RalewayRegular {
|
||||
color: "white"
|
||||
text: "Built using Qt " + HiFiAbout.qtVersion
|
||||
text: "Built using Qt " + About.qtVersion
|
||||
size: 12
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
@ -102,7 +103,7 @@ Rectangle {
|
|||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
HiFiAbout.openUrl("http://opus-codec.org/");
|
||||
About.openUrl("http://opus-codec.org/");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +132,7 @@ Rectangle {
|
|||
text: "Distributed under the <a href=\"http://www.apache.org/licenses/LICENSE-2.0.html\">Apache License, Version 2.0.</a>."
|
||||
size: 14
|
||||
onLinkActivated: {
|
||||
HiFiAbout.openUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
|
||||
About.openUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ Rectangle {
|
|||
}
|
||||
|
||||
function canAddToWorld(path) {
|
||||
var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i, /\.jpg\b/i, /\.png\b/i, /\.gltf\b/i];
|
||||
var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i, /\.jpg\b/i, /\.png\b/i, /\.gltf\b/i, /\.glb\b/i];
|
||||
|
||||
if (selectedItemCount > 1) {
|
||||
return false;
|
||||
|
|
|
@ -333,6 +333,8 @@ Rectangle {
|
|||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
height: childrenRect.height;
|
||||
// FIXME: Reuse or remove wallet-related code.
|
||||
visible: false;
|
||||
|
||||
Rectangle {
|
||||
id: walletHeaderContainer;
|
||||
|
|
|
@ -25,7 +25,7 @@ XmlListModel {
|
|||
readonly property string realPrefix: prefix.match('.*/$') ? prefix : (prefix + "/")
|
||||
readonly property string nameRegex: realPrefix + (filter ? (".*" + filter) : "") + ".*\." + extension
|
||||
readonly property string nameQuery: "Key/substring-before(substring-after(string(), '" + prefix + "'), '." + extension + "')"
|
||||
readonly property string baseUrl: "http://s3.amazonaws.com/hifi-public"
|
||||
readonly property string baseUrl: "https://cdn-1.vircadia.com/eu-c-1/vircadia-public"
|
||||
|
||||
// FIXME need to urlencode prefix?
|
||||
source: baseUrl + "?prefix=" + realPrefix
|
||||
|
|
|
@ -27,6 +27,7 @@ Item {
|
|||
width: parent.width
|
||||
|
||||
property string title: "Controls"
|
||||
property var openVRDevices: ["HTC Vive", "Valve Index", "Valve HMD", "Valve"]
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
|
@ -244,7 +245,7 @@ Item {
|
|||
source: InputConfiguration.configurationLayout(box.textAt(box.currentIndex));
|
||||
onLoaded: {
|
||||
if (loader.item.hasOwnProperty("pluginName")) {
|
||||
if (box.textAt(box.currentIndex) === "HTC Vive") {
|
||||
if (openVRDevices.indexOf(box.textAt(box.currentIndex)) !== -1) {
|
||||
loader.item.pluginName = "OpenVR";
|
||||
} else {
|
||||
loader.item.pluginName = box.textAt(box.currentIndex);
|
||||
|
@ -298,7 +299,7 @@ Item {
|
|||
loader.source = "";
|
||||
var selectedDevice = box.textAt(box.currentIndex);
|
||||
var source = "";
|
||||
if (selectedDevice == "HTC Vive") {
|
||||
if (openVRDevices.indexOf(selectedDevice) !== -1) {
|
||||
source = InputConfiguration.configurationLayout("OpenVR");
|
||||
} else {
|
||||
source = InputConfiguration.configurationLayout(selectedDevice);
|
||||
|
|
|
@ -894,7 +894,7 @@ Flickable {
|
|||
hoverEnabled: true
|
||||
onEntered: privacyPolicyUnderline.visible = true;
|
||||
onExited: privacyPolicyUnderline.visible = false;
|
||||
onClicked: HiFiAbout.openUrl("https://vircadia.com/privacy-policy");
|
||||
onClicked: About.openUrl("https://vircadia.com/privacy-policy");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -296,7 +296,7 @@
|
|||
"lastEdited": 1537901430334966,
|
||||
"lastEditedBy": "{69540019-db48-4375-86c8-ac1a4a90d043}",
|
||||
"locked": true,
|
||||
"modelURL": "http://hifi-content.s3.amazonaws.com/alexia/LoadingScreens/floor.fbx",
|
||||
"modelURL": "https://cdn-1.vircadia.com/eu-c-1/vircadia-content/alexia/LoadingScreens/floor.fbx",
|
||||
"name": "floorModel",
|
||||
"owningAvatarID": "{00000000-0000-0000-0000-000000000000}",
|
||||
"position": {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -45,6 +45,16 @@ QString AboutUtil::getQtVersion() const {
|
|||
}
|
||||
|
||||
void AboutUtil::openUrl(const QString& url) const {
|
||||
auto abboutUtilInstance = AboutUtil::getInstance();
|
||||
if (!abboutUtilInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(abboutUtilInstance, "openUrl", Q_ARG(const QString&, url));
|
||||
return;
|
||||
}
|
||||
|
||||
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
|
||||
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Vlad Stelmahovsky on 15/5/2018.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia Contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -16,6 +17,29 @@
|
|||
#include <QObject>
|
||||
|
||||
/**jsdoc
|
||||
* The <code>About</code> API provides information about the version of Interface that is currently running. It also has the
|
||||
* functionality to open a web page in an Interface browser window.
|
||||
*
|
||||
* @namespace About
|
||||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @property {string} platform - The name of the Interface platform running, e,g., <code>"Vircadia"</code> for the Vircadia.
|
||||
* <em>Read-only.</em>
|
||||
* @property {string} buildDate - The build date of Interface that is currently running. <em>Read-only.</em>
|
||||
* @property {string} buildVersion - The build version of Interface that is currently running. <em>Read-only.</em>
|
||||
* @property {string} qtVersion - The Qt version used in Interface that is currently running. <em>Read-only.</em>
|
||||
*
|
||||
* @example <caption>Report information on the version of Interface currently running.</caption>
|
||||
* print("Interface platform: " + About.platform);
|
||||
* print("Interface build date: " + About.buildDate);
|
||||
* print("Interface version: " + About.buildVersion);
|
||||
* print("Qt version: " + About.qtVersion);
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>HifiAbout</code> API provides information about the version of Interface that is currently running. It also
|
||||
* has the functionality to open a web page in an Interface browser window.
|
||||
*
|
||||
|
@ -25,19 +49,21 @@
|
|||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @deprecated This API is deprecated and will be removed. Use the {@link About} API instead.
|
||||
*
|
||||
* @property {string} platform - The name of the Interface platform running, e,g., <code>"Vircadia"</code> for the Vircadia.
|
||||
* <em>Read-only.</em>
|
||||
* @property {string} buildDate - The build date of Interface that is currently running. <em>Read-only.</em>
|
||||
* @property {string} buildVersion - The build version of Interface that is currently running. <em>Read-only.</em>
|
||||
* @property {string} qtVersion - The Qt version used in Interface that is currently running. <em>Read-only.</em>
|
||||
*
|
||||
* @example <caption>Report build information for the version of Interface currently running.</caption>
|
||||
* print("HiFi build date: " + HifiAbout.buildDate); // Returns the build date of the version of Interface currently running on your machine.
|
||||
* print("HiFi version: " + HifiAbout.buildVersion); // Returns the build version of Interface currently running on your machine.
|
||||
* print("Qt version: " + HifiAbout.qtVersion); // Returns the Qt version details of the version of Interface currently running on your machine.
|
||||
* @borrows About.openUrl as openUrl
|
||||
*/
|
||||
|
||||
class AboutUtil : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString platform READ getPlatformName CONSTANT)
|
||||
Q_PROPERTY(QString buildDate READ getBuildDate CONSTANT)
|
||||
Q_PROPERTY(QString buildVersion READ getBuildVersion CONSTANT)
|
||||
Q_PROPERTY(QString qtVersion READ getQtVersion CONSTANT)
|
||||
|
@ -45,6 +71,7 @@ public:
|
|||
static AboutUtil* getInstance();
|
||||
~AboutUtil() {}
|
||||
|
||||
QString getPlatformName() const { return "Vircadia"; }
|
||||
QString getBuildDate() const;
|
||||
QString getBuildVersion() const;
|
||||
QString getQtVersion() const;
|
||||
|
@ -52,8 +79,8 @@ public:
|
|||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* Display a web page in an Interface browser window.
|
||||
* @function HifiAbout.openUrl
|
||||
* Display a web page in an Interface browser window or the tablet.
|
||||
* @function About.openUrl
|
||||
* @param {string} url - The URL of the web page you want to view in Interface.
|
||||
*/
|
||||
void openUrl(const QString &url) const;
|
||||
|
|
|
@ -253,6 +253,7 @@
|
|||
#include <DesktopPreviewProvider.h>
|
||||
|
||||
#include "AboutUtil.h"
|
||||
#include "ExternalResource.h"
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <VersionHelpers.h>
|
||||
|
@ -680,6 +681,9 @@ private:
|
|||
* <tr><td><code>CameraIndependent</code></td><td>number</td><td>number</td><td>The camera is in independent mode.</td></tr>
|
||||
* <tr><td><code>CameraEntity</code></td><td>number</td><td>number</td><td>The camera is in entity mode.</td></tr>
|
||||
* <tr><td><code>InHMD</code></td><td>number</td><td>number</td><td>The user is in HMD mode.</td></tr>
|
||||
* <tr><td><code>CaptureMouse</code></td><td>number</td><td>number</td><td>The mouse is captured. In this mode,
|
||||
* the mouse is invisible and cannot leave the bounds of Interface, as long as Interface is the active window and
|
||||
* no menu item is selected.</td></tr>
|
||||
* <tr><td><code>AdvancedMovement</code></td><td>number</td><td>number</td><td>Advanced movement (walking) controls are
|
||||
* enabled.</td></tr>
|
||||
* <tr><td><code>StrafeEnabled</code></td><td>number</td><td>number</td><td>Strafing is enabled</td></tr>
|
||||
|
@ -715,6 +719,7 @@ static const QString STATE_PLATFORM_ANDROID = "PlatformAndroid";
|
|||
static const QString STATE_LEFT_HAND_DOMINANT = "LeftHandDominant";
|
||||
static const QString STATE_RIGHT_HAND_DOMINANT = "RightHandDominant";
|
||||
static const QString STATE_STRAFE_ENABLED = "StrafeEnabled";
|
||||
static const QString STATE_CAPTURE_MOUSE = "CaptureMouse";
|
||||
|
||||
// Statically provided display and input plugins
|
||||
extern DisplayPluginList getDisplayPlugins();
|
||||
|
@ -918,7 +923,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
DependencyManager::set<MessagesClient>();
|
||||
controller::StateController::setStateVariables({ { STATE_IN_HMD, STATE_CAMERA_FULL_SCREEN_MIRROR,
|
||||
STATE_CAMERA_FIRST_PERSON, STATE_CAMERA_FIRST_PERSON_LOOK_AT, STATE_CAMERA_THIRD_PERSON,
|
||||
STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT, STATE_CAMERA_LOOK_AT, STATE_CAMERA_SELFIE,
|
||||
STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT, STATE_CAMERA_LOOK_AT, STATE_CAMERA_SELFIE, STATE_CAPTURE_MOUSE,
|
||||
STATE_SNAP_TURN, STATE_ADVANCED_MOVEMENT_CONTROLS, STATE_GROUNDED, STATE_NAV_FOCUSED,
|
||||
STATE_PLATFORM_WINDOWS, STATE_PLATFORM_MAC, STATE_PLATFORM_ANDROID, STATE_LEFT_HAND_DOMINANT, STATE_RIGHT_HAND_DOMINANT, STATE_STRAFE_ENABLED } });
|
||||
DependencyManager::set<UserInputMapper>();
|
||||
|
@ -1352,10 +1357,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
connect(accountManager.data(), &AccountManager::usernameChanged, this, &Application::updateWindowTitle);
|
||||
|
||||
auto domainAccountManager = DependencyManager::get<DomainAccountManager>();
|
||||
connect(domainAccountManager.data(), &DomainAccountManager::authRequired, dialogsManager.data(),
|
||||
&DialogsManager::showDomainLoginDialog);
|
||||
connect(domainAccountManager.data(), &DomainAccountManager::loginComplete, this,
|
||||
&Application::updateWindowTitle);
|
||||
connect(domainAccountManager.data(), &DomainAccountManager::authRequired,
|
||||
dialogsManager.data(), &DialogsManager::showDomainLoginDialog);
|
||||
connect(domainAccountManager.data(), &DomainAccountManager::authRequired, this, &Application::updateWindowTitle);
|
||||
connect(domainAccountManager.data(), &DomainAccountManager::loginComplete, this, &Application::updateWindowTitle);
|
||||
// ####### TODO: Connect any other signals from domainAccountManager.
|
||||
|
||||
// use our MyAvatar position and quat for address manager path
|
||||
|
@ -1891,6 +1896,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
_applicationStateDevice->setInputVariant(STATE_CAMERA_INDEPENDENT, []() -> float {
|
||||
return qApp->getCamera().getMode() == CAMERA_MODE_INDEPENDENT ? 1 : 0;
|
||||
});
|
||||
_applicationStateDevice->setInputVariant(STATE_CAPTURE_MOUSE, []() -> float {
|
||||
return qApp->getCamera().getCaptureMouse() ? 1 : 0;
|
||||
});
|
||||
_applicationStateDevice->setInputVariant(STATE_SNAP_TURN, []() -> float {
|
||||
return qApp->getMyAvatar()->getSnapTurn() ? 1 : 0;
|
||||
});
|
||||
|
@ -2406,6 +2414,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
updateSystemTabletMode();
|
||||
|
||||
connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged);
|
||||
connect(&_myCamera, &Camera::captureMouseChanged, this, &Application::captureMouseChanged);
|
||||
|
||||
DependencyManager::get<PickManager>()->setShouldPickHUDOperator([]() { return DependencyManager::get<HMDScriptingInterface>()->isHMDMode(); });
|
||||
DependencyManager::get<PickManager>()->setCalculatePos2DFromHUDOperator([this](const glm::vec3& intersection) {
|
||||
|
@ -3512,8 +3521,10 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
|
|||
surfaceContext->setContextProperty("Selection", DependencyManager::get<SelectionScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
|
||||
surfaceContext->setContextProperty("WalletScriptingInterface", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance());
|
||||
surfaceContext->setContextProperty("About", AboutUtil::getInstance());
|
||||
surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance()); // Deprecated
|
||||
surfaceContext->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
surfaceContext->setContextProperty("ExternalResource", ExternalResource::getInstance());
|
||||
|
||||
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
||||
surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
|
||||
|
@ -3623,10 +3634,13 @@ void Application::setupQmlSurface(QQmlContext* surfaceContext, bool setAdditiona
|
|||
surfaceContext->setContextProperty("Pointers", DependencyManager::get<PointerScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("Reticle", qApp->getApplicationCompositor().getReticleInterface());
|
||||
surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance());
|
||||
surfaceContext->setContextProperty("About", AboutUtil::getInstance());
|
||||
surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance()); // Deprecated.
|
||||
surfaceContext->setContextProperty("WalletScriptingInterface", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
surfaceContext->setContextProperty("PlatformInfo", PlatformInfoScriptingInterface::getInstance());
|
||||
surfaceContext->setContextProperty("ExternalResource", ExternalResource::getInstance());
|
||||
|
||||
// This `module` context property is blank for the QML scripting interface so that we don't get log errors when importing
|
||||
// certain JS files from both scripts (in the JS context) and QML (in the QML context).
|
||||
surfaceContext->setContextProperty("module", "");
|
||||
|
@ -3974,6 +3988,11 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
|
|||
|
||||
// If this is a first run we short-circuit the address passed in
|
||||
if (_firstRun.get()) {
|
||||
if (!BuildInfo::INITIAL_STARTUP_LOCATION.isEmpty()) {
|
||||
DependencyManager::get<LocationBookmarks>()->setHomeLocationToAddress(NetworkingConstants::DEFAULT_VIRCADIA_ADDRESS);
|
||||
Menu::getInstance()->triggerOption(MenuOption::HomeLocation);
|
||||
}
|
||||
|
||||
if (!_overrideEntry) {
|
||||
DependencyManager::get<AddressManager>()->goToEntry();
|
||||
sentTo = SENT_TO_ENTRY;
|
||||
|
@ -4693,6 +4712,11 @@ void Application::maybeToggleMenuVisible(QMouseEvent* event) const {
|
|||
void Application::mouseMoveEvent(QMouseEvent* event) {
|
||||
PROFILE_RANGE(app_input_mouse, __FUNCTION__);
|
||||
|
||||
if (_ignoreMouseMove) {
|
||||
_ignoreMouseMove = false;
|
||||
return;
|
||||
}
|
||||
|
||||
maybeToggleMenuVisible(event);
|
||||
|
||||
auto& compositor = getApplicationCompositor();
|
||||
|
@ -4738,7 +4762,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
|
|||
}
|
||||
|
||||
if (_keyboardMouseDevice->isActive()) {
|
||||
_keyboardMouseDevice->mouseMoveEvent(event);
|
||||
_keyboardMouseDevice->mouseMoveEvent(event, _captureMouse, _mouseCaptureTarget);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5532,6 +5556,19 @@ void Application::loadSettings() {
|
|||
}
|
||||
|
||||
getMyAvatar()->loadData();
|
||||
|
||||
auto bucketEnum = QMetaEnum::fromType<ExternalResource::Bucket>();
|
||||
auto externalResource = ExternalResource::getInstance();
|
||||
|
||||
for (int i = 0; i < bucketEnum.keyCount(); i++) {
|
||||
const char* keyName = bucketEnum.key(i);
|
||||
QString setting("ExternalResource/");
|
||||
setting += keyName;
|
||||
auto bucket = static_cast<ExternalResource::Bucket>(bucketEnum.keyToValue(keyName));
|
||||
Setting::Handle<QString> url(setting, externalResource->getBase(bucket));
|
||||
externalResource->setBase(bucket, url.get());
|
||||
}
|
||||
|
||||
_settingsLoaded = true;
|
||||
}
|
||||
|
||||
|
@ -5548,6 +5585,22 @@ void Application::saveSettings() const {
|
|||
Menu::getInstance()->saveSettings();
|
||||
getMyAvatar()->saveData();
|
||||
PluginManager::getInstance()->saveSettings();
|
||||
|
||||
// Don't save external resource paths until such time as there's UI to select or set alternatives. Otherwise new default
|
||||
// values won't be used unless Interface.json entries are manually remove or Interface.json is deleted.
|
||||
/*
|
||||
auto bucketEnum = QMetaEnum::fromType<ExternalResource::Bucket>();
|
||||
auto externalResource = ExternalResource::getInstance();
|
||||
|
||||
for (int i = 0; i < bucketEnum.keyCount(); i++) {
|
||||
const char* keyName = bucketEnum.key(i);
|
||||
QString setting("ExternalResource/");
|
||||
setting += keyName;
|
||||
auto bucket = static_cast<ExternalResource::Bucket>(bucketEnum.keyToValue(keyName));
|
||||
Setting::Handle<QString> url(setting, externalResource->getBase(bucket));
|
||||
url.set(externalResource->getBase(bucket));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
bool Application::importEntities(const QString& urlOrFilename, const bool isObservable, const qint64 callerId) {
|
||||
|
@ -5910,6 +5963,20 @@ void Application::cameraModeChanged() {
|
|||
cameraMenuChanged();
|
||||
}
|
||||
|
||||
bool Application::shouldCaptureMouse() const {
|
||||
return _captureMouse && _glWidget->isActiveWindow() && !ui::Menu::isSomeSubmenuShown();
|
||||
}
|
||||
|
||||
void Application::captureMouseChanged(bool captureMouse) {
|
||||
_captureMouse = captureMouse;
|
||||
if (_captureMouse) {
|
||||
_glWidget->setCursor(QCursor(Qt::BlankCursor));
|
||||
} else {
|
||||
_mouseCaptureTarget = QPointF(NAN, NAN);
|
||||
_glWidget->unsetCursor();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::changeViewAsNeeded(float boomLength) {
|
||||
// Switch between first and third person views as needed
|
||||
// This is called when the boom length has changed
|
||||
|
@ -6260,6 +6327,15 @@ void Application::update(float deltaTime) {
|
|||
PROFILE_ASYNC_END(app, "Scene Loading", "");
|
||||
}
|
||||
|
||||
if (shouldCaptureMouse()) {
|
||||
QPoint point = _glWidget->mapToGlobal(_glWidget->geometry().center());
|
||||
if (QCursor::pos() != point) {
|
||||
_mouseCaptureTarget = point;
|
||||
_ignoreMouseMove = true;
|
||||
QCursor::setPos(point);
|
||||
}
|
||||
}
|
||||
|
||||
auto myAvatar = getMyAvatar();
|
||||
{
|
||||
PerformanceTimer perfTimer("devices");
|
||||
|
@ -6315,8 +6391,8 @@ void Application::update(float deltaTime) {
|
|||
if (deltaTime > FLT_EPSILON && userInputMapper->getActionState(controller::Action::TRANSLATE_CAMERA_Z) == 0.0f) {
|
||||
myAvatar->setDriveKey(MyAvatar::PITCH, -1.0f * userInputMapper->getActionState(controller::Action::PITCH));
|
||||
myAvatar->setDriveKey(MyAvatar::YAW, -1.0f * userInputMapper->getActionState(controller::Action::YAW));
|
||||
myAvatar->setDriveKey(MyAvatar::DELTA_PITCH, -1.0f * userInputMapper->getActionState(controller::Action::DELTA_PITCH));
|
||||
myAvatar->setDriveKey(MyAvatar::DELTA_YAW, -1.0f * userInputMapper->getActionState(controller::Action::DELTA_YAW));
|
||||
myAvatar->setDriveKey(MyAvatar::DELTA_PITCH, -_myCamera.getSensitivity() * userInputMapper->getActionState(controller::Action::DELTA_PITCH));
|
||||
myAvatar->setDriveKey(MyAvatar::DELTA_YAW, -_myCamera.getSensitivity() * userInputMapper->getActionState(controller::Action::DELTA_YAW));
|
||||
myAvatar->setDriveKey(MyAvatar::STEP_YAW, -1.0f * userInputMapper->getActionState(controller::Action::STEP_YAW));
|
||||
}
|
||||
}
|
||||
|
@ -7084,8 +7160,9 @@ void Application::updateWindowTitle() const {
|
|||
auto domainAccountManager = DependencyManager::get<DomainAccountManager>();
|
||||
auto isInErrorState = nodeList->getDomainHandler().isInErrorState();
|
||||
bool isMetaverseLoggedIn = accountManager->isLoggedIn();
|
||||
bool hasDomainLogIn = domainAccountManager->hasLogIn();
|
||||
bool isDomainLoggedIn = domainAccountManager->isLoggedIn();
|
||||
QString authedDomain = domainAccountManager->getAuthedDomain();
|
||||
QString authedDomainName = domainAccountManager->getAuthedDomainName();
|
||||
|
||||
QString buildVersion = " - Vircadia - "
|
||||
+ (BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable ? QString("Version") : QString("Build"))
|
||||
|
@ -7102,9 +7179,9 @@ void Application::updateWindowTitle() const {
|
|||
QString currentPlaceName;
|
||||
if (isServerlessMode()) {
|
||||
if (isInErrorState) {
|
||||
currentPlaceName = "serverless: " + nodeList->getDomainHandler().getErrorDomainURL().toString();
|
||||
currentPlaceName = "Serverless: " + nodeList->getDomainHandler().getErrorDomainURL().toString();
|
||||
} else {
|
||||
currentPlaceName = "serverless: " + DependencyManager::get<AddressManager>()->getDomainURL().toString();
|
||||
currentPlaceName = "Serverless: " + DependencyManager::get<AddressManager>()->getDomainURL().toString();
|
||||
}
|
||||
} else {
|
||||
currentPlaceName = DependencyManager::get<AddressManager>()->getDomainURL().host();
|
||||
|
@ -7115,20 +7192,23 @@ void Application::updateWindowTitle() const {
|
|||
|
||||
QString metaverseDetails;
|
||||
if (isMetaverseLoggedIn) {
|
||||
metaverseDetails = "Metaverse: Logged in as " + metaverseUsername;
|
||||
metaverseDetails = " (Metaverse: Connected to " + MetaverseAPI::getCurrentMetaverseServerURL().toString() + " as " + metaverseUsername + ")";
|
||||
} else {
|
||||
metaverseDetails = "Metaverse: Not Logged In";
|
||||
metaverseDetails = " (Metaverse: Not Logged In)";
|
||||
}
|
||||
|
||||
QString domainDetails;
|
||||
if (currentPlaceName == authedDomain && isDomainLoggedIn) {
|
||||
domainDetails = "Domain: Logged in as " + domainUsername;
|
||||
if (hasDomainLogIn) {
|
||||
if (currentPlaceName == authedDomainName && isDomainLoggedIn) {
|
||||
domainDetails = " (Domain: Logged in as " + domainUsername + ")";
|
||||
} else {
|
||||
domainDetails = " (Domain: Not Logged In)";
|
||||
}
|
||||
} else {
|
||||
domainDetails = "Domain: Not Logged In";
|
||||
domainDetails = "";
|
||||
}
|
||||
|
||||
QString title = QString() + currentPlaceName + connectionStatus + " (" + metaverseDetails + ") (" + domainDetails + ")"
|
||||
+ buildVersion;
|
||||
QString title = currentPlaceName + connectionStatus + metaverseDetails + domainDetails + buildVersion;
|
||||
|
||||
#ifndef WIN32
|
||||
// crashes with vs2013/win32
|
||||
|
@ -7520,7 +7600,8 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptEngine
|
|||
scriptEngine->registerGlobalObject("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
|
||||
scriptEngine->registerGlobalObject("WalletScriptingInterface", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance());
|
||||
scriptEngine->registerGlobalObject("About", AboutUtil::getInstance());
|
||||
scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance()); // Deprecated.
|
||||
scriptEngine->registerGlobalObject("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
|
||||
registerInteractiveWindowMetaType(scriptEngine.data());
|
||||
|
@ -7657,7 +7738,7 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
|
|||
|
||||
QUrl scriptURL { scriptFilenameOrURL };
|
||||
|
||||
if (scriptURL.host().endsWith(NetworkingConstants::MARKETPLACE_CDN_HOSTNAME)) {
|
||||
if (scriptURL.host().endsWith(NetworkingConstants::HF_MARKETPLACE_CDN_HOSTNAME)) {
|
||||
int startIndex = shortName.lastIndexOf('/') + 1;
|
||||
int endIndex = shortName.lastIndexOf('?');
|
||||
shortName = shortName.mid(startIndex, endIndex - startIndex);
|
||||
|
@ -7780,7 +7861,7 @@ bool Application::askToReplaceDomainContent(const QString& url) {
|
|||
const int MAX_CHARACTERS_PER_LINE = 90;
|
||||
if (DependencyManager::get<NodeList>()->getThisNodeCanReplaceContent()) {
|
||||
QUrl originURL { url };
|
||||
if (originURL.host().endsWith(NetworkingConstants::MARKETPLACE_CDN_HOSTNAME)) {
|
||||
if (originURL.host().endsWith(NetworkingConstants::HF_MARKETPLACE_CDN_HOSTNAME)) {
|
||||
// Create a confirmation dialog when this call is made
|
||||
static const QString infoText = simpleWordWrap("Your domain's content will be replaced with a new content set. "
|
||||
"If you want to save what you have now, create a backup before proceeding. For more information about backing up "
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Andrzej Kapolka on 5/10/13.
|
||||
// Copyright 2013 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -430,6 +431,7 @@ public slots:
|
|||
void cycleCamera();
|
||||
void cameraModeChanged();
|
||||
void cameraMenuChanged();
|
||||
void captureMouseChanged(bool captureMouse);
|
||||
void toggleOverlays();
|
||||
void setOverlaysVisible(bool visible);
|
||||
Q_INVOKABLE void centerUI();
|
||||
|
@ -602,6 +604,7 @@ private:
|
|||
|
||||
void maybeToggleMenuVisible(QMouseEvent* event) const;
|
||||
void toggleTabletUI(bool shouldOpen = false) const;
|
||||
bool shouldCaptureMouse() const;
|
||||
|
||||
void userKickConfirmation(const QUuid& nodeID);
|
||||
|
||||
|
@ -755,7 +758,9 @@ private:
|
|||
|
||||
bool _settingsLoaded { false };
|
||||
|
||||
bool _fakedMouseEvent { false };
|
||||
bool _captureMouse { false };
|
||||
bool _ignoreMouseMove { false };
|
||||
QPointF _mouseCaptureTarget { NAN, NAN };
|
||||
|
||||
bool _isMissingSequenceNumbers { false };
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Triplelexx on 23/03/17.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -282,12 +283,14 @@ QVariantMap AvatarBookmarks::getAvatarDataToBookmark() {
|
|||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
|
||||
const QString& avatarUrl = myAvatar->getSkeletonModelURL().toString();
|
||||
const QString& avatarIcon = QString("");
|
||||
const QVariant& avatarScale = myAvatar->getAvatarScale();
|
||||
|
||||
// If Avatar attachments ever change, this is where to update them, when saving remember to also append to AVATAR_BOOKMARK_VERSION
|
||||
QVariantMap bookmark;
|
||||
bookmark.insert(ENTRY_VERSION, AVATAR_BOOKMARK_VERSION);
|
||||
bookmark.insert(ENTRY_AVATAR_URL, avatarUrl);
|
||||
bookmark.insert(ENTRY_AVATAR_ICON, avatarIcon);
|
||||
bookmark.insert(ENTRY_AVATAR_SCALE, avatarScale);
|
||||
|
||||
QVariantList wearableEntities;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Triplelexx on 23/03/17.
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -148,6 +149,7 @@ protected slots:
|
|||
private:
|
||||
const QString AVATARBOOKMARKS_FILENAME = "avatarbookmarks.json";
|
||||
const QString ENTRY_AVATAR_URL = "avatarUrl";
|
||||
const QString ENTRY_AVATAR_ICON = "avatarIcon";
|
||||
const QString ENTRY_AVATAR_ATTACHMENTS = "attachments";
|
||||
const QString ENTRY_AVATAR_ENTITIES = "avatarEntites";
|
||||
const QString ENTRY_AVATAR_SCALE = "avatarScale";
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Gabriel Calero on 9/28/18.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -12,4 +13,4 @@
|
|||
#pragma once
|
||||
#include <QString>
|
||||
|
||||
static const QString API_SIGNUP_PATH = "api/v1/users";
|
||||
static const QString API_SIGNUP_PATH = "/api/v1/users";
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
#define hifi_CrashHandler_h
|
||||
|
||||
#include <string>
|
||||
class QCoreApplication;
|
||||
|
||||
bool startCrashHandler(std::string appPath);
|
||||
void setCrashAnnotation(std::string name, std::string value);
|
||||
void startCrashHookMonitor(QCoreApplication* app);
|
||||
|
||||
#endif // hifi_CrashHandler_h
|
||||
|
|
|
@ -81,4 +81,7 @@ void setCrashAnnotation(std::string name, std::string value) {
|
|||
flushAnnotations();
|
||||
}
|
||||
|
||||
void startCrashHookMonitor(QCoreApplication* app) {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,13 +15,14 @@
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include <QtCore/QAtomicInteger>
|
||||
#include <QtCore/QDeadlineTimer>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QStandardPaths>
|
||||
#include <QtCore/QString>
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
|
@ -31,7 +32,6 @@
|
|||
#include <client/crashpad_client.h>
|
||||
#include <client/crash_report_database.h>
|
||||
#include <client/settings.h>
|
||||
#include <client/annotation_list.h>
|
||||
#include <client/crashpad_info.h>
|
||||
|
||||
#if defined(__clang__)
|
||||
|
@ -42,37 +42,274 @@
|
|||
#include <FingerprintUtils.h>
|
||||
#include <UUID.h>
|
||||
|
||||
using namespace crashpad;
|
||||
static const std::string BACKTRACE_URL{ CMAKE_BACKTRACE_URL };
|
||||
static const std::string BACKTRACE_TOKEN{ CMAKE_BACKTRACE_TOKEN };
|
||||
|
||||
static const std::string BACKTRACE_URL { CMAKE_BACKTRACE_URL };
|
||||
static const std::string BACKTRACE_TOKEN { CMAKE_BACKTRACE_TOKEN };
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// SpinLock - a lock that can timeout attempting to lock a block of code, and is in a busy-wait cycle while trying to acquire
|
||||
// note that this code will malfunction if you attempt to grab a lock while already holding it
|
||||
|
||||
CrashpadClient* client { nullptr };
|
||||
std::mutex annotationMutex;
|
||||
crashpad::SimpleStringDictionary* crashpadAnnotations { nullptr };
|
||||
class SpinLock {
|
||||
public:
|
||||
SpinLock();
|
||||
void lock();
|
||||
bool lock(int msecs);
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
QAtomicInteger<int> _lock{ 0 };
|
||||
|
||||
Q_DISABLE_COPY(SpinLock)
|
||||
};
|
||||
|
||||
class SpinLockLocker {
|
||||
public:
|
||||
SpinLockLocker(SpinLock& lock, int msecs = -1);
|
||||
~SpinLockLocker();
|
||||
bool isLocked() const;
|
||||
void unlock();
|
||||
bool relock(int msecs = -1);
|
||||
|
||||
private:
|
||||
SpinLock* _lock;
|
||||
bool _isLocked;
|
||||
|
||||
Q_DISABLE_COPY(SpinLockLocker)
|
||||
};
|
||||
|
||||
SpinLock::SpinLock() {
|
||||
}
|
||||
|
||||
void SpinLock::lock() {
|
||||
while (!_lock.testAndSetAcquire(0, 1))
|
||||
;
|
||||
}
|
||||
|
||||
bool SpinLock::lock(int msecs) {
|
||||
QDeadlineTimer deadline(msecs);
|
||||
for (;;) {
|
||||
if (_lock.testAndSetAcquire(0, 1)) {
|
||||
return true;
|
||||
}
|
||||
if (deadline.hasExpired()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpinLock::unlock() {
|
||||
_lock.storeRelease(0);
|
||||
}
|
||||
|
||||
SpinLockLocker::SpinLockLocker(SpinLock& lock, int msecs /* = -1 */ ) : _lock(&lock) {
|
||||
_isLocked = _lock->lock(msecs);
|
||||
}
|
||||
|
||||
SpinLockLocker::~SpinLockLocker() {
|
||||
if (_isLocked) {
|
||||
_lock->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
bool SpinLockLocker::isLocked() const {
|
||||
return _isLocked;
|
||||
}
|
||||
|
||||
void SpinLockLocker::unlock() {
|
||||
if (_isLocked) {
|
||||
_lock->unlock();
|
||||
_isLocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SpinLockLocker::relock(int msecs /* = -1 */ ) {
|
||||
if (!_isLocked) {
|
||||
_isLocked = _lock->lock(msecs);
|
||||
}
|
||||
return _isLocked;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
crashpad::CrashpadClient* client{ nullptr };
|
||||
SpinLock crashpadAnnotationsProtect;
|
||||
crashpad::SimpleStringDictionary* crashpadAnnotations{ nullptr };
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
static const QString CRASHPAD_HANDLER_NAME { "crashpad_handler.exe" };
|
||||
static const QString CRASHPAD_HANDLER_NAME{ "crashpad_handler.exe" };
|
||||
#else
|
||||
static const QString CRASHPAD_HANDLER_NAME { "crashpad_handler" };
|
||||
static const QString CRASHPAD_HANDLER_NAME{ "crashpad_handler" };
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// The area within this #ifdef is specific to the Microsoft C++ compiler
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QLogging.h>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <typeinfo>
|
||||
|
||||
LONG WINAPI vectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) {
|
||||
if (!client) {
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
static constexpr DWORD STATUS_MSVC_CPP_EXCEPTION = 0xE06D7363;
|
||||
static constexpr ULONG_PTR MSVC_CPP_EXCEPTION_SIGNATURE = 0x19930520;
|
||||
static constexpr int ANNOTATION_LOCK_WEAK_ATTEMPT = 5000; // attempt to lock the annotations list, but give up if it takes more than 5 seconds
|
||||
|
||||
if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_HEAP_CORRUPTION ||
|
||||
pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_BUFFER_OVERRUN) {
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER gl_crashpadUnhandledExceptionFilter = nullptr;
|
||||
QTimer unhandledExceptionTimer; // checks occasionally in case loading an external DLL reset the unhandled exception pointer
|
||||
|
||||
void fatalCxxException(PEXCEPTION_POINTERS pExceptionInfo); // extracts type information from a thrown C++ exception
|
||||
LONG WINAPI firstChanceExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo); // called on any thrown exception (whether or not it's caught)
|
||||
LONG WINAPI unhandledExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo); // called on any exception without a corresponding catch
|
||||
|
||||
static LONG WINAPI firstChanceExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) {
|
||||
// we're catching these exceptions on first-chance as the system state is corrupted at this point and they may not survive the exception handling mechanism
|
||||
if (client && (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_HEAP_CORRUPTION ||
|
||||
pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_BUFFER_OVERRUN)) {
|
||||
client->DumpAndCrash(pExceptionInfo);
|
||||
}
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
#endif
|
||||
|
||||
static LONG WINAPI unhandledExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) {
|
||||
if (client && pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_MSVC_CPP_EXCEPTION) {
|
||||
fatalCxxException(pExceptionInfo);
|
||||
client->DumpAndCrash(pExceptionInfo);
|
||||
}
|
||||
|
||||
if (gl_crashpadUnhandledExceptionFilter != nullptr) {
|
||||
return gl_crashpadUnhandledExceptionFilter(pExceptionInfo);
|
||||
}
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
// The following structures are modified versions of structs defined inplicitly by the Microsoft C++ compiler
|
||||
// as described at http://www.geoffchappell.com/studies/msvc/language/predefined/
|
||||
// They are redefined here as the definitions the compiler gives only work in 32-bit contexts and are out-of-sync
|
||||
// with the internal structures when operating in a 64-bit environment
|
||||
// as discovered and described here: https://stackoverflow.com/questions/39113168/c-rtti-in-a-windows-64-bit-vectoredexceptionhandler-ms-visual-studio-2015
|
||||
|
||||
#pragma pack(push, ehdata, 4)
|
||||
|
||||
struct PMD_internal { // internal name: _PMD (no changes, so could in theory just use the original)
|
||||
int mdisp;
|
||||
int pdisp;
|
||||
int vdisp;
|
||||
};
|
||||
|
||||
struct ThrowInfo_internal { // internal name: _ThrowInfo (changed all pointers into __int32)
|
||||
__int32 attributes;
|
||||
__int32 pmfnUnwind; // 32-bit RVA
|
||||
__int32 pForwardCompat; // 32-bit RVA
|
||||
__int32 pCatchableTypeArray; // 32-bit RVA
|
||||
};
|
||||
|
||||
struct CatchableType_internal { // internal name: _CatchableType (changed all pointers into __int32)
|
||||
__int32 properties;
|
||||
__int32 pType; // 32-bit RVA
|
||||
PMD_internal thisDisplacement;
|
||||
__int32 sizeOrOffset;
|
||||
__int32 copyFunction; // 32-bit RVA
|
||||
};
|
||||
|
||||
#pragma warning(disable : 4200)
|
||||
struct CatchableTypeArray_internal { // internal name: _CatchableTypeArray (changed all pointers into __int32)
|
||||
int nCatchableTypes;
|
||||
__int32 arrayOfCatchableTypes[0]; // 32-bit RVA
|
||||
};
|
||||
#pragma warning(default : 4200)
|
||||
|
||||
#pragma pack(pop, ehdata)
|
||||
|
||||
// everything inside this function is extremely undocumented, attempting to extract
|
||||
// the underlying C++ exception type (or at least its name) before throwing the whole
|
||||
// mess at crashpad
|
||||
// Some links describing how C++ exception handling works in an SEH context
|
||||
// (since C++ exceptions are a figment of the Microsoft compiler):
|
||||
// - https://www.codeproject.com/Articles/175482/Compiler-Internals-How-Try-Catch-Throw-are-Interpr
|
||||
// - https://stackoverflow.com/questions/21888076/how-to-find-the-context-record-for-user-mode-exception-on-x64
|
||||
|
||||
static void fatalCxxException(PEXCEPTION_POINTERS pExceptionInfo) {
|
||||
SpinLockLocker guard(crashpadAnnotationsProtect, ANNOTATION_LOCK_WEAK_ATTEMPT);
|
||||
if (!guard.isLocked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PEXCEPTION_RECORD ExceptionRecord = pExceptionInfo->ExceptionRecord;
|
||||
/*
|
||||
Exception arguments for Microsoft C++ exceptions:
|
||||
[0] signature - magic number
|
||||
[1] void* - variable that is being thrown
|
||||
[2] ThrowInfo* - description of the variable that was thrown
|
||||
[3] HMODULE - (64-bit only) base address that all 32bit pointers are added to
|
||||
*/
|
||||
|
||||
if (ExceptionRecord->NumberParameters != 4 || ExceptionRecord->ExceptionInformation[0] != MSVC_CPP_EXCEPTION_SIGNATURE) {
|
||||
// doesn't match expected parameter counts or magic numbers
|
||||
return;
|
||||
}
|
||||
|
||||
// get the ThrowInfo struct from the exception arguments
|
||||
ThrowInfo_internal* pThrowInfo = reinterpret_cast<ThrowInfo_internal*>(ExceptionRecord->ExceptionInformation[2]);
|
||||
ULONG_PTR moduleBase = ExceptionRecord->ExceptionInformation[3];
|
||||
if (moduleBase == 0 || pThrowInfo == NULL) {
|
||||
return; // broken assumption
|
||||
}
|
||||
|
||||
// get the CatchableTypeArray* struct from ThrowInfo
|
||||
if (pThrowInfo->pCatchableTypeArray == 0) {
|
||||
return; // broken assumption
|
||||
}
|
||||
CatchableTypeArray_internal* pCatchableTypeArray =
|
||||
reinterpret_cast<CatchableTypeArray_internal*>(moduleBase + pThrowInfo->pCatchableTypeArray);
|
||||
if (pCatchableTypeArray->nCatchableTypes == 0 || pCatchableTypeArray->arrayOfCatchableTypes[0] == 0) {
|
||||
return; // broken assumption
|
||||
}
|
||||
|
||||
// get the CatchableType struct for the actual exception type from CatchableTypeArray
|
||||
CatchableType_internal* pCatchableType =
|
||||
reinterpret_cast<CatchableType_internal*>(moduleBase + pCatchableTypeArray->arrayOfCatchableTypes[0]);
|
||||
if (pCatchableType->pType == 0) {
|
||||
return; // broken assumption
|
||||
}
|
||||
const std::type_info* type = reinterpret_cast<std::type_info*>(moduleBase + pCatchableType->pType);
|
||||
|
||||
crashpadAnnotations->SetKeyValue("thrownObject", type->name());
|
||||
|
||||
// After annotating the name of the actual object type, go through the other entries in CatcahleTypeArray and itemize the list of possible
|
||||
// catch() commands that could have caught this so we can find the list of its superclasses
|
||||
QString compatibleObjects;
|
||||
for (int catchTypeIdx = 1; catchTypeIdx < pCatchableTypeArray->nCatchableTypes; catchTypeIdx++) {
|
||||
CatchableType_internal* pCatchableSuperclassType =
|
||||
reinterpret_cast<CatchableType_internal*>(moduleBase + pCatchableTypeArray->arrayOfCatchableTypes[catchTypeIdx]);
|
||||
if (pCatchableSuperclassType->pType == 0) {
|
||||
return; // broken assumption
|
||||
}
|
||||
const std::type_info* superclassType = reinterpret_cast<std::type_info*>(moduleBase + pCatchableSuperclassType->pType);
|
||||
|
||||
if (!compatibleObjects.isEmpty()) {
|
||||
compatibleObjects += ", ";
|
||||
}
|
||||
compatibleObjects += superclassType->name();
|
||||
}
|
||||
crashpadAnnotations->SetKeyValue("thrownObjectLike", compatibleObjects.toStdString());
|
||||
}
|
||||
|
||||
void checkUnhandledExceptionHook() {
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter = SetUnhandledExceptionFilter(unhandledExceptionHandler);
|
||||
if (prevExceptionFilter != unhandledExceptionHandler) {
|
||||
qWarning() << QString("Restored unhandled exception filter (which had been changed to %1)")
|
||||
.arg(reinterpret_cast<ULONG_PTR>(prevExceptionFilter), 16, 16, QChar('0'));
|
||||
}
|
||||
}
|
||||
|
||||
// End of code specific to the Microsoft C++ compiler
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
bool startCrashHandler(std::string appPath) {
|
||||
if (BACKTRACE_URL.empty() || BACKTRACE_TOKEN.empty()) {
|
||||
|
@ -80,7 +317,7 @@ bool startCrashHandler(std::string appPath) {
|
|||
}
|
||||
|
||||
assert(!client);
|
||||
client = new CrashpadClient();
|
||||
client = new crashpad::CrashpadClient();
|
||||
std::vector<std::string> arguments;
|
||||
|
||||
std::map<std::string, std::string> annotations;
|
||||
|
@ -92,17 +329,16 @@ bool startCrashHandler(std::string appPath) {
|
|||
auto machineFingerPrint = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint());
|
||||
annotations["machine_fingerprint"] = machineFingerPrint.toStdString();
|
||||
|
||||
|
||||
arguments.push_back("--no-rate-limit");
|
||||
|
||||
// Setup Crashpad DB directory
|
||||
const auto crashpadDbName = "crashpad-db";
|
||||
const auto crashpadDbDir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
|
||||
QDir(crashpadDbDir).mkpath(crashpadDbName); // Make sure the directory exists
|
||||
QDir(crashpadDbDir).mkpath(crashpadDbName); // Make sure the directory exists
|
||||
const auto crashpadDbPath = crashpadDbDir.toStdString() + "/" + crashpadDbName;
|
||||
|
||||
// Locate Crashpad handler
|
||||
const QFileInfo interfaceBinary { QString::fromStdString(appPath) };
|
||||
const QFileInfo interfaceBinary{ QString::fromStdString(appPath) };
|
||||
const QDir interfaceDir = interfaceBinary.dir();
|
||||
assert(interfaceDir.exists(CRASHPAD_HANDLER_NAME));
|
||||
const std::string CRASHPAD_HANDLER_PATH = interfaceDir.filePath(CRASHPAD_HANDLER_NAME).toStdString();
|
||||
|
@ -124,18 +360,23 @@ bool startCrashHandler(std::string appPath) {
|
|||
// Enable automated uploads.
|
||||
database->GetSettings()->SetUploadsEnabled(true);
|
||||
|
||||
if (!client->StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
AddVectoredExceptionHandler(0, vectoredExceptionHandler);
|
||||
AddVectoredExceptionHandler(0, firstChanceExceptionHandler);
|
||||
gl_crashpadUnhandledExceptionFilter = SetUnhandledExceptionFilter(unhandledExceptionHandler);
|
||||
#endif
|
||||
|
||||
return client->StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void setCrashAnnotation(std::string name, std::string value) {
|
||||
if (client) {
|
||||
std::lock_guard<std::mutex> guard(annotationMutex);
|
||||
SpinLockLocker guard(crashpadAnnotationsProtect);
|
||||
if (!crashpadAnnotations) {
|
||||
crashpadAnnotations = new crashpad::SimpleStringDictionary(); // don't free this, let it leak
|
||||
crashpadAnnotations = new crashpad::SimpleStringDictionary(); // don't free this, let it leak
|
||||
crashpad::CrashpadInfo* crashpad_info = crashpad::CrashpadInfo::GetCrashpadInfo();
|
||||
crashpad_info->set_simple_annotations(crashpadAnnotations);
|
||||
}
|
||||
|
@ -144,4 +385,18 @@ void setCrashAnnotation(std::string name, std::string value) {
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
void startCrashHookMonitor(QCoreApplication* app) {
|
||||
#ifdef Q_OS_WIN
|
||||
// create a timer that checks to see if our exception handler has been reset. This may occur when a new CRT
|
||||
// is initialized, which could happen any time a DLL not compiled with the same compiler is loaded.
|
||||
// It would be nice if this were replaced with a more intelligent response; this fires once a minute which
|
||||
// may be too much (extra code running) and too little (leaving up to a 1min gap after the hook is broken)
|
||||
checkUnhandledExceptionHook();
|
||||
|
||||
unhandledExceptionTimer.moveToThread(app->thread());
|
||||
QObject::connect(&unhandledExceptionTimer, &QTimer::timeout, checkUnhandledExceptionHook);
|
||||
unhandledExceptionTimer.start(60000);
|
||||
#endif // Q_OS_WIN
|
||||
}
|
||||
|
||||
#endif // HAS_CRASHPAD
|
||||
|
|
|
@ -25,4 +25,7 @@ bool startCrashHandler(std::string appPath) {
|
|||
void setCrashAnnotation(std::string name, std::string value) {
|
||||
}
|
||||
|
||||
void startCrashHookMonitor(QCoreApplication* app) {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,6 +36,10 @@ class FancyCamera : public Camera {
|
|||
* @property {ViewFrustum} frustum - The camera frustum.
|
||||
* @property {Uuid} cameraEntity - The ID of the entity that is used for the camera position and orientation when the
|
||||
* camera is in entity mode.
|
||||
* @property {boolean} captureMouse - The mouse capture state. When <code>true</code>, the mouse is invisible and cannot leave the bounds of
|
||||
* Interface, as long as Interface is the active window and no menu item is selected. When <code>false</code>, the mouse
|
||||
* behaves normally.
|
||||
* @property {number} sensitivity - The current camera sensitivity. Must be positive.
|
||||
*/
|
||||
Q_PROPERTY(QUuid cameraEntity READ getCameraEntity WRITE setCameraEntity)
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "avatar/AvatarManager.h"
|
||||
#include "avatar/AvatarPackager.h"
|
||||
#include "AvatarBookmarks.h"
|
||||
#include "DomainAccountManager.h"
|
||||
#include "MainWindow.h"
|
||||
#include "render/DrawStatus.h"
|
||||
#include "scripting/MenuScriptingInterface.h"
|
||||
|
@ -73,6 +74,7 @@ const char* EXCLUSION_GROUP_KEY = "exclusionGroup";
|
|||
Menu::Menu() {
|
||||
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
auto domainAccountManager = DependencyManager::get<DomainAccountManager>();
|
||||
|
||||
// File/Application menu ----------------------------------
|
||||
MenuWrapper* fileMenu = addMenu("File");
|
||||
|
@ -89,11 +91,15 @@ Menu::Menu() {
|
|||
}
|
||||
|
||||
auto domainLogin = addActionToQMenuAndActionHash(fileMenu, "Domain: Log In");
|
||||
domainLogin->setVisible(false);
|
||||
connect(domainLogin, &QAction::triggered, [] {
|
||||
auto dialogsManager = DependencyManager::get<DialogsManager>();
|
||||
dialogsManager->setDomainLoginState();
|
||||
dialogsManager->showDomainLoginDialog();
|
||||
});
|
||||
connect(domainAccountManager.data(), &DomainAccountManager::hasLogInChanged, [domainLogin](bool hasLogIn) {
|
||||
domainLogin->setVisible(hasLogIn);
|
||||
});
|
||||
|
||||
// File > Quit
|
||||
addActionToQMenuAndActionHash(fileMenu, MenuOption::Quit, Qt::CTRL | Qt::Key_Q, qApp, SLOT(quit()), QAction::QuitRole);
|
||||
|
@ -232,11 +238,11 @@ Menu::Menu() {
|
|||
|
||||
// Navigate > Start-up Location
|
||||
MenuWrapper* startupLocationMenu = navigateMenu->addMenu(MenuOption::StartUpLocation);
|
||||
QActionGroup* startupLocatiopnGroup = new QActionGroup(startupLocationMenu);
|
||||
startupLocatiopnGroup->setExclusive(true);
|
||||
startupLocatiopnGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::HomeLocation, 0,
|
||||
QActionGroup* startupLocationGroup = new QActionGroup(startupLocationMenu);
|
||||
startupLocationGroup->setExclusive(true);
|
||||
startupLocationGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::HomeLocation, 0,
|
||||
false));
|
||||
startupLocatiopnGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::LastLocation, 0,
|
||||
startupLocationGroup->addAction(addCheckableActionToQMenuAndActionHash(startupLocationMenu, MenuOption::LastLocation, 0,
|
||||
true));
|
||||
|
||||
// Settings menu ----------------------------------
|
||||
|
@ -716,7 +722,7 @@ Menu::Menu() {
|
|||
// Developer > Crash >>>
|
||||
bool result = false;
|
||||
const QString HIFI_SHOW_DEVELOPER_CRASH_MENU("HIFI_SHOW_DEVELOPER_CRASH_MENU");
|
||||
result = QProcessEnvironment::systemEnvironment().contains(HIFI_SHOW_DEVELOPER_CRASH_MENU);
|
||||
result = true;//QProcessEnvironment::systemEnvironment().contains(HIFI_SHOW_DEVELOPER_CRASH_MENU);
|
||||
if (result) {
|
||||
MenuWrapper* crashMenu = developerMenu->addMenu("Crash");
|
||||
|
||||
|
@ -756,6 +762,11 @@ Menu::Menu() {
|
|||
action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNewFaultThreaded);
|
||||
connect(action, &QAction::triggered, qApp, []() { std::thread(crash::newFault).join(); });
|
||||
|
||||
action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashThrownException);
|
||||
connect(action, &QAction::triggered, qApp, []() { crash::throwException(); });
|
||||
action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashThrownExceptionThreaded);
|
||||
connect(action, &QAction::triggered, qApp, []() { std::thread(crash::throwException).join(); });
|
||||
|
||||
addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashOnShutdown, 0, qApp, SLOT(crashOnShutdown()));
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,8 @@ namespace MenuOption {
|
|||
const QString CrashOutOfBoundsVectorAccessThreaded = "Out of Bounds Vector Access (threaded)";
|
||||
const QString CrashNewFault = "New Fault";
|
||||
const QString CrashNewFaultThreaded = "New Fault (threaded)";
|
||||
const QString CrashThrownException = "Thrown C++ exception";
|
||||
const QString CrashThrownExceptionThreaded = "Thrown C++ exception (threaded)";
|
||||
const QString CreateEntitiesGrabbable = "Create Entities As Grabbable (except Zones, Particles, and Lights)";
|
||||
const QString DeadlockInterface = "Deadlock Interface";
|
||||
const QString UnresponsiveInterface = "Unresponsive Interface";
|
||||
|
|
|
@ -296,7 +296,7 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename
|
|||
mapping.insert(JOINT_FIELD, joints);
|
||||
|
||||
// If there are no blendshape mappings, and we detect that this is likely a mixamo file,
|
||||
// then we can add the default mixamo to "faceshift" mappings
|
||||
// then we can add the default mixamo to blendshape mappings.
|
||||
if (!mapping.contains(BLENDSHAPE_FIELD) && likelyMixamoFile) {
|
||||
QVariantHash blendshapes;
|
||||
blendshapes.insertMulti("BrowsD_L", QVariantList() << "BrowsDown_Left" << 1.0);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// Created by Mark Peng on 8/16/13.
|
||||
// Copyright 2012 High Fidelity, Inc.
|
||||
// Copyright 2020 Vircadia contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -25,31 +26,33 @@
|
|||
#include <scripting/HMDScriptingInterface.h>
|
||||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
#include <AnimDebugDraw.h>
|
||||
#include <AnimClip.h>
|
||||
#include <AnimInverseKinematics.h>
|
||||
#include <AudioClient.h>
|
||||
#include <ClientTraitsHandler.h>
|
||||
#include <recording/Clip.h>
|
||||
#include <recording/Deck.h>
|
||||
#include <display-plugins/DisplayPlugin.h>
|
||||
#include <recording/Frame.h>
|
||||
#include <FSTReader.h>
|
||||
#include <GeometryUtil.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <NodeList.h>
|
||||
#include <NetworkingConstants.h>
|
||||
#include <udt/PacketHeaders.h>
|
||||
#include <PathUtils.h>
|
||||
#include <PerfStat.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <SoundCache.h>
|
||||
#include <ModelEntityItem.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <TextRenderer3D.h>
|
||||
#include <UserActivityLogger.h>
|
||||
#include <AnimDebugDraw.h>
|
||||
#include <AnimClip.h>
|
||||
#include <AnimInverseKinematics.h>
|
||||
#include <recording/Deck.h>
|
||||
#include <recording/Recorder.h>
|
||||
#include <recording/Clip.h>
|
||||
#include <recording/Frame.h>
|
||||
#include <RecordingScriptingInterface.h>
|
||||
#include <RenderableModelEntityItem.h>
|
||||
#include <VariantMapToScriptValue.h>
|
||||
#include <NetworkingConstants.h>
|
||||
|
||||
#include "MyHead.h"
|
||||
#include "MySkeletonModel.h"
|
||||
|
@ -82,7 +85,7 @@ const int SCRIPTED_MOTOR_AVATAR_FRAME = 1;
|
|||
const int SCRIPTED_MOTOR_WORLD_FRAME = 2;
|
||||
const int SCRIPTED_MOTOR_SIMPLE_MODE = 0;
|
||||
const int SCRIPTED_MOTOR_DYNAMIC_MODE = 1;
|
||||
const QString& DEFAULT_AVATAR_COLLISION_SOUND_URL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/Body_Hits_Impact.wav";
|
||||
const QString& DEFAULT_AVATAR_COLLISION_SOUND_URL = NetworkingConstants::HF_PUBLIC_CDN_URL + "sounds/Collisions-otherorganic/Body_Hits_Impact.wav";
|
||||
|
||||
const float MyAvatar::ZOOM_MIN = 0.5f;
|
||||
const float MyAvatar::ZOOM_MAX = 25.0f;
|
||||
|
|
|
@ -168,6 +168,7 @@ const btCollisionShape* OtherAvatar::createCollisionShape(int32_t jointIndex, bo
|
|||
}
|
||||
// Note: MultiSphereLow case really means: "skip fingers and use spheres for hands,
|
||||
// else fall through to MultiSphereHigh case"
|
||||
/* fall-thru */
|
||||
case BodyLOD::MultiSphereHigh:
|
||||
computeDetailedShapeInfo(shapeInfo, jointIndex);
|
||||
break;
|
||||
|
|
|
@ -288,8 +288,10 @@ Wallet::Wallet() {
|
|||
auto& packetReceiver = nodeList->getPacketReceiver();
|
||||
_passphrase = new QString("");
|
||||
|
||||
packetReceiver.registerListener(PacketType::ChallengeOwnership, this, "handleChallengeOwnershipPacket");
|
||||
packetReceiver.registerListener(PacketType::ChallengeOwnershipRequest, this, "handleChallengeOwnershipPacket");
|
||||
packetReceiver.registerListener(PacketType::ChallengeOwnership,
|
||||
PacketReceiver::makeSourcedListenerReference<Wallet>(this, &Wallet::handleChallengeOwnershipPacket));
|
||||
packetReceiver.registerListener(PacketType::ChallengeOwnershipRequest,
|
||||
PacketReceiver::makeSourcedListenerReference<Wallet>(this, &Wallet::handleChallengeOwnershipPacket));
|
||||
|
||||
connect(ledger.data(), &Ledger::accountResult, this, [](QJsonObject result) {
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
|
|
|
@ -81,7 +81,7 @@ int main(int argc, const char* argv[]) {
|
|||
QCommandLineOption noUpdaterOption("no-updater", "Do not show auto-updater");
|
||||
QCommandLineOption checkMinSpecOption("checkMinSpec", "Check if machine meets minimum specifications");
|
||||
QCommandLineOption runServerOption("runServer", "Whether to run the server");
|
||||
QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content", "serverContentPath");
|
||||
QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content <path>", "serverContentPath");
|
||||
QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run");
|
||||
QCommandLineOption overrideAppLocalDataPathOption("cache", "set test cache <dir>", "dir");
|
||||
QCommandLineOption overrideScriptsPathOption(SCRIPTS_SWITCH, "set scripts <path>", "path");
|
||||
|
@ -381,6 +381,7 @@ int main(int argc, const char* argv[]) {
|
|||
#if defined(Q_OS_LINUX)
|
||||
app.setWindowIcon(QIcon(PathUtils::resourcesPath() + "images/vircadia-logo.svg"));
|
||||
#endif
|
||||
startCrashHookMonitor(&app);
|
||||
|
||||
QTimer exitTimer;
|
||||
if (traceDuration > 0.0f) {
|
||||
|
|
|
@ -30,7 +30,7 @@ QNetworkRequest createNetworkRequest() {
|
|||
QNetworkRequest request;
|
||||
|
||||
QUrl requestURL = MetaverseAPI::getCurrentMetaverseServerURL();
|
||||
requestURL.setPath(USER_ACTIVITY_URL);
|
||||
requestURL.setPath(MetaverseAPI::getCurrentMetaverseServerURLPath() + USER_ACTIVITY_URL);
|
||||
|
||||
request.setUrl(requestURL);
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ OctreePacketProcessor::OctreePacketProcessor():
|
|||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
const PacketReceiver::PacketTypeList octreePackets =
|
||||
{ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase, PacketType::EntityQueryInitialResultsComplete };
|
||||
packetReceiver.registerDirectListenerForTypes(octreePackets, this, "handleOctreePacket");
|
||||
packetReceiver.registerDirectListenerForTypes(octreePackets,
|
||||
PacketReceiver::makeSourcedListenerReference<OctreePacketProcessor>(this, &OctreePacketProcessor::handleOctreePacket));
|
||||
}
|
||||
|
||||
OctreePacketProcessor::~OctreePacketProcessor() { }
|
||||
|
|
|
@ -18,11 +18,13 @@
|
|||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <NetworkingConstants.h>
|
||||
#include <NodeList.h>
|
||||
#include <UUID.h>
|
||||
|
||||
#include "EntityScriptingInterface.h"
|
||||
#include "ScreenshareScriptingInterface.h"
|
||||
#include "ExternalResource.h"
|
||||
|
||||
static const int SCREENSHARE_INFO_REQUEST_RETRY_TIMEOUT_MS = 300;
|
||||
ScreenshareScriptingInterface::ScreenshareScriptingInterface() {
|
||||
|
@ -42,7 +44,8 @@ ScreenshareScriptingInterface::ScreenshareScriptingInterface() {
|
|||
// This packet listener handles the packet containing information about the latest zone ID in which we are allowed to share.
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
PacketReceiver& packetReceiver = nodeList->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::AvatarZonePresence, this, "processAvatarZonePresencePacketOnClient");
|
||||
packetReceiver.registerListener(PacketType::AvatarZonePresence,
|
||||
PacketReceiver::makeUnsourcedListenerReference<ScreenshareScriptingInterface>(this, &ScreenshareScriptingInterface::processAvatarZonePresencePacketOnClient));
|
||||
};
|
||||
|
||||
ScreenshareScriptingInterface::~ScreenshareScriptingInterface() {
|
||||
|
@ -108,7 +111,7 @@ void ScreenshareScriptingInterface::requestScreenshareInfo() {
|
|||
// See `DomainServer::screensharePresence()` for more info about that.
|
||||
|
||||
QString currentDomainID = uuidStringWithoutCurlyBraces(addressManager->getDomainID());
|
||||
QString requestURLPath = "api/v1/domains/%1/screenshare";
|
||||
QString requestURLPath = "/api/v1/domains/%1/screenshare";
|
||||
JSONCallbackParameters callbackParams;
|
||||
callbackParams.callbackReceiver = this;
|
||||
callbackParams.jsonCallbackMethod = "handleSuccessfulScreenshareInfoGet";
|
||||
|
@ -128,8 +131,9 @@ static const uint8_t LOCAL_SCREENSHARE_WEB_ENTITY_FPS = 30;
|
|||
// The `z` value here is dynamic.
|
||||
static const glm::vec3 LOCAL_SCREENSHARE_WEB_ENTITY_LOCAL_POSITION(0.0128f, -0.0918f, 0.0f);
|
||||
static const glm::vec3 LOCAL_SCREENSHARE_WEB_ENTITY_DIMENSIONS(3.6790f, 2.0990f, 0.0100f);
|
||||
static const QString LOCAL_SCREENSHARE_WEB_ENTITY_URL =
|
||||
"https://content.highfidelity.com/Experiences/Releases/usefulUtilities/smartBoard/screenshareViewer/screenshareClient.html";
|
||||
static const ExternalResource::Bucket LOCAL_SCREENSHARE_WEB_ENTITY_BUCKET = ExternalResource::Bucket::HF_Content;
|
||||
static const QString LOCAL_SCREENSHARE_WEB_ENTITY_PATH =
|
||||
"Experiences/Releases/usefulUtilities/smartBoard/screenshareViewer/screenshareClient.html";
|
||||
static const QString LOCAL_SCREENSHARE_WEB_ENTITY_HOST_TYPE = "local";
|
||||
void ScreenshareScriptingInterface::startScreenshare(const QUuid& screenshareZoneID,
|
||||
const QUuid& smartboardEntityID,
|
||||
|
@ -281,6 +285,8 @@ void ScreenshareScriptingInterface::handleSuccessfulScreenshareInfoGet(QNetworkR
|
|||
glm::vec3 localPosition(LOCAL_SCREENSHARE_WEB_ENTITY_LOCAL_POSITION);
|
||||
localPosition.z = _localWebEntityZOffset;
|
||||
localScreenshareWebEntityProps.setLocalPosition(localPosition);
|
||||
auto LOCAL_SCREENSHARE_WEB_ENTITY_URL = ExternalResource::getInstance()->getUrl(LOCAL_SCREENSHARE_WEB_ENTITY_BUCKET,
|
||||
LOCAL_SCREENSHARE_WEB_ENTITY_PATH);
|
||||
localScreenshareWebEntityProps.setSourceUrl(LOCAL_SCREENSHARE_WEB_ENTITY_URL);
|
||||
localScreenshareWebEntityProps.setParentID(_smartboardEntityID);
|
||||
localScreenshareWebEntityProps.setDimensions(LOCAL_SCREENSHARE_WEB_ENTITY_DIMENSIONS);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <Trace.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "NetworkingConstants.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(trace_test, "trace.test")
|
||||
|
||||
|
@ -66,8 +67,8 @@ bool TestScriptingInterface::loadTestScene(QString scene) {
|
|||
return result;
|
||||
}
|
||||
|
||||
static const QString TEST_ROOT = "https://raw.githubusercontent.com/highfidelity/hifi_tests/master/";
|
||||
static const QString TEST_BINARY_ROOT = "https://hifi-public.s3.amazonaws.com/test_scene_data/";
|
||||
static const QString TEST_ROOT = "https://raw.githubusercontent.com/hifi-archive/hifi_tests/master/";
|
||||
static const QString TEST_BINARY_ROOT = NetworkingConstants::HF_CONTENT_CDN_URL + "test_scene_data/";
|
||||
static const QString TEST_SCRIPTS_ROOT = TEST_ROOT + "scripts/";
|
||||
static const QString TEST_SCENES_ROOT = TEST_ROOT + "scenes/";
|
||||
|
||||
|
|
|
@ -645,12 +645,16 @@ void WindowScriptingInterface::setActiveDisplayPlugin(int index) {
|
|||
qApp->setActiveDisplayPlugin(name);
|
||||
}
|
||||
|
||||
void WindowScriptingInterface::openWebBrowser() {
|
||||
void WindowScriptingInterface::openWebBrowser(const QString& url) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "openWebBrowser", Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(this, "openWebBrowser", Q_ARG(const QString&, url));
|
||||
return;
|
||||
}
|
||||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->load("Browser.qml");
|
||||
offscreenUi->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) {
|
||||
if (!url.isEmpty()) {
|
||||
newObject->setProperty("url", url);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -616,10 +616,11 @@ public slots:
|
|||
void setActiveDisplayPlugin(int index);
|
||||
|
||||
/**jsdoc
|
||||
* Opens a web browser in a pop-up window.
|
||||
* Opens an Interface web browser window.
|
||||
* @function Window.openWebBrowser
|
||||
* @param {string} [url=""] - The URL of the web page to display.
|
||||
*/
|
||||
void openWebBrowser();
|
||||
void openWebBrowser(const QString& url = "");
|
||||
|
||||
|
||||
private slots:
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
//
|
||||
|
||||
#include "DomainConnectionModel.h"
|
||||
#include <QLoggingCategory>
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtCore/QMetaMethod>
|
||||
|
||||
#include <NodeList.h>
|
||||
#include <NumericalConstants.h>
|
||||
|
|
|
@ -167,6 +167,13 @@ LogDialog::LogDialog(QWidget* parent, AbstractLoggerInterface* logger) : BaseLog
|
|||
}
|
||||
_extraDebuggingBox->show();
|
||||
connect(_extraDebuggingBox, &QCheckBox::stateChanged, this, &LogDialog::handleExtraDebuggingCheckbox);
|
||||
|
||||
_showSourceDebuggingBox = new QCheckBox("Show script sources", this);
|
||||
if (_logger->showSourceDebugging()) {
|
||||
_showSourceDebuggingBox->setCheckState(Qt::Checked);
|
||||
}
|
||||
_showSourceDebuggingBox->show();
|
||||
connect(_showSourceDebuggingBox, &QCheckBox::stateChanged, this, &LogDialog::handleShowSourceDebuggingCheckbox);
|
||||
|
||||
_allLogsButton = new QPushButton("All Messages", this);
|
||||
// set object name for css styling
|
||||
|
@ -196,8 +203,13 @@ void LogDialog::resizeEvent(QResizeEvent* event) {
|
|||
THIRD_ROW,
|
||||
COMBOBOX_WIDTH,
|
||||
ELEMENT_HEIGHT);
|
||||
|
||||
_keepOnTopBox->setGeometry(width() - ELEMENT_MARGIN - COMBOBOX_WIDTH - ELEMENT_MARGIN - ALL_LOGS_BUTTON_WIDTH - ELEMENT_MARGIN - COMBOBOX_WIDTH - ELEMENT_MARGIN,
|
||||
_keepOnTopBox->setGeometry(width() - ELEMENT_MARGIN - COMBOBOX_WIDTH - ELEMENT_MARGIN - ALL_LOGS_BUTTON_WIDTH - ELEMENT_MARGIN - COMBOBOX_WIDTH - ELEMENT_MARGIN,
|
||||
THIRD_ROW,
|
||||
COMBOBOX_WIDTH,
|
||||
ELEMENT_HEIGHT);
|
||||
_showSourceDebuggingBox->setGeometry(width() - ELEMENT_MARGIN - COMBOBOX_WIDTH - ELEMENT_MARGIN - ALL_LOGS_BUTTON_WIDTH
|
||||
- ELEMENT_MARGIN - COMBOBOX_WIDTH - ELEMENT_MARGIN - ELEMENT_MARGIN
|
||||
- COMBOBOX_WIDTH - ELEMENT_MARGIN,
|
||||
THIRD_ROW,
|
||||
COMBOBOX_WIDTH,
|
||||
ELEMENT_HEIGHT);
|
||||
|
@ -217,6 +229,8 @@ void LogDialog::handleRevealButton() {
|
|||
}
|
||||
|
||||
void LogDialog::handleAllLogsButton() {
|
||||
_logger->setShowSourceDebugging(false);
|
||||
_showSourceDebuggingBox->setCheckState(Qt::Unchecked);
|
||||
_logger->setExtraDebugging(false);
|
||||
_extraDebuggingBox->setCheckState(Qt::Unchecked);
|
||||
_logger->setDebugPrint(true);
|
||||
|
@ -238,6 +252,10 @@ void LogDialog::handleAllLogsButton() {
|
|||
printLogFile();
|
||||
}
|
||||
|
||||
void LogDialog::handleShowSourceDebuggingCheckbox(int state) {
|
||||
_logger->setShowSourceDebugging(state != 0);
|
||||
}
|
||||
|
||||
void LogDialog::handleExtraDebuggingCheckbox(int state) {
|
||||
_logger->setExtraDebugging(state != 0);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ public slots:
|
|||
|
||||
private slots:
|
||||
void handleRevealButton();
|
||||
void handleShowSourceDebuggingCheckbox(int);
|
||||
void handleExtraDebuggingCheckbox(int);
|
||||
void handleKeepWindowOnTop(int);
|
||||
void handleDebugPrintBox(int);
|
||||
|
@ -55,6 +56,7 @@ protected:
|
|||
|
||||
|
||||
private:
|
||||
QCheckBox* _showSourceDebuggingBox;
|
||||
QCheckBox* _extraDebuggingBox;
|
||||
QCheckBox* _keepOnTopBox;
|
||||
QPushButton* _revealLogButton;
|
||||
|
|
|
@ -172,7 +172,7 @@ void LoginDialog::linkOculus() {
|
|||
callbackParams.callbackReceiver = this;
|
||||
callbackParams.jsonCallbackMethod = "linkCompleted";
|
||||
callbackParams.errorCallbackMethod = "linkFailed";
|
||||
const QString LINK_OCULUS_PATH = "api/v1/user/oculus/link";
|
||||
const QString LINK_OCULUS_PATH = "/api/v1/user/oculus/link";
|
||||
|
||||
QJsonObject payload;
|
||||
payload["oculus_nonce"] = nonce;
|
||||
|
@ -200,7 +200,7 @@ void LoginDialog::createAccountFromOculus(QString email, QString username, QStri
|
|||
callbackParams.jsonCallbackMethod = "createCompleted";
|
||||
callbackParams.errorCallbackMethod = "createFailed";
|
||||
|
||||
const QString CREATE_ACCOUNT_FROM_OCULUS_PATH = "api/v1/user/oculus/create";
|
||||
const QString CREATE_ACCOUNT_FROM_OCULUS_PATH = "/api/v1/user/oculus/create";
|
||||
|
||||
QJsonObject payload;
|
||||
payload["oculus_nonce"] = nonce;
|
||||
|
@ -251,7 +251,7 @@ void LoginDialog::linkSteam() {
|
|||
callbackParams.jsonCallbackMethod = "linkCompleted";
|
||||
callbackParams.errorCallbackMethod = "linkFailed";
|
||||
|
||||
const QString LINK_STEAM_PATH = "api/v1/user/steam/link";
|
||||
const QString LINK_STEAM_PATH = "/api/v1/user/steam/link";
|
||||
|
||||
QJsonObject payload;
|
||||
payload["steam_auth_ticket"] = QJsonValue::fromVariant(QVariant(ticket));
|
||||
|
@ -278,7 +278,7 @@ void LoginDialog::createAccountFromSteam(QString username) {
|
|||
callbackParams.jsonCallbackMethod = "createCompleted";
|
||||
callbackParams.errorCallbackMethod = "createFailed";
|
||||
|
||||
const QString CREATE_ACCOUNT_FROM_STEAM_PATH = "api/v1/user/steam/create";
|
||||
const QString CREATE_ACCOUNT_FROM_STEAM_PATH = "/api/v1/user/steam/create";
|
||||
|
||||
QJsonObject payload;
|
||||
payload["steam_auth_ticket"] = QJsonValue::fromVariant(QVariant(ticket));
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue