Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion UsdPreviewHandlerServer/UsdPreviewHandlerPython.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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):
Expand Down
24 changes: 24 additions & 0 deletions UsdPreviewHandlerServer/UsdPreviewLocalServer.manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
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.
-->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:application>
<asmv3:windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
1 change: 1 addition & 0 deletions UsdPreviewHandlerServer/UsdPreviewLocalServer.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@
<Image Include="shared\usd.ico" />
</ItemGroup>
<ItemGroup>
<Manifest Include="UsdPreviewLocalServer.manifest" />
<ProjectReference Include="..\shared\EventViewerMessages.vcxproj">
<Project>{f12e597b-b731-4f5a-bec3-980d20159320}</Project>
</ProjectReference>
Expand Down
3 changes: 3 additions & 0 deletions UsdPreviewHandlerServer/UsdPreviewLocalServer.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,7 @@
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<Manifest Include="UsdPreviewLocalServer.manifest" />
</ItemGroup>
</Project>
38 changes: 33 additions & 5 deletions UsdPythonToolsServer/UsdPythonToolsImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ static HRESULT RunDiskPythonScript( LPCWSTR sToolFileName, std::vector<const TPy
return hr;
}

static HRESULT RunResourcePythonScript( UINT nResourceId, std::vector<const TPyChar *> &ArgV, std::string &sStdOut, int& exitCode )
typedef void (*PreExecuteScriptCallback)( CStringA& pyScript );
static HRESULT RunResourcePythonScript( UINT nResourceId, std::vector<const TPyChar *> &ArgV, std::string &sStdOut, int& exitCode, PreExecuteScriptCallback pfnPreExecuteScriptCallback)
{
exitCode = 0;

Expand Down Expand Up @@ -190,6 +191,9 @@ static HRESULT RunResourcePythonScript( UINT nResourceId, std::vector<const TPyC
PyObject* pMainModule = PyImport_AddModule("__main__");
PyObject* pGlobalDict = PyModule_GetDict(pMainModule);

if ( pfnPreExecuteScriptCallback )
pfnPreExecuteScriptCallback( pyScript );

CPyObject result = CPyObject( PyRun_String( pyScript.GetString(), Py_file_input, pGlobalDict, pGlobalDict ) );

HRESULT hr = S_OK;
Expand Down Expand Up @@ -304,7 +308,7 @@ STDMETHODIMP CUsdPythonToolsImpl::Record( IN BSTR usdStagePath, IN int imageWidt
ArgV.push_back( pyTempFileName );

int exitCode = 0;
hr = RunResourcePythonScript( IDR_PYTHON_THUMBNAIL, ArgV, sStdOut, exitCode );
hr = RunResourcePythonScript( IDR_PYTHON_THUMBNAIL, ArgV, sStdOut, exitCode, nullptr );
if ( FAILED( hr ) )
return hr;

Expand All @@ -324,6 +328,19 @@ STDMETHODIMP CUsdPythonToolsImpl::Record( IN BSTR usdStagePath, IN int imageWidt
return S_OK;
}

static void UsdViewPreExecuteScriptCallback(CStringA &pyScript)
{
wchar_t sPath[MAX_PATH];
::GetModuleFileNameW( nullptr, sPath, ARRAYSIZE(sPath) );
::PathCchRemoveFileSpec( sPath, ARRAYSIZE(sPath) );
::PathCchAppend( sPath, ARRAYSIZE(sPath), L"usd.ico" );

CStringW sPathEscaped(sPath);
sPathEscaped.Replace( L"\\", L"\\\\" );

pyScript.Replace( "%PATH_TO_USD_ICO%", (LPCSTR)ATL::CW2A(sPathEscaped.GetString(), CP_UTF8) );
}

STDMETHODIMP CUsdPythonToolsImpl::View( IN BSTR usdStagePath, IN BSTR renderer )
{
DEBUG_RECORD_ENTRY();
Expand All @@ -340,8 +357,19 @@ STDMETHODIMP CUsdPythonToolsImpl::View( IN BSTR usdStagePath, IN BSTR renderer )

std::string sStdOut;

// locate usdview
std::wstring sUsdViewAbsolutePath = FindRelativeFile(L"usdview");
if (sUsdViewAbsolutePath.empty())
{
LogEventMessage(PYTHONTOOLS_CATEGORY, L"Failed to locate usdvview", LogEventType::Error);
return E_FAIL;
}

std::vector<const TPyChar *> 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' )
Expand All @@ -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 )
Expand Down
2 changes: 2 additions & 0 deletions UsdPythonToolsServer/UsdPythonToolsLocalServer.rc
Original file line number Diff line number Diff line change
Expand Up @@ -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
/////////////////////////////////////////////////////////////////////////////

Expand Down
9 changes: 7 additions & 2 deletions UsdPythonToolsServer/UsdPythonToolsLocalServer.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@
<TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
</Midl>
<PostBuildEvent>
<Command>%(Command)</Command>
<Command>xcopy "$(SolutionDir)shared\usd.ico" "$(TargetDir)" /I /Y /D /R

%(Command)</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
Expand Down Expand Up @@ -185,7 +187,9 @@
<TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
</Midl>
<PostBuildEvent>
<Command>%(Command)</Command>
<Command>xcopy "$(SolutionDir)shared\usd.ico" "$(TargetDir)" /I /Y /D /R

%(Command)</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
Expand Down Expand Up @@ -217,6 +221,7 @@
<None Include="UsdPythonToolsImpl.rgs" />
<None Include="UsdPythonToolsLocalServerModule.rgs" />
<None Include="UsdThumbnail.py" />
<None Include="UsdView.py" />
</ItemGroup>
<ItemGroup>
<Midl Include="UsdPythonToolsLocalServer.idl" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
<Filter>Resource Files</Filter>
</None>
<None Include="UsdThumbnail.py" />
<None Include="UsdView.py" />
</ItemGroup>
<ItemGroup>
<Midl Include="UsdPythonToolsLocalServer.idl">
Expand Down
44 changes: 44 additions & 0 deletions UsdPythonToolsServer/UsdView.py
Original file line number Diff line number Diff line change
@@ -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)
5 changes: 2 additions & 3 deletions UsdPythonToolsServer/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions UsdSdkToolsServer/UsdSdkToolsImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down
29 changes: 11 additions & 18 deletions UsdShellExtension/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
Loading