Merge branch 'master' of https://github.com/highfidelity/hifi into black-bis

This commit is contained in:
Sam Gateau 2018-10-08 18:53:28 -07:00
commit 4edf2275b5
61 changed files with 1381 additions and 1204 deletions

View file

@ -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

View file

@ -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)

View file

@ -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)
} }
} }

View file

@ -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
/* /*

View file

@ -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;
} }
} }
} }

View file

@ -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;
} }

View file

@ -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}
) )

View file

@ -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")

View file

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

View file

@ -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/>

View file

@ -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@")

View file

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

File diff suppressed because it is too large Load diff

View file

@ -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>
@ -365,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);
@ -5383,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();
} }
@ -5623,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) {
@ -5921,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
@ -6245,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);
@ -6271,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);
@ -6585,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;
} }

View file

@ -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 };

View file

@ -452,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);
{ {

View file

@ -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

View file

@ -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));

View file

@ -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();
} }

View file

@ -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;

View file

@ -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 =

View file

@ -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}.

View file

@ -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;
} }
@ -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();

View file

@ -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).

View file

@ -339,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);
@ -380,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);
} }

View file

@ -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) {

View file

@ -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);
} }
} }

View file

@ -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()) {

View file

@ -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();

View file

@ -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;

View file

@ -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();

View file

@ -166,6 +166,7 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte
{ {
_type = EntityTypes::ParticleEffect; _type = EntityTypes::ParticleEffect;
setColor(DEFAULT_COLOR); setColor(DEFAULT_COLOR);
_visuallyReady = false;
} }
void ParticleEffectEntityItem::setAlpha(float alpha) { void ParticleEffectEntityItem::setAlpha(float alpha) {
@ -777,4 +778,4 @@ particle::Properties ParticleEffectEntityItem::getParticleProperties() const {
} }
return result; return result;
} }

View file

@ -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 };

View file

@ -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()) {

View file

@ -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

View file

@ -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);

View file

@ -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 };

View file

@ -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

View file

@ -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);

View file

@ -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 };

View file

@ -9,10 +9,7 @@
set(TARGET_NAME hifiCodec) set(TARGET_NAME hifiCodec)
setup_hifi_client_server_plugin() setup_hifi_client_server_plugin()
link_hifi_libraries(audio plugins) link_hifi_libraries(audio plugins)
add_dependency_external_projects(hifiAudioCodec) target_hifiAudioCodec()
target_include_directories(${TARGET_NAME} PRIVATE ${HIFIAUDIOCODEC_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} ${HIFIAUDIOCODEC_LIBRARIES})
if (BUILD_SERVER) if (BUILD_SERVER)
install_beside_console() install_beside_console()
endif () endif ()

View file

@ -39,8 +39,9 @@ var DEFAULT_SCRIPTS_SEPARATE = [
//"system/chat.js" //"system/chat.js"
]; ];
if (Settings.getValue("enableInterstitialMode", false)) { if (Window.interstitialModeEnabled) {
DEFAULT_SCRIPTS_SEPARATE.push("system/interstitialPage.js"); DEFAULT_SCRIPTS_COMBINED.push("system/interstitialPage.js");
DEFAULT_SCRIPTS_COMBINED.push("system/redirectOverlays.js");
} }
// add a menu item for debugging // add a menu item for debugging

View file

@ -75,4 +75,4 @@ Item {
} }
} }
} }

View file

@ -139,8 +139,8 @@ function AppUi(properties) {
that.isOpen = false; that.isOpen = false;
} }
} }
console.debug(that.buttonName + " app reports: Tablet screen changed.\nNew screen type: " + type + // console.debug(that.buttonName + " app reports: Tablet screen changed.\nNew screen type: " + type +
"\nNew screen URL: " + url + "\nCurrent app open status: " + that.isOpen + "\n"); // "\nNew screen URL: " + url + "\nCurrent app open status: " + that.isOpen + "\n");
}; };
// Overwrite with the given properties: // Overwrite with the given properties:

View file

@ -110,6 +110,8 @@ Script.include("/~/system/libraries/Xform.js");
this.reticleMinY = MARGIN; this.reticleMinY = MARGIN;
this.reticleMaxY; this.reticleMaxY;
this.ignoredEntities = [];
var ACTION_TTL = 15; // seconds var ACTION_TTL = 15; // seconds
var DISTANCE_HOLDING_RADIUS_FACTOR = 3.5; // multiplied by distance between hand and object var DISTANCE_HOLDING_RADIUS_FACTOR = 3.5; // multiplied by distance between hand and object
@ -314,6 +316,17 @@ Script.include("/~/system/libraries/Xform.js");
return point2d; return point2d;
}; };
this.restoreIgnoredEntities = function() {
for (var i = 0; i < this.ignoredEntities; i++) {
var data = {
action: 'remove',
id: this.ignoredEntities[i]
};
Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data));
}
this.ignoredEntities = [];
};
this.notPointingAtEntity = function(controllerData) { this.notPointingAtEntity = function(controllerData) {
var intersection = controllerData.rayPicks[this.hand]; var intersection = controllerData.rayPicks[this.hand];
var entityProperty = Entities.getEntityProperties(intersection.objectID); var entityProperty = Entities.getEntityProperties(intersection.objectID);
@ -323,6 +336,15 @@ Script.include("/~/system/libraries/Xform.js");
if ((intersection.type === Picks.INTERSECTED_ENTITY && entityType === "Web") || if ((intersection.type === Picks.INTERSECTED_ENTITY && entityType === "Web") ||
intersection.type === Picks.INTERSECTED_OVERLAY || Window.isPointOnDesktopWindow(point2d)) { intersection.type === Picks.INTERSECTED_OVERLAY || Window.isPointOnDesktopWindow(point2d)) {
return true; return true;
} else if (intersection.type === Picks.INTERSECTED_ENTITY && !Window.isPhysicsEnabled()) {
// add to ignored items.
var data = {
action: 'add',
id: intersection.objectID
};
Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data));
this.ignoredEntities.push(intersection.objectID);
} }
return false; return false;
}; };
@ -383,6 +405,7 @@ Script.include("/~/system/libraries/Xform.js");
this.isReady = function (controllerData) { this.isReady = function (controllerData) {
if (HMD.active) { if (HMD.active) {
if (this.notPointingAtEntity(controllerData)) { if (this.notPointingAtEntity(controllerData)) {
this.restoreIgnoredEntities();
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
@ -394,9 +417,11 @@ Script.include("/~/system/libraries/Xform.js");
return makeRunningValues(true, [], []); return makeRunningValues(true, [], []);
} else { } else {
this.destroyContextOverlay(); this.destroyContextOverlay();
this.restoreIgnoredEntities();
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
} }
this.restoreIgnoredEntities();
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
}; };
@ -407,6 +432,7 @@ Script.include("/~/system/libraries/Xform.js");
Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity",
this.highlightedEntity); this.highlightedEntity);
this.highlightedEntity = null; this.highlightedEntity = null;
this.restoreIgnoredEntities();
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
this.intersectionDistance = controllerData.rayPicks[this.hand].distance; this.intersectionDistance = controllerData.rayPicks[this.hand].distance;
@ -437,6 +463,7 @@ Script.include("/~/system/libraries/Xform.js");
if (nearGrabReadiness[k].active && (nearGrabReadiness[k].targets[0] === this.grabbedThingID if (nearGrabReadiness[k].active && (nearGrabReadiness[k].targets[0] === this.grabbedThingID
|| HMD.tabletID && nearGrabReadiness[k].targets[0] === HMD.tabletID)) { || HMD.tabletID && nearGrabReadiness[k].targets[0] === HMD.tabletID)) {
this.endFarGrabAction(); this.endFarGrabAction();
this.restoreIgnoredEntities();
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
} }
@ -448,6 +475,7 @@ Script.include("/~/system/libraries/Xform.js");
for (var j = 0; j < nearGrabReadiness.length; j++) { for (var j = 0; j < nearGrabReadiness.length; j++) {
if (nearGrabReadiness[j].active) { if (nearGrabReadiness[j].active) {
this.endFarGrabAction(); this.endFarGrabAction();
this.restoreIgnoredEntities();
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
} }
@ -466,6 +494,7 @@ Script.include("/~/system/libraries/Xform.js");
]); ]);
if (targetProps.href !== "") { if (targetProps.href !== "") {
AddressManager.handleLookupString(targetProps.href); AddressManager.handleLookupString(targetProps.href);
this.restoreIgnoredEntities();
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
@ -583,6 +612,7 @@ Script.include("/~/system/libraries/Xform.js");
Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity",
this.highlightedEntity); this.highlightedEntity);
this.highlightedEntity = null; this.highlightedEntity = null;
this.restoreIgnoredEntities();
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
} }

View file

@ -37,6 +37,8 @@
var tablet = null; var tablet = null;
var button = null; var button = null;
var errorConnectingToDomain = false;
// Tips have a character limit of 69 // Tips have a character limit of 69
var userTips = [ var userTips = [
"Tip: Visit TheSpot to explore featured domains!", "Tip: Visit TheSpot to explore featured domains!",
@ -48,7 +50,7 @@
"Tip: Use the Create app to import models and create custom entities.", "Tip: Use the Create app to import models and create custom entities.",
"Tip: We're open source! Feel free to contribute to our code on GitHub!", "Tip: We're open source! Feel free to contribute to our code on GitHub!",
"Tip: What emotes have you used in the Emote app?", "Tip: What emotes have you used in the Emote app?",
"Tip: Take and share your snapshots with the everyone using the Snap app.", "Tip: Take and share your snapshots with everyone using the Snap app.",
"Tip: Did you know you can show websites in-world by creating a web entity?", "Tip: Did you know you can show websites in-world by creating a web entity?",
"Tip: Find out more information about domains by visiting our website!", "Tip: Find out more information about domains by visiting our website!",
"Tip: Did you know you can get cool new apps from the Marketplace?", "Tip: Did you know you can get cool new apps from the Marketplace?",
@ -125,7 +127,7 @@
localPosition: { x: 0.0 , y: -1.6, z: 0.0 }, localPosition: { x: 0.0 , y: -1.6, z: 0.0 },
text: toolTip, text: toolTip,
textAlpha: 1, textAlpha: 1,
backgroundAlpha: 1, backgroundAlpha: 0.00393,
lineHeight: 0.13, lineHeight: 0.13,
visible: isVisible, visible: isVisible,
ignoreRayIntersection: true, ignoreRayIntersection: true,
@ -135,17 +137,47 @@
parentID: anchorOverlay parentID: anchorOverlay
}); });
var loadingToTheSpotID = Overlays.addOverlay("image3d", { var loadingToTheSpotText = Overlays.addOverlay("text3d", {
name: "Loading-Destination-Card-Text", name: "Loading-Destination-Card-Text",
localPosition: { x: 0.0 , y: -1.5, z: -0.3 }, localPosition: { x: 0.0 , y: -1.687, z: -0.3 },
url: Script.resourcesPath() + "images/interstitialPage/goTo_button.png", text: "Go To TheSpot",
textAlpha: 1,
backgroundAlpha: 0.00393,
lineHeight: 0.10,
visible: isVisible,
ignoreRayIntersection: true,
dimensions: {x: 1, y: 0.17},
drawInFront: true,
grabbable: false,
localOrientation: Quat.fromVec3Degrees({ x: 0, y: 180, z: 0 }),
parentID: anchorOverlay
});
var loadingToTheSpotID = Overlays.addOverlay("image3d", {
name: "Loading-Destination-Card-GoTo-Image",
localPosition: { x: 0.0 , y: -1.75, z: -0.3 },
url: Script.resourcesPath() + "images/interstitialPage/button.png",
alpha: 1, alpha: 1,
visible: isVisible, visible: isVisible,
emissive: true, emissive: true,
ignoreRayIntersection: false, ignoreRayIntersection: false,
drawInFront: true, drawInFront: true,
grabbable: false, grabbable: false,
localOrientation: Quat.fromVec3Degrees({ x: 0.0, y: 180.0, z: 0.0 }), localOrientation: Quat.fromVec3Degrees({ x: 0, y: 180, z: 0 }),
parentID: anchorOverlay
});
var loadingToTheSpotHoverID = Overlays.addOverlay("image3d", {
name: "Loading-Destination-Card-GoTo-Image-Hover",
localPosition: { x: 0.0 , y: -1.75, z: -0.3 },
url: Script.resourcesPath() + "images/interstitialPage/button_hover.png",
alpha: 1,
visible: false,
emissive: true,
ignoreRayIntersection: false,
drawInFront: true,
grabbable: false,
localOrientation: Quat.fromVec3Degrees({ x: 0, y: 180, z: 0 }),
parentID: anchorOverlay parentID: anchorOverlay
}); });
@ -185,10 +217,11 @@
var currentDomain = "no domain"; var currentDomain = "no domain";
var timer = null; var timer = null;
var target = 0; var target = 0;
var textureMemSizeStabilityCount = 0;
var textureMemSizeAtLastCheck = 0;
var connectionToDomainFailed = false; var connectionToDomainFailed = false;
function getAnchorLocalYOffset() { function getAnchorLocalYOffset() {
var loadingSpherePosition = Overlays.getProperty(loadingSphereID, "position"); var loadingSpherePosition = Overlays.getProperty(loadingSphereID, "position");
var loadingSphereOrientation = Overlays.getProperty(loadingSphereID, "rotation"); var loadingSphereOrientation = Overlays.getProperty(loadingSphereID, "rotation");
@ -227,6 +260,8 @@
updateOverlays(false); updateOverlays(false);
startAudio(); startAudio();
target = 0; target = 0;
textureMemSizeStabilityCount = 0;
textureMemSizeAtLastCheck = 0;
currentProgress = 0.1; currentProgress = 0.1;
connectionToDomainFailed = false; connectionToDomainFailed = false;
previousCameraMode = Camera.mode; previousCameraMode = Camera.mode;
@ -235,6 +270,13 @@
} }
} }
function toggleInterstitialPage(isInErrorState) {
errorConnectingToDomain = isInErrorState;
if (!errorConnectingToDomain) {
domainChanged(location);
}
}
function startAudio() { function startAudio() {
sample = Audio.playSound(tune, { sample = Audio.playSound(tune, {
localOnly: true, localOnly: true,
@ -251,11 +293,12 @@
function domainChanged(domain) { function domainChanged(domain) {
if (domain !== currentDomain) { if (domain !== currentDomain) {
MyAvatar.restoreAnimation(); MyAvatar.restoreAnimation();
resetValues();
var name = location.placename; var name = location.placename;
domainName = name.charAt(0).toUpperCase() + name.slice(1); domainName = name.charAt(0).toUpperCase() + name.slice(1);
var doRequest = true; var doRequest = true;
if (name.length === 0 && location.href === "file:///~/serverless/tutorial.json") { if (name.length === 0 && location.href === "file:///~/serverless/tutorial.json") {
domainName = "Serveless Domain (Tutorial)"; domainName = "Serverless Domain (Tutorial)";
doRequest = false; doRequest = false;
} }
var domainNameLeftMargin = getLeftMargin(domainNameTextID, domainName); var domainNameLeftMargin = getLeftMargin(domainNameTextID, domainName);
@ -306,8 +349,30 @@
var THE_PLACE = (HifiAbout.buildVersion === "dev") ? "hifi://TheSpot-dev": "hifi://TheSpot"; var THE_PLACE = (HifiAbout.buildVersion === "dev") ? "hifi://TheSpot-dev": "hifi://TheSpot";
function clickedOnOverlay(overlayID, event) { function clickedOnOverlay(overlayID, event) {
if (loadingToTheSpotID === overlayID) { if (loadingToTheSpotHoverID === overlayID) {
location.handleLookupString(THE_PLACE); location.handleLookupString(THE_PLACE);
Overlays.editOverlay(loadingToTheSpotHoverID, {visible: false});
Overlays.editOverlay(loadingToTheSpotID, {visible: true});
}
}
function onEnterOverlay(overlayID, event) {
if (currentDomain === "no domain") {
return;
}
if (overlayID === loadingToTheSpotID) {
Overlays.editOverlay(loadingToTheSpotID, {visible: false});
Overlays.editOverlay(loadingToTheSpotHoverID, {visible: true});
}
}
function onLeaveOverlay(overlayID, event) {
if (currentDomain === "no domain") {
return;
}
if (overlayID === loadingToTheSpotHoverID) {
Overlays.editOverlay(loadingToTheSpotHoverID, {visible: false});
Overlays.editOverlay(loadingToTheSpotID, {visible: true});
} }
} }
@ -340,6 +405,7 @@
renderViewTask.getConfig("LightingModel")["enableDirectionalLight"] = physicsEnabled; renderViewTask.getConfig("LightingModel")["enableDirectionalLight"] = physicsEnabled;
renderViewTask.getConfig("LightingModel")["enablePointLight"] = physicsEnabled; renderViewTask.getConfig("LightingModel")["enablePointLight"] = physicsEnabled;
Overlays.editOverlay(loadingSphereID, mainSphereProperties); Overlays.editOverlay(loadingSphereID, mainSphereProperties);
Overlays.editOverlay(loadingToTheSpotText, properties);
Overlays.editOverlay(loadingToTheSpotID, properties); Overlays.editOverlay(loadingToTheSpotID, properties);
Overlays.editOverlay(domainNameTextID, properties); Overlays.editOverlay(domainNameTextID, properties);
Overlays.editOverlay(domainDescription, domainTextProperties); Overlays.editOverlay(domainDescription, domainTextProperties);
@ -347,10 +413,11 @@
Overlays.editOverlay(loadingBarPlacard, properties); Overlays.editOverlay(loadingBarPlacard, properties);
Overlays.editOverlay(loadingBarProgress, loadingBarProperties); Overlays.editOverlay(loadingBarProgress, loadingBarProperties);
if (!DEBUG) {
Menu.setIsOptionChecked("Show Overlays", physicsEnabled); Menu.setIsOptionChecked("Show Overlays", physicsEnabled);
if (!HMD.active) { if (!HMD.active) {
toolbar.writeProperty("visible", physicsEnabled); toolbar.writeProperty("visible", physicsEnabled);
}
} }
resetValues(); resetValues();
@ -360,7 +427,6 @@
} }
} }
function scaleInterstitialPage(sensorToWorldScale) { function scaleInterstitialPage(sensorToWorldScale) {
var yOffset = getAnchorLocalYOffset(); var yOffset = getAnchorLocalYOffset();
var localPosition = { var localPosition = {
@ -372,19 +438,53 @@
Overlays.editOverlay(anchorOverlay, { localPosition: localPosition }); Overlays.editOverlay(anchorOverlay, { localPosition: localPosition });
} }
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
function update() { function update() {
var renderStats = Render.getConfig("Stats");
var physicsEnabled = Window.isPhysicsEnabled(); var physicsEnabled = Window.isPhysicsEnabled();
var thisInterval = Date.now(); var thisInterval = Date.now();
var deltaTime = (thisInterval - lastInterval); var deltaTime = (thisInterval - lastInterval);
lastInterval = thisInterval; lastInterval = thisInterval;
var domainLoadingProgressPercentage = Window.domainLoadingProgress(); var domainLoadingProgressPercentage = Window.domainLoadingProgress();
var progress = ((TOTAL_LOADING_PROGRESS * 0.4) * domainLoadingProgressPercentage);
var progress = MIN_LOADING_PROGRESS * domainLoadingProgressPercentage;
if (progress >= target) { if (progress >= target) {
target = progress; target = progress;
} }
if (currentProgress >= (TOTAL_LOADING_PROGRESS * 0.4)) {
var textureResourceGPUMemSize = renderStats.textureResourceGPUMemSize;
var texturePopulatedGPUMemSize = renderStats.textureResourcePopulatedGPUMemSize;
if (textureMemSizeAtLastCheck === textureResourceGPUMemSize) {
textureMemSizeStabilityCount++;
} else {
textureMemSizeStabilityCount = 0;
}
textureMemSizeAtLastCheck = textureResourceGPUMemSize;
if (textureMemSizeStabilityCount >= 20) {
if (textureResourceGPUMemSize > 0) {
// print((texturePopulatedGPUMemSize / textureResourceGPUMemSize));
var gpuPercantage = (TOTAL_LOADING_PROGRESS * 0.6) * (texturePopulatedGPUMemSize / textureResourceGPUMemSize);
var totalProgress = progress + gpuPercantage;
if (totalProgress >= target) {
target = totalProgress;
}
}
}
}
if ((physicsEnabled && (currentProgress < TOTAL_LOADING_PROGRESS))) { if ((physicsEnabled && (currentProgress < TOTAL_LOADING_PROGRESS))) {
target = TOTAL_LOADING_PROGRESS; target = TOTAL_LOADING_PROGRESS;
} }
@ -399,30 +499,40 @@
}; };
Overlays.editOverlay(loadingBarProgress, properties); Overlays.editOverlay(loadingBarProgress, properties);
if ((physicsEnabled && (currentProgress >= (TOTAL_LOADING_PROGRESS - EPSILON)))) {
if (errorConnectingToDomain) {
updateOverlays(errorConnectingToDomain);
// setting hover id to invisible
Overlays.editOverlay(loadingToTheSpotHoverID, {visible: false});
endAudio();
currentDomain = "no domain";
timer = null;
// The toolbar doesn't become visible in time to match the speed of
// the signal handling of redirectErrorStateChanged in both this script
// and the redirectOverlays.js script. Use a sleep function to ensure
// the toolbar becomes visible again.
sleep(300);
if (!HMD.active) {
toolbar.writeProperty("visible", true);
}
return;
} else if ((physicsEnabled && (currentProgress >= (TOTAL_LOADING_PROGRESS - EPSILON)))) {
updateOverlays((physicsEnabled || connectionToDomainFailed)); updateOverlays((physicsEnabled || connectionToDomainFailed));
// setting hover id to invisible
Overlays.editOverlay(loadingToTheSpotHoverID, {visible: false});
endAudio(); endAudio();
currentDomain = "no domain"; currentDomain = "no domain";
timer = null; timer = null;
return; return;
} }
timer = Script.setTimeout(update, BASIC_TIMER_INTERVAL_MS); timer = Script.setTimeout(update, BASIC_TIMER_INTERVAL_MS);
} }
var whiteColor = {red: 255, green: 255, blue: 255}; var whiteColor = {red: 255, green: 255, blue: 255};
var greyColor = {red: 125, green: 125, blue: 125}; var greyColor = {red: 125, green: 125, blue: 125};
Overlays.mouseReleaseOnOverlay.connect(clickedOnOverlay); Overlays.mouseReleaseOnOverlay.connect(clickedOnOverlay);
Overlays.hoverEnterOverlay.connect(function(overlayID, event) { Overlays.hoverEnterOverlay.connect(onEnterOverlay);
if (overlayID === loadingToTheSpotID) {
Overlays.editOverlay(loadingToTheSpotID, { color: greyColor });
}
});
Overlays.hoverLeaveOverlay.connect(function(overlayID, event) { Overlays.hoverLeaveOverlay.connect(onLeaveOverlay);
if (overlayID === loadingToTheSpotID) {
Overlays.editOverlay(loadingToTheSpotID, { color: whiteColor });
}
});
location.hostChanged.connect(domainChanged); location.hostChanged.connect(domainChanged);
location.lookupResultsFinished.connect(function() { location.lookupResultsFinished.connect(function() {
@ -430,6 +540,7 @@
connectionToDomainFailed = !location.isConnected; connectionToDomainFailed = !location.isConnected;
}, 1200); }, 1200);
}); });
Window.redirectErrorStateChanged.connect(toggleInterstitialPage);
MyAvatar.sensorToWorldScaleChanged.connect(scaleInterstitialPage); MyAvatar.sensorToWorldScaleChanged.connect(scaleInterstitialPage);
MyAvatar.sessionUUIDChanged.connect(function() { MyAvatar.sessionUUIDChanged.connect(function() {
@ -448,9 +559,17 @@
}); });
} }
// set left margin of text.
var loadingTextProperties = {
leftMargin: getLeftMargin(loadingToTheSpotText, "Go To TheSpot") + 0.045
};
Overlays.editOverlay(loadingToTheSpotText, loadingTextProperties);
function cleanup() { function cleanup() {
Overlays.deleteOverlay(loadingSphereID); Overlays.deleteOverlay(loadingSphereID);
Overlays.deleteOverlay(loadingToTheSpotID); Overlays.deleteOverlay(loadingToTheSpotID);
Overlays.deleteOverlay(loadingToTheSpotHoverID);
Overlays.deleteOverlay(domainNameTextID); Overlays.deleteOverlay(domainNameTextID);
Overlays.deleteOverlay(domainDescription); Overlays.deleteOverlay(domainDescription);
Overlays.deleteOverlay(domainToolTip); Overlays.deleteOverlay(domainToolTip);

View file

@ -0,0 +1,257 @@
"use strict";
(function() {
var ERROR_MESSAGE_MAP = [
"Oops! Protocol version mismatch.",
"Oops! Not authorized to join domain.",
"Oops! Connection timed out.",
"Oops! Something went wrong."
];
var PROTOCOL_VERSION_MISMATCH = 1;
var NOT_AUTHORIZED = 3;
var TIMEOUT = 5;
var hardRefusalErrors = [PROTOCOL_VERSION_MISMATCH,
NOT_AUTHORIZED, TIMEOUT];
var timer = null;
var isErrorState = false;
function getOopsText() {
var error = Window.getLastDomainConnectionError();
var errorMessageMapIndex = hardRefusalErrors.indexOf(error);
if (error === -1) {
// not an error.
return "";
} else if (errorMessageMapIndex >= 0) {
return ERROR_MESSAGE_MAP[errorMessageMapIndex];
} else {
// some other text.
return ERROR_MESSAGE_MAP[4];
}
};
var oopsDimensions = {x: 4.2, y: 0.8};
var redirectOopsText = Overlays.addOverlay("text3d", {
name: "oopsText",
position: {x: 0, y: 1.6763916015625, z: 1.45927095413208},
rotation: {x: -4.57763671875e-05, y: 0.4957197904586792, z: -7.62939453125e-05, w: 0.8684672117233276},
text: getOopsText(),
textAlpha: 1,
backgroundColor: {x: 0, y: 0, z:0},
backgroundAlpha: 0,
lineHeight: 0.10,
leftMargin: 0.538373570564886,
visible: false,
emissive: true,
ignoreRayIntersection: true,
dimensions: oopsDimensions,
grabbable: false,
});
var tryAgainImageNeutral = Overlays.addOverlay("image3d", {
name: "tryAgainImage",
localPosition: {x: -0.6, y: -0.6, z: 0.0},
url: Script.resourcesPath() + "images/interstitialPage/button.png",
alpha: 1,
visible: false,
emissive: true,
ignoreRayIntersection: false,
grabbable: false,
orientation: Overlays.getProperty(redirectOopsText, "orientation"),
parentID: redirectOopsText
});
var tryAgainImageHover = Overlays.addOverlay("image3d", {
name: "tryAgainImageHover",
localPosition: {x: -0.6, y: -0.6, z: 0.0},
url: Script.resourcesPath() + "images/interstitialPage/button_hover.png",
alpha: 1,
visible: false,
emissive: true,
ignoreRayIntersection: false,
grabbable: false,
orientation: Overlays.getProperty(redirectOopsText, "orientation"),
parentID: redirectOopsText
});
var tryAgainText = Overlays.addOverlay("text3d", {
name: "tryAgainText",
localPosition: {x: -0.6, y: -0.962, z: 0.0},
text: "Try Again",
textAlpha: 1,
backgroundAlpha: 0.00393,
lineHeight: 0.08,
visible: false,
emissive: true,
ignoreRayIntersection: true,
grabbable: false,
orientation: Overlays.getProperty(redirectOopsText, "orientation"),
parentID: redirectOopsText
});
var backImageNeutral = Overlays.addOverlay("image3d", {
name: "backImage",
localPosition: {x: 0.6, y: -0.6, z: 0.0},
url: Script.resourcesPath() + "images/interstitialPage/button.png",
alpha: 1,
visible: false,
emissive: true,
ignoreRayIntersection: false,
grabbable: false,
orientation: Overlays.getProperty(redirectOopsText, "orientation"),
parentID: redirectOopsText
});
var backImageHover = Overlays.addOverlay("image3d", {
name: "backImageHover",
localPosition: {x: 0.6, y: -0.6, z: 0.0},
url: Script.resourcesPath() + "images/interstitialPage/button_hover.png",
alpha: 1,
visible: false,
emissive: true,
ignoreRayIntersection: false,
grabbable: false,
orientation: Overlays.getProperty(redirectOopsText, "orientation"),
parentID: redirectOopsText
});
var backText = Overlays.addOverlay("text3d", {
name: "backText",
localPosition: {x: 0.6, y: -0.962, z: 0.0},
text: "Back",
textAlpha: 1,
backgroundAlpha: 0.00393,
lineHeight: 0.08,
visible: false,
emissive: true,
ignoreRayIntersection: true,
grabbable: false,
orientation: Overlays.getProperty(redirectOopsText, "orientation"),
parentID: redirectOopsText
});
function toggleOverlays(isInErrorState) {
isErrorState = isInErrorState;
if (!isInErrorState) {
var properties = {
visible: false
};
Overlays.editOverlay(redirectOopsText, properties);
Overlays.editOverlay(tryAgainImageNeutral, properties);
Overlays.editOverlay(tryAgainImageHover, properties);
Overlays.editOverlay(backImageNeutral, properties);
Overlays.editOverlay(backImageHover, properties);
Overlays.editOverlay(tryAgainText, properties);
Overlays.editOverlay(backText, properties);
return;
}
var oopsText = getOopsText();
// if oopsText === "", it was a success.
var overlaysVisible = (oopsText !== "");
// for catching init or if error state were to be different.
isErrorState = overlaysVisible;
var properties = {
visible: overlaysVisible
};
var textWidth = Overlays.textSize(redirectOopsText, oopsText).width;
var textOverlayWidth = oopsDimensions.x;
var oopsTextProperties = {
visible: overlaysVisible,
text: oopsText,
textAlpha: overlaysVisible,
// either visible or invisible. 0 doesn't work in Mac.
backgroundAlpha: overlaysVisible * 0.00393,
leftMargin: (textOverlayWidth - textWidth) / 2
};
var tryAgainTextWidth = Overlays.textSize(tryAgainText, "Try Again").width;
var tryAgainImageWidth = Overlays.getProperty(tryAgainImageNeutral, "dimensions").x;
var tryAgainTextProperties = {
visible: overlaysVisible,
leftMargin: (tryAgainImageWidth - tryAgainTextWidth) / 2
};
var backTextWidth = Overlays.textSize(backText, "Back").width;
var backImageWidth = Overlays.getProperty(backImageNeutral, "dimensions").x;
var backTextProperties = {
visible: overlaysVisible,
leftMargin: (backImageWidth - backTextWidth) / 2
};
Overlays.editOverlay(redirectOopsText, oopsTextProperties);
Overlays.editOverlay(tryAgainImageNeutral, properties);
Overlays.editOverlay(backImageNeutral, properties);
Overlays.editOverlay(tryAgainImageHover, {visible: false});
Overlays.editOverlay(backImageHover, {visible: false});
Overlays.editOverlay(tryAgainText, tryAgainTextProperties);
Overlays.editOverlay(backText, backTextProperties);
}
function clickedOnOverlay(overlayID, event) {
if (event.isRightButton) {
// don't allow right-clicks.
return;
}
if (tryAgainImageHover === overlayID) {
location.goToLastAddress();
} else if (backImageHover === overlayID && location.canGoBack()) {
location.goBack();
}
}
function cleanup() {
Script.clearInterval(timer);
timer = null;
Overlays.deleteOverlay(redirectOopsText);
Overlays.deleteOverlay(tryAgainImageNeutral);
Overlays.deleteOverlay(backImageNeutral);
Overlays.deleteOverlay(tryAgainImageHover);
Overlays.deleteOverlay(backImageHover);
Overlays.deleteOverlay(tryAgainText);
Overlays.deleteOverlay(backText);
}
toggleOverlays(true);
Overlays.mouseReleaseOnOverlay.connect(clickedOnOverlay);
Overlays.hoverEnterOverlay.connect(function(overlayID, event) {
if (!isErrorState) {
// don't allow hover overlay events to get caught if it's not in error state anymore.
return;
}
if (overlayID === backImageNeutral && location.canGoBack()) {
Overlays.editOverlay(backImageNeutral, {visible: false});
Overlays.editOverlay(backImageHover, {visible: true});
}
if (overlayID === tryAgainImageNeutral) {
Overlays.editOverlay(tryAgainImageNeutral, {visible: false});
Overlays.editOverlay(tryAgainImageHover, {visible: true});
}
});
Overlays.hoverLeaveOverlay.connect(function(overlayID, event) {
if (!isErrorState) {
// don't allow hover overlay events to get caught if it's not in error state anymore.
return;
}
if (overlayID === backImageHover) {
Overlays.editOverlay(backImageHover, {visible: false});
Overlays.editOverlay(backImageNeutral, {visible: true});
}
if (overlayID === tryAgainImageHover) {
Overlays.editOverlay(tryAgainImageHover, {visible: false});
Overlays.editOverlay(tryAgainImageNeutral, {visible: true});
}
});
Window.redirectErrorStateChanged.connect(toggleOverlays);
Script.scriptEnding.connect(cleanup);
}());

View file

@ -4,13 +4,17 @@ if (PRODUCTION_BUILD)
set(PRODUCTION_OPTION "--production") set(PRODUCTION_OPTION "--production")
endif() endif()
if (CLIENT_ONLY)
set(CLIENT_ONLY_OPTION "--client_only")
endif()
# add a target that will package the console # add a target that will package the console
add_custom_target(${TARGET_NAME}-npm-install add_custom_target(${TARGET_NAME}-npm-install
COMMAND npm install COMMAND npm install
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
) )
add_custom_target(${TARGET_NAME} add_custom_target(${TARGET_NAME}
COMMAND npm run packager -- --out ${CMAKE_CURRENT_BINARY_DIR} ${PRODUCTION_OPTION} COMMAND npm run packager -- --out ${CMAKE_CURRENT_BINARY_DIR} ${PRODUCTION_OPTION} ${CLIENT_ONLY_OPTION}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${TARGET_NAME}-npm-install DEPENDS ${TARGET_NAME}-npm-install
) )
@ -19,11 +23,21 @@ set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Server Console")
set_target_properties(${TARGET_NAME}-npm-install PROPERTIES FOLDER "hidden/Server Console") set_target_properties(${TARGET_NAME}-npm-install PROPERTIES FOLDER "hidden/Server Console")
# add a dependency from the package target to the server components # add a dependency from the package target to the server components
add_dependencies(${TARGET_NAME} assignment-client domain-server) if (BUILD_CLIENT)
add_dependencies(${TARGET_NAME} interface)
endif()
if (BUILD_SERVER)
add_dependencies(${TARGET_NAME} assignment-client domain-server)
endif()
# set the packaged console folder depending on platform, so we can copy it # set the packaged console folder depending on platform, so we can copy it
if (APPLE) if (APPLE)
set(PACKAGED_CONSOLE_FOLDER "Sandbox-darwin-x64/${CONSOLE_EXEC_NAME}") if (CLIENT_ONLY)
set(PACKAGED_CONSOLE_FOLDER "Console-darwin-x64/${CONSOLE_EXEC_NAME}")
else ()
set(PACKAGED_CONSOLE_FOLDER "Sandbox-darwin-x64/${CONSOLE_EXEC_NAME}")
endif()
elseif (WIN32) elseif (WIN32)
set(PACKAGED_CONSOLE_FOLDER "server-console-win32-x64") set(PACKAGED_CONSOLE_FOLDER "server-console-win32-x64")
elseif (UNIX) elseif (UNIX)
@ -33,9 +47,9 @@ endif ()
# install the packaged Server Console in our install directory # install the packaged Server Console in our install directory
if (APPLE) if (APPLE)
install( install(
PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGED_CONSOLE_FOLDER}" DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGED_CONSOLE_FOLDER}"
USE_SOURCE_PERMISSIONS
DESTINATION ${CONSOLE_INSTALL_DIR} DESTINATION ${CONSOLE_INSTALL_DIR}
COMPONENT ${SERVER_COMPONENT}
) )
elseif (WIN32) elseif (WIN32)
set(CONSOLE_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGED_CONSOLE_FOLDER}") set(CONSOLE_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGED_CONSOLE_FOLDER}")
@ -43,7 +57,6 @@ elseif (WIN32)
install( install(
DIRECTORY "${CONSOLE_DESTINATION}/" DIRECTORY "${CONSOLE_DESTINATION}/"
DESTINATION ${CONSOLE_INSTALL_DIR} DESTINATION ${CONSOLE_INSTALL_DIR}
COMPONENT ${SERVER_COMPONENT}
) )
# sign the copied server console executable after install # sign the copied server console executable after install

View file

@ -1,6 +1,6 @@
{ {
"name": "HighFidelitySandbox", "name": "HighFidelityConsole",
"description": "High Fidelity Sandbox", "description": "High Fidelity Console",
"author": "High Fidelity", "author": "High Fidelity",
"license": "Apache-2.0", "license": "Apache-2.0",
"version": "1.0.0", "version": "1.0.0",

View file

@ -27,8 +27,8 @@ var options = {
} }
const EXEC_NAME = "server-console"; const EXEC_NAME = "server-console";
const SHORT_NAME = "Sandbox"; var SHORT_NAME = argv.client_only ? "Console" : "Sandbox";
const FULL_NAME = "High Fidelity Sandbox"; var FULL_NAME = argv.client_only ? "High Fidelity Console" : "High Fidelity Sandbox";
// setup per OS options // setup per OS options
if (osType == "Darwin") { if (osType == "Darwin") {

View file

@ -60,7 +60,10 @@ const HOME_CONTENT_URL = "http://cdn.highfidelity.com/content-sets/home-tutorial
const buildInfo = GetBuildInfo(); const buildInfo = GetBuildInfo();
const NotificationState = {
UNNOTIFIED: 'unnotified',
NOTIFIED: 'notified'
};
// Update lock filepath // Update lock filepath
const UPDATER_LOCK_FILENAME = ".updating"; const UPDATER_LOCK_FILENAME = ".updating";
@ -104,12 +107,21 @@ userConfig.load(configPath);
const ipcMain = electron.ipcMain; const ipcMain = electron.ipcMain;
function isServerInstalled() { function isInterfaceInstalled () {
return interfacePath && userConfig.get("serverInstalled", true); if (osType == "Darwin") {
// In OSX Sierra, the app translocation process moves
// the executable to a random location before starting it
// which makes finding the interface near impossible using
// relative paths. For now, as there are no server-only
// installs, we just assume the interface is installed here
return true;
} else {
return interfacePath;
}
} }
function isInterfaceInstalled() { function isServerInstalled () {
return dsPath && acPath && userConfig.get("interfaceInstalled", true); return dsPath && acPath;
} }
var isShuttingDown = false; var isShuttingDown = false;
@ -259,10 +271,14 @@ var debug = argv.debug;
var binaryType = argv.binaryType; var binaryType = argv.binaryType;
interfacePath = pathFinder.discoveredPath("Interface", binaryType, buildInfo.releaseType); interfacePath = pathFinder.discoveredPath("interface", binaryType, buildInfo.releaseType);
dsPath = pathFinder.discoveredPath("domain-server", binaryType, buildInfo.releaseType); dsPath = pathFinder.discoveredPath("domain-server", binaryType, buildInfo.releaseType);
acPath = pathFinder.discoveredPath("assignment-client", binaryType, buildInfo.releaseType); acPath = pathFinder.discoveredPath("assignment-client", binaryType, buildInfo.releaseType);
console.log("Domain Server Path: " + dsPath);
console.log("Assignment Client Path: " + acPath);
console.log("Interface Path: " + interfacePath);
function binaryMissingMessage(displayName, executableName, required) { function binaryMissingMessage(displayName, executableName, required) {
var message = "The " + displayName + " executable was not found.\n"; var message = "The " + displayName + " executable was not found.\n";
@ -286,18 +302,6 @@ function binaryMissingMessage(displayName, executableName, required) {
return message; return message;
} }
// if at this point any of the paths are null, we're missing something we wanted to find
if (!dsPath) {
dialog.showErrorBox("Domain Server Not Found", binaryMissingMessage("domain-server", "domain-server", true));
app.exit(0);
}
if (!acPath) {
dialog.showErrorBox("Assignment Client Not Found", binaryMissingMessage("assignment-client", "assignment-client", true));
app.exit(0);
}
function openFileBrowser(path) { function openFileBrowser(path) {
// Add quotes around path // Add quotes around path
path = '"' + path + '"'; path = '"' + path + '"';
@ -332,12 +336,21 @@ const HifiNotifications = hfNotifications.HifiNotifications;
const HifiNotificationType = hfNotifications.NotificationType; const HifiNotificationType = hfNotifications.NotificationType;
var pendingNotifications = {} var pendingNotifications = {}
function notificationCallback(notificationType, pending = true) { var notificationState = NotificationState.UNNOTIFIED;
function setNotificationState (notificationType, pending = true) {
pendingNotifications[notificationType] = pending; pendingNotifications[notificationType] = pending;
notificationState = NotificationState.UNNOTIFIED;
for (var key in pendingNotifications) {
if (pendingNotifications[key]) {
notificationState = NotificationState.NOTIFIED;
break;
}
}
updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED); updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED);
} }
var trayNotifications = new HifiNotifications(userConfig, notificationCallback); var trayNotifications = new HifiNotifications(userConfig, setNotificationState);
var LogWindow = function(ac, ds) { var LogWindow = function(ac, ds) {
this.ac = ac; this.ac = ac;
@ -373,7 +386,7 @@ LogWindow.prototype = {
}; };
function visitSandboxClicked() { function visitSandboxClicked() {
if (interfacePath) { if (isInterfaceInstalled()) {
StartInterface('hifi://localhost'); StartInterface('hifi://localhost');
} else { } else {
// show an error to say that we can't go home without an interface instance // show an error to say that we can't go home without an interface instance
@ -397,7 +410,7 @@ var labels = {
type: 'checkbox', type: 'checkbox',
checked: true, checked: true,
click: function () { click: function () {
trayNotifications.enable(!trayNotifications.enabled(), notificationCallback); trayNotifications.enable(!trayNotifications.enabled(), setNotificationState);
userConfig.save(configPath); userConfig.save(configPath);
updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED); updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED);
} }
@ -406,32 +419,28 @@ var labels = {
label: 'GoTo', label: 'GoTo',
click: function () { click: function () {
StartInterface("hifiapp:GOTO"); StartInterface("hifiapp:GOTO");
pendingNotifications[HifiNotificationType.GOTO] = false; setNotificationState(HifiNotificationType.GOTO, false);
updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED);
} }
}, },
people: { people: {
label: 'People', label: 'People',
click: function () { click: function () {
StartInterface("hifiapp:PEOPLE"); StartInterface("hifiapp:PEOPLE");
pendingNotifications[HifiNotificationType.PEOPLE] = false; setNotificationState(HifiNotificationType.PEOPLE, false);
updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED);
} }
}, },
wallet: { wallet: {
label: 'Wallet', label: 'Wallet',
click: function () { click: function () {
StartInterface("hifiapp:WALLET"); StartInterface("hifiapp:WALLET");
pendingNotifications[HifiNotificationType.WALLET] = false; setNotificationState(HifiNotificationType.WALLET, false);
updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED);
} }
}, },
marketplace: { marketplace: {
label: 'Market', label: 'Market',
click: function () { click: function () {
StartInterface("hifiapp:MARKET"); StartInterface("hifiapp:MARKET");
pendingNotifications[HifiNotificationType.MARKETPLACE] = false; setNotificationState(HifiNotificationType.MARKETPLACE, false);
updateTrayMenu(homeServer ? homeServer.state : ProcessGroupStates.STOPPED);
} }
}, },
restart: { restart: {
@ -517,11 +526,13 @@ function buildMenuArray(serverState) {
menuArray.push(labels.share); menuArray.push(labels.share);
menuArray.push(separator); menuArray.push(separator);
if (isInterfaceInstalled()) { if (isInterfaceInstalled()) {
menuArray.push(labels.goto); if (trayNotifications.enabled()) {
menuArray.push(labels.people); menuArray.push(labels.goto);
menuArray.push(labels.wallet); menuArray.push(labels.people);
menuArray.push(labels.marketplace); menuArray.push(labels.wallet);
menuArray.push(separator); menuArray.push(labels.marketplace);
menuArray.push(separator);
}
menuArray.push(labels.showNotifications); menuArray.push(labels.showNotifications);
menuArray.push(separator); menuArray.push(separator);
} }
@ -553,10 +564,6 @@ function updateLabels(serverState) {
} }
labels.showNotifications.checked = trayNotifications.enabled(); labels.showNotifications.checked = trayNotifications.enabled();
labels.people.visible = trayNotifications.enabled();
labels.goto.visible = trayNotifications.enabled();
labels.wallet.visible = trayNotifications.enabled();
labels.marketplace.visible = trayNotifications.enabled();
labels.goto.icon = pendingNotifications[HifiNotificationType.GOTO] ? menuNotificationIcon : null; labels.goto.icon = pendingNotifications[HifiNotificationType.GOTO] ? menuNotificationIcon : null;
labels.people.icon = pendingNotifications[HifiNotificationType.PEOPLE] ? menuNotificationIcon : null; labels.people.icon = pendingNotifications[HifiNotificationType.PEOPLE] ? menuNotificationIcon : null;
labels.wallet.icon = pendingNotifications[HifiNotificationType.WALLET] ? menuNotificationIcon : null; labels.wallet.icon = pendingNotifications[HifiNotificationType.WALLET] ? menuNotificationIcon : null;
@ -567,7 +574,7 @@ function updateLabels(serverState) {
function updateTrayMenu(serverState) { function updateTrayMenu(serverState) {
if (tray) { if (tray) {
var menuArray = buildMenuArray(isShuttingDown ? null : serverState); var menuArray = buildMenuArray(isShuttingDown ? null : serverState);
tray.setImage(trayIcons[serverState]); tray.setImage(trayIcons[notificationState]);
tray.setContextMenu(Menu.buildFromTemplate(menuArray)); tray.setContextMenu(Menu.buildFromTemplate(menuArray));
if (isShuttingDown) { if (isShuttingDown) {
tray.setToolTip('High Fidelity - Shutting Down'); tray.setToolTip('High Fidelity - Shutting Down');
@ -787,9 +794,8 @@ function maybeShowSplash() {
const trayIconOS = (osType == "Darwin") ? "osx" : "win"; const trayIconOS = (osType == "Darwin") ? "osx" : "win";
var trayIcons = {}; var trayIcons = {};
trayIcons[ProcessGroupStates.STARTED] = "console-tray-" + trayIconOS + ".png"; trayIcons[NotificationState.UNNOTIFIED] = "console-tray-" + trayIconOS + ".png";
trayIcons[ProcessGroupStates.STOPPED] = "console-tray-" + trayIconOS + "-stopped.png"; trayIcons[NotificationState.NOTIFIED] = "console-tray-" + trayIconOS + "-stopped.png";
trayIcons[ProcessGroupStates.STOPPING] = "console-tray-" + trayIconOS + "-stopping.png";
for (var key in trayIcons) { for (var key in trayIcons) {
var fullPath = path.join(__dirname, '../resources/' + trayIcons[key]); var fullPath = path.join(__dirname, '../resources/' + trayIcons[key]);
var img = nativeImage.createFromPath(fullPath); var img = nativeImage.createFromPath(fullPath);
@ -815,33 +821,33 @@ function onContentLoaded() {
// Disable splash window for now. // Disable splash window for now.
// maybeShowSplash(); // maybeShowSplash();
if (buildInfo.releaseType == 'PRODUCTION' && !argv.noUpdater) {
const CHECK_FOR_UPDATES_INTERVAL_SECONDS = 60 * 30;
var hasShownUpdateNotification = false;
const updateChecker = new updater.UpdateChecker(buildInfo, CHECK_FOR_UPDATES_INTERVAL_SECONDS);
updateChecker.on('update-available', function(latestVersion, url) {
if (!hasShownUpdateNotification) {
notifier.notify({
icon: notificationIcon,
title: 'An update is available!',
message: 'High Fidelity version ' + latestVersion + ' is available',
wait: true,
appID: buildInfo.appUserModelId,
url: url
});
hasShownUpdateNotification = true;
}
});
notifier.on('click', function(notifierObject, options) {
log.debug("Got click", options.url);
shell.openExternal(options.url);
});
}
deleteOldFiles(logPath, DELETE_LOG_FILES_OLDER_THAN_X_SECONDS, LOG_FILE_REGEX);
if (isServerInstalled()) { if (isServerInstalled()) {
if (buildInfo.releaseType == 'PRODUCTION' && !argv.noUpdater) {
const CHECK_FOR_UPDATES_INTERVAL_SECONDS = 60 * 30;
var hasShownUpdateNotification = false;
const updateChecker = new updater.UpdateChecker(buildInfo, CHECK_FOR_UPDATES_INTERVAL_SECONDS);
updateChecker.on('update-available', function(latestVersion, url) {
if (!hasShownUpdateNotification) {
notifier.notify({
icon: notificationIcon,
title: 'An update is available!',
message: 'High Fidelity version ' + latestVersion + ' is available',
wait: true,
appID: buildInfo.appUserModelId,
url: url
});
hasShownUpdateNotification = true;
}
});
notifier.on('click', function(notifierObject, options) {
log.debug("Got click", options.url);
shell.openExternal(options.url);
});
}
deleteOldFiles(logPath, DELETE_LOG_FILES_OLDER_THAN_X_SECONDS, LOG_FILE_REGEX);
var dsArguments = ['--get-temp-name', var dsArguments = ['--get-temp-name',
'--parent-pid', process.pid]; '--parent-pid', process.pid];
domainServer = new Process('domain-server', dsPath, dsArguments, logPath); domainServer = new Process('domain-server', dsPath, dsArguments, logPath);
@ -902,13 +908,16 @@ app.on('ready', function() {
} }
// Create tray icon // Create tray icon
tray = new Tray(trayIcons[ProcessGroupStates.STOPPED]); tray = new Tray(trayIcons[NotificationState.UNNOTIFIED]);
tray.setToolTip('High Fidelity'); tray.setToolTip('High Fidelity');
tray.on('click', function() { tray.on('click', function() {
tray.popUpContextMenu(tray.menu); tray.popUpContextMenu(tray.menu);
}); });
if (isInterfaceInstalled()) {
trayNotifications.startPolling();
}
updateTrayMenu(ProcessGroupStates.STOPPED); updateTrayMenu(ProcessGroupStates.STOPPED);
maybeInstallDefaultContentSet(onContentLoaded); maybeInstallDefaultContentSet(onContentLoaded);

View file

@ -66,7 +66,7 @@ AccountInfo.prototype = {
case VariantTypes.USER_TYPE: case VariantTypes.USER_TYPE:
//user type //user type
var userTypeName = this._parseByteArray().toString('ascii').slice(0,-1); var userTypeName = this._parseByteArray().toString('ascii').slice(0,-1);
if (userTypeName == "DataServerAccountInfo") { if (userTypeName === "DataServerAccountInfo") {
return this._parseDataServerAccountInfo(); return this._parseDataServerAccountInfo();
} }
else { else {
@ -77,7 +77,7 @@ AccountInfo.prototype = {
}, },
_parseByteArray: function () { _parseByteArray: function () {
var length = this._parseUInt32(); var length = this._parseUInt32();
if (length == 0xffffffff) { if (length === 0xffffffff) {
return null; return null;
} }
var result = this.rawData.slice(this.parseOffset, this.parseOffset+length); var result = this.rawData.slice(this.parseOffset, this.parseOffset+length);
@ -91,7 +91,7 @@ AccountInfo.prototype = {
} }
// length in bytes; // length in bytes;
var length = this._parseUInt32(); var length = this._parseUInt32();
if (length == 0xFFFFFFFF) { if (length === 0xFFFFFFFF) {
return null; return null;
} }

View file

@ -7,6 +7,7 @@ const path = require('path');
const argv = require('yargs').argv; const argv = require('yargs').argv;
const hfprocess = require('./hf-process'); const hfprocess = require('./hf-process');
const osHomeDir = require('os-homedir'); const osHomeDir = require('os-homedir');
const childProcess = require('child_process');
const Process = hfprocess.Process; const Process = hfprocess.Process;
const binaryType = argv.binaryType; const binaryType = argv.binaryType;
@ -15,9 +16,9 @@ const osType = os.type();
exports.getBuildInfo = function() { exports.getBuildInfo = function() {
var buildInfoPath = null; var buildInfoPath = null;
if (osType == 'Windows_NT') { if (osType === 'Windows_NT') {
buildInfoPath = path.join(path.dirname(process.execPath), 'build-info.json'); buildInfoPath = path.join(path.dirname(process.execPath), 'build-info.json');
} else if (osType == 'Darwin') { } else if (osType === 'Darwin') {
var contentPath = ".app/Contents/"; var contentPath = ".app/Contents/";
var contentEndIndex = __dirname.indexOf(contentPath); var contentEndIndex = __dirname.indexOf(contentPath);
@ -34,7 +35,7 @@ exports.getBuildInfo = function() {
buildNumber: "0", buildNumber: "0",
stableBuild: "0", stableBuild: "0",
organization: "High Fidelity - dev", organization: "High Fidelity - dev",
appUserModelId: "com.highfidelity.sandbox-dev" appUserModelId: "com.highfidelity.console"
}; };
var buildInfo = DEFAULT_BUILD_INFO; var buildInfo = DEFAULT_BUILD_INFO;
@ -50,37 +51,59 @@ exports.getBuildInfo = function() {
} }
const buildInfo = exports.getBuildInfo(); const buildInfo = exports.getBuildInfo();
const interfacePath = pathFinder.discoveredPath("Interface", binaryType, buildInfo.releaseType); const interfacePath = pathFinder.discoveredPath("interface", binaryType, buildInfo.releaseType);
exports.startInterface = function(url) { exports.startInterface = function(url) {
var argArray = [];
// check if we have a url parameter to include if (osType === 'Darwin') {
if (url) { if (!url) {
argArray = ["--url", url]; log.debug("No URL given for startInterface");
return;
}
// do this as a workaround for app translocation on osx, which makes
// it nearly impossible to find the interface executable
var bundle_id = 'com.highfidelity.interface-dev';
if (buildInfo.releaseType == 'PR') {
bundle_id = 'com.highfidelity.interface-pr';
} else if (buildInfo.releaseType == 'PRODUCTION') {
bundle_id = 'com.highfidelity.interface';
}
childProcess.exec('open -b ' + bundle_id + ' --args --url ' + url);
} else {
var argArray = [];
// check if we have a url parameter to include
if (url) {
argArray = ["--url", url];
}
console.log("Starting with " + url);
// create a new Interface instance - Interface makes sure only one is running at a time
var pInterface = new Process('Interface', interfacePath, argArray);
pInterface.detached = true;
pInterface.start();
} }
console.log("Starting with " + url);
// create a new Interface instance - Interface makes sure only one is running at a time
var pInterface = new Process('Interface', interfacePath, argArray);
pInterface.detached = true;
pInterface.start();
} }
exports.isInterfaceRunning = function(done) { exports.isInterfaceRunning = function(done) {
var pInterface = new Process('interface', 'interface.exe'); if (osType === 'Windows_NT') {
var pInterface = new Process('interface', 'interface.exe');
} else if (osType === 'Darwin') {
var pInterface = new Process('interface', 'interface');
}
return pInterface.isRunning(done); return pInterface.isRunning(done);
} }
exports.getRootHifiDataDirectory = function(local) { exports.getRootHifiDataDirectory = function(local) {
var organization = buildInfo.organization; var organization = buildInfo.organization;
if (osType == 'Windows_NT') { if (osType === 'Windows_NT') {
if (local) { if (local) {
return path.resolve(osHomeDir(), 'AppData/Local', organization); return path.resolve(osHomeDir(), 'AppData/Local', organization);
} else { } else {
return path.resolve(osHomeDir(), 'AppData/Roaming', organization); return path.resolve(osHomeDir(), 'AppData/Roaming', organization);
} }
} else if (osType == 'Darwin') { } else if (osType === 'Darwin') {
return path.resolve(osHomeDir(), 'Library/Application Support', organization); return path.resolve(osHomeDir(), 'Library/Application Support', organization);
} else { } else {
return path.resolve(osHomeDir(), '.local/share/', organization); return path.resolve(osHomeDir(), '.local/share/', organization);

View file

@ -7,12 +7,15 @@ const path = require('path');
const AccountInfo = require('./hf-acctinfo').AccountInfo; const AccountInfo = require('./hf-acctinfo').AccountInfo;
const GetBuildInfo = hfApp.getBuildInfo; const GetBuildInfo = hfApp.getBuildInfo;
const buildInfo = GetBuildInfo(); const buildInfo = GetBuildInfo();
const osType = os.type();
const notificationIcon = path.join(__dirname, '../../resources/console-notification.png'); const notificationIcon = path.join(__dirname, '../../resources/console-notification.png');
const STORIES_NOTIFICATION_POLL_TIME_MS = 120 * 1000; const STORIES_NOTIFICATION_POLL_TIME_MS = 120 * 1000;
const PEOPLE_NOTIFICATION_POLL_TIME_MS = 120 * 1000; const PEOPLE_NOTIFICATION_POLL_TIME_MS = 120 * 1000;
const WALLET_NOTIFICATION_POLL_TIME_MS = 600 * 1000; const WALLET_NOTIFICATION_POLL_TIME_MS = 600 * 1000;
const MARKETPLACE_NOTIFICATION_POLL_TIME_MS = 600 * 1000; const MARKETPLACE_NOTIFICATION_POLL_TIME_MS = 600 * 1000;
const OSX_CLICK_DELAY_TIMEOUT = 500;
const METAVERSE_SERVER_URL= process.env.HIFI_METAVERSE_URL ? process.env.HIFI_METAVERSE_URL : 'https://metaverse.highfidelity.com' const METAVERSE_SERVER_URL= process.env.HIFI_METAVERSE_URL ? process.env.HIFI_METAVERSE_URL : 'https://metaverse.highfidelity.com'
const STORIES_URL= '/api/v1/user_stories'; const STORIES_URL= '/api/v1/user_stories';
@ -33,21 +36,22 @@ const NotificationType = {
MARKETPLACE: 'marketplace' MARKETPLACE: 'marketplace'
}; };
function HifiNotification(notificationType, notificationData, menuNotificationCallback) { function HifiNotification(notificationType, notificationData, menuNotificationCallback) {
this.type = notificationType; this.type = notificationType;
this.data = notificationData; this.data = notificationData;
} }
HifiNotification.prototype = { HifiNotification.prototype = {
show: function () { show: function (finished) {
var text = ""; var text = "";
var message = ""; var message = "";
var url = null; var url = null;
var app = null; var app = null;
switch (this.type) { switch (this.type) {
case NotificationType.GOTO: case NotificationType.GOTO:
if (typeof(this.data) == "number") { if (typeof(this.data) === "number") {
if (this.data == 1) { if (this.data === 1) {
text = "You have " + this.data + " event invitation pending." text = "You have " + this.data + " event invitation pending."
} else { } else {
text = "You have " + this.data + " event invitations pending." text = "You have " + this.data + " event invitations pending."
@ -62,8 +66,8 @@ HifiNotification.prototype = {
break; break;
case NotificationType.PEOPLE: case NotificationType.PEOPLE:
if (typeof(this.data) == "number") { if (typeof(this.data) === "number") {
if (this.data == 1) { if (this.data === 1) {
text = this.data + " of your connections is online." text = this.data + " of your connections is online."
} else { } else {
text = this.data + " of your connections are online." text = this.data + " of your connections are online."
@ -78,8 +82,8 @@ HifiNotification.prototype = {
break; break;
case NotificationType.WALLET: case NotificationType.WALLET:
if (typeof(this.data) == "number") { if (typeof(this.data) === "number") {
if (this.data == 1) { if (this.data === 1) {
text = "You have " + this.data + " unread Wallet transaction."; text = "You have " + this.data + " unread Wallet transaction.";
} else { } else {
text = "You have " + this.data + " unread Wallet transactions."; text = "You have " + this.data + " unread Wallet transactions.";
@ -94,8 +98,8 @@ HifiNotification.prototype = {
break; break;
case NotificationType.MARKETPLACE: case NotificationType.MARKETPLACE:
if (typeof(this.data) == "number") { if (typeof(this.data) === "number") {
if (this.data == 1) { if (this.data === 1) {
text = this.data + " of your purchased items has an update available."; text = this.data + " of your purchased items has an update available.";
} else { } else {
text = this.data + " of your purchased items have updates available."; text = this.data + " of your purchased items have updates available.";
@ -114,8 +118,18 @@ HifiNotification.prototype = {
message: message, message: message,
wait: true, wait: true,
appID: buildInfo.appUserModelId, appID: buildInfo.appUserModelId,
url: url url: url,
}); timeout: 5
},
function (error, reason, metadata) {
if (finished) {
if (osType === 'Darwin') {
setTimeout(finished, OSX_CLICK_DELAY_TIMEOUT);
} else {
finished();
}
}
});
} }
} }
@ -128,7 +142,8 @@ function HifiNotifications(config, menuNotificationCallback) {
this.walletSince = new Date(this.config.get("walletNotifySince", "1970-01-01T00:00:00.000Z")); this.walletSince = new Date(this.config.get("walletNotifySince", "1970-01-01T00:00:00.000Z"));
this.marketplaceSince = new Date(this.config.get("marketplaceNotifySince", "1970-01-01T00:00:00.000Z")); this.marketplaceSince = new Date(this.config.get("marketplaceNotifySince", "1970-01-01T00:00:00.000Z"));
this.enable(this.enabled()); this.pendingNotifications = [];
var _menuNotificationCallback = menuNotificationCallback; var _menuNotificationCallback = menuNotificationCallback;
notifier.on('click', function (notifierObject, options) { notifier.on('click', function (notifierObject, options) {
@ -139,7 +154,7 @@ function HifiNotifications(config, menuNotificationCallback) {
HifiNotifications.prototype = { HifiNotifications.prototype = {
enable: function (enabled) { enable: function (enabled) {
this.config.set("enableTrayNotifications", enabled); this.config.set("disableTrayNotifications", !enabled);
if (enabled) { if (enabled) {
var _this = this; var _this = this;
this.storiesPollTimer = setInterval(function () { this.storiesPollTimer = setInterval(function () {
@ -170,22 +185,14 @@ HifiNotifications.prototype = {
}, },
MARKETPLACE_NOTIFICATION_POLL_TIME_MS); MARKETPLACE_NOTIFICATION_POLL_TIME_MS);
} else { } else {
if (this.storiesPollTimer) { this.stopPolling();
clearInterval(this.storiesPollTimer);
}
if (this.peoplePollTimer) {
clearInterval(this.peoplePollTimer);
}
if (this.walletPollTimer) {
clearInterval(this.walletPollTimer);
}
if (this.marketplacePollTimer) {
clearInterval(this.marketplacePollTimer);
}
} }
}, },
enabled: function () { enabled: function () {
return this.config.get("enableTrayNotifications", true); return !this.config.get("disableTrayNotifications", false);
},
startPolling: function () {
this.enable(this.enabled());
}, },
stopPolling: function () { stopPolling: function () {
this.config.set("storiesNotifySince", this.storiesSince.toISOString()); this.config.set("storiesNotifySince", this.storiesSince.toISOString());
@ -193,7 +200,48 @@ HifiNotifications.prototype = {
this.config.set("walletNotifySince", this.walletSince.toISOString()); this.config.set("walletNotifySince", this.walletSince.toISOString());
this.config.set("marketplaceNotifySince", this.marketplaceSince.toISOString()); this.config.set("marketplaceNotifySince", this.marketplaceSince.toISOString());
this.enable(false); if (this.storiesPollTimer) {
clearInterval(this.storiesPollTimer);
}
if (this.peoplePollTimer) {
clearInterval(this.peoplePollTimer);
}
if (this.walletPollTimer) {
clearInterval(this.walletPollTimer);
}
if (this.marketplacePollTimer) {
clearInterval(this.marketplacePollTimer);
}
},
_showNotification: function () {
var _this = this;
if (osType === 'Darwin') {
this.pendingNotifications[0].show(function () {
// For OSX
// Don't attempt to show the next notification
// until the current is clicked or times out
// as the OSX Notifier stuff will dismiss the
// previous notification immediately when a
// new one is submitted
_this.pendingNotifications.shift();
if(_this.pendingNotifications.length > 0) {
_this._showNotification();
}
});
} else {
// For Windows
// All notifications are sent immediately as they are queued
// by windows in Tray Notifications and can be bulk seen and
// dismissed
_this.pendingNotifications.shift().show();
}
},
_addNotification: function (notification) {
this.pendingNotifications.push(notification);
if (this.pendingNotifications.length === 1) {
this._showNotification();
}
}, },
_pollToDisableHighlight: function (notifyType, error, data) { _pollToDisableHighlight: function (notifyType, error, data) {
if (error || !data.body) { if (error || !data.body) {
@ -248,8 +296,7 @@ HifiNotifications.prototype = {
} }
_this.menuNotificationCallback(notifyType, true); _this.menuNotificationCallback(notifyType, true);
if (content.total_entries >= maxNotificationItemCount) { if (content.total_entries >= maxNotificationItemCount) {
var notification = new HifiNotification(notifyType, content.total_entries); _this._addNotification(new HifiNotification(notifyType, content.total_entries));
notification.show();
} else { } else {
var notifyData = [] var notifyData = []
switch (notifyType) { switch (notifyType) {
@ -268,8 +315,7 @@ HifiNotifications.prototype = {
} }
notifyData.forEach(function (notifyDataEntry) { notifyData.forEach(function (notifyDataEntry) {
var notification = new HifiNotification(notifyType, notifyDataEntry); _this._addNotification(new HifiNotification(notifyType, notifyDataEntry));
notification.show();
}); });
} }
finished(true, token); finished(true, token);
@ -376,13 +422,11 @@ HifiNotifications.prototype = {
} }
if (newUsers.size >= maxNotificationItemCount) { if (newUsers.size >= maxNotificationItemCount) {
var notification = new HifiNotification(NotificationType.PEOPLE, newUsers.size); _this._addNotification(new HifiNotification(NotificationType.PEOPLE, newUsers.size));
notification.show();
return; return;
} }
newUsers.forEach(function (user) { newUsers.forEach(function (user) {
var notification = new HifiNotification(NotificationType.PEOPLE, user); _this._addNotification(new HifiNotification(NotificationType.PEOPLE, user));
notification.show();
}); });
}); });
}); });

View file

@ -274,7 +274,9 @@ Process.prototype = extend(Process.prototype, {
done(running); done(running);
}); });
} else if (os.type == 'Darwin') { } else if (os.type == 'Darwin') {
console.log("TODO IsRunning Darwin"); childProcess.exec('ps cax | grep ' + _command, function (err, stdout, stderr) {
done(stdout.length > 0);
});
} }
}, },

View file

@ -1,8 +1,9 @@
var fs = require('fs'); var fs = require('fs');
var path = require('path'); var path = require('path');
const { app } = require('electron');
function platformExtension(name) { function platformExtension(name) {
if (name == "Interface") { if (name == "interface") {
if (process.platform == "darwin") { if (process.platform == "darwin") {
return ".app/Contents/MacOS/" + name return ".app/Contents/MacOS/" + name
} else if (process.platform == "win32") { } else if (process.platform == "win32") {
@ -53,9 +54,9 @@ exports.searchPaths = function(name, binaryType, releaseType) {
var componentsPath = appPath + "/Contents/MacOS/Components.app/Contents/MacOS/"; var componentsPath = appPath + "/Contents/MacOS/Components.app/Contents/MacOS/";
paths.push(componentsPath + name + extension); paths.push(componentsPath + name + extension);
// check beside the app bundle for the binaries
paths.push(path.join(path.dirname(appPath), name + extension));
} }
// check beside the app bundle for the binaries
paths.push(path.join(path.dirname(app.getAppPath()), "../../..", name + extension));
} }
} }