diff --git a/UsdPreviewHandlerServer/UsdPreviewHandlerPython.py b/UsdPreviewHandlerServer/UsdPreviewHandlerPython.py index be0e77e..70dc335 100644 --- a/UsdPreviewHandlerServer/UsdPreviewHandlerPython.py +++ b/UsdPreviewHandlerServer/UsdPreviewHandlerPython.py @@ -16,8 +16,9 @@ import sys import os import argparse -from pxr import Usd, UsdUtils, Sdf, UsdAppUtils +from pxr import Usd, UsdGeom, UsdUtils, Sdf, Tf, UsdAppUtils from pxr.Usdviewq.stageView import StageView +from pxr.Usdviewq._usdviewq import Utils from pxr.UsdAppUtils.complexityArgs import RefinementComplexities import UsdPreviewHandler @@ -92,6 +93,14 @@ def OnRendererPlugin(self, plugin): action.setDisabled(True) break + def OnCameraSelectionChanged(self, action): + self.model.viewSettings.cameraPrim = action.data() + + # reset the Free-Cam camera + # it can get messed up if camera controls are used in a fixed camera + if not self.model.viewSettings.cameraPrim: + self.view.updateView(resetCam=True, forceComputeBBox=False) + def buildContextMenu_Renderer(self, contextMenu): self.rendererPluginActionGroup = QActionGroup(self) self.rendererPluginActionGroup.setExclusive(True) @@ -218,12 +227,57 @@ def buildContextMenu_DisplayPurposes(self, contextMenu): displayPurposesMenu.addAction(self.actionDisplay_Proxy) displayPurposesMenu.addAction(self.actionDisplay_Render) + def buildContextMenu_Camera(self, contextMenu): + + self.view.allSceneCameras = Utils._GetAllPrimsOfType( + self.model.stage, Tf.Type.Find(UsdGeom.Camera)) + + # only display a camera menu if the scene has cameras + if len(self.view.allSceneCameras) == 0: + return + + currCamera = self.model.viewSettings.cameraPrim + currCameraPath = None + if currCamera: + currCameraPath = currCamera.GetPath() + + cameraMenu = contextMenu.addMenu("Camera") + + cameraGroup = QActionGroup(self) + cameraGroup.setExclusive(True) + cameraGroup.triggered.connect(self.OnCameraSelectionChanged) + + # add free-cam + actionFreeCamera = QAction("Free Camera", self) + actionFreeCamera.setCheckable(True) + actionFreeCamera.setData(None) + actionFreeCamera.setChecked(currCameraPath == None) + cameraMenu.addAction(actionFreeCamera) + cameraGroup.addAction(actionFreeCamera) + + actionSeparator = QAction("", self) + actionSeparator.setSeparator(True) + cameraMenu.addAction(actionSeparator) + cameraGroup.addAction(actionSeparator) + + for camera in self.view.allSceneCameras: + action = QAction(camera.GetName(), self) + action.setData(camera) + action.setToolTip(str(camera.GetPath())) + action.setCheckable(True) + + action.setChecked(camera.GetPath() == currCameraPath) + + cameraMenu.addAction(action) + cameraGroup.addAction(action) + def buildContextMenu(self): self.contextMenu = QMenu(self) self.buildContextMenu_Renderer(self.contextMenu) self.buildContextMenu_Complexity(self.contextMenu) self.buildContextMenu_ShadingMode(self.contextMenu) self.buildContextMenu_DisplayPurposes(self.contextMenu) + self.buildContextMenu_Camera(self.contextMenu) def closeEvent(self, event): diff --git a/UsdPreviewHandlerServer/UsdPreviewLocalServer.manifest b/UsdPreviewHandlerServer/UsdPreviewLocalServer.manifest new file mode 100644 index 0000000..504e68c --- /dev/null +++ b/UsdPreviewHandlerServer/UsdPreviewLocalServer.manifest @@ -0,0 +1,24 @@ + + + + + + true + PerMonitorV2 + + + \ No newline at end of file diff --git a/UsdPreviewHandlerServer/UsdPreviewLocalServer.vcxproj b/UsdPreviewHandlerServer/UsdPreviewLocalServer.vcxproj index a58d689..9387a29 100644 --- a/UsdPreviewHandlerServer/UsdPreviewLocalServer.vcxproj +++ b/UsdPreviewHandlerServer/UsdPreviewLocalServer.vcxproj @@ -237,6 +237,7 @@ + {f12e597b-b731-4f5a-bec3-980d20159320} diff --git a/UsdPreviewHandlerServer/UsdPreviewLocalServer.vcxproj.filters b/UsdPreviewHandlerServer/UsdPreviewLocalServer.vcxproj.filters index c0f66c8..2892d54 100644 --- a/UsdPreviewHandlerServer/UsdPreviewLocalServer.vcxproj.filters +++ b/UsdPreviewHandlerServer/UsdPreviewLocalServer.vcxproj.filters @@ -100,4 +100,7 @@ Resource Files + + + \ No newline at end of file diff --git a/UsdPythonToolsServer/UsdPythonToolsImpl.cpp b/UsdPythonToolsServer/UsdPythonToolsImpl.cpp index aa2459b..e82b193 100644 --- a/UsdPythonToolsServer/UsdPythonToolsImpl.cpp +++ b/UsdPythonToolsServer/UsdPythonToolsImpl.cpp @@ -151,7 +151,8 @@ static HRESULT RunDiskPythonScript( LPCWSTR sToolFileName, std::vector &ArgV, std::string &sStdOut, int& exitCode ) +typedef void (*PreExecuteScriptCallback)( CStringA& pyScript ); +static HRESULT RunResourcePythonScript( UINT nResourceId, std::vector &ArgV, std::string &sStdOut, int& exitCode, PreExecuteScriptCallback pfnPreExecuteScriptCallback) { exitCode = 0; @@ -190,6 +191,9 @@ static HRESULT RunResourcePythonScript( UINT nResourceId, std::vector ArgV; - ArgV.push_back( sPathToHostExe ); + // Set the first argument as the absolute path to the usdview python script + // We will use argv[0] to load it using importlib + CW2Py pyUsdViewAbsolutePath(sUsdViewAbsolutePath.c_str()); + ArgV.push_back(pyUsdViewAbsolutePath); CW2Py pyRenderer(renderer); if ( renderer != nullptr && renderer[0] != '\0' ) @@ -354,8 +382,8 @@ STDMETHODIMP CUsdPythonToolsImpl::View( IN BSTR usdStagePath, IN BSTR renderer ) ArgV.push_back( pyUsdStagePath ); int exitCode = 0; - hr = RunDiskPythonScript( L"usdview", ArgV, sStdOut, exitCode ); - if ( FAILED( hr ) ) + hr = RunResourcePythonScript( IDR_PYTHON_VIEW, ArgV, sStdOut, exitCode, UsdViewPreExecuteScriptCallback ); + if (FAILED(hr)) return hr; if ( exitCode != 0 ) diff --git a/UsdPythonToolsServer/UsdPythonToolsLocalServer.rc b/UsdPythonToolsServer/UsdPythonToolsLocalServer.rc index dba898a..04e7255 100644 --- a/UsdPythonToolsServer/UsdPythonToolsLocalServer.rc +++ b/UsdPythonToolsServer/UsdPythonToolsLocalServer.rc @@ -76,6 +76,8 @@ IDI_ICON_USD ICON "shared\\usd.ico" IDR_PYTHON_THUMBNAIL PYTHON "UsdThumbnail.py" +IDR_PYTHON_VIEW PYTHON "UsdView.py" + #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/UsdPythonToolsServer/UsdPythonToolsLocalServer.vcxproj b/UsdPythonToolsServer/UsdPythonToolsLocalServer.vcxproj index 2bb36c0..66a9b3f 100644 --- a/UsdPythonToolsServer/UsdPythonToolsLocalServer.vcxproj +++ b/UsdPythonToolsServer/UsdPythonToolsLocalServer.vcxproj @@ -147,7 +147,9 @@ $(OutDir)$(ProjectName).tlb - %(Command) + xcopy "$(SolutionDir)shared\usd.ico" "$(TargetDir)" /I /Y /D /R + +%(Command) @@ -185,7 +187,9 @@ $(OutDir)$(ProjectName).tlb - %(Command) + xcopy "$(SolutionDir)shared\usd.ico" "$(TargetDir)" /I /Y /D /R + +%(Command) @@ -217,6 +221,7 @@ + diff --git a/UsdPythonToolsServer/UsdPythonToolsLocalServer.vcxproj.filters b/UsdPythonToolsServer/UsdPythonToolsLocalServer.vcxproj.filters index 57a7293..fe508a1 100644 --- a/UsdPythonToolsServer/UsdPythonToolsLocalServer.vcxproj.filters +++ b/UsdPythonToolsServer/UsdPythonToolsLocalServer.vcxproj.filters @@ -74,6 +74,7 @@ Resource Files + diff --git a/UsdPythonToolsServer/UsdView.py b/UsdPythonToolsServer/UsdView.py new file mode 100644 index 0000000..e48e7d0 --- /dev/null +++ b/UsdPythonToolsServer/UsdView.py @@ -0,0 +1,44 @@ +# Copyright 2021 Activision Publishing, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import print_function +import sys +import pxr.Usdviewq as Usdviewq + +class LauncherOverride(Usdviewq.Launcher): + + def LaunchPreamble(self, arg_parse_result): + try: + from PySide2 import QtGui + except ImportError: + from PySide import QtGui + + (app, appController) = super().LaunchPreamble(arg_parse_result) + + # set the icon that will appear in the taskbar + appController._mainWindow.setWindowIcon(QtGui.QIcon('%PATH_TO_USD_ICO%')) + # activate the window (SetForegroundWindow) + appController._mainWindow.activateWindow() + + return (app, appController) + +if __name__ == '__main__': + # Let Ctrl-C kill the app. + import signal + signal.signal(signal.SIGINT, signal.SIG_DFL) + try: + LauncherOverride().Run() + except Usdviewq.InvalidUsdviewOption as e: + print("ERROR: " + e.message, file=sys.stderr) + sys.exit(1) diff --git a/UsdPythonToolsServer/resource.h b/UsdPythonToolsServer/resource.h index 2fa80a0..fa0016f 100644 --- a/UsdPythonToolsServer/resource.h +++ b/UsdPythonToolsServer/resource.h @@ -9,15 +9,14 @@ #define IDR_PYTHON_PREVIEWHANLDER 107 #define IDR_REGISTRY_THUMBNAILIMPL 108 #define IDR_REGISTRY_USDTHUMBNAILIMPL 108 -#define IDD_DIALOG1 109 -#define IDR_PYTHON1 111 #define IDR_PYTHON_THUMBNAIL 111 +#define IDR_PYTHON_VIEW 112 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 112 +#define _APS_NEXT_RESOURCE_VALUE 113 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1004 #define _APS_NEXT_SYMED_VALUE 101 diff --git a/UsdSdkToolsServer/UsdSdkToolsImpl.cpp b/UsdSdkToolsServer/UsdSdkToolsImpl.cpp index 088813e..73aad4c 100644 --- a/UsdSdkToolsServer/UsdSdkToolsImpl.cpp +++ b/UsdSdkToolsServer/UsdSdkToolsImpl.cpp @@ -156,6 +156,8 @@ STDMETHODIMP CUsdSdkToolsImpl::Edit( IN BSTR usdStagePath, IN VARIANT_BOOL force return E_FAIL; } + ::AllowSetForegroundWindow( pi.dwProcessId ); + ::WaitForSingleObject( pi.hProcess, INFINITE ); ::CloseHandle( pi.hProcess ); diff --git a/UsdShellExtension/Module.cpp b/UsdShellExtension/Module.cpp index eabd8c0..55d40ef 100644 --- a/UsdShellExtension/Module.cpp +++ b/UsdShellExtension/Module.cpp @@ -73,26 +73,19 @@ static bool GetPythonInstallationPath( LPTSTR sBuffer, DWORD nBufferSizeInChars GetPrivateProfileStringAndExpandEnvironmentStrings( L"PYTHON", L"PATH", L"", sPythonPath, ConfigFileList ); wcscpy_s( sBuffer, nBufferSizeInChars, sPythonPath ); - if ( sBuffer[0] == '\0' ) + if (sBuffer[0] == '\0') { -#if PY_MAJOR_VERSION >= 3 - CString sPythonRegKeyInstallPath; - sPythonRegKeyInstallPath.Format( _T( "SOFTWARE\\Python\\PythonCore\\%hs\\InstallPath" ), _CRT_STRINGIZE(PYTHONVERSION) ); - - LSTATUS ls; - - CRegKey regPythonInstallPath; - ls = regPythonInstallPath.Open( HKEY_CURRENT_USER, sPythonRegKeyInstallPath, KEY_READ ); - if ( ls != ERROR_SUCCESS ) - return false; - - ULONG nChars = nBufferSizeInChars; - ls = regPythonInstallPath.QueryStringValue( _T(""), sBuffer, &nChars ); - if ( ls != ERROR_SUCCESS ) - return false; -#elif (PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION == 7) - _tcscpy_s(sBuffer, nBufferSizeInChars, _T("C:\\Python27\\")); + bool bResult = GetPythonInstallPathFromRegistry( sBuffer, nBufferSizeInChars ); +#if (PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION == 7) + if (bResult == false) + { + _tcscpy_s(sBuffer, nBufferSizeInChars, _T("C:\\Python27\\")); + DWORD nAttribs = ::GetFileAttributes( sBuffer ); + if ( (nAttribs != INVALID_FILE_ATTRIBUTES) && (nAttribs & FILE_ATTRIBUTE_DIRECTORY) ) + bResult = true; + } #endif + return bResult; } else { diff --git a/UsdShellExtension/ShellExecute.cpp b/UsdShellExtension/ShellExecute.cpp index a92255d..4726db0 100644 --- a/UsdShellExtension/ShellExecute.cpp +++ b/UsdShellExtension/ShellExecute.cpp @@ -66,6 +66,8 @@ void CALLBACK OpenInUsdViewW( HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in if ( FAILED( hr ) ) return; + ::CoAllowSetForegroundWindow( pUsdPythonTools, nullptr ); + hr = pUsdPythonTools->View( CComBSTR(args.argv[0]), bRendererIsValid ? bstrRenderer : nullptr ); if ( FAILED( hr ) ) return; @@ -199,6 +201,8 @@ void CALLBACK EditInUsdEditW( HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, in if ( FAILED( hr ) ) return; + ::CoAllowSetForegroundWindow( pUSDTools, nullptr ); + hr = pUSDTools->Edit( CComBSTR(args.argv[0]), VARIANT_FALSE ); if ( FAILED( hr ) ) { @@ -274,6 +278,8 @@ void CALLBACK PackageDefaultW( HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, i wcscpy_s( sOutputFile, args.argv[0] ); PathCchRenameExtension( sOutputFile, ARRAYSIZE( sOutputFile ), L"usdz" ); + ::CoAllowSetForegroundWindow( pUSDTools, nullptr ); + hr = pUSDTools->Package( CComBSTR(args.argv[0]), CComBSTR(sOutputFile), UsdSdkToolsLib::USD_PACKAGE_DEFAULT, VARIANT_TRUE ); if ( FAILED( hr ) ) { @@ -310,6 +316,8 @@ void CALLBACK PackageARKitW( HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int wcscpy_s( sOutputFile, args.argv[0] ); PathCchRenameExtension( sOutputFile, ARRAYSIZE( sOutputFile ), L"usdz" ); + ::CoAllowSetForegroundWindow( pUSDTools, nullptr ); + hr = pUSDTools->Package( CComBSTR(args.argv[0]), CComBSTR(sOutputFile), UsdSdkToolsLib::USD_FORMAT_APPLE_ARKIT, VARIANT_TRUE ); if ( FAILED( hr ) ) { @@ -343,6 +351,8 @@ void CALLBACK StageStatsW( HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int n if ( FAILED( hr ) ) return; + ::CoAllowSetForegroundWindow( pUSDTools, nullptr ); + hr = pUSDTools->DisplayStageStats( CComBSTR(args.argv[0]) ); if ( FAILED( hr ) ) { diff --git a/UsdShellExtensionInstaller/PythonPathPage.nsh b/UsdShellExtensionInstaller/PythonPathPage.nsh new file mode 100644 index 0000000..42c3c65 --- /dev/null +++ b/UsdShellExtensionInstaller/PythonPathPage.nsh @@ -0,0 +1,77 @@ + +Var hWndPythonPathDlg +Var hWndPythonPathEditPath +Var hWndPythonPathEditPythonPath +Var hWndPythonPathButtonBuild + +Function PythonPathPage + !insertmacro MUI_HEADER_TEXT "Python ${PYTHON_VERSION}" "Please set the following Python ${PYTHON_VERSION} environment variables." + + nsDialogs::Create 1018 + Pop $hWndPythonPathDlg + + ${If} $hWndPythonPathDlg == error + Abort + ${EndIf} + + SetShellVarContext all + + ${NSD_CreateLabel} 0 0 100% 10u "PATH" + !insertmacro ReadConfigFile "$LOCALAPPDATA\Activision\UsdShellExtension\UsdShellExtension.ini" "Python" "PATH" "" + Pop $R0 + ${If} $R0 == "" + ReadRegStr $R0 HKCU "SOFTWARE\Python\PythonCore\${PYTHON_VERSION}\InstallPath" "" + ${If} $R0 == "" + ReadRegStr $R0 HKLM "SOFTWARE\Python\PythonCore\${PYTHON_VERSION}\InstallPath" "" + ${EndIf} + ${EndIf} + ${NSD_CreateText} 0 10u 100% 12u $R0 + Pop $hWndPythonPathEditPath + + ${NSD_CreateLabel} 0 28u 100% 10u "PYTHONPATH" + !insertmacro ReadConfigFile "$LOCALAPPDATA\Activision\UsdShellExtension\UsdShellExtension.ini" "Python" "PYTHONPATH" "" + Pop $R0 + ${If} $R0 == "" + ReadRegStr $R0 HKCU "SOFTWARE\Python\PythonCore\${PYTHON_VERSION}\PythonPath" "" + ${If} $R0 == "" + ReadRegStr $R0 HKLM "SOFTWARE\Python\PythonCore\${PYTHON_VERSION}\PythonPath" "" + ${EndIf} + ${EndIf} + ${NSD_CreateText} 0 38u 100% 12u $R0 + Pop $hWndPythonPathEditPythonPath + + ${NSD_CreateButton} -140u 62u 140u 15u "Set using root Python ${PYTHON_VERSION} folder" + Pop $hWndPythonPathButtonBuild + ${NSD_OnClick} $hWndPythonPathButtonBuild PythonPathPageBuildClick + + nsDialogs::Show +FunctionEnd + +Function PythonPathPageLeave + SetShellVarContext all + + ${NSD_GetText} $hWndPythonPathEditPath $0 + + IfFileExists "$0\python.exe" PythonFound + MessageBox MB_ICONSTOP|MB_OK "Python.exe was not found at $0" + Abort + +PythonFound: + !insertmacro WriteConfigFile "$LOCALAPPDATA\Activision\UsdShellExtension\UsdShellExtension.ini" "Python" "PATH" $0 + + ${NSD_GetText} $hWndPythonPathEditPythonPath $0 + !insertmacro WriteConfigFile "$LOCALAPPDATA\Activision\UsdShellExtension\UsdShellExtension.ini" "Python" "PYTHONPATH" $0 + +FunctionEnd + +Function PythonPathPageBuildClick + + nsDialogs::SelectFolderDialog "Select root folder of Python ${PYTHON_VERSION} installation" + Pop $R0 + + ${If} $R0 != error + ${NSD_SetText} $hWndPythonPathEditPath "$R0" + ${NSD_SetText} $hWndPythonPathEditPythonPath "$R0\Lib\;$R0\DLLs\" + ${EndIf} + +FunctionEnd diff --git a/UsdShellExtensionInstaller/UsdShellExtensionInstaller.nsi b/UsdShellExtensionInstaller/UsdShellExtensionInstaller.nsi index 155cbce..f39adeb 100644 --- a/UsdShellExtensionInstaller/UsdShellExtensionInstaller.nsi +++ b/UsdShellExtensionInstaller/UsdShellExtensionInstaller.nsi @@ -83,12 +83,14 @@ InstallDirRegKey HKLM "Software\Activision\UsdShellExtension" "Install_Dir" ;-------------------------------- ;Pages +!include "${__FILEDIR__}\PythonPathPage.nsh" !include "${__FILEDIR__}\UsdPathPage.nsh" !include "${__FILEDIR__}\UsdConfigPage.nsh" !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_LICENSE "LICENSE.txt" !insertmacro MUI_PAGE_INSTFILES +Page custom PythonPathPage PythonPathPageLeave Page custom USDPathPage USDPathPageLeave Page custom USDConfigPage USDConfigPageLeave !insertmacro MUI_PAGE_FINISH @@ -195,6 +197,7 @@ SetOutPath "$INSTDIR" File plugInfo.json File LICENSE.txt File NOTICE.txt +File usd.ico SetOutPath "$INSTDIR\usd" File /r .\usd\* @@ -390,6 +393,7 @@ DeleteRegKey HKLM SOFTWARE\Activision\UsdShellExtension Delete /REBOOTOK "$INSTDIR\plugInfo.json" Delete /REBOOTOK "$INSTDIR\LICENSE.txt" Delete /REBOOTOK "$INSTDIR\NOTICE.txt" +Delete /REBOOTOK "$INSTDIR\usd.ico" RMDir /r /REBOOTOK "$INSTDIR\usd" Delete /REBOOTOK "$INSTDIR\UsdPropertyKeys.propdesc" diff --git a/atviversion.props b/atviversion.props index 5aae0f9..c89c89f 100644 --- a/atviversion.props +++ b/atviversion.props @@ -18,7 +18,7 @@ 1 - 09 + 10 00 00 Activision USD Shell Extension diff --git a/docs/INSTALLING.md b/docs/INSTALLING.md index a7cf2e0..7e2a459 100644 --- a/docs/INSTALLING.md +++ b/docs/INSTALLING.md @@ -73,19 +73,26 @@ Troubleshooting **Python** -By default, the shell extension will try to automatically locate a Python install. The Python 3.x installers from python.org will install registry keys that can be used to locate Python. +By default, the shell extension will try to automatically locate a Python install. Python installers from python.org will install registry keys that can be used to locate Python. -| Python Version | Search Location | -|- |- | -| 2.7 | C:\Python27 | -| 3.6 | HKEY_CURRENT_USER\SOFTWARE\Python\PythonCore\3.6\InstallPath | -| 3.7 | HKEY_CURRENT_USER\SOFTWARE\Python\PythonCore\3.7\InstallPath | +The Python install location is searched in the order listed in the table below. + +| Python Version | Search Location | +|- |- | +| 2.7 | HKEY_CURRENT_USER\SOFTWARE\Python\PythonCore\2.7\InstallPath | +| | HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.7\InstallPath | +| | C:\Python27 | +| 3.6 | HKEY_CURRENT_USER\SOFTWARE\Python\PythonCore\3.6\InstallPath | +| | HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\3.6\InstallPath | +| 3.7 | HKEY_CURRENT_USER\SOFTWARE\Python\PythonCore\3.7\InstallPath | +| | HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\3.7\InstallPath | If the Python install is not found at these locations, then it needs to be set explicitly using the `UsdShellExtension.ini` file. ``` [PYTHON] -PATH=C:\Python37 +PATH=C:\Python36\ +PYTHONPATH=C:\Python36\Lib\;C:\Python36\DLLs\ ``` **Event Viewer** diff --git a/shared/EventViewerMessages.vcxproj b/shared/EventViewerMessages.vcxproj index 9162078..05b5147 100644 --- a/shared/EventViewerMessages.vcxproj +++ b/shared/EventViewerMessages.vcxproj @@ -62,6 +62,8 @@ mc %(FullPath) mc %(FullPath) Compiling Messages... %(Filename).rc;%(Filename).h;MSG00409.bin + ClInclude + ClInclude diff --git a/shared/environment.cpp b/shared/environment.cpp index 6f5c577..ad2a183 100644 --- a/shared/environment.cpp +++ b/shared/environment.cpp @@ -97,43 +97,81 @@ static CStringW AppendEnvironmentVariable( LPCWSTR sEnvironmentVariable, LPCWSTR return sSetBuffer; } +bool GetPythonInstallPathFromRegistry( LPTSTR sBuffer, DWORD nBufferSizeInChars ) +{ + CString sPythonRegKeyInstallPath; + sPythonRegKeyInstallPath.Format( _T("SOFTWARE\\Python\\PythonCore\\%hs\\InstallPath"), _CRT_STRINGIZE(PYTHONVERSION) ); + + LSTATUS ls; + + CRegKey regPythonInstallPath; + ls = regPythonInstallPath.Open( HKEY_CURRENT_USER, sPythonRegKeyInstallPath, KEY_READ ); + if (ls != ERROR_SUCCESS) + { + ls = regPythonInstallPath.Open( HKEY_LOCAL_MACHINE, sPythonRegKeyInstallPath, KEY_READ ); + if (ls != ERROR_SUCCESS) + { + return false; + } + } + + ULONG nChars = nBufferSizeInChars; + ls = regPythonInstallPath.QueryStringValue( _T(""), sBuffer, &nChars ); + if (ls != ERROR_SUCCESS) + return false; + + return true; +} + +bool GetPythonPythonPathFromRegistry( LPTSTR sBuffer, DWORD nBufferSizeInChars ) +{ + CString sPythonRegKeyPythonPath; + sPythonRegKeyPythonPath.Format( _T("SOFTWARE\\Python\\PythonCore\\%hs\\PythonPath"), _CRT_STRINGIZE(PYTHONVERSION) ); + + LSTATUS ls; + + CRegKey regPythonPythonPath; + ls = regPythonPythonPath.Open( HKEY_CURRENT_USER, sPythonRegKeyPythonPath, KEY_READ ); + if (ls != ERROR_SUCCESS) + { + ls = regPythonPythonPath.Open( HKEY_LOCAL_MACHINE, sPythonRegKeyPythonPath, KEY_READ ); + if (ls != ERROR_SUCCESS) + { + return false; + } + } + + ULONG nChars = nBufferSizeInChars; + ls = regPythonPythonPath.QueryStringValue( _T(""), sBuffer, &nChars ); + if (ls != ERROR_SUCCESS) + return false; + + return true; +} + static void SetupPathEnvironmentVariable(LPCWSTR sUSD_Path, LPCWSTR sPython_Path) { CStringW sSetBuffer; if ( sPython_Path[0] == '\0' ) { -#if PY_MAJOR_VERSION >= 3 - #if defined(PYTHONVERSION) - CStringW sPythonRegKeyInstallPath; - sPythonRegKeyInstallPath.Format( L"SOFTWARE\\Python\\PythonCore\\%hs\\InstallPath", _CRT_STRINGIZE(PYTHONVERSION) ); - - LSTATUS ls; - CRegKey regPythonInstallPath; - ls = regPythonInstallPath.Open( HKEY_CURRENT_USER, sPythonRegKeyInstallPath, KEY_READ ); - if ( ls == ERROR_SUCCESS ) + TCHAR sValue[512]; + bool bFound = GetPythonInstallPathFromRegistry( sValue, ARRAYSIZE(sValue) ); +#if (PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION == 7) + if (bFound == false) { - TCHAR sValue[512]; - ULONG nChars = ARRAYSIZE( sValue ); - ls = regPythonInstallPath.QueryStringValue( L"", sValue, &nChars ); - if ( ls == ERROR_SUCCESS ) - { - if ( !sSetBuffer.IsEmpty() ) - sSetBuffer += L";"; - sSetBuffer += sValue; - } + _tcscpy_s(sValue, ARRAYSIZE(sValue), _T("C:\\Python27\\")); + DWORD nAttribs = ::GetFileAttributes(sValue); + if ((nAttribs != INVALID_FILE_ATTRIBUTES) && (nAttribs & FILE_ATTRIBUTE_DIRECTORY)) + bFound = true; } - #endif -#elif PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 7 - static constexpr wchar_t python27InstallPath[] = L"C:\\Python27\\"; - DWORD nAttrib = ::GetFileAttributesW( python27InstallPath ); - if ( (nAttrib != INVALID_FILE_ATTRIBUTES) && (nAttrib & FILE_ATTRIBUTE_DIRECTORY) ) +#endif + if (bFound) { - if ( !sSetBuffer.IsEmpty() ) + if (!sSetBuffer.IsEmpty()) sSetBuffer += L";"; - sSetBuffer += python27InstallPath; + sSetBuffer += sValue; } -#endif } else { @@ -152,9 +190,22 @@ static void SetupPathEnvironmentVariable(LPCWSTR sUSD_Path, LPCWSTR sPython_Path static void SetupPythonPathEnvironmentVariable(LPCWSTR sUSD_PythonPath, LPCWSTR sPython_PythonPath) { CStringW sSetBuffer = sUSD_PythonPath; - if ( !sSetBuffer.IsEmpty() ) - sSetBuffer += L";"; - sSetBuffer += sPython_PythonPath; + + if (sPython_PythonPath[0] == '\0') + { + TCHAR sValue[1024]; + bool bFound = GetPythonPythonPathFromRegistry(sValue, ARRAYSIZE(sValue)); + if (bFound) + { + if (!sSetBuffer.IsEmpty()) + sSetBuffer += L";"; + sSetBuffer += sValue; + } + } + else + { + sSetBuffer += sPython_PythonPath; + } g_UsdPythonPath = AppendEnvironmentVariable( L"PYTHONPATH", sSetBuffer ); } diff --git a/shared/environment.h b/shared/environment.h index 2c30e42..b8e7a86 100644 --- a/shared/environment.h +++ b/shared/environment.h @@ -24,4 +24,6 @@ const CStringW &GetUsdPythonPath(); const CStringW &GetUsdEditor(); std::vector BuildConfigFileList( HMODULE hCurrentModule ); -void GetPrivateProfileStringAndExpandEnvironmentStrings( LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpDefault, CStringW &lpReturnedString, const std::vector &ConfigFileList ); \ No newline at end of file +void GetPrivateProfileStringAndExpandEnvironmentStrings( LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpDefault, CStringW &lpReturnedString, const std::vector &ConfigFileList ); +bool GetPythonInstallPathFromRegistry( LPTSTR sBuffer, DWORD nBufferSizeInChars ); +bool GetPythonPythonPathFromRegistry( LPTSTR sBuffer, DWORD nBufferSizeInChars ); diff --git a/usd-monolithic.props b/usd-monolithic.props index 572c9ad..c467b2d 100644 --- a/usd-monolithic.props +++ b/usd-monolithic.props @@ -20,7 +20,7 @@ monolithic - 21.02 + 21.05