mirror of
https://github.com/overte-org/overte.git
synced 2025-07-14 09:36:36 +02:00
Merge branch 'master' into 20855
This commit is contained in:
commit
2ac9f282c7
84 changed files with 1305 additions and 633 deletions
23
cmake/externals/LibOVR/CMakeLists.txt
vendored
23
cmake/externals/LibOVR/CMakeLists.txt
vendored
|
@ -12,19 +12,16 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||||
# 0.5 public
|
# 0.5 public
|
||||||
# URL http://static.oculus.com/sdk-downloads/ovr_sdk_win_0.5.0.1.zip
|
# URL http://static.oculus.com/sdk-downloads/ovr_sdk_win_0.5.0.1.zip
|
||||||
# URL_MD5 d3fc4c02db9be5ff08af4ef4c97b32f9
|
# URL_MD5 d3fc4c02db9be5ff08af4ef4c97b32f9
|
||||||
# 0.6 public
|
# 1.3 public
|
||||||
# URL http://static.oculus.com/sdk-downloads/0.6.0.1/Public/1435190862/ovr_sdk_win_0.6.0.1.zip
|
# URL http://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.3.0_public.zip
|
||||||
# URL_MD5 4b3ef825f9a1d6d3035c9f6820687da9
|
# URL_MD5 4d26faba0c1f35ff80bf674c96ed9259
|
||||||
# 0.8 public
|
|
||||||
# URL http://static.oculus.com/sdk-downloads/0.8.0.0/Public/1445451746/ovr_sdk_win_0.8.0.0.zip
|
|
||||||
# URL_MD5 54944b03b95149d6010f84eb701b9647
|
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
${EXTERNAL_NAME}
|
${EXTERNAL_NAME}
|
||||||
URL http://static.oculus.com/sdk-downloads/0.8.0.0/Public/1445451746/ovr_sdk_win_0.8.0.0.zip
|
URL http://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.3.0_public.zip
|
||||||
URL_MD5 54944b03b95149d6010f84eb701b9647
|
URL_MD5 a2dcf695e0f03a70fdd1ed7480585e82
|
||||||
CONFIGURE_COMMAND ""
|
CONFIGURE_COMMAND ""
|
||||||
BUILD_COMMAND ""
|
BUILD_COMMAND ""
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
|
@ -33,14 +30,16 @@ if (WIN32)
|
||||||
|
|
||||||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||||
|
|
||||||
# FIXME need to account for different architectures
|
set(LIBOVR_DIR ${SOURCE_DIR}/OculusSDK/LibOVR)
|
||||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/LibOVR/Include CACHE TYPE INTERNAL)
|
|
||||||
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/LibOVR/Lib/Windows/x64/Release/VS2013/LibOVR.lib CACHE TYPE INTERNAL)
|
set(LIBOVR_LIB_DIR ${LIBOVR_DIR}/Lib/Windows/x64/Release/VS2013 CACHE TYPE INTERNAL)
|
||||||
else()
|
else()
|
||||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/LibOVR/Lib/Windows/Win32/Release/VS2013/LibOVR.lib CACHE TYPE INTERNAL)
|
set(LIBOVR_LIB_DIR ${LIBOVR_DIR}/Lib/Windows/Win32/Release/VS2013 CACHE TYPE INTERNAL)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${LIBOVR_DIR}/Include CACHE TYPE INTERNAL)
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${LIBOVR_LIB_DIR}/LibOVR.lib CACHE TYPE INTERNAL)
|
||||||
|
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
|
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
|
|
|
@ -85,8 +85,8 @@ macro(GENERATE_INSTALLERS)
|
||||||
|
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
|
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
|
||||||
|
|
||||||
cpack_add_component(${CLIENT_COMPONENT} DISPLAY_NAME "High Fidelity Client")
|
cpack_add_component(${CLIENT_COMPONENT} DISPLAY_NAME "High Fidelity Interface")
|
||||||
cpack_add_component(${SERVER_COMPONENT} DISPLAY_NAME "High Fidelity Server")
|
cpack_add_component(${SERVER_COMPONENT} DISPLAY_NAME "High Fidelity Sandbox")
|
||||||
|
|
||||||
include(CPack)
|
include(CPack)
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
|
@ -53,7 +53,7 @@ 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 "Server Console.app")
|
set(CONSOLE_EXEC_NAME "Sandbox.app")
|
||||||
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")
|
||||||
|
@ -84,12 +84,19 @@ macro(SET_PACKAGING_PARAMETERS)
|
||||||
|
|
||||||
# shortcut names
|
# shortcut names
|
||||||
if (PRODUCTION_BUILD)
|
if (PRODUCTION_BUILD)
|
||||||
set(INTERFACE_SHORTCUT_NAME "High Fidelity")
|
set(INTERFACE_SHORTCUT_NAME "Interface")
|
||||||
set(CONSOLE_SHORTCUT_NAME "Server Console")
|
set(CONSOLE_SHORTCUT_NAME "Sandbox")
|
||||||
else ()
|
else ()
|
||||||
set(INTERFACE_SHORTCUT_NAME "High Fidelity - ${BUILD_VERSION}")
|
set(INTERFACE_SHORTCUT_NAME "Interface - ${BUILD_VERSION}")
|
||||||
set(CONSOLE_SHORTCUT_NAME "Server Console - ${BUILD_VERSION}")
|
set(CONSOLE_SHORTCUT_NAME "Sandbox - ${BUILD_VERSION}")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
set(INTERFACE_HF_SHORTCUT_NAME "High Fidelity ${INTERFACE_SHORTCUT_NAME}")
|
||||||
|
set(CONSOLE_HF_SHORTCUT_NAME "High Fidelity ${CONSOLE_SHORTCUT_NAME}")
|
||||||
|
|
||||||
|
set(PRE_SANDBOX_INTERFACE_SHORTCUT_NAME "High Fidelity")
|
||||||
|
set(PRE_SANDBOX_CONSOLE_SHORTCUT_NAME "Server Console")
|
||||||
|
|
||||||
# check if we need to find signtool
|
# check if we need to find signtool
|
||||||
if (PRODUCTION_BUILD OR PR_BUILD)
|
if (PRODUCTION_BUILD OR PR_BUILD)
|
||||||
find_program(SIGNTOOL_EXECUTABLE signtool PATHS "C:/Program Files (x86)/Windows Kits/8.1" PATH_SUFFIXES "bin/x64")
|
find_program(SIGNTOOL_EXECUTABLE signtool PATHS "C:/Program Files (x86)/Windows Kits/8.1" PATH_SUFFIXES "bin/x64")
|
||||||
|
|
|
@ -10,10 +10,14 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
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_WIN_EXEC_NAME "@INTERFACE_EXEC_PREFIX@.exe")
|
set(INTERFACE_WIN_EXEC_NAME "@INTERFACE_EXEC_PREFIX@.exe")
|
||||||
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_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_CONSOLE_SHORTCUT_NAME "@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@")
|
||||||
set(DS_EXEC_NAME "@DS_EXEC_NAME@")
|
set(DS_EXEC_NAME "@DS_EXEC_NAME@")
|
||||||
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@")
|
||||||
|
|
|
@ -387,7 +387,7 @@ Function PostInstallOptionsPage
|
||||||
StrCpy $OffsetUnits u
|
StrCpy $OffsetUnits u
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
||||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @INTERFACE_SHORTCUT_NAME@"
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @INTERFACE_HF_SHORTCUT_NAME@"
|
||||||
Pop $DesktopClientCheckbox
|
Pop $DesktopClientCheckbox
|
||||||
IntOp $CurrentOffset $CurrentOffset + 15
|
IntOp $CurrentOffset $CurrentOffset + 15
|
||||||
|
|
||||||
|
@ -396,7 +396,7 @@ Function PostInstallOptionsPage
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
||||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for High Fidelity @CONSOLE_SHORTCUT_NAME@"
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Create a desktop shortcut for @CONSOLE_HF_SHORTCUT_NAME@"
|
||||||
Pop $DesktopServerCheckbox
|
Pop $DesktopServerCheckbox
|
||||||
|
|
||||||
; set the checkbox state depending on what is present in the registry
|
; set the checkbox state depending on what is present in the registry
|
||||||
|
@ -404,7 +404,7 @@ Function PostInstallOptionsPage
|
||||||
|
|
||||||
IntOp $CurrentOffset $CurrentOffset + 15
|
IntOp $CurrentOffset $CurrentOffset + 15
|
||||||
|
|
||||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch High Fidelity @CONSOLE_SHORTCUT_NAME@ on startup"
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ on startup"
|
||||||
Pop $ServerStartupCheckbox
|
Pop $ServerStartupCheckbox
|
||||||
|
|
||||||
; set the checkbox state depending on what is present in the registry
|
; set the checkbox state depending on what is present in the registry
|
||||||
|
@ -414,9 +414,9 @@ Function PostInstallOptionsPage
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
||||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch High Fidelity Server Console after install"
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @CONSOLE_HF_SHORTCUT_NAME@ after install"
|
||||||
${Else}
|
${Else}
|
||||||
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch High Fidelity after install"
|
${NSD_CreateCheckbox} 0 $CurrentOffset$OffsetUnits 100% 10u "&Launch @INTERFACE_HF_SHORTCUT_NAME@ after install"
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
Pop $LaunchNowCheckbox
|
Pop $LaunchNowCheckbox
|
||||||
|
@ -465,10 +465,10 @@ Function ReadPostInstallOptions
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
||||||
; check if the user asked for a desktop shortcut to Server Console
|
; check if the user asked for a desktop shortcut to Sandbox
|
||||||
${NSD_GetState} $DesktopServerCheckbox $DesktopServerState
|
${NSD_GetState} $DesktopServerCheckbox $DesktopServerState
|
||||||
|
|
||||||
; check if the user asked to have Server Console launched every startup
|
; check if the user asked to have Sandbox launched every startup
|
||||||
${NSD_GetState} $ServerStartupCheckbox $ServerStartupState
|
${NSD_GetState} $ServerStartupCheckbox $ServerStartupState
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
|
@ -485,7 +485,7 @@ Function HandlePostInstallOptions
|
||||||
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@}
|
||||||
; 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}
|
||||||
CreateShortCut "$DESKTOP\@INTERFACE_SHORTCUT_NAME@.lnk" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"
|
CreateShortCut "$DESKTOP\@INTERFACE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"
|
||||||
!insertmacro WritePostInstallOption "@CLIENT_DESKTOP_SHORTCUT_REG_KEY@" YES
|
!insertmacro WritePostInstallOption "@CLIENT_DESKTOP_SHORTCUT_REG_KEY@" YES
|
||||||
${Else}
|
${Else}
|
||||||
!insertmacro WritePostInstallOption @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ NO
|
!insertmacro WritePostInstallOption @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ NO
|
||||||
|
@ -494,23 +494,23 @@ Function HandlePostInstallOptions
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
|
||||||
; check if the user asked for a desktop shortcut to Server Console
|
; check if the user asked for a desktop shortcut to Sandbox
|
||||||
${If} $DesktopServerState == ${BST_CHECKED}
|
${If} $DesktopServerState == ${BST_CHECKED}
|
||||||
CreateShortCut "$DESKTOP\@CONSOLE_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
CreateShortCut "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
||||||
!insertmacro WritePostInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ YES
|
!insertmacro WritePostInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ YES
|
||||||
${Else}
|
${Else}
|
||||||
!insertmacro WritePostInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO
|
!insertmacro WritePostInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
; check if the user asked to have Server Console launched every startup
|
; check if the user asked to have Sandbox launched every startup
|
||||||
${If} $ServerStartupState == ${BST_CHECKED}
|
${If} $ServerStartupState == ${BST_CHECKED}
|
||||||
; in case we added a shortcut in the global context, pull that now
|
; in case we added a shortcut in the global context, pull that now
|
||||||
SetShellVarContext all
|
SetShellVarContext all
|
||||||
Delete "$SMSTARTUP\@CONSOLE_SHORTCUT_NAME@.lnk"
|
Delete "$SMSTARTUP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
|
||||||
|
|
||||||
; make a startup shortcut in this user's current context
|
; make a startup shortcut in this user's current context
|
||||||
SetShellVarContext current
|
SetShellVarContext current
|
||||||
CreateShortCut "$SMSTARTUP\@CONSOLE_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
CreateShortCut "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
|
||||||
|
|
||||||
; reset the shell var context back
|
; reset the shell var context back
|
||||||
SetShellVarContext all
|
SetShellVarContext all
|
||||||
|
@ -589,6 +589,19 @@ Section "-Core installation"
|
||||||
Delete "$INSTDIR\version"
|
Delete "$INSTDIR\version"
|
||||||
Delete "$INSTDIR\xinput1_3.dll"
|
Delete "$INSTDIR\xinput1_3.dll"
|
||||||
|
|
||||||
|
; Delete old desktop shortcuts before they were renamed during Sandbox rename
|
||||||
|
Delete "$DESKTOP\@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@.lnk"
|
||||||
|
Delete "$DESKTOP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
|
||||||
|
|
||||||
|
; Delete old Start Menu shortcuts before Sandbox rename
|
||||||
|
Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@PRE_SANDBOX_INTERFACE_SHORTCUT_NAME@.lnk"
|
||||||
|
Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
|
||||||
|
|
||||||
|
; Delete old startup item for Server Console before Sandbox rename
|
||||||
|
SetShellVarContext current
|
||||||
|
Delete "$SMSTARTUP\@PRE_SANDBOX_CONSOLE_SHORTCUT_NAME@.lnk"
|
||||||
|
SetShellVarContext all
|
||||||
|
|
||||||
; Rename the incorrectly cased Raleway font
|
; Rename the incorrectly cased Raleway font
|
||||||
Rename "$INSTDIR\resources\qml\styles-uit\RalewaySemibold.qml" "$INSTDIR\resources\qml\styles-uit\RalewaySemiBold.qml"
|
Rename "$INSTDIR\resources\qml\styles-uit\RalewaySemibold.qml" "$INSTDIR\resources\qml\styles-uit\RalewaySemiBold.qml"
|
||||||
|
|
||||||
|
@ -724,8 +737,8 @@ SectionEnd
|
||||||
!macroend
|
!macroend
|
||||||
|
|
||||||
!macro CheckForRunningApplications action prompter
|
!macro CheckForRunningApplications action prompter
|
||||||
!insertmacro PromptForRunningApplication "@INTERFACE_WIN_EXEC_NAME@" "High Fidelity client" ${action} ${prompter}
|
!insertmacro PromptForRunningApplication "@INTERFACE_WIN_EXEC_NAME@" "@CONSOLE_SHORTCUT_NAME@" ${action} ${prompter}
|
||||||
!insertmacro PromptForRunningApplication "@CONSOLE_WIN_EXEC_NAME@" "Server Console" ${action} ${prompter}
|
!insertmacro PromptForRunningApplication "@CONSOLE_WIN_EXEC_NAME@" "@INTERFACE_SHORTCUT_NAME@" ${action} ${prompter}
|
||||||
!insertmacro PromptForRunningApplication "@DS_EXEC_NAME@" "Domain Server" ${action} ${prompter}
|
!insertmacro PromptForRunningApplication "@DS_EXEC_NAME@" "Domain Server" ${action} ${prompter}
|
||||||
!insertmacro PromptForRunningApplication "@AC_EXEC_NAME@" "Assignment Client" ${action} ${prompter}
|
!insertmacro PromptForRunningApplication "@AC_EXEC_NAME@" "Assignment Client" ${action} ${prompter}
|
||||||
!macroend
|
!macroend
|
||||||
|
@ -869,12 +882,12 @@ 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 "$DESKTOP\@INTERFACE_SHORTCUT_NAME@.lnk"
|
Delete "$DESKTOP\@INTERFACE_HF_SHORTCUT_NAME@.lnk"
|
||||||
Delete "$DESKTOP\@CONSOLE_SHORTCUT_NAME@.lnk"
|
Delete "$DESKTOP\@CONSOLE_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_SHORTCUT_NAME@.lnk"
|
Delete "$SMSTARTUP\@CONSOLE_HF_SHORTCUT_NAME@.lnk"
|
||||||
SetShellVarContext all
|
SetShellVarContext all
|
||||||
|
|
||||||
@CPACK_NSIS_DELETE_ICONS@
|
@CPACK_NSIS_DELETE_ICONS@
|
||||||
|
|
1
examples/utilities/render/configSlider/qmldir
Normal file
1
examples/utilities/render/configSlider/qmldir
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ConfigSlider 1.0 ConfigSlider.qml
|
114
examples/utilities/render/culling.qml
Normal file
114
examples/utilities/render/culling.qml
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
//
|
||||||
|
// culling.qml
|
||||||
|
// examples/utilities/render
|
||||||
|
//
|
||||||
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import "configSlider"
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: root
|
||||||
|
spacing: 8
|
||||||
|
property var sceneOctree: Render.getConfig("DrawSceneOctree");
|
||||||
|
property var itemSelection: Render.getConfig("DrawItemSelection");
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
sceneOctree.enabled = true;
|
||||||
|
itemSelection.enabled = true;
|
||||||
|
sceneOctree.showVisibleCells = false;
|
||||||
|
sceneOctree.showEmptyCells = false;
|
||||||
|
itemSelection.showInsideItems = false;
|
||||||
|
itemSelection.showInsideSubcellItems = false;
|
||||||
|
itemSelection.showPartialItems = false;
|
||||||
|
itemSelection.showPartialSubcellItems = false;
|
||||||
|
}
|
||||||
|
Component.onDestruction: {
|
||||||
|
sceneOctree.enabled = false;
|
||||||
|
itemSelection.enabled = false;
|
||||||
|
Render.getConfig("FetchSceneSelection").freezeFrustum = false;
|
||||||
|
Render.getConfig("CullSceneSelection").freezeFrustum = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupBox {
|
||||||
|
title: "Culling"
|
||||||
|
Row {
|
||||||
|
spacing: 8
|
||||||
|
Column {
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
CheckBox {
|
||||||
|
text: "Freeze Culling Frustum"
|
||||||
|
checked: false
|
||||||
|
onCheckedChanged: {
|
||||||
|
Render.getConfig("FetchSceneSelection").freezeFrustum = checked;
|
||||||
|
Render.getConfig("CullSceneSelection").freezeFrustum = checked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: "Octree"
|
||||||
|
}
|
||||||
|
CheckBox {
|
||||||
|
text: "Visible Cells"
|
||||||
|
checked: root.sceneOctree.showVisibleCells
|
||||||
|
onCheckedChanged: { root.sceneOctree.showVisibleCells = checked }
|
||||||
|
}
|
||||||
|
CheckBox {
|
||||||
|
text: "Empty Cells"
|
||||||
|
checked: false
|
||||||
|
onCheckedChanged: { root.sceneOctree.showEmptyCells = checked }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "Frustum Items"
|
||||||
|
}
|
||||||
|
CheckBox {
|
||||||
|
text: "Inside Items"
|
||||||
|
checked: false
|
||||||
|
onCheckedChanged: { root.itemSelection.showInsideItems = checked }
|
||||||
|
}
|
||||||
|
CheckBox {
|
||||||
|
text: "Inside Sub-cell Items"
|
||||||
|
checked: false
|
||||||
|
onCheckedChanged: { root.itemSelection.showInsideSubcellItems = checked }
|
||||||
|
}
|
||||||
|
CheckBox {
|
||||||
|
text: "Partial Items"
|
||||||
|
checked: false
|
||||||
|
onCheckedChanged: { root.itemSelection.showPartialItems = checked }
|
||||||
|
}
|
||||||
|
CheckBox {
|
||||||
|
text: "Partial Sub-cell Items"
|
||||||
|
checked: false
|
||||||
|
onCheckedChanged: { root.itemSelection.showPartialSubcellItems = checked }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupBox {
|
||||||
|
title: "Render Items"
|
||||||
|
|
||||||
|
Column{
|
||||||
|
Repeater {
|
||||||
|
model: [ "Opaque:DrawOpaqueDeferred", "Transparent:DrawTransparentDeferred", "Light:DrawLight",
|
||||||
|
"Opaque Overlays:DrawOverlay3DOpaque", "Transparent Overlays:DrawOverlay3DTransparent" ]
|
||||||
|
ConfigSlider {
|
||||||
|
label: qsTr(modelData.split(":")[0])
|
||||||
|
integral: true
|
||||||
|
config: Render.getConfig(modelData.split(":")[1])
|
||||||
|
property: "maxDrawn"
|
||||||
|
max: config.numDrawn
|
||||||
|
min: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
examples/utilities/render/debugRender.js
Normal file
21
examples/utilities/render/debugRender.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
//
|
||||||
|
// debugRender.js
|
||||||
|
// examples/utilities/render
|
||||||
|
//
|
||||||
|
// Sam Gateau, created on 3/22/2016.
|
||||||
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
// Set up the qml ui
|
||||||
|
var qml = Script.resolvePath('culling.qml');
|
||||||
|
var window = new OverlayWindow({
|
||||||
|
title: 'Render Draws',
|
||||||
|
source: qml,
|
||||||
|
width: 300,
|
||||||
|
height: 200
|
||||||
|
});
|
||||||
|
window.setPosition(200, 50);
|
||||||
|
window.closed.connect(function() { Script.stop(); });
|
|
@ -10,6 +10,7 @@
|
||||||
//
|
//
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
|
import "configSlider"
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: root
|
id: root
|
|
@ -1,6 +1,6 @@
|
||||||
//
|
//
|
||||||
// PlotPerf.qml
|
// PlotPerf.qml
|
||||||
// examples/utilities/tools/render
|
// examples/utilities/render/plotperf
|
||||||
//
|
//
|
||||||
// Created by Sam Gateau on 3//2016
|
// Created by Sam Gateau on 3//2016
|
||||||
// Copyright 2016 High Fidelity, Inc.
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
@ -15,40 +15,64 @@ Item {
|
||||||
id: root
|
id: root
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 100
|
height: 100
|
||||||
|
|
||||||
|
// The title of the graph
|
||||||
property string title
|
property string title
|
||||||
property var config
|
|
||||||
property string parameters
|
|
||||||
|
|
||||||
// THis is my hack to get the name of the first property and assign it to a trigger var in order to get
|
// THe object used as the default source object for the prop plots
|
||||||
|
property var object
|
||||||
|
|
||||||
|
// THis is my hack to get a property and assign it to a trigger var in order to get
|
||||||
// a signal called whenever the value changed
|
// a signal called whenever the value changed
|
||||||
property var trigger: config[parameters.split(":")[3].split("-")[0]]
|
property var trigger
|
||||||
|
|
||||||
|
// Plots is an array of plot descriptor
|
||||||
|
// a default plot descriptor expects the following object:
|
||||||
|
// prop: [ {
|
||||||
|
// object: {} // Optional: this is the object from which the prop will be fetched,
|
||||||
|
// if nothing than the object from root is used
|
||||||
|
// prop:"bufferCPUCount", // Needed the name of the property from the object to feed the plot
|
||||||
|
// label: "CPU", // Optional: Label as displayed on the plot
|
||||||
|
// color: "#00B4EF" // Optional: Color of the curve
|
||||||
|
// unit: "km/h" // Optional: Unit added to the value displayed, if nothing then the default unit is used
|
||||||
|
// scale: 1 // Optional: Extra scaling used to represent the value, this scale is combined with the global scale.
|
||||||
|
// },
|
||||||
|
property var plots
|
||||||
|
|
||||||
|
// Default value scale used to define the max value of the chart
|
||||||
|
property var valueScale: 1
|
||||||
|
|
||||||
|
// Default value unit appended to the value displayed
|
||||||
|
property var valueUnit: ""
|
||||||
|
|
||||||
|
// Default number of digits displayed
|
||||||
|
property var valueNumDigits: 0
|
||||||
|
|
||||||
|
|
||||||
property var inputs: parameters.split(":")
|
|
||||||
property var valueScale: +inputs[0]
|
|
||||||
property var valueUnit: inputs[1]
|
|
||||||
property var valueNumDigits: inputs[2]
|
|
||||||
property var input_VALUE_OFFSET: 3
|
|
||||||
property var valueMax : 1
|
property var valueMax : 1
|
||||||
|
|
||||||
property var _values : new Array()
|
property var _values : new Array()
|
||||||
property var tick : 0
|
property var tick : 0
|
||||||
|
|
||||||
function createValues() {
|
function createValues() {
|
||||||
if (inputs.length > input_VALUE_OFFSET) {
|
print("trigger is: " + JSON.stringify(trigger))
|
||||||
for (var i = input_VALUE_OFFSET; i < inputs.length; i++) {
|
if (Array.isArray(plots)) {
|
||||||
var varProps = inputs[i].split("-")
|
for (var i =0; i < plots.length; i++) {
|
||||||
_values.push( {
|
var plot = plots[i];
|
||||||
value: varProps[0],
|
print(" a pnew Plot:" + JSON.stringify(plot));
|
||||||
valueMax: 1,
|
_values.push( {
|
||||||
numSamplesConstantMax: 0,
|
object: (plot["object"] !== undefined ? plot["object"] : root.object),
|
||||||
valueHistory: new Array(),
|
value: plot["prop"],
|
||||||
label: varProps[1],
|
valueMax: 1,
|
||||||
color: varProps[2],
|
numSamplesConstantMax: 0,
|
||||||
scale: (varProps.length > 3 ? varProps[3] : 1),
|
valueHistory: new Array(),
|
||||||
unit: (varProps.length > 4 ? varProps[4] : valueUnit)
|
label: (plot["label"] !== undefined ? plot["label"] : ""),
|
||||||
})
|
color: (plot["color"] !== undefined ? plot["color"] : "white"),
|
||||||
}
|
scale: (plot["scale"] !== undefined ? plot["scale"] : 1),
|
||||||
}
|
unit: (plot["unit"] !== undefined ? plot["unit"] : valueUnit)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
print("in creator" + JSON.stringify(_values));
|
print("in creator" + JSON.stringify(_values));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -69,7 +93,8 @@ Item {
|
||||||
var currentValueMax = 0
|
var currentValueMax = 0
|
||||||
for (var i = 0; i < _values.length; i++) {
|
for (var i = 0; i < _values.length; i++) {
|
||||||
|
|
||||||
var currentVal = config[_values[i].value] * _values[i].scale;
|
var currentVal = _values[i].object[_values[i].value] * _values[i].scale;
|
||||||
|
|
||||||
_values[i].valueHistory.push(currentVal)
|
_values[i].valueHistory.push(currentVal)
|
||||||
_values[i].numSamplesConstantMax++;
|
_values[i].numSamplesConstantMax++;
|
||||||
|
|
195
examples/utilities/render/stats.qml
Normal file
195
examples/utilities/render/stats.qml
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
//
|
||||||
|
// stats.qml
|
||||||
|
// examples/utilities/render
|
||||||
|
//
|
||||||
|
// Created by Zach Pomerantz on 2/8/2016
|
||||||
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import "plotperf"
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: statsUI
|
||||||
|
anchors.fill:parent
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: stats
|
||||||
|
spacing: 8
|
||||||
|
anchors.fill:parent
|
||||||
|
|
||||||
|
property var config: Render.getConfig("Stats")
|
||||||
|
|
||||||
|
function evalEvenHeight() {
|
||||||
|
// Why do we have to do that manually ? cannot seem to find a qml / anchor / layout mode that does that ?
|
||||||
|
return (height - spacing * (children.length - 1)) / children.length
|
||||||
|
}
|
||||||
|
|
||||||
|
PlotPerf {
|
||||||
|
title: "Num Buffers"
|
||||||
|
height: parent.evalEvenHeight()
|
||||||
|
object: stats.config
|
||||||
|
trigger: stats.config["bufferCPUCount"]
|
||||||
|
plots: [
|
||||||
|
{
|
||||||
|
prop: "bufferCPUCount",
|
||||||
|
label: "CPU",
|
||||||
|
color: "#00B4EF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "bufferGPUCount",
|
||||||
|
label: "GPU",
|
||||||
|
color: "#1AC567"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
PlotPerf {
|
||||||
|
title: "gpu::Buffer Memory"
|
||||||
|
height: parent.evalEvenHeight()
|
||||||
|
object: stats.config
|
||||||
|
trigger: stats.config["bufferCPUMemoryUsage"]
|
||||||
|
valueScale: 1048576
|
||||||
|
valueUnit: "Mb"
|
||||||
|
valueNumDigits: "1"
|
||||||
|
plots: [
|
||||||
|
{
|
||||||
|
prop: "bufferCPUMemoryUsage",
|
||||||
|
label: "CPU",
|
||||||
|
color: "#00B4EF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "bufferGPUMemoryUsage",
|
||||||
|
label: "GPU",
|
||||||
|
color: "#1AC567"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
PlotPerf {
|
||||||
|
title: "Num Textures"
|
||||||
|
height: parent.evalEvenHeight()
|
||||||
|
object: stats.config
|
||||||
|
trigger: stats.config["textureCPUCount"]
|
||||||
|
plots: [
|
||||||
|
{
|
||||||
|
prop: "textureCPUCount",
|
||||||
|
label: "CPU",
|
||||||
|
color: "#00B4EF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "textureGPUCount",
|
||||||
|
label: "GPU",
|
||||||
|
color: "#1AC567"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "frameTextureCount",
|
||||||
|
label: "Frame",
|
||||||
|
color: "#E2334D"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
PlotPerf {
|
||||||
|
title: "gpu::Texture Memory"
|
||||||
|
height: parent.evalEvenHeight()
|
||||||
|
object: stats.config
|
||||||
|
trigger: stats.config["textureCPUMemoryUsage"]
|
||||||
|
valueScale: 1048576
|
||||||
|
valueUnit: "Mb"
|
||||||
|
valueNumDigits: "1"
|
||||||
|
plots: [
|
||||||
|
{
|
||||||
|
prop: "textureCPUMemoryUsage",
|
||||||
|
label: "CPU",
|
||||||
|
color: "#00B4EF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "textureGPUMemoryUsage",
|
||||||
|
label: "GPU",
|
||||||
|
color: "#1AC567"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
PlotPerf {
|
||||||
|
title: "Triangles"
|
||||||
|
height: parent.evalEvenHeight()
|
||||||
|
object: stats.config
|
||||||
|
trigger: stats.config["frameTriangleCount"]
|
||||||
|
valueScale: 1000
|
||||||
|
valueUnit: "K"
|
||||||
|
plots: [
|
||||||
|
{
|
||||||
|
prop: "frameTriangleCount",
|
||||||
|
label: "Triangles",
|
||||||
|
color: "#1AC567"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "frameTriangleRate",
|
||||||
|
label: "rate",
|
||||||
|
color: "#E2334D",
|
||||||
|
scale: 0.001,
|
||||||
|
unit: "MT/s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
PlotPerf {
|
||||||
|
title: "Drawcalls"
|
||||||
|
height: parent.evalEvenHeight()
|
||||||
|
object: stats.config
|
||||||
|
trigger: stats.config["frameDrawcallCount"]
|
||||||
|
plots: [
|
||||||
|
{
|
||||||
|
prop: "frameAPIDrawcallCount",
|
||||||
|
label: "API Drawcalls",
|
||||||
|
color: "#00B4EF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "frameDrawcallCount",
|
||||||
|
label: "GPU Drawcalls",
|
||||||
|
color: "#1AC567"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "frameDrawcallRate",
|
||||||
|
label: "rate",
|
||||||
|
color: "#E2334D",
|
||||||
|
scale: 0.001,
|
||||||
|
unit: "K/s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
property var drawOpaqueConfig: Render.getConfig("DrawOpaqueDeferred")
|
||||||
|
property var drawTransparentConfig: Render.getConfig("DrawTransparentDeferred")
|
||||||
|
property var drawLightConfig: Render.getConfig("DrawLight")
|
||||||
|
|
||||||
|
PlotPerf {
|
||||||
|
title: "Items"
|
||||||
|
height: parent.evalEvenHeight()
|
||||||
|
object: parent.drawOpaqueConfig
|
||||||
|
trigger: Render.getConfig("DrawOpaqueDeferred")["numDrawn"]
|
||||||
|
plots: [
|
||||||
|
{
|
||||||
|
object: Render.getConfig("DrawOpaqueDeferred"),
|
||||||
|
prop: "numDrawn",
|
||||||
|
label: "Opaques",
|
||||||
|
color: "#1AC567"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
object: Render.getConfig("DrawTransparentDeferred"),
|
||||||
|
prop: "numDrawn",
|
||||||
|
label: "Translucents",
|
||||||
|
color: "#00B4EF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
object: Render.getConfig("DrawLight"),
|
||||||
|
prop: "numDrawn",
|
||||||
|
label: "Lights",
|
||||||
|
color: "#E2334D"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,99 +0,0 @@
|
||||||
//
|
|
||||||
// debugRenderOctree.js
|
|
||||||
// examples/utilities/tools
|
|
||||||
//
|
|
||||||
// Sam Gateau
|
|
||||||
// Copyright 2016 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
Script.include("cookies.js");
|
|
||||||
|
|
||||||
var panel = new Panel(10, 300);
|
|
||||||
var drawOctree = Render.RenderDeferredTask.DrawSceneOctree;
|
|
||||||
Render.RenderDeferredTask.DrawSceneOctree.enabled = true;
|
|
||||||
Render.RenderDeferredTask.DrawItemSelection.enabled = true;
|
|
||||||
|
|
||||||
panel.newCheckbox("Show Octree Cells",
|
|
||||||
function(value) { Render.RenderDeferredTask.DrawSceneOctree.showVisibleCells = value; },
|
|
||||||
function() { return (Render.RenderDeferredTask.DrawSceneOctree.showVisibleCells); },
|
|
||||||
function(value) { return (value); }
|
|
||||||
);
|
|
||||||
panel.newCheckbox("Show Empty Cells",
|
|
||||||
function(value) { Render.RenderDeferredTask.DrawSceneOctree.showEmptyCells = value; },
|
|
||||||
function() { return (Render.RenderDeferredTask.DrawSceneOctree.showEmptyCells); },
|
|
||||||
function(value) { return (value); }
|
|
||||||
);
|
|
||||||
panel.newCheckbox("Freeze Frustum",
|
|
||||||
function(value) { Render.RenderDeferredTask.FetchSceneSelection.freezeFrustum = value; Render.RenderDeferredTask.CullSceneSelection.freezeFrustum = value; },
|
|
||||||
function() { return (Render.RenderDeferredTask.FetchSceneSelection.freezeFrustum); },
|
|
||||||
function(value) { return (value); }
|
|
||||||
);
|
|
||||||
panel.newCheckbox("Show Inside Items",
|
|
||||||
function(value) { Render.RenderDeferredTask.DrawItemSelection.showInsideItems = value; },
|
|
||||||
function() { return (Render.RenderDeferredTask.DrawItemSelection.showInsideItems); },
|
|
||||||
function(value) { return (value); }
|
|
||||||
);
|
|
||||||
|
|
||||||
panel.newCheckbox("Show Inside Subcell Items",
|
|
||||||
function(value) { Render.RenderDeferredTask.DrawItemSelection.showInsideSubcellItems = value; },
|
|
||||||
function() { return (Render.RenderDeferredTask.DrawItemSelection.showInsideSubcellItems); },
|
|
||||||
function(value) { return (value); }
|
|
||||||
);
|
|
||||||
|
|
||||||
panel.newCheckbox("Show Partial Items",
|
|
||||||
function(value) { Render.RenderDeferredTask.DrawItemSelection.showPartialItems = value; },
|
|
||||||
function() { return (Render.RenderDeferredTask.DrawItemSelection.showPartialItems); },
|
|
||||||
function(value) { return (value); }
|
|
||||||
);
|
|
||||||
|
|
||||||
panel.newCheckbox("Show Partial Subcell Items",
|
|
||||||
function(value) { Render.RenderDeferredTask.DrawItemSelection.showPartialSubcellItems = value; },
|
|
||||||
function() { return (Render.RenderDeferredTask.DrawItemSelection.showPartialSubcellItems); },
|
|
||||||
function(value) { return (value); }
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
panel.newSlider('Cells Free / Allocated', -1, 1,
|
|
||||||
function(value) { value; }, // setter
|
|
||||||
function() { return Render.RenderDeferredTask.DrawSceneOctree.numFreeCells; }, // getter
|
|
||||||
function(value) { return value; });
|
|
||||||
|
|
||||||
this.update = function () {
|
|
||||||
var numFree = Render.RenderDeferredTask.DrawSceneOctree.numFreeCells;
|
|
||||||
var numAlloc = Render.RenderDeferredTask.DrawSceneOctree.numAllocatedCells;
|
|
||||||
var title = [
|
|
||||||
' ' + name,
|
|
||||||
numFree + ' / ' + numAlloc
|
|
||||||
].join('\t');
|
|
||||||
|
|
||||||
widget.editTitle({ text: title });
|
|
||||||
slider.setMaxValue(numAlloc);
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
function mouseMoveEvent(event) {
|
|
||||||
panel.mouseMoveEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
function mousePressEvent(event) {
|
|
||||||
panel.mousePressEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
function mouseReleaseEvent(event) {
|
|
||||||
panel.mouseReleaseEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
|
||||||
Controller.mousePressEvent.connect(mousePressEvent);
|
|
||||||
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
|
||||||
|
|
||||||
function scriptEnding() {
|
|
||||||
panel.destroy();
|
|
||||||
Render.RenderDeferredTask.DrawSceneOctree.enabled = false;
|
|
||||||
Render.RenderDeferredTask.DrawItemSelection.enabled = false;
|
|
||||||
}
|
|
||||||
Script.scriptEnding.connect(scriptEnding);
|
|
||||||
|
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
//
|
|
||||||
// stats.qml
|
|
||||||
// examples/utilities/tools/render
|
|
||||||
//
|
|
||||||
// Created by Zach Pomerantz on 2/8/2016
|
|
||||||
// Copyright 2016 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
import QtQuick 2.5
|
|
||||||
import QtQuick.Controls 1.4
|
|
||||||
import "plotperf"
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: statsUI
|
|
||||||
anchors.fill:parent
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: stats
|
|
||||||
spacing: 8
|
|
||||||
anchors.fill:parent
|
|
||||||
|
|
||||||
property var config: Render.getConfig("Stats")
|
|
||||||
|
|
||||||
function evalEvenHeight() {
|
|
||||||
// Why do we have to do that manually ? cannot seem to find a qml / anchor / layout mode that does that ?
|
|
||||||
return (height - spacing * (children.length - 1)) / children.length
|
|
||||||
}
|
|
||||||
|
|
||||||
PlotPerf {
|
|
||||||
title: "Num Buffers"
|
|
||||||
config: stats.config
|
|
||||||
height: parent.evalEvenHeight()
|
|
||||||
parameters: "1::0:bufferCPUCount-CPU-#00B4EF:bufferGPUCount-GPU-#1AC567"
|
|
||||||
}
|
|
||||||
PlotPerf {
|
|
||||||
title: "gpu::Buffer Memory"
|
|
||||||
config: stats.config
|
|
||||||
height: parent.evalEvenHeight()
|
|
||||||
parameters: "1048576:Mb:1:bufferCPUMemoryUsage-CPU-#00B4EF:bufferGPUMemoryUsage-GPU-#1AC567"
|
|
||||||
}
|
|
||||||
|
|
||||||
PlotPerf {
|
|
||||||
title: "Num Textures"
|
|
||||||
config: stats.config
|
|
||||||
height: parent.evalEvenHeight()
|
|
||||||
parameters: "1::0:textureCPUCount-CPU-#00B4EF:textureGPUCount-GPU-#1AC567:frameTextureCount-Frame-#E2334D"
|
|
||||||
}
|
|
||||||
PlotPerf {
|
|
||||||
title: "gpu::Texture Memory"
|
|
||||||
config: stats.config
|
|
||||||
height: parent.evalEvenHeight()
|
|
||||||
parameters: "1048576:Mb:1:textureCPUMemoryUsage-CPU-#00B4EF:textureGPUMemoryUsage-GPU-#1AC567"
|
|
||||||
}
|
|
||||||
PlotPerf {
|
|
||||||
title: "Drawcalls"
|
|
||||||
config: stats.config
|
|
||||||
height: parent.evalEvenHeight()
|
|
||||||
parameters: "1::0:frameDrawcallCount-frame-#E2334D:frameDrawcallRate-rate-#1AC567-0.001-K/s"
|
|
||||||
}
|
|
||||||
PlotPerf {
|
|
||||||
title: "Triangles"
|
|
||||||
config: stats.config
|
|
||||||
height: parent.evalEvenHeight()
|
|
||||||
parameters: "1000:K:0:frameTriangleCount-frame-#E2334D:frameTriangleRate-rate-#1AC567-0.001-MT/s"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <QtNetwork/QNetworkRequest>
|
#include <QtNetwork/QNetworkRequest>
|
||||||
|
|
||||||
#include <LimitedNodeList.h>
|
#include <LimitedNodeList.h>
|
||||||
|
#include <NetworkAccessManager.h>
|
||||||
#include <NetworkingConstants.h>
|
#include <NetworkingConstants.h>
|
||||||
#include <udt/PacketHeaders.h>
|
#include <udt/PacketHeaders.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
@ -33,7 +34,8 @@ IceServer::IceServer(int argc, char* argv[]) :
|
||||||
_id(QUuid::createUuid()),
|
_id(QUuid::createUuid()),
|
||||||
_serverSocket(),
|
_serverSocket(),
|
||||||
_activePeers(),
|
_activePeers(),
|
||||||
_httpManager(QHostAddress::AnyIPv4, ICE_SERVER_MONITORING_PORT, QString("%1/web/").arg(QCoreApplication::applicationDirPath()), this)
|
_httpManager(QHostAddress::AnyIPv4, ICE_SERVER_MONITORING_PORT, QString("%1/web/").arg(QCoreApplication::applicationDirPath()), this),
|
||||||
|
_lastInactiveCheckTimestamp(QDateTime::currentMSecsSinceEpoch())
|
||||||
{
|
{
|
||||||
// start the ice-server socket
|
// start the ice-server socket
|
||||||
qDebug() << "ice-server socket is listening on" << ICE_SERVER_DEFAULT_PORT;
|
qDebug() << "ice-server socket is listening on" << ICE_SERVER_DEFAULT_PORT;
|
||||||
|
@ -68,8 +70,6 @@ bool IceServer::packetVersionMatch(const udt::Packet& packet) {
|
||||||
|
|
||||||
void IceServer::processPacket(std::unique_ptr<udt::Packet> packet) {
|
void IceServer::processPacket(std::unique_ptr<udt::Packet> packet) {
|
||||||
|
|
||||||
_lastPacketTimestamp = QDateTime::currentMSecsSinceEpoch();
|
|
||||||
|
|
||||||
auto nlPacket = NLPacket::fromBase(std::move(packet));
|
auto nlPacket = NLPacket::fromBase(std::move(packet));
|
||||||
|
|
||||||
// make sure that this packet at least looks like something we can read
|
// make sure that this packet at least looks like something we can read
|
||||||
|
@ -201,8 +201,8 @@ bool IceServer::isVerifiedHeartbeat(const QUuid& domainID, const QByteArray& pla
|
||||||
|
|
||||||
void IceServer::requestDomainPublicKey(const QUuid& domainID) {
|
void IceServer::requestDomainPublicKey(const QUuid& domainID) {
|
||||||
// send a request to the metaverse API for the public key for this domain
|
// send a request to the metaverse API for the public key for this domain
|
||||||
QNetworkAccessManager* manager = new QNetworkAccessManager { this };
|
auto& networkAccessManager = NetworkAccessManager::getInstance();
|
||||||
connect(manager, &QNetworkAccessManager::finished, this, &IceServer::publicKeyReplyFinished);
|
connect(&networkAccessManager, &QNetworkAccessManager::finished, this, &IceServer::publicKeyReplyFinished);
|
||||||
|
|
||||||
QUrl publicKeyURL { NetworkingConstants::METAVERSE_SERVER_URL };
|
QUrl publicKeyURL { NetworkingConstants::METAVERSE_SERVER_URL };
|
||||||
QString publicKeyPath = QString("/api/v1/domains/%1/public_key").arg(uuidStringWithoutCurlyBraces(domainID));
|
QString publicKeyPath = QString("/api/v1/domains/%1/public_key").arg(uuidStringWithoutCurlyBraces(domainID));
|
||||||
|
@ -213,7 +213,7 @@ void IceServer::requestDomainPublicKey(const QUuid& domainID) {
|
||||||
|
|
||||||
qDebug() << "Requesting public key for domain with ID" << domainID;
|
qDebug() << "Requesting public key for domain with ID" << domainID;
|
||||||
|
|
||||||
manager->get(publicKeyRequest);
|
networkAccessManager.get(publicKeyRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IceServer::publicKeyReplyFinished(QNetworkReply* reply) {
|
void IceServer::publicKeyReplyFinished(QNetworkReply* reply) {
|
||||||
|
@ -281,6 +281,8 @@ void IceServer::sendPeerInformationPacket(const NetworkPeer& peer, const HifiSoc
|
||||||
void IceServer::clearInactivePeers() {
|
void IceServer::clearInactivePeers() {
|
||||||
NetworkPeerHash::iterator peerItem = _activePeers.begin();
|
NetworkPeerHash::iterator peerItem = _activePeers.begin();
|
||||||
|
|
||||||
|
_lastInactiveCheckTimestamp = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
|
||||||
while (peerItem != _activePeers.end()) {
|
while (peerItem != _activePeers.end()) {
|
||||||
SharedNetworkPeer peer = peerItem.value();
|
SharedNetworkPeer peer = peerItem.value();
|
||||||
|
|
||||||
|
@ -309,11 +311,14 @@ bool IceServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url, b
|
||||||
|
|
||||||
const quint64 MAX_PACKET_GAP_MS_FOR_STUCK_SOCKET = 10 * 1000;
|
const quint64 MAX_PACKET_GAP_MS_FOR_STUCK_SOCKET = 10 * 1000;
|
||||||
|
|
||||||
int statusNumber = (QDateTime::currentMSecsSinceEpoch() - _lastPacketTimestamp > MAX_PACKET_GAP_MS_FOR_STUCK_SOCKET)
|
auto sinceLastInactiveCheck = QDateTime::currentMSecsSinceEpoch() - _lastInactiveCheckTimestamp;
|
||||||
? 1 : 0;
|
int statusNumber = (sinceLastInactiveCheck > MAX_PACKET_GAP_MS_FOR_STUCK_SOCKET) ? 1 : 0;
|
||||||
|
|
||||||
connection->respond(HTTPConnection::StatusCode200, QByteArray::number(statusNumber));
|
connection->respond(HTTPConnection::StatusCode200, QByteArray::number(statusNumber));
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ private:
|
||||||
using DomainPublicKeyHash = std::unordered_map<QUuid, RSAUniquePtr>;
|
using DomainPublicKeyHash = std::unordered_map<QUuid, RSAUniquePtr>;
|
||||||
DomainPublicKeyHash _domainPublicKeys;
|
DomainPublicKeyHash _domainPublicKeys;
|
||||||
|
|
||||||
quint64 _lastPacketTimestamp;
|
quint64 _lastInactiveCheckTimestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_IceServer_h
|
#endif // hifi_IceServer_h
|
||||||
|
|
|
@ -224,7 +224,6 @@ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStanda
|
||||||
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).append("/script.js");
|
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).append("/script.js");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const QString DEFAULT_SCRIPTS_JS_URL = "http://s3.amazonaws.com/hifi-public/scripts/defaultScripts.js";
|
|
||||||
Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS);
|
Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS);
|
||||||
|
|
||||||
const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensions {
|
const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensions {
|
||||||
|
@ -1490,11 +1489,15 @@ void Application::paintGL() {
|
||||||
// FIXME not needed anymore?
|
// FIXME not needed anymore?
|
||||||
_offscreenContext->makeCurrent();
|
_offscreenContext->makeCurrent();
|
||||||
|
|
||||||
displayPlugin->updateHeadPose(_frameCount);
|
displayPlugin->beginFrameRender(_frameCount);
|
||||||
|
|
||||||
// update the avatar with a fresh HMD pose
|
// update the avatar with a fresh HMD pose
|
||||||
getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
|
getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
|
||||||
|
|
||||||
|
// update sensorToWorldMatrix for camera and hand controllers
|
||||||
|
getMyAvatar()->updateSensorToWorldMatrix();
|
||||||
|
|
||||||
|
|
||||||
auto lodManager = DependencyManager::get<LODManager>();
|
auto lodManager = DependencyManager::get<LODManager>();
|
||||||
|
|
||||||
|
|
||||||
|
@ -2007,6 +2010,12 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_Y:
|
||||||
|
if (isShifted && isMeta) {
|
||||||
|
getActiveDisplayPlugin()->cycleDebugOutput();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case Qt::Key_B:
|
case Qt::Key_B:
|
||||||
if (isMeta) {
|
if (isMeta) {
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
@ -2572,11 +2581,6 @@ void Application::idle(uint64_t now) {
|
||||||
return; // bail early, nothing to do here.
|
return; // bail early, nothing to do here.
|
||||||
}
|
}
|
||||||
|
|
||||||
checkChangeCursor();
|
|
||||||
|
|
||||||
Stats::getInstance()->updateStats();
|
|
||||||
AvatarInputs::getInstance()->update();
|
|
||||||
|
|
||||||
// These tasks need to be done on our first idle, because we don't want the showing of
|
// These tasks need to be done on our first idle, because we don't want the showing of
|
||||||
// overlay subwindows to do a showDesktop() until after the first time through
|
// overlay subwindows to do a showDesktop() until after the first time through
|
||||||
static bool firstIdle = true;
|
static bool firstIdle = true;
|
||||||
|
@ -2625,6 +2629,11 @@ void Application::idle(uint64_t now) {
|
||||||
// We're going to execute idle processing, so restart the last idle timer
|
// We're going to execute idle processing, so restart the last idle timer
|
||||||
_lastTimeUpdated.start();
|
_lastTimeUpdated.start();
|
||||||
|
|
||||||
|
checkChangeCursor();
|
||||||
|
|
||||||
|
Stats::getInstance()->updateStats();
|
||||||
|
AvatarInputs::getInstance()->update();
|
||||||
|
|
||||||
{
|
{
|
||||||
static uint64_t lastIdleStart{ now };
|
static uint64_t lastIdleStart{ now };
|
||||||
uint64_t idleStartToStartDuration = now - lastIdleStart;
|
uint64_t idleStartToStartDuration = now - lastIdleStart;
|
||||||
|
@ -3389,9 +3398,6 @@ void Application::update(float deltaTime) {
|
||||||
|
|
||||||
qApp->updateMyAvatarLookAtPosition();
|
qApp->updateMyAvatarLookAtPosition();
|
||||||
|
|
||||||
// update sensorToWorldMatrix for camera and hand controllers
|
|
||||||
myAvatar->updateSensorToWorldMatrix();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
PROFILE_RANGE_EX("MyAvatar", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
PROFILE_RANGE_EX("MyAvatar", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||||
avatarManager->updateMyAvatar(deltaTime);
|
avatarManager->updateMyAvatar(deltaTime);
|
||||||
|
|
|
@ -373,32 +373,34 @@ void MyAvatar::simulate(float deltaTime) {
|
||||||
EntityTreeRenderer* entityTreeRenderer = qApp->getEntities();
|
EntityTreeRenderer* entityTreeRenderer = qApp->getEntities();
|
||||||
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
|
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
|
||||||
if (entityTree) {
|
if (entityTree) {
|
||||||
auto now = usecTimestampNow();
|
entityTree->withWriteLock([&] {
|
||||||
EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender();
|
auto now = usecTimestampNow();
|
||||||
MovingEntitiesOperator moveOperator(entityTree);
|
EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender();
|
||||||
forEachDescendant([&](SpatiallyNestablePointer object) {
|
MovingEntitiesOperator moveOperator(entityTree);
|
||||||
// if the queryBox has changed, tell the entity-server
|
forEachDescendant([&](SpatiallyNestablePointer object) {
|
||||||
if (object->computePuffedQueryAACube() && object->getNestableType() == NestableType::Entity) {
|
// if the queryBox has changed, tell the entity-server
|
||||||
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
|
if (object->computePuffedQueryAACube() && object->getNestableType() == NestableType::Entity) {
|
||||||
bool success;
|
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
|
||||||
AACube newCube = entity->getQueryAACube(success);
|
bool success;
|
||||||
if (success) {
|
AACube newCube = entity->getQueryAACube(success);
|
||||||
moveOperator.addEntityToMoveList(entity, newCube);
|
if (success) {
|
||||||
}
|
moveOperator.addEntityToMoveList(entity, newCube);
|
||||||
if (packetSender) {
|
}
|
||||||
EntityItemProperties properties = entity->getProperties();
|
if (packetSender) {
|
||||||
properties.setQueryAACubeDirty();
|
EntityItemProperties properties = entity->getProperties();
|
||||||
properties.setLastEdited(now);
|
properties.setQueryAACubeDirty();
|
||||||
packetSender->queueEditEntityMessage(PacketType::EntityEdit, entity->getID(), properties);
|
properties.setLastEdited(now);
|
||||||
entity->setLastBroadcast(usecTimestampNow());
|
packetSender->queueEditEntityMessage(PacketType::EntityEdit, entity->getID(), properties);
|
||||||
|
entity->setLastBroadcast(usecTimestampNow());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
// also update the position of children in our local octree
|
||||||
|
if (moveOperator.hasMovingEntities()) {
|
||||||
|
PerformanceTimer perfTimer("recurseTreeWithOperator");
|
||||||
|
entityTree->recurseTreeWithOperator(&moveOperator);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// also update the position of children in our local octree
|
|
||||||
if (moveOperator.hasMovingEntities()) {
|
|
||||||
PerformanceTimer perfTimer("recurseTreeWithOperator");
|
|
||||||
entityTree->recurseTreeWithOperator(&moveOperator);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -555,7 +555,7 @@ void AudioClient::configureReverb() {
|
||||||
p.wetDryMix = 100.0f;
|
p.wetDryMix = 100.0f;
|
||||||
p.preDelay = 0.0f;
|
p.preDelay = 0.0f;
|
||||||
p.earlyGain = -96.0f; // disable ER
|
p.earlyGain = -96.0f; // disable ER
|
||||||
p.lateGain -= 12.0f; // quieter than listener reverb
|
p.lateGain += _reverbOptions->getWetDryMix() * (24.0f/100.0f) - 24.0f; // -0dB to -24dB, based on wetDryMix
|
||||||
p.lateMixLeft = 0.0f;
|
p.lateMixLeft = 0.0f;
|
||||||
p.lateMixRight = 0.0f;
|
p.lateMixRight = 0.0f;
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,9 @@ namespace controller {
|
||||||
// Triggers
|
// Triggers
|
||||||
LT,
|
LT,
|
||||||
RT,
|
RT,
|
||||||
|
// Grips (Oculus touch squeeze)
|
||||||
|
LG,
|
||||||
|
RG,
|
||||||
NUM_STANDARD_AXES,
|
NUM_STANDARD_AXES,
|
||||||
LZ = LT,
|
LZ = LT,
|
||||||
RZ = RT
|
RZ = RT
|
||||||
|
|
|
@ -552,9 +552,9 @@ float OpenGLDisplayPlugin::presentRate() {
|
||||||
{
|
{
|
||||||
Lock lock(_mutex);
|
Lock lock(_mutex);
|
||||||
result = _usecsPerFrame.getAverage();
|
result = _usecsPerFrame.getAverage();
|
||||||
result = 1.0f / result;
|
|
||||||
result *= USECS_PER_SECOND;
|
|
||||||
}
|
}
|
||||||
|
result = 1.0f / result;
|
||||||
|
result *= USECS_PER_SECOND;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,9 @@
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
#include <SimpleMovingAverage.h>
|
#include <SimpleMovingAverage.h>
|
||||||
#include <gl/OglplusHelpers.h>
|
#include <gl/OglplusHelpers.h>
|
||||||
|
#include <gl/GLEscrow.h>
|
||||||
|
|
||||||
#define THREADED_PRESENT 1
|
#define THREADED_PRESENT 1
|
||||||
#include <gl/GLEscrow.h>
|
|
||||||
|
|
||||||
class OpenGLDisplayPlugin : public DisplayPlugin {
|
class OpenGLDisplayPlugin : public DisplayPlugin {
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -69,10 +69,11 @@ void HmdDisplayPlugin::compositeOverlay() {
|
||||||
// set the alpha
|
// set the alpha
|
||||||
Uniform<float>(*_program, _alphaUniform).Set(overlayAlpha);
|
Uniform<float>(*_program, _alphaUniform).Set(overlayAlpha);
|
||||||
|
|
||||||
|
auto eyePoses = _currentPresentFrameInfo.eyePoses;
|
||||||
_sphereSection->Use();
|
_sphereSection->Use();
|
||||||
for_each_eye([&](Eye eye) {
|
for_each_eye([&](Eye eye) {
|
||||||
eyeViewport(eye);
|
eyeViewport(eye);
|
||||||
auto modelView = glm::inverse(_currentRenderEyePoses[eye]); // *glm::translate(mat4(), vec3(0, 0, -1));
|
auto modelView = glm::inverse(eyePoses[eye]); // *glm::translate(mat4(), vec3(0, 0, -1));
|
||||||
auto mvp = _eyeProjections[eye] * modelView;
|
auto mvp = _eyeProjections[eye] * modelView;
|
||||||
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mvp);
|
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mvp);
|
||||||
_sphereSection->Draw();
|
_sphereSection->Draw();
|
||||||
|
@ -95,10 +96,10 @@ void HmdDisplayPlugin::compositePointer() {
|
||||||
// Mouse pointer
|
// Mouse pointer
|
||||||
_plane->Use();
|
_plane->Use();
|
||||||
// Reconstruct the headpose from the eye poses
|
// Reconstruct the headpose from the eye poses
|
||||||
auto headPosition = (vec3(_currentRenderEyePoses[Left][3]) + vec3(_currentRenderEyePoses[Right][3])) / 2.0f;
|
auto headPosition = vec3(_currentPresentFrameInfo.headPose[3]);
|
||||||
for_each_eye([&](Eye eye) {
|
for_each_eye([&](Eye eye) {
|
||||||
eyeViewport(eye);
|
eyeViewport(eye);
|
||||||
auto reticleTransform = compositorHelper->getReticleTransform(_currentRenderEyePoses[eye], headPosition);
|
auto reticleTransform = compositorHelper->getReticleTransform(_currentPresentFrameInfo.eyePoses[eye], headPosition);
|
||||||
auto mvp = _eyeProjections[eye] * reticleTransform;
|
auto mvp = _eyeProjections[eye] * reticleTransform;
|
||||||
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mvp);
|
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mvp);
|
||||||
_plane->Draw();
|
_plane->Draw();
|
||||||
|
@ -160,15 +161,28 @@ void HmdDisplayPlugin::internalPresent() {
|
||||||
|
|
||||||
void HmdDisplayPlugin::setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) {
|
void HmdDisplayPlugin::setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) {
|
||||||
Lock lock(_mutex);
|
Lock lock(_mutex);
|
||||||
_renderEyePoses[frameIndex][eye] = pose;
|
FrameInfo& frame = _frameInfos[frameIndex];
|
||||||
|
frame.eyePoses[eye] = pose;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HmdDisplayPlugin::updateFrameData() {
|
void HmdDisplayPlugin::updateFrameData() {
|
||||||
|
// Check if we have old frame data to discard
|
||||||
|
{
|
||||||
|
Lock lock(_mutex);
|
||||||
|
auto itr = _frameInfos.find(_currentRenderFrameIndex);
|
||||||
|
if (itr != _frameInfos.end()) {
|
||||||
|
_frameInfos.erase(itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Parent::updateFrameData();
|
Parent::updateFrameData();
|
||||||
Lock lock(_mutex);
|
|
||||||
_currentRenderEyePoses = _renderEyePoses[_currentRenderFrameIndex];
|
{
|
||||||
|
Lock lock(_mutex);
|
||||||
|
_currentPresentFrameInfo = _frameInfos[_currentRenderFrameIndex];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::mat4 HmdDisplayPlugin::getHeadPose() const {
|
glm::mat4 HmdDisplayPlugin::getHeadPose() const {
|
||||||
return _headPoseCache.get();
|
return _currentRenderFrameInfo.get().headPose;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,16 @@ public:
|
||||||
|
|
||||||
virtual glm::mat4 getHeadPose() const override;
|
virtual glm::mat4 getHeadPose() const override;
|
||||||
|
|
||||||
|
using EyePoses = std::array<glm::mat4, 2>;
|
||||||
|
|
||||||
|
struct FrameInfo {
|
||||||
|
EyePoses eyePoses;
|
||||||
|
glm::mat4 headPose;
|
||||||
|
double sensorSampleTime { 0 };
|
||||||
|
double predictedDisplayTime { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void hmdPresent() = 0;
|
virtual void hmdPresent() = 0;
|
||||||
virtual bool isHmdMounted() const = 0;
|
virtual bool isHmdMounted() const = 0;
|
||||||
|
@ -46,10 +56,10 @@ protected:
|
||||||
glm::mat4 _cullingProjection;
|
glm::mat4 _cullingProjection;
|
||||||
glm::uvec2 _renderTargetSize;
|
glm::uvec2 _renderTargetSize;
|
||||||
float _ipd { 0.064f };
|
float _ipd { 0.064f };
|
||||||
using EyePoses = std::array<glm::mat4, 2>;
|
|
||||||
QMap<uint32_t, EyePoses> _renderEyePoses;
|
QMap<uint32_t, FrameInfo> _frameInfos;
|
||||||
EyePoses _currentRenderEyePoses;
|
FrameInfo _currentPresentFrameInfo;
|
||||||
ThreadSafeValueCache<glm::mat4> _headPoseCache { glm::mat4() };
|
ThreadSafeValueCache<FrameInfo> _currentRenderFrameInfo;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _enablePreview { false };
|
bool _enablePreview { false };
|
||||||
|
|
|
@ -117,12 +117,11 @@ QVariantMap RenderableModelEntityItem::parseTexturesToMap(QString textures) {
|
||||||
QJsonParseError error;
|
QJsonParseError error;
|
||||||
QJsonDocument texturesJson = QJsonDocument::fromJson(textures.toUtf8(), &error);
|
QJsonDocument texturesJson = QJsonDocument::fromJson(textures.toUtf8(), &error);
|
||||||
if (error.error != QJsonParseError::NoError) {
|
if (error.error != QJsonParseError::NoError) {
|
||||||
qCWarning(entitiesrenderer) << "Could not evaluate textures property value:" << _textures;
|
qCWarning(entitiesrenderer) << "Could not evaluate textures property value:" << textures;
|
||||||
return _originalTextures;
|
return _originalTextures;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto parsed = texturesJson.toVariant();
|
return texturesJson.toVariant().toMap();
|
||||||
return parsed.toMap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderableModelEntityItem::remapTextures() {
|
void RenderableModelEntityItem::remapTextures() {
|
||||||
|
@ -144,11 +143,17 @@ void RenderableModelEntityItem::remapTextures() {
|
||||||
_currentTextures = _originalTextures;
|
_currentTextures = _originalTextures;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto textures = parseTexturesToMap(_textures);
|
auto textures = getTextures();
|
||||||
|
if (textures == _lastTextures) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (textures != _currentTextures) {
|
_lastTextures = textures;
|
||||||
geometry->setTextures(textures);
|
auto newTextures = parseTexturesToMap(textures);
|
||||||
_currentTextures = textures;
|
|
||||||
|
if (newTextures != _currentTextures) {
|
||||||
|
geometry->setTextures(newTextures);
|
||||||
|
_currentTextures = newTextures;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,7 @@ private:
|
||||||
bool _needsInitialSimulation = true;
|
bool _needsInitialSimulation = true;
|
||||||
bool _needsModelReload = true;
|
bool _needsModelReload = true;
|
||||||
EntityTreeRenderer* _myRenderer = nullptr;
|
EntityTreeRenderer* _myRenderer = nullptr;
|
||||||
|
QString _lastTextures;
|
||||||
QVariantMap _currentTextures;
|
QVariantMap _currentTextures;
|
||||||
QVariantMap _originalTextures;
|
QVariantMap _originalTextures;
|
||||||
bool _originalTexturesRead = false;
|
bool _originalTexturesRead = false;
|
||||||
|
|
|
@ -42,6 +42,17 @@ ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID) : EntityItem(
|
||||||
_color[0] = _color[1] = _color[2] = 0;
|
_color[0] = _color[1] = _color[2] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString ModelEntityItem::getTextures() const {
|
||||||
|
QReadLocker locker(&_texturesLock);
|
||||||
|
auto textures = _textures;
|
||||||
|
return textures;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModelEntityItem::setTextures(const QString& textures) {
|
||||||
|
QWriteLocker locker(&_texturesLock);
|
||||||
|
_textures = textures;
|
||||||
|
}
|
||||||
|
|
||||||
EntityItemProperties ModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
EntityItemProperties ModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
|
||||||
|
|
|
@ -110,8 +110,8 @@ public:
|
||||||
float getAnimationFPS() const { return _animationLoop.getFPS(); }
|
float getAnimationFPS() const { return _animationLoop.getFPS(); }
|
||||||
|
|
||||||
static const QString DEFAULT_TEXTURES;
|
static const QString DEFAULT_TEXTURES;
|
||||||
const QString& getTextures() const { return _textures; }
|
const QString getTextures() const;
|
||||||
void setTextures(const QString& textures) { _textures = textures; }
|
void setTextures(const QString& textures);
|
||||||
|
|
||||||
virtual bool shouldBePhysical() const;
|
virtual bool shouldBePhysical() const;
|
||||||
|
|
||||||
|
@ -159,7 +159,9 @@ protected:
|
||||||
AnimationPropertyGroup _animationProperties;
|
AnimationPropertyGroup _animationProperties;
|
||||||
AnimationLoop _animationLoop;
|
AnimationLoop _animationLoop;
|
||||||
|
|
||||||
|
mutable QReadWriteLock _texturesLock;
|
||||||
QString _textures;
|
QString _textures;
|
||||||
|
|
||||||
ShapeType _shapeType = SHAPE_TYPE_NONE;
|
ShapeType _shapeType = SHAPE_TYPE_NONE;
|
||||||
|
|
||||||
// used on client side
|
// used on client side
|
||||||
|
|
|
@ -38,11 +38,13 @@ bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) {
|
||||||
_context->setShareContext(sharedContext);
|
_context->setShareContext(sharedContext);
|
||||||
}
|
}
|
||||||
_context->setFormat(getDefaultOpenGLSurfaceFormat());
|
_context->setFormat(getDefaultOpenGLSurfaceFormat());
|
||||||
|
|
||||||
if (_context->create()) {
|
if (_context->create()) {
|
||||||
_offscreenSurface->setFormat(_context->format());
|
_offscreenSurface->setFormat(_context->format());
|
||||||
_offscreenSurface->create();
|
_offscreenSurface->create();
|
||||||
return true;
|
return _offscreenSurface->isValid();
|
||||||
}
|
}
|
||||||
|
qWarning("Failed to create OffscreenGLCanvas context");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,14 +134,13 @@ QEvent* OffscreenQmlRenderThread::Queue::take() {
|
||||||
}
|
}
|
||||||
|
|
||||||
OffscreenQmlRenderThread::OffscreenQmlRenderThread(OffscreenQmlSurface* surface, QOpenGLContext* shareContext) : _surface(surface) {
|
OffscreenQmlRenderThread::OffscreenQmlRenderThread(OffscreenQmlSurface* surface, QOpenGLContext* shareContext) : _surface(surface) {
|
||||||
qDebug() << "Building QML Renderer: creating context";
|
qDebug() << "Building QML Renderer";
|
||||||
if (!_canvas.create(shareContext)) {
|
if (!_canvas.create(shareContext)) {
|
||||||
static const char* error = "Failed to create OffscreenGLCanvas";
|
qWarning("Failed to create OffscreenGLCanvas");
|
||||||
qWarning() << error;
|
_quit = true;
|
||||||
throw error;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
qDebug() << "Building QML Renderer: creating render control";
|
|
||||||
_renderControl = new QMyQuickRenderControl();
|
_renderControl = new QMyQuickRenderControl();
|
||||||
QQuickWindow::setDefaultAlphaBuffer(true);
|
QQuickWindow::setDefaultAlphaBuffer(true);
|
||||||
// Create a QQuickWindow that is associated with our render control.
|
// Create a QQuickWindow that is associated with our render control.
|
||||||
|
@ -149,19 +148,15 @@ OffscreenQmlRenderThread::OffscreenQmlRenderThread(OffscreenQmlSurface* surface,
|
||||||
// NOTE: Must be created on the main thread so that OffscreenQmlSurface can send it events
|
// NOTE: Must be created on the main thread so that OffscreenQmlSurface can send it events
|
||||||
// NOTE: Must be created on the rendering thread or it will refuse to render,
|
// NOTE: Must be created on the rendering thread or it will refuse to render,
|
||||||
// so we wait until after its ctor to move object/context to this thread.
|
// so we wait until after its ctor to move object/context to this thread.
|
||||||
qDebug() << "Building QML Renderer: creating window";
|
|
||||||
_quickWindow = new QQuickWindow(_renderControl);
|
_quickWindow = new QQuickWindow(_renderControl);
|
||||||
_quickWindow->setColor(QColor(255, 255, 255, 0));
|
_quickWindow->setColor(QColor(255, 255, 255, 0));
|
||||||
_quickWindow->setFlags(_quickWindow->flags() | static_cast<Qt::WindowFlags>(Qt::WA_TranslucentBackground));
|
_quickWindow->setFlags(_quickWindow->flags() | static_cast<Qt::WindowFlags>(Qt::WA_TranslucentBackground));
|
||||||
|
|
||||||
// We can prepare, but we must wait to start() the thread until after the ctor
|
// We can prepare, but we must wait to start() the thread until after the ctor
|
||||||
qDebug() << "Building QML Renderer: moving to own thread";
|
|
||||||
_renderControl->prepareThread(this);
|
_renderControl->prepareThread(this);
|
||||||
_canvas.getContextObject()->moveToThread(this);
|
_canvas.getContextObject()->moveToThread(this);
|
||||||
moveToThread(this);
|
moveToThread(this);
|
||||||
|
|
||||||
qDebug() << "Building QML Renderer: complete";
|
|
||||||
|
|
||||||
_queue.add(INIT);
|
_queue.add(INIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
|
|
||||||
int _RSNumTextureBounded = 0;
|
int _RSNumTextureBounded = 0;
|
||||||
|
|
||||||
|
int _DSNumAPIDrawcalls = 0;
|
||||||
int _DSNumDrawcalls = 0;
|
int _DSNumDrawcalls = 0;
|
||||||
int _DSNumTriangles = 0;
|
int _DSNumTriangles = 0;
|
||||||
|
|
||||||
|
|
|
@ -326,6 +326,7 @@ void GLBackend::do_draw(Batch& batch, size_t paramOffset) {
|
||||||
glDrawArrays(mode, startVertex, numVertices);
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
_stats._DSNumTriangles += numVertices / 3;
|
_stats._DSNumTriangles += numVertices / 3;
|
||||||
_stats._DSNumDrawcalls++;
|
_stats._DSNumDrawcalls++;
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
|
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
@ -344,6 +345,7 @@ void GLBackend::do_drawIndexed(Batch& batch, size_t paramOffset) {
|
||||||
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
||||||
_stats._DSNumTriangles += numIndices / 3;
|
_stats._DSNumTriangles += numIndices / 3;
|
||||||
_stats._DSNumDrawcalls++;
|
_stats._DSNumDrawcalls++;
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
|
|
||||||
(void) CHECK_GL_ERROR();
|
(void) CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
@ -358,6 +360,7 @@ void GLBackend::do_drawInstanced(Batch& batch, size_t paramOffset) {
|
||||||
glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances);
|
glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances);
|
||||||
_stats._DSNumTriangles += (numInstances * numVertices) / 3;
|
_stats._DSNumTriangles += (numInstances * numVertices) / 3;
|
||||||
_stats._DSNumDrawcalls += numInstances;
|
_stats._DSNumDrawcalls += numInstances;
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
|
|
||||||
(void) CHECK_GL_ERROR();
|
(void) CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
@ -383,6 +386,7 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, size_t paramOffset) {
|
||||||
#endif
|
#endif
|
||||||
_stats._DSNumTriangles += (numInstances * numIndices) / 3;
|
_stats._DSNumTriangles += (numInstances * numIndices) / 3;
|
||||||
_stats._DSNumDrawcalls += numInstances;
|
_stats._DSNumDrawcalls += numInstances;
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
|
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
@ -395,6 +399,8 @@ void GLBackend::do_multiDrawIndirect(Batch& batch, size_t paramOffset) {
|
||||||
|
|
||||||
glMultiDrawArraysIndirect(mode, reinterpret_cast<GLvoid*>(_input._indirectBufferOffset), commandCount, (GLsizei)_input._indirectBufferStride);
|
glMultiDrawArraysIndirect(mode, reinterpret_cast<GLvoid*>(_input._indirectBufferOffset), commandCount, (GLsizei)_input._indirectBufferStride);
|
||||||
_stats._DSNumDrawcalls += commandCount;
|
_stats._DSNumDrawcalls += commandCount;
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// FIXME implement the slow path
|
// FIXME implement the slow path
|
||||||
#endif
|
#endif
|
||||||
|
@ -410,7 +416,7 @@ void GLBackend::do_multiDrawIndexedIndirect(Batch& batch, size_t paramOffset) {
|
||||||
|
|
||||||
glMultiDrawElementsIndirect(mode, indexType, reinterpret_cast<GLvoid*>(_input._indirectBufferOffset), commandCount, (GLsizei)_input._indirectBufferStride);
|
glMultiDrawElementsIndirect(mode, indexType, reinterpret_cast<GLvoid*>(_input._indirectBufferOffset), commandCount, (GLsizei)_input._indirectBufferStride);
|
||||||
_stats._DSNumDrawcalls += commandCount;
|
_stats._DSNumDrawcalls += commandCount;
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
#else
|
#else
|
||||||
// FIXME implement the slow path
|
// FIXME implement the slow path
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -610,6 +610,8 @@ void GLBackend::do_setStateDepthBias(Vec2 bias) {
|
||||||
glDisable(GL_POLYGON_OFFSET_LINE);
|
glDisable(GL_POLYGON_OFFSET_LINE);
|
||||||
glDisable(GL_POLYGON_OFFSET_POINT);
|
glDisable(GL_POLYGON_OFFSET_POINT);
|
||||||
}
|
}
|
||||||
|
(void) CHECK_GL_ERROR();
|
||||||
|
|
||||||
_pipeline._stateCache.depthBias = bias.x;
|
_pipeline._stateCache.depthBias = bias.x;
|
||||||
_pipeline._stateCache.depthBiasSlopeScale = bias.y;
|
_pipeline._stateCache.depthBiasSlopeScale = bias.y;
|
||||||
}
|
}
|
||||||
|
@ -690,6 +692,7 @@ void GLBackend::do_setStateAlphaToCoverageEnable(bool enable) {
|
||||||
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||||
}
|
}
|
||||||
(void) CHECK_GL_ERROR();
|
(void) CHECK_GL_ERROR();
|
||||||
|
|
||||||
_pipeline._stateCache.alphaToCoverageEnable = enable;
|
_pipeline._stateCache.alphaToCoverageEnable = enable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -703,6 +706,7 @@ void GLBackend::do_setStateSampleMask(uint32 mask) {
|
||||||
glEnable(GL_SAMPLE_MASK);
|
glEnable(GL_SAMPLE_MASK);
|
||||||
glSampleMaski(0, mask);
|
glSampleMaski(0, mask);
|
||||||
}
|
}
|
||||||
|
(void) CHECK_GL_ERROR();
|
||||||
#endif
|
#endif
|
||||||
_pipeline._stateCache.sampleMask = mask;
|
_pipeline._stateCache.sampleMask = mask;
|
||||||
}
|
}
|
||||||
|
@ -743,10 +747,10 @@ void GLBackend::do_setStateBlend(State::BlendFunction function) {
|
||||||
|
|
||||||
glBlendFuncSeparate(BLEND_ARGS[function.getSourceColor()], BLEND_ARGS[function.getDestinationColor()],
|
glBlendFuncSeparate(BLEND_ARGS[function.getSourceColor()], BLEND_ARGS[function.getDestinationColor()],
|
||||||
BLEND_ARGS[function.getSourceAlpha()], BLEND_ARGS[function.getDestinationAlpha()]);
|
BLEND_ARGS[function.getSourceAlpha()], BLEND_ARGS[function.getDestinationAlpha()]);
|
||||||
(void) CHECK_GL_ERROR();
|
|
||||||
} else {
|
} else {
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
(void) CHECK_GL_ERROR();
|
||||||
|
|
||||||
_pipeline._stateCache.blendFunction = function;
|
_pipeline._stateCache.blendFunction = function;
|
||||||
}
|
}
|
||||||
|
@ -758,6 +762,7 @@ void GLBackend::do_setStateColorWriteMask(uint32 mask) {
|
||||||
mask & State::ColorMask::WRITE_GREEN,
|
mask & State::ColorMask::WRITE_GREEN,
|
||||||
mask & State::ColorMask::WRITE_BLUE,
|
mask & State::ColorMask::WRITE_BLUE,
|
||||||
mask & State::ColorMask::WRITE_ALPHA );
|
mask & State::ColorMask::WRITE_ALPHA );
|
||||||
|
(void) CHECK_GL_ERROR();
|
||||||
|
|
||||||
_pipeline._stateCache.colorWriteMask = mask;
|
_pipeline._stateCache.colorWriteMask = mask;
|
||||||
}
|
}
|
||||||
|
@ -765,7 +770,6 @@ void GLBackend::do_setStateColorWriteMask(uint32 mask) {
|
||||||
|
|
||||||
|
|
||||||
void GLBackend::do_setStateBlendFactor(Batch& batch, size_t paramOffset) {
|
void GLBackend::do_setStateBlendFactor(Batch& batch, size_t paramOffset) {
|
||||||
|
|
||||||
Vec4 factor(batch._params[paramOffset + 0]._float,
|
Vec4 factor(batch._params[paramOffset + 0]._float,
|
||||||
batch._params[paramOffset + 1]._float,
|
batch._params[paramOffset + 1]._float,
|
||||||
batch._params[paramOffset + 2]._float,
|
batch._params[paramOffset + 2]._float,
|
||||||
|
|
|
@ -225,6 +225,12 @@ public:
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case gpu::R11G11B10:
|
||||||
|
texel.format = GL_RGB;
|
||||||
|
// the type should be float
|
||||||
|
texel.internalFormat = GL_R11F_G11F_B10F;
|
||||||
|
break;
|
||||||
|
|
||||||
case gpu::DEPTH:
|
case gpu::DEPTH:
|
||||||
texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it
|
texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it
|
||||||
texel.internalFormat = GL_DEPTH_COMPONENT;
|
texel.internalFormat = GL_DEPTH_COMPONENT;
|
||||||
|
@ -302,11 +308,6 @@ public:
|
||||||
case gpu::SRGBA:
|
case gpu::SRGBA:
|
||||||
texel.internalFormat = GL_SRGB; // standard 2.2 gamma correction color
|
texel.internalFormat = GL_SRGB; // standard 2.2 gamma correction color
|
||||||
break;
|
break;
|
||||||
case gpu::R11G11B10: {
|
|
||||||
// the type should be float
|
|
||||||
texel.internalFormat = GL_R11F_G11F_B10F;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
qCDebug(gpulogging) << "Unknown combination of texel format";
|
qCDebug(gpulogging) << "Unknown combination of texel format";
|
||||||
}
|
}
|
||||||
|
|
|
@ -285,7 +285,7 @@ Texture::Size Texture::resize(Type type, const Element& texelFormat, uint16 widt
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here the Texture has been fully defined from the gpu point of view (size and format)
|
// Here the Texture has been fully defined from the gpu point of view (size and format)
|
||||||
_defined = true;
|
_defined = true;
|
||||||
} else {
|
} else {
|
||||||
_stamp++;
|
_stamp++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// will query the underlying hmd api to compute the most recent head pose
|
// will query the underlying hmd api to compute the most recent head pose
|
||||||
virtual void updateHeadPose(uint32_t frameIndex) {}
|
virtual void beginFrameRender(uint32_t frameIndex) {}
|
||||||
|
|
||||||
// returns a copy of the most recent head pose, computed via updateHeadPose
|
// returns a copy of the most recent head pose, computed via updateHeadPose
|
||||||
virtual glm::mat4 getHeadPose() const {
|
virtual glm::mat4 getHeadPose() const {
|
||||||
|
@ -142,6 +142,8 @@ public:
|
||||||
virtual float presentRate() { return -1.0f; }
|
virtual float presentRate() { return -1.0f; }
|
||||||
uint32_t presentCount() const { return _presentedFrameIndex; }
|
uint32_t presentCount() const { return _presentedFrameIndex; }
|
||||||
|
|
||||||
|
virtual void cycleDebugOutput() {}
|
||||||
|
|
||||||
static const QString& MENU_PATH();
|
static const QString& MENU_PATH();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
|
@ -435,8 +435,9 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
|
||||||
float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION);
|
float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION);
|
||||||
// TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume,
|
// TODO: We shouldn;t have to do that test and use a different volume geometry for when inside the vlight volume,
|
||||||
// we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working...
|
// we should be able to draw thre same geometry use DepthClamp but for unknown reason it's s not working...
|
||||||
|
const float OVER_CONSERVATIVE_SCALE = 1.1f;
|
||||||
if ((eyeHalfPlaneDistance > -nearRadius) &&
|
if ((eyeHalfPlaneDistance > -nearRadius) &&
|
||||||
(glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius)) {
|
(glm::distance(eyePoint, glm::vec3(light->getPosition())) < (expandedRadius * OVER_CONSERVATIVE_SCALE) + nearRadius)) {
|
||||||
coneParam.w = 0.0f;
|
coneParam.w = 0.0f;
|
||||||
batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam));
|
batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam));
|
||||||
|
|
||||||
|
@ -452,6 +453,7 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
|
||||||
batch.setProjectionTransform( projMats[side]);
|
batch.setProjectionTransform( projMats[side]);
|
||||||
batch.setViewTransform(viewTransforms[side]);
|
batch.setViewTransform(viewTransforms[side]);
|
||||||
} else {
|
} else {
|
||||||
|
light->setShowContour(false);
|
||||||
coneParam.w = 1.0f;
|
coneParam.w = 1.0f;
|
||||||
batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam));
|
batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam));
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ void FramebufferCache::createPrimaryFramebuffer() {
|
||||||
|
|
||||||
// FIXME: Decide on the proper one, let s stick to R11G11B10 for now
|
// FIXME: Decide on the proper one, let s stick to R11G11B10 for now
|
||||||
//_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, defaultSampler));
|
//_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, height, defaultSampler));
|
||||||
_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::R11G11B10), width, height, defaultSampler));
|
_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::R11G11B10), width, height, defaultSampler));
|
||||||
//_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::HALF, gpu::RGBA), width, height, defaultSampler));
|
//_lightingTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC4, gpu::HALF, gpu::RGBA), width, height, defaultSampler));
|
||||||
_lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
_lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||||
_lightingFramebuffer->setRenderBuffer(0, _lightingTexture);
|
_lightingFramebuffer->setRenderBuffer(0, _lightingTexture);
|
||||||
|
|
|
@ -131,6 +131,8 @@ void Model::setOffset(const glm::vec3& offset) {
|
||||||
|
|
||||||
void Model::enqueueLocationChange() {
|
void Model::enqueueLocationChange() {
|
||||||
|
|
||||||
|
_needsUpdateClusterMatrices = true;
|
||||||
|
|
||||||
// queue up this work for later processing, at the end of update and just before rendering.
|
// queue up this work for later processing, at the end of update and just before rendering.
|
||||||
// the application will ensure only the last lambda is actually invoked.
|
// the application will ensure only the last lambda is actually invoked.
|
||||||
void* key = (void*)this;
|
void* key = (void*)this;
|
||||||
|
@ -536,7 +538,7 @@ void Model::setVisibleInScene(bool newValue, std::shared_ptr<render::Scene> scen
|
||||||
pendingChanges.resetItem(item, _modelMeshRenderItems[item]);
|
pendingChanges.resetItem(item, _modelMeshRenderItems[item]);
|
||||||
}
|
}
|
||||||
foreach (auto item, _collisionRenderItems.keys()) {
|
foreach (auto item, _collisionRenderItems.keys()) {
|
||||||
pendingChanges.resetItem(item, _modelMeshRenderItems[item]);
|
pendingChanges.resetItem(item, _collisionRenderItems[item]);
|
||||||
}
|
}
|
||||||
scene->enqueuePendingChanges(pendingChanges);
|
scene->enqueuePendingChanges(pendingChanges);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,10 @@ public:
|
||||||
|
|
||||||
class RenderDeferred {
|
class RenderDeferred {
|
||||||
public:
|
public:
|
||||||
|
using JobModel = render::Job::Model<RenderDeferred>;
|
||||||
|
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
|
|
||||||
using JobModel = render::Job::Model<RenderDeferred>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DrawConfig : public render::Job::Config {
|
class DrawConfig : public render::Job::Config {
|
||||||
|
|
|
@ -25,6 +25,7 @@ in vec4 _texCoord0;
|
||||||
out vec4 _fragColor;
|
out vec4 _fragColor;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
|
|
||||||
DeferredTransform deferredTransform = getDeferredTransform();
|
DeferredTransform deferredTransform = getDeferredTransform();
|
||||||
|
|
||||||
// Grab the fragment data from the uv
|
// Grab the fragment data from the uv
|
||||||
|
|
|
@ -20,17 +20,14 @@ namespace render {
|
||||||
class DrawSceneOctreeConfig : public Job::Config {
|
class DrawSceneOctreeConfig : public Job::Config {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty())
|
Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty())
|
||||||
Q_PROPERTY(bool showVisibleCells MEMBER showVisibleCells WRITE setShowVisibleCells)
|
Q_PROPERTY(bool showVisibleCells READ getShowVisibleCells WRITE setShowVisibleCells NOTIFY dirty())
|
||||||
Q_PROPERTY(bool showEmptyCells MEMBER showEmptyCells WRITE setShowEmptyCells)
|
Q_PROPERTY(bool showEmptyCells READ getShowEmptyCells WRITE setShowEmptyCells NOTIFY dirty())
|
||||||
Q_PROPERTY(int numAllocatedCells READ getNumAllocatedCells)
|
Q_PROPERTY(int numAllocatedCells READ getNumAllocatedCells)
|
||||||
Q_PROPERTY(int numFreeCells READ getNumFreeCells)
|
Q_PROPERTY(int numFreeCells READ getNumFreeCells)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DrawSceneOctreeConfig() : Job::Config(false) {}
|
DrawSceneOctreeConfig() : Job::Config(false) {}
|
||||||
|
|
||||||
bool showVisibleCells{ true };
|
|
||||||
bool showEmptyCells{ false };
|
|
||||||
|
|
||||||
int numAllocatedCells{ 0 };
|
int numAllocatedCells{ 0 };
|
||||||
int numFreeCells{ 0 };
|
int numFreeCells{ 0 };
|
||||||
|
@ -38,6 +35,12 @@ namespace render {
|
||||||
int getNumAllocatedCells() const { return numAllocatedCells; }
|
int getNumAllocatedCells() const { return numAllocatedCells; }
|
||||||
int getNumFreeCells() const { return numFreeCells; }
|
int getNumFreeCells() const { return numFreeCells; }
|
||||||
|
|
||||||
|
bool showVisibleCells{ true };
|
||||||
|
bool showEmptyCells{ false };
|
||||||
|
|
||||||
|
bool getShowVisibleCells() { return showVisibleCells; }
|
||||||
|
bool getShowEmptyCells() { return showEmptyCells; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setShowVisibleCells(bool show) { showVisibleCells = show; emit dirty(); }
|
void setShowVisibleCells(bool show) { showVisibleCells = show; emit dirty(); }
|
||||||
void setShowEmptyCells(bool show) { showEmptyCells = show; emit dirty(); }
|
void setShowEmptyCells(bool show) { showEmptyCells = show; emit dirty(); }
|
||||||
|
@ -79,10 +82,10 @@ namespace render {
|
||||||
class DrawItemSelectionConfig : public Job::Config {
|
class DrawItemSelectionConfig : public Job::Config {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty())
|
Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty())
|
||||||
Q_PROPERTY(bool showInsideItems MEMBER showInsideItems WRITE setShowInsideItems)
|
Q_PROPERTY(bool showInsideItems READ getShowInsideItems WRITE setShowInsideItems NOTIFY dirty())
|
||||||
Q_PROPERTY(bool showInsideSubcellItems MEMBER showInsideSubcellItems WRITE setShowInsideSubcellItems)
|
Q_PROPERTY(bool showInsideSubcellItems READ getShowInsideSubcellItems WRITE setShowInsideSubcellItems NOTIFY dirty())
|
||||||
Q_PROPERTY(bool showPartialItems MEMBER showPartialItems WRITE setShowPartialItems)
|
Q_PROPERTY(bool showPartialItems READ getShowPartialItems WRITE setShowPartialItems NOTIFY dirty())
|
||||||
Q_PROPERTY(bool showPartialSubcellItems MEMBER showPartialSubcellItems WRITE setShowPartialSubcellItems)
|
Q_PROPERTY(bool showPartialSubcellItems READ getShowPartialSubcellItems WRITE setShowPartialSubcellItems NOTIFY dirty())
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DrawItemSelectionConfig() : Job::Config(false) {}
|
DrawItemSelectionConfig() : Job::Config(false) {}
|
||||||
|
@ -92,7 +95,12 @@ namespace render {
|
||||||
bool showPartialItems{ true };
|
bool showPartialItems{ true };
|
||||||
bool showPartialSubcellItems{ true };
|
bool showPartialSubcellItems{ true };
|
||||||
|
|
||||||
public slots:
|
bool getShowInsideItems() const { return showInsideItems; };
|
||||||
|
bool getShowInsideSubcellItems() const { return showInsideSubcellItems; };
|
||||||
|
bool getShowPartialItems() const { return showPartialItems; };
|
||||||
|
bool getShowPartialSubcellItems() const { return showPartialSubcellItems; };
|
||||||
|
|
||||||
|
public slots:
|
||||||
void setShowInsideItems(bool show) { showInsideItems = show; emit dirty(); }
|
void setShowInsideItems(bool show) { showInsideItems = show; emit dirty(); }
|
||||||
void setShowInsideSubcellItems(bool show) { showInsideSubcellItems = show; emit dirty(); }
|
void setShowInsideSubcellItems(bool show) { showInsideSubcellItems = show; emit dirty(); }
|
||||||
void setShowPartialItems(bool show) { showPartialItems = show; emit dirty(); }
|
void setShowPartialItems(bool show) { showPartialItems = show; emit dirty(); }
|
||||||
|
|
|
@ -20,12 +20,16 @@
|
||||||
|
|
||||||
using namespace render;
|
using namespace render;
|
||||||
|
|
||||||
void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
|
void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, int maxDrawnItems) {
|
||||||
auto& scene = sceneContext->_scene;
|
auto& scene = sceneContext->_scene;
|
||||||
RenderArgs* args = renderContext->args;
|
RenderArgs* args = renderContext->args;
|
||||||
|
|
||||||
for (const auto& itemDetails : inItems) {
|
int numItemsToDraw = (int)inItems.size();
|
||||||
auto& item = scene->getItem(itemDetails.id);
|
if (maxDrawnItems != -1) {
|
||||||
|
numItemsToDraw = glm::min(numItemsToDraw, maxDrawnItems);
|
||||||
|
}
|
||||||
|
for (auto i = 0; i < numItemsToDraw; ++i) {
|
||||||
|
auto& item = scene->getItem(inItems[i].id);
|
||||||
item.render(args);
|
item.render(args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +73,10 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext
|
||||||
// render lights
|
// render lights
|
||||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||||
args->_batch = &batch;
|
args->_batch = &batch;
|
||||||
renderItems(sceneContext, renderContext, inLights);
|
renderItems(sceneContext, renderContext, inLights, _maxDrawn);
|
||||||
args->_batch = nullptr;
|
args->_batch = nullptr;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
|
||||||
|
config->setNumDrawn((int)inLights.size());
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,15 +16,37 @@
|
||||||
|
|
||||||
namespace render {
|
namespace render {
|
||||||
|
|
||||||
void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems);
|
void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, int maxDrawnItems = -1);
|
||||||
void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1);
|
void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class DrawLightConfig : public Job::Config {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged)
|
||||||
|
Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty)
|
||||||
|
public:
|
||||||
|
int getNumDrawn() { return numDrawn; }
|
||||||
|
void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); }
|
||||||
|
|
||||||
|
int maxDrawn{ -1 };
|
||||||
|
signals:
|
||||||
|
void numDrawnChanged();
|
||||||
|
void dirty();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int numDrawn{ 0 };
|
||||||
|
};
|
||||||
|
|
||||||
class DrawLight {
|
class DrawLight {
|
||||||
public:
|
public:
|
||||||
using JobModel = Job::ModelI<DrawLight, ItemBounds>;
|
using Config = DrawLightConfig;
|
||||||
|
using JobModel = Job::ModelI<DrawLight, ItemBounds, Config>;
|
||||||
|
|
||||||
|
void configure(const Config& config) { _maxDrawn = config.maxDrawn; }
|
||||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inLights);
|
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inLights);
|
||||||
protected:
|
protected:
|
||||||
|
int _maxDrawn; // initialized by Config
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ void EngineStats::run(const SceneContextPointer& sceneContext, const RenderConte
|
||||||
gpu::ContextStats gpuStats(_gpuStats);
|
gpu::ContextStats gpuStats(_gpuStats);
|
||||||
renderContext->args->_context->getStats(_gpuStats);
|
renderContext->args->_context->getStats(_gpuStats);
|
||||||
|
|
||||||
|
config->frameAPIDrawcallCount = _gpuStats._DSNumAPIDrawcalls - gpuStats._DSNumAPIDrawcalls;
|
||||||
config->frameDrawcallCount = _gpuStats._DSNumDrawcalls - gpuStats._DSNumDrawcalls;
|
config->frameDrawcallCount = _gpuStats._DSNumDrawcalls - gpuStats._DSNumDrawcalls;
|
||||||
config->frameDrawcallRate = config->frameDrawcallCount * frequency;
|
config->frameDrawcallRate = config->frameDrawcallCount * frequency;
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace render {
|
||||||
Q_PROPERTY(qint64 textureCPUMemoryUsage MEMBER textureCPUMemoryUsage NOTIFY dirty)
|
Q_PROPERTY(qint64 textureCPUMemoryUsage MEMBER textureCPUMemoryUsage NOTIFY dirty)
|
||||||
Q_PROPERTY(qint64 textureGPUMemoryUsage MEMBER textureGPUMemoryUsage NOTIFY dirty)
|
Q_PROPERTY(qint64 textureGPUMemoryUsage MEMBER textureGPUMemoryUsage NOTIFY dirty)
|
||||||
|
|
||||||
|
Q_PROPERTY(quint32 frameAPIDrawcallCount MEMBER frameAPIDrawcallCount NOTIFY dirty)
|
||||||
Q_PROPERTY(quint32 frameDrawcallCount MEMBER frameDrawcallCount NOTIFY dirty)
|
Q_PROPERTY(quint32 frameDrawcallCount MEMBER frameDrawcallCount NOTIFY dirty)
|
||||||
Q_PROPERTY(quint32 frameDrawcallRate MEMBER frameDrawcallRate NOTIFY dirty)
|
Q_PROPERTY(quint32 frameDrawcallRate MEMBER frameDrawcallRate NOTIFY dirty)
|
||||||
|
|
||||||
|
@ -57,6 +58,7 @@ namespace render {
|
||||||
qint64 textureCPUMemoryUsage{ 0 };
|
qint64 textureCPUMemoryUsage{ 0 };
|
||||||
qint64 textureGPUMemoryUsage{ 0 };
|
qint64 textureGPUMemoryUsage{ 0 };
|
||||||
|
|
||||||
|
quint32 frameAPIDrawcallCount{ 0 };
|
||||||
quint32 frameDrawcallCount{ 0 };
|
quint32 frameDrawcallCount{ 0 };
|
||||||
quint32 frameDrawcallRate{ 0 };
|
quint32 frameDrawcallRate{ 0 };
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,13 @@
|
||||||
using namespace render;
|
using namespace render;
|
||||||
|
|
||||||
void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) {
|
void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) {
|
||||||
_resetItems.push_back(id);
|
if (payload) {
|
||||||
_resetPayloads.push_back(payload);
|
_resetItems.push_back(id);
|
||||||
|
_resetPayloads.push_back(payload);
|
||||||
|
} else {
|
||||||
|
qDebug() << "WARNING: PendingChanges::resetItem with a null payload!";
|
||||||
|
removeItem(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PendingChanges::removeItem(ItemID id) {
|
void PendingChanges::removeItem(ItemID id) {
|
||||||
|
|
|
@ -234,7 +234,7 @@ void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) {
|
||||||
void ScriptEngine::scriptContentsAvailable(const QUrl& url, const QString& scriptContents) {
|
void ScriptEngine::scriptContentsAvailable(const QUrl& url, const QString& scriptContents) {
|
||||||
_scriptContents = scriptContents;
|
_scriptContents = scriptContents;
|
||||||
if (_wantSignals) {
|
if (_wantSignals) {
|
||||||
emit scriptLoaded(_fileNameString);
|
emit scriptLoaded(url.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,13 +13,14 @@
|
||||||
|
|
||||||
#include <SettingHandle.h>
|
#include <SettingHandle.h>
|
||||||
#include <UserActivityLogger.h>
|
#include <UserActivityLogger.h>
|
||||||
|
#include <PathUtils.h>
|
||||||
|
|
||||||
#include "ScriptEngine.h"
|
#include "ScriptEngine.h"
|
||||||
#include "ScriptEngineLogging.h"
|
#include "ScriptEngineLogging.h"
|
||||||
|
|
||||||
#define __STR2__(x) #x
|
#define __STR2__(x) #x
|
||||||
#define __STR1__(x) __STR2__(x)
|
#define __STR1__(x) __STR2__(x)
|
||||||
#define __LOC__ __FILE__ "("__STR1__(__LINE__)") : Warning Msg: "
|
#define __LOC__ __FILE__ "(" __STR1__(__LINE__) ") : Warning Msg: "
|
||||||
|
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||||
|
@ -41,25 +42,53 @@ ScriptEngines::ScriptEngines()
|
||||||
_scriptsModelFilter.setDynamicSortFilter(true);
|
_scriptsModelFilter.setDynamicSortFilter(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString normalizeScriptUrl(const QString& rawScriptUrl) {
|
QUrl normalizeScriptURL(const QUrl& rawScriptURL) {
|
||||||
if (!rawScriptUrl.startsWith("http:") && !rawScriptUrl.startsWith("https:") && !rawScriptUrl.startsWith("atp:")) {
|
if (rawScriptURL.scheme() == "file") {
|
||||||
#ifdef Q_OS_LINUX
|
QUrl fullNormal = rawScriptURL;
|
||||||
if (rawScriptUrl.startsWith("file:")) {
|
QUrl defaultScriptLoc = defaultScriptsLocation();
|
||||||
return rawScriptUrl;
|
|
||||||
}
|
|
||||||
return QUrl::fromLocalFile(rawScriptUrl).toString();
|
|
||||||
#else
|
|
||||||
if (rawScriptUrl.startsWith("file:")) {
|
|
||||||
return rawScriptUrl.toLower();
|
|
||||||
}
|
|
||||||
// Force lowercase on file scripts because of drive letter weirdness.
|
|
||||||
return QUrl::fromLocalFile(rawScriptUrl).toString().toLower();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
#else
|
||||||
|
// Force lowercase on file scripts because of drive letter weirdness.
|
||||||
|
if (rawScriptURL.isLocalFile()) {
|
||||||
|
fullNormal.setPath(fullNormal.path().toLower());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// if this url is something "beneath" the default script url, replace the local path with ~
|
||||||
|
if (fullNormal.scheme() == defaultScriptLoc.scheme() &&
|
||||||
|
fullNormal.host() == defaultScriptLoc.host() &&
|
||||||
|
fullNormal.path().startsWith(defaultScriptLoc.path())) {
|
||||||
|
fullNormal.setPath("/~/" + fullNormal.path().mid(defaultScriptLoc.path().size()));
|
||||||
|
}
|
||||||
|
return fullNormal;
|
||||||
|
} else if (rawScriptURL.scheme() == "http" || rawScriptURL.scheme() == "https" || rawScriptURL.scheme() == "atp") {
|
||||||
|
return rawScriptURL;
|
||||||
|
} else {
|
||||||
|
// don't accidently support gopher
|
||||||
|
return QUrl("");
|
||||||
}
|
}
|
||||||
return QUrl(rawScriptUrl).toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QUrl expandScriptUrl(const QUrl& normalizedScriptURL) {
|
||||||
|
if (normalizedScriptURL.scheme() == "http" ||
|
||||||
|
normalizedScriptURL.scheme() == "https" ||
|
||||||
|
normalizedScriptURL.scheme() == "atp") {
|
||||||
|
return normalizedScriptURL;
|
||||||
|
} else if (normalizedScriptURL.scheme() == "file") {
|
||||||
|
if (normalizedScriptURL.path().startsWith("/~/")) {
|
||||||
|
QUrl url = normalizedScriptURL;
|
||||||
|
QStringList splitPath = url.path().split("/");
|
||||||
|
QUrl defaultScriptsLoc = defaultScriptsLocation();
|
||||||
|
url.setPath(defaultScriptsLoc.path() + "/" + splitPath.mid(2).join("/")); // 2 to skip the slashes in /~/
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
return normalizedScriptURL;
|
||||||
|
} else {
|
||||||
|
return QUrl("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QObject* scriptsModel();
|
QObject* scriptsModel();
|
||||||
|
|
||||||
void ScriptEngines::registerScriptInitializer(ScriptInitializer initializer) {
|
void ScriptEngines::registerScriptInitializer(ScriptInitializer initializer) {
|
||||||
|
@ -192,19 +221,25 @@ QVariantList ScriptEngines::getLocal() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantList ScriptEngines::getRunning() {
|
QVariantList ScriptEngines::getRunning() {
|
||||||
const int WINDOWS_DRIVE_LETTER_SIZE = 1;
|
|
||||||
QVariantList result;
|
QVariantList result;
|
||||||
auto runningScripts = getRunningScripts();
|
auto runningScripts = getRunningScripts();
|
||||||
foreach(const QString& runningScript, runningScripts) {
|
foreach(const QString& runningScript, runningScripts) {
|
||||||
QUrl runningScriptURL = QUrl(runningScript);
|
QUrl runningScriptURL = QUrl(runningScript);
|
||||||
if (runningScriptURL.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) {
|
if (!runningScriptURL.isValid()) {
|
||||||
runningScriptURL = QUrl::fromLocalFile(runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded)));
|
runningScriptURL = QUrl::fromLocalFile(runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded)));
|
||||||
}
|
}
|
||||||
QVariantMap resultNode;
|
QVariantMap resultNode;
|
||||||
resultNode.insert("name", runningScriptURL.fileName());
|
resultNode.insert("name", runningScriptURL.fileName());
|
||||||
resultNode.insert("url", runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded)));
|
QUrl displayURL = expandScriptUrl(QUrl(runningScriptURL));
|
||||||
|
QString displayURLString;
|
||||||
|
if (displayURL.isLocalFile()) {
|
||||||
|
displayURLString = displayURL.toLocalFile();
|
||||||
|
} else {
|
||||||
|
displayURLString = displayURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded));
|
||||||
|
}
|
||||||
|
resultNode.insert("url", displayURLString);
|
||||||
// The path contains the exact path/URL of the script, which also is used in the stopScript function.
|
// The path contains the exact path/URL of the script, which also is used in the stopScript function.
|
||||||
resultNode.insert("path", runningScript);
|
resultNode.insert("path", normalizeScriptURL(runningScript).toString());
|
||||||
resultNode.insert("local", runningScriptURL.isLocalFile());
|
resultNode.insert("local", runningScriptURL.isLocalFile());
|
||||||
result.append(resultNode);
|
result.append(resultNode);
|
||||||
}
|
}
|
||||||
|
@ -213,10 +248,11 @@ QVariantList ScriptEngines::getRunning() {
|
||||||
|
|
||||||
|
|
||||||
static const QString SETTINGS_KEY = "Settings";
|
static const QString SETTINGS_KEY = "Settings";
|
||||||
static const QString DEFAULT_SCRIPTS_JS_URL = "http://s3.amazonaws.com/hifi-public/scripts/defaultScripts.js";
|
|
||||||
|
|
||||||
void ScriptEngines::loadDefaultScripts() {
|
void ScriptEngines::loadDefaultScripts() {
|
||||||
loadScript(DEFAULT_SCRIPTS_JS_URL);
|
QUrl defaultScriptsLoc = defaultScriptsLocation();
|
||||||
|
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "/scripts/defaultScripts.js");
|
||||||
|
loadScript(defaultScriptsLoc.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptEngines::loadOneScript(const QString& scriptFilename) {
|
void ScriptEngines::loadOneScript(const QString& scriptFilename) {
|
||||||
|
@ -265,7 +301,7 @@ void ScriptEngines::saveScripts() {
|
||||||
for (auto it = runningScripts.begin(); it != runningScripts.end(); ++it) {
|
for (auto it = runningScripts.begin(); it != runningScripts.end(); ++it) {
|
||||||
if (getScriptEngine(*it)->isUserLoaded()) {
|
if (getScriptEngine(*it)->isUserLoaded()) {
|
||||||
settings.setArrayIndex(i);
|
settings.setArrayIndex(i);
|
||||||
settings.setValue("script", *it);
|
settings.setValue("script", normalizeScriptURL(*it).toString());
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,11 +343,16 @@ void ScriptEngines::stopAllScripts(bool restart) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptEngines::stopScript(const QString& rawScriptUrl, bool restart) {
|
bool ScriptEngines::stopScript(const QString& rawScriptURL, bool restart) {
|
||||||
bool stoppedScript = false;
|
bool stoppedScript = false;
|
||||||
{
|
{
|
||||||
|
QUrl scriptURL = normalizeScriptURL(QUrl(rawScriptURL));
|
||||||
|
if (!scriptURL.isValid()) {
|
||||||
|
scriptURL = normalizeScriptURL(QUrl::fromLocalFile(rawScriptURL));
|
||||||
|
}
|
||||||
|
const QString scriptURLString = scriptURL.toString();
|
||||||
|
|
||||||
QReadLocker lock(&_scriptEnginesHashLock);
|
QReadLocker lock(&_scriptEnginesHashLock);
|
||||||
const QString scriptURLString = normalizeScriptUrl(rawScriptUrl);
|
|
||||||
if (_scriptEnginesHash.contains(scriptURLString)) {
|
if (_scriptEnginesHash.contains(scriptURLString)) {
|
||||||
ScriptEngine* scriptEngine = _scriptEnginesHash[scriptURLString];
|
ScriptEngine* scriptEngine = _scriptEnginesHash[scriptURLString];
|
||||||
if (restart) {
|
if (restart) {
|
||||||
|
@ -344,18 +385,30 @@ void ScriptEngines::reloadAllScripts() {
|
||||||
stopAllScripts(true);
|
stopAllScripts(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptEngine* ScriptEngines::loadScript(const QString& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor, bool activateMainWindow, bool reload) {
|
ScriptEngine* ScriptEngines::loadScript(const QUrl& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor,
|
||||||
|
bool activateMainWindow, bool reload) {
|
||||||
if (thread() != QThread::currentThread()) {
|
if (thread() != QThread::currentThread()) {
|
||||||
ScriptEngine* result { nullptr };
|
ScriptEngine* result { nullptr };
|
||||||
QMetaObject::invokeMethod(this, "loadScript", Qt::BlockingQueuedConnection, Q_RETURN_ARG(ScriptEngine*, result),
|
QMetaObject::invokeMethod(this, "loadScript", Qt::BlockingQueuedConnection, Q_RETURN_ARG(ScriptEngine*, result),
|
||||||
Q_ARG(QString, scriptFilename),
|
Q_ARG(QUrl, scriptFilename),
|
||||||
Q_ARG(bool, isUserLoaded),
|
Q_ARG(bool, isUserLoaded),
|
||||||
Q_ARG(bool, loadScriptFromEditor),
|
Q_ARG(bool, loadScriptFromEditor),
|
||||||
Q_ARG(bool, activateMainWindow),
|
Q_ARG(bool, activateMainWindow),
|
||||||
Q_ARG(bool, reload));
|
Q_ARG(bool, reload));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
QUrl scriptUrl(scriptFilename);
|
QUrl scriptUrl;
|
||||||
|
if (!scriptFilename.isValid() ||
|
||||||
|
(scriptFilename.scheme() != "http" &&
|
||||||
|
scriptFilename.scheme() != "https" &&
|
||||||
|
scriptFilename.scheme() != "atp" &&
|
||||||
|
scriptFilename.scheme() != "file")) {
|
||||||
|
// deal with a "url" like c:/something
|
||||||
|
scriptUrl = normalizeScriptURL(QUrl::fromLocalFile(scriptFilename.toString()));
|
||||||
|
} else {
|
||||||
|
scriptUrl = normalizeScriptURL(scriptFilename);
|
||||||
|
}
|
||||||
|
|
||||||
auto scriptEngine = getScriptEngine(scriptUrl.toString());
|
auto scriptEngine = getScriptEngine(scriptUrl.toString());
|
||||||
if (scriptEngine) {
|
if (scriptEngine) {
|
||||||
return scriptEngine;
|
return scriptEngine;
|
||||||
|
@ -368,7 +421,7 @@ ScriptEngine* ScriptEngines::loadScript(const QString& scriptFilename, bool isUs
|
||||||
}, Qt::QueuedConnection);
|
}, Qt::QueuedConnection);
|
||||||
|
|
||||||
|
|
||||||
if (scriptFilename.isNull()) {
|
if (scriptFilename.isEmpty()) {
|
||||||
launchScriptEngine(scriptEngine);
|
launchScriptEngine(scriptEngine);
|
||||||
} else {
|
} else {
|
||||||
// connect to the appropriate signals of this script engine
|
// connect to the appropriate signals of this script engine
|
||||||
|
@ -376,17 +429,17 @@ ScriptEngine* ScriptEngines::loadScript(const QString& scriptFilename, bool isUs
|
||||||
connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &ScriptEngines::onScriptEngineError);
|
connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &ScriptEngines::onScriptEngineError);
|
||||||
|
|
||||||
// get the script engine object to load the script at the designated script URL
|
// get the script engine object to load the script at the designated script URL
|
||||||
scriptEngine->loadURL(scriptUrl, reload);
|
scriptEngine->loadURL(QUrl(expandScriptUrl(scriptUrl.toString())), reload);
|
||||||
}
|
}
|
||||||
|
|
||||||
return scriptEngine;
|
return scriptEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptEngine* ScriptEngines::getScriptEngine(const QString& rawScriptUrl) {
|
ScriptEngine* ScriptEngines::getScriptEngine(const QString& rawScriptURL) {
|
||||||
ScriptEngine* result = nullptr;
|
ScriptEngine* result = nullptr;
|
||||||
{
|
{
|
||||||
QReadLocker lock(&_scriptEnginesHashLock);
|
QReadLocker lock(&_scriptEnginesHashLock);
|
||||||
const QString scriptURLString = normalizeScriptUrl(rawScriptUrl);
|
const QString scriptURLString = normalizeScriptURL(QUrl(rawScriptURL)).toString();
|
||||||
auto it = _scriptEnginesHash.find(scriptURLString);
|
auto it = _scriptEnginesHash.find(scriptURLString);
|
||||||
if (it != _scriptEnginesHash.end()) {
|
if (it != _scriptEnginesHash.end()) {
|
||||||
result = it.value();
|
result = it.value();
|
||||||
|
@ -396,15 +449,17 @@ ScriptEngine* ScriptEngines::getScriptEngine(const QString& rawScriptUrl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME - change to new version of ScriptCache loading notification
|
// FIXME - change to new version of ScriptCache loading notification
|
||||||
void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptUrl) {
|
void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptURL) {
|
||||||
UserActivityLogger::getInstance().loadedScript(rawScriptUrl);
|
UserActivityLogger::getInstance().loadedScript(rawScriptURL);
|
||||||
ScriptEngine* scriptEngine = qobject_cast<ScriptEngine*>(sender());
|
ScriptEngine* scriptEngine = qobject_cast<ScriptEngine*>(sender());
|
||||||
|
|
||||||
launchScriptEngine(scriptEngine);
|
launchScriptEngine(scriptEngine);
|
||||||
|
|
||||||
{
|
{
|
||||||
QWriteLocker lock(&_scriptEnginesHashLock);
|
QWriteLocker lock(&_scriptEnginesHashLock);
|
||||||
const QString scriptURLString = normalizeScriptUrl(rawScriptUrl);
|
QUrl url = QUrl(rawScriptURL);
|
||||||
|
QUrl normalized = normalizeScriptURL(url);
|
||||||
|
const QString scriptURLString = normalized.toString();
|
||||||
_scriptEnginesHash.insertMulti(scriptURLString, scriptEngine);
|
_scriptEnginesHash.insertMulti(scriptURLString, scriptEngine);
|
||||||
}
|
}
|
||||||
emit scriptCountChanged();
|
emit scriptCountChanged();
|
||||||
|
@ -427,11 +482,11 @@ void ScriptEngines::launchScriptEngine(ScriptEngine* scriptEngine) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ScriptEngines::onScriptFinished(const QString& rawScriptUrl, ScriptEngine* engine) {
|
void ScriptEngines::onScriptFinished(const QString& rawScriptURL, ScriptEngine* engine) {
|
||||||
bool removed = false;
|
bool removed = false;
|
||||||
{
|
{
|
||||||
QWriteLocker lock(&_scriptEnginesHashLock);
|
QWriteLocker lock(&_scriptEnginesHashLock);
|
||||||
const QString scriptURLString = normalizeScriptUrl(rawScriptUrl);
|
const QString scriptURLString = normalizeScriptURL(QUrl(rawScriptURL)).toString();
|
||||||
for (auto it = _scriptEnginesHash.find(scriptURLString); it != _scriptEnginesHash.end(); ++it) {
|
for (auto it = _scriptEnginesHash.find(scriptURLString); it != _scriptEnginesHash.end(); ++it) {
|
||||||
if (it.value() == engine) {
|
if (it.value() == engine) {
|
||||||
_scriptEnginesHash.erase(it);
|
_scriptEnginesHash.erase(it);
|
||||||
|
|
|
@ -51,7 +51,7 @@ public:
|
||||||
ScriptsModelFilter* scriptsModelFilter() { return &_scriptsModelFilter; };
|
ScriptsModelFilter* scriptsModelFilter() { return &_scriptsModelFilter; };
|
||||||
|
|
||||||
Q_INVOKABLE void loadOneScript(const QString& scriptFilename);
|
Q_INVOKABLE void loadOneScript(const QString& scriptFilename);
|
||||||
Q_INVOKABLE ScriptEngine* loadScript(const QString& scriptFilename = QString(),
|
Q_INVOKABLE ScriptEngine* loadScript(const QUrl& scriptFilename = QString(),
|
||||||
bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false);
|
bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false);
|
||||||
Q_INVOKABLE bool stopScript(const QString& scriptHash, bool restart = false);
|
Q_INVOKABLE bool stopScript(const QString& scriptHash, bool restart = false);
|
||||||
|
|
||||||
|
@ -96,4 +96,7 @@ protected:
|
||||||
ScriptsModelFilter _scriptsModelFilter;
|
ScriptsModelFilter _scriptsModelFilter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QUrl normalizeScriptURL(const QUrl& rawScriptURL);
|
||||||
|
QUrl expandScriptUrl(const QUrl& normalizedScriptURL);
|
||||||
|
|
||||||
#endif // hifi_ScriptEngine_h
|
#endif // hifi_ScriptEngine_h
|
||||||
|
|
|
@ -13,21 +13,19 @@
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
|
#include <QDirIterator>
|
||||||
|
|
||||||
#include <NetworkAccessManager.h>
|
#include <NetworkAccessManager.h>
|
||||||
|
#include <PathUtils.h>
|
||||||
|
|
||||||
#include "ScriptEngine.h"
|
#include "ScriptEngine.h"
|
||||||
#include "ScriptEngines.h"
|
#include "ScriptEngines.h"
|
||||||
#include "ScriptEngineLogging.h"
|
#include "ScriptEngineLogging.h"
|
||||||
#define __STR2__(x) #x
|
#define __STR2__(x) #x
|
||||||
#define __STR1__(x) __STR2__(x)
|
#define __STR1__(x) __STR2__(x)
|
||||||
#define __LOC__ __FILE__ "("__STR1__(__LINE__)") : Warning Msg: "
|
#define __LOC__ __FILE__ "(" __STR1__(__LINE__) ") : Warning Msg: "
|
||||||
|
|
||||||
|
|
||||||
static const QString S3_URL = "http://s3.amazonaws.com/hifi-public";
|
|
||||||
static const QString PUBLIC_URL = "http://public.highfidelity.io";
|
|
||||||
static const QString MODELS_LOCATION = "scripts/";
|
static const QString MODELS_LOCATION = "scripts/";
|
||||||
|
|
||||||
static const QString PREFIX_PARAMETER_NAME = "prefix";
|
static const QString PREFIX_PARAMETER_NAME = "prefix";
|
||||||
static const QString MARKER_PARAMETER_NAME = "marker";
|
static const QString MARKER_PARAMETER_NAME = "marker";
|
||||||
static const QString IS_TRUNCATED_NAME = "IsTruncated";
|
static const QString IS_TRUNCATED_NAME = "IsTruncated";
|
||||||
|
@ -63,7 +61,7 @@ ScriptsModel::ScriptsModel(QObject* parent) :
|
||||||
|
|
||||||
connect(&_fsWatcher, &QFileSystemWatcher::directoryChanged, this, &ScriptsModel::reloadLocalFiles);
|
connect(&_fsWatcher, &QFileSystemWatcher::directoryChanged, this, &ScriptsModel::reloadLocalFiles);
|
||||||
reloadLocalFiles();
|
reloadLocalFiles();
|
||||||
reloadRemoteFiles();
|
reloadDefaultFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptsModel::~ScriptsModel() {
|
ScriptsModel::~ScriptsModel() {
|
||||||
|
@ -140,36 +138,56 @@ void ScriptsModel::updateScriptsLocation(const QString& newPath) {
|
||||||
reloadLocalFiles();
|
reloadLocalFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptsModel::reloadRemoteFiles() {
|
void ScriptsModel::reloadDefaultFiles() {
|
||||||
if (!_loadingScripts) {
|
if (!_loadingScripts) {
|
||||||
_loadingScripts = true;
|
_loadingScripts = true;
|
||||||
for (int i = _treeNodes.size() - 1; i >= 0; i--) {
|
for (int i = _treeNodes.size() - 1; i >= 0; i--) {
|
||||||
TreeNodeBase* node = _treeNodes.at(i);
|
TreeNodeBase* node = _treeNodes.at(i);
|
||||||
if (node->getType() == TREE_NODE_TYPE_SCRIPT &&
|
if (node->getType() == TREE_NODE_TYPE_SCRIPT &&
|
||||||
static_cast<TreeNodeScript*>(node)->getOrigin() == SCRIPT_ORIGIN_REMOTE)
|
static_cast<TreeNodeScript*>(node)->getOrigin() == SCRIPT_ORIGIN_DEFAULT)
|
||||||
{
|
{
|
||||||
delete node;
|
delete node;
|
||||||
_treeNodes.removeAt(i);
|
_treeNodes.removeAt(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
requestRemoteFiles();
|
requestDefaultFiles();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptsModel::requestRemoteFiles(QString marker) {
|
void ScriptsModel::requestDefaultFiles(QString marker) {
|
||||||
QUrl url(S3_URL);
|
QUrl url(defaultScriptsLocation());
|
||||||
QUrlQuery query;
|
|
||||||
query.addQueryItem(PREFIX_PARAMETER_NAME, MODELS_LOCATION);
|
|
||||||
if (!marker.isEmpty()) {
|
|
||||||
query.addQueryItem(MARKER_PARAMETER_NAME, marker);
|
|
||||||
}
|
|
||||||
url.setQuery(query);
|
|
||||||
|
|
||||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
if (url.isLocalFile()) {
|
||||||
QNetworkRequest request(url);
|
// if the url indicates a local directory, use QDirIterator
|
||||||
request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
// QString localDir = url.toLocalFile() + "/scripts";
|
||||||
QNetworkReply* reply = networkAccessManager.get(request);
|
QString localDir = expandScriptUrl(url).toLocalFile() + "/scripts";
|
||||||
connect(reply, SIGNAL(finished()), SLOT(downloadFinished()));
|
int localDirPartCount = localDir.split("/").size();
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
localDirPartCount++; // one for the drive letter
|
||||||
|
#endif
|
||||||
|
QDirIterator it(localDir, QStringList() << "*.js", QDir::Files, QDirIterator::Subdirectories);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
QUrl jsFullPath = QUrl::fromLocalFile(it.next());
|
||||||
|
QString jsPartialPath = jsFullPath.path().split("/").mid(localDirPartCount).join("/");
|
||||||
|
jsFullPath = normalizeScriptURL(jsFullPath);
|
||||||
|
_treeNodes.append(new TreeNodeScript(jsPartialPath, jsFullPath.toString(), SCRIPT_ORIGIN_DEFAULT));
|
||||||
|
}
|
||||||
|
_loadingScripts = false;
|
||||||
|
} else {
|
||||||
|
// the url indicates http(s), use QNetworkRequest
|
||||||
|
QUrlQuery query;
|
||||||
|
query.addQueryItem(PREFIX_PARAMETER_NAME, MODELS_LOCATION);
|
||||||
|
if (!marker.isEmpty()) {
|
||||||
|
query.addQueryItem(MARKER_PARAMETER_NAME, marker);
|
||||||
|
}
|
||||||
|
url.setQuery(query);
|
||||||
|
|
||||||
|
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||||
|
QNetworkRequest request(url);
|
||||||
|
request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||||
|
QNetworkReply* reply = networkAccessManager.get(request);
|
||||||
|
connect(reply, SIGNAL(finished()), SLOT(downloadFinished()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptsModel::downloadFinished() {
|
void ScriptsModel::downloadFinished() {
|
||||||
|
@ -182,8 +200,10 @@ void ScriptsModel::downloadFinished() {
|
||||||
if (!data.isEmpty()) {
|
if (!data.isEmpty()) {
|
||||||
finished = parseXML(data);
|
finished = parseXML(data);
|
||||||
} else {
|
} else {
|
||||||
qCDebug(scriptengine) << "Error: Received no data when loading remote scripts";
|
qCDebug(scriptengine) << "Error: Received no data when loading default scripts";
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
qDebug() << "Error: when loading default scripts --" << reply->error();
|
||||||
}
|
}
|
||||||
|
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
@ -218,7 +238,11 @@ bool ScriptsModel::parseXML(QByteArray xmlFile) {
|
||||||
xml.readNext();
|
xml.readNext();
|
||||||
lastKey = xml.text().toString();
|
lastKey = xml.text().toString();
|
||||||
if (jsRegex.exactMatch(xml.text().toString())) {
|
if (jsRegex.exactMatch(xml.text().toString())) {
|
||||||
_treeNodes.append(new TreeNodeScript(lastKey.mid(MODELS_LOCATION.length()), S3_URL + "/" + lastKey, SCRIPT_ORIGIN_REMOTE));
|
QString localPath = lastKey.split("/").mid(1).join("/");
|
||||||
|
QUrl fullPath = defaultScriptsLocation();
|
||||||
|
fullPath.setPath(fullPath.path() + "/" + lastKey);
|
||||||
|
const QString fullPathStr = normalizeScriptURL(fullPath).toString();
|
||||||
|
_treeNodes.append(new TreeNodeScript(localPath, fullPathStr, SCRIPT_ORIGIN_DEFAULT));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xml.readNext();
|
xml.readNext();
|
||||||
|
@ -231,12 +255,12 @@ bool ScriptsModel::parseXML(QByteArray xmlFile) {
|
||||||
|
|
||||||
// Error handling
|
// Error handling
|
||||||
if (xml.hasError()) {
|
if (xml.hasError()) {
|
||||||
qCDebug(scriptengine) << "Error loading remote scripts: " << xml.errorString();
|
qCDebug(scriptengine) << "Error loading default scripts: " << xml.errorString();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (truncated) {
|
if (truncated) {
|
||||||
requestRemoteFiles(lastKey);
|
requestDefaultFiles(lastKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this request was not truncated, we are done.
|
// If this request was not truncated, we are done.
|
||||||
|
@ -261,7 +285,9 @@ void ScriptsModel::reloadLocalFiles() {
|
||||||
const QFileInfoList localFiles = _localDirectory.entryInfoList();
|
const QFileInfoList localFiles = _localDirectory.entryInfoList();
|
||||||
for (int i = 0; i < localFiles.size(); i++) {
|
for (int i = 0; i < localFiles.size(); i++) {
|
||||||
QFileInfo file = localFiles[i];
|
QFileInfo file = localFiles[i];
|
||||||
_treeNodes.append(new TreeNodeScript(file.fileName(), file.absoluteFilePath(), SCRIPT_ORIGIN_LOCAL));
|
QString fileName = file.fileName();
|
||||||
|
QUrl absPath = normalizeScriptURL(QUrl::fromLocalFile(file.absoluteFilePath()));
|
||||||
|
_treeNodes.append(new TreeNodeScript(fileName, absPath.toString(), SCRIPT_ORIGIN_LOCAL));
|
||||||
}
|
}
|
||||||
rebuildTree();
|
rebuildTree();
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
|
|
@ -21,7 +21,7 @@ class TreeNodeFolder;
|
||||||
|
|
||||||
enum ScriptOrigin {
|
enum ScriptOrigin {
|
||||||
SCRIPT_ORIGIN_LOCAL,
|
SCRIPT_ORIGIN_LOCAL,
|
||||||
SCRIPT_ORIGIN_REMOTE
|
SCRIPT_ORIGIN_DEFAULT
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TreeNodeType {
|
enum TreeNodeType {
|
||||||
|
@ -84,10 +84,10 @@ protected slots:
|
||||||
void updateScriptsLocation(const QString& newPath);
|
void updateScriptsLocation(const QString& newPath);
|
||||||
void downloadFinished();
|
void downloadFinished();
|
||||||
void reloadLocalFiles();
|
void reloadLocalFiles();
|
||||||
void reloadRemoteFiles();
|
void reloadDefaultFiles();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void requestRemoteFiles(QString marker = QString());
|
void requestDefaultFiles(QString marker = QString());
|
||||||
bool parseXML(QByteArray xmlFile);
|
bool parseXML(QByteArray xmlFile);
|
||||||
void rebuildTree();
|
void rebuildTree();
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QUrl>
|
||||||
#include "PathUtils.h"
|
#include "PathUtils.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,3 +54,14 @@ QString findMostRecentFileExtension(const QString& originalFileName, QVector<QSt
|
||||||
}
|
}
|
||||||
return newestFileName;
|
return newestFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QUrl defaultScriptsLocation() {
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
return QUrl(("file:///" + QCoreApplication::applicationDirPath()).toLower());
|
||||||
|
#elif defined(Q_OS_OSX)
|
||||||
|
return QUrl(("file://" + QCoreApplication::applicationDirPath() + "/../Resources").toLower());
|
||||||
|
#else
|
||||||
|
// return "http://s3.amazonaws.com/hifi-public";
|
||||||
|
return QUrl("file://" + QCoreApplication::applicationDirPath());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -27,4 +27,6 @@ public:
|
||||||
QString fileNameWithoutExtension(const QString& fileName, const QVector<QString> possibleExtensions);
|
QString fileNameWithoutExtension(const QString& fileName, const QVector<QString> possibleExtensions);
|
||||||
QString findMostRecentFileExtension(const QString& originalFileName, QVector<QString> possibleExtensions);
|
QString findMostRecentFileExtension(const QString& originalFileName, QVector<QString> possibleExtensions);
|
||||||
|
|
||||||
|
QUrl defaultScriptsLocation();
|
||||||
|
|
||||||
#endif // hifi_PathUtils_h
|
#endif // hifi_PathUtils_h
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ThreadSafeValueCache {
|
class ThreadSafeValueCache {
|
||||||
public:
|
public:
|
||||||
|
ThreadSafeValueCache() {}
|
||||||
ThreadSafeValueCache(const T& v) : _value { v } {}
|
ThreadSafeValueCache(const T& v) : _value { v } {}
|
||||||
|
|
||||||
// returns atomic copy of the cached value.
|
// returns atomic copy of the cached value.
|
||||||
|
|
|
@ -12,14 +12,19 @@
|
||||||
#include "OculusHelpers.h"
|
#include "OculusHelpers.h"
|
||||||
|
|
||||||
void OculusBaseDisplayPlugin::resetSensors() {
|
void OculusBaseDisplayPlugin::resetSensors() {
|
||||||
ovr_RecenterPose(_session);
|
ovr_RecenterTrackingOrigin(_session);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusBaseDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
|
void OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
auto displayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
|
FrameInfo frame;
|
||||||
auto trackingState = ovr_GetTrackingState(_session, displayTime, true);
|
frame.sensorSampleTime = ovr_GetTimeInSeconds();;
|
||||||
mat4 headPose = toGlm(trackingState.HeadPose.ThePose);
|
frame.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
|
||||||
_headPoseCache.set(headPose);
|
auto trackingState = ovr_GetTrackingState(_session, frame.predictedDisplayTime, ovrTrue);
|
||||||
|
frame.headPose = toGlm(trackingState.HeadPose.ThePose);
|
||||||
|
|
||||||
|
_currentRenderFrameInfo.set(frame);
|
||||||
|
Lock lock(_mutex);
|
||||||
|
_frameInfos[frameIndex] = frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OculusBaseDisplayPlugin::isSupported() const {
|
bool OculusBaseDisplayPlugin::isSupported() const {
|
||||||
|
@ -42,36 +47,30 @@ bool OculusBaseDisplayPlugin::internalActivate() {
|
||||||
|
|
||||||
_hmdDesc = ovr_GetHmdDesc(_session);
|
_hmdDesc = ovr_GetHmdDesc(_session);
|
||||||
|
|
||||||
_ipd = ovr_GetFloat(_session, OVR_KEY_IPD, _ipd);
|
|
||||||
|
|
||||||
glm::uvec2 eyeSizes[2];
|
glm::uvec2 eyeSizes[2];
|
||||||
_viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
|
_viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
|
||||||
|
|
||||||
|
_ipd = 0;
|
||||||
ovr_for_each_eye([&](ovrEyeType eye) {
|
ovr_for_each_eye([&](ovrEyeType eye) {
|
||||||
_eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye];
|
_eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye];
|
||||||
ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_session, eye, _eyeFovs[eye]);
|
ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_session, eye, _eyeFovs[eye]);
|
||||||
ovrMatrix4f ovrPerspectiveProjection =
|
ovrMatrix4f ovrPerspectiveProjection =
|
||||||
ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded);
|
ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL);
|
||||||
_eyeProjections[eye] = toGlm(ovrPerspectiveProjection);
|
_eyeProjections[eye] = toGlm(ovrPerspectiveProjection);
|
||||||
_eyeOffsets[eye] = glm::translate(mat4(), toGlm(erd.HmdToEyeViewOffset));
|
_eyeOffsets[eye] = glm::translate(mat4(), toGlm(erd.HmdToEyeOffset));
|
||||||
eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_session, eye, erd.Fov, 1.0f));
|
eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_session, eye, erd.Fov, 1.0f));
|
||||||
_viewScaleDesc.HmdToEyeViewOffset[eye] = erd.HmdToEyeViewOffset;
|
_viewScaleDesc.HmdToEyeOffset[eye] = erd.HmdToEyeOffset;
|
||||||
|
_ipd += glm::abs(glm::length(toGlm(erd.HmdToEyeOffset)));
|
||||||
});
|
});
|
||||||
|
|
||||||
auto combinedFov = _eyeFovs[0];
|
auto combinedFov = _eyeFovs[0];
|
||||||
combinedFov.LeftTan = combinedFov.RightTan = std::max(combinedFov.LeftTan, combinedFov.RightTan);
|
combinedFov.LeftTan = combinedFov.RightTan = std::max(combinedFov.LeftTan, combinedFov.RightTan);
|
||||||
_cullingProjection = toGlm(ovrMatrix4f_Projection(combinedFov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded));
|
_cullingProjection = toGlm(ovrMatrix4f_Projection(combinedFov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL));
|
||||||
|
|
||||||
_renderTargetSize = uvec2(
|
_renderTargetSize = uvec2(
|
||||||
eyeSizes[0].x + eyeSizes[1].x,
|
eyeSizes[0].x + eyeSizes[1].x,
|
||||||
std::max(eyeSizes[0].y, eyeSizes[1].y));
|
std::max(eyeSizes[0].y, eyeSizes[1].y));
|
||||||
|
|
||||||
if (!OVR_SUCCESS(ovr_ConfigureTracking(_session,
|
|
||||||
ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) {
|
|
||||||
logWarning("Failed to attach to sensor device");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parent class relies on our _session intialization, so it must come after that.
|
|
||||||
memset(&_sceneLayer, 0, sizeof(ovrLayerEyeFov));
|
memset(&_sceneLayer, 0, sizeof(ovrLayerEyeFov));
|
||||||
_sceneLayer.Header.Type = ovrLayerType_EyeFov;
|
_sceneLayer.Header.Type = ovrLayerType_EyeFov;
|
||||||
_sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;
|
_sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;
|
||||||
|
|
|
@ -20,7 +20,8 @@ public:
|
||||||
|
|
||||||
// Stereo specific methods
|
// Stereo specific methods
|
||||||
virtual void resetSensors() override final;
|
virtual void resetSensors() override final;
|
||||||
virtual void updateHeadPose(uint32_t frameIndex) override;
|
virtual void beginFrameRender(uint32_t frameIndex) override;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void customizeContext() override;
|
void customizeContext() override;
|
||||||
|
@ -28,9 +29,8 @@ protected:
|
||||||
void internalDeactivate() override;
|
void internalDeactivate() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ovrSession _session;
|
ovrSession _session { nullptr };
|
||||||
ovrGraphicsLuid _luid;
|
ovrGraphicsLuid _luid;
|
||||||
float _ipd{ OVR_DEFAULT_IPD };
|
|
||||||
ovrEyeRenderDesc _eyeRenderDescs[2];
|
ovrEyeRenderDesc _eyeRenderDescs[2];
|
||||||
ovrFovPort _eyeFovs[2];
|
ovrFovPort _eyeFovs[2];
|
||||||
ovrHmdDesc _hmdDesc;
|
ovrHmdDesc _hmdDesc;
|
||||||
|
|
219
plugins/oculus/src/OculusControllerManager.cpp
Normal file
219
plugins/oculus/src/OculusControllerManager.cpp
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
//
|
||||||
|
// OculusControllerManager.cpp
|
||||||
|
// input-plugins/src/input-plugins
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis 2016/03/04.
|
||||||
|
// Copyright 2013-2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "OculusControllerManager.h"
|
||||||
|
|
||||||
|
#include <QtCore/QLoggingCategory>
|
||||||
|
|
||||||
|
#include <plugins/PluginContainer.h>
|
||||||
|
#include <controllers/UserInputMapper.h>
|
||||||
|
#include <controllers/StandardControls.h>
|
||||||
|
|
||||||
|
#include <PerfStat.h>
|
||||||
|
#include <PathUtils.h>
|
||||||
|
|
||||||
|
#include "OculusHelpers.h"
|
||||||
|
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(oculus)
|
||||||
|
|
||||||
|
|
||||||
|
static const QString MENU_PARENT = "Avatar";
|
||||||
|
static const QString MENU_NAME = "Oculus Touch Controllers";
|
||||||
|
static const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME;
|
||||||
|
|
||||||
|
const QString OculusControllerManager::NAME = "Oculus";
|
||||||
|
|
||||||
|
bool OculusControllerManager::isSupported() const {
|
||||||
|
return oculusAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OculusControllerManager::activate() {
|
||||||
|
InputPlugin::activate();
|
||||||
|
if (!_session) {
|
||||||
|
_session = acquireOculusSession();
|
||||||
|
}
|
||||||
|
Q_ASSERT(_session);
|
||||||
|
|
||||||
|
// register with UserInputMapper
|
||||||
|
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||||
|
if (_remote) {
|
||||||
|
userInputMapper->registerDevice(_remote);
|
||||||
|
}
|
||||||
|
if (_touch) {
|
||||||
|
userInputMapper->registerDevice(_touch);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusControllerManager::deactivate() {
|
||||||
|
InputPlugin::deactivate();
|
||||||
|
|
||||||
|
if (_session) {
|
||||||
|
releaseOculusSession();
|
||||||
|
_session = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unregister with UserInputMapper
|
||||||
|
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||||
|
if (_touch) {
|
||||||
|
userInputMapper->removeDevice(_touch->getDeviceID());
|
||||||
|
}
|
||||||
|
if (_remote) {
|
||||||
|
userInputMapper->removeDevice(_remote->getDeviceID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) {
|
||||||
|
PerformanceTimer perfTimer("OculusControllerManager::TouchDevice::update");
|
||||||
|
|
||||||
|
if (!OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Touch, &_inputState))) {
|
||||||
|
qCWarning(oculus) << "Unable to read oculus input state";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_touch) {
|
||||||
|
_touch->update(deltaTime, inputCalibrationData, jointsCaptured);
|
||||||
|
}
|
||||||
|
if (_remote) {
|
||||||
|
_remote->update(deltaTime, inputCalibrationData, jointsCaptured);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusControllerManager::pluginFocusOutEvent() {
|
||||||
|
if (_touch) {
|
||||||
|
_touch->focusOutEvent();
|
||||||
|
}
|
||||||
|
if (_remote) {
|
||||||
|
_remote->focusOutEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace controller;
|
||||||
|
|
||||||
|
static const std::vector<std::pair<ovrButton, StandardButtonChannel>> BUTTON_MAP { {
|
||||||
|
{ ovrButton_X, X },
|
||||||
|
{ ovrButton_Y, Y },
|
||||||
|
{ ovrButton_A, A },
|
||||||
|
{ ovrButton_B, B },
|
||||||
|
{ ovrButton_LThumb, LS },
|
||||||
|
{ ovrButton_RThumb, RS },
|
||||||
|
{ ovrButton_LShoulder, LB },
|
||||||
|
{ ovrButton_RShoulder, RB },
|
||||||
|
} };
|
||||||
|
|
||||||
|
static const std::vector<std::pair<ovrTouch, StandardButtonChannel>> TOUCH_MAP { {
|
||||||
|
{ ovrTouch_X, LEFT_SECONDARY_THUMB_TOUCH },
|
||||||
|
{ ovrTouch_Y, LEFT_SECONDARY_THUMB_TOUCH },
|
||||||
|
{ ovrTouch_A, RIGHT_SECONDARY_THUMB_TOUCH },
|
||||||
|
{ ovrTouch_B, RIGHT_SECONDARY_THUMB_TOUCH },
|
||||||
|
{ ovrTouch_LIndexTrigger, LEFT_PRIMARY_INDEX_TOUCH },
|
||||||
|
{ ovrTouch_RIndexTrigger, RIGHT_PRIMARY_INDEX_TOUCH },
|
||||||
|
{ ovrTouch_LThumb, LS_TOUCH },
|
||||||
|
{ ovrTouch_RThumb, RS_TOUCH },
|
||||||
|
{ ovrTouch_LThumbUp, LEFT_THUMB_UP },
|
||||||
|
{ ovrTouch_RThumbUp, RIGHT_THUMB_UP },
|
||||||
|
{ ovrTouch_LIndexPointing, LEFT_INDEX_POINT },
|
||||||
|
{ ovrTouch_RIndexPointing, RIGHT_INDEX_POINT },
|
||||||
|
} };
|
||||||
|
|
||||||
|
void OculusControllerManager::TouchDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) {
|
||||||
|
_poseStateMap.clear();
|
||||||
|
_buttonPressedMap.clear();
|
||||||
|
|
||||||
|
if (!jointsCaptured) {
|
||||||
|
int numTrackedControllers = 0;
|
||||||
|
static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked & ovrStatus_PositionTracked;
|
||||||
|
auto tracking = ovr_GetTrackingState(_parent._session, 0, false);
|
||||||
|
ovr_for_each_hand([&](ovrHandType hand) {
|
||||||
|
++numTrackedControllers;
|
||||||
|
if (REQUIRED_HAND_STATUS == (tracking.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) {
|
||||||
|
handlePose(deltaTime, inputCalibrationData, hand, tracking.HandPoses[hand]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
using namespace controller;
|
||||||
|
// Axes
|
||||||
|
const auto& inputState = _parent._inputState;
|
||||||
|
_axisStateMap[LX] = inputState.Thumbstick[ovrHand_Left].x;
|
||||||
|
_axisStateMap[LY] = inputState.Thumbstick[ovrHand_Left].y;
|
||||||
|
_axisStateMap[LT] = inputState.IndexTrigger[ovrHand_Left];
|
||||||
|
_axisStateMap[LG] = inputState.HandTrigger[ovrHand_Left];
|
||||||
|
|
||||||
|
_axisStateMap[RX] = inputState.Thumbstick[ovrHand_Right].x;
|
||||||
|
_axisStateMap[RY] = inputState.Thumbstick[ovrHand_Right].y;
|
||||||
|
_axisStateMap[RT] = inputState.IndexTrigger[ovrHand_Right];
|
||||||
|
_axisStateMap[RG] = inputState.HandTrigger[ovrHand_Right];
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
for (const auto& pair : BUTTON_MAP) {
|
||||||
|
if (inputState.Buttons & pair.first) {
|
||||||
|
_buttonPressedMap.insert(pair.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Touches
|
||||||
|
for (const auto& pair : TOUCH_MAP) {
|
||||||
|
if (inputState.Touches & pair.first) {
|
||||||
|
_buttonPressedMap.insert(pair.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusControllerManager::TouchDevice::focusOutEvent() {
|
||||||
|
_axisStateMap.clear();
|
||||||
|
_buttonPressedMap.clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
void OculusControllerManager::TouchDevice::handlePose(float deltaTime,
|
||||||
|
const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand,
|
||||||
|
const ovrPoseStatef& handPose) {
|
||||||
|
auto poseId = hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND;
|
||||||
|
auto& pose = _poseStateMap[poseId];
|
||||||
|
pose.translation = toGlm(handPose.ThePose.Position);
|
||||||
|
pose.rotation = toGlm(handPose.ThePose.Orientation);
|
||||||
|
pose.angularVelocity = toGlm(handPose.AngularVelocity);
|
||||||
|
pose.velocity = toGlm(handPose.LinearVelocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
controller::Input::NamedVector OculusControllerManager::TouchDevice::getAvailableInputs() const {
|
||||||
|
using namespace controller;
|
||||||
|
QVector<Input::NamedPair> availableInputs{
|
||||||
|
// Trackpad analogs
|
||||||
|
makePair(LX, "LX"),
|
||||||
|
makePair(LY, "LY"),
|
||||||
|
makePair(RX, "RX"),
|
||||||
|
makePair(RY, "RY"),
|
||||||
|
// trigger analogs
|
||||||
|
makePair(LT, "LT"),
|
||||||
|
makePair(RT, "RT"),
|
||||||
|
|
||||||
|
makePair(LB, "LB"),
|
||||||
|
makePair(RB, "RB"),
|
||||||
|
|
||||||
|
makePair(LS, "LS"),
|
||||||
|
makePair(RS, "RS"),
|
||||||
|
makePair(LEFT_HAND, "LeftHand"),
|
||||||
|
makePair(RIGHT_HAND, "RightHand"),
|
||||||
|
|
||||||
|
makePair(LEFT_PRIMARY_THUMB, "LeftPrimaryThumb"),
|
||||||
|
makePair(LEFT_SECONDARY_THUMB, "LeftSecondaryThumb"),
|
||||||
|
makePair(RIGHT_PRIMARY_THUMB, "RightPrimaryThumb"),
|
||||||
|
makePair(RIGHT_SECONDARY_THUMB, "RightSecondaryThumb"),
|
||||||
|
};
|
||||||
|
return availableInputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString OculusControllerManager::TouchDevice::getDefaultMappingConfig() const {
|
||||||
|
static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/touch.json";
|
||||||
|
return MAPPING_JSON;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
81
plugins/oculus/src/OculusControllerManager.h
Normal file
81
plugins/oculus/src/OculusControllerManager.h
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2016/03/04
|
||||||
|
// Copyright 2013-2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi__OculusControllerManager
|
||||||
|
#define hifi__OculusControllerManager
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include <GLMHelpers.h>
|
||||||
|
|
||||||
|
#include <controllers/InputDevice.h>
|
||||||
|
#include <plugins/InputPlugin.h>
|
||||||
|
|
||||||
|
#include <OVR_CAPI.h>
|
||||||
|
|
||||||
|
class OculusControllerManager : public InputPlugin {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
// Plugin functions
|
||||||
|
bool isSupported() const override;
|
||||||
|
bool isJointController() const override { return true; }
|
||||||
|
const QString& getName() const override { return NAME; }
|
||||||
|
|
||||||
|
bool activate() override;
|
||||||
|
void deactivate() override;
|
||||||
|
|
||||||
|
void pluginFocusOutEvent() override;
|
||||||
|
void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class OculusInputDevice : public controller::InputDevice {
|
||||||
|
public:
|
||||||
|
OculusInputDevice(OculusControllerManager& parent, const QString& name) : controller::InputDevice(name), _parent(parent) {}
|
||||||
|
|
||||||
|
OculusControllerManager& _parent;
|
||||||
|
friend class OculusControllerManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RemoteDevice : public OculusInputDevice {
|
||||||
|
public:
|
||||||
|
using Pointer = std::shared_ptr<RemoteDevice>;
|
||||||
|
RemoteDevice(OculusControllerManager& parent) : OculusInputDevice(parent, "Oculus Remote") {}
|
||||||
|
|
||||||
|
controller::Input::NamedVector getAvailableInputs() const override;
|
||||||
|
QString getDefaultMappingConfig() const override;
|
||||||
|
void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) override;
|
||||||
|
void focusOutEvent() override;
|
||||||
|
|
||||||
|
friend class OculusControllerManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TouchDevice : public OculusInputDevice {
|
||||||
|
public:
|
||||||
|
using Pointer = std::shared_ptr<TouchDevice>;
|
||||||
|
TouchDevice(OculusControllerManager& parent) : OculusInputDevice(parent, "Oculus Touch") {}
|
||||||
|
|
||||||
|
controller::Input::NamedVector getAvailableInputs() const override;
|
||||||
|
QString getDefaultMappingConfig() const override;
|
||||||
|
void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, bool jointsCaptured) override;
|
||||||
|
void focusOutEvent() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose);
|
||||||
|
int _trackedControllers { 0 };
|
||||||
|
friend class OculusControllerManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
ovrSession _session { nullptr };
|
||||||
|
ovrInputState _inputState {};
|
||||||
|
RemoteDevice::Pointer _remote;
|
||||||
|
TouchDevice::Pointer _touch;
|
||||||
|
static const QString NAME;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi__OculusControllerManager
|
|
@ -10,6 +10,23 @@
|
||||||
#include "OculusHelpers.h"
|
#include "OculusHelpers.h"
|
||||||
|
|
||||||
const QString OculusDisplayPlugin::NAME("Oculus Rift");
|
const QString OculusDisplayPlugin::NAME("Oculus Rift");
|
||||||
|
static ovrPerfHudMode currentDebugMode = ovrPerfHud_Off;
|
||||||
|
|
||||||
|
bool OculusDisplayPlugin::internalActivate() {
|
||||||
|
bool result = Parent::internalActivate();
|
||||||
|
currentDebugMode = ovrPerfHud_Off;
|
||||||
|
if (result && _session) {
|
||||||
|
ovr_SetInt(_session, OVR_PERF_HUD_MODE, currentDebugMode);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusDisplayPlugin::cycleDebugOutput() {
|
||||||
|
if (_session) {
|
||||||
|
currentDebugMode = static_cast<ovrPerfHudMode>((currentDebugMode + 1) % ovrPerfHud_Count);
|
||||||
|
ovr_SetInt(_session, OVR_PERF_HUD_MODE, currentDebugMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OculusDisplayPlugin::customizeContext() {
|
void OculusDisplayPlugin::customizeContext() {
|
||||||
Parent::customizeContext();
|
Parent::customizeContext();
|
||||||
|
@ -48,12 +65,6 @@ void blit(const SrcFbo& srcFbo, const DstFbo& dstFbo) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusDisplayPlugin::updateFrameData() {
|
|
||||||
Parent::updateFrameData();
|
|
||||||
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovrPoseFromGlm(_currentRenderEyePoses[Left]);
|
|
||||||
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovrPoseFromGlm(_currentRenderEyePoses[Right]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OculusDisplayPlugin::hmdPresent() {
|
void OculusDisplayPlugin::hmdPresent() {
|
||||||
|
|
||||||
PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentRenderFrameIndex)
|
PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentRenderFrameIndex)
|
||||||
|
@ -63,12 +74,15 @@ void OculusDisplayPlugin::hmdPresent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
blit(_compositeFramebuffer, _sceneFbo);
|
blit(_compositeFramebuffer, _sceneFbo);
|
||||||
|
_sceneFbo->Commit();
|
||||||
{
|
{
|
||||||
|
_sceneLayer.SensorSampleTime = _currentPresentFrameInfo.sensorSampleTime;
|
||||||
|
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovrPoseFromGlm(_currentPresentFrameInfo.headPose);
|
||||||
|
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovrPoseFromGlm(_currentPresentFrameInfo.headPose);
|
||||||
ovrLayerHeader* layers = &_sceneLayer.Header;
|
ovrLayerHeader* layers = &_sceneLayer.Header;
|
||||||
ovrResult result = ovr_SubmitFrame(_session, _currentRenderFrameIndex, &_viewScaleDesc, &layers, 1);
|
ovrResult result = ovr_SubmitFrame(_session, _currentRenderFrameIndex, &_viewScaleDesc, &layers, 1);
|
||||||
if (!OVR_SUCCESS(result)) {
|
if (!OVR_SUCCESS(result)) {
|
||||||
logWarning("Failed to present");
|
logWarning("Failed to present");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_sceneFbo->Increment();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,12 +22,13 @@ public:
|
||||||
float getTargetFrameRate() override { return TARGET_RATE_Oculus; }
|
float getTargetFrameRate() override { return TARGET_RATE_Oculus; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool internalActivate() override;
|
||||||
void hmdPresent() override;
|
void hmdPresent() override;
|
||||||
// FIXME update with Oculus API call once it's available in the SDK
|
// FIXME update with Oculus API call once it's available in the SDK
|
||||||
bool isHmdMounted() const override { return true; }
|
bool isHmdMounted() const override { return true; }
|
||||||
void customizeContext() override;
|
void customizeContext() override;
|
||||||
void uncustomizeContext() override;
|
void uncustomizeContext() override;
|
||||||
void updateFrameData() override;
|
void cycleDebugOutput() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const QString NAME;
|
static const QString NAME;
|
||||||
|
|
|
@ -9,7 +9,10 @@
|
||||||
#include "OculusHelpers.h"
|
#include "OculusHelpers.h"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
#include <QtCore/QLoggingCategory>
|
#include <QtCore/QLoggingCategory>
|
||||||
|
#include <QtCore/QFile>
|
||||||
|
#include <QtCore/QDir>
|
||||||
|
|
||||||
using Mutex = std::mutex;
|
using Mutex = std::mutex;
|
||||||
using Lock = std::unique_lock<Mutex>;
|
using Lock = std::unique_lock<Mutex>;
|
||||||
|
@ -38,9 +41,23 @@ void logFatal(const char* what) {
|
||||||
qFatal(error.c_str());
|
qFatal(error.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const QString OCULUS_RUNTIME_PATH { "C:\\Program Files (x86)\\Oculus\\Support\\oculus-runtime" };
|
||||||
|
static const QString GOOD_OCULUS_RUNTIME_FILE { OCULUS_RUNTIME_PATH + "\\LibOVRRT64_1.dll" };
|
||||||
|
|
||||||
bool oculusAvailable() {
|
bool oculusAvailable() {
|
||||||
ovrDetectResult detect = ovr_Detect(0);
|
ovrDetectResult detect = ovr_Detect(0);
|
||||||
return (detect.IsOculusServiceRunning && detect.IsOculusHMDConnected);
|
if (!detect.IsOculusServiceRunning || !detect.IsOculusHMDConnected) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK Explicitly check for the presence of the 1.0 runtime DLL, and fail if it
|
||||||
|
// doesn't exist
|
||||||
|
if (!QFile(GOOD_OCULUS_RUNTIME_FILE).exists()) {
|
||||||
|
qCWarning(oculus) << "Oculus Runtime detected, but no 1.x DLL present: \"" + GOOD_OCULUS_RUNTIME_FILE + "\"";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ovrSession acquireOculusSession() {
|
ovrSession acquireOculusSession() {
|
||||||
|
@ -98,9 +115,9 @@ SwapFramebufferWrapper::~SwapFramebufferWrapper() {
|
||||||
destroyColor();
|
destroyColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapFramebufferWrapper::Increment() {
|
void SwapFramebufferWrapper::Commit() {
|
||||||
++color->CurrentIndex;
|
auto result = ovr_CommitTextureSwapChain(_session, color);
|
||||||
color->CurrentIndex %= color->TextureCount;
|
Q_ASSERT(OVR_SUCCESS(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapFramebufferWrapper::Resize(const uvec2 & size) {
|
void SwapFramebufferWrapper::Resize(const uvec2 & size) {
|
||||||
|
@ -114,7 +131,7 @@ void SwapFramebufferWrapper::Resize(const uvec2 & size) {
|
||||||
|
|
||||||
void SwapFramebufferWrapper::destroyColor() {
|
void SwapFramebufferWrapper::destroyColor() {
|
||||||
if (color) {
|
if (color) {
|
||||||
ovr_DestroySwapTextureSet(_session, color);
|
ovr_DestroyTextureSwapChain(_session, color);
|
||||||
color = nullptr;
|
color = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,13 +139,30 @@ void SwapFramebufferWrapper::destroyColor() {
|
||||||
void SwapFramebufferWrapper::initColor() {
|
void SwapFramebufferWrapper::initColor() {
|
||||||
destroyColor();
|
destroyColor();
|
||||||
|
|
||||||
if (!OVR_SUCCESS(ovr_CreateSwapTextureSetGL(_session, GL_SRGB8_ALPHA8, size.x, size.y, &color))) {
|
ovrTextureSwapChainDesc desc = {};
|
||||||
|
desc.Type = ovrTexture_2D;
|
||||||
|
desc.ArraySize = 1;
|
||||||
|
desc.Width = size.x;
|
||||||
|
desc.Height = size.y;
|
||||||
|
desc.MipLevels = 1;
|
||||||
|
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||||
|
desc.SampleCount = 1;
|
||||||
|
desc.StaticImage = ovrFalse;
|
||||||
|
|
||||||
|
ovrResult result = ovr_CreateTextureSwapChainGL(_session, &desc, &color);
|
||||||
|
if (!OVR_SUCCESS(result)) {
|
||||||
logFatal("Failed to create swap textures");
|
logFatal("Failed to create swap textures");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < color->TextureCount; ++i) {
|
int length = 0;
|
||||||
ovrGLTexture& ovrTex = (ovrGLTexture&)color->Textures[i];
|
result = ovr_GetTextureSwapChainLength(_session, color, &length);
|
||||||
glBindTexture(GL_TEXTURE_2D, ovrTex.OGL.TexId);
|
if (!OVR_SUCCESS(result) || !length) {
|
||||||
|
qFatal("Unable to count swap chain textures");
|
||||||
|
}
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
GLuint chainTexId;
|
||||||
|
ovr_GetTextureSwapChainBufferGL(_session, color, i, &chainTexId);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, chainTexId);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
@ -141,8 +175,11 @@ void SwapFramebufferWrapper::initDone() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapFramebufferWrapper::onBind(oglplus::Framebuffer::Target target) {
|
void SwapFramebufferWrapper::onBind(oglplus::Framebuffer::Target target) {
|
||||||
ovrGLTexture& tex = (ovrGLTexture&)(color->Textures[color->CurrentIndex]);
|
int curIndex;
|
||||||
glFramebufferTexture2D(toEnum(target), GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.OGL.TexId, 0);
|
ovr_GetTextureSwapChainCurrentIndex(_session, color, &curIndex);
|
||||||
|
GLuint curTexId;
|
||||||
|
ovr_GetTextureSwapChainBufferGL(_session, color, curIndex, &curTexId);
|
||||||
|
glFramebufferTexture2D(toEnum(target), GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, curTexId, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapFramebufferWrapper::onUnbind(oglplus::Framebuffer::Target target) {
|
void SwapFramebufferWrapper::onUnbind(oglplus::Framebuffer::Target target) {
|
||||||
|
|
|
@ -111,10 +111,10 @@ inline ovrPosef ovrPoseFromGlm(const glm::mat4 & m) {
|
||||||
// then submit it and increment to the next texture.
|
// then submit it and increment to the next texture.
|
||||||
// The Oculus SDK manages the creation and destruction of
|
// The Oculus SDK manages the creation and destruction of
|
||||||
// the textures
|
// the textures
|
||||||
struct SwapFramebufferWrapper : public FramebufferWrapper<ovrSwapTextureSet*, void*> {
|
struct SwapFramebufferWrapper : public FramebufferWrapper<ovrTextureSwapChain, void*> {
|
||||||
SwapFramebufferWrapper(const ovrSession& session);
|
SwapFramebufferWrapper(const ovrSession& session);
|
||||||
~SwapFramebufferWrapper();
|
~SwapFramebufferWrapper();
|
||||||
void Increment();
|
void Commit();
|
||||||
void Resize(const uvec2 & size);
|
void Resize(const uvec2 & size);
|
||||||
protected:
|
protected:
|
||||||
void initColor() override final;
|
void initColor() override final;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "OculusDisplayPlugin.h"
|
#include "OculusDisplayPlugin.h"
|
||||||
#include "OculusDebugDisplayPlugin.h"
|
#include "OculusDebugDisplayPlugin.h"
|
||||||
|
#include "OculusControllerManager.h"
|
||||||
|
|
||||||
class OculusProvider : public QObject, public DisplayProvider, InputProvider
|
class OculusProvider : public QObject, public DisplayProvider, InputProvider
|
||||||
{
|
{
|
||||||
|
@ -51,8 +52,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual InputPluginList getInputPlugins() override {
|
virtual InputPluginList getInputPlugins() override {
|
||||||
// FIXME pending full oculus input API and hardware
|
|
||||||
#if 0
|
|
||||||
static std::once_flag once;
|
static std::once_flag once;
|
||||||
std::call_once(once, [&] {
|
std::call_once(once, [&] {
|
||||||
InputPluginPointer plugin(new OculusControllerManager());
|
InputPluginPointer plugin(new OculusControllerManager());
|
||||||
|
@ -60,7 +59,6 @@ public:
|
||||||
_inputPlugins.push_back(plugin);
|
_inputPlugins.push_back(plugin);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
#endif
|
|
||||||
return _inputPlugins;
|
return _inputPlugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,14 @@ void OculusLegacyDisplayPlugin::resetSensors() {
|
||||||
ovrHmd_RecenterPose(_hmd);
|
ovrHmd_RecenterPose(_hmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusLegacyDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
|
void OculusLegacyDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
|
FrameInfo frame;
|
||||||
|
frame.predictedDisplayTime = frame.sensorSampleTime = ovr_GetTimeInSeconds();
|
||||||
|
_trackingState = ovrHmd_GetTrackingState(_hmd, frame.predictedDisplayTime);
|
||||||
|
frame.headPose = toGlm(_trackingState.HeadPose.ThePose);
|
||||||
|
_currentRenderFrameInfo.set(frame);
|
||||||
Lock lock(_mutex);
|
Lock lock(_mutex);
|
||||||
_trackingState = ovrHmd_GetTrackingState(_hmd, ovr_GetTimeInSeconds());
|
_frameInfos[frameIndex] = frame;
|
||||||
_headPoseCache.set(toGlm(_trackingState.HeadPose.ThePose));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OculusLegacyDisplayPlugin::isSupported() const {
|
bool OculusLegacyDisplayPlugin::isSupported() const {
|
||||||
|
|
|
@ -26,7 +26,7 @@ public:
|
||||||
|
|
||||||
// Stereo specific methods
|
// Stereo specific methods
|
||||||
virtual void resetSensors() override;
|
virtual void resetSensors() override;
|
||||||
virtual void updateHeadPose(uint32_t frameIndex) override;
|
virtual void beginFrameRender(uint32_t frameIndex) override;
|
||||||
|
|
||||||
virtual float getTargetFrameRate() override;
|
virtual float getTargetFrameRate() override;
|
||||||
|
|
||||||
|
|
|
@ -121,22 +121,23 @@ void OpenVrDisplayPlugin::resetSensors() {
|
||||||
_sensorResetMat = glm::inverse(cancelOutRollAndPitch(m));
|
_sensorResetMat = glm::inverse(cancelOutRollAndPitch(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenVrDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
|
void OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
|
|
||||||
float displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float);
|
double displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float);
|
||||||
float frameDuration = 1.f / displayFrequency;
|
double frameDuration = 1.f / displayFrequency;
|
||||||
float vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float);
|
double vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float);
|
||||||
|
|
||||||
|
FrameInfo frame;
|
||||||
#if THREADED_PRESENT
|
#if THREADED_PRESENT
|
||||||
// 3 frames of prediction + vsyncToPhotons = 44ms total
|
// 3 frames of prediction + vsyncToPhotons = 44ms total
|
||||||
const float NUM_PREDICTION_FRAMES = 3.0f;
|
const double NUM_PREDICTION_FRAMES = 3.0f;
|
||||||
float predictedSecondsFromNow = NUM_PREDICTION_FRAMES * frameDuration + vsyncToPhotons;
|
frame.predictedDisplayTime = NUM_PREDICTION_FRAMES * frameDuration + vsyncToPhotons;
|
||||||
#else
|
#else
|
||||||
float predictedSecondsFromNow = frameDuration + vsyncToPhotons;
|
frame.predictedDisplayTime = frameDuration + vsyncToPhotons;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vr::TrackedDevicePose_t predictedTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
vr::TrackedDevicePose_t predictedTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
||||||
_system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, predictedSecondsFromNow, predictedTrackedDevicePose, vr::k_unMaxTrackedDeviceCount);
|
_system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, frame.predictedDisplayTime, predictedTrackedDevicePose, vr::k_unMaxTrackedDeviceCount);
|
||||||
|
|
||||||
// copy and process predictedTrackedDevicePoses
|
// copy and process predictedTrackedDevicePoses
|
||||||
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
|
||||||
|
@ -145,8 +146,11 @@ void OpenVrDisplayPlugin::updateHeadPose(uint32_t frameIndex) {
|
||||||
_trackedDeviceLinearVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vVelocity));
|
_trackedDeviceLinearVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vVelocity));
|
||||||
_trackedDeviceAngularVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vAngularVelocity));
|
_trackedDeviceAngularVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vAngularVelocity));
|
||||||
}
|
}
|
||||||
|
frame.headPose = _trackedDevicePoseMat4[0];
|
||||||
|
_currentRenderFrameInfo.set(frame);
|
||||||
|
|
||||||
_headPoseCache.set(_trackedDevicePoseMat4[0]);
|
Lock lock(_mutex);
|
||||||
|
_frameInfos[frameIndex] = frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenVrDisplayPlugin::hmdPresent() {
|
void OpenVrDisplayPlugin::hmdPresent() {
|
||||||
|
|
|
@ -27,7 +27,7 @@ public:
|
||||||
|
|
||||||
// Stereo specific methods
|
// Stereo specific methods
|
||||||
virtual void resetSensors() override;
|
virtual void resetSensors() override;
|
||||||
virtual void updateHeadPose(uint32_t frameIndex) override;
|
virtual void beginFrameRender(uint32_t frameIndex) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool internalActivate() override;
|
bool internalActivate() override;
|
||||||
|
|
1
server-console/.gitignore
vendored
1
server-console/.gitignore
vendored
|
@ -1,5 +1,6 @@
|
||||||
Server\ Console-*/
|
Server\ Console-*/
|
||||||
server-console-*/
|
server-console-*/
|
||||||
|
Sandbox-*/
|
||||||
electron-packager/
|
electron-packager/
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
logs/
|
logs/
|
||||||
|
|
|
@ -23,7 +23,7 @@ add_dependencies(${TARGET_NAME} assignment-client domain-server)
|
||||||
|
|
||||||
# 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 "Server\\ Console-darwin-x64/${CONSOLE_EXEC_NAME}")
|
set(PACKAGED_CONSOLE_FOLDER "Sandbox-darwin-x64/${CONSOLE_EXEC_NAME}")
|
||||||
elseif (WIN32)
|
elseif (WIN32)
|
||||||
set(PACKAGED_CONSOLE_FOLDER "server-console-win32-x64")
|
set(PACKAGED_CONSOLE_FOLDER "server-console-win32-x64")
|
||||||
elseif (UNIX)
|
elseif (UNIX)
|
||||||
|
|
|
@ -23,12 +23,12 @@ var options = {
|
||||||
arch: "x64",
|
arch: "x64",
|
||||||
platform: platform,
|
platform: platform,
|
||||||
icon: "resources/" + iconName,
|
icon: "resources/" + iconName,
|
||||||
ignore: "logs|(S|s)erver(\\s|-)(C|c)onsole-\\S+|electron-packager|README.md|CMakeLists.txt|packager.js|.gitignore"
|
ignore: "logs|(S|s)erver(\\s|-)(C|c)onsole-\\S+|(S|s)andbox-\\S+|electron-packager|README.md|CMakeLists.txt|packager.js|.gitignore"
|
||||||
}
|
}
|
||||||
|
|
||||||
const EXEC_NAME = "server-console";
|
const EXEC_NAME = "server-console";
|
||||||
const SHORT_NAME = "Server Console";
|
const SHORT_NAME = "Sandbox";
|
||||||
const FULL_NAME = "High Fidelity Server Console";
|
const FULL_NAME = "High Fidelity Sandbox";
|
||||||
|
|
||||||
// setup per OS options
|
// setup per OS options
|
||||||
if (osType == "Darwin") {
|
if (osType == "Darwin") {
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
@ -111,8 +111,8 @@ function shutdown() {
|
||||||
dialog.showMessageBox({
|
dialog.showMessageBox({
|
||||||
type: 'question',
|
type: 'question',
|
||||||
buttons: ['Yes', 'No'],
|
buttons: ['Yes', 'No'],
|
||||||
title: 'Stopping Server Console',
|
title: 'Stopping High Fidelity Sandbox',
|
||||||
message: 'Quitting will stop your Server Console and your Home domain will no longer be running.\nDo you wish to continue?'
|
message: 'Quitting will stop your Sandbox and your Home domain will no longer be running.\nDo you wish to continue?'
|
||||||
}, shutdownCallback);
|
}, shutdownCallback);
|
||||||
} else {
|
} else {
|
||||||
shutdownCallback(0);
|
shutdownCallback(0);
|
||||||
|
@ -212,7 +212,7 @@ var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (shouldQuit) {
|
if (shouldQuit) {
|
||||||
console.warn("Another instance of the Server Console is already running - this instance will quit.");
|
console.warn("Another instance of the Sandbox is already running - this instance will quit.");
|
||||||
app.quit();
|
app.quit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -237,7 +237,7 @@ function binaryMissingMessage(displayName, executableName, required) {
|
||||||
var message = "The " + displayName + " executable was not found.\n";
|
var message = "The " + displayName + " executable was not found.\n";
|
||||||
|
|
||||||
if (required) {
|
if (required) {
|
||||||
message += "It is required for the Server Console to run.\n\n";
|
message += "It is required for the High Fidelity Sandbox to run.\n\n";
|
||||||
} else {
|
} else {
|
||||||
message += "\n";
|
message += "\n";
|
||||||
}
|
}
|
||||||
|
@ -250,7 +250,7 @@ function binaryMissingMessage(displayName, executableName, required) {
|
||||||
message += paths.join("\n");
|
message += paths.join("\n");
|
||||||
} else {
|
} else {
|
||||||
message += "It is expected to be found beside this executable.\n";
|
message += "It is expected to be found beside this executable.\n";
|
||||||
message += "You may need to re-install the Server Console.";
|
message += "You may need to re-install the High Fidelity Sandbox.";
|
||||||
}
|
}
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
|
@ -347,134 +347,6 @@ function goHomeClicked() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function stackManagerBasePath() {
|
|
||||||
var dataPath = 'High Fidelity/Stack Manager/resources';
|
|
||||||
|
|
||||||
if (process.platform == "win32") {
|
|
||||||
return path.resolve(osHomeDir(), 'AppData/Local', dataPath);
|
|
||||||
} else if (process.platform == "darwin") {
|
|
||||||
return path.resolve(osHomeDir(), 'Library/Application Support', dataPath);
|
|
||||||
} else {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isStackManagerContentPresent() {
|
|
||||||
var modelsPath = path.resolve(stackManagerBasePath(), 'models.json.gz');
|
|
||||||
|
|
||||||
try {
|
|
||||||
var stats = fs.lstatSync(modelsPath);
|
|
||||||
|
|
||||||
if (stats.isFile()) {
|
|
||||||
console.log("Stack Manager entities file discovered at " + modelsPath)
|
|
||||||
// we found a content file
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log("Stack Manager entities file not found at " + modelsPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function promptToMigrateContent() {
|
|
||||||
dialog.showMessageBox({
|
|
||||||
type: 'question',
|
|
||||||
buttons: ['Yes', 'No'],
|
|
||||||
title: 'Migrate Content',
|
|
||||||
message: 'Are you sure?\n\nThis will stop your home server and replace everything in your home with your content from Stack Manager.'
|
|
||||||
}, function(index) {
|
|
||||||
if (index == 0) {
|
|
||||||
if (homeServer.state != ProcessGroupStates.STOPPED) {
|
|
||||||
var stopThenMigrateCallback = function(processGroup) {
|
|
||||||
if (isShuttingDown) {
|
|
||||||
homeServer.removeListener('state-update', stopThenMigrateCallback);
|
|
||||||
} else if (processGroup.state == ProcessGroupStates.STOPPED) {
|
|
||||||
performContentMigration();
|
|
||||||
|
|
||||||
homeServer.removeListener('state-update', stopThenMigrateCallback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
homeServer.on('state-update', stopThenMigrateCallback);
|
|
||||||
homeServer.stop();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
performContentMigration();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function performContentMigration() {
|
|
||||||
// check if there is a models file to migrate
|
|
||||||
var modelsPath = path.resolve(stackManagerBasePath(), 'models.json.gz');
|
|
||||||
|
|
||||||
try {
|
|
||||||
var stats = fs.lstatSync(modelsPath);
|
|
||||||
} catch (e) {
|
|
||||||
// no entities file
|
|
||||||
dialog.showMessageBox({
|
|
||||||
type: 'info',
|
|
||||||
buttons: ['OK'],
|
|
||||||
title: 'Models File Not Found',
|
|
||||||
message: 'There is no models file at ' + modelsPath + '\n\nStack Manager content migration can not proceed.'
|
|
||||||
}, null);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
function showMigrationCompletionDialog(copyError) {
|
|
||||||
if (!copyError) {
|
|
||||||
// show message for successful migration
|
|
||||||
dialog.showMessageBox({
|
|
||||||
type: 'info',
|
|
||||||
buttons: ['OK'],
|
|
||||||
title: 'Migration Complete',
|
|
||||||
message: 'Your Stack Manager content has been migrated.\n\nYour home server will now be restarted.'
|
|
||||||
}, null);
|
|
||||||
} else {
|
|
||||||
// show error message for copy fail
|
|
||||||
dialog.showMessageBox({
|
|
||||||
type: 'info',
|
|
||||||
buttons: ['OK'],
|
|
||||||
title: 'Migration Failed',
|
|
||||||
message: 'There was an error copying your Stack Manager content: ' + copyError + '\n\nPlease try again.'
|
|
||||||
}, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we have a models file, try and copy it
|
|
||||||
var newModelsPath = path.resolve(getAssignmentClientResourcesDirectory(), 'entities/models.json.gz')
|
|
||||||
console.log("Copying Stack Manager entity file from " + modelsPath + " to " + newModelsPath);
|
|
||||||
|
|
||||||
try {
|
|
||||||
fs.copySync(modelsPath, newModelsPath);
|
|
||||||
|
|
||||||
// check if there are any assets to copy
|
|
||||||
var oldAssetsPath = path.resolve(stackManagerBasePath(), 'assets');
|
|
||||||
|
|
||||||
var assets = fs.readdirSync(oldAssetsPath);
|
|
||||||
|
|
||||||
if (assets.length > 0) {
|
|
||||||
// assume this means the directory is not empty
|
|
||||||
// and that we should copy it
|
|
||||||
var newAssetsPath = path.resolve(getAssignmentClientResourcesDirectory(), 'assets');
|
|
||||||
|
|
||||||
console.log("Copying Stack Manager assets from " + oldAssetsPath + " to " + newAssetsPath);
|
|
||||||
|
|
||||||
// attempt to copy the assets folder
|
|
||||||
fs.copySync(oldAssetsPath, newAssetsPath, {
|
|
||||||
preserveTimestamps: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
showMigrationCompletionDialog(null);
|
|
||||||
} catch (error) {
|
|
||||||
showMigrationCompletionDialog(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
homeServer.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
var logWindow = null;
|
var logWindow = null;
|
||||||
|
|
||||||
var labels = {
|
var labels = {
|
||||||
|
@ -530,12 +402,6 @@ var labels = {
|
||||||
shell.openExternal('http://localhost:40100/settings/?action=share')
|
shell.openExternal('http://localhost:40100/settings/?action=share')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
migrateContent: {
|
|
||||||
label: 'Migrate Stack Manager Content',
|
|
||||||
click: function() {
|
|
||||||
promptToMigrateContent();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
shuttingDown: {
|
shuttingDown: {
|
||||||
label: "Shutting down...",
|
label: "Shutting down...",
|
||||||
enabled: false
|
enabled: false
|
||||||
|
@ -569,13 +435,6 @@ function buildMenuArray(serverState) {
|
||||||
menuArray.push(labels.share);
|
menuArray.push(labels.share);
|
||||||
menuArray.push(separator);
|
menuArray.push(separator);
|
||||||
menuArray.push(labels.quit);
|
menuArray.push(labels.quit);
|
||||||
|
|
||||||
var foundStackManagerContent = isStackManagerContentPresent();
|
|
||||||
if (foundStackManagerContent) {
|
|
||||||
// add a separator and the stack manager content migration option
|
|
||||||
menuArray.splice(menuArray.length - 1, 0, labels.migrateContent, separator);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -724,7 +583,7 @@ function maybeShowSplash() {
|
||||||
var window = new BrowserWindow({
|
var window = new BrowserWindow({
|
||||||
icon: appIcon,
|
icon: appIcon,
|
||||||
width: 1600 * zoomFactor,
|
width: 1600 * zoomFactor,
|
||||||
height: 737 * zoomFactor,
|
height: 650 * zoomFactor,
|
||||||
center: true,
|
center: true,
|
||||||
frame: true,
|
frame: true,
|
||||||
useContentSize: true,
|
useContentSize: true,
|
||||||
|
@ -770,7 +629,7 @@ app.on('ready', function() {
|
||||||
|
|
||||||
// Create tray icon
|
// Create tray icon
|
||||||
tray = new Tray(trayIcons[ProcessGroupStates.STOPPED]);
|
tray = new Tray(trayIcons[ProcessGroupStates.STOPPED]);
|
||||||
tray.setToolTip('High Fidelity Server Console');
|
tray.setToolTip('High Fidelity Sandbox');
|
||||||
|
|
||||||
tray.on('click', function() {
|
tray.on('click', function() {
|
||||||
tray.popUpContextMenu(tray.menu);
|
tray.popUpContextMenu(tray.menu);
|
||||||
|
|
|
@ -122,11 +122,6 @@ h2 {
|
||||||
|
|
||||||
#main-content {
|
#main-content {
|
||||||
height: 350px;
|
height: 350px;
|
||||||
border-bottom: 2px solid #F5F6F6;
|
|
||||||
}
|
|
||||||
|
|
||||||
#existing-resources-area {
|
|
||||||
padding-top: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
|
@ -143,4 +138,4 @@ h2 {
|
||||||
input[type="checkbox"] {
|
input[type="checkbox"] {
|
||||||
-webkit-transform: scale(1.4);
|
-webkit-transform: scale(1.4);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ High Fidelity is now installed and your Home domain is ready for you to explore.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
You can make your home yours by uploading your own models and scripts, and adding items from the Market.
|
You can make your home yours by uploading your own models and scripts.
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
@ -67,12 +67,6 @@ You can make your home yours by uploading your own models and scripts, and addin
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="existing-resources-area">
|
|
||||||
<p>
|
|
||||||
<h2>Your existing Stack Manager content is safe.</h2>
|
|
||||||
Server Console comes with demo content but does not overwrite your data. <a target="_blank" href="https://docs.highfidelity.com/v1.0/docs/migrate-sm-to-sc">See our guide to importing content previously managed with Stack Manager</a>.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom">
|
<div class="bottom">
|
||||||
<div class="content footer">
|
<div class="content footer">
|
||||||
|
|
|
@ -795,3 +795,35 @@ void OctreeTests::modelItemTests() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OctreeTests::elementAddChildTests() {
|
||||||
|
EntityTreePointer tree = std::make_shared<EntityTree>();
|
||||||
|
auto elem = tree->createNewElement();
|
||||||
|
QCOMPARE((bool)elem->getChildAtIndex(0), false);
|
||||||
|
elem->addChildAtIndex(0);
|
||||||
|
QCOMPARE((bool)elem->getChildAtIndex(0), true);
|
||||||
|
|
||||||
|
const int MAX_CHILD_INDEX = 8;
|
||||||
|
for (int i = 0; i < MAX_CHILD_INDEX; i++) {
|
||||||
|
for (int j = 0; j < MAX_CHILD_INDEX; j++) {
|
||||||
|
auto e = tree->createNewElement();
|
||||||
|
|
||||||
|
// add a single child.
|
||||||
|
auto firstChild = e->addChildAtIndex(i);
|
||||||
|
QCOMPARE(e->getChildAtIndex(i), firstChild);
|
||||||
|
|
||||||
|
if (i != j) {
|
||||||
|
// add a second child.
|
||||||
|
auto secondChild = e->addChildAtIndex(j);
|
||||||
|
QCOMPARE(e->getChildAtIndex(i), firstChild);
|
||||||
|
QCOMPARE(e->getChildAtIndex(j), secondChild);
|
||||||
|
|
||||||
|
// remove scecond child.
|
||||||
|
e->removeChildAtIndex(j);
|
||||||
|
|
||||||
|
QCOMPARE((bool)e->getChildAtIndex(j), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
QCOMPARE(e->getChildAtIndex(i), firstChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ private slots:
|
||||||
// This test is fine
|
// This test is fine
|
||||||
void modelItemTests();
|
void modelItemTests();
|
||||||
|
|
||||||
|
void elementAddChildTests();
|
||||||
|
|
||||||
// TODO: Break these into separate test functions
|
// TODO: Break these into separate test functions
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue