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