6
.github/workflows/pr_build.yml
vendored
|
@ -14,7 +14,9 @@ env:
|
|||
RELEASE_TYPE: PR
|
||||
RELEASE_NUMBER: ${{ github.event.number }}
|
||||
VERSION_CODE: ${{ github.event.number }}
|
||||
|
||||
# Sentry Crash Reporting
|
||||
CMAKE_BACKTRACE_URL: ${{ secrets.MINIDUMP_TOKEN }}
|
||||
CMAKE_BACKTRACE_TOKEN: PR_${{ github.event.number }}_${{ github.sha }}
|
||||
|
||||
# OSX specific variables
|
||||
DEVELOPER_DIR: /Applications/Xcode_11.2.app/Contents/Developer
|
||||
|
@ -169,7 +171,7 @@ jobs:
|
|||
- name: Build for Android + Quest
|
||||
if: matrix.build_type == 'android'
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/project-athena
|
||||
working-directory: ${{runner.workspace}}/vircadia
|
||||
run: |
|
||||
echo "Pre-cache the vcpkg managed dependencies"
|
||||
$PYTHON_EXEC prebuild.py --build-root ${{runner.workspace}}/build --android interface
|
||||
|
|
|
@ -66,7 +66,7 @@ The above code to suppress modules is not necessary, but will speed up the build
|
|||
|
||||
### Clone the repository
|
||||
|
||||
`git clone https://github.com/kasenvr/project-athena.git`
|
||||
`git clone https://github.com/vircadia/vircadia.git`
|
||||
|
||||
## Building & Running
|
||||
|
||||
|
@ -119,4 +119,4 @@ Some things you can try if you want to do a clean build
|
|||
* In Android Studio, click _File > Invalidate Caches / Restart_ and select _Invalidate and Restart_
|
||||
|
||||
If you see lots of "couldn't acquire lock" errors,
|
||||
* Open Task Manager and close any running Clang / Gradle processes
|
||||
* Open Task Manager and close any running Clang / Gradle processes
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
# Build Linux
|
||||
|
||||
*Last Updated on April 11, 2020*
|
||||
*Last Updated on December 1, 2020*
|
||||
|
||||
Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Linux specific instructions are found in this file.
|
||||
|
||||
You can use the [Vircadia Builder](https://github.com/vircadia/vircadia-builder) to build on Linux more easily. Alternatively, you can follow the manual steps below.
|
||||
|
||||
## Ubuntu 16.04/18.04 specific build guide
|
||||
### Ubuntu 16.04 only
|
||||
Add the following line to *.bash_profile*
|
||||
|
@ -76,7 +78,7 @@ sudo apt-get install nodejs
|
|||
|
||||
Clone this repository:
|
||||
```bash
|
||||
git clone https://github.com/kasenvr/project-athena.git
|
||||
git clone https://github.com/vircadia/vircadia.git
|
||||
```
|
||||
|
||||
To compile a DEV version checkout the branch you need. To get a list of all tags:
|
||||
|
@ -86,7 +88,7 @@ git fetch -a
|
|||
|
||||
Then checkout the main branch with:
|
||||
```bash
|
||||
git checkout kasen/core
|
||||
git checkout master
|
||||
```
|
||||
|
||||
### Using a custom Qt build
|
||||
|
@ -103,7 +105,7 @@ Qt must be installed in `$HIFI_QT_BASE/$VIRCADIA_USE_QT_VERSION/qt5-install`.
|
|||
|
||||
Create the build directory:
|
||||
```bash
|
||||
cd project-athena
|
||||
cd vircadia
|
||||
mkdir build
|
||||
cd build
|
||||
```
|
||||
|
|
|
@ -107,7 +107,7 @@ Note: You can also run Interface by launching it from command line or File Explo
|
|||
For any problems after Step #6, first try this:
|
||||
* Delete your locally cloned copy of the Vircadia repository
|
||||
* Restart your computer
|
||||
* Redownload the [repository](https://github.com/kasenvr/project-athena)
|
||||
* Redownload the [repository](https://github.com/vircadia/vircadia)
|
||||
* Restart directions from Step #6
|
||||
|
||||
#### CMake gives you the same error message repeatedly after the build fails
|
||||
|
|
|
@ -41,6 +41,12 @@ endif()
|
|||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" "${EXTERNAL_BUILD_ASSETS}")
|
||||
MESSAGE(STATUS "EXTERNAL_BUILD_ASSETS: ${EXTERNAL_BUILD_ASSETS}")
|
||||
|
||||
set(GLES_OPTION "$ENV{USE_GLES}")
|
||||
|
||||
# Will affect VCPKG dependencies
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/_env/USE_GLES.txt" "${GLES_OPTION}")
|
||||
MESSAGE(STATUS "GLES_OPTION: ${GLES_OPTION}")
|
||||
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/macros/TargetPython.cmake")
|
||||
target_python()
|
||||
|
||||
|
@ -129,7 +135,6 @@ set(BUILD_TESTS_OPTION OFF)
|
|||
set(BUILD_MANUAL_TESTS_OPTION ${BUILD_TESTS_OPTION})
|
||||
set(BUILD_TOOLS_OPTION ON)
|
||||
set(BUILD_INSTALLER_OPTION ON)
|
||||
set(GLES_OPTION OFF)
|
||||
set(DISABLE_QML_OPTION OFF)
|
||||
set(DOWNLOAD_SERVERLESS_CONTENT_OPTION OFF)
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
The project embraces distributed development and if you'd like to help, it would be greatly appreciated. Just open a pull request with the revisions.
|
||||
|
||||
Contributing
|
||||
|
@ -6,7 +7,7 @@ Contributing
|
|||
2. Clone your fork of the repository locally
|
||||
|
||||
```
|
||||
git clone git://github.com/USERNAME/project-athena.git
|
||||
git clone git://github.com/USERNAME/vircadia.git
|
||||
```
|
||||
3. Create a new branch
|
||||
|
||||
|
@ -20,7 +21,7 @@ Contributing
|
|||
6. Update your branch
|
||||
|
||||
```
|
||||
git remote add upstream https://github.com/kasenvr/project-athena
|
||||
git remote add upstream https://github.com/vircadia/vircadia
|
||||
git pull upstream master
|
||||
```
|
||||
|
||||
|
@ -35,13 +36,22 @@ Contributing
|
|||
|
||||
*You can follow [GitHub's guide](https://help.github.com/articles/creating-a-pull-request) to find out how to create a pull request.*
|
||||
|
||||
Tips for Pull Requests
|
||||
===
|
||||
To make the QA process go as smoothly as possible.
|
||||
|
||||
1. Have a basic description in your pull request.
|
||||
2. Write a basic test plan if you are altering or adding features.
|
||||
3. If a new API is added, try to make sure that some level of basic documentation on how you can utilize it is included.
|
||||
4. If an added API or feature requires an external service, try to document or link to instructions on how to create a basic working setup.
|
||||
|
||||
Reporting Bugs
|
||||
===
|
||||
1. Always update to the latest code on master, we make many merges every day and it is possible the bug has already been fixed!
|
||||
2. Search [issues](https://github.com/kasenvr/project-athena/issues) to make sure that somebody has not already reported the same bug.
|
||||
3. [Add](https://github.com/kasenvr/project-athena/issues/new) your report to the issues list!
|
||||
2. Search [issues](https://github.com/vircadia/vircadia/issues) to make sure that somebody has not already reported the same bug.
|
||||
3. [Add](https://github.com/vircadia/vircadia/issues/new) your report to the issues list!
|
||||
|
||||
Requesting a Feature
|
||||
===
|
||||
1. Search [issues](https://github.com/kasenvr/project-athena/issues) to make sure that somebody has not already requested the same feature.
|
||||
2. [Add](https://github.com/kasenvr/project-athena/issues/new) your request to the issues list!
|
||||
1. Search [issues](https://github.com/vircadia/vircadia/issues) to make sure that somebody has not already requested the same feature.
|
||||
2. [Add](https://github.com/vircadia/vircadia/issues/new) your request to the issues list!
|
||||
|
|
16
README.md
|
@ -8,17 +8,17 @@ Vircadia is a 3D social software project seeking to incrementally bring about a
|
|||
|
||||
### Releases
|
||||
|
||||
[View Releases here](https://github.com/kasenvr/project-athena/releases/)
|
||||
[View Releases here](https://github.com/vircadia/vircadia/releases/)
|
||||
|
||||
### How to build the Interface
|
||||
|
||||
[For Windows](https://github.com/kasenvr/project-athena/blob/master/BUILD_WIN.md)
|
||||
[For Windows](https://github.com/vircadia/vircadia/blob/master/BUILD_WIN.md)
|
||||
|
||||
[For Mac](https://github.com/kasenvr/project-athena/blob/master/BUILD_OSX.md)
|
||||
[For Mac](https://github.com/vircadia/vircadia/blob/master/BUILD_OSX.md)
|
||||
|
||||
[For Linux](https://github.com/kasenvr/project-athena/blob/master/BUILD_LINUX.md)
|
||||
[For Linux](https://github.com/vircadia/vircadia/blob/master/BUILD_LINUX.md)
|
||||
|
||||
[For Linux - Vircadia Builder](https://github.com/kasenvr/vircadia-builder)
|
||||
[For Linux - Vircadia Builder](https://github.com/vircadia/vircadia-builder)
|
||||
|
||||
### How to deploy a Server
|
||||
|
||||
|
@ -26,13 +26,13 @@ Vircadia is a 3D social software project seeking to incrementally bring about a
|
|||
|
||||
### How to build a Server
|
||||
|
||||
[For Linux - Vircadia Builder](https://github.com/kasenvr/vircadia-builder)
|
||||
[For Linux - Vircadia Builder](https://github.com/vircadia/vircadia-builder)
|
||||
|
||||
### How to generate an Installer
|
||||
|
||||
[For Windows](https://github.com/kasenvr/project-athena/blob/master/INSTALL.md)
|
||||
[For Windows](https://github.com/vircadia/vircadia/blob/master/INSTALLER.md)
|
||||
|
||||
[For Linux - AppImage - Vircadia Builder](https://github.com/kasenvr/vircadia-builder/blob/master/README.md#building-appimages)
|
||||
[For Linux - AppImage - Vircadia Builder](https://github.com/vircadia/vircadia-builder/blob/master/README.md#building-appimages)
|
||||
|
||||
### Boot to Metaverse: The Goal
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ test -z "$STABLE_BUILD" && export STABLE_BUILD=0
|
|||
docker run \
|
||||
--rm \
|
||||
--security-opt seccomp:unconfined \
|
||||
-v "${WORKSPACE}":/home/gha/project-athena \
|
||||
-v "${WORKSPACE}":/home/gha/vircadia \
|
||||
-e RELEASE_NUMBER \
|
||||
-e RELEASE_TYPE \
|
||||
-e ANDROID_APP \
|
||||
|
|
|
@ -72,17 +72,17 @@ RUN mkdir "$HIFI_BASE" && \
|
|||
mkdir "$HIFI_ANDROID_PRECOMPILED"
|
||||
|
||||
# Download the repo
|
||||
RUN git clone https://github.com/kasenvr/project-athena.git
|
||||
RUN git clone https://github.com/vircadia/vircadia.git
|
||||
|
||||
WORKDIR /home/gha/project-athena
|
||||
WORKDIR /home/gha/vircadia
|
||||
|
||||
RUN mkdir build
|
||||
|
||||
# Pre-cache the vcpkg managed dependencies
|
||||
WORKDIR /home/gha/project-athena/build
|
||||
WORKDIR /home/gha/vircadia/build
|
||||
RUN python3 ../prebuild.py --build-root `pwd` --android interface
|
||||
|
||||
# Pre-cache the gradle dependencies
|
||||
WORKDIR /home/gha/project-athena/android
|
||||
WORKDIR /home/gha/vircadia/android
|
||||
RUN ./gradlew -m tasks -PHIFI_ANDROID_PRECOMPILED=$HIFI_ANDROID_PRECOMPILED
|
||||
#RUN ./gradlew extractDependencies -PHIFI_ANDROID_PRECOMPILED=$HIFI_ANDROID_PRECOMPILED
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
|
||||
macro(optional_win_executable_signing)
|
||||
if (WIN32 AND PRODUCTION_BUILD)
|
||||
if (WIN32 AND PRODUCTION_BUILD AND NOT BYPASS_SIGNING)
|
||||
if (DEFINED ENV{HF_PFX_FILE})
|
||||
if (DEFINED ENV{HF_PFX_PASSPHRASE})
|
||||
message(STATUS "Executable for ${TARGET_NAME} will be signed with SignTool.")
|
||||
|
|
|
@ -25,6 +25,7 @@ macro(SET_PACKAGING_PARAMETERS)
|
|||
set_from_env(RELEASE_NUMBER RELEASE_NUMBER "")
|
||||
set_from_env(STABLE_BUILD STABLE_BUILD 0)
|
||||
set_from_env(INITIAL_STARTUP_LOCATION INITIAL_STARTUP_LOCATION "")
|
||||
set_from_env(BYPASS_SIGNING BYPASS_SIGNING 0)
|
||||
|
||||
message(STATUS "The RELEASE_TYPE variable is: ${RELEASE_TYPE}")
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
macro(target_oculus_mobile)
|
||||
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/oculus_1.22/VrApi)
|
||||
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/ovr_sdk_mobile_1.37.0/VrApi)
|
||||
|
||||
# Mobile SDK
|
||||
set(OVR_MOBILE_INCLUDE_DIRS ${INSTALL_DIR}/Include)
|
||||
|
@ -12,7 +12,7 @@ macro(target_oculus_mobile)
|
|||
target_link_libraries(${TARGET_NAME} ${OVR_MOBILE_LIBRARIES})
|
||||
|
||||
# Platform SDK
|
||||
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/oculusPlatform)
|
||||
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/ovr_platform_sdk_23.0.0)
|
||||
set(OVR_PLATFORM_INCLUDE_DIRS ${INSTALL_DIR}/Include)
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${OVR_PLATFORM_INCLUDE_DIRS})
|
||||
set(OVR_PLATFORM_LIBRARIES ${INSTALL_DIR}/Android/libs/arm64-v8a/libovrplatformloader.so)
|
||||
|
|
|
@ -19,7 +19,7 @@ include(vcpkg_common_functions)
|
|||
|
||||
vcpkg_from_github(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
REPO kasenvr/etc2comp
|
||||
REPO vircadia/etc2comp
|
||||
REF 7f1843bf07825c21cab711360c1ddbad04641036
|
||||
SHA512 d747076acda8537d39585858c793a35c3dcc9ef283d723619a47f8c81ec1454c95b3340ad35f0655a939eae5b8271c801c48a9a7568311a01903a344c44af25b
|
||||
HEAD_REF master
|
||||
|
|
|
@ -2,13 +2,22 @@ include(vcpkg_common_functions)
|
|||
vcpkg_check_linkage(ONLY_STATIC_LIBRARY)
|
||||
|
||||
file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS)
|
||||
file(READ "${VCPKG_ROOT_DIR}/_env/USE_GLES.txt" USE_GLES)
|
||||
|
||||
# GitHub Actions Android builds fail with `FILENAME` set while desktop builds with GLES fail without a set `FILENAME`.
|
||||
if (ANDROID)
|
||||
vcpkg_download_distfile(
|
||||
SOURCE_ARCHIVE
|
||||
URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/glad/glad32es.zip
|
||||
SHA512 2e02ac633eed8f2ba2adbf96ea85d08998f48dd2e9ec9a88ec3c25f48eaf1405371d258066327c783772fcb3793bdb82bd7375fdabb2ba5e2ce0835468b17f65
|
||||
)
|
||||
elseif (USE_GLES)
|
||||
vcpkg_download_distfile(
|
||||
SOURCE_ARCHIVE
|
||||
URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/glad/glad32es.zip
|
||||
SHA512 2e02ac633eed8f2ba2adbf96ea85d08998f48dd2e9ec9a88ec3c25f48eaf1405371d258066327c783772fcb3793bdb82bd7375fdabb2ba5e2ce0835468b17f65
|
||||
FILENAME glad32es.zip
|
||||
)
|
||||
else()
|
||||
# else Linux desktop
|
||||
vcpkg_download_distfile(
|
||||
|
|
|
@ -3,7 +3,7 @@ include(vcpkg_common_functions)
|
|||
|
||||
vcpkg_from_github(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
REPO kasenvr/scribe
|
||||
REPO vircadia/scribe
|
||||
REF 1bd638a36ca771e5a68d01985b6389b71835cbd2
|
||||
SHA512 dbe241d86df3912e544f6b9839873f9875df54efc93822b145e7b13243eaf2e3d690bc8a28b1e52d05bdcd7e68fca6b0b2f5c43ffd0f56a9b7a50d54dcf9e31e
|
||||
HEAD_REF master
|
||||
|
|
|
@ -9,7 +9,7 @@ include(vcpkg_common_functions)
|
|||
|
||||
vcpkg_from_github(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
REPO kasenvr/nvidia-texture-tools
|
||||
REPO vircadia/nvidia-texture-tools
|
||||
REF 330c4d56274a0f602a5c70596e2eb670a4ed56c2
|
||||
SHA512 4c0bc2f369120d696cc27710b6d33086b27eef55f537ec66b9a5c8b1839bc2426c0413670b0f65be52c5d353468f0126dfe024be1f0690611d4d7e33ac530127
|
||||
HEAD_REF master
|
||||
|
|
|
@ -837,16 +837,24 @@ Function PostInstallOptionsPage
|
|||
!insertmacro SetInstallOption $DesktopClientCheckbox @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ ${BST_CHECKED}
|
||||
${EndIf}
|
||||
|
||||
; FIXME: Re-enable or permanently remove system tray "Console" for Interface-only installs.
|
||||
;${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
; ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @SANDBOX_HF_SHORTCUT_NAME@"
|
||||
;${Else}
|
||||
; ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @CONSOLE_HF_SHORTCUT_NAME@"
|
||||
;${EndIf}
|
||||
;Pop $DesktopConsoleCheckbox
|
||||
;IntOp $CurrentOffset $CurrentOffset + 15
|
||||
;
|
||||
;; set the checkbox state depending on what is present in the registry
|
||||
;!insertmacro SetInstallOption $DesktopConsoleCheckbox @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ ${BST_UNCHECKED}
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @SANDBOX_HF_SHORTCUT_NAME@"
|
||||
${Else}
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @CONSOLE_HF_SHORTCUT_NAME@"
|
||||
Pop $DesktopConsoleCheckbox
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetInstallOption $DesktopConsoleCheckbox @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ ${BST_UNCHECKED}
|
||||
${EndIf}
|
||||
|
||||
Pop $DesktopConsoleCheckbox
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetInstallOption $DesktopConsoleCheckbox @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ ${BST_UNCHECKED}
|
||||
|
||||
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @INTERFACE_HF_SHORTCUT_NAME@ after install"
|
||||
|
@ -861,31 +869,54 @@ Function PostInstallOptionsPage
|
|||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
; FIXME: Re-enable or permanently remove system tray "Console" for Interface-only installs.
|
||||
;${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
; ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @SANDBOX_HF_SHORTCUT_NAME@ after install"
|
||||
;${Else}
|
||||
; ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ after install"
|
||||
;${EndIf}
|
||||
;Pop $LaunchConsoleNowCheckbox
|
||||
;
|
||||
;; set the checkbox state depending on what is present in the registry
|
||||
;!insertmacro SetInstallOption $LaunchConsoleNowCheckbox @SERVER_LAUNCH_NOW_REG_KEY@ ${BST_UNCHECKED}
|
||||
;${StrContains} $substringResult "/forceNoLaunchServer" $CMDLINE
|
||||
;${IfNot} $substringResult == ""
|
||||
; ${NSD_SetState} $LaunchConsoleNowCheckbox ${BST_UNCHECKED}
|
||||
;${EndIf}
|
||||
;IntOp $CurrentOffset $CurrentOffset + 15
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @SANDBOX_HF_SHORTCUT_NAME@ after install"
|
||||
${Else}
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ after install"
|
||||
${EndIf}
|
||||
Pop $LaunchConsoleNowCheckbox
|
||||
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetInstallOption $LaunchConsoleNowCheckbox @SERVER_LAUNCH_NOW_REG_KEY@ ${BST_UNCHECKED}
|
||||
${StrContains} $substringResult "/forceNoLaunchServer" $CMDLINE
|
||||
${IfNot} $substringResult == ""
|
||||
Pop $LaunchConsoleNowCheckbox
|
||||
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetInstallOption $LaunchConsoleNowCheckbox @SERVER_LAUNCH_NOW_REG_KEY@ ${BST_UNCHECKED}
|
||||
${StrContains} $substringResult "/forceNoLaunchServer" $CMDLINE
|
||||
${IfNot} $substringResult == ""
|
||||
${NSD_SetState} $LaunchConsoleNowCheckbox ${BST_UNCHECKED}
|
||||
${EndIf}
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
${EndIf}
|
||||
IntOp $CurrentOffset $CurrentOffset + 30
|
||||
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @SANDBOX_HF_SHORTCUT_NAME@ on startup"
|
||||
${Else}
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ on startup"
|
||||
${EndIf}
|
||||
Pop $ConsoleStartupCheckbox
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetInstallOption $ConsoleStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_UNCHECKED}
|
||||
; FIXME: Re-enable or permanently remove system tray "Console" for Interface-only installs.
|
||||
;${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
; ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @SANDBOX_HF_SHORTCUT_NAME@ on startup"
|
||||
;${Else}
|
||||
; ${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ on startup"
|
||||
;${EndIf}
|
||||
;Pop $ConsoleStartupCheckbox
|
||||
;IntOp $CurrentOffset $CurrentOffset + 15
|
||||
;
|
||||
;; set the checkbox state depending on what is present in the registry
|
||||
;!insertmacro SetInstallOption $ConsoleStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_UNCHECKED}
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @SANDBOX_HF_SHORTCUT_NAME@ on startup"
|
||||
Pop $ConsoleStartupCheckbox
|
||||
IntOp $CurrentOffset $CurrentOffset + 15
|
||||
|
||||
; set the checkbox state depending on what is present in the registry
|
||||
!insertmacro SetInstallOption $ConsoleStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_UNCHECKED}
|
||||
${EndIf}
|
||||
|
||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Perform a clean install (Delete older settings and content)"
|
||||
Pop $CleanInstallCheckbox
|
||||
|
@ -957,13 +988,29 @@ FunctionEnd
|
|||
|
||||
Function ReadPostInstallOptions
|
||||
|
||||
; check if the user asked for a desktop shortcut to console
|
||||
${NSD_GetState} $DesktopConsoleCheckbox $DesktopConsoleState
|
||||
${LogText} "Option: Start Desktop Console: $DesktopConsoleState"
|
||||
; FIXME: Re-enable or permanently remove system tray "Console" for Interface-only installs.
|
||||
;; check if the user asked for a desktop shortcut to console
|
||||
;${NSD_GetState} $DesktopConsoleCheckbox $DesktopConsoleState
|
||||
;${LogText} "Option: Start Desktop Console: $DesktopConsoleState"
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
; check if the user asked for a desktop shortcut to console
|
||||
${NSD_GetState} $DesktopConsoleCheckbox $DesktopConsoleState
|
||||
${LogText} "Option: Start Desktop Console: $DesktopConsoleState"
|
||||
${Else}
|
||||
StrCpy $DesktopConsoleState ${BST_UNCHECKED}
|
||||
${EndIf}
|
||||
|
||||
; check if the user asked to have console launched every startup
|
||||
${NSD_GetState} $ConsoleStartupCheckbox $ConsoleStartupState
|
||||
${LogText} "Option: Start Desktop Console On Startup: $ConsoleStartupState"
|
||||
; FIXME: Re-enable or permanently remove system tray "Console" for Interface-only installs.
|
||||
;; check if the user asked to have console launched every startup
|
||||
;${NSD_GetState} $ConsoleStartupCheckbox $ConsoleStartupState
|
||||
;${LogText} "Option: Start Desktop Console On Startup: $ConsoleStartupState"
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
; check if the user asked to have console launched every startup
|
||||
${NSD_GetState} $ConsoleStartupCheckbox $ConsoleStartupState
|
||||
${LogText} "Option: Start Desktop Console On Startup: $ConsoleStartupState"
|
||||
${Else}
|
||||
StrCpy $ConsoleStartupState ${BST_UNCHECKED}
|
||||
${EndIf}
|
||||
|
||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||
${LogText} "Option: Install Server"
|
||||
|
@ -1308,10 +1355,13 @@ Section "-Core installation"
|
|||
${Else}
|
||||
; handling for interface only console shortcut
|
||||
Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_HF_SHORTCUT_NAME@.lnk"
|
||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" \
|
||||
"$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
||||
; Set appUserModelId
|
||||
ApplicationID::Set "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@"
|
||||
|
||||
; FIXME: Re-enable or permanently remove system tray "Console" for Interface-only installs.
|
||||
;CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" \
|
||||
; "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
||||
;; Set appUserModelId
|
||||
;ApplicationID::Set "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@"
|
||||
|
||||
${EndIf}
|
||||
|
||||
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\@UNINSTALLER_NAME@"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// index.html
|
||||
//
|
||||
// Created by kasenvr@gmail.com on 21 Jul 2020
|
||||
// Created by somnilibertas@gmail.com on 21 Jul 2020
|
||||
// Copyright 2020 Vircadia and contributors.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
// Here you can put a script that will be run by an assignment-client (AC)
|
||||
// For examples, please go to https://github.com/kasenvr/project-athena/tree/master/script-archive/acScripts
|
||||
// For examples, please go to https://github.com/vircadia/vircadia/tree/master/script-archive/acScripts
|
||||
// The directory named acScripts contains assignment-client specific scripts you can try.
|
||||
|
|
|
@ -39,15 +39,15 @@ ANDROID_PACKAGES = {
|
|||
'sharedLibFolder': 'lib',
|
||||
'includeLibs': ['libnvtt.so', 'libnvmath.so', 'libnvimage.so', 'libnvcore.so']
|
||||
},
|
||||
'oculus_1.22': {
|
||||
'file': 'ovr_sdk_mobile_1.22.zip',
|
||||
'checksum': '1ac3c5b0521e5406f287f351015daff8',
|
||||
'ovr_sdk_mobile_1.37.0': {
|
||||
'file': 'ovr_sdk_mobile_1.37.0.zip',
|
||||
'checksum': '6040e1966f335a3e5015295154cd7383',
|
||||
'sharedLibFolder': 'VrApi/Libs/Android/arm64-v8a/Release',
|
||||
'includeLibs': ['libvrapi.so']
|
||||
},
|
||||
'oculusPlatform': {
|
||||
'file': 'OVRPlatformSDK_v1.34.0.zip',
|
||||
'checksum': '16e4c5f39520f122bc49cb6d5bb88289',
|
||||
'ovr_platform_sdk_23.0.0': {
|
||||
'file': 'ovr_platform_sdk_23.0.0.zip',
|
||||
'checksum': '29d02b560f60d0fa7b8a64cd965dd55b',
|
||||
'sharedLibFolder': 'Android/libs/arm64-v8a',
|
||||
'includeLibs': ['libovrplatformloader.so']
|
||||
},
|
||||
|
|
|
@ -12,7 +12,7 @@ import functools
|
|||
|
||||
print = functools.partial(print, flush=True)
|
||||
|
||||
# Encapsulates the vcpkg system
|
||||
# Encapsulates the vcpkg system
|
||||
class QtDownloader:
|
||||
CMAKE_TEMPLATE = """
|
||||
# this file auto-generated by hifi_qt.py
|
||||
|
@ -72,7 +72,7 @@ endif()
|
|||
self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-18.04.tar.gz'
|
||||
elif u_major == 19 and u_minor == 10:
|
||||
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):
|
||||
elif u_major > 19:
|
||||
print("We don't support " + distro.name(pretty=True) + " yet. Perhaps consider helping us out?")
|
||||
raise Exception('LINUX DISTRO IS NOT SUPPORTED YET!!!')
|
||||
else:
|
||||
|
@ -81,7 +81,7 @@ endif()
|
|||
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:")
|
||||
print("https://github.com/kasenvr/project-athena/tree/kasen/core/tools/qt-builder")
|
||||
print("https://github.com/vircadia/vircadia/tree/master/tools/qt-builder")
|
||||
raise Exception('UNKNOWN LINUX VERSION!!!')
|
||||
else:
|
||||
print("System : " + platform.system())
|
||||
|
|
|
@ -309,8 +309,8 @@ FocusScope {
|
|||
if (child.hasOwnProperty("modality")) {
|
||||
var mappedPoint = mapToItem(child, point.x, point.y);
|
||||
if (child.hasOwnProperty("frame")) {
|
||||
var outLine = child.frame.children[2];
|
||||
var framePoint = outLine.mapFromGlobal(point.x, point.y);
|
||||
var outLine = child.frame.children[2]; // sizeOutline
|
||||
var framePoint = mapToItem(outLine, point.x, point.y);
|
||||
if (outLine.contains(framePoint)) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -54,10 +54,10 @@ Rectangle {
|
|||
textFormat: Text.StyledText
|
||||
linkColor: "#00B4EF"
|
||||
color: "white"
|
||||
text: "<a href=\"https://github.com/kasenvr/project-athena\">Vircadia Github</a>."
|
||||
text: "<a href=\"https://github.com/vircadia/vircadia\">Vircadia Github</a>."
|
||||
size: 20
|
||||
onLinkActivated: {
|
||||
About.openUrl("https:/github.com/kasenvr/project-athena");
|
||||
About.openUrl("https:/github.com/vircadia/vircadia");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// EntityScriptQMLWhitelist.qml
|
||||
// interface/resources/qml/hifi/dialogs/security
|
||||
//
|
||||
// Created by Kasen IO on 2019.12.05 | realities.dev | kasenvr@gmail.com
|
||||
// Copyright 2019 Kasen IO
|
||||
// Created by Kalila L. on 2019.12.05 | realities.dev | somnilibertas@gmail.com
|
||||
// Copyright 2019 Kalila L.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
|
|
@ -314,7 +314,7 @@ Rectangle {
|
|||
onClicked: {
|
||||
lightboxPopup.titleText = "Script Plugin Infrastructure";
|
||||
lightboxPopup.bodyText = "Toggles the activation of scripting plugins in the 'plugins/scripting' folder. \n\n"
|
||||
+ "Created by:\n humbletim@gmail.com\n kasenvr@gmail.com";
|
||||
+ "Created by:\n humbletim@gmail.com\n somnilibertas@gmail.com";
|
||||
lightboxPopup.button1text = "OK";
|
||||
lightboxPopup.button1method = function() {
|
||||
lightboxPopup.visible = false;
|
||||
|
|
|
@ -27,7 +27,6 @@ Item {
|
|||
readonly property int frameMarginRight: frame.decoration ? frame.decoration.frameMarginRight : 0
|
||||
readonly property int frameMarginTop: frame.decoration ? frame.decoration.frameMarginTop : 0
|
||||
readonly property int frameMarginBottom: frame.decoration ? frame.decoration.frameMarginBottom : 0
|
||||
readonly property int offsetCorrection: 20
|
||||
|
||||
// Frames always fill their parents, but their decorations may extend
|
||||
// beyond the window via negative margin sizes
|
||||
|
@ -76,7 +75,7 @@ Item {
|
|||
Rectangle {
|
||||
id: sizeOutline
|
||||
x: -frameMarginLeft
|
||||
y: -frameMarginTop - offsetCorrection
|
||||
y: -frameMarginTop
|
||||
width: window ? window.width + frameMarginLeft + frameMarginRight + 2 : 0
|
||||
height: window ? window.height + frameMarginTop + frameMarginBottom + 2 : 0
|
||||
color: hifi.colors.baseGrayHighlight15
|
||||
|
|
|
@ -8712,7 +8712,7 @@ void Application::notifyPacketVersionMismatch() {
|
|||
}
|
||||
|
||||
void Application::checkSkeleton() const {
|
||||
if (getMyAvatar()->getSkeletonModel()->isActive() && !getMyAvatar()->getSkeletonModel()->hasSkeleton()) {
|
||||
if (getMyAvatar()->getSkeletonModel()->isLoaded() && !getMyAvatar()->getSkeletonModel()->hasSkeleton()) {
|
||||
qCDebug(interfaceapp) << "MyAvatar model has no skeleton";
|
||||
|
||||
QString message = "Your selected avatar body has no skeleton.\n\nThe default body will be loaded...";
|
||||
|
|
|
@ -89,6 +89,7 @@ int main(int argc, const char* argv[]) {
|
|||
QCommandLineOption displayNameOption("displayName", "set user display name <string>", "string");
|
||||
QCommandLineOption setBookmarkOption("setBookmark", "set bookmark key=value pair", "string");
|
||||
QCommandLineOption defaultScriptOverrideOption("defaultScriptsOverride", "override defaultsScripts.js", "string");
|
||||
QCommandLineOption forceCrashReportingOption("forceCrashReporting", "Force crash reporting to initialize");
|
||||
|
||||
parser.addOption(urlOption);
|
||||
parser.addOption(noLauncherOption);
|
||||
|
@ -103,6 +104,7 @@ int main(int argc, const char* argv[]) {
|
|||
parser.addOption(displayNameOption);
|
||||
parser.addOption(setBookmarkOption);
|
||||
parser.addOption(defaultScriptOverrideOption);
|
||||
parser.addOption(forceCrashReportingOption);
|
||||
|
||||
if (!parser.parse(arguments)) {
|
||||
std::cout << parser.errorText().toStdString() << std::endl; // Avoid Qt log spam
|
||||
|
@ -218,8 +220,9 @@ int main(int argc, const char* argv[]) {
|
|||
}
|
||||
qDebug() << "UserActivityLogger is enabled:" << ual.isEnabled();
|
||||
|
||||
qDebug() << "Crash handler logger is enabled:" << ual.isCrashMonitorEnabled();
|
||||
if (ual.isCrashMonitorEnabled()) {
|
||||
bool isCrashHandlerEnabled = ual.isCrashMonitorEnabled() || parser.isSet(forceCrashReportingOption);
|
||||
qDebug() << "Crash handler logger is enabled:" << isCrashHandlerEnabled;
|
||||
if (isCrashHandlerEnabled) {
|
||||
auto crashHandlerStarted = startCrashHandler(argv[0]);
|
||||
qDebug() << "Crash handler started:" << crashHandlerStarted;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ OverlayConductor::OverlayConductor() {
|
|||
OverlayConductor::~OverlayConductor() {
|
||||
}
|
||||
|
||||
bool OverlayConductor::headOutsideOverlay() const {
|
||||
bool OverlayConductor::headNotCenteredInOverlay() const {
|
||||
glm::mat4 hmdMat = qApp->getHMDSensorPose();
|
||||
glm::vec3 hmdPos = extractTranslation(hmdMat);
|
||||
glm::vec3 hmdForward = transformVectorFast(hmdMat, glm::vec3(0.0f, 0.0f, -1.0f));
|
||||
|
@ -32,8 +32,8 @@ bool OverlayConductor::headOutsideOverlay() const {
|
|||
glm::vec3 uiPos = uiTransform.getTranslation();
|
||||
glm::vec3 uiForward = uiTransform.getRotation() * glm::vec3(0.0f, 0.0f, -1.0f);
|
||||
|
||||
const float MAX_COMPOSITOR_DISTANCE = 0.99f; // If you're 1m from center of ui sphere, you're at the surface.
|
||||
const float MAX_COMPOSITOR_ANGLE = 180.0f; // rotation check is effectively disabled
|
||||
const float MAX_COMPOSITOR_DISTANCE = 0.33f;
|
||||
const float MAX_COMPOSITOR_ANGLE = 90.0f;
|
||||
if (glm::distance(uiPos, hmdPos) > MAX_COMPOSITOR_DISTANCE ||
|
||||
glm::dot(uiForward, hmdForward) < cosf(glm::radians(MAX_COMPOSITOR_ANGLE))) {
|
||||
return true;
|
||||
|
@ -70,6 +70,8 @@ bool OverlayConductor::updateAvatarIsAtRest() {
|
|||
void OverlayConductor::centerUI() {
|
||||
// place the overlay at the current hmd position in sensor space
|
||||
auto camMat = cancelOutRollAndPitch(qApp->getHMDSensorPose());
|
||||
// Set its radius.
|
||||
camMat = glm::scale(camMat, glm::vec3(HUD_RADIUS));
|
||||
qApp->getApplicationCompositor().setModelTransform(Transform(camMat));
|
||||
}
|
||||
|
||||
|
@ -83,7 +85,6 @@ void OverlayConductor::update(float dt) {
|
|||
if (!desktop) {
|
||||
return;
|
||||
}
|
||||
bool currentVisible = !desktop->property("pinned").toBool();
|
||||
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
// centerUI when hmd mode is first enabled and mounted
|
||||
|
@ -96,24 +97,24 @@ void OverlayConductor::update(float dt) {
|
|||
_hmdMode = false;
|
||||
}
|
||||
|
||||
bool shouldRecenter = false;
|
||||
|
||||
if (_suppressedByHead) {
|
||||
if (updateAvatarIsAtRest()) {
|
||||
_suppressedByHead = false;
|
||||
shouldRecenter = true;
|
||||
}
|
||||
} else {
|
||||
if (_hmdMode && headOutsideOverlay()) {
|
||||
_suppressedByHead = true;
|
||||
}
|
||||
bool initiateRecenter = false;
|
||||
if (_hmdMode && headNotCenteredInOverlay()) {
|
||||
initiateRecenter = true;
|
||||
}
|
||||
|
||||
bool shouldRecenter = false;
|
||||
if (initiateRecenter || _suppressedByHead) {
|
||||
_suppressedByHead = !updateAvatarIsAtRest();
|
||||
shouldRecenter = !_suppressedByHead;
|
||||
}
|
||||
|
||||
bool currentVisible = !desktop->property("pinned").toBool();
|
||||
bool targetVisible = Menu::getInstance()->isOptionChecked(MenuOption::Overlays) && !_suppressedByHead;
|
||||
if (targetVisible != currentVisible) {
|
||||
offscreenUi->setPinned(!targetVisible);
|
||||
}
|
||||
if (shouldRecenter && !_suppressedByHead) {
|
||||
|
||||
if (shouldRecenter) {
|
||||
centerUI();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -22,7 +22,7 @@ public:
|
|||
void centerUI();
|
||||
|
||||
private:
|
||||
bool headOutsideOverlay() const;
|
||||
bool headNotCenteredInOverlay() const;
|
||||
bool updateAvatarIsAtRest();
|
||||
|
||||
#if !defined(DISABLE_QML)
|
||||
|
|
|
@ -1246,7 +1246,7 @@ glm::quat Avatar::getAbsoluteJointRotationInObjectFrame(int index) const {
|
|||
}
|
||||
case CAMERA_MATRIX_INDEX: {
|
||||
glm::quat rotation;
|
||||
if (_skeletonModel && _skeletonModel->isActive()) {
|
||||
if (_skeletonModel && _skeletonModel->isLoaded()) {
|
||||
int headJointIndex = getJointIndex("Head");
|
||||
if (headJointIndex >= 0) {
|
||||
_skeletonModel->getAbsoluteJointRotationInRigFrame(headJointIndex, rotation);
|
||||
|
@ -1298,7 +1298,7 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const {
|
|||
}
|
||||
case CAMERA_MATRIX_INDEX: {
|
||||
glm::vec3 translation;
|
||||
if (_skeletonModel && _skeletonModel->isActive()) {
|
||||
if (_skeletonModel && _skeletonModel->isLoaded()) {
|
||||
int headJointIndex = getJointIndex("Head");
|
||||
if (headJointIndex >= 0) {
|
||||
_skeletonModel->getAbsoluteJointTranslationInRigFrame(headJointIndex, translation);
|
||||
|
@ -1427,7 +1427,7 @@ void Avatar::withValidJointIndicesCache(std::function<void()> const& worker) con
|
|||
QWriteLocker writeLock(&_modelJointIndicesCacheLock);
|
||||
if (!_modelJointsCached) {
|
||||
_modelJointIndicesCache.clear();
|
||||
if (_skeletonModel && _skeletonModel->isActive()) {
|
||||
if (_skeletonModel && _skeletonModel->isLoaded()) {
|
||||
_modelJointIndicesCache = _skeletonModel->getHFMModel().jointIndices;
|
||||
_modelJointsCached = true;
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
|||
updateRenderItems();
|
||||
}
|
||||
|
||||
if (!isActive() || !_owningAvatar->isMyAvatar()) {
|
||||
if (!isLoaded() || !_owningAvatar->isMyAvatar()) {
|
||||
return; // only simulate for own avatar
|
||||
}
|
||||
|
||||
|
@ -255,19 +255,19 @@ bool SkeletonModel::getRightHandPosition(glm::vec3& position) const {
|
|||
}
|
||||
|
||||
bool SkeletonModel::getHeadPosition(glm::vec3& headPosition) const {
|
||||
return isActive() && getJointPositionInWorldFrame(_rig.indexOfJoint("Head"), headPosition);
|
||||
return isLoaded() && getJointPositionInWorldFrame(_rig.indexOfJoint("Head"), headPosition);
|
||||
}
|
||||
|
||||
bool SkeletonModel::getNeckPosition(glm::vec3& neckPosition) const {
|
||||
return isActive() && getJointPositionInWorldFrame(_rig.indexOfJoint("Neck"), neckPosition);
|
||||
return isLoaded() && getJointPositionInWorldFrame(_rig.indexOfJoint("Neck"), neckPosition);
|
||||
}
|
||||
|
||||
bool SkeletonModel::getLocalNeckPosition(glm::vec3& neckPosition) const {
|
||||
return isActive() && getJointPosition(_rig.indexOfJoint("Neck"), neckPosition);
|
||||
return isLoaded() && getJointPosition(_rig.indexOfJoint("Neck"), neckPosition);
|
||||
}
|
||||
|
||||
bool SkeletonModel::getEyeModelPositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const {
|
||||
if (!isActive()) {
|
||||
if (!isLoaded()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -361,7 +361,7 @@ void SkeletonModel::renderBoundingCollisionShapes(RenderArgs* args, gpu::Batch&
|
|||
}
|
||||
|
||||
bool SkeletonModel::hasSkeleton() {
|
||||
return isActive() ? _rig.indexOfJoint("Hips") != -1 : false;
|
||||
return isLoaded() ? _rig.indexOfJoint("Hips") != -1 : false;
|
||||
}
|
||||
|
||||
void SkeletonModel::onInvalidate() {
|
||||
|
|
|
@ -44,10 +44,10 @@ public:
|
|||
bool getIsJointOverridden(int jointIndex) const;
|
||||
|
||||
/// Returns the index of the left hand joint, or -1 if not found.
|
||||
int getLeftHandJointIndex() const { return isActive() ? _rig.indexOfJoint("LeftHand") : -1; }
|
||||
int getLeftHandJointIndex() const { return isLoaded() ? _rig.indexOfJoint("LeftHand") : -1; }
|
||||
|
||||
/// Returns the index of the right hand joint, or -1 if not found.
|
||||
int getRightHandJointIndex() const { return isActive() ? _rig.indexOfJoint("RightHand") : -1; }
|
||||
int getRightHandJointIndex() const { return isLoaded() ? _rig.indexOfJoint("RightHand") : -1; }
|
||||
|
||||
bool getLeftGrabPosition(glm::vec3& position) const;
|
||||
bool getRightGrabPosition(glm::vec3& position) const;
|
||||
|
|
|
@ -41,10 +41,10 @@ static const float reticleSize = TWO_PI / 100.0f;
|
|||
//EntityItemID CompositorHelper::_noItemId;
|
||||
static QString _tooltipId;
|
||||
|
||||
const uvec2 CompositorHelper::VIRTUAL_SCREEN_SIZE = uvec2(3960, 1188); // ~10% more pixel density than old version, 72dx240d FOV
|
||||
const QRect CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT = QRect(956, 0, 2048, 1188); // don't include entire width only center 2048
|
||||
const uvec2 CompositorHelper::VIRTUAL_SCREEN_SIZE = uvec2(2640, 1188);
|
||||
const QRect CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT = QRect(296, 0, 2048, 1188); // Center 2048 pixels.
|
||||
const float CompositorHelper::VIRTUAL_UI_ASPECT_RATIO = (float)VIRTUAL_SCREEN_SIZE.x / (float)VIRTUAL_SCREEN_SIZE.y;
|
||||
const vec2 CompositorHelper::VIRTUAL_UI_TARGET_FOV = vec2(PI * 3.0f / 2.0f, PI * 3.0f / 2.0f / VIRTUAL_UI_ASPECT_RATIO);
|
||||
const vec2 CompositorHelper::VIRTUAL_UI_TARGET_FOV = vec2(PI, PI / VIRTUAL_UI_ASPECT_RATIO);
|
||||
const vec2 CompositorHelper::MOUSE_EXTENTS_ANGULAR_SIZE = vec2(PI * 2.0f, PI * 0.95f); // horizontal: full sphere, vertical: ~5deg from poles
|
||||
const vec2 CompositorHelper::MOUSE_EXTENTS_PIXELS = vec2(VIRTUAL_SCREEN_SIZE) * (MOUSE_EXTENTS_ANGULAR_SIZE / VIRTUAL_UI_TARGET_FOV);
|
||||
|
||||
|
@ -384,9 +384,9 @@ bool CompositorHelper::calculateRayUICollisionPoint(const glm::vec3& position, c
|
|||
glm::vec3 localPosition = transformPoint(worldToUi, position);
|
||||
glm::vec3 localDirection = glm::normalize(transformVectorFast(worldToUi, direction));
|
||||
|
||||
const float UI_RADIUS = 1.0f;
|
||||
const float UNIT_RADIUS = 1.0f;
|
||||
float intersectionDistance;
|
||||
if (raySphereIntersect(localDirection, localPosition, UI_RADIUS, &intersectionDistance)) {
|
||||
if (raySphereIntersect(localDirection, localPosition, UNIT_RADIUS, &intersectionDistance)) {
|
||||
result = transformPoint(uiToWorld, localPosition + localDirection * intersectionDistance);
|
||||
#ifdef WANT_DEBUG
|
||||
DebugDraw::getInstance().drawRay(position, result, glm::vec4(0.0f, 1.0f, 0.0f, 1.0f));
|
||||
|
@ -407,9 +407,8 @@ bool CompositorHelper::calculateParabolaUICollisionPoint(const glm::vec3& origin
|
|||
glm::vec3 localVelocity = glm::normalize(transformVectorFast(worldToUi, velocity));
|
||||
glm::vec3 localAcceleration = glm::normalize(transformVectorFast(worldToUi, acceleration));
|
||||
|
||||
const float UI_RADIUS = 1.0f;
|
||||
float intersectionDistance;
|
||||
if (findParabolaSphereIntersection(localOrigin, localVelocity, localAcceleration, glm::vec3(0.0f), UI_RADIUS, intersectionDistance)) {
|
||||
if (findParabolaSphereIntersection(localOrigin, localVelocity, localAcceleration, glm::vec3(0.0f), HUD_RADIUS, intersectionDistance)) {
|
||||
result = origin + velocity * intersectionDistance + 0.5f * acceleration * intersectionDistance * intersectionDistance;
|
||||
parabolicDistance = intersectionDistance;
|
||||
return true;
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
|
||||
class ReticleInterface;
|
||||
|
||||
const float DEFAULT_RETICLE_DEPTH = 1.0f; // FIXME - probably should be based on UI radius
|
||||
const float HUD_RADIUS = 1.5f;
|
||||
const float DEFAULT_RETICLE_DEPTH = HUD_RADIUS;
|
||||
|
||||
const float MAGNIFY_WIDTH = 220.0f;
|
||||
const float MAGNIFY_HEIGHT = 100.0f;
|
||||
|
@ -154,7 +155,7 @@ private:
|
|||
std::unique_ptr<QPropertyAnimation> _alphaPropertyAnimation;
|
||||
|
||||
std::atomic<bool> _reticleVisible { true };
|
||||
std::atomic<float> _reticleDepth { 1.0f };
|
||||
std::atomic<float> _reticleDepth { DEFAULT_RETICLE_DEPTH };
|
||||
|
||||
// NOTE: when the compositor is running in HMD mode, it will control the reticle position as a custom
|
||||
// application specific position, when it's in desktop mode, the reticle position will simply move
|
||||
|
|
|
@ -431,13 +431,13 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa
|
|||
_visible = entity->getVisible();
|
||||
setIsVisibleInSecondaryCamera(entity->isVisibleInSecondaryCamera());
|
||||
setRenderLayer(entity->getRenderLayer());
|
||||
setPrimitiveMode(entity->getPrimitiveMode());
|
||||
_primitiveMode = entity->getPrimitiveMode();
|
||||
_canCastShadow = entity->getCanCastShadow();
|
||||
setCullWithParent(entity->getCullWithParent());
|
||||
_cauterized = entity->getCauterized();
|
||||
if (entity->needsZoneOcclusionUpdate()) {
|
||||
entity->resetNeedsZoneOcclusionUpdate();
|
||||
setRenderWithZones(entity->getRenderWithZones());
|
||||
_renderWithZones = entity->getRenderWithZones();
|
||||
}
|
||||
entity->setNeedsRenderUpdate(false);
|
||||
});
|
||||
|
@ -469,11 +469,13 @@ void EntityRenderer::onRemoveFromScene(const EntityItemPointer& entity) {
|
|||
void EntityRenderer::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) {
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
_materials[parentMaterialName].push(material);
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
|
||||
void EntityRenderer::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
_materials[parentMaterialName].remove(material);
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
|
||||
glm::vec4 EntityRenderer::calculatePulseColor(const glm::vec4& color, const PulsePropertyGroup& pulseProperties, quint64 start) {
|
||||
|
|
|
@ -108,18 +108,7 @@ protected:
|
|||
|
||||
virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; }
|
||||
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<QUuid>& renderWithZones) { _renderWithZones = renderWithZones; }
|
||||
|
||||
template <typename F, typename T>
|
||||
T withReadLockResult(const std::function<T()>& f) {
|
||||
T result;
|
||||
withReadLock([&] {
|
||||
result = f();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
signals:
|
||||
void requestRenderUpdate();
|
||||
|
|
|
@ -52,14 +52,11 @@ void GizmoEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
void GizmoEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
bool dirty = false;
|
||||
RingGizmoPropertyGroup ringProperties = entity->getRingProperties();
|
||||
withWriteLock([&] {
|
||||
_gizmoType = entity->getGizmoType();
|
||||
if (_ringProperties != ringProperties) {
|
||||
_ringProperties = ringProperties;
|
||||
dirty = true;
|
||||
|
||||
}
|
||||
});
|
||||
_gizmoType = entity->getGizmoType();
|
||||
if (_ringProperties != ringProperties) {
|
||||
_ringProperties = ringProperties;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if (dirty || _prevPrimitiveMode != _primitiveMode || !_ringGeometryID || !_majorTicksGeometryID || !_minorTicksGeometryID) {
|
||||
_prevPrimitiveMode = _primitiveMode;
|
||||
|
@ -242,19 +239,20 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) {
|
|||
|
||||
if (_gizmoType == GizmoType::RING) {
|
||||
Transform transform;
|
||||
bool hasTickMarks;
|
||||
glm::vec4 tickProperties;
|
||||
bool hasTickMarks = _ringProperties.getHasTickMarks();
|
||||
glm::vec4 tickProperties = glm::vec4(_ringProperties.getMajorTickMarksAngle(), _ringProperties.getMajorTickMarksLength(),
|
||||
_ringProperties.getMinorTickMarksAngle(), _ringProperties.getMinorTickMarksLength());
|
||||
bool forward;
|
||||
bool wireframe;
|
||||
bool transparent;
|
||||
withReadLock([&] {
|
||||
transform = _renderTransform;
|
||||
hasTickMarks = _ringProperties.getHasTickMarks();
|
||||
tickProperties = glm::vec4(_ringProperties.getMajorTickMarksAngle(), _ringProperties.getMajorTickMarksLength(),
|
||||
_ringProperties.getMinorTickMarksAngle(), _ringProperties.getMinorTickMarksLength());
|
||||
transparent = isTransparent();
|
||||
wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
|
||||
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||
});
|
||||
|
||||
bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
|
||||
geometryCache->bindSimpleProgram(batch, false, isTransparent(), wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE);
|
||||
geometryCache->bindSimpleProgram(batch, false, transparent, wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE);
|
||||
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
|
|
|
@ -30,16 +30,6 @@ bool GridEntityRenderer::isTransparent() const {
|
|||
}
|
||||
|
||||
void GridEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
withWriteLock([&] {
|
||||
_color = entity->getColor();
|
||||
_alpha = entity->getAlpha();
|
||||
_pulseProperties = entity->getPulseProperties();
|
||||
|
||||
_followCamera = entity->getFollowCamera();
|
||||
_majorGridEvery = entity->getMajorGridEvery();
|
||||
_minorGridEvery = entity->getMinorGridEvery();
|
||||
});
|
||||
|
||||
void* key = (void*)this;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
||||
withWriteLock([&] {
|
||||
|
@ -49,6 +39,16 @@ void GridEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen
|
|||
});
|
||||
}
|
||||
|
||||
void GridEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
_color = entity->getColor();
|
||||
_alpha = entity->getAlpha();
|
||||
_pulseProperties = entity->getPulseProperties();
|
||||
|
||||
_followCamera = entity->getFollowCamera();
|
||||
_majorGridEvery = entity->getMajorGridEvery();
|
||||
_minorGridEvery = entity->getMinorGridEvery();
|
||||
}
|
||||
|
||||
Item::Bound GridEntityRenderer::getBound() {
|
||||
if (_followCamera) {
|
||||
// This is a UI element that should always be in view, lie to the octree to avoid culling
|
||||
|
@ -73,13 +73,12 @@ ShapeKey GridEntityRenderer::getShapeKey() {
|
|||
}
|
||||
|
||||
void GridEntityRenderer::doRender(RenderArgs* args) {
|
||||
glm::vec4 color;
|
||||
glm::vec4 color = glm::vec4(toGlm(_color), _alpha);
|
||||
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
||||
glm::vec3 dimensions;
|
||||
Transform renderTransform;
|
||||
bool forward;
|
||||
withReadLock([&] {
|
||||
color = glm::vec4(toGlm(_color), _alpha);
|
||||
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
||||
dimensions = _dimensions;
|
||||
renderTransform = _renderTransform;
|
||||
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||
|
|
|
@ -30,10 +30,11 @@ protected:
|
|||
|
||||
private:
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
||||
glm::u8vec3 _color;
|
||||
float _alpha;
|
||||
float _alpha { NAN };
|
||||
PulsePropertyGroup _pulseProperties;
|
||||
|
||||
bool _followCamera;
|
||||
|
|
|
@ -29,44 +29,7 @@ bool ImageEntityRenderer::isTransparent() const {
|
|||
return Parent::isTransparent() || (_textureIsLoaded && _texture->getGPUTexture() && _texture->getGPUTexture()->getUsage().isAlpha()) || _alpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE;
|
||||
}
|
||||
|
||||
bool ImageEntityRenderer::needsRenderUpdate() const {
|
||||
if (resultWithReadLock<bool>([&] {
|
||||
return !_textureIsLoaded;
|
||||
})) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parent::needsRenderUpdate();
|
||||
}
|
||||
|
||||
void ImageEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
withWriteLock([&] {
|
||||
auto imageURL = entity->getImageURL();
|
||||
if (_imageURL != imageURL) {
|
||||
_imageURL = imageURL;
|
||||
if (imageURL.isEmpty()) {
|
||||
_texture.reset();
|
||||
} else {
|
||||
_texture = DependencyManager::get<TextureCache>()->getTexture(_imageURL);
|
||||
}
|
||||
_textureIsLoaded = false;
|
||||
}
|
||||
|
||||
_emissive = entity->getEmissive();
|
||||
_keepAspectRatio = entity->getKeepAspectRatio();
|
||||
_subImage = entity->getSubImage();
|
||||
|
||||
_color = entity->getColor();
|
||||
_alpha = entity->getAlpha();
|
||||
_pulseProperties = entity->getPulseProperties();
|
||||
_billboardMode = entity->getBillboardMode();
|
||||
|
||||
if (!_textureIsLoaded) {
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
_textureIsLoaded = _texture && (_texture->isLoaded() || _texture->isFailed());
|
||||
});
|
||||
|
||||
void* key = (void*)this;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
||||
withWriteLock([&] {
|
||||
|
@ -76,6 +39,33 @@ void ImageEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
});
|
||||
}
|
||||
|
||||
void ImageEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
auto imageURL = entity->getImageURL();
|
||||
if (_imageURL != imageURL) {
|
||||
_imageURL = imageURL;
|
||||
if (imageURL.isEmpty()) {
|
||||
_texture.reset();
|
||||
} else {
|
||||
_texture = DependencyManager::get<TextureCache>()->getTexture(_imageURL);
|
||||
}
|
||||
_textureIsLoaded = false;
|
||||
}
|
||||
|
||||
_emissive = entity->getEmissive();
|
||||
_keepAspectRatio = entity->getKeepAspectRatio();
|
||||
_subImage = entity->getSubImage();
|
||||
|
||||
_color = entity->getColor();
|
||||
_alpha = entity->getAlpha();
|
||||
_pulseProperties = entity->getPulseProperties();
|
||||
_billboardMode = entity->getBillboardMode();
|
||||
|
||||
if (!_textureIsLoaded) {
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
_textureIsLoaded = _texture && (_texture->isLoaded() || _texture->isFailed());
|
||||
}
|
||||
|
||||
Item::Bound ImageEntityRenderer::getBound() {
|
||||
auto bound = Parent::getBound();
|
||||
if (_billboardMode != BillboardMode::NONE) {
|
||||
|
@ -93,33 +83,26 @@ ShapeKey ImageEntityRenderer::getShapeKey() {
|
|||
builder.withTranslucent();
|
||||
}
|
||||
|
||||
withReadLock([&] {
|
||||
if (_emissive) {
|
||||
builder.withUnlit();
|
||||
}
|
||||
if (_emissive) {
|
||||
builder.withUnlit();
|
||||
}
|
||||
|
||||
if (_primitiveMode == PrimitiveMode::LINES) {
|
||||
builder.withWireframe();
|
||||
}
|
||||
});
|
||||
if (_primitiveMode == PrimitiveMode::LINES) {
|
||||
builder.withWireframe();
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
void ImageEntityRenderer::doRender(RenderArgs* args) {
|
||||
NetworkTexturePointer texture;
|
||||
QRect subImage;
|
||||
glm::vec4 color;
|
||||
glm::vec4 color = glm::vec4(toGlm(_color), _alpha);
|
||||
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
||||
Transform transform;
|
||||
withReadLock([&] {
|
||||
texture = _texture;
|
||||
subImage = _subImage;
|
||||
color = glm::vec4(toGlm(_color), _alpha);
|
||||
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
||||
transform = _renderTransform;
|
||||
});
|
||||
|
||||
if (!_visible || !texture || !texture->isLoaded() || color.a == 0.0f) {
|
||||
if (!_visible || !_texture || !_texture->isLoaded() || color.a == 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -129,28 +112,28 @@ void ImageEntityRenderer::doRender(RenderArgs* args) {
|
|||
transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition()));
|
||||
|
||||
batch->setModelTransform(transform);
|
||||
batch->setResourceTexture(0, texture->getGPUTexture());
|
||||
batch->setResourceTexture(0, _texture->getGPUTexture());
|
||||
|
||||
float imageWidth = texture->getWidth();
|
||||
float imageHeight = texture->getHeight();
|
||||
float imageWidth = _texture->getWidth();
|
||||
float imageHeight = _texture->getHeight();
|
||||
|
||||
QRect fromImage;
|
||||
if (subImage.width() <= 0) {
|
||||
if (_subImage.width() <= 0) {
|
||||
fromImage.setX(0);
|
||||
fromImage.setWidth(imageWidth);
|
||||
} else {
|
||||
float scaleX = imageWidth / texture->getOriginalWidth();
|
||||
fromImage.setX(scaleX * subImage.x());
|
||||
fromImage.setWidth(scaleX * subImage.width());
|
||||
float scaleX = imageWidth / _texture->getOriginalWidth();
|
||||
fromImage.setX(scaleX * _subImage.x());
|
||||
fromImage.setWidth(scaleX * _subImage.width());
|
||||
}
|
||||
|
||||
if (subImage.height() <= 0) {
|
||||
if (_subImage.height() <= 0) {
|
||||
fromImage.setY(0);
|
||||
fromImage.setHeight(imageHeight);
|
||||
} else {
|
||||
float scaleY = imageHeight / texture->getOriginalHeight();
|
||||
fromImage.setY(scaleY * subImage.y());
|
||||
fromImage.setHeight(scaleY * subImage.height());
|
||||
float scaleY = imageHeight / _texture->getOriginalHeight();
|
||||
fromImage.setY(scaleY * _subImage.y());
|
||||
fromImage.setHeight(scaleY * _subImage.height());
|
||||
}
|
||||
|
||||
float maxSize = glm::max(fromImage.width(), fromImage.height());
|
||||
|
|
|
@ -29,8 +29,8 @@ protected:
|
|||
bool isTransparent() const override;
|
||||
|
||||
private:
|
||||
virtual bool needsRenderUpdate() const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
||||
QString _imageURL;
|
||||
|
|
|
@ -16,197 +16,177 @@
|
|||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
||||
bool MaterialEntityRenderer::needsRenderUpdate() const {
|
||||
if (_retryApply) {
|
||||
return true;
|
||||
}
|
||||
if (!_texturesLoaded) {
|
||||
return true;
|
||||
}
|
||||
return Parent::needsRenderUpdate();
|
||||
}
|
||||
|
||||
bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
if (resultWithReadLock<bool>([&] {
|
||||
if (entity->getTransform() != _transform) {
|
||||
return true;
|
||||
}
|
||||
if (entity->getUnscaledDimensions() != _dimensions) {
|
||||
return true;
|
||||
}
|
||||
if (entity->getParentID() != _parentID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
void* key = (void*)this;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
||||
withWriteLock([&] {
|
||||
_renderTransform = getModelTransform();
|
||||
// Material entities should fit inside a cube entity of the same size, so a sphere that has dimensions 1x1x1
|
||||
// is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down.
|
||||
const float MATERIAL_ENTITY_SCALE = 0.5f;
|
||||
_renderTransform.postScale(MATERIAL_ENTITY_SCALE);
|
||||
_renderTransform.postScale(ENTITY_ITEM_DEFAULT_DIMENSIONS);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
withWriteLock([&] {
|
||||
bool deleteNeeded = false;
|
||||
bool addNeeded = _retryApply;
|
||||
bool transformChanged = false;
|
||||
{
|
||||
MaterialMappingMode mode = entity->getMaterialMappingMode();
|
||||
if (mode != _materialMappingMode) {
|
||||
_materialMappingMode = mode;
|
||||
transformChanged = true;
|
||||
}
|
||||
bool deleteNeeded = false;
|
||||
bool addNeeded = _retryApply;
|
||||
bool transformChanged = false;
|
||||
{
|
||||
MaterialMappingMode mode = entity->getMaterialMappingMode();
|
||||
if (mode != _materialMappingMode) {
|
||||
_materialMappingMode = mode;
|
||||
transformChanged = true;
|
||||
}
|
||||
{
|
||||
bool repeat = entity->getMaterialRepeat();
|
||||
if (repeat != _materialRepeat) {
|
||||
_materialRepeat = repeat;
|
||||
transformChanged = true;
|
||||
}
|
||||
}
|
||||
{
|
||||
bool repeat = entity->getMaterialRepeat();
|
||||
if (repeat != _materialRepeat) {
|
||||
_materialRepeat = repeat;
|
||||
transformChanged = true;
|
||||
}
|
||||
{
|
||||
glm::vec2 mappingPos = entity->getMaterialMappingPos();
|
||||
glm::vec2 mappingScale = entity->getMaterialMappingScale();
|
||||
float mappingRot = entity->getMaterialMappingRot();
|
||||
if (mappingPos != _materialMappingPos || mappingScale != _materialMappingScale || mappingRot != _materialMappingRot) {
|
||||
_materialMappingPos = mappingPos;
|
||||
_materialMappingScale = mappingScale;
|
||||
_materialMappingRot = mappingRot;
|
||||
transformChanged |= _materialMappingMode == MaterialMappingMode::UV;
|
||||
}
|
||||
}
|
||||
{
|
||||
glm::vec2 mappingPos = entity->getMaterialMappingPos();
|
||||
glm::vec2 mappingScale = entity->getMaterialMappingScale();
|
||||
float mappingRot = entity->getMaterialMappingRot();
|
||||
if (mappingPos != _materialMappingPos || mappingScale != _materialMappingScale || mappingRot != _materialMappingRot) {
|
||||
_materialMappingPos = mappingPos;
|
||||
_materialMappingScale = mappingScale;
|
||||
_materialMappingRot = mappingRot;
|
||||
transformChanged |= _materialMappingMode == MaterialMappingMode::UV;
|
||||
}
|
||||
{
|
||||
Transform transform = entity->getTransform();
|
||||
glm::vec3 dimensions = entity->getUnscaledDimensions();
|
||||
if (transform != _transform || dimensions != _dimensions) {
|
||||
_transform = transform;
|
||||
_dimensions = dimensions;
|
||||
transformChanged |= _materialMappingMode == MaterialMappingMode::PROJECTED;
|
||||
}
|
||||
}
|
||||
{
|
||||
Transform transform = entity->getTransform();
|
||||
glm::vec3 dimensions = entity->getUnscaledDimensions();
|
||||
if (transform != _transform || dimensions != _dimensions) {
|
||||
_transform = transform;
|
||||
_dimensions = dimensions;
|
||||
transformChanged |= _materialMappingMode == MaterialMappingMode::PROJECTED;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto material = getMaterial();
|
||||
// Update the old material regardless of if it's going to change
|
||||
if (transformChanged && material && !_parentID.isNull()) {
|
||||
deleteNeeded = true;
|
||||
addNeeded = true;
|
||||
applyTextureTransform(material);
|
||||
}
|
||||
{
|
||||
auto material = getMaterial();
|
||||
// Update the old material regardless of if it's going to change
|
||||
if (transformChanged && material && !_parentID.isNull()) {
|
||||
deleteNeeded = true;
|
||||
addNeeded = true;
|
||||
applyTextureTransform(material);
|
||||
}
|
||||
}
|
||||
|
||||
bool urlChanged = false;
|
||||
std::string newCurrentMaterialName = _currentMaterialName;
|
||||
{
|
||||
QString materialURL = entity->getMaterialURL();
|
||||
if (materialURL != _materialURL) {
|
||||
_materialURL = materialURL;
|
||||
if (_materialURL.contains("#")) {
|
||||
auto split = _materialURL.split("#");
|
||||
newCurrentMaterialName = split.last().toStdString();
|
||||
} else if (_materialURL.contains("?")) {
|
||||
qDebug() << "DEPRECATED: Use # instead of ? for material URLS:" << _materialURL;
|
||||
auto split = _materialURL.split("?");
|
||||
newCurrentMaterialName = split.last().toStdString();
|
||||
}
|
||||
urlChanged = true;
|
||||
bool urlChanged = false;
|
||||
std::string newCurrentMaterialName = _currentMaterialName;
|
||||
{
|
||||
QString materialURL = entity->getMaterialURL();
|
||||
if (materialURL != _materialURL) {
|
||||
_materialURL = materialURL;
|
||||
if (_materialURL.contains("#")) {
|
||||
auto split = _materialURL.split("#");
|
||||
newCurrentMaterialName = split.last().toStdString();
|
||||
} else if (_materialURL.contains("?")) {
|
||||
qDebug() << "DEPRECATED: Use # instead of ? for material URLS:" << _materialURL;
|
||||
auto split = _materialURL.split("?");
|
||||
newCurrentMaterialName = split.last().toStdString();
|
||||
}
|
||||
urlChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool usingMaterialData = _materialURL.startsWith("materialData");
|
||||
bool materialDataChanged = false;
|
||||
QUuid oldParentID = _parentID;
|
||||
QString oldParentMaterialName = _parentMaterialName;
|
||||
{
|
||||
QString materialData = entity->getMaterialData();
|
||||
if (materialData != _materialData) {
|
||||
_materialData = materialData;
|
||||
if (usingMaterialData) {
|
||||
materialDataChanged = true;
|
||||
}
|
||||
bool usingMaterialData = _materialURL.startsWith("materialData");
|
||||
bool materialDataChanged = false;
|
||||
QUuid oldParentID = _parentID;
|
||||
QString oldParentMaterialName = _parentMaterialName;
|
||||
{
|
||||
QString materialData = entity->getMaterialData();
|
||||
if (materialData != _materialData) {
|
||||
_materialData = materialData;
|
||||
if (usingMaterialData) {
|
||||
materialDataChanged = true;
|
||||
}
|
||||
}
|
||||
{
|
||||
QString parentMaterialName = entity->getParentMaterialName();
|
||||
if (parentMaterialName != _parentMaterialName) {
|
||||
_parentMaterialName = parentMaterialName;
|
||||
deleteNeeded = true;
|
||||
addNeeded = true;
|
||||
}
|
||||
}
|
||||
{
|
||||
QString parentMaterialName = entity->getParentMaterialName();
|
||||
if (parentMaterialName != _parentMaterialName) {
|
||||
_parentMaterialName = parentMaterialName;
|
||||
deleteNeeded = true;
|
||||
addNeeded = true;
|
||||
}
|
||||
{
|
||||
QUuid parentID = entity->getParentID();
|
||||
if (parentID != _parentID) {
|
||||
_parentID = parentID;
|
||||
deleteNeeded = true;
|
||||
addNeeded = true;
|
||||
}
|
||||
}
|
||||
{
|
||||
QUuid parentID = entity->getParentID();
|
||||
if (parentID != _parentID) {
|
||||
_parentID = parentID;
|
||||
deleteNeeded = true;
|
||||
addNeeded = true;
|
||||
}
|
||||
{
|
||||
quint16 priority = entity->getPriority();
|
||||
if (priority != _priority) {
|
||||
_priority = priority;
|
||||
deleteNeeded = true;
|
||||
addNeeded = true;
|
||||
}
|
||||
}
|
||||
{
|
||||
quint16 priority = entity->getPriority();
|
||||
if (priority != _priority) {
|
||||
_priority = priority;
|
||||
deleteNeeded = true;
|
||||
addNeeded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (urlChanged && !usingMaterialData) {
|
||||
_networkMaterial = DependencyManager::get<MaterialCache>()->getMaterial(_materialURL);
|
||||
auto onMaterialRequestFinished = [this, entity, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) {
|
||||
if (success) {
|
||||
deleteMaterial(oldParentID, oldParentMaterialName);
|
||||
_texturesLoaded = false;
|
||||
_parsedMaterials = _networkMaterial->parsedMaterials;
|
||||
setCurrentMaterialName(newCurrentMaterialName);
|
||||
applyMaterial(entity);
|
||||
} else {
|
||||
deleteMaterial(oldParentID, oldParentMaterialName);
|
||||
_retryApply = false;
|
||||
_texturesLoaded = true;
|
||||
}
|
||||
};
|
||||
if (_networkMaterial) {
|
||||
if (_networkMaterial->isLoaded()) {
|
||||
onMaterialRequestFinished(!_networkMaterial->isFailed());
|
||||
} else {
|
||||
connect(_networkMaterial.data(), &Resource::finished, this, [this, onMaterialRequestFinished](bool success) {
|
||||
withWriteLock([&] {
|
||||
onMaterialRequestFinished(success);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (materialDataChanged && usingMaterialData) {
|
||||
if (urlChanged && !usingMaterialData) {
|
||||
_networkMaterial = DependencyManager::get<MaterialCache>()->getMaterial(_materialURL);
|
||||
auto onMaterialRequestFinished = [this, entity, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) {
|
||||
deleteMaterial(oldParentID, oldParentMaterialName);
|
||||
_texturesLoaded = false;
|
||||
_parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(_materialData.toUtf8()), _materialURL);
|
||||
// Since our material changed, the current name might not be valid anymore, so we need to update
|
||||
setCurrentMaterialName(newCurrentMaterialName);
|
||||
applyMaterial(entity);
|
||||
} else {
|
||||
if (deleteNeeded) {
|
||||
deleteMaterial(oldParentID, oldParentMaterialName);
|
||||
}
|
||||
if (addNeeded) {
|
||||
if (success) {
|
||||
_texturesLoaded = false;
|
||||
_parsedMaterials = _networkMaterial->parsedMaterials;
|
||||
setCurrentMaterialName(newCurrentMaterialName);
|
||||
applyMaterial(entity);
|
||||
emit requestRenderUpdate();
|
||||
} else {
|
||||
_retryApply = false;
|
||||
_texturesLoaded = true;
|
||||
}
|
||||
};
|
||||
if (_networkMaterial) {
|
||||
if (_networkMaterial->isLoaded()) {
|
||||
onMaterialRequestFinished(!_networkMaterial->isFailed());
|
||||
} else {
|
||||
connect(_networkMaterial.data(), &Resource::finished, this, [this, onMaterialRequestFinished](bool success) {
|
||||
onMaterialRequestFinished(success);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto material = getMaterial();
|
||||
bool newTexturesLoaded = material ? !material->isMissingTexture() : false;
|
||||
if (!_texturesLoaded && newTexturesLoaded) {
|
||||
material->checkResetOpacityMap();
|
||||
}
|
||||
_texturesLoaded = newTexturesLoaded;
|
||||
} else if (materialDataChanged && usingMaterialData) {
|
||||
deleteMaterial(oldParentID, oldParentMaterialName);
|
||||
_texturesLoaded = false;
|
||||
_parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(_materialData.toUtf8()), _materialURL);
|
||||
// Since our material changed, the current name might not be valid anymore, so we need to update
|
||||
setCurrentMaterialName(newCurrentMaterialName);
|
||||
applyMaterial(entity);
|
||||
} else {
|
||||
if (deleteNeeded) {
|
||||
deleteMaterial(oldParentID, oldParentMaterialName);
|
||||
}
|
||||
if (addNeeded) {
|
||||
applyMaterial(entity);
|
||||
}
|
||||
}
|
||||
|
||||
_renderTransform = getModelTransform();
|
||||
const float MATERIAL_ENTITY_SCALE = 0.5f;
|
||||
_renderTransform.postScale(MATERIAL_ENTITY_SCALE);
|
||||
_renderTransform.postScale(ENTITY_ITEM_DEFAULT_DIMENSIONS);
|
||||
});
|
||||
{
|
||||
auto material = getMaterial();
|
||||
bool newTexturesLoaded = material ? !material->isMissingTexture() : false;
|
||||
if (!_texturesLoaded && newTexturesLoaded) {
|
||||
material->checkResetOpacityMap();
|
||||
}
|
||||
_texturesLoaded = newTexturesLoaded;
|
||||
}
|
||||
|
||||
if (!_texturesLoaded || _retryApply) {
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
ItemKey MaterialEntityRenderer::getKey() {
|
||||
|
@ -268,33 +248,30 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
|
|||
gpu::Batch& batch = *args->_batch;
|
||||
|
||||
// Don't render if our parent is set or our material is null
|
||||
QUuid parentID;
|
||||
withReadLock([&] {
|
||||
parentID = _parentID;
|
||||
});
|
||||
if (!parentID.isNull()) {
|
||||
if (!_parentID.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Transform renderTransform;
|
||||
graphics::MaterialPointer drawMaterial;
|
||||
graphics::MaterialPointer drawMaterial = getMaterial();
|
||||
bool proceduralRender = false;
|
||||
Transform textureTransform;
|
||||
textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0));
|
||||
textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialMappingRot)));
|
||||
textureTransform.setScale(glm::vec3(_materialMappingScale, 1));
|
||||
|
||||
Transform renderTransform;
|
||||
withReadLock([&] {
|
||||
renderTransform = _renderTransform;
|
||||
drawMaterial = getMaterial();
|
||||
textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0));
|
||||
textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialMappingRot)));
|
||||
textureTransform.setScale(glm::vec3(_materialMappingScale, 1));
|
||||
|
||||
if (drawMaterial && drawMaterial->isProcedural() && drawMaterial->isReady()) {
|
||||
proceduralRender = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!drawMaterial) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (drawMaterial->isProcedural() && drawMaterial->isReady()) {
|
||||
proceduralRender = true;
|
||||
}
|
||||
|
||||
batch.setModelTransform(renderTransform);
|
||||
|
||||
if (!proceduralRender) {
|
||||
|
|
|
@ -27,8 +27,7 @@ public:
|
|||
~MaterialEntityRenderer() { deleteMaterial(_parentID, _parentMaterialName); }
|
||||
|
||||
private:
|
||||
virtual bool needsRenderUpdate() const override;
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
||||
|
|
|
@ -51,12 +51,6 @@ ModelPointer ModelEntityWrapper::getModel() const {
|
|||
});
|
||||
}
|
||||
|
||||
bool ModelEntityWrapper::isModelLoaded() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _model.operator bool() && _model->isLoaded();
|
||||
});
|
||||
}
|
||||
|
||||
EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity(new RenderableModelEntityItem(entityID, properties.getDimensionsInitialized()),
|
||||
[](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
|
@ -69,8 +63,7 @@ EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityI
|
|||
RenderableModelEntityItem::RenderableModelEntityItem(const EntityItemID& entityItemID, bool dimensionsInitialized) :
|
||||
ModelEntityWrapper(entityItemID),
|
||||
_dimensionsInitialized(dimensionsInitialized) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
RenderableModelEntityItem::~RenderableModelEntityItem() { }
|
||||
|
@ -83,34 +76,6 @@ void RenderableModelEntityItem::setUnscaledDimensions(const glm::vec3& value) {
|
|||
}
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::doInitialModelSimulation() {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
ModelPointer model = getModel();
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
// The machinery for updateModelBounds will give existing models the opportunity to fix their
|
||||
// translation/rotation/scale/registration. The first two are straightforward, but the latter two have guards to
|
||||
// make sure they don't happen after they've already been set. Here we reset those guards. This doesn't cause the
|
||||
// entity values to change -- it just allows the model to match once it comes in.
|
||||
model->setScaleToFit(false, getScaledDimensions());
|
||||
model->setSnapModelToRegistrationPoint(false, getRegistrationPoint());
|
||||
|
||||
// now recalculate the bounds and registration
|
||||
model->setScaleToFit(true, getScaledDimensions());
|
||||
model->setSnapModelToRegistrationPoint(true, getRegistrationPoint());
|
||||
model->setRotation(getWorldOrientation());
|
||||
model->setTranslation(getWorldPosition());
|
||||
|
||||
glm::vec3 scale = model->getScale();
|
||||
model->setUseDualQuaternionSkinning(!isNonUniformScale(scale));
|
||||
|
||||
if (_needsInitialSimulation) {
|
||||
model->simulate(0.0f);
|
||||
_needsInitialSimulation = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::autoResizeJointArrays() {
|
||||
ModelPointer model = getModel();
|
||||
if (model && model->isLoaded() && !_needsInitialSimulation) {
|
||||
|
@ -125,7 +90,7 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!_dimensionsInitialized || !model->isActive()) {
|
||||
if (!_dimensionsInitialized || !model->isLoaded()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -182,22 +147,25 @@ void RenderableModelEntityItem::updateModelBounds() {
|
|||
}
|
||||
|
||||
bool overridingModelTransform = model->isOverridingModelTransformAndOffset();
|
||||
glm::vec3 scaledDimensions = getScaledDimensions();
|
||||
glm::vec3 registrationPoint = getRegistrationPoint();
|
||||
if (!overridingModelTransform &&
|
||||
(model->getScaleToFitDimensions() != getScaledDimensions() ||
|
||||
model->getRegistrationPoint() != getRegistrationPoint() ||
|
||||
!model->getIsScaledToFit())) {
|
||||
(model->getScaleToFitDimensions() != scaledDimensions ||
|
||||
model->getRegistrationPoint() != registrationPoint ||
|
||||
!model->getIsScaledToFit() || _needsToRescaleModel)) {
|
||||
// The machinery for updateModelBounds will give existing models the opportunity to fix their
|
||||
// translation/rotation/scale/registration. The first two are straightforward, but the latter two
|
||||
// have guards to make sure they don't happen after they've already been set. Here we reset those guards.
|
||||
// This doesn't cause the entity values to change -- it just allows the model to match once it comes in.
|
||||
model->setScaleToFit(false, getScaledDimensions());
|
||||
model->setSnapModelToRegistrationPoint(false, getRegistrationPoint());
|
||||
model->setScaleToFit(false, scaledDimensions);
|
||||
model->setSnapModelToRegistrationPoint(false, registrationPoint);
|
||||
|
||||
// now recalculate the bounds and registration
|
||||
model->setScaleToFit(true, getScaledDimensions());
|
||||
model->setSnapModelToRegistrationPoint(true, getRegistrationPoint());
|
||||
model->setScaleToFit(true, scaledDimensions);
|
||||
model->setSnapModelToRegistrationPoint(true, registrationPoint);
|
||||
updateRenderItems = true;
|
||||
model->scaleToFit();
|
||||
_needsToRescaleModel = false;
|
||||
}
|
||||
|
||||
bool success;
|
||||
|
@ -221,6 +189,9 @@ void RenderableModelEntityItem::updateModelBounds() {
|
|||
glm::vec3 scale = model->getScale();
|
||||
model->setUseDualQuaternionSkinning(!isNonUniformScale(scale));
|
||||
model->updateRenderItems();
|
||||
|
||||
markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
|
||||
locationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,8 +219,6 @@ EntityItemProperties RenderableModelEntityItem::getProperties(const EntityProper
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -261,7 +230,7 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori
|
|||
OctreeElementPointer& element, float& distance, BoxFace& face,
|
||||
glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const {
|
||||
auto model = getModel();
|
||||
if (!model || !isModelLoaded()) {
|
||||
if (!model || !model->isLoaded()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -273,7 +242,7 @@ bool RenderableModelEntityItem::findDetailedParabolaIntersection(const glm::vec3
|
|||
const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face,
|
||||
glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const {
|
||||
auto model = getModel();
|
||||
if (!model || !isModelLoaded()) {
|
||||
if (!model || !model->isLoaded()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -281,8 +250,23 @@ bool RenderableModelEntityItem::findDetailedParabolaIntersection(const glm::vec3
|
|||
face, surfaceNormal, extraInfo, precisionPicking, false);
|
||||
}
|
||||
|
||||
QString RenderableModelEntityItem::getCollisionShapeURL() const {
|
||||
return getShapeType() == SHAPE_TYPE_COMPOUND ? getCompoundShapeURL() : getModelURL();
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::fetchCollisionGeometryResource() {
|
||||
_collisionGeometryResource = DependencyManager::get<ModelCache>()->getCollisionGeometryResource(getCollisionShapeURL());
|
||||
if (_collisionGeometryResource) {
|
||||
if (_collisionGeometryResource->isLoaded()) {
|
||||
markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
|
||||
locationChanged();
|
||||
} else {
|
||||
connect(_collisionGeometryResource.get(), &GeometryResource::finished, this, [&] {
|
||||
markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
|
||||
locationChanged();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderableModelEntityItem::unableToLoadCollisionShape() {
|
||||
|
@ -299,7 +283,7 @@ void RenderableModelEntityItem::setShapeType(ShapeType type) {
|
|||
if (!_collisionGeometryResource && !getCollisionShapeURL().isEmpty()) {
|
||||
fetchCollisionGeometryResource();
|
||||
}
|
||||
} else if (_collisionGeometryResource && !getCompoundShapeURL().isEmpty()) {
|
||||
} else if (_collisionGeometryResource) {
|
||||
// the compoundURL has been set but the shapeType does not agree
|
||||
_collisionGeometryResource.reset();
|
||||
}
|
||||
|
@ -308,49 +292,43 @@ void RenderableModelEntityItem::setShapeType(ShapeType type) {
|
|||
void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) {
|
||||
auto currentCompoundShapeURL = getCompoundShapeURL();
|
||||
ModelEntityItem::setCompoundShapeURL(url);
|
||||
if (getCompoundShapeURL() != currentCompoundShapeURL || !getModel()) {
|
||||
if (getShapeType() == SHAPE_TYPE_COMPOUND) {
|
||||
if (url != currentCompoundShapeURL && !url.isEmpty()) {
|
||||
auto shapeType = getShapeType();
|
||||
if (shapeType == SHAPE_TYPE_COMPOUND) {
|
||||
fetchCollisionGeometryResource();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::setModelURL(const QString& url) {
|
||||
auto currentModelURL = getModelURL();
|
||||
ModelEntityItem::setModelURL(url);
|
||||
if (url != currentModelURL && !url.isEmpty()) {
|
||||
auto shapeType = getShapeType();
|
||||
if (shapeType == SHAPE_TYPE_SIMPLE_COMPOUND) {
|
||||
fetchCollisionGeometryResource();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderableModelEntityItem::isReadyToComputeShape() const {
|
||||
ShapeType type = getShapeType();
|
||||
auto model = getModel();
|
||||
auto shapeType = getShapeType();
|
||||
if (shapeType == SHAPE_TYPE_COMPOUND || shapeType == SHAPE_TYPE_SIMPLE_COMPOUND) {
|
||||
auto shapeURL = getCollisionShapeURL();
|
||||
|
||||
if (!model || shapeURL.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (model->getURL().isEmpty() || !_dimensionsInitialized) {
|
||||
// we need a render geometry with a scale to proceed, so give up.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (model->isLoaded()) {
|
||||
if (!shapeURL.isEmpty() && !_collisionGeometryResource) {
|
||||
// we need a render geometry with a scale to proceed
|
||||
if (model && !model->getURL().isEmpty() && !shapeURL.isEmpty() && _dimensionsInitialized && model->isLoaded()) {
|
||||
if (!_collisionGeometryResource) {
|
||||
const_cast<RenderableModelEntityItem*>(this)->fetchCollisionGeometryResource();
|
||||
}
|
||||
|
||||
if (_collisionGeometryResource && _collisionGeometryResource->isLoaded()) {
|
||||
// we have both URLs AND both geometries AND they are both fully loaded.
|
||||
if (_needsInitialSimulation) {
|
||||
// the _model's offset will be wrong until _needsInitialSimulation is false
|
||||
DETAILED_PERFORMANCE_TIMER("_model->simulate");
|
||||
const_cast<RenderableModelEntityItem*>(this)->doInitialModelSimulation();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// do we have both URLs AND both geometries AND they are both fully loaded?
|
||||
return _collisionGeometryResource && _collisionGeometryResource->isLoaded() && _collisionGeometryResource->isHFMModelLoaded();
|
||||
}
|
||||
|
||||
// the model is still being downloaded.
|
||||
return false;
|
||||
} else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) {
|
||||
return isModelLoaded();
|
||||
} else if (shapeType >= SHAPE_TYPE_SIMPLE_HULL && shapeType <= SHAPE_TYPE_STATIC_MESH) {
|
||||
return model && model->isLoaded() && _dimensionsInitialized;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -362,20 +340,31 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
ShapeType type = getShapeType();
|
||||
|
||||
auto model = getModel();
|
||||
if (!model || !model->isLoaded()) {
|
||||
type = SHAPE_TYPE_NONE;
|
||||
if (type >= SHAPE_TYPE_COMPOUND && type <= SHAPE_TYPE_STATIC_MESH) {
|
||||
if (!model) {
|
||||
type = SHAPE_TYPE_NONE;
|
||||
} else if (!model->isLoaded()) {
|
||||
type = SHAPE_TYPE_NONE;
|
||||
if (!model->didVisualGeometryRequestFail()) {
|
||||
markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
|
||||
locationChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type == SHAPE_TYPE_COMPOUND || type == SHAPE_TYPE_SIMPLE_COMPOUND) {
|
||||
if (!_collisionGeometryResource || !_collisionGeometryResource->isLoaded() || !_collisionGeometryResource->isHFMModelLoaded()) {
|
||||
type = SHAPE_TYPE_NONE;
|
||||
if (!_collisionGeometryResource->isFailed()) {
|
||||
markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
|
||||
locationChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type == SHAPE_TYPE_COMPOUND) {
|
||||
if (!_collisionGeometryResource || !_collisionGeometryResource->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateModelBounds();
|
||||
|
||||
// should never fall in here when collision model not fully loaded
|
||||
// TODO: assert that all geometries exist and are loaded
|
||||
//assert(_model && _model->isLoaded() && _collisionGeometryResource && _collisionGeometryResource->isLoaded());
|
||||
const HFMModel& collisionGeometry = _collisionGeometryResource->getHFMModel();
|
||||
|
||||
ShapeInfo::PointCollection& pointCollection = shapeInfo.getPointCollection();
|
||||
|
@ -452,7 +441,8 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
// collision model's extents).
|
||||
|
||||
glm::vec3 dimensions = getScaledDimensions();
|
||||
glm::vec3 scaleToFit = dimensions / model->getHFMModel().getUnscaledMeshExtents().size();
|
||||
glm::vec3 extents = model->getHFMModel().getUnscaledMeshExtents().size();
|
||||
glm::vec3 scaleToFit = dimensions / extents;
|
||||
// multiply each point by scale before handing the point-set off to the physics engine.
|
||||
// also determine the extents of the collision model.
|
||||
glm::vec3 registrationOffset = dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint());
|
||||
|
@ -462,12 +452,10 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
pointCollection[i][j] = scaleToFit * (pointCollection[i][j] + model->getOffset()) - registrationOffset;
|
||||
}
|
||||
}
|
||||
shapeInfo.setParams(type, dimensions, getCompoundShapeURL());
|
||||
shapeInfo.setParams(type, 0.5f * extents, getCompoundShapeURL());
|
||||
adjustShapeInfoByRegistration(shapeInfo);
|
||||
} else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) {
|
||||
updateModelBounds();
|
||||
// assert we never fall in here when model not fully loaded
|
||||
assert(model && model->isLoaded());
|
||||
model->updateGeometry();
|
||||
|
||||
// compute meshPart local transforms
|
||||
|
@ -476,16 +464,16 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
int numHFMMeshes = hfmModel.meshes.size();
|
||||
int totalNumVertices = 0;
|
||||
glm::vec3 dimensions = getScaledDimensions();
|
||||
glm::mat4 invRegistraionOffset = glm::translate(dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT));
|
||||
glm::mat4 invRegistrationOffset = glm::translate(dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT));
|
||||
for (int i = 0; i < numHFMMeshes; i++) {
|
||||
const HFMMesh& mesh = hfmModel.meshes.at(i);
|
||||
if (mesh.clusters.size() > 0) {
|
||||
const HFMCluster& cluster = mesh.clusters.at(0);
|
||||
auto jointMatrix = model->getRig().getJointTransform(cluster.jointIndex);
|
||||
// we backtranslate by the registration offset so we can apply that offset to the shapeInfo later
|
||||
localTransforms.push_back(invRegistraionOffset * jointMatrix * cluster.inverseBindMatrix);
|
||||
localTransforms.push_back(invRegistrationOffset * jointMatrix * cluster.inverseBindMatrix);
|
||||
} else {
|
||||
localTransforms.push_back(invRegistraionOffset);
|
||||
localTransforms.push_back(invRegistrationOffset);
|
||||
}
|
||||
totalNumVertices += mesh.vertices.size();
|
||||
}
|
||||
|
@ -697,7 +685,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
}
|
||||
}
|
||||
|
||||
shapeInfo.setParams(type, 0.5f * dimensions, getModelURL());
|
||||
shapeInfo.setParams(type, 0.5f * extents.size(), getModelURL());
|
||||
adjustShapeInfoByRegistration(shapeInfo);
|
||||
} else {
|
||||
EntityItem::computeShapeInfo(shapeInfo);
|
||||
|
@ -716,8 +704,8 @@ void RenderableModelEntityItem::setJointMap(std::vector<int> jointMap) {
|
|||
|
||||
int RenderableModelEntityItem::avatarJointIndex(int modelJointIndex) {
|
||||
int result = -1;
|
||||
int mapSize = (int) _jointMap.size();
|
||||
if (modelJointIndex >=0 && modelJointIndex < mapSize) {
|
||||
int mapSize = (int)_jointMap.size();
|
||||
if (modelJointIndex >= 0 && modelJointIndex < mapSize) {
|
||||
result = _jointMap[modelJointIndex];
|
||||
}
|
||||
|
||||
|
@ -726,28 +714,44 @@ int RenderableModelEntityItem::avatarJointIndex(int modelJointIndex) {
|
|||
|
||||
bool RenderableModelEntityItem::contains(const glm::vec3& point) const {
|
||||
auto model = getModel();
|
||||
if (EntityItem::contains(point) && model && _collisionGeometryResource && _collisionGeometryResource->isLoaded()) {
|
||||
glm::mat4 worldToHFMMatrix = model->getWorldToHFMMatrix();
|
||||
glm::vec3 hfmPoint = worldToHFMMatrix * glm::vec4(point, 1.0f);
|
||||
return _collisionGeometryResource->getHFMModel().convexHullContains(hfmPoint);
|
||||
if (model && model->isLoaded()) {
|
||||
auto shapeType = getShapeType();
|
||||
if (shapeType == SHAPE_TYPE_COMPOUND || shapeType == SHAPE_TYPE_SIMPLE_COMPOUND) {
|
||||
if (_collisionGeometryResource && _collisionGeometryResource->isLoaded() && _collisionGeometryResource->isHFMModelLoaded() && EntityItem::contains(point)) {
|
||||
glm::mat4 worldToHFMMatrix = model->getWorldToHFMMatrix();
|
||||
glm::vec3 hfmPoint = worldToHFMMatrix * glm::vec4(point, 1.0f);
|
||||
return _collisionGeometryResource->getHFMModel().convexHullContains(hfmPoint);
|
||||
}
|
||||
} else if (shapeType >= SHAPE_TYPE_SIMPLE_HULL && shapeType <= SHAPE_TYPE_STATIC_MESH) {
|
||||
if (EntityItem::contains(point)) {
|
||||
glm::mat4 worldToHFMMatrix = model->getWorldToHFMMatrix();
|
||||
glm::vec3 hfmPoint = worldToHFMMatrix * glm::vec4(point, 1.0f);
|
||||
return model->getHFMModel().convexHullContains(hfmPoint);
|
||||
}
|
||||
} else {
|
||||
return EntityItem::contains(point);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RenderableModelEntityItem::shouldBePhysical() const {
|
||||
auto model = getModel();
|
||||
// If we have a model, make sure it hasn't failed to download.
|
||||
// If it has, we'll report back that we shouldn't be physical so that physics aren't held waiting for us to be ready.
|
||||
bool physicalModelLoaded = false;
|
||||
ShapeType shapeType = getShapeType();
|
||||
if (model) {
|
||||
if ((shapeType == SHAPE_TYPE_COMPOUND || shapeType == SHAPE_TYPE_SIMPLE_COMPOUND) && model->didCollisionGeometryRequestFail()) {
|
||||
return false;
|
||||
} else if (shapeType != SHAPE_TYPE_NONE && model->didVisualGeometryRequestFail()) {
|
||||
return false;
|
||||
if (shapeType >= SHAPE_TYPE_COMPOUND && shapeType <= SHAPE_TYPE_STATIC_MESH) {
|
||||
auto model = getModel();
|
||||
// If we have a model, make sure it hasn't failed to download.
|
||||
// If it has, we'll report back that we shouldn't be physical so that physics aren't held waiting for us to be ready.
|
||||
physicalModelLoaded = model && !model->didVisualGeometryRequestFail();
|
||||
if (shapeType == SHAPE_TYPE_COMPOUND || shapeType == SHAPE_TYPE_SIMPLE_COMPOUND) {
|
||||
physicalModelLoaded &= _collisionGeometryResource && !_collisionGeometryResource->isFailed();
|
||||
}
|
||||
} else if (shapeType != SHAPE_TYPE_NONE) {
|
||||
physicalModelLoaded = true;
|
||||
}
|
||||
return !isDead() && shapeType != SHAPE_TYPE_NONE && !isLocalEntity() && QUrl(_modelURL).isValid();
|
||||
|
||||
return physicalModelLoaded && !isDead() && !isLocalEntity() && QUrl(getModelURL()).isValid();
|
||||
}
|
||||
|
||||
int RenderableModelEntityItem::getJointParent(int index) const {
|
||||
|
@ -943,13 +947,13 @@ void RenderableModelEntityItem::locationChanged(bool tellPhysics, bool tellChild
|
|||
|
||||
int RenderableModelEntityItem::getJointIndex(const QString& name) const {
|
||||
auto model = getModel();
|
||||
return (model && model->isActive()) ? model->getRig().indexOfJoint(name) : -1;
|
||||
return (model && model->isLoaded()) ? model->getRig().indexOfJoint(name) : -1;
|
||||
}
|
||||
|
||||
QStringList RenderableModelEntityItem::getJointNames() const {
|
||||
QStringList result;
|
||||
auto model = getModel();
|
||||
if (model && model->isActive()) {
|
||||
if (model && model->isLoaded()) {
|
||||
const Rig& rig = model->getRig();
|
||||
int jointCount = rig.getJointStateCount();
|
||||
for (int jointIndex = 0; jointIndex < jointCount; jointIndex++) {
|
||||
|
@ -960,13 +964,13 @@ QStringList RenderableModelEntityItem::getJointNames() const {
|
|||
}
|
||||
|
||||
scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScriptableModel() {
|
||||
auto model = resultWithReadLock<ModelPointer>([this]{ return _model; });
|
||||
auto model = resultWithReadLock<ModelPointer>([&] { return _model; });
|
||||
|
||||
if (!model || !model->isLoaded()) {
|
||||
return scriptable::ScriptableModelBase();
|
||||
}
|
||||
|
||||
auto result = _model->getScriptableModel();
|
||||
auto result = model->getScriptableModel();
|
||||
result.objectID = getEntity()->getID();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||
|
@ -1036,7 +1040,7 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() {
|
|||
});
|
||||
|
||||
if (changed) {
|
||||
locationChanged(true, true);
|
||||
locationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1054,10 +1058,14 @@ ModelEntityRenderer::ModelEntityRenderer(const EntityItemPointer& entity) : Pare
|
|||
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed) {
|
||||
void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed, const ModelPointer& model) {
|
||||
auto builder = ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
||||
|
||||
if (!_cullWithParent && _model && _model->isGroupCulled()) {
|
||||
if (!_visible) {
|
||||
builder.withInvisible();
|
||||
}
|
||||
|
||||
if (!_cullWithParent && model && model->isGroupCulled()) {
|
||||
builder.withMetaCullGroup();
|
||||
} else if (_cullWithParent) {
|
||||
builder.withSubMetaCulled();
|
||||
|
@ -1075,8 +1083,9 @@ ItemKey ModelEntityRenderer::getKey() {
|
|||
}
|
||||
|
||||
uint32_t ModelEntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const {
|
||||
if (_model) {
|
||||
auto metaSubItems = _model->fetchRenderItemIDs();
|
||||
auto model = resultWithReadLock<ModelPointer>([&] { return _model; });
|
||||
if (model) {
|
||||
auto metaSubItems = model->fetchRenderItemIDs();
|
||||
subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end());
|
||||
return (uint32_t)metaSubItems.size();
|
||||
}
|
||||
|
@ -1089,8 +1098,9 @@ void ModelEntityRenderer::handleBlendedVertices(int blendshapeNumber, const QVec
|
|||
}
|
||||
|
||||
void ModelEntityRenderer::removeFromScene(const ScenePointer& scene, Transaction& transaction) {
|
||||
if (_model) {
|
||||
_model->removeFromScene(scene, transaction);
|
||||
auto model = resultWithReadLock<ModelPointer>([&] { return _model; });
|
||||
if (model) {
|
||||
model->removeFromScene(scene, transaction);
|
||||
}
|
||||
Parent::removeFromScene(scene, transaction);
|
||||
}
|
||||
|
@ -1099,14 +1109,14 @@ void ModelEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entit
|
|||
entity->setModel({});
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
|
||||
void ModelEntityRenderer::animate(const TypedEntityPointer& entity, const ModelPointer& model) {
|
||||
if (!_animation || !_animation->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QVector<EntityJointData> jointsData;
|
||||
|
||||
const QVector<HFMAnimationFrame>& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
|
||||
const QVector<HFMAnimationFrame>& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
|
||||
int frameCount = frames.size();
|
||||
if (frameCount <= 0) {
|
||||
return;
|
||||
|
@ -1124,17 +1134,17 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
|
|||
_lastKnownCurrentFrame = currentIntegerFrame;
|
||||
}
|
||||
|
||||
if (_jointMapping.size() != _model->getJointStateCount()) {
|
||||
if (_jointMapping.size() != model->getJointStateCount()) {
|
||||
qCWarning(entitiesrenderer) << "RenderableModelEntityItem::getAnimationFrame -- joint count mismatch"
|
||||
<< _jointMapping.size() << _model->getJointStateCount();
|
||||
<< _jointMapping.size() << model->getJointStateCount();
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList animationJointNames = _animation->getHFMModel().getJointNames();
|
||||
auto& hfmJoints = _animation->getHFMModel().joints;
|
||||
|
||||
auto& originalHFMJoints = _model->getHFMModel().joints;
|
||||
auto& originalHFMIndices = _model->getHFMModel().jointIndices;
|
||||
auto& originalHFMJoints = model->getHFMModel().joints;
|
||||
auto& originalHFMIndices = model->getHFMModel().jointIndices;
|
||||
|
||||
bool allowTranslation = entity->getAnimationAllowTranslation();
|
||||
|
||||
|
@ -1182,146 +1192,49 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
|
|||
entity->copyAnimationJointDataToModel();
|
||||
}
|
||||
|
||||
bool ModelEntityRenderer::needsRenderUpdate() const {
|
||||
if (resultWithReadLock<bool>([&] {
|
||||
if (_moving || _animating) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_texturesLoaded) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_prevModelLoaded) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})) {
|
||||
bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
if (entity->blendshapesChanged()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ModelPointer model;
|
||||
QUrl parsedModelURL;
|
||||
withReadLock([&] {
|
||||
model = _model;
|
||||
parsedModelURL = _parsedModelURL;
|
||||
});
|
||||
|
||||
if (model) {
|
||||
// When the individual mesh parts of a model finish fading, they will mark their Model as needing updating
|
||||
// we will watch for that and ask the model to update it's render items
|
||||
if (parsedModelURL != model->getURL()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (model->needsReload()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (model->needsFixupInScene()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (model->getRenderItemsNeedUpdate()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return Parent::needsRenderUpdate();
|
||||
}
|
||||
|
||||
bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
if (resultWithReadLock<bool>([&] {
|
||||
if (entity->hasModel() != _hasModel) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// No model to render, early exit
|
||||
if (!_hasModel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_animating != entity->isAnimatingSomething()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})) { return true; }
|
||||
|
||||
ModelPointer model;
|
||||
withReadLock([&] {
|
||||
model = _model;
|
||||
});
|
||||
|
||||
if (model && model->isLoaded()) {
|
||||
if (!entity->_dimensionsInitialized || entity->_needsInitialSimulation || !entity->_originalTexturesRead) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (entity->blendshapesChanged()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check to see if we need to update the model bounds
|
||||
if (entity->needsUpdateModelBounds()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check to see if we need to update the model bounds
|
||||
auto transform = entity->getTransform();
|
||||
if (model->getTranslation() != transform.getTranslation() ||
|
||||
model->getRotation() != transform.getRotation()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (model->getScaleToFitDimensions() != entity->getScaledDimensions() ||
|
||||
model->getRegistrationPoint() != entity->getRegistrationPoint()) {
|
||||
return true;
|
||||
}
|
||||
// Check to see if we need to update the model bounds
|
||||
if (entity->needsUpdateModelBounds()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return Parent::needsRenderUpdateFromTypedEntity(entity);
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
void ModelEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
if (_hasModel != entity->hasModel()) {
|
||||
withWriteLock([&] {
|
||||
_hasModel = entity->hasModel();
|
||||
});
|
||||
|
||||
_hasModel = entity->hasModel();
|
||||
QUrl modelURL = QUrl(entity->getModelURL());
|
||||
if (_parsedModelURL != modelURL) {
|
||||
_parsedModelURL = modelURL;
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
_animating = entity->isAnimatingSomething();
|
||||
if (_parsedModelURL != entity->getModelURL()) {
|
||||
_parsedModelURL = QUrl(entity->getModelURL());
|
||||
}
|
||||
ModelPointer model = resultWithReadLock<ModelPointer>([&] {
|
||||
return _model;
|
||||
});
|
||||
|
||||
ModelPointer model;
|
||||
withReadLock([&] { model = _model; });
|
||||
bool visuallyReady = model && model->isLoaded() && _didLastVisualGeometryRequestSucceed && _texturesLoaded;
|
||||
entity->setVisuallyReady(visuallyReady);
|
||||
|
||||
withWriteLock([&] {
|
||||
bool visuallyReady = true;
|
||||
if (_hasModel) {
|
||||
if (model && _didLastVisualGeometryRequestSucceed) {
|
||||
visuallyReady = (_prevModelLoaded && _texturesLoaded);
|
||||
}
|
||||
}
|
||||
entity->setVisuallyReady(visuallyReady);
|
||||
});
|
||||
const render::ScenePointer& scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
|
||||
// Check for removal
|
||||
if (!_hasModel) {
|
||||
if (model) {
|
||||
model->removeFromScene(scene, transaction);
|
||||
entity->bumpAncestorChainRenderableVersion();
|
||||
withWriteLock([&] { _model.reset(); });
|
||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
|
||||
modelRemovedFromScene(entity->getEntityItemID(), NestableType::Entity, _model);
|
||||
modelRemovedFromScene(entity->getEntityItemID(), NestableType::Entity, model);
|
||||
withWriteLock([&] { _model.reset(); });
|
||||
}
|
||||
setKey(false);
|
||||
_didLastVisualGeometryRequestSucceed = false;
|
||||
setKey(_didLastVisualGeometryRequestSucceed, model);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1330,48 +1243,52 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
model = std::make_shared<Model>(nullptr, entity.get(), _created);
|
||||
connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate);
|
||||
connect(model.get(), &Model::setURLFinished, this, [&](bool didVisualGeometryRequestSucceed) {
|
||||
setKey(didVisualGeometryRequestSucceed);
|
||||
_model->setTagMask(getTagMask());
|
||||
_model->setHifiRenderLayer(getHifiRenderLayer());
|
||||
_model->setPrimitiveMode(_primitiveMode);
|
||||
_model->setCullWithParent(_cullWithParent);
|
||||
_model->setRenderWithZones(_renderWithZones);
|
||||
emit requestRenderUpdate();
|
||||
if (didVisualGeometryRequestSucceed) {
|
||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
|
||||
modelAddedToScene(entity->getEntityItemID(), NestableType::Entity, _model);
|
||||
}
|
||||
_didLastVisualGeometryRequestSucceed = didVisualGeometryRequestSucceed;
|
||||
const render::ScenePointer& scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
transaction.updateItem<PayloadProxyInterface>(_renderItemID, [&](PayloadProxyInterface& self) {
|
||||
const render::ScenePointer& scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
withWriteLock([&] {
|
||||
setKey(didVisualGeometryRequestSucceed, _model);
|
||||
_model->setVisibleInScene(_visible, scene);
|
||||
_model->setCauterized(_cauterized, scene);
|
||||
_model->setCanCastShadow(_canCastShadow, scene);
|
||||
_model->setGroupCulled(entity->getGroupCulled(), scene);
|
||||
_model->setTagMask(getTagMask(), scene);
|
||||
_model->setHifiRenderLayer(getHifiRenderLayer(), scene);
|
||||
_model->setPrimitiveMode(_primitiveMode, scene);
|
||||
_model->setCullWithParent(_cullWithParent, scene);
|
||||
_model->setRenderWithZones(_renderWithZones, scene);
|
||||
});
|
||||
if (didVisualGeometryRequestSucceed) {
|
||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
|
||||
modelAddedToScene(entity->getEntityItemID(), NestableType::Entity, model);
|
||||
}
|
||||
entity->_originalTexturesRead = false;
|
||||
entity->_needsJointSimulation = true;
|
||||
entity->_needsToRescaleModel = true;
|
||||
emit requestRenderUpdate();
|
||||
});
|
||||
scene->enqueueTransaction(transaction);
|
||||
});
|
||||
model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity));
|
||||
entity->setModel(model);
|
||||
withWriteLock([&] { _model = model; });
|
||||
}
|
||||
|
||||
// From here on, we are guaranteed a populated model
|
||||
if (_parsedModelURL != model->getURL()) {
|
||||
withWriteLock([&] {
|
||||
_texturesLoaded = false;
|
||||
_jointMappingCompleted = false;
|
||||
model->setURL(_parsedModelURL);
|
||||
});
|
||||
_texturesLoaded = false;
|
||||
_jointMappingCompleted = false;
|
||||
model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity));
|
||||
model->setURL(_parsedModelURL);
|
||||
}
|
||||
|
||||
// Nothing else to do unless the model is loaded
|
||||
if (!model->isLoaded()) {
|
||||
withWriteLock([&] {
|
||||
_prevModelLoaded = false;
|
||||
});
|
||||
emit requestRenderUpdate();
|
||||
return;
|
||||
} else if (!_prevModelLoaded) {
|
||||
withWriteLock([&] {
|
||||
_prevModelLoaded = true;
|
||||
});
|
||||
}
|
||||
|
||||
// Check for initializing the model
|
||||
// FIXME: There are several places below here where we are modifying the entity, which we should not be doing from the renderable
|
||||
if (!entity->_dimensionsInitialized) {
|
||||
EntityItemProperties properties;
|
||||
properties.setLastEdited(usecTimestampNow()); // we must set the edit time since we're editing it
|
||||
|
@ -1391,53 +1308,39 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
entity->_originalTexturesRead = true;
|
||||
}
|
||||
|
||||
if (_textures != entity->getTextures()) {
|
||||
auto textures = entity->getTextures();
|
||||
if (_textures != textures) {
|
||||
QVariantMap newTextures;
|
||||
withWriteLock([&] {
|
||||
_texturesLoaded = false;
|
||||
_textures = entity->getTextures();
|
||||
newTextures = parseTexturesToMap(_textures, entity->_originalTextures);
|
||||
});
|
||||
_texturesLoaded = false;
|
||||
_textures = textures;
|
||||
newTextures = parseTexturesToMap(_textures, entity->_originalTextures);
|
||||
model->setTextures(newTextures);
|
||||
}
|
||||
|
||||
if (entity->_needsJointSimulation) {
|
||||
entity->copyAnimationJointDataToModel();
|
||||
}
|
||||
entity->updateModelBounds();
|
||||
entity->stopModelOverrideIfNoParent();
|
||||
|
||||
if (model->isVisible() != _visible) {
|
||||
withWriteLock([&] {
|
||||
setKey(_didLastVisualGeometryRequestSucceed, model);
|
||||
model->setVisibleInScene(_visible, scene);
|
||||
}
|
||||
|
||||
if (model->isCauterized() != _cauterized) {
|
||||
model->setCauterized(_cauterized, scene);
|
||||
}
|
||||
|
||||
render::hifi::Tag tagMask = getTagMask();
|
||||
if (model->getTagMask() != tagMask) {
|
||||
model->setTagMask(tagMask, scene);
|
||||
}
|
||||
model->setCanCastShadow(_canCastShadow, scene);
|
||||
model->setGroupCulled(entity->getGroupCulled(), scene);
|
||||
model->setTagMask(getTagMask(), scene);
|
||||
model->setHifiRenderLayer(getHifiRenderLayer(), scene);
|
||||
model->setPrimitiveMode(_primitiveMode, scene);
|
||||
model->setCullWithParent(_cullWithParent, scene);
|
||||
model->setRenderWithZones(_renderWithZones, scene);
|
||||
});
|
||||
|
||||
if (entity->blendshapesChanged()) {
|
||||
model->setBlendshapeCoefficients(entity->getBlendshapeCoefficientVector());
|
||||
model->updateBlendshapes();
|
||||
}
|
||||
|
||||
// TODO? early exit here when not visible?
|
||||
|
||||
if (model->canCastShadow() != _canCastShadow) {
|
||||
model->setCanCastShadow(_canCastShadow, scene);
|
||||
}
|
||||
|
||||
{
|
||||
bool groupCulled = entity->getGroupCulled();
|
||||
if (model->isGroupCulled() != groupCulled) {
|
||||
model->setGroupCulled(groupCulled);
|
||||
setKey(_didLastVisualGeometryRequestSucceed);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "Fixup");
|
||||
if (model->needsFixupInScene()) {
|
||||
|
@ -1451,11 +1354,10 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
}
|
||||
}
|
||||
|
||||
bool needsUpdate = false;
|
||||
if (!_texturesLoaded && model->getGeometry() && model->getGeometry()->areTexturesLoaded()) {
|
||||
withWriteLock([&] {
|
||||
_texturesLoaded = true;
|
||||
});
|
||||
model->updateRenderItems();
|
||||
_texturesLoaded = true;
|
||||
needsUpdate = true;
|
||||
} else if (!_texturesLoaded) {
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
|
@ -1481,19 +1383,23 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
emit requestRenderUpdate();
|
||||
} else {
|
||||
_allProceduralMaterialsLoaded = true;
|
||||
model->setRenderItemsNeedUpdate();
|
||||
needsUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
// When the individual mesh parts of a model finish fading, they will mark their Model as needing updating
|
||||
// we will watch for that and ask the model to update it's render items
|
||||
if (model->getRenderItemsNeedUpdate()) {
|
||||
if (needsUpdate || model->getRenderItemsNeedUpdate()) {
|
||||
model->updateRenderItems();
|
||||
}
|
||||
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
// The code to deal with the change of properties is now in ModelEntityItem.cpp
|
||||
// That is where _currentFrame and _lastAnimated were updated.
|
||||
if (_animating) {
|
||||
if (entity->isAnimatingSomething()) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "Animate");
|
||||
|
||||
auto animationURL = entity->getAnimationURL();
|
||||
|
@ -1502,18 +1408,22 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
_animationURL = animationURL;
|
||||
|
||||
if (_animation) {
|
||||
//(_animation->getURL().toString() != entity->getAnimationURL())) { // bad check
|
||||
// the joints have been mapped before but we have a new animation to load
|
||||
_animation.reset();
|
||||
_jointMappingCompleted = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_jointMappingCompleted) {
|
||||
mapJoints(entity, model);
|
||||
}
|
||||
if (entity->readyToAnimate()) {
|
||||
animate(entity);
|
||||
|
||||
ModelPointer model = resultWithReadLock<ModelPointer>([&] {
|
||||
return _model;
|
||||
});
|
||||
if (model && model->isLoaded()) {
|
||||
if (!_jointMappingCompleted) {
|
||||
mapJoints(entity, model);
|
||||
}
|
||||
if (entity->readyToAnimate()) {
|
||||
animate(entity, model);
|
||||
}
|
||||
}
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
|
@ -1521,40 +1431,20 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
|
||||
void ModelEntityRenderer::setIsVisibleInSecondaryCamera(bool value) {
|
||||
Parent::setIsVisibleInSecondaryCamera(value);
|
||||
setKey(_didLastVisualGeometryRequestSucceed);
|
||||
if (_model) {
|
||||
_model->setTagMask(getTagMask());
|
||||
}
|
||||
// called within a lock so no need to lock for _model
|
||||
setKey(_didLastVisualGeometryRequestSucceed, _model);
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::setRenderLayer(RenderLayer value) {
|
||||
Parent::setRenderLayer(value);
|
||||
setKey(_didLastVisualGeometryRequestSucceed);
|
||||
if (_model) {
|
||||
_model->setHifiRenderLayer(getHifiRenderLayer());
|
||||
}
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::setPrimitiveMode(PrimitiveMode value) {
|
||||
Parent::setPrimitiveMode(value);
|
||||
if (_model) {
|
||||
_model->setPrimitiveMode(_primitiveMode);
|
||||
}
|
||||
// called within a lock so no need to lock for _model
|
||||
setKey(_didLastVisualGeometryRequestSucceed, _model);
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::setCullWithParent(bool value) {
|
||||
Parent::setCullWithParent(value);
|
||||
setKey(_didLastVisualGeometryRequestSucceed);
|
||||
if (_model) {
|
||||
_model->setCullWithParent(_cullWithParent);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::setRenderWithZones(const QVector<QUuid>& renderWithZones) {
|
||||
Parent::setRenderWithZones(renderWithZones);
|
||||
if (_model) {
|
||||
_model->setRenderWithZones(renderWithZones);
|
||||
}
|
||||
// called within a lock so no need to lock for _model
|
||||
setKey(_didLastVisualGeometryRequestSucceed, _model);
|
||||
}
|
||||
|
||||
// NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items
|
||||
|
@ -1570,9 +1460,8 @@ void ModelEntityRenderer::doRender(RenderArgs* args) {
|
|||
geometryCache->renderWireCubeInstance(args, batch, greenColor, geometryCache->getShapePipelinePointer(false, false, args->_renderMethod == Args::RenderMethod::FORWARD));
|
||||
|
||||
#if WANT_EXTRA_DEBUGGING
|
||||
ModelPointer model;
|
||||
withReadLock([&] {
|
||||
model = _model;
|
||||
ModelPointer model = resultWithReadLock<ModelPointer>([&] {
|
||||
return _model;
|
||||
});
|
||||
if (model) {
|
||||
model->renderDebugMeshBoxes(batch, args->_renderMethod == Args::RenderMethod::FORWARD);
|
||||
|
|
|
@ -41,7 +41,6 @@ protected:
|
|||
ModelEntityWrapper(const EntityItemID& entityItemID) : Parent(entityItemID) {}
|
||||
void setModel(const ModelPointer& model);
|
||||
ModelPointer getModel() const;
|
||||
bool isModelLoaded() const;
|
||||
|
||||
bool _needsInitialSimulation{ true };
|
||||
private:
|
||||
|
@ -62,7 +61,6 @@ public:
|
|||
virtual void setUnscaledDimensions(const glm::vec3& value) override;
|
||||
|
||||
virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
|
||||
void doInitialModelSimulation();
|
||||
void updateModelBounds();
|
||||
|
||||
virtual bool supportsDetailedIntersection() const override;
|
||||
|
@ -77,6 +75,7 @@ public:
|
|||
|
||||
virtual void setShapeType(ShapeType type) override;
|
||||
virtual void setCompoundShapeURL(const QString& url) override;
|
||||
virtual void setModelURL(const QString& url) override;
|
||||
|
||||
virtual bool isReadyToComputeShape() const override;
|
||||
virtual void computeShapeInfo(ShapeInfo& shapeInfo) override;
|
||||
|
@ -121,6 +120,8 @@ private:
|
|||
bool readyToAnimate() const;
|
||||
void fetchCollisionGeometryResource();
|
||||
|
||||
QString getCollisionShapeURL() const;
|
||||
|
||||
GeometryResource::Pointer _collisionGeometryResource;
|
||||
std::vector<int> _jointMap;
|
||||
QVariantMap _originalTextures;
|
||||
|
@ -128,6 +129,7 @@ private:
|
|||
bool _originalTexturesRead { false };
|
||||
bool _dimensionsInitialized { true };
|
||||
bool _needsJointSimulation { false };
|
||||
bool _needsToRescaleModel { false };
|
||||
};
|
||||
|
||||
namespace render { namespace entities {
|
||||
|
@ -153,25 +155,23 @@ protected:
|
|||
virtual void removeFromScene(const ScenePointer& scene, Transaction& transaction) override;
|
||||
virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
|
||||
|
||||
void setKey(bool didVisualGeometryRequestSucceed);
|
||||
void setKey(bool didVisualGeometryRequestSucceed, const ModelPointer& model);
|
||||
virtual ItemKey getKey() override;
|
||||
virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override;
|
||||
virtual void handleBlendedVertices(int blendshapeNumber, const QVector<BlendshapeOffset>& blendshapeOffsets,
|
||||
const QVector<int>& blendedMeshSizes, const render::ItemIDs& subItemIDs) override;
|
||||
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual bool needsRenderUpdate() const override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
||||
void setIsVisibleInSecondaryCamera(bool value) override;
|
||||
void setRenderLayer(RenderLayer value) override;
|
||||
void setPrimitiveMode(PrimitiveMode value) override;
|
||||
void setCullWithParent(bool value) override;
|
||||
void setRenderWithZones(const QVector<QUuid>& renderWithZones) override;
|
||||
|
||||
private:
|
||||
void animate(const TypedEntityPointer& entity);
|
||||
void animate(const TypedEntityPointer& entity, const ModelPointer& model);
|
||||
void mapJoints(const TypedEntityPointer& entity, const ModelPointer& model);
|
||||
|
||||
// Transparency is handled in ModelMeshPartPayload
|
||||
|
@ -186,20 +186,16 @@ private:
|
|||
bool _hasTransitioned{ false };
|
||||
#endif
|
||||
|
||||
const void* _collisionMeshKey { nullptr };
|
||||
|
||||
QUrl _parsedModelURL;
|
||||
bool _jointMappingCompleted { false };
|
||||
QVector<int> _jointMapping; // domain is index into model-joints, range is index into animation-joints
|
||||
AnimationPointer _animation;
|
||||
bool _animating { false };
|
||||
QString _animationURL;
|
||||
uint64_t _lastAnimated { 0 };
|
||||
|
||||
render::ItemKey _itemKey { render::ItemKey::Builder().withTypeMeta() };
|
||||
|
||||
bool _didLastVisualGeometryRequestSucceed { true };
|
||||
bool _prevModelLoaded { false };
|
||||
|
||||
void processMaterials();
|
||||
bool _allProceduralMaterialsLoaded { false };
|
||||
|
|
|
@ -64,84 +64,7 @@ ParticleEffectEntityRenderer::ParticleEffectEntityRenderer(const EntityItemPoint
|
|||
});
|
||||
}
|
||||
|
||||
bool ParticleEffectEntityRenderer::needsRenderUpdate() const {
|
||||
if (resultWithReadLock<bool>([&] {
|
||||
return !_textureLoaded;
|
||||
})) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parent::needsRenderUpdate();
|
||||
}
|
||||
|
||||
void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
auto newParticleProperties = entity->getParticleProperties();
|
||||
if (!newParticleProperties.valid()) {
|
||||
qCWarning(entitiesrenderer) << "Bad particle properties";
|
||||
}
|
||||
|
||||
if (resultWithReadLock<bool>([&] { return _particleProperties != newParticleProperties; })) {
|
||||
_timeUntilNextEmit = 0;
|
||||
withWriteLock([&] {
|
||||
_particleProperties = newParticleProperties;
|
||||
if (!_prevEmitterShouldTrailInitialized) {
|
||||
_prevEmitterShouldTrailInitialized = true;
|
||||
_prevEmitterShouldTrail = _particleProperties.emission.shouldTrail;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
_pulseProperties = entity->getPulseProperties();
|
||||
_shapeType = entity->getShapeType();
|
||||
QString compoundShapeURL = entity->getCompoundShapeURL();
|
||||
if (_compoundShapeURL != compoundShapeURL) {
|
||||
_compoundShapeURL = compoundShapeURL;
|
||||
_hasComputedTriangles = false;
|
||||
fetchGeometryResource();
|
||||
}
|
||||
});
|
||||
_emitting = entity->getIsEmitting();
|
||||
|
||||
bool textureEmpty = resultWithReadLock<bool>([&] { return _particleProperties.textures.isEmpty(); });
|
||||
if (textureEmpty) {
|
||||
if (_networkTexture) {
|
||||
withWriteLock([&] {
|
||||
_networkTexture.reset();
|
||||
});
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
_textureLoaded = true;
|
||||
entity->setVisuallyReady(true);
|
||||
});
|
||||
} else {
|
||||
bool textureNeedsUpdate = resultWithReadLock<bool>([&] {
|
||||
return !_networkTexture || _networkTexture->getURL() != QUrl(_particleProperties.textures);
|
||||
});
|
||||
if (textureNeedsUpdate) {
|
||||
withWriteLock([&] {
|
||||
_networkTexture = DependencyManager::get<TextureCache>()->getTexture(_particleProperties.textures);
|
||||
_textureLoaded = false;
|
||||
entity->setVisuallyReady(false);
|
||||
});
|
||||
}
|
||||
|
||||
if (!_textureLoaded) {
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
|
||||
bool textureLoaded = resultWithReadLock<bool>([&] {
|
||||
return _networkTexture && (_networkTexture->isLoaded() || _networkTexture->isFailed());
|
||||
});
|
||||
if (textureLoaded) {
|
||||
withWriteLock([&] {
|
||||
entity->setVisuallyReady(true);
|
||||
_textureLoaded = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void* key = (void*)this;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] {
|
||||
withWriteLock([&] {
|
||||
|
@ -151,20 +74,66 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
|
|||
}
|
||||
|
||||
void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
auto newParticleProperties = entity->getParticleProperties();
|
||||
if (!newParticleProperties.valid()) {
|
||||
qCWarning(entitiesrenderer) << "Bad particle properties";
|
||||
}
|
||||
|
||||
if (_particleProperties != newParticleProperties) {
|
||||
_timeUntilNextEmit = 0;
|
||||
_particleProperties = newParticleProperties;
|
||||
if (!_prevEmitterShouldTrailInitialized) {
|
||||
_prevEmitterShouldTrailInitialized = true;
|
||||
_prevEmitterShouldTrail = _particleProperties.emission.shouldTrail;
|
||||
}
|
||||
}
|
||||
|
||||
_pulseProperties = entity->getPulseProperties();
|
||||
_shapeType = entity->getShapeType();
|
||||
QString compoundShapeURL = entity->getCompoundShapeURL();
|
||||
if (_compoundShapeURL != compoundShapeURL) {
|
||||
_compoundShapeURL = compoundShapeURL;
|
||||
_hasComputedTriangles = false;
|
||||
fetchGeometryResource();
|
||||
}
|
||||
_emitting = entity->getIsEmitting();
|
||||
|
||||
if (_particleProperties.textures.isEmpty()) {
|
||||
if (_networkTexture) {
|
||||
_networkTexture.reset();
|
||||
}
|
||||
|
||||
_textureLoaded = true;
|
||||
entity->setVisuallyReady(true);
|
||||
} else {
|
||||
if (!_networkTexture || _networkTexture->getURL() != QUrl(_particleProperties.textures)) {
|
||||
_networkTexture = DependencyManager::get<TextureCache>()->getTexture(_particleProperties.textures);
|
||||
_textureLoaded = false;
|
||||
entity->setVisuallyReady(false);
|
||||
}
|
||||
|
||||
if (!_textureLoaded) {
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
|
||||
if (_networkTexture && (_networkTexture->isLoaded() || _networkTexture->isFailed())) {
|
||||
entity->setVisuallyReady(true);
|
||||
_textureLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill in Uniforms structure
|
||||
ParticleUniforms particleUniforms;
|
||||
withReadLock([&] {
|
||||
particleUniforms.radius.start = _particleProperties.radius.range.start;
|
||||
particleUniforms.radius.middle = _particleProperties.radius.gradient.target;
|
||||
particleUniforms.radius.finish = _particleProperties.radius.range.finish;
|
||||
particleUniforms.radius.spread = _particleProperties.radius.gradient.spread;
|
||||
particleUniforms.spin.start = _particleProperties.spin.range.start;
|
||||
particleUniforms.spin.middle = _particleProperties.spin.gradient.target;
|
||||
particleUniforms.spin.finish = _particleProperties.spin.range.finish;
|
||||
particleUniforms.spin.spread = _particleProperties.spin.gradient.spread;
|
||||
particleUniforms.lifespan = _particleProperties.lifespan;
|
||||
particleUniforms.rotateWithEntity = _particleProperties.rotateWithEntity ? 1 : 0;
|
||||
});
|
||||
particleUniforms.radius.start = _particleProperties.radius.range.start;
|
||||
particleUniforms.radius.middle = _particleProperties.radius.gradient.target;
|
||||
particleUniforms.radius.finish = _particleProperties.radius.range.finish;
|
||||
particleUniforms.radius.spread = _particleProperties.radius.gradient.spread;
|
||||
particleUniforms.spin.start = _particleProperties.spin.range.start;
|
||||
particleUniforms.spin.middle = _particleProperties.spin.gradient.target;
|
||||
particleUniforms.spin.finish = _particleProperties.spin.range.finish;
|
||||
particleUniforms.spin.spread = _particleProperties.spin.gradient.spread;
|
||||
particleUniforms.lifespan = _particleProperties.lifespan;
|
||||
particleUniforms.rotateWithEntity = _particleProperties.rotateWithEntity ? 1 : 0;
|
||||
// Update particle uniforms
|
||||
_uniformBuffer.edit<ParticleUniforms>() = particleUniforms;
|
||||
}
|
||||
|
@ -403,27 +372,18 @@ void ParticleEffectEntityRenderer::stepSimulation() {
|
|||
const auto interval = std::min<uint64_t>(USECS_PER_SECOND / 60, now - _lastSimulated);
|
||||
_lastSimulated = now;
|
||||
|
||||
particle::Properties particleProperties;
|
||||
ShapeType shapeType;
|
||||
GeometryResource::Pointer geometryResource;
|
||||
withReadLock([&] {
|
||||
particleProperties = _particleProperties;
|
||||
shapeType = _shapeType;
|
||||
geometryResource = _geometryResource;
|
||||
});
|
||||
|
||||
const auto& modelTransform = getModelTransform();
|
||||
if (_emitting && particleProperties.emitting() &&
|
||||
(shapeType != SHAPE_TYPE_COMPOUND || (geometryResource && geometryResource->isLoaded()))) {
|
||||
uint64_t emitInterval = particleProperties.emitIntervalUsecs();
|
||||
if (_emitting && _particleProperties.emitting() &&
|
||||
(_shapeType != SHAPE_TYPE_COMPOUND || (_geometryResource && _geometryResource->isLoaded()))) {
|
||||
uint64_t emitInterval = _particleProperties.emitIntervalUsecs();
|
||||
if (emitInterval > 0 && interval >= _timeUntilNextEmit) {
|
||||
auto timeRemaining = interval;
|
||||
while (timeRemaining > _timeUntilNextEmit) {
|
||||
if (_shapeType == SHAPE_TYPE_COMPOUND && !_hasComputedTriangles) {
|
||||
computeTriangles(geometryResource->getHFMModel());
|
||||
computeTriangles(_geometryResource->getHFMModel());
|
||||
}
|
||||
// emit particle
|
||||
_cpuParticles.push_back(createParticle(modelTransform, particleProperties, shapeType, geometryResource, _triangleInfo));
|
||||
_cpuParticles.push_back(createParticle(modelTransform, _particleProperties, _shapeType, _geometryResource, _triangleInfo));
|
||||
_timeUntilNextEmit = emitInterval;
|
||||
if (emitInterval < timeRemaining) {
|
||||
timeRemaining -= emitInterval;
|
||||
|
@ -435,14 +395,14 @@ void ParticleEffectEntityRenderer::stepSimulation() {
|
|||
}
|
||||
|
||||
// Kill any particles that have expired or are over the max size
|
||||
while (_cpuParticles.size() > particleProperties.maxParticles || (!_cpuParticles.empty() && _cpuParticles.front().expiration == 0)) {
|
||||
while (_cpuParticles.size() > _particleProperties.maxParticles || (!_cpuParticles.empty() && _cpuParticles.front().expiration == 0)) {
|
||||
_cpuParticles.pop_front();
|
||||
}
|
||||
|
||||
const float deltaTime = (float)interval / (float)USECS_PER_SECOND;
|
||||
// update the particles
|
||||
for (auto& particle : _cpuParticles) {
|
||||
if (_prevEmitterShouldTrail != particleProperties.emission.shouldTrail) {
|
||||
if (_prevEmitterShouldTrail != _particleProperties.emission.shouldTrail) {
|
||||
if (_prevEmitterShouldTrail) {
|
||||
particle.relativePosition = particle.relativePosition + particle.basePosition - modelTransform.getTranslation();
|
||||
}
|
||||
|
@ -451,14 +411,14 @@ void ParticleEffectEntityRenderer::stepSimulation() {
|
|||
particle.expiration = particle.expiration >= interval ? particle.expiration - interval : 0;
|
||||
particle.integrate(deltaTime);
|
||||
}
|
||||
_prevEmitterShouldTrail = particleProperties.emission.shouldTrail;
|
||||
_prevEmitterShouldTrail = _particleProperties.emission.shouldTrail;
|
||||
|
||||
// Build particle primitives
|
||||
static GpuParticles gpuParticles;
|
||||
gpuParticles.clear();
|
||||
gpuParticles.reserve(_cpuParticles.size()); // Reserve space
|
||||
std::transform(_cpuParticles.begin(), _cpuParticles.end(), std::back_inserter(gpuParticles), [&particleProperties, &modelTransform] (const CpuParticle& particle) {
|
||||
glm::vec3 position = particle.relativePosition + (particleProperties.emission.shouldTrail ? particle.basePosition : modelTransform.getTranslation());
|
||||
std::transform(_cpuParticles.begin(), _cpuParticles.end(), std::back_inserter(gpuParticles), [this, &modelTransform] (const CpuParticle& particle) {
|
||||
glm::vec3 position = particle.relativePosition + (_particleProperties.emission.shouldTrail ? particle.basePosition : modelTransform.getTranslation());
|
||||
return GpuParticle(position, glm::vec2(particle.lifetime, particle.seed));
|
||||
});
|
||||
|
||||
|
@ -487,13 +447,14 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) {
|
|||
// if the particles are marked rotateWithEntity
|
||||
withReadLock([&] {
|
||||
transform.setRotation(_renderTransform.getRotation());
|
||||
auto& color = _uniformBuffer.edit<ParticleUniforms>().color;
|
||||
color.start = EntityRenderer::calculatePulseColor(_particleProperties.getColorStart(), _pulseProperties, _created);
|
||||
color.middle = EntityRenderer::calculatePulseColor(_particleProperties.getColorMiddle(), _pulseProperties, _created);
|
||||
color.finish = EntityRenderer::calculatePulseColor(_particleProperties.getColorFinish(), _pulseProperties, _created);
|
||||
color.spread = EntityRenderer::calculatePulseColor(_particleProperties.getColorSpread(), _pulseProperties, _created);
|
||||
});
|
||||
|
||||
auto& color = _uniformBuffer.edit<ParticleUniforms>().color;
|
||||
color.start = EntityRenderer::calculatePulseColor(_particleProperties.getColorStart(), _pulseProperties, _created);
|
||||
color.middle = EntityRenderer::calculatePulseColor(_particleProperties.getColorMiddle(), _pulseProperties, _created);
|
||||
color.finish = EntityRenderer::calculatePulseColor(_particleProperties.getColorFinish(), _pulseProperties, _created);
|
||||
color.spread = EntityRenderer::calculatePulseColor(_particleProperties.getColorSpread(), _pulseProperties, _created);
|
||||
|
||||
batch.setModelTransform(transform);
|
||||
batch.setUniformBuffer(0, _uniformBuffer);
|
||||
batch.setInputFormat(_vertexFormat);
|
||||
|
|
|
@ -25,7 +25,6 @@ public:
|
|||
ParticleEffectEntityRenderer(const EntityItemPointer& entity);
|
||||
|
||||
protected:
|
||||
virtual bool needsRenderUpdate() const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
|
||||
|
|
|
@ -121,16 +121,6 @@ ShapeKey PolyLineEntityRenderer::getShapeKey() {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
bool PolyLineEntityRenderer::needsRenderUpdate() const {
|
||||
if (resultWithReadLock<bool>([&] {
|
||||
return (!_textureLoaded && _texture && _texture->isLoaded());
|
||||
})) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parent::needsRenderUpdate();
|
||||
}
|
||||
|
||||
bool PolyLineEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
if (entity->pointsChanged() || entity->widthsChanged() || entity->normalsChanged() || entity->texturesChanged() || entity->colorsChanged()) {
|
||||
return true;
|
||||
|
@ -140,6 +130,15 @@ bool PolyLineEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityP
|
|||
}
|
||||
|
||||
void PolyLineEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
void* key = (void*)this;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] {
|
||||
withWriteLock([&] {
|
||||
_renderTransform = getModelTransform();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void PolyLineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
auto pointsChanged = entity->pointsChanged();
|
||||
auto widthsChanged = entity->widthsChanged();
|
||||
auto normalsChanged = entity->normalsChanged();
|
||||
|
@ -159,13 +158,15 @@ void PolyLineEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer&
|
|||
if (!textures.isEmpty()) {
|
||||
entityTextures = QUrl(textures);
|
||||
}
|
||||
withWriteLock([&] {
|
||||
_texture = DependencyManager::get<TextureCache>()->getTexture(entityTextures);
|
||||
});
|
||||
_texture = DependencyManager::get<TextureCache>()->getTexture(entityTextures);
|
||||
_textureAspectRatio = 1.0f;
|
||||
_textureLoaded = false;
|
||||
}
|
||||
|
||||
if (!_textureLoaded) {
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
|
||||
bool textureChanged = false;
|
||||
if (!_textureLoaded && _texture && _texture->isLoaded()) {
|
||||
textureChanged = true;
|
||||
|
@ -175,13 +176,11 @@ void PolyLineEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer&
|
|||
|
||||
// Data
|
||||
bool faceCameraChanged = faceCamera != _faceCamera;
|
||||
withWriteLock([&] {
|
||||
if (faceCameraChanged || glow != _glow) {
|
||||
_faceCamera = faceCamera;
|
||||
_glow = glow;
|
||||
updateData();
|
||||
}
|
||||
});
|
||||
if (faceCameraChanged || glow != _glow) {
|
||||
_faceCamera = faceCamera;
|
||||
_glow = glow;
|
||||
updateData();
|
||||
}
|
||||
|
||||
// Geometry
|
||||
if (pointsChanged) {
|
||||
|
@ -200,19 +199,10 @@ void PolyLineEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer&
|
|||
|
||||
bool uvModeStretchChanged = _isUVModeStretch != isUVModeStretch;
|
||||
_isUVModeStretch = isUVModeStretch;
|
||||
|
||||
bool geometryChanged = uvModeStretchChanged || pointsChanged || widthsChanged || normalsChanged || colorsChanged || textureChanged || faceCameraChanged;
|
||||
|
||||
void* key = (void*)this;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, geometryChanged] {
|
||||
withWriteLock([&] {
|
||||
_renderTransform = getModelTransform();
|
||||
|
||||
if (geometryChanged) {
|
||||
updateGeometry();
|
||||
}
|
||||
});
|
||||
});
|
||||
if (uvModeStretchChanged || pointsChanged || widthsChanged || normalsChanged || colorsChanged || textureChanged || faceCameraChanged) {
|
||||
updateGeometry();
|
||||
}
|
||||
}
|
||||
|
||||
void PolyLineEntityRenderer::updateGeometry() {
|
||||
|
@ -318,19 +308,16 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) {
|
|||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
|
||||
size_t numVertices;
|
||||
Transform transform;
|
||||
gpu::TexturePointer texture;
|
||||
gpu::TexturePointer texture = _textureLoaded ? _texture->getGPUTexture() : DependencyManager::get<TextureCache>()->getWhiteTexture();
|
||||
withReadLock([&] {
|
||||
numVertices = _numVertices;
|
||||
transform = _renderTransform;
|
||||
texture = _textureLoaded ? _texture->getGPUTexture() : DependencyManager::get<TextureCache>()->getWhiteTexture();
|
||||
|
||||
batch.setResourceBuffer(0, _polylineGeometryBuffer);
|
||||
batch.setUniformBuffer(0, _polylineDataBuffer);
|
||||
});
|
||||
|
||||
if (numVertices < 2) {
|
||||
batch.setResourceBuffer(0, _polylineGeometryBuffer);
|
||||
batch.setUniformBuffer(0, _polylineDataBuffer);
|
||||
|
||||
if (_numVertices < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -341,5 +328,5 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) {
|
|||
batch.setPipeline(_pipelines[{args->_renderMethod, isTransparent()}]);
|
||||
batch.setModelTransform(transform);
|
||||
batch.setResourceTexture(0, texture);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, (gpu::uint32)(2 * numVertices), 0);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, (gpu::uint32)(2 * _numVertices), 0);
|
||||
}
|
||||
|
|
|
@ -30,9 +30,9 @@ public:
|
|||
virtual bool isTransparent() const override;
|
||||
|
||||
protected:
|
||||
virtual bool needsRenderUpdate() const override;
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
|
||||
virtual ItemKey getKey() override;
|
||||
virtual ShapeKey getShapeKey() override;
|
||||
|
|
|
@ -1802,25 +1802,44 @@ ShapeKey PolyVoxEntityRenderer::getShapeKey() {
|
|||
}
|
||||
|
||||
bool PolyVoxEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
if (entity->voxelToWorldMatrix() != _lastVoxelToWorldMatrix) {
|
||||
if (resultWithReadLock<bool>([&] {
|
||||
if (entity->voxelToWorldMatrix() != _lastVoxelToWorldMatrix) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (entity->_mesh != _mesh) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (entity->_mesh != _mesh) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return Parent::needsRenderUpdateFromTypedEntity(entity);
|
||||
}
|
||||
|
||||
void PolyVoxEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
if (!_hasTransitioned) {
|
||||
transaction.resetTransitionOnItem(_renderItemID, render::Transition::ELEMENT_ENTER_DOMAIN);
|
||||
_hasTransitioned = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PolyVoxEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
_lastVoxelToWorldMatrix = entity->voxelToWorldMatrix();
|
||||
_lastVoxelVolumeSize = entity->getVoxelVolumeSize();
|
||||
_params->setSubData(0, vec4(_lastVoxelVolumeSize, 0.0));
|
||||
graphics::MeshPointer newMesh;
|
||||
entity->withReadLock([&] {
|
||||
newMesh = entity->_mesh;
|
||||
});
|
||||
|
||||
if (newMesh && newMesh->getIndexBuffer()._buffer) {
|
||||
_mesh = newMesh;
|
||||
}
|
||||
|
||||
std::array<QString, 3> xyzTextureURLs{ {
|
||||
entity->getXTextureURL(),
|
||||
|
@ -1838,20 +1857,6 @@ void PolyVoxEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& s
|
|||
}
|
||||
}
|
||||
|
||||
void PolyVoxEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
_lastVoxelToWorldMatrix = entity->voxelToWorldMatrix();
|
||||
_lastVoxelVolumeSize = entity->getVoxelVolumeSize();
|
||||
_params->setSubData(0, vec4(_lastVoxelVolumeSize, 0.0));
|
||||
graphics::MeshPointer newMesh;
|
||||
entity->withReadLock([&] {
|
||||
newMesh = entity->_mesh;
|
||||
});
|
||||
|
||||
if (newMesh && newMesh->getIndexBuffer()._buffer) {
|
||||
_mesh = newMesh;
|
||||
}
|
||||
}
|
||||
|
||||
void PolyVoxEntityRenderer::doRender(RenderArgs* args) {
|
||||
if (!_mesh || !_mesh->getIndexBuffer()._buffer) {
|
||||
return;
|
||||
|
|
|
@ -51,24 +51,7 @@ bool ShapeEntityRenderer::needsRenderUpdate() const {
|
|||
return Parent::needsRenderUpdate();
|
||||
}
|
||||
|
||||
bool ShapeEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
if (_dimensions != entity->getScaledDimensions()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_proceduralData != entity->getUserData()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
withWriteLock([&] {
|
||||
_shape = entity->getShape();
|
||||
_pulseProperties = entity->getPulseProperties();
|
||||
});
|
||||
|
||||
void* key = (void*)this;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
||||
withWriteLock([&] {
|
||||
|
@ -86,47 +69,53 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
}
|
||||
|
||||
void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
_shape = entity->getShape();
|
||||
_pulseProperties = entity->getPulseProperties();
|
||||
|
||||
bool materialChanged = false;
|
||||
glm::vec3 color = toGlm(entity->getColor());
|
||||
if (_color != color) {
|
||||
_color = color;
|
||||
_material->setAlbedo(color);
|
||||
materialChanged = true;
|
||||
}
|
||||
|
||||
float alpha = entity->getAlpha();
|
||||
if (_alpha != alpha) {
|
||||
_alpha = alpha;
|
||||
_material->setOpacity(alpha);
|
||||
materialChanged = true;
|
||||
}
|
||||
|
||||
auto userData = entity->getUserData();
|
||||
if (_proceduralData != userData) {
|
||||
_proceduralData = userData;
|
||||
_material->setProceduralData(_proceduralData);
|
||||
materialChanged = true;
|
||||
}
|
||||
|
||||
withReadLock([&] {
|
||||
auto mat = _materials.find("0");
|
||||
if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() && mat->second.top().material->isReady()) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(mat->second.top().material);
|
||||
if (procedural->isFading()) {
|
||||
procedural->setIsFading(Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) < 1.0f);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
withWriteLock([&] {
|
||||
bool materialChanged = false;
|
||||
glm::vec3 color = toGlm(entity->getColor());
|
||||
if (_color != color) {
|
||||
_color = color;
|
||||
_material->setAlbedo(color);
|
||||
materialChanged = true;
|
||||
}
|
||||
|
||||
float alpha = entity->getAlpha();
|
||||
if (_alpha != alpha) {
|
||||
_alpha = alpha;
|
||||
_material->setOpacity(alpha);
|
||||
materialChanged = true;
|
||||
}
|
||||
|
||||
auto userData = entity->getUserData();
|
||||
if (_proceduralData != userData) {
|
||||
_proceduralData = userData;
|
||||
_material->setProceduralData(_proceduralData);
|
||||
materialChanged = true;
|
||||
}
|
||||
|
||||
auto materials = _materials.find("0");
|
||||
if (materials != _materials.end()) {
|
||||
if (materialChanged) {
|
||||
materials->second.setNeedsUpdate(true);
|
||||
}
|
||||
|
||||
bool requestUpdate = false;
|
||||
if (materials->second.top().material && materials->second.top().material->isProcedural() && materials->second.top().material->isReady()) {
|
||||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(materials->second.top().material);
|
||||
if (procedural->isFading()) {
|
||||
procedural->setIsFading(Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) < 1.0f);
|
||||
requestUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (materials->second.shouldUpdate()) {
|
||||
RenderPipelines::updateMultiMaterial(materials->second);
|
||||
requestUpdate = true;
|
||||
}
|
||||
|
||||
if (requestUpdate) {
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
}
|
||||
|
@ -231,13 +220,12 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
|
||||
graphics::MultiMaterial materials;
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
GeometryCache::Shape geometryShape;
|
||||
GeometryCache::Shape geometryShape = geometryCache->getShapeForEntityShape(_shape);
|
||||
PrimitiveMode primitiveMode;
|
||||
RenderLayer renderLayer;
|
||||
glm::vec4 outColor;
|
||||
Pipeline pipelineType;
|
||||
withReadLock([&] {
|
||||
geometryShape = geometryCache->getShapeForEntityShape(_shape);
|
||||
primitiveMode = _primitiveMode;
|
||||
renderLayer = _renderLayer;
|
||||
batch.setModelTransform(_renderTransform); // use a transform with scale, rotation, registration point and translation
|
||||
|
@ -245,9 +233,10 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
pipelineType = getPipelineType(materials);
|
||||
auto& schema = materials.getSchemaBuffer().get<graphics::MultiMaterial::Schema>();
|
||||
outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity);
|
||||
outColor = EntityRenderer::calculatePulseColor(outColor, _pulseProperties, _created);
|
||||
});
|
||||
|
||||
outColor = EntityRenderer::calculatePulseColor(outColor, _pulseProperties, _created);
|
||||
|
||||
if (outColor.a == 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
@ -256,7 +245,9 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
auto procedural = std::static_pointer_cast<graphics::ProceduralMaterial>(materials.top().material);
|
||||
outColor = procedural->getColor(outColor);
|
||||
outColor.a *= procedural->isFading() ? Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) : 1.0f;
|
||||
procedural->prepare(batch, _position, _dimensions, _orientation, _created, ProceduralProgramKey(outColor.a < 1.0f));
|
||||
withReadLock([&] {
|
||||
procedural->prepare(batch, _position, _dimensions, _orientation, _created, ProceduralProgramKey(outColor.a < 1.0f));
|
||||
});
|
||||
|
||||
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) {
|
||||
geometryCache->renderWireShape(batch, geometryShape, outColor);
|
||||
|
|
|
@ -30,7 +30,6 @@ protected:
|
|||
|
||||
private:
|
||||
virtual bool needsRenderUpdate() const override;
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
|
|
@ -92,14 +92,6 @@ uint32_t TextEntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const {
|
|||
return parentSubs;
|
||||
}
|
||||
|
||||
bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
if (_dimensions != entity->getScaledDimensions()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void TextEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
void* key = (void*)this;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
||||
|
@ -112,26 +104,24 @@ void TextEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen
|
|||
}
|
||||
|
||||
void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
withWriteLock([&] {
|
||||
_pulseProperties = entity->getPulseProperties();
|
||||
_text = entity->getText();
|
||||
_lineHeight = entity->getLineHeight();
|
||||
_textColor = toGlm(entity->getTextColor());
|
||||
_textAlpha = entity->getTextAlpha();
|
||||
_backgroundColor = toGlm(entity->getBackgroundColor());
|
||||
_backgroundAlpha = entity->getBackgroundAlpha();
|
||||
_billboardMode = entity->getBillboardMode();
|
||||
_leftMargin = entity->getLeftMargin();
|
||||
_rightMargin = entity->getRightMargin();
|
||||
_topMargin = entity->getTopMargin();
|
||||
_bottomMargin = entity->getBottomMargin();
|
||||
_unlit = entity->getUnlit();
|
||||
_font = entity->getFont();
|
||||
_effect = entity->getTextEffect();
|
||||
_effectColor = toGlm(entity->getTextEffectColor());
|
||||
_effectThickness = entity->getTextEffectThickness();
|
||||
updateTextRenderItem();
|
||||
});
|
||||
_pulseProperties = entity->getPulseProperties();
|
||||
_text = entity->getText();
|
||||
_lineHeight = entity->getLineHeight();
|
||||
_textColor = toGlm(entity->getTextColor());
|
||||
_textAlpha = entity->getTextAlpha();
|
||||
_backgroundColor = toGlm(entity->getBackgroundColor());
|
||||
_backgroundAlpha = entity->getBackgroundAlpha();
|
||||
_billboardMode = entity->getBillboardMode();
|
||||
_leftMargin = entity->getLeftMargin();
|
||||
_rightMargin = entity->getRightMargin();
|
||||
_topMargin = entity->getTopMargin();
|
||||
_bottomMargin = entity->getBottomMargin();
|
||||
_unlit = entity->getUnlit();
|
||||
_font = entity->getFont();
|
||||
_effect = entity->getTextEffect();
|
||||
_effectColor = toGlm(entity->getTextEffectColor());
|
||||
_effectThickness = entity->getTextEffectThickness();
|
||||
updateTextRenderItem();
|
||||
}
|
||||
|
||||
void TextEntityRenderer::doRender(RenderArgs* args) {
|
||||
|
@ -141,25 +131,23 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
|
|||
|
||||
glm::vec4 backgroundColor;
|
||||
Transform modelTransform;
|
||||
BillboardMode billboardMode;
|
||||
PrimitiveMode primitiveMode;
|
||||
RenderLayer renderLayer;
|
||||
withReadLock([&] {
|
||||
modelTransform = _renderTransform;
|
||||
billboardMode = _billboardMode;
|
||||
primitiveMode = _primitiveMode;
|
||||
renderLayer = _renderLayer;
|
||||
|
||||
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
backgroundColor = glm::vec4(_backgroundColor, fadeRatio * _backgroundAlpha);
|
||||
backgroundColor = EntityRenderer::calculatePulseColor(backgroundColor, _pulseProperties, _created);
|
||||
});
|
||||
backgroundColor = EntityRenderer::calculatePulseColor(backgroundColor, _pulseProperties, _created);
|
||||
|
||||
if (backgroundColor.a <= 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), billboardMode, args->getViewFrustum().getPosition()));
|
||||
modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), _billboardMode, args->getViewFrustum().getPosition()));
|
||||
batch.setModelTransform(modelTransform);
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
@ -323,53 +311,36 @@ void entities::TextPayload::render(RenderArgs* args) {
|
|||
glm::vec3 dimensions;
|
||||
BillboardMode billboardMode;
|
||||
|
||||
QString text;
|
||||
glm::vec4 textColor;
|
||||
QString font;
|
||||
TextEffect effect;
|
||||
glm::vec3 effectColor;
|
||||
float effectThickness;
|
||||
float lineHeight, leftMargin, rightMargin, topMargin, bottomMargin;
|
||||
bool forward;
|
||||
textRenderable->withReadLock([&] {
|
||||
modelTransform = textRenderable->_renderTransform;
|
||||
dimensions = textRenderable->_dimensions;
|
||||
billboardMode = textRenderable->_billboardMode;
|
||||
|
||||
text = textRenderable->_text;
|
||||
font = textRenderable->_font;
|
||||
effect = textRenderable->_effect;
|
||||
effectThickness = textRenderable->_effectThickness;
|
||||
|
||||
lineHeight = textRenderable->_lineHeight;
|
||||
leftMargin = textRenderable->_leftMargin;
|
||||
rightMargin = textRenderable->_rightMargin;
|
||||
topMargin = textRenderable->_topMargin;
|
||||
bottomMargin = textRenderable->_bottomMargin;
|
||||
|
||||
float fadeRatio = textRenderable->_isFading ? Interpolate::calculateFadeRatio(textRenderable->_fadeStartTime) : 1.0f;
|
||||
textColor = glm::vec4(textRenderable->_textColor, fadeRatio * textRenderable->_textAlpha);
|
||||
textColor = EntityRenderer::calculatePulseColor(textColor, textRenderable->_pulseProperties, textRenderable->_created);
|
||||
|
||||
effectColor = EntityRenderer::calculatePulseColor(textRenderable->_effectColor, textRenderable->_pulseProperties, textRenderable->_created);
|
||||
|
||||
forward = textRenderable->_renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD;
|
||||
});
|
||||
|
||||
textColor = EntityRenderer::calculatePulseColor(textColor, textRenderable->_pulseProperties, textRenderable->_created);
|
||||
glm::vec3 effectColor = EntityRenderer::calculatePulseColor(textRenderable->_effectColor, textRenderable->_pulseProperties, textRenderable->_created);
|
||||
|
||||
if (textColor.a <= 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), billboardMode, args->getViewFrustum().getPosition()));
|
||||
|
||||
float scale = lineHeight / textRenderer->getFontSize();
|
||||
float scale = textRenderable->_lineHeight / textRenderer->getFontSize();
|
||||
modelTransform.postTranslate(glm::vec3(-0.5, 0.5, 1.0f + EPSILON / dimensions.z));
|
||||
modelTransform.setScale(scale);
|
||||
batch.setModelTransform(modelTransform);
|
||||
|
||||
glm::vec2 bounds = glm::vec2(dimensions.x - (leftMargin + rightMargin), dimensions.y - (topMargin + bottomMargin));
|
||||
textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, bounds / scale, scale,
|
||||
text, font, textColor, effectColor, effectThickness, effect,
|
||||
glm::vec2 bounds = glm::vec2(dimensions.x - (textRenderable->_leftMargin + textRenderable->_rightMargin), dimensions.y - (textRenderable->_topMargin + textRenderable->_bottomMargin));
|
||||
textRenderer->draw(batch, textRenderable->_leftMargin / scale, -textRenderable->_topMargin / scale, bounds / scale, scale,
|
||||
textRenderable->_text, textRenderable->_font, textColor, effectColor, textRenderable->_effectThickness, textRenderable->_effect,
|
||||
textRenderable->_unlit, forward);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@ protected:
|
|||
void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
|
||||
|
||||
private:
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
|
|
@ -125,16 +125,6 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe
|
|||
return false;
|
||||
}
|
||||
|
||||
bool WebEntityRenderer::needsRenderUpdate() const {
|
||||
if (resultWithReadLock<bool>([this] {
|
||||
return !_webSurface;
|
||||
})) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parent::needsRenderUpdate();
|
||||
}
|
||||
|
||||
void WebEntityRenderer::onTimeout() {
|
||||
uint64_t lastRenderTime;
|
||||
if (!resultWithReadLock<bool>([&] {
|
||||
|
@ -261,6 +251,8 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
|
|||
_renderTransform.postScale(entity->getScaledDimensions());
|
||||
});
|
||||
});
|
||||
} else {
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -339,8 +331,11 @@ void WebEntityRenderer::buildWebSurface(const EntityItemPointer& entity, const Q
|
|||
return;
|
||||
}
|
||||
|
||||
++_currentWebCount;
|
||||
WebEntityRenderer::acquireWebSurface(newSourceURL, _contentType == ContentType::HtmlContent, _webSurface, _cachedWebSurface);
|
||||
bool isHTML = _contentType == ContentType::HtmlContent;
|
||||
if (isHTML) {
|
||||
++_currentWebCount;
|
||||
}
|
||||
WebEntityRenderer::acquireWebSurface(newSourceURL, isHTML, _webSurface, _cachedWebSurface);
|
||||
_fadeStartTime = usecTimestampNow();
|
||||
_webSurface->resume();
|
||||
|
||||
|
@ -358,12 +353,15 @@ void WebEntityRenderer::destroyWebSurface() {
|
|||
QSharedPointer<OffscreenQmlSurface> webSurface;
|
||||
withWriteLock([&] {
|
||||
webSurface.swap(_webSurface);
|
||||
_contentType = ContentType::NoContent;
|
||||
|
||||
if (webSurface) {
|
||||
--_currentWebCount;
|
||||
if (_contentType == ContentType::HtmlContent) {
|
||||
--_currentWebCount;
|
||||
}
|
||||
WebEntityRenderer::releaseWebSurface(webSurface, _cachedWebSurface, _connections);
|
||||
}
|
||||
|
||||
_contentType = ContentType::NoContent;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@ public:
|
|||
virtual QObject* getEventHandler() override;
|
||||
|
||||
protected:
|
||||
virtual bool needsRenderUpdate() const override;
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
|
|
@ -189,7 +189,7 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) {
|
|||
CullTest::_containingZones.insert(_entityID);
|
||||
}
|
||||
|
||||
void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
void ZoneEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
auto position = entity->getWorldPosition();
|
||||
auto rotation = entity->getWorldOrientation();
|
||||
auto dimensions = entity->getScaledDimensions();
|
||||
|
@ -199,7 +199,11 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen
|
|||
auto visible = entity->getVisible();
|
||||
if (transformChanged || visible != _lastVisible) {
|
||||
_lastVisible = visible;
|
||||
DependencyManager::get<EntityTreeRenderer>()->updateZone(entity->getID());
|
||||
void* key = (void*)this;
|
||||
EntityItemID id = entity->getID();
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [id] {
|
||||
DependencyManager::get<EntityTreeRenderer>()->updateZone(id);
|
||||
});
|
||||
}
|
||||
|
||||
auto proceduralUserData = entity->getUserData();
|
||||
|
@ -267,10 +271,6 @@ ItemKey ZoneEntityRenderer::getKey() {
|
|||
}
|
||||
|
||||
bool ZoneEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
if (entity->getVisible() != _lastVisible) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (entity->keyLightPropertiesChanged() ||
|
||||
entity->ambientLightPropertiesChanged() ||
|
||||
entity->hazePropertiesChanged() ||
|
||||
|
@ -280,29 +280,11 @@ bool ZoneEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint
|
|||
return true;
|
||||
}
|
||||
|
||||
if (_skyboxTextureURL != entity->getSkyboxProperties().getURL()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (entity->getWorldPosition() != _lastPosition) {
|
||||
return true;
|
||||
}
|
||||
if (entity->getScaledDimensions() != _lastDimensions) {
|
||||
return true;
|
||||
}
|
||||
if (entity->getWorldOrientation() != _lastRotation) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (entity->getUserData() != _proceduralUserData) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ZoneEntityRenderer::updateKeySunFromEntity(const TypedEntityPointer& entity) {
|
||||
setKeyLightMode((ComponentMode)entity->getKeyLightMode());
|
||||
_keyLightMode = (ComponentMode)entity->getKeyLightMode();
|
||||
|
||||
const auto& sunLight = editSunLight();
|
||||
sunLight->setType(graphics::Light::SUN);
|
||||
|
@ -319,7 +301,7 @@ void ZoneEntityRenderer::updateKeySunFromEntity(const TypedEntityPointer& entity
|
|||
}
|
||||
|
||||
void ZoneEntityRenderer::updateAmbientLightFromEntity(const TypedEntityPointer& entity) {
|
||||
setAmbientLightMode((ComponentMode)entity->getAmbientLightMode());
|
||||
_ambientLightMode = (ComponentMode)entity->getAmbientLightMode();
|
||||
|
||||
const auto& ambientLight = editAmbientLight();
|
||||
ambientLight->setType(graphics::Light::AMBIENT);
|
||||
|
@ -339,11 +321,12 @@ void ZoneEntityRenderer::updateAmbientLightFromEntity(const TypedEntityPointer&
|
|||
}
|
||||
|
||||
void ZoneEntityRenderer::updateHazeFromEntity(const TypedEntityPointer& entity) {
|
||||
setHazeMode((ComponentMode)entity->getHazeMode());
|
||||
const uint32_t hazeMode = entity->getHazeMode();
|
||||
|
||||
_hazeMode = (ComponentMode)hazeMode;
|
||||
|
||||
const auto& haze = editHaze();
|
||||
|
||||
const uint32_t hazeMode = entity->getHazeMode();
|
||||
haze->setHazeActive(hazeMode == COMPONENT_MODE_ENABLED);
|
||||
haze->setAltitudeBased(_hazeProperties.getHazeAltitudeEffect());
|
||||
|
||||
|
@ -367,7 +350,7 @@ void ZoneEntityRenderer::updateHazeFromEntity(const TypedEntityPointer& entity)
|
|||
}
|
||||
|
||||
void ZoneEntityRenderer::updateBloomFromEntity(const TypedEntityPointer& entity) {
|
||||
setBloomMode((ComponentMode)entity->getBloomMode());
|
||||
_bloomMode = (ComponentMode)entity->getBloomMode();
|
||||
|
||||
const auto& bloom = editBloom();
|
||||
|
||||
|
@ -377,7 +360,7 @@ void ZoneEntityRenderer::updateBloomFromEntity(const TypedEntityPointer& entity)
|
|||
}
|
||||
|
||||
void ZoneEntityRenderer::updateKeyBackgroundFromEntity(const TypedEntityPointer& entity) {
|
||||
setSkyboxMode((ComponentMode)entity->getSkyboxMode());
|
||||
_skyboxMode = (ComponentMode)entity->getSkyboxMode();
|
||||
|
||||
editBackground();
|
||||
setSkyboxColor(toGlm(_skyboxProperties.getColor()));
|
||||
|
@ -478,26 +461,6 @@ void ZoneEntityRenderer::updateSkyboxMap() {
|
|||
}
|
||||
}
|
||||
|
||||
void ZoneEntityRenderer::setHazeMode(ComponentMode mode) {
|
||||
_hazeMode = mode;
|
||||
}
|
||||
|
||||
void ZoneEntityRenderer::setKeyLightMode(ComponentMode mode) {
|
||||
_keyLightMode = mode;
|
||||
}
|
||||
|
||||
void ZoneEntityRenderer::setAmbientLightMode(ComponentMode mode) {
|
||||
_ambientLightMode = mode;
|
||||
}
|
||||
|
||||
void ZoneEntityRenderer::setSkyboxMode(ComponentMode mode) {
|
||||
_skyboxMode = mode;
|
||||
}
|
||||
|
||||
void ZoneEntityRenderer::setBloomMode(ComponentMode mode) {
|
||||
_bloomMode = mode;
|
||||
}
|
||||
|
||||
void ZoneEntityRenderer::setSkyboxColor(const glm::vec3& color) {
|
||||
editSkybox()->setColor(color);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ protected:
|
|||
virtual ItemKey getKey() override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
|
||||
private:
|
||||
void updateKeyZoneItemFromEntity(const TypedEntityPointer& entity);
|
||||
|
@ -52,12 +52,6 @@ private:
|
|||
void setAmbientURL(const QString& ambientUrl);
|
||||
void setSkyboxURL(const QString& skyboxUrl);
|
||||
|
||||
void setHazeMode(ComponentMode mode);
|
||||
void setKeyLightMode(ComponentMode mode);
|
||||
void setAmbientLightMode(ComponentMode mode);
|
||||
void setSkyboxMode(ComponentMode mode);
|
||||
void setBloomMode(ComponentMode mode);
|
||||
|
||||
void setSkyboxColor(const glm::vec3& color);
|
||||
void setProceduralUserData(const QString& userData);
|
||||
|
||||
|
|
|
@ -1911,13 +1911,11 @@ void EntityItem::setUnscaledDimensions(const glm::vec3& value) {
|
|||
if (glm::length2(getUnscaledDimensions() - newDimensions) > MIN_SCALE_CHANGE_SQUARED) {
|
||||
withWriteLock([&] {
|
||||
_unscaledDimensions = newDimensions;
|
||||
});
|
||||
locationChanged();
|
||||
dimensionsChanged();
|
||||
withWriteLock([&] {
|
||||
_flags |= (Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
|
||||
_queryAACubeSet = false;
|
||||
});
|
||||
locationChanged();
|
||||
dimensionsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,14 @@ void LightEntityItem::setFalloffRadius(float value) {
|
|||
}
|
||||
|
||||
void LightEntityItem::setIsSpotlight(bool value) {
|
||||
if (value == getIsSpotlight()) {
|
||||
bool needsRenderUpdate;
|
||||
withWriteLock([&] {
|
||||
needsRenderUpdate = value != _isSpotlight;
|
||||
_needsRenderUpdate |= needsRenderUpdate;
|
||||
_isSpotlight = value;
|
||||
});
|
||||
|
||||
if (!needsRenderUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -92,25 +99,25 @@ void LightEntityItem::setIsSpotlight(bool value) {
|
|||
newDimensions = glm::vec3(glm::compMax(dimensions));
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
_needsRenderUpdate = true;
|
||||
_isSpotlight = value;
|
||||
});
|
||||
setScaledDimensions(newDimensions);
|
||||
}
|
||||
|
||||
void LightEntityItem::setCutoff(float value) {
|
||||
value = glm::clamp(value, MIN_CUTOFF, MAX_CUTOFF);
|
||||
if (value == getCutoff()) {
|
||||
bool needsRenderUpdate;
|
||||
bool spotlight;
|
||||
withWriteLock([&] {
|
||||
needsRenderUpdate = value != _cutoff;
|
||||
_needsRenderUpdate |= needsRenderUpdate;
|
||||
_cutoff = value;
|
||||
spotlight = _isSpotlight;
|
||||
});
|
||||
|
||||
if (!needsRenderUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
_needsRenderUpdate = true;
|
||||
_cutoff = value;
|
||||
});
|
||||
|
||||
if (getIsSpotlight()) {
|
||||
if (spotlight) {
|
||||
// If we are a spotlight, adjusting the cutoff will affect the area we encapsulate,
|
||||
// so update the dimensions to reflect this.
|
||||
const float length = getScaledDimensions().z;
|
||||
|
|
|
@ -254,26 +254,30 @@ void ModelEntityItem::debugDump() const {
|
|||
}
|
||||
|
||||
void ModelEntityItem::setShapeType(ShapeType type) {
|
||||
bool changed = false;
|
||||
uint32_t flags = 0;
|
||||
withWriteLock([&] {
|
||||
if (type != _shapeType) {
|
||||
if (type == SHAPE_TYPE_STATIC_MESH && _dynamic) {
|
||||
// dynamic and STATIC_MESH are incompatible
|
||||
// since the shape is being set here we clear the dynamic bit
|
||||
_dynamic = false;
|
||||
_flags |= Simulation::DIRTY_MOTION_TYPE;
|
||||
flags = Simulation::DIRTY_MOTION_TYPE;
|
||||
}
|
||||
_shapeType = type;
|
||||
_flags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS;
|
||||
flags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS;
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
markDirtyFlags(flags);
|
||||
locationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
ShapeType ModelEntityItem::getShapeType() const {
|
||||
return computeTrueShapeType();
|
||||
}
|
||||
|
||||
ShapeType ModelEntityItem::computeTrueShapeType() const {
|
||||
ShapeType type = _shapeType;
|
||||
ShapeType type = resultWithReadLock<ShapeType>([&] { return _shapeType; });
|
||||
if (type == SHAPE_TYPE_STATIC_MESH && _dynamic) {
|
||||
// dynamic is incompatible with STATIC_MESH
|
||||
// shouldn't fall in here but just in case --> fall back to COMPOUND
|
||||
|
@ -290,7 +294,6 @@ void ModelEntityItem::setModelURL(const QString& url) {
|
|||
withWriteLock([&] {
|
||||
if (_modelURL != url) {
|
||||
_modelURL = url;
|
||||
_flags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS;
|
||||
_needsRenderUpdate = true;
|
||||
}
|
||||
});
|
||||
|
@ -325,18 +328,10 @@ void ModelEntityItem::setCompoundShapeURL(const QString& url) {
|
|||
withWriteLock([&] {
|
||||
if (_compoundShapeURL.get() != url) {
|
||||
_compoundShapeURL.set(url);
|
||||
_flags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ModelEntityItem::setAnimationURL(const QString& url) {
|
||||
_flags |= Simulation::DIRTY_UPDATEABLE;
|
||||
withWriteLock([&] {
|
||||
_animationProperties.setURL(url);
|
||||
});
|
||||
}
|
||||
|
||||
void ModelEntityItem::setAnimationSettings(const QString& value) {
|
||||
// NOTE: this method only called for old bitstream format
|
||||
|
||||
|
@ -399,20 +394,6 @@ void ModelEntityItem::setAnimationSettings(const QString& value) {
|
|||
});
|
||||
}
|
||||
|
||||
void ModelEntityItem::setAnimationIsPlaying(bool value) {
|
||||
_flags |= Simulation::DIRTY_UPDATEABLE;
|
||||
withWriteLock([&] {
|
||||
_animationProperties.setRunning(value);
|
||||
});
|
||||
}
|
||||
|
||||
void ModelEntityItem::setAnimationFPS(float value) {
|
||||
_flags |= Simulation::DIRTY_UPDATEABLE;
|
||||
withWriteLock([&] {
|
||||
_animationProperties.setFPS(value);
|
||||
});
|
||||
}
|
||||
|
||||
void ModelEntityItem::resizeJointArrays(int newSize) {
|
||||
if (newSize < 0) {
|
||||
return;
|
||||
|
@ -588,10 +569,6 @@ QString ModelEntityItem::getCompoundShapeURL() const {
|
|||
return _compoundShapeURL.get();
|
||||
}
|
||||
|
||||
QString ModelEntityItem::getCollisionShapeURL() const {
|
||||
return getShapeType() == SHAPE_TYPE_COMPOUND ? getCompoundShapeURL() : getModelURL();
|
||||
}
|
||||
|
||||
void ModelEntityItem::setColor(const glm::u8vec3& value) {
|
||||
withWriteLock([&] {
|
||||
_color = value;
|
||||
|
@ -629,61 +606,18 @@ void ModelEntityItem::setAnimationCurrentFrame(float value) {
|
|||
});
|
||||
}
|
||||
|
||||
void ModelEntityItem::setAnimationAllowTranslation(bool value) {
|
||||
withWriteLock([&] {
|
||||
_animationProperties.setAllowTranslation(value);
|
||||
});
|
||||
}
|
||||
|
||||
bool ModelEntityItem::getAnimationAllowTranslation() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _animationProperties.getAllowTranslation();
|
||||
});
|
||||
}
|
||||
|
||||
void ModelEntityItem::setAnimationLoop(bool loop) {
|
||||
withWriteLock([&] {
|
||||
_animationProperties.setLoop(loop);
|
||||
});
|
||||
}
|
||||
|
||||
bool ModelEntityItem::getAnimationLoop() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _animationProperties.getLoop();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void ModelEntityItem::setAnimationHold(bool hold) {
|
||||
withWriteLock([&] {
|
||||
_animationProperties.setHold(hold);
|
||||
});
|
||||
}
|
||||
|
||||
bool ModelEntityItem::getAnimationHold() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _animationProperties.getHold();
|
||||
});
|
||||
}
|
||||
|
||||
bool ModelEntityItem::getAnimationIsPlaying() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _animationProperties.getRunning();
|
||||
});
|
||||
}
|
||||
|
||||
float ModelEntityItem::getAnimationCurrentFrame() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _animationProperties.getCurrentFrame();
|
||||
});
|
||||
}
|
||||
|
||||
float ModelEntityItem::getAnimationFPS() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _animationProperties.getFPS();
|
||||
});
|
||||
}
|
||||
|
||||
bool ModelEntityItem::isAnimatingSomething() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _animationProperties.isValidAndRunning();
|
||||
|
@ -722,6 +656,7 @@ bool ModelEntityItem::applyNewAnimationProperties(AnimationPropertyGroup newProp
|
|||
bool somethingChanged = newProperties != _animationProperties;
|
||||
if (somethingChanged) {
|
||||
_animationProperties = newProperties;
|
||||
_needsRenderUpdate = true;
|
||||
_flags |= Simulation::DIRTY_UPDATEABLE;
|
||||
}
|
||||
return somethingChanged;
|
||||
|
|
|
@ -76,33 +76,18 @@ public:
|
|||
static const QString DEFAULT_COMPOUND_SHAPE_URL;
|
||||
QString getCompoundShapeURL() const;
|
||||
|
||||
// Returns the URL used for the collision shape
|
||||
QString getCollisionShapeURL() const;
|
||||
|
||||
// model related properties
|
||||
virtual void setModelURL(const QString& url);
|
||||
virtual void setCompoundShapeURL(const QString& url);
|
||||
|
||||
// Animation related items...
|
||||
AnimationPropertyGroup getAnimationProperties() const;
|
||||
|
||||
// TODO: audit and remove unused Animation accessors
|
||||
bool hasAnimation() const;
|
||||
QString getAnimationURL() const;
|
||||
virtual void setAnimationURL(const QString& url);
|
||||
|
||||
void setAnimationCurrentFrame(float value);
|
||||
void setAnimationIsPlaying(bool value);
|
||||
void setAnimationFPS(float value);
|
||||
|
||||
void setAnimationAllowTranslation(bool value);
|
||||
float getAnimationCurrentFrame() const;
|
||||
bool getAnimationAllowTranslation() const;
|
||||
|
||||
void setAnimationLoop(bool loop);
|
||||
bool getAnimationLoop() const;
|
||||
|
||||
void setAnimationHold(bool hold);
|
||||
bool getAnimationHold() const;
|
||||
bool isAnimatingSomething() const;
|
||||
|
||||
void setRelayParentJoints(bool relayJoints);
|
||||
bool getRelayParentJoints() const;
|
||||
|
@ -110,11 +95,6 @@ public:
|
|||
void setGroupCulled(bool value);
|
||||
bool getGroupCulled() const;
|
||||
|
||||
bool getAnimationIsPlaying() const;
|
||||
float getAnimationCurrentFrame() const;
|
||||
float getAnimationFPS() const;
|
||||
bool isAnimatingSomething() const;
|
||||
|
||||
static const QString DEFAULT_TEXTURES;
|
||||
const QString getTextures() const;
|
||||
void setTextures(const QString& textures);
|
||||
|
@ -142,7 +122,6 @@ public:
|
|||
private:
|
||||
void setAnimationSettings(const QString& value); // only called for old bitstream format
|
||||
bool applyNewAnimationProperties(AnimationPropertyGroup newProperties);
|
||||
ShapeType computeTrueShapeType() const;
|
||||
|
||||
protected:
|
||||
void resizeJointArrays(int newSize);
|
||||
|
|
|
@ -266,21 +266,21 @@ glm::u8vec3 PolyLineEntityItem::getColor() const {
|
|||
|
||||
void PolyLineEntityItem::setIsUVModeStretch(bool isUVModeStretch) {
|
||||
withWriteLock([&] {
|
||||
_needsRenderUpdate = _isUVModeStretch != isUVModeStretch;
|
||||
_needsRenderUpdate |= _isUVModeStretch != isUVModeStretch;
|
||||
_isUVModeStretch = isUVModeStretch;
|
||||
});
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::setGlow(bool glow) {
|
||||
withWriteLock([&] {
|
||||
_needsRenderUpdate = _glow != glow;
|
||||
_needsRenderUpdate |= _glow != glow;
|
||||
_glow = glow;
|
||||
});
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::setFaceCamera(bool faceCamera) {
|
||||
withWriteLock([&] {
|
||||
_needsRenderUpdate = _faceCamera != faceCamera;
|
||||
_needsRenderUpdate |= _faceCamera != faceCamera;
|
||||
_faceCamera = faceCamera;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -442,4 +442,11 @@ PulsePropertyGroup ShapeEntityItem::getPulseProperties() const {
|
|||
return resultWithReadLock<PulsePropertyGroup>([&] {
|
||||
return _pulseProperties;
|
||||
});
|
||||
}
|
||||
|
||||
void ShapeEntityItem::setUserData(const QString& value) {
|
||||
withWriteLock([&] {
|
||||
_needsRenderUpdate |= _userData != value;
|
||||
_userData = value;
|
||||
});
|
||||
}
|
|
@ -101,6 +101,8 @@ public:
|
|||
|
||||
PulsePropertyGroup getPulseProperties() const;
|
||||
|
||||
void setUserData(const QString& value) override;
|
||||
|
||||
protected:
|
||||
glm::u8vec3 _color;
|
||||
float _alpha { 1.0f };
|
||||
|
|
|
@ -84,12 +84,12 @@ bool ZoneEntityItem::setSubClassProperties(const EntityItemProperties& propertie
|
|||
|
||||
// Contains a QString property, must be synchronized
|
||||
withWriteLock([&] {
|
||||
_keyLightPropertiesChanged = _keyLightProperties.setProperties(properties);
|
||||
_ambientLightPropertiesChanged = _ambientLightProperties.setProperties(properties);
|
||||
_skyboxPropertiesChanged = _skyboxProperties.setProperties(properties);
|
||||
_keyLightPropertiesChanged |= _keyLightProperties.setProperties(properties);
|
||||
_ambientLightPropertiesChanged |= _ambientLightProperties.setProperties(properties);
|
||||
_skyboxPropertiesChanged |= _skyboxProperties.setProperties(properties);
|
||||
});
|
||||
_hazePropertiesChanged = _hazeProperties.setProperties(properties);
|
||||
_bloomPropertiesChanged = _bloomProperties.setProperties(properties);
|
||||
_hazePropertiesChanged |= _hazeProperties.setProperties(properties);
|
||||
_bloomPropertiesChanged |= _bloomProperties.setProperties(properties);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(flyingAllowed, setFlyingAllowed);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(ghostingAllowed, setGhostingAllowed);
|
||||
|
@ -125,7 +125,7 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
bytesFromKeylight = _keyLightProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
propertyFlags, overwriteLocalData, _keyLightPropertiesChanged);
|
||||
});
|
||||
somethingChanged = somethingChanged || _keyLightPropertiesChanged;
|
||||
somethingChanged |= _keyLightPropertiesChanged;
|
||||
bytesRead += bytesFromKeylight;
|
||||
dataAt += bytesFromKeylight;
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
bytesFromAmbientlight = _ambientLightProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
propertyFlags, overwriteLocalData, _ambientLightPropertiesChanged);
|
||||
});
|
||||
somethingChanged = somethingChanged || _ambientLightPropertiesChanged;
|
||||
somethingChanged |= _ambientLightPropertiesChanged;
|
||||
bytesRead += bytesFromAmbientlight;
|
||||
dataAt += bytesFromAmbientlight;
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
bytesFromSkybox = _skyboxProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
propertyFlags, overwriteLocalData, _skyboxPropertiesChanged);
|
||||
});
|
||||
somethingChanged = somethingChanged || _skyboxPropertiesChanged;
|
||||
somethingChanged |= _skyboxPropertiesChanged;
|
||||
bytesRead += bytesFromSkybox;
|
||||
dataAt += bytesFromSkybox;
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
{
|
||||
int bytesFromHaze = _hazeProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
propertyFlags, overwriteLocalData, _hazePropertiesChanged);
|
||||
somethingChanged = somethingChanged || _hazePropertiesChanged;
|
||||
somethingChanged |= _hazePropertiesChanged;
|
||||
bytesRead += bytesFromHaze;
|
||||
dataAt += bytesFromHaze;
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
{
|
||||
int bytesFromBloom = _bloomProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
propertyFlags, overwriteLocalData, _bloomPropertiesChanged);
|
||||
somethingChanged = somethingChanged || _bloomPropertiesChanged;
|
||||
somethingChanged |= _bloomPropertiesChanged;
|
||||
bytesRead += bytesFromBloom;
|
||||
dataAt += bytesFromBloom;
|
||||
}
|
||||
|
@ -444,6 +444,13 @@ uint32_t ZoneEntityItem::getSkyboxMode() const {
|
|||
return _skyboxMode;
|
||||
}
|
||||
|
||||
void ZoneEntityItem::setUserData(const QString& value) {
|
||||
withWriteLock([&] {
|
||||
_needsRenderUpdate |= _userData != value;
|
||||
_userData = value;
|
||||
});
|
||||
}
|
||||
|
||||
void ZoneEntityItem::fetchCollisionGeometryResource() {
|
||||
QUrl hullURL(getCompoundShapeURL());
|
||||
if (hullURL.isEmpty()) {
|
||||
|
|
|
@ -104,6 +104,8 @@ public:
|
|||
uint32_t getScreenshare() const { return _screenshare; }
|
||||
void setScreenshare(uint32_t value) { _screenshare = value; }
|
||||
|
||||
void setUserData(const QString& value) override;
|
||||
|
||||
bool keyLightPropertiesChanged() const { return _keyLightPropertiesChanged; }
|
||||
bool ambientLightPropertiesChanged() const { return _ambientLightPropertiesChanged; }
|
||||
bool skyboxPropertiesChanged() const { return _skyboxPropertiesChanged; }
|
||||
|
|
|
@ -35,11 +35,6 @@ class GLPaintEngine : public QPaintEngine {
|
|||
};
|
||||
|
||||
GLWidget::GLWidget() {
|
||||
#ifdef Q_OS_LINUX
|
||||
// Cause GLWidget::eventFilter to be called.
|
||||
// It wouldn't hurt to do this on Mac and PC too; but apparently it's only needed on linux.
|
||||
qApp->installEventFilter(this);
|
||||
#endif
|
||||
setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
setAttribute(Qt::WA_NativeWindow);
|
||||
setAttribute(Qt::WA_PaintOnScreen);
|
||||
|
@ -118,39 +113,6 @@ bool GLWidget::event(QEvent* event) {
|
|||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the
|
||||
// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to
|
||||
// receive keyPress events for the Alt (and Meta) key in a reliable manner.
|
||||
//
|
||||
// This filter catches events before QMenuBar can steal the keyboard focus.
|
||||
// The idea was borrowed from
|
||||
// http://www.archivum.info/qt-interest@trolltech.com/2006-09/00053/Re-(Qt4)-Alt-key-focus-QMenuBar-(solved).html
|
||||
|
||||
bool GLWidget::eventFilter(QObject*, QEvent* event) {
|
||||
switch (event->type()) {
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease:
|
||||
case QEvent::ShortcutOverride:
|
||||
{
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||
if (keyEvent->key() == Qt::Key_Alt || keyEvent->key() == Qt::Key_Meta) {
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
keyPressEvent(keyEvent);
|
||||
} else if (event->type() == QEvent::KeyRelease) {
|
||||
keyReleaseEvent(keyEvent);
|
||||
} else {
|
||||
QWidget::event(event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool GLWidget::nativeEvent(const QByteArray &eventType, void *message, long *result) {
|
||||
#ifdef Q_OS_WIN32
|
||||
MSG* win32message = static_cast<MSG*>(message);
|
||||
|
|
|
@ -42,9 +42,6 @@ protected:
|
|||
virtual bool event(QEvent* event) override;
|
||||
gl::Context* _context { nullptr };
|
||||
|
||||
private slots:
|
||||
virtual bool eventFilter(QObject*, QEvent* event) override;
|
||||
|
||||
private:
|
||||
QPaintEngine* _paintEngine { nullptr };
|
||||
bool _vsyncSupported { false };
|
||||
|
|
|
@ -153,7 +153,7 @@ void GLBackend::init() {
|
|||
|
||||
if (vendor.contains("NVIDIA") ) {
|
||||
qCDebug(gpugllogging) << "NVIDIA card detected";
|
||||
#if !defined(Q_OS_ANDROID)
|
||||
#if !defined(Q_OS_ANDROID) && !defined(USE_GLES)
|
||||
GL_GET_INTEGER(GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX);
|
||||
GL_GET_INTEGER(GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX);
|
||||
GL_GET_INTEGER(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX);
|
||||
|
@ -170,7 +170,7 @@ void GLBackend::init() {
|
|||
|
||||
} else if (vendor.contains("ATI")) {
|
||||
qCDebug(gpugllogging) << "ATI card detected";
|
||||
#if !defined(Q_OS_ANDROID)
|
||||
#if !defined(Q_OS_ANDROID) && !defined(USE_GLES)
|
||||
GL_GET_INTEGER(TEXTURE_FREE_MEMORY_ATI);
|
||||
#endif
|
||||
|
||||
|
@ -225,12 +225,12 @@ size_t GLBackend::getAvailableMemory() {
|
|||
|
||||
switch( _videoCard ) {
|
||||
case NVIDIA:
|
||||
#if !defined(Q_OS_ANDROID)
|
||||
#if !defined(Q_OS_ANDROID) && !defined(USE_GLES)
|
||||
glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &mem[0]);
|
||||
#endif
|
||||
return mem[0] * BYTES_PER_KIB;
|
||||
case ATI:
|
||||
#if !defined(Q_OS_ANDROID)
|
||||
#if !defined(Q_OS_ANDROID) && !defined(USE_GLES)
|
||||
glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, &mem[0]);
|
||||
#endif
|
||||
return mem[0] * BYTES_PER_KIB;
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace NetworkingConstants {
|
|||
const QUrl HELP_FORUM_URL { "https://forums.vircadia.dev" };
|
||||
const QUrl HELP_SCRIPTING_REFERENCE_URL{ "https://apidocs.vircadia.dev/" };
|
||||
const QUrl HELP_RELEASE_NOTES_URL{ "https://docs.vircadia.dev/release-notes.html" };
|
||||
const QUrl HELP_BUG_REPORT_URL{ "https://github.com/kasenvr/project-athena/issues" };
|
||||
const QUrl HELP_BUG_REPORT_URL{ "https://github.com/vircadia/vircadia/issues" };
|
||||
|
||||
const QString DEFAULT_VIRCADIA_ADDRESS = "file:///~/serverless/tutorial.json";
|
||||
const QString DEFAULT_HOME_ADDRESS = "file:///~/serverless/tutorial.json";
|
||||
|
|
|
@ -31,9 +31,9 @@ static inline void for_each_eye(const std::function<void(ovrEye)>& f) {
|
|||
f(VRAPI_EYE_RIGHT);
|
||||
}
|
||||
|
||||
static inline void for_each_hand(const std::function<void(ovrHandedness)>& f) {
|
||||
f(VRAPI_HAND_LEFT);
|
||||
f(VRAPI_HAND_RIGHT);
|
||||
static inline void for_each_hand(const std::function<void(ovrTrackedDeviceTypeId)>& f) {
|
||||
f(VRAPI_TRACKED_DEVICE_HAND_LEFT);
|
||||
f(VRAPI_TRACKED_DEVICE_HAND_RIGHT);
|
||||
}
|
||||
|
||||
static inline glm::mat4 toGlm(const ovrMatrix4f& om) {
|
||||
|
|
|
@ -324,7 +324,7 @@ struct VrSurface : public TaskQueue {
|
|||
vrapi_SetTrackingSpace( session, VRAPI_TRACKING_SPACE_LOCAL);
|
||||
vrapi_SetPerfThread(session, VRAPI_PERF_THREAD_TYPE_RENDERER, gettid());
|
||||
vrapi_SetClockLevels(session, 2, 4);
|
||||
vrapi_SetExtraLatencyMode(session, VRAPI_EXTRA_LATENCY_MODE_DYNAMIC);
|
||||
vrapi_SetExtraLatencyMode(session, VRAPI_EXTRA_LATENCY_MODE_ON);
|
||||
// Generates a warning on the quest: "vrapi_SetDisplayRefreshRate: Dynamic Display Refresh Rate not supported"
|
||||
// vrapi_SetDisplayRefreshRate(session, 72);
|
||||
});
|
||||
|
|
|
@ -31,7 +31,7 @@ const quint64 LOST_TRACKING_DELAY = 3000000;
|
|||
|
||||
namespace ovr {
|
||||
|
||||
controller::Pose toControllerPose(ovrHandedness hand, const ovrRigidBodyPosef& handPose) {
|
||||
controller::Pose toControllerPose(ovrTrackedDeviceTypeId hand, const ovrRigidBodyPosef& handPose) {
|
||||
// When the sensor-to-world rotation is identity the coordinate axes look like this:
|
||||
//
|
||||
// user
|
||||
|
@ -111,7 +111,7 @@ namespace ovr {
|
|||
return pose;
|
||||
}
|
||||
|
||||
controller::Pose toControllerPose(ovrHandedness hand,
|
||||
controller::Pose toControllerPose(ovrTrackedDeviceTypeId hand,
|
||||
const ovrRigidBodyPosef& handPose,
|
||||
const ovrRigidBodyPosef& lastHandPose) {
|
||||
static const glm::quat yFlip = glm::angleAxis(PI, Vectors::UNIT_Y);
|
||||
|
@ -165,9 +165,9 @@ public:
|
|||
|
||||
private:
|
||||
void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData,
|
||||
ovrHandedness hand, const ovrRigidBodyPosef& handPose);
|
||||
ovrTrackedDeviceTypeId hand, const ovrRigidBodyPosef& handPose);
|
||||
void handleRotationForUntrackedHand(const controller::InputCalibrationData& inputCalibrationData,
|
||||
ovrHandedness hand, const ovrRigidBodyPosef& handPose);
|
||||
ovrTrackedDeviceTypeId hand, const ovrRigidBodyPosef& handPose);
|
||||
void handleHeadPose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData,
|
||||
const ovrRigidBodyPosef& headPose);
|
||||
|
||||
|
@ -379,9 +379,9 @@ void OculusMobileInputDevice::update(float deltaTime, const controller::InputCal
|
|||
handleHeadPose(deltaTime, inputCalibrationData, _headTracking.HeadPose);
|
||||
|
||||
static const auto REQUIRED_HAND_STATUS = VRAPI_TRACKING_STATUS_ORIENTATION_TRACKED | VRAPI_TRACKING_STATUS_POSITION_TRACKED;
|
||||
ovr::for_each_hand([&](ovrHandedness hand) {
|
||||
size_t handIndex = (hand == VRAPI_HAND_LEFT) ? 0 : 1;
|
||||
int controller = (hand == VRAPI_HAND_LEFT) ? controller::LEFT_HAND : controller::RIGHT_HAND;
|
||||
ovr::for_each_hand([&](ovrTrackedDeviceTypeId hand) {
|
||||
size_t handIndex = (hand == VRAPI_TRACKED_DEVICE_HAND_LEFT) ? 0 : 1;
|
||||
int controller = (hand == VRAPI_TRACKED_DEVICE_HAND_LEFT) ? controller::LEFT_HAND : controller::RIGHT_HAND;
|
||||
auto& handData = _hands[handIndex];
|
||||
const auto& tracking = handData.tracking;
|
||||
++numTrackedControllers;
|
||||
|
@ -476,7 +476,7 @@ void OculusMobileInputDevice::focusOutEvent() {
|
|||
|
||||
void OculusMobileInputDevice::handlePose(float deltaTime,
|
||||
const controller::InputCalibrationData& inputCalibrationData,
|
||||
ovrHandedness hand, const ovrRigidBodyPosef& handPose) {
|
||||
ovrTrackedDeviceTypeId hand, const ovrRigidBodyPosef& handPose) {
|
||||
auto poseId = (hand == VRAPI_HAND_LEFT) ? controller::LEFT_HAND : controller::RIGHT_HAND;
|
||||
auto& pose = _poseStateMap[poseId];
|
||||
pose = ovr::toControllerPose(hand, handPose);
|
||||
|
@ -507,7 +507,7 @@ void OculusMobileInputDevice::handleHeadPose(float deltaTime,
|
|||
}
|
||||
|
||||
void OculusMobileInputDevice::handleRotationForUntrackedHand(const controller::InputCalibrationData& inputCalibrationData,
|
||||
ovrHandedness hand, const ovrRigidBodyPosef& handPose) {
|
||||
ovrTrackedDeviceTypeId hand, const ovrRigidBodyPosef& handPose) {
|
||||
auto poseId = (hand == VRAPI_HAND_LEFT ? controller::LEFT_HAND : controller::RIGHT_HAND);
|
||||
auto& pose = _poseStateMap[poseId];
|
||||
const auto& lastHandPose = (hand == VRAPI_HAND_LEFT) ? _hands[0].lastPose : _hands[1].lastPose;
|
||||
|
|
|
@ -425,12 +425,12 @@ void PhysicalEntitySimulation::buildPhysicsTransaction(PhysicsEngine::Transactio
|
|||
continue;
|
||||
}
|
||||
|
||||
bool needsNewShape = object->needsNewShape();
|
||||
bool needsNewShape = object->needsNewShape() && object->_entity->isReadyToComputeShape();
|
||||
if (needsNewShape) {
|
||||
ShapeType shapeType = object->getShapeType();
|
||||
if (shapeType == SHAPE_TYPE_STATIC_MESH) {
|
||||
ShapeRequest shapeRequest(object->_entity);
|
||||
ShapeRequests::iterator requestItr = _shapeRequests.find(shapeRequest);
|
||||
ShapeRequests::iterator requestItr = _shapeRequests.find(shapeRequest);
|
||||
if (requestItr == _shapeRequests.end()) {
|
||||
ShapeInfo shapeInfo;
|
||||
object->_entity->computeShapeInfo(shapeInfo);
|
||||
|
|
|
@ -338,7 +338,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
|
|||
bool intersectedSomething = false;
|
||||
|
||||
// if we aren't active, we can't pick yet...
|
||||
if (!isActive()) {
|
||||
if (!isLoaded()) {
|
||||
return intersectedSomething;
|
||||
}
|
||||
|
||||
|
@ -493,7 +493,7 @@ bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, co
|
|||
bool intersectedSomething = false;
|
||||
|
||||
// if we aren't active, we can't pick yet...
|
||||
if (!isActive()) {
|
||||
if (!isLoaded()) {
|
||||
return intersectedSomething;
|
||||
}
|
||||
|
||||
|
@ -958,16 +958,42 @@ void Model::setCauterized(bool cauterized, const render::ScenePointer& scene) {
|
|||
}
|
||||
}
|
||||
|
||||
void Model::setPrimitiveMode(PrimitiveMode primitiveMode) {
|
||||
void Model::setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePointer& scene) {
|
||||
if (_primitiveMode != primitiveMode) {
|
||||
_primitiveMode = primitiveMode;
|
||||
updateRenderItemsKey(nullptr);
|
||||
if (!scene) {
|
||||
_needsFixupInScene = true;
|
||||
return;
|
||||
}
|
||||
|
||||
bool useDualQuaternionSkinning = _useDualQuaternionSkinning;
|
||||
std::unordered_map<int, bool> shouldInvalidatePayloadShapeKeyMap;
|
||||
|
||||
for (auto& shape : _modelMeshRenderItemShapes) {
|
||||
shouldInvalidatePayloadShapeKeyMap[shape.meshIndex] = shouldInvalidatePayloadShapeKey(shape.meshIndex);
|
||||
}
|
||||
|
||||
render::Transaction transaction;
|
||||
|
||||
for (int i = 0; i < (int)_modelMeshRenderItemIDs.size(); i++) {
|
||||
auto itemID = _modelMeshRenderItemIDs[i];
|
||||
auto meshIndex = _modelMeshRenderItemShapes[i].meshIndex;
|
||||
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
|
||||
transaction.updateItem<ModelMeshPartPayload>(itemID, [invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning] (ModelMeshPartPayload& data) {
|
||||
data.setShapeKey(invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning);
|
||||
});
|
||||
}
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
void Model::setCullWithParent(bool cullWithParent) {
|
||||
void Model::setCullWithParent(bool cullWithParent, const render::ScenePointer& scene) {
|
||||
if (_cullWithParent != cullWithParent) {
|
||||
_cullWithParent = cullWithParent;
|
||||
if (!scene) {
|
||||
_needsFixupInScene = true;
|
||||
return;
|
||||
}
|
||||
|
||||
render::Transaction transaction;
|
||||
auto renderItemsKey = _renderItemKeyGlobalFlags;
|
||||
|
@ -977,14 +1003,27 @@ void Model::setCullWithParent(bool cullWithParent) {
|
|||
data.updateKey(renderItemsKey);
|
||||
});
|
||||
}
|
||||
AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
void Model::setRenderWithZones(const QVector<QUuid>& renderWithZones) {
|
||||
void Model::setRenderWithZones(const QVector<QUuid>& renderWithZones, const render::ScenePointer& scene) {
|
||||
if (_renderWithZones != renderWithZones) {
|
||||
_renderWithZones = renderWithZones;
|
||||
setRenderItemsNeedUpdate();
|
||||
|
||||
if (!scene) {
|
||||
_needsFixupInScene = true;
|
||||
return;
|
||||
}
|
||||
|
||||
render::Transaction transaction;
|
||||
auto renderItemsKey = _renderItemKeyGlobalFlags;
|
||||
for (auto item : _modelMeshRenderItemIDs) {
|
||||
transaction.updateItem<ModelMeshPartPayload>(item, [renderWithZones, renderItemsKey](ModelMeshPartPayload& data) {
|
||||
data.setRenderWithZones(renderWithZones);
|
||||
});
|
||||
}
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1129,7 +1168,7 @@ void Model::renderDebugMeshBoxes(gpu::Batch& batch, bool forward) {
|
|||
}
|
||||
|
||||
Extents Model::getBindExtents() const {
|
||||
if (!isActive()) {
|
||||
if (!isLoaded()) {
|
||||
return Extents();
|
||||
}
|
||||
const Extents& bindExtents = getHFMModel().bindExtents;
|
||||
|
@ -1143,7 +1182,7 @@ glm::vec3 Model::getNaturalDimensions() const {
|
|||
}
|
||||
|
||||
Extents Model::getMeshExtents() const {
|
||||
if (!isActive()) {
|
||||
if (!isLoaded()) {
|
||||
return Extents();
|
||||
}
|
||||
const Extents& extents = getHFMModel().meshExtents;
|
||||
|
@ -1157,7 +1196,7 @@ Extents Model::getMeshExtents() const {
|
|||
}
|
||||
|
||||
Extents Model::getUnscaledMeshExtents() const {
|
||||
if (!isActive()) {
|
||||
if (!isLoaded()) {
|
||||
return Extents();
|
||||
}
|
||||
|
||||
|
@ -1189,7 +1228,7 @@ void Model::setJointTranslation(int index, bool valid, const glm::vec3& translat
|
|||
}
|
||||
|
||||
int Model::getParentJointIndex(int jointIndex) const {
|
||||
return (isActive() && jointIndex != -1) ? getHFMModel().joints.at(jointIndex).parentIndex : -1;
|
||||
return (isLoaded() && jointIndex != -1) ? getHFMModel().joints.at(jointIndex).parentIndex : -1;
|
||||
}
|
||||
|
||||
void Model::setTextures(const QVariantMap& textures) {
|
||||
|
@ -1290,7 +1329,7 @@ QStringList Model::getJointNames() const {
|
|||
Q_RETURN_ARG(QStringList, result));
|
||||
return result;
|
||||
}
|
||||
return isActive() ? getHFMModel().getJointNames() : QStringList();
|
||||
return isLoaded() ? getHFMModel().getJointNames() : QStringList();
|
||||
}
|
||||
|
||||
void Model::setScaleToFit(bool scaleToFit, const glm::vec3& dimensions, bool forceRescale) {
|
||||
|
@ -1306,7 +1345,7 @@ void Model::setScaleToFit(bool scaleToFit, float largestDimension, bool forceRes
|
|||
// mesh, and so we can't do the needed calculations for scaling to fit to a single largest dimension. In this
|
||||
// case we will record that we do want to do this, but we will stick our desired single dimension into the
|
||||
// first element of the vec3 for the non-fixed aspect ration dimensions
|
||||
if (!isActive()) {
|
||||
if (!isLoaded()) {
|
||||
_scaleToFit = scaleToFit;
|
||||
if (scaleToFit) {
|
||||
_scaleToFitDimensions = glm::vec3(largestDimension, FAKE_DIMENSION_PLACEHOLDER, FAKE_DIMENSION_PLACEHOLDER);
|
||||
|
@ -1387,7 +1426,7 @@ void Model::simulate(float deltaTime, bool fullUpdate) {
|
|||
fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit)
|
||||
|| (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint);
|
||||
|
||||
if (isActive() && fullUpdate) {
|
||||
if (isLoaded() && fullUpdate) {
|
||||
onInvalidate();
|
||||
|
||||
// check for scale to fit
|
||||
|
@ -1454,7 +1493,6 @@ void Model::updateBlendshapes() {
|
|||
}
|
||||
|
||||
void Model::deleteGeometry() {
|
||||
_deleteGeometryCounter++;
|
||||
_meshStates.clear();
|
||||
_rig.destroyAnimGraph();
|
||||
_blendedBlendshapeCoefficients.clear();
|
||||
|
|
|
@ -116,14 +116,14 @@ public:
|
|||
void setHifiRenderLayer(render::hifi::Layer layer, const render::ScenePointer& scene = nullptr);
|
||||
|
||||
bool isCauterized() const { return _cauterized; }
|
||||
void setCauterized(bool value, const render::ScenePointer& scene);
|
||||
void setCauterized(bool value, const render::ScenePointer& scene = nullptr);
|
||||
|
||||
void setPrimitiveMode(PrimitiveMode primitiveMode);
|
||||
void setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePointer& scene = nullptr);
|
||||
PrimitiveMode getPrimitiveMode() const { return _primitiveMode; }
|
||||
|
||||
void setCullWithParent(bool value);
|
||||
void setCullWithParent(bool value, const render::ScenePointer& scene = nullptr);
|
||||
|
||||
void setRenderWithZones(const QVector<QUuid>& renderWithZones);
|
||||
void setRenderWithZones(const QVector<QUuid>& renderWithZones, const render::ScenePointer& scene = nullptr);
|
||||
const QVector<QUuid>& getRenderWithZones() const { return _renderWithZones; }
|
||||
|
||||
// Access the current RenderItemKey Global Flags used by the model and applied to the render items representing the parts of the model.
|
||||
|
@ -183,10 +183,7 @@ public:
|
|||
const HFMModel& getHFMModel() const { assert(isLoaded()); return _renderGeometry->getHFMModel(); }
|
||||
const MaterialMapping& getMaterialMapping() const { assert(isLoaded()); return _renderGeometry->getMaterialMapping(); }
|
||||
|
||||
bool isActive() const { return isLoaded(); }
|
||||
|
||||
bool didVisualGeometryRequestFail() const { return _visualGeometryRequestFailed; }
|
||||
bool didCollisionGeometryRequestFail() const { return _collisionGeometryRequestFailed; }
|
||||
|
||||
glm::mat4 getWorldToHFMMatrix() const;
|
||||
|
||||
|
@ -338,7 +335,6 @@ public:
|
|||
|
||||
const MeshState& getMeshState(int index) { return _meshStates.at(index); }
|
||||
|
||||
uint32_t getGeometryCounter() const { return _deleteGeometryCounter; }
|
||||
const QMap<render::ItemID, render::PayloadPointer>& getRenderItems() const { return _modelMeshRenderItemsMap; }
|
||||
BlendShapeOperator getModelBlendshapeOperator() const { return _modelBlendshapeOperator; }
|
||||
|
||||
|
@ -474,10 +470,7 @@ protected:
|
|||
friend class ModelMeshPartPayload;
|
||||
Rig _rig;
|
||||
|
||||
uint32_t _deleteGeometryCounter { 0 };
|
||||
|
||||
bool _visualGeometryRequestFailed { false };
|
||||
bool _collisionGeometryRequestFailed { false };
|
||||
|
||||
bool _renderItemsNeedUpdate { false };
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ public slots:
|
|||
* @param {number} roll - The roll angle in degrees.
|
||||
* @returns {Quat} A quaternion created using the <code>pitch</code>, <code>yaw</code>, and <code>roll</code> Euler angles.
|
||||
* @example <caption>Create a rotation of 180 degrees about the y axis.</caption>
|
||||
* var rotation = Quat.fromPitchYawRollDgrees(0, 180, 0 );
|
||||
* var rotation = Quat.fromPitchYawRollDegrees(0, 180, 0 );
|
||||
*/
|
||||
glm::quat fromPitchYawRollDegrees(float pitch, float yaw, float roll);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Collection of scripts to create server distribution packages. Most of these scripts assume
|
||||
use of the build script at https://github.com/kasenvr/vircadia-builder, specifically that
|
||||
use of the build script at https://github.com/vircadia/vircadia-builder, specifically that
|
||||
the following directory structure exists
|
||||
|
||||
base folder/
|
||||
|
|
|
@ -5,8 +5,8 @@ Maintainer: Heather Anderson <heath@odysseus.anderson.name>
|
|||
Build-Depends: debhelper (>= 10)
|
||||
Standards-Version: 4.1.2
|
||||
Homepage: https://vircadia.com
|
||||
Vcs-Git: https://github.com/kasenvr/project-athena.git
|
||||
Vcs-Browser: https://github.com/kasenvr/project-athena
|
||||
Vcs-Git: https://github.com/vircadia/vircadia.git
|
||||
Vcs-Browser: https://github.com/vircadia/vircadia
|
||||
|
||||
Package: vircadia-server
|
||||
Architecture: any
|
||||
|
|
|
@ -9,7 +9,7 @@ Summary: Vircadia metaverse platform, based on the High Fidelity Engine.
|
|||
|
||||
License: ASL 2.0
|
||||
URL: https://vircadia.com
|
||||
Source0: https://github.com/kasenvr/vircadia-builder/blob/master/vircadia-builder
|
||||
Source0: https://github.com/vircadia/vircadia-builder/blob/master/vircadia-builder
|
||||
|
||||
#BuildRequires: systemd-rpm-macros
|
||||
BuildRequires: chrpath
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// plugins/JSAPIExample/src
|
||||
//
|
||||
// Copyright (c) 2019-2020 humbletim (humbletim@gmail.com)
|
||||
// Copyright (c) 2019 Kalila L. (kasenvr@gmail.com)
|
||||
// Copyright (c) 2019 Kalila L. (somnilibertas@gmail.com)
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
|
|
@ -102,7 +102,7 @@ def parse_args():
|
|||
if True:
|
||||
args = parser.parse_args()
|
||||
else:
|
||||
args = parser.parse_args(['--android', 'questInterface', '--build-root', 'C:/git/project-athena/android/apps/questInterface/.externalNativeBuild/cmake/debug/arm64-v8a'])
|
||||
args = parser.parse_args(['--android', 'questInterface', '--build-root', 'C:/git/vircadia/android/apps/questInterface/.externalNativeBuild/cmake/debug/arm64-v8a'])
|
||||
return args
|
||||
|
||||
def main():
|
||||
|
|
41
screenshare/package-lock.json
generated
|
@ -655,6 +655,12 @@
|
|||
"yargs-parser": "^13.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||
|
@ -680,6 +686,16 @@
|
|||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "13.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
|
||||
"integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1091,9 +1107,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
|
||||
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz",
|
||||
"integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-arrayish": {
|
||||
|
@ -2246,23 +2262,13 @@
|
|||
"requires": {
|
||||
"ansi-regex": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "15.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz",
|
||||
"integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==",
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "13.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz",
|
||||
"integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==",
|
||||
"dev": true,
|
||||
"version": "15.0.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz",
|
||||
"integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==",
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
|
@ -2271,8 +2277,7 @@
|
|||
"camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
5
scripts/system/create/assets/images/icon-material.svg
Normal file
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" style="" xml:space="preserve" width="512" height="512"><rect id="backgroundrect" width="100%" height="100%" x="0" y="0" fill="none" stroke="none"/>
|
||||
|
||||
|
||||
|
||||
<g class="currentLayer" style=""><title>Layer 1</title><g class=""><rect fill="#ffffff" stroke-dashoffset="" fill-rule="nonzero" id="svg_5" x="160.85614078625295" y="158.9852023923402" width="10.531234830969368" height="98.06203275549922" style="color: rgb(0, 0, 0);" class="" fill-opacity="1"/><rect fill="#ffffff" stroke-dashoffset="" fill-rule="nonzero" x="209.15666843567067" y="108.3932784182918" width="10.843375325202928" height="102.80722260475153" style="color: rgb(0, 0, 0);" class="" fill-opacity="1" id="svg_9" transform="matrix(-0.0018477934675853714,0.9538420822131074,-0.9712119570660508,-0.0018147461589597617,367.3500746247034,-41.18663668001403) "/><rect fill="#ffffff" stroke-dashoffset="" fill-rule="nonzero" x="207.3494403472917" y="201.76676589082615" width="10.843375325202928" height="102.80722260475153" style="color: rgb(0, 0, 0);" class="" fill-opacity="1" transform="matrix(-0.0018477934675853714,0.9538420822131074,-0.9712119570660508,-0.0018147461589597617,456.2769576505074,49.770340126555396) " id="svg_10"/><rect fill="#ffffff" stroke-dashoffset="" fill-rule="nonzero" x="248.61641124634482" y="158.98520352941063" width="10.531234830969368" height="98.06203275549922" style="color: rgb(0, 0, 0);" class="" fill-opacity="1" id="svg_8"/></g><g class="" id="svg_11"><rect fill="#ffffff" stroke-dashoffset="" fill-rule="nonzero" id="svg_12" x="253.65058110708242" y="251.20481491088867" width="10.843375325202942" height="102.80722260475159" style="color: rgb(0, 0, 0);" class="" fill-opacity="1"/><rect fill="#ffffff" stroke-dashoffset="" fill-rule="nonzero" x="300.6385287498856" y="204.2168674468994" width="10.843375325202942" height="102.80722260475159" style="color: rgb(0, 0, 0);" class="" fill-opacity="1" id="svg_13" transform="rotate(90.1090087890625 306.0600280761718,255.6206359863281) "/><rect fill="#ffffff" stroke-dashoffset="" fill-rule="nonzero" x="298.8313006615067" y="297.5903549194336" width="10.843375325202942" height="102.80722260475159" style="color: rgb(0, 0, 0);" class="" fill-opacity="1" transform="rotate(90.1090087890625 304.25280761718756,348.9941101074219) " id="svg_14"/><rect fill="#ffffff" stroke-dashoffset="" fill-rule="nonzero" x="344.01202176565175" y="251.20481610298157" width="10.843375325202942" height="102.80722260475159" style="color: rgb(0, 0, 0);" class="" fill-opacity="1" id="svg_15"/></g><path d="M353.92333081107876,157.9109143298332 c1.8017621501637127,0 3.1795802649947857,1.468567041994318 3.1795802649947857,3.146929375702109 v190.28432958412085 c0,1.7832599795645292 -1.3778181148310744,3.146929375702109 -3.1795802649947857,3.146929375702109 H161.77069679656054 c-1.695776141330552,0 -3.1795802649947857,-1.3636693961375808 -3.1795802649947857,-3.146929375702109 V161.05784370553528 c0,-1.678362333707791 1.483804123664234,-3.146929375702109 3.1795802649947857,-3.146929375702109 H353.92333081107876 M353.92333081107876,140.07831453418788 H161.77069679656054 c-11.65846097164755,0 -21.197201766631906,9.440788127106327 -21.197201766631906,20.979529171347394 v190.28432958412085 c0,11.538741044241068 9.538740794984358,20.979529171347394 21.197201766631906,20.979529171347394 h192.2586200233514 c11.65846097164755,0 21.197201766631906,-9.440788127106327 21.197201766631906,-20.979529171347394 V161.05784370553528 C375.12053257771066,149.51910266129423 365.68777779155954,140.07831453418788 353.92333081107876,140.07831453418788 L353.92333081107876,140.07831453418788 z" class="" id="svg_4" fill="#ffffff" fill-opacity="1"/><path d="M348.5,162.5c1.7,0,3,1.4,3,3v181.4c0,1.7-1.3,3-3,3H167.2c-1.6,0-3-1.3-3-3V165.5c0-1.6,1.4-3,3-3H348.5 M348.5,145.5 H167.2c-11,0-20,9-20,20v181.4c0,11,9,20,20,20h181.4c11,0,20-9,20-20V165.5C368.5,154.5,359.6,145.5,348.5,145.5L348.5,145.5z" id="svg_1" class="" fill="#242424" fill-opacity="1"/><rect x="160.3951836560118" y="253.60000610351562" width="97.50482530835689" height="97.50482530835689" id="svg_2" class="" fill="#242424" fill-opacity="1"/><rect x="256.1000061035156" y="159.8000030517578" width="97.80964364091233" height="94.79759099712055" id="svg_3" class=""/><rect x="256.1000061035156" y="157.99277523323144" width="99.61686881173529" height="96.60481879341887" class="" id="svg_19" fill="#242424" fill-opacity="1"/></g></svg>
|
After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 9.2 KiB |
|
@ -1,57 +1,48 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 960 560" style="enable-background:new 0 0 960 560;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path style="fill:#333333;" d="M478.879,127.676c-83.872,0-152.325,68.454-152.325,152.325s68.454,152.325,152.325,152.325
|
||||
s152.325-67.837,152.325-152.325C631.204,196.13,563.366,127.676,478.879,127.676z"/>
|
||||
<path style="fill:#FFFFFF;" d="M478.881,437.281C392.156,437.281,321.6,366.725,321.6,280s70.557-157.281,157.281-157.281
|
||||
S636.157,193.275,636.157,280S565.606,437.281,478.881,437.281z M478.881,132.627c-81.263,0-147.373,66.115-147.373,147.373
|
||||
s66.11,147.373,147.373,147.373c81.258,0,147.368-66.115,147.368-147.373S560.138,132.627,478.881,132.627z"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="459.145" y="4.952" style="fill:#333333;" width="40.086" height="75.237"/>
|
||||
<path style="fill:#FFFFFF;" d="M504.183,85.147h-49.99V0h49.99V85.147z M464.1,75.239h30.174V9.908H464.1V75.239z"/>
|
||||
</g>
|
||||
<g>
|
||||
|
||||
<rect x="272.766" y="90.696" transform="matrix(-0.707 -0.7072 0.7072 -0.707 451.5123 408.5368)" style="fill:#333333;" width="75.236" height="40.085"/>
|
||||
<path style="fill:#FFFFFF;" d="M322.809,158.519l-60.198-60.212l35.351-35.346l60.198,60.212L322.809,158.519z M276.621,98.307
|
||||
l46.188,46.202l21.34-21.335l-46.188-46.202L276.621,98.307z"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="201.98" y="257.8" style="fill:#333333;" width="75.237" height="40.086"/>
|
||||
<path style="fill:#FFFFFF;" d="M282.17,302.845h-85.142V252.85h85.142V302.845z M206.936,292.937h65.327v-30.179h-65.327V292.937z
|
||||
"/>
|
||||
</g>
|
||||
<g>
|
||||
|
||||
<rect x="287.46" y="408.97" transform="matrix(0.7072 0.707 -0.707 0.7072 405.7749 -86.6482)" style="fill:#333333;" width="40.085" height="75.236"/>
|
||||
<path style="fill:#FFFFFF;" d="M295.083,494.359l-35.355-35.346l60.198-60.212l35.355,35.346L295.083,494.359z M273.738,459.013
|
||||
l21.345,21.335l46.187-46.202l-21.345-21.335L273.738,459.013z"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="454.827" y="479.812" style="fill:#333333;" width="40.086" height="75.237"/>
|
||||
<path style="fill:#FFFFFF;" d="M499.868,560h-49.995v-85.137h49.995V560z M459.781,550.091h30.179V484.77h-30.179V550.091z"/>
|
||||
</g>
|
||||
<g>
|
||||
|
||||
<rect x="606.017" y="429.505" transform="matrix(0.707 0.7072 -0.7072 0.707 506.5034 -323.4691)" style="fill:#333333;" width="75.236" height="40.085"/>
|
||||
<path style="fill:#FFFFFF;" d="M656.06,497.32l-60.198-60.212l35.351-35.346l60.198,60.212L656.06,497.32z M609.872,437.107
|
||||
l46.187,46.202l21.34-21.335l-46.188-46.202L609.872,437.107z"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="676.839" y="262.117" style="fill:#333333;" width="75.237" height="40.086"/>
|
||||
<path style="fill:#FFFFFF;" d="M757.032,307.16h-85.147v-49.995h85.147V307.16z M681.792,297.252h65.332v-30.179h-65.332V297.252z
|
||||
"/>
|
||||
</g>
|
||||
<g>
|
||||
|
||||
<rect x="626.205" y="75.756" transform="matrix(-0.7072 -0.707 0.707 -0.7072 1023.1211 650.4535)" style="fill:#333333;" width="40.085" height="75.236"/>
|
||||
<path style="fill:#FFFFFF;" d="M633.825,161.161l-35.351-35.346l60.198-60.212l35.351,35.346L633.825,161.161z M612.485,125.815
|
||||
l21.34,21.335l46.188-46.202l-21.34-21.335L612.485,125.815z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" style="enable-background:new 0 0 960 560;" xml:space="preserve" width="960" height="560"><rect id="backgroundrect" width="100%" height="100%" x="0" y="0" fill="none" stroke="none"/>
|
||||
|
||||
<g class="currentLayer" style=""><title>Layer 1</title>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<g class="selected"><path style="" d="M478.879,127.676c-83.872,0-152.325,68.454-152.325,152.325s68.454,152.325,152.325,152.325 s152.325-67.837,152.325-152.325C631.204,196.13,563.366,127.676,478.879,127.676z" id="svg_3" class="" fill="#242424" fill-opacity="1"/><path style="fill:#FFFFFF;" d="M478.881,437.281C392.156,437.281,321.6,366.725,321.6,280s70.557-157.281,157.281-157.281 S636.157,193.275,636.157,280S565.606,437.281,478.881,437.281z M478.881,132.627c-81.263,0-147.373,66.115-147.373,147.373 s66.11,147.373,147.373,147.373c81.258,0,147.368-66.115,147.368-147.373S560.138,132.627,478.881,132.627z" id="svg_4" class=""/><rect x="459.1449890136719" y="4.952000141143799" style="" width="40.08599853515625" height="75.23699951171875" id="svg_6" class="" fill="#242424" fill-opacity="1"/><path style="fill:#FFFFFF;" d="M504.183,85.147h-49.99V0h49.99V85.147z M464.1,75.239h30.174V9.908H464.1V75.239z" id="svg_7" class=""/><rect x="272.7659912109375" y="90.69599914550781" transform="matrix(-0.707,-0.7072,0.7072,-0.707,451.5123,408.5368) " style="" width="75.23600006103516" height="40.084999084472656" id="svg_9" class="" fill="#242424" fill-opacity="1"/><path style="fill:#FFFFFF;" d="M322.809,158.519l-60.198-60.212l35.351-35.346l60.198,60.212L322.809,158.519z M276.621,98.307 l46.188,46.202l21.34-21.335l-46.188-46.202L276.621,98.307z" id="svg_10" class=""/><rect x="201.97999572753906" y="257.79998779296875" style="" width="75.23699951171875" height="40.08599853515625" id="svg_12" class="" fill="#242424" fill-opacity="1"/><path style="fill:#FFFFFF;" d="M282.17,302.845h-85.142V252.85h85.142V302.845z M206.936,292.937h65.327v-30.179h-65.327V292.937z " id="svg_13" class=""/><g id="svg_14" class="">
|
||||
|
||||
<rect x="287.4599914550781" y="408.9700012207031" transform="matrix(0.7072,0.707,-0.707,0.7072,405.7749,-86.6482) " style="fill:#333333;" width="40.084999084472656" height="75.23600006103516" id="svg_15"/>
|
||||
<path style="fill:#FFFFFF;" d="M295.083,494.359l-35.355-35.346l60.198-60.212l35.355,35.346L295.083,494.359z M273.738,459.013 l21.345,21.335l46.187-46.202l-21.345-21.335L273.738,459.013z" id="svg_16"/>
|
||||
</g><rect x="676.8389892578125" y="262.11700439453125" style="" width="75.23699951171875" height="40.08599853515625" id="svg_24" class="" fill="#242424" fill-opacity="1"/><path style="fill:#FFFFFF;" d="M757.032,307.16h-85.147v-49.995h85.147V307.16z M681.792,297.252h65.332v-30.179h-65.332V297.252z " id="svg_25" class=""/><rect x="626.2050170898438" y="75.75599670410156" transform="matrix(-0.7072,-0.707,0.707,-0.7072,1023.1211,650.4535) " style="" width="40.084999084472656" height="75.23600006103516" id="svg_27" class="" fill="#242424" fill-opacity="1"/><path style="fill:#FFFFFF;" d="M633.825,161.161l-35.351-35.346l60.198-60.212l35.351,35.346L633.825,161.161z M612.485,125.815 l21.34,21.335l46.188-46.202l-21.34-21.335L612.485,125.815z" id="svg_28" class=""/><rect x="287.4599914550781" y="408.9700012207031" transform="matrix(0.7072,0.707,-0.707,0.7072,405.7749,-86.6482) " style="" width="40.084999084472656" height="75.23600006103516" id="svg_31" class="" fill="#242424" fill-opacity="1"/><path style="fill:#FFFFFF;" d="M295.083,494.359l-35.355-35.346l60.198-60.212l35.355,35.346L295.083,494.359z M273.738,459.013 l21.345,21.335l46.187-46.202l-21.345-21.335L273.738,459.013z" id="svg_33" class=""/><rect x="454.8269958496094" y="479.81201171875" style="" width="40.08599853515625" height="75.23699951171875" id="svg_18" class="" fill="#242424" fill-opacity="1"/><path style="fill:#FFFFFF;" d="M499.868,560h-49.995v-85.137h49.995V560z M459.781,550.091h30.179V484.77h-30.179V550.091z" id="svg_19" class=""/><rect x="606.0170288085938" y="429.5050048828125" transform="matrix(0.707,0.7072,-0.7072,0.707,506.5034,-323.4691) " style="" width="75.23600006103516" height="40.084999084472656" id="svg_21" class="" fill="#242424" fill-opacity="1"/><path style="fill:#FFFFFF;" d="M656.06,497.32l-60.198-60.212l35.351-35.346l60.198,60.212L656.06,497.32z M609.872,437.107 l46.187,46.202l21.34-21.335l-46.188-46.202L609.872,437.107z" id="svg_22" class=""/></g></g></svg>
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 4.5 KiB |
|
@ -1,37 +1,26 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="3.44 0 735.338 557.9" style="enable-background:new 3.44 0 735.338 557.9;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<rect x="503.95" y="260.767" style="fill:#333333;" width="227.728" height="36.376"/>
|
||||
<path style="fill:#FFFFFF;" d="M738.778,304.24H496.854v-50.566h241.924V304.24z M511.052,290.042H724.58v-22.17H511.052V290.042z
|
||||
"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
|
||||
<rect x="426.085" y="465.518" transform="matrix(-0.9213 -0.3888 0.3888 -0.9213 849.3369 1139.2869)" style="fill:#333333;" width="227.719" height="36.374"/>
|
||||
<path style="fill:#FFFFFF;" d="M641.55,554.032l-222.88-94.06l19.668-46.6l222.88,94.06L641.55,554.032z M437.277,452.401
|
||||
l196.717,83.024l8.617-20.423l-196.717-83.024L437.277,452.401z"/>
|
||||
</g>
|
||||
<g>
|
||||
|
||||
<rect x="426.295" y="56.081" transform="matrix(0.9213 -0.3888 0.3888 0.9213 13.624 215.8596)" style="fill:#333333;" width="227.719" height="36.374"/>
|
||||
<path style="fill:#FFFFFF;" d="M438.545,144.598l-19.668-46.6l222.887-94.06l19.667,46.6L438.545,144.598z M437.484,105.568
|
||||
l8.617,20.423l196.724-83.024l-8.617-20.423L437.484,105.568z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#333333;" d="M430.774,280.311c0-50.839-32.955-93.895-78.642-109.198V13.262L124.404,165.081H10.54v227.728
|
||||
h113.864l227.728,151.819V389.51C397.818,374.206,430.774,331.151,430.774,280.311z"/>
|
||||
<path style="fill:#FFFFFF;" d="M359.23,557.9L122.257,399.908H3.44V157.978h118.816L359.23,0v166.117
|
||||
c47.245,18.038,78.642,63.308,78.642,114.192s-31.397,96.154-78.642,114.192V557.9z M17.638,385.711h108.917l218.478,145.652
|
||||
V384.407l4.846-1.622c44.139-14.794,73.796-55.973,73.796-102.476s-29.657-87.682-73.796-102.476l-4.846-1.622V26.538
|
||||
L126.555,172.176H17.638V385.711z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" style="enable-background:new 3.44 0 735.338 557.9;" xml:space="preserve" width="735.338" height="557.9"><rect id="backgroundrect" width="100%" height="100%" x="0" y="0" fill="none" stroke="none"/>
|
||||
|
||||
<g class="currentLayer" style=""><title>Layer 1</title>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<g class="selected"><rect x="503.95001220703125" y="260.7669982910156" style="" width="227.72799682617188" height="36.375999450683594" id="svg_3" class="" fill="#242424" fill-opacity="1"/><path style="fill:#FFFFFF;" d="M738.778,304.24H496.854v-50.566h241.924V304.24z M511.052,290.042H724.58v-22.17H511.052V290.042z " id="svg_4" class=""/><rect x="426.0849914550781" y="465.51800537109375" transform="matrix(-0.9213,-0.3888,0.3888,-0.9213,849.3369,1139.2869) " style="" width="227.718994140625" height="36.374000549316406" id="svg_8" class="" fill="#242424" fill-opacity="1"/><path style="fill:#FFFFFF;" d="M641.55,554.032l-222.88-94.06l19.668-46.6l222.88,94.06L641.55,554.032z M437.277,452.401 l196.717,83.024l8.617-20.423l-196.717-83.024L437.277,452.401z" id="svg_9" class=""/><rect x="426.2950134277344" y="56.08100128173828" transform="matrix(0.9213,-0.3888,0.3888,0.9213,13.624,215.8596) " style="" width="227.718994140625" height="36.374000549316406" id="svg_11" class="" fill="#242424" fill-opacity="1"/><path style="fill:#FFFFFF;" d="M438.545,144.598l-19.668-46.6l222.887-94.06l19.667,46.6L438.545,144.598z M437.484,105.568 l8.617,20.423l196.724-83.024l-8.617-20.423L437.484,105.568z" id="svg_12" class=""/><path style="" d="M430.774,280.311c0-50.839-32.955-93.895-78.642-109.198V13.262L124.404,165.081H10.54v227.728 h113.864l227.728,151.819V389.51C397.818,374.206,430.774,331.151,430.774,280.311z" id="svg_14" class="" fill="#242424" fill-opacity="1"/><path style="fill:#FFFFFF;" d="M359.23,557.9L122.257,399.908H3.44V157.978h118.816L359.23,0v166.117 c47.245,18.038,78.642,63.308,78.642,114.192s-31.397,96.154-78.642,114.192V557.9z M17.638,385.711h108.917l218.478,145.652 V384.407l4.846-1.622c44.139-14.794,73.796-55.973,73.796-102.476s-29.657-87.682-73.796-102.476l-4.846-1.622V26.538 L126.555,172.176H17.638V385.711z" id="svg_15" class=""/></g></g></svg>
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 24 KiB |
|
@ -41,7 +41,7 @@ Script.include([
|
|||
var CreateWindow = Script.require('./modules/createWindow.js');
|
||||
|
||||
var TITLE_OFFSET = 60;
|
||||
var CREATE_TOOLS_WIDTH = 490;
|
||||
var CREATE_TOOLS_WIDTH = 750;
|
||||
var MAX_DEFAULT_ENTITY_LIST_HEIGHT = 942;
|
||||
var ENTIRE_DOMAIN_SCAN_RADIUS = 27713;
|
||||
|
||||
|
@ -87,21 +87,24 @@ var PARTICLE_SYSTEM_URL = Script.resolvePath("assets/images/icon-particles.svg")
|
|||
var POINT_LIGHT_URL = Script.resolvePath("assets/images/icon-point-light.svg");
|
||||
var SPOT_LIGHT_URL = Script.resolvePath("assets/images/icon-spot-light.svg");
|
||||
var ZONE_URL = Script.resolvePath("assets/images/icon-zone.svg");
|
||||
var MATERIAL_URL = Script.resolvePath("assets/images/icon-material.svg");
|
||||
|
||||
var entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect', 'Zone'], function(entityID) {
|
||||
var properties = Entities.getEntityProperties(entityID, ['type', 'isSpotlight']);
|
||||
if (properties.type === 'Light') {
|
||||
return {
|
||||
url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL,
|
||||
};
|
||||
} else if (properties.type === 'Zone') {
|
||||
return {
|
||||
url: ZONE_URL,
|
||||
var entityIconOverlayManager = new EntityIconOverlayManager(["Light", "ParticleEffect", "Zone", "Material"], function(entityID) {
|
||||
var properties = Entities.getEntityProperties(entityID, ["type", "isSpotlight", "parentID", "name"]);
|
||||
if (properties.type === "Light") {
|
||||
return {
|
||||
imageURL: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL
|
||||
};
|
||||
} else if (properties.type === "Zone") {
|
||||
return { imageURL: ZONE_URL };
|
||||
} else if (properties.type === "Material") {
|
||||
if (properties.parentID !== Uuid.NULL && properties.name !== "MATERIAL_" + entityShapeVisualizerSessionName) {
|
||||
return { imageURL: MATERIAL_URL };
|
||||
} else {
|
||||
return { imageURL: "" };
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
url: PARTICLE_SYSTEM_URL,
|
||||
};
|
||||
return { imageURL: PARTICLE_SYSTEM_URL };
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -148,11 +151,13 @@ var DEFAULT_DIMENSIONS = {
|
|||
|
||||
var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS);
|
||||
|
||||
var SUBMENU_ENTITY_EDITOR_PREFERENCES = "Edit > Create Application - Preferences";
|
||||
var MENU_IMPORT_FROM_FILE = "Import Entities (.json) From a File";
|
||||
var MENU_IMPORT_FROM_URL = "Import Entities (.json) From a URL";
|
||||
var MENU_CREATE_SEPARATOR = "Create Application";
|
||||
var SUBMENU_ENTITY_EDITOR_PREFERENCES = "Edit > Preferences";
|
||||
var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select";
|
||||
var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus";
|
||||
var MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "Show Lights and Particle Systems in Create Mode";
|
||||
var MENU_SHOW_ZONES_IN_EDIT_MODE = "Show Zones in Create Mode";
|
||||
var MENU_SHOW_ICONS_IN_CREATE_MODE = "Show Icons in Create Mode";
|
||||
var MENU_CREATE_ENTITIES_GRABBABLE = "Create Entities As Grabbable (except Zones, Particles, and Lights)";
|
||||
var MENU_ALLOW_SELECTION_LARGE = "Allow Selecting of Large Models";
|
||||
var MENU_ALLOW_SELECTION_SMALL = "Allow Selecting of Small Models";
|
||||
|
@ -880,13 +885,11 @@ var toolBar = (function () {
|
|||
});
|
||||
|
||||
addButton("importEntitiesButton", function() {
|
||||
Window.browseChanged.connect(onFileOpenChanged);
|
||||
Window.browseAsync("Select .json to Import", "", "*.json");
|
||||
importEntitiesFromFile();
|
||||
});
|
||||
|
||||
addButton("importEntitiesFromUrlButton", function() {
|
||||
Window.promptTextChanged.connect(onPromptTextChanged);
|
||||
Window.promptAsync("URL of a .json to import", "");
|
||||
importEntitiesFromUrl();
|
||||
});
|
||||
|
||||
addButton("openAssetBrowserButton", function() {
|
||||
|
@ -1040,8 +1043,7 @@ var toolBar = (function () {
|
|||
// everybody else to think that Interface has lost focus overall. fogbugzid:558
|
||||
// Window.setFocus();
|
||||
}
|
||||
entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE));
|
||||
Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
|
||||
entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_ICONS_IN_CREATE_MODE));
|
||||
};
|
||||
|
||||
initialize();
|
||||
|
@ -1402,6 +1404,22 @@ function setupModelMenus() {
|
|||
position: 1,
|
||||
});
|
||||
|
||||
Menu.addMenuItem({
|
||||
menuName: "Edit",
|
||||
menuItemName: MENU_CREATE_SEPARATOR,
|
||||
isSeparator: true
|
||||
});
|
||||
Menu.addMenuItem({
|
||||
menuName: "Edit",
|
||||
menuItemName: MENU_IMPORT_FROM_FILE,
|
||||
afterItem: MENU_CREATE_SEPARATOR
|
||||
});
|
||||
Menu.addMenuItem({
|
||||
menuName: "Edit",
|
||||
menuItemName: MENU_IMPORT_FROM_URL,
|
||||
afterItem: MENU_IMPORT_FROM_FILE
|
||||
});
|
||||
|
||||
Menu.addMenu(SUBMENU_ENTITY_EDITOR_PREFERENCES);
|
||||
|
||||
Menu.addMenuItem({
|
||||
|
@ -1448,22 +1466,15 @@ function setupModelMenus() {
|
|||
});
|
||||
Menu.addMenuItem({
|
||||
menuName: SUBMENU_ENTITY_EDITOR_PREFERENCES,
|
||||
menuItemName: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE,
|
||||
menuItemName: MENU_SHOW_ICONS_IN_CREATE_MODE,
|
||||
afterItem: MENU_EASE_ON_FOCUS,
|
||||
isCheckable: true,
|
||||
isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) !== "false"
|
||||
});
|
||||
Menu.addMenuItem({
|
||||
menuName: SUBMENU_ENTITY_EDITOR_PREFERENCES,
|
||||
menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE,
|
||||
afterItem: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE,
|
||||
isCheckable: true,
|
||||
isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) !== "false"
|
||||
});
|
||||
Menu.addMenuItem({
|
||||
menuName: SUBMENU_ENTITY_EDITOR_PREFERENCES,
|
||||
menuItemName: MENU_ENTITY_LIST_DEFAULT_RADIUS,
|
||||
afterItem: MENU_SHOW_ZONES_IN_EDIT_MODE
|
||||
afterItem: MENU_SHOW_ICONS_IN_CREATE_MODE
|
||||
});
|
||||
|
||||
Entities.setLightsArePickable(false);
|
||||
|
@ -1480,19 +1491,20 @@ function cleanupModelMenus() {
|
|||
Menu.removeMenuItem(SUBMENU_ENTITY_EDITOR_PREFERENCES, MENU_ALLOW_SELECTION_LIGHTS);
|
||||
Menu.removeMenuItem(SUBMENU_ENTITY_EDITOR_PREFERENCES, MENU_AUTO_FOCUS_ON_SELECT);
|
||||
Menu.removeMenuItem(SUBMENU_ENTITY_EDITOR_PREFERENCES, MENU_EASE_ON_FOCUS);
|
||||
Menu.removeMenuItem(SUBMENU_ENTITY_EDITOR_PREFERENCES, MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE);
|
||||
Menu.removeMenuItem(SUBMENU_ENTITY_EDITOR_PREFERENCES, MENU_SHOW_ZONES_IN_EDIT_MODE);
|
||||
Menu.removeMenuItem(SUBMENU_ENTITY_EDITOR_PREFERENCES, MENU_SHOW_ICONS_IN_CREATE_MODE);
|
||||
Menu.removeMenuItem(SUBMENU_ENTITY_EDITOR_PREFERENCES, MENU_CREATE_ENTITIES_GRABBABLE);
|
||||
Menu.removeMenuItem(SUBMENU_ENTITY_EDITOR_PREFERENCES, MENU_ENTITY_LIST_DEFAULT_RADIUS);
|
||||
Menu.removeMenu(SUBMENU_ENTITY_EDITOR_PREFERENCES);
|
||||
Menu.removeMenu(SUBMENU_ENTITY_EDITOR_PREFERENCES);
|
||||
Menu.removeMenuItem("Edit", MENU_IMPORT_FROM_URL);
|
||||
Menu.removeMenuItem("Edit", MENU_IMPORT_FROM_FILE);
|
||||
Menu.removeSeparator("Edit", MENU_CREATE_SEPARATOR);
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
toolBar.setActive(false);
|
||||
Settings.setValue(SETTING_AUTO_FOCUS_ON_SELECT, Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT));
|
||||
Settings.setValue(SETTING_EASE_ON_FOCUS, Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
|
||||
Settings.setValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE));
|
||||
Settings.setValue(SETTING_SHOW_ZONES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
|
||||
Settings.setValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ICONS_IN_CREATE_MODE));
|
||||
|
||||
Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LARGE));
|
||||
Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, Menu.isOptionChecked(MENU_ALLOW_SELECTION_SMALL));
|
||||
|
@ -1849,15 +1861,17 @@ function handleMenuEvent(menuItem) {
|
|||
undoHistory.undo();
|
||||
} else if (menuItem === "Redo") {
|
||||
undoHistory.redo();
|
||||
} else if (menuItem === MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) {
|
||||
entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE));
|
||||
} else if (menuItem === MENU_SHOW_ZONES_IN_EDIT_MODE) {
|
||||
Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
|
||||
} else if (menuItem === MENU_SHOW_ICONS_IN_CREATE_MODE) {
|
||||
entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_ICONS_IN_CREATE_MODE));
|
||||
} else if (menuItem === MENU_CREATE_ENTITIES_GRABBABLE) {
|
||||
Settings.setValue(SETTING_EDIT_PREFIX + menuItem, Menu.isOptionChecked(menuItem));
|
||||
} else if (menuItem === MENU_ENTITY_LIST_DEFAULT_RADIUS) {
|
||||
Window.promptTextChanged.connect(onPromptTextChangedDefaultRadiusUserPref);
|
||||
Window.promptAsync("Entity List Default Radius (in meters)", "" + Settings.getValue(SETTING_ENTITY_LIST_DEFAULT_RADIUS, 100));
|
||||
} else if (menuItem === MENU_IMPORT_FROM_FILE) {
|
||||
importEntitiesFromFile();
|
||||
} else if (menuItem === MENU_IMPORT_FROM_URL) {
|
||||
importEntitiesFromUrl();
|
||||
}
|
||||
tooltip.show(false);
|
||||
}
|
||||
|
@ -2015,18 +2029,27 @@ function toggleKey(value) {
|
|||
}
|
||||
function focusKey(value) {
|
||||
if (value === 0) { // on release
|
||||
cameraManager.enable();
|
||||
if (selectionManager.hasSelection()) {
|
||||
cameraManager.focus(selectionManager.worldPosition, selectionManager.worldDimensions,
|
||||
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
|
||||
}
|
||||
setCameraFocusToSelection();
|
||||
}
|
||||
}
|
||||
function gridKey(value) {
|
||||
if (value === 0) { // on release
|
||||
if (selectionManager.hasSelection()) {
|
||||
grid.moveToSelection();
|
||||
}
|
||||
alignGridToSelection();
|
||||
}
|
||||
}
|
||||
function viewGridKey(value) {
|
||||
if (value === 0) { // on release
|
||||
toggleGridVisibility();
|
||||
}
|
||||
}
|
||||
function snapKey(value) {
|
||||
if (value === 0) { // on release
|
||||
entityListTool.toggleSnapToGrid();
|
||||
}
|
||||
}
|
||||
function gridToAvatarKey(value) {
|
||||
if (value === 0) { // on release
|
||||
alignGridToAvatar();
|
||||
}
|
||||
}
|
||||
function recursiveAdd(newParentID, parentData) {
|
||||
|
@ -2426,7 +2449,6 @@ var PropertiesTool = function (opts) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (data.onlyUpdateEntities) {
|
||||
blockPropertyUpdates = true;
|
||||
} else {
|
||||
|
@ -2435,6 +2457,10 @@ var PropertiesTool = function (opts) {
|
|||
}
|
||||
selectionManager._update(false, this);
|
||||
blockPropertyUpdates = false;
|
||||
|
||||
if (data.snapToGrid !== undefined) {
|
||||
entityListTool.setListMenuSnapToGrid(data.snapToGrid);
|
||||
}
|
||||
} else if (data.type === 'saveUserData' || data.type === 'saveMaterialData') {
|
||||
data.ids.forEach(function(entityID) {
|
||||
Entities.editEntity(entityID, data.properties);
|
||||
|
@ -2789,7 +2815,10 @@ if (isOnMacPlatform) {
|
|||
}
|
||||
mapping.from([Controller.Hardware.Keyboard.T]).to(toggleKey);
|
||||
mapping.from([Controller.Hardware.Keyboard.F]).to(focusKey);
|
||||
mapping.from([Controller.Hardware.Keyboard.G]).to(gridKey);
|
||||
mapping.from([Controller.Hardware.Keyboard.J]).to(gridKey);
|
||||
mapping.from([Controller.Hardware.Keyboard.G]).to(viewGridKey);
|
||||
mapping.from([Controller.Hardware.Keyboard.H]).to(snapKey);
|
||||
mapping.from([Controller.Hardware.Keyboard.K]).to(gridToAvatarKey);
|
||||
mapping.from([Controller.Hardware.Keyboard.X])
|
||||
.when([Controller.Hardware.Keyboard.Control])
|
||||
.to(whenReleased(function() { selectionManager.cutSelectedEntities() }));
|
||||
|
@ -2830,8 +2859,14 @@ keyUpEventFromUIWindow = function(keyUpEvent) {
|
|||
toggleKey(pressedValue);
|
||||
} else if (keyUpEvent.keyCodeString === "F") {
|
||||
focusKey(pressedValue);
|
||||
} else if (keyUpEvent.keyCodeString === "G") {
|
||||
} else if (keyUpEvent.keyCodeString === "J") {
|
||||
gridKey(pressedValue);
|
||||
} else if (keyUpEvent.keyCodeString === "G") {
|
||||
viewGridKey(pressedValue);
|
||||
} else if (keyUpEvent.keyCodeString === "H") {
|
||||
snapKey(pressedValue);
|
||||
} else if (keyUpEvent.keyCodeString === "K") {
|
||||
gridToAvatarKey(pressedValue);
|
||||
} else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "X") {
|
||||
selectionManager.cutSelectedEntities();
|
||||
} else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "C") {
|
||||
|
@ -2938,4 +2973,46 @@ function getDomainOnlyChildrenIDs(id) {
|
|||
return realChildren;
|
||||
}
|
||||
|
||||
function importEntitiesFromFile() {
|
||||
Window.browseChanged.connect(onFileOpenChanged);
|
||||
Window.browseAsync("Select .json to Import", "", "*.json");
|
||||
}
|
||||
|
||||
function importEntitiesFromUrl() {
|
||||
Window.promptTextChanged.connect(onPromptTextChanged);
|
||||
Window.promptAsync("URL of a .json to import", "");
|
||||
}
|
||||
|
||||
function setCameraFocusToSelection() {
|
||||
cameraManager.enable();
|
||||
if (selectionManager.hasSelection()) {
|
||||
cameraManager.focus(selectionManager.worldPosition, selectionManager.worldDimensions,
|
||||
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
|
||||
}
|
||||
}
|
||||
|
||||
function alignGridToSelection() {
|
||||
if (selectionManager.hasSelection()) {
|
||||
if (!grid.getVisible()) {
|
||||
grid.setVisible(true, true);
|
||||
}
|
||||
grid.moveToSelection();
|
||||
}
|
||||
}
|
||||
|
||||
function alignGridToAvatar() {
|
||||
if (!grid.getVisible()) {
|
||||
grid.setVisible(true, true);
|
||||
}
|
||||
grid.moveToAvatar();
|
||||
}
|
||||
|
||||
function toggleGridVisibility() {
|
||||
if (!grid.getVisible()) {
|
||||
grid.setVisible(true, true);
|
||||
} else {
|
||||
grid.setVisible(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
}()); // END LOCAL_SCOPE
|
||||
|
|
|
@ -146,6 +146,20 @@ EntityListTool = function(shouldUseEditTabletApp) {
|
|||
});
|
||||
};
|
||||
|
||||
that.setListMenuSnapToGrid = function (isSnapToGrid) {
|
||||
emitJSONScriptEvent({ "type": "setSnapToGrid", "snap": isSnapToGrid });
|
||||
};
|
||||
|
||||
that.toggleSnapToGrid = function () {
|
||||
if (!grid.getSnapToGrid()) {
|
||||
grid.setSnapToGrid(true);
|
||||
emitJSONScriptEvent({ "type": "setSnapToGrid", "snap": true });
|
||||
} else {
|
||||
grid.setSnapToGrid(false);
|
||||
emitJSONScriptEvent({ "type": "setSnapToGrid", "snap": false });
|
||||
}
|
||||
};
|
||||
|
||||
function valueIfDefined(value) {
|
||||
return value !== undefined ? value : "";
|
||||
}
|
||||
|
@ -381,7 +395,22 @@ EntityListTool = function(shouldUseEditTabletApp) {
|
|||
});
|
||||
} else if (data.type === 'saveColumnsConfigSetting') {
|
||||
Settings.setValue(SETTING_EDITOR_COLUMNS_SETUP, data.columnsData);
|
||||
} else if (data.type === 'importFromFile') {
|
||||
importEntitiesFromFile();
|
||||
} else if (data.type === 'importFromUrl') {
|
||||
importEntitiesFromUrl();
|
||||
} else if (data.type === 'setCameraFocusToSelection') {
|
||||
setCameraFocusToSelection();
|
||||
} else if (data.type === 'alignGridToSelection') {
|
||||
alignGridToSelection();
|
||||
} else if (data.type === 'alignGridToAvatar') {
|
||||
alignGridToAvatar();
|
||||
} else if (data.type === 'toggleGridVisibility') {
|
||||
toggleGridVisibility();
|
||||
} else if (data.type === 'toggleSnapToGrid') {
|
||||
that.toggleSnapToGrid();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
webView.webEventReceived.connect(onWebEventReceived);
|
||||
|
|
|
@ -32,8 +32,9 @@
|
|||
</div>
|
||||
<button id="toggle-space-mode" class="hifi-edit-button space-mode-local">Local</button>
|
||||
<input type="button" class="vglyph" id="hmdmultiselect" value="I" style="display: none;" />
|
||||
<input type="button" class="normal" id="selection" value="Selection..." />
|
||||
<input type="button" class="normal" id="actions" value="Actions..." />
|
||||
<input type="button" class="normal" id="selection" value="Select▾" />
|
||||
<input type="button" class="normal" id="actions" value="Edit▾" />
|
||||
<input type="button" class="normal" id="tools" value="Tools▾" />
|
||||
</div>
|
||||
<div id="entity-list">
|
||||
<div id="filter-area">
|
||||
|
@ -159,7 +160,7 @@
|
|||
<div class="entity-list-menu" id="selection-menu" >
|
||||
<button class="menu-button" id="selectall" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Select All</div>
|
||||
<div class = "menu-item-caption">Select All (in List)</div>
|
||||
<div class = "menu-item-shortcut">Ctrl-A</div>
|
||||
</div>
|
||||
</button>
|
||||
|
@ -171,7 +172,7 @@
|
|||
</button>
|
||||
<button class="menu-button" id="selectinverse" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Inverse Selection</div>
|
||||
<div class = "menu-item-caption">Inverse Selection (in List)</div>
|
||||
<div class = "menu-item-shortcut">Ctrl-I</div>
|
||||
</div>
|
||||
</button>
|
||||
|
@ -219,13 +220,71 @@
|
|||
<div class = "menu-item-shortcut"></div>
|
||||
</div>
|
||||
</button>
|
||||
<div class="menu-separator"></div>
|
||||
</div>
|
||||
<div class="entity-list-menu" id="tools-menu" >
|
||||
<button class="menu-button" id="setCameraFocusToSelection" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Set Camera Focus To Selection</div>
|
||||
<div class = "menu-item-shortcut">F</div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="menu-button" id="teleport-to-entity" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Teleport To Selected Entities</div>
|
||||
<div class = "menu-item-shortcut"></div>
|
||||
</div>
|
||||
</button>
|
||||
<div class="menu-separator"></div>
|
||||
<button class="menu-button" id="toggleLocalWorldMode" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Toggle Local/World Mode</div>
|
||||
<div class = "menu-item-shortcut">T</div>
|
||||
</div>
|
||||
</button>
|
||||
<div class="menu-separator"></div>
|
||||
<button class="menu-button" id="exportSelectedEntities" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Export Selected Entities</div>
|
||||
<div class = "menu-item-shortcut"></div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="menu-button" id="importEntitiesFromFile" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Import Entities (.json) From a File</div>
|
||||
<div class = "menu-item-shortcut"></div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="menu-button" id="importEntitiesFromUrl" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Import Entities (.json) From a URL</div>
|
||||
<div class = "menu-item-shortcut"></div>
|
||||
</div>
|
||||
</button>
|
||||
<div class="menu-separator"></div>
|
||||
<button class="menu-button" id="gridActivator" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Toggle Grid</div>
|
||||
<div class = "menu-item-shortcut">G</div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="menu-button" id="snapToGridActivator" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption" id="snapToGridActivatorCaption">Activate Snap to Grid</div>
|
||||
<div class = "menu-item-shortcut">H</div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="menu-button" id="alignGridToSelection" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Align Grid to Selected Entities</div>
|
||||
<div class = "menu-item-shortcut">J</div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="menu-button" id="alignGridToAvatar" >
|
||||
<div class = "menu-item">
|
||||
<div class = "menu-item-caption">Align Grid to Avatar</div>
|
||||
<div class = "menu-item-shortcut">K</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div id="menuBackgroundOverlay" ></div>
|
||||
</body>
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
const ASCENDING_SORT = 1;
|
||||
const DESCENDING_SORT = -1;
|
||||
const ASCENDING_STRING = '▴';
|
||||
const DESCENDING_STRING = '▾';
|
||||
const ASCENDING_STRING = "▴";
|
||||
const DESCENDING_STRING = "▾";
|
||||
const BYTES_PER_MEGABYTE = 1024 * 1024;
|
||||
const COLLAPSE_EXTRA_INFO = "E";
|
||||
const EXPAND_EXTRA_INFO = "D";
|
||||
|
@ -34,7 +34,7 @@ function displayIfNonZero(number) {
|
|||
}
|
||||
|
||||
function getFilename(url) {
|
||||
let urlParts = url.split('/');
|
||||
let urlParts = url.split("/");
|
||||
return urlParts[urlParts.length - 1];
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ let lastSelectedEntity;
|
|||
*/
|
||||
let entityListContextMenu = null;
|
||||
|
||||
let currentSortColumnID = 'type';
|
||||
let currentSortColumnID = "type";
|
||||
let currentSortOrder = ASCENDING_SORT;
|
||||
let elSortOrders = {};
|
||||
let typeFilters = [];
|
||||
|
@ -226,6 +226,7 @@ let elEntityTable,
|
|||
elToggleVisible,
|
||||
elActionsMenu,
|
||||
elSelectionMenu,
|
||||
elToolsMenu,
|
||||
elMenuBackgroundOverlay,
|
||||
elHmdMultiSelect,
|
||||
elHmdCopy,
|
||||
|
@ -249,6 +250,16 @@ let elEntityTable,
|
|||
elSelectFamily,
|
||||
elSelectTopFamily,
|
||||
elTeleportToEntity,
|
||||
elSetCameraFocusToSelection,
|
||||
elToggleLocalWorldMode,
|
||||
elExportSelectedEntities,
|
||||
elImportEntitiesFromFile,
|
||||
elImportEntitiesFromUrl,
|
||||
elGridActivator,
|
||||
elSnapToGridActivator,
|
||||
elSnapToGridActivatorCaption,
|
||||
elAlignGridToSelection,
|
||||
elAlignGridToAvatar,
|
||||
elFilterTypeMultiselectBox,
|
||||
elFilterTypeText,
|
||||
elFilterTypeOptions,
|
||||
|
@ -268,7 +279,7 @@ let elEntityTable,
|
|||
elRenameInput;
|
||||
|
||||
const ENABLE_PROFILING = false;
|
||||
let profileIndent = '';
|
||||
let profileIndent = "";
|
||||
const PROFILE_NOOP = function(_name, fn, args) {
|
||||
fn.apply(this, args);
|
||||
} ;
|
||||
|
@ -298,6 +309,7 @@ function loaded() {
|
|||
elHmdMultiSelect = document.getElementById("hmdmultiselect");
|
||||
elActionsMenu = document.getElementById("actions");
|
||||
elSelectionMenu = document.getElementById("selection");
|
||||
elToolsMenu = document.getElementById("tools");
|
||||
elMenuBackgroundOverlay = document.getElementById("menuBackgroundOverlay");
|
||||
elHmdCopy = document.getElementById("hmdcopy");
|
||||
elHmdCut = document.getElementById("hmdcut");
|
||||
|
@ -320,6 +332,16 @@ function loaded() {
|
|||
elSelectFamily = document.getElementById("selectfamily");
|
||||
elSelectTopFamily = document.getElementById("selecttopfamily");
|
||||
elTeleportToEntity = document.getElementById("teleport-to-entity");
|
||||
elSetCameraFocusToSelection = document.getElementById("setCameraFocusToSelection");
|
||||
elToggleLocalWorldMode = document.getElementById("toggleLocalWorldMode");
|
||||
elExportSelectedEntities = document.getElementById("exportSelectedEntities");
|
||||
elImportEntitiesFromFile = document.getElementById("importEntitiesFromFile");
|
||||
elImportEntitiesFromUrl = document.getElementById("importEntitiesFromUrl");
|
||||
elGridActivator = document.getElementById("gridActivator");
|
||||
elSnapToGridActivator = document.getElementById("snapToGridActivator");
|
||||
elSnapToGridActivatorCaption = document.getElementById("snapToGridActivatorCaption");
|
||||
elAlignGridToSelection = document.getElementById("alignGridToSelection");
|
||||
elAlignGridToAvatar = document.getElementById("alignGridToAvatar");
|
||||
elFilterTypeMultiselectBox = document.getElementById("filter-type-multiselect-box");
|
||||
elFilterTypeText = document.getElementById("filter-type-text");
|
||||
elFilterTypeOptions = document.getElementById("filter-type-options");
|
||||
|
@ -335,17 +357,17 @@ function loaded() {
|
|||
elNoEntitiesMessage = document.getElementById("no-entities");
|
||||
elColumnsMultiselectBox = document.getElementById("entity-table-columns-multiselect-box");
|
||||
elColumnsOptions = document.getElementById("entity-table-columns-options");
|
||||
elToggleSpaceMode = document.getElementById('toggle-space-mode');
|
||||
elToggleSpaceMode = document.getElementById("toggle-space-mode");
|
||||
|
||||
document.body.onclick = onBodyClick;
|
||||
elToggleLocked.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'toggleLocked' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "toggleLocked" }));
|
||||
};
|
||||
elToggleVisible.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'toggleVisible' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "toggleVisible" }));
|
||||
};
|
||||
elExport.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'export'}));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "export"}));
|
||||
};
|
||||
elHmdMultiSelect.onclick = function() {
|
||||
if (hmdMultiSelectMode) {
|
||||
|
@ -355,7 +377,7 @@ function loaded() {
|
|||
elHmdMultiSelect.className = "white vglyph";
|
||||
hmdMultiSelectMode = true;
|
||||
}
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'hmdMultiSelectMode', value: hmdMultiSelectMode }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "hmdMultiSelectMode", value: hmdMultiSelectMode }));
|
||||
};
|
||||
elActionsMenu.onclick = function() {
|
||||
document.getElementById("menuBackgroundOverlay").style.display = "block";
|
||||
|
@ -365,47 +387,51 @@ function loaded() {
|
|||
document.getElementById("menuBackgroundOverlay").style.display = "block";
|
||||
document.getElementById("selection-menu").style.display = "block";
|
||||
};
|
||||
elToolsMenu.onclick = function() {
|
||||
document.getElementById("menuBackgroundOverlay").style.display = "block";
|
||||
document.getElementById("tools-menu").style.display = "block";
|
||||
};
|
||||
elMenuBackgroundOverlay.onclick = function() {
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elHmdCopy.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'copy' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "copy" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elHmdCut.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'cut' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "cut" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elHmdPaste.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'paste' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "paste" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elHmdDuplicate.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'duplicate' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "duplicate" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elParent.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'parent' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "parent" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elUnparent.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'unparent' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "unparent" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elUndo.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'undo' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "undo" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elRedo.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'redo' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "redo" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elDelete.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "delete" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elMoveEntitySelectionToAvatar.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'moveEntitySelectionToAvatar' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "moveEntitySelectionToAvatar" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elSelectAll.onclick = function() {
|
||||
|
@ -467,39 +493,75 @@ function loaded() {
|
|||
closeAllEntityListMenu();
|
||||
};
|
||||
elSelectAllInBox.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'selectAllInBox' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "selectAllInBox" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elSelectAllTouchingBox.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'selectAllTouchingBox' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "selectAllTouchingBox" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elSelectParent.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'selectParent' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "selectParent" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elSelectTopParent.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'selectTopParent' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "selectTopParent" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elAddChildrenToSelection.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'addChildrenToSelection' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "addChildrenToSelection" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elSelectFamily.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'selectFamily' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "selectFamily" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elSelectTopFamily.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'selectTopFamily' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "selectTopFamily" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elTeleportToEntity.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "teleportToEntity" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elSetCameraFocusToSelection.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "setCameraFocusToSelection" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elToggleLocalWorldMode.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "toggleSpaceMode" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elExportSelectedEntities.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "export"}));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elImportEntitiesFromFile.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "importFromFile"}));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elImportEntitiesFromUrl.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "importFromUrl"}));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elGridActivator.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "toggleGridVisibility" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elSnapToGridActivator.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "toggleSnapToGrid" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elAlignGridToSelection.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "alignGridToSelection" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elAlignGridToAvatar.onclick = function () {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "alignGridToAvatar" }));
|
||||
closeAllEntityListMenu();
|
||||
};
|
||||
elToggleSpaceMode.onclick = function() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'toggleSpaceMode' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "toggleSpaceMode" }));
|
||||
};
|
||||
elRefresh.onclick = refreshEntities;
|
||||
elFilterTypeMultiselectBox.onclick = onToggleTypeDropdown;
|
||||
|
@ -517,11 +579,11 @@ function loaded() {
|
|||
let type = FILTER_TYPES[i];
|
||||
let typeFilterID = "filter-type-" + type;
|
||||
|
||||
let elDiv = document.createElement('div');
|
||||
let elDiv = document.createElement("div");
|
||||
elDiv.onclick = onToggleTypeFilter;
|
||||
elFilterTypeOptions.insertBefore(elDiv, elFilterTypeOptionsButtons);
|
||||
|
||||
let elInput = document.createElement('input');
|
||||
let elInput = document.createElement("input");
|
||||
elInput.setAttribute("type", "checkbox");
|
||||
elInput.setAttribute("id", typeFilterID);
|
||||
elInput.setAttribute("filterType", type);
|
||||
|
@ -529,12 +591,12 @@ function loaded() {
|
|||
elFilterTypeInputs[type] = elInput;
|
||||
elDiv.appendChild(elInput);
|
||||
|
||||
let elLabel = document.createElement('label');
|
||||
let elLabel = document.createElement("label");
|
||||
elLabel.setAttribute("for", typeFilterID);
|
||||
elLabel.innerText = type;
|
||||
elDiv.appendChild(elLabel);
|
||||
|
||||
let elSpan = document.createElement('span');
|
||||
let elSpan = document.createElement("span");
|
||||
elSpan.setAttribute("class", "typeIcon");
|
||||
elSpan.innerHTML = ENTITY_TYPE_ICON[type];
|
||||
|
||||
|
@ -567,11 +629,11 @@ function loaded() {
|
|||
elTh.innerText = columnData.columnHeader;
|
||||
}
|
||||
elTh.onmousedown = function(event) {
|
||||
if (event.target.nodeName === 'TH') {
|
||||
if (event.target.nodeName === "TH") {
|
||||
elTargetTh = event.target;
|
||||
targetColumnIndex = parseInt(elTargetTh.getAttribute("columnIndex"));
|
||||
lastColumnSwapPosition = event.clientX;
|
||||
} else if (event.target.nodeName === 'SPAN') {
|
||||
} else if (event.target.nodeName === "SPAN") {
|
||||
elTargetSpan = event.target;
|
||||
}
|
||||
initialThEvent = event;
|
||||
|
@ -594,18 +656,18 @@ function loaded() {
|
|||
if (columnData.alwaysShown !== true) {
|
||||
let columnDropdownID = "entity-table-column-" + columnID;
|
||||
|
||||
let elDiv = document.createElement('div');
|
||||
let elDiv = document.createElement("div");
|
||||
elDiv.onclick = onToggleColumn;
|
||||
elColumnsOptions.appendChild(elDiv);
|
||||
|
||||
let elInput = document.createElement('input');
|
||||
let elInput = document.createElement("input");
|
||||
elInput.setAttribute("type", "checkbox");
|
||||
elInput.setAttribute("id", columnDropdownID);
|
||||
elInput.setAttribute("columnID", columnID);
|
||||
elInput.checked = columnData.initiallyShown === true;
|
||||
elDiv.appendChild(elInput);
|
||||
|
||||
let elLabel = document.createElement('label');
|
||||
let elLabel = document.createElement("label");
|
||||
elLabel.setAttribute("for", columnDropdownID);
|
||||
elLabel.innerText = columnData.dropdownLabel;
|
||||
elDiv.appendChild(elLabel);
|
||||
|
@ -640,7 +702,7 @@ function loaded() {
|
|||
|
||||
let elCell = entity.elRow.childNodes[getColumnIndex("name")];
|
||||
elRenameInput = document.createElement("input");
|
||||
elRenameInput.setAttribute('class', 'rename-entity');
|
||||
elRenameInput.setAttribute("class", "rename-entity");
|
||||
elRenameInput.value = entity.name;
|
||||
let ignoreClicks = function(event) {
|
||||
event.stopPropagation();
|
||||
|
@ -705,22 +767,22 @@ function loaded() {
|
|||
entityListContextMenu.setOnSelectedCallback(function(optionName, selectedEntityID) {
|
||||
switch (optionName) {
|
||||
case "Cut":
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'cut' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "cut" }));
|
||||
break;
|
||||
case "Copy":
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'copy' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "copy" }));
|
||||
break;
|
||||
case "Paste":
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'paste' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "paste" }));
|
||||
break;
|
||||
case "Rename":
|
||||
startRenamingEntity(selectedEntityID);
|
||||
break;
|
||||
case "Duplicate":
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'duplicate' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "duplicate" }));
|
||||
break;
|
||||
case "Delete":
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "delete" }));
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
@ -744,11 +806,11 @@ function loaded() {
|
|||
}));
|
||||
}
|
||||
|
||||
let enabledContextMenuItems = ['Copy', 'Paste', 'Duplicate'];
|
||||
let enabledContextMenuItems = ["Copy", "Paste", "Duplicate"];
|
||||
if (entitiesByID[entityID] && !entitiesByID[entityID].locked) {
|
||||
enabledContextMenuItems.push('Cut');
|
||||
enabledContextMenuItems.push('Rename');
|
||||
enabledContextMenuItems.push('Delete');
|
||||
enabledContextMenuItems.push("Cut");
|
||||
enabledContextMenuItems.push("Rename");
|
||||
enabledContextMenuItems.push("Delete");
|
||||
}
|
||||
|
||||
entityListContextMenu.open(clickEvent, entityID, enabledContextMenuItems);
|
||||
|
@ -947,7 +1009,7 @@ function loaded() {
|
|||
if (id === deletedIDs[i]) {
|
||||
let elRow = entities[j].elRow;
|
||||
if (elRow) {
|
||||
elRow.className = '';
|
||||
elRow.className = "";
|
||||
elRow.dataset.entityID = EMPTY_ENTITY_ID;
|
||||
}
|
||||
entities.splice(j, 1);
|
||||
|
@ -1030,7 +1092,7 @@ function loaded() {
|
|||
}
|
||||
|
||||
function refreshEntities() {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'refresh' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "refresh" }));
|
||||
}
|
||||
|
||||
function refreshFooter() {
|
||||
|
@ -1057,7 +1119,7 @@ function loaded() {
|
|||
if (entity !== undefined) {
|
||||
entity.selected = false;
|
||||
if (entity.elRow) {
|
||||
entity.elRow.className = '';
|
||||
entity.elRow.className = "";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1071,9 +1133,9 @@ function loaded() {
|
|||
entity.selected = true;
|
||||
if (entity.elRow) {
|
||||
if (id === lastSelectedEntity) {
|
||||
entity.elRow.className = 'last-selected';
|
||||
entity.elRow.className = "last-selected";
|
||||
} else {
|
||||
entity.elRow.className = 'selected';
|
||||
entity.elRow.className = "selected";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1144,12 +1206,12 @@ function loaded() {
|
|||
// if this entity was previously selected flag it's row as selected
|
||||
if (itemData.selected) {
|
||||
if (itemData.id === lastSelectedEntity) {
|
||||
elRow.className = 'last-selected';
|
||||
elRow.className = "last-selected";
|
||||
} else {
|
||||
elRow.className = 'selected';
|
||||
elRow.className = "selected";
|
||||
}
|
||||
} else {
|
||||
elRow.className = '';
|
||||
elRow.className = "";
|
||||
}
|
||||
|
||||
// if this row previously had an associated entity ID that wasn't the new entity ID then clear
|
||||
|
@ -1202,9 +1264,9 @@ function loaded() {
|
|||
}
|
||||
|
||||
function onRadiusChange() {
|
||||
elFilterRadius.value = elFilterRadius.value.replace(/[^0-9]/g, '');
|
||||
elFilterRadius.value = elFilterRadius.value.replace(/[^0-9]/g, "");
|
||||
elFilterRadius.value = Math.max(elFilterRadius.value, 0);
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'radius', radius: elFilterRadius.value }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "radius", radius: elFilterRadius.value }));
|
||||
refreshEntities();
|
||||
}
|
||||
|
||||
|
@ -1425,7 +1487,7 @@ function loaded() {
|
|||
}
|
||||
|
||||
if (isColumnsSettingLoaded) {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'saveColumnsConfigSetting', columnsData: columns }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "saveColumnsConfigSetting", columnsData: columns }));
|
||||
}
|
||||
|
||||
entityList.refresh();
|
||||
|
@ -1628,7 +1690,7 @@ function loaded() {
|
|||
}
|
||||
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: 'keyUpEvent',
|
||||
type: "keyUpEvent",
|
||||
keyUpEvent: {
|
||||
code,
|
||||
key,
|
||||
|
@ -1673,6 +1735,12 @@ function loaded() {
|
|||
removeEntities(data.ids);
|
||||
} else if (data.type === "setSpaceMode") {
|
||||
setSpaceMode(data.spaceMode);
|
||||
} else if (data.type === "setSnapToGrid") {
|
||||
if (data.snap) {
|
||||
elSnapToGridActivatorCaption.innerHTML = "✓ Deactivate Snap to Grid";
|
||||
} else {
|
||||
elSnapToGridActivatorCaption.innerHTML = "Activate Snap to Grid";
|
||||
}
|
||||
} else if (data.type === "confirmHMDstate") {
|
||||
if (data.isHmd) {
|
||||
document.getElementById("hmdmultiselect").style.display = "inline";
|
||||
|
@ -1722,7 +1790,7 @@ function loaded() {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'saveColumnsConfigSetting', columnsData: "" }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "saveColumnsConfigSetting", columnsData: "" }));
|
||||
}
|
||||
}
|
||||
isColumnsSettingLoaded = true;
|
||||
|
@ -1735,7 +1803,7 @@ function loaded() {
|
|||
|
||||
window.addEventListener("resize", updateColumnWidths);
|
||||
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'loadConfigSetting' }));
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "loadConfigSetting" }));
|
||||
});
|
||||
|
||||
augmentSpinButtons();
|
||||
|
@ -1758,6 +1826,7 @@ function loaded() {
|
|||
document.getElementById("menuBackgroundOverlay").style.display = "none";
|
||||
document.getElementById("selection-menu").style.display = "none";
|
||||
document.getElementById("actions-menu").style.display = "none";
|
||||
document.getElementById("tools-menu").style.display = "none";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -143,6 +143,7 @@ EntityShape.prototype = {
|
|||
var PROJECTED_MATERIALS = false;
|
||||
this.materialEntity = Entities.addEntity({
|
||||
type: "Material",
|
||||
name: "MATERIAL_" + this.entityShapeVisualizerSessionName,
|
||||
localPosition: Vec3.ZERO,
|
||||
localRotation: Quat.IDENTITY,
|
||||
localDimensions: properties.localDimensions,
|
||||
|
|
|
@ -210,8 +210,8 @@ TabBar {
|
|||
text: "Import Entities (.json) from a File"
|
||||
color: hifi.buttons.black
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
anchors.right: parent.horizontalCenter
|
||||
anchors.rightMargin: 10
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 55
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 55
|
||||
anchors.top: assetServerButton.bottom
|
||||
|
@ -231,9 +231,9 @@ TabBar {
|
|||
colorScheme: hifi.colorSchemes.dark
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 55
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.leftMargin: 10
|
||||
anchors.top: assetServerButton.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 55
|
||||
anchors.top: importButton.bottom
|
||||
anchors.topMargin: 20
|
||||
onClicked: {
|
||||
editRoot.sendToScript({
|
||||
|
|
|
@ -404,7 +404,7 @@ input[type=button], button.hifi-edit-button {
|
|||
text-transform: uppercase;
|
||||
vertical-align: top;
|
||||
height: 28px;
|
||||
min-width: 120px;
|
||||
min-width: 70px;
|
||||
padding: 0 18px;
|
||||
margin-right: 6px;
|
||||
border-radius: 5px;
|
||||
|
|
|
@ -29,7 +29,7 @@ EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) {
|
|||
overlayProperties[key] = customProperties[key];
|
||||
}
|
||||
}
|
||||
Overlays.editOverlay(entityOverlays[entityID], overlayProperties);
|
||||
Entities.editEntity(entityOverlays[entityID], overlayProperties);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -63,7 +63,7 @@ EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) {
|
|||
if (visible !== isVisible) {
|
||||
visible = isVisible;
|
||||
for (var id in entityOverlays) {
|
||||
Overlays.editOverlay(entityOverlays[id], {
|
||||
Entities.editEntity(entityOverlays[id], {
|
||||
visible: visible,
|
||||
ignorePickIntersection: !visible
|
||||
});
|
||||
|
@ -75,7 +75,11 @@ EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) {
|
|||
function getOverlay() {
|
||||
var overlay;
|
||||
if (unusedOverlays.length === 0) {
|
||||
overlay = Overlays.addOverlay("image3d", {});
|
||||
overlay = Entities.addEntity({
|
||||
type: "Image",
|
||||
billboardMode: "full",
|
||||
emissive: true
|
||||
}, "local");
|
||||
allOverlays.push(overlay);
|
||||
} else {
|
||||
overlay = unusedOverlays.pop();
|
||||
|
@ -85,7 +89,7 @@ EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) {
|
|||
|
||||
function releaseOverlay(overlay) {
|
||||
unusedOverlays.push(overlay);
|
||||
Overlays.editOverlay(overlay, {
|
||||
Entities.editEntity(overlay, {
|
||||
visible: false,
|
||||
ignorePickIntersection: true
|
||||
});
|
||||
|
@ -103,9 +107,8 @@ EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) {
|
|||
visible: visible,
|
||||
ignorePickIntersection: !visible,
|
||||
alpha: 0.9,
|
||||
scale: 0.5,
|
||||
drawInFront: true,
|
||||
isFacingAvatar: true,
|
||||
dimensions: { x: 0.5, y: 0.5, z: 0.01 },
|
||||
renderLayer: "front",
|
||||
color: {
|
||||
red: 255,
|
||||
green: 255,
|
||||
|
@ -118,7 +121,7 @@ EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) {
|
|||
overlayProperties[key] = customProperties[key];
|
||||
}
|
||||
}
|
||||
Overlays.editOverlay(overlay, overlayProperties);
|
||||
Entities.editEntity(overlay, overlayProperties);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,7 +152,7 @@ EntityIconOverlayManager = function(entityTypes, getOverlayPropertiesFunc) {
|
|||
|
||||
Script.scriptEnding.connect(function() {
|
||||
for (var i = 0; i < allOverlays.length; i++) {
|
||||
Overlays.deleteOverlay(allOverlays[i]);
|
||||
Entities.deleteEntity(allOverlays[i]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
// gridTool.js
|
||||
//
|
||||
// Created by Ryan Huffman on 6 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
|
||||
//
|
||||
/* global keyUpEventFromUIWindow */
|
||||
|
||||
var GRID_CONTROLS_HTML_URL = Script.resolvePath('../html/gridControls.html');
|
||||
|
||||
Grid = function() {
|
||||
var that = {};
|
||||
var gridColor = { red: 0, green: 0, blue: 0 };
|
||||
var gridColor = { red: 255, green: 255, blue: 255 };
|
||||
var gridAlpha = 0.6;
|
||||
var origin = { x: 0, y: +MyAvatar.getJointPosition('LeftToeBase').y.toFixed(1) + 0.1, z: 0 };
|
||||
var scale = 500;
|
||||
|
@ -16,18 +25,19 @@ Grid = function() {
|
|||
|
||||
var snapToGrid = false;
|
||||
|
||||
var gridOverlay = Overlays.addOverlay("grid", {
|
||||
var gridEntityTool = Entities.addEntity({
|
||||
type: "Grid",
|
||||
rotation: Quat.fromPitchYawRollDegrees(90, 0, 0),
|
||||
dimensions: { x: scale, y: scale, z: scale },
|
||||
position: origin,
|
||||
visible: false,
|
||||
drawInFront: false,
|
||||
renderLayer: "world",
|
||||
color: gridColor,
|
||||
alpha: gridAlpha,
|
||||
minorGridEvery: minorGridEvery,
|
||||
majorGridEvery: majorGridEvery,
|
||||
ignorePickIntersection: true
|
||||
});
|
||||
}, "local");
|
||||
|
||||
that.visible = false;
|
||||
that.enabled = false;
|
||||
|
@ -163,6 +173,14 @@ Grid = function() {
|
|||
newPosition = Vec3.subtract(newPosition, { x: 0, y: SelectionManager.worldDimensions.y * 0.5, z: 0 });
|
||||
that.setPosition(newPosition);
|
||||
};
|
||||
|
||||
that.moveToAvatar = function() {
|
||||
var position = MyAvatar.getJointPosition("LeftFoot");
|
||||
if (position.x === 0.0 && position.y === 0.0 && position.z === 0.0) {
|
||||
position = MyAvatar.position;
|
||||
}
|
||||
that.setPosition(position);
|
||||
};
|
||||
|
||||
that.emitUpdate = function() {
|
||||
if (that.onUpdate) {
|
||||
|
@ -214,7 +232,7 @@ Grid = function() {
|
|||
};
|
||||
|
||||
function updateGrid(noUpdate) {
|
||||
Overlays.editOverlay(gridOverlay, {
|
||||
Entities.editEntity(gridEntityTool, {
|
||||
position: { x: 0, y: origin.y, z: 0 },
|
||||
visible: that.visible && that.enabled,
|
||||
minorGridEvery: minorGridEvery,
|
||||
|
@ -222,6 +240,7 @@ Grid = function() {
|
|||
color: gridColor,
|
||||
alpha: gridAlpha
|
||||
});
|
||||
|
||||
|
||||
if (!noUpdate) {
|
||||
that.emitUpdate();
|
||||
|
@ -229,7 +248,7 @@ Grid = function() {
|
|||
}
|
||||
|
||||
function cleanup() {
|
||||
Overlays.deleteOverlay(gridOverlay);
|
||||
Entities.deleteEntity(gridEntityTool);
|
||||
}
|
||||
|
||||
that.addListener = function(callback) {
|
||||
|
@ -283,11 +302,7 @@ GridTool = function(opts) {
|
|||
} else if (data.type === "action") {
|
||||
var action = data.action;
|
||||
if (action === "moveToAvatar") {
|
||||
var position = MyAvatar.getJointPosition("LeftFoot");
|
||||
if (position.x === 0 && position.y === 0 && position.z === 0) {
|
||||
position = MyAvatar.position;
|
||||
}
|
||||
horizontalGrid.setPosition(position);
|
||||
horizontalGrid.moveToAvatar();
|
||||
} else if (action === "moveToSelection") {
|
||||
horizontalGrid.moveToSelection();
|
||||
}
|
||||
|
|