3
0
Fork 0
mirror of https://github.com/lubosz/overte.git synced 2025-04-26 07:35:35 +02:00

Merge branch 'master' into M16440

# Conflicts:
#	scripts/system/controllers/controllerModules/hudOverlayPointer.js
#	scripts/system/controllers/controllerModules/inVREditMode.js
This commit is contained in:
David Rowe 2018-10-19 09:06:33 +13:00
commit 490c085eb8
411 changed files with 6657 additions and 5893 deletions
CMakeLists.txt
android
assignment-client/src/avatars
cmake
docs
interface
libraries

View file

@ -68,6 +68,7 @@ if (USE_GLES AND (NOT ANDROID))
set(DISABLE_QML_OPTION ON)
endif()
option(BUILD_CLIENT "Build client components" ${BUILD_CLIENT_OPTION})
option(BUILD_SERVER "Build server components" ${BUILD_SERVER_OPTION})
option(BUILD_TESTS "Build tests" ${BUILD_TESTS_OPTION})
@ -162,7 +163,6 @@ if (BUILD_SERVER)
set_target_properties(domain-server PROPERTIES FOLDER "Apps")
add_subdirectory(ice-server)
set_target_properties(ice-server PROPERTIES FOLDER "Apps")
add_subdirectory(server-console)
endif()
if (BUILD_CLIENT)
@ -174,6 +174,7 @@ endif()
if (BUILD_CLIENT OR BUILD_SERVER)
add_subdirectory(plugins)
add_subdirectory(server-console)
endif()
# BUILD_TOOLS option will be handled inside the tools's CMakeLists.txt because 'scribe' tool is required for build anyway

View file

@ -7,6 +7,8 @@ target_bullet()
set(INTERFACE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../interface")
add_subdirectory("${INTERFACE_DIR}" "libraries/interface")
include_directories("${INTERFACE_DIR}/src")
set(HIFI_CODEC_PLUGIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../plugins/hifiCodec")
add_subdirectory("${HIFI_CODEC_PLUGIN_DIR}" "libraries/hifiCodecPlugin")
target_link_libraries(native-lib android log m interface)

View file

@ -80,8 +80,10 @@ android {
if (Os.isFamily(Os.FAMILY_UNIX)) {
def uploadDumpSymsTask = rootProject.getTasksByName("uploadBreakpadDumpSyms${variant.name.capitalize()}", false).first()
def runDumpSymsTask = rootProject.getTasksByName("runBreakpadDumpSyms${variant.name.capitalize()}", false).first()
def renameHifiACTask = rootProject.getTasksByName("renameHifiACTask${variant.name.capitalize()}", false).first()
runDumpSymsTask.dependsOn(task)
variant.assemble.dependsOn(uploadDumpSymsTask)
variant.mergeResources.dependsOn(renameHifiACTask)
}
}

View file

@ -143,11 +143,9 @@ def packages = [
includeLibs: ['libtbb.so', 'libtbbmalloc.so'],
],
hifiAC: [
file: 'libplugins_libhifiCodec.zip',
versionId: 'i31pW.qNbvFOXRxbyiJUxg3sphaFNmZU',
checksum: '9412a8e12c88a4096c1fc843bb9fe52d',
sharedLibFolder: '',
includeLibs: ['libplugins_libhifiCodec.so']
baseUrl: 'http://s3.amazonaws.com/hifi-public/dependencies/',
file: 'codecSDK-android_armv8-2.0.zip',
checksum: '1cbef929675818fc64c4101b72f84a6a'
],
etc2comp: [
file: 'etc2comp-patched-armv8-libcpp.tgz',
@ -367,7 +365,8 @@ task downloadDependencies {
doLast {
packages.each { entry ->
def filename = entry.value['file'];
def url = baseUrl + filename;
def dependencyBaseUrl = entry.value['baseUrl']
def url = (dependencyBaseUrl?.trim() ? dependencyBaseUrl : baseUrl) + filename;
if (entry.value.containsKey('versionId')) {
url = url + '?versionId=' + entry.value['versionId']
}
@ -668,6 +667,21 @@ task uploadBreakpadDumpSymsRelease(type:io.github.httpbuilderng.http.HttpTask, d
}
}
task renameHifiACTaskDebug() {
doLast {
def sourceFile = new File("${appDir}/build/intermediates/cmake/debug/obj/arm64-v8a/","libhifiCodec.so")
def destinationFile = new File("${appDir}/src/main/jniLibs/arm64-v8a", "libplugins_libhifiCodec.so")
copy { from sourceFile; into destinationFile.parent; rename(sourceFile.name, destinationFile.name) }
}
}
task renameHifiACTaskRelease(type: Copy) {
doLast {
def sourceFile = new File("${appDir}/build/intermediates/cmake/release/obj/arm64-v8a/","libhifiCodec.so")
def destinationFile = new File("${appDir}/src/main/jniLibs/arm64-v8a", "libplugins_libhifiCodec.so")
copy { from sourceFile; into destinationFile.parent; rename(sourceFile.name, destinationFile.name) }
}
}
// FIXME this code is prototyping the desired functionality for doing build time binary dependency resolution.
// See the comment on the qtBundle task above
/*

View file

@ -112,6 +112,11 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message,
AvatarTraits::TraitWireSize traitSize;
message.readPrimitive(&traitSize);
if (traitSize < -1 || traitSize > message.getBytesLeftToRead()) {
qWarning() << "Refusing to process simple trait of size" << traitSize << "from" << message.getSenderSockAddr();
break;
}
if (packetTraitVersion > _lastReceivedTraitVersions[traitType]) {
_avatar->processTrait(traitType, message.read(traitSize));
_lastReceivedTraitVersions[traitType] = packetTraitVersion;
@ -128,26 +133,41 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message,
} else {
AvatarTraits::TraitInstanceID instanceID = QUuid::fromRfc4122(message.readWithoutCopy(NUM_BYTES_RFC4122_UUID));
if (message.getBytesLeftToRead() == 0) {
qWarning () << "Received an instanced trait with no size from" << message.getSenderSockAddr();
break;
}
AvatarTraits::TraitWireSize traitSize;
message.readPrimitive(&traitSize);
auto& instanceVersionRef = _lastReceivedTraitVersions.getInstanceValueRef(traitType, instanceID);
if (traitSize < -1 || traitSize > message.getBytesLeftToRead()) {
qWarning() << "Refusing to process instanced trait of size" << traitSize << "from" << message.getSenderSockAddr();
break;
}
if (packetTraitVersion > instanceVersionRef) {
if (traitSize == AvatarTraits::DELETED_TRAIT_SIZE) {
_avatar->processDeletedTraitInstance(traitType, instanceID);
if (traitType == AvatarTraits::AvatarEntity) {
auto& instanceVersionRef = _lastReceivedTraitVersions.getInstanceValueRef(traitType, instanceID);
// to track a deleted instance but keep version information
// the avatar mixer uses the negative value of the sent version
instanceVersionRef = -packetTraitVersion;
if (packetTraitVersion > instanceVersionRef) {
if (traitSize == AvatarTraits::DELETED_TRAIT_SIZE) {
_avatar->processDeletedTraitInstance(traitType, instanceID);
// to track a deleted instance but keep version information
// the avatar mixer uses the negative value of the sent version
instanceVersionRef = -packetTraitVersion;
} else {
_avatar->processTraitInstance(traitType, instanceID, message.read(traitSize));
instanceVersionRef = packetTraitVersion;
}
anyTraitsChanged = true;
} else {
_avatar->processTraitInstance(traitType, instanceID, message.read(traitSize));
instanceVersionRef = packetTraitVersion;
message.seek(message.getPosition() + traitSize);
}
anyTraitsChanged = true;
} else {
message.seek(message.getPosition() + traitSize);
qWarning() << "Refusing to process traits packet with instanced trait of unprocessable type from" << message.getSenderSockAddr();
break;
}
}
}

View file

@ -152,6 +152,7 @@ qint64 AvatarMixerSlave::addChangedTraitsToBulkPacket(AvatarMixerClientData* lis
});
if (!isDeleted && (sentInstanceIt == sentIDValuePairs.end() || receivedVersion > sentInstanceIt->value)) {
// this instance version exists and has never been sent or is newer so we need to send it
bytesWritten += sendingAvatar->packTraitInstance(traitType, instanceID, traitsPacketList, receivedVersion);
@ -161,6 +162,7 @@ qint64 AvatarMixerSlave::addChangedTraitsToBulkPacket(AvatarMixerClientData* lis
sentIDValuePairs.emplace_back(instanceID, receivedVersion);
}
} else if (isDeleted && sentInstanceIt != sentIDValuePairs.end() && absoluteReceivedVersion > sentInstanceIt->value) {
// this instance version was deleted and we haven't sent the delete to this client yet
bytesWritten += AvatarTraits::packInstancedTraitDelete(traitType, instanceID, traitsPacketList, absoluteReceivedVersion);
@ -180,6 +182,7 @@ qint64 AvatarMixerSlave::addChangedTraitsToBulkPacket(AvatarMixerClientData* lis
listeningNodeData->setLastOtherAvatarTraitsSendPoint(otherNodeLocalID, timeOfLastTraitsChange);
}
return bytesWritten;
}

View file

@ -88,7 +88,7 @@ if (APPLE)
set(OSX_SDK "${OSX_VERSION}" CACHE String "OS X SDK version to look for inside Xcode bundle or at OSX_SDK_PATH")
# set our OS X deployment target
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8)
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9)
# find the SDK path for the desired SDK
find_path(

View file

@ -1,14 +1,12 @@
set(EXTERNAL_NAME quazip)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
cmake_policy(SET CMP0046 OLD)
include(ExternalProject)
set(QUAZIP_CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=<INSTALL_DIR>/lib -DZLIB_ROOT=${ZLIB_ROOT} -DCMAKE_POSITION_INDEPENDENT_CODE=ON)
if (APPLE)
else ()
set(QUAZIP_CMAKE_ARGS ${QUAZIP_CMAKE_ARGS} -DCMAKE_CXX_STANDARD=11)
if (NOT APPLE)
set(QUAZIP_CMAKE_ARGS ${QUAZIP_CMAKE_ARGS} -DCMAKE_CXX_STANDARD=11)
endif ()
ExternalProject_Add(
@ -22,10 +20,12 @@ ExternalProject_Add(
LOG_BUILD 1
)
add_dependencies(quazip zlib)
if (WIN32)
add_dependencies(quazip zlib)
endif ()
# Hide this external target (for ide users)
set_target_properties(${EXTERNAL_NAME} PROPERTIES
set_target_properties(${EXTERNAL_NAME} PROPERTIES
FOLDER "hidden/externals"
INSTALL_NAME_DIR ${INSTALL_DIR}/lib
BUILD_WITH_INSTALL_RPATH True)
@ -54,4 +54,4 @@ select_library_configurations(${EXTERNAL_NAME_UPPER})
# Force selected libraries into the cache
set(${EXTERNAL_NAME_UPPER}_LIBRARY ${${EXTERNAL_NAME_UPPER}_LIBRARY} CACHE FILEPATH "Location of QuaZip libraries")
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Location of QuaZip libraries")
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Location of QuaZip libraries")

View file

@ -3,11 +3,11 @@ if (WIN32)
endif (WIN32)
if (POLICY CMP0043)
cmake_policy(SET CMP0043 OLD)
cmake_policy(SET CMP0043 NEW)
endif ()
if (POLICY CMP0042)
cmake_policy(SET CMP0042 OLD)
cmake_policy(SET CMP0042 NEW)
endif ()
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
@ -34,7 +34,7 @@ file(GLOB HIFI_CUSTOM_MACROS "cmake/macros/*.cmake")
foreach(CUSTOM_MACRO ${HIFI_CUSTOM_MACROS})
include(${CUSTOM_MACRO})
endforeach()
unset(HIFI_CUSTOM_MACROS)
unset(HIFI_CUSTOM_MACROS)
if (ANDROID)
set(BUILD_SHARED_LIBS ON)

View file

@ -66,8 +66,8 @@ macro(install_beside_console)
install(CODE "
set(MACOSX_BUNDLE_EXECUTABLE_NAME domain-server)
set(MACOSX_BUNDLE_GUI_IDENTIFIER com.highfidelity.server-components)
set(MACOSX_BUNDLE_BUNDLE_NAME Sandbox\\ Components)
configure_file(${HF_CMAKE_DIR}/templates/MacOSXBundleSandboxComponentsInfo.plist.in ${ESCAPED_BUNDLE_NAME}/Contents/Info.plist)
set(MACOSX_BUNDLE_BUNDLE_NAME Console\\ Components)
configure_file(${HF_CMAKE_DIR}/templates/MacOSXBundleConsoleComponentsInfo.plist.in ${ESCAPED_BUNDLE_NAME}/Contents/Info.plist)
execute_process(COMMAND ${MACDEPLOYQT_COMMAND} ${ESCAPED_BUNDLE_NAME} -verbose=2 -executable=${ESCAPED_EXECUTABLE_NAME})"
COMPONENT ${SERVER_COMPONENT}
)

View file

@ -18,7 +18,7 @@ macro(SET_PACKAGING_PARAMETERS)
set(BUILD_GLOBAL_SERVICES "DEVELOPMENT")
set(USE_STABLE_GLOBAL_SERVICES 0)
set(BUILD_NUMBER 0)
set(APP_USER_MODEL_ID "com.highfidelity.sandbox-dev")
set(APP_USER_MODEL_ID "com.highfidelity.console-dev")
set_from_env(RELEASE_TYPE RELEASE_TYPE "DEV")
set_from_env(RELEASE_NUMBER RELEASE_NUMBER "")
@ -37,6 +37,7 @@ macro(SET_PACKAGING_PARAMETERS)
set(BUILD_VERSION ${RELEASE_NUMBER})
set(BUILD_ORGANIZATION "High Fidelity")
set(HIGH_FIDELITY_PROTOCOL "hifi")
set(HIGH_FIDELITY_APP_PROTOCOL "hifiapp")
set(INTERFACE_BUNDLE_NAME "Interface")
set(INTERFACE_ICON_PREFIX "interface")
@ -142,7 +143,12 @@ macro(SET_PACKAGING_PARAMETERS)
set(CONSOLE_INSTALL_DIR ${DMG_SUBFOLDER_NAME})
set(INTERFACE_INSTALL_DIR ${DMG_SUBFOLDER_NAME})
set(CONSOLE_EXEC_NAME "Sandbox.app")
if (CLIENT_ONLY)
set(CONSOLE_EXEC_NAME "Console.app")
else ()
set(CONSOLE_EXEC_NAME "Sandbox.app")
endif()
set(CONSOLE_INSTALL_APP_PATH "${CONSOLE_INSTALL_DIR}/${CONSOLE_EXEC_NAME}")
set(CONSOLE_APP_CONTENTS "${CONSOLE_INSTALL_APP_PATH}/Contents")
@ -176,16 +182,19 @@ macro(SET_PACKAGING_PARAMETERS)
# shortcut names
if (PRODUCTION_BUILD)
set(INTERFACE_SHORTCUT_NAME "High Fidelity Interface")
set(CONSOLE_SHORTCUT_NAME "Sandbox")
set(APP_USER_MODEL_ID "com.highfidelity.sandbox")
set(CONSOLE_SHORTCUT_NAME "Console")
set(SANDBOX_SHORTCUT_NAME "Sandbox")
set(APP_USER_MODEL_ID "com.highfidelity.console")
else ()
set(INTERFACE_SHORTCUT_NAME "High Fidelity Interface - ${BUILD_VERSION_NO_SHA}")
set(CONSOLE_SHORTCUT_NAME "Sandbox - ${BUILD_VERSION_NO_SHA}")
set(CONSOLE_SHORTCUT_NAME "Console - ${BUILD_VERSION_NO_SHA}")
set(SANDBOX_SHORTCUT_NAME "Sandbox - ${BUILD_VERSION_NO_SHA}")
endif ()
set(INTERFACE_HF_SHORTCUT_NAME "${INTERFACE_SHORTCUT_NAME}")
set(CONSOLE_HF_SHORTCUT_NAME "High Fidelity ${CONSOLE_SHORTCUT_NAME}")
set(SANDBOX_HF_SHORTCUT_NAME "High Fidelity ${SANDBOX_SHORTCUT_NAME}")
set(PRE_SANDBOX_INTERFACE_SHORTCUT_NAME "High Fidelity")
set(PRE_SANDBOX_CONSOLE_SHORTCUT_NAME "Server Console")

View file

@ -0,0 +1,22 @@
#
# Copyright 2018 High Fidelity, Inc.
# Created by Gabriel Calero and Cristian Duarte on 2018/10/05
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(TARGET_HIFIAUDIOCODEC)
if (ANDROID)
set(HIFIAC_INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/hifiAC/codecSDK)
set(HIFIAC_LIB_DIR "${HIFIAC_INSTALL_DIR}/Release")
set(HIFIAC_INCLUDE_DIRS "${HIFIAC_INSTALL_DIR}/include" CACHE TYPE INTERNAL)
list(APPEND HIFIAC_LIBS "${HIFIAC_LIB_DIR}/libaudio.a")
set(HIFIAC_LIBRARIES ${HIFIAC_LIBS} CACHE TYPE INTERNAL)
else()
add_dependency_external_projects(hifiAudioCodec)
target_include_directories(${TARGET_NAME} PRIVATE ${HIFIAUDIOCODEC_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} ${HIFIAUDIOCODEC_LIBRARIES})
endif()
target_include_directories(${TARGET_NAME} PRIVATE ${HIFIAC_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} ${HIFIAC_LIBRARIES})
endmacro()

View file

@ -1,10 +1,10 @@
#
#
# Copyright 2015 High Fidelity, Inc.
# Created by Bradley Austin Davis on 2015/10/10
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
#
macro(TARGET_ZLIB)
if (WIN32)

View file

@ -42,6 +42,14 @@
<string>hifi</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME} APP URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>hifiapp</string>
</array>
</dict>
</array>
<key>NSHighResolutionCapable</key>
<true/>

View file

@ -13,10 +13,12 @@ set(INTERFACE_DISPLAY_NAME "Interface")
set(INTERFACE_SHORTCUT_NAME "@INTERFACE_SHORTCUT_NAME@")
set(INTERFACE_HF_SHORTCUT_NAME "@INTERFACE_HF_SHORTCUT_NAME@")
set(INTERFACE_WIN_EXEC_NAME "@INTERFACE_EXEC_PREFIX@.exe")
set(CONSOLE_DISPLAY_NAME "Sandbox")
set(CONSOLE_DISPLAY_NAME "Console")
set(CONSOLE_INSTALL_SUBDIR "@CONSOLE_INSTALL_DIR@")
set(CONSOLE_SHORTCUT_NAME "@CONSOLE_SHORTCUT_NAME@")
set(CONSOLE_HF_SHORTCUT_NAME "@CONSOLE_HF_SHORTCUT_NAME@")
set(SANDBOX_SHORTCUT_NAME "@SANDBOX_SHORTCUT_NAME@")
set(SANDBOX_HF_SHORTCUT_NAME "@SANDBOX_HF_SHORTCUT_NAME@")
set(CONSOLE_WIN_EXEC_NAME "@CONSOLE_EXEC_NAME@")
set(PRE_SANDBOX_INTERFACE_SHORTCUT_NAME "@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@")
set(PRE_SANDBOX_CONSOLE_SHORTCUT_NAME "@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@")
@ -25,6 +27,7 @@ set(DS_EXEC_NAME "@DS_EXEC_NAME@")
set(AC_DISPLAY_NAME "Assignment Client")
set(AC_EXEC_NAME "@AC_EXEC_NAME@")
set(HIGH_FIDELITY_PROTOCOL "@HIGH_FIDELITY_PROTOCOL@")
set(HIGH_FIDELITY_APP_PROTOCOL "@HIGH_FIDELITY_APP_PROTOCOL@")
set(PRODUCTION_BUILD "@PRODUCTION_BUILD@")
set(PR_BUILD "@PR_BUILD@")
set(BUILD_ORGANIZATION "@BUILD_ORGANIZATION@")

View file

@ -405,6 +405,14 @@ Var GAClientID
Section "-Previous Install Cleanup"
; Remove the resources folder so we don't end up including removed QML files
RMDir /r "$INSTDIR\resources"
; delete old assignment-client and domain-server so they're no longer present
; in client only installs.
Delete "$INSTDIR\@DS_EXEC_NAME@"
Delete "$INSTDIR\@AC_EXEC_NAME@"
; delete interface so it's not there for server-only installs
Delete "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"
SectionEnd
@CPACK_NSIS_INSTALLATION_TYPES@
@ -532,9 +540,9 @@ SectionEnd
Var PostInstallDialog
Var DesktopClientCheckbox
Var DesktopServerCheckbox
Var ServerStartupCheckbox
Var LaunchServerNowCheckbox
Var DesktopConsoleCheckbox
Var ConsoleStartupCheckbox
Var LaunchConsoleNowCheckbox
Var LaunchClientNowCheckbox
Var CleanInstallCheckbox
Var CurrentOffset
@ -747,32 +755,20 @@ Function PostInstallOptionsPage
${EndIf}
${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 $DesktopServerCheckbox
IntOp $CurrentOffset $CurrentOffset + 15
; set the checkbox state depending on what is present in the registry
!insertmacro SetInstallOption $DesktopServerCheckbox @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ ${BST_UNCHECKED}
${EndIf}
${If} @SERVER_COMPONENT_CONDITIONAL@
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ after install"
Pop $LaunchServerNowCheckbox
; set the checkbox state depending on what is present in the registry
!insertmacro SetInstallOption $LaunchServerNowCheckbox @SERVER_LAUNCH_NOW_REG_KEY@ ${BST_CHECKED}
${StrContains} $substringResult "/forceNoLaunchServer" $CMDLINE
${IfNot} $substringResult == ""
${NSD_SetState} $LaunchServerNowCheckbox ${BST_UNCHECKED}
${EndIf}
IntOp $CurrentOffset $CurrentOffset + 15
${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"
Pop $LaunchClientNowCheckbox
IntOp $CurrentOffset $CurrentOffset + 30
IntOp $CurrentOffset $CurrentOffset + 15
; set the checkbox state depending on what is present in the registry
!insertmacro SetInstallOption $LaunchClientNowCheckbox @CLIENT_LAUNCH_NOW_REG_KEY@ ${BST_CHECKED}
@ -783,27 +779,44 @@ Function PostInstallOptionsPage
${EndIf}
${If} @SERVER_COMPONENT_CONDITIONAL@
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ on startup"
Pop $ServerStartupCheckbox
IntOp $CurrentOffset $CurrentOffset + 15
; set the checkbox state depending on what is present in the registry
!insertmacro SetInstallOption $ServerStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_CHECKED}
${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_CHECKED}
${StrContains} $substringResult "/forceNoLaunchServer" $CMDLINE
${IfNot} $substringResult == ""
${NSD_SetState} $LaunchConsoleNowCheckbox ${BST_UNCHECKED}
${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_CHECKED}
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Perform a clean install (Delete older settings and content)"
Pop $CleanInstallCheckbox
IntOp $CurrentOffset $CurrentOffset + 15
${If} @PR_BUILD@ == 1
; a PR build defaults all install options expect LaunchServerNowCheckbox, LaunchClientNowCheckbox and the settings copy to unchecked
; a PR build defaults all install options expect LaunchConsoleNowCheckbox, LaunchClientNowCheckbox and the settings copy to unchecked
${If} @CLIENT_COMPONENT_CONDITIONAL@
${NSD_SetState} $DesktopClientCheckbox ${BST_UNCHECKED}
${EndIf}
${If} @SERVER_COMPONENT_CONDITIONAL@
${NSD_SetState} $DesktopServerCheckbox ${BST_UNCHECKED}
${NSD_SetState} $ServerStartupCheckbox ${BST_UNCHECKED}
${NSD_SetState} $DesktopConsoleCheckbox ${BST_UNCHECKED}
${NSD_SetState} $ConsoleStartupCheckbox ${BST_UNCHECKED}
${EndIf}
; push the offset
@ -824,9 +837,9 @@ FunctionEnd
!macroend
Var DesktopClientState
Var DesktopServerState
Var ServerStartupState
Var LaunchServerNowState
Var DesktopConsoleState
Var ConsoleStartupState
Var LaunchConsoleNowState
Var LaunchClientNowState
Var CopyFromProductionState
Var CleanInstallState
@ -842,11 +855,11 @@ Function ReadInstallTypes
StrCpy $Express "1"
StrCpy $DesktopClientState ${BST_CHECKED}
StrCpy $ServerStartupState ${BST_CHECKED}
StrCpy $LaunchServerNowState ${BST_CHECKED}
StrCpy $ConsoleStartupState ${BST_CHECKED}
StrCpy $LaunchConsoleNowState ${BST_CHECKED}
StrCpy $LaunchClientNowState ${BST_CHECKED}
StrCpy $CleanInstallState ${BST_UNCHECKED}
StrCpy $DesktopServerState ${BST_UNCHECKED}
StrCpy $DesktopConsoleState ${BST_UNCHECKED}
${If} @PR_BUILD@ == 1
StrCpy $CopyFromProductionState ${BST_UNCHECKED}
@ -860,28 +873,25 @@ Function ReadInstallTypes
FunctionEnd
Function ReadPostInstallOptions
; check if the user asked for a desktop shortcut to console
${NSD_GetState} $DesktopConsoleCheckbox $DesktopConsoleState
; check if the user asked to have console launched every startup
${NSD_GetState} $ConsoleStartupCheckbox $ConsoleStartupState
${If} @CLIENT_COMPONENT_CONDITIONAL@
; check if the user asked for a desktop shortcut to High Fidelity
${NSD_GetState} $DesktopClientCheckbox $DesktopClientState
${EndIf}
${If} @SERVER_COMPONENT_CONDITIONAL@
; check if the user asked for a desktop shortcut to Sandbox
${NSD_GetState} $DesktopServerCheckbox $DesktopServerState
; check if the user asked to have Sandbox launched every startup
${NSD_GetState} $ServerStartupCheckbox $ServerStartupState
${EndIf}
${If} @PR_BUILD@ == 1
; check if we need to copy settings/content from production for this PR build
${NSD_GetState} $CopyFromProductionCheckbox $CopyFromProductionState
${EndIf}
${If} @SERVER_COMPONENT_CONDITIONAL@
; check if we need to launch the server post-install
${NSD_GetState} $LaunchServerNowCheckbox $LaunchServerNowState
${EndIf}
; check if we need to launch the console post-install
${NSD_GetState} $LaunchConsoleNowCheckbox $LaunchConsoleNowState
${If} @CLIENT_COMPONENT_CONDITIONAL@
; check if we need to launch the client post-install
@ -893,6 +903,31 @@ Function ReadPostInstallOptions
FunctionEnd
Function HandlePostInstallOptions
${If} @SERVER_COMPONENT_CONDITIONAL@
; check if the user asked for a desktop shortcut to the console
${If} $DesktopConsoleState == ${BST_CHECKED}
Delete "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk"
CreateShortCut "$DESKTOP\@SANDBOX_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
!insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ YES
; Set appUserModelId
ApplicationID::Set "$DESKTOP\@SANDBOX_HF_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@"
${Else}
!insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO
${EndIf}
${Else}
; check if the user asked for a desktop shortcut to the console
${If} $DesktopConsoleState == ${BST_CHECKED}
Delete "$DESKTOP\@SANDBOX_HF_SHORTCUT_NAME@.lnk"
CreateShortCut "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
!insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ YES
; Set appUserModelId
ApplicationID::Set "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@"
${Else}
!insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO
${EndIf}
${EndIf}
${If} @CLIENT_COMPONENT_CONDITIONAL@
; check if the user asked for a desktop shortcut to High Fidelity
${If} $DesktopClientState == ${BST_CHECKED}
@ -901,38 +936,25 @@ Function HandlePostInstallOptions
${Else}
!insertmacro WriteInstallOption @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ NO
${EndIf}
${EndIf}
${If} @SERVER_COMPONENT_CONDITIONAL@
; check if the user asked for a desktop shortcut to Sandbox
${If} $DesktopServerState == ${BST_CHECKED}
CreateShortCut "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
!insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ YES
; Set appUserModelId
ApplicationID::Set "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@"
${Else}
!insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO
${EndIf}
; check if the user asked to have Console launched every startup
${If} $ConsoleStartupState == ${BST_CHECKED}
; in case we added a shortcut in the global context, pull that now
SetShellVarContext all
Delete "$SMSTARTUP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
; make a startup shortcut in this user's current context
; use the console shortcut name regardless of server/interface install
SetShellVarContext current
CreateShortCut "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
; check if the user asked to have Sandbox launched every startup
${If} $ServerStartupState == ${BST_CHECKED}
; in case we added a shortcut in the global context, pull that now
SetShellVarContext all
Delete "$SMSTARTUP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
; reset the shell var context back
SetShellVarContext all
; make a startup shortcut in this user's current context
SetShellVarContext current
CreateShortCut "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
; reset the shell var context back
SetShellVarContext all
!insertmacro WriteInstallOption @CONSOLE_STARTUP_REG_KEY@ YES
${Else}
!insertmacro WriteInstallOption @CONSOLE_STARTUP_REG_KEY@ NO
${EndIf}
!insertmacro WriteInstallOption @CONSOLE_STARTUP_REG_KEY@ YES
${Else}
!insertmacro WriteInstallOption @CONSOLE_STARTUP_REG_KEY@ NO
${EndIf}
; check if the user asked for a clean install
@ -982,32 +1004,38 @@ Function HandlePostInstallOptions
${EndIf}
${EndIf}
${If} @SERVER_COMPONENT_CONDITIONAL@
${AndIf} $LaunchServerNowState == ${BST_CHECKED}
!insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ YES
; both launches use the explorer trick in case the user has elevated permissions for the installer
${If} $LaunchClientNowState == ${BST_CHECKED}
${If} $LaunchClientNowState == ${BST_CHECKED}
!insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ YES
; create shortcut with ARGUMENTS
CreateShortCut "$TEMP\SandboxShortcut.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" "-- --launchInterface"
Exec '"$WINDIR\explorer.exe" "$TEMP\SandboxShortcut.lnk"'
${Else}
${Else}
!insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ NO
${EndIf}
${If} $LaunchConsoleNowState == ${BST_CHECKED}
!insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ YES
${Else}
!insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ NO
${EndIf}
${If} $LaunchConsoleNowState == ${BST_CHECKED}
${If} @SERVER_COMPONENT_CONDITIONAL@
${AndIf} $LaunchClientNowState == ${BST_CHECKED}
${AndIf} @CLIENT_COMPONENT_CONDITIONAL@
; both launches use the explorer trick in case the user has elevated permissions for the installer
; create shortcut with ARGUMENTS
CreateShortCut "$TEMP\ConsoleShortcut.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" "-- --launchInterface"
Exec '"$WINDIR\explorer.exe" "$TEMP\ConsoleShortcut.lnk"'
${Else}
Exec '"$WINDIR\explorer.exe" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"'
${EndIf}
${EndIf}
${ElseIf} @CLIENT_COMPONENT_CONDITIONAL@
!insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ NO
; launch uses the explorer trick in case the user has elevated permissions for the installer
${If} $LaunchClientNowState == ${BST_CHECKED}
!insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ YES
${If} $LaunchClientNowState == ${BST_CHECKED}
${AndIf} @CLIENT_COMPONENT_CONDITIONAL@
${Unless} $LaunchConsoleNowState == ${BST_CHECKED}
${OrUnless} @SERVER_COMPONENT_CONDITIONAL@
; launch uses the explorer trick in case the user has elevated permissions for the installer
Exec '"$WINDIR\explorer.exe" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"'
${Else}
!insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ NO
${EndIf}
${EndIf}
FunctionEnd
@ -1164,8 +1192,16 @@ Section "-Core installation"
${EndIf}
; Conditional handling for server console shortcut
${If} @SERVER_COMPONENT_CONDITIONAL@
; handling for server console shortcut
Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk"
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_SHORTCUT_NAME@.lnk" \
"$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
; Set appUserModelId
ApplicationID::Set "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@"
${Else}
; handling for interface only console shortcut
Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_SHORTCUT_NAME@.lnk"
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" \
"$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
; Set appUserModelId
@ -1376,12 +1412,15 @@ Section "Uninstall"
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
Delete "$SMPROGRAMS\$MUI_TEMP\@INTERFACE_SHORTCUT_NAME@.lnk"
Delete "$SMPROGRAMS\$MUI_TEMP\@CONSOLE_SHORTCUT_NAME@.lnk"
Delete "$SMPROGRAMS\$MUI_TEMP\@SANDBOX_SHORTCUT_NAME@.lnk"
Delete "$DESKTOP\@INTERFACE_HF_SHORTCUT_NAME@.lnk"
Delete "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk"
Delete "$DESKTOP\@SANDBOX_HF_SHORTCUT_NAME@.lnk"
; if it exists, delete the startup shortcut for the current user
SetShellVarContext current
Delete "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk"
Delete "$SMSTARTUP\@SANDBOX_HF_SHORTCUT_NAME@.lnk"
SetShellVarContext all
@CPACK_NSIS_DELETE_ICONS@
@ -1414,6 +1453,7 @@ Section "Uninstall"
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
Delete "$SMPROGRAMS\$MUI_TEMP\@INTERFACE_SHORTCUT_NAME@.lnk"
Delete "$SMPROGRAMS\$MUI_TEMP\@CONSOLE_SHORTCUT_NAME@.lnk"
Delete "$SMPROGRAMS\$MUI_TEMP\@SANDBOX_SHORTCUT_NAME@.lnk"
@CPACK_NSIS_DELETE_ICONS_EXTRA@
;Delete empty start menu parent diretories

View file

@ -0,0 +1,24 @@
Copyright (c) 2006, Ivan Sagalaev
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of
conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list
of conditions and the following disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of highlight.js nor the names of its contributors may be used to
endorse or promote products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

23
docs/LICENSE_markdeep.txt Normal file
View file

@ -0,0 +1,23 @@
Copyright 2015-2017, Morgan McGuire
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,280 @@
<meta charset="utf-8">
**Pick Parenting**
# What is a pick?
A pick calculates spatial information about the world on on the client.
Picks are immutable to allow efficient use by scripts. There are currently four types of picks:
- Ray pick - Finds the first intersected object along a straight path
- Parabola pick - Finds the first intersected object along a parabolic path
- Stylus pick - Finds the distance between a point and the XZ planes of a list of whitelisted objects
- Collision pick - Uses a volume to check for collisions in the physics engine
With the exception of collision picks, all picks use the visible appearance of the object to check for collisions.
# What is parenting?
Parenting allows an object's position, orientation, and scale (where applicable) to be calculated to another object. This collection of state defines the transform of the object.
Pick parenting allows the pick's transform to be calculated relative to another object, without creating a new pick.
# What can be parented to what?
This object... | | Entity | My Avatar | 3D Overlay | Pick^1 | Pointer^1
---------------------|----------------|--------|-----------|------------|--------|-----------
Can be parented to...| Entity | yes | yes | yes | yes | yes
| My Avatar | yes | no | yes | yes | yes
| Other Avatar | yes | yes | yes | yes | yes
| 3D Overlay | yes | yes | yes | yes | yes
| Pick | no | no | no | yes | yes
| Pointer | no | no | no | no | no
| The Mouse | no | no | no | yes | yes
- ^1 Excluding stylus, which can only be parented to My Avatar's hands for now
# How pick parenting works
This section describes what happens when picks are parented to things.
Since pointers use picks to calculate their results, the rules below
also apply when pointers are parented to things.
## Parent transform exposed
The way a pick is moved/rescaled depends on its parent. In particular,
parenting to a pick actually parents to the pick's result, which
has no notion of scale. A pick can also be transformed relative to
a joint on a model, such as an avatar's hand.
Parent type: | Entity/Avatar | 3D Overlay | Pick
--------------------------|-----------------|--------------|--------
Has position | yes | yes | yes
Has orientation | yes | yes | no
Has scale | yes | yes | no
Can have joints | yes | no | no
## Entity or overlay parent
Parenting a pick to an entity or overlay works similarly to
parenting entities to other things. However, unlike entities,
picks with scale will rescale their dimensions when
their parent rescales.
************************************************************************
* May have a joint, otherwise parent to the parent's origin *
* | *
* scale ^ +--+------+ ^ --+ orientation *
* determined / / | /| |orientation \ offset *
* from / / v / | | v *
* dimensions / / o /..|...................... ^ *
* +-> +---------+ | ------------. . / *
* | | | / position +----> */ <----+ *
* | | | / offset child *
* | | |/ ^ transform*
* v +---------+ / <---+ *
* . +-> dimensions *
* . . . . . . . . . . . . . . | relative *
* . . . v to parent *
************************************************************************
!!! WARNING
Skew is not supported for collision picks. Scaling a parent entity or
overlay non-uniformly can lead to inaccurate shapes for the child
collision pick.
## Avatar parent
A pick parented to an avatar behaves like a wearable. It will maintain
its position relative to some point on the avatar's body. If the pick
has scale (currently only collision picks), then the pick will rescale
when the avatar rescales.
****************************************************************
* Avatar .---. hand ^ -. *
* | | | joint / | *
* '-----> | | \ /orientation | *
* '-+-' +-> o | *
* | / ^ position |relative *
* +---------' +----- |avatar *
* | |scale *
* | if not a joint, |factor *
* | parent to the |(default: 1) *
* | avatar's origin | *
* |\ | |uniform scale *
* | \ | | ^ *
* | \ | | +-> *
* | o \ <-+ -' v *
****************************************************************
***************************************************************
* orientation offset *
* <-----+ *
* ^ \ *
* \ *
* \ child *
* Avatar .---. hand .......... * <-- transform *
* | | | joint . ^ | *
* '-----> | | \ . / v *
* '-+-' +-> o ---------+ ^ *
* | / position +-> scale *
* +---------' offset v relative *
* | to avatar *
***************************************************************
## Pick parent
Picks can also be parented to other picks.
When this is done, the child pick is actually parented to
the parent pick's result, not the pick itself.
A pick parented to another pick will have its position changed,
but not its orientation or scale.
### Ray pick parent
**********************************
* position *
* o *
* \ \ orientation *
* \ \ *
* \ v . . . . *
* \ . *
* \ . result transform *
* * <-- no scale *
* . no orientation *
* . *
**********************************
### Parabola pick parent
**************************************************************
* .------. acceleration *
* + + | ^ *
* speed x ^ / \ . | | *
* orientation / / \ . v | *
* / / * y axis to rotate *
* | . ^ acceleration with *
* o . | *
* position result transform *
* no scale *
* no orientation *
**************************************************************
### Stylus pick parent
********************************************
* *
* *
* . *
* . *
* . *
* .---. avatar * *
* | | hand / ^. *
* | | \ / \ . *
* '-+-' +-> o \ *
* | / result transform *
* +---------' no scale *
* | no orientation *
********************************************
### Collision pick parent
********************************************
* *
* .---. *
* | | <-- collision pick *
* | | *
* | *<-+--- result transform at *
* | | collision pick position *
* | | no scale *
* . . . '---' . . no orientation *
* *
********************************************
# Effect of scale on picks
Scale affects the position and shape of picks, which in turn affects the pick result.
Scale currently does not affect the max distance of a pick.
## Ray and stylus pick scaling
Rescaling the parent of a ray pick or stylus pick can result in a translation of the pick.
***************************************
* before after *
* *
* pick *
* pick +--------------+ ^ *
* ^ | |/ *
* +-----+/ | o *
* | o | | *
* | | | | *
* +-----+ | | *
* parent | | *
* +--------------+ *
* parent *
* *
***************************************
## Parabola pick scaling
***************************************************************************
* before after after *
* (scaleWithParent (scaleWithParent *
* is false) is true) *
* *
* .----. *
* + + *
* .--. / \ *
* + + / \ *
* .--. / \ / \ *
* + + /pick \ /pick \ *
* / \ +-------o +-------o *
* /pick \ | | | | *
* +---o | | | | *
* | | | | | | *
* +---+ +-------+ +-------+ *
* parent parent parent *
***************************************************************************
## Collision pick scaling
Collision picks use the full transform of their parent (position, orientation, and scale/dimensions).
When first created, a collision pick's transform is defined in world space.
As the parent rescales, the collision pick rescales proportionally.
The collision pick's threshold also rescales. The change is proportional to the largest
dimension of the parent. So, if the largest dimension of the parent was 3.0 and is now 6.0,
the threshold doubles.
**************************************************************************************
* *
* before after after *
* (scaleWithParent (scaleWithParent *
* is false) is true) *
* *
* pick *
* +------------+ *
* | | *
* pick | ........ | *
* +-----+ | . . | *
* |.....| | . . | *
* |. .| theshold | . . | *
* pick |.....|___ | | . . | *
* +-----+ +-----+--- <-+ | ........ +___ *
* |.....| | | theshold *
* |. .| theshold +------------+--- *
* |.....|___ | *
* +-----+--- <-+ *
* +----------+ +----------+ *
* +---+ / \ / \ *
* +-----+ +--------------+ +--------------+ *
* parent parent parent *
* *
**************************************************************************************
<style class="fallback">body{visibility:hidden}</style><script>markdeepOptions={tocStyle:'medium'};</script>
<link rel="stylesheet" href="../../markdeep_apidoc.css?">
<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="../../markdeep.min.js"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>

7
docs/markdeep.min.js vendored Normal file

File diff suppressed because one or more lines are too long

170
docs/markdeep_apidoc.css Normal file
View file

@ -0,0 +1,170 @@
/* Custom stylesheet for API documentation by Aras Pranckevičius, http://aras-p.info/
and tweaked by Morgan McGuire.
Licensed as public domain or BSD 2-clause, whichever is more convenient for you.
Originally from https://github.com/aras-p/markdeep-docs-style */
body {
max-width: 50em;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
text-align: left;
margin: 1.5em;
padding: 0 1em;
}
/* if screen is wide enough, put table of contents on the right side */
@media screen and (min-width: 64em) {
.md .longTOC, .md .mediumTOC, .md .shortTOC {
max-width: 20em;
left: 54em;
display:block;
position: fixed;
top:0;
bottom:0;
overflow-y:scroll;
margin-top:0;
margin-bottom:0;
padding-top:1em;
}
}
/* for narrow screens or print, hide table of contents */
@media screen and (max-width: 64em) {
.md .longTOC, .md .mediumTOC, .md .shortTOC { display: none; }
}
@media print {
.md .longTOC, .md .mediumTOC, .md .shortTOC { display: none; }
body { max-width: 100%; }
}
/* reset heading/link fonts to that of body */
.md a,
.md div.title, contents, .md .tocHeader,
.md h1, .md h2, .md h3, .md h4, .md h5, .md h6,
.md .nonumberh1, .md .nonumberh2, .md .nonumberh3, .md .nonumberh4, .md .nonumberh5, .md .nonumberh6,
.md .shortTOC, .md .mediumTOC, .md .longTOC {
font-family: inherit;
}
.md div.title {
margin: 0.4em 0 0 0;
padding: 0;
text-align: inherit;
}
.md div.subtitle {
text-align: inherit;
}
/* faint border below headings */
.md h1, .md h2, .md h3, .md h4,
.md .nonumberh1, .md .nonumberh2, .md .nonumberh3, .md .nonumberh4 {
border-bottom: 1px solid rgba(0,0,0,.1);
}
/* heading font styles */
.md h1, .md .nonumberh1, .md div.title {
font-size: 150%;
font-weight: 600;
color: rgba(0,0,0,.7);
}
.md h2, .md .nonumberh2 {
font-size: 120%;
font-weight: 400;
color: rgba(0,0,0,.9);
}
.md h3, .md .nonumberh3 {
font-size: 110%;
font-weight: 400;
color: rgba(0,0,0,.7);
}
/* no numbering of headings */
.md h1:before, .md h2:before, .md h3:before, .md h4:before { content: none; }
/* link styling */
.md a:link, .md a:visited {
color: #3f51b5;
}
/* inline and block code */
.md code, .md pre.listing {
background-color: rgba(0,0,0,.05);
padding: 0.1em 0.2em;
border-radius: 0.15em;
}
.md pre.listing code {
background-color: transparent;
padding: 0;
border: none;
}
/* table of contents styling; make all 3 forms of it look the same */
.md .longTOC, .md .mediumTOC, .md .shortTOC {
font-size: inherit;
line-height: 120%;
margin: 1em 0;
padding: .4rem;
border-left: .1rem solid #3f51b5;
}
.md .tocHeader {
margin: 0;
padding: 0;
border: none;
font-size: inherit;
}
.md .tocNumber {
display: none;
}
.md .longTOC .level1, .md .mediumTOC .level1, .md .shortTOC .level1 {
font-weight: inherit;
padding: 0;
margin: 0;
}
.md .longTOC p, .md .mediumTOC p, .md .shortTOC p {
overflow: hidden;
text-overflow: ellipsis;
}
.md .longTOC center, .md .mediumTOC center, .md .shortTOC center, .md .tocHeader {
text-align: left;
}
.md .longTOC b, .md .mediumTOC b, .md .shortTOC b {
font-weight: 400;
}
.md .longTOC center b, .md .mediumTOC center b, .md .shortTOC center b {
font-weight: bold;
}
.md .longTOC a, .md .mediumTOC a, .md .shortTOC a {
color: black;
}
.md .longTOC .level1, .md .mediumTOC .level1, .md .shortTOC .level1,
.md .longTOC .level2, .md .mediumTOC .level2, .md .shortTOC .level2,
.md .longTOC .level3, .md .mediumTOC .level3, .md .shortTOC .level3 {
white-space: nowrap;
margin: 0;
padding: 0;
font-size: 90%;
}
/* tables; use fainter colors than regular markdeep style */
.md table.table {
font-size: 90%;
}
.md table.table th {
border: none;
background-color: #ccc;
color: rgba(0,0,0,.6);
}
.md table.table tr, .md table.table td {
border-color: #eee;
}
.md table.table tr:nth-child(even) {
background-color: #f4f4f4;
}

Binary file not shown.

After

(image error) Size: 548 KiB

View file

@ -0,0 +1,8 @@
{
"compressed": {
"COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT": "Default-Sky-9-cubemap_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT.ktx",
"COMPRESSED_SRGB8_ETC2": "Default-Sky-9-cubemap_COMPRESSED_SRGB8_ETC2.ktx"
},
"original": "Default-Sky-9-cubemap.jpg",
"uncompressed": "Default-Sky-9-cubemap.ktx"
}

Binary file not shown.

After

(image error) Size: 2.8 KiB

Binary file not shown.

After

(image error) Size: 3.8 KiB

Binary file not shown.

After

(image error) Size: 2.1 KiB

Binary file not shown.

After

(image error) Size: 4.4 KiB

View file

@ -100,6 +100,25 @@ Rectangle {
wearablesModel.setProperty(wearableIndex, 'properties', wearableModelItemProperties);
}
function entityHasAvatarJoints(entityID) {
var hasAvatarJoint = false;
var props = Entities.getEntityProperties(entityID);
var avatarJointsCount = MyAvatar.getJointNames().length;
if (props && avatarJointsCount >= 0 ) {
var entityJointNames = Entities.getJointNames(entityID);
for (var index = 0; index < entityJointNames.length; index++) {
var avatarJointIndex = MyAvatar.getJointIndex(entityJointNames[index]);
if (avatarJointIndex >= 0) {
hasAvatarJoint = true;
break;
}
}
}
return hasAvatarJoint;
}
function getCurrentWearable() {
return wearablesCombobox.currentIndex !== -1 ? wearablesCombobox.model.get(wearablesCombobox.currentIndex) : null;
}
@ -109,6 +128,7 @@ Rectangle {
var wearable = wearablesCombobox.model.get(i);
if (wearable.id === entityID) {
wearablesCombobox.currentIndex = i;
softWearableTimer.restart();
break;
}
}
@ -118,6 +138,7 @@ Rectangle {
visible = false;
adjustWearablesClosed(status, avatarName);
}
HifiConstants { id: hifi }
@ -130,6 +151,20 @@ Rectangle {
hoverEnabled: true;
}
Timer {
id: softWearableTimer
interval: 1000
running: false
repeat: true
onTriggered: {
var currentWearable = getCurrentWearable();
var soft = currentWearable ? currentWearable.relayParentJoints : false;
var softEnabled = currentWearable ? entityHasAvatarJoints(currentWearable.id) : false;
isSoft.set(soft);
isSoft.enabled = softEnabled;
}
}
Column {
anchors.top: parent.top
anchors.topMargin: 12
@ -247,13 +282,13 @@ Rectangle {
var rotation = currentWearable ? currentWearable.localRotationAngles : { x : 0, y : 0, z : 0 };
var scale = currentWearable ? currentWearable.dimensions.x / currentWearable.naturalDimensions.x : 1.0;
var joint = currentWearable ? currentWearable.parentJointIndex : -1;
var soft = currentWearable ? currentWearable.relayParentJoints : false;
softWearableTimer.restart();
positionVector.set(position);
rotationVector.set(rotation);
scalespinner.set(scale);
jointsCombobox.set(joint);
isSoft.set(soft);
if (currentWearable) {
wearableSelected(currentWearable.id);

File diff suppressed because it is too large Load diff

View file

@ -122,6 +122,7 @@
#include <RecordingScriptingInterface.h>
#include <UpdateSceneTask.h>
#include <RenderViewTask.h>
#include <render/EngineStats.h>
#include <SecondaryCamera.h>
#include <ResourceCache.h>
#include <ResourceRequest.h>
@ -151,6 +152,8 @@
#include <avatars-renderer/ScriptAvatar.h>
#include <RenderableEntityItem.h>
#include <procedural/ProceduralSkybox.h>
#include <model-networking/MaterialCache.h>
#include "recording/ClipCache.h"
#include "AudioClient.h"
#include "audio/AudioScope.h"
@ -215,7 +218,8 @@
#include <raypick/LaserPointerScriptingInterface.h>
#include <raypick/PickScriptingInterface.h>
#include <raypick/PointerScriptingInterface.h>
#include <raypick/MouseRayPick.h>
#include <raypick/RayPick.h>
#include <raypick/MouseTransformNode.h>
#include <FadeEffect.h>
@ -326,9 +330,9 @@ static bool DISABLE_DEFERRED = QProcessEnvironment::systemEnvironment().contains
#endif
#if !defined(Q_OS_ANDROID)
static const int MAX_CONCURRENT_RESOURCE_DOWNLOADS = 16;
static const uint32_t MAX_CONCURRENT_RESOURCE_DOWNLOADS = 16;
#else
static const int MAX_CONCURRENT_RESOURCE_DOWNLOADS = 4;
static const uint32_t MAX_CONCURRENT_RESOURCE_DOWNLOADS = 4;
#endif
// For processing on QThreadPool, we target a number of threads after reserving some
@ -364,7 +368,6 @@ static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SI
static const uint32_t INVALID_FRAME = UINT32_MAX;
static const float PHYSICS_READY_RANGE = 3.0f; // how far from avatar to check for entities that aren't ready for simulation
static const float INITIAL_QUERY_RADIUS = 10.0f; // priority radius for entities before physics enabled
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
@ -1326,7 +1329,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
QString concurrentDownloadsStr = getCmdOption(argc, constArgv, "--concurrent-downloads");
bool success;
int concurrentDownloads = concurrentDownloadsStr.toInt(&success);
uint32_t concurrentDownloads = concurrentDownloadsStr.toUInt(&success);
if (!success) {
concurrentDownloads = MAX_CONCURRENT_RESOURCE_DOWNLOADS;
}
@ -2053,7 +2056,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
}
properties["active_downloads"] = loadingRequests.size();
properties["pending_downloads"] = ResourceCache::getPendingRequestCount();
properties["pending_downloads"] = (int)ResourceCache::getPendingRequestCount();
properties["active_downloads_details"] = loadingRequestsStats;
auto statTracker = DependencyManager::get<StatTracker>();
@ -2286,8 +2289,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
});
// Setup the mouse ray pick and related operators
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickID(DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, std::make_shared<MouseRayPick>(
PickFilter(PickScriptingInterface::PICK_ENTITIES() | PickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE()), 0.0f, true)));
{
auto mouseRayPick = std::make_shared<RayPick>(Vectors::ZERO, Vectors::UP, PickFilter(PickScriptingInterface::PICK_ENTITIES() | PickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE()), 0.0f, true);
mouseRayPick->parentTransform = std::make_shared<MouseTransformNode>();
mouseRayPick->setJointState(PickQuery::JOINT_STATE_MOUSE);
auto mouseRayPickID = DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, mouseRayPick);
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickID(mouseRayPickID);
}
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickResultOperator([](unsigned int rayPickID) {
RayToEntityIntersectionResult entityResult;
entityResult.intersects = false;
@ -4647,8 +4655,8 @@ void Application::idle() {
PROFILE_COUNTER_IF_CHANGED(app, "present", float, displayPlugin->presentRate());
}
PROFILE_COUNTER_IF_CHANGED(app, "renderLoopRate", float, _renderLoopCounter.rate());
PROFILE_COUNTER_IF_CHANGED(app, "currentDownloads", int, ResourceCache::getLoadingRequests().length());
PROFILE_COUNTER_IF_CHANGED(app, "pendingDownloads", int, ResourceCache::getPendingRequestCount());
PROFILE_COUNTER_IF_CHANGED(app, "currentDownloads", uint32_t, ResourceCache::getLoadingRequestCount());
PROFILE_COUNTER_IF_CHANGED(app, "pendingDownloads", uint32_t, ResourceCache::getPendingRequestCount());
PROFILE_COUNTER_IF_CHANGED(app, "currentProcessing", int, DependencyManager::get<StatTracker>()->getStat("Processing").toInt());
PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, DependencyManager::get<StatTracker>()->getStat("PendingProcessing").toInt());
auto renderConfig = _renderEngine->getConfiguration();
@ -5377,8 +5385,8 @@ void Application::resetPhysicsReadyInformation() {
// collision information of nearby entities to make running bullet be safe.
_fullSceneReceivedCounter = 0;
_fullSceneCounterAtLastPhysicsCheck = 0;
_nearbyEntitiesCountAtLastPhysicsCheck = 0;
_nearbyEntitiesStabilityCount = 0;
_gpuTextureMemSizeStabilityCount = 0;
_gpuTextureMemSizeAtLastCheck = 0;
_physicsEnabled = false;
_octreeProcessor.startEntitySequence();
}
@ -5393,13 +5401,21 @@ void Application::reloadResourceCaches() {
queryOctree(NodeType::EntityServer, PacketType::EntityQuery);
// Clear the entities and their renderables
getEntities()->clear();
DependencyManager::get<AssetClient>()->clearCache();
DependencyManager::get<ScriptCache>()->clearCache();
// Clear all the resource caches
DependencyManager::get<ResourceCacheSharedItems>()->clear();
DependencyManager::get<AnimationCache>()->refreshAll();
DependencyManager::get<ModelCache>()->refreshAll();
DependencyManager::get<SoundCache>()->refreshAll();
MaterialCache::instance().refreshAll();
DependencyManager::get<ModelCache>()->refreshAll();
ShaderCache::instance().refreshAll();
DependencyManager::get<TextureCache>()->refreshAll();
DependencyManager::get<recording::ClipCache>()->refreshAll();
DependencyManager::get<NodeList>()->reset(); // Force redownload of .fst models
@ -5617,18 +5633,21 @@ void Application::update(float deltaTime) {
// for nearby entities before starting bullet up.
quint64 now = usecTimestampNow();
if (isServerlessMode() || _octreeProcessor.isLoadSequenceComplete()) {
// we've received a new full-scene octree stats packet, or it's been long enough to try again anyway
_lastPhysicsCheckTime = now;
_fullSceneCounterAtLastPhysicsCheck = _fullSceneReceivedCounter;
_lastQueriedViews.clear(); // Force new view.
bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
if (gpuTextureMemSizeStable() || !enableInterstitial) {
// we've received a new full-scene octree stats packet, or it's been long enough to try again anyway
_lastPhysicsCheckTime = now;
_fullSceneCounterAtLastPhysicsCheck = _fullSceneReceivedCounter;
_lastQueriedViews.clear(); // Force new view.
// process octree stats packets are sent in between full sends of a scene (this isn't currently true).
// We keep physics disabled until we've received a full scene and everything near the avatar in that
// scene is ready to compute its collision shape.
if (getMyAvatar()->isReadyForPhysics()) {
_physicsEnabled = true;
setIsInterstitialMode(false);
getMyAvatar()->updateMotionBehaviorFromMenu();
// process octree stats packets are sent in between full sends of a scene (this isn't currently true).
// We keep physics disabled until we've received a full scene and everything near the avatar in that
// scene is ready to compute its collision shape.
if (getMyAvatar()->isReadyForPhysics()) {
_physicsEnabled = true;
setIsInterstitialMode(false);
getMyAvatar()->updateMotionBehaviorFromMenu();
}
}
}
} else if (domainLoadingInProgress) {
@ -5915,6 +5934,10 @@ void Application::update(float deltaTime) {
// update the rendering without any simulation
getEntities()->update(false);
}
// remove recently dead avatarEntities
SetOfEntities deadAvatarEntities;
_entitySimulation->takeDeadAvatarEntities(deadAvatarEntities);
avatarManager->removeDeadAvatarEntities(deadAvatarEntities);
}
// AvatarManager update
@ -6239,6 +6262,8 @@ int Application::sendNackPackets() {
missingSequenceNumbers = sequenceNumberStats.getMissingSet();
});
_isMissingSequenceNumbers = (missingSequenceNumbers.size() != 0);
// construct nack packet(s) for this node
foreach(const OCTREE_PACKET_SEQUENCE& missingNumber, missingSequenceNumbers) {
nackPacketList->writePrimitive(missingNumber);
@ -6265,9 +6290,19 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType) {
const bool isModifiedQuery = !_physicsEnabled;
if (isModifiedQuery) {
// Create modified view that is a simple sphere.
bool interstitialModeEnabled = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
ConicalViewFrustum sphericalView;
sphericalView.setSimpleRadius(INITIAL_QUERY_RADIUS);
_octreeQuery.setConicalViews({ sphericalView });
if (interstitialModeEnabled) {
ConicalViewFrustum farView;
farView.set(_viewFrustum);
_octreeQuery.setConicalViews({ sphericalView, farView });
} else {
_octreeQuery.setConicalViews({ sphericalView });
}
_octreeQuery.setOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE);
static constexpr float MIN_LOD_ADJUST = -20.0f;
_octreeQuery.setBoundaryLevelAdjust(MIN_LOD_ADJUST);
@ -6445,9 +6480,12 @@ void Application::clearDomainOctreeDetails() {
skyStage->setBackgroundMode(graphics::SunSkyStage::SKY_DEFAULT);
DependencyManager::get<AnimationCache>()->clearUnusedResources();
DependencyManager::get<ModelCache>()->clearUnusedResources();
DependencyManager::get<SoundCache>()->clearUnusedResources();
MaterialCache::instance().clearUnusedResources();
DependencyManager::get<ModelCache>()->clearUnusedResources();
ShaderCache::instance().clearUnusedResources();
DependencyManager::get<TextureCache>()->clearUnusedResources();
DependencyManager::get<recording::ClipCache>()->clearUnusedResources();
getMyAvatar()->setAvatarEntityDataChanged(true);
}
@ -6579,69 +6617,23 @@ void Application::trackIncomingOctreePacket(ReceivedMessage& message, SharedNode
}
}
bool Application::nearbyEntitiesAreReadyForPhysics() {
// this is used to avoid the following scenario:
// A table has some items sitting on top of it. The items are at rest, meaning they aren't active in bullet.
// Someone logs in close to the table. They receive information about the items on the table before they
// receive information about the table. The items are very close to the avatar's capsule, so they become
// activated in bullet. This causes them to fall to the floor, because the table's shape isn't yet in bullet.
EntityTreePointer entityTree = getEntities()->getTree();
if (!entityTree) {
return false;
}
bool Application::gpuTextureMemSizeStable() {
auto renderConfig = qApp->getRenderEngine()->getConfiguration();
auto renderStats = renderConfig->getConfig<render::EngineStats>("Stats");
// We don't want to use EntityTree::findEntities(AABox, ...) method because that scan will snarf parented entities
// whose bounding boxes cannot be computed (it is too loose for our purposes here). Instead we manufacture
// custom filters and use the general-purpose EntityTree::findEntities(filter, ...)
QVector<EntityItemPointer> entities;
AABox avatarBox(getMyAvatar()->getWorldPosition() - glm::vec3(PHYSICS_READY_RANGE), glm::vec3(2 * PHYSICS_READY_RANGE));
// create two functions that use avatarBox (entityScan and elementScan), the second calls the first
std::function<bool (EntityItemPointer&)> entityScan = [=](EntityItemPointer& entity) {
if (entity->shouldBePhysical()) {
bool success = false;
AABox entityBox = entity->getAABox(success);
// important: bail for entities that cannot supply a valid AABox
return success && avatarBox.touches(entityBox);
}
return false;
};
std::function<bool(const OctreeElementPointer&, void*)> elementScan = [&](const OctreeElementPointer& element, void* unused) {
if (element->getAACube().touches(avatarBox)) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
entityTreeElement->getEntities(entityScan, entities);
return true;
}
return false;
};
qint64 textureResourceGPUMemSize = renderStats->textureResourceGPUMemSize;
qint64 texturePopulatedGPUMemSize = renderStats->textureResourcePopulatedGPUMemSize;
qint64 textureTransferSize = renderStats->texturePendingGPUTransferSize;
entityTree->withReadLock([&] {
// Pass the second function to the general-purpose EntityTree::findEntities()
// which will traverse the tree, apply the two filter functions (to element, then to entities)
// as it traverses. The end result will be a list of entities that match.
entityTree->findEntities(elementScan, entities);
});
uint32_t nearbyCount = entities.size();
if (nearbyCount == _nearbyEntitiesCountAtLastPhysicsCheck) {
_nearbyEntitiesStabilityCount++;
if (_gpuTextureMemSizeAtLastCheck == textureResourceGPUMemSize) {
_gpuTextureMemSizeStabilityCount++;
} else {
_nearbyEntitiesStabilityCount = 0;
_gpuTextureMemSizeStabilityCount = 0;
}
_nearbyEntitiesCountAtLastPhysicsCheck = nearbyCount;
_gpuTextureMemSizeAtLastCheck = textureResourceGPUMemSize;
const uint32_t MINIMUM_NEARBY_ENTITIES_STABILITY_COUNT = 3;
if (_nearbyEntitiesStabilityCount >= MINIMUM_NEARBY_ENTITIES_STABILITY_COUNT) {
// We've seen the same number of nearby entities for several stats packets in a row. assume we've got all
// the local entities.
bool result = true;
foreach (EntityItemPointer entity, entities) {
if (entity->shouldBePhysical() && !entity->isReadyToComputeShape()) {
HIFI_FCDEBUG(interfaceapp(), "Physics disabled until entity loads: " << entity->getID() << entity->getName());
// don't break here because we want all the relevant entities to start their downloads
result = false;
}
}
return result;
if (_gpuTextureMemSizeStabilityCount >= _minimumGPUTextureMemSizeStabilityCount) {
return (textureResourceGPUMemSize == texturePopulatedGPUMemSize) && (textureTransferSize == 0);
}
return false;
}

View file

@ -183,6 +183,8 @@ public:
// passes, mirror window passes, etc
void copyDisplayViewFrustum(ViewFrustum& viewOut) const;
bool isMissingSequenceNumbers() { return _isMissingSequenceNumbers; }
const ConicalViewFrustums& getConicalViews() const override { return _conicalViews; }
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
@ -230,6 +232,8 @@ public:
float getSettingConstrainToolbarPosition() { return _constrainToolbarPosition.get(); }
void setSettingConstrainToolbarPosition(bool setting);
Q_INVOKABLE void setMinimumGPUTextureMemStabilityCount(int stabilityCount) { _minimumGPUTextureMemSizeStabilityCount = stabilityCount; }
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; }
@ -525,7 +529,7 @@ private:
bool importFromZIP(const QString& filePath);
bool importImage(const QString& urlString);
bool nearbyEntitiesAreReadyForPhysics();
bool gpuTextureMemSizeStable();
int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode);
void trackIncomingOctreePacket(ReceivedMessage& message, SharedNodePointer sendingNode, bool wasStatsPacket);
@ -581,6 +585,8 @@ private:
QElapsedTimer _lastTimeUpdated;
QElapsedTimer _lastTimeRendered;
int _minimumGPUTextureMemSizeStabilityCount { 30 };
ShapeManager _shapeManager;
PhysicalEntitySimulationPointer _entitySimulation;
PhysicsEnginePointer _physicsEngine;
@ -709,6 +715,8 @@ private:
bool _fakedMouseEvent { false };
bool _isMissingSequenceNumbers { false };
void checkChangeCursor();
mutable QMutex _changeCursorLock { QMutex::Recursive };
Qt::CursorShape _desiredCursor{ Qt::BlankCursor };
@ -719,8 +727,10 @@ private:
std::atomic<uint32_t> _fullSceneReceivedCounter { 0 }; // how many times have we received a full-scene octree stats packet
uint32_t _fullSceneCounterAtLastPhysicsCheck { 0 }; // _fullSceneReceivedCounter last time we checked physics ready
uint32_t _nearbyEntitiesCountAtLastPhysicsCheck { 0 }; // how many in-range entities last time we checked physics ready
uint32_t _nearbyEntitiesStabilityCount { 0 }; // how many times has _nearbyEntitiesCountAtLastPhysicsCheck been the same
qint64 _gpuTextureMemSizeStabilityCount { 0 };
qint64 _gpuTextureMemSizeAtLastCheck { 0 };
quint64 _lastPhysicsCheckTime { usecTimestampNow() }; // when did we last check to see if physics was ready
bool _keyboardDeviceHasFocus { true };

View file

@ -275,7 +275,11 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
if (inView && avatar->hasNewJointData()) {
numAvatarsUpdated++;
}
avatar->_transit.update(deltaTime, avatar->_globalPosition, _transitConfig);
auto transitStatus = avatar->_transit.update(deltaTime, avatar->_globalPosition, _transitConfig);
if (avatar->getIsNewAvatar() && (transitStatus == AvatarTransit::Status::START_TRANSIT || transitStatus == AvatarTransit::Status::ABORT_TRANSIT)) {
avatar->_transit.reset();
avatar->setIsNewAvatar(false);
}
avatar->simulate(deltaTime, inView);
avatar->updateRenderItem(renderTransaction);
avatar->updateSpaceProxy(workloadTransaction);
@ -448,6 +452,17 @@ void AvatarManager::handleProcessedPhysicsTransaction(PhysicsEngine::Transaction
transaction.clear();
}
void AvatarManager::removeDeadAvatarEntities(const SetOfEntities& deadEntities) {
for (auto entity : deadEntities) {
QUuid sessionID = entity->getOwningAvatarID();
AvatarSharedPointer avatar = getAvatarBySessionID(sessionID);
if (avatar) {
const bool REQUIRES_REMOVAL_FROM_TREE = false;
avatar->clearAvatarEntity(entity->getID(), REQUIRES_REMOVAL_FROM_TREE);
}
}
}
void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) {
auto avatar = std::static_pointer_cast<OtherAvatar>(removedAvatar);
{

View file

@ -26,6 +26,7 @@
#include <avatars-renderer/ScriptAvatar.h>
#include <AudioInjector.h>
#include <workload/Space.h>
#include <EntitySimulation.h> // for SetOfEntities
#include "AvatarMotionState.h"
#include "MyAvatar.h"
@ -187,6 +188,7 @@ public:
void queuePhysicsChange(const OtherAvatarPointer& avatar);
void buildPhysicsTransaction(PhysicsEngine::Transaction& transaction);
void handleProcessedPhysicsTransaction(PhysicsEngine::Transaction& transaction);
void removeDeadAvatarEntities(const SetOfEntities& deadEntities);
public slots:
/**jsdoc

View file

@ -137,7 +137,7 @@ MyAvatar::MyAvatar(QThread* thread) :
_useSnapTurnSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "useSnapTurn", _useSnapTurn),
_userHeightSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "userHeight", DEFAULT_AVATAR_HEIGHT),
_flyingHMDSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "flyingHMD", _flyingPrefHMD),
_avatarEntityCountSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" << "size", _flyingPrefHMD)
_avatarEntityCountSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" << "size", 0)
{
_clientTraitsHandler = std::unique_ptr<ClientTraitsHandler>(new ClientTraitsHandler(this));
@ -1942,7 +1942,7 @@ void MyAvatar::updateMotors() {
horizontalMotorTimescale = FLYING_MOTOR_TIMESCALE;
verticalMotorTimescale = FLYING_MOTOR_TIMESCALE;
} else {
horizontalMotorTimescale = WALKING_MOTOR_TIMESCALE;
horizontalMotorTimescale = WALKING_MOTOR_TIMESCALE * getSensorToWorldScale();
verticalMotorTimescale = INVALID_MOTOR_TIMESCALE;
}

View file

@ -11,12 +11,12 @@
#include "AvatarMotionState.h"
static xColor getLoadingOrbColor(Avatar::LoadingStatus loadingStatus) {
static glm::u8vec3 getLoadingOrbColor(Avatar::LoadingStatus loadingStatus) {
const xColor NO_MODEL_COLOR(0xe3, 0xe3, 0xe3);
const xColor LOAD_MODEL_COLOR(0xef, 0x93, 0xd1);
const xColor LOAD_SUCCESS_COLOR(0x1f, 0xc6, 0xa6);
const xColor LOAD_FAILURE_COLOR(0xc6, 0x21, 0x47);
const glm::u8vec3 NO_MODEL_COLOR(0xe3, 0xe3, 0xe3);
const glm::u8vec3 LOAD_MODEL_COLOR(0xef, 0x93, 0xd1);
const glm::u8vec3 LOAD_SUCCESS_COLOR(0x1f, 0xc6, 0xa6);
const glm::u8vec3 LOAD_FAILURE_COLOR(0xc6, 0x21, 0x47);
switch (loadingStatus) {
case Avatar::LoadingStatus::NoModel:
return NO_MODEL_COLOR;

View file

@ -10,8 +10,11 @@
//
#include "SafeLanding.h"
#include <SharedUtil.h>
#include "EntityTreeRenderer.h"
#include "ModelEntityItem.h"
#include "RenderableModelEntityItem.h"
#include "InterfaceLogging.h"
#include "Application.h"
@ -39,6 +42,7 @@ void SafeLanding::startEntitySequence(QSharedPointer<EntityTreeRenderer> entityT
_entityTree = entityTree;
_trackedEntities.clear();
_trackingEntities = true;
_maxTrackedEntityCount = 0;
connect(std::const_pointer_cast<EntityTree>(_entityTree).get(),
&EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity);
connect(std::const_pointer_cast<EntityTree>(_entityTree).get(),
@ -47,6 +51,7 @@ void SafeLanding::startEntitySequence(QSharedPointer<EntityTreeRenderer> entityT
_sequenceNumbers.clear();
_initialStart = INVALID_SEQUENCE;
_initialEnd = INVALID_SEQUENCE;
_startTime = usecTimestampNow();
EntityTreeRenderer::setEntityLoadingPriorityFunction(&ElevatedPriority);
}
}
@ -55,6 +60,7 @@ void SafeLanding::stopEntitySequence() {
Locker lock(_lock);
_trackingEntities = false;
_maxTrackedEntityCount = 0;
_trackedEntityStabilityCount = 0;
_initialStart = INVALID_SEQUENCE;
_initialEnd = INVALID_SEQUENCE;
_trackedEntities.clear();
@ -66,18 +72,17 @@ void SafeLanding::addTrackedEntity(const EntityItemID& entityID) {
Locker lock(_lock);
EntityItemPointer entity = _entityTree->findEntityByID(entityID);
if (entity) {
if (entity && entity->getCreated() < _startTime) {
_trackedEntities.emplace(entityID, entity);
int trackedEntityCount = (int)_trackedEntities.size();
if (trackedEntityCount > _maxTrackedEntityCount) {
_maxTrackedEntityCount = trackedEntityCount;
_trackedEntityStabilityCount = 0;
}
qCDebug(interfaceapp) << "Safe Landing: Tracking entity " << entity->getItemName();
}
} else {
qCDebug(interfaceapp) << "Safe Landing: Null Entity: " << entityID;
}
}
@ -104,10 +109,10 @@ void SafeLanding::noteReceivedsequenceNumber(int sequenceNumber) {
bool SafeLanding::isLoadSequenceComplete() {
if (isEntityLoadingComplete() && isSequenceNumbersComplete()) {
Locker lock(_lock);
_trackedEntities.clear();
_initialStart = INVALID_SEQUENCE;
_initialEnd = INVALID_SEQUENCE;
_entityTree = nullptr;
_trackingEntities = false; // Don't track anything else that comes in.
EntityTreeRenderer::setEntityLoadingPriorityFunction(StandardPriority);
}
@ -116,11 +121,18 @@ bool SafeLanding::isLoadSequenceComplete() {
float SafeLanding::loadingProgressPercentage() {
Locker lock(_lock);
static const int MINIMUM_TRACKED_ENTITY_STABILITY_COUNT = 15;
float entityReadyPercentage = 0.0f;
if (_maxTrackedEntityCount > 0) {
return ((_maxTrackedEntityCount - _trackedEntities.size()) / (float)_maxTrackedEntityCount);
entityReadyPercentage = ((_maxTrackedEntityCount - _trackedEntities.size()) / (float)_maxTrackedEntityCount);
}
return 0.0f;
if (_trackedEntityStabilityCount < MINIMUM_TRACKED_ENTITY_STABILITY_COUNT) {
entityReadyPercentage *= 0.20f;
}
return entityReadyPercentage;
}
bool SafeLanding::isSequenceNumbersComplete() {
@ -130,11 +142,16 @@ bool SafeLanding::isSequenceNumbersComplete() {
_initialEnd + SEQUENCE_MODULO - _initialStart;
auto startIter = _sequenceNumbers.find(_initialStart);
auto endIter = _sequenceNumbers.find(_initialEnd - 1);
bool missingSequenceNumbers = qApp->isMissingSequenceNumbers();
if (sequenceSize == 0 ||
(startIter != _sequenceNumbers.end()
&& endIter != _sequenceNumbers.end()
&& distance(startIter, endIter) == sequenceSize - 1) ) {
_trackingEntities = false; // Don't track anything else that comes in.
&& ((distance(startIter, endIter) == sequenceSize - 1) || !missingSequenceNumbers))) {
bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
if (!enableInterstitial) {
_trackingEntities = false; // Don't track anything else that comes in.
}
return true;
}
}
@ -145,13 +162,13 @@ bool isEntityPhysicsReady(const EntityItemPointer& entity) {
if (entity && !entity->getCollisionless()) {
const auto& entityType = entity->getType();
if (entityType == EntityTypes::Model) {
ModelEntityItem * modelEntity = std::dynamic_pointer_cast<ModelEntityItem>(entity).get();
RenderableModelEntityItem * modelEntity = std::dynamic_pointer_cast<RenderableModelEntityItem>(entity).get();
static const std::set<ShapeType> downloadedCollisionTypes
{ SHAPE_TYPE_COMPOUND, SHAPE_TYPE_SIMPLE_COMPOUND, SHAPE_TYPE_STATIC_MESH, SHAPE_TYPE_SIMPLE_HULL };
bool hasAABox;
entity->getAABox(hasAABox);
if (hasAABox && downloadedCollisionTypes.count(modelEntity->getShapeType()) != 0) {
return (!entity->shouldBePhysical() || entity->isReadyToComputeShape());
return (!entity->shouldBePhysical() || entity->isReadyToComputeShape() || modelEntity->computeShapeFailedToLoad());
}
}
}
@ -166,16 +183,20 @@ bool SafeLanding::isEntityLoadingComplete() {
auto entityTree = qApp->getEntities();
auto entityMapIter = _trackedEntities.begin();
bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
while (entityMapIter != _trackedEntities.end()) {
auto entity = entityMapIter->second;
bool isVisuallyReady = true;
Settings settings;
bool enableInterstitial = settings.value("enableIntersitialMode", false).toBool();
if (enableInterstitial) {
isVisuallyReady = (entity->isVisuallyReady() || !entityTree->renderableForEntityId(entityMapIter->first));
auto entityRenderable = entityTree->renderableForEntityId(entityMapIter->first);
if (!entityRenderable) {
entityTree->addingEntity(entityMapIter->first);
}
isVisuallyReady = entity->isVisuallyReady() || (!entityRenderable && !entity->isParentPathComplete());
}
if (isEntityPhysicsReady(entity) && isVisuallyReady) {
@ -188,6 +209,12 @@ bool SafeLanding::isEntityLoadingComplete() {
entityMapIter++;
}
}
if (enableInterstitial) {
_trackedEntityStabilityCount++;
}
return _trackedEntities.empty();
}

View file

@ -52,6 +52,9 @@ private:
int _initialStart { INVALID_SEQUENCE };
int _initialEnd { INVALID_SEQUENCE };
int _maxTrackedEntityCount { 0 };
int _trackedEntityStabilityCount { 0 };
quint64 _startTime { 0 };
struct SequenceLessThan {
bool operator()(const int& a, const int& b) const;

View file

@ -345,9 +345,9 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
}
}
CollisionPick::CollisionPick(const PickFilter& filter, float maxDistance, bool enabled, CollisionRegion collisionRegion, PhysicsEnginePointer physicsEngine) :
Pick(filter, maxDistance, enabled),
_mathPick(collisionRegion),
CollisionPick::CollisionPick(const PickFilter& filter, float maxDistance, bool enabled, bool scaleWithParent, CollisionRegion collisionRegion, PhysicsEnginePointer physicsEngine) :
Pick(collisionRegion, filter, maxDistance, enabled),
_scaleWithParent(scaleWithParent),
_physicsEngine(physicsEngine) {
if (collisionRegion.shouldComputeShapeInfo()) {
_cachedResource = DependencyManager::get<ModelCache>()->getCollisionGeometryResource(collisionRegion.modelURL);
@ -361,9 +361,15 @@ CollisionRegion CollisionPick::getMathematicalPick() const {
if (parentTransform) {
Transform parentTransformValue = parentTransform->getTransform();
mathPick.transform = parentTransformValue.worldTransform(mathPick.transform);
glm::vec3 scale = parentTransformValue.getScale();
float largestDimension = glm::max(glm::max(scale.x, scale.y), scale.z);
mathPick.threshold *= largestDimension;
if (_scaleWithParent) {
glm::vec3 scale = parentTransformValue.getScale();
float largestDimension = glm::max(glm::max(scale.x, scale.y), scale.z);
mathPick.threshold *= largestDimension;
} else {
// We need to undo parent scaling after-the-fact because the parent's scale was needed to calculate this mathPick's position
mathPick.transform.setScale(_mathPick.transform.getScale());
}
}
return mathPick;
}
@ -424,5 +430,7 @@ PickResultPointer CollisionPick::getHUDIntersection(const CollisionRegion& pick)
}
Transform CollisionPick::getResultTransform() const {
return Transform(getMathematicalPick().transform);
Transform transform;
transform.setTranslation(_mathPick.transform.getTranslation());
return transform;
}

View file

@ -47,7 +47,7 @@ public:
class CollisionPick : public Pick<CollisionRegion> {
public:
CollisionPick(const PickFilter& filter, float maxDistance, bool enabled, CollisionRegion collisionRegion, PhysicsEnginePointer physicsEngine);
CollisionPick(const PickFilter& filter, float maxDistance, bool enabled, bool scaleWithParent, CollisionRegion collisionRegion, PhysicsEnginePointer physicsEngine);
CollisionRegion getMathematicalPick() const override;
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override {
@ -67,7 +67,8 @@ protected:
void computeShapeInfoDimensionsOnly(const CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer<GeometryResource> resource);
void filterIntersections(std::vector<ContactTestResult>& intersections) const;
CollisionRegion _mathPick;
bool _scaleWithParent;
PhysicsEnginePointer _physicsEngine;
QSharedPointer<GeometryResource> _cachedResource;

View file

@ -1,43 +0,0 @@
//
// Created by Sam Gondelman 7/2/2018
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "JointParabolaPick.h"
#include "avatar/AvatarManager.h"
JointParabolaPick::JointParabolaPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset,
float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool scaleWithAvatar, PickFilter& filter, float maxDistance, bool enabled) :
ParabolaPick(speed, accelerationAxis, rotateAccelerationWithAvatar, scaleWithAvatar, filter, maxDistance, enabled),
_jointName(jointName),
_posOffset(posOffset),
_dirOffset(dirOffset)
{
}
PickParabola JointParabolaPick::getMathematicalPick() const {
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
int jointIndex = myAvatar->getJointIndex(QString::fromStdString(_jointName));
bool useAvatarHead = _jointName == "Avatar";
const int INVALID_JOINT = -1;
if (jointIndex != INVALID_JOINT || useAvatarHead) {
glm::vec3 jointPos = useAvatarHead ? myAvatar->getHeadPosition() : myAvatar->getAbsoluteJointTranslationInObjectFrame(jointIndex);
glm::quat jointRot = useAvatarHead ? myAvatar->getHeadOrientation() : myAvatar->getAbsoluteJointRotationInObjectFrame(jointIndex);
glm::vec3 avatarPos = myAvatar->getWorldPosition();
glm::quat avatarRot = myAvatar->getWorldOrientation();
glm::vec3 pos = useAvatarHead ? jointPos : avatarPos + (avatarRot * jointPos);
glm::quat rot = useAvatarHead ? jointRot * glm::angleAxis(-PI / 2.0f, Vectors::RIGHT) : avatarRot * jointRot;
// Apply offset
pos = pos + (rot * (myAvatar->getSensorToWorldScale() * _posOffset));
glm::vec3 dir = glm::normalize(rot * glm::normalize(_dirOffset));
return PickParabola(pos, getSpeed() * dir, getAcceleration());
}
return PickParabola();
}

View file

@ -1,32 +0,0 @@
//
// Created by Sam Gondelman 7/2/2018
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_JointParabolaPick_h
#define hifi_JointParabolaPick_h
#include "ParabolaPick.h"
class JointParabolaPick : public ParabolaPick {
public:
JointParabolaPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset,
float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool scaleWithAvatar,
PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
PickParabola getMathematicalPick() const override;
bool isLeftHand() const override { return (_jointName == "_CONTROLLER_LEFTHAND") || (_jointName == "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"); }
bool isRightHand() const override { return (_jointName == "_CONTROLLER_RIGHTHAND") || (_jointName == "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND"); }
private:
std::string _jointName;
glm::vec3 _posOffset;
glm::vec3 _dirOffset;
};
#endif // hifi_JointParabolaPick_h

View file

@ -1,45 +0,0 @@
//
// JointRayPick.cpp
// interface/src/raypick
//
// Created by Sam Gondelman 7/11/2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "JointRayPick.h"
#include "avatar/AvatarManager.h"
JointRayPick::JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, float maxDistance, bool enabled) :
RayPick(filter, maxDistance, enabled),
_jointName(jointName),
_posOffset(posOffset),
_dirOffset(dirOffset)
{
}
PickRay JointRayPick::getMathematicalPick() const {
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
int jointIndex = myAvatar->getJointIndex(QString::fromStdString(_jointName));
bool useAvatarHead = _jointName == "Avatar";
const int INVALID_JOINT = -1;
if (jointIndex != INVALID_JOINT || useAvatarHead) {
glm::vec3 jointPos = useAvatarHead ? myAvatar->getHeadPosition() : myAvatar->getAbsoluteJointTranslationInObjectFrame(jointIndex);
glm::quat jointRot = useAvatarHead ? myAvatar->getHeadOrientation() : myAvatar->getAbsoluteJointRotationInObjectFrame(jointIndex);
glm::vec3 avatarPos = myAvatar->getWorldPosition();
glm::quat avatarRot = myAvatar->getWorldOrientation();
glm::vec3 pos = useAvatarHead ? jointPos : avatarPos + (avatarRot * jointPos);
glm::quat rot = useAvatarHead ? jointRot * glm::angleAxis(-PI / 2.0f, Vectors::RIGHT) : avatarRot * jointRot;
// Apply offset
pos = pos + (rot * (myAvatar->getSensorToWorldScale() * _posOffset));
glm::vec3 dir = glm::normalize(rot * glm::normalize(_dirOffset));
return PickRay(pos, dir);
}
return PickRay();
}

View file

@ -1,33 +0,0 @@
//
// JointRayPick.h
// interface/src/raypick
//
// Created by Sam Gondelman 7/11/2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_JointRayPick_h
#define hifi_JointRayPick_h
#include "RayPick.h"
class JointRayPick : public RayPick {
public:
JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
PickRay getMathematicalPick() const override;
bool isLeftHand() const override { return (_jointName == "_CONTROLLER_LEFTHAND") || (_jointName == "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"); }
bool isRightHand() const override { return (_jointName == "_CONTROLLER_RIGHTHAND") || (_jointName == "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND"); }
private:
std::string _jointName;
glm::vec3 _posOffset;
glm::vec3 _dirOffset;
};
#endif // hifi_JointRayPick_h

View file

@ -14,13 +14,14 @@
#include "avatar/AvatarManager.h"
#include <DependencyManager.h>
#include "PickManager.h"
#include "RayPick.h"
LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, bool hover,
const PointerTriggers& triggers, bool faceAvatar, bool followNormal, float followNormalTime, bool centerEndY, bool lockEnd,
bool distanceScaleEnd, bool scaleWithAvatar, bool enabled) :
bool distanceScaleEnd, bool scaleWithParent, bool enabled) :
PathPointer(PickQuery::Ray, rayProps, renderStates, defaultRenderStates, hover, triggers, faceAvatar, followNormal, followNormalTime,
centerEndY, lockEnd, distanceScaleEnd, scaleWithAvatar, enabled)
centerEndY, lockEnd, distanceScaleEnd, scaleWithParent, enabled)
{
}
@ -146,9 +147,9 @@ void LaserPointer::RenderState::disable() {
}
}
void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY,
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) {
StartEndRenderState::update(origin, end, surfaceNormal, scaleWithAvatar, distanceScaleEnd, centerEndY, faceAvatar, followNormal, followNormalStrength, distance, pickResult);
StartEndRenderState::update(origin, end, surfaceNormal, parentScale, distanceScaleEnd, centerEndY, faceAvatar, followNormal, followNormalStrength, distance, pickResult);
QVariant endVariant = vec3toVariant(end);
if (!getPathID().isNull()) {
QVariantMap pathProps;
@ -156,9 +157,7 @@ void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3&
pathProps.insert("end", endVariant);
pathProps.insert("visible", true);
pathProps.insert("ignoreRayIntersection", doesPathIgnoreRays());
if (scaleWithAvatar) {
pathProps.insert("lineWidth", getLineWidth() * DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale());
}
pathProps.insert("lineWidth", getLineWidth() * parentScale);
qApp->getOverlays().editOverlay(getPathID(), pathProps);
}
}

View file

@ -24,12 +24,12 @@ public:
const OverlayID& getPathID() const { return _pathID; }
const bool& doesPathIgnoreRays() const { return _pathIgnoreRays; }
void setLineWidth(const float& lineWidth) { _lineWidth = lineWidth; }
const float& getLineWidth() const { return _lineWidth; }
void setLineWidth(float width) { _lineWidth = width; }
float getLineWidth() const { return _lineWidth; }
void cleanup() override;
void disable() override;
void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY,
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) override;
private:
@ -40,7 +40,7 @@ public:
};
LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, bool hover, const PointerTriggers& triggers,
bool faceAvatar, bool followNormal, float followNormalStrength, bool centerEndY, bool lockEnd, bool distanceScaleEnd, bool scaleWithAvatar, bool enabled);
bool faceAvatar, bool followNormal, float followNormalStrength, bool centerEndY, bool lockEnd, bool distanceScaleEnd, bool scaleWithParent, bool enabled);
QVariantMap toVariantMap() const override;

View file

@ -1,28 +0,0 @@
//
// Created by Sam Gondelman 7/2/2018
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "MouseParabolaPick.h"
#include "Application.h"
#include "display-plugins/CompositorHelper.h"
MouseParabolaPick::MouseParabolaPick(float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar,
bool scaleWithAvatar, const PickFilter& filter, float maxDistance, bool enabled) :
ParabolaPick(speed, accelerationAxis, rotateAccelerationWithAvatar, scaleWithAvatar, filter, maxDistance, enabled)
{
}
PickParabola MouseParabolaPick::getMathematicalPick() const {
QVariant position = qApp->getApplicationCompositor().getReticleInterface()->getPosition();
if (position.isValid()) {
QVariantMap posMap = position.toMap();
PickRay pickRay = qApp->getCamera().computePickRay(posMap["x"].toFloat(), posMap["y"].toFloat());
return PickParabola(pickRay.origin, getSpeed() * pickRay.direction, getAcceleration());
}
return PickParabola();
}

View file

@ -1,24 +0,0 @@
//
// Created by Sam Gondelman 7/2/2018
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_MouseParabolaPick_h
#define hifi_MouseParabolaPick_h
#include "ParabolaPick.h"
class MouseParabolaPick : public ParabolaPick {
public:
MouseParabolaPick(float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool scaleWithAvatar,
const PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
PickParabola getMathematicalPick() const override;
bool isMouse() const override { return true; }
};
#endif // hifi_MouseParabolaPick_h

View file

@ -1,29 +0,0 @@
//
// MouseRayPick.cpp
// interface/src/raypick
//
// Created by Sam Gondelman 7/19/2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "MouseRayPick.h"
#include "Application.h"
#include "display-plugins/CompositorHelper.h"
MouseRayPick::MouseRayPick(const PickFilter& filter, float maxDistance, bool enabled) :
RayPick(filter, maxDistance, enabled)
{
}
PickRay MouseRayPick::getMathematicalPick() const {
QVariant position = qApp->getApplicationCompositor().getReticleInterface()->getPosition();
if (position.isValid()) {
QVariantMap posMap = position.toMap();
return qApp->getCamera().computePickRay(posMap["x"].toFloat(), posMap["y"].toFloat());
}
return PickRay();
}

View file

@ -1,26 +0,0 @@
//
// MouseRayPick.h
// interface/src/raypick
//
// Created by Sam Gondelman 7/19/2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_MouseRayPick_h
#define hifi_MouseRayPick_h
#include "RayPick.h"
class MouseRayPick : public RayPick {
public:
MouseRayPick(const PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
PickRay getMathematicalPick() const override;
bool isMouse() const override { return true; }
};
#endif // hifi_MouseRayPick_h

View file

@ -15,6 +15,46 @@
#include "DependencyManager.h"
#include "PickManager.h"
ParabolaPick::ParabolaPick(const glm::vec3& position, const glm::vec3& direction, float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool rotateAccelerationWithParent, bool scaleWithParent, const PickFilter& filter, float maxDistance, bool enabled) :
Pick(PickParabola(position, speed * direction, accelerationAxis), filter, maxDistance, enabled),
_rotateAccelerationWithAvatar(rotateAccelerationWithAvatar),
_rotateAccelerationWithParent(rotateAccelerationWithParent),
_scaleWithParent(scaleWithParent),
_speed(speed) {
}
PickParabola ParabolaPick::getMathematicalPick() const {
if (!parentTransform) {
PickParabola mathPick = _mathPick;
if (_rotateAccelerationWithAvatar) {
mathPick.acceleration = DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * mathPick.acceleration;
}
return mathPick;
}
Transform currentParentTransform = parentTransform->getTransform();
glm::vec3 position = currentParentTransform.transform(_mathPick.origin);
glm::vec3 velocity = _mathPick.velocity;
if (_scaleWithParent) {
velocity = currentParentTransform.transformDirection(velocity);
} else {
glm::vec3 transformedVelocity = currentParentTransform.transformDirection(velocity);
velocity = glm::normalize(transformedVelocity) * _speed;
}
glm::vec3 acceleration = _mathPick.acceleration;
if (_scaleWithParent) {
acceleration *= currentParentTransform.getScale();
}
if (_rotateAccelerationWithAvatar) {
acceleration = DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * acceleration;
} else if (_rotateAccelerationWithParent) {
acceleration = currentParentTransform.getRotation() * acceleration;
}
return PickParabola(position, velocity, acceleration);
}
PickResultPointer ParabolaPick::getEntityIntersection(const PickParabola& pick) {
if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) {
bool precisionPicking = !(getFilter().doesPickCoarse() || DependencyManager::get<PickManager>()->getForceCoarsePicking());
@ -60,18 +100,6 @@ PickResultPointer ParabolaPick::getHUDIntersection(const PickParabola& pick) {
return std::make_shared<ParabolaPickResult>(pick.toVariantMap());
}
float ParabolaPick::getSpeed() const {
return (_scaleWithAvatar ? DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale() * _speed : _speed);
}
glm::vec3 ParabolaPick::getAcceleration() const {
float scale = (_scaleWithAvatar ? DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale() : 1.0f);
if (_rotateAccelerationWithAvatar) {
return scale * (DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * _accelerationAxis);
}
return scale * _accelerationAxis;
}
Transform ParabolaPick::getResultTransform() const {
PickResultPointer result = getPrevPickResult();
if (!result) {

View file

@ -74,9 +74,9 @@ public:
class ParabolaPick : public Pick<PickParabola> {
public:
ParabolaPick(float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool scaleWithAvatar, const PickFilter& filter, float maxDistance, bool enabled) :
Pick(filter, maxDistance, enabled), _speed(speed), _accelerationAxis(accelerationAxis), _rotateAccelerationWithAvatar(rotateAccelerationWithAvatar),
_scaleWithAvatar(scaleWithAvatar) {}
ParabolaPick(const glm::vec3& position, const glm::vec3& direction, float speed, const glm::vec3& acceleration, bool rotateAccelerationWithAvatar, bool rotateAccelerationWithParent, bool scaleWithParent, const PickFilter& filter, float maxDistance, bool enabled);
PickParabola getMathematicalPick() const override;
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared<ParabolaPickResult>(pickVariant); }
PickResultPointer getEntityIntersection(const PickParabola& pick) override;
@ -86,13 +86,11 @@ public:
Transform getResultTransform() const override;
protected:
float _speed;
glm::vec3 _accelerationAxis;
bool _rotateAccelerationWithAvatar;
bool _scaleWithAvatar;
float getSpeed() const;
glm::vec3 getAcceleration() const;
bool _rotateAccelerationWithParent;
bool _scaleWithParent;
// Cached magnitude of _mathPick.velocity
float _speed;
};
#endif // hifi_ParabolaPick_h

View file

@ -52,8 +52,7 @@ void ParabolaPointer::editRenderStatePath(const std::string& state, const QVaria
if (!pathMap.isEmpty()) {
enabled = true;
if (pathMap["color"].isValid()) {
bool valid;
color = toGlm(xColorFromVariant(pathMap["color"], valid));
color = toGlm(u8vec3FromVariant(pathMap["color"]));
}
if (pathMap["alpha"].isValid()) {
alpha = pathMap["alpha"].toFloat();
@ -204,9 +203,9 @@ void ParabolaPointer::RenderState::editParabola(const glm::vec3& color, float al
}
}
void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY,
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) {
StartEndRenderState::update(origin, end, surfaceNormal, scaleWithAvatar, distanceScaleEnd, centerEndY, faceAvatar, followNormal, followNormalStrength, distance, pickResult);
StartEndRenderState::update(origin, end, surfaceNormal, parentScale, distanceScaleEnd, centerEndY, faceAvatar, followNormal, followNormalStrength, distance, pickResult);
auto parabolaPickResult = std::static_pointer_cast<ParabolaPickResult>(pickResult);
if (parabolaPickResult && render::Item::isValidID(_pathID)) {
render::Transaction transaction;
@ -216,7 +215,7 @@ void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::ve
glm::vec3 velocity = parabola.velocity;
glm::vec3 acceleration = parabola.acceleration;
float parabolicDistance = distance > 0.0f ? distance : parabolaPickResult->parabolicDistance;
float width = scaleWithAvatar ? getPathWidth() * DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale() : getPathWidth();
float width = getPathWidth() * parentScale;
transaction.updateItem<ParabolaRenderItem>(_pathID, [origin, velocity, acceleration, parabolicDistance, width](ParabolaRenderItem& item) {
item.setVisible(true);
item.setOrigin(origin);
@ -250,8 +249,7 @@ std::shared_ptr<StartEndRenderState> ParabolaPointer::buildRenderState(const QVa
enabled = true;
QVariantMap pathMap = propMap["path"].toMap();
if (pathMap["color"].isValid()) {
bool valid;
color = toGlm(xColorFromVariant(pathMap["color"], valid));
color = toGlm(u8vec3FromVariant(pathMap["color"]));
}
if (pathMap["alpha"].isValid()) {

View file

@ -79,7 +79,7 @@ public:
};
RenderState() {}
RenderState(const OverlayID& startID, const OverlayID& endID, const glm::vec3& pathColor, float pathAlpha, float pathWidth,
RenderState(const OverlayID& startID, const OverlayID& endID, const glm::vec3& pathColor, float pathAlpha, float parentScale,
bool isVisibleInSecondaryCamera, bool drawInFront, bool pathEnabled);
void setPathWidth(float width) { _pathWidth = width; }
@ -87,7 +87,7 @@ public:
void cleanup() override;
void disable() override;
void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY,
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) override;
void editParabola(const glm::vec3& color, float alpha, float width, bool isVisibleInSecondaryCamera, bool drawInFront, bool enabled);

View file

@ -17,7 +17,7 @@
PathPointer::PathPointer(PickQuery::PickType type, const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
bool hover, const PointerTriggers& triggers, bool faceAvatar, bool followNormal, float followNormalStrength, bool centerEndY, bool lockEnd,
bool distanceScaleEnd, bool scaleWithAvatar, bool enabled) :
bool distanceScaleEnd, bool scaleWithParent, bool enabled) :
Pointer(DependencyManager::get<PickScriptingInterface>()->createPick(type, rayProps), enabled, hover),
_renderStates(renderStates),
_defaultRenderStates(defaultRenderStates),
@ -28,7 +28,7 @@ PathPointer::PathPointer(PickQuery::PickType type, const QVariant& rayProps, con
_centerEndY(centerEndY),
_lockEnd(lockEnd),
_distanceScaleEnd(distanceScaleEnd),
_scaleWithAvatar(scaleWithAvatar)
_scaleWithParent(scaleWithParent)
{
for (auto& state : _renderStates) {
if (!enabled || state.first != _currentRenderState) {
@ -146,12 +146,18 @@ void PathPointer::updateVisuals(const PickResultPointer& pickResult) {
IntersectionType type = getPickedObjectType(pickResult);
auto renderState = _renderStates.find(_currentRenderState);
auto defaultRenderState = _defaultRenderStates.find(_currentRenderState);
float parentScale = 1.0f;
if (_enabled && _scaleWithParent) {
glm::vec3 dimensions = DependencyManager::get<PickManager>()->getParentTransform(_pickUID).getScale();
parentScale = glm::max(glm::max(dimensions.x, dimensions.y), dimensions.z);
}
if (_enabled && !_currentRenderState.empty() && renderState != _renderStates.end() &&
(type != IntersectionType::NONE || _pathLength > 0.0f)) {
glm::vec3 origin = getPickOrigin(pickResult);
glm::vec3 end = getPickEnd(pickResult, _pathLength);
glm::vec3 surfaceNormal = getPickedObjectNormal(pickResult);
renderState->second->update(origin, end, surfaceNormal, _scaleWithAvatar, _distanceScaleEnd, _centerEndY, _faceAvatar,
renderState->second->update(origin, end, surfaceNormal, parentScale, _distanceScaleEnd, _centerEndY, _faceAvatar,
_followNormal, _followNormalStrength, _pathLength, pickResult);
if (defaultRenderState != _defaultRenderStates.end() && defaultRenderState->second.second->isEnabled()) {
defaultRenderState->second.second->disable();
@ -162,7 +168,7 @@ void PathPointer::updateVisuals(const PickResultPointer& pickResult) {
}
glm::vec3 origin = getPickOrigin(pickResult);
glm::vec3 end = getPickEnd(pickResult, defaultRenderState->second.first);
defaultRenderState->second.second->update(origin, end, Vectors::UP, _scaleWithAvatar, _distanceScaleEnd, _centerEndY,
defaultRenderState->second.second->update(origin, end, Vectors::UP, parentScale, _distanceScaleEnd, _centerEndY,
_faceAvatar, _followNormal, _followNormalStrength, defaultRenderState->second.first, pickResult);
} else if (!_currentRenderState.empty()) {
if (renderState != _renderStates.end() && renderState->second->isEnabled()) {
@ -281,15 +287,13 @@ void StartEndRenderState::disable() {
_enabled = false;
}
void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY,
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) {
if (!getStartID().isNull()) {
QVariantMap startProps;
startProps.insert("position", vec3toVariant(origin));
startProps.insert("visible", true);
if (scaleWithAvatar) {
startProps.insert("dimensions", vec3toVariant(getStartDim() * DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale()));
}
startProps.insert("dimensions", vec3toVariant(getStartDim() * parentScale));
startProps.insert("ignoreRayIntersection", doesStartIgnoreRays());
qApp->getOverlays().editOverlay(getStartID(), startProps);
}
@ -300,8 +304,8 @@ void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end,
if (distanceScaleEnd) {
dim = getEndDim() * glm::distance(origin, end);
endProps.insert("dimensions", vec3toVariant(dim));
} else if (scaleWithAvatar) {
dim = getEndDim() * DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale();
} else {
dim = getEndDim() * parentScale;
endProps.insert("dimensions", vec3toVariant(dim));
}

View file

@ -45,7 +45,7 @@ public:
virtual void cleanup();
virtual void disable();
virtual void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
virtual void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY,
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult);
bool isEnabled() const { return _enabled; }
@ -74,7 +74,7 @@ class PathPointer : public Pointer {
public:
PathPointer(PickQuery::PickType type, const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
bool hover, const PointerTriggers& triggers, bool faceAvatar, bool followNormal, float followNormalStrength, bool centerEndY, bool lockEnd,
bool distanceScaleEnd, bool scaleWithAvatar, bool enabled);
bool distanceScaleEnd, bool scaleWithParent, bool enabled);
virtual ~PathPointer();
void setRenderState(const std::string& state) override;
@ -98,7 +98,7 @@ protected:
bool _centerEndY;
bool _lockEnd;
bool _distanceScaleEnd;
bool _scaleWithAvatar;
bool _scaleWithParent;
LockEndObject _lockEndObject;
struct TriggerState {

View file

@ -14,13 +14,9 @@
#include "Application.h"
#include <PickManager.h>
#include "StaticRayPick.h"
#include "JointRayPick.h"
#include "MouseRayPick.h"
#include "RayPick.h"
#include "StylusPick.h"
#include "StaticParabolaPick.h"
#include "JointParabolaPick.h"
#include "MouseParabolaPick.h"
#include "ParabolaPick.h"
#include "CollisionPick.h"
#include "SpatialParentFinder.h"
@ -56,9 +52,9 @@ unsigned int PickScriptingInterface::createPick(const PickQuery::PickType type,
* @property {boolean} [enabled=false] If this Pick should start enabled or not. Disabled Picks do not updated their pick results.
* @property {number} [filter=Picks.PICK_NOTHING] The filter for this Pick to use, constructed using filter flags combined using bitwise OR.
* @property {number} [maxDistance=0.0] The max distance at which this Pick will intersect. 0.0 = no max. < 0.0 is invalid.
* @property {string} [joint] Only for Joint or Mouse Ray Picks. If "Mouse", it will create a Ray Pick that follows the system mouse, in desktop or HMD.
* If "Avatar", it will create a Joint Ray Pick that follows your avatar's head. Otherwise, it will create a Joint Ray Pick that follows the given joint, if it
* exists on your current avatar.
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick.
* @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint)
* @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar.
* @property {Vec3} [posOffset=Vec3.ZERO] Only for Joint Ray Picks. A local joint position offset, in meters. x = upward, y = forward, z = lateral
* @property {Vec3} [dirOffset=Vec3.UP] Only for Joint Ray Picks. A local joint direction offset. x = upward, y = forward, z = lateral
* @property {Vec3} [position] Only for Static Ray Picks. The world-space origin of the ray.
@ -82,38 +78,29 @@ unsigned int PickScriptingInterface::createRayPick(const QVariant& properties) {
maxDistance = propMap["maxDistance"].toFloat();
}
if (propMap["joint"].isValid()) {
std::string jointName = propMap["joint"].toString().toStdString();
if (jointName != "Mouse") {
// x = upward, y = forward, z = lateral
glm::vec3 posOffset = Vectors::ZERO;
if (propMap["posOffset"].isValid()) {
posOffset = vec3FromVariant(propMap["posOffset"]);
}
glm::vec3 dirOffset = Vectors::UP;
if (propMap["dirOffset"].isValid()) {
dirOffset = vec3FromVariant(propMap["dirOffset"]);
}
return DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, std::make_shared<JointRayPick>(jointName, posOffset, dirOffset, filter, maxDistance, enabled));
} else {
return DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, std::make_shared<MouseRayPick>(filter, maxDistance, enabled));
}
} else if (propMap["position"].isValid()) {
glm::vec3 position = vec3FromVariant(propMap["position"]);
glm::vec3 direction = -Vectors::UP;
if (propMap["direction"].isValid()) {
direction = vec3FromVariant(propMap["direction"]);
}
return DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, std::make_shared<StaticRayPick>(position, direction, filter, maxDistance, enabled));
glm::vec3 position = Vectors::ZERO;
if (propMap["position"].isValid()) {
position = vec3FromVariant(propMap["position"]);
} else if (propMap["posOffset"].isValid()) {
position = vec3FromVariant(propMap["posOffset"]);
}
return PickManager::INVALID_PICK_ID;
// direction has two defaults to ensure compatibility with older scripts
// Joint ray picks had default direction = Vec3.UP
// Static ray picks had default direction = -Vec3.UP
glm::vec3 direction = propMap["joint"].isValid() ? Vectors::UP : -Vectors::UP;
if (propMap["orientation"].isValid()) {
direction = quatFromVariant(propMap["orientation"]) * Vectors::UP;
} else if (propMap["direction"].isValid()) {
direction = vec3FromVariant(propMap["direction"]);
} else if (propMap["dirOffset"].isValid()) {
direction = vec3FromVariant(propMap["dirOffset"]);
}
auto rayPick = std::make_shared<RayPick>(position, direction, filter, maxDistance, enabled);
setParentTransform(rayPick, propMap);
return DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, rayPick);
}
/**jsdoc
@ -153,23 +140,25 @@ unsigned int PickScriptingInterface::createStylusPick(const QVariant& properties
return DependencyManager::get<PickManager>()->addPick(PickQuery::Stylus, std::make_shared<StylusPick>(side, filter, maxDistance, enabled));
}
// NOTE: Laser pointer still uses scaleWithAvatar. Until scaleWithAvatar is also deprecated for pointers, scaleWithAvatar should not be removed from the pick API.
/**jsdoc
* A set of properties that can be passed to {@link Picks.createPick} to create a new Parabola Pick.
* @typedef {object} Picks.ParabolaPickProperties
* @property {boolean} [enabled=false] If this Pick should start enabled or not. Disabled Picks do not updated their pick results.
* @property {number} [filter=Picks.PICK_NOTHING] The filter for this Pick to use, constructed using filter flags combined using bitwise OR.
* @property {number} [maxDistance=0.0] The max distance at which this Pick will intersect. 0.0 = no max. < 0.0 is invalid.
* @property {string} [joint] Only for Joint or Mouse Parabola Picks. If "Mouse", it will create a Parabola Pick that follows the system mouse, in desktop or HMD.
* If "Avatar", it will create a Joint Parabola Pick that follows your avatar's head. Otherwise, it will create a Joint Parabola Pick that follows the given joint, if it
* exists on your current avatar.
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick.
* @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint)
* @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar.
* @property {Vec3} [posOffset=Vec3.ZERO] Only for Joint Parabola Picks. A local joint position offset, in meters. x = upward, y = forward, z = lateral
* @property {Vec3} [dirOffset=Vec3.UP] Only for Joint Parabola Picks. A local joint direction offset. x = upward, y = forward, z = lateral
* @property {Vec3} [position] Only for Static Parabola Picks. The world-space origin of the parabola segment.
* @property {Vec3} [direction=-Vec3.FRONT] Only for Static Parabola Picks. The world-space direction of the parabola segment.
* @property {number} [speed=1] The initial speed of the parabola, i.e. the initial speed of the projectile whose trajectory defines the parabola.
* @property {Vec3} [accelerationAxis=-Vec3.UP] The acceleration of the parabola, i.e. the acceleration of the projectile whose trajectory defines the parabola, both magnitude and direction.
* @property {boolean} [rotateAccelerationWithAvatar=true] Whether or not the acceleration axis should rotate with your avatar's local Y axis.
* @property {boolean} [scaleWithAvatar=false] If true, the velocity and acceleration of the Pick will scale linearly with your avatar.
* @property {boolean} [rotateAccelerationWithAvatar=true] Whether or not the acceleration axis should rotate with the avatar's local Y axis.
* @property {boolean} [rotateAccelerationWithParent=false] Whether or not the acceleration axis should rotate with the parent's local Y axis, if available.
* @property {boolean} [scaleWithParent=true] If true, the velocity and acceleration of the Pick will scale linearly with the parent, if available. scaleWithAvatar is an alias but is deprecated.
*/
unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properties) {
QVariantMap propMap = properties.toMap();
@ -204,48 +193,37 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti
rotateAccelerationWithAvatar = propMap["rotateAccelerationWithAvatar"].toBool();
}
bool scaleWithAvatar = false;
if (propMap["scaleWithAvatar"].isValid()) {
scaleWithAvatar = propMap["scaleWithAvatar"].toBool();
bool rotateAccelerationWithParent = false;
if (propMap["rotateAccelerationWithParent"].isValid()) {
rotateAccelerationWithParent = propMap["rotateAccelerationWithParent"].toBool();
}
if (propMap["joint"].isValid()) {
std::string jointName = propMap["joint"].toString().toStdString();
if (jointName != "Mouse") {
// x = upward, y = forward, z = lateral
glm::vec3 posOffset = Vectors::ZERO;
if (propMap["posOffset"].isValid()) {
posOffset = vec3FromVariant(propMap["posOffset"]);
}
glm::vec3 dirOffset = Vectors::UP;
if (propMap["dirOffset"].isValid()) {
dirOffset = vec3FromVariant(propMap["dirOffset"]);
}
return DependencyManager::get<PickManager>()->addPick(PickQuery::Parabola, std::make_shared<JointParabolaPick>(jointName, posOffset, dirOffset,
speed, accelerationAxis, rotateAccelerationWithAvatar,
scaleWithAvatar, filter, maxDistance, enabled));
} else {
return DependencyManager::get<PickManager>()->addPick(PickQuery::Parabola, std::make_shared<MouseParabolaPick>(speed, accelerationAxis, rotateAccelerationWithAvatar,
scaleWithAvatar, filter, maxDistance, enabled));
}
} else if (propMap["position"].isValid()) {
glm::vec3 position = vec3FromVariant(propMap["position"]);
glm::vec3 direction = -Vectors::FRONT;
if (propMap["direction"].isValid()) {
direction = vec3FromVariant(propMap["direction"]);
}
return DependencyManager::get<PickManager>()->addPick(PickQuery::Parabola, std::make_shared<StaticParabolaPick>(position, direction, speed, accelerationAxis,
rotateAccelerationWithAvatar, scaleWithAvatar,
filter, maxDistance, enabled));
bool scaleWithParent = true;
if (propMap["scaleWithParent"].isValid()) {
scaleWithParent = propMap["scaleWithParent"].toBool();
} else if (propMap["scaleWithAvatar"].isValid()) {
scaleWithParent = propMap["scaleWithAvatar"].toBool();
}
return PickManager::INVALID_PICK_ID;
glm::vec3 position = Vectors::ZERO;
glm::vec3 direction = propMap["joint"].isValid() ? Vectors::UP : -Vectors::FRONT;
if (propMap["position"].isValid()) {
position = vec3FromVariant(propMap["position"]);
} else if (propMap["posOffset"].isValid()) {
position = vec3FromVariant(propMap["posOffset"]);
}
if (propMap["orientation"].isValid()) {
direction = quatFromVariant(propMap["orientation"]) * Vectors::UP;
} else if (propMap["direction"].isValid()) {
direction = vec3FromVariant(propMap["direction"]);
} else if (propMap["dirOffset"].isValid()) {
direction = vec3FromVariant(propMap["dirOffset"]);
}
auto parabolaPick = std::make_shared<ParabolaPick>(position, direction, speed, accelerationAxis,
rotateAccelerationWithAvatar, rotateAccelerationWithParent, scaleWithParent, filter, maxDistance, enabled);
setParentTransform(parabolaPick, propMap);
return DependencyManager::get<PickManager>()->addPick(PickQuery::Parabola, parabolaPick);
}
/**jsdoc
@ -272,9 +250,10 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti
* The depth is measured in world space, but will scale with the parent if defined.
* @property {CollisionMask} [collisionGroup=8] - The type of object this collision pick collides as. Objects whose collision masks overlap with the pick's collision group
* will be considered colliding with the pick.
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or an overlay.
* @property {number} parentJointIndex - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint)
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick.
* @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint)
* @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar.
* @property {boolean} [scaleWithParent=true] If true, the collision pick's dimensions and threshold will adjust according to the scale of the parent.
*/
unsigned int PickScriptingInterface::createCollisionPick(const QVariant& properties) {
QVariantMap propMap = properties.toMap();
@ -294,9 +273,14 @@ unsigned int PickScriptingInterface::createCollisionPick(const QVariant& propert
maxDistance = propMap["maxDistance"].toFloat();
}
bool scaleWithParent = true;
if (propMap["scaleWithParent"].isValid()) {
scaleWithParent = propMap["scaleWithParent"].toBool();
}
CollisionRegion collisionRegion(propMap);
auto collisionPick = std::make_shared<CollisionPick>(filter, maxDistance, enabled, collisionRegion, qApp->getPhysicsEngine());
collisionPick->parentTransform = createTransformNode(propMap);
auto collisionPick = std::make_shared<CollisionPick>(filter, maxDistance, enabled, scaleWithParent, collisionRegion, qApp->getPhysicsEngine());
setParentTransform(collisionPick, propMap);
return DependencyManager::get<PickManager>()->addPick(PickQuery::Collision, collisionPick);
}
@ -373,51 +357,63 @@ void PickScriptingInterface::setPerFrameTimeBudget(unsigned int numUsecs) {
DependencyManager::get<PickManager>()->setPerFrameTimeBudget(numUsecs);
}
std::shared_ptr<TransformNode> PickScriptingInterface::createTransformNode(const QVariantMap& propMap) {
if (propMap["parentID"].isValid()) {
QUuid parentUuid = propMap["parentID"].toUuid();
if (!parentUuid.isNull()) {
// Infer object type from parentID
// For now, assume a QUuuid is a SpatiallyNestable. This should change when picks are converted over to QUuids.
bool success;
std::weak_ptr<SpatiallyNestable> nestablePointer = DependencyManager::get<SpatialParentFinder>()->find(parentUuid, success, nullptr);
int parentJointIndex = 0;
if (propMap["parentJointIndex"].isValid()) {
parentJointIndex = propMap["parentJointIndex"].toInt();
}
auto sharedNestablePointer = nestablePointer.lock();
if (success && sharedNestablePointer) {
NestableType nestableType = sharedNestablePointer->getNestableType();
if (nestableType == NestableType::Avatar) {
return std::make_shared<AvatarTransformNode>(std::static_pointer_cast<Avatar>(sharedNestablePointer), parentJointIndex);
} else if (nestableType == NestableType::Overlay) {
return std::make_shared<OverlayTransformNode>(std::static_pointer_cast<Base3DOverlay>(sharedNestablePointer), parentJointIndex);
} else if (nestableType == NestableType::Entity) {
return std::make_shared<EntityTransformNode>(std::static_pointer_cast<EntityItem>(sharedNestablePointer), parentJointIndex);
} else {
return std::make_shared<NestableTransformNode>(nestablePointer, parentJointIndex);
}
}
}
void PickScriptingInterface::setParentTransform(std::shared_ptr<PickQuery> pick, const QVariantMap& propMap) {
QUuid parentUuid;
int parentJointIndex = 0;
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
unsigned int pickID = propMap["parentID"].toUInt();
if (pickID != 0) {
return std::make_shared<PickTransformNode>(pickID);
if (propMap["parentID"].isValid()) {
parentUuid = propMap["parentID"].toUuid();
if (propMap["parentJointIndex"].isValid()) {
parentJointIndex = propMap["parentJointIndex"].toInt();
}
}
if (propMap["joint"].isValid()) {
} else if (propMap["joint"].isValid()) {
QString joint = propMap["joint"].toString();
if (joint == "Mouse") {
return std::make_shared<MouseTransformNode>();
pick->parentTransform = std::make_shared<MouseTransformNode>();
pick->setJointState(PickQuery::JOINT_STATE_MOUSE);
return;
} else if (joint == "Avatar") {
return std::make_shared<MyAvatarHeadTransformNode>();
} else if (!joint.isNull()) {
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
int jointIndex = myAvatar->getJointIndex(joint);
return std::make_shared<AvatarTransformNode>(myAvatar, jointIndex);
pick->parentTransform = std::make_shared<MyAvatarHeadTransformNode>();
return;
} else {
parentUuid = myAvatar->getSessionUUID();
parentJointIndex = myAvatar->getJointIndex(joint);
}
}
return std::shared_ptr<TransformNode>();
if (parentUuid == myAvatar->getSessionUUID()) {
if (parentJointIndex == CONTROLLER_LEFTHAND_INDEX || parentJointIndex == CAMERA_RELATIVE_CONTROLLER_LEFTHAND_INDEX) {
pick->setJointState(PickQuery::JOINT_STATE_LEFT_HAND);
} else if (parentJointIndex == CONTROLLER_RIGHTHAND_INDEX || parentJointIndex == CAMERA_RELATIVE_CONTROLLER_RIGHTHAND_INDEX) {
pick->setJointState(PickQuery::JOINT_STATE_RIGHT_HAND);
}
pick->parentTransform = std::make_shared<AvatarTransformNode>(myAvatar, parentJointIndex);
} else if (!parentUuid.isNull()) {
// Infer object type from parentID
// For now, assume a QUuid is a SpatiallyNestable. This should change when picks are converted over to QUuids.
bool success;
std::weak_ptr<SpatiallyNestable> nestablePointer = DependencyManager::get<SpatialParentFinder>()->find(parentUuid, success, nullptr);
auto sharedNestablePointer = nestablePointer.lock();
if (success && sharedNestablePointer) {
NestableType nestableType = sharedNestablePointer->getNestableType();
if (nestableType == NestableType::Avatar) {
pick->parentTransform = std::make_shared<AvatarTransformNode>(std::static_pointer_cast<Avatar>(sharedNestablePointer), parentJointIndex);
} else if (nestableType == NestableType::Overlay) {
pick->parentTransform = std::make_shared<OverlayTransformNode>(std::static_pointer_cast<Base3DOverlay>(sharedNestablePointer), parentJointIndex);
} else if (nestableType == NestableType::Entity) {
pick->parentTransform = std::make_shared<EntityTransformNode>(std::static_pointer_cast<EntityItem>(sharedNestablePointer), parentJointIndex);
} else {
pick->parentTransform = std::make_shared<NestableTransformNode>(nestablePointer, parentJointIndex);
}
}
} else {
unsigned int pickID = propMap["parentID"].toUInt();
if (pickID != 0) {
pick->parentTransform = std::make_shared<PickTransformNode>(pickID);
}
}
}

View file

@ -320,7 +320,7 @@ public slots:
static constexpr unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; }
protected:
static std::shared_ptr<TransformNode> createTransformNode(const QVariantMap& propMap);
static void setParentTransform(std::shared_ptr<PickQuery> pick, const QVariantMap& propMap);
};
#endif // hifi_PickScriptingInterface_h

View file

@ -97,7 +97,7 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties)
* @property {boolean} [centerEndY=true] If false, the end of the Pointer will be moved up by half of its height.
* @property {boolean} [lockEnd=false] If true, the end of the Pointer will lock on to the center of the object at which the pointer is pointing.
* @property {boolean} [distanceScaleEnd=false] If true, the dimensions of the end of the Pointer will scale linearly with distance.
* @property {boolean} [scaleWithAvatar=false] If true, the width of the Pointer's path will scale linearly with your avatar's scale.
* @property {boolean} [scaleWithParent=false] If true, the width of the Pointer's path will scale linearly with the pick parent's scale. scaleWithAvatar is an alias but is deprecated.
* @property {boolean} [followNormal=false] If true, the end of the Pointer will rotate to follow the normal of the intersected surface.
* @property {number} [followNormalStrength=0.0] The strength of the interpolation between the real normal and the visual normal if followNormal is true. <code>0-1</code>. If 0 or 1,
* the normal will follow exactly.
@ -134,9 +134,11 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope
distanceScaleEnd = propertyMap["distanceScaleEnd"].toBool();
}
bool scaleWithAvatar = false;
if (propertyMap["scaleWithAvatar"].isValid()) {
scaleWithAvatar = propertyMap["scaleWithAvatar"].toBool();
bool scaleWithParent = false;
if (propertyMap["scaleWithParent"].isValid()) {
scaleWithParent = propertyMap["scaleWithParent"].toBool();
} else if (propertyMap["scaleWithAvatar"].isValid()) {
scaleWithParent = propertyMap["scaleWithAvatar"].toBool();
}
bool followNormal = false;
@ -207,7 +209,7 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope
return DependencyManager::get<PointerManager>()->addPointer(std::make_shared<LaserPointer>(properties, renderStates, defaultRenderStates, hover, triggers,
faceAvatar, followNormal, followNormalStrength, centerEndY, lockEnd,
distanceScaleEnd, scaleWithAvatar, enabled));
distanceScaleEnd, scaleWithParent, enabled));
}
/**jsdoc
@ -249,7 +251,7 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope
* @property {boolean} [centerEndY=true] If false, the end of the Pointer will be moved up by half of its height.
* @property {boolean} [lockEnd=false] If true, the end of the Pointer will lock on to the center of the object at which the pointer is pointing.
* @property {boolean} [distanceScaleEnd=false] If true, the dimensions of the end of the Pointer will scale linearly with distance.
* @property {boolean} [scaleWithAvatar=false] If true, the width of the Pointer's path will scale linearly with your avatar's scale.
* @property {boolean} [scaleWithParent=true] If true, the width of the Pointer's path will scale linearly with the pick parent's scale. scaleWithAvatar is an alias but is deprecated.
* @property {boolean} [followNormal=false] If true, the end of the Pointer will rotate to follow the normal of the intersected surface.
* @property {number} [followNormalStrength=0.0] The strength of the interpolation between the real normal and the visual normal if followNormal is true. <code>0-1</code>. If 0 or 1,
* the normal will follow exactly.
@ -286,9 +288,11 @@ unsigned int PointerScriptingInterface::createParabolaPointer(const QVariant& pr
distanceScaleEnd = propertyMap["distanceScaleEnd"].toBool();
}
bool scaleWithAvatar = false;
if (propertyMap["scaleWithAvatar"].isValid()) {
scaleWithAvatar = propertyMap["scaleWithAvatar"].toBool();
bool scaleWithParent = true;
if (propertyMap["scaleWithParent"].isValid()) {
scaleWithParent = propertyMap["scaleWithParent"].toBool();
} else if (propertyMap["scaleWithAvatar"].isValid()) {
scaleWithParent = propertyMap["scaleWithAvatar"].toBool();
}
bool followNormal = false;
@ -359,7 +363,7 @@ unsigned int PointerScriptingInterface::createParabolaPointer(const QVariant& pr
return DependencyManager::get<PointerManager>()->addPointer(std::make_shared<ParabolaPointer>(properties, renderStates, defaultRenderStates, hover, triggers,
faceAvatar, followNormal, followNormalStrength, centerEndY, lockEnd, distanceScaleEnd,
scaleWithAvatar, enabled));
scaleWithParent, enabled));
}
void PointerScriptingInterface::editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) const {

View file

@ -15,6 +15,17 @@
#include "DependencyManager.h"
#include "PickManager.h"
PickRay RayPick::getMathematicalPick() const {
if (!parentTransform) {
return _mathPick;
}
Transform currentParentTransform = parentTransform->getTransform();
glm::vec3 origin = currentParentTransform.transform(_mathPick.origin);
glm::vec3 direction = glm::normalize(currentParentTransform.transformDirection(_mathPick.direction));
return PickRay(origin, direction);
}
PickResultPointer RayPick::getEntityIntersection(const PickRay& pick) {
bool precisionPicking = !(getFilter().doesPickCoarse() || DependencyManager::get<PickManager>()->getForceCoarsePicking());
RayToEntityIntersectionResult entityRes =

View file

@ -70,7 +70,11 @@ public:
class RayPick : public Pick<PickRay> {
public:
RayPick(const PickFilter& filter, float maxDistance, bool enabled) : Pick(filter, maxDistance, enabled) {}
RayPick(glm::vec3 position, glm::vec3 direction, const PickFilter& filter, float maxDistance, bool enabled) :
Pick(PickRay(position, direction), filter, maxDistance, enabled) {
}
PickRay getMathematicalPick() const override;
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared<RayPickResult>(pickVariant); }
PickResultPointer getEntityIntersection(const PickRay& pick) override;

View file

@ -16,10 +16,6 @@
#include <PickManager.h>
#include "StaticRayPick.h"
#include "JointRayPick.h"
#include "MouseRayPick.h"
unsigned int RayPickScriptingInterface::createRayPick(const QVariant& properties) {
return DependencyManager::get<PickScriptingInterface>()->createRayPick(properties);
}

View file

@ -1,19 +0,0 @@
//
// Created by Sam Gondelman 7/2/2018
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "StaticParabolaPick.h"
StaticParabolaPick::StaticParabolaPick(const glm::vec3& position, const glm::vec3& direction, float speed, const glm::vec3& accelerationAxis,
bool scaleWithAvatar, bool rotateAccelerationWithAvatar, const PickFilter& filter, float maxDistance, bool enabled) :
ParabolaPick(speed, accelerationAxis, rotateAccelerationWithAvatar, scaleWithAvatar, filter, maxDistance, enabled),
_position(position), _velocity(direction)
{
}
PickParabola StaticParabolaPick::getMathematicalPick() const {
return PickParabola(_position, getSpeed() * _velocity, getAcceleration());
}

View file

@ -1,26 +0,0 @@
//
// Created by Sam Gondelman 7/2/2018
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_StaticParabolaPick_h
#define hifi_StaticParabolaPick_h
#include "ParabolaPick.h"
class StaticParabolaPick : public ParabolaPick {
public:
StaticParabolaPick(const glm::vec3& position, const glm::vec3& direction, float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar,
bool scaleWithAvatar, const PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
PickParabola getMathematicalPick() const override;
private:
glm::vec3 _position;
glm::vec3 _velocity;
};
#endif // hifi_StaticParabolaPick_h

View file

@ -1,18 +0,0 @@
//
// Created by Sam Gondelman 7/11/2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "StaticRayPick.h"
StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, float maxDistance, bool enabled) :
RayPick(filter, maxDistance, enabled),
_pickRay(position, direction)
{
}
PickRay StaticRayPick::getMathematicalPick() const {
return _pickRay;
}

View file

@ -1,25 +0,0 @@
//
// Created by Sam Gondelman 7/11/2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_StaticRayPick_h
#define hifi_StaticRayPick_h
#include "RayPick.h"
class StaticRayPick : public RayPick {
public:
StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
PickRay getMathematicalPick() const override;
private:
PickRay _pickRay;
};
#endif // hifi_StaticRayPick_h

View file

@ -65,8 +65,7 @@ bool StylusPickResult::checkOrFilterAgainstMaxDistance(float maxDistance) {
}
StylusPick::StylusPick(Side side, const PickFilter& filter, float maxDistance, bool enabled) :
Pick(filter, maxDistance, enabled),
_side(side)
Pick(StylusTip(side), filter, maxDistance, enabled)
{
}
@ -130,9 +129,9 @@ static StylusTip getControllerWorldLocation(Side side) {
StylusTip StylusPick::getMathematicalPick() const {
StylusTip result;
if (qApp->getPreferAvatarFingerOverStylus()) {
result = getFingerWorldLocation(_side);
result = getFingerWorldLocation(_mathPick.side);
} else {
result = getControllerWorldLocation(_side);
result = getControllerWorldLocation(_mathPick.side);
}
return result;
}

View file

@ -68,11 +68,9 @@ public:
PickResultPointer getHUDIntersection(const StylusTip& pick) override;
Transform getResultTransform() const override;
bool isLeftHand() const override { return _side == Side::Left; }
bool isRightHand() const override { return _side == Side::Right; }
private:
const Side _side;
bool isLeftHand() const override { return _mathPick.side == Side::Left; }
bool isRightHand() const override { return _mathPick.side == Side::Right; }
bool isMouse() const override { return false; }
};
#endif // hifi_StylusPick_h

View file

@ -421,7 +421,7 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
auto colorVariant = properties["outlineUnoccludedColor"];
if (colorVariant.isValid()) {
bool isValid;
auto color = xColorFromVariant(colorVariant, isValid);
auto color = u8vec3FromVariant(colorVariant, isValid);
if (isValid) {
_style._outlineUnoccluded.color = toGlm(color);
}
@ -429,7 +429,7 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
colorVariant = properties["outlineOccludedColor"];
if (colorVariant.isValid()) {
bool isValid;
auto color = xColorFromVariant(colorVariant, isValid);
auto color = u8vec3FromVariant(colorVariant, isValid);
if (isValid) {
_style._outlineOccluded.color = toGlm(color);
}
@ -437,7 +437,7 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
colorVariant = properties["fillUnoccludedColor"];
if (colorVariant.isValid()) {
bool isValid;
auto color = xColorFromVariant(colorVariant, isValid);
auto color = u8vec3FromVariant(colorVariant, isValid);
if (isValid) {
_style._fillUnoccluded.color = toGlm(color);
}
@ -445,7 +445,7 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
colorVariant = properties["fillOccludedColor"];
if (colorVariant.isValid()) {
bool isValid;
auto color = xColorFromVariant(colorVariant, isValid);
auto color = u8vec3FromVariant(colorVariant, isValid);
if (isValid) {
_style._fillOccluded.color = toGlm(color);
}
@ -497,10 +497,11 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
QVariantMap SelectionHighlightStyle::toVariantMap() const {
QVariantMap properties;
properties["outlineUnoccludedColor"] = xColorToVariant(xColorFromGlm(_style._outlineUnoccluded.color));
properties["outlineOccludedColor"] = xColorToVariant(xColorFromGlm(_style._outlineOccluded.color));
properties["fillUnoccludedColor"] = xColorToVariant(xColorFromGlm(_style._fillUnoccluded.color));
properties["fillOccludedColor"] = xColorToVariant(xColorFromGlm(_style._fillOccluded.color));
const float MAX_COLOR = 255.0f;
properties["outlineUnoccludedColor"] = u8vec3ColortoVariant(_style._outlineUnoccluded.color * MAX_COLOR);
properties["outlineOccludedColor"] = u8vec3ColortoVariant(_style._outlineOccluded.color * MAX_COLOR);
properties["fillUnoccludedColor"] = u8vec3ColortoVariant(_style._fillUnoccluded.color * MAX_COLOR);
properties["fillOccludedColor"] = u8vec3ColortoVariant(_style._fillOccluded.color * MAX_COLOR);
properties["outlineUnoccludedAlpha"] = _style._outlineUnoccluded.alpha;
properties["outlineOccludedAlpha"] = _style._outlineOccluded.alpha;

View file

@ -39,6 +39,7 @@ WindowScriptingInterface::WindowScriptingInterface() {
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &WindowScriptingInterface::disconnectedFromDomain);
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &WindowScriptingInterface::domainConnectionRefused);
connect(&domainHandler, &DomainHandler::redirectErrorStateChanged, this, &WindowScriptingInterface::redirectErrorStateChanged);
connect(qApp, &Application::svoImportRequested, [this](const QString& urlString) {
static const QMetaMethod svoImportRequestedSignal =

View file

@ -611,6 +611,14 @@ signals:
*/
void domainConnectionRefused(const QString& reasonMessage, int reasonCode, const QString& extraInfo);
/**jsdoc
* Triggered when you try to visit a domain but are redirected into the error state.
* @function Window.redirectErrorStateChanged
* @param {boolean} isInErrorState - If <code>true</code>, the user has been redirected to the error URL.
* @returns {Signal}
*/
void redirectErrorStateChanged(bool isInErrorState);
/**jsdoc
* Triggered when a still snapshot has been taken by calling {@link Window.takeSnapshot|takeSnapshot} with
* <code>includeAnimated = false</code> or {@link Window.takeSecondaryCameraSnapshot|takeSecondaryCameraSnapshot}.

View file

@ -267,8 +267,8 @@ void Stats::updateStats(bool force) {
auto loadingRequests = ResourceCache::getLoadingRequests();
STAT_UPDATE(downloads, loadingRequests.size());
STAT_UPDATE(downloadLimit, ResourceCache::getRequestLimit())
STAT_UPDATE(downloadsPending, ResourceCache::getPendingRequestCount());
STAT_UPDATE(downloadLimit, (int)ResourceCache::getRequestLimit())
STAT_UPDATE(downloadsPending, (int)ResourceCache::getPendingRequestCount());
STAT_UPDATE(processing, DependencyManager::get<StatTracker>()->getStat("Processing").toInt());
STAT_UPDATE(processingPending, DependencyManager::get<StatTracker>()->getStat("PendingProcessing").toInt());

View file

@ -191,8 +191,6 @@ void Base3DOverlay::setProperties(const QVariantMap& originalProperties) {
if (properties["parentID"].isValid()) {
setParentID(QUuid(properties["parentID"].toString()));
bool success;
getParentPointer(success); // call this to hook-up the parent's back-pointers to its child overlays
needRenderItemUpdate = true;
}
if (properties["parentJointIndex"].isValid()) {

View file

@ -75,7 +75,6 @@ void Circle3DOverlay::render(RenderArgs* args) {
const float FULL_CIRCLE = 360.0f;
const float SLICES = 180.0f; // The amount of segment to create the circle
const float SLICE_ANGLE_RADIANS = glm::radians(FULL_CIRCLE / SLICES);
const float MAX_COLOR = 255.0f;
auto geometryCache = DependencyManager::get<GeometryCache>();
@ -246,20 +245,15 @@ void Circle3DOverlay::render(RenderArgs* args) {
angle += tickMarkAngle;
}
}
xColor majorColorX = getMajorTickMarksColor();
glm::vec4 majorColor(majorColorX.red / MAX_COLOR, majorColorX.green / MAX_COLOR, majorColorX.blue / MAX_COLOR, alpha);
glm::vec4 majorColor(toGlm(getMajorTickMarksColor()), alpha);
geometryCache->updateVertices(_majorTicksVerticesID, majorPoints, majorColor);
xColor minorColorX = getMinorTickMarksColor();
glm::vec4 minorColor(minorColorX.red / MAX_COLOR, minorColorX.green / MAX_COLOR, minorColorX.blue / MAX_COLOR, alpha);
glm::vec4 minorColor(toGlm(getMinorTickMarksColor()), alpha);
geometryCache->updateVertices(_minorTicksVerticesID, minorPoints, minorColor);
}
geometryCache->renderVertices(batch, gpu::LINES, _majorTicksVerticesID);
geometryCache->renderVertices(batch, gpu::LINES, _minorTicksVerticesID);
}
}
@ -280,8 +274,8 @@ template<typename T> T fromVariant(const QVariant& v, bool& valid) {
return qvariant_cast<T>(v);
}
template<> xColor fromVariant(const QVariant& v, bool& valid) {
return xColorFromVariant(v, valid);
template<> glm::u8vec3 fromVariant(const QVariant& v, bool& valid) {
return u8vec3FromVariant(v, valid);
}
template<typename T>
@ -344,11 +338,11 @@ void Circle3DOverlay::setProperties(const QVariantMap& properties) {
_dirty |= updateIfValid(properties, "outerStartAlpha", _outerStartAlpha);
_dirty |= updateIfValid(properties, "outerEndAlpha", _outerEndAlpha);
_dirty |= updateIfValid<xColor>(properties, "color", { _innerStartColor, _innerEndColor, _outerStartColor, _outerEndColor });
_dirty |= updateIfValid<xColor>(properties, "startColor", { _innerStartColor, _outerStartColor } );
_dirty |= updateIfValid<xColor>(properties, "endColor", { _innerEndColor, _outerEndColor } );
_dirty |= updateIfValid<xColor>(properties, "innerColor", { _innerStartColor, _innerEndColor } );
_dirty |= updateIfValid<xColor>(properties, "outerColor", { _outerStartColor, _outerEndColor } );
_dirty |= updateIfValid<glm::u8vec3>(properties, "color", { _innerStartColor, _innerEndColor, _outerStartColor, _outerEndColor });
_dirty |= updateIfValid<glm::u8vec3>(properties, "startColor", { _innerStartColor, _outerStartColor } );
_dirty |= updateIfValid<glm::u8vec3>(properties, "endColor", { _innerEndColor, _outerEndColor } );
_dirty |= updateIfValid<glm::u8vec3>(properties, "innerColor", { _innerStartColor, _innerEndColor } );
_dirty |= updateIfValid<glm::u8vec3>(properties, "outerColor", { _outerStartColor, _outerEndColor } );
_dirty |= updateIfValid(properties, "innerStartColor", _innerStartColor);
_dirty |= updateIfValid(properties, "innerEndColor", _innerEndColor);
_dirty |= updateIfValid(properties, "outerStartColor", _outerStartColor);
@ -421,7 +415,7 @@ void Circle3DOverlay::setProperties(const QVariantMap& properties) {
* @property {number} endAt=360 - The counter-clockwise angle from the overlay's x-axis that drawing ends at, in degrees.
* @property {number} outerRadius=1 - The outer radius of the overlay, in meters. Synonym: <code>radius</code>.
* @property {number} innerRadius=0 - The inner radius of the overlay, in meters.
* @property {Color} color=255,255,255 - The color of the overlay. Setting this value also sets the values of
* @property {Color} color=255,255,255 - The color of the overlay. Setting this value also sets the values of
* <code>innerStartColor</code>, <code>innerEndColor</code>, <code>outerStartColor</code>, and <code>outerEndColor</code>.
* @property {Color} startColor - Sets the values of <code>innerStartColor</code> and <code>outerStartColor</code>.
* <em>Write-only.</em>
@ -478,16 +472,16 @@ QVariant Circle3DOverlay::getProperty(const QString& property) {
return _innerRadius;
}
if (property == "innerStartColor") {
return xColorToVariant(_innerStartColor);
return u8vec3ColortoVariant(_innerStartColor);
}
if (property == "innerEndColor") {
return xColorToVariant(_innerEndColor);
return u8vec3ColortoVariant(_innerEndColor);
}
if (property == "outerStartColor") {
return xColorToVariant(_outerStartColor);
return u8vec3ColortoVariant(_outerStartColor);
}
if (property == "outerEndColor") {
return xColorToVariant(_outerEndColor);
return u8vec3ColortoVariant(_outerEndColor);
}
if (property == "innerStartAlpha") {
return _innerStartAlpha;
@ -517,10 +511,10 @@ QVariant Circle3DOverlay::getProperty(const QString& property) {
return _minorTickMarksLength;
}
if (property == "majorTickMarksColor") {
return xColorToVariant(_majorTickMarksColor);
return u8vec3ColortoVariant(_majorTickMarksColor);
}
if (property == "minorTickMarksColor") {
return xColorToVariant(_minorTickMarksColor);
return u8vec3ColortoVariant(_minorTickMarksColor);
}
return Planar3DOverlay::getProperty(property);

View file

@ -39,8 +39,8 @@ public:
float getMinorTickMarksAngle() const { return _minorTickMarksAngle; }
float getMajorTickMarksLength() const { return _majorTickMarksLength; }
float getMinorTickMarksLength() const { return _minorTickMarksLength; }
xColor getMajorTickMarksColor() const { return _majorTickMarksColor; }
xColor getMinorTickMarksColor() const { return _minorTickMarksColor; }
glm::u8vec3 getMajorTickMarksColor() const { return _majorTickMarksColor; }
glm::u8vec3 getMinorTickMarksColor() const { return _minorTickMarksColor; }
void setStartAt(float value) { _startAt = value; }
void setEndAt(float value) { _endAt = value; }
@ -51,8 +51,8 @@ public:
void setMinorTickMarksAngle(float value) { _minorTickMarksAngle = value; }
void setMajorTickMarksLength(float value) { _majorTickMarksLength = value; }
void setMinorTickMarksLength(float value) { _minorTickMarksLength = value; }
void setMajorTickMarksColor(const xColor& value) { _majorTickMarksColor = value; }
void setMinorTickMarksColor(const xColor& value) { _minorTickMarksColor = value; }
void setMajorTickMarksColor(const glm::u8vec3& value) { _majorTickMarksColor = value; }
void setMinorTickMarksColor(const glm::u8vec3& value) { _minorTickMarksColor = value; }
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
@ -67,10 +67,10 @@ protected:
float _outerRadius { 1 };
float _innerRadius { 0 };
xColor _innerStartColor { DEFAULT_OVERLAY_COLOR };
xColor _innerEndColor { DEFAULT_OVERLAY_COLOR };
xColor _outerStartColor { DEFAULT_OVERLAY_COLOR };
xColor _outerEndColor { DEFAULT_OVERLAY_COLOR };
glm::u8vec3 _innerStartColor { DEFAULT_OVERLAY_COLOR };
glm::u8vec3 _innerEndColor { DEFAULT_OVERLAY_COLOR };
glm::u8vec3 _outerStartColor { DEFAULT_OVERLAY_COLOR };
glm::u8vec3 _outerEndColor { DEFAULT_OVERLAY_COLOR };
float _innerStartAlpha { DEFAULT_ALPHA };
float _innerEndAlpha { DEFAULT_ALPHA };
float _outerStartAlpha { DEFAULT_ALPHA };
@ -81,8 +81,8 @@ protected:
float _minorTickMarksAngle { 0 };
float _majorTickMarksLength { 0 };
float _minorTickMarksLength { 0 };
xColor _majorTickMarksColor { DEFAULT_OVERLAY_COLOR };
xColor _minorTickMarksColor { DEFAULT_OVERLAY_COLOR };
glm::u8vec3 _majorTickMarksColor { DEFAULT_OVERLAY_COLOR };
glm::u8vec3 _minorTickMarksColor { DEFAULT_OVERLAY_COLOR };
gpu::Primitive _solidPrimitive { gpu::TRIANGLE_FAN };
int _quadVerticesID { 0 };
int _lineVerticesID { 0 };

View file

@ -83,7 +83,7 @@ ContextOverlayInterface::ContextOverlayInterface() {
_challengeOwnershipTimeoutTimer.setSingleShot(true);
}
static const xColor CONTEXT_OVERLAY_COLOR = { 255, 255, 255 };
static const glm::u8vec3 CONTEXT_OVERLAY_COLOR = { 255, 255, 255 };
static const float CONTEXT_OVERLAY_INSIDE_DISTANCE = 1.0f; // in meters
static const float CONTEXT_OVERLAY_SIZE = 0.09f; // in meters, same x and y dims
static const float CONTEXT_OVERLAY_OFFSET_DISTANCE = 0.1f;
@ -142,14 +142,15 @@ bool ContextOverlayInterface::createOrDestroyContextOverlay(const EntityItemID&
glm::vec3 cameraPosition = qApp->getCamera().getPosition();
glm::vec3 entityDimensions = entityProperties.getDimensions();
glm::vec3 entityPosition = entityProperties.getPosition();
glm::vec3 registrationPoint = entityProperties.getRegistrationPoint();
glm::vec3 contextOverlayPosition = entityProperties.getPosition();
glm::vec2 contextOverlayDimensions;
// Update the position of the overlay if the registration point of the entity
// isn't default
if (entityProperties.getRegistrationPoint() != glm::vec3(0.5f)) {
glm::vec3 adjustPos = entityProperties.getRegistrationPoint() - glm::vec3(0.5f);
entityPosition = entityPosition - (entityProperties.getRotation() * (adjustPos * entityProperties.getDimensions()));
if (registrationPoint != glm::vec3(0.5f)) {
glm::vec3 adjustPos = registrationPoint - glm::vec3(0.5f);
entityPosition = entityPosition - (entityProperties.getRotation() * (adjustPos * entityDimensions));
}
enableEntityHighlight(entityItemID);

View file

@ -49,11 +49,8 @@ void Cube3DOverlay::render(RenderArgs* args) {
}
float alpha = getAlpha();
xColor color = getColor();
const float MAX_COLOR = 255.0f;
glm::vec4 cubeColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
glm::u8vec3 color = getColor();
glm::vec4 cubeColor(toGlm(color), alpha);
auto batch = args->_batch;
if (batch) {

View file

@ -57,11 +57,9 @@ void Grid3DOverlay::render(RenderArgs* args) {
return; // do nothing if we're not visible
}
const float MAX_COLOR = 255.0f;
float alpha = getAlpha();
xColor color = getColor();
glm::vec4 gridColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
glm::u8vec3 color = getColor();
glm::vec4 gridColor(toGlm(color), alpha);
auto batch = args->_batch;

View file

@ -107,17 +107,16 @@ void Image3DOverlay::render(RenderArgs* args) {
glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width() - 0.5f) / imageWidth,
(fromImage.y() + fromImage.height() - 0.5f) / imageHeight);
const float MAX_COLOR = 255.0f;
xColor color = getColor();
float alpha = getAlpha();
glm::u8vec3 color = getColor();
glm::vec4 imageColor(toGlm(color), alpha);
batch->setModelTransform(getRenderTransform());
batch->setResourceTexture(0, _texture->getGPUTexture());
DependencyManager::get<GeometryCache>()->renderQuad(
*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha),
_geometryId
imageColor, _geometryId
);
batch->setResourceTexture(0, nullptr); // restore default white color after me

View file

@ -128,9 +128,8 @@ void Line3DOverlay::render(RenderArgs* args) {
}
float alpha = getAlpha();
xColor color = getColor();
const float MAX_COLOR = 255.0f;
glm::vec4 colorv4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
glm::u8vec3 color = getColor();
glm::vec4 colorv4(toGlm(color), alpha);
auto batch = args->_batch;
if (batch) {
batch->setModelTransform(Transform());

View file

@ -15,7 +15,7 @@
#include "Application.h"
const xColor Overlay::DEFAULT_OVERLAY_COLOR = { 255, 255, 255 };
const glm::u8vec3 Overlay::DEFAULT_OVERLAY_COLOR = { 255, 255, 255 };
const float Overlay::DEFAULT_ALPHA = 0.7f;
Overlay::Overlay() :
@ -57,7 +57,7 @@ Overlay::~Overlay() {
void Overlay::setProperties(const QVariantMap& properties) {
bool valid;
auto color = xColorFromVariant(properties["color"], valid);
auto color = u8vec3FromVariant(properties["color"], valid);
if (valid) {
_color = color;
}
@ -116,7 +116,7 @@ QVariant Overlay::getProperty(const QString& property) {
return QVariant(getType());
}
if (property == "color") {
return xColorToVariant(_color);
return u8vec3ColortoVariant(_color);
}
if (property == "alpha") {
return _alpha;
@ -143,21 +143,21 @@ QVariant Overlay::getProperty(const QString& property) {
return QVariant();
}
xColor Overlay::getColor() {
glm::u8vec3 Overlay::getColor() {
if (_colorPulse == 0.0f) {
return _color;
}
float pulseLevel = updatePulse();
xColor result = _color;
glm::u8vec3 result = _color;
if (_colorPulse < 0.0f) {
result.red *= (1.0f - pulseLevel);
result.green *= (1.0f - pulseLevel);
result.blue *= (1.0f - pulseLevel);
result.x *= (1.0f - pulseLevel);
result.y *= (1.0f - pulseLevel);
result.z *= (1.0f - pulseLevel);
} else {
result.red *= pulseLevel;
result.green *= pulseLevel;
result.blue *= pulseLevel;
result.x *= pulseLevel;
result.y *= pulseLevel;
result.z *= pulseLevel;
}
return result;
}

View file

@ -11,8 +11,6 @@
#ifndef hifi_Overlay_h
#define hifi_Overlay_h
// include this before QGLWidget, which includes an earlier version of OpenGL
#include <SharedUtil.h> // for xColor
#include <render/Scene.h>
class OverlayID : public QUuid {
@ -59,7 +57,7 @@ public:
virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; };
virtual bool getIsVisibleInSecondaryCamera() const { return false; }
xColor getColor();
glm::u8vec3 getColor();
float getAlpha();
float getPulseMax() const { return _pulseMax; }
@ -73,7 +71,7 @@ public:
// setters
virtual void setVisible(bool visible) { _visible = visible; }
void setDrawHUDLayer(bool drawHUDLayer);
void setColor(const xColor& color) { _color = color; }
void setColor(const glm::u8vec3& color) { _color = color; }
void setAlpha(float alpha) { _alpha = alpha; }
void setPulseMax(float value) { _pulseMax = value; }
@ -115,12 +113,12 @@ protected:
float _alphaPulse; // ratio of the pulse to the alpha
float _colorPulse; // ratio of the pulse to the color
xColor _color;
glm::u8vec3 _color;
bool _visible; // should the overlay be drawn at all
unsigned int _stackOrder { 0 };
static const xColor DEFAULT_OVERLAY_COLOR;
static const glm::u8vec3 DEFAULT_OVERLAY_COLOR;
static const float DEFAULT_ALPHA;
std::unordered_map<std::string, graphics::MultiMaterial> _materials;

View file

@ -629,9 +629,9 @@ QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine,
obj.setProperty("distance", value.distance);
obj.setProperty("face", boxFaceToString(value.face));
QScriptValue intersection = vec3toScriptValue(engine, value.intersection);
QScriptValue intersection = vec3ToScriptValue(engine, value.intersection);
obj.setProperty("intersection", intersection);
QScriptValue surfaceNormal = vec3toScriptValue(engine, value.surfaceNormal);
QScriptValue surfaceNormal = vec3ToScriptValue(engine, value.surfaceNormal);
obj.setProperty("surfaceNormal", surfaceNormal);
obj.setProperty("extraInfo", engine->toScriptValue(value.extraInfo));
return obj;

View file

@ -64,7 +64,7 @@ void Planar3DOverlay::setProperties(const QVariantMap& properties) {
*/
QVariant Planar3DOverlay::getProperty(const QString& property) {
if (property == "dimensions" || property == "scale" || property == "size") {
return vec2toVariant(getDimensions());
return vec2ToVariant(getDimensions());
}
return Base3DOverlay::getProperty(property);

View file

@ -51,9 +51,8 @@ void Rectangle3DOverlay::render(RenderArgs* args) {
}
float alpha = getAlpha();
xColor color = getColor();
const float MAX_COLOR = 255.0f;
glm::vec4 rectangleColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
glm::u8vec3 color = getColor();
glm::vec4 rectangleColor(toGlm(color), alpha);
auto batch = args->_batch;
if (batch) {

View file

@ -30,9 +30,8 @@ void Shape3DOverlay::render(RenderArgs* args) {
}
float alpha = getAlpha();
xColor color = getColor();
const float MAX_COLOR = 255.0f;
glm::vec4 cubeColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
glm::u8vec3 color = getColor();
glm::vec4 shapeColor(toGlm(color), alpha);
auto batch = args->_batch;
if (batch) {
@ -44,9 +43,9 @@ void Shape3DOverlay::render(RenderArgs* args) {
batch->setModelTransform(getRenderTransform());
if (_isSolid) {
geometryCache->renderSolidShapeInstance(args, *batch, _shape, cubeColor, shapePipeline);
geometryCache->renderSolidShapeInstance(args, *batch, _shape, shapeColor, shapePipeline);
} else {
geometryCache->renderWireShapeInstance(args, *batch, _shape, cubeColor, shapePipeline);
geometryCache->renderWireShapeInstance(args, *batch, _shape, shapeColor, shapePipeline);
}
}
}

View file

@ -77,9 +77,8 @@ void Sphere3DOverlay::render(RenderArgs* args) {
}
float alpha = getAlpha();
xColor color = getColor();
const float MAX_COLOR = 255.0f;
glm::vec4 sphereColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
glm::u8vec3 color = getColor();
glm::vec4 sphereColor(toGlm(color), alpha);
auto batch = args->_batch;

View file

@ -64,21 +64,21 @@ void Text3DOverlay::setText(const QString& text) {
_text = text;
}
xColor Text3DOverlay::getBackgroundColor() {
glm::u8vec3 Text3DOverlay::getBackgroundColor() {
if (_colorPulse == 0.0f) {
return _backgroundColor;
}
float pulseLevel = updatePulse();
xColor result = _backgroundColor;
glm::u8vec3 result = _backgroundColor;
if (_colorPulse < 0.0f) {
result.red *= (1.0f - pulseLevel);
result.green *= (1.0f - pulseLevel);
result.blue *= (1.0f - pulseLevel);
result.x *= (1.0f - pulseLevel);
result.y *= (1.0f - pulseLevel);
result.z *= (1.0f - pulseLevel);
} else {
result.red *= pulseLevel;
result.green *= pulseLevel;
result.blue *= pulseLevel;
result.x *= pulseLevel;
result.y *= pulseLevel;
result.z *= pulseLevel;
}
return result;
}
@ -94,10 +94,8 @@ void Text3DOverlay::render(RenderArgs* args) {
auto transform = getRenderTransform();
batch.setModelTransform(transform);
const float MAX_COLOR = 255.0f;
xColor backgroundColor = getBackgroundColor();
glm::vec4 quadColor(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR,
backgroundColor.blue / MAX_COLOR, getBackgroundAlpha());
glm::u8vec3 backgroundColor = getBackgroundColor();
glm::vec4 quadColor(toGlm(backgroundColor), getBackgroundAlpha());
glm::vec2 dimensions = getDimensions();
glm::vec2 halfDimensions = dimensions * 0.5f;
@ -122,8 +120,7 @@ void Text3DOverlay::render(RenderArgs* args) {
transform.setScale(scaleFactor);
batch.setModelTransform(transform);
glm::vec4 textColor = { _color.red / MAX_COLOR, _color.green / MAX_COLOR,
_color.blue / MAX_COLOR, getTextAlpha() };
glm::vec4 textColor = { toGlm(_color), getTextAlpha() };
// FIXME: Factor out textRenderer so that Text3DOverlay overlay parts can be grouped by pipeline for a gpu performance increase.
_textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f), true);
@ -164,7 +161,7 @@ void Text3DOverlay::setProperties(const QVariantMap& properties) {
bool valid;
auto backgroundColor = properties["backgroundColor"];
if (backgroundColor.isValid()) {
auto color = xColorFromVariant(backgroundColor, valid);
auto color = u8vec3FromVariant(backgroundColor, valid);
if (valid) {
_backgroundColor = color;
}
@ -260,7 +257,7 @@ QVariant Text3DOverlay::getProperty(const QString& property) {
return _textAlpha;
}
if (property == "backgroundColor") {
return xColorToVariant(_backgroundColor);
return u8vec3ColortoVariant(_backgroundColor);
}
if (property == "backgroundAlpha") {
return Billboard3DOverlay::getProperty("alpha");

View file

@ -39,7 +39,7 @@ public:
float getTopMargin() const { return _topMargin; }
float getRightMargin() const { return _rightMargin; }
float getBottomMargin() const { return _bottomMargin; }
xColor getBackgroundColor();
glm::u8vec3 getBackgroundColor();
float getTextAlpha() { return _textAlpha; }
float getBackgroundAlpha() { return getAlpha(); }
bool isTransparent() override { return Overlay::isTransparent() || _textAlpha < 1.0f; }
@ -65,7 +65,7 @@ private:
QString _text;
mutable QMutex _mutex; // used to make get/setText threadsafe, mutable so can be used in const functions
xColor _backgroundColor = xColor { 0, 0, 0 };
glm::u8vec3 _backgroundColor { 0, 0, 0 };
float _textAlpha { 1.0f };
float _lineHeight { 1.0f };
float _leftMargin { 0.1f };

View file

@ -40,7 +40,7 @@ QScriptValue AnimVariantMap::animVariantMapToScriptValue(QScriptEngine* engine,
target.setProperty(name, value.getString());
break;
case AnimVariant::Type::Vec3:
target.setProperty(name, vec3toScriptValue(engine, value.getVec3()));
target.setProperty(name, vec3ToScriptValue(engine, value.getVec3()));
break;
case AnimVariant::Type::Quat:
target.setProperty(name, quatToScriptValue(engine, value.getQuat()));

View file

@ -32,12 +32,6 @@ AnimationCache::AnimationCache(QObject* parent) :
}
AnimationPointer AnimationCache::getAnimation(const QUrl& url) {
if (QThread::currentThread() != thread()) {
AnimationPointer result;
BLOCKING_INVOKE_METHOD(this, "getAnimation",
Q_RETURN_ARG(AnimationPointer, result), Q_ARG(const QUrl&, url));
return result;
}
return getResource(url).staticCast<Animation>();
}

View file

@ -34,7 +34,7 @@ AudioInjectorOptions::AudioInjectorOptions() :
QScriptValue injectorOptionsToScriptValue(QScriptEngine* engine, const AudioInjectorOptions& injectorOptions) {
QScriptValue obj = engine->newObject();
obj.setProperty("position", vec3toScriptValue(engine, injectorOptions.position));
obj.setProperty("position", vec3ToScriptValue(engine, injectorOptions.position));
obj.setProperty("volume", injectorOptions.volume);
obj.setProperty("loop", injectorOptions.loop);
obj.setProperty("orientation", quatToScriptValue(engine, injectorOptions.orientation));

View file

@ -30,12 +30,6 @@ SoundCache::SoundCache(QObject* parent) :
}
SharedSoundPointer SoundCache::getSound(const QUrl& url) {
if (QThread::currentThread() != thread()) {
SharedSoundPointer result;
BLOCKING_INVOKE_METHOD(this, "getSound",
Q_RETURN_ARG(SharedSoundPointer, result), Q_ARG(const QUrl&, url));
return result;
}
return getResource(url).staticCast<Sound>();
}

View file

@ -118,14 +118,24 @@ AvatarTransit::Status AvatarTransit::update(float deltaTime, const glm::vec3& av
float oneFrameDistance = glm::length(currentPosition - _lastPosition);
const float MAX_TRANSIT_DISTANCE = 30.0f;
float scaledMaxTransitDistance = MAX_TRANSIT_DISTANCE * _scale;
if (oneFrameDistance > config._triggerDistance && oneFrameDistance < scaledMaxTransitDistance && !_isTransiting) {
start(deltaTime, _lastPosition, currentPosition, config);
if (oneFrameDistance > config._triggerDistance && !_isTransiting) {
if (oneFrameDistance < scaledMaxTransitDistance) {
start(deltaTime, _lastPosition, currentPosition, config);
} else {
_lastPosition = currentPosition;
return Status::ABORT_TRANSIT;
}
}
_lastPosition = currentPosition;
_status = updatePosition(deltaTime);
return _status;
}
void AvatarTransit::reset() {
_lastPosition = _endPosition;
_currentPosition = _endPosition;
_isTransiting = false;
}
void AvatarTransit::start(float deltaTime, const glm::vec3& startPosition, const glm::vec3& endPosition, const AvatarTransit::TransitConfig& config) {
_startPosition = startPosition;
_endPosition = endPosition;
@ -510,9 +520,13 @@ void Avatar::relayJointDataToChildren() {
modelEntity->setLocalJointTranslation(jointIndex, jointTranslation);
}
}
Transform finalTransform;
Transform avatarTransform = _skeletonModel->getTransform();
avatarTransform.setScale(_skeletonModel->getScale());
modelEntity->setOverrideTransform(avatarTransform, _skeletonModel->getOffset());
Transform entityTransform = modelEntity->getLocalTransform();
Transform::mult(finalTransform, avatarTransform, entityTransform);
finalTransform.setScale(_skeletonModel->getScale());
modelEntity->setOverrideTransform(finalTransform, _skeletonModel->getOffset());
modelEntity->simulateRelayedJoints();
}
}

View file

@ -56,7 +56,8 @@ public:
IDLE = 0,
START_TRANSIT,
TRANSITING,
END_TRANSIT
END_TRANSIT,
ABORT_TRANSIT
};
enum EaseType {
@ -84,6 +85,7 @@ public:
glm::vec3 getEndPosition() { return _endPosition; }
float getTransitTime() { return _totalTime; }
void setScale(float scale) { _scale = scale; }
void reset();
private:
Status updatePosition(float deltaTime);

Some files were not shown because too many files have changed in this diff Show more