From 5719541bd94921ec9be3ba4611564052b748d34d Mon Sep 17 00:00:00 2001 From: Luca Scheller Date: Thu, 21 Mar 2024 21:36:08 -0700 Subject: [PATCH] Make update manager maya compatible --- CMakeLists.txt | 22 +- README.md | 8 +- docs.sh | 0 docs/src/installation/automatic_install.md | 16 +- docs/src/installation/building.md | 31 +- docs/src/installation/requirements.md | 30 +- docs/src/overview.md | 4 +- tools/update_manager.py | 410 +++++++++++++-------- 8 files changed, 328 insertions(+), 193 deletions(-) mode change 100644 => 100755 docs.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index e0ff36f..7d5bafe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,16 +194,18 @@ add_compile_definitions(HBOOST_ALL_NO_LIB BOOST_ALL_NO_LIB) if (WIN32) add_compile_definitions(NOMINMAX) else() - # Notes: - # Houdini 20 - Switched to the new C++11 ABI for Linux https://www.sidefx.com/docs/houdini/news/20/platforms.html - # For Houdini versions that use gcc 9.3, please set this to _GLIBCXX_USE_CXX11_ABI=0 - file(REAL_PATH ${AR_HOUDINI_ROOT} AR_HOUDINI_ROOT_RESOLVED) - string(FIND ${AR_HOUDINI_ROOT_RESOLVED} "19.5" AR_HOUDINI_ROOT_IS_H195) - if (${AR_HOUDINI_ROOT_IS_H195} STREQUAL "-1") - add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=1) - else() - message("Houdini 19.5 detected, switching to _GLIBCXX_USE_CXX11_ABI=0") - add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0) + if("$ENV{AR_DCC_NAME}" STREQUAL "HOUDINI") + # Notes: + # Houdini 20 - Switched to the new C++11 ABI for Linux https://www.sidefx.com/docs/houdini/news/20/platforms.html + # For Houdini versions that use gcc 9.3, please set this to _GLIBCXX_USE_CXX11_ABI=0 + file(REAL_PATH ${AR_HOUDINI_ROOT} AR_HOUDINI_ROOT_RESOLVED) + string(FIND ${AR_HOUDINI_ROOT_RESOLVED} "19.5" AR_HOUDINI_ROOT_IS_H195) + if (${AR_HOUDINI_ROOT_IS_H195} STREQUAL "-1") + add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=1) + else() + message("Houdini 19.5 detected, switching to _GLIBCXX_USE_CXX11_ABI=0") + add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0) + endif() endif() endif() # Compiler Options diff --git a/README.md b/README.md index 3aa7df4..173f7f4 100644 --- a/README.md +++ b/README.md @@ -9,17 +9,17 @@ This repository holds reference implementations for [Usd](https://openusd.org/re To build the various resolvers, follow the instructions in the [install guide](https://lucascheller.github.io/VFX-UsdAssetResolver/installation/requirements.html). > [!NOTE] -> This guide currently covers compiling against Houdini on Linux and Windows. Alternatively you can also download a pre-compiled builds on our [release page](https://github.com/LucaScheller/VFX-UsdAssetResolver/releases). To load the resolver, you must specify a few environment variables, see our [environment variables](https://lucascheller.github.io/VFX-UsdAssetResolver/resolvers/overview.html#environment-variables) section for more details. +> This guide currently covers compiling against Houdini/Maya on Linux and Windows. Alternatively you can also download a pre-compiled builds on our [release page](https://github.com/LucaScheller/VFX-UsdAssetResolver/releases). To load the resolver, you must specify a few environment variables, see our [environment variables](https://lucascheller.github.io/VFX-UsdAssetResolver/resolvers/overview.html#environment-variables) section for more details. > [!IMPORTANT] -> We also offer a quick install method for Houdini that does the download of the compiled resolvers and environment variable setup for you. This is ideal if you want to get your hands dirty right away and you don't have any C++ knowledge or extensive USD developer knowledge. If you are a small studio, you can jump right in and play around with our resolvers and prototype them further to make it fit your production needs. +> We also offer a quick install method for Houdini/Maya that does the download of the compiled resolvers and environment variable setup for you. This is ideal if you want to get your hands dirty right away and you don't have any C++ knowledge or extensive USD developer knowledge. If you are a small studio, you can jump right in and play around with our resolvers and prototype them further to make it fit your production needs. -To run the "Update Manager" simply run this snippet in the "Houdini Python Source Editor" panel: +To run the "Update Manager" simply run this snippet in the Houdini "Python Source Editor" or Maya "Script Editor" panel: import urllib,ssl update_manager_url = 'https://raw.githubusercontent.com/LucaScheller/VFX-UsdAssetResolver/main/tools/update_manager.py?token=$(date%20+%s)' exec(urllib.request.urlopen(update_manager_url,context=ssl._create_unverified_context()).read(), globals(), locals()) - run_houdini() + run_dcc() See our [Automatic Installation](https://lucascheller.github.io/VFX-UsdAssetResolver/installation/automatic_install.html) section for more information. diff --git a/docs.sh b/docs.sh old mode 100644 new mode 100755 diff --git a/docs/src/installation/automatic_install.md b/docs/src/installation/automatic_install.md index 0a0b942..57fed4b 100644 --- a/docs/src/installation/automatic_install.md +++ b/docs/src/installation/automatic_install.md @@ -29,8 +29,20 @@ In Houdini we simply need to open the "Python Source Editor" from the "Windows" import urllib,ssl update_manager_url = 'https://raw.githubusercontent.com/LucaScheller/VFX-UsdAssetResolver/main/tools/update_manager.py?token=$(date%20+%s)' exec(urllib.request.urlopen(update_manager_url,context=ssl._create_unverified_context()).read(), globals(), locals()) -run_houdini() +run_dcc() ``` ~~~ -![Houdini Python Source editor](./media/HoudiniPythonSourceEditor.jpg) \ No newline at end of file +![Houdini Python Source editor](./media/HoudiniPythonSourceEditor.jpg) + +## Maya +In Maya we simply need to open the "Script Editor" and run the following code to get access to the update manager. You should preferably do this in a clean Maya session as a safety measure. + +~~~admonish info title="" +```python +import urllib,ssl +update_manager_url = 'https://raw.githubusercontent.com/LucaScheller/VFX-UsdAssetResolver/main/tools/update_manager.py?token=$(date%20+%s)' +exec(urllib.request.urlopen(update_manager_url,context=ssl._create_unverified_context()).read(), globals(), locals()) +run_dcc() +``` +~~~ diff --git a/docs/src/installation/building.md b/docs/src/installation/building.md index 8dee650..2cd80f3 100644 --- a/docs/src/installation/building.md +++ b/docs/src/installation/building.md @@ -1,11 +1,11 @@ # Building -Currently we support building against Houdini on Linux and Windows. If you don't want to self-compile, you can also download pre-compiled builds on our [release page](https://github.com/LucaScheller/VFX-UsdAssetResolver/releases). To load the resolver, you must specify a few environment variables, see our [Resolvers > Environment Variables](../resolvers/overview.md#environment-variables) section for more details. +Currently we support building against Houdini and Maya on Linux and Windows. If you don't want to self-compile, you can also download pre-compiled builds on our [release page](https://github.com/LucaScheller/VFX-UsdAssetResolver/releases). To load the resolver, you must specify a few environment variables, see our [Resolvers > Environment Variables](../resolvers/overview.md#environment-variables) section for more details. ## Setting up our build environment After installing the [requirements](./requirements.md), we first need to set a couple of environment variables that our cmake file depends on. ### Using our convenience setup script -On Linux we provide a bash script that you can source that sets up our development environment. This sets a few environment variables needed to build the resolver as well as for Houdini to load it. +On Linux we provide a bash script that you can source that sets up our development environment. This sets a few environment variables needed to build the resolver as well as for Houdini/Maya to load it. This can be done by running the following from the source directory: ~~~admonish info title="" ```bash @@ -13,7 +13,7 @@ source setup.sh ``` ~~~ -In the [setup.sh](https://github.com/LucaScheller/VFX-UsdAssetResolver/blob/main/setup.sh) file you can define what resolver to compile by setting the `RESOLVER_NAME` variable to one of the resolvers listed in [resolvers](../resolvers/overview.md) in camelCase syntax (for example `fileResolver` or `pythonResolver`). Here you'll also have to define what Houdini version to compile against. +In the [setup.sh](https://github.com/LucaScheller/VFX-UsdAssetResolver/blob/main/setup.sh) file you can define what resolver to compile by setting the `RESOLVER_NAME` variable to one of the resolvers listed in [resolvers](../resolvers/overview.md) in camelCase syntax (for example `fileResolver` or `pythonResolver`). Here you'll also have to define what Houdini/Maya version to compile against. It will then automatically set the `PATH`, `PYTHONPATH`, `PXR_PLUGINPATH_NAME` and `LD_LIBRARY_PATH` environment variables to the correct paths so that after your run the compile, the resolver will be loaded correctly (e.g. if you launch Houdini via `houdinifx`, it will load everything correctly). The build process also logs this information again. @@ -25,11 +25,28 @@ If you don't want to use our convenience script, you can also setup the environm ~~~admonish info title="" ```bash # Linux +## Houdini +export AR_DCC_NAME=houdini export HFS= # For example "/opt/hfs" -export RESOLVER_NAME=fileResolver +## Maya +export AR_DCC_NAME=maya +export MAYA_USD_SDK_ROOT="/path/to/maya/usd/sdk/root/.../mayausd/USD" +export MAYA_USD_SDK_DEVKIT_ROOT="/path/to/maya/usd/sdk/root/.../content/of/devkit.zip" +export PYTHON_ROOT="/path/to/python/root" +## Resolver +export AR_RESOLVER_NAME=fileResolver + # Windows +## Houdini +set AR_DCC_NAME=houdini set HFS= # For example "C:\Program Files\Side Effects Software\" -set RESOLVER_NAME=fileResolver +## Maya +set AR_DCC_NAME=maya +set MAYA_USD_SDK_ROOT="/path/to/maya/usd/sdk/root/.../mayausd/USD" +set MAYA_USD_SDK_DEVKIT_ROOT="/path/to/maya/usd/sdk/root/.../content/of/devkit.zip" +set PYTHON_ROOT="/path/to/python/root" +## Resolver +set AR_RESOLVER_NAME=fileResolver ``` ~~~ @@ -65,9 +82,9 @@ build.bat The `build.sh/.bat` files also contain (commented out) the environment definition part above, so alternatively just comment out the lines and you are good to go. ## Testing the build -Unit tests are automatically run post-build on Linux using the Houdini version you are using. You can find each resolvers tests in its respective src//testenv folder. +Unit tests are automatically run post-build on Linux using the Houdini/Maya version you are using. You can find each resolvers tests in its respective src//testenv folder. -Alternatively you can run Houdini and check if the resolver executes correctly. If you didn't use our convenience script as noted above, you'll have to specify a few environment variables, so that our plugin is correctly detected by USD. +Alternatively you can run Houdini/Maya and check if the resolver executes correctly. If you didn't use our convenience script as noted above, you'll have to specify a few environment variables, so that our plugin is correctly detected by USD. Head over to our [Resolvers > Environment Variables](../resolvers/overview.md#environment-variables) section on how to do this. diff --git a/docs/src/installation/requirements.md b/docs/src/installation/requirements.md index e03a870..967aabb 100644 --- a/docs/src/installation/requirements.md +++ b/docs/src/installation/requirements.md @@ -1,32 +1,36 @@ # Requirements ## System dependencies -Currently building on Linux and Windows is documented. We use CMake as our build system and link against Houdini to avoid having to compile our own version of Usd. +Currently building on Linux and Windows is documented. We use CMake as our build system and link against Houdini/Maya to avoid having to compile our own version of Usd. It is also possible to compile against a self-compiled Usd build, this is not covered by this guide though. VFX DCC vendors try to keep in sync with the versions specified in the [VFX Reference Platform](https://vfxplatform.com), so if something doesn't work, first make sure that your software versions are supported. ```admonish warning -Since the Usd Asset Resolver API changed with the AR 2.0 standard proposed in the [Asset Resolver 2.0 Specification](https://openusd.org/release/wp_ar2.html), you can only compile against Houdini versions 19.5 and higher. +Since the Usd Asset Resolver API changed with the AR 2.0 standard proposed in the [Asset Resolver 2.0 Specification](https://openusd.org/release/wp_ar2.html), you can only compile against Houdini versions 19.5 and higher/Maya versions 2024 and higher. ``` ## Linux ```admonish success title="" -| Software | Website | Min (Not Tested) | Max (Tested) | -|-----------------|--------------------------------------------------|----------------------|---------------| -| gcc | [https://gcc.gnu.org](https://gcc.gnu.org/) | 11.2.1 | 13.1.1 | -| cmake | [https://cmake.org](https://cmake.org/) | 3.26.4 | 3.26.4 | -| SideFX Houdini | [https://www.sidefx.com](https://www.sidefx.com) | 19.5 | 19.5 | +| Software | Website | Min (Not Tested) | Max (Tested) | +|------------------------|------------------------------------------------------------------------|----------------------|---------------| +| gcc | [https://gcc.gnu.org](https://gcc.gnu.org/) | 11.2.1 | 13.1.1 | +| cmake | [https://cmake.org](https://cmake.org/) | 3.26.4 | 3.26.4 | +| SideFX Houdini | [SideFX Houdini](https://www.sidefx.com) | 19.5 | 19.5 | +| Autodesk Maya | [Autodesk Maya](https://www.autodesk.com/ca-en/products/maya/overview) | 2024 | 2024 | +| Autodesk Maya USD SDK | [Autodesk Maya USD SDK](https://github.com/Autodesk/maya-usd) | 0.27.0 | 0.27.0 | ``` ## Windows ```admonish success title="" -| Software | Website | Min (Not Tested) | Max (Tested) | -|----------------------|------------------------------------------------------------------------------------|----------------------|---------------| -|Visual Studio 16 2019 | [https://visualstudio.microsoft.com/vs/](https://visualstudio.microsoft.com/vs/) | 11.2.1 | 13.1.1 | -| cmake | [https://cmake.org](https://cmake.org/) | 3.26.4 | 3.26.4 | -| SideFX Houdini | [https://www.sidefx.com](https://www.sidefx.com) | 19.5 | 19.5 | +| Software | Website | Min (Not Tested) | Max (Tested) | +|------------------------|------------------------------------------------------------------------------------|----------------------|---------------| +|Visual Studio 16 2019 | [https://visualstudio.microsoft.com/vs/](https://visualstudio.microsoft.com/vs/) | 11.2.1 | 13.1.1 | +| cmake | [https://cmake.org](https://cmake.org/) | 3.26.4 | 3.26.4 | +| SideFX Houdini | [SideFX Houdini](https://www.sidefx.com) | 19.5 | 19.5 | +| Autodesk Maya | [Autodesk Maya](https://www.autodesk.com/ca-en/products/maya/overview) | 2024 | 2024 | +| Autodesk Maya USD SDK | [Autodesk Maya USD SDK](https://github.com/Autodesk/maya-usd) | 0.27.0 | 0.27.0 | ``` -When compiling against Houdini on Windows, make sure you use the Visual Studio version that Houdini was compiled with as noted in the [HDK](https://www.sidefx.com/docs/hdk/_h_d_k__intro__getting_started.html#HDK_Intro_Compiling_Intro_Windows). You'll also need to install the [Visual Studio build tools](https://visualstudio.microsoft.com/downloads/?q=build+tools) that match the Visual Studio release if you want to run everything from the terminal. \ No newline at end of file +When compiling against Houdini/Maya on Windows, make sure you use the Visual Studio version that Houdini/Maya was compiled with as noted in the [HDK](https://www.sidefx.com/docs/hdk/_h_d_k__intro__getting_started.html#HDK_Intro_Compiling_Intro_Windows)/[SDK](https://github.com/Autodesk/maya-usd). You'll also need to install the [Visual Studio build tools](https://visualstudio.microsoft.com/downloads/?q=build+tools) that match the Visual Studio release if you want to run everything from the terminal. \ No newline at end of file diff --git a/docs/src/overview.md b/docs/src/overview.md index c52d7e3..0ed9fc4 100644 --- a/docs/src/overview.md +++ b/docs/src/overview.md @@ -10,11 +10,11 @@ This repository holds reference implementations for [Usd](https://openusd.org/re To build the various resolvers, follow the instructions in the [install guide](./installation/overview.md). ```admonish info -This guide currently covers compiling against Houdini on Linux and Windows. Alternatively you can also download a pre-compiled builds on our [release page](https://github.com/LucaScheller/VFX-UsdAssetResolver/releases). To load the resolver, you must specify a few environment variables, see our [environment variables](./resolvers/overview.md#environment-variables) section for more details. +This guide currently covers compiling against Houdini/Maya on Linux and Windows. Alternatively you can also download a pre-compiled builds on our [release page](https://github.com/LucaScheller/VFX-UsdAssetResolver/releases). To load the resolver, you must specify a few environment variables, see our [environment variables](./resolvers/overview.md#environment-variables) section for more details. ``` ```admonish tip -We also offer a quick install method for Houdini that does the download of the compiled resolvers and environment variable setup for you. This is ideal if you want to get your hands dirty right away and you don't have any C++ knowledge or extensive USD developer knowledge. If you are a small studio, you can jump right in and play around with our resolvers and prototype them further to make it fit your production needs. See our [Automatic Installation](./installation/automatic_install.md) section for more information. +We also offer a quick install method for Houdini/Maya that does the download of the compiled resolvers and environment variable setup for you. This is ideal if you want to get your hands dirty right away and you don't have any C++ knowledge or extensive USD developer knowledge. If you are a small studio, you can jump right in and play around with our resolvers and prototype them further to make it fit your production needs. See our [Automatic Installation](./installation/automatic_install.md) section for more information. ``` ## Feature Overview diff --git a/tools/update_manager.py b/tools/update_manager.py index 89fb438..9689344 100644 --- a/tools/update_manager.py +++ b/tools/update_manager.py @@ -11,7 +11,6 @@ import zipfile from urllib import request - from PySide2 import QtCore, QtGui, QtWidgets # To run, execute this in the Houdini Python Source Editor @@ -19,24 +18,28 @@ import urllib,ssl update_manager_url = 'https://raw.githubusercontent.com/LucaScheller/VFX-UsdAssetResolver/main/tools/update_manager.py?token=$(date +%s)' exec(urllib.request.urlopen(update_manager_url,context=ssl._create_unverified_context()).read(), globals(), locals()) -run_houdini() +run_dcc() """ REPO_URL = "https://api.github.com/repos/lucascheller/VFX-UsdAssetResolver" -RELEASE_ASSET_ELEMENTS_REGEX = re.compile( - "UsdAssetResolver_(houdini)(-py[0-9]+)?-([0-9.]+)-(linux|win64).zip" -) RELEASE_INSTALL_DIRECTORY_PREFIX = "UsdAssetResolver_v" ENV_USD_ASSET_RESOLVER = "USD_ASSET_RESOLVER" -HOU_PACKAGE_FILE_NAME = "UsdAssetResolver.json" +HOUDINI_PACKAGE_FILE_NAME = "UsdAssetResolver.json" +HOUDINI_RELEASE_ASSET_ELEMENTS_REGEX = re.compile( + "UsdAssetResolver_(houdini)(-py[0-9]+)?-([0-9.]+)-(linux|win64).zip" +) +MAYA_RELEASE_ASSET_ELEMENTS_REGEX = re.compile( + "UsdAssetResolver_(maya)-([0-9.]+)-USD-SDK-([0-9.]+)-(Linux|Windows).zip" +) QT_WINDOW_TITLE = "USD Asset Resolver - Update Manager" QT_ROLE_RELEASE = QtCore.Qt.UserRole + 1001 class ZipFileWithPermissions(zipfile.ZipFile): - """ Custom ZipFile class handling file permissions. + """Custom ZipFile class handling file permissions. See https://stackoverflow.com/questions/39296101/python-zipfile-removes-execute-permissions-from-binaries """ + def _extract_member(self, member, target_path, pwd): if not isinstance(member, zipfile.ZipInfo): member = self.getinfo(member) @@ -48,8 +51,8 @@ def _extract_member(self, member, target_path, pwd): class UpdateManagerUI(QtWidgets.QDialog): - def __init__(self, parent): - super(UpdateManagerUI, self).__init__(parent) + def __init__(self): + super(UpdateManagerUI, self).__init__() # Window settings self.setWindowTitle(QT_WINDOW_TITLE) @@ -253,7 +256,7 @@ def uninstall_button_clicked(self): QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel, ) if answer == QtWidgets.QMessageBox.Yes: - run_houdini() + run_dcc() class UpdateManager(object): @@ -266,9 +269,14 @@ def __init__(self): def initialize(self): self.platform = self.get_platform() - self.product_name, self.product_version, self.product_python_version = self.get_software() + self.product_name, self.product_version, self.product_python_version = ( + self.get_software() + ) self.releases = self.get_release_data( - self.get_platform(), self.product_name, self.product_version, self.product_python_version + self.platform, + self.product_name, + self.product_version, + self.product_python_version, ) def get_platform(self): @@ -278,7 +286,7 @@ def get_platform(self): """ current_platform = platform.system() if current_platform == "Windows" or current_platform.startswith("CYGWIN"): - return "win64" + return "windows" elif current_platform == "Darwin": return "macos" elif current_platform == "Linux": @@ -286,6 +294,33 @@ def get_platform(self): else: return "" + def get_dcc_name(self): + """Get the active dcc + Returns: + str: The active dcc + """ + # Houdini + try: + import hou + + if not hou.isUIAvailable(): + raise ImportError + return "houdini" + except ImportError: + pass + # Maya + try: + import pymel + + return "maya" + except ImportError: + pass + + raise Exception( + "This function can only be run in an active DCC session." + "Currently support are Houdini and Maya." + ) + def get_software(self): """Get the active software Returns: @@ -296,16 +331,22 @@ def get_software(self): product_name = "" product_version = "" product_python_version = "" - if os.environ.get("HFS"): - try: - import hou - - product_name = "houdini" - product_version = hou.applicationVersionString() - product_python_version = "-py{}{}".format(sys.version_info.major, - str(sys.version_info.minor)[:1]) - except ImportError: - pass + dcc_name = self.get_dcc_name() + if dcc_name == "houdini": + import hou + + product_name = "houdini" + product_version = hou.applicationVersionString() + product_python_version = "-py{}{}".format( + sys.version_info.major, str(sys.version_info.minor)[:1] + ) + elif dcc_name == "maya": + import pymel + + product_name = "maya" + product_version = pymel.versions.shortName + product_python_version = "" + return product_name, product_version, product_python_version def get_software_houdini_version_match(self, active_version, target_version): @@ -330,11 +371,28 @@ def get_software_houdini_version_match(self, active_version, target_version): # return False return True - def get_release_data(self, platform_name, product_name, product_version, product_python_version): + def get_software_maya_version_match(self, active_version, target_version): + """Check if the active version is compatible with the target version. + Currently this just assumes that major/minor release versions use are USD API/ABI compatible. + Args: + active_version(str): The active software version string + target_version(str): The target software version string + Returns: + bool: The match state + """ + target_version = target_version.split(".")[0] + # Major version + if active_version != target_version: + return False + return True + + def get_release_data( + self, platform_name, product_name, product_version, product_python_version + ): """Get release data via GitHub API Args: - platform_name(str): The OS ('linux' or 'win64') - product_name(str): The software name ('houdini' or 'houdini-py3') + platform_name(str): The OS. + product_name(str): The software name ('houdini' or 'maya') product_version(str): The software version string. Only exact matches and major version matches are considered. product_python_version (str): The python version string in the form of '-py39', '-py37', etc. @@ -353,6 +411,11 @@ def get_release_data(self, platform_name, product_name, product_version, product except Exception: data = [] + dcc_vendor_platform_mapping = { + "houdini": {"windows": "win64", "macos": "macos", "linux": "linux"}, + "maya": {"windows": "Windows", "macos": "MacOS", "linux": "Linux"}, + } + # Extract relevant data filtered_data = {} for release in data: @@ -364,26 +427,41 @@ def get_release_data(self, platform_name, product_name, product_version, product if asset["content_type"] != "application/zip": continue asset_name = asset["name"] - asset_name_elements = RELEASE_ASSET_ELEMENTS_REGEX.match(asset_name) - if not asset_name_elements: - continue - ( - asset_product_name, - asset_product_python_version, - asset_product_version, - asset_platform, - ) = asset_name_elements.groups() - if asset_platform != platform_name: - continue - elif asset_product_name != product_name: + asset_product_python_version = "" + asset_product_sdk_version = "" + if product_name == "houdini": + asset_name_elements = HOUDINI_RELEASE_ASSET_ELEMENTS_REGEX.match(asset_name) + if not asset_name_elements: + continue + ( + asset_product_name, + asset_product_python_version, + asset_product_version, + asset_platform, + ) = asset_name_elements.groups() + elif product_name == "maya": + asset_name_elements = MAYA_RELEASE_ASSET_ELEMENTS_REGEX.match(asset_name) + if not asset_name_elements: + continue + ( + asset_product_name, + asset_product_version, + asset_product_sdk_version, + asset_platform, + ) = asset_name_elements.groups() + if asset_platform != dcc_vendor_platform_mapping[product_name][platform_name]: continue if product_name == "houdini": if not self.get_software_houdini_version_match( product_version, asset_product_version ): continue + elif product_name == "maya": + if not self.get_software_maya_version_match( + product_version, asset_product_version + ): + continue else: - # We currently only support Houdini continue asset_url = asset["browser_download_url"] # Since we don't track via metadata what resolvers are stored per release, @@ -400,8 +478,11 @@ def get_release_data(self, platform_name, product_name, product_version, product asset_file.write(asset_file_content.read()) # Inspect archive with zipfile.ZipFile(asset_file_path, "r") as asset_zip_file: + print(asset_file_path) resolvers = [] - for asset_zip_path in zipfile.Path(asset_zip_file).iterdir(): + for asset_zip_path in zipfile.Path( + asset_zip_file + ).iterdir(): resolvers.append(asset_zip_path.name) if not resolvers: resolvers = None @@ -409,15 +490,28 @@ def get_release_data(self, platform_name, product_name, product_version, product # Only collect the first possible match filtered_data.setdefault(release["name"], {}) filtered_data[release["name"]].setdefault(asset_product_version, {}) - filtered_data[release["name"]][asset_product_version][asset_product_python_version or "__default__"] = {"name": release["name"], "resolvers": resolvers, "url": asset_url, - "product_python_version": asset_product_python_version, "product_version": asset_product_version} - + filtered_data[release["name"]][asset_product_version][ + asset_product_python_version or "__default__" + ] = { + "name": release["name"], + "resolvers": resolvers, + "url": asset_url, + "product_python_version": asset_product_python_version, + "product_sdk_version": asset_product_sdk_version, + "product_version": asset_product_version, + } + # Prefer exact Python version matches over inferred matches latest_filtered_data = [] for release_name, release_product_versions in filtered_data.items(): - latest_release_product_version = release_product_versions[sorted(release_product_versions.keys(), reverse=True)[0]] + latest_release_product_version = release_product_versions[ + sorted(release_product_versions.keys(), reverse=True)[0] + ] latest_filtered_data.append( - latest_release_product_version.get(product_python_version, latest_release_product_version["__default__"]) + latest_release_product_version.get( + product_python_version, + latest_release_product_version["__default__"], + ) ) return latest_filtered_data @@ -459,7 +553,9 @@ def uncompress_file(self, file_path, compression_type="zip"): ) if not os.path.exists(dir_path): os.makedirs(dir_path) - with ZipFileWithPermissions(file_path, "r", zipfile.ZIP_DEFLATED) as archive: + with ZipFileWithPermissions( + file_path, "r", zipfile.ZIP_DEFLATED + ) as archive: archive.extractall(dir_path) os.remove(file_path) else: @@ -490,50 +586,55 @@ def install_release( directory_path(str): The directory to download the resolvers to resolver_name(str): The resolver name to initialize """ - - if product_name == "houdini": - download_file_path = self.download_file( - download_url, "{}.{}".format(directory_path, "zip") - ) - directory_path = self.uncompress_file(download_file_path) - resolver_dir_path = os.path.join(directory_path, resolver_name) - # Cleanup other resolvers - for dir_name in os.listdir(directory_path): - if dir_name != resolver_name: - shutil.rmtree(os.path.join(directory_path, dir_name)) - # Build launcher - env = { - "PXR_PLUGINPATH_NAME": os.path.join(resolver_dir_path, "resources"), - "PYTHONPATH": os.path.join(resolver_dir_path, "lib", "python"), - } - if resolver_name in ["PythonResolver", "CachedResolver"]: - env.update({ - "AR_ENV_SEARCH_PATHS": "{}{}{}".format("/change/this/path/to/shots", os.pathsep, "/change/this/path/to/assets"), + download_file_path = self.download_file( + download_url, "{}.{}".format(directory_path, "zip") + ) + directory_path = self.uncompress_file(download_file_path) + resolver_dir_path = os.path.join(directory_path, resolver_name) + # Cleanup other resolvers + for dir_name in os.listdir(directory_path): + if dir_name != resolver_name: + shutil.rmtree(os.path.join(directory_path, dir_name)) + # Build launcher + env = { + "PXR_PLUGINPATH_NAME": os.path.join(resolver_dir_path, "resources"), + "PYTHONPATH": os.path.join(resolver_dir_path, "lib", "python"), + } + if resolver_name in ["PythonResolver", "CachedResolver"]: + env.update( + { + "AR_ENV_SEARCH_PATHS": "{}{}{}".format( + "/change/this/path/to/shots", + os.pathsep, + "/change/this/path/to/assets", + ), "AR_ENV_SEARCH_REGEX_EXPRESSION": "(v\d\d\d)", - "AR_ENV_SEARCH_REGEX_FORMAT": "v000" - }) - - if platform_name == "linux": - env["LD_LIBRARY_PATH"] = os.path.join(resolver_dir_path, "lib") - launch_file_path = os.path.join(directory_path, "launch.sh") - with open(launch_file_path, "w") as launch_file: - lines = [] - lines.append("#!/bin/bash") - # Environment - lines.append("# Setup environment") - # UpdateManager + "AR_ENV_SEARCH_REGEX_FORMAT": "v000", + } + ) + + if platform_name == "linux": + env["LD_LIBRARY_PATH"] = os.path.join(resolver_dir_path, "lib") + launch_file_path = os.path.join(directory_path, "launch.sh") + with open(launch_file_path, "w") as launch_file: + lines = [] + lines.append("#!/bin/bash") + # Environment + lines.append("# Setup environment") + # UpdateManager + lines.append( + "export {}={}".format(ENV_USD_ASSET_RESOLVER, directory_path) + ) + # Debug + lines.append("export {}={}".format("TF_DEBUG", "AR_RESOLVER_INIT")) + # Env + for env_name, env_value in sorted(env.items(), key=lambda k: k[0]): lines.append( - "export {}={}".format(ENV_USD_ASSET_RESOLVER, directory_path) - ) - # Debug - lines.append("export {}={}".format("TF_DEBUG", "AR_RESOLVER_INIT")) - # Env - for env_name, env_value in sorted(env.items(), key=lambda k: k[0]): - lines.append( - "export {env_name}={env_value}{sep}${env_name}".format( - env_name=env_name, env_value=env_value, sep=os.pathsep - ) + "export {env_name}={env_value}{sep}${env_name}".format( + env_name=env_name, env_value=env_value, sep=os.pathsep ) + ) + if product_name == "houdini": # App lines.append("# Launch Houdini") lines.append( @@ -544,71 +645,77 @@ def install_release( # Command lines.append('houdini -foreground "$@"') launch_file.writelines(line + "\n" for line in lines) - # Make executable - os.chmod(launch_file_path, 0o0777) - elif platform_name == "win64": - env["PATH"] = os.path.join(resolver_dir_path, "lib") - launch_file_path = os.path.join(directory_path, "launch.bat") - with open(launch_file_path, "w") as launch_file: - lines = [] - # Environment - lines.append("REM Setup environment") - # UpdateManager + elif product_name == "maya": + # App + lines.append("# Launch Maya") + # Command + lines.append('{} "$@"'.format(os.path.join(os.environ["MAYA_LOCATION"], "bin", "maya"))) + launch_file.writelines(line + "\n" for line in lines) + # Make executable + os.chmod(launch_file_path, 0o0777) + elif platform_name == "windows": + env["PATH"] = os.path.join(resolver_dir_path, "lib") + launch_file_path = os.path.join(directory_path, "launch.bat") + with open(launch_file_path, "w") as launch_file: + lines = [] + # Environment + lines.append("REM Setup environment") + # UpdateManager + lines.append( + "set {}={}".format(ENV_USD_ASSET_RESOLVER, directory_path) + ) + # Debug + lines.append("set {}={}".format("TF_DEBUG", "AR_RESOLVER_INIT")) + # Env + for env_name, env_value in sorted(env.items(), key=lambda k: k[0]): lines.append( - "set {}={}".format(ENV_USD_ASSET_RESOLVER, directory_path) - ) - # Debug - lines.append("set {}={}".format("TF_DEBUG", "AR_RESOLVER_INIT")) - # Env - for env_name, env_value in sorted(env.items(), key=lambda k: k[0]): - lines.append( - "set {env_name}={env_value}{sep}%{env_name}%".format( - env_name=env_name, env_value=env_value, sep=os.pathsep - ) + "set {env_name}={env_value}{sep}%{env_name}%".format( + env_name=env_name, env_value=env_value, sep=os.pathsep ) - # App & command + ) + # App & command + if product_name == "houdini": lines.append("REM Launch Houdini") lines.append(os.path.join(os.environ["HFS"], "bin", "houdini")) launch_file.writelines(line + "\n" for line in lines) - # Make executable - os.chmod(launch_file_path, 0o0777) - else: - raise Exception( - "Platform {} is currently not supported!".format(platform_name) - ) - # # This currently doesn't work because packages are processed after startup (after USD is initialized) - # package_content = { "env" : [{ ENV_USD_ASSET_RESOLVER : directory_path}, - # { "PXR_PLUGINPATH_NAME" : os.path.join(resolver_dir_path, "resources")}, - # { "PYTHONPATH" : os.path.join(resolver_dir_path, "lib", "python")}, - # { "LD_LIBRARY_PATH" : os.path.join(resolver_dir_path, "lib")}, - # { "TF_DEBUG" : "AR_RESOLVER_INIT"}]} - # if platform_name == "win64": - # package_content["env"].append({"PATH": os.path.join(resolver_dir_path, "lib")}) - # hou_user_pref_dir_path = os.environ["HOUDINI_USER_PREF_DIR"] - # hou_packages_dir_path = os.path.join(hou_user_pref_dir_path, "packages") - # hou_package_file_path = os.path.join(hou_packages_dir_path, HOU_PACKAGE_FILE_NAME) - # # This doesn't work for language specific user folders - # # ToDo Find a platform agnostic way to do this - # # if platform_name == "win64": - # # hou_user_pref_dir_path = os.path.join(os.path.expanduser("~"), "Documents", - # # "houdini{}".format(".".join(product_version.split("."[:2])))) - # # hou_packages_dir_path = os.path.join(hou_user_pref_dir_path, "packages") - # # elif platform_name == "linux": - # # hou_user_pref_dir_path = os.path.join(os.path.expanduser("~"), - # # "houdini{}".format(".".join(product_version.split("."[:2])))) - # # hou_packages_dir_path = os.path.join(hou_user_pref_dir_path, "packages") - # # else: - # # raise Exception("Platform {} is currently not supported!".format(platform)) - # if not os.path.exists(hou_packages_dir_path): - # os.makedirs(hou_packages_dir_path) - # with open(hou_package_file_path, "w") as hou_package_file: - # json.dump(package_content, hou_package_file, indent=4) + elif product_name == "maya": + lines.append("REM Launch Maya") + lines.append(os.path.join(os.environ["MAYA_LOCATION"], "bin", "maya")) + launch_file.writelines(line + "\n" for line in lines) + # Make executable + os.chmod(launch_file_path, 0o0777) else: raise Exception( - "The application '{}' is currently not supported by the installer.".format( - product_name - ) + "Platform {} is currently not supported!".format(platform_name) ) + # Houdini Packages + # # This currently doesn't work because packages are processed after startup (after USD is initialized) + # package_content = { "env" : [{ ENV_USD_ASSET_RESOLVER : directory_path}, + # { "PXR_PLUGINPATH_NAME" : os.path.join(resolver_dir_path, "resources")}, + # { "PYTHONPATH" : os.path.join(resolver_dir_path, "lib", "python")}, + # { "LD_LIBRARY_PATH" : os.path.join(resolver_dir_path, "lib")}, + # { "TF_DEBUG" : "AR_RESOLVER_INIT"}]} + # if platform_name == "win64": + # package_content["env"].append({"PATH": os.path.join(resolver_dir_path, "lib")}) + # hou_user_pref_dir_path = os.environ["HOUDINI_USER_PREF_DIR"] + # hou_packages_dir_path = os.path.join(hou_user_pref_dir_path, "packages") + # hou_package_file_path = os.path.join(hou_packages_dir_path, HOUDINI_PACKAGE_FILE_NAME) + # # This doesn't work for language specific user folders + # # ToDo Find a platform agnostic way to do this + # # if platform_name == "win64": + # # hou_user_pref_dir_path = os.path.join(os.path.expanduser("~"), "Documents", + # # "houdini{}".format(".".join(product_version.split("."[:2])))) + # # hou_packages_dir_path = os.path.join(hou_user_pref_dir_path, "packages") + # # elif platform_name == "linux": + # # hou_user_pref_dir_path = os.path.join(os.path.expanduser("~"), + # # "houdini{}".format(".".join(product_version.split("."[:2])))) + # # hou_packages_dir_path = os.path.join(hou_user_pref_dir_path, "packages") + # # else: + # # raise Exception("Platform {} is currently not supported!".format(platform)) + # if not os.path.exists(hou_packages_dir_path): + # os.makedirs(hou_packages_dir_path) + # with open(hou_package_file_path, "w") as hou_package_file: + # json.dump(package_content, hou_package_file, indent=4) # This protects against running the updated multiple times in the same session. os.environ[ENV_USD_ASSET_RESOLVER] = directory_path @@ -622,15 +729,8 @@ def release_uninstall(self, directory_path): del os.environ[ENV_USD_ASSET_RESOLVER] -def run_houdini(): - """Run the Update Manager in Houdini""" - try: - import hou - - if not hou.isUIAvailable(): - raise ImportError - except ImportError: - raise Exception("This function can only be run in an active Houdini session.") +def run_dcc(): + """Run the Update Manager in a DCC""" - dialog = UpdateManagerUI(hou.ui.mainQtWindow()) - dialog.exec_() \ No newline at end of file + dialog = UpdateManagerUI() + dialog.exec_()