diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index d1ecb1bb02..4b3d66da50 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -9,7 +9,8 @@ env: BUILD_TYPE: Release CI_BUILD: Github GIT_COMMIT: ${{ github.sha }} - HIFI_VCPKG_BOOTSTRAP: true + # 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: PR RELEASE_NUMBER: ${{ github.event.number }} VERSION_CODE: ${{ github.event.number }} @@ -28,8 +29,12 @@ jobs: build: strategy: matrix: - os: [windows-latest, macOS-latest] + os: [windows-latest, macOS-latest, ubuntu-18.04] 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}} if: github.event.action != 'labeled' || github.event.label.name == 'rebuild' @@ -39,10 +44,14 @@ jobs: id: buildenv1 run: | 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=INSTALLER_EXT::* + echo ::set-env name=CMAKE_BUILD_EXTRA::"-- -j3" + echo ::set-env name=CMAKE_EXTRA::"-DBUILD_TOOLS:BOOLEAN=FALSE" fi # Mac build variables if [ "${{ matrix.os }}" = "macOS-latest" ]; then @@ -61,11 +70,11 @@ jobs: 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::ProjectAthena-Alpha-PR${{ github.event.number }}-*.$INSTALLER_EXT # Build type variables echo ::set-env name=INSTALLER::HighFidelity-Beta-$RELEASE_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT - name: Clear Working Directory - if: matrix.os[1] == 'windows' + if: startsWith(matrix.os, 'windows') shell: bash working-directory: ${{runner.workspace}} run: rm -rf ./* @@ -73,61 +82,83 @@ jobs: with: submodules: true fetch-depth: 1 + - name: Install dependencies + shell: bash + if: startsWith(matrix.os, 'ubuntu') + 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: 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 $CMAKE_EXTRA + run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DVCPKG_BUILD_TYPE=release $CMAKE_EXTRA - name: Build Application working-directory: ${{runner.workspace}}/build shell: bash - run: cmake --build . --config $BUILD_TYPE --target $APP_NAME + 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 domain-server + 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 assignment-client + 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 + run: cmake --build . --config $BUILD_TYPE --target packaged-server-console $CMAKE_BUILD_EXTRA - name: Build Installer working-directory: ${{runner.workspace}}/build shell: bash - run: cmake --build . --config $BUILD_TYPE --target package + 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: Output system stats + if: ${{ always() }} + working-directory: ${{runner.workspace}}/build + shell: bash + run: | + echo "Disk usage:" + df -h - name: Output Installer Logs if: failure() && matrix.os == 'windows-latest' shell: bash working-directory: ${{runner.workspace}}/build run: cat ./_CPack_Packages/win64/NSIS/NSISOutput.log - - build_full_linux: - runs-on: ubuntu-latest - if: github.event.action != 'labeled' || github.event.label.name == 'rebuild' - steps: - - uses: actions/checkout@v1 - with: - submodules: true - fetch-depth: 1 - - name: Update apt repository index - run: sudo apt update - - name: Install apt packages - run: sudo apt install -y mesa-common-dev libegl1 libglvnd-dev libdouble-conversion1 libpulse0 - - name: Install python modules - shell: bash - run: pip install boto3 distro PyGithub - - name: Create Build Environment - 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 -DBUILD_TOOLS:BOOLEAN=FALSE - - name: + - name: Upload Artifact shell: bash working-directory: ${{runner.workspace}}/build - run: cmake --build . -- -j3 + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: $PYTHON_EXEC "$GITHUB_WORKSPACE/tools/ci-scripts/upload_to_publish_server.py" diff --git a/BUILD.md b/BUILD.md index bc032d4ec7..1cad8724b3 100644 --- a/BUILD.md +++ b/BUILD.md @@ -73,6 +73,18 @@ Create a build directory in the root of your checkout and then run the CMake bui If cmake gives you the same error message repeatedly after the build fails, try removing `CMakeCache.txt`. +##### Generating a release/debug only vcpkg build + +In order to generate a release or debug only vcpkg package, you could use the use the `VCPKG_BUILD_TYPE` define in your cmake generate command. Building a release only vcpkg can drastically decrease the total build time. + +For release only vcpkg: + +`cmake .. -DVCPKG_BUILD_TYPE=release` + +For debug only vcpkg: + +`cmake .. -DVCPKG_BUILD_TYPE=debug` + #### Variables Any variables that need to be set for CMake to find dependencies can be set as ENV variables in your shell profile, or passed directly to CMake with a `-D` flag appended to the `cmake ..` command. diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bf7b8bc56..ecbfd2eed9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,8 +67,12 @@ if (HIFI_ANDROID) WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) else() + set(VCPKG_BUILD_TYPE_PARAM "") + if (VCPKG_BUILD_TYPE) + set(VCPKG_BUILD_TYPE_PARAM --vcpkg-build-type ${VCPKG_BUILD_TYPE}) + endif() execute_process( - COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_CURRENT_SOURCE_DIR}/prebuild.py --release-type ${RELEASE_TYPE} --build-root ${CMAKE_BINARY_DIR} + COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_CURRENT_SOURCE_DIR}/prebuild.py --release-type ${RELEASE_TYPE} --build-root ${CMAKE_BINARY_DIR} ${VCPKG_BUILD_TYPE_PARAM} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) # squelch the Policy CMP0074 warning without requiring an update to cmake 3.12. diff --git a/assignment-client/src/avatars/ScriptableAvatar.h b/assignment-client/src/avatars/ScriptableAvatar.h index 500c3f44fb..1e6046ba7e 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.h +++ b/assignment-client/src/avatars/ScriptableAvatar.h @@ -82,15 +82,15 @@ *

Note: This property will automatically be set to true if the Controller system has valid facial * blend shape actions.

* @property {boolean} hasProceduralBlinkFaceMovement=true - true if avatars blink automatically by animating - * facial blend shapes, false if automatic blinking is disabled. Set this property to false if - * you wish to fully control the blink facial blend shapes via the {@link MyAvatar.setBlendshape} method. + * facial blend shapes, false if automatic blinking is disabled. Set to false to fully control + * the blink facial blend shapes via the {@link MyAvatar.setBlendshape} method. * @property {boolean} hasProceduralEyeFaceMovement=true - true if the facial blend shapes for an avatar's eyes * adjust automatically as the eyes move, false if this automatic movement is disabled. Set this property - * to true to prevent the iris from being obscured by the upper or lower lids. Set this property to - * false if you wish to fully control the eye blend shapes via the {@link MyAvatar.setBlendshape} method. + * to true to prevent the iris from being obscured by the upper or lower lids. Set to false to + * fully control the eye blend shapes via the {@link MyAvatar.setBlendshape} method. * @property {boolean} hasAudioEnabledFaceMovement=true - true if the avatar's mouth blend shapes animate * automatically based on detected microphone input, false if this automatic movement is disabled. Set - * this property to false if you wish to fully control the mouth facial blend shapes via the + * this property to false to fully control the mouth facial blend shapes via the * {@link MyAvatar.setBlendshape} method. * * @example Create a scriptable avatar. diff --git a/cmake/macros/TargetDraco.cmake b/cmake/macros/TargetDraco.cmake index 520786d4c3..e23069d1d3 100755 --- a/cmake/macros/TargetDraco.cmake +++ b/cmake/macros/TargetDraco.cmake @@ -1,6 +1,5 @@ macro(TARGET_DRACO) set(LIBS draco dracodec dracoenc) - find_library(LIBPATH ${LIB} PATHS ) if (ANDROID) set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/draco) set(DRACO_INCLUDE_DIRS "${INSTALL_DIR}/include" CACHE STRING INTERNAL) @@ -12,6 +11,8 @@ macro(TARGET_DRACO) else() set(LIB_SEARCH_PATH_RELEASE ${VCPKG_INSTALL_ROOT}/lib/) set(LIB_SEARCH_PATH_DEBUG ${VCPKG_INSTALL_ROOT}/debug/lib/) + set(DRACO_LIBRARY_RELEASE "") + set(DRACO_LIBRARY_DEBUG "") foreach(LIB ${LIBS}) find_library(${LIB}_LIBPATH ${LIB} PATHS ${LIB_SEARCH_PATH_RELEASE} NO_DEFAULT_PATH) list(APPEND DRACO_LIBRARY_RELEASE ${${LIB}_LIBPATH}) diff --git a/cmake/macros/TargetOpenEXR.cmake b/cmake/macros/TargetOpenEXR.cmake index 8d61f216e7..9d63ba3ef4 100644 --- a/cmake/macros/TargetOpenEXR.cmake +++ b/cmake/macros/TargetOpenEXR.cmake @@ -28,6 +28,8 @@ macro(TARGET_OPENEXR) string(REGEX MATCHALL "[0-9]" OPENEXR_MINOR_VERSION ${TMP}) endif() + set(OPENEXR_LIBRARY_RELEASE "") + set(OPENEXR_LIBRARY_DEBUG "") foreach(OPENEXR_LIB IlmImf IlmImfUtil diff --git a/cmake/ports/glad/portfile.cmake b/cmake/ports/glad/portfile.cmake index 56ee59e0d4..54b1d91c89 100644 --- a/cmake/ports/glad/portfile.cmake +++ b/cmake/ports/glad/portfile.cmake @@ -1,17 +1,19 @@ include(vcpkg_common_functions) vcpkg_check_linkage(ONLY_STATIC_LIBRARY) +file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS) + if (ANDROID) vcpkg_download_distfile( SOURCE_ARCHIVE - URLS https://athena-public.s3.amazonaws.com/dependencies/glad/glad32es.zip + URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/glad/glad32es.zip SHA512 2e02ac633eed8f2ba2adbf96ea85d08998f48dd2e9ec9a88ec3c25f48eaf1405371d258066327c783772fcb3793bdb82bd7375fdabb2ba5e2ce0835468b17f65 ) else() # else Linux desktop vcpkg_download_distfile( SOURCE_ARCHIVE - URLS https://athena-public.s3.amazonaws.com/dependencies/glad/glad45.zip + URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/glad/glad45.zip SHA512 653a7b873f9fbc52e0ab95006cc3143bc7b6f62c6e032bc994e87669273468f37978525c9af5efe36f924cb4acd221eb664ad9af0ce4bf711b4f1be724c0065e FILENAME glad45.zip ) @@ -33,4 +35,3 @@ vcpkg_install_cmake() file(COPY ${CMAKE_CURRENT_LIST_DIR}/copyright DESTINATION ${CURRENT_PACKAGES_DIR}/share/glad) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) - diff --git a/cmake/ports/glm/disable_warnings_as_error.patch b/cmake/ports/glm/disable_warnings_as_error.patch index f87616b1ec..5dabaa6323 100644 --- a/cmake/ports/glm/disable_warnings_as_error.patch +++ b/cmake/ports/glm/disable_warnings_as_error.patch @@ -1,7 +1,16 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 756673a3..5fbc8906 100644 +index 756673a..9b3aa07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt +@@ -194,7 +194,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + message("GLM: Clang - ${CMAKE_CXX_COMPILER_ID} compiler") + endif() + +- add_compile_options(-Werror -Weverything) ++ add_compile_options(-Weverything) + add_compile_options(-Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-c++11-long-long -Wno-padded -Wno-gnu-anonymous-struct -Wno-nested-anon-types) + add_compile_options(-Wno-undefined-reinterpret-cast -Wno-sign-conversion -Wno-unused-variable -Wno-missing-prototypes -Wno-unreachable-code -Wno-missing-variable-declarations -Wno-sign-compare -Wno-global-constructors -Wno-unused-macros -Wno-format-nonliteral) + @@ -216,7 +216,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") message("GLM: Visual C++ - ${CMAKE_CXX_COMPILER_ID} compiler") endif() diff --git a/cmake/ports/hifi-deps/CONTROL b/cmake/ports/hifi-deps/CONTROL index d4b4acd4c5..ff689c7a2a 100644 --- a/cmake/ports/hifi-deps/CONTROL +++ b/cmake/ports/hifi-deps/CONTROL @@ -1,4 +1,4 @@ Source: hifi-deps -Version: 0.1.4-github-actions +Version: 0.1.5-github-actions Description: Collected dependencies for High Fidelity applications Build-Depends: bullet3, draco, etc2comp, glad, glm, nvtt, openexr (!android), openssl (windows), opus, polyvox, tbb (!android), vhacd, webrtc (!android), zlib diff --git a/cmake/ports/polyvox/portfile.cmake b/cmake/ports/polyvox/portfile.cmake index 54cc74d4dd..9204b26dbd 100644 --- a/cmake/ports/polyvox/portfile.cmake +++ b/cmake/ports/polyvox/portfile.cmake @@ -1,9 +1,11 @@ include(vcpkg_common_functions) +file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS) + # else Linux desktop vcpkg_download_distfile( SOURCE_ARCHIVE - URLS https://athena-public.s3.amazonaws.com/dependencies/polyvox-master-2015-7-15.zip + URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/polyvox-master-2015-7-15.zip SHA512 cc04cd43ae74b9c7bb065953540c0048053fcba6b52dc4218b3d9431fba178d65ad4f6c53cc1122ba61d0ab4061e99a7ebbb15db80011d607c5070ebebf8eddc FILENAME polyvox.zip ) @@ -23,33 +25,45 @@ vcpkg_install_cmake() file(INSTALL ${SOURCE_PATH}/LICENSE.TXT DESTINATION ${CURRENT_PACKAGES_DIR}/share/polyvox RENAME copyright) file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/include) -file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/lib) -file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/debug/lib) +if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") + file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/lib) +endif() +if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/debug/lib) +endif() if(WIN32) - file(RENAME ${CURRENT_PACKAGES_DIR}/PolyVoxCore/lib/Release/PolyVoxCore.lib ${CURRENT_PACKAGES_DIR}/lib/PolyVoxCore.lib) - file(RENAME ${CURRENT_PACKAGES_DIR}/debug/PolyVoxCore/lib/Debug/PolyVoxCore.lib ${CURRENT_PACKAGES_DIR}/debug/lib/PolyVoxCore.lib) - file(RENAME ${CURRENT_PACKAGES_DIR}/PolyVoxUtil/lib/PolyVoxUtil.lib ${CURRENT_PACKAGES_DIR}/lib/PolyVoxUtil.lib) - file(RENAME ${CURRENT_PACKAGES_DIR}/debug/PolyVoxUtil/lib/PolyVoxUtil.lib ${CURRENT_PACKAGES_DIR}/debug/lib/PolyVoxUtil.lib) + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") + file(RENAME ${CURRENT_PACKAGES_DIR}/PolyVoxCore/lib/Release/PolyVoxCore.lib ${CURRENT_PACKAGES_DIR}/lib/PolyVoxCore.lib) + file(RENAME ${CURRENT_PACKAGES_DIR}/PolyVoxUtil/lib/PolyVoxUtil.lib ${CURRENT_PACKAGES_DIR}/lib/PolyVoxUtil.lib) + endif() + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + file(RENAME ${CURRENT_PACKAGES_DIR}/debug/PolyVoxCore/lib/Debug/PolyVoxCore.lib ${CURRENT_PACKAGES_DIR}/debug/lib/PolyVoxCore.lib) + file(RENAME ${CURRENT_PACKAGES_DIR}/debug/PolyVoxUtil/lib/PolyVoxUtil.lib ${CURRENT_PACKAGES_DIR}/debug/lib/PolyVoxUtil.lib) + endif() file(RENAME ${CURRENT_PACKAGES_DIR}/PolyVoxCore/include/PolyVoxCore ${CURRENT_PACKAGES_DIR}/include/PolyVoxCore) file(RENAME ${CURRENT_PACKAGES_DIR}/PolyVoxUtil/include/PolyVoxUtil ${CURRENT_PACKAGES_DIR}/include/PolyVoxUtil) file(RENAME ${CURRENT_PACKAGES_DIR}/cmake/PolyVoxConfig.cmake ${CURRENT_PACKAGES_DIR}/share/polyvox/polyvoxConfig.cmake) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/cmake) - file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/cmake) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/PolyVoxCore) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/PolyVoxUtil) - file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/PolyVoxUtil) + file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/cmake) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/PolyVoxCore) + file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/PolyVoxUtil) else() - file(GLOB LIBS ${CURRENT_PACKAGES_DIR}/lib/Release/*) - foreach(_lib ${LIBS}) - file(RELATIVE_PATH _libName ${CURRENT_PACKAGES_DIR}/lib/Release ${_lib}) - file(RENAME ${_lib} ${CURRENT_PACKAGES_DIR}/lib/${_libName}) - endforeach() - file(GLOB LIBS ${CURRENT_PACKAGES_DIR}/debug/lib/Debug/*) - foreach(_lib ${LIBS}) - file(RELATIVE_PATH _libName ${CURRENT_PACKAGES_DIR}/debug/lib/Debug ${_lib}) - file(RENAME ${_lib} ${CURRENT_PACKAGES_DIR}/debug/lib/${_libName}) - endforeach() + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") + file(GLOB LIBS ${CURRENT_PACKAGES_DIR}/lib/Release/*) + foreach(_lib ${LIBS}) + file(RELATIVE_PATH _libName ${CURRENT_PACKAGES_DIR}/lib/Release ${_lib}) + file(RENAME ${_lib} ${CURRENT_PACKAGES_DIR}/lib/${_libName}) + endforeach() + endif() + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + file(GLOB LIBS ${CURRENT_PACKAGES_DIR}/debug/lib/Debug/*) + foreach(_lib ${LIBS}) + file(RELATIVE_PATH _libName ${CURRENT_PACKAGES_DIR}/debug/lib/Debug ${_lib}) + file(RENAME ${_lib} ${CURRENT_PACKAGES_DIR}/debug/lib/${_libName}) + endforeach() + endif() file(RENAME ${CURRENT_PACKAGES_DIR}/include/PolyVoxCore ${CURRENT_PACKAGES_DIR}/include/PolyVoxCore.temp) file(RENAME ${CURRENT_PACKAGES_DIR}/include/PolyVoxCore.temp/PolyVoxCore ${CURRENT_PACKAGES_DIR}/include/PolyVoxCore) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/include/PolyVoxCore.temp) diff --git a/cmake/ports/quazip/portfile.cmake b/cmake/ports/quazip/portfile.cmake index 07a8ebc3c3..0789062892 100644 --- a/cmake/ports/quazip/portfile.cmake +++ b/cmake/ports/quazip/portfile.cmake @@ -1,10 +1,11 @@ include(vcpkg_common_functions) file(READ "${VCPKG_ROOT_DIR}/_env/QT_CMAKE_PREFIX_PATH.txt" QT_CMAKE_PREFIX_PATH) +file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS) vcpkg_download_distfile( SOURCE_ARCHIVE - URLS https://athena-public.s3.amazonaws.com/dependencies/quazip-0.7.3.zip + URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/quazip-0.7.3.zip SHA512 b2d812b6346317fd6d8f4f1344ad48b721d697c429acc8b7e7cb776ce5cba15a59efd64b2c5ae1f31b5a3c928014f084aa1379fd55d8a452a6cf4fd510b3afcc FILENAME quazip.zip ) @@ -24,10 +25,14 @@ vcpkg_configure_cmake( vcpkg_install_cmake() if (WIN32) - file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/bin) - file(RENAME ${CURRENT_PACKAGES_DIR}/lib/quazip5.dll ${CURRENT_PACKAGES_DIR}/bin/quazip5.dll) - file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/debug/bin) - file(RENAME ${CURRENT_PACKAGES_DIR}/debug/lib/quazip5d.dll ${CURRENT_PACKAGES_DIR}/debug/bin/quazip5.dll) + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") + file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/bin) + file(RENAME ${CURRENT_PACKAGES_DIR}/lib/quazip5.dll ${CURRENT_PACKAGES_DIR}/bin/quazip5.dll) + endif() + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/debug/bin) + file(RENAME ${CURRENT_PACKAGES_DIR}/debug/lib/quazip5d.dll ${CURRENT_PACKAGES_DIR}/debug/bin/quazip5.dll) + endif() elseif(DEFINED VCPKG_TARGET_IS_LINUX) # We only want static libs. file(GLOB QUAZIP5_DYNAMIC_LIBS ${CURRENT_PACKAGES_DIR}/lib/libquazip5.so* ${CURRENT_PACKAGES_DIR}/debug/lib/libquazip5d.so*) diff --git a/cmake/ports/tbb/CONTROL b/cmake/ports/tbb/CONTROL index da29e48794..73569fe661 100644 --- a/cmake/ports/tbb/CONTROL +++ b/cmake/ports/tbb/CONTROL @@ -1,4 +1,4 @@ Source: tbb Version: 2019_U8-1 -Homepage: https://github.com/01org/tbb +Homepage: https://github.com/oneapi-src/oneTBB Description: Intel's Threading Building Blocks. diff --git a/cmake/ports/vhacd/portfile.cmake b/cmake/ports/vhacd/portfile.cmake index 02d90cab18..4c74bb6532 100644 --- a/cmake/ports/vhacd/portfile.cmake +++ b/cmake/ports/vhacd/portfile.cmake @@ -1,10 +1,12 @@ include(vcpkg_common_functions) vcpkg_check_linkage(ONLY_STATIC_LIBRARY) +file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS) + # else Linux desktop vcpkg_download_distfile( SOURCE_ARCHIVE - URLS https://athena-public.s3.amazonaws.com/dependencies/v-hacd-master.zip + URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/v-hacd-master.zip SHA512 5d9bd4872ead9eb3574e4806d6c4f490353a04036fd5f571e1e44f47cb66b709e311abcd53af30bae0015a690152170aeed93209a626c28ebcfd6591f3bb036f FILENAME vhacd.zip ) @@ -22,10 +24,17 @@ vcpkg_configure_cmake( vcpkg_install_cmake() file(COPY ${CMAKE_CURRENT_LIST_DIR}/copyright DESTINATION ${CURRENT_PACKAGES_DIR}/share/vhacd) -file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) +if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) +endif() + if (WIN32) - file(RENAME ${CURRENT_PACKAGES_DIR}/lib/Release/VHACD_LIB.lib ${CURRENT_PACKAGES_DIR}/lib/VHACD.lib) - file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/lib/Release) - file(RENAME ${CURRENT_PACKAGES_DIR}/debug/lib/Debug/VHACD_LIB.lib ${CURRENT_PACKAGES_DIR}/debug/lib/VHACD.lib) - file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/lib/Debug) -endif() \ No newline at end of file + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") + file(RENAME ${CURRENT_PACKAGES_DIR}/lib/Release/VHACD_LIB.lib ${CURRENT_PACKAGES_DIR}/lib/VHACD.lib) + file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/lib/Release) + endif() + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + file(RENAME ${CURRENT_PACKAGES_DIR}/debug/lib/Debug/VHACD_LIB.lib ${CURRENT_PACKAGES_DIR}/debug/lib/VHACD.lib) + file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/lib/Debug) + endif() +endif() diff --git a/cmake/ports/zlib/CONTROL b/cmake/ports/zlib/CONTROL index aa7c7b6e92..601fb1bc0e 100644 --- a/cmake/ports/zlib/CONTROL +++ b/cmake/ports/zlib/CONTROL @@ -1,4 +1,4 @@ Source: zlib -Version: 1.2.11-5 +Version: 1.2.11-6 Homepage: https://www.zlib.net/ Description: A compression library diff --git a/cmake/ports/zlib/cmake_dont_build_more_than_needed.patch b/cmake/ports/zlib/cmake_dont_build_more_than_needed.patch index 229a2d055b..a374f76d62 100644 --- a/cmake/ports/zlib/cmake_dont_build_more_than_needed.patch +++ b/cmake/ports/zlib/cmake_dont_build_more_than_needed.patch @@ -1,5 +1,5 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 0fe939d..8d2f5f1 100644 +index 0fe939d..a1291d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ set(VERSION "1.2.11") @@ -10,24 +10,56 @@ index 0fe939d..8d2f5f1 100644 set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") -@@ -211,7 +212,15 @@ elseif(BUILD_SHARED_LIBS AND WIN32) +@@ -124,9 +125,11 @@ set(ZLIB_SRCS + ) + + if(NOT MINGW) +- set(ZLIB_DLL_SRCS +- win32/zlib1.rc # If present will override custom build rule below. +- ) ++ if(BUILD_SHARED_LIBS) ++ set(ZLIB_DLL_SRCS ++ win32/zlib1.rc # If present will override custom build rule below. ++ ) ++ endif() + endif() + + if(CMAKE_COMPILER_IS_GNUCC) +@@ -180,11 +183,12 @@ if(MINGW) + -I ${CMAKE_CURRENT_BINARY_DIR} + -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) +- set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) ++ if(BUILD_SHARED_LIBS) ++ set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) ++ endif() + endif(MINGW) + +-add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +-add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) ++add_library(zlib ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) + set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) + set_target_properties(zlib PROPERTIES SOVERSION 1) + +@@ -201,7 +205,7 @@ endif() + + if(UNIX) + # On unix-like platforms the library is almost always called libz +- set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z) ++ set_target_properties(zlib PROPERTIES OUTPUT_NAME z) + if(NOT APPLE) + set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") + endif() +@@ -211,7 +215,7 @@ elseif(BUILD_SHARED_LIBS AND WIN32) endif() if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) - install(TARGETS zlib zlibstatic -+ if (BUILD_SHARED_LIBS) -+ set(ZLIB_TARGETS zlib) -+ set_target_properties(zlibstatic PROPERTIES EXCLUDE_FROM_ALL ON) -+ else() -+ set(ZLIB_TARGETS zlibstatic) -+ set_target_properties(zlib PROPERTIES EXCLUDE_FROM_ALL ON) -+ endif() -+ -+ install(TARGETS ${ZLIB_TARGETS} ++ install(TARGETS zlib RUNTIME DESTINATION "${INSTALL_BIN_DIR}" ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" LIBRARY DESTINATION "${INSTALL_LIB_DIR}" ) -@@ -230,6 +239,7 @@ endif() +@@ -230,6 +234,7 @@ endif() # Example binaries #============================================================================ @@ -35,7 +67,7 @@ index 0fe939d..8d2f5f1 100644 add_executable(example test/example.c) target_link_libraries(example zlib) add_test(example example) -@@ -247,3 +257,4 @@ if(HAVE_OFF64_T) +@@ -247,3 +252,4 @@ if(HAVE_OFF64_T) target_link_libraries(minigzip64 zlib) set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") endif() diff --git a/hifi_qt.py b/hifi_qt.py index 6cae3bf59d..10708e4bc9 100644 --- a/hifi_qt.py +++ b/hifi_qt.py @@ -29,7 +29,7 @@ endif() self.configFilePath = os.path.join(args.build_root, 'qt.cmake') self.version = os.getenv('VIRCADIA_USE_QT_VERSION', '5.12.3') - self.assets_url = self.readVar('EXTERNAL_BUILD_ASSETS') + self.assets_url = hifi_utils.readEnviromentVariableFromFile(args.build_root, 'EXTERNAL_BUILD_ASSETS') defaultBasePath = os.path.expanduser('~/hifi/qt') self.basePath = os.getenv('HIFI_QT_BASE', defaultBasePath) @@ -74,10 +74,10 @@ endif() self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.12.6-ubuntu-19.10.tar.xz' elif u_major > 18 and ( u_major != 19 and u_minor != 4): print("We don't support " + distro.name(pretty=True) + " yet. Perhaps consider helping us out?") - raise Exception('UNSUPPORTED LINUX VERSION!!!') + raise Exception('LINUX DISTRO IS NOT SUPPORTED YET!!!') else: print("Sorry, " + distro.name(pretty=True) + " is old and won't be officially supported. Please consider upgrading."); - raise Exception('UNSUPPORTED LINUX VERSION!!!') + raise Exception('UNKNOWN LINUX DISTRO VERSION!!!') else: print("Sorry, " + distro.name(pretty=True) + " is not supported. Please consider helping us out.") print("It's also possible to build Qt for your distribution, please see the documentation at:") @@ -89,10 +89,6 @@ endif() print("Machine : " + platform.machine()) raise Exception('UNKNOWN OPERATING SYSTEM!!!') - def readVar(self, var): - with open(os.path.join(self.args.build_root, '_env', var + ".txt")) as fp: - return fp.read() - def writeConfig(self): print("Writing cmake config to {}".format(self.configFilePath)) # Write out the configuration for use by CMake diff --git a/hifi_utils.py b/hifi_utils.py index 3a49f6d52b..157e5858a8 100644 --- a/hifi_utils.py +++ b/hifi_utils.py @@ -121,3 +121,7 @@ def downloadAndExtract(url, destPath, hash=None, hasher=hashlib.sha512(), isZip= with tarfile.open(tempFileName, 'r:*') as tgz: tgz.extractall(destPath) os.remove(tempFileName) + +def readEnviromentVariableFromFile(buildRootDir, var): + with open(os.path.join(buildRootDir, '_env', var + ".txt")) as fp: + return fp.read() diff --git a/hifi_vcpkg.py b/hifi_vcpkg.py index 9846d386c4..1b9976da6e 100644 --- a/hifi_vcpkg.py +++ b/hifi_vcpkg.py @@ -21,6 +21,7 @@ get_filename_component(CMAKE_TOOLCHAIN_FILE "{}" ABSOLUTE CACHE) get_filename_component(CMAKE_TOOLCHAIN_FILE_UNCACHED "{}" ABSOLUTE) set(VCPKG_INSTALL_ROOT "{}") set(VCPKG_TOOLS_DIR "{}") +set(VCPKG_TARGET_TRIPLET "{}") """ CMAKE_TEMPLATE_NON_ANDROID = """ @@ -34,7 +35,11 @@ endif() self.args = args # our custom ports, relative to the script location self.sourcePortsPath = args.ports_path - self.id = hifi_utils.hashFolder(self.sourcePortsPath)[:8] + self.vcpkgBuildType = args.vcpkg_build_type + if (self.vcpkgBuildType): + self.id = hifi_utils.hashFolder(self.sourcePortsPath)[:8] + "-" + self.vcpkgBuildType + else: + self.id = hifi_utils.hashFolder(self.sourcePortsPath)[:8] self.configFilePath = os.path.join(args.build_root, 'vcpkg.cmake') self.assets_url = self.readVar('EXTERNAL_BUILD_ASSETS') @@ -78,27 +83,31 @@ endif() self.bootstrapEnv = os.environ.copy() self.buildEnv = os.environ.copy() self.prebuiltArchive = None - usePrebuilt = ('CI_BUILD' in os.environ) and os.environ["CI_BUILD"] == "Github" and (not self.noClean) + usePrebuilt = False + # usePrebuild Disabled, to re-enabled using the prebuilt archives for GitHub action builds uncomment the following line: + # usePrebuilt = ('CI_BUILD' in os.environ) and os.environ["CI_BUILD"] == "Github" and (not self.noClean) if 'Windows' == system: self.exe = os.path.join(self.path, 'vcpkg.exe') - self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.bat') ] + self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.bat'), '-disableMetrics' ] self.vcpkgUrl = self.assets_url + '/dependencies/vcpkg/builds/vcpkg-win32-client.zip%3FversionId=tSFzbw01VkkVFeRQ6YuAY4dro2HxJR9U' self.vcpkgHash = 'a650db47a63ccdc9904b68ddd16af74772e7e78170b513ea8de5a3b47d032751a3b73dcc7526d88bcb500753ea3dd9880639ca842bb176e2bddb1710f9a58cd3' self.hostTriplet = 'x64-windows' if usePrebuilt: - self.prebuiltArchive = self.assets_url + "/dependencies/vcpkg/builds/vcpkg-win32.zip%3FversionId=3SF3mDC8dkQH1JP041m88xnYmWNzZflx" + self.prebuiltArchive = self.assets_url + "/dependencies/vcpkg/builds/vcpkg-win32.zip%3FversionId=3SF3mDC8dkQH1JP041m88xnYmWNzZflx" elif 'Darwin' == system: self.exe = os.path.join(self.path, 'vcpkg') - self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.sh'), '--allowAppleClang' ] + self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.sh'), '--allowAppleClang', '-disableMetrics' ] self.vcpkgUrl = self.assets_url + '/dependencies/vcpkg/builds/vcpkg-osx-client.tgz%3FversionId=j0b4azo_zTlH_Q9DElEWOz1UMYZ2nqQw' self.vcpkgHash = '519d666d02ef22b87c793f016ca412e70f92e1d55953c8f9bd4ee40f6d9f78c1df01a6ee293907718f3bbf24075cc35492fb216326dfc50712a95858e9cbcb4d' self.hostTriplet = 'x64-osx' + # Potential fix for a vcpkg build issue on OSX (see https://github.com/microsoft/vcpkg/issues/9029) + self.bootstrapEnv['CXXFLAGS'] = '-D_CTERMID_H_' if usePrebuilt: self.prebuiltArchive = self.assets_url + "/dependencies/vcpkg/builds/vcpkg-osx.tgz%3FversionId=6JrIMTdvpBF3MAsjA92BMkO79Psjzs6Z" else: self.exe = os.path.join(self.path, 'vcpkg') - self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.sh') ] + self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.sh'), '-disableMetrics' ] self.vcpkgUrl = self.assets_url + '/dependencies/vcpkg/builds/vcpkg-linux-client.tgz%3FversionId=y7mct0gFicEXz5hJy3KROBugcLR56YWf' self.vcpkgHash = '6a1ce47ef6621e699a4627e8821ad32528c82fce62a6939d35b205da2d299aaa405b5f392df4a9e5343dd6a296516e341105fbb2dd8b48864781d129d7fba10d' self.hostTriplet = 'x64-linux' @@ -206,6 +215,19 @@ endif() print(actualCommands) hifi_utils.executeSubprocess(actualCommands, folder=self.path, env=self.buildEnv) + def copyTripletForBuildType(self, triplet): + print('Copying triplet ' + triplet + ' to have build type ' + self.vcpkgBuildType) + tripletPath = os.path.join(self.path, 'triplets', triplet + '.cmake') + tripletForBuildTypePath = os.path.join(self.path, 'triplets', self.getTripletWithBuildType(triplet) + '.cmake') + shutil.copy(tripletPath, tripletForBuildTypePath) + with open(tripletForBuildTypePath, "a") as tripletForBuildTypeFile: + tripletForBuildTypeFile.write("set(VCPKG_BUILD_TYPE " + self.vcpkgBuildType + ")\n") + + def getTripletWithBuildType(self, triplet): + if (not self.vcpkgBuildType): + return triplet + return triplet + '-' + self.vcpkgBuildType + def setupDependencies(self, qt=None): if self.prebuiltArchive: if not os.path.isfile(self.prebuildTagFile): @@ -224,12 +246,16 @@ endif() self.setupAndroidDependencies() print("Installing host tools") - self.run(['install', '--triplet', self.hostTriplet, 'hifi-host-tools']) + if (self.vcpkgBuildType): + self.copyTripletForBuildType(self.hostTriplet) + self.run(['install', '--triplet', self.getTripletWithBuildType(self.hostTriplet), 'hifi-host-tools']) # If not android, install the hifi-client-deps libraries if not self.args.android: print("Installing build dependencies") - self.run(['install', '--triplet', self.triplet, 'hifi-client-deps']) + if (self.vcpkgBuildType): + self.copyTripletForBuildType(self.triplet) + self.run(['install', '--triplet', self.getTripletWithBuildType(self.triplet), 'hifi-client-deps']) def cleanBuilds(self): if self.noClean: @@ -240,6 +266,12 @@ endif() print("Wiping build trees") shutil.rmtree(builddir, ignore_errors=True) + # Removes large files used to build the vcpkg, for CI purposes. + def cleanupDevelopmentFiles(self): + shutil.rmtree(os.path.join(self.path, "downloads"), ignore_errors=True) + shutil.rmtree(os.path.join(self.path, "packages"), ignore_errors=True) + + def setupAndroidDependencies(self): # vcpkg prebuilt if not os.path.isdir(os.path.join(self.path, 'installed', 'arm64-android')): @@ -276,12 +308,32 @@ endif() with open(self.prebuildTagFile, 'w') as f: f.write(self.tagContents) + def fixupCmakeScript(self): + cmakeScript = os.path.join(self.path, 'scripts/buildsystems/vcpkg.cmake') + newCmakeScript = cmakeScript + '.new' + isFileChanged = False + removalPrefix = "set(VCPKG_TARGET_TRIPLET " + # Open original file in read only mode and dummy file in write mode + with open(cmakeScript, 'r') as read_obj, open(newCmakeScript, 'w') as write_obj: + # Line by line copy data from original file to dummy file + for line in read_obj: + if not line.startswith(removalPrefix): + write_obj.write(line) + else: + isFileChanged = True + + if isFileChanged: + shutil.move(newCmakeScript, cmakeScript) + else: + os.remove(newCmakeScript) + + def writeConfig(self): print("Writing cmake config to {}".format(self.configFilePath)) # Write out the configuration for use by CMake cmakeScript = os.path.join(self.path, 'scripts/buildsystems/vcpkg.cmake') - installPath = os.path.join(self.path, 'installed', self.triplet) - toolsPath = os.path.join(self.path, 'installed', self.hostTriplet, 'tools') + installPath = os.path.join(self.path, 'installed', self.getTripletWithBuildType(self.triplet)) + toolsPath = os.path.join(self.path, 'installed', self.getTripletWithBuildType(self.hostTriplet), 'tools') cmakeTemplate = VcpkgRepo.CMAKE_TEMPLATE if self.args.android: @@ -289,7 +341,7 @@ endif() cmakeTemplate += 'set(HIFI_ANDROID_PRECOMPILED "{}")\n'.format(precompiled) else: cmakeTemplate += VcpkgRepo.CMAKE_TEMPLATE_NON_ANDROID - cmakeConfig = cmakeTemplate.format(cmakeScript, cmakeScript, installPath, toolsPath).replace('\\', '/') + cmakeConfig = cmakeTemplate.format(cmakeScript, cmakeScript, installPath, toolsPath, self.getTripletWithBuildType(self.hostTriplet)).replace('\\', '/') with open(self.configFilePath, 'w') as f: f.write(cmakeConfig) diff --git a/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml b/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml index 74d1b53cd9..ac09f14d9e 100644 --- a/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml +++ b/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml @@ -7,7 +7,7 @@ MessageBox { popup.onButton2Clicked = callback; popup.titleText = 'Specify Avatar URL' popup.bodyText = 'This will not overwrite your existing favorite if you are wearing one.
' + - '' + + '' + 'Learn to make a custom avatar by opening this link on your desktop.' + '' popup.inputText.visible = true; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 341a403f40..2a83ab69c1 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -154,12 +154,12 @@ class MyAvatar : public Avatar { *

Note: This property will automatically be set to true if the controller system has * valid facial blend shape actions.

* @property {boolean} hasProceduralBlinkFaceMovement=true - true if avatars blink automatically by animating - * facial blend shapes, false if automatic blinking is disabled. Set this property to false - * to fully control the blink facial blend shapes via the {@link MyAvatar.setBlendshape} method. + * facial blend shapes, false if automatic blinking is disabled. Set to false to fully control + * the blink facial blend shapes via the {@link MyAvatar.setBlendshape} method. * @property {boolean} hasProceduralEyeFaceMovement=true - true if the facial blend shapes for an avatar's eyes * adjust automatically as the eyes move, false if this automatic movement is disabled. Set this property - * to true to prevent the iris from being obscured by the upper or lower lids. Set this property to - * false to fully control the eye blend shapes via the {@link MyAvatar.setBlendshape} method. + * to true to prevent the iris from being obscured by the upper or lower lids. Set to false to + * fully control the eye blend shapes via the {@link MyAvatar.setBlendshape} method. * @property {boolean} hasAudioEnabledFaceMovement=true - true if the avatar's mouth blend shapes animate * automatically based on detected microphone input, false if this automatic movement is disabled. Set * this property to false to fully control the mouth facial blend shapes via the @@ -654,7 +654,7 @@ public: *

Note: When using pre-built animation data, it's critical that the joint orientation of the source animation and target * rig are equivalent, since the animation data applies absolute values onto the joints. If the orientations are different, * the avatar will move in unpredictable ways. For more information about avatar joint orientation standards, see - * Avatar Standards.

+ * Avatar Standards.

* @function MyAvatar.overrideAnimation * @param {string} url - The URL to the animation file. Animation files may be in glTF or FBX format, but only need to * contain the avatar skeleton and animation data. glTF models may be in JSON or binary format (".gltf" or ".glb" URLs @@ -665,7 +665,7 @@ public: * @param {number} firstFrame - The frame to start the animation at. * @param {number} lastFrame - The frame to end the animation at. * @example Play a clapping animation on your avatar for three seconds. - * var ANIM_URL = "https://s3.amazonaws.com/hifi-public/animations/ClapAnimations/ClapHands_Standing.fbx"; + * var ANIM_URL = "https://apidocs.vircadia.dev/models/ClapHands_Standing.fbx"; * MyAvatar.overrideAnimation(ANIM_URL, 30, true, 0, 53); * Script.setTimeout(function () { * MyAvatar.restoreAnimation(); @@ -688,7 +688,7 @@ public: * @param {number} firstFrame - The frame to start the animation at. * @param {number} lastFrame - The frame to end the animation at. * @example Override left hand animation for three seconds. - * var ANIM_URL = "https://s3.amazonaws.com/hifi-public/animations/ClapAnimations/ClapHands_Standing.fbx"; + * var ANIM_URL = "https://apidocs.vircadia.dev/models/ClapHands_Standing.fbx"; * MyAvatar.overrideHandAnimation(isLeft, ANIM_URL, 30, true, 0, 53); * Script.setTimeout(function () { * MyAvatar.restoreHandAnimation(); @@ -705,7 +705,7 @@ public: * animation, this function has no effect.

* @function MyAvatar.restoreAnimation * @example Play a clapping animation on your avatar for three seconds. - * var ANIM_URL = "https://s3.amazonaws.com/hifi-public/animations/ClapAnimations/ClapHands_Standing.fbx"; + * var ANIM_URL = "https://apidocs.vircadia.dev/models/ClapHands_Standing.fbx"; * MyAvatar.overrideAnimation(ANIM_URL, 30, true, 0, 53); * Script.setTimeout(function () { * MyAvatar.restoreAnimation(); @@ -722,7 +722,7 @@ public: * @function MyAvatar.restoreHandAnimation * @param isLeft {boolean} Set to true if using the left hand * @example Override left hand animation for three seconds. - * var ANIM_URL = "https://s3.amazonaws.com/hifi-public/animations/ClapAnimations/ClapHands_Standing.fbx"; + * var ANIM_URL = "https://apidocs.projectathena.dev/models/ClapHands_Standing.fbx"; * MyAvatar.overrideHandAnimation(isLeft, ANIM_URL, 30, true, 0, 53); * Script.setTimeout(function () { * MyAvatar.restoreHandAnimation(); @@ -780,7 +780,7 @@ public: * hanging at its sides when it is not moving, the avatar will stand and clap its hands. Note that just as it did before, as soon as the avatar * starts to move, the animation will smoothly blend into the walk animation used by the "walkFwd" animation role. * // An animation of the avatar clapping its hands while standing. Restore default after 30s. - * var ANIM_URL = "https://s3.amazonaws.com/hifi-public/animations/ClapAnimations/ClapHands_Standing.fbx"; + * var ANIM_URL = "https://apidocs.projectathena.dev/models/ClapHands_Standing.fbx"; * MyAvatar.overrideRoleAnimation("idleStand", ANIM_URL, 30, true, 0, 53); * Script.setTimeout(function () { * MyAvatar.restoreRoleAnimation(); @@ -1793,15 +1793,15 @@ public: /**jsdoc * Turns the avatar's head until it faces the target point within a +90/-90 degree range. - * Once this method is called, API calls will have full control of the head for a limited time. - * If this method is not called for 2 seconds, the engine will regain control of the head. + * Once this method is called, API calls have full control of the head for a limited time. + * If this method is not called for 2 seconds, the engine regains control of the head. * @function MyAvatar.setHeadLookAt * @param {Vec3} lookAtTarget - The target point in world coordinates. */ Q_INVOKABLE void setHeadLookAt(const glm::vec3& lookAtTarget); /**jsdoc - * Returns the current target point of the head's look direction in world coordinates. + * Gets the current target point of the head's look direction in world coordinates. * @function MyAvatar.getHeadLookAt * @returns {Vec3} The head's look-at target in world coordinates. */ @@ -1815,7 +1815,7 @@ public: /**jsdoc * Forces the avatar's eyes to look at a specified location. Once this method is called, API calls - * have full control of the eyes for a limited time. If this method is not called for two seconds, + * full control of the eyes for a limited time. If this method is not called for 2 seconds, * the engine regains control of the eyes. * @function MyAvatar.setEyesLookAt * @param {Vec3} lookAtTarget - The target point in world coordinates. @@ -1823,7 +1823,7 @@ public: Q_INVOKABLE void setEyesLookAt(const glm::vec3& lookAtTarget); /**jsdoc - * Returns the current target point of the eyes look direction in world coordinates. + * Gets the current target point of the eyes look direction in world coordinates. * @function MyAvatar.getEyesLookAt * @returns {Vec3} The eyes' look-at target in world coordinates. */ @@ -2051,7 +2051,8 @@ public slots: float getGravity(); /**jsdoc - * Moves the avatar to a new position and/or orientation in the domain, while taking into account Avatar leg-length. + * Moves the avatar to a new position and/or orientation in the domain, with safe landing, while taking into account avatar + * leg length. * @function MyAvatar.goToFeetLocation * @param {Vec3} position - The new position for the avatar, in world coordinates. * @param {boolean} [hasOrientation=false] - Set to true to set the orientation of the avatar. @@ -2076,14 +2077,14 @@ public slots: bool hasOrientation = false, const glm::quat& newOrientation = glm::quat(), bool shouldFaceLocation = false, bool withSafeLanding = true); /**jsdoc - * Moves the avatar to a new position and (optional) orientation in the domain. + * Moves the avatar to a new position and (optional) orientation in the domain, with safe landing. * @function MyAvatar.goToLocation * @param {MyAvatar.GoToProperties} target - The goto target. */ void goToLocation(const QVariant& properties); /**jsdoc - * Moves the avatar to a new position and then enables collisions. + * Moves the avatar to a new position, with safe landing, and enables collisions. * @function MyAvatar.goToLocationAndEnableCollisions * @param {Vec3} position - The new position for the avatar, in world coordinates. */ diff --git a/interface/src/graphics/WorldBox.h b/interface/src/graphics/WorldBox.h index 114777ba0f..4d53652c0e 100644 --- a/interface/src/graphics/WorldBox.h +++ b/interface/src/graphics/WorldBox.h @@ -19,8 +19,6 @@ #include #include "Menu.h" - - class WorldBoxRenderData { public: typedef render::Payload Payload; @@ -29,8 +27,6 @@ public: int _val = 0; static render::ItemID _item; // unique WorldBoxRenderData - - static void renderWorldBox(RenderArgs* args, gpu::Batch& batch); }; diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index bf39073db1..0c2fdd1614 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -325,7 +325,7 @@ public slots: * @param {number} [aspectRatio=0] - The width/height ratio of the snapshot required. If the value is 0, the * full resolution is used (window dimensions in desktop mode; HMD display dimensions in HMD mode), otherwise one of the * dimensions is adjusted in order to match the aspect ratio. - * @param {string} [filename=""] - If a filename is not provided, the image is saved as "hifi-snap-by-<user + * @param {string} [filename=""] - If a filename is not provided, the image is saved as "vircadia-snap-by-<user * name>-on-YYYY-MM-DD_HH-MM-SS". *

Still images are saved in JPEG or PNG format according to the extension provided — ".jpg", * ".jpeg", or ".png" — or if not provided then in JPEG format with an extension of @@ -364,7 +364,7 @@ public slots: * @function Window.takeSecondaryCameraSnapshot * @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken} * signal. - * @param {string} [filename=""] - If a filename is not provided, the image is saved as "hifi-snap-by-<user + * @param {string} [filename=""] - If a filename is not provided, the image is saved as "vircadia-snap-by-<user * name>-on-YYYY-MM-DD_HH-MM-SS". *

Images are saved in JPEG or PNG format according to the extension provided — ".jpg", * ".jpeg", or ".png" — or if not provided then in JPEG format with an extension of @@ -383,7 +383,7 @@ public slots: * otherwise it is saved as an equirectangular image. * @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken} * signal. - * @param {string} [filename=""] - If a filename is not provided, the image is saved as "hifi-snap-by-<user + * @param {string} [filename=""] - If a filename is not provided, the image is saved as "vircadia-snap-by-<user * name>-on-YYYY-MM-DD_HH-MM-SS". *

Images are saved in JPEG or PNG format according to the extension provided — ".jpg", * ".jpeg", or ".png" — or if not provided then in JPEG format with an extension of diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index 2acac2c529..0ac1f05737 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -145,7 +145,7 @@ void InteractiveWindow::emitMainWindowResizeEvent() { * @property {InteractiveWindow.Flags} [additionalFlags=0] - Customizes window behavior. * @property {InteractiveWindow.OverrideFlags} [overrideFlags=0] - Customizes window controls. - * @property {InteractiveWindow.RelativePositionAnchor} [relativePositionAnchor] - he anchor for the + * @property {InteractiveWindow.RelativePositionAnchor} [relativePositionAnchor] - The anchor for the * relativePosition, if used. * @property {Vec2} [relativePosition] - The position of the window, relative to the relativePositionAnchor, in * pixels. Excludes the window frame. diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index bb9971e582..4882d6e5da 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -42,9 +42,9 @@ #include "Snapshot.h" #include "SnapshotUploader.h" -// filename format: hifi-snap-by-%username%-on-%date%_%time%_@-%location%.jpg +// filename format: vircadia-snap-by-%username%-on-%date%_%time%_@-%location%.jpg // %1 <= username, %2 <= date and time, %3 <= current location -const QString FILENAME_PATH_FORMAT = "hifi-snap-by-%1-on-%2.jpg"; +const QString FILENAME_PATH_FORMAT = "vircadia-snap-by-%1-on-%2.jpg"; const QString DATETIME_FORMAT = "yyyy-MM-dd_hh-mm-ss"; const QString SNAPSHOTS_DIRECTORY = "Snapshots"; const QString URL = "highfidelity_url"; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index a9e16e9ff1..3792057052 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1925,7 +1925,7 @@ void Avatar::setParentJointIndex(quint16 parentJointIndex) { * @typedef {object} SkeletonJoint * @property {string} name - Joint name. * @property {number} index - Joint index. - * @property {number} parentIndex - Index of this joint's parent (-1 if no parent). + * @property {number} parentIndex - Index of this joint's parent (-1 if no parent). */ QList Avatar::getSkeleton() { SkeletonModelPointer skeletonModel = _skeletonModel; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 9730ddf96c..cd1fc7c7fc 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -442,7 +442,7 @@ public: void setOrientationViaScript(const glm::quat& orientation) override; /**jsdoc - * Gets the ID of the entity of avatar that the avatar is parented to. + * Gets the ID of the entity or avatar that the avatar is parented to. * @function MyAvatar.getParentID * @returns {Uuid} The ID of the entity or avatar that the avatar is parented to. {@link Uuid(0)|Uuid.NULL} if not parented. */ @@ -450,7 +450,7 @@ public: Q_INVOKABLE virtual const QUuid getParentID() const override { return SpatiallyNestable::getParentID(); } /**jsdoc - * Sets the ID of the entity of avatar that the avatar is parented to. + * Sets the ID of the entity or avatar that the avatar is parented to. * @function MyAvatar.setParentID * @param {Uuid} parentID - The ID of the entity or avatar that the avatar should be parented to. Set to * {@link Uuid(0)|Uuid.NULL} to unparent. diff --git a/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h b/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h index 3f8fc4f88b..0b89e9d59e 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h @@ -19,7 +19,7 @@ /**jsdoc * Information about an avatar. * - *

Created using {@link MyAvatar.getTargetAvatar} or {@link AvatarList.getAvatar}.

+ *

Create using {@link MyAvatar.getTargetAvatar} or {@link AvatarList.getAvatar}.

* * @class ScriptAvatar * @hideconstructor @@ -87,7 +87,7 @@ public slots: /**jsdoc * Gets the default rotation of a joint in the avatar relative to its parent. *

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function ScriptAvatar.getDefaultJointRotation * @param {number} index - The joint index. * @returns {Quat} The default rotation of the joint if avatar data are available and the joint index is valid, otherwise @@ -99,7 +99,7 @@ public slots: * Gets the default translation of a joint in the avatar relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function ScriptAvatar.getDefaultJointTranslation * @param {number} index - The joint index. * @returns {Vec3} The default translation of the joint (in model coordinates) if avatar data are available and the joint @@ -152,7 +152,7 @@ public slots: /**jsdoc - * Gets the ID of the entity of avatar that the avatar is parented to. + * Gets the ID of the entity or avatar that the avatar is parented to. * @function ScriptAvatar.getParentID * @returns {Uuid} The ID of the entity or avatar that the avatar is parented to. {@link Uuid(0)|Uuid.NULL} if not parented * or avatar data aren't available. diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index f5e72b2dfe..d6a4497ee7 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -538,12 +538,12 @@ class AvatarData : public QObject, public SpatiallyNestable { *

Note: This property will automatically be set to true if the controller system has * valid facial blend shape actions.

* @property {boolean} hasProceduralBlinkFaceMovement=true - true if avatars blink automatically by animating - * facial blend shapes, false if automatic blinking is disabled. Set this property to false - * to fully control the blink facial blend shapes via the {@link Avatar.setBlendshape} method. + * facial blend shapes, false if automatic blinking is disabled. Set to false to fully control + * the blink facial blend shapes via the {@link Avatar.setBlendshape} method. * @property {boolean} hasProceduralEyeFaceMovement=true - true if the facial blend shapes for an avatar's eyes * adjust automatically as the eyes move, false if this automatic movement is disabled. Set this property - * to true to prevent the iris from being obscured by the upper or lower lids. Set this property to - * false to fully control the eye blend shapes via the {@link Avatar.setBlendshape} method. + * to true to prevent the iris from being obscured by the upper or lower lids. Set to false to + * fully control the eye blend shapes via the {@link Avatar.setBlendshape} method. * @property {boolean} hasAudioEnabledFaceMovement=true - true if the avatar's mouth blend shapes animate * automatically based on detected microphone input, false if this automatic movement is disabled. Set * this property to false to fully control the mouth facial blend shapes via the @@ -1274,7 +1274,7 @@ public: * null to remove all attachments. * @deprecated This function is deprecated and will be removed. Use avatar entities instead. * @example Remove a hat attachment if your avatar is wearing it. - * var hatURL = "https://s3.amazonaws.com/hifi-public/tony/cowboy-hat.fbx"; + * var hatURL = "https://apidocs.vircadia.dev/models/cowboy-hat.fbx"; * var attachments = MyAvatar.getAttachmentData(); * * for (var i = 0; i < attachments.length; i++) { @@ -1311,7 +1311,7 @@ public: * @deprecated This function is deprecated and will be removed. Use avatar entities instead. * @example Attach a cowboy hat to your avatar's head. * var attachment = { - * modelURL: "https://s3.amazonaws.com/hifi-public/tony/cowboy-hat.fbx", + * modelURL: "https://apidocs.vircadia.dev/models/cowboy-hat.fbx", * jointName: "Head", * translation: {"x": 0, "y": 0.25, "z": 0}, * rotation: {"x": 0, "y": 0, "z": 0, "w": 1}, @@ -1542,7 +1542,7 @@ signals: void sessionDisplayNameChanged(); /**jsdoc - * Triggered when the avatar's model (i.e., skeletonModelURL property value) is changed. + * Triggered when the avatar's model (i.e., skeletonModelURL property value) changes. * @function Avatar.skeletonModelURLChanged * @returns {Signal} * @example Report when your avatar's skeleton model changes. diff --git a/libraries/avatars/src/ScriptAvatarData.h b/libraries/avatars/src/ScriptAvatarData.h index 7dcd7cc7e1..290e8c178a 100644 --- a/libraries/avatars/src/ScriptAvatarData.h +++ b/libraries/avatars/src/ScriptAvatarData.h @@ -117,7 +117,7 @@ public: /**jsdoc * Gets the rotation of a joint relative to its parent. For information on the joint hierarchy used, see - * Avatar Standards. + * Avatar Standards. * @function ScriptAvatar.getJointRotation * @param {number} index - The index of the joint. * @returns {Quat} The rotation of the joint relative to its parent, or {@link Quat(0)|Quat.IDENTITY} if the avatar data @@ -129,7 +129,7 @@ public: * Gets the translation of a joint relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function ScriptAvatar.getJointTranslation * @param {number} index - The index of the joint. * @returns {Vec3} The translation of the joint relative to its parent, in model coordinates, or {@link Vec3(0)|Vec3.ZERO} @@ -139,7 +139,7 @@ public: /**jsdoc * Gets the rotation of a joint relative to its parent. For information on the joint hierarchy used, see - * Avatar Standards. + * Avatar Standards. * @function ScriptAvatar.getJointRotation * @param {string} name - The name of the joint. * @returns {Quat} The rotation of the joint relative to its parent, or {@link Quat(0)|Quat.IDENTITY} if the avatar data @@ -151,7 +151,7 @@ public: * Gets the translation of a joint relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function ScriptAvatar.getJointTranslation * @param {number} name - The name of the joint. * @returns {Vec3} The translation of the joint relative to its parent, in model coordinates, or {@link Vec3(0)|Vec3.ZERO} @@ -248,7 +248,7 @@ signals: void sessionDisplayNameChanged(); /**jsdoc - * Triggered when the avatar's model (i.e., skeletonModelURL property value) is changed. + * Triggered when the avatar's model (i.e., skeletonModelURL property value) changes. * @function ScriptAvatar.skeletonModelURLChanged * @returns {Signal} */ diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index f38a6c23bc..9ca958d128 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -129,7 +129,7 @@ std::shared_ptr make_renderer(const EntityItemPointer& entity) { return std::shared_ptr(new T(entity), [](T* ptr) { ptr->deleteLater(); }); } -EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _created(entity->getCreated()), _entity(entity) {} +EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _created(entity->getCreated()), _entity(entity), _entityID(entity->getID()) {} EntityRenderer::~EntityRenderer() {} @@ -197,6 +197,23 @@ uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const { return 0; } +bool EntityRenderer::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { + auto renderWithZones = resultWithReadLock>([&] { + return _renderWithZones; + }); + if (!renderWithZones.isEmpty()) { + if (!containingZones.empty()) { + for (auto renderWithZone : renderWithZones) { + if (containingZones.find(renderWithZone) != containingZones.end()) { + return true; + } + } + } + return false; + } + return true; +} + void EntityRenderer::render(RenderArgs* args) { if (!isValidRenderItem()) { return; @@ -386,6 +403,10 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity return true; } + if (entity->needsZoneOcclusionUpdate()) { + return true; + } + return false; } @@ -427,6 +448,10 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa _canCastShadow = entity->getCanCastShadow(); setCullWithParent(entity->getCullWithParent()); _cauterized = entity->getCauterized(); + if (entity->needsZoneOcclusionUpdate()) { + entity->resetNeedsZoneOcclusionUpdate(); + setRenderWithZones(entity->getRenderWithZones()); + } entity->setNeedsRenderUpdate(false); }); } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 227eb6a018..9c787d82c2 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -65,6 +65,7 @@ public: virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override; virtual Item::Bound getBound() override; + bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const override; protected: virtual bool needsRenderUpdateFromEntity() const final { return needsRenderUpdateFromEntity(_entity); } @@ -109,6 +110,7 @@ protected: virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; } virtual void setPrimitiveMode(PrimitiveMode value) { _primitiveMode = value; } virtual void setCullWithParent(bool value) { _cullWithParent = value; } + virtual void setRenderWithZones(const QVector& renderWithZones) { _renderWithZones = renderWithZones; } template T withReadLockResult(const std::function& f) { @@ -143,6 +145,7 @@ protected: bool _cullWithParent { false }; RenderLayer _renderLayer { RenderLayer::WORLD }; PrimitiveMode _primitiveMode { PrimitiveMode::SOLID }; + QVector _renderWithZones; bool _cauterized { false }; bool _moving { false }; // Only touched on the rendering thread @@ -153,6 +156,7 @@ protected: std::mutex _materialsLock; quint64 _created; + QUuid _entityID; // The base class relies on comparing the model transform to the entity transform in order // to trigger an update, so the member must not be visible to derived classes as a modifiable diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index ad2737143c..90b5546786 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1264,6 +1264,9 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce setKey(didVisualGeometryRequestSucceed); _model->setTagMask(getTagMask()); _model->setHifiRenderLayer(getHifiRenderLayer()); + _model->setPrimitiveMode(_primitiveMode); + _model->setCullWithParent(_cullWithParent); + _model->setRenderWithZones(_renderWithZones); emit requestRenderUpdate(); if(didVisualGeometryRequestSucceed) { emit DependencyManager::get()-> @@ -1447,6 +1450,13 @@ void ModelEntityRenderer::setCullWithParent(bool value) { } } +void ModelEntityRenderer::setRenderWithZones(const QVector& renderWithZones) { + Parent::setRenderWithZones(renderWithZones); + if (_model) { + _model->setRenderWithZones(renderWithZones); + } +} + // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items void ModelEntityRenderer::doRender(RenderArgs* args) { DETAILED_PROFILE_RANGE(render_detail, "MetaModelRender"); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index eb8aeefba9..104301a440 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -165,6 +165,7 @@ protected: void setRenderLayer(RenderLayer value) override; void setPrimitiveMode(PrimitiveMode value) override; void setCullWithParent(bool value) override; + void setRenderWithZones(const QVector& renderWithZones) override; private: void animate(const TypedEntityPointer& entity); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index fbd10e2f5b..2ba1acea11 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -289,6 +289,17 @@ ShapeKey entities::TextPayload::getShapeKey() const { return ShapeKey::Builder::invalid(); } +bool entities::TextPayload::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { + auto entityTreeRenderer = DependencyManager::get(); + if (entityTreeRenderer) { + auto renderable = entityTreeRenderer->renderableForEntityId(_entityID); + if (renderable) { + return std::static_pointer_cast(renderable)->passesZoneOcclusionTest(containingZones); + } + } + return false; +} + void entities::TextPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("TextPayload::render"); Q_ASSERT(args->_batch); @@ -388,4 +399,12 @@ template <> const ShapeKey shapeGetShapeKey(const TextPayload::Pointer& payload) template <> void payloadRender(const TextPayload::Pointer& payload, RenderArgs* args) { return payload->render(args); } + +template <> bool payloadPassesZoneOcclusionTest(const entities::TextPayload::Pointer& payload, const std::unordered_set& containingZones) { + if (payload) { + return payload->passesZoneOcclusionTest(containingZones); + } + return false; +} + } diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index 63cf3e6e9e..87102daa32 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -94,6 +94,7 @@ public: Item::Bound getBound() const; ShapeKey getShapeKey() const; void render(RenderArgs* args); + bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const; protected: QUuid _entityID; @@ -109,6 +110,7 @@ namespace render { template <> const Item::Bound payloadGetBound(const entities::TextPayload::Pointer& payload); template <> const ShapeKey shapeGetShapeKey(const entities::TextPayload::Pointer& payload); template <> void payloadRender(const entities::TextPayload::Pointer& payload, RenderArgs* args); + template <> bool payloadPassesZoneOcclusionTest(const entities::TextPayload::Pointer& payload, const std::unordered_set& containingZones); } #endif // hifi_RenderableTextEntityItem_h diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index bbb8c67ad1..948c6ca762 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -71,6 +71,11 @@ void ZoneEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity } void ZoneEntityRenderer::doRender(RenderArgs* args) { + // This is necessary so that zones can themselves be zone culled + if (!passesZoneOcclusionTest(CullTest::_prevContainingZones)) { + return; + } + if (!_stage) { _stage = args->_scene->getStage(); assert(_stage); @@ -180,6 +185,8 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) { _bloomStage->_currentFrame.pushBloom(_bloomIndex); } } + + CullTest::_containingZones.insert(_entityID); } void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf index 3d5cc190d0..eb46be1e20 100644 --- a/libraries/entities-renderer/src/paintStroke.slf +++ b/libraries/entities-renderer/src/paintStroke.slf @@ -19,6 +19,8 @@ <@include paintStroke.slh@> <$declarePolyLineBuffers()$> +<@include CullFace.slh@> + LAYOUT(binding=0) uniform sampler2D _texture; <@if not HIFI_USE_FORWARD@> @@ -35,9 +37,9 @@ void main(void) { <@if not HIFI_USE_FORWARD@> <@if HIFI_USE_TRANSLUCENT@> - packDeferredFragmentTranslucent((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS); + packDeferredFragmentTranslucent(evalFrontOrBackFaceNormal(_normalWS), texel.a, texel.rgb, DEFAULT_ROUGHNESS); <@else@> - packDeferredFragmentUnlit((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb); + packDeferredFragmentUnlit(evalFrontOrBackFaceNormal(_normalWS), texel.a, texel.rgb); <@endif@> <@else@> _fragColor0 = texel; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 5fc99882c0..3623e5f96a 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -106,6 +106,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_RENDER_LAYER; requestedProperties += PROP_PRIMITIVE_MODE; requestedProperties += PROP_IGNORE_PICK_INTERSECTION; + requestedProperties += PROP_RENDER_WITH_ZONES; requestedProperties += _grabProperties.getEntityProperties(params); // Physics @@ -301,6 +302,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_RENDER_LAYER, (uint32_t)getRenderLayer()); APPEND_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, (uint32_t)getPrimitiveMode()); APPEND_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, getIgnorePickIntersection()); + APPEND_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, getRenderWithZones()); withReadLock([&] { _grabProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -876,6 +878,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_RENDER_LAYER, RenderLayer, setRenderLayer); READ_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, PrimitiveMode, setPrimitiveMode); READ_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, bool, setIgnorePickIntersection); + READ_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, QVector, setRenderWithZones); withWriteLock([&] { int bytesFromGrab = _grabProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData, @@ -1355,6 +1358,7 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire COPY_ENTITY_PROPERTY_TO_PROPERTIES(renderLayer, getRenderLayer); COPY_ENTITY_PROPERTY_TO_PROPERTIES(primitiveMode, getPrimitiveMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(ignorePickIntersection, getIgnorePickIntersection); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(renderWithZones, getRenderWithZones); withReadLock([&] { _grabProperties.getProperties(properties); }); @@ -1504,6 +1508,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(renderLayer, setRenderLayer); SET_ENTITY_PROPERTY_FROM_PROPERTIES(primitiveMode, setPrimitiveMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignorePickIntersection, setIgnorePickIntersection); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(renderWithZones, setRenderWithZones); withWriteLock([&] { bool grabPropertiesChanged = _grabProperties.setProperties(properties); somethingChanged |= grabPropertiesChanged; @@ -3564,3 +3569,18 @@ void EntityItem::disableGrab(GrabPointer grab) { } } } + +void EntityItem::setRenderWithZones(const QVector& renderWithZones) { + withWriteLock([&] { + if (_renderWithZones != renderWithZones) { + _needsZoneOcclusionUpdate = true; + _renderWithZones = renderWithZones; + } + }); +} + +QVector EntityItem::getRenderWithZones() const { + return resultWithReadLock>([&] { + return _renderWithZones; + }); +} \ No newline at end of file diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 5f0f90ad68..2bb5dab16b 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -582,6 +582,11 @@ public: bool needsRenderUpdate() const { return resultWithReadLock([&] { return _needsRenderUpdate; }); } void setNeedsRenderUpdate(bool needsRenderUpdate) { withWriteLock([&] { _needsRenderUpdate = needsRenderUpdate; }); } + void setRenderWithZones(const QVector& renderWithZones); + QVector getRenderWithZones() const; + bool needsZoneOcclusionUpdate() const { return _needsZoneOcclusionUpdate; } + void resetNeedsZoneOcclusionUpdate() { withWriteLock([&] { _needsZoneOcclusionUpdate = false; }); } + signals: void spaceUpdate(std::pair data); @@ -770,6 +775,9 @@ protected: QHash _grabActions; + QVector _renderWithZones; + mutable bool _needsZoneOcclusionUpdate { false }; + bool _cullWithParent { false }; mutable bool _needsRenderUpdate { false }; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 09a8021a43..ebc8ae1c59 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -431,6 +431,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_RENDER_LAYER, renderLayer); CHECK_PROPERTY_CHANGE(PROP_PRIMITIVE_MODE, primitiveMode); CHECK_PROPERTY_CHANGE(PROP_IGNORE_PICK_INTERSECTION, ignorePickIntersection); + CHECK_PROPERTY_CHANGE(PROP_RENDER_WITH_ZONES, renderWithZones); changedProperties += _grab.getChangedProperties(); // Physics @@ -804,6 +805,10 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * avatar entities, false if they won't be. * @property {Uuid} cloneOriginID - The ID of the entity that this entity was cloned from. * + * @property {Uuid[]} renderWithZones=[]] - A list of entity IDs representing with which zones this entity should render. + * If it is empty, this entity will render normally. Otherwise, this entity will only render if your avatar is within + * one of the zones in this list. + * * @property {Entities.Grab} grab - The entity's grab-related properties. * * @property {string} itemName="" - Certifiable name of the Marketplace item. @@ -1036,8 +1041,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * type: "Model", * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.75, z: -2 })), * rotation: MyAvatar.orientation, - * modelURL: "http://content.highfidelity.com/seefo/production/puck-attach/vive_tracker_puck.obj", - * dimensions: { x: 0.0945, y: 0.0921, z: 0.0423 }, + * modelURL: "https://apidocs.vircadia.dev/models/cowboy-hat.fbx", + * dimensions: { x: 0.8569, y: 0.3960, z: 1.0744 }, * lifetime: 300 // Delete after 5 minutes. * }); */ @@ -1596,6 +1601,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_RENDER_LAYER, renderLayer, getRenderLayerAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_PRIMITIVE_MODE, primitiveMode, getPrimitiveModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IGNORE_PICK_INTERSECTION, ignorePickIntersection); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RENDER_WITH_ZONES, renderWithZones); _grab.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); // Physics @@ -2014,6 +2020,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(renderLayer, RenderLayer); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(primitiveMode, PrimitiveMode); COPY_PROPERTY_FROM_QSCRIPTVALUE(ignorePickIntersection, bool, setIgnorePickIntersection); + COPY_PROPERTY_FROM_QSCRIPTVALUE(renderWithZones, qVectorQUuid, setRenderWithZones); _grab.copyFromScriptValue(object, _defaultSettings); // Physics @@ -2308,6 +2315,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(renderLayer); COPY_PROPERTY_IF_CHANGED(primitiveMode); COPY_PROPERTY_IF_CHANGED(ignorePickIntersection); + COPY_PROPERTY_IF_CHANGED(renderWithZones); _grab.merge(other._grab); // Physics @@ -2601,6 +2609,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_PROPERTY_TO_MAP(PROP_RENDER_LAYER, RenderLayer, renderLayer, RenderLayer); ADD_PROPERTY_TO_MAP(PROP_PRIMITIVE_MODE, PrimitiveMode, primitiveMode, PrimitiveMode); ADD_PROPERTY_TO_MAP(PROP_IGNORE_PICK_INTERSECTION, IgnorePickIntersection, ignorePickIntersection, bool); + ADD_PROPERTY_TO_MAP(PROP_RENDER_WITH_ZONES, RenderWithZones, renderWithZones, QVector); { // Grab ADD_GROUP_PROPERTY_TO_MAP(PROP_GRAB_GRABBABLE, Grab, grab, Grabbable, grabbable); ADD_GROUP_PROPERTY_TO_MAP(PROP_GRAB_KINEMATIC, Grab, grab, GrabKinematic, grabKinematic); @@ -3090,6 +3099,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_RENDER_LAYER, (uint32_t)properties.getRenderLayer()); APPEND_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, (uint32_t)properties.getPrimitiveMode()); APPEND_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, properties.getIgnorePickIntersection()); + APPEND_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, properties.getRenderWithZones()); _staticGrab.setProperties(properties); _staticGrab.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -3580,6 +3590,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RENDER_LAYER, RenderLayer, setRenderLayer); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PRIMITIVE_MODE, PrimitiveMode, setPrimitiveMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IGNORE_PICK_INTERSECTION, bool, setIgnorePickIntersection); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RENDER_WITH_ZONES, QVector, setRenderWithZones); properties.getGrab().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); // Physics @@ -3998,6 +4009,7 @@ void EntityItemProperties::markAllChanged() { _renderLayerChanged = true; _primitiveModeChanged = true; _ignorePickIntersectionChanged = true; + _renderWithZonesChanged = true; _grab.markAllChanged(); // Physics @@ -4401,6 +4413,9 @@ QList EntityItemProperties::listChangedProperties() { if (ignorePickIntersectionChanged()) { out += "ignorePickIntersection"; } + if (renderWithZonesChanged()) { + out += "renderWithZones"; + } getGrab().listChangedProperties(out); // Physics diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 264fc3881b..baad0bcd6f 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -195,6 +195,7 @@ public: DEFINE_PROPERTY_REF_ENUM(PROP_RENDER_LAYER, RenderLayer, renderLayer, RenderLayer, RenderLayer::WORLD); DEFINE_PROPERTY_REF_ENUM(PROP_PRIMITIVE_MODE, PrimitiveMode, primitiveMode, PrimitiveMode, PrimitiveMode::SOLID); DEFINE_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, IgnorePickIntersection, ignorePickIntersection, bool, false); + DEFINE_PROPERTY_REF(PROP_RENDER_WITH_ZONES, RenderWithZones, renderWithZones, QVector, QVector()); DEFINE_PROPERTY_GROUP(Grab, grab, GrabPropertyGroup); // Physics diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 4c989ef74e..c25eb21e6c 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -119,6 +119,7 @@ inline QScriptValue qVectorVec3Color_convertScriptValue(QScriptEngine* e, const inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) {return qVectorQuatToScriptValue(e, v); } inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) {return qVectorBoolToScriptValue(e, v); } inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) { return qVectorFloatToScriptValue(e, v); } +inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) { return qVectorQUuidToScriptValue(e, v); } inline QScriptValue convertScriptValue(QScriptEngine* e, const QRect& v) { return qRectToScriptValue(e, v); } @@ -216,6 +217,7 @@ typedef QVector qVectorVec3; typedef QVector qVectorQuat; typedef QVector qVectorBool; typedef QVector qVectorFloat; +typedef QVector qVectorQUuid; inline float float_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toFloat(&isValid); } inline quint64 quint64_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toULongLong(&isValid); } inline quint32 quint32_convertFromScriptValue(const QScriptValue& v, bool& isValid) { @@ -293,6 +295,11 @@ inline qVectorBool qVectorBool_convertFromScriptValue(const QScriptValue& v, boo return qVectorBoolFromScriptValue(v); } +inline qVectorQUuid qVectorQUuid_convertFromScriptValue(const QScriptValue& v, bool& isValid) { + isValid = true; + return qVectorQUuidFromScriptValue(v); +} + inline glm::quat quat_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = false; /// assume it can't be converted QScriptValue x = v.property("x"); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 1ffd8fdc3c..37ea303166 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -43,6 +43,7 @@ enum EntityPropertyList { PROP_RENDER_LAYER, PROP_PRIMITIVE_MODE, PROP_IGNORE_PICK_INTERSECTION, + PROP_RENDER_WITH_ZONES, // Grab PROP_GRAB_GRABBABLE, PROP_GRAB_KINEMATIC, diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 11cd6309da..1c1b3a41f5 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -784,6 +784,7 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator) } } if (theEntity->isSimulated()) { + theEntity->die(); _simulation->prepareEntityForDelete(theEntity); } } diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp index 9d36cfd91a..a27eff9cbe 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp @@ -434,7 +434,7 @@ namespace scriptable { * @property {string} [glossMap] - The URL of the gloss texture image. * Only use one of roughnessMap and glossMap. * "hifi_pbr" model only. - * @property {string} [normalMa]p - The URL of the normal texture image. + * @property {string} [normalMap] - The URL of the normal texture image. * If "fallthrough" then it and bumpMap fall through to the material below. * Only use one of normalMap and bumpMap. * "hifi_pbr" model only. diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h index 9b56433bf6..0f24ae8461 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h @@ -87,8 +87,8 @@ public slots: * type: "Model", * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(Camera.orientation, { x: -0.5, y: 0, z: -3 })), * rotation: MyAvatar.orientation, - * modelURL: "http://content.highfidelity.com/seefo/production/puck-attach/vive_tracker_puck.obj", - * dimensions: { x: 0.945, y: 0.921, z: 0.423 }, + * modelURL: "https://apidocs.vircadia.dev/models/cowboy-hat.fbx", + * dimensions: { x: 0.8569, y: 0.3960, z: 1.0744 }, * lifetime: 300 // Delete after 5 minutes. * }); * var shapeEntityID = Entities.addEntity({ diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h index 8d70eda9e4..0e7eecc03b 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h @@ -31,7 +31,7 @@ namespace scriptable { /**jsdoc * A handle to in-memory mesh data in a {@link GraphicsModel}. * - *

Created using the {@link Graphics} API, {@link GraphicsModel.cloneModel}, or {@link GraphicsMesh.cloneMesh}.

+ *

Create using the {@link Graphics} API, {@link GraphicsModel.cloneModel}, or {@link GraphicsMesh.cloneMesh}.

* * @class GraphicsMesh * @hideconstructor @@ -133,7 +133,7 @@ namespace scriptable { QVector findNearbyVertexIndices(const glm::vec3& origin, float epsilon = 1e-6) const; /**jsdoc - * Adds an attribute to the (whole) mesh's vertices. + * Adds an attribute for all vertices. * @function GraphicsMesh.addAttribute * @param {Graphics.BufferTypeName} name - The name of the attribute. * @param {Graphics.BufferType} [defaultValue] - The value to give the attributes added to the vertices. diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h index 78ddb4f2b0..878b239f3d 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h @@ -13,7 +13,7 @@ namespace scriptable { /**jsdoc * A handle to in-memory mesh part data in a {@link GraphicsModel}. * - *

Created using the {@link Graphics} API, {@link GraphicsModel.cloneModel}, {@link GraphicsMesh.cloneMesh}, or + *

Create using the {@link Graphics} API, {@link GraphicsModel.cloneModel}, {@link GraphicsMesh.cloneMesh}, or * {@link GraphicsMeshPart.cloneMeshPart}.

* * @class GraphicsMeshPart diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h index 6dc2a06747..a6f135c321 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h @@ -22,7 +22,7 @@ namespace scriptable { *

Note: The model may be used for more than one instance of an item displayed in the scene. Modifying the model updates * all instances displayed.

* - *

Created using the {@link Graphics} API or {@link GraphicsModel.cloneModel}.

+ *

Create using the {@link Graphics} API or {@link GraphicsModel.cloneModel}.

* * @class GraphicsModel * @hideconstructor @@ -34,7 +34,7 @@ namespace scriptable { * @property {Uuid} objectID - The ID of the entity or avatar that the model is associated with, if any; null * if the model is not associated with an entity or avatar. * Read-only. - * @property {number} numMeshes - The number of meshes contained in the model. + * @property {number} numMeshes - The number of meshes in the model. * Read-only. * @property {GraphicsMesh[]} meshes - The meshes in the model. Each mesh may have more than one mesh part. * Read-only. diff --git a/libraries/graphics/src/graphics/BufferViewHelpers.cpp b/libraries/graphics/src/graphics/BufferViewHelpers.cpp index 076cb92dcf..88caa3cea4 100644 --- a/libraries/graphics/src/graphics/BufferViewHelpers.cpp +++ b/libraries/graphics/src/graphics/BufferViewHelpers.cpp @@ -76,7 +76,7 @@ const std::array ZERO123 = { { "0", "1", "2", "3" } }; * {@link Vec2}"texcoord4"Fifth UV coordinates buffer. * * - * @typedef {Vec3|vec2} Graphics.BufferType + * @typedef {Vec4|Vec3|Vec2} Graphics.BufferType */ QMap ATTRIBUTES{ {"position", gpu::Stream::POSITION }, @@ -120,50 +120,6 @@ template<> glm::uint32 forEach(const gpu::BufferView& view, std::func return forEachGlmVec(view, func); } -template -QVariant glmVecToVariant(const T& v, bool asArray /*= false*/) { - static const auto len = T().length(); - if (asArray) { - QVariantList list; - for (int i = 0; i < len ; i++) { - list << v[i]; - } - return list; - } else { - QVariantMap obj; - for (int i = 0; i < len ; i++) { - obj[XYZW[i]] = v[i]; - } - return obj; - } -} - -template -const T glmVecFromVariant(const QVariant& v) { - auto isMap = v.type() == (QVariant::Type)QMetaType::QVariantMap; - static const auto len = T().length(); - const auto& components = isMap ? XYZW : ZERO123; - T result; - QVariantMap map; - QVariantList list; - if (isMap) map = v.toMap(); else list = v.toList(); - for (int i = 0; i < len ; i++) { - float value; - if (isMap) { - value = map.value(components[i]).toFloat(); - } else { - value = list.value(i).toFloat(); - } -#ifdef DEBUG_BUFFERVIEW_HELPERS - if (value != value) { // NAN - qWarning().nospace()<< "vec" << len << "." << components[i] << " NAN received from script.... " << v.toString(); - } -#endif - result[i] = value; - } - return result; -} - // QVector => BufferView template gpu::BufferView newFromVector(const QVector& elements, const gpu::Element& elementType) { diff --git a/libraries/graphics/src/graphics/BufferViewHelpers.h b/libraries/graphics/src/graphics/BufferViewHelpers.h index 3635ef64e5..c42bb0426d 100644 --- a/libraries/graphics/src/graphics/BufferViewHelpers.h +++ b/libraries/graphics/src/graphics/BufferViewHelpers.h @@ -27,8 +27,54 @@ namespace buffer_helpers { extern const std::array XYZW; extern const std::array ZERO123; - template QVariant glmVecToVariant(const T& v, bool asArray = false); - template const T glmVecFromVariant(const QVariant& v); + template + QVariant glmVecToVariant(const T& v, bool asArray = false) { + static const auto len = T().length(); + if (asArray) { + QVariantList list; + for (int i = 0; i < len; i++) { + list << v[i]; + } + return list; + } else { + QVariantMap obj; + for (int i = 0; i < len; i++) { + obj[XYZW[i]] = v[i]; + } + return obj; + } + } + + template + const T glmVecFromVariant(const QVariant& v) { + auto isMap = v.type() == (QVariant::Type)QMetaType::QVariantMap; + static const auto len = T().length(); + const auto& components = isMap ? XYZW : ZERO123; + T result; + QVariantMap map; + QVariantList list; + if (isMap) { + map = v.toMap(); + } else { + list = v.toList(); + } + for (int i = 0; i < len; i++) { + float value; + if (isMap) { + value = map.value(components[i]).toFloat(); + } else { + value = list.value(i).toFloat(); + } +#ifdef DEBUG_BUFFERVIEW_HELPERS + if (value != value) { // NAN + qWarning().nospace() << "vec" << len << "." << components[i] << " NAN received from script.... " << v.toString(); + } +#endif + result[i] = value; + } + return result; + } + glm::uint32 forEachVariant(const gpu::BufferView& view, std::function func, const char* hint = ""); template glm::uint32 forEach(const gpu::BufferView& view, std::function func); @@ -36,7 +82,7 @@ namespace buffer_helpers { template gpu::BufferView newFromVector(const QVector& elements, const gpu::Element& elementType); template gpu::BufferView newFromVariantList(const QVariantList& list, const gpu::Element& elementType); - template QVector variantToVector(const QVariant& list); + template QVector variantToVector(const QVariant& value); template QVector bufferToVector(const gpu::BufferView& view, const char *hint = ""); // note: these do value conversions from the underlying buffer type into the template type diff --git a/libraries/graphics/src/graphics/Material.slh b/libraries/graphics/src/graphics/Material.slh index 328ff4a3af..274dbc1cdd 100644 --- a/libraries/graphics/src/graphics/Material.slh +++ b/libraries/graphics/src/graphics/Material.slh @@ -13,7 +13,6 @@ <@include graphics/ShaderConstants.h@> - const int MAX_TEXCOORDS = 2; struct TexMapArray { diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 805e5d3a09..bfcf806843 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -212,10 +212,11 @@ using PacketType = PacketTypeEnum::Value; const int NUM_BYTES_MD5_HASH = 16; -typedef char PacketVersion; +// NOTE: There is a max limit of 255, hopefully we have a better way to manage this by then. +typedef uint8_t PacketVersion; PacketVersion versionForPacketType(PacketType packetType); -QByteArray protocolVersionsSignature(); /// returns a unqiue signature for all the current protocols +QByteArray protocolVersionsSignature(); /// returns a unique signature for all the current protocols QString protocolVersionsSignatureBase64(); #if (PR_BUILD || DEV_BUILD) @@ -226,7 +227,7 @@ uint qHash(const PacketType& key, uint seed); QDebug operator<<(QDebug debug, const PacketType& type); // Due to the different legacy behaviour, we need special processing for domains that were created before -// the zone inheritance modes were added. These have version numbers up to 80 +// the zone inheritance modes were added. These have version numbers up to 80. enum class EntityVersion : PacketVersion { StrokeColorProperty = 0, HasDynamicOwnershipTests, @@ -278,6 +279,7 @@ enum class EntityVersion : PacketVersion { TextEntityFonts, ScriptServerKinematicMotion, ScreenshareZone, + ZoneOcclusion, // Add new versions above here NUM_PACKET_TYPE, diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 8ab502e951..5e6825c886 100755 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -482,6 +482,19 @@ bool OctreePacketData::appendValue(const QVector& value) { return success; } +bool OctreePacketData::appendValue(const QVector& value) { + uint16_t qVecSize = value.size(); + bool success = appendValue(qVecSize); + if (success) { + success = append((const unsigned char*)value.constData(), qVecSize * sizeof(QUuid)); + if (success) { + _bytesOfValues += qVecSize * sizeof(QUuid); + _totalBytesOfValues += qVecSize * sizeof(QUuid); + } + } + return success; +} + bool OctreePacketData::appendValue(const glm::quat& value) { const size_t VALUES_PER_QUAT = 4; const size_t PACKED_QUAT_SIZE = sizeof(uint16_t) * VALUES_PER_QUAT; @@ -774,6 +787,15 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVecto return (dataBytes - start) + (int)sizeof(uint16_t); } +int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVector& result) { + uint16_t length; + memcpy(&length, dataBytes, sizeof(uint16_t)); + dataBytes += sizeof(length); + result.resize(length); + memcpy(result.data(), dataBytes, length * sizeof(QUuid)); + return sizeof(uint16_t) + length * sizeof(QUuid); +} + int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result) { uint16_t length; memcpy(&length, dataBytes, sizeof(length)); diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index 46e5de9bda..2050dd1487 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -186,6 +186,9 @@ public: /// appends a QVector of bools to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const QVector& value); + /// appends a QVector of QUuids to the end of the stream, may fail if new data stream is too long to fit in packet + bool appendValue(const QVector& value); + /// appends a packed quat to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const glm::quat& value); @@ -284,6 +287,7 @@ public: static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); + static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result); static int unpackDataFromBytes(const unsigned char* dataBytes, AACube& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QRect& result); diff --git a/libraries/render-utils/src/CullFace.slh b/libraries/render-utils/src/CullFace.slh new file mode 100644 index 0000000000..61b76bb22f --- /dev/null +++ b/libraries/render-utils/src/CullFace.slh @@ -0,0 +1,20 @@ + +<@if not CULL_FACE_SLH@> +<@def CULL_FACE_SLH@> + +// NOTE: this calculation happens once per fragment. this could be optimized by creating different shaders (via defines) +// for front, back, and double-sided. for front/back-only triangles, this will simplify to always 1 or always -1 +vec3 evalFrontOrBackFaceNormal(vec3 normal) { + return (2.0 * float(gl_FrontFacing) - 1.0) * normal; +} + +<@endif@> diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 0786ef62ca..3b51d195f7 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -55,6 +55,13 @@ template <> const ShapeKey shapeGetShapeKey(const MeshPartPayload::Pointer& payl template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args) { return payload->render(args); } + +template <> bool payloadPassesZoneOcclusionTest(const MeshPartPayload::Pointer& payload, const std::unordered_set& containingZones) { + if (payload) { + return payload->passesZoneOcclusionTest(containingZones); + } + return false; +} } MeshPartPayload::MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material, const uint64_t& created) : @@ -171,10 +178,23 @@ void MeshPartPayload::bindMesh(gpu::Batch& batch) { batch.setInputStream(0, _drawMesh->getVertexStream()); } - void MeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const { +void MeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const { batch.setModelTransform(_worldFromLocalTransform); } +bool MeshPartPayload::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { + if (!_renderWithZones.isEmpty()) { + if (!containingZones.empty()) { + for (auto renderWithZone : _renderWithZones) { + if (containingZones.find(renderWithZone) != containingZones.end()) { + return true; + } + } + } + return false; + } + return true; +} void MeshPartPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("MeshPartPayload::render"); @@ -246,6 +266,12 @@ template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, Ren return payload->render(args); } +template <> bool payloadPassesZoneOcclusionTest(const ModelMeshPartPayload::Pointer& payload, const std::unordered_set& containingZones) { + if (payload) { + return payload->passesZoneOcclusionTest(containingZones); + } + return false; +} } ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 92dbae2e01..0a1562ff44 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -74,11 +74,15 @@ public: void setCullWithParent(bool value) { _cullWithParent = value; } + void setRenderWithZones(const QVector& renderWithZones) { _renderWithZones = renderWithZones; } + bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const; + static bool enableMaterialProceduralShaders; protected: render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() }; bool _cullWithParent { false }; + QVector _renderWithZones; uint64_t _created; }; @@ -87,6 +91,7 @@ namespace render { template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload); template <> const ShapeKey shapeGetShapeKey(const MeshPartPayload::Pointer& payload); template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args); + template <> bool payloadPassesZoneOcclusionTest(const MeshPartPayload::Pointer& payload, const std::unordered_set& containingZones); } class ModelMeshPartPayload : public MeshPartPayload { @@ -147,6 +152,7 @@ namespace render { template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload); template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload); template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args); + template <> bool payloadPassesZoneOcclusionTest(const ModelMeshPartPayload::Pointer& payload, const std::unordered_set& containingZones); } #endif // hifi_MeshPartPayload_h diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 0320d8ee01..1b7e1ebfb6 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -893,7 +893,7 @@ void Model::updateRenderItemsKey(const render::ScenePointer& scene) { } auto renderItemsKey = _renderItemKeyGlobalFlags; render::Transaction transaction; - for(auto itemID: _modelMeshRenderItemIDs) { + for (auto itemID: _modelMeshRenderItemIDs) { transaction.updateItem(itemID, [renderItemsKey](ModelMeshPartPayload& data) { data.updateKey(renderItemsKey); }); @@ -979,7 +979,7 @@ void Model::setCullWithParent(bool cullWithParent) { render::Transaction transaction; auto renderItemsKey = _renderItemKeyGlobalFlags; - for(auto item : _modelMeshRenderItemIDs) { + for (auto item : _modelMeshRenderItemIDs) { transaction.updateItem(item, [cullWithParent, renderItemsKey](ModelMeshPartPayload& data) { data.setCullWithParent(cullWithParent); data.updateKey(renderItemsKey); @@ -989,6 +989,16 @@ void Model::setCullWithParent(bool cullWithParent) { } } +void Model::setRenderWithZones(const QVector& renderWithZones) { + render::Transaction transaction; + for (auto item : _modelMeshRenderItemIDs) { + transaction.updateItem(item, [renderWithZones](ModelMeshPartPayload& data) { + data.setRenderWithZones(renderWithZones); + }); + } + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); +} + const render::ItemKey Model::getRenderItemKeyGlobalFlags() const { return _renderItemKeyGlobalFlags; } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 2def9f3287..ab7a748a32 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -131,6 +131,8 @@ public: void setCullWithParent(bool value); + void setRenderWithZones(const QVector& renderWithZones); + // Access the current RenderItemKey Global Flags used by the model and applied to the render items representing the parts of the model. const render::ItemKey getRenderItemKeyGlobalFlags() const; diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index a6cc82e335..98abc29d8c 100644 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -13,6 +13,7 @@ <@include graphics/Material.slh@> <@include graphics/MaterialTextures.slh@> <@include render-utils/ShaderConstants.h@> +<@include CullFace.slh@> <@if not HIFI_USE_SHADOW@> <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> @@ -129,7 +130,7 @@ void main(void) { _fragColor0 = vec4(albedo * isUnlitEnabled(), opacity); <@else@> packDeferredFragmentUnlit( - normalize(_normalWS), + evalFrontOrBackFaceNormal(normalize(_normalWS)), opacity, albedo * isUnlitEnabled()); <@endif@> @@ -195,7 +196,7 @@ void main(void) { <@else@> vec3 fragNormalWS = _normalWS; <@endif@> - fragNormalWS = normalize(fragNormalWS); + fragNormalWS = evalFrontOrBackFaceNormal(normalize(fragNormalWS)); <@if HIFI_USE_FORWARD@> TransformCamera cam = getTransformCamera(); diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 9760216682..fabe85cb4f 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -13,6 +13,7 @@ <@include gpu/Color.slh@> <@include DefaultMaterials.slh@> <@include render-utils/ShaderConstants.h@> +<@include CullFace.slh@> <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> <@if not HIFI_USE_UNLIT@> @@ -94,7 +95,7 @@ void main(void) { 1.0, DEFAULT_OCCLUSION, fragPosition, - normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), + evalFrontOrBackFaceNormal(normalize(_normalWS)), texel.rgb, fresnel, metallic, @@ -111,7 +112,7 @@ void main(void) { 1.0, DEFAULT_OCCLUSION, fragPosition, - normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), + evalFrontOrBackFaceNormal(normalize(_normalWS)), texel.rgb, fresnel, metallic, @@ -119,7 +120,7 @@ void main(void) { texel.a); <@else@> packDeferredFragment( - normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), + evalFrontOrBackFaceNormal(normalize(_normalWS)), 1.0, texel.rgb, DEFAULT_ROUGHNESS, @@ -141,7 +142,7 @@ void main(void) { , texel.a); <@else@> packDeferredFragmentUnlit( - normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), + evalFrontOrBackFaceNormal(normalize(_normalWS)), 1.0, texel.rgb <@if HIFI_USE_FADE@> diff --git a/libraries/render-utils/src/simple_procedural.slf b/libraries/render-utils/src/simple_procedural.slf index 5b0eb62cca..cc8edbb415 100644 --- a/libraries/render-utils/src/simple_procedural.slf +++ b/libraries/render-utils/src/simple_procedural.slf @@ -24,6 +24,7 @@ <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> +<@include CullFace.slh@> <@include render-utils/ShaderConstants.h@> layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _positionMS; @@ -66,7 +67,7 @@ float getProceduralFragmentWithPosition(inout ProceduralFragmentWithPosition pro #line 2030 void main(void) { - vec3 normal = normalize(_normalWS.xyz) * (2.0 * float(gl_FrontFacing) - 1.0); + vec3 normal = evalFrontOrBackFaceNormal(normalize(_normalWS.xyz)); vec3 diffuse = _color.rgb; vec3 fresnel = DEFAULT_FRESNEL; float roughness = DEFAULT_ROUGHNESS; diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index a75192bad7..5fee00b370 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -13,15 +13,16 @@ #include #include #include +#include #include #include #include +#include #include #include "Forward.h" - class AABox; namespace render { @@ -142,13 +143,6 @@ namespace render { bool _takingSnapshot { false }; StencilMaskMode _stencilMaskMode { StencilMaskMode::NONE }; std::function _stencilMaskOperator; - - float _visionSqueezeX { 0.0f }; - float _visionSqueezeY { 0.0f }; - float _visionSqueezeTransition { 0.15f }; - int _visionSqueezePerEye { 0 }; - float _visionSqueezeGroundPlaneY { 0.0f }; - float _visionSqueezeSpotlightSize { 0.02f }; }; } diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index 8cedbc7f3e..164d8e9f21 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -19,6 +19,9 @@ using namespace render; +std::unordered_set CullTest::_containingZones = std::unordered_set(); +std::unordered_set CullTest::_prevContainingZones = std::unordered_set(); + CullTest::CullTest(CullFunctor& functor, RenderArgs* pargs, RenderDetails::Item& renderDetails, ViewFrustumPointer antiFrustum) : _functor(functor), _args(pargs), @@ -64,46 +67,8 @@ bool CullTest::solidAngleTest(const AABox& bound) { return true; } -void render::cullItems(const RenderContextPointer& renderContext, const CullFunctor& cullFunctor, RenderDetails::Item& details, - const ItemBounds& inItems, ItemBounds& outItems) { - assert(renderContext->args); - assert(renderContext->args->hasViewFrustum()); - - RenderArgs* args = renderContext->args; - const ViewFrustum& frustum = args->getViewFrustum(); - - details._considered += (int)inItems.size(); - - // Culling / LOD - for (auto item : inItems) { - if (item.bound.isNull()) { - outItems.emplace_back(item); // One more Item to render - continue; - } - - // TODO: some entity types (like lights) might want to be rendered even - // when they are outside of the view frustum... - bool inView; - { - PerformanceTimer perfTimer("boxIntersectsFrustum"); - inView = frustum.boxIntersectsFrustum(item.bound); - } - if (inView) { - bool bigEnoughToRender; - { - PerformanceTimer perfTimer("shouldRender"); - bigEnoughToRender = cullFunctor(args, item.bound); - } - if (bigEnoughToRender) { - outItems.emplace_back(item); // One more Item to render - } else { - details._tooSmall++; - } - } else { - details._outOfView++; - } - } - details._rendered += (int)outItems.size(); +bool CullTest::zoneOcclusionTest(const render::Item& item) { + return item.passesZoneOcclusionTest(_containingZones); } void FetchNonspatialItems::run(const RenderContextPointer& renderContext, const ItemFilter& filter, ItemBounds& outItems) { @@ -117,7 +82,7 @@ void FetchNonspatialItems::run(const RenderContextPointer& renderContext, const outItems.reserve(items.size()); for (auto& id : items) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && item.passesZoneOcclusionTest(CullTest::_containingZones)) { outItems.emplace_back(ItemBound(id, item.getBound())); } } @@ -126,7 +91,6 @@ void FetchNonspatialItems::run(const RenderContextPointer& renderContext, const void FetchSpatialTree::configure(const Config& config) { _justFrozeFrustum = _justFrozeFrustum || (config.freezeFrustum && !_freezeFrustum); _freezeFrustum = config.freezeFrustum; - _lodAngle = config.lodAngle; } void FetchSpatialTree::run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemSpatialTree::ItemSelection& outSelection) { @@ -223,7 +187,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("insideFitItems"); for (auto id : inSelection.insideItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -238,7 +202,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("insideSmallItems"); for (auto id : inSelection.insideSubcellItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -253,7 +217,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("partialFitItems"); for (auto id : inSelection.partialItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -268,7 +232,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("partialSmallItems"); for (auto id : inSelection.partialSubcellItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -285,7 +249,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("insideFitItems"); for (auto id : inSelection.insideItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -300,7 +264,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("insideSmallItems"); for (auto id : inSelection.insideSubcellItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); if (test.solidAngleTest(itemBound.bound)) { outItems.emplace_back(itemBound); @@ -317,7 +281,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("partialFitItems"); for (auto id : inSelection.partialItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); if (test.frustumTest(itemBound.bound)) { outItems.emplace_back(itemBound); @@ -334,14 +298,12 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("partialSmallItems"); for (auto id : inSelection.partialSubcellItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); - if (test.frustumTest(itemBound.bound)) { - if (test.solidAngleTest(itemBound.bound)) { - outItems.emplace_back(itemBound); - if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); - } + if (test.frustumTest(itemBound.bound) && test.solidAngleTest(itemBound.bound)) { + outItems.emplace_back(itemBound); + if (item.getKey().isMetaCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); } } } @@ -452,3 +414,13 @@ void ApplyCullFunctorOnItemBounds::run(const RenderContextPointer& renderContext args->popViewFrustum(); } } + +void ClearContainingZones::run(const RenderContextPointer& renderContext) { + // This is a bit of a hack. We want to do zone culling as early as possible, so we do it + // during the RenderFetchCullSortTask (in CullSpatialSelection and FetchNonspatialItems), + // but the zones aren't collected until after (in SetupZones). To get around this, + // we actually use the zones from the previous frame to render, and then clear at the beginning + // of the next frame + CullTest::_prevContainingZones = CullTest::_containingZones; + CullTest::_containingZones.clear(); +} \ No newline at end of file diff --git a/libraries/render/src/render/CullTask.h b/libraries/render/src/render/CullTask.h index e67edd6666..9a7466223d 100644 --- a/libraries/render/src/render/CullTask.h +++ b/libraries/render/src/render/CullTask.h @@ -19,9 +19,6 @@ namespace render { using CullFunctor = std::function; - void cullItems(const RenderContextPointer& renderContext, const CullFunctor& cullFunctor, RenderDetails::Item& details, - const ItemBounds& inItems, ItemBounds& outItems); - // Culling Frustum / solidAngle test helper class struct CullTest { CullFunctor _functor; @@ -36,6 +33,10 @@ namespace render { bool frustumTest(const AABox& bound); bool antiFrustumTest(const AABox& bound); bool solidAngleTest(const AABox& bound); + bool zoneOcclusionTest(const render::Item& item); + + static std::unordered_set _containingZones; + static std::unordered_set _prevContainingZones; }; class FetchNonspatialItems { @@ -48,7 +49,6 @@ namespace render { Q_OBJECT Q_PROPERTY(int numItems READ getNumItems) Q_PROPERTY(bool freezeFrustum MEMBER freezeFrustum WRITE setFreezeFrustum) - Q_PROPERTY(float LODAngle MEMBER lodAngle NOTIFY dirty) public: int numItems{ 0 }; @@ -56,7 +56,6 @@ namespace render { bool freezeFrustum{ false }; - float lodAngle{ 2.0 }; public slots: void setFreezeFrustum(bool enabled) { freezeFrustum = enabled; emit dirty(); } @@ -68,7 +67,6 @@ namespace render { bool _freezeFrustum{ false }; // initialized by Config bool _justFrozeFrustum{ false }; ViewFrustum _frozenFrustum; - float _lodAngle; public: using Config = FetchSpatialTreeConfig; @@ -159,6 +157,12 @@ namespace render { render::CullFunctor _cullFunctor; }; + + class ClearContainingZones { + public: + using JobModel = Job::Model; + void run(const RenderContextPointer& renderContext); + }; } #endif // hifi_render_CullTask_h; \ No newline at end of file diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index 532964777f..f21df58368 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -154,4 +154,10 @@ namespace render { return payload->metaFetchMetaSubItems(subItems); } + template <> bool payloadPassesZoneOcclusionTest(const PayloadProxyInterface::Pointer& payload, const std::unordered_set& containingZones) { + if (!payload) { + return false; + } + return payload->passesZoneOcclusionTest(containingZones); + } } diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 3383101b5b..cb9fb32c7f 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -436,6 +436,8 @@ public: virtual uint32_t fetchMetaSubItems(ItemIDs& subItems) const = 0; + virtual bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const = 0; + ~PayloadInterface() {} // Status interface is local to the base class @@ -487,6 +489,8 @@ public: uint32_t fetchMetaSubItems(ItemIDs& subItems) const { return _payload->fetchMetaSubItems(subItems); } uint32_t fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene) const; + bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const { return _payload->passesZoneOcclusionTest(containingZones); } + // Access the status const StatusPointer& getStatus() const { return _payload->getStatus(); } @@ -537,6 +541,10 @@ template const ShapeKey shapeGetShapeKey(const std::shared_ptr& pay // Meta items act as the grouping object for several sub items (typically shapes). template uint32_t metaFetchMetaSubItems(const std::shared_ptr& payloadData, ItemIDs& subItems) { return 0; } +// Zone Occlusion Interface +// Allows payloads to determine if they should render or not, based on the zones that contain the current camera +template bool payloadPassesZoneOcclusionTest(const std::shared_ptr& payloadData, const std::unordered_set& containingZones) { return true; } + // THe Payload class is the real Payload to be used // THis allow anything to be turned into a Payload as long as the required interface functions are available // When creating a new kind of payload from a new "stuff" class then you need to create specialized version for "stuff" @@ -561,6 +569,8 @@ public: // Meta Type Interface virtual uint32_t fetchMetaSubItems(ItemIDs& subItems) const override { return metaFetchMetaSubItems(_data, subItems); } + virtual bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const override { return payloadPassesZoneOcclusionTest(_data, containingZones); } + protected: DataPointer _data; @@ -615,6 +625,7 @@ public: virtual Item::Bound getBound() = 0; virtual void render(RenderArgs* args) = 0; virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const = 0; + virtual bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const = 0; }; template <> const ItemKey payloadGetKey(const PayloadProxyInterface::Pointer& payload); @@ -622,7 +633,7 @@ template <> const Item::Bound payloadGetBound(const PayloadProxyInterface::Point template <> void payloadRender(const PayloadProxyInterface::Pointer& payload, RenderArgs* args); template <> uint32_t metaFetchMetaSubItems(const PayloadProxyInterface::Pointer& payload, ItemIDs& subItems); template <> const ShapeKey shapeGetShapeKey(const PayloadProxyInterface::Pointer& payload); - +template <> bool payloadPassesZoneOcclusionTest(const PayloadProxyInterface::Pointer& payload, const std::unordered_set& containingZones); typedef Item::PayloadPointer PayloadPointer; typedef std::vector Payloads; diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index ebcf5a432b..b2656a597f 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -74,6 +74,7 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin const auto filteredLayeredOpaque = task.addJob("FilterLayeredOpaque", layeredOpaques, ItemKey::Layer::LAYER_1); const auto filteredLayeredTransparent = task.addJob("FilterLayeredTransparent", layeredTransparents, ItemKey::Layer::LAYER_1); + task.addJob("ClearContainingZones"); output = Output(BucketList{ opaques, transparents, lights, metas, filteredLayeredOpaque.getN(0), filteredLayeredTransparent.getN(0), diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index eb3e286843..57904be586 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -13,6 +13,13 @@ if (ANDROID) target_link_libraries(${TARGET_NAME} android) endif() +if (APPLE) + find_library(FRAMEWORK_IOKIT IOKit) + find_library(CORE_FOUNDATION CoreFoundation) + find_library(OpenGL OpenGL) + target_link_libraries(${TARGET_NAME} ${FRAMEWORK_IOKIT} ${CORE_FOUNDATION} ${OpenGL}) +endif() + target_zlib() target_nsight() target_json() diff --git a/libraries/shared/src/JointData.h b/libraries/shared/src/JointData.h index 3f957fa046..329c2dd151 100644 --- a/libraries/shared/src/JointData.h +++ b/libraries/shared/src/JointData.h @@ -16,7 +16,7 @@ public: // Used by the avatar mixer to describe a single joint // Translations relative to their parent joint // Rotations are absolute (i.e. not relative to parent) and are in rig space. -// No JSDoc because its not provided as a type to the script engine. +// No JSDoc because it's not provided as a type to the script engine. class JointData { public: glm::quat rotation; diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 7c30d4f205..d47cc0769a 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -36,6 +36,7 @@ int qVectorVec3MetaTypeId = qRegisterMetaType>(); int qVectorQuatMetaTypeId = qRegisterMetaType>(); int qVectorBoolMetaTypeId = qRegisterMetaType>(); int qVectorGLMUint32MetaTypeId = qRegisterMetaType>("QVector"); +int qVectorQUuidMetaTypeId = qRegisterMetaType>(); int quatMetaTypeId = qRegisterMetaType(); int pickRayMetaTypeId = qRegisterMetaType(); int collisionMetaTypeId = qRegisterMetaType(); @@ -58,6 +59,7 @@ void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, qVectorBoolToScriptValue, qVectorBoolFromScriptValue); qScriptRegisterMetaType(engine, qVectorFloatToScriptValue, qVectorFloatFromScriptValue); qScriptRegisterMetaType(engine, qVectorIntToScriptValue, qVectorIntFromScriptValue); + qScriptRegisterMetaType(engine, qVectorQUuidToScriptValue, qVectorQUuidFromScriptValue); qScriptRegisterMetaType(engine, qSizeFToScriptValue, qSizeFFromScriptValue); qScriptRegisterMetaType(engine, qRectToScriptValue, qRectFromScriptValue); @@ -874,6 +876,22 @@ QVector qVectorFloatFromScriptValue(const QScriptValue& array) { return newVector; } +QScriptValue qVectorQUuidToScriptValue(QScriptEngine* engine, const QVector& vector) { + QScriptValue array = engine->newArray(); + for (int i = 0; i < vector.size(); i++) { + array.setProperty(i, quuidToScriptValue(engine, vector.at(i))); + } + return array; +} + +void qVectorQUuidFromScriptValue(const QScriptValue& array, QVector& vector) { + int length = array.property("length").toInteger(); + + for (int i = 0; i < length; i++) { + vector << array.property(i).toVariant().toUuid(); + } +} + QVector qVectorQUuidFromScriptValue(const QScriptValue& array) { if (!array.isArray()) { return QVector(); @@ -1309,7 +1327,7 @@ void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out) { /**jsdoc * A triangle in a mesh. * @typedef {object} MeshFace - * @property {number[]} vertices - The indexes of the three vertices that make up the fase. + * @property {number[]} vertices - The indexes of the three vertices that make up the face. */ QScriptValue meshFaceToScriptValue(QScriptEngine* engine, const MeshFace &meshFace) { QScriptValue obj = engine->newObject(); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index a7b7c4edf4..86e06d7f93 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -247,6 +247,8 @@ QVector qVectorFloatFromScriptValue(const QScriptValue& array); QScriptValue qVectorIntToScriptValue(QScriptEngine* engine, const QVector& vector); void qVectorIntFromScriptValue(const QScriptValue& array, QVector& vector); +QScriptValue qVectorQUuidToScriptValue(QScriptEngine* engine, const QVector& vector); +void qVectorQUuidFromScriptValue(const QScriptValue& array, QVector& vector); QVector qVectorQUuidFromScriptValue(const QScriptValue& array); QScriptValue aaCubeToScriptValue(QScriptEngine* engine, const AACube& aaCube); diff --git a/libraries/shared/src/shared/FileLogger.cpp b/libraries/shared/src/shared/FileLogger.cpp index 2ccc247af3..9fc72bd000 100644 --- a/libraries/shared/src/shared/FileLogger.cpp +++ b/libraries/shared/src/shared/FileLogger.cpp @@ -38,12 +38,12 @@ private: QMutex _fileMutex; }; -static const QString FILENAME_FORMAT = "hifi-log_%1%2.txt"; +static const QString FILENAME_FORMAT = "vircadia-log_%1%2.txt"; static const QString DATETIME_FORMAT = "yyyy-MM-dd_hh.mm.ss"; static const QString LOGS_DIRECTORY = "Logs"; static const QString DATETIME_WILDCARD = "20[0-9][0-9]-[01][0-9]-[0-3][0-9]_[0-2][0-9]\\.[0-6][0-9]\\.[0-6][0-9]"; static const QString SESSION_WILDCARD = "[0-9a-z]{8}(-[0-9a-z]{4}){3}-[0-9a-z]{12}"; -static QRegExp LOG_FILENAME_REGEX { "hifi-log_" + DATETIME_WILDCARD + "(_" + SESSION_WILDCARD + ")?\\.txt" }; +static QRegExp LOG_FILENAME_REGEX { "vircadia-log_" + DATETIME_WILDCARD + "(_" + SESSION_WILDCARD + ")?\\.txt" }; static QUuid SESSION_ID; // Max log size is 512 KB. We send log files to our crash reporter, so we want to keep this relatively @@ -68,7 +68,7 @@ QString getLogRollerFilename() { } const QString& getLogFilename() { - static QString fileName = FileUtils::standardPath(LOGS_DIRECTORY) + "hifi-log.txt"; + static QString fileName = FileUtils::standardPath(LOGS_DIRECTORY) + "vircadia-log.txt"; return fileName; } diff --git a/prebuild.py b/prebuild.py index 03677f21d7..cc315a49a4 100644 --- a/prebuild.py +++ b/prebuild.py @@ -94,6 +94,8 @@ def parse_args(): parser.add_argument('--force-build', action='store_true') parser.add_argument('--release-type', type=str, default="DEV", help="DEV, PR, or PRODUCTION") parser.add_argument('--vcpkg-root', type=str, help='The location of the vcpkg distribution') + parser.add_argument('--vcpkg-build-type', type=str, help='Could be `release` or `debug`. By default it doesn`t set the build-type') + parser.add_argument('--vcpkg-skip-clean', action='store_true', help='Skip the cleanup of vcpkg downloads and packages folders after vcpkg build completition.') parser.add_argument('--build-root', required=True, type=str, help='The location of the cmake build') parser.add_argument('--ports-path', type=str, default=defaultPortsPath) parser.add_argument('--ci-build', action='store_true', default=os.getenv('CI_BUILD') is not None) @@ -113,6 +115,7 @@ def main(): del os.environ[var] args = parse_args() + assets_url = hifi_utils.readEnviromentVariableFromFile(args.build_root, 'EXTERNAL_BUILD_ASSETS') if args.ci_build: logging.basicConfig(datefmt='%H:%M:%S', format='%(asctime)s %(guid)s %(message)s', level=logging.INFO) @@ -125,7 +128,7 @@ def main(): if 'Windows' == system and 'CI_BUILD' in os.environ and os.environ["CI_BUILD"] == "Github": logger.info("Downloading NSIS") with timer('NSIS'): - hifi_utils.downloadAndExtract('https://athena-public.s3.amazonaws.com/dependencies/NSIS-hifi-plugins-1.0.tgz', "C:/Program Files (x86)") + hifi_utils.downloadAndExtract(assets_url + '/dependencies/NSIS-hifi-plugins-1.0.tgz', "C:/Program Files (x86)") qtInstallPath = '' # If not android, install our Qt build @@ -138,6 +141,11 @@ def main(): qt.writeConfig() pm = hifi_vcpkg.VcpkgRepo(args) + if qtInstallPath != '': + pm.writeVar('QT_CMAKE_PREFIX_PATH', qtInstallPath) + + # Only allow one instance of the program to run at a time + if qtInstallPath != '': pm.writeVar('QT_CMAKE_PREFIX_PATH', qtInstallPath) @@ -160,7 +168,7 @@ def main(): pm.setupDependencies(qt=qtInstallPath) # wipe out the build directories (after writing the tag, since failure - # here shouldn't invalidte the vcpkg install) + # here shouldn't invalidate the vcpkg install) with timer('Cleaning builds'): pm.cleanBuilds() @@ -175,6 +183,13 @@ def main(): qtPath = os.path.join(pm.androidPackagePath, 'qt') hifi_android.QtPackager(appPath, qtPath).bundle() + # Fixup the vcpkg cmake to not reset VCPKG_TARGET_TRIPLET + pm.fixupCmakeScript() + + if not args.vcpkg_skip_clean: + # Cleanup downloads and packages folders in vcpkg to make it smaller for CI + pm.cleanupDevelopmentFiles() + # Write the vcpkg config to the build directory last with timer('Writing configuration'): pm.writeConfig() diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json index da12d2d503..4efd0593fb 100644 --- a/scripts/system/create/assets/data/createAppTooltips.json +++ b/scripts/system/create/assets/data/createAppTooltips.json @@ -3,7 +3,10 @@ "tooltip": "The shape of this entity's geometry." }, "color": { - "tooltip": "The RGB value of this entity." + "tooltip": "The color of this entity." + }, + "shapeAlpha": { + "tooltip": "The opacity of the entity between 0.0 fully transparent and 1.0 completely opaque." }, "text": { "tooltip": "The text to display on the entity." @@ -12,17 +15,29 @@ "tooltip": "The color of the text." }, "textAlpha": { - "tooltip": "The alpha of the text." + "tooltip": "The opacity of the text between 0.0 fully transparent and 1.0 completely opaque." }, "backgroundColor": { "tooltip": "The color of the background." }, "backgroundAlpha": { - "tooltip": "The alpha of the background." + "tooltip": "The opacity of the background between 0.0 fully transparent and 1.0 completely opaque." }, "lineHeight": { "tooltip": "The height of each line of text. This determines the size of the text." }, + "font": { + "tooltip": "The font to render the text. Supported values: \"Courier\", \"Inconsolata\", \"Roboto\", \"Timeless\", or a URL to a .sdff file." + }, + "textEffect": { + "tooltip": "The effect that is applied to the text." + }, + "textEffectColor": { + "tooltip": "The color of the text effect." + }, + "textEffectThickness": { + "tooltip": "The magnitude of the text effect." + }, "textBillboardMode": { "tooltip": "If enabled, determines how the entity will face the camera.", "jsPropertyName": "billboardMode" @@ -149,7 +164,7 @@ }, "screenshare": { "tooltip": "Enable screen-sharing within this zone" - }, + }, "modelURL": { "tooltip": "A mesh model from an FBX or OBJ file." }, @@ -199,6 +214,9 @@ "tooltip": "The tint to be applied to the image.", "jsPropertyName": "color" }, + "imageAlpha": { + "tooltip": "The opacity of the image between 0.0 fully transparent and 1.0 completely opaque." + }, "emissive": { "tooltip": "If enabled, the image will display at full brightness." }, @@ -218,6 +236,16 @@ "dpi": { "tooltip": "The resolution to display the page at, in pixels per inch. Use this to resize your web source in the frame." }, + "webBillboardMode": { + "tooltip": "If enabled, determines how the entity will face the camera.", + "jsPropertyName": "billboardMode" + }, + "inputMode": { + "tooltip": "The user input mode to use." + }, + "showKeyboardFocusHighlight": { + "tooltip": "If enabled, highlights when it has keyboard focus." + }, "isEmitting": { "tooltip": "If enabled, then particles are emitted." }, @@ -294,20 +322,20 @@ "tooltip": "The spread in color that each particle is given, resulting in a variety of colors." }, "particleAlphaTriple": { - "tooltip": "The alpha of each particle.", + "tooltip": "The opacity of each particle between 0.0 fully transparent and 1.0 completely opaque.", "jsPropertyName": "alpha" }, "alpha": { - "tooltip": "The alpha of each particle." + "tooltip": "The opacity of each particle between 0.0 fully transparent and 1.0 completely opaque." }, "alphaStart": { - "tooltip": "The start alpha of each particle." + "tooltip": "The initial opacity level of each particle between 0.0 fully transparent and 1.0 completely opaque." }, "alphaFinish": { - "tooltip": "The finish alpha of each particle." + "tooltip": "The final opacity level of each particle between 0.0 fully transparent and 1.0 completely opaque." }, "alphaSpread": { - "tooltip": "The spread in alpha that each particle is given, resulting in a variety of alphas." + "tooltip": "The spread in opacity that each particle is given, resulting in a variety of opacity levels." }, "emitAcceleration": { "tooltip": "The acceleration that is applied to each particle during its lifetime." @@ -567,6 +595,9 @@ "primitiveMode": { "tooltip": "The mode in which to draw an entity, either \"Solid\" or \"Wireframe\"." }, + "renderWithZones": { + "tooltip": "If set, this entity will only render when your avatar is inside of a zone in this list." + }, "groupCulled": { "tooltip": "If false, individual pieces of the entity may be culled by the render engine. If true, either the entire entity will be culled, or it won't at all." }, @@ -574,7 +605,7 @@ "tooltip": "The tint of the web entity." }, "webAlpha": { - "tooltip": "The alpha of the web entity." + "tooltip": "The opacity of the web entity between 0.0 fully transparent and 1.0 completely opaque." }, "maxFPS": { "tooltip": "The FPS at which to render the web entity. Higher values will have a performance impact." diff --git a/scripts/system/create/edit.js b/scripts/system/create/edit.js index 16b11698ac..564ce512aa 100644 --- a/scripts/system/create/edit.js +++ b/scripts/system/create/edit.js @@ -3,6 +3,7 @@ // Created by Brad Hefta-Gaub on 10/2/14. // Persist toolbar by HRS 6/11/15. // Copyright 2014 High Fidelity, Inc. +// Copyright 2020 Vircadia contributors. // // This script allows you to edit entities with a new UI/UX for mouse and trackpad based editing // @@ -41,6 +42,7 @@ var CreateWindow = Script.require('./modules/createWindow.js'); var TITLE_OFFSET = 60; var CREATE_TOOLS_WIDTH = 490; var MAX_DEFAULT_ENTITY_LIST_HEIGHT = 942; +var ENTIRE_DOMAIN_SCAN_RADIUS = 27713; var DEFAULT_IMAGE = "https://hifi-content.s3.amazonaws.com/DomainContent/production/no-image.jpg"; @@ -562,7 +564,7 @@ var toolBar = (function () { if (!properties.grab) { properties.grab = {}; if (Menu.isOptionChecked(MENU_CREATE_ENTITIES_GRABBABLE) && - !(properties.type === "Zone" || properties.type === "Light" + !(properties.type === "Zone" || properties.type === "Light" || properties.type === "ParticleEffect" || properties.type === "Web")) { properties.grab.grabbable = true; } else { @@ -2587,6 +2589,11 @@ var PropertiesTool = function (opts) { entityID: data.entityID, materialTargetData: parentModelData, }); + } else if (data.type === "zoneListRequest") { + emitScriptEvent({ + type: 'zoneListRequest', + zones: getExistingZoneList() + }); } }; @@ -2884,4 +2891,21 @@ selectionDisplay.onSpaceModeChange = function(spaceMode) { propertiesTool.setSpaceMode(spaceMode); }; +function getExistingZoneList() { + var center = { "x": 0, "y": 0, "z": 0 }; + var existingZoneIDs = Entities.findEntitiesByType("Zone", center, ENTIRE_DOMAIN_SCAN_RADIUS); + var listExistingZones = []; + var thisZone = {}; + var properties; + for (var k = 0; k < existingZoneIDs.length; k++) { + properties = Entities.getEntityProperties(existingZoneIDs[k], ["name"]); + thisZone = { + "id": existingZoneIDs[k], + "name": properties.name + }; + listExistingZones.push(thisZone); + } + return listExistingZones; +} + }()); // END LOCAL_SCOPE diff --git a/scripts/system/create/entityProperties/html/entityProperties.html b/scripts/system/create/entityProperties/html/entityProperties.html index 876e75ec35..6eadf4d3c0 100644 --- a/scripts/system/create/entityProperties/html/entityProperties.html +++ b/scripts/system/create/entityProperties/html/entityProperties.html @@ -1,52 +1,63 @@ - - - Properties - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-
-
-
-
+ + Properties + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+
+
+
+
+ + + + + +
+
+
+
+ +
+
- -
- - + diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 64d44cc270..182dddf817 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -1,8 +1,8 @@ // entityProperties.js // // Created by Ryan Huffman on 13 Nov 2014 -// Modified by David Back on 19 Oct 2018 // 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 @@ -10,6 +10,8 @@ /* global alert, augmentSpinButtons, clearTimeout, console, document, Element, EventBridge, JSONEditor, openEventBridge, setTimeout, window, _, $ */ +var currentTab = "base"; + const DEGREES_TO_RADIANS = Math.PI / 180.0; const NO_SELECTION = ","; @@ -24,7 +26,7 @@ const PROPERTY_SELECTION_VISIBILITY = Object.freeze({ SINGLE_SELECTION: 1, MULTIPLE_SELECTIONS: 2, MULTI_DIFF_SELECTIONS: 4, - ANY_SELECTIONS: 7, /* SINGLE_SELECTION | MULTIPLE_SELECTIONS | MULTI_DIFF_SELECTIONS */ + ANY_SELECTIONS: 7 /* SINGLE_SELECTION | MULTIPLE_SELECTIONS | MULTI_DIFF_SELECTIONS */ }); // Multiple-selection behavior @@ -34,12 +36,13 @@ const PROPERTY_MULTI_DISPLAY_MODE = Object.freeze({ * Comma separated values * Limited for properties with type "string" or "textarea" and readOnly enabled */ - COMMA_SEPARATED_VALUES: 1, + COMMA_SEPARATED_VALUES: 1 }); const GROUPS = [ { id: "base", + label: "ENTITY", properties: [ { label: NO_SELECTION, @@ -113,11 +116,16 @@ const GROUPS = [ }, propertyID: "primitiveMode", }, + { + label: "Render With Zones", + type: "multipleZonesSelection", + propertyID: "renderWithZones", + } ] }, { id: "shape", - addToGroup: "base", + label: "SHAPE", properties: [ { label: "Shape", @@ -133,11 +141,21 @@ const GROUPS = [ type: "color", propertyID: "color", }, + { + label: "Alpha", + type: "number-draggable", + min: 0, + max: 1, + step: 0.01, + decimals: 2, + propertyID: "shapeAlpha", + propertyName: "alpha", + }, ] }, { id: "text", - addToGroup: "base", + label: "TEXT", properties: [ { label: "Text", @@ -181,6 +199,36 @@ const GROUPS = [ unit: "m", propertyID: "lineHeight", }, + { + label: "Font", + type: "string", + propertyID: "font", + }, + { + label: "Effect", + type: "dropdown", + options: { + none: "None", + outline: "Outline", + "outline fill": "Outline with fill", + shadow: "Shadow" + }, + propertyID: "textEffect", + }, + { + label: "Effect Color", + type: "color", + propertyID: "textEffectColor", + }, + { + label: "Effect Thickness", + type: "number-draggable", + min: 0.0, + max: 0.5, + step: 0.01, + decimals: 2, + propertyID: "textEffectThickness", + }, { label: "Billboard Mode", type: "dropdown", @@ -220,12 +268,12 @@ const GROUPS = [ label: "Unlit", type: "bool", propertyID: "unlit", - }, + } ] }, { id: "zone", - addToGroup: "base", + label: "ZONE", properties: [ { label: "Shape Type", @@ -255,7 +303,13 @@ const GROUPS = [ label: "Filter", type: "string", propertyID: "filterURL", - }, + } + ] + }, + { + id: "zone_key_light", + label: "ZONE KEY LIGHT", + properties: [ { label: "Key Light", type: "dropdown", @@ -272,7 +326,7 @@ const GROUPS = [ { label: "Light Intensity", type: "number-draggable", - min: 0, + min: -40, max: 40, step: 0.01, decimals: 2, @@ -324,7 +378,13 @@ const GROUPS = [ decimals: 2, propertyID: "keyLight.shadowMaxDistance", showPropertyRule: { "keyLightMode": "enabled" }, - }, + } + ] + }, + { + id: "zone_skybox", + label: "ZONE SKYBOX", + properties: [ { label: "Skybox", type: "dropdown", @@ -342,7 +402,13 @@ const GROUPS = [ type: "string", propertyID: "skybox.url", showPropertyRule: { "skyboxMode": "enabled" }, - }, + } + ] + }, + { + id: "zone_ambient_light", + label: "ZONE AMBIENT LIGHT", + properties: [ { label: "Ambient Light", type: "dropdown", @@ -352,7 +418,7 @@ const GROUPS = [ { label: "Ambient Intensity", type: "number-draggable", - min: 0, + min: -200, max: 200, step: 0.1, decimals: 2, @@ -371,7 +437,13 @@ const GROUPS = [ className: "black", onClick: copySkyboxURLToAmbientURL } ], propertyID: "copyURLToAmbient", showPropertyRule: { "ambientLightMode": "enabled" }, - }, + } + ] + }, + { + id: "zone_haze", + label: "ZONE HAZE", + properties: [ { label: "Haze", type: "dropdown", @@ -454,7 +526,13 @@ const GROUPS = [ decimals: 0, propertyID: "haze.hazeGlareAngle", showPropertyRule: { "hazeMode": "enabled" }, - }, + } + ] + }, + { + id: "zone_bloom", + label: "ZONE BLOOM", + properties: [ { label: "Bloom", type: "dropdown", @@ -490,7 +568,13 @@ const GROUPS = [ decimals: 3, propertyID: "bloom.bloomSize", showPropertyRule: { "bloomMode": "enabled" }, - }, + } + ] + }, + { + id: "zone_avatar_priority", + label: "ZONE AVATAR PRIORITY", + properties: [ { label: "Avatar Priority", type: "dropdown", @@ -503,12 +587,11 @@ const GROUPS = [ options: { inherit: "Inherit", disabled: "Off", enabled: "On" }, propertyID: "screenshare", } - ] }, { id: "model", - addToGroup: "base", + label: "MODEL", properties: [ { label: "Model", @@ -548,7 +631,7 @@ const GROUPS = [ propertyID: "animation.loop", }, { - label: "Allow Transition", + label: "Allow Translation", type: "bool", propertyID: "animation.allowTranslation", }, @@ -593,12 +676,12 @@ const GROUPS = [ label: "Group Culled", type: "bool", propertyID: "groupCulled", - }, + } ] }, { id: "image", - addToGroup: "base", + label: "IMAGE", properties: [ { label: "Image", @@ -612,6 +695,16 @@ const GROUPS = [ propertyID: "imageColor", propertyName: "color", // actual entity property name }, + { + label: "Alpha", + type: "number-draggable", + min: 0, + max: 1, + step: 0.01, + decimals: 2, + propertyID: "imageAlpha", + propertyName: "alpha", + }, { label: "Emissive", type: "bool", @@ -636,12 +729,12 @@ const GROUPS = [ label: "Keep Aspect Ratio", type: "bool", propertyID: "keepAspectRatio", - }, + } ] }, { id: "web", - addToGroup: "base", + label: "WEB", properties: [ { label: "Source", @@ -676,17 +769,38 @@ const GROUPS = [ decimals: 0, propertyID: "maxFPS", }, + { + label: "Billboard Mode", + type: "dropdown", + options: { none: "None", yaw: "Yaw", full: "Full"}, + propertyID: "webBillboardMode", + propertyName: "billboardMode", // actual entity property name + }, + { + label: "Input Mode", + type: "dropdown", + options: { + touch: "Touch events", + mouse: "Mouse events" + }, + propertyID: "inputMode", + }, + { + label: "Focus Highlight", + type: "bool", + propertyID: "showKeyboardFocusHighlight", + }, { label: "Script URL", type: "string", propertyID: "scriptURL", placeholder: "URL", - }, + } ] }, { id: "light", - addToGroup: "base", + label: "LIGHT", properties: [ { label: "Light Color", @@ -697,7 +811,7 @@ const GROUPS = [ { label: "Intensity", type: "number-draggable", - min: 0, + min: -1000, max: 10000, step: 0.1, decimals: 2, @@ -732,12 +846,12 @@ const GROUPS = [ step: 0.01, decimals: 2, propertyID: "cutoff", - }, + } ] }, { id: "material", - addToGroup: "base", + label: "MATERIAL", properties: [ { label: "Material URL", @@ -806,12 +920,12 @@ const GROUPS = [ label: "Material Repeat", type: "bool", propertyID: "materialRepeat", - }, + } ] }, { id: "grid", - addToGroup: "base", + label: "GRID", properties: [ { label: "Color", @@ -839,12 +953,12 @@ const GROUPS = [ step: 0.01, decimals: 2, propertyID: "minorGridEvery", - }, + } ] }, { id: "particles", - addToGroup: "base", + label: "PARTICLES", properties: [ { label: "Emit", @@ -870,13 +984,12 @@ const GROUPS = [ type: "texture", propertyID: "particleTextures", propertyName: "textures", // actual entity property name - }, + } ] }, { id: "particles_emit", - label: "EMIT", - isMinor: true, + label: "PARTICLES EMIT", properties: [ { label: "Emit Rate", @@ -943,13 +1056,12 @@ const GROUPS = [ label: "Trails", type: "bool", propertyID: "emitterShouldTrail", - }, + } ] }, { id: "particles_size", - label: "SIZE", - isMinor: true, + label: "PARTICLES SIZE", properties: [ { type: "triple", @@ -978,7 +1090,7 @@ const GROUPS = [ decimals: 2, propertyID: "radiusFinish", fallbackProperty: "particleRadius", - }, + } ] }, { @@ -987,13 +1099,12 @@ const GROUPS = [ step: 0.01, decimals: 2, propertyID: "radiusSpread", - }, + } ] }, { id: "particles_color", - label: "COLOR", - isMinor: true, + label: "PARTICLES COLOR", properties: [ { type: "triple", @@ -1017,7 +1128,7 @@ const GROUPS = [ type: "color", propertyID: "colorFinish", fallbackProperty: "color", - }, + } ] }, { @@ -1025,13 +1136,6 @@ const GROUPS = [ type: "color", propertyID: "colorSpread", }, - ] - }, - { - id: "particles_alpha", - label: "ALPHA", - isMinor: true, - properties: [ { type: "triple", label: "Alpha", @@ -1059,7 +1163,7 @@ const GROUPS = [ decimals: 3, propertyID: "alphaFinish", fallbackProperty: "alpha", - }, + } ] }, { @@ -1068,13 +1172,12 @@ const GROUPS = [ step: 0.001, decimals: 3, propertyID: "alphaSpread", - }, + } ] }, { - id: "particles_acceleration", - label: "ACCELERATION", - isMinor: true, + id: "particles_behavior", + label: "PARTICLES BEHAVIOR", properties: [ { label: "Emit Acceleration", @@ -1094,13 +1197,6 @@ const GROUPS = [ subLabels: [ "x", "y", "z" ], propertyID: "accelerationSpread", }, - ] - }, - { - id: "particles_spin", - label: "SPIN", - isMinor: true, - properties: [ { type: "triple", label: "Spin", @@ -1134,7 +1230,7 @@ const GROUPS = [ unit: "deg", propertyID: "spinFinish", fallbackProperty: "particleSpin", - }, + } ] }, { @@ -1150,13 +1246,12 @@ const GROUPS = [ label: "Rotate with Entity", type: "bool", propertyID: "rotateWithEntity", - }, + } ] }, { id: "particles_constraints", - label: "CONSTRAINTS", - isMinor: true, + label: "PARTICLES CONSTRAINTS", properties: [ { type: "triple", @@ -1180,7 +1275,7 @@ const GROUPS = [ multiplier: DEGREES_TO_RADIANS, unit: "deg", propertyID: "polarFinish", - }, + } ], }, { @@ -1205,7 +1300,7 @@ const GROUPS = [ multiplier: DEGREES_TO_RADIANS, unit: "deg", propertyID: "azimuthFinish", - }, + } ] } ] @@ -1305,7 +1400,7 @@ const GROUPS = [ buttons: [ { id: "selection", label: "Selection to Grid", className: "black", onClick: moveSelectionToGrid }, { id: "all", label: "All to Grid", className: "black", onClick: moveAllToGrid } ], propertyID: "alignToGrid", - }, + } ] }, { @@ -1375,6 +1470,18 @@ const GROUPS = [ type: "bool", propertyID: "ignorePickIntersection", }, + { + label: "Lifetime", + type: "number", + unit: "s", + propertyID: "lifetime", + } + ] + }, + { + id: "scripts", + label: "SCRIPTS", + properties: [ { label: "Script", type: "string", @@ -1397,12 +1504,6 @@ const GROUPS = [ propertyID: "serverScriptStatus", selectionVisibility: PROPERTY_SELECTION_VISIBILITY.SINGLE_SELECTION, }, - { - label: "Lifetime", - type: "number", - unit: "s", - propertyID: "lifetime", - }, { label: "User Data", type: "textarea", @@ -1410,7 +1511,7 @@ const GROUPS = [ { id: "edit", label: "Edit as JSON", className: "blue", onClick: newJSONEditor }, { id: "save", label: "Save User Data", className: "black", onClick: saveUserData } ], propertyID: "userData", - }, + } ] }, { @@ -1475,7 +1576,7 @@ const GROUPS = [ label: "Dynamic", type: "bool", propertyID: "dynamic", - }, + } ] }, { @@ -1551,26 +1652,37 @@ const GROUPS = [ unit: "m/s2", propertyID: "gravity", }, + { + label: "Acceleration", + type: "vec3", + vec3Type: "xyz", + subLabels: [ "x", "y", "z" ], + step: 0.1, + decimals: 4, + unit: "m/s2", + propertyID: "acceleration", + } ] }, ]; const GROUPS_PER_TYPE = { - None: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], - Shape: [ 'base', 'shape', 'spatial', 'behavior', 'collision', 'physics' ], - Text: [ 'base', 'text', 'spatial', 'behavior', 'collision', 'physics' ], - Zone: [ 'base', 'zone', 'spatial', 'behavior', 'physics' ], - Model: [ 'base', 'model', 'spatial', 'behavior', 'collision', 'physics' ], - Image: [ 'base', 'image', 'spatial', 'behavior', 'collision', 'physics' ], - Web: [ 'base', 'web', 'spatial', 'behavior', 'collision', 'physics' ], - Light: [ 'base', 'light', 'spatial', 'behavior', 'collision', 'physics' ], - Material: [ 'base', 'material', 'spatial', 'behavior' ], - ParticleEffect: [ 'base', 'particles', 'particles_emit', 'particles_size', 'particles_color', 'particles_alpha', - 'particles_acceleration', 'particles_spin', 'particles_constraints', 'spatial', 'behavior', 'physics' ], - PolyLine: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], - PolyVox: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], - Grid: [ 'base', 'grid', 'spatial', 'behavior', 'physics' ], - Multiple: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], + None: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Shape: [ 'base', 'shape', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Text: [ 'base', 'text', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Zone: [ 'base', 'zone', 'zone_key_light', 'zone_skybox', 'zone_ambient_light', 'zone_haze', + 'zone_bloom', 'zone_avatar_priority', 'spatial', 'behavior', 'scripts', 'physics' ], + Model: [ 'base', 'model', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Image: [ 'base', 'image', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Web: [ 'base', 'web', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Light: [ 'base', 'light', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Material: [ 'base', 'material', 'spatial', 'behavior', 'scripts', 'physics' ], + ParticleEffect: [ 'base', 'particles', 'particles_emit', 'particles_size', 'particles_color', + 'particles_behavior', 'particles_constraints', 'spatial', 'behavior', 'scripts', 'physics' ], + PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + PolyVox: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Grid: [ 'base', 'grid', 'spatial', 'behavior', 'scripts', 'physics' ], + Multiple: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], }; const EDITOR_TIMEOUT_DURATION = 1500; @@ -1637,7 +1749,7 @@ let selectedEntityIDs = new Set(); let currentSelections = []; let createAppTooltip = new CreateAppTooltip(); let currentSpaceMode = PROPERTY_SPACE_MODE.LOCAL; - +let zonesList = []; function createElementFromHTML(htmlString) { let elTemplate = document.createElement('template'); @@ -1654,7 +1766,7 @@ function isFlagSet(value, flag) { */ function getPropertyInputElement(propertyID) { - let property = properties[propertyID]; + let property = properties[propertyID]; switch (property.data.type) { case 'string': case 'number': @@ -1663,6 +1775,8 @@ function getPropertyInputElement(propertyID) { case 'textarea': case 'texture': return property.elInput; + case 'multipleZonesSelection': + return property.elInput; case 'number-draggable': return property.elNumber.elInput; case 'rect': @@ -1703,12 +1817,7 @@ function disableChildren(el, selector) { function enableProperties() { enableChildren(document.getElementById("properties-list"), ENABLE_DISABLE_SELECTOR); enableChildren(document, ".colpick"); - - let elLocked = getPropertyInputElement("locked"); - if (elLocked.checked === false) { - removeStaticUserData(); - removeStaticMaterialData(); - } + enableAllMultipleZoneSelector(); } function disableProperties() { @@ -1717,16 +1826,7 @@ function disableProperties() { for (let pickKey in colorPickers) { colorPickers[pickKey].colpickHide(); } - - let elLocked = getPropertyInputElement("locked"); - if (elLocked.checked === true) { - if ($('#property-userData-editor').css('display') === "block") { - showStaticUserData(); - } - if ($('#property-materialData-editor').css('display') === "block") { - showStaticMaterialData(); - } - } + disableAllMultipleZoneSelector(); } function showPropertyElement(propertyID, show) { @@ -1739,7 +1839,7 @@ function setPropertyVisibility(property, visible) { function resetProperties() { for (let propertyID in properties) { - let property = properties[propertyID]; + let property = properties[propertyID]; let propertyData = property.data; switch (propertyData.type) { @@ -1801,6 +1901,12 @@ function resetProperties() { setTextareaScrolling(property.elInput); break; } + case 'multipleZonesSelection': { + property.elInput.classList.remove('multi-diff'); + property.elInput.value = "[]"; + setZonesSelectionData(property.elInput, false); + break; + } case 'icon': { property.elSpan.style.display = "none"; break; @@ -1816,7 +1922,7 @@ function resetProperties() { break; } } - + let showPropertyRules = properties[propertyID].showPropertyRules; if (showPropertyRules !== undefined) { for (let propertyToHide in showPropertyRules) { @@ -1838,9 +1944,15 @@ function resetServerScriptStatus() { function showGroupsForType(type) { if (type === "Box" || type === "Sphere") { showGroupsForTypes(["Shape"]); + showOnTheSamePage(["Shape"]); return; } + if (type === "None") { + showGroupsForTypes(["None"]); + return; + } showGroupsForTypes([type]); + showOnTheSamePage([type]); } function getGroupsForTypes(types) { @@ -1854,9 +1966,15 @@ function getGroupsForTypes(types) { function showGroupsForTypes(types) { Object.entries(elGroups).forEach(([groupKey, elGroup]) => { if (types.map(type => GROUPS_PER_TYPE[type].includes(groupKey)).every(function (hasGroup) { return hasGroup; })) { - elGroup.style.display = "block"; + elGroup.style.display = "none"; + if (types !== "None") { + document.getElementById("tab-" + groupKey).style.display = "block"; + } else { + document.getElementById("tab-" + groupKey).style.display = "none"; + } } else { elGroup.style.display = "none"; + document.getElementById("tab-" + groupKey).style.display = "none"; } }); } @@ -2253,7 +2371,7 @@ function updateCheckedSubProperty(propertyName, propertyMultiValue, subPropertyE * PROPERTY ELEMENT CREATION FUNCTIONS */ -function createStringProperty(property, elProperty) { +function createStringProperty(property, elProperty) { let elementID = property.elementID; let propertyData = property.data; @@ -2266,12 +2384,12 @@ function createStringProperty(property, elProperty) { ${propertyData.readOnly ? 'readonly' : ''}/> `); - + elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); if (propertyData.onChange !== undefined) { elInput.addEventListener('change', propertyData.onChange); } - + let elMultiDiff = document.createElement('span'); elMultiDiff.className = "multi-diff"; @@ -2282,7 +2400,7 @@ function createStringProperty(property, elProperty) { if (propertyData.buttons !== undefined) { addButtons(elProperty, elementID, propertyData.buttons, false); } - + return elInput; } @@ -2290,9 +2408,9 @@ function createBoolProperty(property, elProperty) { let propertyName = property.name; let elementID = property.elementID; let propertyData = property.data; - + elProperty.className = "checkbox"; - + if (propertyData.glyph !== undefined) { let elSpan = document.createElement('span'); elSpan.innerHTML = propertyData.glyph; @@ -2521,7 +2639,7 @@ function createVec3Property(property, elProperty) { let propertyData = property.data; elProperty.className = propertyData.vec3Type + " fstuple"; - + let elNumberX = createTupleNumberInput(property, propertyData.subLabels[VECTOR_ELEMENTS.X_NUMBER]); let elNumberY = createTupleNumberInput(property, propertyData.subLabels[VECTOR_ELEMENTS.Y_NUMBER]); let elNumberZ = createTupleNumberInput(property, propertyData.subLabels[VECTOR_ELEMENTS.Z_NUMBER]); @@ -2536,7 +2654,7 @@ function createVec3Property(property, elProperty) { elNumberX.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'x')); elNumberY.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'y')); elNumberZ.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'z')); - + let elResult = []; elResult[VECTOR_ELEMENTS.X_NUMBER] = elNumberX; elResult[VECTOR_ELEMENTS.Y_NUMBER] = elNumberY; @@ -2544,11 +2662,11 @@ function createVec3Property(property, elProperty) { return elResult; } -function createVec2Property(property, elProperty) { +function createVec2Property(property, elProperty) { let propertyData = property.data; elProperty.className = propertyData.vec2Type + " fstuple"; - + let elTuple = document.createElement('div'); elTuple.className = "tuple"; @@ -2585,19 +2703,19 @@ function createColorProperty(property, elProperty) { let propertyName = property.name; let elementID = property.elementID; let propertyData = property.data; - + elProperty.className += " rgb fstuple"; - + let elColorPicker = document.createElement('div'); elColorPicker.className = "color-picker"; elColorPicker.setAttribute("id", elementID); - + let elTuple = document.createElement('div'); elTuple.className = "tuple"; - + elProperty.appendChild(elColorPicker); elProperty.appendChild(elTuple); - + if (propertyData.min === undefined) { propertyData.min = COLOR_MIN; } @@ -2607,19 +2725,19 @@ function createColorProperty(property, elProperty) { if (propertyData.step === undefined) { propertyData.step = COLOR_STEP; } - + let elNumberR = createTupleNumberInput(property, "red"); let elNumberG = createTupleNumberInput(property, "green"); let elNumberB = createTupleNumberInput(property, "blue"); elTuple.appendChild(elNumberR.elDiv); elTuple.appendChild(elNumberG.elDiv); elTuple.appendChild(elNumberB.elDiv); - + let valueChangeFunction = createEmitColorPropertyUpdateFunction(property); elNumberR.setValueChangeFunction(valueChangeFunction); elNumberG.setValueChangeFunction(valueChangeFunction); elNumberB.setValueChangeFunction(valueChangeFunction); - + let colorPickerID = "#" + elementID; colorPickers[colorPickerID] = $(colorPickerID).colpick({ colorScheme: 'dark', @@ -2648,7 +2766,7 @@ function createColorProperty(property, elProperty) { } } }); - + let elResult = []; elResult[COLOR_ELEMENTS.COLOR_PICKER] = elColorPicker; elResult[COLOR_ELEMENTS.RED_NUMBER] = elNumberR; @@ -2673,26 +2791,26 @@ function createDropdownProperty(property, propertyID, elProperty) { option.text = propertyData.options[optionKey]; elInput.add(option); } - + elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); elProperty.appendChild(elInput); - + return elInput; } -function createTextareaProperty(property, elProperty) { +function createTextareaProperty(property, elProperty) { let elementID = property.elementID; let propertyData = property.data; - + elProperty.className = "textarea"; - + let elInput = document.createElement('textarea'); elInput.setAttribute("id", elementID); if (propertyData.readOnly) { elInput.readOnly = true; - } - + } + elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); let elMultiDiff = document.createElement('span'); @@ -2700,42 +2818,42 @@ function createTextareaProperty(property, elProperty) { elProperty.appendChild(elInput); elProperty.appendChild(elMultiDiff); - + if (propertyData.buttons !== undefined) { addButtons(elProperty, elementID, propertyData.buttons, true); } - + return elInput; } -function createIconProperty(property, elProperty) { +function createIconProperty(property, elProperty) { let elementID = property.elementID; elProperty.className = "value"; - + let elSpan = document.createElement('span'); elSpan.setAttribute("id", elementID + "-icon"); elSpan.className = 'icon'; elProperty.appendChild(elSpan); - + return elSpan; } -function createTextureProperty(property, elProperty) { +function createTextureProperty(property, elProperty) { let elementID = property.elementID; - + elProperty.className = "texture"; - + let elDiv = document.createElement("div"); let elImage = document.createElement("img"); elDiv.className = "texture-image no-texture"; elDiv.appendChild(elImage); - + let elInput = document.createElement('input'); elInput.setAttribute("id", elementID); elInput.setAttribute("type", "text"); - + let imageLoad = function(url) { elDiv.style.display = null; if (url.slice(0, 5).toLowerCase() === "atp:/") { @@ -2772,7 +2890,7 @@ function createTextureProperty(property, elProperty) { elMultiDiff.className = "multi-diff"; elProperty.appendChild(elMultiDiff); elProperty.appendChild(elDiv); - + let elResult = []; elResult[TEXTURE_ELEMENTS.IMAGE] = elImage; elResult[TEXTURE_ELEMENTS.TEXT_INPUT] = elInput; @@ -2788,23 +2906,23 @@ function createButtonsProperty(property, elProperty) { if (propertyData.buttons !== undefined) { addButtons(elProperty, elementID, propertyData.buttons, false); } - + return elProperty; } function createDynamicMultiselectProperty(property, elProperty) { let elementID = property.elementID; let propertyData = property.data; - + elProperty.className = "dynamic-multiselect"; - + let elDivOptions = document.createElement('div'); elDivOptions.setAttribute("id", elementID + "-options"); elDivOptions.style = "overflow-y:scroll;max-height:160px;"; - + let elDivButtons = document.createElement('div'); elDivButtons.setAttribute("id", elDivOptions.getAttribute("id") + "-buttons"); - + let elLabel = document.createElement('label'); elLabel.innerText = "No Options"; elDivOptions.appendChild(elLabel); @@ -2812,10 +2930,10 @@ function createDynamicMultiselectProperty(property, elProperty) { let buttons = [ { id: "selectAll", label: "Select All", className: "black", onClick: selectAllMaterialTarget }, { id: "clearAll", label: "Clear All", className: "black", onClick: clearAllMaterialTarget } ]; addButtons(elDivButtons, elementID, buttons, false); - + elProperty.appendChild(elDivOptions); elProperty.appendChild(elDivButtons); - + return elDivOptions; } @@ -2833,13 +2951,13 @@ function createTupleNumberInput(property, subLabel) { let propertyElementID = property.elementID; let propertyData = property.data; let elementID = propertyElementID + "-" + subLabel.toLowerCase(); - + let elLabel = document.createElement('label'); elLabel.className = "sublabel " + subLabel; elLabel.innerText = subLabel[0].toUpperCase() + subLabel.slice(1); elLabel.setAttribute("for", elementID); elLabel.style.visibility = "visible"; - + let dragStartFunction = createDragStartFunction(property); let dragEndFunction = createDragEndFunction(property); let elDraggableNumber = new DraggableNumber(propertyData.min, propertyData.max, propertyData.step, @@ -2847,14 +2965,14 @@ function createTupleNumberInput(property, subLabel) { elDraggableNumber.elInput.setAttribute("id", elementID); elDraggableNumber.elDiv.className += " fstuple"; elDraggableNumber.elDiv.insertBefore(elLabel, elDraggableNumber.elLeftArrow); - + return elDraggableNumber; } function addButtons(elProperty, propertyID, buttons, newRow) { let elDiv = document.createElement('div'); elDiv.className = "row"; - + buttons.forEach(function(button) { let elButton = document.createElement('input'); elButton.className = button.className; @@ -2876,7 +2994,7 @@ function addButtons(elProperty, propertyID, buttons, newRow) { } function createProperty(propertyData, propertyElementID, propertyName, propertyID, elProperty) { - let property = { + let property = { data: propertyData, elementID: propertyElementID, name: propertyName, @@ -2938,6 +3056,10 @@ function createProperty(propertyData, propertyElementID, propertyName, propertyI property.elInput = createTextareaProperty(property, elProperty); break; } + case 'multipleZonesSelection': { + property.elInput = createZonesSelection(property, elProperty); + break; + } case 'icon': { property.elSpan = createIconProperty(property, elProperty); break; @@ -3167,19 +3289,6 @@ function hideUserDataSaved() { $('#property-userData-saved').hide(); } -function showStaticUserData() { - if (editor !== null) { - let $propertyUserDataStatic = $('#property-userData-static'); - $propertyUserDataStatic.show(); - $propertyUserDataStatic.css('height', $('#property-userData-editor').height()); - $propertyUserDataStatic.text(editor.getText()); - } -} - -function removeStaticUserData() { - $('#property-userData-static').hide(); -} - function setEditorJSON(json) { editor.set(json); if (editor.hasOwnProperty('expandAll')) { @@ -3332,19 +3441,6 @@ function hideMaterialDataSaved() { $('#property-materialData-saved').hide(); } -function showStaticMaterialData() { - if (materialEditor !== null) { - let $propertyMaterialDataStatic = $('#property-materialData-static'); - $propertyMaterialDataStatic.show(); - $propertyMaterialDataStatic.css('height', $('#property-materialData-editor').height()); - $propertyMaterialDataStatic.text(materialEditor.getText()); - } -} - -function removeStaticMaterialData() { - $('#property-materialData-static').hide(); -} - function setMaterialEditorJSON(json) { materialEditor.set(json); if (materialEditor.hasOwnProperty('expandAll')) { @@ -3456,6 +3552,175 @@ function setTextareaScrolling(element) { element.setAttribute("scrolling", isScrolling ? "true" : "false"); } +/** + * ZONE SELECTOR FUNCTIONS + */ + +function enableAllMultipleZoneSelector() { + let allMultiZoneSelectors = document.querySelectorAll(".hiddenMultiZonesSelection"); + let i, propId; + for (i = 0; i < allMultiZoneSelectors.length; i++) { + propId = allMultiZoneSelectors[i].id; + displaySelectedZones(propId, true); + } +} + +function disableAllMultipleZoneSelector() { + let allMultiZoneSelectors = document.querySelectorAll(".hiddenMultiZonesSelection"); + let i, propId; + for (i = 0; i < allMultiZoneSelectors.length; i++) { + propId = allMultiZoneSelectors[i].id; + displaySelectedZones(propId, false); + } +} + +function requestZoneList() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "zoneListRequest" + })); +} + +function addZoneToZonesSelection(propertyId) { + let hiddenField = document.getElementById(propertyId); + if (JSON.stringify(hiddenField.value) === '"undefined"') { + hiddenField.value = "[]"; + } + let selectedZones = JSON.parse(hiddenField.value); + let zoneToAdd = document.getElementById("zones-select-" + propertyId).value; + if (!selectedZones.includes(zoneToAdd)) { + selectedZones.push(zoneToAdd); + } + hiddenField.value = JSON.stringify(selectedZones); + displaySelectedZones(propertyId, true); + let propertyName = propertyId.replace("property-", ""); + updateProperty(propertyName, selectedZones, false); +} + +function removeZoneFromZonesSelection(propertyId, zoneId) { + let hiddenField = document.getElementById(propertyId); + if (JSON.stringify(hiddenField.value) === '"undefined"') { + hiddenField.value = "[]"; + } + let selectedZones = JSON.parse(hiddenField.value); + let index = selectedZones.indexOf(zoneId); + if (index > -1) { + selectedZones.splice(index, 1); + } + hiddenField.value = JSON.stringify(selectedZones); + displaySelectedZones(propertyId, true); + let propertyName = propertyId.replace("property-", ""); + updateProperty(propertyName, selectedZones, false); +} + +function displaySelectedZones(propertyId, isEditable) { + let i,j, name, listedZoneInner, hiddenData, isMultiple; + hiddenData = document.getElementById(propertyId).value; + if (JSON.stringify(hiddenData) === '"undefined"') { + isMultiple = true; + hiddenData = "[]"; + } else { + isMultiple = false; + } + let selectedZones = JSON.parse(hiddenData); + listedZoneInner = ""; + if (selectedZones.length === 0) { + if (!isMultiple) { + listedZoneInner += ""; + } else { + listedZoneInner += ""; + } + } else { + for (i = 0; i < selectedZones.length; i++) { + name = "{ERROR: NOT FOUND}"; + for (j = 0; j < zonesList.length; j++) { + if (selectedZones[i] === zonesList[j].id) { + if (zonesList[j].name !== "") { + name = zonesList[j].name; + } else { + name = zonesList[j].id; + } + break; + } + } + if (isEditable) { + listedZoneInner += ""; + } else { + listedZoneInner += ""; + } + } + } + listedZoneInner += "
  
[ WARNING: Any changes will apply to all. ] 
" + name + ""; + listedZoneInner += "
" + name + " 
"; + document.getElementById("selected-zones-" + propertyId).innerHTML = listedZoneInner; + if (isEditable) { + document.getElementById("multiZoneSelTools-" + propertyId).style.display = "block"; + } else { + document.getElementById("multiZoneSelTools-" + propertyId).style.display = "none"; + } +} + +function createZonesSelection(property, elProperty) { + let elementID = property.elementID; + requestZoneList(); + elProperty.className = "multipleZonesSelection"; + let elInput = document.createElement('input'); + elInput.setAttribute("id", elementID); + elInput.setAttribute("type", "hidden"); + elInput.className = "hiddenMultiZonesSelection"; + + let elZonesSelector = document.createElement('div'); + elZonesSelector.setAttribute("id", "zones-selector-" + elementID); + + let elMultiDiff = document.createElement('span'); + elMultiDiff.className = "multi-diff"; + + elProperty.appendChild(elInput); + elProperty.appendChild(elZonesSelector); + elProperty.appendChild(elMultiDiff); + + return elInput; +} + +function setZonesSelectionData(element, isEditable) { + let zoneSelectorContainer = document.getElementById("zones-selector-" + element.id); + let zoneSelector = "
 "; + zoneSelector += "
"; + zoneSelector += "
"; + zoneSelectorContainer.innerHTML = zoneSelector; + displaySelectedZones(element.id, isEditable); +} + +function updateAllZoneSelect() { + let allZoneSelects = document.querySelectorAll(".zoneSelect"); + let i, j, name, propId; + for (i = 0; i < allZoneSelects.length; i++) { + allZoneSelects[i].options.length = 0; + for (j = 0; j < zonesList.length; j++) { + if (zonesList[j].name === "") { + name = zonesList[j].id; + } else { + name = zonesList[j].name; + } + allZoneSelects[i].options[j] = new Option(name, zonesList[j].id, false , false); + } + propId = allZoneSelects[i].id.replace("zones-select-", ""); + if (document.getElementById("multiZoneSelTools-" + propId).style.display === "block") { + displaySelectedZones(propId, true); + } else { + displaySelectedZones(propId, false); + } + } +} /** * MATERIAL TARGET FUNCTIONS @@ -3467,15 +3732,15 @@ function requestMaterialTarget() { entityID: getFirstSelectedID(), })); } - + function setMaterialTargetData(materialTargetData) { let elDivOptions = getPropertyInputElement("parentMaterialName"); resetDynamicMultiselectProperty(elDivOptions); - + if (materialTargetData === undefined) { return; } - + elDivOptions.firstChild.style.display = "none"; // hide "No Options" text elDivOptions.parentNode.lastChild.style.display = null; // show Select/Clear all buttons @@ -3483,7 +3748,7 @@ function setMaterialTargetData(materialTargetData) { for (let i = 0; i < numMeshes; ++i) { addMaterialTarget(elDivOptions, i, false); } - + let materialNames = materialTargetData.materialNames; let materialNamesAdded = []; for (let i = 0; i < materialNames.length; ++i) { @@ -3493,7 +3758,7 @@ function setMaterialTargetData(materialTargetData) { materialNamesAdded.push(materialName); } } - + materialTargetPropertyUpdate(elDivOptions.propertyValue); } @@ -3501,12 +3766,12 @@ function addMaterialTarget(elDivOptions, targetID, isMaterialName) { let elementID = elDivOptions.getAttribute("id"); elementID += isMaterialName ? "-material-" : "-mesh-"; elementID += targetID; - + let elDiv = document.createElement('div'); elDiv.className = "materialTargetDiv"; elDiv.onclick = onToggleMaterialTarget; elDivOptions.appendChild(elDiv); - + let elInput = document.createElement('input'); elInput.className = "materialTargetInput"; elInput.setAttribute("type", "checkbox"); @@ -3514,12 +3779,12 @@ function addMaterialTarget(elDivOptions, targetID, isMaterialName) { elInput.setAttribute("targetID", targetID); elInput.setAttribute("isMaterialName", isMaterialName); elDiv.appendChild(elInput); - + let elLabel = document.createElement('label'); elLabel.setAttribute("for", elementID); elLabel.innerText = isMaterialName ? "Material " + targetID : "Mesh Index " + targetID; elDiv.appendChild(elLabel); - + return elDiv; } @@ -3552,7 +3817,7 @@ function clearAllMaterialTarget() { function sendMaterialTargetProperty() { let elDivOptions = getPropertyInputElement("parentMaterialName"); let elInputs = elDivOptions.getElementsByClassName("materialTargetInput"); - + let materialTargetList = []; for (let i = 0; i < elInputs.length; ++i) { let elInput = elInputs[i]; @@ -3565,26 +3830,26 @@ function sendMaterialTargetProperty() { } } } - + let propertyValue = materialTargetList.join(","); if (propertyValue.length > 1) { propertyValue = "[" + propertyValue + "]"; } - + updateProperty("parentMaterialName", propertyValue, false); } function materialTargetPropertyUpdate(propertyValue) { let elDivOptions = getPropertyInputElement("parentMaterialName"); let elInputs = elDivOptions.getElementsByClassName("materialTargetInput"); - + if (propertyValue.startsWith('[')) { propertyValue = propertyValue.substring(1, propertyValue.length); } if (propertyValue.endsWith(']')) { propertyValue = propertyValue.substring(0, propertyValue.length - 1); } - + let materialTargets = propertyValue.split(","); for (let i = 0; i < elInputs.length; ++i) { let elInput = elInputs[i]; @@ -3595,7 +3860,7 @@ function materialTargetPropertyUpdate(propertyValue) { } elInput.checked = materialTargets.indexOf(materialTargetName) >= 0; } - + elDivOptions.propertyValue = propertyValue; } @@ -3629,7 +3894,9 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { selectedEntityIDs = new Set(selections.map(selection => selection.id)); const multipleSelections = currentSelections.length > 1; const hasSelectedEntityChanged = !areSetsEqual(selectedEntityIDs, previouslySelectedEntityIDs); - + + requestZoneList(); + if (selections.length === 0) { deleteJSONEditor(); deleteJSONMaterialEditor(); @@ -3674,6 +3941,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { const shownGroups = getGroupsForTypes(entityTypes); showGroupsForTypes(entityTypes); + showOnTheSamePage(entityTypes); const lockedMultiValue = getMultiplePropertyValue('locked'); @@ -3683,7 +3951,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { } else { enableProperties(); disableSaveUserDataButton(); - disableSaveMaterialDataButton() + disableSaveMaterialDataButton(); } const certificateIDMultiValue = getMultiplePropertyValue('certificateID'); @@ -3839,6 +4107,15 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { setTextareaScrolling(property.elInput); break; } + case 'multipleZonesSelection': { + property.elInput.value = JSON.stringify(propertyValue); + if (lockedMultiValue.isMultiDiffValue || lockedMultiValue.value) { + setZonesSelectionData(property.elInput, false); + } else { + setZonesSelectionData(property.elInput, true); + } + break; + } case 'icon': { property.elSpan.innerHTML = propertyData.icons[propertyValue]; property.elSpan.style.display = "inline-block"; @@ -3884,7 +4161,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { } } - if (json !== null) { + if (json !== null && !lockedMultiValue.isMultiDiffValue && !lockedMultiValue.value) { if (editor === null) { createJSONEditor(); } @@ -3916,7 +4193,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { } } - if (materialJson !== null) { + if (materialJson !== null && !lockedMultiValue.isMultiDiffValue && !lockedMultiValue.value) { if (materialEditor === null) { createJSONMaterialEditor(); } @@ -3950,44 +4227,35 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { function loaded() { openEventBridge(function() { - let elPropertiesList = document.getElementById("properties-list"); - + let elPropertiesList = document.getElementById("properties-pages"); + let elTabs = document.getElementById("tabs"); + GROUPS.forEach(function(group) { let elGroup; - if (group.addToGroup !== undefined) { - let fieldset = document.getElementById("properties-" + group.addToGroup); - elGroup = document.createElement('div'); - fieldset.appendChild(elGroup); - } else { - elGroup = document.createElement('div'); - elGroup.className = 'section ' + (group.isMinor ? "minor" : "major"); - elGroup.setAttribute("id", "properties-" + group.id); - elPropertiesList.appendChild(elGroup); - } + + elGroup = document.createElement('div'); + elGroup.className = 'section ' + "major"; + elGroup.setAttribute("id", "properties-" + group.id); + elPropertiesList.appendChild(elGroup); if (group.label !== undefined) { let elLegend = document.createElement('div'); - elLegend.className = "section-header"; - - elLegend.appendChild(createElementFromHTML(`
${group.label}
`)); - - let elSpan = document.createElement('span'); - elSpan.className = "collapse-icon"; - elSpan.innerText = "M"; - elLegend.appendChild(elSpan); + elLegend.className = "tab-section-header"; + elLegend.appendChild(createElementFromHTML(`
${group.label}
`)); elGroup.appendChild(elLegend); + elTabs.appendChild(createElementFromHTML('')); } - + group.properties.forEach(function(propertyData) { let propertyType = propertyData.type; - let propertyID = propertyData.propertyID; + let propertyID = propertyData.propertyID; let propertyName = propertyData.propertyName !== undefined ? propertyData.propertyName : propertyID; let propertySpaceMode = propertyData.spaceMode !== undefined ? propertyData.spaceMode : PROPERTY_SPACE_MODE.ALL; let propertyElementID = "property-" + propertyID; propertyElementID = propertyElementID.replace('.', '-'); - + let elContainer, elLabel; - + if (propertyData.replaceID === undefined) { // Create subheader, or create new property and append it. if (propertyType === "sub-header") { @@ -4077,15 +4345,15 @@ function loaded() { property.elContainer = elContainer; property.spaceMode = propertySpaceMode; property.group_id = group.id; - + if (property.type !== 'placeholder') { properties[propertyID] = property; - } + } if (propertyData.type === 'number' || propertyData.type === 'number-draggable' || propertyData.type === 'vec2' || propertyData.type === 'vec3' || propertyData.type === 'rect') { propertyRangeRequests.push(propertyID); } - + let showPropertyRule = propertyData.showPropertyRule; if (showPropertyRule !== undefined) { let dependentProperty = Object.keys(showPropertyRule)[0]; @@ -4100,15 +4368,12 @@ function loaded() { } } }); - + elGroups[group.id] = elGroup; }); - let minorSections = document.querySelectorAll(".section.minor"); - minorSections[minorSections.length - 1].className += " last"; - updateVisibleSpaceModeProperties(); - + if (window.EventBridge !== undefined) { EventBridge.scriptEventReceived.connect(function(data) { data = JSON.parse(data); @@ -4180,6 +4445,9 @@ function loaded() { if (data.entityID === getFirstSelectedID()) { setMaterialTargetData(data.materialTargetData); } + } else if (data.type === 'zoneListRequest') { + zonesList = data.zones; + updateAllZoneSelect(); } }); @@ -4187,7 +4455,7 @@ function loaded() { EventBridge.emitWebEvent(JSON.stringify({ type: 'tooltipsRequest' })); EventBridge.emitWebEvent(JSON.stringify({ type: 'propertyRangeRequest', properties: propertyRangeRequests })); } - + // Server Script Status let elServerScriptStatusOuter = document.getElementById('div-property-serverScriptStatus'); let elServerScriptStatusContainer = document.getElementById('div-property-serverScriptStatus').childNodes[1]; @@ -4196,7 +4464,7 @@ function loaded() { let elServerScriptStatus = document.createElement('div'); elServerScriptStatus.setAttribute("id", serverScriptStatusElementID); elServerScriptStatusContainer.appendChild(elServerScriptStatus); - + // Server Script Error let elServerScripts = getPropertyInputElement("serverScripts"); let elDiv = document.createElement('div'); @@ -4206,18 +4474,16 @@ function loaded() { elServerScriptError.setAttribute("id", serverScriptErrorElementID); elDiv.appendChild(elServerScriptError); elServerScriptStatusContainer.appendChild(elDiv); - + let elScript = getPropertyInputElement("script"); elScript.parentNode.className = "url refresh"; elServerScripts.parentNode.className = "url refresh"; - + // User Data let userDataProperty = properties["userData"]; let elUserData = userDataProperty.elInput; let userDataElementID = userDataProperty.elementID; elDiv = elUserData.parentNode; - let elStaticUserData = document.createElement('div'); - elStaticUserData.setAttribute("id", userDataElementID + "-static"); let elUserDataEditor = document.createElement('div'); elUserDataEditor.setAttribute("id", userDataElementID + "-editor"); let elUserDataEditorStatus = document.createElement('div'); @@ -4226,17 +4492,14 @@ function loaded() { elUserDataSaved.setAttribute("id", userDataElementID + "-saved"); elUserDataSaved.innerText = "Saved!"; elDiv.childNodes[JSON_EDITOR_ROW_DIV_INDEX].appendChild(elUserDataSaved); - elDiv.insertBefore(elStaticUserData, elUserData); elDiv.insertBefore(elUserDataEditor, elUserData); elDiv.insertBefore(elUserDataEditorStatus, elUserData); - + // Material Data let materialDataProperty = properties["materialData"]; let elMaterialData = materialDataProperty.elInput; let materialDataElementID = materialDataProperty.elementID; elDiv = elMaterialData.parentNode; - let elStaticMaterialData = document.createElement('div'); - elStaticMaterialData.setAttribute("id", materialDataElementID + "-static"); let elMaterialDataEditor = document.createElement('div'); elMaterialDataEditor.setAttribute("id", materialDataElementID + "-editor"); let elMaterialDataEditorStatus = document.createElement('div'); @@ -4245,26 +4508,9 @@ function loaded() { elMaterialDataSaved.setAttribute("id", materialDataElementID + "-saved"); elMaterialDataSaved.innerText = "Saved!"; elDiv.childNodes[JSON_EDITOR_ROW_DIV_INDEX].appendChild(elMaterialDataSaved); - elDiv.insertBefore(elStaticMaterialData, elMaterialData); elDiv.insertBefore(elMaterialDataEditor, elMaterialData); elDiv.insertBefore(elMaterialDataEditorStatus, elMaterialData); - - // Collapsible sections - let elCollapsible = document.getElementsByClassName("collapse-icon"); - let toggleCollapsedEvent = function(event) { - let element = this.parentNode.parentNode; - let isCollapsed = element.dataset.collapsed !== "true"; - element.dataset.collapsed = isCollapsed ? "true" : false; - element.setAttribute("collapsed", isCollapsed ? "true" : "false"); - this.textContent = isCollapsed ? "L" : "M"; - }; - - for (let collapseIndex = 0, numCollapsibles = elCollapsible.length; collapseIndex < numCollapsibles; ++collapseIndex) { - let curCollapsibleElement = elCollapsible[collapseIndex]; - curCollapsibleElement.addEventListener("click", toggleCollapsedEvent, true); - } - // Textarea scrollbars let elTextareas = document.getElementsByTagName("TEXTAREA"); @@ -4281,7 +4527,7 @@ function loaded() { event; mouseup is a partial stand-in but doesn't handle resizing if mouse moves outside textarea rectangle. */ curTextAreaElement.addEventListener("mouseup", textareaOnChangeEvent, false); } - + // Dropdowns // For each dropdown the following replacement is created in place of the original dropdown... // Structure created: @@ -4293,7 +4539,7 @@ function loaded() { //
  • ...
  • // // - // + // let elDropdowns = document.getElementsByTagName("select"); for (let dropDownIndex = 0; dropDownIndex < elDropdowns.length; ++dropDownIndex) { let elDropdown = elDropdowns[dropDownIndex]; @@ -4342,7 +4588,7 @@ function loaded() { li.addEventListener("click", setDropdownValue); ul.appendChild(li); } - + let propertyID = elDropdown.getAttribute("propertyID"); let property = properties[propertyID]; property.elInput = dt; @@ -4403,14 +4649,14 @@ function loaded() { } })); }, false); - + window.onblur = function() { // Fake a change event let ev = document.createEvent("HTMLEvents"); ev.initEvent("change", true, true); document.activeElement.dispatchEvent(ev); }; - + // For input and textarea elements, select all of the text on focus let els = document.querySelectorAll("input, textarea"); for (let i = 0; i < els.length; ++i) { @@ -4418,12 +4664,14 @@ function loaded() { e.target.select(); }; } - - bindAllNonJSONEditorElements(); + + bindAllNonJSONEditorElements(); showGroupsForType("None"); + showPage("base"); resetProperties(); - disableProperties(); + disableProperties(); + }); augmentSpinButtons(); @@ -4438,3 +4686,30 @@ function loaded() { EventBridge.emitWebEvent(JSON.stringify({ type: 'propertiesPageReady' })); }, 1000); } + +function showOnTheSamePage(entityType) { + let numberOfTypes = entityType.length; + let matchingType = 0; + for (let i = 0; i < numberOfTypes; i++) { + if (GROUPS_PER_TYPE[entityType[i]].includes(currentTab)) { + matchingType = matchingType + 1; + } + } + if (matchingType !== numberOfTypes) { + currentTab = "base"; + } + showPage(currentTab); +} + +function showPage(id) { + currentTab = id; + Object.entries(elGroups).forEach(([groupKey, elGroup]) => { + if (groupKey === id) { + elGroup.style.display = "block"; + document.getElementById("tab-" + groupKey).style.backgroundColor = "#2E2E2E"; + } else { + elGroup.style.display = "none"; + document.getElementById("tab-" + groupKey).style.backgroundColor = "#404040"; + } + }); +} diff --git a/scripts/system/create/entityProperties/html/tabs/base.png b/scripts/system/create/entityProperties/html/tabs/base.png new file mode 100644 index 0000000000..9f656abe27 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/base.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/behavior.png b/scripts/system/create/entityProperties/html/tabs/behavior.png new file mode 100644 index 0000000000..12662b8a1d Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/behavior.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/collision.png b/scripts/system/create/entityProperties/html/tabs/collision.png new file mode 100644 index 0000000000..c9bed39385 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/collision.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/grid.png b/scripts/system/create/entityProperties/html/tabs/grid.png new file mode 100644 index 0000000000..d9b8afb1ae Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/grid.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/image.png b/scripts/system/create/entityProperties/html/tabs/image.png new file mode 100644 index 0000000000..ebd03648f6 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/image.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/light.png b/scripts/system/create/entityProperties/html/tabs/light.png new file mode 100644 index 0000000000..bed097d54e Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/light.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/material.png b/scripts/system/create/entityProperties/html/tabs/material.png new file mode 100644 index 0000000000..458c6bad48 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/material.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/model.png b/scripts/system/create/entityProperties/html/tabs/model.png new file mode 100644 index 0000000000..79aa6b3830 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/model.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/particles.png b/scripts/system/create/entityProperties/html/tabs/particles.png new file mode 100644 index 0000000000..6a0d47cacb Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/particles.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/particles_alpha.png b/scripts/system/create/entityProperties/html/tabs/particles_alpha.png new file mode 100644 index 0000000000..8df2981f14 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/particles_alpha.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/particles_behavior.png b/scripts/system/create/entityProperties/html/tabs/particles_behavior.png new file mode 100644 index 0000000000..6be9f90638 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/particles_behavior.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/particles_color.png b/scripts/system/create/entityProperties/html/tabs/particles_color.png new file mode 100644 index 0000000000..ac66a902cf Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/particles_color.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/particles_constraints.png b/scripts/system/create/entityProperties/html/tabs/particles_constraints.png new file mode 100644 index 0000000000..9c783acc9b Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/particles_constraints.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/particles_emit.png b/scripts/system/create/entityProperties/html/tabs/particles_emit.png new file mode 100644 index 0000000000..223baa5d56 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/particles_emit.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/particles_size.png b/scripts/system/create/entityProperties/html/tabs/particles_size.png new file mode 100644 index 0000000000..b51fe65cdf Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/particles_size.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/physics.png b/scripts/system/create/entityProperties/html/tabs/physics.png new file mode 100644 index 0000000000..f0fc451d37 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/physics.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/scripts.png b/scripts/system/create/entityProperties/html/tabs/scripts.png new file mode 100644 index 0000000000..2249af165b Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/scripts.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/shape.png b/scripts/system/create/entityProperties/html/tabs/shape.png new file mode 100644 index 0000000000..5f3722caf7 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/shape.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/spatial.png b/scripts/system/create/entityProperties/html/tabs/spatial.png new file mode 100644 index 0000000000..a280d0e822 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/spatial.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/text.png b/scripts/system/create/entityProperties/html/tabs/text.png new file mode 100644 index 0000000000..405d8e4104 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/text.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/web.png b/scripts/system/create/entityProperties/html/tabs/web.png new file mode 100644 index 0000000000..c1fc573619 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/web.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/zone.png b/scripts/system/create/entityProperties/html/tabs/zone.png new file mode 100644 index 0000000000..276ba26799 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/zone.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/zone_ambient_light.png b/scripts/system/create/entityProperties/html/tabs/zone_ambient_light.png new file mode 100644 index 0000000000..ff01b16aaf Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/zone_ambient_light.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/zone_avatar_priority.png b/scripts/system/create/entityProperties/html/tabs/zone_avatar_priority.png new file mode 100644 index 0000000000..e91111fb9b Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/zone_avatar_priority.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/zone_bloom.png b/scripts/system/create/entityProperties/html/tabs/zone_bloom.png new file mode 100644 index 0000000000..925654df81 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/zone_bloom.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/zone_haze.png b/scripts/system/create/entityProperties/html/tabs/zone_haze.png new file mode 100644 index 0000000000..0cf96692f8 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/zone_haze.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/zone_key_light.png b/scripts/system/create/entityProperties/html/tabs/zone_key_light.png new file mode 100644 index 0000000000..6527c65320 Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/zone_key_light.png differ diff --git a/scripts/system/create/entityProperties/html/tabs/zone_skybox.png b/scripts/system/create/entityProperties/html/tabs/zone_skybox.png new file mode 100644 index 0000000000..17697a817b Binary files /dev/null and b/scripts/system/create/entityProperties/html/tabs/zone_skybox.png differ diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 470e57ad6d..c72456d414 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -3,6 +3,7 @@ // // Created by Ryan Huffman on 13 Nov 2014 // 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 @@ -1794,3 +1795,28 @@ input[type=number].hide-spinner::-webkit-inner-spin-button { div.jsoneditor-menu a.jsoneditor-poweredBy { display: none; } +td.zoneItem { + width: 100%; +} + +select.zoneSelect { + clear: both; + cursor: pointer; + font-family: FiraSans-SemiBold; + font-size: 15px; + width: 90%; + height: 28px; + padding: 0 28px 0 12px; + color: #afafaf; + background: #575757; + position: relative; + display: inline; + border: 0px; + align-items: center; + outline: none; +} + +div.multiZoneSelToolbar { + padding: 0px; +} + diff --git a/scripts/system/html/css/img/add_icon.png b/scripts/system/html/css/img/add_icon.png new file mode 100644 index 0000000000..f60e5561f2 Binary files /dev/null and b/scripts/system/html/css/img/add_icon.png differ diff --git a/scripts/system/html/css/img/remove_icon.png b/scripts/system/html/css/img/remove_icon.png new file mode 100644 index 0000000000..7a34bd0304 Binary files /dev/null and b/scripts/system/html/css/img/remove_icon.png differ diff --git a/scripts/system/html/css/tabs.css b/scripts/system/html/css/tabs.css new file mode 100644 index 0000000000..b2d63b5652 --- /dev/null +++ b/scripts/system/html/css/tabs.css @@ -0,0 +1,77 @@ +/* +// tabs.css +// +// Created by Alezia Kurdis on 27 Feb 2020 +// Copyright 2020 Project Athena contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +*/ + +div.tabsContainer { + float: left; + width: 32px; + padding: 0px; +} + +.tabsContainer button { + padding: 4px; + text-align: center; + cursor: pointer; + transition: 0.4s; + font-size: 14px; + background-color: #404040; + border-color: #404040; + border-width: 1px 0px 1px 1px; + border-radius: 5px 0px 0px 5px; + outline: none; +} + +.tabsContainer button:hover { + background-color: #575757; +} + +.tabsContainer button.active { + background-color: #2E2E2E; +} + +div.labelTabHeader { + font-size: 20px; + font-weight: 700; + height: 40px; + color: #ffffff; +} + +div.tab-section-header { + width: 100%; + padding: 5px; +} + +table.tabsTableFrame { + width: 100%; + min-height: 352px; + display: block; +} + +tr.tabsTrFrame { + width: 100%; +} + +td.tabsFrame { + width: 32px; + vertical-align: top; + background-color: #575757; + padding: 0px; + border: 0px; +} + +td.tabsPropertiesFrame { + width: 100%; + vertical-align: top; + border: 0px; +} + +div.tabsPropertiesPage { + min-height: 352px; + display: block; +} diff --git a/tools/ci-scripts/upload_to_publish_server.py b/tools/ci-scripts/upload_to_publish_server.py new file mode 100644 index 0000000000..5e1a9b24f2 --- /dev/null +++ b/tools/ci-scripts/upload_to_publish_server.py @@ -0,0 +1,77 @@ +import os +import json +from hashlib import sha256 +import http.client +from http import HTTPStatus +import time +import struct +import random +import glob + +FILE_READ_BUFFER = 4096 + +path = os.path.join(os.getcwd(), os.environ['ARTIFACT_PATTERN']) +files = glob.glob(path, recursive=False) +uploading_files = [] +for archive_file in files: + file = open(archive_file, 'rb') + sha256_hash = sha256() + file.seek(0, 0) + for byte_block in iter(lambda: file.read(FILE_READ_BUFFER), b""): + sha256_hash.update(byte_block) + + checksum = sha256_hash.hexdigest() + + uploading_files.append({ + "filename": os.path.basename(archive_file), + "sha256_checksum": checksum, + "file_length": file.tell() + }) + file.close() + +print("BuildFileHashes: " + json.dumps(uploading_files)) + +file_contents = [] +file_sizes = [] + +for archiveFile in files: + file = open(archiveFile, 'rb') + file_data = file.read() + file_sizes.append(len(file_data)) + file_contents.append(file_data) + file.close() + +conn = http.client.HTTPSConnection("build-uploader.vircadia.com") + +context = json.loads(os.environ['GITHUB_CONTEXT']) + +owner_and_repository = context["repository"].split("/") +owner = owner_and_repository[0] +repository = owner_and_repository[1] + +headers = { + "owner": owner, + "repo": repository, + "commit_hash": context["event"]["pull_request"]["head"]["sha"], + "pull_number": context["event"]["number"], + "job_name": os.environ["JOB_NAME"], + "run_id": context["run_id"], + "file_sizes": ','.join(str(e) for e in file_sizes) +} + +concat_file_body = b''.join(file_contents) + +print("Total files size: " + str(len(concat_file_body))) + +conn.request("PUT", "/", body=concat_file_body, headers=headers) +response = conn.getresponse() + +EXIT_CODE_OK = 0 +EXIT_CODE_ERROR = 1 + +if (response.status == HTTPStatus.OK): + print("response: ", json.loads(response.read())) + exit(EXIT_CODE_OK) +else: + print(response.status, response.reason, response.read()) + exit(EXIT_CODE_ERROR) diff --git a/unpublishedScripts/marketplace/record/html/record.html b/unpublishedScripts/marketplace/record/html/record.html index 89392e6951..810238a580 100644 --- a/unpublishedScripts/marketplace/record/html/record.html +++ b/unpublishedScripts/marketplace/record/html/record.html @@ -3,6 +3,7 @@ // // Created by David Rowe on 5 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 @@ -41,9 +42,9 @@

    Setup Instructions

    In your sandbox domain:

      -
    • Right-click the High Fidelity Sandbox icon in your system tray and click “Settings”.
    • +
    • Right-click the Vircadia Sandbox icon in your system tray and click “Settings”.
    • In the “Scripts” section add a new row and paste in this script URL:
      - +
    • Set the number of recordings you’d like to run at a given time in the “Instances” slot.
    • Click “Save and restart”.
    • diff --git a/unpublishedScripts/marketplace/record/icon.svg b/unpublishedScripts/marketplace/record/icon.svg new file mode 100644 index 0000000000..06f8a3276f --- /dev/null +++ b/unpublishedScripts/marketplace/record/icon.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + +