mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 12:17:45 +02:00
Merge branch 'master' into scriptvec3
This commit is contained in:
commit
67662df760
223 changed files with 3234 additions and 3165 deletions
|
@ -68,6 +68,7 @@ if (USE_GLES AND (NOT ANDROID))
|
||||||
set(DISABLE_QML_OPTION ON)
|
set(DISABLE_QML_OPTION ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
option(BUILD_CLIENT "Build client components" ${BUILD_CLIENT_OPTION})
|
option(BUILD_CLIENT "Build client components" ${BUILD_CLIENT_OPTION})
|
||||||
option(BUILD_SERVER "Build server components" ${BUILD_SERVER_OPTION})
|
option(BUILD_SERVER "Build server components" ${BUILD_SERVER_OPTION})
|
||||||
option(BUILD_TESTS "Build tests" ${BUILD_TESTS_OPTION})
|
option(BUILD_TESTS "Build tests" ${BUILD_TESTS_OPTION})
|
||||||
|
@ -162,7 +163,6 @@ if (BUILD_SERVER)
|
||||||
set_target_properties(domain-server PROPERTIES FOLDER "Apps")
|
set_target_properties(domain-server PROPERTIES FOLDER "Apps")
|
||||||
add_subdirectory(ice-server)
|
add_subdirectory(ice-server)
|
||||||
set_target_properties(ice-server PROPERTIES FOLDER "Apps")
|
set_target_properties(ice-server PROPERTIES FOLDER "Apps")
|
||||||
add_subdirectory(server-console)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (BUILD_CLIENT)
|
if (BUILD_CLIENT)
|
||||||
|
@ -174,6 +174,7 @@ endif()
|
||||||
|
|
||||||
if (BUILD_CLIENT OR BUILD_SERVER)
|
if (BUILD_CLIENT OR BUILD_SERVER)
|
||||||
add_subdirectory(plugins)
|
add_subdirectory(plugins)
|
||||||
|
add_subdirectory(server-console)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# BUILD_TOOLS option will be handled inside the tools's CMakeLists.txt because 'scribe' tool is required for build anyway
|
# BUILD_TOOLS option will be handled inside the tools's CMakeLists.txt because 'scribe' tool is required for build anyway
|
||||||
|
|
|
@ -7,6 +7,8 @@ target_bullet()
|
||||||
set(INTERFACE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../interface")
|
set(INTERFACE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../interface")
|
||||||
add_subdirectory("${INTERFACE_DIR}" "libraries/interface")
|
add_subdirectory("${INTERFACE_DIR}" "libraries/interface")
|
||||||
include_directories("${INTERFACE_DIR}/src")
|
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)
|
target_link_libraries(native-lib android log m interface)
|
||||||
|
|
||||||
|
|
|
@ -80,8 +80,10 @@ android {
|
||||||
if (Os.isFamily(Os.FAMILY_UNIX)) {
|
if (Os.isFamily(Os.FAMILY_UNIX)) {
|
||||||
def uploadDumpSymsTask = rootProject.getTasksByName("uploadBreakpadDumpSyms${variant.name.capitalize()}", false).first()
|
def uploadDumpSymsTask = rootProject.getTasksByName("uploadBreakpadDumpSyms${variant.name.capitalize()}", false).first()
|
||||||
def runDumpSymsTask = rootProject.getTasksByName("runBreakpadDumpSyms${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)
|
runDumpSymsTask.dependsOn(task)
|
||||||
variant.assemble.dependsOn(uploadDumpSymsTask)
|
variant.assemble.dependsOn(uploadDumpSymsTask)
|
||||||
|
variant.mergeResources.dependsOn(renameHifiACTask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,11 +143,9 @@ def packages = [
|
||||||
includeLibs: ['libtbb.so', 'libtbbmalloc.so'],
|
includeLibs: ['libtbb.so', 'libtbbmalloc.so'],
|
||||||
],
|
],
|
||||||
hifiAC: [
|
hifiAC: [
|
||||||
file: 'libplugins_libhifiCodec.zip',
|
baseUrl: 'http://s3.amazonaws.com/hifi-public/dependencies/',
|
||||||
versionId: 'i31pW.qNbvFOXRxbyiJUxg3sphaFNmZU',
|
file: 'codecSDK-android_armv8-2.0.zip',
|
||||||
checksum: '9412a8e12c88a4096c1fc843bb9fe52d',
|
checksum: '1cbef929675818fc64c4101b72f84a6a'
|
||||||
sharedLibFolder: '',
|
|
||||||
includeLibs: ['libplugins_libhifiCodec.so']
|
|
||||||
],
|
],
|
||||||
etc2comp: [
|
etc2comp: [
|
||||||
file: 'etc2comp-patched-armv8-libcpp.tgz',
|
file: 'etc2comp-patched-armv8-libcpp.tgz',
|
||||||
|
@ -367,7 +365,8 @@ task downloadDependencies {
|
||||||
doLast {
|
doLast {
|
||||||
packages.each { entry ->
|
packages.each { entry ->
|
||||||
def filename = entry.value['file'];
|
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')) {
|
if (entry.value.containsKey('versionId')) {
|
||||||
url = url + '?versionId=' + entry.value['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.
|
// FIXME this code is prototyping the desired functionality for doing build time binary dependency resolution.
|
||||||
// See the comment on the qtBundle task above
|
// See the comment on the qtBundle task above
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -112,6 +112,11 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message,
|
||||||
AvatarTraits::TraitWireSize traitSize;
|
AvatarTraits::TraitWireSize traitSize;
|
||||||
message.readPrimitive(&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]) {
|
if (packetTraitVersion > _lastReceivedTraitVersions[traitType]) {
|
||||||
_avatar->processTrait(traitType, message.read(traitSize));
|
_avatar->processTrait(traitType, message.read(traitSize));
|
||||||
_lastReceivedTraitVersions[traitType] = packetTraitVersion;
|
_lastReceivedTraitVersions[traitType] = packetTraitVersion;
|
||||||
|
@ -128,26 +133,41 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message,
|
||||||
} else {
|
} else {
|
||||||
AvatarTraits::TraitInstanceID instanceID = QUuid::fromRfc4122(message.readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
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;
|
AvatarTraits::TraitWireSize traitSize;
|
||||||
message.readPrimitive(&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 (traitType == AvatarTraits::AvatarEntity) {
|
||||||
if (traitSize == AvatarTraits::DELETED_TRAIT_SIZE) {
|
auto& instanceVersionRef = _lastReceivedTraitVersions.getInstanceValueRef(traitType, instanceID);
|
||||||
_avatar->processDeletedTraitInstance(traitType, instanceID);
|
|
||||||
|
|
||||||
// to track a deleted instance but keep version information
|
if (packetTraitVersion > instanceVersionRef) {
|
||||||
// the avatar mixer uses the negative value of the sent version
|
if (traitSize == AvatarTraits::DELETED_TRAIT_SIZE) {
|
||||||
instanceVersionRef = -packetTraitVersion;
|
_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 {
|
} else {
|
||||||
_avatar->processTraitInstance(traitType, instanceID, message.read(traitSize));
|
message.seek(message.getPosition() + traitSize);
|
||||||
instanceVersionRef = packetTraitVersion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
anyTraitsChanged = true;
|
|
||||||
} else {
|
} else {
|
||||||
message.seek(message.getPosition() + traitSize);
|
qWarning() << "Refusing to process traits packet with instanced trait of unprocessable type from" << message.getSenderSockAddr();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,6 +152,7 @@ qint64 AvatarMixerSlave::addChangedTraitsToBulkPacket(AvatarMixerClientData* lis
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!isDeleted && (sentInstanceIt == sentIDValuePairs.end() || receivedVersion > sentInstanceIt->value)) {
|
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
|
// 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);
|
bytesWritten += sendingAvatar->packTraitInstance(traitType, instanceID, traitsPacketList, receivedVersion);
|
||||||
|
|
||||||
|
@ -161,6 +162,7 @@ qint64 AvatarMixerSlave::addChangedTraitsToBulkPacket(AvatarMixerClientData* lis
|
||||||
sentIDValuePairs.emplace_back(instanceID, receivedVersion);
|
sentIDValuePairs.emplace_back(instanceID, receivedVersion);
|
||||||
}
|
}
|
||||||
} else if (isDeleted && sentInstanceIt != sentIDValuePairs.end() && absoluteReceivedVersion > sentInstanceIt->value) {
|
} 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
|
// this instance version was deleted and we haven't sent the delete to this client yet
|
||||||
bytesWritten += AvatarTraits::packInstancedTraitDelete(traitType, instanceID, traitsPacketList, absoluteReceivedVersion);
|
bytesWritten += AvatarTraits::packInstancedTraitDelete(traitType, instanceID, traitsPacketList, absoluteReceivedVersion);
|
||||||
|
|
||||||
|
@ -180,6 +182,7 @@ qint64 AvatarMixerSlave::addChangedTraitsToBulkPacket(AvatarMixerClientData* lis
|
||||||
listeningNodeData->setLastOtherAvatarTraitsSendPoint(otherNodeLocalID, timeOfLastTraitsChange);
|
listeningNodeData->setLastOtherAvatarTraitsSendPoint(otherNodeLocalID, timeOfLastTraitsChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return bytesWritten;
|
return bytesWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,8 +66,8 @@ macro(install_beside_console)
|
||||||
install(CODE "
|
install(CODE "
|
||||||
set(MACOSX_BUNDLE_EXECUTABLE_NAME domain-server)
|
set(MACOSX_BUNDLE_EXECUTABLE_NAME domain-server)
|
||||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER com.highfidelity.server-components)
|
set(MACOSX_BUNDLE_GUI_IDENTIFIER com.highfidelity.server-components)
|
||||||
set(MACOSX_BUNDLE_BUNDLE_NAME Sandbox\\ Components)
|
set(MACOSX_BUNDLE_BUNDLE_NAME Console\\ Components)
|
||||||
configure_file(${HF_CMAKE_DIR}/templates/MacOSXBundleSandboxComponentsInfo.plist.in ${ESCAPED_BUNDLE_NAME}/Contents/Info.plist)
|
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})"
|
execute_process(COMMAND ${MACDEPLOYQT_COMMAND} ${ESCAPED_BUNDLE_NAME} -verbose=2 -executable=${ESCAPED_EXECUTABLE_NAME})"
|
||||||
COMPONENT ${SERVER_COMPONENT}
|
COMPONENT ${SERVER_COMPONENT}
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,7 +18,7 @@ macro(SET_PACKAGING_PARAMETERS)
|
||||||
set(BUILD_GLOBAL_SERVICES "DEVELOPMENT")
|
set(BUILD_GLOBAL_SERVICES "DEVELOPMENT")
|
||||||
set(USE_STABLE_GLOBAL_SERVICES 0)
|
set(USE_STABLE_GLOBAL_SERVICES 0)
|
||||||
set(BUILD_NUMBER 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_TYPE RELEASE_TYPE "DEV")
|
||||||
set_from_env(RELEASE_NUMBER RELEASE_NUMBER "")
|
set_from_env(RELEASE_NUMBER RELEASE_NUMBER "")
|
||||||
|
@ -37,6 +37,7 @@ macro(SET_PACKAGING_PARAMETERS)
|
||||||
set(BUILD_VERSION ${RELEASE_NUMBER})
|
set(BUILD_VERSION ${RELEASE_NUMBER})
|
||||||
set(BUILD_ORGANIZATION "High Fidelity")
|
set(BUILD_ORGANIZATION "High Fidelity")
|
||||||
set(HIGH_FIDELITY_PROTOCOL "hifi")
|
set(HIGH_FIDELITY_PROTOCOL "hifi")
|
||||||
|
set(HIGH_FIDELITY_APP_PROTOCOL "hifiapp")
|
||||||
set(INTERFACE_BUNDLE_NAME "Interface")
|
set(INTERFACE_BUNDLE_NAME "Interface")
|
||||||
set(INTERFACE_ICON_PREFIX "interface")
|
set(INTERFACE_ICON_PREFIX "interface")
|
||||||
|
|
||||||
|
@ -142,7 +143,12 @@ macro(SET_PACKAGING_PARAMETERS)
|
||||||
set(CONSOLE_INSTALL_DIR ${DMG_SUBFOLDER_NAME})
|
set(CONSOLE_INSTALL_DIR ${DMG_SUBFOLDER_NAME})
|
||||||
set(INTERFACE_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_INSTALL_APP_PATH "${CONSOLE_INSTALL_DIR}/${CONSOLE_EXEC_NAME}")
|
||||||
|
|
||||||
set(CONSOLE_APP_CONTENTS "${CONSOLE_INSTALL_APP_PATH}/Contents")
|
set(CONSOLE_APP_CONTENTS "${CONSOLE_INSTALL_APP_PATH}/Contents")
|
||||||
|
@ -176,16 +182,19 @@ macro(SET_PACKAGING_PARAMETERS)
|
||||||
# shortcut names
|
# shortcut names
|
||||||
if (PRODUCTION_BUILD)
|
if (PRODUCTION_BUILD)
|
||||||
set(INTERFACE_SHORTCUT_NAME "High Fidelity Interface")
|
set(INTERFACE_SHORTCUT_NAME "High Fidelity Interface")
|
||||||
set(CONSOLE_SHORTCUT_NAME "Sandbox")
|
set(CONSOLE_SHORTCUT_NAME "Console")
|
||||||
set(APP_USER_MODEL_ID "com.highfidelity.sandbox")
|
set(SANDBOX_SHORTCUT_NAME "Sandbox")
|
||||||
|
set(APP_USER_MODEL_ID "com.highfidelity.console")
|
||||||
else ()
|
else ()
|
||||||
set(INTERFACE_SHORTCUT_NAME "High Fidelity Interface - ${BUILD_VERSION_NO_SHA}")
|
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 ()
|
endif ()
|
||||||
|
|
||||||
set(INTERFACE_HF_SHORTCUT_NAME "${INTERFACE_SHORTCUT_NAME}")
|
set(INTERFACE_HF_SHORTCUT_NAME "${INTERFACE_SHORTCUT_NAME}")
|
||||||
set(CONSOLE_HF_SHORTCUT_NAME "High Fidelity ${CONSOLE_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_INTERFACE_SHORTCUT_NAME "High Fidelity")
|
||||||
set(PRE_SANDBOX_CONSOLE_SHORTCUT_NAME "Server Console")
|
set(PRE_SANDBOX_CONSOLE_SHORTCUT_NAME "Server Console")
|
||||||
|
|
||||||
|
|
22
cmake/macros/TargetHifiAudioCodec.cmake
Normal file
22
cmake/macros/TargetHifiAudioCodec.cmake
Normal 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()
|
|
@ -42,6 +42,14 @@
|
||||||
<string>hifi</string>
|
<string>hifi</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleURLName</key>
|
||||||
|
<string>${MACOSX_BUNDLE_BUNDLE_NAME} APP URL</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>hifiapp</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>NSHighResolutionCapable</key>
|
<key>NSHighResolutionCapable</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
|
|
@ -13,10 +13,12 @@ set(INTERFACE_DISPLAY_NAME "Interface")
|
||||||
set(INTERFACE_SHORTCUT_NAME "@INTERFACE_SHORTCUT_NAME@")
|
set(INTERFACE_SHORTCUT_NAME "@INTERFACE_SHORTCUT_NAME@")
|
||||||
set(INTERFACE_HF_SHORTCUT_NAME "@INTERFACE_HF_SHORTCUT_NAME@")
|
set(INTERFACE_HF_SHORTCUT_NAME "@INTERFACE_HF_SHORTCUT_NAME@")
|
||||||
set(INTERFACE_WIN_EXEC_NAME "@INTERFACE_EXEC_PREFIX@.exe")
|
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_INSTALL_SUBDIR "@CONSOLE_INSTALL_DIR@")
|
||||||
set(CONSOLE_SHORTCUT_NAME "@CONSOLE_SHORTCUT_NAME@")
|
set(CONSOLE_SHORTCUT_NAME "@CONSOLE_SHORTCUT_NAME@")
|
||||||
set(CONSOLE_HF_SHORTCUT_NAME "@CONSOLE_HF_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(CONSOLE_WIN_EXEC_NAME "@CONSOLE_EXEC_NAME@")
|
||||||
set(PRE_SANDBOX_INTERFACE_SHORTCUT_NAME "@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@")
|
set(PRE_SANDBOX_INTERFACE_SHORTCUT_NAME "@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@")
|
||||||
set(PRE_SANDBOX_CONSOLE_SHORTCUT_NAME "@PRE_SANDBOX_CONSOLE_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_DISPLAY_NAME "Assignment Client")
|
||||||
set(AC_EXEC_NAME "@AC_EXEC_NAME@")
|
set(AC_EXEC_NAME "@AC_EXEC_NAME@")
|
||||||
set(HIGH_FIDELITY_PROTOCOL "@HIGH_FIDELITY_PROTOCOL@")
|
set(HIGH_FIDELITY_PROTOCOL "@HIGH_FIDELITY_PROTOCOL@")
|
||||||
|
set(HIGH_FIDELITY_APP_PROTOCOL "@HIGH_FIDELITY_APP_PROTOCOL@")
|
||||||
set(PRODUCTION_BUILD "@PRODUCTION_BUILD@")
|
set(PRODUCTION_BUILD "@PRODUCTION_BUILD@")
|
||||||
set(PR_BUILD "@PR_BUILD@")
|
set(PR_BUILD "@PR_BUILD@")
|
||||||
set(BUILD_ORGANIZATION "@BUILD_ORGANIZATION@")
|
set(BUILD_ORGANIZATION "@BUILD_ORGANIZATION@")
|
||||||
|
|
|
@ -405,6 +405,14 @@ Var GAClientID
|
||||||
Section "-Previous Install Cleanup"
|
Section "-Previous Install Cleanup"
|
||||||
; Remove the resources folder so we don't end up including removed QML files
|
; Remove the resources folder so we don't end up including removed QML files
|
||||||
RMDir /r "$INSTDIR\resources"
|
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
|
SectionEnd
|
||||||
|
|
||||||
@CPACK_NSIS_INSTALLATION_TYPES@
|
@CPACK_NSIS_INSTALLATION_TYPES@
|
||||||
|
@ -532,9 +540,9 @@ SectionEnd
|
||||||
|
|
||||||
Var PostInstallDialog
|
Var PostInstallDialog
|
||||||
Var DesktopClientCheckbox
|
Var DesktopClientCheckbox
|
||||||
Var DesktopServerCheckbox
|
Var DesktopConsoleCheckbox
|
||||||
Var ServerStartupCheckbox
|
Var ConsoleStartupCheckbox
|
||||||
Var LaunchServerNowCheckbox
|
Var LaunchConsoleNowCheckbox
|
||||||
Var LaunchClientNowCheckbox
|
Var LaunchClientNowCheckbox
|
||||||
Var CleanInstallCheckbox
|
Var CleanInstallCheckbox
|
||||||
Var CurrentOffset
|
Var CurrentOffset
|
||||||
|
@ -747,32 +755,20 @@ Function PostInstallOptionsPage
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
${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@"
|
${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}
|
${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@
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @INTERFACE_HF_SHORTCUT_NAME@ after install"
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @INTERFACE_HF_SHORTCUT_NAME@ after install"
|
||||||
Pop $LaunchClientNowCheckbox
|
Pop $LaunchClientNowCheckbox
|
||||||
IntOp $CurrentOffset $CurrentOffset + 30
|
IntOp $CurrentOffset $CurrentOffset + 15
|
||||||
|
|
||||||
; set the checkbox state depending on what is present in the registry
|
; set the checkbox state depending on what is present in the registry
|
||||||
!insertmacro SetInstallOption $LaunchClientNowCheckbox @CLIENT_LAUNCH_NOW_REG_KEY@ ${BST_CHECKED}
|
!insertmacro SetInstallOption $LaunchClientNowCheckbox @CLIENT_LAUNCH_NOW_REG_KEY@ ${BST_CHECKED}
|
||||||
|
@ -783,27 +779,44 @@ Function PostInstallOptionsPage
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ on startup"
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @SANDBOX_HF_SHORTCUT_NAME@ after install"
|
||||||
Pop $ServerStartupCheckbox
|
${Else}
|
||||||
IntOp $CurrentOffset $CurrentOffset + 15
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ after install"
|
||||||
|
|
||||||
; set the checkbox state depending on what is present in the registry
|
|
||||||
!insertmacro SetInstallOption $ServerStartupCheckbox @CONSOLE_STARTUP_REG_KEY@ ${BST_CHECKED}
|
|
||||||
${EndIf}
|
${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)"
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Perform a clean install (Delete older settings and content)"
|
||||||
Pop $CleanInstallCheckbox
|
Pop $CleanInstallCheckbox
|
||||||
IntOp $CurrentOffset $CurrentOffset + 15
|
IntOp $CurrentOffset $CurrentOffset + 15
|
||||||
|
|
||||||
${If} @PR_BUILD@ == 1
|
${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@
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
${NSD_SetState} $DesktopClientCheckbox ${BST_UNCHECKED}
|
${NSD_SetState} $DesktopClientCheckbox ${BST_UNCHECKED}
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
${NSD_SetState} $DesktopServerCheckbox ${BST_UNCHECKED}
|
${NSD_SetState} $DesktopConsoleCheckbox ${BST_UNCHECKED}
|
||||||
${NSD_SetState} $ServerStartupCheckbox ${BST_UNCHECKED}
|
${NSD_SetState} $ConsoleStartupCheckbox ${BST_UNCHECKED}
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
; push the offset
|
; push the offset
|
||||||
|
@ -824,9 +837,9 @@ FunctionEnd
|
||||||
!macroend
|
!macroend
|
||||||
|
|
||||||
Var DesktopClientState
|
Var DesktopClientState
|
||||||
Var DesktopServerState
|
Var DesktopConsoleState
|
||||||
Var ServerStartupState
|
Var ConsoleStartupState
|
||||||
Var LaunchServerNowState
|
Var LaunchConsoleNowState
|
||||||
Var LaunchClientNowState
|
Var LaunchClientNowState
|
||||||
Var CopyFromProductionState
|
Var CopyFromProductionState
|
||||||
Var CleanInstallState
|
Var CleanInstallState
|
||||||
|
@ -842,11 +855,11 @@ Function ReadInstallTypes
|
||||||
StrCpy $Express "1"
|
StrCpy $Express "1"
|
||||||
|
|
||||||
StrCpy $DesktopClientState ${BST_CHECKED}
|
StrCpy $DesktopClientState ${BST_CHECKED}
|
||||||
StrCpy $ServerStartupState ${BST_CHECKED}
|
StrCpy $ConsoleStartupState ${BST_CHECKED}
|
||||||
StrCpy $LaunchServerNowState ${BST_CHECKED}
|
StrCpy $LaunchConsoleNowState ${BST_CHECKED}
|
||||||
StrCpy $LaunchClientNowState ${BST_CHECKED}
|
StrCpy $LaunchClientNowState ${BST_CHECKED}
|
||||||
StrCpy $CleanInstallState ${BST_UNCHECKED}
|
StrCpy $CleanInstallState ${BST_UNCHECKED}
|
||||||
StrCpy $DesktopServerState ${BST_UNCHECKED}
|
StrCpy $DesktopConsoleState ${BST_UNCHECKED}
|
||||||
|
|
||||||
${If} @PR_BUILD@ == 1
|
${If} @PR_BUILD@ == 1
|
||||||
StrCpy $CopyFromProductionState ${BST_UNCHECKED}
|
StrCpy $CopyFromProductionState ${BST_UNCHECKED}
|
||||||
|
@ -860,28 +873,25 @@ Function ReadInstallTypes
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|
||||||
Function ReadPostInstallOptions
|
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@
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
; check if the user asked for a desktop shortcut to High Fidelity
|
; check if the user asked for a desktop shortcut to High Fidelity
|
||||||
${NSD_GetState} $DesktopClientCheckbox $DesktopClientState
|
${NSD_GetState} $DesktopClientCheckbox $DesktopClientState
|
||||||
${EndIf}
|
${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
|
${If} @PR_BUILD@ == 1
|
||||||
; check if we need to copy settings/content from production for this PR build
|
; check if we need to copy settings/content from production for this PR build
|
||||||
${NSD_GetState} $CopyFromProductionCheckbox $CopyFromProductionState
|
${NSD_GetState} $CopyFromProductionCheckbox $CopyFromProductionState
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
; check if we need to launch the console post-install
|
||||||
; check if we need to launch the server post-install
|
${NSD_GetState} $LaunchConsoleNowCheckbox $LaunchConsoleNowState
|
||||||
${NSD_GetState} $LaunchServerNowCheckbox $LaunchServerNowState
|
|
||||||
${EndIf}
|
|
||||||
|
|
||||||
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
; check if we need to launch the client post-install
|
; check if we need to launch the client post-install
|
||||||
|
@ -893,6 +903,31 @@ Function ReadPostInstallOptions
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|
||||||
Function HandlePostInstallOptions
|
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@
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
; check if the user asked for a desktop shortcut to High Fidelity
|
; check if the user asked for a desktop shortcut to High Fidelity
|
||||||
${If} $DesktopClientState == ${BST_CHECKED}
|
${If} $DesktopClientState == ${BST_CHECKED}
|
||||||
|
@ -901,38 +936,25 @@ Function HandlePostInstallOptions
|
||||||
${Else}
|
${Else}
|
||||||
!insertmacro WriteInstallOption @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ NO
|
!insertmacro WriteInstallOption @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ NO
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
; check if the user asked to have Console launched every startup
|
||||||
; check if the user asked for a desktop shortcut to Sandbox
|
${If} $ConsoleStartupState == ${BST_CHECKED}
|
||||||
${If} $DesktopServerState == ${BST_CHECKED}
|
; in case we added a shortcut in the global context, pull that now
|
||||||
CreateShortCut "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
SetShellVarContext all
|
||||||
!insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ YES
|
Delete "$SMSTARTUP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
|
||||||
; Set appUserModelId
|
|
||||||
ApplicationID::Set "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@"
|
|
||||||
${Else}
|
|
||||||
!insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO
|
|
||||||
${EndIf}
|
|
||||||
|
|
||||||
|
; 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
|
; reset the shell var context back
|
||||||
${If} $ServerStartupState == ${BST_CHECKED}
|
SetShellVarContext all
|
||||||
; 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
|
!insertmacro WriteInstallOption @CONSOLE_STARTUP_REG_KEY@ YES
|
||||||
SetShellVarContext current
|
${Else}
|
||||||
CreateShortCut "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
!insertmacro WriteInstallOption @CONSOLE_STARTUP_REG_KEY@ NO
|
||||||
|
|
||||||
; reset the shell var context back
|
|
||||||
SetShellVarContext all
|
|
||||||
|
|
||||||
!insertmacro WriteInstallOption @CONSOLE_STARTUP_REG_KEY@ YES
|
|
||||||
${Else}
|
|
||||||
!insertmacro WriteInstallOption @CONSOLE_STARTUP_REG_KEY@ NO
|
|
||||||
${EndIf}
|
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
; check if the user asked for a clean install
|
; check if the user asked for a clean install
|
||||||
|
@ -982,32 +1004,38 @@ Function HandlePostInstallOptions
|
||||||
${EndIf}
|
${EndIf}
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
${If} $LaunchClientNowState == ${BST_CHECKED}
|
||||||
${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}
|
|
||||||
!insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ YES
|
!insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ YES
|
||||||
; create shortcut with ARGUMENTS
|
${Else}
|
||||||
CreateShortCut "$TEMP\SandboxShortcut.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" "-- --launchInterface"
|
|
||||||
Exec '"$WINDIR\explorer.exe" "$TEMP\SandboxShortcut.lnk"'
|
|
||||||
${Else}
|
|
||||||
!insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ NO
|
!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@"'
|
Exec '"$WINDIR\explorer.exe" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"'
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
${ElseIf} @CLIENT_COMPONENT_CONDITIONAL@
|
${If} $LaunchClientNowState == ${BST_CHECKED}
|
||||||
!insertmacro WriteInstallOption @SERVER_LAUNCH_NOW_REG_KEY@ NO
|
${AndIf} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
|
${Unless} $LaunchConsoleNowState == ${BST_CHECKED}
|
||||||
; launch uses the explorer trick in case the user has elevated permissions for the installer
|
${OrUnless} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
${If} $LaunchClientNowState == ${BST_CHECKED}
|
; launch uses the explorer trick in case the user has elevated permissions for the installer
|
||||||
!insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ YES
|
|
||||||
Exec '"$WINDIR\explorer.exe" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"'
|
Exec '"$WINDIR\explorer.exe" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"'
|
||||||
${Else}
|
|
||||||
!insertmacro WriteInstallOption @CLIENT_LAUNCH_NOW_REG_KEY@ NO
|
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${EndIf}
|
${EndIf}
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|
||||||
|
@ -1164,8 +1192,16 @@ Section "-Core installation"
|
||||||
|
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
; Conditional handling for server console shortcut
|
|
||||||
${If} @SERVER_COMPONENT_CONDITIONAL@
|
${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" \
|
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" \
|
||||||
"$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
"$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
||||||
; Set appUserModelId
|
; Set appUserModelId
|
||||||
|
@ -1376,12 +1412,15 @@ Section "Uninstall"
|
||||||
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
||||||
Delete "$SMPROGRAMS\$MUI_TEMP\@INTERFACE_SHORTCUT_NAME@.lnk"
|
Delete "$SMPROGRAMS\$MUI_TEMP\@INTERFACE_SHORTCUT_NAME@.lnk"
|
||||||
Delete "$SMPROGRAMS\$MUI_TEMP\@CONSOLE_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\@INTERFACE_HF_SHORTCUT_NAME@.lnk"
|
||||||
Delete "$DESKTOP\@CONSOLE_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
|
; if it exists, delete the startup shortcut for the current user
|
||||||
SetShellVarContext current
|
SetShellVarContext current
|
||||||
Delete "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk"
|
Delete "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk"
|
||||||
|
Delete "$SMSTARTUP\@SANDBOX_HF_SHORTCUT_NAME@.lnk"
|
||||||
SetShellVarContext all
|
SetShellVarContext all
|
||||||
|
|
||||||
@CPACK_NSIS_DELETE_ICONS@
|
@CPACK_NSIS_DELETE_ICONS@
|
||||||
|
@ -1414,6 +1453,7 @@ Section "Uninstall"
|
||||||
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
|
||||||
Delete "$SMPROGRAMS\$MUI_TEMP\@INTERFACE_SHORTCUT_NAME@.lnk"
|
Delete "$SMPROGRAMS\$MUI_TEMP\@INTERFACE_SHORTCUT_NAME@.lnk"
|
||||||
Delete "$SMPROGRAMS\$MUI_TEMP\@CONSOLE_SHORTCUT_NAME@.lnk"
|
Delete "$SMPROGRAMS\$MUI_TEMP\@CONSOLE_SHORTCUT_NAME@.lnk"
|
||||||
|
Delete "$SMPROGRAMS\$MUI_TEMP\@SANDBOX_SHORTCUT_NAME@.lnk"
|
||||||
@CPACK_NSIS_DELETE_ICONS_EXTRA@
|
@CPACK_NSIS_DELETE_ICONS_EXTRA@
|
||||||
|
|
||||||
;Delete empty start menu parent diretories
|
;Delete empty start menu parent diretories
|
||||||
|
|
24
docs/LICENSE_highlight.js.txt
Normal file
24
docs/LICENSE_highlight.js.txt
Normal 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
23
docs/LICENSE_markdeep.txt
Normal 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.
|
280
docs/interface/raypick/pick-parenting.md.html
Normal file
280
docs/interface/raypick/pick-parenting.md.html
Normal 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
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
170
docs/markdeep_apidoc.css
Normal 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;
|
||||||
|
}
|
||||||
|
|
BIN
interface/resources/images/interstitialPage/button.png
Normal file
BIN
interface/resources/images/interstitialPage/button.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
BIN
interface/resources/images/interstitialPage/button_back.png
Normal file
BIN
interface/resources/images/interstitialPage/button_back.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
BIN
interface/resources/images/interstitialPage/button_hover.png
Normal file
BIN
interface/resources/images/interstitialPage/button_hover.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
BIN
interface/resources/images/interstitialPage/button_tryAgain.png
Normal file
BIN
interface/resources/images/interstitialPage/button_tryAgain.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
|
@ -100,6 +100,25 @@ Rectangle {
|
||||||
wearablesModel.setProperty(wearableIndex, 'properties', wearableModelItemProperties);
|
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() {
|
function getCurrentWearable() {
|
||||||
return wearablesCombobox.currentIndex !== -1 ? wearablesCombobox.model.get(wearablesCombobox.currentIndex) : null;
|
return wearablesCombobox.currentIndex !== -1 ? wearablesCombobox.model.get(wearablesCombobox.currentIndex) : null;
|
||||||
}
|
}
|
||||||
|
@ -109,6 +128,7 @@ Rectangle {
|
||||||
var wearable = wearablesCombobox.model.get(i);
|
var wearable = wearablesCombobox.model.get(i);
|
||||||
if (wearable.id === entityID) {
|
if (wearable.id === entityID) {
|
||||||
wearablesCombobox.currentIndex = i;
|
wearablesCombobox.currentIndex = i;
|
||||||
|
softWearableTimer.restart();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,6 +138,7 @@ Rectangle {
|
||||||
visible = false;
|
visible = false;
|
||||||
adjustWearablesClosed(status, avatarName);
|
adjustWearablesClosed(status, avatarName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HifiConstants { id: hifi }
|
HifiConstants { id: hifi }
|
||||||
|
|
||||||
|
@ -130,6 +151,20 @@ Rectangle {
|
||||||
hoverEnabled: true;
|
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 {
|
Column {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 12
|
anchors.topMargin: 12
|
||||||
|
@ -247,13 +282,13 @@ Rectangle {
|
||||||
var rotation = currentWearable ? currentWearable.localRotationAngles : { x : 0, y : 0, z : 0 };
|
var rotation = currentWearable ? currentWearable.localRotationAngles : { x : 0, y : 0, z : 0 };
|
||||||
var scale = currentWearable ? currentWearable.dimensions.x / currentWearable.naturalDimensions.x : 1.0;
|
var scale = currentWearable ? currentWearable.dimensions.x / currentWearable.naturalDimensions.x : 1.0;
|
||||||
var joint = currentWearable ? currentWearable.parentJointIndex : -1;
|
var joint = currentWearable ? currentWearable.parentJointIndex : -1;
|
||||||
var soft = currentWearable ? currentWearable.relayParentJoints : false;
|
softWearableTimer.restart();
|
||||||
|
|
||||||
positionVector.set(position);
|
positionVector.set(position);
|
||||||
rotationVector.set(rotation);
|
rotationVector.set(rotation);
|
||||||
scalespinner.set(scale);
|
scalespinner.set(scale);
|
||||||
jointsCombobox.set(joint);
|
jointsCombobox.set(joint);
|
||||||
isSoft.set(soft);
|
|
||||||
|
|
||||||
if (currentWearable) {
|
if (currentWearable) {
|
||||||
wearableSelected(currentWearable.id);
|
wearableSelected(currentWearable.id);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -122,6 +122,7 @@
|
||||||
#include <RecordingScriptingInterface.h>
|
#include <RecordingScriptingInterface.h>
|
||||||
#include <UpdateSceneTask.h>
|
#include <UpdateSceneTask.h>
|
||||||
#include <RenderViewTask.h>
|
#include <RenderViewTask.h>
|
||||||
|
#include <render/EngineStats.h>
|
||||||
#include <SecondaryCamera.h>
|
#include <SecondaryCamera.h>
|
||||||
#include <ResourceCache.h>
|
#include <ResourceCache.h>
|
||||||
#include <ResourceRequest.h>
|
#include <ResourceRequest.h>
|
||||||
|
@ -215,7 +216,8 @@
|
||||||
#include <raypick/LaserPointerScriptingInterface.h>
|
#include <raypick/LaserPointerScriptingInterface.h>
|
||||||
#include <raypick/PickScriptingInterface.h>
|
#include <raypick/PickScriptingInterface.h>
|
||||||
#include <raypick/PointerScriptingInterface.h>
|
#include <raypick/PointerScriptingInterface.h>
|
||||||
#include <raypick/MouseRayPick.h>
|
#include <raypick/RayPick.h>
|
||||||
|
#include <raypick/MouseTransformNode.h>
|
||||||
|
|
||||||
#include <FadeEffect.h>
|
#include <FadeEffect.h>
|
||||||
|
|
||||||
|
@ -364,7 +366,6 @@ static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SI
|
||||||
|
|
||||||
static const uint32_t INVALID_FRAME = UINT32_MAX;
|
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 float INITIAL_QUERY_RADIUS = 10.0f; // priority radius for entities before physics enabled
|
||||||
|
|
||||||
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||||
|
@ -2286,8 +2287,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
});
|
});
|
||||||
|
|
||||||
// Setup the mouse ray pick and related operators
|
// 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) {
|
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickResultOperator([](unsigned int rayPickID) {
|
||||||
RayToEntityIntersectionResult entityResult;
|
RayToEntityIntersectionResult entityResult;
|
||||||
entityResult.intersects = false;
|
entityResult.intersects = false;
|
||||||
|
@ -5377,8 +5383,8 @@ void Application::resetPhysicsReadyInformation() {
|
||||||
// collision information of nearby entities to make running bullet be safe.
|
// collision information of nearby entities to make running bullet be safe.
|
||||||
_fullSceneReceivedCounter = 0;
|
_fullSceneReceivedCounter = 0;
|
||||||
_fullSceneCounterAtLastPhysicsCheck = 0;
|
_fullSceneCounterAtLastPhysicsCheck = 0;
|
||||||
_nearbyEntitiesCountAtLastPhysicsCheck = 0;
|
_gpuTextureMemSizeStabilityCount = 0;
|
||||||
_nearbyEntitiesStabilityCount = 0;
|
_gpuTextureMemSizeAtLastCheck = 0;
|
||||||
_physicsEnabled = false;
|
_physicsEnabled = false;
|
||||||
_octreeProcessor.startEntitySequence();
|
_octreeProcessor.startEntitySequence();
|
||||||
}
|
}
|
||||||
|
@ -5617,18 +5623,21 @@ void Application::update(float deltaTime) {
|
||||||
// for nearby entities before starting bullet up.
|
// for nearby entities before starting bullet up.
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
if (isServerlessMode() || _octreeProcessor.isLoadSequenceComplete()) {
|
if (isServerlessMode() || _octreeProcessor.isLoadSequenceComplete()) {
|
||||||
// we've received a new full-scene octree stats packet, or it's been long enough to try again anyway
|
bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
|
||||||
_lastPhysicsCheckTime = now;
|
if (gpuTextureMemSizeStable() || !enableInterstitial) {
|
||||||
_fullSceneCounterAtLastPhysicsCheck = _fullSceneReceivedCounter;
|
// we've received a new full-scene octree stats packet, or it's been long enough to try again anyway
|
||||||
_lastQueriedViews.clear(); // Force new view.
|
_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).
|
// 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
|
// 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.
|
// scene is ready to compute its collision shape.
|
||||||
if (getMyAvatar()->isReadyForPhysics()) {
|
if (getMyAvatar()->isReadyForPhysics()) {
|
||||||
_physicsEnabled = true;
|
_physicsEnabled = true;
|
||||||
setIsInterstitialMode(false);
|
setIsInterstitialMode(false);
|
||||||
getMyAvatar()->updateMotionBehaviorFromMenu();
|
getMyAvatar()->updateMotionBehaviorFromMenu();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (domainLoadingInProgress) {
|
} else if (domainLoadingInProgress) {
|
||||||
|
@ -5915,6 +5924,10 @@ void Application::update(float deltaTime) {
|
||||||
// update the rendering without any simulation
|
// update the rendering without any simulation
|
||||||
getEntities()->update(false);
|
getEntities()->update(false);
|
||||||
}
|
}
|
||||||
|
// remove recently dead avatarEntities
|
||||||
|
SetOfEntities deadAvatarEntities;
|
||||||
|
_entitySimulation->takeDeadAvatarEntities(deadAvatarEntities);
|
||||||
|
avatarManager->removeDeadAvatarEntities(deadAvatarEntities);
|
||||||
}
|
}
|
||||||
|
|
||||||
// AvatarManager update
|
// AvatarManager update
|
||||||
|
@ -6239,6 +6252,8 @@ int Application::sendNackPackets() {
|
||||||
missingSequenceNumbers = sequenceNumberStats.getMissingSet();
|
missingSequenceNumbers = sequenceNumberStats.getMissingSet();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_isMissingSequenceNumbers = (missingSequenceNumbers.size() != 0);
|
||||||
|
|
||||||
// construct nack packet(s) for this node
|
// construct nack packet(s) for this node
|
||||||
foreach(const OCTREE_PACKET_SEQUENCE& missingNumber, missingSequenceNumbers) {
|
foreach(const OCTREE_PACKET_SEQUENCE& missingNumber, missingSequenceNumbers) {
|
||||||
nackPacketList->writePrimitive(missingNumber);
|
nackPacketList->writePrimitive(missingNumber);
|
||||||
|
@ -6265,9 +6280,19 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType) {
|
||||||
const bool isModifiedQuery = !_physicsEnabled;
|
const bool isModifiedQuery = !_physicsEnabled;
|
||||||
if (isModifiedQuery) {
|
if (isModifiedQuery) {
|
||||||
// Create modified view that is a simple sphere.
|
// Create modified view that is a simple sphere.
|
||||||
|
bool interstitialModeEnabled = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
|
||||||
|
|
||||||
ConicalViewFrustum sphericalView;
|
ConicalViewFrustum sphericalView;
|
||||||
sphericalView.setSimpleRadius(INITIAL_QUERY_RADIUS);
|
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);
|
_octreeQuery.setOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE);
|
||||||
static constexpr float MIN_LOD_ADJUST = -20.0f;
|
static constexpr float MIN_LOD_ADJUST = -20.0f;
|
||||||
_octreeQuery.setBoundaryLevelAdjust(MIN_LOD_ADJUST);
|
_octreeQuery.setBoundaryLevelAdjust(MIN_LOD_ADJUST);
|
||||||
|
@ -6579,69 +6604,23 @@ void Application::trackIncomingOctreePacket(ReceivedMessage& message, SharedNode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::nearbyEntitiesAreReadyForPhysics() {
|
bool Application::gpuTextureMemSizeStable() {
|
||||||
// this is used to avoid the following scenario:
|
auto renderConfig = qApp->getRenderEngine()->getConfiguration();
|
||||||
// A table has some items sitting on top of it. The items are at rest, meaning they aren't active in bullet.
|
auto renderStats = renderConfig->getConfig<render::EngineStats>("Stats");
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't want to use EntityTree::findEntities(AABox, ...) method because that scan will snarf parented entities
|
qint64 textureResourceGPUMemSize = renderStats->textureResourceGPUMemSize;
|
||||||
// whose bounding boxes cannot be computed (it is too loose for our purposes here). Instead we manufacture
|
qint64 texturePopulatedGPUMemSize = renderStats->textureResourcePopulatedGPUMemSize;
|
||||||
// custom filters and use the general-purpose EntityTree::findEntities(filter, ...)
|
qint64 textureTransferSize = renderStats->texturePendingGPUTransferSize;
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
entityTree->withReadLock([&] {
|
if (_gpuTextureMemSizeAtLastCheck == textureResourceGPUMemSize) {
|
||||||
// Pass the second function to the general-purpose EntityTree::findEntities()
|
_gpuTextureMemSizeStabilityCount++;
|
||||||
// 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++;
|
|
||||||
} else {
|
} else {
|
||||||
_nearbyEntitiesStabilityCount = 0;
|
_gpuTextureMemSizeStabilityCount = 0;
|
||||||
}
|
}
|
||||||
_nearbyEntitiesCountAtLastPhysicsCheck = nearbyCount;
|
_gpuTextureMemSizeAtLastCheck = textureResourceGPUMemSize;
|
||||||
|
|
||||||
const uint32_t MINIMUM_NEARBY_ENTITIES_STABILITY_COUNT = 3;
|
if (_gpuTextureMemSizeStabilityCount >= _minimumGPUTextureMemSizeStabilityCount) {
|
||||||
if (_nearbyEntitiesStabilityCount >= MINIMUM_NEARBY_ENTITIES_STABILITY_COUNT) {
|
return (textureResourceGPUMemSize == texturePopulatedGPUMemSize) && (textureTransferSize == 0);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,6 +183,8 @@ public:
|
||||||
// passes, mirror window passes, etc
|
// passes, mirror window passes, etc
|
||||||
void copyDisplayViewFrustum(ViewFrustum& viewOut) const;
|
void copyDisplayViewFrustum(ViewFrustum& viewOut) const;
|
||||||
|
|
||||||
|
bool isMissingSequenceNumbers() { return _isMissingSequenceNumbers; }
|
||||||
|
|
||||||
const ConicalViewFrustums& getConicalViews() const override { return _conicalViews; }
|
const ConicalViewFrustums& getConicalViews() const override { return _conicalViews; }
|
||||||
|
|
||||||
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
|
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
|
||||||
|
@ -230,6 +232,8 @@ public:
|
||||||
float getSettingConstrainToolbarPosition() { return _constrainToolbarPosition.get(); }
|
float getSettingConstrainToolbarPosition() { return _constrainToolbarPosition.get(); }
|
||||||
void setSettingConstrainToolbarPosition(bool setting);
|
void setSettingConstrainToolbarPosition(bool setting);
|
||||||
|
|
||||||
|
Q_INVOKABLE void setMinimumGPUTextureMemStabilityCount(int stabilityCount) { _minimumGPUTextureMemSizeStabilityCount = stabilityCount; }
|
||||||
|
|
||||||
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
|
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
|
||||||
|
|
||||||
virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; }
|
virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; }
|
||||||
|
@ -525,7 +529,7 @@ private:
|
||||||
bool importFromZIP(const QString& filePath);
|
bool importFromZIP(const QString& filePath);
|
||||||
bool importImage(const QString& urlString);
|
bool importImage(const QString& urlString);
|
||||||
|
|
||||||
bool nearbyEntitiesAreReadyForPhysics();
|
bool gpuTextureMemSizeStable();
|
||||||
int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode);
|
int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode);
|
||||||
void trackIncomingOctreePacket(ReceivedMessage& message, SharedNodePointer sendingNode, bool wasStatsPacket);
|
void trackIncomingOctreePacket(ReceivedMessage& message, SharedNodePointer sendingNode, bool wasStatsPacket);
|
||||||
|
|
||||||
|
@ -581,6 +585,8 @@ private:
|
||||||
QElapsedTimer _lastTimeUpdated;
|
QElapsedTimer _lastTimeUpdated;
|
||||||
QElapsedTimer _lastTimeRendered;
|
QElapsedTimer _lastTimeRendered;
|
||||||
|
|
||||||
|
int _minimumGPUTextureMemSizeStabilityCount { 30 };
|
||||||
|
|
||||||
ShapeManager _shapeManager;
|
ShapeManager _shapeManager;
|
||||||
PhysicalEntitySimulationPointer _entitySimulation;
|
PhysicalEntitySimulationPointer _entitySimulation;
|
||||||
PhysicsEnginePointer _physicsEngine;
|
PhysicsEnginePointer _physicsEngine;
|
||||||
|
@ -709,6 +715,8 @@ private:
|
||||||
|
|
||||||
bool _fakedMouseEvent { false };
|
bool _fakedMouseEvent { false };
|
||||||
|
|
||||||
|
bool _isMissingSequenceNumbers { false };
|
||||||
|
|
||||||
void checkChangeCursor();
|
void checkChangeCursor();
|
||||||
mutable QMutex _changeCursorLock { QMutex::Recursive };
|
mutable QMutex _changeCursorLock { QMutex::Recursive };
|
||||||
Qt::CursorShape _desiredCursor{ Qt::BlankCursor };
|
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
|
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 _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
|
quint64 _lastPhysicsCheckTime { usecTimestampNow() }; // when did we last check to see if physics was ready
|
||||||
|
|
||||||
bool _keyboardDeviceHasFocus { true };
|
bool _keyboardDeviceHasFocus { true };
|
||||||
|
|
|
@ -275,7 +275,11 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
if (inView && avatar->hasNewJointData()) {
|
if (inView && avatar->hasNewJointData()) {
|
||||||
numAvatarsUpdated++;
|
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->simulate(deltaTime, inView);
|
||||||
avatar->updateRenderItem(renderTransaction);
|
avatar->updateRenderItem(renderTransaction);
|
||||||
avatar->updateSpaceProxy(workloadTransaction);
|
avatar->updateSpaceProxy(workloadTransaction);
|
||||||
|
@ -448,6 +452,17 @@ void AvatarManager::handleProcessedPhysicsTransaction(PhysicsEngine::Transaction
|
||||||
transaction.clear();
|
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) {
|
void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) {
|
||||||
auto avatar = std::static_pointer_cast<OtherAvatar>(removedAvatar);
|
auto avatar = std::static_pointer_cast<OtherAvatar>(removedAvatar);
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <avatars-renderer/ScriptAvatar.h>
|
#include <avatars-renderer/ScriptAvatar.h>
|
||||||
#include <AudioInjector.h>
|
#include <AudioInjector.h>
|
||||||
#include <workload/Space.h>
|
#include <workload/Space.h>
|
||||||
|
#include <EntitySimulation.h> // for SetOfEntities
|
||||||
|
|
||||||
#include "AvatarMotionState.h"
|
#include "AvatarMotionState.h"
|
||||||
#include "MyAvatar.h"
|
#include "MyAvatar.h"
|
||||||
|
@ -187,6 +188,7 @@ public:
|
||||||
void queuePhysicsChange(const OtherAvatarPointer& avatar);
|
void queuePhysicsChange(const OtherAvatarPointer& avatar);
|
||||||
void buildPhysicsTransaction(PhysicsEngine::Transaction& transaction);
|
void buildPhysicsTransaction(PhysicsEngine::Transaction& transaction);
|
||||||
void handleProcessedPhysicsTransaction(PhysicsEngine::Transaction& transaction);
|
void handleProcessedPhysicsTransaction(PhysicsEngine::Transaction& transaction);
|
||||||
|
void removeDeadAvatarEntities(const SetOfEntities& deadEntities);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
|
|
@ -137,7 +137,7 @@ MyAvatar::MyAvatar(QThread* thread) :
|
||||||
_useSnapTurnSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "useSnapTurn", _useSnapTurn),
|
_useSnapTurnSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "useSnapTurn", _useSnapTurn),
|
||||||
_userHeightSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "userHeight", DEFAULT_AVATAR_HEIGHT),
|
_userHeightSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "userHeight", DEFAULT_AVATAR_HEIGHT),
|
||||||
_flyingHMDSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "flyingHMD", _flyingPrefHMD),
|
_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));
|
_clientTraitsHandler = std::unique_ptr<ClientTraitsHandler>(new ClientTraitsHandler(this));
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,11 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "SafeLanding.h"
|
#include "SafeLanding.h"
|
||||||
|
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
#include "EntityTreeRenderer.h"
|
#include "EntityTreeRenderer.h"
|
||||||
#include "ModelEntityItem.h"
|
#include "RenderableModelEntityItem.h"
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
|
@ -39,6 +42,7 @@ void SafeLanding::startEntitySequence(QSharedPointer<EntityTreeRenderer> entityT
|
||||||
_entityTree = entityTree;
|
_entityTree = entityTree;
|
||||||
_trackedEntities.clear();
|
_trackedEntities.clear();
|
||||||
_trackingEntities = true;
|
_trackingEntities = true;
|
||||||
|
_maxTrackedEntityCount = 0;
|
||||||
connect(std::const_pointer_cast<EntityTree>(_entityTree).get(),
|
connect(std::const_pointer_cast<EntityTree>(_entityTree).get(),
|
||||||
&EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity);
|
&EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity);
|
||||||
connect(std::const_pointer_cast<EntityTree>(_entityTree).get(),
|
connect(std::const_pointer_cast<EntityTree>(_entityTree).get(),
|
||||||
|
@ -47,6 +51,7 @@ void SafeLanding::startEntitySequence(QSharedPointer<EntityTreeRenderer> entityT
|
||||||
_sequenceNumbers.clear();
|
_sequenceNumbers.clear();
|
||||||
_initialStart = INVALID_SEQUENCE;
|
_initialStart = INVALID_SEQUENCE;
|
||||||
_initialEnd = INVALID_SEQUENCE;
|
_initialEnd = INVALID_SEQUENCE;
|
||||||
|
_startTime = usecTimestampNow();
|
||||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(&ElevatedPriority);
|
EntityTreeRenderer::setEntityLoadingPriorityFunction(&ElevatedPriority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +60,7 @@ void SafeLanding::stopEntitySequence() {
|
||||||
Locker lock(_lock);
|
Locker lock(_lock);
|
||||||
_trackingEntities = false;
|
_trackingEntities = false;
|
||||||
_maxTrackedEntityCount = 0;
|
_maxTrackedEntityCount = 0;
|
||||||
|
_trackedEntityStabilityCount = 0;
|
||||||
_initialStart = INVALID_SEQUENCE;
|
_initialStart = INVALID_SEQUENCE;
|
||||||
_initialEnd = INVALID_SEQUENCE;
|
_initialEnd = INVALID_SEQUENCE;
|
||||||
_trackedEntities.clear();
|
_trackedEntities.clear();
|
||||||
|
@ -66,18 +72,17 @@ void SafeLanding::addTrackedEntity(const EntityItemID& entityID) {
|
||||||
Locker lock(_lock);
|
Locker lock(_lock);
|
||||||
EntityItemPointer entity = _entityTree->findEntityByID(entityID);
|
EntityItemPointer entity = _entityTree->findEntityByID(entityID);
|
||||||
|
|
||||||
if (entity) {
|
if (entity && entity->getCreated() < _startTime) {
|
||||||
|
|
||||||
_trackedEntities.emplace(entityID, entity);
|
_trackedEntities.emplace(entityID, entity);
|
||||||
int trackedEntityCount = (int)_trackedEntities.size();
|
int trackedEntityCount = (int)_trackedEntities.size();
|
||||||
|
|
||||||
if (trackedEntityCount > _maxTrackedEntityCount) {
|
if (trackedEntityCount > _maxTrackedEntityCount) {
|
||||||
_maxTrackedEntityCount = trackedEntityCount;
|
_maxTrackedEntityCount = trackedEntityCount;
|
||||||
|
_trackedEntityStabilityCount = 0;
|
||||||
}
|
}
|
||||||
qCDebug(interfaceapp) << "Safe Landing: Tracking entity " << entity->getItemName();
|
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() {
|
bool SafeLanding::isLoadSequenceComplete() {
|
||||||
if (isEntityLoadingComplete() && isSequenceNumbersComplete()) {
|
if (isEntityLoadingComplete() && isSequenceNumbersComplete()) {
|
||||||
Locker lock(_lock);
|
Locker lock(_lock);
|
||||||
_trackedEntities.clear();
|
|
||||||
_initialStart = INVALID_SEQUENCE;
|
_initialStart = INVALID_SEQUENCE;
|
||||||
_initialEnd = INVALID_SEQUENCE;
|
_initialEnd = INVALID_SEQUENCE;
|
||||||
_entityTree = nullptr;
|
_entityTree = nullptr;
|
||||||
|
_trackingEntities = false; // Don't track anything else that comes in.
|
||||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(StandardPriority);
|
EntityTreeRenderer::setEntityLoadingPriorityFunction(StandardPriority);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,11 +121,18 @@ bool SafeLanding::isLoadSequenceComplete() {
|
||||||
|
|
||||||
float SafeLanding::loadingProgressPercentage() {
|
float SafeLanding::loadingProgressPercentage() {
|
||||||
Locker lock(_lock);
|
Locker lock(_lock);
|
||||||
|
static const int MINIMUM_TRACKED_ENTITY_STABILITY_COUNT = 15;
|
||||||
|
|
||||||
|
float entityReadyPercentage = 0.0f;
|
||||||
if (_maxTrackedEntityCount > 0) {
|
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() {
|
bool SafeLanding::isSequenceNumbersComplete() {
|
||||||
|
@ -130,11 +142,16 @@ bool SafeLanding::isSequenceNumbersComplete() {
|
||||||
_initialEnd + SEQUENCE_MODULO - _initialStart;
|
_initialEnd + SEQUENCE_MODULO - _initialStart;
|
||||||
auto startIter = _sequenceNumbers.find(_initialStart);
|
auto startIter = _sequenceNumbers.find(_initialStart);
|
||||||
auto endIter = _sequenceNumbers.find(_initialEnd - 1);
|
auto endIter = _sequenceNumbers.find(_initialEnd - 1);
|
||||||
|
|
||||||
|
bool missingSequenceNumbers = qApp->isMissingSequenceNumbers();
|
||||||
if (sequenceSize == 0 ||
|
if (sequenceSize == 0 ||
|
||||||
(startIter != _sequenceNumbers.end()
|
(startIter != _sequenceNumbers.end()
|
||||||
&& endIter != _sequenceNumbers.end()
|
&& endIter != _sequenceNumbers.end()
|
||||||
&& distance(startIter, endIter) == sequenceSize - 1) ) {
|
&& ((distance(startIter, endIter) == sequenceSize - 1) || !missingSequenceNumbers))) {
|
||||||
_trackingEntities = false; // Don't track anything else that comes in.
|
bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
|
||||||
|
if (!enableInterstitial) {
|
||||||
|
_trackingEntities = false; // Don't track anything else that comes in.
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,13 +162,13 @@ bool isEntityPhysicsReady(const EntityItemPointer& entity) {
|
||||||
if (entity && !entity->getCollisionless()) {
|
if (entity && !entity->getCollisionless()) {
|
||||||
const auto& entityType = entity->getType();
|
const auto& entityType = entity->getType();
|
||||||
if (entityType == EntityTypes::Model) {
|
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
|
static const std::set<ShapeType> downloadedCollisionTypes
|
||||||
{ SHAPE_TYPE_COMPOUND, SHAPE_TYPE_SIMPLE_COMPOUND, SHAPE_TYPE_STATIC_MESH, SHAPE_TYPE_SIMPLE_HULL };
|
{ SHAPE_TYPE_COMPOUND, SHAPE_TYPE_SIMPLE_COMPOUND, SHAPE_TYPE_STATIC_MESH, SHAPE_TYPE_SIMPLE_HULL };
|
||||||
bool hasAABox;
|
bool hasAABox;
|
||||||
entity->getAABox(hasAABox);
|
entity->getAABox(hasAABox);
|
||||||
if (hasAABox && downloadedCollisionTypes.count(modelEntity->getShapeType()) != 0) {
|
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 entityTree = qApp->getEntities();
|
||||||
auto entityMapIter = _trackedEntities.begin();
|
auto entityMapIter = _trackedEntities.begin();
|
||||||
|
|
||||||
|
bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled();
|
||||||
|
|
||||||
while (entityMapIter != _trackedEntities.end()) {
|
while (entityMapIter != _trackedEntities.end()) {
|
||||||
auto entity = entityMapIter->second;
|
auto entity = entityMapIter->second;
|
||||||
|
|
||||||
bool isVisuallyReady = true;
|
bool isVisuallyReady = true;
|
||||||
|
|
||||||
Settings settings;
|
|
||||||
bool enableInterstitial = settings.value("enableIntersitialMode", false).toBool();
|
|
||||||
|
|
||||||
if (enableInterstitial) {
|
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) {
|
if (isEntityPhysicsReady(entity) && isVisuallyReady) {
|
||||||
|
@ -188,6 +209,12 @@ bool SafeLanding::isEntityLoadingComplete() {
|
||||||
entityMapIter++;
|
entityMapIter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (enableInterstitial) {
|
||||||
|
_trackedEntityStabilityCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return _trackedEntities.empty();
|
return _trackedEntities.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,9 @@ private:
|
||||||
int _initialStart { INVALID_SEQUENCE };
|
int _initialStart { INVALID_SEQUENCE };
|
||||||
int _initialEnd { INVALID_SEQUENCE };
|
int _initialEnd { INVALID_SEQUENCE };
|
||||||
int _maxTrackedEntityCount { 0 };
|
int _maxTrackedEntityCount { 0 };
|
||||||
|
int _trackedEntityStabilityCount { 0 };
|
||||||
|
|
||||||
|
quint64 _startTime { 0 };
|
||||||
|
|
||||||
struct SequenceLessThan {
|
struct SequenceLessThan {
|
||||||
bool operator()(const int& a, const int& b) const;
|
bool operator()(const int& a, const int& b) const;
|
||||||
|
|
|
@ -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) :
|
CollisionPick::CollisionPick(const PickFilter& filter, float maxDistance, bool enabled, bool scaleWithParent, CollisionRegion collisionRegion, PhysicsEnginePointer physicsEngine) :
|
||||||
Pick(filter, maxDistance, enabled),
|
Pick(collisionRegion, filter, maxDistance, enabled),
|
||||||
_mathPick(collisionRegion),
|
_scaleWithParent(scaleWithParent),
|
||||||
_physicsEngine(physicsEngine) {
|
_physicsEngine(physicsEngine) {
|
||||||
if (collisionRegion.shouldComputeShapeInfo()) {
|
if (collisionRegion.shouldComputeShapeInfo()) {
|
||||||
_cachedResource = DependencyManager::get<ModelCache>()->getCollisionGeometryResource(collisionRegion.modelURL);
|
_cachedResource = DependencyManager::get<ModelCache>()->getCollisionGeometryResource(collisionRegion.modelURL);
|
||||||
|
@ -361,9 +361,15 @@ CollisionRegion CollisionPick::getMathematicalPick() const {
|
||||||
if (parentTransform) {
|
if (parentTransform) {
|
||||||
Transform parentTransformValue = parentTransform->getTransform();
|
Transform parentTransformValue = parentTransform->getTransform();
|
||||||
mathPick.transform = parentTransformValue.worldTransform(mathPick.transform);
|
mathPick.transform = parentTransformValue.worldTransform(mathPick.transform);
|
||||||
glm::vec3 scale = parentTransformValue.getScale();
|
|
||||||
float largestDimension = glm::max(glm::max(scale.x, scale.y), scale.z);
|
if (_scaleWithParent) {
|
||||||
mathPick.threshold *= largestDimension;
|
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;
|
return mathPick;
|
||||||
}
|
}
|
||||||
|
@ -424,5 +430,7 @@ PickResultPointer CollisionPick::getHUDIntersection(const CollisionRegion& pick)
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform CollisionPick::getResultTransform() const {
|
Transform CollisionPick::getResultTransform() const {
|
||||||
return Transform(getMathematicalPick().transform);
|
Transform transform;
|
||||||
|
transform.setTranslation(_mathPick.transform.getTranslation());
|
||||||
|
return transform;
|
||||||
}
|
}
|
|
@ -47,7 +47,7 @@ public:
|
||||||
|
|
||||||
class CollisionPick : public Pick<CollisionRegion> {
|
class CollisionPick : public Pick<CollisionRegion> {
|
||||||
public:
|
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;
|
CollisionRegion getMathematicalPick() const override;
|
||||||
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) 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 computeShapeInfoDimensionsOnly(const CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer<GeometryResource> resource);
|
||||||
void filterIntersections(std::vector<ContactTestResult>& intersections) const;
|
void filterIntersections(std::vector<ContactTestResult>& intersections) const;
|
||||||
|
|
||||||
CollisionRegion _mathPick;
|
bool _scaleWithParent;
|
||||||
|
|
||||||
PhysicsEnginePointer _physicsEngine;
|
PhysicsEnginePointer _physicsEngine;
|
||||||
QSharedPointer<GeometryResource> _cachedResource;
|
QSharedPointer<GeometryResource> _cachedResource;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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();
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -14,13 +14,14 @@
|
||||||
#include "avatar/AvatarManager.h"
|
#include "avatar/AvatarManager.h"
|
||||||
|
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
|
#include "PickManager.h"
|
||||||
#include "RayPick.h"
|
#include "RayPick.h"
|
||||||
|
|
||||||
LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, bool hover,
|
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,
|
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,
|
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) {
|
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);
|
QVariant endVariant = vec3toVariant(end);
|
||||||
if (!getPathID().isNull()) {
|
if (!getPathID().isNull()) {
|
||||||
QVariantMap pathProps;
|
QVariantMap pathProps;
|
||||||
|
@ -156,9 +157,7 @@ void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3&
|
||||||
pathProps.insert("end", endVariant);
|
pathProps.insert("end", endVariant);
|
||||||
pathProps.insert("visible", true);
|
pathProps.insert("visible", true);
|
||||||
pathProps.insert("ignoreRayIntersection", doesPathIgnoreRays());
|
pathProps.insert("ignoreRayIntersection", doesPathIgnoreRays());
|
||||||
if (scaleWithAvatar) {
|
pathProps.insert("lineWidth", getLineWidth() * parentScale);
|
||||||
pathProps.insert("lineWidth", getLineWidth() * DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale());
|
|
||||||
}
|
|
||||||
qApp->getOverlays().editOverlay(getPathID(), pathProps);
|
qApp->getOverlays().editOverlay(getPathID(), pathProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,12 @@ public:
|
||||||
const OverlayID& getPathID() const { return _pathID; }
|
const OverlayID& getPathID() const { return _pathID; }
|
||||||
const bool& doesPathIgnoreRays() const { return _pathIgnoreRays; }
|
const bool& doesPathIgnoreRays() const { return _pathIgnoreRays; }
|
||||||
|
|
||||||
void setLineWidth(const float& lineWidth) { _lineWidth = lineWidth; }
|
void setLineWidth(float width) { _lineWidth = width; }
|
||||||
const float& getLineWidth() const { return _lineWidth; }
|
float getLineWidth() const { return _lineWidth; }
|
||||||
|
|
||||||
void cleanup() override;
|
void cleanup() override;
|
||||||
void disable() 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;
|
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -40,7 +40,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, bool hover, const PointerTriggers& triggers,
|
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;
|
QVariantMap toVariantMap() const override;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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();
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -15,6 +15,46 @@
|
||||||
#include "DependencyManager.h"
|
#include "DependencyManager.h"
|
||||||
#include "PickManager.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) {
|
PickResultPointer ParabolaPick::getEntityIntersection(const PickParabola& pick) {
|
||||||
if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) {
|
if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) {
|
||||||
bool precisionPicking = !(getFilter().doesPickCoarse() || DependencyManager::get<PickManager>()->getForceCoarsePicking());
|
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());
|
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 {
|
Transform ParabolaPick::getResultTransform() const {
|
||||||
PickResultPointer result = getPrevPickResult();
|
PickResultPointer result = getPrevPickResult();
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
|
|
@ -74,9 +74,9 @@ public:
|
||||||
class ParabolaPick : public Pick<PickParabola> {
|
class ParabolaPick : public Pick<PickParabola> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ParabolaPick(float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool scaleWithAvatar, const PickFilter& filter, float maxDistance, bool enabled) :
|
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);
|
||||||
Pick(filter, maxDistance, enabled), _speed(speed), _accelerationAxis(accelerationAxis), _rotateAccelerationWithAvatar(rotateAccelerationWithAvatar),
|
|
||||||
_scaleWithAvatar(scaleWithAvatar) {}
|
PickParabola getMathematicalPick() const override;
|
||||||
|
|
||||||
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared<ParabolaPickResult>(pickVariant); }
|
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared<ParabolaPickResult>(pickVariant); }
|
||||||
PickResultPointer getEntityIntersection(const PickParabola& pick) override;
|
PickResultPointer getEntityIntersection(const PickParabola& pick) override;
|
||||||
|
@ -86,13 +86,11 @@ public:
|
||||||
Transform getResultTransform() const override;
|
Transform getResultTransform() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float _speed;
|
|
||||||
glm::vec3 _accelerationAxis;
|
|
||||||
bool _rotateAccelerationWithAvatar;
|
bool _rotateAccelerationWithAvatar;
|
||||||
bool _scaleWithAvatar;
|
bool _rotateAccelerationWithParent;
|
||||||
|
bool _scaleWithParent;
|
||||||
float getSpeed() const;
|
// Cached magnitude of _mathPick.velocity
|
||||||
glm::vec3 getAcceleration() const;
|
float _speed;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ParabolaPick_h
|
#endif // hifi_ParabolaPick_h
|
||||||
|
|
|
@ -204,9 +204,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) {
|
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);
|
auto parabolaPickResult = std::static_pointer_cast<ParabolaPickResult>(pickResult);
|
||||||
if (parabolaPickResult && render::Item::isValidID(_pathID)) {
|
if (parabolaPickResult && render::Item::isValidID(_pathID)) {
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
|
@ -216,7 +216,7 @@ void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::ve
|
||||||
glm::vec3 velocity = parabola.velocity;
|
glm::vec3 velocity = parabola.velocity;
|
||||||
glm::vec3 acceleration = parabola.acceleration;
|
glm::vec3 acceleration = parabola.acceleration;
|
||||||
float parabolicDistance = distance > 0.0f ? distance : parabolaPickResult->parabolicDistance;
|
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) {
|
transaction.updateItem<ParabolaRenderItem>(_pathID, [origin, velocity, acceleration, parabolicDistance, width](ParabolaRenderItem& item) {
|
||||||
item.setVisible(true);
|
item.setVisible(true);
|
||||||
item.setOrigin(origin);
|
item.setOrigin(origin);
|
||||||
|
|
|
@ -79,7 +79,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
RenderState() {}
|
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);
|
bool isVisibleInSecondaryCamera, bool drawInFront, bool pathEnabled);
|
||||||
|
|
||||||
void setPathWidth(float width) { _pathWidth = width; }
|
void setPathWidth(float width) { _pathWidth = width; }
|
||||||
|
@ -87,7 +87,7 @@ public:
|
||||||
|
|
||||||
void cleanup() override;
|
void cleanup() override;
|
||||||
void disable() 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;
|
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);
|
void editParabola(const glm::vec3& color, float alpha, float width, bool isVisibleInSecondaryCamera, bool drawInFront, bool enabled);
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
PathPointer::PathPointer(PickQuery::PickType type, const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
|
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 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),
|
Pointer(DependencyManager::get<PickScriptingInterface>()->createPick(type, rayProps), enabled, hover),
|
||||||
_renderStates(renderStates),
|
_renderStates(renderStates),
|
||||||
_defaultRenderStates(defaultRenderStates),
|
_defaultRenderStates(defaultRenderStates),
|
||||||
|
@ -28,7 +28,7 @@ PathPointer::PathPointer(PickQuery::PickType type, const QVariant& rayProps, con
|
||||||
_centerEndY(centerEndY),
|
_centerEndY(centerEndY),
|
||||||
_lockEnd(lockEnd),
|
_lockEnd(lockEnd),
|
||||||
_distanceScaleEnd(distanceScaleEnd),
|
_distanceScaleEnd(distanceScaleEnd),
|
||||||
_scaleWithAvatar(scaleWithAvatar)
|
_scaleWithParent(scaleWithParent)
|
||||||
{
|
{
|
||||||
for (auto& state : _renderStates) {
|
for (auto& state : _renderStates) {
|
||||||
if (!enabled || state.first != _currentRenderState) {
|
if (!enabled || state.first != _currentRenderState) {
|
||||||
|
@ -146,12 +146,18 @@ void PathPointer::updateVisuals(const PickResultPointer& pickResult) {
|
||||||
IntersectionType type = getPickedObjectType(pickResult);
|
IntersectionType type = getPickedObjectType(pickResult);
|
||||||
auto renderState = _renderStates.find(_currentRenderState);
|
auto renderState = _renderStates.find(_currentRenderState);
|
||||||
auto defaultRenderState = _defaultRenderStates.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() &&
|
if (_enabled && !_currentRenderState.empty() && renderState != _renderStates.end() &&
|
||||||
(type != IntersectionType::NONE || _pathLength > 0.0f)) {
|
(type != IntersectionType::NONE || _pathLength > 0.0f)) {
|
||||||
glm::vec3 origin = getPickOrigin(pickResult);
|
glm::vec3 origin = getPickOrigin(pickResult);
|
||||||
glm::vec3 end = getPickEnd(pickResult, _pathLength);
|
glm::vec3 end = getPickEnd(pickResult, _pathLength);
|
||||||
glm::vec3 surfaceNormal = getPickedObjectNormal(pickResult);
|
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);
|
_followNormal, _followNormalStrength, _pathLength, pickResult);
|
||||||
if (defaultRenderState != _defaultRenderStates.end() && defaultRenderState->second.second->isEnabled()) {
|
if (defaultRenderState != _defaultRenderStates.end() && defaultRenderState->second.second->isEnabled()) {
|
||||||
defaultRenderState->second.second->disable();
|
defaultRenderState->second.second->disable();
|
||||||
|
@ -162,7 +168,7 @@ void PathPointer::updateVisuals(const PickResultPointer& pickResult) {
|
||||||
}
|
}
|
||||||
glm::vec3 origin = getPickOrigin(pickResult);
|
glm::vec3 origin = getPickOrigin(pickResult);
|
||||||
glm::vec3 end = getPickEnd(pickResult, defaultRenderState->second.first);
|
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);
|
_faceAvatar, _followNormal, _followNormalStrength, defaultRenderState->second.first, pickResult);
|
||||||
} else if (!_currentRenderState.empty()) {
|
} else if (!_currentRenderState.empty()) {
|
||||||
if (renderState != _renderStates.end() && renderState->second->isEnabled()) {
|
if (renderState != _renderStates.end() && renderState->second->isEnabled()) {
|
||||||
|
@ -281,15 +287,13 @@ void StartEndRenderState::disable() {
|
||||||
_enabled = false;
|
_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) {
|
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) {
|
||||||
if (!getStartID().isNull()) {
|
if (!getStartID().isNull()) {
|
||||||
QVariantMap startProps;
|
QVariantMap startProps;
|
||||||
startProps.insert("position", vec3toVariant(origin));
|
startProps.insert("position", vec3toVariant(origin));
|
||||||
startProps.insert("visible", true);
|
startProps.insert("visible", true);
|
||||||
if (scaleWithAvatar) {
|
startProps.insert("dimensions", vec3toVariant(getStartDim() * parentScale));
|
||||||
startProps.insert("dimensions", vec3toVariant(getStartDim() * DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale()));
|
|
||||||
}
|
|
||||||
startProps.insert("ignoreRayIntersection", doesStartIgnoreRays());
|
startProps.insert("ignoreRayIntersection", doesStartIgnoreRays());
|
||||||
qApp->getOverlays().editOverlay(getStartID(), startProps);
|
qApp->getOverlays().editOverlay(getStartID(), startProps);
|
||||||
}
|
}
|
||||||
|
@ -300,8 +304,8 @@ void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end,
|
||||||
if (distanceScaleEnd) {
|
if (distanceScaleEnd) {
|
||||||
dim = getEndDim() * glm::distance(origin, end);
|
dim = getEndDim() * glm::distance(origin, end);
|
||||||
endProps.insert("dimensions", vec3toVariant(dim));
|
endProps.insert("dimensions", vec3toVariant(dim));
|
||||||
} else if (scaleWithAvatar) {
|
} else {
|
||||||
dim = getEndDim() * DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale();
|
dim = getEndDim() * parentScale;
|
||||||
endProps.insert("dimensions", vec3toVariant(dim));
|
endProps.insert("dimensions", vec3toVariant(dim));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ public:
|
||||||
|
|
||||||
virtual void cleanup();
|
virtual void cleanup();
|
||||||
virtual void disable();
|
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 faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult);
|
||||||
|
|
||||||
bool isEnabled() const { return _enabled; }
|
bool isEnabled() const { return _enabled; }
|
||||||
|
@ -74,7 +74,7 @@ class PathPointer : public Pointer {
|
||||||
public:
|
public:
|
||||||
PathPointer(PickQuery::PickType type, const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
|
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 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();
|
virtual ~PathPointer();
|
||||||
|
|
||||||
void setRenderState(const std::string& state) override;
|
void setRenderState(const std::string& state) override;
|
||||||
|
@ -98,7 +98,7 @@ protected:
|
||||||
bool _centerEndY;
|
bool _centerEndY;
|
||||||
bool _lockEnd;
|
bool _lockEnd;
|
||||||
bool _distanceScaleEnd;
|
bool _distanceScaleEnd;
|
||||||
bool _scaleWithAvatar;
|
bool _scaleWithParent;
|
||||||
LockEndObject _lockEndObject;
|
LockEndObject _lockEndObject;
|
||||||
|
|
||||||
struct TriggerState {
|
struct TriggerState {
|
||||||
|
|
|
@ -14,13 +14,9 @@
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include <PickManager.h>
|
#include <PickManager.h>
|
||||||
|
|
||||||
#include "StaticRayPick.h"
|
#include "RayPick.h"
|
||||||
#include "JointRayPick.h"
|
|
||||||
#include "MouseRayPick.h"
|
|
||||||
#include "StylusPick.h"
|
#include "StylusPick.h"
|
||||||
#include "StaticParabolaPick.h"
|
#include "ParabolaPick.h"
|
||||||
#include "JointParabolaPick.h"
|
|
||||||
#include "MouseParabolaPick.h"
|
|
||||||
#include "CollisionPick.h"
|
#include "CollisionPick.h"
|
||||||
|
|
||||||
#include "SpatialParentFinder.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 {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} [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 {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.
|
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick.
|
||||||
* 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
|
* @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)
|
||||||
* exists on your current avatar.
|
* @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} [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} [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.
|
* @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();
|
maxDistance = propMap["maxDistance"].toFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (propMap["joint"].isValid()) {
|
glm::vec3 position = Vectors::ZERO;
|
||||||
std::string jointName = propMap["joint"].toString().toStdString();
|
if (propMap["position"].isValid()) {
|
||||||
|
position = vec3FromVariant(propMap["position"]);
|
||||||
if (jointName != "Mouse") {
|
} else if (propMap["posOffset"].isValid()) {
|
||||||
// x = upward, y = forward, z = lateral
|
position = vec3FromVariant(propMap["posOffset"]);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
/**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));
|
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
|
/**jsdoc
|
||||||
* A set of properties that can be passed to {@link Picks.createPick} to create a new Parabola Pick.
|
* A set of properties that can be passed to {@link Picks.createPick} to create a new Parabola Pick.
|
||||||
* @typedef {object} Picks.ParabolaPickProperties
|
* @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 {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} [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 {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.
|
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick.
|
||||||
* 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
|
* @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)
|
||||||
* exists on your current avatar.
|
* @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} [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} [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} [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 {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 {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 {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} [rotateAccelerationWithAvatar=true] Whether or not the acceleration axis should rotate with the 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} [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) {
|
unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properties) {
|
||||||
QVariantMap propMap = properties.toMap();
|
QVariantMap propMap = properties.toMap();
|
||||||
|
@ -204,48 +193,37 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti
|
||||||
rotateAccelerationWithAvatar = propMap["rotateAccelerationWithAvatar"].toBool();
|
rotateAccelerationWithAvatar = propMap["rotateAccelerationWithAvatar"].toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scaleWithAvatar = false;
|
bool rotateAccelerationWithParent = false;
|
||||||
if (propMap["scaleWithAvatar"].isValid()) {
|
if (propMap["rotateAccelerationWithParent"].isValid()) {
|
||||||
scaleWithAvatar = propMap["scaleWithAvatar"].toBool();
|
rotateAccelerationWithParent = propMap["rotateAccelerationWithParent"].toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (propMap["joint"].isValid()) {
|
bool scaleWithParent = true;
|
||||||
std::string jointName = propMap["joint"].toString().toStdString();
|
if (propMap["scaleWithParent"].isValid()) {
|
||||||
|
scaleWithParent = propMap["scaleWithParent"].toBool();
|
||||||
if (jointName != "Mouse") {
|
} else if (propMap["scaleWithAvatar"].isValid()) {
|
||||||
// x = upward, y = forward, z = lateral
|
scaleWithParent = propMap["scaleWithAvatar"].toBool();
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
/**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.
|
* 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
|
* @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.
|
* will be considered colliding with the pick.
|
||||||
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or an overlay.
|
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick.
|
||||||
* @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 {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 {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) {
|
unsigned int PickScriptingInterface::createCollisionPick(const QVariant& properties) {
|
||||||
QVariantMap propMap = properties.toMap();
|
QVariantMap propMap = properties.toMap();
|
||||||
|
@ -294,9 +273,14 @@ unsigned int PickScriptingInterface::createCollisionPick(const QVariant& propert
|
||||||
maxDistance = propMap["maxDistance"].toFloat();
|
maxDistance = propMap["maxDistance"].toFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool scaleWithParent = true;
|
||||||
|
if (propMap["scaleWithParent"].isValid()) {
|
||||||
|
scaleWithParent = propMap["scaleWithParent"].toBool();
|
||||||
|
}
|
||||||
|
|
||||||
CollisionRegion collisionRegion(propMap);
|
CollisionRegion collisionRegion(propMap);
|
||||||
auto collisionPick = std::make_shared<CollisionPick>(filter, maxDistance, enabled, collisionRegion, qApp->getPhysicsEngine());
|
auto collisionPick = std::make_shared<CollisionPick>(filter, maxDistance, enabled, scaleWithParent, collisionRegion, qApp->getPhysicsEngine());
|
||||||
collisionPick->parentTransform = createTransformNode(propMap);
|
setParentTransform(collisionPick, propMap);
|
||||||
|
|
||||||
return DependencyManager::get<PickManager>()->addPick(PickQuery::Collision, collisionPick);
|
return DependencyManager::get<PickManager>()->addPick(PickQuery::Collision, collisionPick);
|
||||||
}
|
}
|
||||||
|
@ -373,51 +357,63 @@ void PickScriptingInterface::setPerFrameTimeBudget(unsigned int numUsecs) {
|
||||||
DependencyManager::get<PickManager>()->setPerFrameTimeBudget(numUsecs);
|
DependencyManager::get<PickManager>()->setPerFrameTimeBudget(numUsecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<TransformNode> PickScriptingInterface::createTransformNode(const QVariantMap& propMap) {
|
void PickScriptingInterface::setParentTransform(std::shared_ptr<PickQuery> pick, const QVariantMap& propMap) {
|
||||||
if (propMap["parentID"].isValid()) {
|
QUuid parentUuid;
|
||||||
QUuid parentUuid = propMap["parentID"].toUuid();
|
int parentJointIndex = 0;
|
||||||
if (!parentUuid.isNull()) {
|
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int pickID = propMap["parentID"].toUInt();
|
if (propMap["parentID"].isValid()) {
|
||||||
if (pickID != 0) {
|
parentUuid = propMap["parentID"].toUuid();
|
||||||
return std::make_shared<PickTransformNode>(pickID);
|
if (propMap["parentJointIndex"].isValid()) {
|
||||||
|
parentJointIndex = propMap["parentJointIndex"].toInt();
|
||||||
}
|
}
|
||||||
}
|
} else if (propMap["joint"].isValid()) {
|
||||||
|
|
||||||
if (propMap["joint"].isValid()) {
|
|
||||||
QString joint = propMap["joint"].toString();
|
QString joint = propMap["joint"].toString();
|
||||||
if (joint == "Mouse") {
|
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") {
|
} else if (joint == "Avatar") {
|
||||||
return std::make_shared<MyAvatarHeadTransformNode>();
|
pick->parentTransform = std::make_shared<MyAvatarHeadTransformNode>();
|
||||||
} else if (!joint.isNull()) {
|
return;
|
||||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
} else {
|
||||||
int jointIndex = myAvatar->getJointIndex(joint);
|
parentUuid = myAvatar->getSessionUUID();
|
||||||
return std::make_shared<AvatarTransformNode>(myAvatar, jointIndex);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -320,7 +320,7 @@ public slots:
|
||||||
static constexpr unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; }
|
static constexpr unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; }
|
||||||
|
|
||||||
protected:
|
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
|
#endif // hifi_PickScriptingInterface_h
|
||||||
|
|
|
@ -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} [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} [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} [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 {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,
|
* @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.
|
* the normal will follow exactly.
|
||||||
|
@ -134,9 +134,11 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope
|
||||||
distanceScaleEnd = propertyMap["distanceScaleEnd"].toBool();
|
distanceScaleEnd = propertyMap["distanceScaleEnd"].toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scaleWithAvatar = false;
|
bool scaleWithParent = false;
|
||||||
if (propertyMap["scaleWithAvatar"].isValid()) {
|
if (propertyMap["scaleWithParent"].isValid()) {
|
||||||
scaleWithAvatar = propertyMap["scaleWithAvatar"].toBool();
|
scaleWithParent = propertyMap["scaleWithParent"].toBool();
|
||||||
|
} else if (propertyMap["scaleWithAvatar"].isValid()) {
|
||||||
|
scaleWithParent = propertyMap["scaleWithAvatar"].toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool followNormal = false;
|
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,
|
return DependencyManager::get<PointerManager>()->addPointer(std::make_shared<LaserPointer>(properties, renderStates, defaultRenderStates, hover, triggers,
|
||||||
faceAvatar, followNormal, followNormalStrength, centerEndY, lockEnd,
|
faceAvatar, followNormal, followNormalStrength, centerEndY, lockEnd,
|
||||||
distanceScaleEnd, scaleWithAvatar, enabled));
|
distanceScaleEnd, scaleWithParent, enabled));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**jsdoc
|
/**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} [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} [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} [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 {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,
|
* @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.
|
* the normal will follow exactly.
|
||||||
|
@ -286,9 +288,11 @@ unsigned int PointerScriptingInterface::createParabolaPointer(const QVariant& pr
|
||||||
distanceScaleEnd = propertyMap["distanceScaleEnd"].toBool();
|
distanceScaleEnd = propertyMap["distanceScaleEnd"].toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scaleWithAvatar = false;
|
bool scaleWithParent = true;
|
||||||
if (propertyMap["scaleWithAvatar"].isValid()) {
|
if (propertyMap["scaleWithParent"].isValid()) {
|
||||||
scaleWithAvatar = propertyMap["scaleWithAvatar"].toBool();
|
scaleWithParent = propertyMap["scaleWithParent"].toBool();
|
||||||
|
} else if (propertyMap["scaleWithAvatar"].isValid()) {
|
||||||
|
scaleWithParent = propertyMap["scaleWithAvatar"].toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool followNormal = false;
|
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,
|
return DependencyManager::get<PointerManager>()->addPointer(std::make_shared<ParabolaPointer>(properties, renderStates, defaultRenderStates, hover, triggers,
|
||||||
faceAvatar, followNormal, followNormalStrength, centerEndY, lockEnd, distanceScaleEnd,
|
faceAvatar, followNormal, followNormalStrength, centerEndY, lockEnd, distanceScaleEnd,
|
||||||
scaleWithAvatar, enabled));
|
scaleWithParent, enabled));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PointerScriptingInterface::editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) const {
|
void PointerScriptingInterface::editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) const {
|
||||||
|
|
|
@ -15,6 +15,17 @@
|
||||||
#include "DependencyManager.h"
|
#include "DependencyManager.h"
|
||||||
#include "PickManager.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) {
|
PickResultPointer RayPick::getEntityIntersection(const PickRay& pick) {
|
||||||
bool precisionPicking = !(getFilter().doesPickCoarse() || DependencyManager::get<PickManager>()->getForceCoarsePicking());
|
bool precisionPicking = !(getFilter().doesPickCoarse() || DependencyManager::get<PickManager>()->getForceCoarsePicking());
|
||||||
RayToEntityIntersectionResult entityRes =
|
RayToEntityIntersectionResult entityRes =
|
||||||
|
|
|
@ -70,7 +70,11 @@ public:
|
||||||
class RayPick : public Pick<PickRay> {
|
class RayPick : public Pick<PickRay> {
|
||||||
|
|
||||||
public:
|
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 getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared<RayPickResult>(pickVariant); }
|
||||||
PickResultPointer getEntityIntersection(const PickRay& pick) override;
|
PickResultPointer getEntityIntersection(const PickRay& pick) override;
|
||||||
|
|
|
@ -16,10 +16,6 @@
|
||||||
|
|
||||||
#include <PickManager.h>
|
#include <PickManager.h>
|
||||||
|
|
||||||
#include "StaticRayPick.h"
|
|
||||||
#include "JointRayPick.h"
|
|
||||||
#include "MouseRayPick.h"
|
|
||||||
|
|
||||||
unsigned int RayPickScriptingInterface::createRayPick(const QVariant& properties) {
|
unsigned int RayPickScriptingInterface::createRayPick(const QVariant& properties) {
|
||||||
return DependencyManager::get<PickScriptingInterface>()->createRayPick(properties);
|
return DependencyManager::get<PickScriptingInterface>()->createRayPick(properties);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -65,8 +65,7 @@ bool StylusPickResult::checkOrFilterAgainstMaxDistance(float maxDistance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
StylusPick::StylusPick(Side side, const PickFilter& filter, float maxDistance, bool enabled) :
|
StylusPick::StylusPick(Side side, const PickFilter& filter, float maxDistance, bool enabled) :
|
||||||
Pick(filter, maxDistance, enabled),
|
Pick(StylusTip(side), filter, maxDistance, enabled)
|
||||||
_side(side)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,9 +129,9 @@ static StylusTip getControllerWorldLocation(Side side) {
|
||||||
StylusTip StylusPick::getMathematicalPick() const {
|
StylusTip StylusPick::getMathematicalPick() const {
|
||||||
StylusTip result;
|
StylusTip result;
|
||||||
if (qApp->getPreferAvatarFingerOverStylus()) {
|
if (qApp->getPreferAvatarFingerOverStylus()) {
|
||||||
result = getFingerWorldLocation(_side);
|
result = getFingerWorldLocation(_mathPick.side);
|
||||||
} else {
|
} else {
|
||||||
result = getControllerWorldLocation(_side);
|
result = getControllerWorldLocation(_mathPick.side);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,11 +68,9 @@ public:
|
||||||
PickResultPointer getHUDIntersection(const StylusTip& pick) override;
|
PickResultPointer getHUDIntersection(const StylusTip& pick) override;
|
||||||
Transform getResultTransform() const override;
|
Transform getResultTransform() const override;
|
||||||
|
|
||||||
bool isLeftHand() const override { return _side == Side::Left; }
|
bool isLeftHand() const override { return _mathPick.side == Side::Left; }
|
||||||
bool isRightHand() const override { return _side == Side::Right; }
|
bool isRightHand() const override { return _mathPick.side == Side::Right; }
|
||||||
|
bool isMouse() const override { return false; }
|
||||||
private:
|
|
||||||
const Side _side;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_StylusPick_h
|
#endif // hifi_StylusPick_h
|
|
@ -39,6 +39,7 @@ WindowScriptingInterface::WindowScriptingInterface() {
|
||||||
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &WindowScriptingInterface::disconnectedFromDomain);
|
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &WindowScriptingInterface::disconnectedFromDomain);
|
||||||
|
|
||||||
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &WindowScriptingInterface::domainConnectionRefused);
|
connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &WindowScriptingInterface::domainConnectionRefused);
|
||||||
|
connect(&domainHandler, &DomainHandler::redirectErrorStateChanged, this, &WindowScriptingInterface::redirectErrorStateChanged);
|
||||||
|
|
||||||
connect(qApp, &Application::svoImportRequested, [this](const QString& urlString) {
|
connect(qApp, &Application::svoImportRequested, [this](const QString& urlString) {
|
||||||
static const QMetaMethod svoImportRequestedSignal =
|
static const QMetaMethod svoImportRequestedSignal =
|
||||||
|
|
|
@ -611,6 +611,14 @@ signals:
|
||||||
*/
|
*/
|
||||||
void domainConnectionRefused(const QString& reasonMessage, int reasonCode, const QString& extraInfo);
|
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
|
/**jsdoc
|
||||||
* Triggered when a still snapshot has been taken by calling {@link Window.takeSnapshot|takeSnapshot} with
|
* Triggered when a still snapshot has been taken by calling {@link Window.takeSnapshot|takeSnapshot} with
|
||||||
* <code>includeAnimated = false</code> or {@link Window.takeSecondaryCameraSnapshot|takeSecondaryCameraSnapshot}.
|
* <code>includeAnimated = false</code> or {@link Window.takeSecondaryCameraSnapshot|takeSecondaryCameraSnapshot}.
|
||||||
|
|
|
@ -118,14 +118,24 @@ AvatarTransit::Status AvatarTransit::update(float deltaTime, const glm::vec3& av
|
||||||
float oneFrameDistance = glm::length(currentPosition - _lastPosition);
|
float oneFrameDistance = glm::length(currentPosition - _lastPosition);
|
||||||
const float MAX_TRANSIT_DISTANCE = 30.0f;
|
const float MAX_TRANSIT_DISTANCE = 30.0f;
|
||||||
float scaledMaxTransitDistance = MAX_TRANSIT_DISTANCE * _scale;
|
float scaledMaxTransitDistance = MAX_TRANSIT_DISTANCE * _scale;
|
||||||
if (oneFrameDistance > config._triggerDistance && oneFrameDistance < scaledMaxTransitDistance && !_isTransiting) {
|
if (oneFrameDistance > config._triggerDistance && !_isTransiting) {
|
||||||
start(deltaTime, _lastPosition, currentPosition, config);
|
if (oneFrameDistance < scaledMaxTransitDistance) {
|
||||||
|
start(deltaTime, _lastPosition, currentPosition, config);
|
||||||
|
} else {
|
||||||
|
_lastPosition = currentPosition;
|
||||||
|
return Status::ABORT_TRANSIT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_lastPosition = currentPosition;
|
_lastPosition = currentPosition;
|
||||||
_status = updatePosition(deltaTime);
|
_status = updatePosition(deltaTime);
|
||||||
return _status;
|
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) {
|
void AvatarTransit::start(float deltaTime, const glm::vec3& startPosition, const glm::vec3& endPosition, const AvatarTransit::TransitConfig& config) {
|
||||||
_startPosition = startPosition;
|
_startPosition = startPosition;
|
||||||
_endPosition = endPosition;
|
_endPosition = endPosition;
|
||||||
|
@ -510,9 +520,13 @@ void Avatar::relayJointDataToChildren() {
|
||||||
modelEntity->setLocalJointTranslation(jointIndex, jointTranslation);
|
modelEntity->setLocalJointTranslation(jointIndex, jointTranslation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transform finalTransform;
|
||||||
Transform avatarTransform = _skeletonModel->getTransform();
|
Transform avatarTransform = _skeletonModel->getTransform();
|
||||||
avatarTransform.setScale(_skeletonModel->getScale());
|
Transform entityTransform = modelEntity->getLocalTransform();
|
||||||
modelEntity->setOverrideTransform(avatarTransform, _skeletonModel->getOffset());
|
Transform::mult(finalTransform, avatarTransform, entityTransform);
|
||||||
|
finalTransform.setScale(_skeletonModel->getScale());
|
||||||
|
modelEntity->setOverrideTransform(finalTransform, _skeletonModel->getOffset());
|
||||||
modelEntity->simulateRelayedJoints();
|
modelEntity->simulateRelayedJoints();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,8 @@ public:
|
||||||
IDLE = 0,
|
IDLE = 0,
|
||||||
START_TRANSIT,
|
START_TRANSIT,
|
||||||
TRANSITING,
|
TRANSITING,
|
||||||
END_TRANSIT
|
END_TRANSIT,
|
||||||
|
ABORT_TRANSIT
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EaseType {
|
enum EaseType {
|
||||||
|
@ -84,6 +85,7 @@ public:
|
||||||
glm::vec3 getEndPosition() { return _endPosition; }
|
glm::vec3 getEndPosition() { return _endPosition; }
|
||||||
float getTransitTime() { return _totalTime; }
|
float getTransitTime() { return _totalTime; }
|
||||||
void setScale(float scale) { _scale = scale; }
|
void setScale(float scale) { _scale = scale; }
|
||||||
|
void reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Status updatePosition(float deltaTime);
|
Status updatePosition(float deltaTime);
|
||||||
|
|
|
@ -206,11 +206,13 @@ float AvatarData::getDistanceBasedMinRotationDOT(glm::vec3 viewerPosition) const
|
||||||
if (distance < AVATAR_DISTANCE_LEVEL_1) {
|
if (distance < AVATAR_DISTANCE_LEVEL_1) {
|
||||||
result = AVATAR_MIN_ROTATION_DOT;
|
result = AVATAR_MIN_ROTATION_DOT;
|
||||||
} else if (distance < AVATAR_DISTANCE_LEVEL_2) {
|
} else if (distance < AVATAR_DISTANCE_LEVEL_2) {
|
||||||
result = ROTATION_CHANGE_15D;
|
result = ROTATION_CHANGE_2D;
|
||||||
} else if (distance < AVATAR_DISTANCE_LEVEL_3) {
|
} else if (distance < AVATAR_DISTANCE_LEVEL_3) {
|
||||||
result = ROTATION_CHANGE_45D;
|
result = ROTATION_CHANGE_4D;
|
||||||
} else if (distance < AVATAR_DISTANCE_LEVEL_4) {
|
} else if (distance < AVATAR_DISTANCE_LEVEL_4) {
|
||||||
result = ROTATION_CHANGE_90D;
|
result = ROTATION_CHANGE_6D;
|
||||||
|
} else if (distance < AVATAR_DISTANCE_LEVEL_5) {
|
||||||
|
result = ROTATION_CHANGE_15D;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -594,7 +596,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
||||||
// The dot product for larger rotations is a lower number.
|
// The dot product for larger rotations is a lower number.
|
||||||
// So if the dot() is less than the value, then the rotation is a larger angle of rotation
|
// So if the dot() is less than the value, then the rotation is a larger angle of rotation
|
||||||
if (sendAll || last.rotationIsDefaultPose || (!cullSmallChanges && last.rotation != data.rotation)
|
if (sendAll || last.rotationIsDefaultPose || (!cullSmallChanges && last.rotation != data.rotation)
|
||||||
|| (cullSmallChanges && glm::dot(last.rotation, data.rotation) < minRotationDOT) ) {
|
|| (cullSmallChanges && fabsf(glm::dot(last.rotation, data.rotation)) < minRotationDOT) ) {
|
||||||
validity |= (1 << validityBit);
|
validity |= (1 << validityBit);
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
rotationSentCount++;
|
rotationSentCount++;
|
||||||
|
@ -1802,15 +1804,24 @@ QUrl AvatarData::getWireSafeSkeletonModelURL() const {
|
||||||
|
|
||||||
qint64 AvatarData::packTrait(AvatarTraits::TraitType traitType, ExtendedIODevice& destination,
|
qint64 AvatarData::packTrait(AvatarTraits::TraitType traitType, ExtendedIODevice& destination,
|
||||||
AvatarTraits::TraitVersion traitVersion) {
|
AvatarTraits::TraitVersion traitVersion) {
|
||||||
qint64 bytesWritten = 0;
|
|
||||||
bytesWritten += destination.writePrimitive(traitType);
|
|
||||||
|
|
||||||
if (traitVersion > AvatarTraits::DEFAULT_TRAIT_VERSION) {
|
qint64 bytesWritten = 0;
|
||||||
bytesWritten += destination.writePrimitive(traitVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (traitType == AvatarTraits::SkeletonModelURL) {
|
if (traitType == AvatarTraits::SkeletonModelURL) {
|
||||||
|
|
||||||
QByteArray encodedSkeletonURL = getWireSafeSkeletonModelURL().toEncoded();
|
QByteArray encodedSkeletonURL = getWireSafeSkeletonModelURL().toEncoded();
|
||||||
|
|
||||||
|
if (encodedSkeletonURL.size() > AvatarTraits::MAXIMUM_TRAIT_SIZE) {
|
||||||
|
qWarning() << "Refusing to pack simple trait" << traitType << "of size" << encodedSkeletonURL.size()
|
||||||
|
<< "bytes since it exceeds the maximum size" << AvatarTraits::MAXIMUM_TRAIT_SIZE << "bytes";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesWritten += destination.writePrimitive(traitType);
|
||||||
|
|
||||||
|
if (traitVersion > AvatarTraits::DEFAULT_TRAIT_VERSION) {
|
||||||
|
bytesWritten += destination.writePrimitive(traitVersion);
|
||||||
|
}
|
||||||
|
|
||||||
AvatarTraits::TraitWireSize encodedURLSize = encodedSkeletonURL.size();
|
AvatarTraits::TraitWireSize encodedURLSize = encodedSkeletonURL.size();
|
||||||
bytesWritten += destination.writePrimitive(encodedURLSize);
|
bytesWritten += destination.writePrimitive(encodedURLSize);
|
||||||
|
@ -1825,14 +1836,6 @@ qint64 AvatarData::packTraitInstance(AvatarTraits::TraitType traitType, AvatarTr
|
||||||
ExtendedIODevice& destination, AvatarTraits::TraitVersion traitVersion) {
|
ExtendedIODevice& destination, AvatarTraits::TraitVersion traitVersion) {
|
||||||
qint64 bytesWritten = 0;
|
qint64 bytesWritten = 0;
|
||||||
|
|
||||||
bytesWritten += destination.writePrimitive(traitType);
|
|
||||||
|
|
||||||
if (traitVersion > AvatarTraits::DEFAULT_TRAIT_VERSION) {
|
|
||||||
bytesWritten += destination.writePrimitive(traitVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
bytesWritten += destination.write(traitInstanceID.toRfc4122());
|
|
||||||
|
|
||||||
if (traitType == AvatarTraits::AvatarEntity) {
|
if (traitType == AvatarTraits::AvatarEntity) {
|
||||||
// grab a read lock on the avatar entities and check for entity data for the given ID
|
// grab a read lock on the avatar entities and check for entity data for the given ID
|
||||||
QByteArray entityBinaryData;
|
QByteArray entityBinaryData;
|
||||||
|
@ -1843,6 +1846,20 @@ qint64 AvatarData::packTraitInstance(AvatarTraits::TraitType traitType, AvatarTr
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (entityBinaryData.size() > AvatarTraits::MAXIMUM_TRAIT_SIZE) {
|
||||||
|
qWarning() << "Refusing to pack instanced trait" << traitType << "of size" << entityBinaryData.size()
|
||||||
|
<< "bytes since it exceeds the maximum size " << AvatarTraits::MAXIMUM_TRAIT_SIZE << "bytes";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesWritten += destination.writePrimitive(traitType);
|
||||||
|
|
||||||
|
if (traitVersion > AvatarTraits::DEFAULT_TRAIT_VERSION) {
|
||||||
|
bytesWritten += destination.writePrimitive(traitVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesWritten += destination.write(traitInstanceID.toRfc4122());
|
||||||
|
|
||||||
if (!entityBinaryData.isNull()) {
|
if (!entityBinaryData.isNull()) {
|
||||||
AvatarTraits::TraitWireSize entityBinarySize = entityBinaryData.size();
|
AvatarTraits::TraitWireSize entityBinarySize = entityBinaryData.size();
|
||||||
|
|
||||||
|
|
|
@ -309,16 +309,19 @@ const float AVATAR_SEND_FULL_UPDATE_RATIO = 0.02f;
|
||||||
const float AVATAR_MIN_ROTATION_DOT = 0.9999999f;
|
const float AVATAR_MIN_ROTATION_DOT = 0.9999999f;
|
||||||
const float AVATAR_MIN_TRANSLATION = 0.0001f;
|
const float AVATAR_MIN_TRANSLATION = 0.0001f;
|
||||||
|
|
||||||
const float ROTATION_CHANGE_15D = 0.9914449f;
|
// quaternion dot products
|
||||||
const float ROTATION_CHANGE_45D = 0.9238795f;
|
const float ROTATION_CHANGE_2D = 0.99984770f; // 2 degrees
|
||||||
const float ROTATION_CHANGE_90D = 0.7071068f;
|
const float ROTATION_CHANGE_4D = 0.99939083f; // 4 degrees
|
||||||
const float ROTATION_CHANGE_179D = 0.0087266f;
|
const float ROTATION_CHANGE_6D = 0.99862953f; // 6 degrees
|
||||||
|
const float ROTATION_CHANGE_15D = 0.99144486f; // 15 degrees
|
||||||
const float AVATAR_DISTANCE_LEVEL_1 = 10.0f;
|
const float ROTATION_CHANGE_179D = 0.00872653f; // 179 degrees
|
||||||
const float AVATAR_DISTANCE_LEVEL_2 = 100.0f;
|
|
||||||
const float AVATAR_DISTANCE_LEVEL_3 = 1000.0f;
|
|
||||||
const float AVATAR_DISTANCE_LEVEL_4 = 10000.0f;
|
|
||||||
|
|
||||||
|
// rotation culling distance thresholds
|
||||||
|
const float AVATAR_DISTANCE_LEVEL_1 = 12.5f; // meters
|
||||||
|
const float AVATAR_DISTANCE_LEVEL_2 = 16.6f; // meters
|
||||||
|
const float AVATAR_DISTANCE_LEVEL_3 = 25.0f; // meters
|
||||||
|
const float AVATAR_DISTANCE_LEVEL_4 = 50.0f; // meters
|
||||||
|
const float AVATAR_DISTANCE_LEVEL_5 = 200.0f; // meters
|
||||||
|
|
||||||
// Where one's own Avatar begins in the world (will be overwritten if avatar data file is found).
|
// Where one's own Avatar begins in the world (will be overwritten if avatar data file is found).
|
||||||
// This is the start location in the Sandbox (xyz: 6270, 211, 6000).
|
// This is the start location in the Sandbox (xyz: 6270, 211, 6000).
|
||||||
|
@ -1190,6 +1193,9 @@ public:
|
||||||
void setReplicaIndex(int replicaIndex) { _replicaIndex = replicaIndex; }
|
void setReplicaIndex(int replicaIndex) { _replicaIndex = replicaIndex; }
|
||||||
int getReplicaIndex() { return _replicaIndex; }
|
int getReplicaIndex() { return _replicaIndex; }
|
||||||
|
|
||||||
|
void setIsNewAvatar(bool isNewAvatar) { _isNewAvatar = isNewAvatar; }
|
||||||
|
bool getIsNewAvatar() { return _isNewAvatar; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
@ -1452,6 +1458,7 @@ protected:
|
||||||
bool _hasProcessedFirstIdentity { false };
|
bool _hasProcessedFirstIdentity { false };
|
||||||
float _density;
|
float _density;
|
||||||
int _replicaIndex { 0 };
|
int _replicaIndex { 0 };
|
||||||
|
bool _isNewAvatar { true };
|
||||||
|
|
||||||
// null unless MyAvatar or ScriptableAvatar sending traits data to mixer
|
// null unless MyAvatar or ScriptableAvatar sending traits data to mixer
|
||||||
std::unique_ptr<ClientTraitsHandler> _clientTraitsHandler;
|
std::unique_ptr<ClientTraitsHandler> _clientTraitsHandler;
|
||||||
|
|
|
@ -259,18 +259,20 @@ AvatarSharedPointer AvatarHashMap::parseAvatarData(QSharedPointer<ReceivedMessag
|
||||||
if (isNewAvatar) {
|
if (isNewAvatar) {
|
||||||
QWriteLocker locker(&_hashLock);
|
QWriteLocker locker(&_hashLock);
|
||||||
_pendingAvatars.insert(sessionUUID, { std::chrono::steady_clock::now(), 0, avatar });
|
_pendingAvatars.insert(sessionUUID, { std::chrono::steady_clock::now(), 0, avatar });
|
||||||
|
avatar->setIsNewAvatar(true);
|
||||||
auto replicaIDs = _replicas.getReplicaIDs(sessionUUID);
|
auto replicaIDs = _replicas.getReplicaIDs(sessionUUID);
|
||||||
for (auto replicaID : replicaIDs) {
|
for (auto replicaID : replicaIDs) {
|
||||||
auto replicaAvatar = addAvatar(replicaID, sendingNode);
|
auto replicaAvatar = addAvatar(replicaID, sendingNode);
|
||||||
|
replicaAvatar->setIsNewAvatar(true);
|
||||||
_replicas.addReplica(sessionUUID, replicaAvatar);
|
_replicas.addReplica(sessionUUID, replicaAvatar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// have the matching (or new) avatar parse the data from the packet
|
// have the matching (or new) avatar parse the data from the packet
|
||||||
int bytesRead = avatar->parseDataFromBuffer(byteArray);
|
int bytesRead = avatar->parseDataFromBuffer(byteArray);
|
||||||
message->seek(positionBeforeRead + bytesRead);
|
message->seek(positionBeforeRead + bytesRead);
|
||||||
_replicas.parseDataFromBuffer(sessionUUID, byteArray);
|
_replicas.parseDataFromBuffer(sessionUUID, byteArray);
|
||||||
|
|
||||||
|
|
||||||
return avatar;
|
return avatar;
|
||||||
} else {
|
} else {
|
||||||
|
@ -337,7 +339,7 @@ void AvatarHashMap::processBulkAvatarTraits(QSharedPointer<ReceivedMessage> mess
|
||||||
// grab the last trait versions for this avatar
|
// grab the last trait versions for this avatar
|
||||||
auto& lastProcessedVersions = _processedTraitVersions[avatarID];
|
auto& lastProcessedVersions = _processedTraitVersions[avatarID];
|
||||||
|
|
||||||
while (traitType != AvatarTraits::NullTrait) {
|
while (traitType != AvatarTraits::NullTrait && message->getBytesLeftToRead() > 0) {
|
||||||
AvatarTraits::TraitVersion packetTraitVersion;
|
AvatarTraits::TraitVersion packetTraitVersion;
|
||||||
message->readPrimitive(&packetTraitVersion);
|
message->readPrimitive(&packetTraitVersion);
|
||||||
|
|
||||||
|
@ -378,7 +380,7 @@ void AvatarHashMap::processBulkAvatarTraits(QSharedPointer<ReceivedMessage> mess
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skipBinaryTrait) {
|
if (skipBinaryTrait && traitBinarySize > 0) {
|
||||||
// we didn't read this trait because it was older or because we didn't have an avatar to process it for
|
// we didn't read this trait because it was older or because we didn't have an avatar to process it for
|
||||||
message->seek(message->getPosition() + traitBinarySize);
|
message->seek(message->getPosition() + traitBinarySize);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ namespace AvatarTraits {
|
||||||
|
|
||||||
using TraitWireSize = int16_t;
|
using TraitWireSize = int16_t;
|
||||||
const TraitWireSize DELETED_TRAIT_SIZE = -1;
|
const TraitWireSize DELETED_TRAIT_SIZE = -1;
|
||||||
|
const TraitWireSize MAXIMUM_TRAIT_SIZE = INT16_MAX;
|
||||||
|
|
||||||
inline qint64 packInstancedTraitDelete(TraitType traitType, TraitInstanceID instanceID, ExtendedIODevice& destination,
|
inline qint64 packInstancedTraitDelete(TraitType traitType, TraitInstanceID instanceID, ExtendedIODevice& destination,
|
||||||
TraitVersion traitVersion = NULL_TRAIT_VERSION) {
|
TraitVersion traitVersion = NULL_TRAIT_VERSION) {
|
||||||
|
|
|
@ -310,10 +310,10 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r
|
||||||
}
|
}
|
||||||
|
|
||||||
auto entityID = entity->getEntityItemID();
|
auto entityID = entity->getEntityItemID();
|
||||||
processedIds.insert(entityID);
|
|
||||||
auto renderable = EntityRenderer::addToScene(*this, entity, scene, transaction);
|
auto renderable = EntityRenderer::addToScene(*this, entity, scene, transaction);
|
||||||
if (renderable) {
|
if (renderable) {
|
||||||
_entitiesInScene.insert({ entityID, renderable });
|
_entitiesInScene.insert({ entityID, renderable });
|
||||||
|
processedIds.insert(entityID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -315,6 +315,14 @@ void RenderableModelEntityItem::getCollisionGeometryResource() {
|
||||||
_compoundShapeResource = DependencyManager::get<ModelCache>()->getCollisionGeometryResource(hullURL);
|
_compoundShapeResource = DependencyManager::get<ModelCache>()->getCollisionGeometryResource(hullURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RenderableModelEntityItem::computeShapeFailedToLoad() {
|
||||||
|
if (!_compoundShapeResource) {
|
||||||
|
getCollisionGeometryResource();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (_compoundShapeResource && _compoundShapeResource->isFailed());
|
||||||
|
}
|
||||||
|
|
||||||
void RenderableModelEntityItem::setShapeType(ShapeType type) {
|
void RenderableModelEntityItem::setShapeType(ShapeType type) {
|
||||||
ModelEntityItem::setShapeType(type);
|
ModelEntityItem::setShapeType(type);
|
||||||
if (getShapeType() == SHAPE_TYPE_COMPOUND) {
|
if (getShapeType() == SHAPE_TYPE_COMPOUND) {
|
||||||
|
@ -343,7 +351,6 @@ void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) {
|
||||||
|
|
||||||
bool RenderableModelEntityItem::isReadyToComputeShape() const {
|
bool RenderableModelEntityItem::isReadyToComputeShape() const {
|
||||||
ShapeType type = getShapeType();
|
ShapeType type = getShapeType();
|
||||||
|
|
||||||
auto model = getModel();
|
auto model = getModel();
|
||||||
if (type == SHAPE_TYPE_COMPOUND) {
|
if (type == SHAPE_TYPE_COMPOUND) {
|
||||||
if (!model || getCompoundShapeURL().isEmpty()) {
|
if (!model || getCompoundShapeURL().isEmpty()) {
|
||||||
|
|
|
@ -81,6 +81,7 @@ public:
|
||||||
|
|
||||||
virtual bool isReadyToComputeShape() const override;
|
virtual bool isReadyToComputeShape() const override;
|
||||||
virtual void computeShapeInfo(ShapeInfo& shapeInfo) override;
|
virtual void computeShapeInfo(ShapeInfo& shapeInfo) override;
|
||||||
|
bool computeShapeFailedToLoad();
|
||||||
|
|
||||||
virtual bool contains(const glm::vec3& point) const override;
|
virtual bool contains(const glm::vec3& point) const override;
|
||||||
void stopModelOverrideIfNoParent();
|
void stopModelOverrideIfNoParent();
|
||||||
|
|
|
@ -104,6 +104,10 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
|
||||||
_networkTexture.reset();
|
_networkTexture.reset();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
withWriteLock([&] {
|
||||||
|
entity->setVisuallyReady(true);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
bool textureNeedsUpdate = resultWithReadLock<bool>([&]{
|
bool textureNeedsUpdate = resultWithReadLock<bool>([&]{
|
||||||
return !_networkTexture || _networkTexture->getURL() != QUrl(_particleProperties.textures);
|
return !_networkTexture || _networkTexture->getURL() != QUrl(_particleProperties.textures);
|
||||||
|
@ -113,6 +117,12 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
|
||||||
_networkTexture = DependencyManager::get<TextureCache>()->getTexture(_particleProperties.textures);
|
_networkTexture = DependencyManager::get<TextureCache>()->getTexture(_particleProperties.textures);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_networkTexture) {
|
||||||
|
withWriteLock([&] {
|
||||||
|
entity->setVisuallyReady(_networkTexture->isFailed() || _networkTexture->isLoaded());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* key = (void*)this;
|
void* key = (void*)this;
|
||||||
|
|
|
@ -1754,8 +1754,9 @@ int EntityScriptingInterface::getJointIndex(const QUuid& entityID, const QString
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int result;
|
int result;
|
||||||
BLOCKING_INVOKE_METHOD(_entityTree.get(), "getJointIndex",
|
_entityTree->withReadLock([&] {
|
||||||
Q_RETURN_ARG(int, result), Q_ARG(QUuid, entityID), Q_ARG(QString, name));
|
result = _entityTree->getJointIndex(entityID, name);
|
||||||
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1764,8 +1765,9 @@ QStringList EntityScriptingInterface::getJointNames(const QUuid& entityID) {
|
||||||
return QStringList();
|
return QStringList();
|
||||||
}
|
}
|
||||||
QStringList result;
|
QStringList result;
|
||||||
BLOCKING_INVOKE_METHOD(_entityTree.get(), "getJointNames",
|
_entityTree->withReadLock([&] {
|
||||||
Q_RETURN_ARG(QStringList, result), Q_ARG(QUuid, entityID));
|
result = _entityTree->getJointNames(entityID);
|
||||||
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ protected:
|
||||||
QMutex _dynamicsMutex { QMutex::Recursive };
|
QMutex _dynamicsMutex { QMutex::Recursive };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SetOfEntities _deadEntities;
|
SetOfEntities _deadEntities; // dead entities that might still be in the _entityTree
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void moveSimpleKinematics();
|
void moveSimpleKinematics();
|
||||||
|
|
|
@ -162,6 +162,7 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte
|
||||||
EntityItem(entityItemID)
|
EntityItem(entityItemID)
|
||||||
{
|
{
|
||||||
_type = EntityTypes::ParticleEffect;
|
_type = EntityTypes::ParticleEffect;
|
||||||
|
_visuallyReady = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleEffectEntityItem::setAlpha(float alpha) {
|
void ParticleEffectEntityItem::setAlpha(float alpha) {
|
||||||
|
@ -747,4 +748,4 @@ particle::Properties ParticleEffectEntityItem::getParticleProperties() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,11 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) {
|
||||||
QString materialMapString = mapping.value("materialMap").toString();
|
QString materialMapString = mapping.value("materialMap").toString();
|
||||||
QJsonDocument materialMapDocument = QJsonDocument::fromJson(materialMapString.toUtf8());
|
QJsonDocument materialMapDocument = QJsonDocument::fromJson(materialMapString.toUtf8());
|
||||||
QJsonObject materialMap = materialMapDocument.object();
|
QJsonObject materialMap = materialMapDocument.object();
|
||||||
|
if (!materialMapString.isEmpty()) {
|
||||||
|
if (materialMapDocument.isEmpty() || materialMap.isEmpty()) {
|
||||||
|
qCDebug(modelformat) << "fbx Material Map found but did not produce valid JSON:" << materialMapString;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (QHash<QString, FBXMaterial>::iterator it = _fbxMaterials.begin(); it != _fbxMaterials.end(); it++) {
|
for (QHash<QString, FBXMaterial>::iterator it = _fbxMaterials.begin(); it != _fbxMaterials.end(); it++) {
|
||||||
FBXMaterial& material = (*it);
|
FBXMaterial& material = (*it);
|
||||||
|
|
||||||
|
|
|
@ -585,7 +585,6 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
|
||||||
|
|
||||||
FBXMesh& fbxMesh = extractedMesh;
|
FBXMesh& fbxMesh = extractedMesh;
|
||||||
graphics::MeshPointer mesh(new graphics::Mesh());
|
graphics::MeshPointer mesh(new graphics::Mesh());
|
||||||
bool hasBlendShapes = !fbxMesh.blendshapes.empty();
|
|
||||||
int numVerts = extractedMesh.vertices.size();
|
int numVerts = extractedMesh.vertices.size();
|
||||||
|
|
||||||
if (!fbxMesh.normals.empty() && fbxMesh.tangents.empty()) {
|
if (!fbxMesh.normals.empty() && fbxMesh.tangents.empty()) {
|
||||||
|
@ -618,7 +617,6 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
|
||||||
qWarning() << "Unexpected tangents in " << url;
|
qWarning() << "Unexpected tangents in " << url;
|
||||||
}
|
}
|
||||||
const auto normalsAndTangentsSize = normalsSize + tangentsSize;
|
const auto normalsAndTangentsSize = normalsSize + tangentsSize;
|
||||||
const int normalsAndTangentsStride = 2 * normalElement.getSize();
|
|
||||||
|
|
||||||
// Color attrib
|
// Color attrib
|
||||||
const auto colorElement = FBX_COLOR_ELEMENT;
|
const auto colorElement = FBX_COLOR_ELEMENT;
|
||||||
|
@ -761,33 +759,7 @@ void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
|
||||||
bool interleavePositions = true;
|
bool interleavePositions = true;
|
||||||
bool interleaveNormalsTangents = true;
|
bool interleaveNormalsTangents = true;
|
||||||
|
|
||||||
// TODO: We are using the same vertex format layout for all meshes because this is more efficient
|
// Define the vertex format, compute the offset for each attributes as we append them to the vertex format
|
||||||
// This work is going into rc73 release which is meant to be used for the SPot500 event and we are picking the format
|
|
||||||
// that works best for blendshaped and skinned meshes aka the avatars.
|
|
||||||
// We will improve this technique in a hot fix to 73.
|
|
||||||
hasBlendShapes = true;
|
|
||||||
|
|
||||||
// If has blend shapes allocate and assign buffers for pos and tangents now
|
|
||||||
if (hasBlendShapes) {
|
|
||||||
auto posBuffer = std::make_shared<gpu::Buffer>();
|
|
||||||
posBuffer->setData(positionsSize, (const gpu::Byte*) vertBuffer->getData() + positionsOffset);
|
|
||||||
vertexBufferStream->addBuffer(posBuffer, 0, positionElement.getSize());
|
|
||||||
|
|
||||||
auto normalsAndTangentsBuffer = std::make_shared<gpu::Buffer>();
|
|
||||||
normalsAndTangentsBuffer->setData(normalsAndTangentsSize, (const gpu::Byte*) vertBuffer->getData() + normalsAndTangentsOffset);
|
|
||||||
vertexBufferStream->addBuffer(normalsAndTangentsBuffer, 0, normalsAndTangentsStride);
|
|
||||||
|
|
||||||
// update channels and attribBuffer size accordingly
|
|
||||||
interleavePositions = false;
|
|
||||||
interleaveNormalsTangents = false;
|
|
||||||
|
|
||||||
tangentChannel = 1;
|
|
||||||
attribChannel = 2;
|
|
||||||
|
|
||||||
totalAttribBufferSize = totalVertsSize - positionsSize - normalsAndTangentsSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define the vertex format, compute the offset for each attributes as we append them to the vertex format
|
|
||||||
gpu::Offset bufOffset = 0;
|
gpu::Offset bufOffset = 0;
|
||||||
if (positionsSize) {
|
if (positionsSize) {
|
||||||
vertexFormat->setAttribute(gpu::Stream::POSITION, posChannel, positionElement, bufOffset);
|
vertexFormat->setAttribute(gpu::Stream::POSITION, posChannel, positionElement, bufOffset);
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
#include "nvToolsExt.h"
|
#include "nvToolsExt.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Define the GPU_BATCH_DETAILED_TRACING to get detailed tracing of the commands during the batch executions
|
||||||
|
// #define GPU_BATCH_DETAILED_TRACING
|
||||||
|
|
||||||
#include <GPUIdent.h>
|
#include <GPUIdent.h>
|
||||||
|
|
||||||
#include "GLTexture.h"
|
#include "GLTexture.h"
|
||||||
|
@ -271,6 +274,9 @@ void GLBackend::renderPassDraw(const Batch& batch) {
|
||||||
case Batch::COMMAND_drawIndexedInstanced:
|
case Batch::COMMAND_drawIndexedInstanced:
|
||||||
case Batch::COMMAND_multiDrawIndirect:
|
case Batch::COMMAND_multiDrawIndirect:
|
||||||
case Batch::COMMAND_multiDrawIndexedIndirect: {
|
case Batch::COMMAND_multiDrawIndexedIndirect: {
|
||||||
|
#ifdef GPU_BATCH_DETAILED_TRACING
|
||||||
|
PROFILE_RANGE(render_gpu_gl_detail, "drawcall");
|
||||||
|
#endif
|
||||||
// updates for draw calls
|
// updates for draw calls
|
||||||
++_currentDraw;
|
++_currentDraw;
|
||||||
updateInput();
|
updateInput();
|
||||||
|
@ -281,6 +287,94 @@ void GLBackend::renderPassDraw(const Batch& batch) {
|
||||||
(this->*(call))(batch, *offset);
|
(this->*(call))(batch, *offset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifdef GPU_BATCH_DETAILED_TRACING
|
||||||
|
//case Batch::COMMAND_setModelTransform:
|
||||||
|
//case Batch::COMMAND_setViewTransform:
|
||||||
|
//case Batch::COMMAND_setProjectionTransform:
|
||||||
|
case Batch::COMMAND_setProjectionJitter:
|
||||||
|
case Batch::COMMAND_setViewportTransform:
|
||||||
|
case Batch::COMMAND_setDepthRangeTransform:
|
||||||
|
{
|
||||||
|
PROFILE_RANGE(render_gpu_gl_detail, "transform");
|
||||||
|
CommandCall call = _commandCalls[(*command)];
|
||||||
|
(this->*(call))(batch, *offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Batch::COMMAND_clearFramebuffer:
|
||||||
|
{
|
||||||
|
PROFILE_RANGE(render_gpu_gl_detail, "clear");
|
||||||
|
CommandCall call = _commandCalls[(*command)];
|
||||||
|
(this->*(call))(batch, *offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Batch::COMMAND_blit:
|
||||||
|
{
|
||||||
|
PROFILE_RANGE(render_gpu_gl_detail, "blit");
|
||||||
|
CommandCall call = _commandCalls[(*command)];
|
||||||
|
(this->*(call))(batch, *offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Batch::COMMAND_setInputFormat:
|
||||||
|
case Batch::COMMAND_setInputBuffer:
|
||||||
|
case Batch::COMMAND_setIndexBuffer:
|
||||||
|
case Batch::COMMAND_setIndirectBuffer: {
|
||||||
|
PROFILE_RANGE(render_gpu_gl_detail, "input");
|
||||||
|
CommandCall call = _commandCalls[(*command)];
|
||||||
|
(this->*(call))(batch, *offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Batch::COMMAND_setStateBlendFactor:
|
||||||
|
case Batch::COMMAND_setStateScissorRect:
|
||||||
|
case Batch::COMMAND_setPipeline: {
|
||||||
|
PROFILE_RANGE(render_gpu_gl_detail, "pipeline");
|
||||||
|
CommandCall call = _commandCalls[(*command)];
|
||||||
|
(this->*(call))(batch, *offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Batch::COMMAND_setUniformBuffer:
|
||||||
|
{
|
||||||
|
PROFILE_RANGE(render_gpu_gl_detail, "ubo");
|
||||||
|
CommandCall call = _commandCalls[(*command)];
|
||||||
|
(this->*(call))(batch, *offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Batch::COMMAND_setResourceBuffer:
|
||||||
|
case Batch::COMMAND_setResourceTexture:
|
||||||
|
case Batch::COMMAND_setResourceTextureTable:
|
||||||
|
{
|
||||||
|
PROFILE_RANGE(render_gpu_gl_detail, "resource");
|
||||||
|
CommandCall call = _commandCalls[(*command)];
|
||||||
|
(this->*(call))(batch, *offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Batch::COMMAND_setResourceFramebufferSwapChainTexture:
|
||||||
|
case Batch::COMMAND_setFramebuffer:
|
||||||
|
case Batch::COMMAND_setFramebufferSwapChain:
|
||||||
|
{
|
||||||
|
PROFILE_RANGE(render_gpu_gl_detail, "framebuffer");
|
||||||
|
CommandCall call = _commandCalls[(*command)];
|
||||||
|
(this->*(call))(batch, *offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Batch::COMMAND_generateTextureMips:
|
||||||
|
{
|
||||||
|
PROFILE_RANGE(render_gpu_gl_detail, "genMipMaps");
|
||||||
|
|
||||||
|
CommandCall call = _commandCalls[(*command)];
|
||||||
|
(this->*(call))(batch, *offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Batch::COMMAND_beginQuery:
|
||||||
|
case Batch::COMMAND_endQuery:
|
||||||
|
case Batch::COMMAND_getQuery:
|
||||||
|
{
|
||||||
|
PROFILE_RANGE(render_gpu_gl_detail, "query");
|
||||||
|
CommandCall call = _commandCalls[(*command)];
|
||||||
|
(this->*(call))(batch, *offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
default: {
|
default: {
|
||||||
CommandCall call = _commandCalls[(*command)];
|
CommandCall call = _commandCalls[(*command)];
|
||||||
(this->*(call))(batch, *offset);
|
(this->*(call))(batch, *offset);
|
||||||
|
@ -294,6 +388,8 @@ void GLBackend::renderPassDraw(const Batch& batch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::render(const Batch& batch) {
|
void GLBackend::render(const Batch& batch) {
|
||||||
|
PROFILE_RANGE(render_gpu_gl, batch.getName());
|
||||||
|
|
||||||
_transform._skybox = _stereo._skybox = batch.isSkyboxEnabled();
|
_transform._skybox = _stereo._skybox = batch.isSkyboxEnabled();
|
||||||
// Allow the batch to override the rendering stereo settings
|
// Allow the batch to override the rendering stereo settings
|
||||||
// for things like full framebuffer copy operations (deferred lighting passes)
|
// for things like full framebuffer copy operations (deferred lighting passes)
|
||||||
|
|
|
@ -20,7 +20,10 @@ namespace gpu {
|
||||||
|
|
||||||
~GL41Buffer() {
|
~GL41Buffer() {
|
||||||
if (_texBuffer) {
|
if (_texBuffer) {
|
||||||
glDeleteTextures(1, &_texBuffer);
|
auto backend = _backend.lock();
|
||||||
|
if (backend) {
|
||||||
|
backend->releaseTexture(_texBuffer, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,9 +61,9 @@ GLBuffer* GL45Backend::syncGPUObject(const Buffer& buffer) {
|
||||||
|
|
||||||
|
|
||||||
bool GL45Backend::bindResourceBuffer(uint32_t slot, const BufferPointer& buffer) {
|
bool GL45Backend::bindResourceBuffer(uint32_t slot, const BufferPointer& buffer) {
|
||||||
GLBuffer* object = syncGPUObject((*buffer));
|
auto bo = getBufferIDUnsynced((*buffer));
|
||||||
if (object) {
|
if (bo) {
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot, object->_id);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot, bo);
|
||||||
|
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,8 @@ void Batch::clear() {
|
||||||
_name = nullptr;
|
_name = nullptr;
|
||||||
_invalidModel = true;
|
_invalidModel = true;
|
||||||
_currentModel = Transform();
|
_currentModel = Transform();
|
||||||
|
_drawcallUniform = 0;
|
||||||
|
_drawcallUniformReset = 0;
|
||||||
_projectionJitter = glm::vec2(0.0f);
|
_projectionJitter = glm::vec2(0.0f);
|
||||||
_enableStereo = true;
|
_enableStereo = true;
|
||||||
_enableSkybox = false;
|
_enableSkybox = false;
|
||||||
|
@ -112,6 +114,13 @@ size_t Batch::cacheData(size_t size, const void* data) {
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Batch::setDrawcallUniform(uint16_t uniform) {
|
||||||
|
_drawcallUniform = uniform;
|
||||||
|
}
|
||||||
|
void Batch::setDrawcallUniformReset(uint16_t uniformReset) {
|
||||||
|
_drawcallUniformReset = uniformReset;
|
||||||
|
}
|
||||||
|
|
||||||
void Batch::draw(Primitive primitiveType, uint32 numVertices, uint32 startVertex) {
|
void Batch::draw(Primitive primitiveType, uint32 numVertices, uint32 startVertex) {
|
||||||
ADD_COMMAND(draw);
|
ADD_COMMAND(draw);
|
||||||
|
|
||||||
|
@ -545,7 +554,8 @@ void Batch::captureDrawCallInfoImpl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& drawCallInfos = getDrawCallInfoBuffer();
|
auto& drawCallInfos = getDrawCallInfoBuffer();
|
||||||
drawCallInfos.emplace_back((uint16)_objects.size() - 1);
|
drawCallInfos.emplace_back((uint16)_objects.size() - 1, _drawcallUniform);
|
||||||
|
_drawcallUniform = _drawcallUniformReset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::captureDrawCallInfo() {
|
void Batch::captureDrawCallInfo() {
|
||||||
|
@ -679,6 +689,8 @@ void Batch::_glColor4f(float red, float green, float blue, float alpha) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::finishFrame(BufferUpdates& updates) {
|
void Batch::finishFrame(BufferUpdates& updates) {
|
||||||
|
PROFILE_RANGE(render_gpu, __FUNCTION__);
|
||||||
|
|
||||||
for (auto& mapItem : _namedData) {
|
for (auto& mapItem : _namedData) {
|
||||||
auto& name = mapItem.first;
|
auto& name = mapItem.first;
|
||||||
auto& instance = mapItem.second;
|
auto& instance = mapItem.second;
|
||||||
|
@ -707,6 +719,7 @@ void Batch::finishFrame(BufferUpdates& updates) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::flush() {
|
void Batch::flush() {
|
||||||
|
PROFILE_RANGE(render_gpu, __FUNCTION__);
|
||||||
for (auto& mapItem : _namedData) {
|
for (auto& mapItem : _namedData) {
|
||||||
auto& name = mapItem.first;
|
auto& name = mapItem.first;
|
||||||
auto& instance = mapItem.second;
|
auto& instance = mapItem.second;
|
||||||
|
|
|
@ -48,6 +48,7 @@ public:
|
||||||
using Index = uint16_t;
|
using Index = uint16_t;
|
||||||
|
|
||||||
DrawCallInfo(Index idx) : index(idx) {}
|
DrawCallInfo(Index idx) : index(idx) {}
|
||||||
|
DrawCallInfo(Index idx, Index user) : index(idx), unused(user) {}
|
||||||
|
|
||||||
Index index { 0 };
|
Index index { 0 };
|
||||||
uint16_t unused { 0 }; // Reserved space for later
|
uint16_t unused { 0 }; // Reserved space for later
|
||||||
|
@ -95,6 +96,7 @@ public:
|
||||||
~Batch();
|
~Batch();
|
||||||
|
|
||||||
void setName(const char* name);
|
void setName(const char* name);
|
||||||
|
const char* getName() const { return _name; }
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
// Batches may need to override the context level stereo settings
|
// Batches may need to override the context level stereo settings
|
||||||
|
@ -110,6 +112,14 @@ public:
|
||||||
void enableSkybox(bool enable = true);
|
void enableSkybox(bool enable = true);
|
||||||
bool isSkyboxEnabled() const;
|
bool isSkyboxEnabled() const;
|
||||||
|
|
||||||
|
// Drawcall Uniform value
|
||||||
|
// One 16bit word uniform value is available during the drawcall
|
||||||
|
// its value must be set before each drawcall
|
||||||
|
void setDrawcallUniform(uint16 uniform);
|
||||||
|
// It is reset to the reset value between each drawcalls
|
||||||
|
// The reset value is 0 by default and can be changed as a batch state with this call
|
||||||
|
void setDrawcallUniformReset(uint16 resetUniform);
|
||||||
|
|
||||||
// Drawcalls
|
// Drawcalls
|
||||||
void draw(Primitive primitiveType, uint32 numVertices, uint32 startVertex = 0);
|
void draw(Primitive primitiveType, uint32 numVertices, uint32 startVertex = 0);
|
||||||
void drawIndexed(Primitive primitiveType, uint32 numIndices, uint32 startIndex = 0);
|
void drawIndexed(Primitive primitiveType, uint32 numIndices, uint32 startIndex = 0);
|
||||||
|
@ -498,6 +508,9 @@ public:
|
||||||
|
|
||||||
NamedBatchDataMap _namedData;
|
NamedBatchDataMap _namedData;
|
||||||
|
|
||||||
|
uint16_t _drawcallUniform{ 0 };
|
||||||
|
uint16_t _drawcallUniformReset{ 0 };
|
||||||
|
|
||||||
glm::vec2 _projectionJitter{ 0.0f, 0.0f };
|
glm::vec2 _projectionJitter{ 0.0f, 0.0f };
|
||||||
bool _enableStereo{ true };
|
bool _enableStereo{ true };
|
||||||
bool _enableSkybox { false };
|
bool _enableSkybox { false };
|
||||||
|
|
|
@ -84,6 +84,7 @@ void Context::appendFrameBatch(const BatchPointer& batch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FramePointer Context::endFrame() {
|
FramePointer Context::endFrame() {
|
||||||
|
PROFILE_RANGE(render_gpu, __FUNCTION__);
|
||||||
assert(_frameActive);
|
assert(_frameActive);
|
||||||
auto result = _currentFrame;
|
auto result = _currentFrame;
|
||||||
_currentFrame.reset();
|
_currentFrame.reset();
|
||||||
|
@ -101,10 +102,12 @@ void Context::executeBatch(Batch& batch) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::recycle() const {
|
void Context::recycle() const {
|
||||||
|
PROFILE_RANGE(render_gpu, __FUNCTION__);
|
||||||
_backend->recycle();
|
_backend->recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::consumeFrameUpdates(const FramePointer& frame) const {
|
void Context::consumeFrameUpdates(const FramePointer& frame) const {
|
||||||
|
PROFILE_RANGE(render_gpu, __FUNCTION__);
|
||||||
frame->preRender();
|
frame->preRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,14 @@ Frame::~Frame() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Frame::finish() {
|
void Frame::finish() {
|
||||||
|
PROFILE_RANGE(render_gpu, __FUNCTION__);
|
||||||
for (const auto& batch : batches) {
|
for (const auto& batch : batches) {
|
||||||
batch->finishFrame(bufferUpdates);
|
batch->finishFrame(bufferUpdates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Frame::preRender() {
|
void Frame::preRender() {
|
||||||
|
PROFILE_RANGE(render_gpu, __FUNCTION__);
|
||||||
for (auto& update : bufferUpdates) {
|
for (auto& update : bufferUpdates) {
|
||||||
update.apply();
|
update.apply();
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,18 @@ TransformObject getTransformObject() {
|
||||||
}
|
}
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
|
<@func transformModelToWorldAndEyeAndClipPos(cameraTransform, objectTransform, modelPos, worldPos, eyePos, clipPos)@>
|
||||||
|
{ // transformModelToEyeAndClipPos
|
||||||
|
vec4 eyeWAPos;
|
||||||
|
<$transformModelToEyeWorldAlignedPos($cameraTransform$, $objectTransform$, $modelPos$, eyeWAPos)$>
|
||||||
|
<$worldPos$> = vec4(eyeWAPos.xyz + <$cameraTransform$>._viewInverse[3].xyz, 1.0);
|
||||||
|
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos;
|
||||||
|
<$eyePos$> = vec4((<$cameraTransform$>._view * vec4(eyeWAPos.xyz, 0.0)).xyz, 1.0);
|
||||||
|
|
||||||
|
<$transformStereoClipsSpace($cameraTransform$, $clipPos$)$>
|
||||||
|
}
|
||||||
|
<@endfunc@>
|
||||||
|
|
||||||
<@func transformModelToEyePos(cameraTransform, objectTransform, modelPos, eyePos)@>
|
<@func transformModelToEyePos(cameraTransform, objectTransform, modelPos, eyePos)@>
|
||||||
{ // transformModelToEyePos
|
{ // transformModelToEyePos
|
||||||
vec4 eyeWAPos;
|
vec4 eyeWAPos;
|
||||||
|
|
|
@ -20,15 +20,11 @@ using namespace gpu;
|
||||||
Material::Material() :
|
Material::Material() :
|
||||||
_key(0),
|
_key(0),
|
||||||
_schemaBuffer(),
|
_schemaBuffer(),
|
||||||
_texMapArrayBuffer(),
|
|
||||||
_textureMaps()
|
_textureMaps()
|
||||||
{
|
{
|
||||||
// created from nothing: create the Buffer to store the properties
|
// created from nothing: create the Buffer to store the properties
|
||||||
Schema schema;
|
Schema schema;
|
||||||
_schemaBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Schema), (const gpu::Byte*) &schema));
|
_schemaBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Schema), (const gpu::Byte*) &schema, sizeof(Schema)));
|
||||||
|
|
||||||
TexMapArraySchema TexMapArraySchema;
|
|
||||||
_texMapArrayBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(TexMapArraySchema), (const gpu::Byte*) &TexMapArraySchema));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Material::Material(const Material& material) :
|
Material::Material(const Material& material) :
|
||||||
|
@ -38,12 +34,8 @@ Material::Material(const Material& material) :
|
||||||
{
|
{
|
||||||
// copied: create the Buffer to store the properties, avoid holding a ref to the old Buffer
|
// copied: create the Buffer to store the properties, avoid holding a ref to the old Buffer
|
||||||
Schema schema;
|
Schema schema;
|
||||||
_schemaBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Schema), (const gpu::Byte*) &schema));
|
_schemaBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Schema), (const gpu::Byte*) &schema, sizeof(Schema)));
|
||||||
_schemaBuffer.edit<Schema>() = material._schemaBuffer.get<Schema>();
|
_schemaBuffer.edit<Schema>() = material._schemaBuffer.get<Schema>();
|
||||||
|
|
||||||
TexMapArraySchema texMapArraySchema;
|
|
||||||
_texMapArrayBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(TexMapArraySchema), (const gpu::Byte*) &texMapArraySchema));
|
|
||||||
_texMapArrayBuffer.edit<TexMapArraySchema>() = material._texMapArrayBuffer.get<TexMapArraySchema>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Material& Material::operator= (const Material& material) {
|
Material& Material::operator= (const Material& material) {
|
||||||
|
@ -57,13 +49,9 @@ Material& Material::operator= (const Material& material) {
|
||||||
|
|
||||||
// copied: create the Buffer to store the properties, avoid holding a ref to the old Buffer
|
// copied: create the Buffer to store the properties, avoid holding a ref to the old Buffer
|
||||||
Schema schema;
|
Schema schema;
|
||||||
_schemaBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Schema), (const gpu::Byte*) &schema));
|
_schemaBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Schema), (const gpu::Byte*) &schema, sizeof(Schema)));
|
||||||
_schemaBuffer.edit<Schema>() = material._schemaBuffer.get<Schema>();
|
_schemaBuffer.edit<Schema>() = material._schemaBuffer.get<Schema>();
|
||||||
|
|
||||||
TexMapArraySchema texMapArraySchema;
|
|
||||||
_texMapArrayBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(TexMapArraySchema), (const gpu::Byte*) &texMapArraySchema));
|
|
||||||
_texMapArrayBuffer.edit<TexMapArraySchema>() = material._texMapArrayBuffer.get<TexMapArraySchema>();
|
|
||||||
|
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,17 +125,17 @@ void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textur
|
||||||
resetOpacityMap();
|
resetOpacityMap();
|
||||||
|
|
||||||
// update the texcoord0 with albedo
|
// update the texcoord0 with albedo
|
||||||
_texMapArrayBuffer.edit<TexMapArraySchema>()._texcoordTransforms[0] = (textureMap ? textureMap->getTextureTransform().getMatrix() : glm::mat4());
|
_schemaBuffer.edit<Schema>()._texcoordTransforms[0] = (textureMap ? textureMap->getTextureTransform().getMatrix() : glm::mat4());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel == MaterialKey::OCCLUSION_MAP) {
|
if (channel == MaterialKey::OCCLUSION_MAP) {
|
||||||
_texMapArrayBuffer.edit<TexMapArraySchema>()._texcoordTransforms[1] = (textureMap ? textureMap->getTextureTransform().getMatrix() : glm::mat4());
|
_schemaBuffer.edit<Schema>()._texcoordTransforms[1] = (textureMap ? textureMap->getTextureTransform().getMatrix() : glm::mat4());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel == MaterialKey::LIGHTMAP_MAP) {
|
if (channel == MaterialKey::LIGHTMAP_MAP) {
|
||||||
// update the texcoord1 with lightmap
|
// update the texcoord1 with lightmap
|
||||||
_texMapArrayBuffer.edit<TexMapArraySchema>()._texcoordTransforms[1] = (textureMap ? textureMap->getTextureTransform().getMatrix() : glm::mat4());
|
_schemaBuffer.edit<Schema>()._texcoordTransforms[1] = (textureMap ? textureMap->getTextureTransform().getMatrix() : glm::mat4());
|
||||||
_texMapArrayBuffer.edit<TexMapArraySchema>()._lightmapParams = (textureMap ? glm::vec4(textureMap->getLightmapOffsetScale(), 0.0, 0.0) : glm::vec4(0.0, 1.0, 0.0, 0.0));
|
_schemaBuffer.edit<Schema>()._lightmapParams = (textureMap ? glm::vec4(textureMap->getLightmapOffsetScale(), 0.0, 0.0) : glm::vec4(0.0, 1.0, 0.0, 0.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
|
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
|
||||||
|
@ -235,6 +223,6 @@ void Material::setTextureTransforms(const Transform& transform) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < NUM_TEXCOORD_TRANSFORMS; i++) {
|
for (int i = 0; i < NUM_TEXCOORD_TRANSFORMS; i++) {
|
||||||
_texMapArrayBuffer.edit<TexMapArraySchema>()._texcoordTransforms[i] = transform.getMatrix();
|
_schemaBuffer.edit<Schema>()._texcoordTransforms[i] = transform.getMatrix();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -268,6 +268,9 @@ public:
|
||||||
|
|
||||||
typedef glm::vec3 Color;
|
typedef glm::vec3 Color;
|
||||||
|
|
||||||
|
// Texture Map Array Schema
|
||||||
|
static const int NUM_TEXCOORD_TRANSFORMS{ 2 };
|
||||||
|
|
||||||
typedef MaterialKey::MapChannel MapChannel;
|
typedef MaterialKey::MapChannel MapChannel;
|
||||||
typedef std::map<MapChannel, TextureMapPointer> TextureMaps;
|
typedef std::map<MapChannel, TextureMapPointer> TextureMaps;
|
||||||
typedef std::bitset<MaterialKey::NUM_MAP_CHANNELS> MapFlags;
|
typedef std::bitset<MaterialKey::NUM_MAP_CHANNELS> MapFlags;
|
||||||
|
@ -323,6 +326,11 @@ public:
|
||||||
|
|
||||||
// for alignment beauty, Material size == Mat4x4
|
// for alignment beauty, Material size == Mat4x4
|
||||||
|
|
||||||
|
// Texture Coord Transform Array
|
||||||
|
glm::mat4 _texcoordTransforms[NUM_TEXCOORD_TRANSFORMS];
|
||||||
|
|
||||||
|
glm::vec4 _lightmapParams{ 0.0, 1.0, 0.0, 0.0 };
|
||||||
|
|
||||||
Schema() {}
|
Schema() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -340,17 +348,6 @@ public:
|
||||||
// conversion from legacy material properties to PBR equivalent
|
// conversion from legacy material properties to PBR equivalent
|
||||||
static float shininessToRoughness(float shininess) { return 1.0f - shininess / 100.0f; }
|
static float shininessToRoughness(float shininess) { return 1.0f - shininess / 100.0f; }
|
||||||
|
|
||||||
// Texture Map Array Schema
|
|
||||||
static const int NUM_TEXCOORD_TRANSFORMS{ 2 };
|
|
||||||
class TexMapArraySchema {
|
|
||||||
public:
|
|
||||||
glm::mat4 _texcoordTransforms[NUM_TEXCOORD_TRANSFORMS];
|
|
||||||
glm::vec4 _lightmapParams{ 0.0, 1.0, 0.0, 0.0 };
|
|
||||||
TexMapArraySchema() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
const UniformBufferView& getTexMapArrayBuffer() const { return _texMapArrayBuffer; }
|
|
||||||
|
|
||||||
int getTextureCount() const { calculateMaterialInfo(); return _textureCount; }
|
int getTextureCount() const { calculateMaterialInfo(); return _textureCount; }
|
||||||
size_t getTextureSize() const { calculateMaterialInfo(); return _textureSize; }
|
size_t getTextureSize() const { calculateMaterialInfo(); return _textureSize; }
|
||||||
bool hasTextureInfo() const { return _hasCalculatedTextureInfo; }
|
bool hasTextureInfo() const { return _hasCalculatedTextureInfo; }
|
||||||
|
@ -370,7 +367,6 @@ protected:
|
||||||
private:
|
private:
|
||||||
mutable MaterialKey _key;
|
mutable MaterialKey _key;
|
||||||
mutable UniformBufferView _schemaBuffer;
|
mutable UniformBufferView _schemaBuffer;
|
||||||
mutable UniformBufferView _texMapArrayBuffer;
|
|
||||||
mutable gpu::TextureTablePointer _textureTable{ std::make_shared<gpu::TextureTable>() };
|
mutable gpu::TextureTablePointer _textureTable{ std::make_shared<gpu::TextureTable>() };
|
||||||
|
|
||||||
TextureMaps _textureMaps;
|
TextureMaps _textureMaps;
|
||||||
|
|
|
@ -13,6 +13,31 @@
|
||||||
|
|
||||||
<@include graphics/ShaderConstants.h@>
|
<@include graphics/ShaderConstants.h@>
|
||||||
|
|
||||||
|
|
||||||
|
const int MAX_TEXCOORDS = 2;
|
||||||
|
|
||||||
|
struct TexMapArray {
|
||||||
|
mat4 _texcoordTransforms0;
|
||||||
|
mat4 _texcoordTransforms1;
|
||||||
|
vec4 _lightmapParams;
|
||||||
|
};
|
||||||
|
|
||||||
|
<@func declareMaterialTexMapArrayBuffer()@>
|
||||||
|
|
||||||
|
<@func evalTexMapArrayTexcoord0(texMapArray, inTexcoord0, outTexcoord0)@>
|
||||||
|
{
|
||||||
|
<$outTexcoord0$> = (<$texMapArray$>._texcoordTransforms0 * vec4(<$inTexcoord0$>.st, 0.0, 1.0)).st;
|
||||||
|
}
|
||||||
|
<@endfunc@>
|
||||||
|
|
||||||
|
<@func evalTexMapArrayTexcoord1(texMapArray, inTexcoord1, outTexcoord1)@>
|
||||||
|
{
|
||||||
|
<$outTexcoord1$> = (<$texMapArray$>._texcoordTransforms1 * vec4(<$inTexcoord1$>.st, 0.0, 1.0)).st;
|
||||||
|
}
|
||||||
|
<@endfunc@>
|
||||||
|
|
||||||
|
<@endfunc@>
|
||||||
|
|
||||||
// The material values (at least the material key) must be precisely bitwise accurate
|
// The material values (at least the material key) must be precisely bitwise accurate
|
||||||
// to what is provided by the uniform buffer, or the material key has the wrong bits
|
// to what is provided by the uniform buffer, or the material key has the wrong bits
|
||||||
|
|
||||||
|
@ -25,11 +50,15 @@ struct Material {
|
||||||
|
|
||||||
layout(binding=GRAPHICS_BUFFER_MATERIAL) uniform materialBuffer {
|
layout(binding=GRAPHICS_BUFFER_MATERIAL) uniform materialBuffer {
|
||||||
Material _mat;
|
Material _mat;
|
||||||
|
TexMapArray _texMapArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
Material getMaterial() {
|
Material getMaterial() {
|
||||||
return _mat;
|
return _mat;
|
||||||
}
|
}
|
||||||
|
TexMapArray getTexMapArray() {
|
||||||
|
return _texMapArray;
|
||||||
|
}
|
||||||
|
|
||||||
vec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }
|
vec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; }
|
||||||
float getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }
|
float getMaterialOpacity(Material m) { return m._emissiveOpacity.a; }
|
||||||
|
|
|
@ -11,41 +11,7 @@
|
||||||
<@if not MODEL_MATERIAL_TEXTURES_SLH@>
|
<@if not MODEL_MATERIAL_TEXTURES_SLH@>
|
||||||
<@def MODEL_MATERIAL_TEXTURES_SLH@>
|
<@def MODEL_MATERIAL_TEXTURES_SLH@>
|
||||||
|
|
||||||
<@include graphics/ShaderConstants.h@>
|
<@include graphics/Material.slh@>
|
||||||
|
|
||||||
<@func declareMaterialTexMapArrayBuffer()@>
|
|
||||||
|
|
||||||
const int MAX_TEXCOORDS = 2;
|
|
||||||
|
|
||||||
struct TexMapArray {
|
|
||||||
// mat4 _texcoordTransforms[MAX_TEXCOORDS];
|
|
||||||
mat4 _texcoordTransforms0;
|
|
||||||
mat4 _texcoordTransforms1;
|
|
||||||
vec4 _lightmapParams;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding=GRAPHICS_BUFFER_TEXMAPARRAY) uniform texMapArrayBuffer {
|
|
||||||
TexMapArray _texMapArray;
|
|
||||||
};
|
|
||||||
|
|
||||||
TexMapArray getTexMapArray() {
|
|
||||||
return _texMapArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
<@func evalTexMapArrayTexcoord0(texMapArray, inTexcoord0, outTexcoord0)@>
|
|
||||||
{
|
|
||||||
<$outTexcoord0$> = (<$texMapArray$>._texcoordTransforms0 * vec4(<$inTexcoord0$>.st, 0.0, 1.0)).st;
|
|
||||||
}
|
|
||||||
<@endfunc@>
|
|
||||||
|
|
||||||
<@func evalTexMapArrayTexcoord1(texMapArray, inTexcoord1, outTexcoord1)@>
|
|
||||||
{
|
|
||||||
<$outTexcoord1$> = (<$texMapArray$>._texcoordTransforms1 * vec4(<$inTexcoord1$>.st, 0.0, 1.0)).st;
|
|
||||||
}
|
|
||||||
<@endfunc@>
|
|
||||||
|
|
||||||
<@endfunc@>
|
|
||||||
|
|
||||||
|
|
||||||
<@func declareMaterialTextures(withAlbedo, withRoughness, withNormal, withMetallic, withEmissive, withOcclusion, withScattering)@>
|
<@func declareMaterialTextures(withAlbedo, withRoughness, withNormal, withMetallic, withEmissive, withOcclusion, withScattering)@>
|
||||||
|
|
||||||
|
|
|
@ -551,6 +551,11 @@ QUrl NetworkMaterial::getTextureUrl(const QUrl& baseUrl, const FBXTexture& textu
|
||||||
|
|
||||||
graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, const FBXTexture& fbxTexture,
|
graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, const FBXTexture& fbxTexture,
|
||||||
image::TextureUsage::Type type, MapChannel channel) {
|
image::TextureUsage::Type type, MapChannel channel) {
|
||||||
|
|
||||||
|
if (baseUrl.isEmpty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
const auto url = getTextureUrl(baseUrl, fbxTexture);
|
const auto url = getTextureUrl(baseUrl, fbxTexture);
|
||||||
const auto texture = DependencyManager::get<TextureCache>()->getTexture(url, type, fbxTexture.content, fbxTexture.maxNumPixels);
|
const auto texture = DependencyManager::get<TextureCache>()->getTexture(url, type, fbxTexture.content, fbxTexture.maxNumPixels);
|
||||||
_textures[channel] = Texture { fbxTexture.name, texture };
|
_textures[channel] = Texture { fbxTexture.name, texture };
|
||||||
|
|
|
@ -161,8 +161,14 @@ void AddressManager::storeCurrentAddress() {
|
||||||
// be loaded over http(s)
|
// be loaded over http(s)
|
||||||
// url.scheme() == URL_SCHEME_HTTP ||
|
// url.scheme() == URL_SCHEME_HTTP ||
|
||||||
// url.scheme() == URL_SCHEME_HTTPS ||
|
// url.scheme() == URL_SCHEME_HTTPS ||
|
||||||
|
bool isInErrorState = DependencyManager::get<NodeList>()->getDomainHandler().isInErrorState();
|
||||||
if (isConnected()) {
|
if (isConnected()) {
|
||||||
currentAddressHandle.set(url);
|
if (isInErrorState) {
|
||||||
|
// save the last address visited before the problem url.
|
||||||
|
currentAddressHandle.set(lastAddress());
|
||||||
|
} else {
|
||||||
|
currentAddressHandle.set(url);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
qCWarning(networking) << "Ignoring attempt to save current address because not connected to domain:" << url;
|
qCWarning(networking) << "Ignoring attempt to save current address because not connected to domain:" << url;
|
||||||
}
|
}
|
||||||
|
@ -861,6 +867,10 @@ void AddressManager::goToUser(const QString& username, bool shouldMatchOrientati
|
||||||
QByteArray(), nullptr, requestParams);
|
QByteArray(), nullptr, requestParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AddressManager::canGoBack() const {
|
||||||
|
return (_backStack.size() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
void AddressManager::refreshPreviousLookup() {
|
void AddressManager::refreshPreviousLookup() {
|
||||||
// if we have a non-empty previous lookup, fire it again now (but don't re-store it in the history)
|
// if we have a non-empty previous lookup, fire it again now (but don't re-store it in the history)
|
||||||
if (!_previousAPILookup.isEmpty()) {
|
if (!_previousAPILookup.isEmpty()) {
|
||||||
|
|
|
@ -254,6 +254,12 @@ public slots:
|
||||||
*/
|
*/
|
||||||
void goToLastAddress() { handleUrl(_lastVisitedURL, LookupTrigger::AttemptedRefresh); }
|
void goToLastAddress() { handleUrl(_lastVisitedURL, LookupTrigger::AttemptedRefresh); }
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Returns if going back is possible.
|
||||||
|
* @function location.canGoBack
|
||||||
|
*/
|
||||||
|
bool canGoBack() const;
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Refresh the current address, e.g., after connecting to a domain in order to position the user to the desired location.
|
* Refresh the current address, e.g., after connecting to a domain in order to position the user to the desired location.
|
||||||
* @function location.refreshPreviousLookup
|
* @function location.refreshPreviousLookup
|
||||||
|
|
|
@ -123,6 +123,7 @@ void DomainHandler::hardReset() {
|
||||||
|
|
||||||
softReset();
|
softReset();
|
||||||
_isInErrorState = false;
|
_isInErrorState = false;
|
||||||
|
emit redirectErrorStateChanged(_isInErrorState);
|
||||||
|
|
||||||
qCDebug(networking) << "Hard reset in NodeList DomainHandler.";
|
qCDebug(networking) << "Hard reset in NodeList DomainHandler.";
|
||||||
_pendingDomainID = QUuid();
|
_pendingDomainID = QUuid();
|
||||||
|
@ -138,6 +139,11 @@ void DomainHandler::hardReset() {
|
||||||
_pendingPath.clear();
|
_pendingPath.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DomainHandler::isHardRefusal(int reasonCode) {
|
||||||
|
return (reasonCode == (int)ConnectionRefusedReason::ProtocolMismatch || reasonCode == (int)ConnectionRefusedReason::NotAuthorized ||
|
||||||
|
reasonCode == (int)ConnectionRefusedReason::TimedOut);
|
||||||
|
}
|
||||||
|
|
||||||
bool DomainHandler::getInterstitialModeEnabled() const {
|
bool DomainHandler::getInterstitialModeEnabled() const {
|
||||||
return _interstitialModeSettingLock.resultWithReadLock<bool>([&] {
|
return _interstitialModeSettingLock.resultWithReadLock<bool>([&] {
|
||||||
return _enableInterstitialMode.get();
|
return _enableInterstitialMode.get();
|
||||||
|
@ -327,6 +333,7 @@ void DomainHandler::setIsConnected(bool isConnected) {
|
||||||
_isConnected = isConnected;
|
_isConnected = isConnected;
|
||||||
|
|
||||||
if (_isConnected) {
|
if (_isConnected) {
|
||||||
|
_lastDomainConnectionError = -1;
|
||||||
emit connectedToDomain(_domainURL);
|
emit connectedToDomain(_domainURL);
|
||||||
|
|
||||||
if (_domainURL.scheme() == URL_SCHEME_HIFI && !_domainURL.host().isEmpty()) {
|
if (_domainURL.scheme() == URL_SCHEME_HIFI && !_domainURL.host().isEmpty()) {
|
||||||
|
@ -358,9 +365,11 @@ void DomainHandler::loadedErrorDomain(std::map<QString, QString> namedPaths) {
|
||||||
|
|
||||||
void DomainHandler::setRedirectErrorState(QUrl errorUrl, QString reasonMessage, int reasonCode, const QString& extraInfo) {
|
void DomainHandler::setRedirectErrorState(QUrl errorUrl, QString reasonMessage, int reasonCode, const QString& extraInfo) {
|
||||||
_lastDomainConnectionError = reasonCode;
|
_lastDomainConnectionError = reasonCode;
|
||||||
if (getInterstitialModeEnabled()) {
|
if (getInterstitialModeEnabled() && isHardRefusal(reasonCode)) {
|
||||||
_errorDomainURL = errorUrl;
|
_errorDomainURL = errorUrl;
|
||||||
_isInErrorState = true;
|
_isInErrorState = true;
|
||||||
|
qCDebug(networking) << "Error connecting to domain: " << reasonMessage;
|
||||||
|
emit redirectErrorStateChanged(_isInErrorState);
|
||||||
emit redirectToErrorDomainURL(_errorDomainURL);
|
emit redirectToErrorDomainURL(_errorDomainURL);
|
||||||
} else {
|
} else {
|
||||||
emit domainConnectionRefused(reasonMessage, reasonCode, extraInfo);
|
emit domainConnectionRefused(reasonMessage, reasonCode, extraInfo);
|
||||||
|
|
|
@ -187,8 +187,6 @@ private slots:
|
||||||
signals:
|
signals:
|
||||||
void domainURLChanged(QUrl domainURL);
|
void domainURLChanged(QUrl domainURL);
|
||||||
|
|
||||||
void domainConnectionErrorChanged(int reasonCode);
|
|
||||||
|
|
||||||
// NOTE: the emission of completedSocketDiscovery does not mean a connection to DS is established
|
// NOTE: the emission of completedSocketDiscovery does not mean a connection to DS is established
|
||||||
// It means that, either from DNS lookup or ICE, we think we have a socket we can talk to DS on
|
// It means that, either from DNS lookup or ICE, we think we have a socket we can talk to DS on
|
||||||
void completedSocketDiscovery();
|
void completedSocketDiscovery();
|
||||||
|
@ -205,6 +203,7 @@ signals:
|
||||||
|
|
||||||
void domainConnectionRefused(QString reasonMessage, int reason, const QString& extraInfo);
|
void domainConnectionRefused(QString reasonMessage, int reason, const QString& extraInfo);
|
||||||
void redirectToErrorDomainURL(QUrl errorDomainURL);
|
void redirectToErrorDomainURL(QUrl errorDomainURL);
|
||||||
|
void redirectErrorStateChanged(bool isInErrorState);
|
||||||
|
|
||||||
void limitOfSilentDomainCheckInsReached();
|
void limitOfSilentDomainCheckInsReached();
|
||||||
|
|
||||||
|
@ -213,6 +212,8 @@ private:
|
||||||
void sendDisconnectPacket();
|
void sendDisconnectPacket();
|
||||||
void hardReset();
|
void hardReset();
|
||||||
|
|
||||||
|
bool isHardRefusal(int reasonCode);
|
||||||
|
|
||||||
QUuid _uuid;
|
QUuid _uuid;
|
||||||
Node::LocalID _localID;
|
Node::LocalID _localID;
|
||||||
QUrl _domainURL;
|
QUrl _domainURL;
|
||||||
|
@ -230,7 +231,7 @@ private:
|
||||||
QString _pendingPath;
|
QString _pendingPath;
|
||||||
QTimer _settingsTimer;
|
QTimer _settingsTimer;
|
||||||
mutable ReadWriteLockable _interstitialModeSettingLock;
|
mutable ReadWriteLockable _interstitialModeSettingLock;
|
||||||
Setting::Handle<bool> _enableInterstitialMode{ "enableInterstitialMode", false };
|
Setting::Handle<bool> _enableInterstitialMode{ "enableInterstitialMode", true };
|
||||||
|
|
||||||
QSet<QString> _domainConnectionRefusals;
|
QSet<QString> _domainConnectionRefusals;
|
||||||
bool _hasCheckedForAccessToken { false };
|
bool _hasCheckedForAccessToken { false };
|
||||||
|
|
|
@ -332,7 +332,6 @@ void NodeList::sendDomainServerCheckIn() {
|
||||||
qCDebug(networking) << "Local domain-server port read from shared memory (or default) is" << domainPort;
|
qCDebug(networking) << "Local domain-server port read from shared memory (or default) is" << domainPort;
|
||||||
_domainHandler.setPort(domainPort);
|
_domainHandler.setPort(domainPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we're missing a keypair we need to verify ourselves with the domain-server
|
// check if we're missing a keypair we need to verify ourselves with the domain-server
|
||||||
|
|
|
@ -79,6 +79,9 @@ void PhysicalEntitySimulation::removeEntityInternal(EntityItemPointer entity) {
|
||||||
_deadEntities.insert(entity);
|
_deadEntities.insert(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (entity->getClientOnly()) {
|
||||||
|
_deadAvatarEntities.insert(entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicalEntitySimulation::removeOwnershipData(EntityMotionState* motionState) {
|
void PhysicalEntitySimulation::removeOwnershipData(EntityMotionState* motionState) {
|
||||||
|
@ -123,6 +126,11 @@ void PhysicalEntitySimulation::takeDeadEntities(SetOfEntities& deadEntities) {
|
||||||
_deadEntities.clear();
|
_deadEntities.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhysicalEntitySimulation::takeDeadAvatarEntities(SetOfEntities& deadEntities) {
|
||||||
|
_deadAvatarEntities.swap(deadEntities);
|
||||||
|
_deadAvatarEntities.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) {
|
void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) {
|
||||||
// queue incoming changes: from external sources (script, EntityServer, etc) to physics engine
|
// queue incoming changes: from external sources (script, EntityServer, etc) to physics engine
|
||||||
QMutexLocker lock(&_mutex);
|
QMutexLocker lock(&_mutex);
|
||||||
|
|
|
@ -60,6 +60,7 @@ public:
|
||||||
virtual void applyDynamicChanges() override;
|
virtual void applyDynamicChanges() override;
|
||||||
|
|
||||||
virtual void takeDeadEntities(SetOfEntities& deadEntities) override;
|
virtual void takeDeadEntities(SetOfEntities& deadEntities) override;
|
||||||
|
void takeDeadAvatarEntities(SetOfEntities& deadEntities);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
||||||
|
@ -112,6 +113,7 @@ private:
|
||||||
|
|
||||||
VectorOfEntityMotionStates _owned;
|
VectorOfEntityMotionStates _owned;
|
||||||
VectorOfEntityMotionStates _bids;
|
VectorOfEntityMotionStates _bids;
|
||||||
|
SetOfEntities _deadAvatarEntities;
|
||||||
workload::SpacePointer _space;
|
workload::SpacePointer _space;
|
||||||
uint64_t _nextBidExpiry;
|
uint64_t _nextBidExpiry;
|
||||||
uint32_t _lastStepSendPackets { 0 };
|
uint32_t _lastStepSendPackets { 0 };
|
||||||
|
|
|
@ -171,6 +171,13 @@ public:
|
||||||
};
|
};
|
||||||
Q_ENUM(PickType)
|
Q_ENUM(PickType)
|
||||||
|
|
||||||
|
enum JointState {
|
||||||
|
JOINT_STATE_NONE = 0,
|
||||||
|
JOINT_STATE_LEFT_HAND,
|
||||||
|
JOINT_STATE_RIGHT_HAND,
|
||||||
|
JOINT_STATE_MOUSE
|
||||||
|
};
|
||||||
|
|
||||||
void enable(bool enabled = true);
|
void enable(bool enabled = true);
|
||||||
void disable() { enable(false); }
|
void disable() { enable(false); }
|
||||||
|
|
||||||
|
@ -211,9 +218,11 @@ public:
|
||||||
void setIgnoreItems(const QVector<QUuid>& items);
|
void setIgnoreItems(const QVector<QUuid>& items);
|
||||||
void setIncludeItems(const QVector<QUuid>& items);
|
void setIncludeItems(const QVector<QUuid>& items);
|
||||||
|
|
||||||
virtual bool isLeftHand() const { return false; }
|
virtual bool isLeftHand() const { return _jointState == JOINT_STATE_LEFT_HAND; }
|
||||||
virtual bool isRightHand() const { return false; }
|
virtual bool isRightHand() const { return _jointState == JOINT_STATE_RIGHT_HAND; }
|
||||||
virtual bool isMouse() const { return false; }
|
virtual bool isMouse() const { return _jointState == JOINT_STATE_MOUSE; }
|
||||||
|
|
||||||
|
void setJointState(JointState jointState) { _jointState = jointState; }
|
||||||
|
|
||||||
virtual Transform getResultTransform() const = 0;
|
virtual Transform getResultTransform() const = 0;
|
||||||
|
|
||||||
|
@ -227,13 +236,15 @@ private:
|
||||||
|
|
||||||
QVector<QUuid> _ignoreItems;
|
QVector<QUuid> _ignoreItems;
|
||||||
QVector<QUuid> _includeItems;
|
QVector<QUuid> _includeItems;
|
||||||
|
|
||||||
|
JointState _jointState { JOINT_STATE_NONE };
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(PickQuery::PickType)
|
Q_DECLARE_METATYPE(PickQuery::PickType)
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Pick : public PickQuery {
|
class Pick : public PickQuery {
|
||||||
public:
|
public:
|
||||||
Pick(const PickFilter& filter, const float maxDistance, const bool enabled) : PickQuery(filter, maxDistance, enabled) {}
|
Pick(const T& mathPick, const PickFilter& filter, const float maxDistance, const bool enabled) : PickQuery(filter, maxDistance, enabled), _mathPick(mathPick) {}
|
||||||
virtual ~Pick() {}
|
virtual ~Pick() {}
|
||||||
|
|
||||||
virtual T getMathematicalPick() const = 0;
|
virtual T getMathematicalPick() const = 0;
|
||||||
|
@ -242,6 +253,9 @@ public:
|
||||||
virtual PickResultPointer getOverlayIntersection(const T& pick) = 0;
|
virtual PickResultPointer getOverlayIntersection(const T& pick) = 0;
|
||||||
virtual PickResultPointer getAvatarIntersection(const T& pick) = 0;
|
virtual PickResultPointer getAvatarIntersection(const T& pick) = 0;
|
||||||
virtual PickResultPointer getHUDIntersection(const T& pick) = 0;
|
virtual PickResultPointer getHUDIntersection(const T& pick) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
T _mathPick;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
|
|
|
@ -90,6 +90,17 @@ void PickManager::setIncludeItems(unsigned int uid, const QVector<QUuid>& includ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transform PickManager::getParentTransform(unsigned int uid) const {
|
||||||
|
auto pick = findPick(uid);
|
||||||
|
if (pick) {
|
||||||
|
auto parentTransform = pick->parentTransform;
|
||||||
|
if (parentTransform) {
|
||||||
|
return parentTransform->getTransform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Transform();
|
||||||
|
}
|
||||||
|
|
||||||
Transform PickManager::getResultTransform(unsigned int uid) const {
|
Transform PickManager::getResultTransform(unsigned int uid) const {
|
||||||
auto pick = findPick(uid);
|
auto pick = findPick(uid);
|
||||||
if (pick) {
|
if (pick) {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue