diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml
index 3dec64eab..c7d876475 100644
--- a/.github/workflows/build-linux.yml
+++ b/.github/workflows/build-linux.yml
@@ -5,12 +5,17 @@ on:
branches: [main]
pull_request:
branches: [main]
+ paths:
+ - '.github/workflows/build-linux.yml'
jobs:
build-linux:
runs-on: ubuntu-24.04
+ timeout-minutes: 60
steps:
+ - uses: actions/checkout@v4
+
- name: Build Linux
shell: bash
run: ./build.sh --rebuild --release
diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml
index b85112a72..21d01dcef 100644
--- a/.github/workflows/build-windows.yml
+++ b/.github/workflows/build-windows.yml
@@ -5,14 +5,19 @@ on:
branches: [main]
pull_request:
branches: [main]
+ paths:
+ - '.github/workflows/build-windows.yml'
jobs:
build-windows:
runs-on: windows-2022
+ timeout-minutes: 60
- steps:
+ steps:
+ - uses: actions/checkout@v4
+
- name: Build Windows
shell: powershell
run: |
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
- . .\build.bat --rebuild --release
+ .\build.bat --rebuild --release
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cd7afd0ee..0562998ec 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Created 1.0.0 build
- Added release notes for 1.0.0
+- Added tests for REST API endpoints
+- REMIX-3891: Added Material Property Widget control with Stage Manager Materials Tab
### Changed
- Improved the documentation layout and contents
@@ -19,8 +21,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Fixed tests for the `omni.flux.validator.mass.widget` extension
- Fixed `get_texture_material_inputs` API endpoint for Kit 106.5
+- Fixed `is_valid_texture_prim` API validator for Kit 106.5
+- Redirect documentation pages that were moved to avoid 404 errors
+- REMIX-3869: Made extension lowercase for texture validation
+- Fixed Quick Start Guide link on the home page
+- REMIX-3900: Added ImageWithProvider to better display single channel textures
+- REMIX-3581: Fix multi-selection visibility toggle to have consistent behavior
+- REMIX-4043: Fixed layer creation transferring metadata from parent layer
+- REMIX-4073: Fixed Material Property Widget saving overrides onto instances instead of meshes
+- Fixed Toolkit Build Dependencies to allow building externally
### Removed
+- Cleaned up legacy code and unused files
## [1.0.0]
diff --git a/auto_update_extension_deps.bat b/auto_update_extension_deps.bat
deleted file mode 100644
index 47a143ea0..000000000
--- a/auto_update_extension_deps.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-call "%~dp0repo" auto_update_deps %*
diff --git a/auto_update_extension_deps.sh b/auto_update_extension_deps.sh
deleted file mode 100644
index 64aa915c8..000000000
--- a/auto_update_extension_deps.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-set -e
-SCRIPT_DIR=$(dirname ${BASH_SOURCE})
-source "$SCRIPT_DIR/repo.sh" auto_update_deps $@ || exit $?
diff --git a/deps/host-deps.packman.xml b/deps/host-deps.packman.xml
index 9505df174..c20f808e5 100644
--- a/deps/host-deps.packman.xml
+++ b/deps/host-deps.packman.xml
@@ -2,15 +2,4 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/howto/learning-packaging.md b/docs/howto/learning-packaging.md
index f701a166f..8f90ca12f 100644
--- a/docs/howto/learning-packaging.md
+++ b/docs/howto/learning-packaging.md
@@ -8,6 +8,8 @@ If any references are missing, you'll see a dialog prompting you to fix the unre
See the [Fixing Unresolved Assets section](../toolkitinterface/remix-toolkitinterface-layouttab.md#fixing-unresolved-assets) for more information on the dialog in question.
```
+
+
Once packaging is complete, click the "Open in Explorer" button to see your packaged mod directory.
You can easily zip up this directory, and it'll be ready for uploading and sharing.
diff --git a/docs/remix-overview.md b/docs/remix-overview.md
index bc7d6c702..ac96d03c7 100644
--- a/docs/remix-overview.md
+++ b/docs/remix-overview.md
@@ -33,15 +33,15 @@ Finally, using the RTX Remix Toolkit, you are able to easily make and add new ga
## Technical Requirements
-RTX Remix and its mods are built to run on RTX-powered machines. For ideal performance, we recommend using GeForce RTX™ 4070 or higher. For latest drivers, visit [NVIDIA Driver Downloads](https://www.nvidia.com/Download/index.aspx)s. For Quadro, select 'Quadro New Feature Driver (QNF).
+RTX Remix and its mods are built to run on RTX-powered machines. For ideal performance, we recommend using GeForce RTX™ 4070 or higher. For latest drivers, visit [NVIDIA Driver Downloads](https://www.nvidia.com/Download/index.aspx). For Quadro, select 'Quadro New Feature Driver (QNF).
-| Level | Operating System | CPU | CPU Cores | RAM | GPU | VRAM | Disk |
-| :------------------: | :---------------: | :-------------------: | :-------: | :-----: | :----------------: | :---: |:-------------:|
-| Min | Windows 10/11 | Intel I7 or AMD Ryzen 7 | 4 | 16 GB | GeForce RTX 3060Ti | 8 GB | 10 GB SSD |
-| Rec | Windows 10/11 | Intel I7 or AMD Ryzen 7 | 8 | 32 GB | GeForce RTX 4070 | 12 GB | 10 GB M.2 SSD |
+| Level | Operating System | CPU | RAM | GPU | VRAM | Disk |
+|:---------------:|:----------------:|:-----------------------------------:|:-----:|:----------------:|:-----:|:--------------:|
+| **Minimum** | Windows 10 | N/A | N/A | Any RTX GPU | N/A | 10 GB SSD |
+| **Recommended** | Windows 11 | Intel i7 13700K / AMD Ryzen 7 7700X | 32 GB | GeForce RTX 4070 | 12 GB | 10 GB NVME SSD |
-Since the RTX Remix Application is built using the Omniverse Kit SDK, We recommend that you review the [Omniverse Technical Requirement Documentation](https://docs.omniverse.nvidia.com/materials-and-rendering/latest/common/technical-requirements.html) for further details on what is required to use Applications within the Omniverse Platform.
+Since the RTX Remix Toolkit is built using the Omniverse Kit SDK, We recommend that you review the [Omniverse Technical Requirement Documentation](https://docs.omniverse.nvidia.com/materials-and-rendering/latest/common/technical-requirements.html) for further details on what is required to use Applications within the Omniverse Platform.
## Requirements For Modders
diff --git a/docs_dev/REVIEW_CHECKLIST.md b/docs_dev/REVIEW_CHECKLIST.md
index d11ab43c9..eb33ae528 100644
--- a/docs_dev/REVIEW_CHECKLIST.md
+++ b/docs_dev/REVIEW_CHECKLIST.md
@@ -22,7 +22,6 @@ Before submitting your code for review, please ensure you have thoroughly evalua
5. **Version Bumping and Dependency Updates**:
- Always bump the version of any extensions you modify.
- - After updating the extensions, run `./auto_update_extension_deps.bat` to update the kit files accordingly.
- Add an entry to the `changelog.md` files for all modified extensions, as well as the central `CHANGELOG.md` file
in the root of the repository, to describe the changes that were made.
@@ -43,8 +42,7 @@ Before submitting your code for review, please ensure you have thoroughly evalua
purpose and usage. The documentation for the code will be generated from these docstrings.
- **Version Bumping and Dependency Updates**: Incrementing the version of modified extensions ensures that changes are
- tracked and managed properly. Running `./auto_update_extension_deps.bat` updates the kit files to reflect these
- changes, maintaining consistency across the project. Additionally, updating the `changelog.md` files for all modified
+ tracked and managed properly. Additionally, updating the `changelog.md` files for all modified
extensions and the central `CHANGELOG.md` file in the repository provides a clear record of the changes made.
## Examples
@@ -112,10 +110,7 @@ Maintain version control and update dependencies to ensure consistency:
1. **Bump Extension Versions**: Always increment the version of any extensions you modify. This practice helps in
tracking changes and managing updates effectively.
-2. **Update Kit Files**: After making changes to the extensions, run `./auto_update_extension_deps.bat` to update the
- kit files accordingly. This step ensures that all dependencies are accurately reflected in the project.
-
-3. **Update Changelog**: Add an entry to the `changelog.md` files for all modified extensions, as well as the
+2. **Update Changelog**: Add an entry to the `changelog.md` files for all modified extensions, as well as the
central `CHANGELOG.md` file in the root of the repository, to describe the changes that were made.
## Conclusion
diff --git a/repo.toml b/repo.toml
index 7c9356b46..06bb04e72 100644
--- a/repo.toml
+++ b/repo.toml
@@ -6,8 +6,13 @@
logging = "warn"
# Use Kit Template repo configuration as a base. Only override things specific to the repo.
-import_configs = ["${root}/_repo/deps/repo_kit_tools/kit-template/repo.toml", "${root}/repo_public.toml"]
-import_optional_configs = ["${root}/repo_internal.toml"]
+import_configs = [
+ "${root}/_repo/deps/repo_kit_tools/kit-template/repo.toml",
+ "${root}/repo_public.toml"
+]
+import_optional_configs = [
+ "${root}/repo_internal.toml"
+]
# Reposiory Name. It is used for solution name and final package name
name = "rtx_remix"
@@ -341,17 +346,19 @@ release.files_exclude = [
#######################################################################################################################
[repo_build]
+# Build is disabled but pre-build commands are still executed
pre_build.commands = [
+ # Pull install-time dependencies
["${root}/_build/${platform}/${config}/pull_dependencies${shell_ext}"],
-]
-# Multiple commands (processes) can be executed in order after build.
-# These have the same behavior as repo_build.pre_build.commands, except that they run after the build.
-post_build.commands = [
+ # Generate the stubgen config file
["${root}/repo${shell_ext}", "stubgen", "-c", "${config}"],
- # Generate a shortcut to run the Mass Ingestion CLI in LSS
- ["${root}/_build/${platform}/${config}/kit/kit${exe_ext}", "${root}/_build/${platform}/${config}/apps/lightspeed.app.trex.validation_cli_generator.kit", "--no-window", "--/app/extensions/excluded/0='omni.kit.splash' --/app/extensions/excluded/1='omni.kit.window.splash' --/app/settings/persistent=0 --/app/settings/loadUserConfig=0 --/structuredLog/enable=0 --/app/hangDetector/enabled=0 --/crashreporter/skipOldDumpUpload=1 --/app/content/emptyStageOnStart=1", "--/app/file/ignoreUnsavedOnExit=1", "--/app/fastShutdown=1", "--/app/quitAfter=10", "--exec", "${root}/tools/custom/generate_mass_cli.py"],
- ["${root}/_build/${platform}/${config}/kit/kit${exe_ext}", "${root}/_build/${platform}/${config}/apps/omni.flux.app.service.documentation_cli_generator.kit", "--no-window", "--exec", "${root}/tools/custom/generate_app.py -id omni.flux.service.documentation -n omni.flux.app.service.documentation.cli"],
+# TODO: rewrite without extension manager dependency running in app. Should be able to pass root path to tool.
+# # Generate a shortcut to run the Mass Ingestion CLI in LSS
+# ["${root}/_build/${platform}/${config}/kit/kit${exe_ext}", "${root}/_build/${platform}/${config}/apps/lightspeed.app.trex.validation_cli_generator.kit", "--no-window", "--/app/extensions/excluded/0='omni.kit.splash' --/app/extensions/excluded/1='omni.kit.window.splash' --/app/settings/persistent=0 --/app/settings/loadUserConfig=0 --/structuredLog/enable=0 --/app/hangDetector/enabled=0 --/crashreporter/skipOldDumpUpload=1 --/app/content/emptyStageOnStart=1", "--/app/file/ignoreUnsavedOnExit=1", "--/app/fastShutdown=1", "--/app/quitAfter=10", "--exec", "${root}/tools/custom/generate_mass_cli.py"],
+# TODO: Need to figure out how to skip for github builds
+# # Generate the service documentation
+# ["${root}/_build/${platform}/${config}/kit/kit${exe_ext}", "${root}/_build/${platform}/${config}/apps/omni.flux.app.service.documentation_cli_generator.kit", "--no-window", "--exec", "${root}/tools/custom/generate_app.py -id omni.flux.service.documentation -n omni.flux.app.service.documentation.cli"],
]
copy = [
@@ -367,10 +374,12 @@ files_to_pull = [
"${root}/deps/pip_internal.toml",
]
+[repo_build.build]
+enabled = false
+
+# Disable linbuild until we have a public image available.
[repo_build.docker]
-# Linbuild against Ubuntu 22 CI Builder images
-"platform:linux-x86_64".image_url = "urm.nvidia.com/ct-omniverse-docker/ci-jammy-x86_64-builder:1.0.6-97c67f00"
-"platform:linux-aarch64".image_url = "urm.nvidia.com/ct-omniverse-docker/ci-jammy-aarch64-builder:1.0.6-97c67f00"
+enabled = false
[repo_stubgen]
exts_exclude = [
@@ -523,35 +532,12 @@ autodoc_mock_imports = [
sphinx_exclude_patterns = [
####################################################################################################################
# Documentation generation failures
- # Undocumented errors are: WARNING: document isn't included in any toctree
####################################################################################################################
- "source/extensions/lightspeed.asset_capture_localizer.*",
- "source/extensions/lightspeed.color_to_normal.*",
- "source/extensions/lightspeed.color_to_roughness.*",
- "source/extensions/lightspeed.common*",
- "source/extensions/lightspeed.error_popup.*",
- "source/extensions/lightspeed.event.*",
- "source/extensions/lightspeed.events_manager*",
- "source/extensions/lightspeed.export*",
- "source/extensions/lightspeed.layer_helpers*",
- "source/extensions/lightspeed.layer_manager*",
- "source/extensions/lightspeed.light.gizmos*",
- "source/extensions/lightspeed.lock_xform*",
- "source/extensions/lightspeed.paths_to_relative.*",
- "source/extensions/lightspeed.pip_archive*",
- "source/extensions/lightspeed.property_template*",
- "source/extensions/lightspeed.stage_column_nickname*",
- "source/extensions/lightspeed.tool.material.*",
- "source/extensions/lightspeed.tool.octahedral_converter*",
- "source/extensions/lightspeed.trex.layout.*",
- "source/extensions/lightspeed.trex.stage_manager.plugin.widget.usd*", # Excluded to avoid viewports import doc build failure
- "source/extensions/lightspeed.trex.viewports.shared.*", # Kit is Executing extension-logic at the module-level which crashes docs generation
- "source/extensions/lightspeed.upscale.*",
- "source/extensions/lightspeed.widget.content_viewer*",
- "source/extensions/lightspeed.widget.game_captures*",
- "source/extensions/lightspeed.widget.new_game*",
- "source/extensions/lightspeed.widget.new_workspace*",
- "source/extensions/lightspeed.workspace*",
+ "source/extensions/lightspeed.event.waypoint_game_camera*", # Carb interface is not available
+ "source/extensions/lightspeed.event.generate_thumbnail*", # Carb interface is not available
+ "source/extensions/lightspeed.trex.layout.*", # Carb interface is not available
+ "source/extensions/lightspeed.trex.stage_manager.plugin.widget.usd*", # Carb interface is not available
+ "source/extensions/lightspeed.trex.viewports.shared.*", # Carb interface is not available
####################################################################################################################
# Ignore directories
####################################################################################################################
@@ -563,9 +549,6 @@ sphinx_exclude_patterns = [
"tools",
"SECURITY.md",
"VERSION.md",
- "source/extensions/lightspeed_example*",
- "source/extensions/lightspeed.common/**/tools/*", # 3rd part tools documentation
- "source/extensions/lightspeed.widget.content_viewer/**/jxnblk-LICENSE.md", # 3rd part tools documentation
"**/omni-core-materials-LICENSE.md",
####################################################################################################################
# Development READMEs
@@ -576,7 +559,11 @@ sphinx_exclude_patterns = [
]
redirects = [
- { path = "docs/remix-releasenote.html", target = "docs/remix-releasenotes.html" }
+ { path = "docs/remix-releasenote.html", target = "docs/remix-releasenotes.html" },
+ { path = "docs/howto/learning-runtimesetup.html", target = "docs/gettingstarted/learning-runtimesetup.html" },
+ { path = "docs/howto/tutorial-remixtool.html", target = "docs/tutorials/tutorial-remixtool.html" },
+ { path = "docs/howto/learning-viewport.html", target = "docs/toolkitinterface/remix-toolkitinterface-viewport.html" },
+ { path = "docs/howto/tutorial-portalhl2.html", target = "docs/tutorials/tutorial-portalhl2.html" },
]
repo_url = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/blob/master"
diff --git a/source/apps/exts.deps.generated.kit b/source/apps/exts.deps.generated.kit
index 787cabe2c..8babafa55 100644
--- a/source/apps/exts.deps.generated.kit
+++ b/source/apps/exts.deps.generated.kit
@@ -18,13 +18,6 @@
# All local extensions built in this repo:
[dependencies]
-"lightspeed.asset_capture_localizer.core" = {}
-"lightspeed.asset_capture_localizer.menu" = {}
-"lightspeed.asset_capture_localizer.window" = {}
-"lightspeed.color_to_normal.core" = {}
-"lightspeed.color_to_normal.menu" = {}
-"lightspeed.color_to_roughness.core" = {}
-"lightspeed.color_to_roughness.menu" = {}
"lightspeed.common" = {}
"lightspeed.dependencies" = {}
"lightspeed.error_popup.window" = {}
@@ -45,22 +38,15 @@
"lightspeed.events_manager" = {}
"lightspeed.hydra.remix.bootstrap" = {}
"lightspeed.hydra.remix.core" = {}
-"lightspeed.layer_helpers" = {}
"lightspeed.layer_manager.core" = {}
"lightspeed.layer_manager.service" = {}
"lightspeed.light.gizmos" = {}
-"lightspeed.lock_xform" = {}
-"lightspeed.paths_to_relative.core" = {}
-"lightspeed.paths_to_relative.menu" = {}
-"lightspeed.paths_to_relative.window" = {}
"lightspeed.pip_archive" = {}
"lightspeed.progress_popup.window" = {}
"lightspeed.project_manager.service" = {}
"lightspeed.sentry_manager.core" = {}
"lightspeed.sentry_manager.event" = {}
-"lightspeed.stage_column_nickname" = {}
"lightspeed.tool.material.core" = {}
-"lightspeed.tool.material.widget" = {}
"lightspeed.tool.octahedral_converter" = {}
"lightspeed.trex.app.resources" = {}
"lightspeed.trex.app.setup" = {}
@@ -109,6 +95,7 @@
"lightspeed.trex.properties_pane.shared.mod_setup.widget" = {}
"lightspeed.trex.properties_pane.shared.render.widget" = {}
"lightspeed.trex.properties_pane.stagecraft.widget" = {}
+"lightspeed.trex.recent_projects.core" = {}
"lightspeed.trex.replacement.core.shared" = {}
"lightspeed.trex.selection_tree.shared.widget" = {}
"lightspeed.trex.service.core" = {}
@@ -137,21 +124,6 @@
"lightspeed.trex.viewports.stagecraft.bundle" = {}
"lightspeed.trex.waypoint.core" = {}
"lightspeed.ui_scene.light_manipulator" = {}
-"lightspeed.upscale.content_browser.menu" = {}
-"lightspeed.upscale.core" = {}
-"lightspeed.upscale.menu" = {}
-"lightspeed.widget.content_viewer" = {}
-"lightspeed.widget.game_captures" = {}
-"lightspeed.widget.new_game" = {}
-"lightspeed.widget.new_workspace" = {}
-"lightspeed.workspace" = {}
-"lightspeed_example.app.resources" = {}
-"lightspeed_example.my_name.controller" = {}
-"lightspeed_example.my_name.core" = {}
-"lightspeed_example.my_name.menu" = {}
-"lightspeed_example.my_name.widget" = {}
-"lightspeed_example.my_name.window" = {}
-"lightspeed_example.style" = {}
"omni.flux.asset_importer.core" = {}
"omni.flux.asset_importer.widget" = {}
"omni.flux.bookmark_tree.model.usd" = {}
@@ -234,8 +206,6 @@
"omni.flux.wizard.window" = {}
-
-
########################################################################################################################
# BEGIN GENERATED PART (Remove from 'BEGIN' to 'END' to regenerate)
########################################################################################################################
diff --git a/source/apps/lightspeed.app.trex.stagecraft.kit b/source/apps/lightspeed.app.trex.stagecraft.kit
index 713441337..2b3c87318 100644
--- a/source/apps/lightspeed.app.trex.stagecraft.kit
+++ b/source/apps/lightspeed.app.trex.stagecraft.kit
@@ -66,6 +66,9 @@ context = ""
[settings.exts."lightspeed.event.save_global_muteness"]
context = ""
+[settings.exts."lightspeed.event.save_recent"]
+context = ""
+
[settings.exts."lightspeed.event.save_root_mod"]
context = ""
diff --git a/source/extensions/lightspeed.asset_capture_localizer.core/config/extension.toml b/source/extensions/lightspeed.asset_capture_localizer.core/config/extension.toml
deleted file mode 100644
index 72f193c2e..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.core/config/extension.toml
+++ /dev/null
@@ -1,44 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.4"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Damien Bataille "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Lightspeed Asset Capture Localize Core"
-description="Lightspeed Utils to localize in what capture an asset is"
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.paths_to_relative.core"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["kit", "path", "asset", "localize", "capture"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
-icon = "data/icon.png"
-
-[dependencies]
-"lightspeed.common" = {}
-"lightspeed.layer_manager.core" = {}
-"omni.client" = {}
-"omni.flux.utils.common" = {}
-"omni.usd" = {}
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.asset_capture_localizer.core"
diff --git a/source/extensions/lightspeed.asset_capture_localizer.core/data/icon.png b/source/extensions/lightspeed.asset_capture_localizer.core/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.core/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.asset_capture_localizer.core/docs/CHANGELOG.md b/source/extensions/lightspeed.asset_capture_localizer.core/docs/CHANGELOG.md
deleted file mode 100644
index 3ca6c85bd..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.core/docs/CHANGELOG.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.4]
-### Changed
-- Changed repo link
-
-## [0.1.3]
-- Use updated `lightspeed.layer_manager.core` extension
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.1] - 2022-04-18
-### Changed
-- Moved python dependencies to lightspeed common
-### Fixed
-- Normalized Pixels
-
-## [0.1.0] - 2022-04-15
-### Added
-- Created
diff --git a/source/extensions/lightspeed.asset_capture_localizer.core/docs/README.md b/source/extensions/lightspeed.asset_capture_localizer.core/docs/README.md
deleted file mode 100644
index 23d9c80fe..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.core/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.asset_capture_localizer.core
diff --git a/source/extensions/lightspeed.asset_capture_localizer.core/docs/index.rst b/source/extensions/lightspeed.asset_capture_localizer.core/docs/index.rst
deleted file mode 100644
index 9e8980c64..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.core/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.asset_capture_localizer.core
-########################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.asset_capture_localizer.core
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.asset_capture_localizer.core/lightspeed/asset_capture_localizer/core/core.py b/source/extensions/lightspeed.asset_capture_localizer.core/lightspeed/asset_capture_localizer/core/core.py
deleted file mode 100644
index c4366ee1d..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.core/lightspeed/asset_capture_localizer/core/core.py
+++ /dev/null
@@ -1,99 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import glob
-import os
-import re
-from typing import List, Tuple
-
-import omni.usd
-from lightspeed.common.constants import CAPTURE_FILE_PREFIX, INSTANCE_PATH, MESHES_FILE_PREFIX
-from lightspeed.layer_manager.core import LayerManagerCore, LayerType
-from omni.flux.utils.common import reset_default_attrs as _reset_default_attrs
-from pxr import Sdf, Usd
-
-
-class AssetCaptureLocalizerCore:
- def __init__(self, context: omni.usd.UsdContext):
- self.default_attr = {}
- for attr, value in self.default_attr.items():
- setattr(self, attr, value)
-
- self._context = context
- self._layer_manager = LayerManagerCore()
-
- def __traverse_instanced_children(self, prim):
- for child in prim.GetFilteredChildren(Usd.PrimAllPrimsPredicate):
- yield child
- yield from self.__traverse_instanced_children(child)
-
- def get_capture_usd_files(self):
- layer = self._layer_manager.get_layer(LayerType.capture)
- capture_usd_files = []
- if layer:
- # we generate a list of hashes from the list of mesh usd files
- capture_folder = os.path.dirname(layer.identifier)
- for capture_usd in glob.glob(os.path.join(capture_folder, "*.usd")):
- match = re.match(f"^{CAPTURE_FILE_PREFIX}(.*).usd$", os.path.basename(capture_usd))
- if match:
- capture_usd_files.append(capture_usd)
- return capture_usd_files
-
- def get_capture_mesh_dict(self):
- capture_files = self.get_capture_usd_files()
- result = {}
- for layer_path in capture_files:
- sub_stage = Usd.Stage.Open(layer_path)
- all_prims = list(self.__traverse_instanced_children(sub_stage.GetPseudoRoot()))
- if not all_prims:
- continue
- for prim in all_prims:
- result[prim.GetName()] = layer_path
- return result
-
- def get_all_user_references(self) -> List[Tuple[Usd.Prim, Sdf.Reference, Sdf.Layer, str]]:
- stage = self._context.get_stage()
- result = []
- all_prims = list(self.__traverse_instanced_children(stage.GetPseudoRoot()))
- if not all_prims:
- return []
- capture_prims_dict = self.get_capture_mesh_dict()
- regex_pattern = re.compile("^.*\/([a-zA-Z]+)_([A-Z0-9]{16})(_[0-9]+)*$") # noqa
- for prim in all_prims:
- if not regex_pattern.match(prim.GetPath().pathString):
- continue
- if INSTANCE_PATH in prim.GetPath().pathString:
- continue
- refs_and_layers = omni.usd.get_composed_references_from_prim(prim)
- capture_layer_path = "Not found"
- if refs_and_layers:
- for ref, layer in refs_and_layers:
- if ref.assetPath:
- match = re.match(f"^{MESHES_FILE_PREFIX}(.*).usd$", os.path.basename(ref.assetPath))
- if match:
- continue
- if capture_prims_dict.get(prim.GetName()):
- capture_layer_path = capture_prims_dict[prim.GetName()]
- result.append((prim, ref, layer, capture_layer_path))
- else:
- if capture_prims_dict.get(prim.GetName()):
- capture_layer_path = capture_prims_dict[prim.GetName()]
- result.append((prim, None, None, capture_layer_path))
- return result
-
- def destroy(self):
- _reset_default_attrs(self)
diff --git a/source/extensions/lightspeed.asset_capture_localizer.menu/config/extension.toml b/source/extensions/lightspeed.asset_capture_localizer.menu/config/extension.toml
deleted file mode 100644
index 2ede94eda..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.menu/config/extension.toml
+++ /dev/null
@@ -1,42 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.3"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Damien Bataille "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Lightspeed Asset Capture Localize Menu"
-description="Lightspeed Utils to localize in what capture an asset is"
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.paths_to_relative.core"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["kit", "path", "asset", "localize", "capture"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
-icon = "data/icon.png"
-
-[dependencies]
-"lightspeed.asset_capture_localizer.window" = {}
-"omni.kit.menu.utils" = {}
-"omni.usd" = {}
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.asset_capture_localizer.menu"
diff --git a/source/extensions/lightspeed.asset_capture_localizer.menu/data/icon.png b/source/extensions/lightspeed.asset_capture_localizer.menu/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.menu/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.asset_capture_localizer.menu/data/preview.png b/source/extensions/lightspeed.asset_capture_localizer.menu/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.menu/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.asset_capture_localizer.menu/docs/CHANGELOG.md b/source/extensions/lightspeed.asset_capture_localizer.menu/docs/CHANGELOG.md
deleted file mode 100644
index 05aa1d005..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.menu/docs/CHANGELOG.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.3]
-### Changed
-- Changed repo link
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-07-28
-### Added
-- Created
diff --git a/source/extensions/lightspeed.asset_capture_localizer.menu/docs/README.md b/source/extensions/lightspeed.asset_capture_localizer.menu/docs/README.md
deleted file mode 100644
index 54db2f3e8..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.menu/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.asset_capture_localizer.menu
diff --git a/source/extensions/lightspeed.asset_capture_localizer.menu/docs/index.rst b/source/extensions/lightspeed.asset_capture_localizer.menu/docs/index.rst
deleted file mode 100644
index 6f1b7a801..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.menu/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.asset_capture_localizer.menu
-########################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.asset_capture_localizer.menu
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.asset_capture_localizer.menu/lightspeed/asset_capture_localizer/menu/menu.py b/source/extensions/lightspeed.asset_capture_localizer.menu/lightspeed/asset_capture_localizer/menu/menu.py
deleted file mode 100644
index eb0148132..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.menu/lightspeed/asset_capture_localizer/menu/menu.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-
-import omni.ext
-import omni.kit.menu.utils as omni_utils
-import omni.usd
-from lightspeed.asset_capture_localizer.window import get_instance
-from omni.kit.menu.utils import MenuItemDescription
-
-
-class AssetCaptureLocalizerMenuExtension(omni.ext.IExt):
- def on_startup(self, ext_id):
- self.__create_save_menu()
-
- def __create_save_menu(self):
- self._tools_manager_menus = [
- MenuItemDescription(
- name="Toggle asset capture localizer window",
- onclick_fn=self.__clicked,
- glyph="none.svg",
- )
- ]
- omni_utils.add_menu_items(self._tools_manager_menus, "Utils")
-
- def on_shutdown(self):
- omni_utils.remove_menu_items(self._tools_manager_menus, "Utils")
-
- @omni.usd.handle_exception
- async def _show(self):
- get_instance().toggle_window()
-
- def __clicked(self):
- asyncio.ensure_future(self._show())
diff --git a/source/extensions/lightspeed.asset_capture_localizer.menu/premake5.lua b/source/extensions/lightspeed.asset_capture_localizer.menu/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.menu/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/config/extension.toml b/source/extensions/lightspeed.asset_capture_localizer.window/config/extension.toml
deleted file mode 100644
index bdfc3735f..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.window/config/extension.toml
+++ /dev/null
@@ -1,43 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.3"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Damien Bataille "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Lightspeed Asset Capture Localize Window"
-description="Lightspeed Utils to localize in what capture an asset is"
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.paths_to_relative.core"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["kit", "path", "asset", "localize", "capture"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
-icon = "data/icon.png"
-
-[dependencies]
-"lightspeed.asset_capture_localizer.core" = {}
-"omni.flux.utils.common" = {}
-"omni.ui" = {}
-"omni.usd" = {}
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.asset_capture_localizer.window"
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/data/icon.png b/source/extensions/lightspeed.asset_capture_localizer.window/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.window/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/data/icons/cross.svg b/source/extensions/lightspeed.asset_capture_localizer.window/data/icons/cross.svg
deleted file mode 100644
index 7ea19885b..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.window/data/icons/cross.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:f98e6c7dd09daac9d54157983ddeac43dc02eefc963d9daf65e2f00326569111
-size 2463
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/data/icons/search.svg b/source/extensions/lightspeed.asset_capture_localizer.window/data/icons/search.svg
deleted file mode 100644
index 6148de409..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.window/data/icons/search.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:7afb7cb879d3e9d7b9a145a1df3fed9b81f52ef71bd101a40a4a191f2042f85e
-size 1982
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/data/preview.png b/source/extensions/lightspeed.asset_capture_localizer.window/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.window/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/docs/CHANGELOG.md b/source/extensions/lightspeed.asset_capture_localizer.window/docs/CHANGELOG.md
deleted file mode 100644
index 99a8881c6..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.window/docs/CHANGELOG.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.3]
-### Changed
-- Changed repo link
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.1] - 2022-04-18
-### Changed
-- Moved python dependencies to lightspeed common
-### Fixed
-- Normalized Pixels
-
-## [0.1.0] - 2022-04-15
-### Added
-- Created
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/docs/README.md b/source/extensions/lightspeed.asset_capture_localizer.window/docs/README.md
deleted file mode 100644
index 1790d2358..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.window/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.asset_capture_localizer.window
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/docs/index.rst b/source/extensions/lightspeed.asset_capture_localizer.window/docs/index.rst
deleted file mode 100644
index 3d6a3109b..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.window/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.asset_capture_localizer.window
-##########################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.asset_capture_localizer.window
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/extension.py b/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/extension.py
deleted file mode 100644
index bc3484a03..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/extension.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import carb
-import omni.ext
-from omni.flux.utils.common import reset_default_attrs as _reset_default_attrs
-
-from .setup_ui import AssetCaptureLocalizerWindow
-
-_INSTANCE = None
-
-
-def get_instance():
- """Expose the created instance of the tool"""
- return _INSTANCE
-
-
-class AssetCaptureLocalizerExtension(omni.ext.IExt):
- """Standard extension support class, necessary for extension management"""
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.default_attr = {}
- for attr, value in self.default_attr.items():
- setattr(self, attr, value)
-
- def on_startup(self, ext_id):
- global _INSTANCE
- carb.log_info("[lightspeed.asset_capture_localizer.window] startup")
- _INSTANCE = AssetCaptureLocalizerWindow()
-
- def on_shutdown(self):
- global _INSTANCE
- _reset_default_attrs(self)
- _INSTANCE.destroy()
- _INSTANCE = None
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/setup_ui.py b/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/setup_ui.py
deleted file mode 100644
index be78925d1..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/setup_ui.py
+++ /dev/null
@@ -1,129 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import os
-
-import omni.ui as ui
-from omni.flux.utils.common import reset_default_attrs as _reset_default_attrs
-
-from .tree import delegate, model
-
-_ICONS_DIR = os.path.dirname(__file__)
-for _ in range(3):
- _ICONS_DIR = os.path.dirname(_ICONS_DIR)
-
-_ICONS_DIR = os.path.join(_ICONS_DIR, "data", "icons")
-DICT_ICONS = {
- "search": os.path.join(_ICONS_DIR, "search.svg"),
- "cross": os.path.join(_ICONS_DIR, "cross.svg"),
-}
-
-
-class AssetCaptureLocalizerWindow:
- def __init__(self):
- self.__default_attr = {
- "_model": None,
- "_delegate": None,
- "_window": None,
- "_tree": None,
- "_action_search_attr": None,
- "_label_search": None,
- "_cross_image": None,
- "_label_no_item": None,
- }
- for attr, value in self.__default_attr.items():
- setattr(self, attr, value)
-
- self._delegate = delegate.Delegate()
- self._model = model.ListModel()
-
- self.__create_ui()
-
- def __create_ui(self):
- """Create the main UI"""
- window_name = "Asset capture localizer"
- self._window = ui.Window(window_name, name=window_name, width=1500, height=600, visible=False)
-
- with self._window.frame:
- with ui.VStack(spacing=8):
- with ui.HStack(height=22):
- ui.Spacer()
- with ui.ZStack(width=ui.Percent(25)):
- with ui.HStack():
- with ui.ZStack(width=20):
- ui.Rectangle(name="Search")
- ui.Image(str(DICT_ICONS["search"]), name="Search")
- with ui.ZStack():
- self._action_search_attr = ui.StringField()
- self._action_search_attr.model.add_value_changed_fn(lambda m: self._filter_content())
- with ui.HStack():
- ui.Spacer(width=8)
- self._label_search = ui.Label("Search", name="Search")
- with ui.ZStack(width=20):
- ui.Rectangle(name="Search")
- self._cross_image = ui.Image(
- str(DICT_ICONS["cross"]),
- name="Cross",
- mouse_pressed_fn=lambda x, y, b, m: self._on_search_cross_clicked(),
- visible=False,
- )
- ui.Spacer(width=24)
- self._label_no_item = ui.Label("No item found", visible=False, style={"color": 0xFF0000FF})
- ui.Spacer()
- with ui.ScrollingFrame(
- style_type_name_override="TreeView",
- ):
- self._tree = ui.TreeView(
- self._model,
- delegate=self._delegate,
- root_visible=False,
- header_visible=True,
- columns_resizable=True,
- column_widths=[ui.Percent(40), ui.Percent(20), ui.Percent(5), ui.Percent(35)],
- )
- ui.Button("Refresh", clicked_fn=self._on_refresh, height=24)
-
- def _filter_content(self):
- """Filter content by name"""
- filter_content_title_value = self._action_search_attr.model.as_string
- self._label_search.visible = not bool(filter_content_title_value)
- self._cross_image.visible = bool(filter_content_title_value)
- self._model.set_filter(filter_content_title_value)
- self._model.filter_items()
- self._show_no_item_label()
-
- def _show_no_item_label(self):
- items = self._model.get_item_children(None)
- self._label_no_item.visible = not bool(items)
-
- def _on_search_cross_clicked(self):
- """Called when the cross from the search box is clicked"""
- self._action_search_attr.model.set_value("")
- self._filter_content()
-
- def _on_refresh(self):
- self._model.refresh()
- self._show_no_item_label()
-
- def toggle_window(self):
- if self._window:
- self._window.visible = not self._window.visible
- if self._window.visible:
- self._on_refresh()
-
- def destroy(self):
- _reset_default_attrs(self)
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/tree/__init__.py b/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/tree/__init__.py
deleted file mode 100644
index 2a4b35b86..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/tree/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/tree/delegate.py b/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/tree/delegate.py
deleted file mode 100644
index 7e3c5153a..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/tree/delegate.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import omni.ui as ui
-
-from .model import HEADER_DICT
-
-
-class Delegate(ui.AbstractItemDelegate):
- """Delegate of the action lister"""
-
- def build_branch(self, model, item, column_id, level, expanded):
- """Create a branch widget that opens or closes subtree"""
- pass
-
- # noinspection PyUnusedLocal
- def build_widget(self, model, item, column_id, level, expanded):
- """Create a widget per item"""
- if item is None:
- return
- if column_id == 0:
- ui.Label(item.ref.assetPath if item.ref else "None")
- elif column_id == 1:
- ui.Label(item.prim.GetPath().pathString)
- elif column_id == 2:
- ui.Label(item.nickname)
- elif column_id == 3:
- ui.Label(item.capture_layer_path)
-
- def build_header(self, column_id):
- """Build the header"""
- style_type_name = "TreeView.Header"
- with ui.HStack():
- ui.Label(HEADER_DICT[column_id], style_type_name_override=style_type_name)
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/tree/model.py b/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/tree/model.py
deleted file mode 100644
index 3099e616f..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/tree/model.py
+++ /dev/null
@@ -1,128 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import omni.ui as ui
-import omni.usd
-from lightspeed.asset_capture_localizer.core import AssetCaptureLocalizerCore
-from omni.flux.utils.common import reset_default_attrs as _reset_default_attrs
-
-HEADER_DICT = {0: "Reference path", 1: "Mesh name", 2: "Nickname", 3: "Capture layer path"}
-
-
-def _get_nickname(prim):
- if prim.HasAttribute("nickname"):
- return prim.GetAttribute("nickname").Get()
- return ""
-
-
-class Item(ui.AbstractItem):
- """Item of the model"""
-
- def __init__(self, prim, ref, layer, capture_layer_path):
- super().__init__()
- self.prim = prim
- self.ref = ref
- self.layer = layer
- self.capture_layer_path = capture_layer_path
- self.ref_asset_path_model = ui.SimpleStringModel(self.ref.assetPath if self.ref else "None")
- self._nickname = None
-
- @property
- def nickname(self) -> str:
- return _get_nickname(self.prim)
-
- def __repr__(self):
- return f'"{self.ref.assetPath}"'
-
-
-class ListModel(ui.AbstractItemModel):
- """List model of actions"""
-
- def __init__(self):
- super().__init__()
- self.default_attr = {"_core": None}
- for attr, value in self.default_attr.items():
- setattr(self, attr, value)
- self._context = omni.usd.get_context()
- self._filter = None
- self._core = AssetCaptureLocalizerCore(self._context)
- self.__children = []
- self.__children_unfiltered = []
-
- def get_stage_selection(self):
- return self._context.get_selection().get_selected_prim_paths()
-
- def refresh(self):
- """Refresh the list"""
- items = []
- user_references = self._core.get_all_user_references()
- for prim, ref, layer, capture_layer_path in user_references:
- if (
- self._filter
- and self._filter.lower() not in prim.GetPath().pathString.lower()
- and ((ref and self._filter.lower() not in ref.assetPath.lower()) or not ref)
- and self._filter.lower() not in capture_layer_path.lower()
- and self._filter.lower() not in _get_nickname(prim).lower()
- ):
- continue
- items.append(Item(prim, ref, layer, capture_layer_path))
- items = sorted(items, key=lambda x: x.ref.assetPath if x.ref else "None")
- self.__children = items
- self.__children_unfiltered = items
- self._item_changed(None)
-
- def filter_items(self):
- items = []
- for item in self.__children_unfiltered:
- if (
- self._filter
- and self._filter.lower() not in item.prim.GetPath().pathString.lower()
- and ((item.ref and self._filter.lower() not in item.ref.assetPath.lower()) or not item.ref)
- and self._filter.lower() not in item.capture_layer_path.lower()
- and self._filter.lower() not in item.nickname.lower()
- ):
- continue
- items.append(item)
- items = sorted(items, key=lambda x: x.ref.assetPath if x.ref else "None")
- self.__children = items
- self._item_changed(None)
-
- def set_filter(self, filter_str):
- self._filter = filter_str
-
- def get_item_children(self, item):
- """Returns all the children when the widget asks it."""
- if item is None:
- return self.__children
- return []
-
- def get_item_value_model_count(self, item):
- """The number of columns"""
- return len(HEADER_DICT.keys())
-
- def get_item_value_model(self, item, column_id):
- """
- Return value model.
- It's the object that tracks the specific value.
- In our case we use ui.SimpleStringModel.
- """
- if column_id == 0:
- return item.ref_asset_path_model
- return None
-
- def destroy(self):
- _reset_default_attrs(self)
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/premake5.lua b/source/extensions/lightspeed.asset_capture_localizer.window/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.asset_capture_localizer.window/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.color_to_normal.core/config/extension.toml b/source/extensions/lightspeed.color_to_normal.core/config/extension.toml
deleted file mode 100644
index bc00af446..000000000
--- a/source/extensions/lightspeed.color_to_normal.core/config/extension.toml
+++ /dev/null
@@ -1,43 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.4"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Alexander Jaus "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Color Texture To Normal Map Converter"
-description="Invokes an AI upscaler on textures passed to it."
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.color_to_normal.core"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["convert", "normal", "color"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
-icon = "data/icon.png"
-
-[dependencies]
-"omni.usd" = {}
-"lightspeed.common" = {}
-"omni.kit.pip_archive" = {} # For PIL
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.color_to_normal.core"
-
diff --git a/source/extensions/lightspeed.color_to_normal.core/data/icon.png b/source/extensions/lightspeed.color_to_normal.core/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.color_to_normal.core/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.color_to_normal.core/data/preview.png b/source/extensions/lightspeed.color_to_normal.core/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.color_to_normal.core/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.color_to_normal.core/docs/CHANGELOG.md b/source/extensions/lightspeed.color_to_normal.core/docs/CHANGELOG.md
deleted file mode 100644
index 78d392b13..000000000
--- a/source/extensions/lightspeed.color_to_normal.core/docs/CHANGELOG.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.4]
-### Changed
-- Changed repo link
-
-## [0.1.3]
-### Changed
-- Update to Kit 106
-
-## [0.1.2]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.1] - 2022-04-18
-### Changed
-- Moved python dependencies to lightspeed common
-### Fixed
-- Normalized Pixels
-
-## [0.1.0] - 2022-04-15
-### Added
-- Created
diff --git a/source/extensions/lightspeed.color_to_normal.core/docs/README.md b/source/extensions/lightspeed.color_to_normal.core/docs/README.md
deleted file mode 100644
index 900e64bb6..000000000
--- a/source/extensions/lightspeed.color_to_normal.core/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.color_to_normal.core
diff --git a/source/extensions/lightspeed.color_to_normal.core/docs/index.rst b/source/extensions/lightspeed.color_to_normal.core/docs/index.rst
deleted file mode 100644
index 9e0726496..000000000
--- a/source/extensions/lightspeed.color_to_normal.core/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.color_to_normal.core
-################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.color_to_normal.core
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.color_to_normal.core/lightspeed/color_to_normal/core/color_to_normal_core.py b/source/extensions/lightspeed.color_to_normal.core/lightspeed/color_to_normal/core/color_to_normal_core.py
deleted file mode 100644
index 75269f482..000000000
--- a/source/extensions/lightspeed.color_to_normal.core/lightspeed/color_to_normal/core/color_to_normal_core.py
+++ /dev/null
@@ -1,197 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-import contextlib
-import os
-import platform
-import shutil
-import subprocess
-import sys
-import tempfile
-from pathlib import Path
-
-import carb
-import carb.tokens
-import numpy as np
-import omni.usd
-from lightspeed.common import constants
-from PIL import Image
-
-
-class ColorToNormalCore:
- @staticmethod
- def perform_conversion(texture, output_texture, overwrite=False):
- # Get the paths to the nvtt process for format conversion and pix2pix for access to the neural net driver
- if os.path.exists(output_texture) and not overwrite:
- carb.log_info("Skipping " + texture + " since " + output_texture + " already exists.")
- return
- if not output_texture.lower().endswith(".dds") and not output_texture.lower().endswith(".png"):
- carb.log_info("Output texture " + output_texture + "must be either png or dds format.")
- return
- if os.path.exists(output_texture) and overwrite:
- # delete
- os.remove(output_texture)
-
- nvtt_path = carb.tokens.get_tokens_interface().resolve(constants.NVTT_PATH)
- converter_path = Path(constants.PIX2PIX_TEST_SCRIPT_PATH)
- converter_dir = Path(constants.PIX2PIX_ROOT_PATH)
- # Copy the neural net data files over to the driver if they don't already exist
- neural_net_data_path = Path(constants.PIX2PIX_CHECKPOINTS_PATH).joinpath("Color_NormalDX")
- if not neural_net_data_path.exists():
- shutil.copytree(str(Path(__file__).parent.joinpath("tools", "Color_NormalDX")), neural_net_data_path)
- # Set up the path to where the neural net driver leaves the results of the conversion
- result_path = Path(constants.PIX2PIX_RESULTS_PATH).joinpath(
- "Color_NormalDX", "test_latest", "images", "texture_fake_B.png"
- )
- # Create temp dir and set up texture name/path
- original_texture_name = Path(texture).stem
- temp_dir = tempfile.TemporaryDirectory().name # noqa PLR1732
- test_path = Path(temp_dir).joinpath("test", "texture", "texture.png")
- test_path.parent.mkdir(parents=True, exist_ok=True)
- carb.log_info("Converting: " + texture)
- # Convert the input image to a PNG if it already isn't
- if not texture.lower().endswith(".png"):
- png_texture_path = Path(temp_dir).joinpath(original_texture_name + ".png")
- with subprocess.Popen(
- [str(nvtt_path), texture, "--output", str(png_texture_path)],
- stdout=subprocess.DEVNULL,
- stderr=subprocess.STDOUT,
- ) as convert_png_process:
- convert_png_process.wait()
- # use PILLOW as a fallback if nvtt fails
- if png_texture_path.exists():
- with contextlib.suppress(NotImplementedError):
- with Image.open(texture) as im: # noqa
- im.save(png_texture_path, "PNG")
- else:
- png_texture_path = texture
- # Double the width of the input image so that the neural net driver thinks there's a known result for comparison
- # This can be just empty since it's not used in any way, but is the required input format
- try:
- with Image.open(png_texture_path) as im: # noqa
- width, height = im.size
- im = im.crop((0, 0, width * 2, height)) # noqa
- im.save(test_path, "PNG")
- except NotImplementedError:
- return
- # Create the dirtectory for the output and delete the results directory if it exists
- Path(output_texture).parent.mkdir(parents=True, exist_ok=True)
- if result_path.exists():
- result_path.unlink()
- # Configure environment to find kit's python.pipapi libraries
- python_path = carb.tokens.get_tokens_interface().resolve("${python}")
- separator = ";" if platform.system() == "Windows" else ":"
- pythonpath_env = separator.join(sys.path)[1:] # strip leading colon
- new_env = os.environ.copy()
- new_env["PYTHONPATH"] = pythonpath_env
- # Perform the conversion
- with subprocess.Popen(
- [
- python_path,
- str(converter_path),
- "--dataroot",
- temp_dir,
- "--name",
- "Color_NormalDX",
- "--model",
- "pix2pix",
- "--num_test",
- "1",
- "--gpu_ids",
- "-1",
- "--preprocess",
- "scale_width",
- "--load_size",
- "1024",
- ],
- cwd=str(converter_dir),
- stdout=subprocess.DEVNULL,
- stderr=subprocess.STDOUT,
- env=new_env,
- ) as conversion_process:
- conversion_process.wait()
- # The resulting normal map isn't guarenteed to have perfectly normal vector values, so we need to normalize it
- # Then convert to octohedral encoding
- with Image.open(str(result_path)) as im: # noqa
- normal_map_array = (np.asarray(im) / 255)[:, :, 0:3]
- normal_map_array = (normal_map_array * 2) - 1
- squared_array = np.square(normal_map_array)
- summed_array = np.sum(squared_array, axis=2)
- sqrted_array = np.sqrt(summed_array)
- repeated_array = np.repeat(sqrted_array[:, :, np.newaxis], 3, axis=2)
- normalized_array = normal_map_array / repeated_array
- # Invert Red!
- normalized_array[:, :, 0] = -1 * normalized_array[:, :, 0]
- rescaled_array = ((normalized_array + 1) / 2) * 255
- rounded_array = np.round(rescaled_array)
- hemi_sphere_array = 2 * ((np.asarray(rounded_array) / 255)[:, :, 0:3]) - 1
- hemi_mag = np.sqrt(
- np.square(hemi_sphere_array[:, :, 0][:, :, np.newaxis])
- + np.square(hemi_sphere_array[:, :, 1][:, :, np.newaxis])
- + np.square(hemi_sphere_array[:, :, 2][:, :, np.newaxis])
- )
- hemi_sphere_array = hemi_sphere_array / np.repeat(hemi_mag, 3, axis=2)
- p = hemi_sphere_array[:, :, (0, 1)] * ( # noqa
- 1
- / (
- np.absolute(hemi_sphere_array[:, :, 0][:, :, np.newaxis])
- + np.absolute(hemi_sphere_array[:, :, 1][:, :, np.newaxis])
- + hemi_sphere_array[:, :, 2][:, :, np.newaxis]
- )
- )
- unorm_oct_array = (
- np.clip(
- np.dstack(
- (
- p[:, :, 0][:, :, np.newaxis] + p[:, :, 1][:, :, np.newaxis],
- p[:, :, 0][:, :, np.newaxis] - p[:, :, 1][:, :, np.newaxis],
- )
- ),
- -1,
- 1,
- )
- * 0.5
- + 0.5
- )
- unorm_oct_array = np.insert(unorm_oct_array, 2, 0, axis=2)
- out_im = Image.fromarray(np.uint8((unorm_oct_array * 255).round()))
- out_im.save(str(result_path))
- out_im.close()
- # Convert to DDS if necessary, and generate mips (note dont use the temp dir for this)
- if output_texture.lower().endswith(".dds"):
- with subprocess.Popen(
- [
- str(nvtt_path),
- str(result_path),
- "--output",
- output_texture,
- ]
- + constants.TEXTURE_INFO[constants.MATERIAL_INPUTS_NORMALMAP_TEXTURE].to_nvtt_flag_array(),
- stdout=subprocess.DEVNULL,
- stderr=subprocess.STDOUT,
- ) as compress_mip_process:
- compress_mip_process.wait()
-
- else:
- shutil.copy(str(result_path), output_texture)
-
- @staticmethod
- @omni.usd.handle_exception
- async def async_perform_upscale(texture, output_texture):
- loop = asyncio.get_event_loop()
- await loop.run_in_executor(None, ColorToNormalCore.perform_conversion, texture, output_texture)
diff --git a/source/extensions/lightspeed.color_to_normal.core/lightspeed/color_to_normal/core/tools/Color_NormalDX/latest_net_D.pth b/source/extensions/lightspeed.color_to_normal.core/lightspeed/color_to_normal/core/tools/Color_NormalDX/latest_net_D.pth
deleted file mode 100644
index 67ae31644..000000000
--- a/source/extensions/lightspeed.color_to_normal.core/lightspeed/color_to_normal/core/tools/Color_NormalDX/latest_net_D.pth
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:92faa42d19a59c6a57f0c0d0affe05f3e1f885f6f7d2f568de7e278007769e1a
-size 11088291
diff --git a/source/extensions/lightspeed.color_to_normal.core/lightspeed/color_to_normal/core/tools/Color_NormalDX/latest_net_G.pth b/source/extensions/lightspeed.color_to_normal.core/lightspeed/color_to_normal/core/tools/Color_NormalDX/latest_net_G.pth
deleted file mode 100644
index 6ccfedafe..000000000
--- a/source/extensions/lightspeed.color_to_normal.core/lightspeed/color_to_normal/core/tools/Color_NormalDX/latest_net_G.pth
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:be390e58f1f8e92d5ed9804c507b3ca76d8a5c9e025312c78ef93b402536c7c9
-size 217725487
diff --git a/source/extensions/lightspeed.color_to_normal.core/premake5.lua b/source/extensions/lightspeed.color_to_normal.core/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.color_to_normal.core/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.color_to_normal.menu/config/extension.toml b/source/extensions/lightspeed.color_to_normal.menu/config/extension.toml
deleted file mode 100644
index b2ae7a8df..000000000
--- a/source/extensions/lightspeed.color_to_normal.menu/config/extension.toml
+++ /dev/null
@@ -1,62 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.6"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Alexander Jaus "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Lightspeed Game Export Color Texture To Normal Map"
-description="A menu that can invoke an color to normal texture converter on the textures in the loaded USD."
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.color_to_normal.menu"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["kit", "color", "normal", "texture", "exporter","menu"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
-icon = "data/icon.png"
-
-[dependencies]
-"omni.kit.menu.utils" = {}
-"omni.kit.widget.layers" = {}
-"lightspeed.layer_helpers" = {}
-"lightspeed.layer_manager.core" = {}
-"lightspeed.common" = {}
-"lightspeed.color_to_normal.core" = {}
-"lightspeed.error_popup.window" = {}
-"lightspeed.progress_popup.window" = {}
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.color_to_normal.menu"
-
-[[test]]
-dependencies = [
- "lightspeed.trex.tests.dependencies",
-]
-
-stdoutFailPatterns.exclude = [
- "*[omni.kit.registry.nucleus.utils.common] Skipping deletion of:*",
-]
-
-[[test]]
-name = "startup"
-dependencies = [
- "lightspeed.trex.tests.dependencies",
-]
diff --git a/source/extensions/lightspeed.color_to_normal.menu/data/icon.png b/source/extensions/lightspeed.color_to_normal.menu/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.color_to_normal.menu/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.color_to_normal.menu/data/preview.png b/source/extensions/lightspeed.color_to_normal.menu/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.color_to_normal.menu/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.color_to_normal.menu/docs/CHANGELOG.md b/source/extensions/lightspeed.color_to_normal.menu/docs/CHANGELOG.md
deleted file mode 100644
index 071431be7..000000000
--- a/source/extensions/lightspeed.color_to_normal.menu/docs/CHANGELOG.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.6]
-## Changed
-- Update to Kit 106.5
-
-## [0.1.5]
-### Fixed
-- Added missing test config
-
-## [0.1.4]
-### Changed
-- Changed repo link
-
-## [0.1.3]
-- Use updated `lightspeed.layer_manager.core` extension
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed.color_to_normal.menu/docs/README.md b/source/extensions/lightspeed.color_to_normal.menu/docs/README.md
deleted file mode 100644
index 259a6cbb5..000000000
--- a/source/extensions/lightspeed.color_to_normal.menu/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.color_to_normal.menu
diff --git a/source/extensions/lightspeed.color_to_normal.menu/docs/index.rst b/source/extensions/lightspeed.color_to_normal.menu/docs/index.rst
deleted file mode 100644
index 0d883f6f9..000000000
--- a/source/extensions/lightspeed.color_to_normal.menu/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.color_to_normal.menu
-################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.color_to_normal.menu
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.color_to_normal.menu/lightspeed/color_to_normal/menu/__init__.py b/source/extensions/lightspeed.color_to_normal.menu/lightspeed/color_to_normal/menu/__init__.py
deleted file mode 100644
index 084e7bbe3..000000000
--- a/source/extensions/lightspeed.color_to_normal.menu/lightspeed/color_to_normal/menu/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .menu import * # noqa: F401
diff --git a/source/extensions/lightspeed.color_to_normal.menu/lightspeed/color_to_normal/menu/menu.py b/source/extensions/lightspeed.color_to_normal.menu/lightspeed/color_to_normal/menu/menu.py
deleted file mode 100644
index cc1f2ecad..000000000
--- a/source/extensions/lightspeed.color_to_normal.menu/lightspeed/color_to_normal/menu/menu.py
+++ /dev/null
@@ -1,104 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-import functools
-
-import omni
-import omni.ext
-import omni.kit.menu.utils as omni_utils
-import omni.usd
-from lightspeed.color_to_normal.core import ColorToNormalCore
-from lightspeed.common import constants
-from lightspeed.error_popup.window import ErrorPopup
-from lightspeed.layer_helpers import LightspeedTextureProcessingCore
-from lightspeed.progress_popup.window import ProgressPopup
-from omni.kit.menu.utils import MenuItemDescription
-
-# processing_method = UpscalerCore.perform_upscale
-# input_texture_type = constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE
-# output_texture_type = constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE
-# output_suffix = "_upscaled4x.png"
-processing_config = (
- ColorToNormalCore.perform_conversion,
- constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE,
- constants.MATERIAL_INPUTS_NORMALMAP_TEXTURE,
- "_color2normal.png",
-)
-processing_config_overwrite = (
- functools.partial(ColorToNormalCore.perform_conversion, overwrite=True),
- constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE,
- constants.MATERIAL_INPUTS_NORMALMAP_TEXTURE,
- "_color2normal.png",
-)
-
-
-class LightspeedColorToNormalMenuExtension(omni.ext.IExt):
- def on_startup(self, ext_id):
- self.__create_save_menu()
- self._progress_bar = None
-
- def __create_save_menu(self):
- sub_menu = [
- MenuItemDescription(
- name="Skip already converted one",
- onclick_fn=self.__clicked,
- glyph="none.svg",
- ),
- MenuItemDescription(
- name="Overwrite all textures (re-convert everything)",
- onclick_fn=self.__clicked_overwrite,
- glyph="none.svg",
- ),
- ]
- self._tools_manager_menus = [
- MenuItemDescription(
- name="Batch Convert All Game Capture Color Textures to Normal Maps", glyph="none.svg", sub_menu=sub_menu
- )
- ]
- omni_utils.add_menu_items(self._tools_manager_menus, "Batch Tools")
-
- def on_shutdown(self):
- omni_utils.remove_menu_items(self._tools_manager_menus, "Batch Tools")
-
- def _batch_upscale_set_progress(self, progress):
- if not self._progress_bar:
- self._progress_bar = ProgressPopup(title="Converting")
- self._progress_bar.show()
- self._progress_bar.set_progress(progress)
-
- @omni.usd.handle_exception
- async def _run_batch_upscale(self, config):
- if not self._progress_bar:
- self._progress_bar = ProgressPopup(title="Converting")
- self._progress_bar.set_progress(0)
- self._progress_bar.show()
- error = await LightspeedTextureProcessingCore.lss_async_batch_process_entire_capture_layer(
- config, progress_callback=self._batch_upscale_set_progress
- )
- if error:
- self._error_popup = ErrorPopup("An error occurred while converting", error, window_size=(350, 150))
- self._error_popup.show()
- if self._progress_bar:
- self._progress_bar.hide()
- self._progress_bar = None
-
- def __clicked(self):
- asyncio.ensure_future(self._run_batch_upscale(processing_config))
-
- def __clicked_overwrite(self):
- asyncio.ensure_future(self._run_batch_upscale(processing_config_overwrite))
diff --git a/source/extensions/lightspeed.color_to_normal.menu/premake5.lua b/source/extensions/lightspeed.color_to_normal.menu/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.color_to_normal.menu/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.color_to_roughness.core/config/extension.toml b/source/extensions/lightspeed.color_to_roughness.core/config/extension.toml
deleted file mode 100644
index 9e0e28810..000000000
--- a/source/extensions/lightspeed.color_to_roughness.core/config/extension.toml
+++ /dev/null
@@ -1,43 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.3"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Alexander Jaus "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Color Texture To Normal Map Converter"
-description="Invokes an AI upscaler on textures passed to it."
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.color_to_roughness.core"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["convert", "roughness", "color"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
-icon = "data/icon.png"
-
-[dependencies]
-"omni.usd" = {}
-"lightspeed.common" = {}
-"omni.kit.pip_archive" = {} # For PIL
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.color_to_roughness.core"
-
diff --git a/source/extensions/lightspeed.color_to_roughness.core/data/icon.png b/source/extensions/lightspeed.color_to_roughness.core/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.color_to_roughness.core/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.color_to_roughness.core/data/preview.png b/source/extensions/lightspeed.color_to_roughness.core/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.color_to_roughness.core/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.color_to_roughness.core/docs/CHANGELOG.md b/source/extensions/lightspeed.color_to_roughness.core/docs/CHANGELOG.md
deleted file mode 100644
index ba14f8531..000000000
--- a/source/extensions/lightspeed.color_to_roughness.core/docs/CHANGELOG.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.3]
-### Changed
-- Changed repo link
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed.color_to_roughness.core/docs/README.md b/source/extensions/lightspeed.color_to_roughness.core/docs/README.md
deleted file mode 100644
index 411e883ff..000000000
--- a/source/extensions/lightspeed.color_to_roughness.core/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.color_to_roughness.core
diff --git a/source/extensions/lightspeed.color_to_roughness.core/docs/index.rst b/source/extensions/lightspeed.color_to_roughness.core/docs/index.rst
deleted file mode 100644
index b6dd27a48..000000000
--- a/source/extensions/lightspeed.color_to_roughness.core/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.color_to_roughness.core
-###################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.color_to_roughness.core
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.color_to_roughness.core/lightspeed/color_to_roughness/core/__init__.py b/source/extensions/lightspeed.color_to_roughness.core/lightspeed/color_to_roughness/core/__init__.py
deleted file mode 100644
index 4df8671de..000000000
--- a/source/extensions/lightspeed.color_to_roughness.core/lightspeed/color_to_roughness/core/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .color_to_roughness_core import * # noqa: F401
diff --git a/source/extensions/lightspeed.color_to_roughness.core/lightspeed/color_to_roughness/core/color_to_roughness_core.py b/source/extensions/lightspeed.color_to_roughness.core/lightspeed/color_to_roughness/core/color_to_roughness_core.py
deleted file mode 100644
index e1804c400..000000000
--- a/source/extensions/lightspeed.color_to_roughness.core/lightspeed/color_to_roughness/core/color_to_roughness_core.py
+++ /dev/null
@@ -1,159 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-import contextlib
-import os
-import platform
-import shutil
-import subprocess
-import sys
-import tempfile
-from pathlib import Path
-
-import carb
-import carb.tokens
-
-# import numpy as np
-import omni.usd
-from lightspeed.common import constants
-from PIL import Image, ImageOps
-
-
-class ColorToRoughnessCore:
- @staticmethod
- def perform_conversion(texture, output_texture, overwrite=False):
- # Get the paths to the nvtt process for format conversion and pix2pix for access to the nueral net driver
- if os.path.exists(output_texture) and not overwrite:
- carb.log_info("Skipping " + texture + " since " + output_texture + " already exists.")
- return
- if not output_texture.lower().endswith(".dds") and not output_texture.lower().endswith(".png"):
- carb.log_info("Output texture " + output_texture + "must be either png or dds format.")
- return
- if os.path.exists(output_texture) and overwrite:
- # delete
- os.remove(output_texture)
- nvtt_path = carb.tokens.get_tokens_interface().resolve(constants.NVTT_PATH)
- converter_path = Path(constants.PIX2PIX_TEST_SCRIPT_PATH)
- converter_dir = Path(constants.PIX2PIX_ROOT_PATH)
- # Copy the neural net data files over to the driver if they don't already exist
- neural_net_data_path = Path(constants.PIX2PIX_CHECKPOINTS_PATH).joinpath("Color_Roughness")
- if not neural_net_data_path.exists():
- shutil.copytree(str(Path(__file__).parent.joinpath("tools", "Color_Roughness")), neural_net_data_path)
- # Set up the path to where the neural net driver leaves the results of the conversion
- result_path = Path(constants.PIX2PIX_RESULTS_PATH).joinpath(
- "Color_Roughness", "test_latest", "images", "texture_fake_B.png"
- )
- # Create temp dir and set up texture name/path
- original_texture_name = Path(texture).stem
- temp_dir = tempfile.TemporaryDirectory().name # noqa PLR1732
- test_path = Path(temp_dir).joinpath("test", "texture", "texture.png")
- test_path.parent.mkdir(parents=True, exist_ok=True)
- carb.log_info("Converting: " + texture)
- # Convert the input image to a PNG if it already isn't
- if not texture.lower().endswith(".png"):
- png_texture_path = Path(temp_dir).joinpath(original_texture_name + ".png")
- with subprocess.Popen(
- [str(nvtt_path), texture, "--output", str(png_texture_path)],
- stdout=subprocess.DEVNULL,
- stderr=subprocess.STDOUT,
- ) as convert_png_process:
- convert_png_process.wait()
- # use PILLOW as a fallback if nvtt fails
- if png_texture_path.exists():
- with contextlib.suppress(NotImplementedError):
- with Image.open(texture) as im: # noqa
- im.save(png_texture_path, "PNG")
- else:
- png_texture_path = texture
- # Double the width of the input image so that the neural net driver thinks there's a known result for comparison
- # This can be just empty since it's not used in any way, but is the required input format
- try:
- with Image.open(png_texture_path) as im: # noqa
- width, height = im.size
- im = im.crop((0, 0, width * 2, height)) # noqa
- im.save(test_path, "PNG")
- except NotImplementedError:
- return
- # Create the dirtectory for the output and delete the results directory if it exists
- Path(output_texture).parent.mkdir(parents=True, exist_ok=True)
- if result_path.exists():
- result_path.unlink()
- # Configure environment to find kit's python.pipapi libraries
- python_path = carb.tokens.get_tokens_interface().resolve("${python}")
- separator = ";" if platform.system() == "Windows" else ":"
- pythonpath_env = separator.join(sys.path)[1:] # strip leading colon
- new_env = os.environ.copy()
- new_env["PYTHONPATH"] = pythonpath_env
- # Perform the conversion
- with subprocess.Popen(
- [
- python_path,
- str(converter_path),
- "--dataroot",
- temp_dir,
- "--name",
- "Color_Roughness",
- "--model",
- "pix2pix",
- "--num_test",
- "1",
- "--gpu_ids",
- "-1",
- "--preprocess",
- "scale_width",
- "--load_size",
- "1024",
- ],
- cwd=str(converter_dir),
- stdout=subprocess.DEVNULL,
- stderr=subprocess.STDOUT,
- env=new_env,
- ) as conversion_process:
- conversion_process.wait()
- # Reduce the 3 channel output to a single channgel image
- try:
- with Image.open(str(result_path)) as im: # noqa
- grey_im = ImageOps.grayscale(im)
- # Convert Smoothness to roughness
- grey_im = ImageOps.invert(grey_im)
- grey_im.save(str(result_path))
- grey_im.close()
- except NotImplementedError:
- return
- # Convert to DDS if necessary, and generate mips (note dont use the temp dir for this)
- if output_texture.lower().endswith(".dds"):
- with subprocess.Popen(
- [
- str(nvtt_path),
- str(result_path),
- "--output",
- output_texture,
- ]
- + constants.TEXTURE_INFO[constants.MATERIAL_INPUTS_REFLECTIONROUGHNESS_TEXTURE].to_nvtt_flag_array(),
- stdout=subprocess.DEVNULL,
- stderr=subprocess.STDOUT,
- ) as compress_mip_process:
- compress_mip_process.wait()
- else:
- shutil.copy(str(result_path), output_texture)
-
- @staticmethod
- @omni.usd.handle_exception
- async def async_perform_upscale(texture, output_texture):
- loop = asyncio.get_event_loop()
- await loop.run_in_executor(None, ColorToRoughnessCore.perform_conversion, texture, output_texture)
diff --git a/source/extensions/lightspeed.color_to_roughness.core/lightspeed/color_to_roughness/core/tools/Color_Roughness/latest_net_D.pth b/source/extensions/lightspeed.color_to_roughness.core/lightspeed/color_to_roughness/core/tools/Color_Roughness/latest_net_D.pth
deleted file mode 100644
index 476d53e80..000000000
--- a/source/extensions/lightspeed.color_to_roughness.core/lightspeed/color_to_roughness/core/tools/Color_Roughness/latest_net_D.pth
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:1011eb61680cdd041dd86c81658304104954536aa5e2ba68a09783829a414574
-size 11088291
diff --git a/source/extensions/lightspeed.color_to_roughness.core/lightspeed/color_to_roughness/core/tools/Color_Roughness/latest_net_G.pth b/source/extensions/lightspeed.color_to_roughness.core/lightspeed/color_to_roughness/core/tools/Color_Roughness/latest_net_G.pth
deleted file mode 100644
index 0944b8376..000000000
--- a/source/extensions/lightspeed.color_to_roughness.core/lightspeed/color_to_roughness/core/tools/Color_Roughness/latest_net_G.pth
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:01f67ca2869e5ed24314ee25a4444fc47b113fa72f9a461d0bde08c8e48179dd
-size 217725487
diff --git a/source/extensions/lightspeed.color_to_roughness.core/premake5.lua b/source/extensions/lightspeed.color_to_roughness.core/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.color_to_roughness.core/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.color_to_roughness.menu/config/extension.toml b/source/extensions/lightspeed.color_to_roughness.menu/config/extension.toml
deleted file mode 100644
index 79a6d7d01..000000000
--- a/source/extensions/lightspeed.color_to_roughness.menu/config/extension.toml
+++ /dev/null
@@ -1,48 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.4"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Alexander Jaus "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Lightspeed Game Export Color Texture To Normal Map"
-description="A menu that can invoke an color to roughness texture converter on the textures in the loaded USD."
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.color_to_roughness.menu"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["kit", "color", "roughness", "texture", "exporter","menu"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
-icon = "data/icon.png"
-
-[dependencies]
-"omni.kit.menu.utils" = {}
-"omni.kit.widget.layers" = {}
-"lightspeed.layer_helpers" = {}
-"lightspeed.layer_manager.core" = {}
-"lightspeed.common" = {}
-"lightspeed.color_to_roughness.core" = {}
-"lightspeed.error_popup.window" = {}
-"lightspeed.progress_popup.window" = {}
-
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.color_to_roughness.menu"
diff --git a/source/extensions/lightspeed.color_to_roughness.menu/data/icon.png b/source/extensions/lightspeed.color_to_roughness.menu/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.color_to_roughness.menu/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.color_to_roughness.menu/data/preview.png b/source/extensions/lightspeed.color_to_roughness.menu/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.color_to_roughness.menu/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.color_to_roughness.menu/docs/CHANGELOG.md b/source/extensions/lightspeed.color_to_roughness.menu/docs/CHANGELOG.md
deleted file mode 100644
index d4b9ec697..000000000
--- a/source/extensions/lightspeed.color_to_roughness.menu/docs/CHANGELOG.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.4]
-### Changed
-- Changed repo link
-
-## [0.1.3]
-- Use updated `lightspeed.layer_manager.core` extension
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed.color_to_roughness.menu/docs/README.md b/source/extensions/lightspeed.color_to_roughness.menu/docs/README.md
deleted file mode 100644
index d29894fd7..000000000
--- a/source/extensions/lightspeed.color_to_roughness.menu/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.color_to_roughness.menu
diff --git a/source/extensions/lightspeed.color_to_roughness.menu/docs/index.rst b/source/extensions/lightspeed.color_to_roughness.menu/docs/index.rst
deleted file mode 100644
index f59babe79..000000000
--- a/source/extensions/lightspeed.color_to_roughness.menu/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.color_to_roughness.menu
-###################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.color_to_roughness.menu
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.color_to_roughness.menu/lightspeed/color_to_roughness/menu/menu.py b/source/extensions/lightspeed.color_to_roughness.menu/lightspeed/color_to_roughness/menu/menu.py
deleted file mode 100644
index 89ed5abf2..000000000
--- a/source/extensions/lightspeed.color_to_roughness.menu/lightspeed/color_to_roughness/menu/menu.py
+++ /dev/null
@@ -1,108 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-import functools
-
-import omni
-import omni.ext
-import omni.kit.menu.utils as omni_utils
-import omni.usd
-from lightspeed.color_to_roughness.core import ColorToRoughnessCore
-from lightspeed.common import constants
-from lightspeed.error_popup.window import ErrorPopup
-from lightspeed.layer_helpers import LightspeedTextureProcessingCore
-from lightspeed.progress_popup.window import ProgressPopup
-from omni.kit.menu.utils import MenuItemDescription
-
-# processing_method = UpscalerCore.perform_upscale
-# input_texture_type = constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE
-# output_texture_type = constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE
-# output_suffix = "_upscaled4x.png"
-processing_config = (
- ColorToRoughnessCore.perform_conversion,
- constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE,
- constants.MATERIAL_INPUTS_REFLECTIONROUGHNESS_TEXTURE,
- "_color2roughness.png",
-)
-processing_config_overwrite = (
- functools.partial(ColorToRoughnessCore.perform_conversion, overwrite=True),
- constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE,
- constants.MATERIAL_INPUTS_REFLECTIONROUGHNESS_TEXTURE,
- "_color2roughness.png",
-)
-
-
-class LightspeedColorToNormalMenuExtension(omni.ext.IExt):
- def on_startup(self, ext_id):
- self.__create_save_menu()
- self._progress_bar = None
-
- def __create_save_menu(self):
-
- sub_menu = [
- MenuItemDescription(
- name="Skip already converted one",
- onclick_fn=self.__clicked,
- glyph="none.svg",
- ),
- MenuItemDescription(
- name="Overwrite all textures (re-convert everything)",
- onclick_fn=self.__clicked_overwrite,
- glyph="none.svg",
- ),
- ]
-
- self._tools_manager_menus = [
- MenuItemDescription(
- name="Batch Convert All Game Capture Color Textures to Roughness Maps",
- glyph="none.svg",
- sub_menu=sub_menu,
- )
- ]
- omni_utils.add_menu_items(self._tools_manager_menus, "Batch Tools")
-
- def on_shutdown(self):
- omni_utils.remove_menu_items(self._tools_manager_menus, "Batch Tools")
-
- def _batch_upscale_set_progress(self, progress):
- if not self._progress_bar:
- self._progress_bar = ProgressPopup(title="Converting")
- self._progress_bar.show()
- self._progress_bar.set_progress(progress)
-
- @omni.usd.handle_exception
- async def _run_batch_upscale(self, config):
- if not self._progress_bar:
- self._progress_bar = ProgressPopup(title="Converting")
- self._progress_bar.set_progress(0)
- self._progress_bar.show()
- error = await LightspeedTextureProcessingCore.lss_async_batch_process_entire_capture_layer(
- config, progress_callback=self._batch_upscale_set_progress
- )
- if error:
- self._error_popup = ErrorPopup("An error occurred while converting", error, window_size=(350, 150))
- self._error_popup.show()
- if self._progress_bar:
- self._progress_bar.hide()
- self._progress_bar = None
-
- def __clicked(self):
- asyncio.ensure_future(self._run_batch_upscale(processing_config))
-
- def __clicked_overwrite(self):
- asyncio.ensure_future(self._run_batch_upscale(processing_config_overwrite))
diff --git a/source/extensions/lightspeed.color_to_roughness.menu/premake5.lua b/source/extensions/lightspeed.color_to_roughness.menu/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.color_to_roughness.menu/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.common/config/extension.toml b/source/extensions/lightspeed.common/config/extension.toml
index 69e766e61..f225f5016 100644
--- a/source/extensions/lightspeed.common/config/extension.toml
+++ b/source/extensions/lightspeed.common/config/extension.toml
@@ -1,6 +1,6 @@
[package]
# Semantic Versionning is used: https://semver.org/
-version = "1.4.0"
+version = "1.5.1"
# Lists people or organizations that are considered the "authors" of the package.
authors = ["Alexander Jaus "]
diff --git a/source/extensions/lightspeed.common/docs/CHANGELOG.md b/source/extensions/lightspeed.common/docs/CHANGELOG.md
index b7451ab56..792a69bc6 100644
--- a/source/extensions/lightspeed.common/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.common/docs/CHANGELOG.md
@@ -1,6 +1,14 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.5.1]
+### Fixed
+- Fixed incorrect URL
+
+## [1.5.0]
+### Added
+- Updated constants for getting started documentation
+
## [1.4.0]
### Added
- Added constants for properties name column width
diff --git a/source/extensions/lightspeed.common/lightspeed/common/constants.py b/source/extensions/lightspeed.common/lightspeed/common/constants.py
index 65a582fd3..4c6b6128e 100644
--- a/source/extensions/lightspeed.common/lightspeed/common/constants.py
+++ b/source/extensions/lightspeed.common/lightspeed/common/constants.py
@@ -268,11 +268,11 @@
LICENSE_AGREEMENT_URL = (
"https://docs.omniverse.nvidia.com/platform/latest/common/NVIDIA_Omniverse_License_Agreement.html"
)
-QUICK_START_GUIDE_URL = (
- "https://docs.omniverse.nvidia.com/kit/docs/rtx_remix/latest/docs/howto/learning-runtimesetup.html"
-)
-RELEASE_NOTES_URL = "https://docs.omniverse.nvidia.com/kit/docs/rtx_remix/latest/docs/remix-releasenotes.html"
DOCUMENTATION_URL = "https://docs.omniverse.nvidia.com/kit/docs/rtx_remix/latest/"
+DOCUMENTATION_ROOT_URL = f"{DOCUMENTATION_URL}docs/"
+QUICK_START_GUIDE_URL = f"{DOCUMENTATION_ROOT_URL}gettingstarted/learning-runtimesetup.html"
+RELEASE_NOTES_URL = f"{DOCUMENTATION_ROOT_URL}remix-releasenotes.html"
+
TUTORIALS_URL = "https://www.youtube.com/playlist?list=PL4w6jm6S2lzvgJ97T1_VbLGBR_l6zzOUm"
COMMUNITY_SUPPORT_URL = (
"https://github.com/NVIDIAGameWorks/rtx-remix/?tab=readme-ov-file#forums-support--community-resources"
diff --git a/source/extensions/lightspeed.event.save_recent/config/extension.toml b/source/extensions/lightspeed.event.save_recent/config/extension.toml
index 40c86ec78..4ecdaf501 100644
--- a/source/extensions/lightspeed.event.save_recent/config/extension.toml
+++ b/source/extensions/lightspeed.event.save_recent/config/extension.toml
@@ -1,5 +1,5 @@
[package]
-version = "1.2.1"
+version = "2.0.0"
authors = ["dbataille@nvidia.com"]
repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit"
changelog = "docs/CHANGELOG.md"
@@ -14,6 +14,7 @@ preview_image = "data/preview.png"
[dependencies]
"lightspeed.events_manager" = {}
"lightspeed.layer_manager.core" = {}
+"lightspeed.trex.recent_projects.core" = {}
"omni.flux.utils.common" = {}
"omni.client" = {}
"omni.usd" = {}
diff --git a/source/extensions/lightspeed.event.save_recent/docs/CHANGELOG.md b/source/extensions/lightspeed.event.save_recent/docs/CHANGELOG.md
index cf98c7197..1f469b6f9 100644
--- a/source/extensions/lightspeed.event.save_recent/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.event.save_recent/docs/CHANGELOG.md
@@ -1,6 +1,11 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [2.0.0]
+### Changed
+- Moved the recent files utils to their own extension (`lightspeed.trex.recent_projects.core`)
+- Get the context name from settings instead of having a hardcoded value
+
## [1.2.1]
### Fixed
- Fix bug if a project layer cannot be opened.
diff --git a/source/extensions/lightspeed.event.save_recent/lightspeed/event/save_recent/core.py b/source/extensions/lightspeed.event.save_recent/lightspeed/event/save_recent/core.py
index 0cd78ed2f..ebc365428 100644
--- a/source/extensions/lightspeed.event.save_recent/lightspeed/event/save_recent/core.py
+++ b/source/extensions/lightspeed.event.save_recent/lightspeed/event/save_recent/core.py
@@ -20,20 +20,24 @@
import omni.usd
from lightspeed.events_manager import ILSSEvent as _ILSSEvent
from lightspeed.layer_manager.core import LSS_LAYER_GAME_NAME, LayerManagerCore, LayerType
+from lightspeed.trex.recent_projects.core import RecentProjectsCore
from omni.flux.utils.common import reset_default_attrs as _reset_default_attrs
-from .recent_saved_file_utils import RecentSavedFile
+_CONTEXT = "/exts/lightspeed.event.save_recent/context"
class EventSaveRecentCore(_ILSSEvent):
def __init__(self):
super().__init__()
- self.default_attr = {"_subscription": None}
+ self.default_attr = {"_context_name": None, "_context": None, "_subscription": None}
for attr, value in self.default_attr.items():
setattr(self, attr, value)
- self.__rencent_saved_file = RecentSavedFile()
- self._context = omni.usd.get_context()
- self.__layer_manager = LayerManagerCore()
+
+ self._context_name = carb.settings.get_settings().get(_CONTEXT) or ""
+ self._context = omni.usd.get_context(self._context_name)
+
+ self.__project_core = RecentProjectsCore()
+ self.__layer_manager = LayerManagerCore(context_name=self._context_name)
@property
def name(self) -> str:
@@ -67,7 +71,7 @@ def __on_save_event(self, event):
carb.log_verbose("Anonymous layer(s) can't be in the recent list")
return
path = self._context.get_stage_url()
- self.__rencent_saved_file.append_path_to_recent_file(
+ self.__project_core.append_path_to_recent_file(
omni.client.normalize_url(path),
layer_replacement.customLayerData.get(LSS_LAYER_GAME_NAME),
omni.client.normalize_url(layer_capture.realPath),
diff --git a/source/extensions/lightspeed.layer_helpers/config/extension.toml b/source/extensions/lightspeed.layer_helpers/config/extension.toml
deleted file mode 100644
index 433a39579..000000000
--- a/source/extensions/lightspeed.layer_helpers/config/extension.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-version = "0.1.3"
-authors = ["ajaus@nvidia.com"]
-repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit"
-keywords = ["lss", "lightspeed", "layer", "helper", "helpers"]
-title = "LightSpeed Layer Helpers"
-description = "Contains helper functions for lightspeed capture, export, and replacement layers."
-category = "internal"
-changelog = "docs/CHANGELOG.md"
-readme = "docs/README.md"
-icon = "data/icon.png"
-preview_image = "data/preview.png"
-
-[dependencies]
-"lightspeed.common" = {}
-"lightspeed.layer_manager.core" = {}
-
-[[python.module]]
-name = "lightspeed.layer_helpers"
diff --git a/source/extensions/lightspeed.layer_helpers/data/preview.png b/source/extensions/lightspeed.layer_helpers/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.layer_helpers/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.layer_helpers/docs/CHANGELOG.md b/source/extensions/lightspeed.layer_helpers/docs/CHANGELOG.md
deleted file mode 100644
index 47a32a868..000000000
--- a/source/extensions/lightspeed.layer_helpers/docs/CHANGELOG.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.3]
-- Use updated `lightspeed.layer_manager.core` extension
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed.layer_helpers/docs/README.md b/source/extensions/lightspeed.layer_helpers/docs/README.md
deleted file mode 100644
index 99cd866a3..000000000
--- a/source/extensions/lightspeed.layer_helpers/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.layer_helpers
diff --git a/source/extensions/lightspeed.layer_helpers/docs/index.rst b/source/extensions/lightspeed.layer_helpers/docs/index.rst
deleted file mode 100644
index 87eee7da1..000000000
--- a/source/extensions/lightspeed.layer_helpers/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.layer_helpers
-###########################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.layer_helpers
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.layer_helpers/lightspeed/layer_helpers/__init__.py b/source/extensions/lightspeed.layer_helpers/lightspeed/layer_helpers/__init__.py
deleted file mode 100644
index a27c842e4..000000000
--- a/source/extensions/lightspeed.layer_helpers/lightspeed/layer_helpers/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .texture_process import * # noqa F401
diff --git a/source/extensions/lightspeed.layer_helpers/lightspeed/layer_helpers/texture_process.py b/source/extensions/lightspeed.layer_helpers/lightspeed/layer_helpers/texture_process.py
deleted file mode 100644
index 630878cce..000000000
--- a/source/extensions/lightspeed.layer_helpers/lightspeed/layer_helpers/texture_process.py
+++ /dev/null
@@ -1,165 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-from pathlib import Path
-from typing import Optional
-
-import omni.usd
-from lightspeed.common import constants
-from lightspeed.layer_manager.core import LayerManagerCore, LayerType
-
-
-class LightspeedTextureProcessingCore:
- @staticmethod
- def lss_get_capture_textures_by_prim_paths(input_texture_type, prim_paths, context_name=""):
- layer_manager = LayerManagerCore(context_name)
- return layer_manager.get_layer_instance(LayerType.capture).get_textures_by_prim_paths(
- prim_paths, input_texture_type
- )
-
- @staticmethod
- def lss_collect_capture_textures(input_texture_type, context_name=""):
- layer_manager = LayerManagerCore(context_name)
- return layer_manager.get_layer_instance(LayerType.capture).get_textures(input_texture_type)
-
- @staticmethod
- @omni.usd.handle_exception
- async def async_batch_texture_process(
- processing_method, asset_absolute_paths, output_asset_absolute_paths, progress_callback=None
- ):
- loop = asyncio.get_event_loop()
- if len(asset_absolute_paths) != len(output_asset_absolute_paths):
- raise RuntimeError("List length mismatch.")
- total = len(asset_absolute_paths)
- for i, asset_absolute_path in enumerate(asset_absolute_paths):
- # perform upscale and place the output textures next to the enhancements layer location
- await loop.run_in_executor(None, processing_method, asset_absolute_path, output_asset_absolute_paths[i])
- if progress_callback:
- progress_callback((i + 1) / total)
-
- @staticmethod
- def blocking_batch_texture_process(processing_method, asset_absolute_paths, output_asset_absolute_paths):
- if len(asset_absolute_paths) != len(output_asset_absolute_paths):
- raise RuntimeError("List length mismatch.")
- for i, asset_absolute_path in enumerate(asset_absolute_paths):
- # perform upscale and place the output textures next to the enhancements layer location
- processing_method(asset_absolute_path, output_asset_absolute_paths[i])
-
- @staticmethod
- def lss_generate_populate_and_child_autoupscale_layer(
- output_texture_type, prim_paths, output_asset_relative_paths, context_name=""
- ):
- layer_manager = LayerManagerCore(context_name)
- # get/setup layers
- replacement_layer = layer_manager.get_layer(LayerType.replacement)
- # create/open and populate auto-upscale layer, placing it next to the enhancements layer
- enhancement_usd_dir = str(Path(replacement_layer.realPath).parent)
- auto_upscale_stage_absolute_path = str(Path(enhancement_usd_dir).joinpath(constants.AUTOUPSCALE_LAYER_FILENAME))
- if Path(auto_upscale_stage_absolute_path).exists():
- layer_manager.insert_sublayer(
- auto_upscale_stage_absolute_path, LayerType.autoupscale, False, -1, True, replacement_layer
- )
- else:
- layer_manager.create_new_sublayer(
- layer_type=LayerType.autoupscale,
- path=auto_upscale_stage_absolute_path,
- set_as_edit_target=False,
- parent_layer=replacement_layer,
- )
- layer_manager.get_layer_instance(LayerType.autoupscale).set_texture_attributes(
- output_texture_type, prim_paths, output_asset_relative_paths
- )
-
- @staticmethod
- def lss_filter_lists_for_file_existence(prim_paths, output_asset_absolute_paths, output_asset_relative_paths):
- return_prim_paths, return_output_asset_relative_paths = [], []
- if len(prim_paths) != len(output_asset_absolute_paths) or len(prim_paths) != len(output_asset_relative_paths):
- raise RuntimeError("List length mismatch.")
- for i, prim_path in enumerate(prim_paths):
- if Path(output_asset_absolute_paths[i]).exists():
- return_prim_paths.append(prim_path)
- return_output_asset_relative_paths.append(output_asset_relative_paths[i])
- return return_prim_paths, return_output_asset_relative_paths
-
- @staticmethod
- @omni.usd.handle_exception
- async def lss_async_batch_process_capture_layer(
- processing_config, prim_paths, abs_paths, rel_paths, progress_callback=None, context_name=""
- ) -> Optional[str]:
- """
- returns the error message if an error occurred
- """
- output_suffix = processing_config[3]
- processing_method = processing_config[0]
- output_texture_type = processing_config[2]
- replacement_layer = LayerManagerCore(context_name).get_layer(LayerType.replacement)
- if replacement_layer is None:
- return "No replacement layer was found. Make sure the opened USD file contains a replacement layer."
- replacement_layer_path = replacement_layer.realPath
- out_rel_paths = [path.replace(Path(path).suffix, output_suffix) for path in rel_paths]
- out_abs_paths = [
- str(Path(replacement_layer_path).parent.joinpath(out_rel_path)) for out_rel_path in out_rel_paths
- ]
- await LightspeedTextureProcessingCore.async_batch_texture_process(
- processing_method, abs_paths, out_abs_paths, progress_callback
- )
- prim_paths, out_rel_paths = LightspeedTextureProcessingCore.lss_filter_lists_for_file_existence(
- prim_paths, out_abs_paths, out_rel_paths
- )
- LightspeedTextureProcessingCore.lss_generate_populate_and_child_autoupscale_layer(
- output_texture_type, prim_paths, out_rel_paths, context_name
- )
- return None
-
- @staticmethod
- @omni.usd.handle_exception
- async def lss_async_batch_process_entire_capture_layer(
- processing_config, progress_callback=None, context_name=""
- ) -> Optional[str]:
- """
- returns the error message if an error occurred
- """
- LightspeedTextureProcessingCore.lss_workaround_gpu_crash()
- input_texture_type = processing_config[1]
- prim_paths, abs_paths, rel_paths = LightspeedTextureProcessingCore.lss_collect_capture_textures(
- input_texture_type, context_name
- )
- return await LightspeedTextureProcessingCore.lss_async_batch_process_capture_layer(
- processing_config, prim_paths, abs_paths, rel_paths, progress_callback, context_name
- )
-
- @staticmethod
- @omni.usd.handle_exception
- async def lss_async_batch_process_capture_layer_by_prim_paths(
- processing_config, prim_paths, progress_callback=None, context_name=""
- ) -> Optional[str]:
- """
- returns the error message if an error occurred
- """
- LightspeedTextureProcessingCore.lss_workaround_gpu_crash()
- input_texture_type = processing_config[1]
- abs_paths, rel_paths = LightspeedTextureProcessingCore.lss_get_capture_textures_by_prim_paths(
- input_texture_type, prim_paths, context_name
- )
- return await LightspeedTextureProcessingCore.lss_async_batch_process_capture_layer(
- processing_config, prim_paths, abs_paths, rel_paths, progress_callback, context_name
- )
-
- @staticmethod
- def lss_workaround_gpu_crash(context_name=""):
- LayerManagerCore(context_name).remove_layer(layer_type=LayerType.autoupscale)
diff --git a/source/extensions/lightspeed.layer_helpers/premake5.lua b/source/extensions/lightspeed.layer_helpers/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.layer_helpers/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.layer_manager.core/config/extension.toml b/source/extensions/lightspeed.layer_manager.core/config/extension.toml
index f39f7d3f3..8c8542d27 100644
--- a/source/extensions/lightspeed.layer_manager.core/config/extension.toml
+++ b/source/extensions/lightspeed.layer_manager.core/config/extension.toml
@@ -1,5 +1,5 @@
[package]
-version = "2.2.7"
+version = "2.2.8"
authors = ["dbataille@nvidia.com"]
repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit"
changelog = "docs/CHANGELOG.md"
@@ -18,13 +18,14 @@ name = "Lightspeed Layer Manager"
"lightspeed.common" = {}
"lightspeed.pip_archive" = {}
"omni.client" = {}
+"omni.flux.commands" = {} # Using custom commands
"omni.flux.layer_tree.usd.core" = {}
"omni.flux.service.shared" = {}
"omni.flux.utils.common" = {}
"omni.kit.commands" = {}
"omni.kit.usd.layers" = {}
-"omni.usd" = {}
"omni.kit.window.file" = {}
+"omni.usd" = {}
[[python.module]]
name = "lightspeed.layer_manager.core"
diff --git a/source/extensions/lightspeed.layer_manager.core/docs/CHANGELOG.md b/source/extensions/lightspeed.layer_manager.core/docs/CHANGELOG.md
index a47b50381..f3b73b699 100644
--- a/source/extensions/lightspeed.layer_manager.core/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.layer_manager.core/docs/CHANGELOG.md
@@ -1,16 +1,20 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [2.2.8]
+### Fixed
+- Changed usages of the `CreateSublayer` command for `CreateOrInsertSublayer`
+
## [2.2.7]
-## Changed
+### Changed
- Update to Kit 106.5
## [2.2.6]
-## Fixed
+### Fixed
- Fixed crash for new stage unloading logic
## [2.2.5]
-## Changed
+### Changed
- update to use omni.kit.test public api
## [2.2.4]
diff --git a/source/extensions/lightspeed.layer_manager.core/lightspeed/layer_manager/core/core.py b/source/extensions/lightspeed.layer_manager.core/lightspeed/layer_manager/core/core.py
index 2e7bd0394..4d2177e2d 100644
--- a/source/extensions/lightspeed.layer_manager.core/lightspeed/layer_manager/core/core.py
+++ b/source/extensions/lightspeed.layer_manager.core/lightspeed/layer_manager/core/core.py
@@ -386,8 +386,8 @@ def create_layer(
self.remove_layer(layer_type, do_undo=False)
# Create the sublayer
- omni.kit.commands.execute(
- "CreateSublayer",
+ success, new_layer_path = omni.kit.commands.execute(
+ "CreateOrInsertSublayer",
new_layer_path=str(path),
layer_identifier=str(parent_layer_identifier),
sublayer_position=sublayer_position,
@@ -396,14 +396,17 @@ def create_layer(
usd_context=self.context_name,
)
+ if not success:
+ raise ValueError(f'An error occurred when creating the layer with identifier "{path}".')
+
# Set the newly created sublayer as edit target
if set_edit_target:
- self.set_edit_target_with_identifier(path)
+ self.set_edit_target_with_identifier(new_layer_path)
# Update the newly created sublayer custom data to match the given layer type
if layer_type:
try:
- self.set_custom_layer_type_data_with_identifier(path, layer_type)
+ self.set_custom_layer_type_data_with_identifier(new_layer_path, layer_type)
except ValueError as e:
raise ValueError(
f"Unable to update the created layer's metadata. "
@@ -572,8 +575,8 @@ def insert_sublayer(
stage = self.__context.get_stage()
if parent_layer is None:
parent_layer = stage.GetRootLayer()
- omni.kit.commands.execute(
- "CreateSublayer",
+ success, new_layer_path = omni.kit.commands.execute(
+ "CreateOrInsertSublayer",
layer_identifier=parent_layer.identifier,
sublayer_position=sublayer_insert_position,
new_layer_path=path,
@@ -582,23 +585,24 @@ def insert_sublayer(
layer_name="",
usd_context=self.__context,
)
- for layer in stage.GetLayerStack():
- if omni.client.normalize_url(layer.realPath) == omni.client.normalize_url(path):
- # add customData
- if add_custom_layer_data:
- custom_layer_data = layer.customLayerData
- custom_layer_data.update({LayerTypeKeys.layer_type.value: layer_type.value})
- layer_inst = self.get_layer_instance(layer_type)
- custom_data_layer_inst = layer_inst.get_custom_layer_data()
- if custom_data_layer_inst:
- custom_layer_data.update(custom_data_layer_inst)
- layer.customLayerData = custom_layer_data
- layer.Save() # because of new customLayerData
- if set_as_edit_target:
- self.set_edit_target_layer(layer_type, force_layer_identifier=layer.identifier, do_undo=False)
- if do_undo:
- omni.kit.undo.end_group()
- return layer
+ if success:
+ for layer in stage.GetLayerStack():
+ if omni.client.normalize_url(layer.realPath) == omni.client.normalize_url(new_layer_path):
+ # add customData
+ if add_custom_layer_data:
+ custom_layer_data = layer.customLayerData
+ custom_layer_data.update({LayerTypeKeys.layer_type.value: layer_type.value})
+ layer_inst = self.get_layer_instance(layer_type)
+ custom_data_layer_inst = layer_inst.get_custom_layer_data()
+ if custom_data_layer_inst:
+ custom_layer_data.update(custom_data_layer_inst)
+ layer.customLayerData = custom_layer_data
+ layer.Save() # because of new customLayerData
+ if set_as_edit_target:
+ self.set_edit_target_layer(layer_type, force_layer_identifier=layer.identifier, do_undo=False)
+ if do_undo:
+ omni.kit.undo.end_group()
+ return layer
if do_undo:
omni.kit.undo.end_group()
return None
diff --git a/source/extensions/lightspeed.layer_manager.core/lightspeed/layer_manager/core/layers/i_layer.py b/source/extensions/lightspeed.layer_manager.core/lightspeed/layer_manager/core/layers/i_layer.py
index 8401ec70f..a5a1f08d0 100644
--- a/source/extensions/lightspeed.layer_manager.core/lightspeed/layer_manager/core/layers/i_layer.py
+++ b/source/extensions/lightspeed.layer_manager.core/lightspeed/layer_manager/core/layers/i_layer.py
@@ -16,19 +16,17 @@
"""
import abc
-from typing import TYPE_CHECKING, Dict, Optional
+from typing import Dict, Optional
import omni.kit.commands
import omni.kit.undo
import omni.usd
import six
from omni.flux.utils.common import reset_default_attrs as _reset_default_attrs
+from pxr import Sdf
from ..data_models import LayerType, LayerTypeKeys
-if TYPE_CHECKING:
- from pxr import Sdf
-
@six.add_metaclass(abc.ABCMeta)
class ILayer:
@@ -87,8 +85,8 @@ def create_sublayer(
if not parent_layer:
parent_layer = stage.GetRootLayer()
current_layers = stage.GetLayerStack()
- omni.kit.commands.execute(
- "CreateSublayer",
+ success, _ = omni.kit.commands.execute(
+ "CreateOrInsertSublayer",
layer_identifier=parent_layer.identifier,
sublayer_position=sublayer_create_position,
new_layer_path=path if path else "",
@@ -96,6 +94,10 @@ def create_sublayer(
create_or_insert=True,
usd_context=self._core.context_name or "",
)
+ if not success:
+ return None
+
+ # Add the desired metadata:
layers = stage.GetLayerStack()
new_layers = list(set(layers) - set(current_layers))
layer = sorted(new_layers, key=lambda x: x.GetDisplayName())[0]
diff --git a/source/extensions/lightspeed.layer_manager.core/lightspeed/layer_manager/core/tests/unit/test_core.py b/source/extensions/lightspeed.layer_manager.core/lightspeed/layer_manager/core/tests/unit/test_core.py
index e9ae290ec..b1eb78806 100644
--- a/source/extensions/lightspeed.layer_manager.core/lightspeed/layer_manager/core/tests/unit/test_core.py
+++ b/source/extensions/lightspeed.layer_manager.core/lightspeed/layer_manager/core/tests/unit/test_core.py
@@ -17,6 +17,7 @@
import contextlib
import pathlib
+import re
from types import NoneType
from typing import Union
from unittest.mock import Mock, call, patch
@@ -880,10 +881,13 @@ async def __run_create_layer(
f'Can\'t find the layer with identifier "{layer_path}".',
)
+ # Replace any "parent/../dir" with "dir" and any "dir/./" with "dir/"
+ resolved_path = re.sub(r"(/[^/]+/\.\./)|(\./)|(//+)", "/", layer_path)
+
self.assertEqual(1 if set_edit_target and not create_will_fail else 0, set_edit_target_mock.call_count)
if set_edit_target and not create_will_fail:
- self.assertEqual(call(layer_path), set_edit_target_mock.call_args)
+ self.assertEqual(call(resolved_path), set_edit_target_mock.call_args)
self.assertEqual(1 if set_layer_type and not create_will_fail else 0, set_custom_data_mock.call_count)
if set_layer_type and not create_will_fail:
- self.assertEqual(call(layer_path, layer_type), set_custom_data_mock.call_args)
+ self.assertEqual(call(resolved_path, layer_type), set_custom_data_mock.call_args)
diff --git a/source/extensions/lightspeed.layer_manager.service/config/extension.toml b/source/extensions/lightspeed.layer_manager.service/config/extension.toml
index 5dca9d0f7..38e4f2f1e 100644
--- a/source/extensions/lightspeed.layer_manager.service/config/extension.toml
+++ b/source/extensions/lightspeed.layer_manager.service/config/extension.toml
@@ -1,5 +1,5 @@
[package]
-version = "1.2.0"
+version = "1.2.1"
authors =["Pierre-Oliver Trottier "]
changelog = "docs/CHANGELOG.md"
readme = "docs/README.md"
@@ -16,3 +16,21 @@ preview_image = "data/preview.png"
[[python.module]]
name = "lightspeed.layer_manager.service"
+
+[[test]]
+dependencies = [
+ "lightspeed.trex.tests.dependencies",
+ "omni.flux.utils.widget",
+ "omni.kit.usd.layers",
+ "omni.services.core",
+]
+
+stdoutFailPatterns.exclude = [
+ "*[omni.kit.registry.nucleus.utils.common] Skipping deletion of:*",
+]
+
+[[test]]
+name = "startup"
+dependencies = [
+ "lightspeed.trex.tests.dependencies",
+]
diff --git a/source/extensions/lightspeed.layer_manager.service/docs/CHANGELOG.md b/source/extensions/lightspeed.layer_manager.service/docs/CHANGELOG.md
index 724a72d8d..007c23d32 100644
--- a/source/extensions/lightspeed.layer_manager.service/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.layer_manager.service/docs/CHANGELOG.md
@@ -1,6 +1,10 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.2.1]
+### Added
+- Added tests for all the endpoints in the layer manager service
+
## [1.2.0]
### Changed
- Use generic factory instead of service-specific factory
diff --git a/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/__init__.py b/source/extensions/lightspeed.layer_manager.service/lightspeed/layer_manager/service/tests/__init__.py
similarity index 92%
rename from source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/__init__.py
rename to source/extensions/lightspeed.layer_manager.service/lightspeed/layer_manager/service/tests/__init__.py
index 5fc560efe..ed06130d4 100644
--- a/source/extensions/lightspeed.asset_capture_localizer.window/lightspeed/asset_capture_localizer/window/__init__.py
+++ b/source/extensions/lightspeed.layer_manager.service/lightspeed/layer_manager/service/tests/__init__.py
@@ -15,4 +15,4 @@
* limitations under the License.
"""
-from .extension import * # noqa F401
+from .e2e.test_service import TestLayerManagerService
diff --git a/source/extensions/lightspeed.layer_manager.service/lightspeed/layer_manager/service/tests/e2e/test_service.py b/source/extensions/lightspeed.layer_manager.service/lightspeed/layer_manager/service/tests/e2e/test_service.py
new file mode 100644
index 000000000..457f12843
--- /dev/null
+++ b/source/extensions/lightspeed.layer_manager.service/lightspeed/layer_manager/service/tests/e2e/test_service.py
@@ -0,0 +1,321 @@
+"""
+* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+* SPDX-License-Identifier: Apache-2.0
+*
+* 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
+*
+* https://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 pathlib import Path
+
+import omni.kit.usd.layers as _layers
+import omni.usd
+from omni.flux.service.factory import get_instance as get_service_factory_instance
+from omni.flux.utils.common.api import send_request
+from omni.flux.utils.widget.resources import get_test_data
+from omni.kit.test import AsyncTestCase
+from omni.kit.test_suite.helpers import open_stage
+from omni.services.core import main
+from pxr import Sdf, Usd
+
+
+class TestLayerManagerService(AsyncTestCase):
+ # Before running each test
+ async def setUp(self):
+ self.project_path = get_test_data("usd/project_example/combined.usda")
+
+ self.context = omni.usd.get_context()
+ await open_stage(self.project_path)
+
+ factory = get_service_factory_instance()
+
+ # Register the service in the app
+ self.service = factory.get_plugin_from_name("LayerManagerService")()
+ main.register_router(router=self.service.router, prefix=self.service.prefix)
+
+ # After running each test
+ async def tearDown(self):
+ main.deregister_router(router=self.service.router, prefix=self.service.prefix)
+
+ self.service = None
+
+ if self.context.can_close_stage():
+ await self.context.close_stage_async()
+
+ self.context = None
+ self.project_path = None
+
+ async def test_get_layers_no_args_returns_project_layers(self):
+ # Arrange
+ project_dir = Path(get_test_data("usd/project_example"))
+
+ # Act
+ response = await send_request("GET", f"{self.service.prefix}/")
+
+ # Assert
+ self.assertEqual(
+ str(response).lower(),
+ str(
+ {
+ "layers": [
+ {
+ "layer_id": str(project_dir / "combined.usda"),
+ "layer_type": "workfile",
+ "children": [
+ {
+ "layer_id": str(project_dir / "replacements.usda"),
+ "layer_type": "replacement",
+ "children": [],
+ },
+ {
+ "layer_id": str(project_dir / ".deps" / "captures" / "capture.usda"),
+ "layer_type": "capture",
+ "children": [],
+ },
+ ],
+ }
+ ]
+ }
+ ).lower(),
+ )
+
+ async def test_get_layers_layer_types_args_returns_project_layers_of_type(self):
+ # Arrange
+ project_dir = Path(get_test_data("usd/project_example"))
+
+ # Act
+ response = await send_request("GET", f"{self.service.prefix}/?layer_types=workfile&layer_types=replacement")
+
+ # Assert
+ layers = response.get("layers") or []
+ self.assertEqual(
+ str(sorted(layers, key=lambda i: i.get("layer_id"))).lower(), # Sort the layers to remove flakiness
+ str(
+ [
+ {
+ "layer_id": str(project_dir / "combined.usda"),
+ "layer_type": "workfile",
+ "children": [],
+ },
+ {
+ "layer_id": str(project_dir / "replacements.usda"),
+ "layer_type": "replacement",
+ "children": [],
+ },
+ ]
+ ).lower(),
+ )
+
+ async def test_get_layers_layer_count_args_returns_n_project_layers(self):
+ # Arrange
+ project_dir = Path(get_test_data("usd/project_example"))
+
+ # Act
+ response = await send_request("GET", f"{self.service.prefix}/?layer_types=workfile&layer_count=1")
+
+ # Assert
+ self.assertEqual(
+ str(response).lower(),
+ str(
+ {
+ "layers": [
+ {
+ "layer_id": str(project_dir / "combined.usda"),
+ "layer_type": "workfile",
+ "children": [],
+ }
+ ]
+ }
+ ).lower(),
+ )
+
+ async def test_get_sublayers_returns_layer_sublayers(self):
+ # Arrange
+ project_dir = Path(get_test_data("usd/project_example"))
+ project_layer = (project_dir / "combined.usda").as_posix().replace("/", "%2F")
+
+ # Act
+ response = await send_request("GET", f"{self.service.prefix}/{project_layer}/sublayers")
+
+ # Assert
+ self.assertEqual(
+ str(response).lower(),
+ str(
+ {
+ "layers": [
+ {
+ "layer_id": str(project_dir / "replacements.usda"),
+ "layer_type": "replacement",
+ "children": [],
+ },
+ {
+ "layer_id": str(project_dir / ".deps" / "captures" / "capture.usda"),
+ "layer_type": "capture",
+ "children": [],
+ },
+ ],
+ }
+ ).lower(),
+ )
+
+ async def test_get_layer_types_returns_expected_layer_types(self):
+ # Arrange
+ pass
+
+ # Act
+ response = await send_request("GET", f"{self.service.prefix}/types")
+
+ # Assert
+ self.assertEqual(
+ response, {"layer_types": ["autoupscale", "capture_baker", "capture", "replacement", "workfile"]}
+ )
+
+ async def test_get_edit_target_returns_expected_edit_target(self):
+ # Arrange
+ expected_target = Path(get_test_data("usd/project_example/replacements.usda"))
+
+ target_layer = Sdf.Layer.FindOrOpen(expected_target.as_posix())
+ self.context.get_stage().SetEditTarget(Usd.EditTarget(target_layer))
+
+ # Act
+ response = await send_request("GET", f"{self.service.prefix}/target")
+
+ # Assert
+ self.assertEqual(str(response).lower(), str({"layer_id": str(expected_target)}).lower())
+
+ async def test_layer_manipulations_should_work_as_expected(self):
+ stage = self.context.get_stage()
+
+ project_dir = Path(get_test_data("usd/project_example"))
+ new_layer_path_01 = project_dir / "new_layer_01.usda"
+ new_layer_path_02 = project_dir / "new_layer_02.usda"
+ mod_layer_path = project_dir / "replacements.usda"
+
+ # Clean up previous tests
+ new_layer_path_01.unlink(missing_ok=True)
+ new_layer_path_02.unlink(missing_ok=True)
+
+ try:
+ # CREATE SUBLAYER
+ response = await send_request(
+ "POST",
+ f"{self.service.prefix}/",
+ json={
+ "layer_path": str(new_layer_path_01),
+ "layer_type": "autoupscale",
+ "parent_layer_id": str(mod_layer_path),
+ },
+ )
+
+ self.assertEqual(response, "OK")
+
+ response = await send_request(
+ "POST",
+ f"{self.service.prefix}/",
+ json={
+ "layer_path": str(new_layer_path_02),
+ "sublayer_position": 0,
+ "set_edit_target": True,
+ "parent_layer_id": str(mod_layer_path),
+ },
+ )
+
+ self.assertEqual(response, "OK")
+ self.assertEqual(
+ self.context.get_stage().GetEditTarget().GetLayer().realPath.lower(), str(new_layer_path_02).lower()
+ )
+
+ mod_layer = self.context.get_stage().GetLayerStack()[2] # replacements.usda
+ self.assertListEqual(list(mod_layer.subLayerPaths), ["./new_layer_02.usda", "./new_layer_01.usda"])
+
+ # MOVE SUBLAYER
+ response = await send_request(
+ "PUT",
+ f"{self.service.prefix}/{str(new_layer_path_02)}/move",
+ json={
+ "current_parent_layer_id": str(mod_layer_path),
+ "new_parent_layer_id": str(new_layer_path_01),
+ },
+ )
+
+ self.assertEqual(response, "OK")
+
+ mod_layer = self.context.get_stage().GetLayerStack()[2] # replacements.usda
+ new_layer_01 = self.context.get_stage().GetLayerStack()[3] # new_layer_01.usda
+ self.assertListEqual(list(mod_layer.subLayerPaths), ["./new_layer_01.usda"])
+ self.assertListEqual(list(new_layer_01.subLayerPaths), ["./new_layer_02.usda"])
+
+ # LOCK SUBLAYER
+ response = await send_request(
+ "PUT",
+ f"{self.service.prefix}/{str(new_layer_path_01)}/lock",
+ json={"value": True},
+ )
+
+ self.assertEqual(response, "OK")
+
+ state = _layers.get_layers(self.context).get_layers_state()
+ self.assertTrue(state.is_layer_locked(new_layer_path_01.as_posix()))
+ self.assertFalse(state.is_layer_locked(new_layer_path_02.as_posix())) # in USD, lock state is not inherited
+
+ # MUTE SUBLAYER
+ response = await send_request(
+ "PUT",
+ f"{self.service.prefix}/{str(new_layer_path_01)}/mute",
+ json={"value": True},
+ )
+
+ self.assertEqual(response, "OK")
+
+ self.assertTrue(stage.IsLayerMuted(new_layer_path_01.as_posix()))
+ self.assertFalse(stage.IsLayerMuted(new_layer_path_02.as_posix())) # in USD, mute state is not inherited
+
+ # SET SUBLAYER AS EDIT TARGET
+ response = await send_request(
+ "PUT",
+ f"{self.service.prefix}/target/{str(mod_layer_path)}",
+ )
+
+ self.assertEqual(response, "OK")
+ self.assertEqual(
+ self.context.get_stage().GetEditTarget().GetLayer().realPath.lower(), str(mod_layer_path).lower()
+ )
+
+ # SAVE SUBLAYER
+ response = await send_request(
+ "POST",
+ f"{self.service.prefix}/{str(new_layer_path_01)}/save",
+ )
+
+ self.assertEqual(response, "OK")
+ self.assertNotIn(
+ new_layer_path_01.as_posix().lower(),
+ [i.lower() for i in _layers.get_layers_state().get_dirty_layer_identifiers()],
+ )
+
+ # REMOVE SUBLAYER
+ response = await send_request(
+ "DELETE",
+ f"{self.service.prefix}/{str(new_layer_path_01)}",
+ json={"parent_layer_id": str(mod_layer_path)},
+ )
+
+ self.assertEqual(response, "OK")
+
+ mod_layer = self.context.get_stage().GetLayerStack()[2] # replacements.usda
+ self.assertListEqual(list(mod_layer.subLayerPaths), [])
+ except Exception as e:
+ raise e
+ finally:
+ # Clean up
+ new_layer_path_01.unlink(missing_ok=True)
+ new_layer_path_02.unlink(missing_ok=True)
diff --git a/source/extensions/lightspeed.lock_xform/config/extension.toml b/source/extensions/lightspeed.lock_xform/config/extension.toml
deleted file mode 100644
index d8f5c90c3..000000000
--- a/source/extensions/lightspeed.lock_xform/config/extension.toml
+++ /dev/null
@@ -1,47 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.2"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Nicholas Freybler "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Lightspeed Transform Lock"
-description="Extension used to manage locking (prevent editing) of transform-related attributes"
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/dxvk_rt/"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["lightspeed", "xform", "transform", "lock"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
-icon = "data/icon.png"
-
-[dependencies]
-"omni.usd" = {}
-"omni.kit.menu.utils" = {}
-"omni.kit.usd_undo" = {}
-"omni.kit.window.popup_dialog" = {}
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.lock_xform"
-
-[settings]
-exts."lightspeed.lock_xform".prim_filter = ""
-exts."lightspeed.lock_xform".reason_for_lock = ""
diff --git a/source/extensions/lightspeed.lock_xform/data/icon.png b/source/extensions/lightspeed.lock_xform/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.lock_xform/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.lock_xform/data/preview.png b/source/extensions/lightspeed.lock_xform/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.lock_xform/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.lock_xform/docs/CHANGELOG.md b/source/extensions/lightspeed.lock_xform/docs/CHANGELOG.md
deleted file mode 100644
index 96a5c1394..000000000
--- a/source/extensions/lightspeed.lock_xform/docs/CHANGELOG.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed.lock_xform/docs/README.md b/source/extensions/lightspeed.lock_xform/docs/README.md
deleted file mode 100644
index 694ff8e82..000000000
--- a/source/extensions/lightspeed.lock_xform/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.lock_xform
diff --git a/source/extensions/lightspeed.lock_xform/docs/index.rst b/source/extensions/lightspeed.lock_xform/docs/index.rst
deleted file mode 100644
index 69e924905..000000000
--- a/source/extensions/lightspeed.lock_xform/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.lock_xform
-###########################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.lock_xform
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.lock_xform/lightspeed/lock_xform/__init__.py b/source/extensions/lightspeed.lock_xform/lightspeed/lock_xform/__init__.py
deleted file mode 100644
index c8ecd2592..000000000
--- a/source/extensions/lightspeed.lock_xform/lightspeed/lock_xform/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .extension import * # noqa: F401
diff --git a/source/extensions/lightspeed.lock_xform/lightspeed/lock_xform/core.py b/source/extensions/lightspeed.lock_xform/lightspeed/lock_xform/core.py
deleted file mode 100644
index bdc09a841..000000000
--- a/source/extensions/lightspeed.lock_xform/lightspeed/lock_xform/core.py
+++ /dev/null
@@ -1,116 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import carb
-import carb.settings
-import omni.kit.menu.utils
-import omni.usd
-
-from .session import LockXformSession
-
-
-class LockXformCore:
- """Core functionality + meta data + state manager for lightspeed.lock_xform extension"""
-
- def __init__(self):
- self._enabled = True
- self._add_toggle_to_edit_menu()
- self._sessions = {}
- # Create stage event subscriptions so we know when to manage sessions
- self._stage_event = (
- omni.usd.get_context()
- .get_stage_event_stream()
- .create_subscription_to_pop(self._on_stage_event, name="[lightspeed.lock_xform] Stage Event")
- )
- self._reason_for_lock = carb.settings.get_settings().get_as_string(
- "/exts/lightspeed.lock_xform/reason_for_lock"
- )
- # Retrieve prim filter setting
- self._prim_filter = carb.settings.get_settings().get_as_string("/exts/lightspeed.lock_xform/prim_filter")
-
- def unsubscribe_from_events(self):
- self._stage_event.unsubscribe()
-
- def _on_stage_event(self, event):
- usd_context = omni.usd.get_context()
- if event.type == int(omni.usd.StageEventType.OPENED):
- # On stage open, create new session
- stage = usd_context.get_stage()
- self._sessions[usd_context.get_stage_id()] = LockXformSession(
- usd_context.get_stage_id(), stage, self._display_dialog
- )
- elif event.type == int(omni.usd.StageEventType.CLOSED):
- # On stage close, delete session
- if usd_context.get_stage_id() in self._sessions:
- del self._sessions[usd_context.get_stage_id()]
- elif event.type == int(omni.usd.StageEventType.SELECTION_CHANGED):
- # On prim selection, cache the transform attributes that we want to lock
- stage = usd_context.get_stage()
- selected_prim_paths = usd_context.get_selection().get_selected_prim_paths()
- if self._prim_filter == "":
- self._sessions[usd_context.get_stage_id()].lock_prims(stage, selected_prim_paths)
- else:
- # Filter based on prim names
- filtered_prim_paths = []
- for selected_prim_path in selected_prim_paths:
- if self._prim_filter in selected_prim_path:
- filtered_prim_paths.append(selected_prim_path)
- self._sessions[usd_context.get_stage_id()].lock_prims(stage, filtered_prim_paths)
-
- def _add_toggle_to_edit_menu(self):
- self._tools_manager_menus = [
- omni.kit.menu.utils.MenuItemDescription(name=""), # Create divider
- omni.kit.menu.utils.MenuItemDescription(
- name="Xform Lock",
- glyph="none.svg",
- enabled=True,
- onclick_fn=self._toggle_enablement,
- ticked_fn=self._ticked_menu_eval,
- ),
- ]
- omni.kit.menu.utils.add_menu_items(self._tools_manager_menus, "Edit")
-
- def _toggle_enablement(self):
- self._enabled = not self._enabled
- for _, session in self._sessions.items():
- session.set_enablement(self._enabled)
-
- def _ticked_menu_eval(self):
- return self._enabled
-
- def _display_dialog(self):
- def _hide_dialog(d):
- d.hide()
-
- # Title
- title = "[lightspeed.lock_xform]"
- # First message chunk
- common_msg = "We noticed you tried to modify a locked transform."
- # If a reason has been specified by an extension or Kit app, indicate here
- reason_msg = '\n\nReason for lock: "' + self._reason_for_lock + '"' if (self._reason_for_lock != "") else ""
- # If a prim filter has been specified by an extension or Kit app, indicate here
- prim_filter_msg = '\n\nFilter found: "' + self._prim_filter + '"' if (self._prim_filter != "") else ""
- # Inform how to disable
- disable_msg = "\n\nYou can disable this functionality in the menu: (Edit) -> (Xform Lock)."
- # Inform this will only appear once per session
- display_once_msg = "\n\n" + "!! This message will not display again, except on new stage !!"
-
- msg = common_msg + reason_msg + prim_filter_msg + disable_msg + display_once_msg
- dialog = omni.kit.window.popup_dialog.MessageDialog(
- title=title, message=msg, disable_cancel_button=True, ok_handler=_hide_dialog
- )
- dialog.show()
diff --git a/source/extensions/lightspeed.lock_xform/lightspeed/lock_xform/extension.py b/source/extensions/lightspeed.lock_xform/lightspeed/lock_xform/extension.py
deleted file mode 100644
index df8167da8..000000000
--- a/source/extensions/lightspeed.lock_xform/lightspeed/lock_xform/extension.py
+++ /dev/null
@@ -1,34 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import carb
-import omni.ext
-
-from .core import LockXformCore
-
-
-class LightspeedLockXform(omni.ext.IExt):
- """Extension used to manage locking (prevent editing) of transform-related attributes"""
-
- def on_startup(self, ext_id):
- carb.log_info("[lightspeed.lock_xform] Lightspeed Lock Transform startup")
- self._core = LockXformCore()
-
- def on_shutdown(self):
- carb.log_info("[lightspeed.lock_xform] Lightspeed Lock Transform shutdown")
- # There's a weird race condition with stage closure if we don't explicitly do this before Core dtor
- self._core.unsubscribe_from_events()
diff --git a/source/extensions/lightspeed.lock_xform/lightspeed/lock_xform/session.py b/source/extensions/lightspeed.lock_xform/lightspeed/lock_xform/session.py
deleted file mode 100644
index a8e1bddf4..000000000
--- a/source/extensions/lightspeed.lock_xform/lightspeed/lock_xform/session.py
+++ /dev/null
@@ -1,69 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import omni.kit.usd_undo
-import omni.kit.window.popup_dialog.message_dialog
-import omni.usd
-import pxr.Tf
-import pxr.Usd
-
-prim_filter_setting_path = "/exts/lightspeed.lock_xform/prim_filter"
-
-
-class LockXformSession:
- """A "session" (associated with a stage). Keeps track of an individual stage's prims + disabling the lock"""
-
- def __init__(self, identifier, stage, display_dialog_callback):
- self._enabled = True
- self._id = identifier # id isn't really used, but leaving it here for debug and convenience
- self._prim_xformOp_cache = set()
- # Register USD Notifer/Listener whenever UsdObjects are changed
- self._listener = pxr.Tf.Notice.RegisterGlobally(pxr.Usd.Notice.ObjectsChanged, self._undo_xform_deltas)
- self._usd_undo = omni.kit.usd_undo.UsdEditTargetUndo(stage.GetEditTarget())
- self._display_dialog = True
- self._display_dialog_callback = display_dialog_callback
-
- def set_enablement(self, enabled):
- self._enabled = enabled
-
- def lock_prims(self, stage, prim_paths):
- """A "session" (associated with a stage). Keeps track of an individual stage's prims + disabling the lock"""
- # Reset prim cache
- self._prim_xformOp_cache = set()
- for prim_path in prim_paths:
- prim = stage.GetPrimAtPath(prim_path)
- for attr in prim.GetAttributes():
- attr_path = attr.GetPath()
- if "xformOp:" in str(attr_path):
- # Cache prim state using usd_undo module
- self._usd_undo.reserve(attr_path)
- self._prim_xformOp_cache.add(attr_path)
-
- def _undo_xform_deltas(self, usd_notice, stage):
- if self._enabled:
- _undo_occurred = False
- # Only care about prims that have actually changed; not their subtrees
- attr_paths_changed = usd_notice.GetChangedInfoOnlyPaths()
- for attr_path in attr_paths_changed:
- if attr_path in self._prim_xformOp_cache:
- # Undo prim change
- self._usd_undo.undo()
- _undo_occurred = True
- if self._display_dialog and _undo_occurred:
- # Display dialog only once
- self._display_dialog = False
- self._display_dialog_callback()
diff --git a/source/extensions/lightspeed.lock_xform/premake5.lua b/source/extensions/lightspeed.lock_xform/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.lock_xform/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.paths_to_relative.core/config/extension.toml b/source/extensions/lightspeed.paths_to_relative.core/config/extension.toml
deleted file mode 100644
index 96e6c5fad..000000000
--- a/source/extensions/lightspeed.paths_to_relative.core/config/extension.toml
+++ /dev/null
@@ -1,42 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.3"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Damien Bataille "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Lightspeed Utils to translate paths to relative paths"
-description="A menu that can invoke the tool that convert paths to relative paths. It will convert 'locally to each layers'."
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.paths_to_relative.core"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["kit", "path", "relative", "absolute", "core"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
-icon = "data/icon.png"
-
-[dependencies]
-"lightspeed.error_popup.window" = {}
-"omni.client" = {}
-"omni.usd" = {}
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.paths_to_relative.core"
diff --git a/source/extensions/lightspeed.paths_to_relative.core/data/icon.png b/source/extensions/lightspeed.paths_to_relative.core/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.paths_to_relative.core/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.paths_to_relative.core/data/preview.png b/source/extensions/lightspeed.paths_to_relative.core/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.paths_to_relative.core/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.paths_to_relative.core/docs/CHANGELOG.md b/source/extensions/lightspeed.paths_to_relative.core/docs/CHANGELOG.md
deleted file mode 100644
index 99a8881c6..000000000
--- a/source/extensions/lightspeed.paths_to_relative.core/docs/CHANGELOG.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.3]
-### Changed
-- Changed repo link
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.1] - 2022-04-18
-### Changed
-- Moved python dependencies to lightspeed common
-### Fixed
-- Normalized Pixels
-
-## [0.1.0] - 2022-04-15
-### Added
-- Created
diff --git a/source/extensions/lightspeed.paths_to_relative.core/docs/README.md b/source/extensions/lightspeed.paths_to_relative.core/docs/README.md
deleted file mode 100644
index 9e49d2bc8..000000000
--- a/source/extensions/lightspeed.paths_to_relative.core/docs/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# lightspeed.paths_to_relative.core
-
-Convert all textures paths/mdl paths/reference paths to relative paths
diff --git a/source/extensions/lightspeed.paths_to_relative.core/docs/index.rst b/source/extensions/lightspeed.paths_to_relative.core/docs/index.rst
deleted file mode 100644
index 963f60e3e..000000000
--- a/source/extensions/lightspeed.paths_to_relative.core/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.paths_to_relative.core
-##################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.paths_to_relative.core
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.paths_to_relative.core/lightspeed/paths_to_relative/core/__init__.py b/source/extensions/lightspeed.paths_to_relative.core/lightspeed/paths_to_relative/core/__init__.py
deleted file mode 100644
index 4d01f78b3..000000000
--- a/source/extensions/lightspeed.paths_to_relative.core/lightspeed/paths_to_relative/core/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .paths_to_relative import * # noqa: F401
diff --git a/source/extensions/lightspeed.paths_to_relative.core/lightspeed/paths_to_relative/core/paths_to_relative.py b/source/extensions/lightspeed.paths_to_relative.core/lightspeed/paths_to_relative/core/paths_to_relative.py
deleted file mode 100644
index 897bacb5a..000000000
--- a/source/extensions/lightspeed.paths_to_relative.core/lightspeed/paths_to_relative/core/paths_to_relative.py
+++ /dev/null
@@ -1,332 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-import collections.abc
-import os
-from typing import Callable
-
-import carb
-import omni.client
-import omni.usd
-from pxr import Sdf, Usd, UsdUtils
-
-
-def deep_update_data(d, u): # noqa PLC0103
- for k, v in u.items(): # noqa PLC0103
- if isinstance(v, collections.abc.Mapping):
- d[k] = deep_update_data(d.get(k, {}), v)
- elif isinstance(v, list):
- d[k] = d.get(k, []) + v
- else:
- d[k] = v
- return d
-
-
-class PathsToRelative:
- @staticmethod
- def _ref_to_relative(chk, item):
- str_value = str(item.assetPath)
- # check if exist
- skip = False
- if not os.path.exists(str_value):
- # try to find the texture next to the usd or sub folder?
- base_name_text = os.path.basename(str_value)
- if base_name_text[-1:] == "@":
- base_name_text = base_name_text[:-1]
- skip = True
- for root, _, files in os.walk(os.path.dirname(chk)):
- for name in files:
- if name == base_name_text:
- str_value = os.path.join(root, name)
- skip = False
- break
- if not skip:
- break
- if not skip:
- # for whatever reason, this doesnt work. Need to use omni.client (?)
- # result = Sdf.ComputeAssetPathRelativeToLayer(layer, str_value)
- result = omni.client.make_relative_url(chk, str_value)
- return Sdf.Reference(
- assetPath=result,
- primPath=item.primPath,
- layerOffset=item.layerOffset,
- )
- return None
-
- @staticmethod # noqa C901
- @omni.usd.handle_exception
- async def convert_current_stage(
- context=None,
- progress_callback: Callable[[float], None] = None,
- scan_only: bool = True,
- only_data=None,
- show_print=True,
- ):
- def traverse_instanced_children(prim):
- for child in prim.GetFilteredChildren(Usd.PrimAllPrimsPredicate):
- yield child
- yield from traverse_instanced_children(child)
-
- usd_path_errors = {}
- mdl_path_errors = {}
- texture_path_errors = {}
-
- if context is None:
- context = omni.usd.get_context()
- stage = context.get_stage()
-
- usd = stage.GetRootLayer().identifier
- path = Sdf.AssetPath(usd)
- layers, _, _ = UsdUtils.ComputeAllDependencies(path)
- to_add = 100 / len(layers)
- global_progress = 0.0
- last_progress_int = 0
- if progress_callback:
- progress_callback(global_progress)
- doublon = {}
-
- data = {}
-
- save_errors = ""
-
- for layer in layers: # noqa PLR1702
- to_save_layer = False
- chk = layer.identifier
- # we skip the root layer if there are sublayers
- if chk == path and len(layers) > 1:
- continue
-
- if only_data and chk not in only_data:
- continue
-
- sub_stage = Usd.Stage.Open(chk)
- all_prims = list(traverse_instanced_children(sub_stage.GetPseudoRoot()))
-
- for prim in all_prims:
- if prim.GetTypeName() in ["Shader"]:
- if progress_callback:
- global_progress += to_add / len(all_prims)
- if int(global_progress) != last_progress_int:
- await asyncio.sleep(0.001)
- last_progress_int = int(global_progress)
- progress_callback(global_progress / 100)
-
- for attr in prim.GetAttributes():
-
- if only_data and str(attr.GetPath()) not in only_data[chk]:
- continue
-
- layers = [
- x.layer.identifier
- for x in attr.GetPropertyStack(Usd.TimeCode.Default())
- if x.layer.identifier.strip()
- ]
- if chk not in layers:
- # ignore things that are not overridden in the current layer or part of the current layer
- continue
-
- if attr.GetName() == "info:mdl:sourceAsset":
- if ":/" in str(attr.Get()):
- # Not relative path
- key = f"{chk}::{prim.GetPath().pathString}::{attr.GetName()}"
- mdl_path_errors[key] = f"ERROR: {attr.GetName()} has absolute MDL path: {attr.Get()}"
- result = os.path.basename(str(attr.Get()))
- if result[-1:] == "@":
- result = result[:-1]
- if show_print:
- carb.log_info(f"From layer {chk} {prim.GetPath().pathString}\n")
- carb.log_info(f" {attr.Get()}\n -->\n {result}\n" + "=" * 30)
- if not scan_only:
- attr.Set(result)
- deep_update_data(
- data, {chk: {"attr": {str(attr.GetPath()): {str(attr.Get()): result}}}}
- )
- to_save_layer = True
- if "\\" in str(attr.Get()):
- # Incorrect slash direction
- key = f"{chk}::{prim.GetPath().pathString}::{attr.GetName()}"
- mdl_path_errors[key] = (
- f"ERROR: {attr.GetName()} has incorrect slash(es). "
- f"Needs to be forward slash: {attr.Get()}"
- )
- result = os.path.basename(str(attr.Get()))
- if result[-1:] == "@":
- result = result[:-1]
- if show_print:
- carb.log_info(f"From layer {chk} {prim.GetPath().pathString}\n")
- carb.log_info(f" {attr.Get()}\n -->\n {result}\n" + "=" * 30)
- if not scan_only:
- attr.Set(result)
- deep_update_data(
- data, {chk: {"attr": {str(attr.GetPath()): {str(attr.Get()): result}}}}
- )
- to_save_layer = True
- else:
- if ":/" in str(attr.Get()):
- key = f"{chk}::{prim.GetPath().pathString}::{attr.GetName()}"
- texture_path_errors[key] = (
- f"ERROR: {attr.GetName()} has absolute asset path: {str(attr.Get())}"
- )
- str_value = str(attr.Get())
- # check if exist
- skip = False
- if not os.path.exists(str_value):
- # try to find the texture next to the usd or sub folder?
- base_name_text = os.path.basename(str_value)
- if base_name_text[-1:] == "@":
- base_name_text = base_name_text[:-1]
- skip = True
- for root, _, files in os.walk(os.path.dirname(chk)):
- for name in files:
- if name == base_name_text:
- str_value = os.path.join(root, name)
- skip = False
- break
- if not skip:
- break
- if not skip:
- # for whatever reason, this doesnt work. Need to use omni.client (?)
- # result = Sdf.ComputeAssetPathRelativeToLayer(layer, str_value)
- result = omni.client.make_relative_url(chk, str_value)
- if show_print:
- carb.log_info(f"From layer {chk} {prim.GetPath().pathString}\n")
- carb.log_info(f" {attr.Get()}\n -->\n {result}\n" + "=" * 30)
- if not scan_only:
- attr.Set(result)
- deep_update_data(
- data, {chk: {"attr": {str(attr.GetPath()): {str(attr.Get()): result}}}}
- )
- to_save_layer = True
- if result not in doublon:
- doublon[os.path.basename(result)] = [chk]
- else:
- doublon[os.path.basename(result)].append(chk)
- else: # can't find relative path
- if show_print:
- carb.log_info(f"From layer {chk}\n")
- carb.log_info(
- f" {attr.Get()}\n -->\n Can't find relative path\n" + "=" * 30
- )
- for primspec in prim.GetPrimStack():
- if not primspec:
- continue
- if not primspec.referenceList:
- continue
- if primspec.layer and primspec.layer.identifier != chk:
- # ignore things that are not overridden in the current layer or part of the current layer
- continue
- # Checking USDA
- items = primspec.referenceList.explicitItems
- result_items = []
- new_ref = False
- for item in items:
- if item is not None and ":/" in item.assetPath:
- if only_data and str(prim.GetPath().pathString) + str(item.assetPath) not in only_data[chk]:
- continue
- key = f"{chk}::{prim.GetPath().pathString}"
- usd_path_errors[key] = (
- f"ERROR: {prim.GetName()} has absolute reference path: {item.assetPath}"
- )
- result = PathsToRelative._ref_to_relative(chk, item)
- if result:
- result_items.append((item, result))
- new_ref = True
- if show_print:
- carb.log_info(f"From layer {chk} {prim.GetPath().pathString}\n")
- carb.log_info(f" {item.assetPath}\n -->\n {result.assetPath}\n" + "=" * 30)
- else: # can't find the relative path, keep
- result_items.append((item, item))
- else:
- result_items.append((item, item))
- if new_ref:
- to_save_layer = True
- if not scan_only:
- primspec.referenceList.explicitItems = [result_item[1] for result_item in result_items]
- deep_update_data(
- data,
- {
- chk: {
- "ref": {
- prim.GetPath().pathString: {
- primspec.referenceList.explicitItems: {
- result_item[0]: result_item[1] for result_item in result_items
- }
- }
- }
- }
- },
- )
-
- # Checking USD
- items = primspec.referenceList.prependedItems
- result_items = []
- new_ref = False
- for item in items:
- if item is not None and ":/" in item.assetPath:
- if only_data and str(prim.GetPath().pathString) + str(item.assetPath) not in only_data[chk]:
- continue
- key = f"{chk}::{prim.GetPath().pathString}"
- usd_path_errors[key] = (
- f"ERROR: {prim.GetName()} has absolute reference path: {item.assetPath}"
- )
-
- result = PathsToRelative._ref_to_relative(chk, item)
- if result:
- result_items.append((item, result))
- new_ref = True
- if show_print:
- carb.log_info(f"From layer {chk} {prim.GetPath().pathString}\n")
- carb.log_info(f" {item.assetPath}\n -->\n {result.assetPath}\n" + "=" * 30)
- else: # can't find the relative path, keep
- result_items.append((item, item))
- else:
- result_items.append((item, item))
- if new_ref:
- to_save_layer = True
- if show_print:
- carb.log_info(("5" * 50), to_save_layer, scan_only)
- if not scan_only:
- primspec.referenceList.prependedItems = [result_item[1] for result_item in result_items]
- deep_update_data(
- data,
- {
- chk: {
- "ref": {
- prim.GetPath().pathString: {
- primspec.referenceList.prependedItems: {
- result_item[0]: result_item[1] for result_item in result_items
- }
- }
- }
- }
- },
- )
-
- if to_save_layer and not scan_only:
- if show_print:
- carb.log_info(f"Save layer {chk}")
- try:
- sub_stage.Save()
- except Exception: # noqa PLW0703
- save_errors += f"Can't save {chk}. Read only?\n"
- for tex, lays in doublon.items():
- if len(lays) > 1 and show_print:
- carb.log_info(("Doublon", tex, lays))
- # reload
- await context.open_stage_async(usd)
- return data, save_errors
diff --git a/source/extensions/lightspeed.paths_to_relative.core/premake5.lua b/source/extensions/lightspeed.paths_to_relative.core/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.paths_to_relative.core/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.paths_to_relative.menu/config/extension.toml b/source/extensions/lightspeed.paths_to_relative.menu/config/extension.toml
deleted file mode 100644
index 69ec1be0e..000000000
--- a/source/extensions/lightspeed.paths_to_relative.menu/config/extension.toml
+++ /dev/null
@@ -1,43 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.3"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Damien Bataille "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Lightspeed Utils to translate paths to relative paths"
-description="A menu that can invoke the tool that convert paths to relative paths. It will convert 'locally to each layers'."
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.paths_to_relative.menu"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["kit", "path", "relative", "absolute", "menu"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
-icon = "data/icon.png"
-
-[dependencies]
-"omni.kit.menu.utils" = {}
-"lightspeed.paths_to_relative.window" = {}
-
-
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.paths_to_relative.menu"
diff --git a/source/extensions/lightspeed.paths_to_relative.menu/data/icon.png b/source/extensions/lightspeed.paths_to_relative.menu/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.paths_to_relative.menu/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.paths_to_relative.menu/data/preview.png b/source/extensions/lightspeed.paths_to_relative.menu/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.paths_to_relative.menu/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.paths_to_relative.menu/docs/CHANGELOG.md b/source/extensions/lightspeed.paths_to_relative.menu/docs/CHANGELOG.md
deleted file mode 100644
index 05aa1d005..000000000
--- a/source/extensions/lightspeed.paths_to_relative.menu/docs/CHANGELOG.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.3]
-### Changed
-- Changed repo link
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-07-28
-### Added
-- Created
diff --git a/source/extensions/lightspeed.paths_to_relative.menu/docs/README.md b/source/extensions/lightspeed.paths_to_relative.menu/docs/README.md
deleted file mode 100644
index bd71731bf..000000000
--- a/source/extensions/lightspeed.paths_to_relative.menu/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.paths_to_relative.menu
diff --git a/source/extensions/lightspeed.paths_to_relative.menu/docs/index.rst b/source/extensions/lightspeed.paths_to_relative.menu/docs/index.rst
deleted file mode 100644
index 896187ec1..000000000
--- a/source/extensions/lightspeed.paths_to_relative.menu/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.paths_to_relative.menu
-##################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.paths_to_relative.menu
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.paths_to_relative.menu/lightspeed/paths_to_relative/menu/__init__.py b/source/extensions/lightspeed.paths_to_relative.menu/lightspeed/paths_to_relative/menu/__init__.py
deleted file mode 100644
index 084e7bbe3..000000000
--- a/source/extensions/lightspeed.paths_to_relative.menu/lightspeed/paths_to_relative/menu/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .menu import * # noqa: F401
diff --git a/source/extensions/lightspeed.paths_to_relative.menu/lightspeed/paths_to_relative/menu/menu.py b/source/extensions/lightspeed.paths_to_relative.menu/lightspeed/paths_to_relative/menu/menu.py
deleted file mode 100644
index b7f70926c..000000000
--- a/source/extensions/lightspeed.paths_to_relative.menu/lightspeed/paths_to_relative/menu/menu.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-
-import omni.ext
-import omni.kit.menu.utils as omni_utils
-import omni.usd
-from lightspeed.paths_to_relative.window import get_instance
-from omni.kit.menu.utils import MenuItemDescription
-
-
-class LightspeedColorToNormalMenuExtension(omni.ext.IExt):
- def on_startup(self, ext_id):
- self.__create_save_menu()
-
- def __create_save_menu(self):
- self._tools_manager_menus = [
- MenuItemDescription(
- name="Toggle paths to relative paths window",
- onclick_fn=self.__clicked,
- glyph="none.svg",
- )
- ]
- omni_utils.add_menu_items(self._tools_manager_menus, "Utils")
-
- def on_shutdown(self):
- omni_utils.remove_menu_items(self._tools_manager_menus, "Batch Tools")
-
- @omni.usd.handle_exception
- async def _show(self):
- get_instance().toggle_window()
-
- def __clicked(self):
- asyncio.ensure_future(self._show())
diff --git a/source/extensions/lightspeed.paths_to_relative.menu/premake5.lua b/source/extensions/lightspeed.paths_to_relative.menu/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.paths_to_relative.menu/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.paths_to_relative.window/config/extension.toml b/source/extensions/lightspeed.paths_to_relative.window/config/extension.toml
deleted file mode 100644
index dc88b32fb..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/config/extension.toml
+++ /dev/null
@@ -1,43 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.3"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Damien Bataille "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Lightspeed Utils to translate paths to relative paths"
-description="A menu that can invoke the tool that convert paths to relative paths. It will convert 'locally to each layers'."
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.paths_to_relative.window"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["kit", "path", "relative", "absolute", "window"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
-icon = "data/icon.png"
-
-[dependencies]
-"lightspeed.paths_to_relative.core" = {}
-"lightspeed.progress_popup.window" = {}
-"omni.flux.utils.common" = {}
-"omni.usd" = {}
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.paths_to_relative.window"
diff --git a/source/extensions/lightspeed.paths_to_relative.window/data/icon.png b/source/extensions/lightspeed.paths_to_relative.window/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.paths_to_relative.window/data/icons/Minus.svg b/source/extensions/lightspeed.paths_to_relative.window/data/icons/Minus.svg
deleted file mode 100644
index 6bb6ed58e..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/data/icons/Minus.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:69fbb4deb00c352a9a86d68b03f7826ece90816ebfcf6665289e261ae67765e5
-size 2632
diff --git a/source/extensions/lightspeed.paths_to_relative.window/data/icons/Plus.svg b/source/extensions/lightspeed.paths_to_relative.window/data/icons/Plus.svg
deleted file mode 100644
index bf6b6420a..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/data/icons/Plus.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:34c894b8de50d5d1573e6eafa3b8ea8545cae3c4288d9708d5d8b6fb6f4f2501
-size 2937
diff --git a/source/extensions/lightspeed.paths_to_relative.window/data/preview.png b/source/extensions/lightspeed.paths_to_relative.window/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.paths_to_relative.window/docs/CHANGELOG.md b/source/extensions/lightspeed.paths_to_relative.window/docs/CHANGELOG.md
deleted file mode 100644
index 99a8881c6..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/docs/CHANGELOG.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.3]
-### Changed
-- Changed repo link
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.1] - 2022-04-18
-### Changed
-- Moved python dependencies to lightspeed common
-### Fixed
-- Normalized Pixels
-
-## [0.1.0] - 2022-04-15
-### Added
-- Created
diff --git a/source/extensions/lightspeed.paths_to_relative.window/docs/README.md b/source/extensions/lightspeed.paths_to_relative.window/docs/README.md
deleted file mode 100644
index 763e0bac5..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/docs/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# lightspeed.paths_to_relative.window
-
-Convert all textures paths/mdl paths/reference paths to relative paths
diff --git a/source/extensions/lightspeed.paths_to_relative.window/docs/index.rst b/source/extensions/lightspeed.paths_to_relative.window/docs/index.rst
deleted file mode 100644
index a79be974e..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.paths_to_relative.window
-####################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.paths_to_relative.window
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/__init__.py b/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/__init__.py
deleted file mode 100644
index 5fc560efe..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .extension import * # noqa F401
diff --git a/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/extension.py b/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/extension.py
deleted file mode 100644
index 7061c758b..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/extension.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import carb
-import omni.ext
-from omni.flux.utils.common import reset_default_attrs as _reset_default_attrs
-
-from .setup_ui import PathsToRelativeWindow
-
-_INSTANCE = None
-
-
-def get_instance():
- """Expose the created instance of the tool"""
- return _INSTANCE
-
-
-class PathsToRelativesExtension(omni.ext.IExt):
- """Standard extension support class, necessary for extension management"""
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.default_attr = {}
- for attr, value in self.default_attr.items():
- setattr(self, attr, value)
-
- def on_startup(self, ext_id):
- global _INSTANCE
- carb.log_info("[lightspeed.paths_to_relative.window] startup")
- _INSTANCE = PathsToRelativeWindow()
-
- def on_shutdown(self):
- global _INSTANCE
- _reset_default_attrs(self)
- _INSTANCE.destroy()
- _INSTANCE = None
diff --git a/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/setup_ui.py b/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/setup_ui.py
deleted file mode 100644
index ecbaaa77d..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/setup_ui.py
+++ /dev/null
@@ -1,134 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-
-import omni.ui as ui
-import omni.usd
-from lightspeed.error_popup.window import ErrorPopup
-from lightspeed.paths_to_relative.core import PathsToRelative, deep_update_data
-from lightspeed.progress_popup.window import ProgressPopup
-from omni.flux.utils.common import reset_default_attrs as _reset_default_attrs
-
-from .tree import delegate, model
-
-
-class PathsToRelativeWindow:
- def __init__(self):
- self.__default_attr = {
- "_core": None,
- "_model": None,
- "_delegate": None,
- "_window": None,
- "_tree": None,
- "_progress_bar": None,
- "_error_popup": None,
- }
- for attr, value in self.__default_attr.items():
- setattr(self, attr, value)
-
- self._core = PathsToRelative()
- self._delegate = delegate.Delegate()
- self._model = model.ListModel()
-
- self.__create_ui()
-
- def __create_ui(self):
- """Create the main UI"""
- window_name = "Paths to relative window"
- self._window = ui.Window(window_name, name=window_name, width=1280, height=600, visible=False)
-
- with self._window.frame:
- with ui.VStack():
- ui.Button("Scan current stage (included all dependencies)", clicked_fn=self._scan, height=24)
- with ui.ScrollingFrame(
- horizontal_scrollbar_policy=ui.ScrollBarPolicy.SCROLLBAR_ALWAYS_OFF,
- vertical_scrollbar_policy=ui.ScrollBarPolicy.SCROLLBAR_ALWAYS_ON,
- style_type_name_override="TreeView",
- ):
- self._tree = ui.TreeView(
- self._model,
- delegate=self._delegate,
- root_visible=False,
- header_visible=True,
- columns_resizable=True,
- column_widths=[ui.Pixel(90), ui.Percent(70), ui.Percent(30)],
- )
- ui.Button("Fix it!", clicked_fn=self._fix, height=24)
-
- def _batch_upscale_set_progress(self, progress):
- if not self._progress_bar:
- self._progress_bar = ProgressPopup(title="Scanning")
- self._progress_bar.show()
- self._progress_bar.set_progress(progress)
-
- @omni.usd.handle_exception
- async def _run_batch_convert(self, scan_only=True):
- def grab_data(item):
- data = {}
- if not item.enabled:
- return data
- if item.children:
- for child in item.children:
- deep_update_data(data, grab_data(child))
- else:
- deep_update_data(data, {item.stage_path: [item.attr_path]})
- return data
-
- if not self._progress_bar:
- self._progress_bar = ProgressPopup(title="Scanning" if scan_only else "Fixing")
- self._progress_bar.set_progress(0)
- self._progress_bar.show()
-
- data = None
- if not scan_only:
- # grab enabled stuff
- data = {}
- for item in self._model.get_item_children(None):
- deep_update_data(data, grab_data(item))
-
- await asyncio.sleep(0.01)
-
- result, errors_messages = await PathsToRelative.convert_current_stage(
- progress_callback=self._batch_upscale_set_progress, scan_only=scan_only, only_data=data
- )
- if scan_only:
- self._model.refresh(result)
- else:
- # we re-scan after the fix to update the UI
- await self._run_batch_convert()
-
- if self._progress_bar:
- self._progress_bar.hide()
- self._progress_bar = None
-
- if errors_messages:
- self._error_popup = ErrorPopup("Errors!", "There are some errors:", errors_messages)
- self._error_popup.show()
-
- def _scan(self):
- asyncio.ensure_future(self._run_batch_convert())
-
- def _fix(self):
- asyncio.ensure_future(self._run_batch_convert(scan_only=False))
-
- def toggle_window(self):
- if self._window:
- self._window.visible = not self._window.visible
-
- def destroy(self):
- _reset_default_attrs(self)
diff --git a/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/tree/__init__.py b/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/tree/__init__.py
deleted file mode 100644
index 2a4b35b86..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/tree/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
diff --git a/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/tree/delegate.py b/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/tree/delegate.py
deleted file mode 100644
index c3047b029..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/tree/delegate.py
+++ /dev/null
@@ -1,126 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import functools
-import os
-
-import omni.ui as ui
-
-from .model import HEADER_DICT
-
-_ICONS_DIR = os.path.dirname(__file__)
-for _ in range(4):
- _ICONS_DIR = os.path.dirname(_ICONS_DIR)
-
-_ICONS_DIR = os.path.join(_ICONS_DIR, "data", "icons")
-_DICT_ICONS = {
- "plus": os.path.join(_ICONS_DIR, "Plus.svg"),
- "minus": os.path.join(_ICONS_DIR, "Minus.svg"),
-}
-
-
-class Delegate(ui.AbstractItemDelegate):
- """Delegate of the action lister"""
-
- def __init__(self):
- super().__init__()
- self.__checkbox_widgets = {}
- self.__ignore_checkbox = False
-
- def build_branch(self, model, item, column_id, level, expanded):
- """Create a branch widget that opens or closes subtree"""
- if column_id == 0:
- with ui.HStack(width=16 * (level + 2), height=0):
- ui.Spacer()
- if model.can_item_have_children(item):
- # Draw the +/- icon
- image_name = "minus" if expanded else "plus"
- ui.Image(
- _DICT_ICONS[image_name],
- width=10,
- height=10,
- style_type_name_override="TreeView.Item",
- )
- ui.Spacer(width=4)
-
- # noinspection PyUnusedLocal
- def build_widget(self, model, item, column_id, level, expanded):
- """Create a widget per item"""
- if item is None:
- return
- if column_id == 0:
- checkbox = ui.CheckBox()
- checkbox.model.set_value(item.enabled)
- checkbox.model.add_value_changed_fn(functools.partial(self._on_enabled_changed, item))
- self.__checkbox_widgets[id(item)] = checkbox
- elif column_id == 1:
- if item.children and item.data_type == "stage":
- ui.Label(item.stage_path, style_type_name_override="TreeView.Item")
- elif item.children and item.data_type != "stage":
- ui.Label(item.attr_path, style_type_name_override="TreeView.Item")
- else:
- ui.Label(item.display_old_path, style_type_name_override="TreeView.Item")
- elif column_id == 2 and not item.children:
- with ui.HStack():
- ui.Spacer(width=16)
- ui.Label(item.display_new_path, style_type_name_override="TreeView.Item")
-
- def _on_enabled_changed(self, item, model):
- def has_child_enabled(t_item):
- for child in t_item.children:
- if child.enabled:
- return True
- if child.children and has_child_enabled(child):
- return True
- return False
-
- def enable_all_children(item, value):
- item.enabled = value
- if id(item) in self.__checkbox_widgets:
- self.__checkbox_widgets[id(item)].model.set_value(value)
- for child in item.children:
- enable_all_children(child, value)
-
- def enable_all_parent(item, value):
- if not value and has_child_enabled(item):
- value = True
- item.enabled = value
- if id(item) in self.__checkbox_widgets:
- self.__checkbox_widgets[id(item)].model.set_value(value)
- if item.parent:
- enable_all_parent(item.parent, value)
-
- if self.__ignore_checkbox:
- return
- self.__ignore_checkbox = True
- value = model.get_value_as_bool()
- item.enabled = value
- for child in item.children:
- enable_all_children(child, value)
- if item.parent:
- enable_all_parent(item.parent, value)
- self.__ignore_checkbox = False
-
- def build_header(self, column_id):
- """Build the header"""
- style_type_name = "TreeView.Header"
- with ui.HStack():
- ui.Label(HEADER_DICT[column_id], style_type_name_override=style_type_name)
-
- def destroy(self):
- super().destroy()
- self.__checkbox_widgets = None
diff --git a/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/tree/model.py b/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/tree/model.py
deleted file mode 100644
index 92567a68f..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/lightspeed/paths_to_relative/window/tree/model.py
+++ /dev/null
@@ -1,127 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 typing import Dict
-
-import omni.ui as ui
-from omni.flux.utils.common import reset_default_attrs as _reset_default_attrs
-
-HEADER_DICT = {0: "Enabled", 1: "Old Path", 2: "New Path"}
-
-
-class Item(ui.AbstractItem):
- """Item of the model"""
-
- def __init__(
- self, stage_path, attr_path, old_path, display_old_path, new_path, display_new_path, children, parent, data_type
- ):
- super().__init__()
- self.enabled = False
- self.attr_path = attr_path
- self.data_type = data_type
- self.stage_path = stage_path
- self.old_path = old_path
- self.display_old_path = display_old_path
- self.new_path = new_path
- self.display_new_path = display_new_path
- self.children = children
- self.parent = parent
- self.stage_path_model = ui.SimpleStringModel(self.stage_path)
-
- def __repr__(self):
- return f'"{self.path}"'
-
-
-class ListModel(ui.AbstractItemModel):
- """List model of actions"""
-
- def __init__(self):
- super().__init__()
- self.default_attr = {}
- for attr, value in self.default_attr.items():
- setattr(self, attr, value)
- self.__children = []
-
- def refresh(self, data: Dict):
- """Refresh the list"""
- items = []
- for stage_path, data_types in data.items(): # noqa PLR1702
- children = []
- stage_item = Item(stage_path, None, None, None, None, None, children, None, "stage")
- for data_type, data1 in data_types.items():
- if data_type == "attr":
- for attr_path, attr_data in data1.items():
- child_tex = []
- parent = Item(stage_path, attr_path, None, None, None, None, child_tex, stage_item, data_type)
- for old_path, new_path in attr_data.items():
- child_tex.append(
- Item(
- stage_path, attr_path, old_path, old_path, new_path, new_path, [], parent, data_type
- )
- )
- parent.children = child_tex
- children.append(parent)
- elif data_type == "ref":
- for prim_path, ref_data in data1.items():
- ref_children = []
- parent = Item(
- stage_path, prim_path, None, None, None, None, ref_children, stage_item, data_type
- )
- for _ref_type, ref_path_data in ref_data.items():
- for old_ref, new_ref in ref_path_data.items():
- ref_children.append(
- Item(
- stage_path,
- str(prim_path) + str(old_ref.assetPath),
- old_ref,
- old_ref.assetPath,
- new_ref,
- new_ref.assetPath,
- [],
- parent,
- data_type,
- )
- )
- parent.children = ref_children
- children.append(parent)
- stage_item.children = children
- items.append(stage_item)
- self.__children = items
- self._item_changed(None)
-
- def get_item_children(self, item):
- """Returns all the children when the widget asks it."""
- if item is None:
- return self.__children
- return item.children
-
- def get_item_value_model_count(self, item):
- """The number of columns"""
- return len(HEADER_DICT.keys())
-
- def get_item_value_model(self, item, column_id):
- """
- Return value model.
- It's the object that tracks the specific value.
- In our case we use ui.SimpleStringModel.
- """
- if column_id == 0:
- return item.stage_path_model
- return None
-
- def destroy(self):
- _reset_default_attrs(self)
diff --git a/source/extensions/lightspeed.paths_to_relative.window/premake5.lua b/source/extensions/lightspeed.paths_to_relative.window/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.paths_to_relative.window/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.stage_column_nickname/config/extension.toml b/source/extensions/lightspeed.stage_column_nickname/config/extension.toml
deleted file mode 100644
index 249805f85..000000000
--- a/source/extensions/lightspeed.stage_column_nickname/config/extension.toml
+++ /dev/null
@@ -1,43 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.4"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Alexander Jaus "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Lightspeed Nickname Stage Column"
-description="Adds a nickname column to the stage window."
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.stage_column_nickname"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["stage", "nickname", "lightspeed", "lss"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-icon = "data/icon.png"
-
-[dependencies]
-"omni.kit.widget.stage" = {}
-"lightspeed.layer_manager.core" = {}
-"lightspeed.common" = {}
-"omni.kit.commands" = {}
-"omni.ui" = {}
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.stage_column_nickname"
diff --git a/source/extensions/lightspeed.stage_column_nickname/data/icon.png b/source/extensions/lightspeed.stage_column_nickname/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.stage_column_nickname/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.stage_column_nickname/data/preview.png b/source/extensions/lightspeed.stage_column_nickname/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.stage_column_nickname/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.stage_column_nickname/docs/CHANGELOG.md b/source/extensions/lightspeed.stage_column_nickname/docs/CHANGELOG.md
deleted file mode 100644
index d4b9ec697..000000000
--- a/source/extensions/lightspeed.stage_column_nickname/docs/CHANGELOG.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.4]
-### Changed
-- Changed repo link
-
-## [0.1.3]
-- Use updated `lightspeed.layer_manager.core` extension
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed.stage_column_nickname/docs/README.md b/source/extensions/lightspeed.stage_column_nickname/docs/README.md
deleted file mode 100644
index 1a337f86e..000000000
--- a/source/extensions/lightspeed.stage_column_nickname/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.stage_column_nickname
diff --git a/source/extensions/lightspeed.stage_column_nickname/docs/index.rst b/source/extensions/lightspeed.stage_column_nickname/docs/index.rst
deleted file mode 100644
index 81cc38168..000000000
--- a/source/extensions/lightspeed.stage_column_nickname/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.stage_column_nickname
-#################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.stage_column_nickname
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.stage_column_nickname/lightspeed/stage_column_nickname/__init__.py b/source/extensions/lightspeed.stage_column_nickname/lightspeed/stage_column_nickname/__init__.py
deleted file mode 100644
index c8ecd2592..000000000
--- a/source/extensions/lightspeed.stage_column_nickname/lightspeed/stage_column_nickname/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .extension import * # noqa: F401
diff --git a/source/extensions/lightspeed.stage_column_nickname/lightspeed/stage_column_nickname/extension.py b/source/extensions/lightspeed.stage_column_nickname/lightspeed/stage_column_nickname/extension.py
deleted file mode 100644
index ee8dbe28c..000000000
--- a/source/extensions/lightspeed.stage_column_nickname/lightspeed/stage_column_nickname/extension.py
+++ /dev/null
@@ -1,31 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import omni.ext
-from omni.kit.widget.stage.stage_column_delegate_registry import StageColumnDelegateRegistry
-
-from .nickname_delegate import NicknameStageColumnDelegate
-
-
-class StageNicknameWidgetExtension(omni.ext.IExt):
- def on_startup(self, ext_id):
- self._nickname_column_sub = StageColumnDelegateRegistry().register_column_delegate(
- "Nickname", NicknameStageColumnDelegate
- )
-
- def on_shutdown(self):
- self._nickname_column_sub = None
diff --git a/source/extensions/lightspeed.stage_column_nickname/lightspeed/stage_column_nickname/nickname_delegate.py b/source/extensions/lightspeed.stage_column_nickname/lightspeed/stage_column_nickname/nickname_delegate.py
deleted file mode 100644
index 80697aff3..000000000
--- a/source/extensions/lightspeed.stage_column_nickname/lightspeed/stage_column_nickname/nickname_delegate.py
+++ /dev/null
@@ -1,114 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 typing import Optional
-
-import omni.ui as ui
-from lightspeed.common import constants
-from omni.kit.widget.stage.abstract_stage_column_delegate import AbstractStageColumnDelegate, StageColumnItem
-from omni.kit.widget.stage.usd_property_watch import UsdPropertyWatch, UsdPropertyWatchModel
-from pxr import Sdf, UsdGeom, UsdShade
-
-
-class UsdNicknameWatchModel(UsdPropertyWatchModel):
- """The value model that is reimplemented in Python to watch the visibility of the selection"""
-
- def __init__(self, stage, path):
- """
- ## Arguments:
- `stage`: USD Stage
- `path`: The full path to the watched property
- """
- UsdPropertyWatchModel.__init__(self, stage, path)
- if not self._path: # noqa PLE0203
- self._path = path
-
- def get_value_as_string(self) -> str:
- """Reimplemented get string"""
- prop = self._get_prop()
- if prop:
- return prop.Get()
- return ""
-
- def set_value(self, value: str):
- """Reimplemented set string"""
- if self._path:
- prop = self._get_prop()
- if not prop:
- prim = self._get_stage().GetPrimAtPath(self._path.GetPrimPath())
- prop = prim.CreateAttribute(constants.LSS_NICKNAME, Sdf.ValueTypeNames.String)
- prop.Set(value)
-
-
-class NicknameStageColumnDelegate(AbstractStageColumnDelegate):
- """The column delegate that represents the nickname column"""
-
- def __init__(self):
- super().__init__()
- self._nickname_watch: Optional[UsdPropertyWatch] = None
-
- def destroy(self):
- if self._nickname_watch:
- self._nickname_watch.destroy()
- self._nickname_watch = None
-
- @property
- def initial_width(self):
- """The width of the column"""
- return ui.Pixel(256)
-
- def build_header(self):
- """Build the header"""
- with ui.HStack():
- ui.Spacer()
- with ui.VStack(width=0):
- ui.Spacer()
- ui.Label("Nickname", name="nickname_column_label")
- ui.Spacer()
- ui.Spacer()
-
- def _on_label_click(self, label, field):
- label.visible = False
- field.visible = True
-
- async def build_widget(self, item: StageColumnItem):
- """Build the widget"""
- if not item or not item.stage:
- return
-
- prim = item.stage.GetPrimAtPath(item.path)
- if not prim or not prim.IsValid() or not (prim.IsA(UsdGeom.Xform) or (prim.IsA(UsdShade.Material))):
- return
-
- if self._nickname_watch is None:
- self._nickname_watch = UsdPropertyWatch(
- item.stage, constants.LSS_NICKNAME, model_type=UsdNicknameWatchModel
- )
-
- watch_model = self._nickname_watch.get_model(item.path)
-
- text = watch_model.get_value_as_string()
- if not text:
- text = ""
- stack = ui.ZStack(height=20)
- with stack:
- ui.Spacer(width=1)
- label = ui.Label(text, width=0, name=text + "_label_name", style_type_name_override="TreeView.Item")
- string_field = ui.StringField(model=watch_model, name=text + "_label_name", visible=False)
- stack.set_mouse_pressed_fn(lambda x, y, b, _: self._on_label_click(label, string_field))
- # Min size
- ui.Spacer(width=1)
diff --git a/source/extensions/lightspeed.stage_column_nickname/premake5.lua b/source/extensions/lightspeed.stage_column_nickname/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.stage_column_nickname/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.tool.material.widget/config/extension.toml b/source/extensions/lightspeed.tool.material.widget/config/extension.toml
deleted file mode 100644
index 5eb54856e..000000000
--- a/source/extensions/lightspeed.tool.material.widget/config/extension.toml
+++ /dev/null
@@ -1,53 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "1.0.4"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Alex Dunn ", "Damien Bataille ", "Pierre-Olivier Trottier "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Lightspeed Tool Material Widget"
-description="Add tools related to materials."
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.setup"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["lightspeed", "material", "tool", "widget"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
-icon = "data/icon.png"
-
-[dependencies]
-"omni.ui" = {}
-"omni.usd" = {}
-"lightspeed.common" = {}
-"lightspeed.error_popup.window" = {}
-"lightspeed.layer_helpers" = {}
-"lightspeed.progress_popup.window" = {}
-"lightspeed.upscale.core" = {}
-"lightspeed.tool.material.core" = {}
-"omni.kit.window.toolbar" = {}
-
-[[python.module]]
-name = "lightspeed.tool.material.widget"
-
-[[test]]
-stdoutFailPatterns.exclude = [
- "*[gpu.foundation.plugin] Failed to*",
- "*[omni.kit.registry.nucleus.utils.common] Skipping deletion of:*",
-]
diff --git a/source/extensions/lightspeed.tool.material.widget/data/icon.png b/source/extensions/lightspeed.tool.material.widget/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.tool.material.widget/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.tool.material.widget/data/preview.png b/source/extensions/lightspeed.tool.material.widget/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.tool.material.widget/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.tool.material.widget/data/toolbar_glass_material.png b/source/extensions/lightspeed.tool.material.widget/data/toolbar_glass_material.png
deleted file mode 100644
index da59966ab..000000000
--- a/source/extensions/lightspeed.tool.material.widget/data/toolbar_glass_material.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:125a429f77d8b819e45869e498d7364a9ef6f915a2516237bb800ec120c1dead
-size 1793
diff --git a/source/extensions/lightspeed.tool.material.widget/data/toolbar_glass_material_disabled.png b/source/extensions/lightspeed.tool.material.widget/data/toolbar_glass_material_disabled.png
deleted file mode 100644
index f88dd8803..000000000
--- a/source/extensions/lightspeed.tool.material.widget/data/toolbar_glass_material_disabled.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:ef42af1ca5a5f5d4304d03294a38159b2d6f560f0e59bbfbd82472b28310b289
-size 1590
diff --git a/source/extensions/lightspeed.tool.material.widget/data/toolbar_opaque_material.png b/source/extensions/lightspeed.tool.material.widget/data/toolbar_opaque_material.png
deleted file mode 100644
index 25c9ae0a2..000000000
--- a/source/extensions/lightspeed.tool.material.widget/data/toolbar_opaque_material.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:4aef34c940d708e7d3da995d84397fda6c58ebfac0d5fc82bcf2806699f10dcd
-size 1242
diff --git a/source/extensions/lightspeed.tool.material.widget/data/toolbar_opaque_material_disabled.png b/source/extensions/lightspeed.tool.material.widget/data/toolbar_opaque_material_disabled.png
deleted file mode 100644
index 58b0821bc..000000000
--- a/source/extensions/lightspeed.tool.material.widget/data/toolbar_opaque_material_disabled.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:52321e07cfacae0f8be73ea6502c3e51d5f12119497478d0e30b7f858a8d31b8
-size 941
diff --git a/source/extensions/lightspeed.tool.material.widget/data/toolbar_upscale_material.png b/source/extensions/lightspeed.tool.material.widget/data/toolbar_upscale_material.png
deleted file mode 100644
index b8b17c0b1..000000000
--- a/source/extensions/lightspeed.tool.material.widget/data/toolbar_upscale_material.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:756bcd7592880a3de9258b90eede80e7fc9292b2926052202e46bb32216bc9fc
-size 15427
diff --git a/source/extensions/lightspeed.tool.material.widget/data/toolbar_upscale_material_disabled.png b/source/extensions/lightspeed.tool.material.widget/data/toolbar_upscale_material_disabled.png
deleted file mode 100644
index a88a5380f..000000000
--- a/source/extensions/lightspeed.tool.material.widget/data/toolbar_upscale_material_disabled.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:1e329d2a24a7be2e4013c0ffc8152398b06c032b2e3ae9f141f8c566a6bcc163
-size 5980
diff --git a/source/extensions/lightspeed.tool.material.widget/docs/CHANGELOG.md b/source/extensions/lightspeed.tool.material.widget/docs/CHANGELOG.md
deleted file mode 100644
index e02b152c6..000000000
--- a/source/extensions/lightspeed.tool.material.widget/docs/CHANGELOG.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [1.0.4]
-### Fixed
-- Fixed tests flakiness
-
-## [1.0.3]
-### Changed
-- Changed repo link
-
-## [1.0.2]
-### Changed
-- Update to Kit 106
-
-## [1.0.1]
-### Changed
-- Set Apache 2 license headers
-
-## [1.0.0] - 2024-02-28
-### Added
-- Created
diff --git a/source/extensions/lightspeed.tool.material.widget/docs/README.md b/source/extensions/lightspeed.tool.material.widget/docs/README.md
deleted file mode 100644
index f5969690c..000000000
--- a/source/extensions/lightspeed.tool.material.widget/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.tool.material.widget
diff --git a/source/extensions/lightspeed.tool.material.widget/docs/index.rst b/source/extensions/lightspeed.tool.material.widget/docs/index.rst
deleted file mode 100644
index 984e7f2dc..000000000
--- a/source/extensions/lightspeed.tool.material.widget/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.tool.material.widget
-################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.tool.material.widget
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager,partial
diff --git a/source/extensions/lightspeed.tool.material.widget/lightspeed/tool/material/widget/__init__.py b/source/extensions/lightspeed.tool.material.widget/lightspeed/tool/material/widget/__init__.py
deleted file mode 100644
index 7307c22d1..000000000
--- a/source/extensions/lightspeed.tool.material.widget/lightspeed/tool/material/widget/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .extension import LightspeedSetupExtension
-from .ui import MaterialButtonGroup, MaterialButtons
diff --git a/source/extensions/lightspeed.tool.material.widget/lightspeed/tool/material/widget/extension.py b/source/extensions/lightspeed.tool.material.widget/lightspeed/tool/material/widget/extension.py
deleted file mode 100644
index 0a7d63530..000000000
--- a/source/extensions/lightspeed.tool.material.widget/lightspeed/tool/material/widget/extension.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import carb
-import omni.ext
-import omni.kit.app
-import omni.kit.window.toolbar
-
-from .ui import MaterialButtonGroup
-
-
-class LightspeedSetupExtension(omni.ext.IExt):
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self._material_tools = None
-
- def on_startup(self, ext_id):
- carb.log_info("[lightspeed.tool.material] Lightspeed Tool Material startup")
- toolbar = omni.kit.window.toolbar.toolbar.get_instance()
- # add material tools
- self._material_tools = MaterialButtonGroup()
- toolbar.add_widget(self._material_tools, 100)
-
- def on_shutdown(self):
- carb.log_info("[lightspeed.tool.material] Lightspeed Tool Material startup")
- # cleanup the toolbar
- toolbar = omni.kit.window.toolbar.toolbar.get_instance()
- if toolbar and self._material_tools:
- toolbar.remove_widget(self._material_tools)
- self._material_tools = None
diff --git a/source/extensions/lightspeed.tool.material.widget/lightspeed/tool/material/widget/ui.py b/source/extensions/lightspeed.tool.material.widget/lightspeed/tool/material/widget/ui.py
deleted file mode 100644
index e24dbc22b..000000000
--- a/source/extensions/lightspeed.tool.material.widget/lightspeed/tool/material/widget/ui.py
+++ /dev/null
@@ -1,265 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-from functools import partial
-from pathlib import Path
-from typing import List
-
-import carb
-import omni.ui as ui
-import omni.usd
-from lightspeed.common import constants
-from lightspeed.error_popup.window import ErrorPopup
-from lightspeed.layer_helpers import LightspeedTextureProcessingCore
-from lightspeed.progress_popup.window import ProgressPopup
-from lightspeed.tool.material.core import ToolMaterialCore
-from lightspeed.upscale.core import UpscaleModels, UpscalerCore
-from omni.kit.window.toolbar.widget_group import WidgetGroup
-from pxr import UsdShade
-
-
-class MaterialButtons:
- def __init__(self, force_material_paths: List[str] = None, enable_stage_event=False):
- """Add new tools in the toolbar:
- - Convert to Opaque Material
- - Convert to Translucent Material
- - Upscale all textures on selected materials
- """
- super().__init__()
- self._opaque_button = None
- self._translucent_button = None
- self._upscale_button = None
- self._core = ToolMaterialCore()
- self._upscale_progress_bar = None
- self._force_material_paths = [] if force_material_paths is None else force_material_paths
- self._stage_event = None
- if enable_stage_event:
- self._stage_event = (
- omni.usd.get_context()
- .get_stage_event_stream()
- .create_subscription_to_pop(self._on_stage_event, name="[lightspeed.tool.material] Stage Event")
- )
-
- def _on_stage_event(self, event):
- if event.type == int(omni.usd.StageEventType.SELECTION_CHANGED):
- self.refresh_buttons_stat()
-
- def set_force_material_paths(self, paths: List[str]):
- self._force_material_paths = paths
-
- def clean(self):
- self._core = None
- self._upscale_progress_bar = None
- self._stage_event = None
- self._opaque_button = None
- self._translucent_button = None
- self._upscale_button = None
-
- def _material_upscale_set_progress(self, progress):
- self._upscale_progress_bar.set_progress(progress)
-
- async def _run_material_upscale(self, material_prim_paths):
- if not self._upscale_progress_bar:
- self._upscale_progress_bar = ProgressPopup(title="Upscaling")
- self._upscale_progress_bar.set_progress(0)
- self._upscale_progress_bar.show()
- processing_config = (
- partial(UpscalerCore.perform_upscale, UpscaleModels.ESRGAN.value),
- constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE,
- constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE,
- "_upscaled4x.png",
- )
- error = await LightspeedTextureProcessingCore.lss_async_batch_process_capture_layer_by_prim_paths(
- processing_config, material_prim_paths, progress_callback=self._material_upscale_set_progress
- )
- if error:
- self._error_popup = ErrorPopup("An error occurred while upscaling", error, window_size=(350, 150))
- self._error_popup.show()
- if self._upscale_progress_bar:
- self._upscale_progress_bar.hide()
- self._upscale_progress_bar = None
-
- def _on_opaque_clicked(self, *_):
- if not self._opaque_button.enabled:
- return
- self._opaque_button.checked = False
-
- select_prim_paths = (
- self._force_material_paths or omni.usd.get_context().get_selection().get_selected_prim_paths()
- )
-
- usd_context = omni.usd.get_context()
- stage = usd_context.get_stage()
-
- material_prims = self._core.get_materials_from_prim_paths(select_prim_paths)
- shaders = [self._core.get_shader_from_material(material_prim) for material_prim in material_prims]
- # check shaders in the current selection
- for select_prim_path in select_prim_paths:
- prim = stage.GetPrimAtPath(select_prim_path)
- if prim.IsValid() and prim.IsA(UsdShade.Shader):
- shaders.append(UsdShade.Shader(prim))
- carb.log_info("Convert to Opaque Material for selection")
- carb.log_verbose(str(shaders))
- self._core.set_new_mdl_to_shaders(shaders, material_prims, stage, "AperturePBR_Opacity.mdl")
-
- def _on_translucent_clicked(self, *_):
- if not self._translucent_button.enabled:
- return
- self._translucent_button.checked = False
-
- select_prim_paths = (
- self._force_material_paths or omni.usd.get_context().get_selection().get_selected_prim_paths()
- )
- usd_context = omni.usd.get_context()
- stage = usd_context.get_stage()
-
- material_prims = self._core.get_materials_from_prim_paths(select_prim_paths)
- shaders = [self._core.get_shader_from_material(material_prim) for material_prim in material_prims]
- shader_paths = [shader.GetPath() for shader in shaders]
- # check shaders in the current selection
- for select_prim_path in select_prim_paths:
- prim = stage.GetPrimAtPath(select_prim_path)
- if prim.IsValid() and prim.IsA(UsdShade.Shader) and UsdShade.Shader(prim).GetPath() not in shader_paths:
- shaders.append(UsdShade.Shader(prim))
- shader_paths.append(UsdShade.Shader(prim).GetPath())
- carb.log_info("Convert to Translucent Material for selection")
- carb.log_verbose(str(shaders))
- self._core.set_new_mdl_to_shaders(shaders, material_prims, stage, "AperturePBR_Translucent.mdl")
-
- def _on_upscale_clicked(self, *_):
- if not self._upscale_button.enabled:
- return
- select_prim_paths = (
- self._force_material_paths or omni.usd.get_context().get_selection().get_selected_prim_paths()
- )
-
- material_objects = self._core.get_materials_from_prim_paths(select_prim_paths)
- carb.log_info("Upscale textures on selected materials")
-
- material_prim_paths = []
- for material in material_objects:
- material_prim_paths.append(material.GetPrim().GetPath())
- asyncio.ensure_future(self._run_material_upscale(material_prim_paths))
-
- def refresh_buttons_stat(self):
- select_prim_paths = (
- self._force_material_paths or omni.usd.get_context().get_selection().get_selected_prim_paths()
- )
- material_prims = self._core.get_materials_from_prim_paths(select_prim_paths)
- to_enable = False
- for material_prim in material_prims:
- refs_and_layers = omni.usd.get_composed_references_from_prim(material_prim.GetPrim())
- if refs_and_layers:
- to_enable = True
- break
- if self._opaque_button:
- self._opaque_button.enabled = to_enable
- if self._translucent_button:
- self._translucent_button.enabled = to_enable
- if self._upscale_button:
- self._upscale_button.enabled = to_enable
- return to_enable # noqa
-
- def create(self, default_size):
- self._opaque_button = ui.Button(
- name="opaqueMaterial",
- tooltip="Convert to Opaque Material",
- width=default_size,
- height=default_size,
- mouse_pressed_fn=self._on_opaque_clicked,
- )
-
- self._translucent_button = ui.Button(
- name="translucentMaterial",
- tooltip="Convert to Translucent Material",
- width=default_size,
- height=default_size,
- mouse_pressed_fn=self._on_translucent_clicked,
- )
-
- self._upscale_button = ui.Button(
- name="upscaleMaterial",
- tooltip="Upscale textures associated with the selected material(s) in the capture layer",
- width=default_size,
- height=default_size,
- mouse_pressed_fn=self._on_upscale_clicked,
- )
- self.refresh_buttons_stat()
- return {
- "opaqueMaterial": self._opaque_button,
- "translucentMaterial": self._translucent_button,
- "upscaleMaterial": self._upscale_button,
- }
-
- def _get_data_path(self):
- current_path = Path(__file__).parent
- for _ in range(3):
- current_path = current_path.parent
- return str(current_path.joinpath("data"))
-
- def get_style(self):
- """
- Gets the style of all widgets defined in this Widgets group.
- Subclassed
- """
- return {
- "Button.Image::opaqueMaterial": {"image_url": f"{self._get_data_path()}/toolbar_opaque_material.png"},
- "Button.Image::opaqueMaterial:disabled": {
- "image_url": f"{self._get_data_path()}/toolbar_opaque_material_disabled.png"
- },
- "Button.Image::translucentMaterial": {"image_url": f"{self._get_data_path()}/toolbar_glass_material.png"},
- "Button.Image::translucentMaterial:disabled": {
- "image_url": f"{self._get_data_path()}/toolbar_glass_material_disabled.png"
- },
- "Button.Image::upscaleMaterial": {"image_url": f"{self._get_data_path()}/toolbar_upscale_material.png"},
- "Button.Image::upscaleMaterial:disabled": {
- "image_url": f"{self._get_data_path()}/toolbar_upscale_material_disabled.png"
- },
- }
-
-
-class MaterialButtonGroup(WidgetGroup):
- def __init__(self):
- super().__init__()
- self._button = MaterialButtons(enable_stage_event=True)
-
- def _on_opaque_clicked(self, *_):
- self._acquire_toolbar_context()
- super()._on_opaque_clicked(*_)
-
- def _on_translucent_clicked(self, *_):
- self._acquire_toolbar_context()
- super()._on_translucent_clicked(*_)
-
- def _on_upscale_clicked(self, *_):
- self._acquire_toolbar_context()
- super()._on_upscale_clicked(*_)
-
- def create(self, default_size):
- self._button.create(default_size)
-
- def get_style(self):
- """
- Gets the style of all widgets defined in this Widgets group.
- Subclassed
- """
- return self._button.get_style()
-
- def clean(self):
- self._button.clean()
- super().clean()
diff --git a/source/extensions/lightspeed.tool.material.widget/premake5.lua b/source/extensions/lightspeed.tool.material.widget/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.tool.material.widget/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.tool.octahedral_converter/config/extension.toml b/source/extensions/lightspeed.tool.octahedral_converter/config/extension.toml
index 5dc251605..5c1cc39e9 100644
--- a/source/extensions/lightspeed.tool.octahedral_converter/config/extension.toml
+++ b/source/extensions/lightspeed.tool.octahedral_converter/config/extension.toml
@@ -1,6 +1,6 @@
[package]
# Semantic Versionning is used: https://semver.org/
-version = "0.1.7"
+version = "0.1.8"
# Lists people or organizations that are considered the "authors" of the package.
authors = ["Mark Henderson "]
diff --git a/source/extensions/lightspeed.tool.octahedral_converter/docs/CHANGELOG.md b/source/extensions/lightspeed.tool.octahedral_converter/docs/CHANGELOG.md
index aadeb72d1..ad8210856 100644
--- a/source/extensions/lightspeed.tool.octahedral_converter/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.tool.octahedral_converter/docs/CHANGELOG.md
@@ -1,6 +1,10 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [0.1.8]
+## Fixed
+- Fixed documentation build
+
## [0.1.7]
## Changed
- Update to Kit 106.5
diff --git a/source/extensions/lightspeed.tool.octahedral_converter/docs/index.rst b/source/extensions/lightspeed.tool.octahedral_converter/docs/index.rst
index d58a33a2a..27513e799 100644
--- a/source/extensions/lightspeed.tool.octahedral_converter/docs/index.rst
+++ b/source/extensions/lightspeed.tool.octahedral_converter/docs/index.rst
@@ -18,3 +18,4 @@ This is a simple utility to convert 3 channel tangent space normal map textures
:show-inheritance:
:imported-members:
:exclude-members: contextmanager
+ :noindex: pathlib
diff --git a/source/extensions/lightspeed.trex.app.resources/config/extension.toml b/source/extensions/lightspeed.trex.app.resources/config/extension.toml
index b6b98cec9..81bc2cb59 100644
--- a/source/extensions/lightspeed.trex.app.resources/config/extension.toml
+++ b/source/extensions/lightspeed.trex.app.resources/config/extension.toml
@@ -1,5 +1,5 @@
[package]
-version = "1.15.3"
+version = "1.15.5"
authors = ["dbataille@nvidia.com"]
repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit"
changelog = "docs/CHANGELOG.md"
diff --git a/source/extensions/lightspeed.trex.app.resources/data/stage_manager_schema/default_schema.json b/source/extensions/lightspeed.trex.app.resources/data/stage_manager_schema/default_schema.json
index f5bb42ed8..cf28e6b22 100644
--- a/source/extensions/lightspeed.trex.app.resources/data/stage_manager_schema/default_schema.json
+++ b/source/extensions/lightspeed.trex.app.resources/data/stage_manager_schema/default_schema.json
@@ -122,7 +122,7 @@
]
},
{
- "name": "AllMaterialsInteractionPlugin",
+ "name": "AllMaterialsRemixInteractionPlugin",
"filters": [
{ "name": "IsCaptureFilterPlugin" }
],
diff --git a/source/extensions/lightspeed.trex.app.resources/data/tests/usd/project_example/ingested_assets/output/good/Bricks092-PNG_Color.a.rtex.dds b/source/extensions/lightspeed.trex.app.resources/data/tests/usd/project_example/ingested_assets/output/good/Bricks092-PNG_Color.a.rtex.dds
new file mode 100644
index 000000000..3c7b802d8
--- /dev/null
+++ b/source/extensions/lightspeed.trex.app.resources/data/tests/usd/project_example/ingested_assets/output/good/Bricks092-PNG_Color.a.rtex.dds
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:db291fc036396de1ad09960c9578261cfd30d1c5cc4f9eba24d611398c68e0fd
+size 22369796
diff --git a/source/extensions/lightspeed.trex.app.resources/data/tests/usd/project_example/ingested_assets/output/good/Bricks092-PNG_Color.a.rtex.dds.meta b/source/extensions/lightspeed.trex.app.resources/data/tests/usd/project_example/ingested_assets/output/good/Bricks092-PNG_Color.a.rtex.dds.meta
new file mode 100644
index 000000000..b492212c1
--- /dev/null
+++ b/source/extensions/lightspeed.trex.app.resources/data/tests/usd/project_example/ingested_assets/output/good/Bricks092-PNG_Color.a.rtex.dds.meta
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3cf6a07e88b7c3eac45170f27c1e4578b889989a131081515cd00fbaba901187
+size 6184
diff --git a/source/extensions/lightspeed.trex.app.resources/docs/CHANGELOG.md b/source/extensions/lightspeed.trex.app.resources/docs/CHANGELOG.md
index b3706c458..19780ab55 100644
--- a/source/extensions/lightspeed.trex.app.resources/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.trex.app.resources/docs/CHANGELOG.md
@@ -1,6 +1,14 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.15.5]
+## Changed
+- Stage Manager: Added LSS Materials Tab interaction plugin wrapper
+
+## [1.15.4]
+## Added
+- Added ingested images to test project
+
## [1.15.3]
## Fixed
- Fixed the Mixed icon to be colorable in the styles
diff --git a/source/extensions/lightspeed.trex.asset_replacements.core.shared/config/extension.toml b/source/extensions/lightspeed.trex.asset_replacements.core.shared/config/extension.toml
index 28f65bbf4..975ab3906 100644
--- a/source/extensions/lightspeed.trex.asset_replacements.core.shared/config/extension.toml
+++ b/source/extensions/lightspeed.trex.asset_replacements.core.shared/config/extension.toml
@@ -1,5 +1,5 @@
[package]
-version = "2.5.3"
+version = "2.5.4"
authors =["Damien Bataille "]
title = "NVIDIA RTX Remix Asset Replacements extension for the StageCraft"
description = "Extension that works on asset replacement data for NVIDIA RTX Remix StageCraft App"
diff --git a/source/extensions/lightspeed.trex.asset_replacements.core.shared/docs/CHANGELOG.md b/source/extensions/lightspeed.trex.asset_replacements.core.shared/docs/CHANGELOG.md
index 5a8cbfa86..85805c2b4 100644
--- a/source/extensions/lightspeed.trex.asset_replacements.core.shared/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.trex.asset_replacements.core.shared/docs/CHANGELOG.md
@@ -1,6 +1,10 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [2.5.4]
+## Fixed
+- Fixed some validators and core functions with bugs discovered during testing
+
## [2.5.3]
## Changed
- rename trex prim utility names for clarity
diff --git a/source/extensions/lightspeed.trex.asset_replacements.core.shared/lightspeed/trex/asset_replacements/core/shared/data_models/validators.py b/source/extensions/lightspeed.trex.asset_replacements.core.shared/lightspeed/trex/asset_replacements/core/shared/data_models/validators.py
index beabfa8a3..164d099b3 100644
--- a/source/extensions/lightspeed.trex.asset_replacements.core.shared/lightspeed/trex/asset_replacements/core/shared/data_models/validators.py
+++ b/source/extensions/lightspeed.trex.asset_replacements.core.shared/lightspeed/trex/asset_replacements/core/shared/data_models/validators.py
@@ -26,7 +26,7 @@
from lightspeed.trex.utils.common.prim_utils import is_material_prototype
from omni.flux.utils.common import path_utils
from omni.flux.utils.common.omni_url import OmniUrl
-from pxr import Sdf
+from pxr import Sdf, Usd
class AssetReplacementsValidators:
@@ -46,7 +46,7 @@ def is_valid_prim(cls, prim_path: str, context_name: str):
@classmethod
def is_valid_mesh(cls, prim_path: str):
- if not re.match(constants.REGEX_MESH_PATH, prim_path):
+ if not re.match(constants.REGEX_MESH_PATH, prim_path) and not re.match(constants.REGEX_IN_MESH_PATH, prim_path):
raise ValueError(f"The prim path does not point to a model: {prim_path}")
return prim_path
@@ -65,7 +65,11 @@ def is_valid_material(cls, prim_path: str, context_name: str):
@classmethod
def has_at_least_one_ref(cls, prim_path: str, context_name: str):
prim = omni.usd.get_context(context_name).get_stage().GetPrimAtPath(prim_path)
- references = omni.usd.get_composed_references_from_prim(prim)
+
+ if not prim:
+ raise ValueError(f"The prim path does not exist in the current stage: {prim_path}")
+
+ _, references = cls.get_prim_references(prim_path, context_name)
if not references:
raise ValueError("The selected prim has no references")
@@ -75,12 +79,16 @@ def has_at_least_one_ref(cls, prim_path: str, context_name: str):
@classmethod
def ref_exists_in_prim(cls, asset_path: Path, layer_id: Path, prim_path: str, context_name: str):
prim = omni.usd.get_context(context_name).get_stage().GetPrimAtPath(prim_path)
- references = omni.usd.get_composed_references_from_prim(prim)
+
+ if not prim:
+ raise ValueError(f"The prim path does not exist in the current stage: {prim_path}")
+
+ _, references = cls.get_prim_references(prim_path, context_name)
for reference, layer in references:
if (
- OmniUrl(reference.assetPath).path == OmniUrl(asset_path).path
- and OmniUrl(layer.identifier).path == OmniUrl(layer_id).path
+ OmniUrl(reference.assetPath).path.lower() == OmniUrl(asset_path).path.lower()
+ and OmniUrl(layer.identifier).path.lower() == OmniUrl(layer_id).path.lower()
):
return prim_path
@@ -120,3 +128,38 @@ def layer_is_in_project(cls, layer_id: Path | None, context_name: str):
raise ValueError(f"The layer is not present in the loaded project's layer stack: {layer_id}")
return layer_id
+
+ @classmethod
+ def get_prim_references(
+ cls, prim_path: str, context_name: str
+ ) -> tuple[Usd.Prim, list[tuple[Sdf.Reference, Sdf.Layer]]]:
+ stage = omni.usd.get_context(context_name).get_stage()
+ prim = stage.GetPrimAtPath(str(prim_path))
+ if not prim:
+ # Invalid prim path
+ return prim, []
+
+ introducing_prim = prim
+
+ # If the asset has a reference, it should have more than 1 prim in the stack
+ prim_stack = introducing_prim.GetPrimStack()
+ while len(prim_stack) <= 1:
+ introducing_prim = introducing_prim.GetParent()
+ if not introducing_prim:
+ # No reference found
+ return prim, []
+ prim_stack = introducing_prim.GetPrimStack()
+
+ references = omni.usd.get_composed_references_from_prim(introducing_prim)
+
+ # If no references are found, try to build a reference using the prim stack
+ if not references:
+ external_layers = [i.layer for i in introducing_prim.GetPrimStack() if i.layer not in stage.GetLayerStack()]
+ if external_layers:
+ reference_layer = external_layers[-1]
+ introducing_layer = prim_stack[0].layer
+ relative_path = str(Path(reference_layer.realPath).relative_to(Path(introducing_layer.realPath).parent))
+
+ references = [(Sdf.Reference(relative_path), introducing_layer)]
+
+ return introducing_prim, references
diff --git a/source/extensions/lightspeed.trex.asset_replacements.core.shared/lightspeed/trex/asset_replacements/core/shared/setup.py b/source/extensions/lightspeed.trex.asset_replacements.core.shared/lightspeed/trex/asset_replacements/core/shared/setup.py
index ef9842454..c28d8d683 100644
--- a/source/extensions/lightspeed.trex.asset_replacements.core.shared/lightspeed/trex/asset_replacements/core/shared/setup.py
+++ b/source/extensions/lightspeed.trex.asset_replacements.core.shared/lightspeed/trex/asset_replacements/core/shared/setup.py
@@ -47,8 +47,6 @@
from omni.usd.commands import remove_prim_spec as _remove_prim_spec
from pxr import Sdf, Usd, UsdGeom, UsdShade, UsdSkel
-from .data_models import DefaultAssetDirectory as _DefaultAssetDirectory
-
if typing.TYPE_CHECKING:
from lightspeed.trex.selection_tree.shared.widget.selection_tree.model import ItemInstance as _ItemInstance
from lightspeed.trex.selection_tree.shared.widget.selection_tree.model import (
@@ -58,6 +56,8 @@
from .data_models import (
AppendReferenceRequestModel,
AssetPathResponseModel,
+ AssetReplacementsValidators,
+ DefaultAssetDirectory,
GetPrimsQueryModel,
GetTexturesQueryModel,
PrimInstancesPathParamModel,
@@ -129,17 +129,24 @@ def get_textures_with_data_model(
self, params: PrimTexturesPathParamModel, query: GetTexturesQueryModel
) -> TexturesResponseModel:
return TexturesResponseModel(
- textures=self.get_textures_from_material_path(params.asset_path, texture_types=query.texture_types)
+ textures=self.get_textures_from_material_path(
+ params.asset_path,
+ texture_types=(
+ {_TextureTypes[texture_type.value] for texture_type in query.texture_types}
+ if query.texture_types
+ else None
+ ),
+ )
)
def get_reference_with_data_model(self, params: PrimReferencePathParamModel) -> ReferenceResponseModel:
- stage = self._context.get_stage()
- prim = stage.GetPrimAtPath(str(params.asset_path))
-
- references = omni.usd.get_composed_references_from_prim(prim)
-
+ introducing_prim, references = AssetReplacementsValidators.get_prim_references(
+ params.asset_path, self._context_name
+ )
return ReferenceResponseModel(
- reference_paths=[(str(prim.GetPath()), (str(ref.assetPath), layer.identifier)) for ref, layer in references]
+ reference_paths=[
+ (str(introducing_prim.GetPath()), (str(ref.assetPath), layer.identifier)) for ref, layer in references
+ ]
)
def replace_reference_with_data_model(
@@ -147,23 +154,23 @@ def replace_reference_with_data_model(
) -> ReferenceResponseModel:
with omni.kit.undo.group():
stage = self._context.get_stage()
-
edit_target_layer = stage.GetEditTarget().GetLayer()
+ introducing_prim, references = AssetReplacementsValidators.get_prim_references(
+ params.asset_path, self._context_name
+ )
+ prim_path = introducing_prim.GetPath()
+
if body.existing_asset_layer_id and body.existing_asset_file_path:
current_layer = Sdf.Layer.FindOrOpen(str(body.existing_asset_layer_id))
current_ref = Sdf.Reference(
assetPath=_OmniUrl(body.existing_asset_file_path).path, primPath=str(params.asset_path)
)
else:
- prim = stage.GetPrimAtPath(str(params.asset_path))
- references = omni.usd.get_composed_references_from_prim(prim)
current_ref, current_layer = references[0]
# Remove the existing reference
- self.remove_reference(
- stage, Sdf.Path(str(params.asset_path)), current_ref, current_layer, remove_if_remix_ref=False
- )
+ self.remove_reference(stage, prim_path, current_ref, current_layer, remove_if_remix_ref=False)
# Get the new reference prim path
ref_prim_path = self.get_reference_prim_path_from_asset_path(
@@ -173,7 +180,7 @@ def replace_reference_with_data_model(
# Add the new reference prim path
reference, child_prim_path = self.add_new_reference(
stage,
- Sdf.Path(str(params.asset_path)),
+ prim_path,
self.switch_ref_abs_to_rel_path(stage, str(body.asset_file_path)),
ref_prim_path,
edit_target_layer,
@@ -190,9 +197,11 @@ def append_reference_with_data_model(
with omni.kit.undo.group():
stage = self._context.get_stage()
edit_target_layer = stage.GetEditTarget().GetLayer()
+ introducing_prim, _ = AssetReplacementsValidators.get_prim_references(params.asset_path, self._context_name)
+
reference, child_prim_path = self.add_new_reference(
stage,
- Sdf.Path(str(params.asset_path)),
+ introducing_prim.GetPath(),
self.switch_ref_abs_to_rel_path(stage, str(body.asset_file_path)),
self.get_ref_default_prim_tag(),
edit_target_layer,
@@ -203,7 +212,7 @@ def append_reference_with_data_model(
)
def get_default_output_directory_with_data_model(
- self, directory: _DefaultAssetDirectory = _DefaultAssetDirectory.INGESTED
+ self, directory: DefaultAssetDirectory = DefaultAssetDirectory.INGESTED
) -> AssetPathResponseModel:
stage = self._context.get_stage()
if not stage:
@@ -261,12 +270,14 @@ def get_textures_from_material_path(
if not shader:
return textures
+ texture_type_names = None
+ if texture_types is not None:
+ texture_type_names = [_get_texture_type_attribute(texture_type) for texture_type in texture_types]
+
for shader_input in shader.GetInputs():
# Make sure the input matches the filter if set
- if texture_types is not None:
- texture_type_names = [_get_texture_type_attribute(texture_type) for texture_type in texture_types]
- if shader_input.GetBaseName() not in texture_type_names:
- continue
+ if texture_type_names is not None and shader_input.GetFullName() not in texture_type_names:
+ continue
# Make sure the input expects an asset
if shader_input.GetTypeName() != Sdf.ValueTypeNames.Asset:
continue
@@ -274,10 +285,8 @@ def get_textures_from_material_path(
texture_asset_path = shader_input.Get().resolvedPath
if _OmniUrl(texture_asset_path).suffix.lower() not in _SUPPORTED_TEXTURE_EXTENSIONS:
continue
- # Build the full property path
- texture_input_path = shader_prim.GetPath().AppendProperty(shader_input.GetFullName())
# Store the texture property and the asset path
- textures.append((str(texture_input_path), str(texture_asset_path)))
+ textures.append((str(shader_input.GetAttr().GetPath()), str(texture_asset_path)))
return textures
diff --git a/source/extensions/lightspeed.trex.asset_replacements.service/config/extension.toml b/source/extensions/lightspeed.trex.asset_replacements.service/config/extension.toml
index 58d97c1cd..2be6b1de1 100644
--- a/source/extensions/lightspeed.trex.asset_replacements.service/config/extension.toml
+++ b/source/extensions/lightspeed.trex.asset_replacements.service/config/extension.toml
@@ -1,5 +1,5 @@
[package]
-version = "1.3.0"
+version = "1.3.2"
authors =["Pierre-Oliver Trottier "]
title = "NVIDIA RTX Remix Asset Replacements Service extension"
description = "Extension that exposes microservices for asset replacement data for NVIDIA RTX Remix"
@@ -17,3 +17,20 @@ preview_image = "data/preview.png"
[[python.module]]
name = "lightspeed.trex.asset_replacements.service"
+
+[[test]]
+dependencies = [
+ "lightspeed.trex.tests.dependencies",
+ "omni.flux.utils.widget",
+ "omni.services.core",
+]
+
+stdoutFailPatterns.exclude = [
+ "*[omni.kit.registry.nucleus.utils.common] Skipping deletion of:*",
+]
+
+[[test]]
+name = "startup"
+dependencies = [
+ "lightspeed.trex.tests.dependencies",
+]
diff --git a/source/extensions/lightspeed.trex.asset_replacements.service/docs/CHANGELOG.md b/source/extensions/lightspeed.trex.asset_replacements.service/docs/CHANGELOG.md
index 026694a8f..99508ab3f 100644
--- a/source/extensions/lightspeed.trex.asset_replacements.service/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.trex.asset_replacements.service/docs/CHANGELOG.md
@@ -1,6 +1,17 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.3.2]
+### Added
+- Enabled selection test
+- Use async send_request function in tests
+- Validate USD state in tests
+
+## [1.3.1]
+### Added
+- Added test dependencies
+- Added e2e tests for the service
+
## [1.3.0]
### Added
- Added endpoints to get default model and texture directories
diff --git a/source/extensions/lightspeed.asset_capture_localizer.menu/lightspeed/asset_capture_localizer/menu/__init__.py b/source/extensions/lightspeed.trex.asset_replacements.service/lightspeed/trex/asset_replacements/service/tests/__init__.py
similarity index 92%
rename from source/extensions/lightspeed.asset_capture_localizer.menu/lightspeed/asset_capture_localizer/menu/__init__.py
rename to source/extensions/lightspeed.trex.asset_replacements.service/lightspeed/trex/asset_replacements/service/tests/__init__.py
index 084e7bbe3..4669d5279 100644
--- a/source/extensions/lightspeed.asset_capture_localizer.menu/lightspeed/asset_capture_localizer/menu/__init__.py
+++ b/source/extensions/lightspeed.trex.asset_replacements.service/lightspeed/trex/asset_replacements/service/tests/__init__.py
@@ -15,4 +15,4 @@
* limitations under the License.
"""
-from .menu import * # noqa: F401
+from .e2e.test_service import TestAssetReplacementsService
diff --git a/source/extensions/lightspeed.trex.asset_replacements.service/lightspeed/trex/asset_replacements/service/tests/e2e/test_service.py b/source/extensions/lightspeed.trex.asset_replacements.service/lightspeed/trex/asset_replacements/service/tests/e2e/test_service.py
new file mode 100644
index 000000000..dc0c2f3b7
--- /dev/null
+++ b/source/extensions/lightspeed.trex.asset_replacements.service/lightspeed/trex/asset_replacements/service/tests/e2e/test_service.py
@@ -0,0 +1,358 @@
+"""
+* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+* SPDX-License-Identifier: Apache-2.0
+*
+* 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
+*
+* https://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 pathlib import Path
+
+import omni.usd
+from omni.flux.service.factory import get_instance as get_service_factory_instance
+from omni.flux.utils.common.api import send_request
+from omni.flux.utils.widget.resources import get_test_data
+from omni.kit.test import AsyncTestCase
+from omni.kit.test_suite.helpers import open_stage
+from omni.services.core import main
+
+
+class TestAssetReplacementsService(AsyncTestCase):
+ # Before running each test
+ async def setUp(self):
+ self.project_path = get_test_data("usd/project_example/combined.usda")
+
+ self.context = omni.usd.get_context()
+ await open_stage(self.project_path)
+
+ factory = get_service_factory_instance()
+
+ # Register the service in the app
+ self.service = factory.get_plugin_from_name("AssetReplacementsService")()
+ main.register_router(router=self.service.router, prefix=self.service.prefix)
+
+ # After running each test
+ async def tearDown(self):
+ main.deregister_router(router=self.service.router, prefix=self.service.prefix)
+
+ self.service = None
+
+ if self.context.can_close_stage():
+ await self.context.close_stage_async()
+
+ self.context = None
+ self.project_path = None
+
+ async def test_get_default_model_asset_path_directory_returns_expected_response(self):
+ # Arrange
+ expected_value = (Path(get_test_data("usd/project_example")) / "assets" / "models").as_posix()
+
+ # Act
+ response = await send_request("GET", f"{self.service.prefix}/default-directory/models")
+
+ # Assert
+ self.assertEqual(str(response).lower(), str({"asset_path": expected_value}).lower())
+
+ async def test_get_default_texture_asset_path_directory_returns_expected_response(self):
+ # Arrange
+ expected_value = (Path(get_test_data("usd/project_example/")) / "assets" / "textures").as_posix()
+
+ # Act
+ response = await send_request("GET", f"{self.service.prefix}/default-directory/textures")
+
+ # Assert
+ self.assertEqual(str(response).lower(), str({"asset_path": expected_value}).lower())
+
+ async def test_get_default_ingested_asset_path_directory_returns_expected_response(self):
+ # Arrange
+ expected_value = (Path(get_test_data("usd/project_example")) / "assets" / "ingested").as_posix()
+
+ # Act
+ response = await send_request("GET", f"{self.service.prefix}/default-directory")
+
+ # Assert
+ self.assertEqual(str(response).lower(), str({"asset_path": expected_value}).lower())
+
+ async def test_get_assets_returns_expected_response(self):
+ for index, test_data in enumerate(
+ [
+ (
+ "",
+ {
+ "asset_paths": [
+ "/RootNode/lights/light_9907D0B07D040077",
+ "/RootNode/lights/light_EDF9B59568FD1142",
+ "/RootNode/lights/light_0FBF0D906770A019",
+ "/RootNode/meshes/mesh_0AB745B8BEE1F16B/mesh",
+ "/RootNode/meshes/mesh_CED45075A077A49A/mesh",
+ "/RootNode/meshes/mesh_BAC90CAA733B0859/ref_c89e0497f4ff4dc4a7b70b79c85692da/Cube",
+ "/RootNode/meshes/mesh_BAC90CAA733B0859/ref_c89e0497f4ff4dc4a7b70b79c85692da/Cube_01",
+ "/RootNode/Looks/mat_BC868CE5A075ABB1",
+ ]
+ },
+ ),
+ (
+ "asset_hashes=CED45075A077A49A&asset_hashes=BAC90CAA733B0859",
+ {
+ "asset_paths": [
+ "/RootNode/meshes/mesh_CED45075A077A49A/mesh",
+ "/RootNode/meshes/mesh_BAC90CAA733B0859/ref_c89e0497f4ff4dc4a7b70b79c85692da/Cube",
+ "/RootNode/meshes/mesh_BAC90CAA733B0859/ref_c89e0497f4ff4dc4a7b70b79c85692da/Cube_01",
+ ]
+ },
+ ),
+ (
+ "asset_types=lights",
+ {
+ "asset_paths": [
+ "/RootNode/lights/light_9907D0B07D040077",
+ "/RootNode/lights/light_EDF9B59568FD1142",
+ "/RootNode/lights/light_0FBF0D906770A019",
+ ]
+ },
+ ),
+ ]
+ ):
+ params, expected_response = test_data
+ with self.subTest(name=f"test_{index}"):
+ # Arrange
+ pass
+
+ # Act
+ response = await send_request("GET", f"{self.service.prefix}/?{params}")
+
+ # Assert
+ self.assertEqual(response, expected_response)
+
+ async def test_get_model_instances_returns_expected_response(self):
+ # Arrange
+ pass
+
+ # Act
+ response = await send_request(
+ "GET", f"{self.service.prefix}/%2FRootNode%2Fmeshes%2Fmesh_CED45075A077A49A%2Fmesh/instances"
+ )
+
+ # Assert
+ self.assertEqual(response, {"asset_paths": ["/RootNode/instances/inst_CED45075A077A49A_0/mesh"]})
+
+ async def test_get_material_textures_returns_expected_response(self):
+ # Arrange
+ expected_diffuse_value = str(
+ Path(get_test_data("usd/project_example"))
+ / ".deps"
+ / "captures"
+ / "materials"
+ / "textures"
+ / "BC868CE5A075ABB1.dds"
+ )
+ expected_metallic_value = str(
+ Path(get_test_data("usd/project_example"))
+ / "sources"
+ / "textures"
+ / "T_MetalPanelWall_HeavyRust_metallic.png"
+ )
+ expected_normal_value = str(
+ Path(get_test_data("usd/project_example"))
+ / "sources"
+ / "textures"
+ / "T_MetalPanelWall_HeavyRust_normal.png"
+ )
+ expected_roughness_value = str(
+ Path(get_test_data("usd/project_example"))
+ / "sources"
+ / "textures"
+ / "T_MetalPanelWall_HeavyRust_roughness.png"
+ )
+
+ # Act
+ response = await send_request(
+ "GET", f"{self.service.prefix}/%2FRootNode%2FLooks%2Fmat_BC868CE5A075ABB1/textures"
+ )
+
+ # Assert
+ self.assertEqual(
+ str(response).lower(),
+ str(
+ {
+ "textures": [
+ ["/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:diffuse_texture", expected_diffuse_value],
+ [
+ "/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:metallic_texture",
+ expected_metallic_value,
+ ],
+ ["/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:normalmap_texture", expected_normal_value],
+ [
+ "/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:reflectionroughness_texture",
+ expected_roughness_value,
+ ],
+ ]
+ }
+ ).lower(),
+ )
+
+ async def test_get_material_textures_args_returns_expected_response(self):
+ # Arrange
+ expected_diffuse_value = str(
+ Path(get_test_data("usd/project_example"))
+ / ".deps"
+ / "captures"
+ / "materials"
+ / "textures"
+ / "BC868CE5A075ABB1.dds"
+ )
+ expected_normal_value = str(
+ Path(get_test_data("usd/project_example"))
+ / "sources"
+ / "textures"
+ / "T_MetalPanelWall_HeavyRust_normal.png"
+ )
+
+ # Act
+ response = await send_request(
+ "GET",
+ f"{self.service.prefix}/%2FRootNode%2FLooks%2Fmat_BC868CE5A075ABB1/textures?texture_types=DIFFUSE&texture_types=NORMAL_OGL", # noqa E501
+ )
+
+ # Assert
+ self.assertEqual(
+ str(response).lower(),
+ str(
+ {
+ "textures": [
+ ["/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:diffuse_texture", expected_diffuse_value],
+ ["/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:normalmap_texture", expected_normal_value],
+ ]
+ }
+ ).lower(),
+ )
+
+ async def test_get_asset_file_paths_returns_expected_response(self):
+ # Arrange
+ expected_relative_path = str(Path("meshes") / "mesh_CED45075A077A49A.usda")
+ expected_layer_path = str(Path(get_test_data("usd/project_example")) / ".deps" / "captures" / "capture.usda")
+
+ # Act
+ response = await send_request(
+ "GET",
+ f"{self.service.prefix}/%2FRootNode%2Fmeshes%2Fmesh_CED45075A077A49A%2Fmesh/file-paths",
+ )
+
+ # Assert
+ self.assertEqual(
+ str(response).lower(),
+ str(
+ {
+ "reference_paths": [
+ ["/RootNode/meshes/mesh_CED45075A077A49A", [expected_relative_path, expected_layer_path]]
+ ]
+ }
+ ).lower(),
+ )
+
+ async def test_append_asset_file_path_should_add_new_reference(self):
+ # Arrange
+ append_asset_path = str(Path(get_test_data("usd/project_example/ingested_assets/output/good/cube.usda")))
+ mod_layer = str(Path(get_test_data("usd/project_example/combined.usda"))).replace("\\", "\\\\")
+
+ # Act
+ response = await send_request(
+ "PUT",
+ f"{self.service.prefix}/%2FRootNode%2Fmeshes%2Fmesh_CED45075A077A49A%2Fmesh/file-paths",
+ json={
+ "asset_file_path": append_asset_path,
+ "force": False,
+ },
+ )
+
+ # Assert
+ self.assertRegex(
+ str(response).replace("\\\\", "\\").lower(),
+ f"{{'reference_paths': \\[\\['/RootNode/meshes/mesh_CED45075A077A49A/ref_[0-9a-z]{{32}}', "
+ f"\\['ingested_assets\\\\output\\\\good\\\\cube.usda', '{mod_layer}'\\]\\]\\]}}".lower(),
+ )
+
+ # Make sure the stage has the appended the reference
+ ref_path = response["reference_paths"][0][0]
+ self.assertTrue(self.context.get_stage().GetPrimAtPath(f"{ref_path}/Cube_01").IsValid())
+
+ async def test_replace_asset_file_path_no_ref_should_replace_first_ref(self):
+ # Arrange
+ replace_asset_path = str(Path(get_test_data("usd/project_example/ingested_assets/output/good/cube.usda")))
+ mod_layer = str(Path(get_test_data("usd/project_example/combined.usda"))).replace("\\", "\\\\")
+
+ # Act
+ response = await send_request(
+ "PUT",
+ f"{self.service.prefix}/%2FRootNode%2Fmeshes%2Fmesh_0AB745B8BEE1F16B%2Fmesh/file-paths",
+ json={
+ "asset_file_path": replace_asset_path,
+ "force": False,
+ },
+ )
+
+ # Assert
+ self.assertRegex(
+ str(response).replace("\\\\", "\\").lower(),
+ f"{{'reference_paths': \\[\\['/RootNode/meshes/mesh_0AB745B8BEE1F16B/ref_[0-9a-z]{{32}}', "
+ f"\\['ingested_assets\\\\output\\\\good\\\\cube.usda', '{mod_layer}'\\]\\]\\]}}".lower(),
+ )
+
+ # Make sure the stage has the appended the reference
+ ref_path = response["reference_paths"][0][0]
+ self.assertTrue(self.context.get_stage().GetPrimAtPath(f"{ref_path}/Cube_01").IsValid())
+
+ async def test_replace_asset_file_path_with_ref_should_replace_expected_ref(self):
+ # Arrange
+ original_asset_path = "sources\\\\cube.usda"
+ original_layer = str(Path(get_test_data("usd/project_example/replacements.usda"))).replace("\\", "\\\\")
+
+ replace_asset_path = str(Path(get_test_data("usd/project_example/ingested_assets/output/good/cube.usda")))
+ mod_layer = str(Path(get_test_data("usd/project_example/combined.usda"))).replace("\\", "\\\\")
+
+ # Act
+ response = await send_request(
+ "PUT",
+ f"{self.service.prefix}/%2FRootNode%2Fmeshes%2Fmesh_BAC90CAA733B0859%2Fref_c89e0497f4ff4dc4a7b70b79c85692da%2FCube_01/file-paths", # noqa: E501
+ json={
+ "existing_asset_file_path": original_asset_path,
+ "existing_asset_layer_id": original_layer,
+ "asset_file_path": replace_asset_path,
+ "force": False,
+ },
+ )
+
+ # Assert
+ self.assertRegex(
+ str(response).replace("\\\\", "\\").lower(),
+ f"{{'reference_paths': \\[\\['/RootNode/meshes/mesh_BAC90CAA733B0859/ref_[0-9a-z]{{32}}', "
+ f"\\['ingested_assets\\\\output\\\\good\\\\cube.usda', '{mod_layer}'\\]\\]\\]}}".lower(),
+ )
+
+ # Make sure the stage has the appended the reference
+ ref_path = response["reference_paths"][0][0]
+ self.assertTrue(self.context.get_stage().GetPrimAtPath(f"{ref_path}/Cube_01").IsValid())
+
+ async def test_set_selection_updates_stage_selection(self):
+ # Arrange
+ pass
+
+ # Act
+ response = await send_request(
+ "PUT", f"{self.service.prefix}/selection/%2FRootNode%2Flights%2Flight_9907D0B07D040077"
+ )
+
+ # Assert
+ self.assertEqual(response, "OK")
+ self.assertEqual(
+ self.context.get_selection().get_selected_prim_paths(), ["/RootNode/lights/light_9907D0B07D040077"]
+ )
diff --git a/source/extensions/lightspeed.trex.capture.core.shared/config/extension.toml b/source/extensions/lightspeed.trex.capture.core.shared/config/extension.toml
index eb6346fb7..1be561a5a 100644
--- a/source/extensions/lightspeed.trex.capture.core.shared/config/extension.toml
+++ b/source/extensions/lightspeed.trex.capture.core.shared/config/extension.toml
@@ -1,5 +1,5 @@
[package]
-version = "1.1.9"
+version = "1.2.0"
authors =["Damien Bataille "]
repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit"
changelog = "docs/CHANGELOG.md"
@@ -16,7 +16,6 @@ preview_image = "data/preview.png"
"lightspeed.event.capture_persp_to_persp" = {optional=true} # because this extension subscribe to the global event
"lightspeed.events_manager" = {}
"lightspeed.layer_manager.core" = {}
-"lightspeed.upscale.core" = {}
"omni.client" = {}
"omni.kit.pip_archive" = {} # For PIL
"omni.flux.utils.common" = {}
diff --git a/source/extensions/lightspeed.trex.capture.core.shared/docs/CHANGELOG.md b/source/extensions/lightspeed.trex.capture.core.shared/docs/CHANGELOG.md
index 6f741cf66..ff006f70a 100644
--- a/source/extensions/lightspeed.trex.capture.core.shared/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.trex.capture.core.shared/docs/CHANGELOG.md
@@ -1,6 +1,10 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.2.0]
+## Removed
+- Removed Upscale Core dependency
+
## [1.1.9]
## Changed
- Update to Kit 106.5
diff --git a/source/extensions/lightspeed.trex.capture.core.shared/lightspeed/trex/capture/core/shared/setup.py b/source/extensions/lightspeed.trex.capture.core.shared/lightspeed/trex/capture/core/shared/setup.py
index 71a480173..7b072a3fa 100644
--- a/source/extensions/lightspeed.trex.capture.core.shared/lightspeed/trex/capture/core/shared/setup.py
+++ b/source/extensions/lightspeed.trex.capture.core.shared/lightspeed/trex/capture/core/shared/setup.py
@@ -26,7 +26,6 @@
from lightspeed.events_manager import get_instance as _get_event_manager_instance
from lightspeed.layer_manager.core import LayerManagerCore as _LayerManagerCore
from lightspeed.layer_manager.core.data_models import LayerType, LayerTypeKeys
-from lightspeed.upscale.core import UpscaleModels, UpscalerCore
from omni.flux.utils.common import async_wrap as _async_wrap
from omni.flux.utils.common import reset_default_attrs as _reset_default_attrs
from PIL import Image
@@ -92,24 +91,12 @@ def get_upscaled_game_icon_from_folder(folder_path: str) -> Optional[str]:
default_icon = Setup.get_game_icon_from_folder(folder_path)
if not default_icon:
return None
- # look for the upscaled icon
- upscaled = default_icon.replace("_icon.bmp", "_upscaled_icon.png")
- upscaled_path = Path(upscaled)
# first we convert the bmp to png without alpha
png_file = default_icon.replace("_icon.bmp", "_icon.png")
with Image.open(default_icon) as im1:
im1 = im1.convert("RGB")
im1.save(png_file)
- if (
- not upscaled_path.exists()
- and Path(constants.REAL_ESRGAN_ROOT_PATH).joinpath("realesrgan-ncnn-vulkan.exe").exists()
- ):
- # we upscale
- UpscalerCore.perform_upscale(UpscaleModels.ESRGAN.value, png_file, str(upscaled_path))
- else:
- # we can't upscale. Back to the low resolution icon
- upscaled_path = png_file
- return str(upscaled_path)
+ return str(png_file)
@omni.usd.handle_exception
async def deferred_get_upscaled_game_icon_from_folder(self, folder_path: str, callback): # noqa PLW0238
diff --git a/source/extensions/lightspeed.trex.layout.stagecraft/config/extension.toml b/source/extensions/lightspeed.trex.layout.stagecraft/config/extension.toml
index f60f2322f..cd966f75b 100644
--- a/source/extensions/lightspeed.trex.layout.stagecraft/config/extension.toml
+++ b/source/extensions/lightspeed.trex.layout.stagecraft/config/extension.toml
@@ -1,5 +1,5 @@
[package]
-version = "2.3.0"
+version = "2.4.0"
authors =["Damien Bataille "]
title = "NVIDIA RTX Remix layout for the StageCraft"
description = "Layout for NVIDIA RTX Remix StageCraft App"
@@ -13,7 +13,6 @@ repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tr
[dependencies]
"lightspeed.common" = {}
-"lightspeed.event.save_recent" = {}
"lightspeed.events_manager" = {}
"lightspeed.layer_manager.core" = {}
"lightspeed.trex.components_pane.stagecraft.controller" = {}
@@ -23,6 +22,7 @@ repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tr
"lightspeed.trex.layout.shared.base" = {}
"lightspeed.trex.menu.workfile" = {}
"lightspeed.trex.properties_pane.stagecraft.widget" = {}
+"lightspeed.trex.recent_projects.core" = {}
"lightspeed.trex.stage_manager.widget" = {}
"lightspeed.trex.utils.common" = {}
"lightspeed.trex.utils.widget" = {}
diff --git a/source/extensions/lightspeed.trex.layout.stagecraft/docs/CHANGELOG.md b/source/extensions/lightspeed.trex.layout.stagecraft/docs/CHANGELOG.md
index 42e6280cf..e6d20d466 100644
--- a/source/extensions/lightspeed.trex.layout.stagecraft/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.trex.layout.stagecraft/docs/CHANGELOG.md
@@ -1,6 +1,10 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [2.4.0]
+## Changed
+- Use better dependency for recent projects
+
## [2.3.0]
## Changed
- Enable the Stage Manager by default
diff --git a/source/extensions/lightspeed.trex.layout.stagecraft/lightspeed/trex/layout/stagecraft/setup_ui.py b/source/extensions/lightspeed.trex.layout.stagecraft/lightspeed/trex/layout/stagecraft/setup_ui.py
index 664deac28..77d2b88a4 100644
--- a/source/extensions/lightspeed.trex.layout.stagecraft/lightspeed/trex/layout/stagecraft/setup_ui.py
+++ b/source/extensions/lightspeed.trex.layout.stagecraft/lightspeed/trex/layout/stagecraft/setup_ui.py
@@ -34,7 +34,6 @@
REMIX_SAMPLE_PATH,
GlobalEventNames,
)
-from lightspeed.event.save_recent.recent_saved_file_utils import RecentSavedFile as _RecentSavedFile
from lightspeed.events_manager import get_instance as _get_event_manager_instance
from lightspeed.layer_manager.core import LayerManagerCore as _LayerManagerCore
from lightspeed.trex.components_pane.stagecraft.controller import SetupUI as ComponentsPaneSetupUI
@@ -45,6 +44,7 @@
from lightspeed.trex.layout.shared.base import SetupUI as TrexLayout
from lightspeed.trex.menu.workfile import get_instance as get_burger_menu_instance
from lightspeed.trex.properties_pane.stagecraft.widget import SetupUI as PropertyPanelUI
+from lightspeed.trex.recent_projects.core import RecentProjectsCore as _RecentProjectsCore
from lightspeed.trex.stage_manager.widget import StageManagerWidget as _StageManagerWidget
from lightspeed.trex.utils.common.dialog_utils import delete_dialogs as _delete_dialogs
from lightspeed.trex.utils.common.file_utils import (
@@ -100,7 +100,7 @@ def __init__(self, ext_id):
self.__on_stage_event, name="StageChanged"
)
- self._recent_saved_file = _RecentSavedFile()
+ self._recent_saved_file = _RecentProjectsCore()
self.__current_page = None
diff --git a/source/extensions/lightspeed.trex.material.core.shared/config/extension.toml b/source/extensions/lightspeed.trex.material.core.shared/config/extension.toml
index 6bfab01e2..0061082a0 100644
--- a/source/extensions/lightspeed.trex.material.core.shared/config/extension.toml
+++ b/source/extensions/lightspeed.trex.material.core.shared/config/extension.toml
@@ -1,5 +1,5 @@
[package]
-version = "1.0.3"
+version = "1.1.0"
authors =["Damien Bataille "]
title = "NVIDIA RTX Remix Material Core extension for the StageCraft"
description = "Extension that works on material data for NVIDIA RTX Remix StageCraft App"
diff --git a/source/extensions/lightspeed.trex.material.core.shared/docs/CHANGELOG.md b/source/extensions/lightspeed.trex.material.core.shared/docs/CHANGELOG.md
index 4618b0a00..8b0cfac35 100644
--- a/source/extensions/lightspeed.trex.material.core.shared/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.trex.material.core.shared/docs/CHANGELOG.md
@@ -1,6 +1,9 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.1.0]
+### Changed
+- Added material prim input support for `get_materials_from_prim()`
## [1.0.3]
### Changed
diff --git a/source/extensions/lightspeed.trex.material.core.shared/lightspeed/trex/material/core/shared/setup.py b/source/extensions/lightspeed.trex.material.core.shared/lightspeed/trex/material/core/shared/setup.py
index 1b80a4072..999a42685 100644
--- a/source/extensions/lightspeed.trex.material.core.shared/lightspeed/trex/material/core/shared/setup.py
+++ b/source/extensions/lightspeed.trex.material.core.shared/lightspeed/trex/material/core/shared/setup.py
@@ -55,8 +55,13 @@ def get_mat_from_geo(_prim):
return _material.GetPath()
return None
+ if not isinstance(prim, Usd.Prim) or not prim.IsValid():
+ return None
+
result = []
- if prim.IsValid() and (prim.IsA(UsdGeom.Subset) or prim.IsA(UsdGeom.Mesh)):
+ if prim.IsA(UsdShade.Material):
+ return [prim.GetPath()]
+ if prim.IsA(UsdGeom.Subset) or prim.IsA(UsdGeom.Mesh):
mat_prim = get_mat_from_geo(prim)
if mat_prim:
result.append(mat_prim)
diff --git a/source/extensions/lightspeed.trex.material_properties.shared.widget/config/extension.toml b/source/extensions/lightspeed.trex.material_properties.shared.widget/config/extension.toml
index 941580014..ce0ba8de2 100644
--- a/source/extensions/lightspeed.trex.material_properties.shared.widget/config/extension.toml
+++ b/source/extensions/lightspeed.trex.material_properties.shared.widget/config/extension.toml
@@ -1,5 +1,5 @@
[package]
-version = "1.3.21"
+version = "1.4.1"
authors =["Damien Bataille ", "Pierre-Olivier Trottier "]
title = "NVIDIA RTX Remix Material Properties implementation for the StageCraft"
description = "Material Properties implementation for NVIDIA RTX Remix StageCraft App"
@@ -20,7 +20,6 @@ repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tr
"lightspeed.tool.material.core" = {}
"lightspeed.trex.asset_replacements.core.shared" = {}
"lightspeed.trex.material.core.shared" = {}
-"lightspeed.trex.selection_tree.shared.widget" = {}
"lightspeed.trex.utils.widget" = {}
"lightspeed.trex.contexts" = {}
"omni.flux.asset_importer.core" = {}
diff --git a/source/extensions/lightspeed.trex.material_properties.shared.widget/docs/CHANGELOG.md b/source/extensions/lightspeed.trex.material_properties.shared.widget/docs/CHANGELOG.md
index a7780512c..d2a542290 100644
--- a/source/extensions/lightspeed.trex.material_properties.shared.widget/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.trex.material_properties.shared.widget/docs/CHANGELOG.md
@@ -1,6 +1,15 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.4.1]
+### Fixed
+- Fixed `refresh()` to function to account for instance prims
+
+## [1.4.0]
+### Changed
+- Changed `refresh()` to function based off of USD stage selection instead of Selection Tree
+- Removed Selection Tree logic and connections from e2e tests
+
## [1.3.21]
## Changed
- Set the column widths and allow resizing
diff --git a/source/extensions/lightspeed.trex.material_properties.shared.widget/lightspeed/trex/material_properties/shared/widget/setup_ui.py b/source/extensions/lightspeed.trex.material_properties.shared.widget/lightspeed/trex/material_properties/shared/widget/setup_ui.py
index 5fcb8a6b6..47021582b 100644
--- a/source/extensions/lightspeed.trex.material_properties.shared.widget/lightspeed/trex/material_properties/shared/widget/setup_ui.py
+++ b/source/extensions/lightspeed.trex.material_properties.shared.widget/lightspeed/trex/material_properties/shared/widget/setup_ui.py
@@ -20,7 +20,6 @@
import asyncio
import functools
import re
-import typing
from functools import partial
from pathlib import Path
@@ -35,7 +34,9 @@
from lightspeed.trex.contexts import get_instance as _trex_contexts_instance
from lightspeed.trex.contexts.setup import Contexts as _Contexts
from lightspeed.trex.material.core.shared import Setup as _MaterialCore
-from lightspeed.trex.selection_tree.shared.widget.selection_tree.model import ItemPrim as _ItemPrim
+from lightspeed.trex.utils.common.prim_utils import get_reference_file_paths as _get_reference_file_paths
+from lightspeed.trex.utils.common.prim_utils import is_instance as _is_instance
+from lightspeed.trex.utils.common.prim_utils import is_material_prototype as _is_material_prototype
from lightspeed.trex.utils.widget import TrexMessageDialog as _TrexMessageDialog
from omni import ui, usd
from omni.flux.asset_importer.core import determine_ideal_types as _determine_ideal_types
@@ -58,19 +59,6 @@
from .texture_assignment_model import Delegate, Model
-if typing.TYPE_CHECKING:
- from lightspeed.trex.selection_tree.shared.widget.selection_tree.model import (
- ItemAddNewReferenceFile as _ItemAddNewReferenceFileMesh,
- )
- from lightspeed.trex.selection_tree.shared.widget.selection_tree.model import ItemAsset as _ItemAsset
- from lightspeed.trex.selection_tree.shared.widget.selection_tree.model import ItemInstance as _ItemInstance
- from lightspeed.trex.selection_tree.shared.widget.selection_tree.model import (
- ItemInstancesGroup as _ItemInstancesGroup,
- )
- from lightspeed.trex.selection_tree.shared.widget.selection_tree.model import (
- ItemReferenceFile as _ItemReferenceFile,
- )
-
class TextureDialog(ui.Window):
def hide(self):
@@ -81,6 +69,7 @@ class SetupUI:
MATERIAL_LABEL_NAME_SIZE = 32
_WIDGET_PADDING = 16
+ MAT_PROP_FRAME = "material_property_frame"
def __init__(self, context_name: str):
"""Nvidia StageCraft Viewport UI"""
@@ -165,7 +154,7 @@ def __create_ui(self):
with ui.VStack(height=ui.Pixel(32)):
ui.Label("None", name="PropertiesWidgetLabel", alignment=ui.Alignment.CENTER)
self._frame_material_widget = ui.Frame(visible=False, identifier="frame_material_widget")
- self._material_properties_frames[_ItemPrim] = self._frame_material_widget
+ self._material_properties_frames[self.MAT_PROP_FRAME] = self._frame_material_widget
with self._frame_material_widget:
with ui.VStack(spacing=ui.Pixel(8)):
@@ -560,84 +549,95 @@ def _shorten_material_id_string(input_string: str, size: int, delimiter: str):
def _concat_list_to_string(items):
return "\n".join([str(item) for item in items])
- def refresh(
- self,
- items: list[
- _ItemAsset
- | _ItemReferenceFile
- | _ItemAddNewReferenceFileMesh
- | _ItemInstancesGroup
- | _ItemInstance
- | _ItemPrim
- ],
- ):
+ def refresh(self, items: list[Usd.Prim]):
+ """Items should be a list Usd.Prim from which materials can be derived."""
+
+ def hide_properties():
+ self._material_properties_widget.show(False) # to disable the listener
+ self._material_properties_frames[None].visible = True
+ self._material_properties_frames[self.MAT_PROP_FRAME].visible = False
+ self._set_material_label("None")
+ self._set_material_mdl_label("")
+
self._current_material_mdl_file = None
self._current_single_material = None
+ mdl_files: set[Path] = set()
- found = False
- for item_type, frame in self._material_properties_frames.items():
- if item_type is None:
- self._material_properties_frames[None].visible = False
+ # Filter prims and handle prims with refs
+ filtered_items = []
+ for item in items:
+ if not isinstance(item, Usd.Prim):
continue
- value = any(isinstance(item, item_type) for item in items) if items else False
- frame.visible = value
- if value:
- found = True
-
- if found:
- # we select the material
- self._selected_prims = [item.prim for item in items if isinstance(item, _ItemPrim)]
- if self._selected_prims:
- materials = []
- for prim in self._selected_prims:
- for mat in self._core.get_materials_from_prim(prim):
- if mat not in materials:
- materials.append(mat)
-
- mdl_files: set[Path] = set()
- for material in materials:
- material_prim = self._stage.GetPrimAtPath(material)
- shader_prim = omni.usd.get_shader_from_material(material_prim, True)
- if shader_prim:
- shader = UsdShade.Shader(shader_prim)
- source_asset = shader.GetSourceAsset("mdl") if shader else None
- if source_asset:
- mdl_file = source_asset.resolvedPath
- mdl_files.add(Path(mdl_file))
-
- if materials:
- asyncio.ensure_future(self._refresh_material_menu())
- self._material_properties_widget.show(True)
- # TODO: Selection is not ordered by user but by tree view position, so displaying only one value
- # value where user cannot control which one is shown is not the best UX.
- self._material_properties_widget.refresh(materials)
- material_label_text = self._shorten_material_id_string(
- str(materials[0]), self.MATERIAL_LABEL_NAME_SIZE, "/"
- )
- if len(materials) == 1:
- self._set_material_label(material_label_text)
- self._current_single_material = materials[0]
- else:
- multiple_info_text = f"Multiple Selected (editing all, displaying {material_label_text})"
- multiple_info_details = multiple_info_text + "\n\n" + SetupUI._concat_list_to_string(materials)
- self._set_material_label(multiple_info_text, tooltip=multiple_info_details)
-
- mdl_file_label = "None"
- mdl_file_label_tooltip = ""
- if len(mdl_files) == 1:
- self._current_material_mdl_file = mdl_files.pop()
- mdl_file_label = self._current_material_mdl_file.name
- mdl_file_label_tooltip = str(self._current_material_mdl_file.absolute())
- elif len(mdl_files) > 1:
- mdl_file_label = "Multiple"
- self._set_material_mdl_label(mdl_file_label, tooltip=mdl_file_label_tooltip)
-
- return
- self._material_properties_widget.show(False) # to disable the listener
- self._material_properties_frames[None].visible = True
- self._material_properties_frames[_ItemPrim].visible = False
- self._set_material_label("None")
- self._set_material_mdl_label("")
+
+ # If instance prim, get and use the correlating mesh prim
+ if _is_instance(item):
+ prototype_prim = self._asset_replacement_core.get_corresponding_prototype_prims([item])
+ if not prototype_prim:
+ continue
+ item = self._stage.GetPrimAtPath(prototype_prim[0])
+ if not item:
+ continue
+
+ # If not a mat prim and has reference, refresh widget to clear
+ if not _is_material_prototype(item) and _get_reference_file_paths(item)[1]:
+ self.refresh([])
+
+ # Add the item; Should be mat or mesh prim
+ filtered_items.append(item)
+
+ if not filtered_items:
+ hide_properties()
+ return
+
+ # Gather materials
+ materials = set()
+ for prim in filtered_items:
+ for mat in self._core.get_materials_from_prim(prim):
+ materials.add(mat)
+ materials = list(materials)
+
+ if not materials:
+ hide_properties()
+ return
+
+ # Build material property widget accordingly
+ self._material_properties_frames[self.MAT_PROP_FRAME].visible = True
+ self._material_properties_frames[None].visible = False
+
+ for material in materials:
+ material_prim = self._stage.GetPrimAtPath(material)
+ shader_prim = omni.usd.get_shader_from_material(material_prim, True)
+ if shader_prim:
+ shader = UsdShade.Shader(shader_prim)
+ source_asset = shader.GetSourceAsset("mdl") if shader else None
+ if source_asset:
+ mdl_file = source_asset.resolvedPath
+ mdl_files.add(Path(mdl_file))
+
+ asyncio.ensure_future(self._refresh_material_menu())
+ self._material_properties_widget.show(True)
+ # TODO: For multi-selection, properties are ordered by USD, not click-order in Stage Manager or Selection Tree.
+ # Displaying only one set of shared property values is not the best UX.
+ self._material_properties_widget.refresh(materials)
+ material_label_text = self._shorten_material_id_string(str(materials[0]), self.MATERIAL_LABEL_NAME_SIZE, "/")
+ if len(materials) == 1:
+ self._set_material_label(material_label_text)
+ self._current_single_material = materials[0]
+ else:
+ multiple_info_text = f"Multiple Selected (editing all, displaying {material_label_text})"
+ multiple_info_details = multiple_info_text + "\n\n" + SetupUI._concat_list_to_string(materials)
+ self._set_material_label(multiple_info_text, tooltip=multiple_info_details)
+ self._current_single_material = None
+
+ mdl_file_label = "None"
+ mdl_file_label_tooltip = ""
+ if len(mdl_files) == 1:
+ self._current_material_mdl_file = mdl_files.pop()
+ mdl_file_label = self._current_material_mdl_file.name
+ mdl_file_label_tooltip = str(self._current_material_mdl_file.absolute())
+ elif len(mdl_files) > 1:
+ mdl_file_label = "Multiple"
+ self._set_material_mdl_label(mdl_file_label, tooltip=mdl_file_label_tooltip)
def _set_material_label(self, label: str, tooltip=None):
self._current_material_label.text = label
diff --git a/source/extensions/lightspeed.trex.material_properties.shared.widget/lightspeed/trex/material_properties/shared/widget/tests/e2e/test_widget.py b/source/extensions/lightspeed.trex.material_properties.shared.widget/lightspeed/trex/material_properties/shared/widget/tests/e2e/test_widget.py
index 467a7ef94..2c9a3ee65 100644
--- a/source/extensions/lightspeed.trex.material_properties.shared.widget/lightspeed/trex/material_properties/shared/widget/tests/e2e/test_widget.py
+++ b/source/extensions/lightspeed.trex.material_properties.shared.widget/lightspeed/trex/material_properties/shared/widget/tests/e2e/test_widget.py
@@ -33,7 +33,6 @@
from lightspeed.trex.contexts import get_instance as _trex_contexts_instance
from lightspeed.trex.contexts.setup import Contexts as _Contexts
from lightspeed.trex.material_properties.shared.widget import SetupUI as _MaterialPropertiesWidget
-from lightspeed.trex.selection_tree.shared.widget import SetupUI as _SelectionTreeWidget
from omni.flux.utils.common import path_utils as _path_utils
from omni.flux.utils.common.omni_url import OmniUrl
from omni.flux.utils.widget.resources import get_test_data as _get_test_data
@@ -92,11 +91,7 @@ class TestComponents(Enum):
FILE_PICKER_CANCEL = 18
-class TestSelectionTreeWidget(AsyncTestCase):
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.__sub_tree_selection_changed = []
-
+class TestMaterialPropertyWidget(AsyncTestCase):
# Before running each test
async def setUp(self):
await arrange_windows()
@@ -110,25 +105,34 @@ async def tearDown(self):
pass
async def __setup_widget(self):
- window = ui.Window("TestSelectionTreeUI", height=1200, width=800)
+ window = ui.Window("TestMaterialPropertyWidgetUI", height=800, width=500)
with window.frame:
with ui.HStack():
- selection_wid = _SelectionTreeWidget("")
- selection_wid.show(True)
- mesh_property_wid = _MaterialPropertiesWidget("")
- mesh_property_wid.show(True)
+ mat_property_wid = _MaterialPropertiesWidget("")
+ mat_property_wid.show(True)
- def _on_tree_selection_changed(items):
- items = selection_wid.get_selection()
- mesh_property_wid.refresh(items)
+ usd_context = omni.usd.get_context()
- self.__sub_tree_selection_changed.append(
- selection_wid.subscribe_tree_selection_changed(_on_tree_selection_changed)
+ # Create Material Property refresher for USD selection changed events
+ def on_stage_event(event):
+ if event.type == int(omni.usd.StageEventType.SELECTION_CHANGED):
+ # Grab the USD selected prims
+ prim_paths = list(set(usd_context.get_selection().get_selected_prim_paths()))
+ items = [usd_context.get_stage().GetPrimAtPath(prim_path) for prim_path in prim_paths]
+
+ # Grab prims and refresh the material properties
+ mat_property_wid.refresh(items) # NOTE: This occurs from AssetReplacementsPane in app
+
+ # Subscribe to USD selection changes
+ self._events = usd_context.get_stage_event_stream()
+ self._stage_event_delegate = self._events.create_subscription_to_pop(
+ on_stage_event,
+ name="Selection Change Subscription",
)
await ui_test.human_delay(human_delay_speed=1)
- return window, selection_wid, mesh_property_wid
+ return window, mat_property_wid
async def __find_file_picker_buttons(self, window_title):
components = {
@@ -151,9 +155,12 @@ async def __find_file_picker_buttons(self, window_title):
return components
- async def __destroy(self, window, selection_wid, mesh_property_wid):
- mesh_property_wid.destroy()
- selection_wid.destroy()
+ async def __destroy(self, window, material_property_wid):
+ self._events = None
+ self._stage_event_delegate.unsubscribe()
+ self._stage_event_delegate = None
+
+ material_property_wid.destroy()
window.destroy()
# destroy prompt dialogs to avoid unwanted references
@@ -198,7 +205,7 @@ async def _get_group_texture_file_fields(self, _window, group):
async def test_select_one_prim_mesh(self):
# setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# select
usd_context = omni.usd.get_context()
@@ -213,11 +220,11 @@ async def test_select_one_prim_mesh(self):
self.assertFalse(frame_none.widget.visible)
self.assertTrue(frame_material.widget.visible)
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_select_instance_mesh_prim(self):
# setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# select
usd_context = omni.usd.get_context()
@@ -234,11 +241,11 @@ async def test_select_instance_mesh_prim(self):
self.assertFalse(frame_none.widget.visible)
self.assertTrue(frame_material.widget.visible)
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_select_nothing(self):
# setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# select
usd_context = omni.usd.get_context()
@@ -253,11 +260,11 @@ async def test_select_nothing(self):
self.assertTrue(frame_none.widget.visible)
self.assertFalse(frame_material.widget.visible)
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_override_texture_ingested_texture(self):
# setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# select
usd_context = omni.usd.get_context()
@@ -289,11 +296,11 @@ async def test_override_texture_ingested_texture(self):
OmniUrl(asset_path).path, OmniUrl(texture_file_fields[0].widget.model.get_value_as_string()).path
)
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_override_texture_not_ingested_texture_cancel(self):
# setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# select
usd_context = omni.usd.get_context()
@@ -328,11 +335,11 @@ async def test_override_texture_not_ingested_texture_cancel(self):
# text should go back like before
self.assertEquals(original_text, texture_file_fields[0].widget.model.get_value_as_string())
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_override_texture_not_ingested_texture_ignore(self):
# setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# select
usd_context = omni.usd.get_context()
@@ -368,11 +375,11 @@ async def test_override_texture_not_ingested_texture_ignore(self):
OmniUrl(asset_path).path, OmniUrl(diffuse_texture_file_field.widget.model.get_value_as_string()).path
)
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_override_texture_ingested_texture_outside_project_dir_cancel(self):
# Setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# Select
usd_context = omni.usd.get_context()
@@ -425,11 +432,11 @@ async def test_override_texture_ingested_texture_outside_project_dir_cancel(self
# Text field should revert to the original path
self.assertEquals(original_text, diffuse_texture_file_field.widget.model.get_value_as_string())
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_override_texture_ingested_texture_outside_project_dir_copy_and_re_ref(self):
# Setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# Select
usd_context = omni.usd.get_context()
@@ -486,11 +493,11 @@ async def test_override_texture_ingested_texture_outside_project_dir_copy_and_re
# Delete the newly created project_example/assets/ingested subdirectory and its contents
shutil.rmtree(_get_test_data(f"usd/project_example/{str(_constants.REMIX_INGESTED_ASSETS_FOLDER)}"))
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_override_texture_not_ingested_texture_outside_project_dir_no_metadata_cancel(self):
# Setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# Select
usd_context = omni.usd.get_context()
@@ -542,12 +549,12 @@ async def test_override_texture_not_ingested_texture_outside_project_dir_no_meta
# Text should go back like before
self.assertEquals(original_text, diffuse_texture_file_field.widget.model.get_value_as_string())
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_drop_texture(self):
# setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
- _mesh_property_wid.set_external_drag_and_drop(window_name=_window.title)
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
+ _material_property_wid.set_external_drag_and_drop(window_name=_window.title)
# select
usd_context = omni.usd.get_context()
@@ -583,11 +590,11 @@ async def test_drop_texture(self):
)
self.assertEquals(rel_path, texture_file_fields[1].widget.model.get_value_as_string())
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_texture_set_assignment(self):
# setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# select
usd_context = omni.usd.get_context()
@@ -618,11 +625,11 @@ async def test_texture_set_assignment(self):
OmniUrl(rel_path).path, OmniUrl(texture_file_fields[1].widget.model.get_value_as_string()).path
)
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_texture_set_multiple_assignment(self):
# setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# Create a temp directory to create a variety of files
with tempfile.TemporaryDirectory(
@@ -712,11 +719,11 @@ async def test_texture_set_multiple_assignment(self):
with self.subTest(name=rel_path):
self.assertEquals(rel_path, texture_file_fields[index].widget.model.get_value_as_string())
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_copy_from_material_label_copy_menu(self):
# setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# select
usd_context = omni.usd.get_context()
@@ -751,11 +758,11 @@ async def test_copy_from_material_label_copy_menu(self):
copied_text = omni.kit.clipboard.paste()
self.assertTrue(copied_text.endswith("AperturePBR_Opacity.mdl"))
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_copy_from_texture_string_field_copy_menu(self):
# setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# select
usd_context = omni.usd.get_context()
@@ -808,11 +815,11 @@ async def test_copy_from_texture_string_field_copy_menu(self):
await ui_test.human_delay(5)
self.assertFalse("Copy File Path Hash" in context_menu.get("_"))
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_texture_string_field_tooltips_set_and_update(self):
# setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# select
usd_context = omni.usd.get_context()
@@ -868,11 +875,11 @@ async def test_texture_string_field_tooltips_set_and_update(self):
await ui_test.human_delay(5)
self.assertEqual(texture_file_fields[1].widget.tooltip.lower(), roughness_texture_asset_path.lower())
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
async def test_texture_string_field_tooltips_with_different_layer_and_edit_target(self):
# setup
- _window, _selection_wid, _mesh_property_wid = await self.__setup_widget() # Keep in memory during test
+ _window, _material_property_wid = await self.__setup_widget() # Keep in memory during test
# select
usd_context = omni.usd.get_context()
@@ -919,4 +926,4 @@ async def test_texture_string_field_tooltips_with_different_layer_and_edit_targe
asset_path = _get_test_data(f"usd/{RELATIVE_CAPTURE_TEXTURE_PATH}{MATERIAL_HASH}.dds")
self.assertEqual(texture_file_fields[0].widget.tooltip.lower(), asset_path.lower())
- await self.__destroy(_window, _selection_wid, _mesh_property_wid)
+ await self.__destroy(_window, _material_property_wid)
diff --git a/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/config/extension.toml b/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/config/extension.toml
index f00132e54..f33a6c903 100644
--- a/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/config/extension.toml
+++ b/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/config/extension.toml
@@ -1,5 +1,5 @@
[package]
-version = "1.3.2"
+version = "1.4.0"
authors =["Damien Bataille "]
title = "NVIDIA RTX Remix Properties Pane Asset Replacements widget for the StageCraft"
description = "Asset Replacements Properties Pane widget for NVIDIA RTX Remix StageCraft App"
@@ -12,6 +12,7 @@ preview_image = "data/preview.png"
repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget"
[dependencies]
+"lightspeed.trex.material.core.shared" = {}
"lightspeed.trex.material_properties.shared.widget" = {}
"lightspeed.trex.mesh_properties.shared.widget" = {}
"lightspeed.trex.replacement.core.shared" = {}
@@ -24,6 +25,7 @@ repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tr
"omni.flux.utils.common" = {}
"omni.flux.utils.widget" = {}
"omni.ui" = {}
+"omni.usd" = {}
"omni.client" = {}
[[python.module]]
@@ -32,7 +34,6 @@ name = "lightspeed.trex.properties_pane.shared.asset_replacements.widget"
[[test]]
dependencies = [
"lightspeed.trex.tests.dependencies",
- "omni.usd"
]
args = [
diff --git a/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/docs/CHANGELOG.md b/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/docs/CHANGELOG.md
index d862aeaa4..313043cc1 100644
--- a/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/docs/CHANGELOG.md
@@ -1,6 +1,12 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.4.0]
+## Changed
+- Material property widget & pinning now driven by USD stage selection
+- Direct material prim selection now populates the material property widget
+- Fixed test bug where tests couldn't re-run without failing
+
## [1.3.2]
## Changed
- Update to Kit 106.5
diff --git a/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/lightspeed/trex/properties_pane/shared/asset_replacements/widget/setup_ui.py b/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/lightspeed/trex/properties_pane/shared/asset_replacements/widget/setup_ui.py
index 37b116383..32cf36c4b 100644
--- a/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/lightspeed/trex/properties_pane/shared/asset_replacements/widget/setup_ui.py
+++ b/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/lightspeed/trex/properties_pane/shared/asset_replacements/widget/setup_ui.py
@@ -21,10 +21,12 @@
from typing import Any, Callable, List
import omni.client
+import omni.usd
from lightspeed.common.constants import GAME_READY_ASSETS_FOLDER as _GAME_READY_ASSETS_FOLDER
from lightspeed.common.constants import REMIX_CAPTURE_FOLDER as _REMIX_CAPTURE_FOLDER
from lightspeed.layer_manager.core import LayerManagerCore as _LayerManagerCore
from lightspeed.layer_manager.core import LayerType as _LayerType
+from lightspeed.trex.material.core.shared import Setup as _MaterialCore
from lightspeed.trex.material_properties.shared.widget import SetupUI as _MaterialPropertiesWidget
from lightspeed.trex.mesh_properties.shared.widget import SetupUI as _MeshPropertiesWidget
from lightspeed.trex.replacement.core.shared import Setup as _AssetReplacementCore
@@ -47,7 +49,7 @@
from omni.flux.utils.widget.collapsable_frame import (
PropertyCollapsableFrameWithInfoPopup as _PropertyCollapsableFrameWithInfoPopup,
)
-from pxr import Sdf, Tf
+from pxr import Sdf, Tf, Usd
class CollapsiblePanels(Enum):
@@ -94,6 +96,7 @@ def __init__(self, context_name: str):
self._context_name = context_name
self._replacement_core = _AssetReplacementCore(context_name)
self._layers_core = _AssetReplacementLayersCore(context_name)
+ self._material_core = _MaterialCore(context_name)
self._material_converted_sub = None
@@ -289,7 +292,7 @@ def __create_ui(self):
"the weaker layer (bottom).\n",
collapsed=False,
pinnable=True,
- pinned_text_fn=lambda: self._get_selection_name_by_type([_ItemPrim]),
+ pinned_text_fn=lambda: self._get_selection_name_by_type([Usd.Prim]),
unpinned_fn=self._refresh_material_properties_widget,
)
self._collapsible_frame_states[CollapsiblePanels.MATERIAL_PROPERTIES] = True
@@ -338,19 +341,31 @@ def selection_tree_widget(self):
return self._selection_tree_widget
def _get_selection_name_by_type(self, selection_types: List):
- # get a selection based on desired types in descending order from selection_types
- selection = []
+ context = omni.usd.get_context(self._context_name)
+ stage = context.get_stage()
+ selection_prim_paths = context.get_selection().get_selected_prim_paths()
+
+ # Get all of the material prims from the current selection without duplicates
+ material_prims = set()
+ for prim_path in selection_prim_paths:
+ prim = stage.GetPrimAtPath(prim_path)
+ for material_prim in self._material_core.get_materials_from_prim(prim):
+ material_prims.add(stage.GetPrimAtPath(material_prim))
+ selection = list(material_prims)
+
+ # Get a filtered selection based on desired types in descending order from selection_types
+ type_filtered_selection = []
for selection_type in selection_types:
- selection = [
- item for item in self._selection_tree_widget.get_selection() if isinstance(item, selection_type)
- ]
- if selection:
+ type_filtered_selection = [item for item in selection if isinstance(item, selection_type)]
+ if type_filtered_selection:
break
- if not selection:
+ if not type_filtered_selection:
return "None Selected"
- if len(selection) == 1:
- formatted_name = "/".join(selection[0].path.split("/")[-2:]).lstrip("/")
+ if len(type_filtered_selection) == 1:
+ # Create parent/child formatted name and limit to 50 chars in length
+ path = type_filtered_selection[0].GetPath()
+ formatted_name = f"{path.GetParentPath().name}/{path.name}"
return formatted_name if len(formatted_name) < 50 else "..." + formatted_name[-50:]
return "Multiple Selected"
@@ -424,7 +439,11 @@ def _refresh_mesh_properties_widget(self):
def _refresh_material_properties_widget(self):
if self._material_properties_collapsable_frame.pinned:
return
- items = self._selection_tree_widget.get_selection()
+
+ # Grab the selection prims and refresh the properties
+ context = omni.usd.get_context(self._context_name)
+ prim_paths = list(set(context.get_selection().get_selected_prim_paths()))
+ items = [context.get_stage().GetPrimAtPath(prim_path) for prim_path in prim_paths]
self._material_properties_widget.refresh(items)
def refresh(self):
diff --git a/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/lightspeed/trex/properties_pane/shared/asset_replacements/widget/tests/e2e/test_widget.py b/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/lightspeed/trex/properties_pane/shared/asset_replacements/widget/tests/e2e/test_widget.py
index c1bfda462..2bf264872 100644
--- a/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/lightspeed/trex/properties_pane/shared/asset_replacements/widget/tests/e2e/test_widget.py
+++ b/source/extensions/lightspeed.trex.properties_pane.shared.asset_replacements.widget/lightspeed/trex/properties_pane/shared/asset_replacements/widget/tests/e2e/test_widget.py
@@ -47,7 +47,7 @@ async def __setup_widget(self, title: str):
wid = _AssetReplacementsPane("")
wid.show(True)
- await ui_test.human_delay(human_delay_speed=1)
+ await ui_test.human_delay(human_delay_speed=2) # test re-runs will fail if speed < 2
return window, wid
@@ -236,6 +236,119 @@ async def test_material_properties_cleared_when_none_selected(self):
await self.__destroy(_window, _wid)
+ async def test_select_material_prim_populates_material_properties(self):
+ # setup
+ _window, _wid = await self.__setup_widget("test_select_material_prim")
+
+ # ensure the proper frames exist
+ frame_material = ui_test.find(f"{_window.title}//Frame/**/Frame[*].identifier=='frame_material_widget'")
+ self.assertIsNotNone(frame_material)
+
+ # ensure the none frames exist and all are visible
+ none_frames = ui_test.find_all(f"{_window.title}//Frame/**/Frame[*].identifier=='frame_none'")
+ self.assertEqual(len(none_frames), 3)
+ self.assertTrue(none_frames[0].widget.visible) # selection tree
+ self.assertTrue(none_frames[1].widget.visible) # object properties
+ self.assertTrue(none_frames[2].widget.visible) # material properties
+
+ # ensure selection tree is empty still
+ selection_tree = ui_test.find(f"{_window.title}//Frame/**/TreeView[*].identifier=='LiveSelectionTreeView'")
+ self.assertEqual(len(selection_tree.widget.selection), 0)
+
+ # select
+ usd_context = omni.usd.get_context()
+ usd_context.get_selection().set_selected_prim_paths(["/RootNode/Looks/mat_BC868CE5A075ABB1"], False)
+ await ui_test.human_delay(human_delay_speed=3)
+
+ # ensure the respective none frames are visible/invisible and material widget is visible
+ none_frames = ui_test.find_all(f"{_window.title}//Frame/**/Frame[*].identifier=='frame_none'")
+ frame_material = ui_test.find(f"{_window.title}//Frame/**/Frame[*].identifier=='frame_material_widget'")
+ self.assertTrue(none_frames[0].widget.visible) # selection tree
+ self.assertTrue(none_frames[1].widget.visible) # object properties
+ self.assertFalse(none_frames[2].widget.visible) # material properties
+ self.assertTrue(frame_material.widget.visible) # material widget
+
+ # ensure the selection tree is still not occupied since direct mat selection
+ self.assertEqual(len(selection_tree.widget.selection), 0)
+
+ await self.__destroy(_window, _wid)
+
+ async def test_select_mesh_prim_populates_widgets(self):
+ # setup
+ _window, _wid = await self.__setup_widget("test_select_mesh_prim_populates_widgets")
+
+ # ensure the proper frames exist
+ frame_material = ui_test.find(f"{_window.title}//Frame/**/Frame[*].identifier=='frame_material_widget'")
+ self.assertIsNotNone(frame_material)
+
+ # ensure the none frames exist and all are visible
+ none_frames = ui_test.find_all(f"{_window.title}//Frame/**/Frame[*].identifier=='frame_none'")
+ self.assertEqual(len(none_frames), 3)
+ self.assertTrue(none_frames[0].widget.visible) # selection tree
+ self.assertTrue(none_frames[1].widget.visible) # object properties
+ self.assertTrue(none_frames[2].widget.visible) # material properties
+
+ # ensure selection tree is empty still
+ selection_tree = ui_test.find(f"{_window.title}//Frame/**/TreeView[*].identifier=='LiveSelectionTreeView'")
+ self.assertEqual(len(selection_tree.widget.selection), 0)
+
+ # select
+ usd_context = omni.usd.get_context()
+ usd_context.get_selection().set_selected_prim_paths(["/RootNode/meshes/mesh_0AB745B8BEE1F16B/mesh"], False)
+ await ui_test.human_delay(human_delay_speed=3)
+
+ # ensure the respective none frames are not visible and material widget is visible
+ none_frames = ui_test.find_all(f"{_window.title}//Frame/**/Frame[*].identifier=='frame_none'")
+ frame_material = ui_test.find(f"{_window.title}//Frame/**/Frame[*].identifier=='frame_material_widget'")
+ self.assertFalse(none_frames[0].widget.visible) # selection tree
+ self.assertFalse(none_frames[1].widget.visible) # object properties
+ self.assertFalse(none_frames[2].widget.visible) # material properties
+ self.assertTrue(frame_material.widget.visible) # material widget
+
+ # ensure the selection tree is occupied with the selection since mesh selection
+ self.assertEqual(len(selection_tree.widget.selection), 1)
+
+ await self.__destroy(_window, _wid)
+
+ async def test_select_material_and_mesh_prims_populates_widgets(self):
+ # setup
+ _window, _wid = await self.__setup_widget("test_select_material_and_mesh_prims")
+
+ # ensure the proper frames exist
+ frame_material = ui_test.find(f"{_window.title}//Frame/**/Frame[*].identifier=='frame_material_widget'")
+ self.assertIsNotNone(frame_material)
+
+ # ensure the none frames exist and all are visible
+ none_frames = ui_test.find_all(f"{_window.title}//Frame/**/Frame[*].identifier=='frame_none'")
+ self.assertEqual(len(none_frames), 3)
+ self.assertTrue(none_frames[0].widget.visible) # selection tree
+ self.assertTrue(none_frames[1].widget.visible) # object properties
+ self.assertTrue(none_frames[2].widget.visible) # material properties
+
+ # ensure selection tree is empty still
+ selection_tree = ui_test.find(f"{_window.title}//Frame/**/TreeView[*].identifier=='LiveSelectionTreeView'")
+ self.assertEqual(len(selection_tree.widget.selection), 0)
+
+ # select
+ usd_context = omni.usd.get_context()
+ usd_context.get_selection().set_selected_prim_paths(
+ ["/RootNode/Looks/mat_BC868CE5A075ABB1", "/RootNode/meshes/mesh_0AB745B8BEE1F16B/mesh"], False
+ )
+ await ui_test.human_delay(human_delay_speed=3)
+
+ # ensure the respective none frames are not visible and material widget is visible
+ none_frames = ui_test.find_all(f"{_window.title}//Frame/**/Frame[*].identifier=='frame_none'")
+ frame_material = ui_test.find(f"{_window.title}//Frame/**/Frame[*].identifier=='frame_material_widget'")
+ self.assertFalse(none_frames[0].widget.visible) # selection tree
+ self.assertFalse(none_frames[1].widget.visible) # object properties
+ self.assertFalse(none_frames[2].widget.visible) # material properties
+ self.assertTrue(frame_material.widget.visible) # material widget
+
+ # ensure the selection tree is occupied with the selection since mesh selection
+ self.assertEqual(len(selection_tree.widget.selection), 1)
+
+ await self.__destroy(_window, _wid)
+
async def test_object_pinning(self):
# setup
_window, _wid = await self.__setup_widget("test_collapse_refresh_object_property_when_collapsed")
@@ -279,7 +392,7 @@ async def test_object_pinning(self):
self.assertTrue(frame_mesh_prim.widget.visible)
await self.__destroy(_window, _wid)
- async def test_material_pinning(self):
+ async def test_material_pinning_from_mesh_selection(self):
# setup
_window, _wid = await self.__setup_widget("test_collapse_refresh_object_property_when_collapsed")
@@ -316,6 +429,45 @@ async def test_material_pinning(self):
self.assertFalse(frame_material.widget.visible)
await self.__destroy(_window, _wid)
+ async def test_material_pinning_from_material_selection(self):
+ # setup
+ _window, _wid = await self.__setup_widget("test_collapse_refresh_object_property_when_collapsed")
+
+ # ensure the material frame exists
+ frame_material = ui_test.find(f"{_window.title}//Frame/**/Frame[*].identifier=='frame_material_widget'")
+ self.assertIsNotNone(frame_material)
+
+ # select a mesh and ensure the material properties are visible
+ usd_context = omni.usd.get_context()
+ usd_context.get_selection().set_selected_prim_paths(["/RootNode/Looks/mat_BC868CE5A075ABB1"], False)
+ await ui_test.human_delay(human_delay_speed=10)
+ self.assertTrue(frame_material.widget.visible)
+
+ # click the pin icons to pin
+ pin_icon_images = ui_test.find_all(f"{_window.title}//Frame/**/Image[*].identifier=='property_frame_pin_icon'")
+ self.assertEqual(len(pin_icon_images), 2)
+ await pin_icon_images[1].click()
+ await ui_test.human_delay()
+
+ # change selection to the mesh reference in USD context and selection tree
+ usd_context.get_selection().set_selected_prim_paths(["/RootNode/meshes/mesh_0AB745B8BEE1F16B/mesh"], False)
+ await ui_test.human_delay(human_delay_speed=10)
+ item_prims = ui_test.find_all(f"{_window.title}//Frame/**/Label[*].identifier=='item_prim'")
+ await item_prims[0].click()
+ await ui_test.human_delay()
+
+ # material properties should still be visible since pinned
+ self.assertTrue(frame_material.widget.visible)
+
+ # click the pin icons to un-pin
+ pin_icon_images = ui_test.find_all(f"{_window.title}//Frame/**/Image[*].identifier=='property_frame_pin_icon'")
+ await pin_icon_images[1].click()
+ await ui_test.human_delay()
+
+ # material properties should no longer be visible since un-pinned
+ self.assertFalse(frame_material.widget.visible)
+ await self.__destroy(_window, _wid)
+
async def test_object_and_material_pin_labels_exist(self):
# setup
_window, _wid = await self.__setup_widget("test_collapse_refresh_object_property_when_collapsed")
diff --git a/source/extensions/lightspeed.trex.recent_projects.core/config/extension.toml b/source/extensions/lightspeed.trex.recent_projects.core/config/extension.toml
new file mode 100644
index 000000000..d3b7e6a88
--- /dev/null
+++ b/source/extensions/lightspeed.trex.recent_projects.core/config/extension.toml
@@ -0,0 +1,21 @@
+[package]
+version = "1.0.0"
+authors = ["dbataille@nvidia.com", "ptrottier@nvidia.com"]
+repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit"
+changelog = "docs/CHANGELOG.md"
+readme = "docs/README.md"
+keywords = ["core", "save", "manager", "recent", "project"]
+title = "Lightspeed Recent Project Core"
+description = "Core funtionality to get and save recent projects"
+icon = "data/icon.png"
+preview_image = "data/preview.png"
+category = "internal"
+
+[dependencies]
+"lightspeed.layer_manager.core" = {}
+"omni.client" = {}
+"omni.flux.utils.common" = {}
+"omni.usd" = {}
+
+[[python.module]]
+name = "lightspeed.trex.recent_projects.core"
diff --git a/source/extensions/lightspeed.layer_helpers/data/icon.png b/source/extensions/lightspeed.trex.recent_projects.core/data/icon.png
similarity index 100%
rename from source/extensions/lightspeed.layer_helpers/data/icon.png
rename to source/extensions/lightspeed.trex.recent_projects.core/data/icon.png
diff --git a/source/extensions/lightspeed.asset_capture_localizer.core/data/preview.png b/source/extensions/lightspeed.trex.recent_projects.core/data/preview.png
similarity index 100%
rename from source/extensions/lightspeed.asset_capture_localizer.core/data/preview.png
rename to source/extensions/lightspeed.trex.recent_projects.core/data/preview.png
diff --git a/source/extensions/lightspeed.trex.recent_projects.core/docs/CHANGELOG.md b/source/extensions/lightspeed.trex.recent_projects.core/docs/CHANGELOG.md
new file mode 100644
index 000000000..db85d9d8c
--- /dev/null
+++ b/source/extensions/lightspeed.trex.recent_projects.core/docs/CHANGELOG.md
@@ -0,0 +1,6 @@
+# Changelog
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+
+## [1.0.0]
+### Added
+- Init commit
diff --git a/source/extensions/lightspeed.trex.recent_projects.core/docs/README.md b/source/extensions/lightspeed.trex.recent_projects.core/docs/README.md
new file mode 100644
index 000000000..9c14b524f
--- /dev/null
+++ b/source/extensions/lightspeed.trex.recent_projects.core/docs/README.md
@@ -0,0 +1 @@
+# lightspeed.trex.recent_projects.core
diff --git a/source/extensions/lightspeed.upscale.core/docs/index.rst b/source/extensions/lightspeed.trex.recent_projects.core/docs/index.rst
similarity index 54%
rename from source/extensions/lightspeed.upscale.core/docs/index.rst
rename to source/extensions/lightspeed.trex.recent_projects.core/docs/index.rst
index df539dc94..9046c16e3 100644
--- a/source/extensions/lightspeed.upscale.core/docs/index.rst
+++ b/source/extensions/lightspeed.trex.recent_projects.core/docs/index.rst
@@ -1,6 +1,5 @@
-lightspeed.upscale.core
-###########################
-
+lightspeed.trex.recent_projects.core
+#####################################
.. toctree::
:maxdepth: 1
@@ -8,11 +7,10 @@ lightspeed.upscale.core
README
CHANGELOG
-
-.. automodule:: lightspeed.upscale.core
+.. automodule:: lightspeed.trex.recent_projects.core
:platform: Windows-x86_64, Linux-x86_64
:members:
:undoc-members:
:show-inheritance:
:imported-members:
- :exclude-members: contextmanager
+ :exclude-members:
diff --git a/source/extensions/lightspeed.color_to_roughness.menu/lightspeed/color_to_roughness/menu/__init__.py b/source/extensions/lightspeed.trex.recent_projects.core/lightspeed/trex/recent_projects/core/__init__.py
similarity index 94%
rename from source/extensions/lightspeed.color_to_roughness.menu/lightspeed/color_to_roughness/menu/__init__.py
rename to source/extensions/lightspeed.trex.recent_projects.core/lightspeed/trex/recent_projects/core/__init__.py
index 084e7bbe3..918c4e293 100644
--- a/source/extensions/lightspeed.color_to_roughness.menu/lightspeed/color_to_roughness/menu/__init__.py
+++ b/source/extensions/lightspeed.trex.recent_projects.core/lightspeed/trex/recent_projects/core/__init__.py
@@ -15,4 +15,4 @@
* limitations under the License.
"""
-from .menu import * # noqa: F401
+from .core import RecentProjectsCore
diff --git a/source/extensions/lightspeed.event.save_recent/lightspeed/event/save_recent/recent_saved_file_utils.py b/source/extensions/lightspeed.trex.recent_projects.core/lightspeed/trex/recent_projects/core/core.py
similarity index 95%
rename from source/extensions/lightspeed.event.save_recent/lightspeed/event/save_recent/recent_saved_file_utils.py
rename to source/extensions/lightspeed.trex.recent_projects.core/lightspeed/trex/recent_projects/core/core.py
index c313aed13..b0e56e496 100644
--- a/source/extensions/lightspeed.event.save_recent/lightspeed/event/save_recent/recent_saved_file_utils.py
+++ b/source/extensions/lightspeed.trex.recent_projects.core/lightspeed/trex/recent_projects/core/core.py
@@ -15,7 +15,7 @@
* limitations under the License.
"""
-__all__ = ["RecentSavedFile"]
+__all__ = ["RecentProjectsCore"]
import asyncio
@@ -29,6 +29,7 @@
import carb
import carb.tokens
import omni.client
+import omni.usd
from lightspeed.layer_manager.core import (
LSS_LAYER_GAME_NAME,
LSS_LAYER_MOD_NAME,
@@ -40,7 +41,7 @@
from pxr import Sdf, Tf
-class RecentSavedFile:
+class RecentProjectsCore:
def __get_recent_dir(self) -> str:
"""Return the file"""
token = carb.tokens.get_tokens_interface()
@@ -171,7 +172,7 @@ async def find_thumbnail_async(path: str, auto=False):
if result == omni.client.Result.OK:
return path, thumbnail
if not auto:
- return await RecentSavedFile.find_thumbnail_async(path, auto=True)
+ return await RecentProjectsCore.find_thumbnail_async(path, auto=True)
return None, None
@staticmethod
@@ -183,13 +184,3 @@ def convert_size(size_bytes):
p = math.pow(1024, i)
s = round(size_bytes / p, 2)
return f"{s} {size_name[i]}"
-
-
-_INSTANCE = None
-
-
-def get_instance():
- global _INSTANCE
- if _INSTANCE is None:
- _INSTANCE = RecentSavedFile()
- return _INSTANCE # noqa R504
diff --git a/source/extensions/lightspeed.asset_capture_localizer.core/premake5.lua b/source/extensions/lightspeed.trex.recent_projects.core/premake5.lua
similarity index 100%
rename from source/extensions/lightspeed.asset_capture_localizer.core/premake5.lua
rename to source/extensions/lightspeed.trex.recent_projects.core/premake5.lua
diff --git a/source/extensions/lightspeed.trex.selection_tree.shared.widget/config/extension.toml b/source/extensions/lightspeed.trex.selection_tree.shared.widget/config/extension.toml
index eb65b6629..3f0e9cbb9 100644
--- a/source/extensions/lightspeed.trex.selection_tree.shared.widget/config/extension.toml
+++ b/source/extensions/lightspeed.trex.selection_tree.shared.widget/config/extension.toml
@@ -1,5 +1,5 @@
[package]
-version = "1.5.2"
+version = "1.5.3"
authors =["Damien Bataille "]
title = "NVIDIA RTX Remix Selection Tree implementation for the StageCraft"
description = "Selection Tree implementation for NVIDIA RTX Remix StageCraft App"
diff --git a/source/extensions/lightspeed.trex.selection_tree.shared.widget/docs/CHANGELOG.md b/source/extensions/lightspeed.trex.selection_tree.shared.widget/docs/CHANGELOG.md
index b0963e8f8..50b3a017d 100644
--- a/source/extensions/lightspeed.trex.selection_tree.shared.widget/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.trex.selection_tree.shared.widget/docs/CHANGELOG.md
@@ -1,6 +1,12 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.5.3]
+## Changed
+- Changed `__get_model_from_prototype_path()` to exclude prims that are simultaneously materials
+- The Selection Tree will no longer activate solely with mesh prims that are also materials
+- Moved `__reference_file_paths()` to generic `prim_utils.py` from `model.py`
+
## [1.5.2]
## Changed
- Update to Kit 106.5
diff --git a/source/extensions/lightspeed.trex.selection_tree.shared.widget/lightspeed/trex/selection_tree/shared/widget/selection_tree/model.py b/source/extensions/lightspeed.trex.selection_tree.shared.widget/lightspeed/trex/selection_tree/shared/widget/selection_tree/model.py
index 97f2f7cfa..a811ffb06 100644
--- a/source/extensions/lightspeed.trex.selection_tree.shared.widget/lightspeed/trex/selection_tree/shared/widget/selection_tree/model.py
+++ b/source/extensions/lightspeed.trex.selection_tree.shared.widget/lightspeed/trex/selection_tree/shared/widget/selection_tree/model.py
@@ -21,7 +21,7 @@
import re
import typing
from contextlib import contextmanager
-from typing import Dict, List, Optional, Tuple, Type, TypeAlias, Union
+from typing import Dict, List, Optional, Type, TypeAlias, Union
import carb.events
import omni.kit.commands
@@ -29,10 +29,11 @@
import omni.usd
from lightspeed.common import constants
from lightspeed.trex.asset_replacements.core.shared import Setup as _AssetReplacementsCore
+from lightspeed.trex.utils.common.prim_utils import get_reference_file_paths as _get_reference_file_paths
from omni.flux.utils.common import reset_default_attrs as _reset_default_attrs
from omni.flux.utils.common.decorators import ignore_function_decorator as _ignore_function_decorator
from omni.kit.usd.layers import LayerEventType, get_layer_event_payload, get_layers
-from pxr import Usd, UsdGeom, UsdLux
+from pxr import Usd, UsdGeom, UsdLux, UsdShade
from .listener import USDListener as _USDListener
@@ -373,7 +374,7 @@ def __init__(self, prim: "Usd.Prim", instance_prims: List["Usd.Prim"], context_n
self._live_light_group = ItemLiveLightGroup(self, context_name)
# instance also for light, to have a selected item to show properties
self._instance_group_item = ItemInstancesGroup(instance_prims, self)
- prim_paths, total_ref = self.__reference_file_paths(self._prim)
+ prim_paths, total_ref = _get_reference_file_paths(self._prim)
self._reference_items = [
ItemReferenceFile(_prim, ref, layer, i, total_ref, self, context_name)
for _prim, ref, layer, i in prim_paths
@@ -419,32 +420,6 @@ def instance_group_item(self):
def reference_items(self):
return self._reference_items
- @staticmethod
- def __reference_file_paths(prim) -> Tuple[List[Tuple["Usd.Prim", "Sdf.Reference", "Sdf.Layer", int]], int]:
- prim_paths = []
- ref_and_layers = omni.usd.get_composed_references_from_prim(prim, False)
- i = 0
- for ref, layer in ref_and_layers:
- if not ref.assetPath:
- continue
- prim_paths.append((prim, ref, layer, i))
- i += 1
-
- # it can happen that we added the same reference multiple time. But USD can't do that.
- # As a workaround, we had to create a xform child and add the reference to it.
- # Check the children and find the attribute that define that
- for child in prim.GetChildren():
- is_remix_ref = child.GetAttribute(constants.IS_REMIX_REF_ATTR)
- if is_remix_ref.IsValid():
- ref_and_layers = omni.usd.get_composed_references_from_prim(child, False)
- for ref, layer in ref_and_layers:
- if not ref.assetPath:
- continue
- prim_paths.append((child, ref, layer, i))
- i += 1
-
- return prim_paths, i
-
def __repr__(self):
return f"{self.__class__.__name__}('{self.path}')"
@@ -588,16 +563,23 @@ def __get_reference_prims(prims) -> Dict["Usd.Prim", List["Sdf.Path"]]:
def __get_model_from_prototype_path(self, path):
if not path.startswith(constants.MESH_PATH) and not path.startswith(constants.LIGHT_PATH):
return None
+
+ # ensure prim is valid and not simultaneously a material
prim = self.stage.GetPrimAtPath(path)
if not prim.IsValid():
return None
+ if prim.IsA(UsdShade.Material):
+ return None
+
+ # return input path if is regex mesh or light match
regex_pattern = re.compile(constants.REGEX_MESH_PATH)
if regex_pattern.match(prim.GetName()):
return path
regex_pattern = re.compile(constants.REGEX_LIGHT_PATH)
if regex_pattern.match(prim.GetName()):
return path
- # get parent
+
+ # get and return parent
parent = prim.GetParent()
if not parent or not parent.IsValid():
return None
diff --git a/source/extensions/lightspeed.trex.stage_manager.plugin.interaction.usd/config/extension.toml b/source/extensions/lightspeed.trex.stage_manager.plugin.interaction.usd/config/extension.toml
index 5981d0e8d..18f9c319b 100644
--- a/source/extensions/lightspeed.trex.stage_manager.plugin.interaction.usd/config/extension.toml
+++ b/source/extensions/lightspeed.trex.stage_manager.plugin.interaction.usd/config/extension.toml
@@ -1,6 +1,6 @@
[package]
# Semantic Versionning is used: https://semver.org/
-version = "1.1.1"
+version = "1.2.0"
# Lists people or organizations that are considered the "authors" of the package.
authors = ["Shona Gillard ", "Scott Fitzpatrick "]
title = "NVIDIA RTX Remix Texture Replacements extension for the StageCraft"
description = "Extension that works on texture replacement data for NVIDIA RTX Remix StageCraft App"
diff --git a/source/extensions/lightspeed.trex.texture_replacements.core.shared/docs/CHANGELOG.md b/source/extensions/lightspeed.trex.texture_replacements.core.shared/docs/CHANGELOG.md
index 2e4106ccd..f3d444b07 100644
--- a/source/extensions/lightspeed.trex.texture_replacements.core.shared/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.trex.texture_replacements.core.shared/docs/CHANGELOG.md
@@ -1,6 +1,14 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.2.4]
+## Fixed
+- Fixed Kit 106.5 issue where non-existing attributes aren't created
+
+## [1.2.3]
+## Fixed
+- Fixed validator shader input logic for 106.5
+
## [1.2.2]
## Fixed
- Fixed shader input logic for 106.5
diff --git a/source/extensions/lightspeed.trex.texture_replacements.core.shared/lightspeed/trex/texture_replacements/core/shared/data_models/validators.py b/source/extensions/lightspeed.trex.texture_replacements.core.shared/lightspeed/trex/texture_replacements/core/shared/data_models/validators.py
index aae399497..d32c4ebf9 100644
--- a/source/extensions/lightspeed.trex.texture_replacements.core.shared/lightspeed/trex/texture_replacements/core/shared/data_models/validators.py
+++ b/source/extensions/lightspeed.trex.texture_replacements.core.shared/lightspeed/trex/texture_replacements/core/shared/data_models/validators.py
@@ -22,6 +22,7 @@
import omni.usd
from lightspeed.trex.utils.common.asset_utils import is_asset_ingested
from omni.flux.asset_importer.core.data_models import SUPPORTED_TEXTURE_EXTENSIONS
+from omni.flux.material_api import ShaderInfoAPI
from omni.flux.utils.common.omni_url import OmniUrl
from pxr import Sdf, UsdShade
@@ -38,19 +39,19 @@ def is_valid_texture_prim(cls, texture_tuple: tuple[str, Path], context_name: st
except Exception as e:
raise ValueError(f"The string is not a valid path: {property_path}") from e
- usd_property = omni.usd.get_context(context_name).get_stage().GetPropertyAtPath(path)
- if not usd_property:
- raise ValueError(f"The property path does not exist in the current stage: {property_path}")
+ prim_path = path.GetPrimPath()
+ prim = omni.usd.get_context(context_name).get_stage().GetPrimAtPath(prim_path)
+ if not prim:
+ raise ValueError(f"The prim path does not exist in the current stage: {prim_path}")
- prim = usd_property.GetPrim()
if not prim.IsA(UsdShade.Shader):
raise ValueError(f"The property path does not point to a valid USD shader property: {property_path}")
- shader = UsdShade.Shader(prim)
- if not shader.GetInput(usd_property.GetBaseName()):
- raise ValueError(f"The property path does not point to a valid USD shader input: {property_path}")
+ for input_property in ShaderInfoAPI(prim).get_input_properties():
+ if input_property.GetName() == path.name:
+ return texture_tuple
- return texture_tuple
+ raise ValueError(f"The property path does not point to a valid USD shader input: {property_path}")
@classmethod
def is_valid_texture_asset(cls, texture_tuple: tuple[str, Path], force: bool):
diff --git a/source/extensions/lightspeed.trex.texture_replacements.core.shared/lightspeed/trex/texture_replacements/core/shared/setup.py b/source/extensions/lightspeed.trex.texture_replacements.core.shared/lightspeed/trex/texture_replacements/core/shared/setup.py
index 0f99d859f..cf21896c9 100644
--- a/source/extensions/lightspeed.trex.texture_replacements.core.shared/lightspeed/trex/texture_replacements/core/shared/setup.py
+++ b/source/extensions/lightspeed.trex.texture_replacements.core.shared/lightspeed/trex/texture_replacements/core/shared/setup.py
@@ -196,6 +196,14 @@ def replace_textures(
except ValueError:
continue
+ attr_type = None
+ attr_path = Sdf.Path(texture_attr_path)
+ prim = self._context.get_stage().GetPrimAtPath(attr_path.GetPrimPath())
+ for input_property in _ShaderInfoAPI(prim).get_input_properties():
+ if attr_path.name == input_property.GetName():
+ attr_type = Sdf.ValueTypeNames.Find(input_property.GetTypeName())
+ break
+
if texture_asset_path:
commands.execute(
"ChangeProperty",
@@ -206,6 +214,7 @@ def replace_textures(
)
),
prev=None,
+ type_to_create_if_not_exist=attr_type,
usd_context_name=self._context_name,
target_layer=self._context.get_stage().GetEditTarget().GetLayer(),
)
diff --git a/source/extensions/lightspeed.trex.texture_replacements.core.shared/lightspeed/trex/texture_replacements/core/shared/tests/unit/test_validators.py b/source/extensions/lightspeed.trex.texture_replacements.core.shared/lightspeed/trex/texture_replacements/core/shared/tests/unit/test_validators.py
index b0e242dd5..995af9212 100644
--- a/source/extensions/lightspeed.trex.texture_replacements.core.shared/lightspeed/trex/texture_replacements/core/shared/tests/unit/test_validators.py
+++ b/source/extensions/lightspeed.trex.texture_replacements.core.shared/lightspeed/trex/texture_replacements/core/shared/tests/unit/test_validators.py
@@ -55,10 +55,10 @@ async def test_is_valid_texture_prim_returns_expected_value_or_raises(self):
False,
"The property path does not point to a valid USD shader input",
),
- valid_prim_path: (False, "The property path does not exist in the current stage"),
- invalid_prim_path: (False, "The property path does not exist in the current stage"),
+ valid_prim_path: (False, "The property path does not point to a valid USD shader input"),
+ invalid_prim_path: (False, "The property path does not point to a valid USD shader property"),
"This.Is/Not A Prim": (False, "The string is not a valid path"),
- "/test/non/existent/prim": (False, "The property path does not exist in the current stage"),
+ "/test/non/existent/prim": (False, "The prim path does not exist in the current stage"),
}
for prim_path, expected_value in test_cases.items():
diff --git a/source/extensions/lightspeed.trex.texture_replacements.service/config/extension.toml b/source/extensions/lightspeed.trex.texture_replacements.service/config/extension.toml
index 25bcf5a8f..efc49c145 100644
--- a/source/extensions/lightspeed.trex.texture_replacements.service/config/extension.toml
+++ b/source/extensions/lightspeed.trex.texture_replacements.service/config/extension.toml
@@ -1,5 +1,5 @@
[package]
-version = "1.2.0"
+version = "1.2.1"
authors =["Pierre-Oliver Trottier "]
title = "NVIDIA RTX Remix Texture Replacements Service extension"
description = "Extension that exposes microservices for texture replacement data for NVIDIA RTX Remix"
@@ -17,3 +17,24 @@ preview_image = "data/preview.png"
[[python.module]]
name = "lightspeed.trex.texture_replacements.service"
+
+[[test]]
+dependencies = [
+ "lightspeed.trex.tests.dependencies",
+ "omni.flux.utils.widget",
+ "omni.services.core",
+]
+
+args = [
+ "--/renderer/mdl/searchPaths/templates=${kit}/../omni_core_materials/Base;${kit}/mdl/core/Base;${kit}/mdl/core/Volume;${kit}/mdl/core/mdl"
+]
+
+stdoutFailPatterns.exclude = [
+ "*[omni.kit.registry.nucleus.utils.common] Skipping deletion of:*",
+]
+
+[[test]]
+name = "startup"
+dependencies = [
+ "lightspeed.trex.tests.dependencies",
+]
diff --git a/source/extensions/lightspeed.trex.texture_replacements.service/docs/CHANGELOG.md b/source/extensions/lightspeed.trex.texture_replacements.service/docs/CHANGELOG.md
index 45c655b7d..28d90cc14 100644
--- a/source/extensions/lightspeed.trex.texture_replacements.service/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.trex.texture_replacements.service/docs/CHANGELOG.md
@@ -1,6 +1,10 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.2.1]
+### Added
+- Added tests for all texture replacement service endpoints
+
## [1.2.0]
### Changed
- Use generic factory instead of service-specific factory
diff --git a/source/extensions/lightspeed.color_to_normal.core/lightspeed/color_to_normal/core/__init__.py b/source/extensions/lightspeed.trex.texture_replacements.service/lightspeed/trex/texture_replacements/service/tests/__init__.py
similarity index 91%
rename from source/extensions/lightspeed.color_to_normal.core/lightspeed/color_to_normal/core/__init__.py
rename to source/extensions/lightspeed.trex.texture_replacements.service/lightspeed/trex/texture_replacements/service/tests/__init__.py
index 3a930d1ca..0ca2c8b1f 100644
--- a/source/extensions/lightspeed.color_to_normal.core/lightspeed/color_to_normal/core/__init__.py
+++ b/source/extensions/lightspeed.trex.texture_replacements.service/lightspeed/trex/texture_replacements/service/tests/__init__.py
@@ -15,4 +15,4 @@
* limitations under the License.
"""
-from .color_to_normal_core import * # noqa: F401
+from .e2e.test_service import TestTextureReplacementsService
diff --git a/source/extensions/lightspeed.trex.texture_replacements.service/lightspeed/trex/texture_replacements/service/tests/e2e/test_service.py b/source/extensions/lightspeed.trex.texture_replacements.service/lightspeed/trex/texture_replacements/service/tests/e2e/test_service.py
new file mode 100644
index 000000000..71261dcbe
--- /dev/null
+++ b/source/extensions/lightspeed.trex.texture_replacements.service/lightspeed/trex/texture_replacements/service/tests/e2e/test_service.py
@@ -0,0 +1,248 @@
+"""
+* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+* SPDX-License-Identifier: Apache-2.0
+*
+* 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
+*
+* https://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 pathlib import Path
+from urllib.parse import quote
+
+import omni.usd
+from omni.flux.asset_importer.core.data_models import TEXTURE_TYPE_INPUT_MAP
+from omni.flux.service.factory import get_instance as get_service_factory_instance
+from omni.flux.utils.common.api import send_request
+from omni.flux.utils.widget.resources import get_test_data
+from omni.kit.test import AsyncTestCase
+from omni.kit.test_suite.helpers import open_stage
+from omni.services.core import main
+
+
+class TestTextureReplacementsService(AsyncTestCase):
+ # Before running each test
+ async def setUp(self):
+ self.project_path = get_test_data("usd/project_example/combined.usda")
+
+ self.context = omni.usd.get_context()
+ await open_stage(self.project_path)
+
+ factory = get_service_factory_instance()
+
+ # Register the service in the app
+ self.service = factory.get_plugin_from_name("TextureReplacementsService")()
+ main.register_router(router=self.service.router, prefix=self.service.prefix)
+
+ # After running each test
+ async def tearDown(self):
+ main.deregister_router(router=self.service.router, prefix=self.service.prefix)
+
+ self.service = None
+
+ if self.context.can_close_stage():
+ await self.context.close_stage_async()
+
+ self.context = None
+ self.project_path = None
+
+ async def test_get_textures_returns_expected_response(self):
+ project_dir = Path(get_test_data("usd/project_example"))
+
+ for index, test_data in enumerate(
+ [
+ (
+ "",
+ {
+ "textures": [
+ [
+ "/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:diffuse_texture",
+ str(
+ project_dir
+ / ".deps"
+ / "captures"
+ / "materials"
+ / "textures"
+ / "BC868CE5A075ABB1.dds"
+ ),
+ ],
+ [
+ "/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:metallic_texture",
+ str(project_dir / "sources" / "textures" / "T_MetalPanelWall_HeavyRust_metallic.png"),
+ ],
+ [
+ "/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:normalmap_texture",
+ str(project_dir / "sources" / "textures" / "T_MetalPanelWall_HeavyRust_normal.png"),
+ ],
+ [
+ "/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:reflectionroughness_texture",
+ str(project_dir / "sources" / "textures" / "T_MetalPanelWall_HeavyRust_roughness.png"),
+ ],
+ ]
+ },
+ ),
+ (
+ "texture_types=METALLIC&texture_types=ROUGHNESS",
+ {
+ "textures": [
+ [
+ "/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:metallic_texture",
+ str(project_dir / "sources" / "textures" / "T_MetalPanelWall_HeavyRust_metallic.png"),
+ ],
+ [
+ "/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:reflectionroughness_texture",
+ str(project_dir / "sources" / "textures" / "T_MetalPanelWall_HeavyRust_roughness.png"),
+ ],
+ ]
+ },
+ ),
+ ]
+ ):
+ params, expected_response = test_data
+ with self.subTest(name=f"test_{index}"):
+ # Arrange
+ pass
+
+ # Act
+ response = await send_request("GET", f"{self.service.prefix}/?{params}")
+
+ # Assert
+ self.assertEqual(str(response).lower(), str(expected_response).lower())
+
+ async def test_get_texture_types_returns_expected_response(self):
+ # Arrange
+ pass
+
+ # Act
+ response = await send_request("GET", f"{self.service.prefix}/types")
+
+ # Assert
+ self.assertEqual(
+ response,
+ {
+ "texture_types": [
+ "DIFFUSE",
+ "ROUGHNESS",
+ "ANISOTROPY",
+ "METALLIC",
+ "EMISSIVE",
+ "NORMAL_OGL",
+ "NORMAL_DX",
+ "NORMAL_OTH",
+ "HEIGHT",
+ "TRANSMITTANCE",
+ "MEASUREMENT_DISTANCE",
+ "SINGLE_SCATTERING",
+ "OTHER",
+ ]
+ },
+ )
+
+ async def test_get_texture_material_returns_expected_response(self):
+ # Arrange
+ asset_path = quote("/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:metallic_texture", safe="")
+ expected_material = "/RootNode/Looks/mat_BC868CE5A075ABB1"
+
+ # Act
+ response = await send_request("GET", f"{self.service.prefix}/{asset_path}/material")
+
+ # Assert
+ self.assertEqual(response, {"asset_paths": [expected_material]})
+
+ async def test_get_texture_material_inputs_no_args_returns_all_inputs(self):
+ # Arrange
+ base_path = "/RootNode/Looks/mat_BC868CE5A075ABB1/Shader."
+ asset_path = quote(f"{base_path}inputs:metallic_texture", safe="")
+
+ expected_inputs = sorted({f"{base_path}{i}" for i in TEXTURE_TYPE_INPUT_MAP.values()})
+
+ # Act
+ response = await send_request("GET", f"{self.service.prefix}/{asset_path}/material/inputs")
+
+ # Assert
+ self.assertListEqual(sorted(response.get("asset_paths", [])), expected_inputs)
+
+ async def test_get_texture_material_inputs_texture_type_returns_expected_inputs(self):
+ # Arrange
+ base_path = "/RootNode/Looks/mat_BC868CE5A075ABB1/Shader."
+ asset_path = quote(f"{base_path}inputs:metallic_texture", safe="")
+
+ expected_inputs = [f"{base_path}inputs:reflectionroughness_texture"]
+
+ # Act
+ response = await send_request(
+ "GET", f"{self.service.prefix}/{asset_path}/material/inputs?texture_type=ROUGHNESS"
+ )
+
+ # Assert
+ self.assertEqual(response, {"asset_paths": expected_inputs})
+
+ async def test_override_textures_overrides_expected_inputs(self):
+ # Arrange
+ stage = self.context.get_stage()
+ diffuse_input_path = "/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:diffuse_texture"
+ metallic_input_path = "/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:metallic_texture"
+
+ asset_relative_path = "/ingested_assets/output/good/Bricks092-PNG_Color.a.rtex.dds"
+ asset_path = str(get_test_data(f"usd/project_example{asset_relative_path}"))
+
+ # Act
+ response = await send_request(
+ "PUT",
+ f"{self.service.prefix}/",
+ json={
+ "force": False,
+ "textures": [
+ [diffuse_input_path, asset_path],
+ [metallic_input_path, asset_path],
+ ],
+ },
+ )
+
+ # Assert
+ self.assertEqual(response, "OK")
+
+ diffuse_input = stage.GetAttributeAtPath(diffuse_input_path)
+ metallic_input = stage.GetAttributeAtPath(metallic_input_path)
+
+ self.assertEqual(diffuse_input.Get().path, f".{asset_relative_path}")
+ self.assertEqual(metallic_input.Get().path, f".{asset_relative_path}")
+
+ async def test_override_textures_new_texture_creates_expected_input(self):
+ # Arrange
+ stage = self.context.get_stage()
+ diffuse_input_path = "/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:diffuse_texture"
+ emissive_input_path = "/RootNode/Looks/mat_BC868CE5A075ABB1/Shader.inputs:emissive_mask_texture"
+
+ asset_relative_path = "/ingested_assets/output/good/Bricks092-PNG_Color.a.rtex.dds"
+ asset_path = str(get_test_data(f"usd/project_example{asset_relative_path}"))
+
+ # Act
+ response = await send_request(
+ "PUT",
+ f"{self.service.prefix}/",
+ json={
+ "force": False,
+ "textures": [
+ [diffuse_input_path, asset_path], # Existing
+ [emissive_input_path, asset_path], # New
+ ],
+ },
+ )
+
+ # Assert
+ self.assertEqual(response, "OK")
+
+ diffuse_input = stage.GetAttributeAtPath(diffuse_input_path)
+ emissive_input = stage.GetAttributeAtPath(emissive_input_path)
+
+ self.assertEqual(diffuse_input.Get().path, f".{asset_relative_path}")
+ self.assertEqual(emissive_input.Get().path, f".{asset_relative_path}")
diff --git a/source/extensions/lightspeed.trex.utils.common/config/extension.toml b/source/extensions/lightspeed.trex.utils.common/config/extension.toml
index 0ae1e7432..f260313f9 100644
--- a/source/extensions/lightspeed.trex.utils.common/config/extension.toml
+++ b/source/extensions/lightspeed.trex.utils.common/config/extension.toml
@@ -2,7 +2,7 @@
authors =["Damien Bataille ", "Pierre-Olivier Trottier "]
title = "NVIDIA RTX Remix common utils"
description = "Common utils helper for Lightspeed widgets"
-version = "1.4.0"
+version = "1.5.0"
readme = "docs/README.md"
repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.trex.utils.common"
category = "internal"
diff --git a/source/extensions/lightspeed.trex.utils.common/docs/CHANGELOG.md b/source/extensions/lightspeed.trex.utils.common/docs/CHANGELOG.md
index b768a96c3..6b932fbe9 100644
--- a/source/extensions/lightspeed.trex.utils.common/docs/CHANGELOG.md
+++ b/source/extensions/lightspeed.trex.utils.common/docs/CHANGELOG.md
@@ -1,6 +1,10 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.5.0]
+## Added
+- Added `get_reference_file_paths` to `prim_utils.py`
+
## [1.4.0]
## Changed
- Renamed trex prim utility names for clarity
diff --git a/source/extensions/lightspeed.trex.utils.common/lightspeed/trex/utils/common/prim_utils.py b/source/extensions/lightspeed.trex.utils.common/lightspeed/trex/utils/common/prim_utils.py
index d17aab588..16bb83d81 100644
--- a/source/extensions/lightspeed.trex.utils.common/lightspeed/trex/utils/common/prim_utils.py
+++ b/source/extensions/lightspeed.trex.utils.common/lightspeed/trex/utils/common/prim_utils.py
@@ -30,7 +30,7 @@
import re
from enum import Enum
-from typing import Callable
+from typing import Callable, List, Tuple
import omni.usd
from lightspeed.common import constants
@@ -341,3 +341,40 @@ def traverse_instanced_children(_prim, _current_level, _skip_remix_ref):
yield from traverse_instanced_children(child, _current_level, _skip_remix_ref)
return list(traverse_instanced_children(prim, current_level, skip_remix_ref))
+
+
+def get_reference_file_paths(prim) -> Tuple[List[Tuple["Usd.Prim", "Sdf.Reference", "Sdf.Layer", int]], int]:
+ """
+ Collects file references from a USD prim and its reference children.
+ Handles special child prims for multiple identical references.
+
+ Args:
+ prim (Usd.Prim): The USD prim to get references from.
+
+ Returns:
+ Tuple[List[Tuple[Usd.Prim, Sdf.Reference, Sdf.Layer, int]], int]:
+ List of (prim, reference, layer, index) tuples and total reference count.
+ """
+ prim_paths = []
+ ref_and_layers = omni.usd.get_composed_references_from_prim(prim, False)
+ i = 0
+ for ref, layer in ref_and_layers:
+ if not ref.assetPath:
+ continue
+ prim_paths.append((prim, ref, layer, i))
+ i += 1
+
+ # It can happen that we added the same reference multiple time. But USD can't do that.
+ # As a workaround, we had to create a xform child and add the reference to it.
+ # Check the children and find the attribute that define that
+ for child in prim.GetChildren():
+ is_remix_ref = child.GetAttribute(constants.IS_REMIX_REF_ATTR)
+ if is_remix_ref.IsValid():
+ ref_and_layers = omni.usd.get_composed_references_from_prim(child, False)
+ for ref, layer in ref_and_layers:
+ if not ref.assetPath:
+ continue
+ prim_paths.append((child, ref, layer, i))
+ i += 1
+
+ return prim_paths, i
diff --git a/source/extensions/lightspeed.upscale.content_browser.menu/config/extension.toml b/source/extensions/lightspeed.upscale.content_browser.menu/config/extension.toml
deleted file mode 100644
index fbfbdf4e1..000000000
--- a/source/extensions/lightspeed.upscale.content_browser.menu/config/extension.toml
+++ /dev/null
@@ -1,37 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.3"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Alexander Jaus "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Texture Up-Scaler"
-description="A content browser context menu option for the lightspeed.upscaler.core extension."
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.upscale.content_browser.menu"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["kit", "upscale"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-icon = "data/icon.png"
-preview_image = "data/preview.png"
-
-[dependencies]
-"lightspeed.upscale.core" = {}
-"omni.kit.window.content_browser" = {}
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.upscale.content_browser.menu"
diff --git a/source/extensions/lightspeed.upscale.content_browser.menu/data/icon.png b/source/extensions/lightspeed.upscale.content_browser.menu/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.upscale.content_browser.menu/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.upscale.content_browser.menu/data/preview.png b/source/extensions/lightspeed.upscale.content_browser.menu/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.upscale.content_browser.menu/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.upscale.content_browser.menu/docs/CHANGELOG.md b/source/extensions/lightspeed.upscale.content_browser.menu/docs/CHANGELOG.md
deleted file mode 100644
index ba14f8531..000000000
--- a/source/extensions/lightspeed.upscale.content_browser.menu/docs/CHANGELOG.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.3]
-### Changed
-- Changed repo link
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed.upscale.content_browser.menu/docs/README.md b/source/extensions/lightspeed.upscale.content_browser.menu/docs/README.md
deleted file mode 100644
index b68412d26..000000000
--- a/source/extensions/lightspeed.upscale.content_browser.menu/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.upscale.content_browser.menu
diff --git a/source/extensions/lightspeed.upscale.content_browser.menu/docs/index.rst b/source/extensions/lightspeed.upscale.content_browser.menu/docs/index.rst
deleted file mode 100644
index 61bf2b5f8..000000000
--- a/source/extensions/lightspeed.upscale.content_browser.menu/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.upscale.content_browser.menu
-########################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.upscale.content_browser.menu
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.upscale.content_browser.menu/lightspeed/upscale/content_browser/menu/__init__.py b/source/extensions/lightspeed.upscale.content_browser.menu/lightspeed/upscale/content_browser/menu/__init__.py
deleted file mode 100644
index 749ed1f3e..000000000
--- a/source/extensions/lightspeed.upscale.content_browser.menu/lightspeed/upscale/content_browser/menu/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .upscale import * # noqa: F401
diff --git a/source/extensions/lightspeed.upscale.content_browser.menu/lightspeed/upscale/content_browser/menu/upscale.py b/source/extensions/lightspeed.upscale.content_browser.menu/lightspeed/upscale/content_browser/menu/upscale.py
deleted file mode 100644
index d681604e3..000000000
--- a/source/extensions/lightspeed.upscale.content_browser.menu/lightspeed/upscale/content_browser/menu/upscale.py
+++ /dev/null
@@ -1,52 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-import os
-
-import omni.ext
-import omni.kit.window.content_browser
-from lightspeed.upscale.core import UpscaleModels, UpscalerCore
-
-
-class UpscalerContentBrowserMenuExtension(omni.ext.IExt):
- def on_startup(self, ext_id):
- win = omni.kit.window.content_browser.get_content_window()
- win.add_context_menu(
- "Upscale Texture",
- glyph="none.svg",
- click_fn=self.context_menu_on_click_upscale,
- show_fn=self.context_menu_can_show_menu_upscale,
- index=0,
- )
-
- def on_shutdown(self):
- win = omni.kit.window.content_browser.get_content_window()
- if win is not None:
- win.delete_context_menu("Upscale Texture")
-
- def upscale(self, source_path, dest_path):
- UpscalerCore.perform_upscale(UpscaleModels.ESRGAN.value, source_path, dest_path)
-
- def context_menu_on_click_upscale(self, menu, value):
- upscale_path = value.replace(os.path.splitext(value)[1], "_upscaled4x" + os.path.splitext(value)[1])
- asyncio.ensure_future(UpscalerCore.async_perform_upscale(UpscaleModels.ESRGAN.value, value, upscale_path))
-
- def context_menu_can_show_menu_upscale(self, path):
- if path.lower().endswith(".dds") or path.lower().endswith(".png"):
- return True
- return False
diff --git a/source/extensions/lightspeed.upscale.content_browser.menu/premake5.lua b/source/extensions/lightspeed.upscale.content_browser.menu/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.upscale.content_browser.menu/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.upscale.core/config/extension.toml b/source/extensions/lightspeed.upscale.core/config/extension.toml
deleted file mode 100644
index c77c77f9b..000000000
--- a/source/extensions/lightspeed.upscale.core/config/extension.toml
+++ /dev/null
@@ -1,37 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.3"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Alexander Jaus "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Texture Up-Scaler"
-description="Invokes an AI upscaler on textures passed to it."
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.upscale.core"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["kit", "upscale"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-icon = "data/icon.png"
-preview_image = "data/preview.png"
-
-[dependencies]
-"lightspeed.common" = {}
-"omni.kit.pip_archive" = {} # For PIL
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.upscale.core"
diff --git a/source/extensions/lightspeed.upscale.core/data/icon.png b/source/extensions/lightspeed.upscale.core/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.upscale.core/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.upscale.core/data/lss/capture/materials/AperturePBR_Opacity.mdl b/source/extensions/lightspeed.upscale.core/data/lss/capture/materials/AperturePBR_Opacity.mdl
deleted file mode 100644
index 167d0b8fa..000000000
--- a/source/extensions/lightspeed.upscale.core/data/lss/capture/materials/AperturePBR_Opacity.mdl
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:1a5f96d9f8004c74a9cc0aac8ad6c4c6ea0e5e73c9195bf2e23330874102de2b
-size 17602
diff --git a/source/extensions/lightspeed.upscale.core/data/lss/capture/materials/mat_F5CE656D9F82F196.usd b/source/extensions/lightspeed.upscale.core/data/lss/capture/materials/mat_F5CE656D9F82F196.usd
deleted file mode 100644
index e1199e340..000000000
--- a/source/extensions/lightspeed.upscale.core/data/lss/capture/materials/mat_F5CE656D9F82F196.usd
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:301cc98fe3a9d316ebf527faa0e30072f31a4196b715ba8141007b173a8f642d
-size 1202
diff --git a/source/extensions/lightspeed.upscale.core/data/lss/capture/meshes/mesh_1714784A67BC21F8.usd b/source/extensions/lightspeed.upscale.core/data/lss/capture/meshes/mesh_1714784A67BC21F8.usd
deleted file mode 100644
index b5d5a1db2..000000000
--- a/source/extensions/lightspeed.upscale.core/data/lss/capture/meshes/mesh_1714784A67BC21F8.usd
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:5d1a37788e95070c4f371ba3f15419b66e080e4fcf134a7a94288d86b37aa52f
-size 344000
diff --git a/source/extensions/lightspeed.upscale.core/data/lss/capture/portal-gun-test-stage.usda b/source/extensions/lightspeed.upscale.core/data/lss/capture/portal-gun-test-stage.usda
deleted file mode 100644
index 254dff974..000000000
--- a/source/extensions/lightspeed.upscale.core/data/lss/capture/portal-gun-test-stage.usda
+++ /dev/null
@@ -1,94 +0,0 @@
-#usda 1.0
-(
- customLayerData = {
- dictionary cameraSettings = {
- string boundCamera = "/RootNode/Camera"
- }
- string lightspeed_layer_type = "capture"
- dictionary omni_layer = {
- dictionary muteness = {
- }
- }
- }
- defaultPrim = "RootNode"
- endTimeCode = 0
- metersPerUnit = 1
- startTimeCode = 0
- timeCodesPerSecond = 1
- upAxis = "Z"
-)
-
-def "RootNode"
-{
- def "lights"
- {
- def SphereLight "sphereLight_3C659AB59DED28BB"
- {
- color3f color = (0.6804372, 0.8641359, 1)
- float intensity = 0
- float intensity.timeSamples = {
- 0: 137983.92,
- 5e-324: 0,
- }
- float radius = 1.16
- matrix4d xformOp:transform.timeSamples = {
- 0: ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (312, 280, 241, 1) ),
- }
- uniform token[] xformOpOrder = ["xformOp:transform"]
- }
- }
-
- def "meshes"
- {
- def Xform "mesh_1714784A67BC21F8" (
- instanceable = true
- prepend references = @./meshes/mesh_1714784A67BC21F8.usd@
- )
- {
- rel material:binding =
- token visibility = "invisible"
- }
- }
-
- def "Looks"
- {
- def Material "mat_F5CE656D9F82F196" (
- prepend references = @./materials/mat_F5CE656D9F82F196.usd@
- )
- {
- }
- }
-
- def "instances"
- {
- def Xform "inst_1714784A67BC21F8_0" (
- instanceable = true
- prepend references =
- )
- {
- rel material:binding =
- token visibility = "inherited"
- token visibility.timeSamples = {
- 0: "inherited",
- 5e-324: "invisible",
- }
- matrix4d xformOp:transform.timeSamples = {
- 0: ( (-0.9912359118461609, -0.0854286178946495, -0.10076329857110977, 0), (0.08582086116075516, -0.9963104724884033, 0.00044370806426741183, 0), (-0.10042943805456161, -0.008207772858440876, 0.9949102997779846, 0), (-42.02739715576172, 837.9118041992188, 63.965999603271484, 1) ),
- }
- uniform token[] xformOpOrder = ["xformOp:transform"]
- }
- }
-
- def Camera "Camera"
- {
- float2 clippingRange = (7, 29996.916)
- float focalLength = 10.240908
- float horizontalAperture = 20.955
- float verticalAperture = 11.787188
- matrix4d xformOp:transform.timeSamples = {
- 0: ( (-0.08658816665410995, 0.9962441921234131, 4.6566128730773926e-9, -0), (-0.10073842853307724, -0.008755644783377647, 0.9948744177818298, 0), (0.9911378622055054, 0.0861443504691124, 0.10111820697784424, -0), (-42.16962814331055, 837.2620849609375, 64.03125, 1) ),
- }
- uniform token[] xformOpOrder = ["xformOp:transform"]
- }
-}
-
diff --git a/source/extensions/lightspeed.upscale.core/data/lss/capture/textures/F5CE656D9F82F196.dds b/source/extensions/lightspeed.upscale.core/data/lss/capture/textures/F5CE656D9F82F196.dds
deleted file mode 100644
index 22ad4e7c2..000000000
--- a/source/extensions/lightspeed.upscale.core/data/lss/capture/textures/F5CE656D9F82F196.dds
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:0fa47a071447ab4b9ffafae66769d50bb94d74e61b3eb120ff3336dc33270b54
-size 699008
diff --git a/source/extensions/lightspeed.upscale.core/data/preview.png b/source/extensions/lightspeed.upscale.core/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.upscale.core/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.upscale.core/docs/CHANGELOG.md b/source/extensions/lightspeed.upscale.core/docs/CHANGELOG.md
deleted file mode 100644
index ba14f8531..000000000
--- a/source/extensions/lightspeed.upscale.core/docs/CHANGELOG.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.3]
-### Changed
-- Changed repo link
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed.upscale.core/docs/README.md b/source/extensions/lightspeed.upscale.core/docs/README.md
deleted file mode 100644
index 28b07fffb..000000000
--- a/source/extensions/lightspeed.upscale.core/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.upscale.core
diff --git a/source/extensions/lightspeed.upscale.core/lightspeed/upscale/core/__init__.py b/source/extensions/lightspeed.upscale.core/lightspeed/upscale/core/__init__.py
deleted file mode 100644
index f2afc2ddc..000000000
--- a/source/extensions/lightspeed.upscale.core/lightspeed/upscale/core/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-__all__ = ["UpscalerCore", "UpscaleModels"]
-
-from .items import UpscaleModels
-from .upscale_core import UpscalerCore
diff --git a/source/extensions/lightspeed.upscale.core/lightspeed/upscale/core/items.py b/source/extensions/lightspeed.upscale.core/lightspeed/upscale/core/items.py
deleted file mode 100644
index 78ef2f464..000000000
--- a/source/extensions/lightspeed.upscale.core/lightspeed/upscale/core/items.py
+++ /dev/null
@@ -1,108 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import abc
-import platform
-import shutil
-import subprocess
-import tempfile
-from enum import Enum
-from pathlib import Path
-
-import carb
-from lightspeed.common import constants as _constants
-
-
-class BaseUpscaleModel:
- @property
- @abc.abstractmethod
- def name(self) -> str:
- return "BaseModel"
-
- @abc.abstractmethod
- def perform(self, input_path: Path, output_path: Path):
- pass
-
-
-class EsrganUpscaleModel(BaseUpscaleModel):
- @property
- def name(self) -> str:
- return "ESRGAN"
-
- def perform(self, input_path: Path, output_path: Path):
- esrgan_tool_path = Path(_constants.REAL_ESRGAN_ROOT_PATH) / "realesrgan-ncnn-vulkan.exe"
-
- with subprocess.Popen(
- [str(esrgan_tool_path), "-i", str(input_path), "-o", str(output_path)],
- stdout=subprocess.DEVNULL,
- stderr=subprocess.STDOUT,
- ) as upscale_process:
- upscale_process.wait()
-
-
-class SR3UpscaleModel(BaseUpscaleModel):
- @property
- def name(self) -> str:
- return "SR3+"
-
- def perform(self, input_path: Path, output_path: Path):
- sr3_tool_path = Path(_constants.MAT_SR_ROOT_PATH) / "app" / "app.py"
- sr3_python_path = (
- Path(_constants.MAT_SR_ROOT_PATH)
- / "tools"
- / "packman"
- / ("python.bat" if platform.system() == "Windows" else "python.sh")
- )
-
- sr3_artifacts_base_path = (
- Path(_constants.MAT_SR_ARTIFACTS_ROOT_PATH) / "diffusionSR" / "MATSR3_diffuse_X4" / "250223_160k"
- )
- sr3_config_path = sr3_artifacts_base_path / "config.yaml"
- sr3_model_path = sr3_artifacts_base_path / "model_latest.pth.tar"
-
- with tempfile.TemporaryDirectory() as temp_dir:
- with subprocess.Popen(
- [
- str(sr3_python_path),
- str(sr3_tool_path),
- "--config",
- str(sr3_config_path),
- "--model",
- str(sr3_model_path),
- "run",
- str(input_path),
- "--outdir",
- temp_dir,
- ],
- stdout=subprocess.DEVNULL,
- stderr=subprocess.STDOUT,
- ) as upscale_process:
- upscale_process.wait()
-
- upscaled_texture = Path(temp_dir) / input_path.stem / "diffuse.png"
- upscaled_output_texture = output_path.with_suffix(".png")
-
- if upscaled_texture.exists():
- carb.log_info(f"Moving Upscaled Image from '{upscaled_texture}' to '{upscaled_output_texture}'")
- shutil.move(str(upscaled_texture), str(upscaled_output_texture))
- else:
- carb.log_warn(f"Unable to find upscaled texture: {upscaled_texture}")
-
-
-class UpscaleModels(Enum):
- ESRGAN = EsrganUpscaleModel()
- SR3 = SR3UpscaleModel()
diff --git a/source/extensions/lightspeed.upscale.core/lightspeed/upscale/core/upscale_core.py b/source/extensions/lightspeed.upscale.core/lightspeed/upscale/core/upscale_core.py
deleted file mode 100644
index 8eb949de6..000000000
--- a/source/extensions/lightspeed.upscale.core/lightspeed/upscale/core/upscale_core.py
+++ /dev/null
@@ -1,183 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-import contextlib
-import os
-import subprocess
-import tempfile
-from pathlib import Path
-from typing import TYPE_CHECKING, Callable, Union
-
-import carb
-import omni.usd
-from lightspeed.common import constants
-from PIL import Image
-
-if TYPE_CHECKING:
- from lightspeed.upscale.core.items import BaseUpscaleModel
-
-
-class UpscalerCore:
- @staticmethod
- def __validate_path(input_texture: Path, output_texture: Path, overwrite: bool) -> bool:
- """Make sure the provided paths are valid and cleanup output if overwriting"""
-
- if output_texture.exists() and not overwrite:
- carb.log_info(f"Skipping '{input_texture}' since '{output_texture}' already exists.")
- return False
-
- accepted_extensions = [".dds", ".png"]
- if output_texture.suffix.lower() not in accepted_extensions:
- carb.log_info(
- f"Output texture {output_texture} must be have on of the following file extensions: "
- f"{', '.join(accepted_extensions)}"
- )
- return False
-
- if os.path.exists(output_texture) and overwrite:
- # Cleanup the existing Output
- os.remove(output_texture)
-
- return True
-
- @staticmethod
- def __convert_input_texture_to_png(input_texture: Path, temp_path: Path):
- """Make sure the input texture is a PNG file and convert it if it's not"""
- if input_texture.suffix.lower() == ".png":
- return input_texture
-
- output_path = (temp_path / input_texture.stem).with_suffix(".png")
- with subprocess.Popen(
- [
- carb.tokens.get_tokens_interface().resolve(constants.NVTT_PATH),
- str(input_texture),
- "--output",
- str(output_path),
- ],
- stdout=subprocess.DEVNULL,
- stderr=subprocess.STDOUT,
- ) as convert_png_process:
- convert_png_process.wait()
-
- # use PILLOW as a fallback if NVTT fails
- if not output_path.exists():
- with contextlib.suppress(NotImplementedError):
- with Image.open(input_texture) as img:
- img.save(output_path, "PNG")
-
- return output_path
-
- @staticmethod
- def __convert_output_texture_to_png(output_texture: Path):
- """Make sure the output texture uses a PNG extension and its parent directory exists"""
- output_texture.parent.mkdir(parents=True, exist_ok=True)
- return Path(output_texture).with_suffix(".png")
-
- @staticmethod
- def __upscale_alpha_channel(
- perform_upscale: Callable[[Path, Path], None], input_texture: Path, output_texture: Path, temp_path: Path
- ):
- """Check for alpha channel and upscale it if it exists"""
- try:
- with Image.open(input_texture) as img:
- if img.mode == "RGBA":
- alpha_path = temp_path / (input_texture.stem + "_alpha.png")
- upscaled_alpha_path = temp_path / (input_texture.stem + "_upscaled4x_alpha.png")
-
- img.split()[-1].save(alpha_path)
- perform_upscale(alpha_path, upscaled_alpha_path)
-
- with Image.open(upscaled_alpha_path).convert("L") as upscaled_alpha_img:
- with Image.open(output_texture) as upscaled_output_img:
- upscaled_output_img.putalpha(upscaled_alpha_img)
- upscaled_output_img.save(output_texture, "PNG")
-
- except FileNotFoundError:
- carb.log_info(f"Unable to upscale texture alpha channel: {input_texture}")
-
- @staticmethod
- def __convert_to_dds(converted_output_texture: Path, output_texture: Path):
- """Convert to DDS, and generate mips (Note: don't use the temp dir for this)"""
- if output_texture.suffix.lower() != ".dds":
- return
-
- with subprocess.Popen(
- [
- carb.tokens.get_tokens_interface().resolve(constants.NVTT_PATH),
- str(converted_output_texture),
- "--output",
- str(output_texture),
- *constants.TEXTURE_INFO[constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE].to_nvtt_flag_array(),
- ],
- stdout=subprocess.DEVNULL,
- stderr=subprocess.STDOUT,
- ) as convert_process:
- convert_process.wait()
-
- @staticmethod
- def __cleanup_temporary_pngs(converted_output_texture: Path, output_texture: Path, keep_png: bool):
- """Cleanup the leftover temporary PNGs"""
- if keep_png or output_texture == converted_output_texture or not converted_output_texture.exists():
- return
-
- os.remove(converted_output_texture)
-
- @staticmethod
- def perform_upscale(
- upscale_model: "BaseUpscaleModel",
- input_texture: Union[Path, str],
- output_texture: Union[Path, str],
- keep_png: bool = False,
- overwrite: bool = False,
- ):
- carb.log_info(f"Upscaling using {upscale_model.name}: {input_texture}")
-
- # Make sure paths are of type Pathlib.Path
- input_texture = Path(input_texture)
- output_texture = Path(output_texture)
-
- if not UpscalerCore.__validate_path(input_texture, output_texture, overwrite):
- return
-
- with tempfile.TemporaryDirectory() as temp_dir:
- temp_path = Path(temp_dir)
-
- converted_input_texture = UpscalerCore.__convert_input_texture_to_png(input_texture, temp_path)
- converted_output_texture = UpscalerCore.__convert_output_texture_to_png(output_texture)
-
- upscale_model.perform(converted_input_texture, converted_output_texture)
-
- UpscalerCore.__upscale_alpha_channel(
- upscale_model.perform, converted_input_texture, converted_output_texture, temp_path
- )
- UpscalerCore.__convert_to_dds(converted_output_texture, output_texture)
- UpscalerCore.__cleanup_temporary_pngs(converted_output_texture, output_texture, keep_png)
-
- @staticmethod
- @omni.usd.handle_exception
- async def async_perform_upscale(
- upscale_model: "BaseUpscaleModel",
- input_texture: Union[Path, str],
- output_texture: Union[Path, str],
- keep_png: bool = False,
- overwrite: bool = False,
- ):
- loop = asyncio.get_event_loop()
- await loop.run_in_executor(
- None, UpscalerCore.perform_upscale, upscale_model, input_texture, output_texture, keep_png, overwrite
- )
diff --git a/source/extensions/lightspeed.upscale.core/premake5.lua b/source/extensions/lightspeed.upscale.core/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.upscale.core/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.upscale.menu/config/extension.toml b/source/extensions/lightspeed.upscale.menu/config/extension.toml
deleted file mode 100644
index 7c6de9fb2..000000000
--- a/source/extensions/lightspeed.upscale.menu/config/extension.toml
+++ /dev/null
@@ -1,49 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.4"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Alexander Jaus "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Lightspeed Game Export Texture Up-Scaler"
-description="A menu that can invoke an AI upscaler on the textures in the loaded USD."
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.upscale.menu"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["kit", "upscale", "texture", "exporter","menu"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
-icon = "data/icon.png"
-
-[dependencies]
-"omni.kit.window.content_browser" = {}
-"omni.kit.test" = {}
-"omni.kit.menu.utils" = {}
-"omni.kit.widget.layers" = {}
-"lightspeed.layer_helpers" = {}
-"lightspeed.layer_manager.core" = {}
-"lightspeed.common" = {}
-"lightspeed.error_popup.window" = {}
-"lightspeed.progress_popup.window" = {}
-"lightspeed.upscale.core" = {}
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.upscale.menu"
diff --git a/source/extensions/lightspeed.upscale.menu/data/icon.png b/source/extensions/lightspeed.upscale.menu/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.upscale.menu/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.upscale.menu/data/preview.png b/source/extensions/lightspeed.upscale.menu/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.upscale.menu/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.upscale.menu/docs/CHANGELOG.md b/source/extensions/lightspeed.upscale.menu/docs/CHANGELOG.md
deleted file mode 100644
index d4b9ec697..000000000
--- a/source/extensions/lightspeed.upscale.menu/docs/CHANGELOG.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.4]
-### Changed
-- Changed repo link
-
-## [0.1.3]
-- Use updated `lightspeed.layer_manager.core` extension
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed.upscale.menu/docs/README.md b/source/extensions/lightspeed.upscale.menu/docs/README.md
deleted file mode 100644
index e1613a236..000000000
--- a/source/extensions/lightspeed.upscale.menu/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.upscale.menu
diff --git a/source/extensions/lightspeed.upscale.menu/docs/index.rst b/source/extensions/lightspeed.upscale.menu/docs/index.rst
deleted file mode 100644
index 8a0fb1b2a..000000000
--- a/source/extensions/lightspeed.upscale.menu/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.upscale.menu
-###########################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.upscale.menu
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.upscale.menu/lightspeed/upscale/menu/__init__.py b/source/extensions/lightspeed.upscale.menu/lightspeed/upscale/menu/__init__.py
deleted file mode 100644
index 749ed1f3e..000000000
--- a/source/extensions/lightspeed.upscale.menu/lightspeed/upscale/menu/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .upscale import * # noqa: F401
diff --git a/source/extensions/lightspeed.upscale.menu/lightspeed/upscale/menu/upscale.py b/source/extensions/lightspeed.upscale.menu/lightspeed/upscale/menu/upscale.py
deleted file mode 100644
index f6aa52c10..000000000
--- a/source/extensions/lightspeed.upscale.menu/lightspeed/upscale/menu/upscale.py
+++ /dev/null
@@ -1,100 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-import functools
-
-import omni.kit.menu.utils as omni_utils
-import omni.usd
-from lightspeed.common import constants
-from lightspeed.error_popup.window import ErrorPopup
-from lightspeed.layer_helpers import LightspeedTextureProcessingCore
-from lightspeed.progress_popup.window import ProgressPopup
-from lightspeed.upscale.core import UpscaleModels, UpscalerCore
-from omni.kit.menu.utils import MenuItemDescription
-
-# processing_method = UpscalerCore.perform_upscale -> UpscaleModels.ESRGAN
-# input_texture_type = constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE
-# output_texture_type = constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE
-# output_suffix = "_upscaled4x.png"
-processing_config = (
- functools.partial(UpscalerCore.perform_upscale, UpscaleModels.ESRGAN.value),
- constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE,
- constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE,
- "_upscaled4x.png",
-)
-processing_config_overwrite = (
- functools.partial(UpscalerCore.perform_upscale, UpscaleModels.ESRGAN.value, overwrite=True),
- constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE,
- constants.MATERIAL_INPUTS_DIFFUSE_TEXTURE,
- "_upscaled4x.png",
-)
-
-
-class LightspeedUpscalerMenuExtension(omni.ext.IExt):
- def on_startup(self, ext_id):
- self.__create_save_menu()
- self._progress_bar = None
-
- def __create_save_menu(self):
- sub_menu = [
- MenuItemDescription(
- name="Skip already converted one",
- onclick_fn=self.__clicked,
- glyph="none.svg",
- ),
- MenuItemDescription(
- name="Overwrite all textures (re-convert everything)",
- onclick_fn=self.__clicked_overwrite,
- glyph="none.svg",
- ),
- ]
- self._tools_manager_menus = [
- MenuItemDescription(name="Batch Upscale All Game Capture Textures", glyph="none.svg", sub_menu=sub_menu)
- ]
- omni_utils.add_menu_items(self._tools_manager_menus, "Batch Tools")
-
- def on_shutdown(self):
- omni_utils.remove_menu_items(self._tools_manager_menus, "Batch Tools")
-
- def _batch_upscale_set_progress(self, progress):
- if not self._progress_bar:
- self._progress_bar = ProgressPopup(title="Upscaling")
- self._progress_bar.show()
- self._progress_bar.set_progress(progress)
-
- @omni.usd.handle_exception
- async def _run_batch_upscale(self, config):
- if not self._progress_bar:
- self._progress_bar = ProgressPopup(title="Upscaling")
- self._progress_bar.set_progress(0)
- self._progress_bar.show()
- error = await LightspeedTextureProcessingCore.lss_async_batch_process_entire_capture_layer(
- config, progress_callback=self._batch_upscale_set_progress
- )
- if error:
- self._error_popup = ErrorPopup("An error occurred while upscaling", error, window_size=(350, 150))
- self._error_popup.show()
- if self._progress_bar:
- self._progress_bar.hide()
- self._progress_bar = None
-
- def __clicked(self):
- asyncio.ensure_future(self._run_batch_upscale(processing_config))
-
- def __clicked_overwrite(self):
- asyncio.ensure_future(self._run_batch_upscale(processing_config_overwrite))
diff --git a/source/extensions/lightspeed.upscale.menu/premake5.lua b/source/extensions/lightspeed.upscale.menu/premake5.lua
deleted file mode 100644
index 41fa76cf5..000000000
--- a/source/extensions/lightspeed.upscale.menu/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.widget.content_viewer/config/extension.toml b/source/extensions/lightspeed.widget.content_viewer/config/extension.toml
deleted file mode 100644
index d8dd98878..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/config/extension.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-[package]
-version = "0.1.2"
-authors = ["dbataille@nvidia.com"]
-repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit"
-changelog = "docs/CHANGELOG.md"
-readme = "docs/README.md"
-keywords = ["content", "viewer", "widget"]
-title = "Lightspeed Content viewer"
-description = "Widget Content Viewer that shows content"
-icon = "data/icon.png"
-category = "internal"
-preview_image = "data/preview.png"
-
-[ui]
-name = "Lightspeed Widget Content Viewer"
-
-[dependencies]
-"omni.client" = {}
-"omni.ui" = {}
-"lightspeed.pip_archive" = {} # For Pydantic
-
-[[python.module]]
-name = "lightspeed.widget.content_viewer"
-
diff --git a/source/extensions/lightspeed.widget.content_viewer/data/icon.png b/source/extensions/lightspeed.widget.content_viewer/data/icon.png
deleted file mode 100644
index 4068f06a1..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:67df76f6fc87594c2f309dd98d44826b42dd530000f63b616697e1dcc1728540
-size 1343
diff --git a/source/extensions/lightspeed.widget.content_viewer/data/preview.png b/source/extensions/lightspeed.widget.content_viewer/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.widget.content_viewer/docs/CHANGELOG.md b/source/extensions/lightspeed.widget.content_viewer/docs/CHANGELOG.md
deleted file mode 100644
index 936914e84..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/docs/CHANGELOG.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2021-04-09
-### Added
-- Created
diff --git a/source/extensions/lightspeed.widget.content_viewer/docs/README.md b/source/extensions/lightspeed.widget.content_viewer/docs/README.md
deleted file mode 100644
index 980b43e01..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.widget.content_viewer
diff --git a/source/extensions/lightspeed.widget.content_viewer/docs/index.rst b/source/extensions/lightspeed.widget.content_viewer/docs/index.rst
deleted file mode 100644
index e8a558fdf..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.widget.content_viewer
-#################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.widget.content_viewer
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.widget.content_viewer/docs/jxnblk-LICENSE.md b/source/extensions/lightspeed.widget.content_viewer/docs/jxnblk-LICENSE.md
deleted file mode 100644
index 80d9d8c73..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/docs/jxnblk-LICENSE.md
+++ /dev/null
@@ -1,4 +0,0 @@
-Copyright 2021 jxnblk
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/source/extensions/lightspeed.widget.content_viewer/icons/add.svg b/source/extensions/lightspeed.widget.content_viewer/icons/add.svg
deleted file mode 100644
index 09920159e..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/icons/add.svg
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
diff --git a/source/extensions/lightspeed.widget.content_viewer/icons/cross.svg b/source/extensions/lightspeed.widget.content_viewer/icons/cross.svg
deleted file mode 100644
index e475011db..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/icons/cross.svg
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
diff --git a/source/extensions/lightspeed.widget.content_viewer/icons/refresh.svg b/source/extensions/lightspeed.widget.content_viewer/icons/refresh.svg
deleted file mode 100644
index e9ac8dac7..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/icons/refresh.svg
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
diff --git a/source/extensions/lightspeed.widget.content_viewer/icons/search.svg b/source/extensions/lightspeed.widget.content_viewer/icons/search.svg
deleted file mode 100644
index 8c323c9bc..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/icons/search.svg
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
diff --git a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/__init__.py b/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/__init__.py
deleted file mode 100644
index 2a4b35b86..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
diff --git a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/__init__.py b/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/__init__.py
deleted file mode 100644
index 2a4b35b86..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
diff --git a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/core.py b/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/core.py
deleted file mode 100644
index c51a8fa41..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/core.py
+++ /dev/null
@@ -1,258 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import abc
-from typing import Callable, List, Optional
-
-import carb
-import omni.client
-import six
-from pydantic import BaseModel, root_validator
-
-from .core_detail_popup import AssetDetailCore
-
-
-class ContentData(BaseModel):
- """
- Schema of options
- """
-
- title: str
- path: str
- image_path_fn: Optional[Callable[[], str]] = None # function that return an image path
- # function that return an image path for the detail window
- image_primary_detail_fn: Optional[Callable[[], str]] = None
- checkpoint_version: Optional[int] = None
- original_path: Optional[str] = None # dont set it
-
- @root_validator(allow_reuse=True)
- def inject_checkpoint_version(cls, values): # noqa: N805
- if values["original_path"] is None:
- values["original_path"] = values["path"]
- if values["checkpoint_version"] is not None:
- values["path"] = f"{values['original_path']}?&{values['checkpoint_version']}"
- return values
-
- def is_checkpointed(self) -> bool:
- result, entry = omni.client.stat(self.original_path)
- if result == omni.client.Result.OK and entry.flags & omni.client.ItemFlags.IS_CHECKPOINTED:
- return True
- return False
-
- class Config:
- underscore_attrs_are_private = True
- validate_assignment = True
-
-
-class ContentDataAdd(BaseModel):
- """
- Schema of options
- """
-
- title: Optional[str]
- path: Optional[str]
-
-
-@six.add_metaclass(abc.ABCMeta)
-class ContentViewerCore:
- class _Event(set):
- """
- A list of callable objects. Calling an instance of this will cause a
- call to each item in the list in ascending order by index.
- """
-
- def __call__(self, *args, **kwargs):
- """Called when the instance is “called” as a function"""
- # Call all the saved functions
- for f in self:
- f(*args, **kwargs)
-
- def __repr__(self):
- """
- Called by the repr() built-in function to compute the “official”
- string representation of an object.
- """
- return f"Event({set.__repr__(self)})"
-
- class _EventSubscription:
- """
- Event subscription.
-
- _Event has callback while this object exists.
- """
-
- def __init__(self, event, fn):
- """
- Save the function, the event, and add the function to the event.
- """
- self._fn = fn
- self._event = event
- event.add(self._fn)
-
- def __del__(self):
- """Called by GC."""
- self._event.remove(self._fn)
-
- def __init__(self):
- self._default_attr = {}
- for attr, value in self.default_attr.items():
- setattr(self, attr, value)
-
- self.__ignore_thumbnails = False # noqa PLW0238
- self.__selection_blocked = False
-
- self.__asset_detail_core = AssetDetailCore() # noqa PLW0238
-
- self.__on_content_changed = self._Event()
- self.__on_error_get_data = self._Event()
- self.__on_selection_changed = self._Event()
- self.__on_primary_thumbnail_loaded = self._Event()
-
- @property
- def default_attr(self):
- return {"_content": [], "_selection": [], "_item_was_clicked": False}
-
- @abc.abstractmethod
- def _get_content_data(self) -> Optional[List[ContentData]]:
- """If None is returned, an error message is showed"""
- return []
-
- def _content_changed(self, maps: List[ContentData] = None):
- """Call the event object that has the list of functions"""
- self.__on_content_changed(maps)
-
- def subscribe_content_changed(self, fn):
- """
- Return the object that will automatically unsubscribe when destroyed.
- """
- return self._EventSubscription(self.__on_content_changed, fn)
-
- def _error_get_data(self, message):
- """Call the event object that has the list of functions"""
- self.__on_error_get_data(message)
-
- def subscribe_error_get_data(self, fn):
- """
- Return the object that will automatically unsubscribe when destroyed.
- """
- return self._EventSubscription(self.__on_error_get_data, fn)
-
- def _selection_changed(self):
- """Call the event object that has the list of functions"""
- self.__on_selection_changed(self._selection)
-
- def subscribe_selection_changed(self, fn):
- """
- Return the object that will automatically unsubscribe when destroyed.
- """
- return self._EventSubscription(self.__on_selection_changed, fn)
-
- def primary_thumbnail_loaded(self, path, thumbnail_path):
- """Call the event object that has the list of functions"""
- self.__on_primary_thumbnail_loaded(path, thumbnail_path)
-
- def subscribe_primary_thumbnail_loaded(self, fn):
- """
- Return the object that will automatically unsubscribe when destroyed.
- """
- return self._EventSubscription(self.__on_primary_thumbnail_loaded, fn)
-
- def set_selection(self, content_data: Optional[ContentData], append: bool = False, append_in_between: bool = False):
- """Set the selected content"""
- if content_data is None:
- self._selection = []
- else:
- if append:
- if self._selection and isinstance(self._selection[0], ContentDataAdd):
- # we cant have a multi selection with a ContentDataAdd
- return
- if content_data in self._selection:
- self._selection.remove(content_data)
- else:
- self._selection.append(content_data)
- elif append_in_between:
- if not self._selection:
- self._selection = [content_data]
- else:
- if self._selection and isinstance(self._selection[0], ContentDataAdd):
- # we cant have a multi selection with a ContentDataAdd
- return
- idx_clicked = self._content.index(content_data)
- ix_last_selected = self._content.index(self._selection[-1])
- start_idx = ix_last_selected + 1 if idx_clicked - ix_last_selected > 0 else idx_clicked
- end_idx = idx_clicked + 1 if idx_clicked - ix_last_selected > 0 else ix_last_selected
- for content in self._content[start_idx:end_idx]:
- if content not in self._selection:
- self._selection.append(content)
- else:
- self._selection = [content_data]
- self._selection_changed()
-
- def get_selection(self) -> List[ContentData]:
- """Get the current selection"""
- return self._selection
-
- def set_item_was_clicked(self, value):
- self._item_was_clicked = value
-
- def was_item_clicked(self):
- return self._item_was_clicked
-
- def set_block_selection(self, value):
- self.__selection_blocked = value
-
- def is_selection_blocked(self):
- return self.__selection_blocked
-
- def refresh_content(self):
- """Refresh the list of content"""
- data = self._get_content_data()
- if data is None:
- message = "Error: can't get any data.\nDo you have access to your data (vpn? wrong server?)?"
- carb.log_error(message)
- self._error_get_data(message)
- return
- self._content = data
- self._content_changed(self._content)
-
- def get_current_content(self):
- return self._content
-
- def get_content_size(self):
- self.__ignore_thumbnails = True # noqa PLW0238
- result = len(self._get_content_data())
- self.__ignore_thumbnails = False # noqa PLW0238
- return result # noqa R504
-
- def destroy(self):
- self.__ignore_thumbnails = False # noqa PLW0238
- self.__selection_blocked = False
- for attr, value in self.default_attr.items():
- m_attr = getattr(self, attr)
- if isinstance(m_attr, list):
- m_attrs = m_attr
- else:
- m_attrs = [m_attr]
- for m_attr in m_attrs:
- destroy = getattr(m_attr, "destroy", None)
- if callable(destroy):
- destroy() # noqa PLE1102
- del m_attr # noqa PLW4701
- setattr(self, attr, value)
- instance = super(ContentViewerCore, self) # noqa PLR1725
- if instance:
- del instance
diff --git a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/core_detail_popup.py b/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/core_detail_popup.py
deleted file mode 100644
index 7d7af091d..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/core_detail_popup.py
+++ /dev/null
@@ -1,77 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import os
-import re
-from typing import List
-
-import omni.client
-
-
-class AssetDetailCore:
-
- THUMBNAILS_DIR = "custom_thumbnails"
-
- def _get_autogenerated_thumbnails(self, path, auto=False):
- dir_path = os.path.dirname(path)
- autogenerated_thumbnails_dir = omni.client.normalize_url(dir_path)
- if auto:
- thumbnail = f"{autogenerated_thumbnails_dir}/.thumbs/256x256/{os.path.basename(path)}.auto.png"
- else:
- thumbnail = f"{autogenerated_thumbnails_dir}/.thumbs/256x256/{os.path.basename(path)}.png"
-
- result, _ = omni.client.stat(thumbnail)
- if result == omni.client.Result.OK:
- return thumbnail
- if not auto:
- return self._get_autogenerated_thumbnails(path, auto=True)
-
- return ""
-
- def get_primary_thumbnails(self, path) -> str:
- """Get the primary thumbnail from the current asset"""
- dir_path = os.path.dirname(path)
- custom_thumbnails_dir = omni.client.normalize_url(f"{dir_path}/{self.THUMBNAILS_DIR}")
- entries = self.list_entries_custom_thumbnails_dir(custom_thumbnails_dir)
- for entry in entries:
- match = f"{os.path.basename(path)}.primary_thumb.png"
- if entry.relative_path == match:
- return f"{custom_thumbnails_dir}/{entry.relative_path}"
- return self._get_autogenerated_thumbnails(path)
-
- def get_additional_thumbnail(self, path) -> List[str]:
- """Get additional thumbnails from the current asset"""
- result = []
- dir_path = os.path.dirname(path)
- custom_thumbnails_dir = omni.client.normalize_url(f"{dir_path}/{self.THUMBNAILS_DIR}")
- entries = self.list_entries_custom_thumbnails_dir(custom_thumbnails_dir)
- for entry in entries:
- regex = f"^{os.path.basename(path)}.[^primary_thumb]\S+.png$" # noqa W605
- if re.match(regex, entry.relative_path):
- result.append(f"{custom_thumbnails_dir}/{entry.relative_path}")
-
- return result
-
- @staticmethod
- def list_entries_custom_thumbnails_dir(custom_thumbnails_dir):
- """List entries"""
- result, entry = omni.client.stat(custom_thumbnails_dir)
- if result == omni.client.Result.OK and entry.flags & omni.client.ItemFlags.CAN_HAVE_CHILDREN:
- (result, entries) = omni.client.list(custom_thumbnails_dir)
- if result == omni.client.Result.OK:
- return entries
- return []
diff --git a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/delegate_detail_poup.py b/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/delegate_detail_poup.py
deleted file mode 100644
index b07057651..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/delegate_detail_poup.py
+++ /dev/null
@@ -1,58 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import functools
-
-import omni.ui as ui
-
-from .model_detail_popup import HEADER_DICT
-
-
-class AssetDetailTagsDelegate(ui.AbstractItemDelegate):
- """Delegate of the Mapper Batcher"""
-
- def __init__(self, on_image_hovered_fn):
- super().__init__()
- self.__on_image_hovered_fn = on_image_hovered_fn
-
- def build_branch(self, model, item, column_id, level, expanded):
- """Create a branch widget that opens or closes subtree"""
- pass
-
- def build_widget(self, model, item, column_id, level, expanded):
- """Create a widget per item"""
- if item is None:
- return
- if column_id == 0:
- with ui.VStack():
- ui.Spacer(height=5)
- with ui.HStack():
- ui.Spacer(width=5)
- image = ui.Image(
- item.image_path, width=model.SIZE_ADDITIONAL_THUMBNAIL, height=model.SIZE_ADDITIONAL_THUMBNAIL
- )
- image.set_mouse_hovered_fn(functools.partial(self.__on_image_hovered_fn, image))
- ui.Spacer(width=5)
- ui.Spacer(height=5)
- elif column_id == 1:
- ui.Label(item.tags, style_type_name_override="TreeView.Item", alignment=ui.Alignment.CENTER)
-
- def build_header(self, column_id):
- """Build the header"""
- style_type_name = "TreeView.Header"
- with ui.HStack():
- ui.Label(HEADER_DICT[column_id], style_type_name_override=style_type_name)
diff --git a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/model_detail_popup.py b/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/model_detail_popup.py
deleted file mode 100644
index 25417ff98..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/model_detail_popup.py
+++ /dev/null
@@ -1,94 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import omni.ui as ui
-
-HEADER_DICT = {0: "Image", 1: "Tags"}
-
-
-class EntityItem(ui.AbstractItem):
- """Item of the model"""
-
- def __init__(self, image_path, tags):
- super().__init__()
- self.image_path = image_path
- self.image_path_model = ui.SimpleStringModel(image_path)
- self.tags = tags
- self.tags_model = ui.SimpleStringModel(tags)
-
- def __repr__(self):
- return f'"{self.image_path}"'
-
-
-class AssetDetailTagsModel(ui.AbstractItemModel):
- """List model of textures"""
-
- SIZE_ADDITIONAL_THUMBNAIL = 100
-
- def __init__(self, core):
- super().__init__()
- self._core = core
- self.__filter_str = ""
- self.__all_items = []
- self.__image_paths = []
-
- def set_filter_str(self, filter_str: str):
- """Set the filter that filters names"""
- self.__filter_str = filter_str
- self.refresh_list()
-
- def refresh_image_paths(self, path):
- """Refresh images paths to use"""
- if not path:
- return
- self.__image_paths = self._core.get_additional_thumbnail(path)
- self.refresh_list()
-
- def refresh_list(self):
- """Refresh the list"""
- self.__all_items = []
- for i, image_path in enumerate(self.__image_paths):
- tag = f"tag_{i}" # TODO: add tags
- if self.__filter_str not in tag.lower():
- continue
- self.__all_items.append(EntityItem(image_path, tag))
-
- self._item_changed(None)
-
- def get_item_children(self, item):
- """Returns all the children when the widget asks it."""
- if item is None:
- return self.__all_items
- return []
-
- def get_item_value_model_count(self, item):
- """The number of columns"""
- return len(HEADER_DICT.keys())
-
- def get_item_value_model(self, item, column_id):
- """
- Return value model.
- It's the object that tracks the specific value.
- In our case we use ui.SimpleStringModel.
- """
- if item is None:
- return self.__root
- if column_id == 0:
- return item.image_path_model
- if column_id == 1:
- return item.tags_model
- return None
diff --git a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/ui.py b/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/ui.py
deleted file mode 100644
index 6a417ce5a..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/ui.py
+++ /dev/null
@@ -1,808 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-import functools
-import traceback
-from pathlib import Path
-from typing import List, Optional
-
-import carb
-import carb.input
-import omni.kit
-import omni.ui as ui
-
-from .core import ContentData, ContentDataAdd, ContentViewerCore
-from .ui_detail_popup import AssetDetailWindow
-from .utils import is_path_readable
-
-
-def handle_exception(func):
- """
- Decorator to print exception in async functions
-
- TODO: The alternative way would be better, but we want to use traceback.format_exc for better error message.
- result = await asyncio.gather(*[func(*args)], return_exceptions=True)
- """
-
- @functools.wraps(func)
- async def wrapper(*args, **kwargs):
- try:
- return await func(*args, **kwargs)
- except asyncio.CancelledError:
- # We always cancel the task. It's not a problem.
- pass
- except Exception as e: # noqa PLW0703, PLC0103
- carb.log_error(f"Exception when async '{func}'")
- carb.log_error(f"{e}")
- carb.log_error(f"{traceback.format_exc()}")
-
- return wrapper
-
-
-def async_wrap(func):
- @asyncio.coroutine
- @functools.wraps(func)
- def run(*args, loop=None, executor=None, **kwargs):
- if loop is None:
- loop = asyncio.get_event_loop()
- pfunc = functools.partial(func, *args, **kwargs)
- return loop.run_in_executor(executor, pfunc)
-
- return run
-
-
-class ContentItemAdd:
-
- NO_FONT_SIZE = 14
- TITLE_FONT_SIZE = 14
-
- def __init__(self, content_data: ContentDataAdd, core):
- """Content Item represent the UI of 1 content in the grid"""
- self._default_attr = {}
- for attr, value in self.default_attr.items():
- setattr(self, attr, value)
-
- self._style = {
- "Image::Add": {"color": 0xFFDADADA},
- "Rectangle.Overlay": {"background_color": 0x00FFFFFF},
- "Rectangle.Overlay:hovered": {"background_color": 0x21FFFFFF},
- "Rectangle::Wide": {"background_color": 0x00FFFFFF},
- "Rectangle::Wide:selected": {
- "border_color": 0xFFC5911A,
- "border_width": 1.0,
- "background_color": 0x70C5911A,
- },
- }
- self.content_data = content_data
- self._core = core
-
- self.__overlay_wide_rectangle = None
- self.__overlay_highlight_rectangle = None # noqa PLW0238
-
- self.__create_ui()
-
- @property
- def current_extension_path(self):
- current_path = Path(__file__).parent
- for _ in range(4):
- current_path = current_path.parent
- return current_path
-
- def _get_icon_path(self, name: str):
- """Get an icon path form his name"""
- path = self.current_extension_path.joinpath("icons", f"{name}.svg")
- if path.exists():
- return str(path)
- return None
-
- @property
- def default_attr(self):
- return {"_core": None, "_current_extension_path": None}
-
- def __create_ui(self):
- """Create the UI"""
- with ui.ZStack(style=self._style):
- with ui.HStack():
- ui.Spacer(width=ui.Fraction(1))
- self.__overlay_wide_rectangle = ui.Rectangle(
- name="Wide",
- mouse_pressed_fn=self._on_mouse_clicked,
- mouse_released_fn=self._on_mouse_released,
- mouse_moved_fn=self._on_mouse_moved,
- width=ui.Fraction(80),
- )
- ui.Spacer(width=ui.Fraction(1))
- with ui.HStack():
- ui.Spacer(width=ui.Fraction(1))
- with ui.VStack(width=ui.Fraction(30)):
- ui.Spacer(height=ui.Fraction(1))
- with ui.VStack(height=ui.Fraction(30), spacing=8):
- with ui.ZStack():
- # no image/loading frame for label
- with ui.Frame():
- ui.Label("Image", name="NoImage")
- ui.Image(self._get_icon_path("add"), name="Add")
-
- # highlight rectangle when the mouse is over it
- self.__overlay_highlight_rectangle = ui.Rectangle( # noqa PLW0238
- style_type_name_override="Rectangle.Overlay"
- )
- ui.Spacer(height=ui.Fraction(1))
- ui.Spacer(width=ui.Fraction(1))
-
- def on_resized_grid(self, grid_size):
- pass
-
- def set_selected(self, value):
- """Select the item"""
- self.__overlay_wide_rectangle.selected = value
-
- def is_selected(self):
- return self.__overlay_wide_rectangle.selected
-
- def _on_mouse_clicked(self, x, y, b, m): # noqa PLC0103
- """Called when the item is clicked on"""
- self._core.set_item_was_clicked(True)
- self._core.set_selection(self.content_data)
-
- def _on_mouse_released(self, x, y, b, m): # noqa PLC0103
- """Called when the mouse is released"""
- pass
-
- def _on_mouse_moved(self, x, y, b, m): # noqa PLC0103
- """Called when the mouse is moved"""
- pass
-
- def destroy(self):
- self.__overlay_highlight_rectangle = None # noqa PLW0238
- self.__overlay_wide_rectangle = None
- for attr, value in self.default_attr.items():
- m_attr = getattr(self, attr)
- if isinstance(m_attr, list):
- m_attrs = m_attr
- else:
- m_attrs = [m_attr]
- for m_attr in m_attrs:
- destroy = getattr(m_attr, "destroy", None)
- if callable(destroy):
- destroy()
- del m_attr
- setattr(self, attr, value)
-
-
-class ContentItem:
-
- NO_FONT_SIZE = 14
- TITLE_FONT_SIZE = 14
- MULTI_SELECTION = True
- DRAG = False
- CAN_CHOSE_CHECKPOINT = False
-
- def __init__(self, content_data: ContentData, core, asset_detail_windows):
- """Content Item represent the UI of 1 content in the grid"""
- self._default_attr = {}
- for attr, value in self.default_attr.items():
- setattr(self, attr, value)
- self.content_data = content_data
- self._core = core
- self._asset_detail_windows = asset_detail_windows
- self._is_usd_path_valid = False
- self._style = {}
- self.__background_image = None # noqa PLW0238
- self.__checkpoint_zstack = None
- self.__checkpoint_combobox = None
- self.__overlay_wide_rectangle = None
- self.__overlay_highlight_rectangle = None
- self.__no_image_frame = None
- self.__no_usd_path_frame = None
- self.__title_frame = None
- self.__image_frame = None
- self.__label_message_no_image = None
-
- self.__create_ui()
-
- self._primary_thumbnail_loaded_subscription = self._core.subscribe_primary_thumbnail_loaded(
- self._on_primary_thumbnail_loaded
- )
-
- @property
- def style(self):
- return {
- "Label::Title": {"color": 0xFF9C9C9C, "font_size": self.TITLE_FONT_SIZE},
- "Label::NoImage": {"font_size": self.NO_FONT_SIZE, "margin": 5},
- "Label::NoUSDPath": {"font_size": self.NO_FONT_SIZE, "color": 0xDB0000FF},
- "Rectangle::NoImage": {"background_color": 0x80464646},
- "Rectangle.Overlay": {"background_color": 0x00FFFFFF, "border_width": 1.0, "border_color": 0x20FFFFFF},
- "Rectangle.Overlay:hovered": {"background_color": 0x21FFFFFF},
- "Rectangle.Overlay_NoUSDPath": {"background_color": 0x400000FF},
- "Rectangle.Overlay_NoUSDPath:hovered": {"background_color": 0x600000FF},
- "Rectangle::Wide": {"background_color": 0x00FFFFFF},
- "Rectangle::Wide:selected": {
- "border_color": 0xFFC5911A,
- "border_width": 1.0,
- "background_color": 0x70C5911A,
- },
- "Rectangle::Wide_NoUSDPath:selected": {
- "border_color": 0xDB0000FF,
- "border_width": 1.0,
- "background_color": 0x400000FF,
- },
- }
-
- @property
- def default_attr(self):
- return {"_asset_detail_windows": None, "_core": None}
-
- @property
- def is_usd_path_valid(self):
- """Check is the USD path exist"""
- return is_path_readable(self.content_data.path)
-
- @handle_exception
- async def __deferred_primary_image(self, callback):
- wrapped_fn = async_wrap(callback)
- result = await wrapped_fn()
- self._core.primary_thumbnail_loaded(self.content_data.path, result)
-
- @handle_exception
- async def __deferred_update_ui(self):
- def do_update_ui():
- result = self.is_usd_path_valid
- if not result:
- self.__no_usd_path_frame.clear()
- with self.__no_usd_path_frame:
- ui.Label("Path not found on disk", alignment=ui.Alignment.CENTER, word_wrap=True, name="NoUSDPath")
- self.__no_usd_path_frame.visible = not result
- style_type_name_override = "Rectangle.Overlay_NoUSDPath" if not result else "Rectangle.Overlay"
- self.__overlay_highlight_rectangle.style_type_name_override = style_type_name_override
- with self.__no_image_frame:
- alignment = ui.Alignment.CENTER_BOTTOM if self.__no_usd_path_frame.visible else ui.Alignment.CENTER
- ui.Label(self.__label_message_no_image, alignment=alignment, name="NoImage")
-
- wrapped_fn = async_wrap(do_update_ui)
- await wrapped_fn()
-
- def _on_primary_thumbnail_loaded(self, path, thumbnail_path):
- if path != self.content_data.path:
- return
- if thumbnail_path:
- self.__no_image_frame.clear()
- self.__no_image_frame.visible = False
- self.__image_frame.visible = True
- with self.__image_frame:
- self.__background_image = ui.Image( # noqa PLW0238
- thumbnail_path, fill_policy=ui.FillPolicy.PRESERVE_ASPECT_FIT, visible=True, name="Background"
- )
- else:
- self.__label_message_no_image = "No image"
- self.__no_image_frame.visible = True
- self.__no_image_frame.clear()
- with self.__no_image_frame:
- alignment = ui.Alignment.CENTER_BOTTOM if self.__no_usd_path_frame.visible else ui.Alignment.CENTER
- ui.Label(self.__label_message_no_image, alignment=alignment, name="NoImage")
-
- def on_resized_grid(self, grid_size):
- """Called when the grid is resized"""
- old_max = 200
- old_min = 0
- new_max = 140
- new_min = 60
- old_range = old_max - old_min
- new_range = new_max - new_min
- new_value = (((grid_size - old_min) * new_range) / old_range) + new_min
- self.style.update(
- {
- "Label::NoImage": {"font_size": (grid_size / 100) * self.NO_FONT_SIZE},
- "Label::NoUSDPath": {"font_size": (grid_size / 100) * self.NO_FONT_SIZE, "color": 0xDB0000FF},
- "Label::Title": {"color": 0xFF9C9C9C, "font_size": (new_value / 100) * self.TITLE_FONT_SIZE},
- }
- )
- self.__create_labels()
-
- def __create_labels(self):
- """Create all 'no' labels (no image, no usd...)"""
- if self.__no_image_frame is not None:
- self.__no_image_frame.clear()
- self.__no_image_frame.style = self.style
- with self.__no_image_frame:
- alignment = ui.Alignment.CENTER_BOTTOM if self.__no_usd_path_frame.visible else ui.Alignment.CENTER
- ui.Label(self.__label_message_no_image, alignment=alignment, name="NoImage")
- if self.__no_usd_path_frame is not None:
- self.__no_usd_path_frame.clear()
- self.__no_usd_path_frame.style = self.style
- with self.__no_usd_path_frame:
- ui.Label("Path not found on disk", alignment=ui.Alignment.CENTER, word_wrap=True, name="NoUSDPath")
- if self.__title_frame is not None:
- self.__title_frame.clear()
- self.__title_frame.style = self.style
- with self.__title_frame:
- ui.Label(self.content_data.title, alignment=ui.Alignment.CENTER, name="Title", height=0, word_wrap=True)
-
- def __create_ui(self):
- """Create the UI"""
- with ui.ZStack(style=self.style):
- with ui.HStack():
- ui.Spacer(width=ui.Fraction(1))
- with ui.VStack(width=ui.Fraction(30)):
- ui.Spacer(height=ui.Fraction(1))
- with ui.VStack(height=ui.Fraction(30), spacing=8):
- with ui.ZStack():
- # image frame
- self.__image_frame = ui.Frame(visible=False)
-
- # no image/loading frame for label
- self.__no_image_frame = ui.Frame()
- self.__label_message_no_image = "Loading..."
-
- # no usd path frame for label
- self.__no_usd_path_frame = ui.Frame(visible=False)
-
- # highlight rectangle when the mouse is over it
- self.__overlay_highlight_rectangle = ui.Rectangle(
- style_type_name_override="Rectangle.Overlay"
- )
- if self.content_data.is_checkpointed():
- result, entries = omni.client.list_checkpoints(self.content_data.path)
- if result == omni.client.Result.OK:
- with ui.VStack():
- ui.Spacer()
- with ui.HStack(height=0):
- ui.Spacer()
- self.__checkpoint_zstack = ui.ZStack(width=60, tooltip=entries[-1].comment)
- with self.__checkpoint_zstack:
- if self.CAN_CHOSE_CHECKPOINT:
- ui.Rectangle(
- name="CheckPoint",
- style={
- "background_color": 0x00FFFFFF,
- "border_width": 3.0,
- "border_color": 0x20FFFFFF,
- },
- )
- self.__checkpoint_combobox = ui.ComboBox(
- 0,
- *reversed([f"v{entry.relative_path[1:]}" for entry in entries]),
- mouse_pressed_fn=self._on_checkpoint_combobox_mouse_clicked,
- mouse_released_fn=self._on_checkpoint_combobox_mouse_released,
- )
- self.__checkpoint_combobox.model.add_item_changed_fn(
- self._on_checkpoint_changed
- )
- else:
- ui.Rectangle(
- name="CheckPoint",
- style={
- "background_color": 0x00FFFFFF,
- "border_width": 1.0,
- "border_color": 0x20FFFFFF,
- },
- )
- ui.Label(
- [f"v{entry.relative_path[1:]}" for entry in entries][-1],
- alignment=ui.Alignment.CENTER,
- )
- self.__title_frame = ui.Frame(height=0)
- ui.Spacer(height=ui.Fraction(1))
- ui.Spacer(width=ui.Fraction(1))
- with ui.HStack():
- ui.Spacer(width=ui.Fraction(1))
- self.__overlay_wide_rectangle = ui.Rectangle(
- name="Wide",
- mouse_pressed_fn=self._on_mouse_clicked,
- mouse_released_fn=self._on_mouse_released,
- mouse_moved_fn=self._on_mouse_moved,
- width=ui.Fraction(80),
- )
- if self.DRAG:
- self.__overlay_wide_rectangle.set_drag_fn(self._on_drag)
- ui.Spacer(width=ui.Fraction(1))
- self.__create_labels()
- # get the primary image async for speed
- image_fn = self.content_data.image_path_fn
- if image_fn is not None:
- asyncio.ensure_future(self.__deferred_primary_image(image_fn))
- else:
- self._on_primary_thumbnail_loaded(self.content_data.path, None)
- # update the ui in async functions for speed (ui that need to check usd path for example, etc etc)
- asyncio.ensure_future(self.__deferred_update_ui())
-
- def _on_drag(self):
- return self.content_data.path
-
- def destroy(self):
- self.__background_image = None # noqa PLW0238
- self.__checkpoint_zstack = None # noqa PLW0238
- self.__checkpoint_combobox = None # noqa PLW0238
- self.__overlay_wide_rectangle = None # noqa PLW0238
- self.__overlay_highlight_rectangle = None # noqa PLW0238
- self.__no_image_frame = None # noqa PLW0238
- self.__no_usd_path_frame = None # noqa PLW0238
- self.__title_frame = None # noqa PLW0238
- self.__image_frame = None # noqa PLW0238
- self.__label_message_no_image = None # noqa PLW0238
- for attr, value in self.default_attr.items():
- m_attr = getattr(self, attr)
- if isinstance(m_attr, list):
- m_attrs = m_attr
- else:
- m_attrs = [m_attr]
- for m_attr in m_attrs:
- destroy = getattr(m_attr, "destroy", None)
- if callable(destroy):
- destroy()
- del m_attr
- setattr(self, attr, value)
-
- def set_selected(self, value):
- """Select the item"""
- self.__overlay_wide_rectangle.selected = value
-
- def is_selected(self):
- return self.__overlay_wide_rectangle.selected
-
- def _on_checkpoint_changed(self, model, item):
- entry = self.get_current_checkpoint()
- if entry is not None:
- self.content_data.checkpoint_version = entry.relative_path[1:]
- self.__checkpoint_zstack.set_tooltip(entry.comment)
-
- def get_current_checkpoint(self) -> Optional[omni.client.ListEntry]:
- if self.CAN_CHOSE_CHECKPOINT and self.content_data.is_checkpointed():
- result, entries = omni.client.list_checkpoints(self.content_data.path)
- if result == omni.client.Result.OK:
- return entries[::-1][self.__checkpoint_combobox.model.get_item_value_model().as_int]
- return None
-
- def _on_checkpoint_combobox_mouse_clicked(self, x, y, b, m): # noqa PLC0103
- self._core.set_block_selection(True)
-
- def _on_checkpoint_combobox_mouse_released(self, x, y, b, m): # noqa PLC0103
- self._core.set_block_selection(False)
-
- def _on_mouse_clicked(self, x, y, b, m): # noqa PLC0103
- """Called when the item is clicked on"""
- if self._core.is_selection_blocked():
- return
- if b == 1:
- if self._asset_detail_windows is not None:
- self._asset_detail_windows.show(self.content_data)
- elif b == 0 and self._asset_detail_windows is not None:
- self._asset_detail_windows.hide()
- self._core.set_item_was_clicked(True)
- key_mod = m & ~ui.Widget.FLAG_WANT_CAPTURE_KEYBOARD
- if key_mod == int(carb.input.KEYBOARD_MODIFIER_FLAG_SHIFT) and self.MULTI_SELECTION:
- self._core.set_selection(self.content_data, append_in_between=True)
- elif key_mod == int(carb.input.KEYBOARD_MODIFIER_FLAG_CONTROL) and self.MULTI_SELECTION:
- self._core.set_selection(self.content_data, append=True)
- else:
- self._core.set_selection(self.content_data)
-
- def _on_mouse_released(self, x, y, b, m): # noqa PLC0103
- """Called when the mouse is released"""
- pass
-
- def _on_mouse_moved(self, x, y, b, m): # noqa PLC0103
- """Called when the mouse is moved"""
- pass
-
-
-class ContentViewer:
-
- WIDTH_BACKGROUND_SLIDER = 100
- HEIGHT_BACKGROUND_SLIDER = 60
- GRID_COLUMN_WIDTH = 110
- GRID_ROW_HEIGHT = 120
- SHOW_ASSET_DETAIL_WINDOW = True
- CONTENT_ITEM_TYPE = ContentItem
- ENABLE_ADD_ITEM = False
-
- def __init__(self, core: ContentViewerCore, extension_path: str):
- """Window to list all content"""
- self._extension_path = extension_path
- self._current_extension_path = None
- self._calling_extension_path = None
- self._style = None
- self._default_attr = {}
- for attr, value in self.default_attr.items():
- setattr(self, attr, value)
- self._core = core
- if self.SHOW_ASSET_DETAIL_WINDOW:
- self._asset_detail_windows = AssetDetailWindow()
-
- self._model_subscription = self._core.subscribe_content_changed(self._on_content_changed)
- self._selection_subscription = self._core.subscribe_selection_changed(self._on_selection_changed)
- self._error_get_data_subscription = self._core.subscribe_error_get_data(self._on_error_get_data)
-
- self.__frame = None
- self.__label_error = None
- self.__action_search_attr = None
- self.__label_search = None
- self.__cross_image = None
- self.__scroll_frame = None
- self.__top_frame = None
- self.__left_frame = None
- self.__right_frame = None
- self.__bottom_frame = None
- self.__content_grid = None
- self.__on_scroll_frame_mouse_clicked_task = None
- self.__content_items = None
- self.__content_data = None
- self.__slider = None
- self.__filter_content_title_value = None
-
- def get_content_items(self):
- return self.__content_items
-
- def get_left_frame(self):
- return self.__left_frame
-
- def get_top_frame(self):
- return self.__top_frame
-
- def get_right_frame(self):
- return self.__right_frame
-
- def get_bottom_frame(self):
- return self.__bottom_frame
-
- @property
- def current_extension_path(self):
- current_path = Path(__file__).parent
- for _ in range(4):
- current_path = current_path.parent
- return current_path
-
- @property
- def calling_extension_path(self):
- return self.current_extension_path
-
- @property
- def default_attr(self):
- return {"_core": None, "_asset_detail_windows": None}
-
- @property
- def style(self):
- return {
- "Label::Error": {"font_size": 20, "color": 0xFF2C2CDB},
- "Label::Open": {"font_size": 20},
- "Label::Refresh": {"font_size": 14},
- "Label::Search": {"color": 0x908A8777},
- "Image::Cross": {"color": 0xFF8A8777, "margin": 3},
- "Image::Search": {"color": 0xFF8A8777},
- "Image::Refresh": {"color": 0xFF8A8777, "margin": 3},
- "Rectangle::Background": {"background_color": 0xFF23211F},
- "Rectangle::BackgroundSearch": {"border_width": 1, "border_color": 0x20FFFFFF, "background_color": 0x0},
- "Rectangle::Open": {"background_color": 0xFF292929},
- "Rectangle::Open:hovered": {"background_color": 0xFF9E9E9E},
- "Rectangle::Search": {"background_color": 0xFF23211F},
- "Rectangle::Slider": {"background_color": 0x50676767},
- }
-
- def _get_icon_path(self, name: str, from_base_extension=True):
- """Get an icon path form his name"""
- if from_base_extension:
- path = self.current_extension_path.joinpath("icons", f"{name}.svg")
- else:
- path = self.calling_extension_path.joinpath("icons", f"{name}.svg")
- if path.exists():
- return path
- return None
-
- def _on_selection_changed(self, contents_data: List[ContentData]):
- """Called when the selection of an item content is changed"""
- if self.__content_items is None:
- return
- for content_item in self.__content_items:
- content_item.set_selected(content_item.content_data in contents_data)
-
- def _on_error_get_data(self, message):
- """Called when there was an error getting data"""
- if message is not None:
- self.__label_error.text = message
- self.__label_error.visible = True
-
- def _on_content_changed(self, content_data: List[ContentData]):
- """Called when the content is changed"""
- self.__label_error.visible = False
- self.__frame.clear()
- self.__content_items = []
- self.__content_data = content_data
- with self.__frame:
- self.__content_grid = ui.VGrid(
- column_width=self.GRID_COLUMN_WIDTH, row_height=self.GRID_ROW_HEIGHT, spacing=50
- )
- with self.__content_grid:
- if self.ENABLE_ADD_ITEM:
- self.__content_items.insert(0, ContentItemAdd(ContentDataAdd(), self._core))
- for data in content_data:
- if (
- self.__filter_content_title_value is not None
- and self.__filter_content_title_value.lower() not in data.title.lower()
- ):
- continue
- self.__content_items.append(self.CONTENT_ITEM_TYPE(data, self._core, self._asset_detail_windows))
- self._resize_grid()
-
- def _create_ui(self):
- """Create the main UI"""
- with ui.Frame():
- with ui.VStack(style=self.style, spacing=8):
- with ui.ZStack(height=22):
- self.__top_frame = ui.Frame(width=0)
- with ui.VStack():
- ui.Spacer()
- with ui.HStack(height=22):
- ui.Spacer()
- with ui.ZStack(width=ui.Percent(25)):
- with ui.HStack():
- with ui.ZStack(width=20):
- ui.Rectangle(name="Search")
- ui.Image(str(self._get_icon_path("search")), name="Search")
- with ui.ZStack():
- self.__action_search_attr = ui.StringField()
- self.__action_search_attr.model.add_value_changed_fn(
- lambda m: self._filter_content()
- )
- with ui.HStack():
- ui.Spacer(width=8)
- self.__label_search = ui.Label("Search", name="Search")
- with ui.ZStack(width=20):
- ui.Rectangle(name="Search")
- self.__cross_image = ui.Image(
- str(self._get_icon_path("cross")),
- name="Cross",
- mouse_pressed_fn=lambda x, y, b, m: self._on_search_cross_clicked(),
- visible=False,
- )
- ui.Rectangle(name="BackgroundSearch")
- ui.Spacer()
- ui.Spacer()
- with ui.HStack(spacing=8):
- self.__left_frame = ui.Frame(width=0)
- with ui.VStack():
- with ui.ZStack(content_clipping=True):
- self.__scroll_frame = ui.ScrollingFrame(
- horizontal_scrollbar_policy=ui.ScrollBarPolicy.SCROLLBAR_ALWAYS_OFF,
- mouse_pressed_fn=lambda x, y, b, m: self._on_scroll_frame_mouse_clicked(),
- )
- with self.__scroll_frame:
- with ui.ZStack():
- ui.Rectangle(name="Background")
- self.__frame = ui.Frame()
- # slider for change the size of the grid
- with ui.Frame(separate_window=True):
- with ui.HStack():
- ui.Spacer(width=ui.Fraction(40))
- with ui.VStack(width=ui.Pixel(self.WIDTH_BACKGROUND_SLIDER)):
- ui.Spacer(height=ui.Fraction(40))
- with ui.ZStack(height=ui.Pixel(self.HEIGHT_BACKGROUND_SLIDER)):
- ui.Rectangle(name="Slider")
- with ui.VStack():
- ui.Spacer(height=ui.Fraction(1))
- with ui.HStack(height=ui.Fraction(10), content_clipping=True):
- ui.Spacer(width=7)
- ui.Label("Refresh", name="Refresh")
- ui.Image(
- str(self._get_icon_path("refresh")),
- name="Refresh",
- mouse_pressed_fn=lambda x, y, b, m: self._on_refresh_clicked(),
- )
- with ui.HStack(height=ui.Fraction(10), content_clipping=True):
- ui.Spacer(width=ui.Fraction(1))
- self.__slider = ui.IntSlider(
- min=0,
- max=200,
- alignment=ui.Alignment.CENTER,
- width=ui.Pixel(self.WIDTH_BACKGROUND_SLIDER - 10),
- )
- self.__slider.model.set_value(100)
- self.__slider.model.add_value_changed_fn(
- lambda m: self._resize_grid()
- )
- ui.Spacer(width=ui.Fraction(1))
- ui.Spacer(height=ui.Fraction(1))
- ui.Spacer(height=ui.Fraction(2))
- ui.Spacer(width=ui.Fraction(1))
- with ui.Frame(separate_window=True):
- self.__label_error = ui.Label(
- "Error", name="Error", alignment=ui.Alignment.CENTER, visible=False
- )
- self.__bottom_frame = ui.Frame(height=0)
- self.__right_frame = ui.Frame(width=0)
-
- def _filter_content(self):
- """Filter content by name"""
- self.__filter_content_title_value = self.__action_search_attr.model.as_string
- self.__label_search.visible = not bool(self.__filter_content_title_value)
- self.__cross_image.visible = bool(self.__filter_content_title_value)
- self._on_content_changed(self.__content_data)
-
- def _on_search_cross_clicked(self):
- """Called when the cross from the search box is clicked"""
- self.__action_search_attr.model.set_value("")
- self._filter_content()
-
- def _on_refresh_clicked(self):
- """Called when the ui is refreshed"""
- self._core.refresh_content()
-
- def _on_scroll_frame_mouse_clicked(self):
- """Called when we click in the UI but not on a content"""
- if self.__on_scroll_frame_mouse_clicked_task:
- self.__on_scroll_frame_mouse_clicked_task.cancel()
- self.__on_scroll_frame_mouse_clicked_task = asyncio.ensure_future(
- self.__deferred_on_scroll_frame_mouse_clicked()
- )
-
- @handle_exception
- async def __deferred_on_scroll_frame_mouse_clicked(self):
- await omni.kit.app.get_app().next_update_async()
- if self._core.is_selection_blocked():
- return
- if not self._core.was_item_clicked():
- self._core.set_selection(None)
- if self._asset_detail_windows is not None:
- self._asset_detail_windows.hide()
- self._core.set_item_was_clicked(False)
-
- def _resize_grid(self):
- """Called when the grid is resized"""
- if not self.__content_data and not self.ENABLE_ADD_ITEM:
- return
- value = self.__slider.model.as_int
- smoother = 2
- final_value = 100 - ((100 - value) / smoother)
- self.__content_grid.column_width = self.GRID_COLUMN_WIDTH * (final_value / 100)
- self.__content_grid.row_height = self.GRID_ROW_HEIGHT * (final_value / 100)
- for content_item in self.__content_items:
- content_item.on_resized_grid(value)
-
- def destroy(self):
- for attr, value in self.default_attr.items():
- m_attr = getattr(self, attr)
- if isinstance(m_attr, list):
- m_attrs = m_attr
- else:
- m_attrs = [m_attr]
- for m_attr in m_attrs:
- destroy = getattr(m_attr, "destroy", None)
- if callable(destroy):
- destroy()
- del m_attr
- setattr(self, attr, value)
- if self.__content_items:
- for content_item in self.__content_items:
- content_item.destroy()
- self.__frame = None
- self.__label_error = None
- self.__action_search_attr = None
- self.__label_search = None
- self.__cross_image = None
- self.__slider = None
- self.__scroll_frame = None
- self.__top_frame = None
- self.__left_frame = None
- self.__bottom_frame = None
- self.__on_scroll_frame_mouse_clicked_task = None
- self.__content_grid = None
- self.__content_items = None
- self.__content_data = None
- self.__filter_content_title_value = None
- instance = super()
- if instance:
- del instance
diff --git a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/ui_detail_popup.py b/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/ui_detail_popup.py
deleted file mode 100644
index 0117e7cd5..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/lightspeed/widget/content_viewer/scripts/ui_detail_popup.py
+++ /dev/null
@@ -1,309 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-import functools
-import typing
-from pathlib import Path
-
-import carb
-import carb.input
-import omni.appwindow
-import omni.ui as ui
-
-from .core_detail_popup import AssetDetailCore
-from .delegate_detail_poup import AssetDetailTagsDelegate
-from .model_detail_popup import AssetDetailTagsModel
-
-if typing.TYPE_CHECKING:
- from .core import ContentData
-
-
-class AssetDetailWindow:
-
- WINDOW_NAME = "Asset details"
- WINDOW_IMAGE_BIGGER_NAME = "Image bigger"
-
- def __init__(self):
- self.__default_attr = {"_core": None, "_window": None, "_dockspace_window": None, "_window_bigger_image": None}
- for attr, value in self.__default_attr.items():
- setattr(self, attr, value)
-
- self.__style = {
- "Label::Search": {"color": 0x908A8777},
- "Image::Cross": {"color": 0xFF8A8777, "margin": 3},
- "Image::Search": {"color": 0xFF8A8777},
- "Rectangle::MainFrame": {"border_color": 0xFF23211F, "border_width": 4, "background_color": 0xFF343432},
- "Rectangle::Background": {"background_color": 0xFF23211F},
- "Rectangle::Search": {"background_color": 0xFF23211F},
- "TreeView": {
- "background_color": 0xFF23211F,
- "background_selected_color": 0x664F4D43,
- "secondary_color": 0xFF403B3B,
- },
- "TreeView.ScrollingFrame": {"background_color": 0xFF23211F},
- "TreeView.Header": {"background_color": 0xFF343432, "color": 0xFFCCCCCC, "font_size": 13},
- "TreeView.Item": {"color": 0xFF8A8777},
- "TreeView.Item:selected": {"color": 0xFF23211F},
- "TreeView:selected": {"background_color": 0xFF8A8777},
- }
-
- self._core = AssetDetailCore()
-
- self.__bigger_image = None
- self.__primary_thumnail = None
- self.__tree_view = None # noqa PLW0238
- self.__string_field_custom_tags = None
- self.__string_field_name = None
- self.__string_field_file_path = None
- self.__action_search_attr = None
- self.__cross_image = None
- self.__label_search = None
- self.__show_window_task = None
-
- self.__cancel_mouse_hovered = False
-
- self._appwindow = omni.appwindow.get_default_app_window()
- self._mouse = self._appwindow.get_mouse()
- self._input = carb.input.acquire_input_interface()
- self._dpi_scale = ui.Workspace.get_dpi_scale()
-
- self.__model = AssetDetailTagsModel(self._core)
- self.__delegate = AssetDetailTagsDelegate(self._on_image_hovered)
-
- self.__create_ui()
- self.__create_bigger_image_ui()
-
- @property
- def current_extension_path(self):
- current_path = Path(__file__).parent
- for _ in range(4):
- current_path = current_path.parent
- return current_path
-
- @property
- def calling_extension_path(self):
- return self.current_extension_path
-
- def _get_icon_path(self, name: str, from_base_extension=True):
- """Get an icon path form his name"""
- if from_base_extension:
- path = self.current_extension_path.joinpath("icons", f"{name}.svg")
- else:
- path = self.calling_extension_path.joinpath("icons", f"{name}.svg")
- if path.exists():
- return path
- return None
-
- def __create_ui(self):
- self._window = ui.Window(
- self.WINDOW_NAME,
- width=404,
- height=600,
- visible=False,
- # flags=ui.WINDOW_FLAGS_POPUP | ui.WINDOW_FLAGS_NO_TITLE_BAR, # can't use popup under a popup (bigger img)
- flags=ui.WINDOW_FLAGS_NO_TITLE_BAR,
- )
- with self._window.frame:
- with ui.VStack(spacing=8, style=self.__style):
- with ui.ZStack(height=ui.Percent(30)):
- ui.Rectangle(name="MainFrame")
- with ui.VStack():
- ui.Spacer(height=10)
- with ui.HStack():
- ui.Spacer(width=10)
- with ui.HStack(spacing=8):
- with ui.VStack(width=ui.Percent(30)):
- ui.Spacer(height=2)
- with ui.Frame():
- self.__primary_thumnail = ui.Image("")
- self.__primary_thumnail.set_mouse_hovered_fn(
- functools.partial(self._on_image_hovered, self.__primary_thumnail)
- )
- ui.Spacer(height=2)
- with ui.VStack(height=0, spacing=8, width=ui.Percent(70)):
- ui.Label("Name:")
- self.__string_field_name = ui.StringField(read_only=True)
- ui.Label("File Path:")
- self.__string_field_file_path = ui.StringField(read_only=True)
- ui.Label("Custom tags:")
- self.__string_field_custom_tags = ui.StringField(read_only=True)
- ui.Spacer(width=10)
- ui.Spacer(height=10)
- with ui.ZStack(height=ui.Percent(70)):
- ui.Rectangle(name="MainFrame")
- with ui.VStack():
- ui.Spacer(height=10)
- with ui.HStack():
- ui.Spacer(width=10)
- with ui.VStack(spacing=8):
- with ui.HStack(height=ui.Pixel(22)):
- with ui.ZStack(width=20):
- ui.Rectangle(name="Search")
- ui.Image(str(self._get_icon_path("search")), name="Search")
- with ui.ZStack():
- self.__action_search_attr = ui.StringField()
- self.__action_search_attr.model.add_value_changed_fn(
- lambda m: self._filter_content()
- )
- with ui.HStack():
- ui.Spacer(width=8)
- self.__label_search = ui.Label("Search", name="Search")
- with ui.ZStack(width=20):
- ui.Rectangle(name="Search")
- self.__cross_image = ui.Image(
- str(self._get_icon_path("cross")),
- name="Cross",
- mouse_pressed_fn=lambda x, y, b, m: self._on_search_cross_clicked(),
- visible=False,
- )
- with ui.ScrollingFrame(style_type_name_override="TreeView.ScrollingFrame"):
- self.__tree_view = ui.TreeView( # noqa PLW0238
- self.__model,
- delegate=self.__delegate,
- root_visible=False,
- column_widths=[
- ui.Pixel(self.__model.SIZE_ADDITIONAL_THUMBNAIL + 10),
- ui.Fraction(3),
- ],
- header_visible=False,
- columns_resizable=True,
- )
- ui.Spacer(width=10)
- ui.Spacer(height=10)
-
- # build the ui from of the viewport for the drop
- self._dockspace_window = ui.Window("DockSpace")
- self._dockspace_window.detachable = False
- with self._dockspace_window.frame:
- with ui.VStack():
- frame = ui.Frame()
- frame.set_mouse_pressed_fn(self._on_mouse_clicked_fn)
-
- def _on_mouse_clicked_fn(self, x, y, b, m):
- """Hide everything"""
- self._window_bigger_image.visible = False
- self._window.visible = False
-
- def get_current_mouse_coords(self):
- """Get current mouse coords"""
- pos_x, pos_y = self._input.get_mouse_coords_pixel(self._mouse)
- return pos_x / self._dpi_scale, pos_y / self._dpi_scale
-
- def __create_bigger_image_ui(self):
- self._window_bigger_image = ui.Window(
- self.WINDOW_IMAGE_BIGGER_NAME,
- width=600,
- height=600,
- visible=False,
- flags=ui.WINDOW_FLAGS_POPUP | ui.WINDOW_FLAGS_NO_TITLE_BAR | ui.WINDOW_FLAGS_NO_RESIZE,
- )
- with self._window_bigger_image.frame:
- self.__bigger_image = ui.Image("")
- self.__bigger_image.set_mouse_hovered_fn(self.__on_bigger_image_hovered)
-
- def _on_image_hovered(self, image_widget, hovered):
- if not image_widget.source_url:
- return
- if (
- self.__cancel_mouse_hovered
- and self.__bigger_image.source_url == image_widget.source_url
- and hovered
- and self._window_bigger_image.visible
- ):
- return
- if hovered:
- self.__bigger_image.source_url = image_widget.source_url
- self._window_bigger_image.position_x = image_widget.screen_position_x + image_widget.computed_width + 10
- self._window_bigger_image.position_y = image_widget.screen_position_y
- self._window_bigger_image.visible = True
- self.__cancel_mouse_hovered = True
- else:
- self._window_bigger_image.visible = False
- self.__cancel_mouse_hovered = False
-
- def __on_bigger_image_hovered(self, hovered):
- self.__cancel_mouse_hovered = hovered
- if not hovered:
- self._window_bigger_image.visible = False
-
- def _filter_content(self):
- """Filter content by name"""
- filter_content_title_value = self.__action_search_attr.model.as_string
- self.__label_search.visible = not bool(filter_content_title_value)
- self.__cross_image.visible = bool(filter_content_title_value)
- self.__model.set_filter_str(filter_content_title_value)
-
- def _on_search_cross_clicked(self):
- """Called when the cross from the search box is clicked"""
- self.__action_search_attr.model.set_value("")
- self._filter_content()
-
- def _refresh(self, data: "ContentData"):
- self.__model.refresh_list()
- if data.image_primary_detail_fn is not None:
- primary_thumbnail = data.image_primary_detail_fn()
- else:
- primary_thumbnail = self._core.get_primary_thumbnails(data.path)
- if primary_thumbnail:
- self.__primary_thumnail.source_url = primary_thumbnail
- self.__string_field_custom_tags.model.set_value("To do, to do") # TODO: add tags
- self.__string_field_file_path.model.set_value(data.path)
- self.__string_field_name.model.set_value(data.title)
-
- def show(self, data: "ContentData"):
- if self.__show_window_task:
- self.__show_window_task.cancel()
- self.__show_window_task = asyncio.ensure_future(self.__deferred_show(data))
-
- async def __deferred_show(self, data: "ContentData"):
- await omni.kit.app.get_app().next_update_async() # wait 1 frame to appear after the dockspace mouse click
- self._refresh(data)
- self.__model.refresh_image_paths(data.path)
- x, y = self.get_current_mouse_coords()
- self._window.position_x = x
- self._window.position_y = y
- self._window.visible = True
-
- def hide(self):
- self._window.visible = False
-
- def destroy(self):
- self.__primary_thumnail = None
- self.__bigger_image = None
- self.__tree_view = None # noqa PLW0238
- self.__string_field_custom_tags = None
- self.__string_field_file_path = None
- self.__string_field_name = None
- self.__action_search_attr = None
- self.__cross_image = None
- self.__label_search = None
- self.__show_window_task = None
- for attr, value in self.__default_attr.items():
- m_attr = getattr(self, attr)
- if isinstance(m_attr, list):
- m_attrs = m_attr
- else:
- m_attrs = [m_attr]
- for m_attr in m_attrs:
- destroy = getattr(m_attr, "destroy", None)
- if callable(destroy):
- destroy() # noqa PLE1102
- del m_attr
- setattr(self, attr, value)
- self.__model = None
- self.__delegate = None
diff --git a/source/extensions/lightspeed.widget.content_viewer/premake5.lua b/source/extensions/lightspeed.widget.content_viewer/premake5.lua
deleted file mode 100644
index 2a7d977ad..000000000
--- a/source/extensions/lightspeed.widget.content_viewer/premake5.lua
+++ /dev/null
@@ -1,12 +0,0 @@
-local ext = get_current_extension_info()
-
-project_ext (ext)
-
--- Link only those files and folders into the extension target directory
-repo_build.prebuild_link {
- {"lightspeed", ext.target_dir.."/lightspeed"},
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "icons", ext.target_dir.."/icons" }
-}
-repo_build.prebuild_copy { "docs/jxnblk-LICENSE.md", ext.target_dir.."/PACKAGE-LICENSES/jxnblk-LICENSE.md" }
diff --git a/source/extensions/lightspeed.widget.game_captures/config/extension.toml b/source/extensions/lightspeed.widget.game_captures/config/extension.toml
deleted file mode 100644
index 1826cbac2..000000000
--- a/source/extensions/lightspeed.widget.game_captures/config/extension.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-[package]
-version = "0.1.2"
-authors = ["dbataille@nvidia.com"]
-repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit"
-changelog = "docs/CHANGELOG.md"
-readme = "docs/README.md"
-keywords = ["viewer", "widget", "capture"]
-title = "Lightspeed Widget Game Captures"
-description = "Let the user view game capture(s) for a game"
-icon = "data/icon.png"
-category = "internal"
-preview_image = "data/preview.png"
-
-[ui]
-name = "Lightspeed Widget Game Captures"
-
-[dependencies]
-"omni.client" = {}
-"lightspeed.common" = {}
-"lightspeed.widget.content_viewer" = {}
-"omni.ui" = {}
-
-[[python.module]]
-name = "lightspeed.widget.game_captures"
diff --git a/source/extensions/lightspeed.widget.game_captures/data/icon.png b/source/extensions/lightspeed.widget.game_captures/data/icon.png
deleted file mode 100644
index 4068f06a1..000000000
--- a/source/extensions/lightspeed.widget.game_captures/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:67df76f6fc87594c2f309dd98d44826b42dd530000f63b616697e1dcc1728540
-size 1343
diff --git a/source/extensions/lightspeed.widget.game_captures/data/preview.png b/source/extensions/lightspeed.widget.game_captures/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.widget.game_captures/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.widget.game_captures/docs/CHANGELOG.md b/source/extensions/lightspeed.widget.game_captures/docs/CHANGELOG.md
deleted file mode 100644
index 0869269ef..000000000
--- a/source/extensions/lightspeed.widget.game_captures/docs/CHANGELOG.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2021-11-17
-### Added
-- Created
diff --git a/source/extensions/lightspeed.widget.game_captures/docs/README.md b/source/extensions/lightspeed.widget.game_captures/docs/README.md
deleted file mode 100644
index 59efe789a..000000000
--- a/source/extensions/lightspeed.widget.game_captures/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.widget.game_captures
diff --git a/source/extensions/lightspeed.widget.game_captures/docs/index.rst b/source/extensions/lightspeed.widget.game_captures/docs/index.rst
deleted file mode 100644
index fa5733988..000000000
--- a/source/extensions/lightspeed.widget.game_captures/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.widget.game_captures
-################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.widget.game_captures
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.widget.game_captures/icons/folder_open.svg b/source/extensions/lightspeed.widget.game_captures/icons/folder_open.svg
deleted file mode 100644
index e5a522970..000000000
--- a/source/extensions/lightspeed.widget.game_captures/icons/folder_open.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/source/extensions/lightspeed.widget.game_captures/icons/rig.svg b/source/extensions/lightspeed.widget.game_captures/icons/rig.svg
deleted file mode 100644
index 7d5d5ee67..000000000
--- a/source/extensions/lightspeed.widget.game_captures/icons/rig.svg
+++ /dev/null
@@ -1,43 +0,0 @@
-
diff --git a/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/__init__.py b/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/__init__.py
deleted file mode 100644
index a50f7a298..000000000
--- a/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .scripts import * # noqa F401
diff --git a/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/scripts/__init__.py b/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/scripts/__init__.py
deleted file mode 100644
index 2a4b35b86..000000000
--- a/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/scripts/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
diff --git a/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/scripts/core.py b/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/scripts/core.py
deleted file mode 100644
index 98bed63c6..000000000
--- a/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/scripts/core.py
+++ /dev/null
@@ -1,136 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import functools
-from pathlib import Path
-from typing import Optional
-
-import carb
-from lightspeed.widget.content_viewer.scripts.core import ContentData, ContentViewerCore
-from pydantic import ValidationError
-
-from .utils import get_capture_image, get_captures
-
-
-class GameCapturesCore(ContentViewerCore):
- class _Event(set):
- """
- A list of callable objects. Calling an instance of this will cause a
- call to each item in the list in ascending order by index.
- """
-
- def __call__(self, *args, **kwargs):
- """Called when the instance is “called” as a function"""
- # Call all the saved functions
- for f in self:
- f(*args, **kwargs)
-
- def __repr__(self):
- """
- Called by the repr() built-in function to compute the “official”
- string representation of an object.
- """
- return f"Event({set.__repr__(self)})"
-
- class _EventSubscription:
- """
- Event subscription.
-
- _Event has callback while this object exists.
- """
-
- def __init__(self, event, fn):
- """
- Save the function, the event, and add the function to the event.
- """
- self._fn = fn
- self._event = event
- event.add(self._fn)
-
- def __del__(self):
- """Called by GC."""
- self._event.remove(self._fn)
-
- def __init__(self):
- super().__init__()
- self.__current_game_capture_folder = None
- self.__current_capture = None
- self.__on_current_game_capture_folder_changed = self._Event()
- self.__on_current_capture_changed = self._Event()
-
- @property
- def default_attr(self):
- result = super().default_attr
- result.update({})
- return result
-
- def set_current_game_capture_folder(self, data: Optional[ContentData]):
- self.__current_game_capture_folder = data
- self._current_game_capture_folder_changed()
-
- def get_current_game_capture_folder(self) -> Optional[ContentData]:
- return self.__current_game_capture_folder
-
- def _current_game_capture_folder_changed(self):
- """Call the event object that has the list of functions"""
- self.__on_current_game_capture_folder_changed(self.__current_game_capture_folder)
-
- def subscribe_current_game_capture_folder_changed(self, fn):
- """
- Return the object that will automatically unsubscribe when destroyed.
- """
- return self._EventSubscription(self.__on_current_game_capture_folder_changed, fn)
-
- def set_current_capture(self, data: Optional[ContentData]):
- self.__current_capture = data
- self._current_capture_changed()
-
- def get_current_capture(self) -> Optional[ContentData]:
- return self.__current_capture
-
- def _current_capture_changed(self):
- """Call the event object that has the list of functions"""
- self.__on_current_capture_changed(self.__current_capture)
-
- def subscribe_current_capture_changed(self, fn):
- """
- Return the object that will automatically unsubscribe when destroyed.
- """
- return self._EventSubscription(self.__on_current_capture_changed, fn)
-
- def _get_capture_image(self, capture_usd_path: str) -> Optional[str]:
- return get_capture_image(capture_usd_path)
-
- def _get_content_data(self):
- files = get_captures(self.__current_game_capture_folder)
-
- result = []
- for path in files:
- try:
- p_obj = Path(path)
- result.append(
- ContentData(
- title=p_obj.stem.capitalize(),
- path=path,
- image_path_fn=functools.partial(self._get_capture_image, path),
- image_primary_detail_fn=functools.partial(self._get_capture_image, path),
- )
- )
- except ValidationError as e:
- carb.log_error(e.json())
-
- return result
diff --git a/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/scripts/ui.py b/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/scripts/ui.py
deleted file mode 100644
index f87dfaef9..000000000
--- a/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/scripts/ui.py
+++ /dev/null
@@ -1,94 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import typing
-from pathlib import Path
-from typing import List
-
-from lightspeed.widget.content_viewer.scripts.ui import ContentItem, ContentViewer
-
-if typing.TYPE_CHECKING:
- from .core import GameCapturesCore
- from lightspeed.widget.content_viewer.scripts.core import ContentData
-
-import omni.ui as ui # TODO: menu, switch to the new method when Kit switched
-
-
-class ContentItemCapture(ContentItem):
- MULTI_SELECTION = False
-
-
-class GameCapturesViewer(ContentViewer):
-
- GRID_COLUMN_WIDTH = 165
- GRID_ROW_HEIGHT = 165
- CONTENT_ITEM_TYPE = ContentItemCapture
-
- def __init__(self, core: "GameCapturesCore", extension_path: str):
- """Window to list all maps"""
- super().__init__(core, extension_path)
- self._subcription_current_game_changed = self._core.subscribe_current_game_capture_folder_changed(
- self._on_current_game_changed
- )
-
- @property
- def default_attr(self):
- result = super().default_attr
- result.update({"_label_game": None})
- return result
-
- @property
- def style(self):
- style = super().style
- style.update(
- {
- "Label::vehicle": {"font_size": 22},
- "Rectangle::SubBackground0": {
- "background_color": 0x60333333,
- "border_width": 1.0,
- "border_color": 0x20FFFFFF,
- },
- }
- )
- return style
-
- def _on_selection_changed(self, contents_data: List["ContentData"]):
- super()._on_selection_changed(contents_data)
- if not contents_data:
- self._core.set_current_capture(None)
- return
- self._core.set_current_capture(contents_data[0])
-
- def _on_current_game_changed(self, data):
- self._label_game.text = f"{data.title} game capture(s):"
-
- def create_ui(self):
- """Create the main UI"""
- with ui.Frame(style=self.style):
- with ui.VStack():
- self._create_ui()
-
- with self.get_top_frame():
- with ui.HStack():
- self._label_game = ui.Label("", name="vehicle")
-
- @property
- def calling_extension_path(self):
- current_path = Path(__file__).parent
- for _ in range(4):
- current_path = current_path.parent
- return current_path
diff --git a/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/scripts/utils.py b/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/scripts/utils.py
deleted file mode 100644
index 39323cc11..000000000
--- a/source/extensions/lightspeed.widget.game_captures/lightspeed/widget/game_captures/scripts/utils.py
+++ /dev/null
@@ -1,63 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import typing
-from pathlib import Path
-from typing import List, Optional
-
-import carb
-import carb.tokens
-import omni.client
-from lightspeed.common.constants import CAPTURE_FOLDER, LSS_FOLDER, USD_EXTENSIONS
-
-if typing.TYPE_CHECKING:
- from lightspeed.widget.content_viewer.scripts.core import ContentData
-
-
-def get_captures(data: "ContentData") -> List[str]:
- return sorted(
- [
- str(file)
- for file in Path(data.path).iterdir()
- if file.is_file() and file.suffix in USD_EXTENSIONS and str(file.stem).startswith(f"{CAPTURE_FOLDER}_")
- ],
- reverse=True,
- )
-
-
-def get_capture_image(usd_path: str) -> Optional[str]:
- image_path = Path(usd_path).parent.joinpath(".thumbs", f"{Path(usd_path).name}.dds")
- return str(image_path) if image_path.exists() else None
-
-
-def get_captures_directory(data: "ContentData") -> str:
- return str(Path(data.path).parent.joinpath(LSS_FOLDER, CAPTURE_FOLDER))
-
-
-def read_file(file_path) -> Optional[bytes]:
- """Read a file on the disk"""
- result, _, content = omni.client.read_file(file_path)
- if result == omni.client.Result.OK:
- data = memoryview(content).tobytes()
- else:
- try: # try local
- with open(file_path, "rb") as in_file:
- data = in_file.read()
- except IOError:
- carb.log_error(f"Cannot read {file_path}, error code: {result}.")
- return None
- return data # noqa R504
diff --git a/source/extensions/lightspeed.widget.game_captures/premake5.lua b/source/extensions/lightspeed.widget.game_captures/premake5.lua
deleted file mode 100644
index 49a6046fd..000000000
--- a/source/extensions/lightspeed.widget.game_captures/premake5.lua
+++ /dev/null
@@ -1,11 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "lightspeed", ext.target_dir.."/lightspeed" },
- { "icons", ext.target_dir.."/icons" }
-}
diff --git a/source/extensions/lightspeed.widget.new_game/config/extension.toml b/source/extensions/lightspeed.widget.new_game/config/extension.toml
deleted file mode 100644
index c024997fe..000000000
--- a/source/extensions/lightspeed.widget.new_game/config/extension.toml
+++ /dev/null
@@ -1,43 +0,0 @@
-[package]
-version = "0.1.6"
-authors = ["dbataille@nvidia.com"]
-repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit"
-changelog = "docs/CHANGELOG.md"
-readme = "docs/README.md"
-keywords = ["new", "widget", "game"]
-title = "Lightspeed New Game Widget"
-description = "Lightspeed New Game Widget let the user creates a new game category"
-icon = "data/icon.png"
-category = "internal"
-preview_image = "data/preview.png"
-
-[dependencies]
-"lightspeed.common" = {}
-"lightspeed.pip_archive" = {} # Required for Pydantic
-"lightspeed.upscale.core" = {}
-"omni.client" = {}
-"omni.flux.utils.widget" = {}
-"omni.kit.pip_archive" = {} # For PIL
-"omni.kit.widget.filebrowser" = {}
-"omni.kit.window.filepicker" = {}
-"omni.kit.window.popup_dialog" = {}
-"omni.ui" = {}
-"omni.usd" = {}
-
-[[python.module]]
-name = "lightspeed.widget.new_game"
-
-[[test]]
-dependencies = [
- "lightspeed.trex.tests.dependencies",
-]
-
-stdoutFailPatterns.exclude = [
- "*[omni.kit.registry.nucleus.utils.common] Skipping deletion of:*",
-]
-
-[[test]]
-name = "startup"
-dependencies = [
- "lightspeed.trex.tests.dependencies",
-]
diff --git a/source/extensions/lightspeed.widget.new_game/data/icon.png b/source/extensions/lightspeed.widget.new_game/data/icon.png
deleted file mode 100644
index 4068f06a1..000000000
--- a/source/extensions/lightspeed.widget.new_game/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:67df76f6fc87594c2f309dd98d44826b42dd530000f63b616697e1dcc1728540
-size 1343
diff --git a/source/extensions/lightspeed.widget.new_game/data/preview.png b/source/extensions/lightspeed.widget.new_game/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.widget.new_game/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.widget.new_game/docs/CHANGELOG.md b/source/extensions/lightspeed.widget.new_game/docs/CHANGELOG.md
deleted file mode 100644
index 796cffb4e..000000000
--- a/source/extensions/lightspeed.widget.new_game/docs/CHANGELOG.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.6]
-## Changed
-- Update to Kit 106.5
-
-## [0.1.5]
-### Fixed
-- Added missing test config
-
-## [0.1.4]
-### Fixed
-- Close Pillow image
-
-## [0.1.3]
-- Use updated `lightspeed.layer_manager.core` extension
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2021-11-17
-### Added
-- Created
diff --git a/source/extensions/lightspeed.widget.new_game/docs/README.md b/source/extensions/lightspeed.widget.new_game/docs/README.md
deleted file mode 100644
index 9f453f069..000000000
--- a/source/extensions/lightspeed.widget.new_game/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.widget.new_game
diff --git a/source/extensions/lightspeed.widget.new_game/docs/index.rst b/source/extensions/lightspeed.widget.new_game/docs/index.rst
deleted file mode 100644
index af15de151..000000000
--- a/source/extensions/lightspeed.widget.new_game/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.widget.new_game
-###########################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.widget.new_game
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.widget.new_game/icons/folder_open.svg b/source/extensions/lightspeed.widget.new_game/icons/folder_open.svg
deleted file mode 100644
index e5a522970..000000000
--- a/source/extensions/lightspeed.widget.new_game/icons/folder_open.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/__init__.py b/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/__init__.py
deleted file mode 100644
index a50f7a298..000000000
--- a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .scripts import * # noqa F401
diff --git a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/__init__.py b/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/__init__.py
deleted file mode 100644
index 2a4b35b86..000000000
--- a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
diff --git a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/core.py b/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/core.py
deleted file mode 100644
index 2dc1d9260..000000000
--- a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/core.py
+++ /dev/null
@@ -1,143 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import functools
-from pathlib import Path
-from typing import Optional
-
-import carb
-import carb.settings
-from lightspeed.common.constants import CAPTURE_FOLDER
-from lightspeed.widget.content_viewer.scripts.core import ContentData, ContentDataAdd, ContentViewerCore
-from lightspeed.widget.content_viewer.scripts.utils import is_path_readable
-from pydantic import ValidationError
-
-from .utils import get_instance as get_game_json_instance
-from .utils import get_upscaled_game_icon_from_capture_folder
-
-
-class GameContentData(ContentData):
- @property
- def is_path_valid(self):
- """Check is the USD path exist"""
- return is_path_readable(self.path) and str(Path(self.path).name) == CAPTURE_FOLDER
-
-
-class GameCore(ContentViewerCore):
- class _Event(set):
- """
- A list of callable objects. Calling an instance of this will cause a
- call to each item in the list in ascending order by index.
- """
-
- def __call__(self, *args, **kwargs):
- """Called when the instance is “called” as a function"""
- # Call all the saved functions
- for f in self:
- f(*args, **kwargs)
-
- def __repr__(self):
- """
- Called by the repr() built-in function to compute the “official”
- string representation of an object.
- """
- return f"Event({set.__repr__(self)})"
-
- class _EventSubscription:
- """
- Event subscription.
-
- _Event has callback while this object exists.
- """
-
- def __init__(self, event, fn):
- """
- Save the function, the event, and add the function to the event.
- """
- self._fn = fn
- self._event = event
- event.add(self._fn)
-
- def __del__(self):
- """Called by GC."""
- self._event.remove(self._fn)
-
- def __init__(self):
- super().__init__()
- self._settings = carb.settings.get_settings()
- self._filter = None
-
- self.__current_game_capture_folder = None
- self.__on_current_game_capture_folder_changed = self._Event()
-
- def set_filter(self, _filter: str):
- self._filter = _filter
-
- def set_current_game_capture_folder(self, data: Optional[GameContentData]):
- self.__current_game_capture_folder = data
- self._current_game_capture_folder_changed()
-
- def get_current_game_capture_folder(self) -> GameContentData:
- return self.__current_game_capture_folder
-
- def _current_game_capture_folder_changed(self):
- """Call the event object that has the list of functions"""
- self.__on_current_game_capture_folder_changed(self.__current_game_capture_folder)
-
- def subscribe_current_game_capture_folder_changed(self, fn):
- """
- Return the object that will automatically unsubscribe when destroyed.
- """
- return self._EventSubscription(self.__on_current_game_capture_folder_changed, fn)
-
- def save_current_game_capture_folder_in_json(self):
- if isinstance(self.__current_game_capture_folder, ContentDataAdd):
- get_game_json_instance().append_path_to_file(
- self.__current_game_capture_folder.path, self.__current_game_capture_folder.title
- )
-
- def delete_selected_game(self):
- selection = self.get_selection()
- get_game_json_instance().delete_names([item.title for item in selection])
-
- @property
- def default_attr(self):
- result = super().default_attr
- result.update({})
- return result
-
- def _get_game_icon(self, capture_folder_path: str) -> Optional[str]:
- return get_upscaled_game_icon_from_capture_folder(capture_folder_path)
-
- def _get_primary_detail_image(self, capture_folder_path: str) -> Optional[str]:
- return None
-
- def _get_content_data(self):
- json_data = get_game_json_instance().get_file_data()
- result = []
- for title, data in json_data.items():
- try:
- result.append(
- GameContentData(
- title=title,
- path=data.get("path"),
- image_path_fn=functools.partial(self._get_game_icon, str(Path(data.get("path")).resolve())),
- )
- )
- except ValidationError as e:
- carb.log_error(e.json())
- return result
diff --git a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/relink/__init__.py b/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/relink/__init__.py
deleted file mode 100644
index 2a4b35b86..000000000
--- a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/relink/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
diff --git a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/relink/delegate.py b/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/relink/delegate.py
deleted file mode 100644
index 3c3e46d02..000000000
--- a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/relink/delegate.py
+++ /dev/null
@@ -1,45 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import omni.ui as ui
-
-from .model import HEADER_DICT
-
-
-class Delegate(ui.AbstractItemDelegate):
- """Delegate of the action lister"""
-
- def build_branch(self, model, item, column_id, level, expanded):
- """Create a branch widget that opens or closes subtree"""
- pass
-
- # noinspection PyUnusedLocal
- def build_widget(self, model, item, column_id, level, expanded):
- """Create a widget per item"""
- if item is None:
- return
- if column_id == 0:
- ui.Label(item.path, style_type_name_override="TreeView.Item")
- elif column_id == 1:
- name = "" if item.replaced_path_valid() else "NotValid"
- ui.Label(item.replaced_path, style_type_name_override="TreeView.Item", name=name)
-
- def build_header(self, column_id):
- """Build the header"""
- style_type_name = "TreeView.Header"
- with ui.HStack():
- ui.Label(HEADER_DICT[column_id], style_type_name_override=style_type_name)
diff --git a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/relink/model.py b/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/relink/model.py
deleted file mode 100644
index 57156c96c..000000000
--- a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/relink/model.py
+++ /dev/null
@@ -1,108 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import typing
-from pathlib import Path
-from typing import List
-
-import omni.ui as ui
-
-if typing.TYPE_CHECKING:
- from lightspeed.widget.content_viewer.scripts.core import ContentData
-
-from ..utils import get_instance as get_game_json_instance
-
-HEADER_DICT = {0: "Original", 1: "Result"}
-
-
-class Item(ui.AbstractItem):
- """Item of the model"""
-
- def __init__(self, title, path, search_value, replace_value):
- super().__init__()
- self.title = title
- resolved = Path(path).resolve()
- self.path = str(resolved)
- self.replaced_path = str(resolved).replace(search_value, replace_value)
- self.path_model = ui.SimpleStringModel(self.path)
-
- def replaced_path_valid(self):
- return Path(self.replaced_path).resolve().exists()
-
- def __repr__(self):
- return f'"{self.path}"'
-
-
-class ListModel(ui.AbstractItemModel):
- """List model of actions"""
-
- def __init__(self):
- super().__init__()
- self.default_attr = {}
- for attr, value in self.default_attr.items():
- setattr(self, attr, value)
- self.__children = []
-
- def refresh(self, items: List["ContentData"], search_value, replace_value):
- """Refresh the list"""
- self.__children = [Item(data.title, data.path, search_value, replace_value) for data in items]
- self._item_changed(None)
-
- def relink(self):
- result = {}
- dict_game_capture_folder_data = get_game_json_instance().get_file_data()
- for game_name, data in dict_game_capture_folder_data.items():
- result[game_name] = data
- for item in self.__children:
- if item.title == game_name:
- result[game_name] = {"path": item.replaced_path}
- break
- get_game_json_instance().override_data_with(result)
-
- def get_item_children(self, item):
- """Returns all the children when the widget asks it."""
- if item is None:
- return self.__children
- return []
-
- def get_item_value_model_count(self, item):
- """The number of columns"""
- return len(HEADER_DICT.keys())
-
- def get_item_value_model(self, item, column_id):
- """
- Return value model.
- It's the object that tracks the specific value.
- In our case we use ui.SimpleStringModel.
- """
- if column_id == 0:
- return item.path_model
- return None
-
- def destroy(self):
- for attr, value in self.default_attr.items():
- m_attr = getattr(self, attr)
- if isinstance(m_attr, list):
- m_attrs = m_attr
- else:
- m_attrs = [m_attr]
- for m_attr in m_attrs:
- destroy = getattr(m_attr, "destroy", None)
- if callable(destroy):
- destroy()
- del m_attr
- setattr(self, attr, value)
diff --git a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/ui.py b/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/ui.py
deleted file mode 100644
index b004f685e..000000000
--- a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/ui.py
+++ /dev/null
@@ -1,384 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import typing
-from pathlib import Path
-from typing import List
-
-import carb
-import carb.settings
-from lightspeed.common.constants import CAPTURE_FOLDER
-from lightspeed.widget.content_viewer.scripts.core import ContentData, ContentDataAdd
-from lightspeed.widget.content_viewer.scripts.ui import ContentItem, ContentViewer
-from lightspeed.widget.content_viewer.scripts.utils import is_path_readable
-
-if typing.TYPE_CHECKING:
- from .core import GameCore
-
-import omni.ui as ui # TODO: menu, switch to the new method when Kit switched
-
-from .relink.delegate import Delegate as RelinkTreeDelegate
-from .relink.model import ListModel as RelinkTreeModel
-from .usd_file_picker import open_file_picker
-
-
-class GameContentItem(ContentItem):
- MULTI_SELECTION = False
-
- @property
- def style(self):
- style = super().style
- style.update(
- {
- "Image::Background": {"border_radius": 20},
- "Rectangle.Overlay": {
- "background_color": 0x00FFFFFF,
- "border_width": 1.0,
- "border_color": 0x20FFFFFF,
- "border_radius": 20,
- },
- }
- )
- return style
-
- @property
- def is_usd_path_valid(self):
- """Check is the USD path exist"""
- return self.content_data.is_path_valid
-
-
-class GameViewer(ContentViewer):
-
- GRID_COLUMN_WIDTH = 100
- GRID_ROW_HEIGHT = 128
- ENABLE_ADD_ITEM = True
- CONTENT_ITEM_TYPE = GameContentItem
-
- def __init__(self, core: "GameCore", extension_path: str):
- """Window to list all maps"""
- super().__init__(core, extension_path)
- self._settings = carb.settings.get_settings()
- self._relink_tree_model = RelinkTreeModel()
- self._relink_tree_delegate = RelinkTreeDelegate()
-
- @property
- def default_attr(self):
- result = super().default_attr
- result.update(
- {
- "_label_game": None,
- "_game_capture_folder_field": None,
- "_game_name_field": None,
- "_relink_window": None,
- "_relink_tree_model": None,
- "_relink_tree_delegate": None,
- "_relink_tree": None,
- }
- )
- return result
-
- @property
- def style(self):
- style = super().style
- style.update(
- {
- "Button::relink": {"background_color": 0x70C5911A},
- "Label::vehicle": {"font_size": 22},
- "Label::relink": {"font_size": 22},
- "Image::SavePath": {"color": 0x90FFFFFF},
- "Image::SavePath:hovered": {"color": 0xFFFFFFFF},
- "Rectangle::SubBackground0": {
- "background_color": 0x60333333,
- "border_width": 1.0,
- "border_color": 0x20FFFFFF,
- },
- "Rectangle::SubBackground1": {
- "background_color": 0x00333333,
- "border_width": 1.0,
- "border_color": 0x20FFFFFF,
- },
- "TreeView": {
- "background_color": 0xFF23211F,
- "background_selected_color": 0x664F4D43,
- "secondary_color": 0xFF403B3B,
- },
- "TreeView.ScrollingFrame": {"background_color": 0xFF23211F},
- "TreeView.Header": {"background_color": 0xFF343432, "color": 0xFFCCCCCC, "font_size": 13},
- "TreeView.Item": {"color": 0xFF8A8777},
- "TreeView.Item:selected": {"color": 0xFF23211F},
- "TreeView.Item::NotValid": {"color": 0xFF0000B4},
- "TreeView:selected": {"background_color": 0xFF8A8777},
- }
- )
- return style
-
- def _on_selection_changed(self, contents_data: List[ContentData]):
- super()._on_selection_changed(contents_data)
- if not contents_data:
- self.CONTENT_ITEM_TYPE.MULTI_SELECTION = False
- self._label_game.text = ""
- self._core.set_current_game_capture_folder(None)
- self._frame_buttons.clear()
- self._frame_buttons.height = ui.Percent(0)
- return
- if contents_data and isinstance(contents_data[0], ContentData):
- # multi selection is off, so only the first one
- game_capture_path = Path(contents_data[0].path).resolve()
- if is_path_readable(str(game_capture_path)) and str(game_capture_path.name) == CAPTURE_FOLDER:
- self.CONTENT_ITEM_TYPE.MULTI_SELECTION = False
- if len(contents_data) > 1:
- carb.log_warn("Only the first item from the selection will be selected")
- self._label_game.text = contents_data[0].title
- self._frame_buttons.clear()
- else: # doesnt exist. We show the relink UI
- # relink UI can relink multiple captures in 1 click
- self.CONTENT_ITEM_TYPE.MULTI_SELECTION = True
- self._label_game.text = contents_data[0].title
- with self._frame_buttons:
- with ui.ZStack(height=0):
- ui.Rectangle(name="SubBackground0")
- with ui.VStack():
- ui.Spacer(height=8)
- with ui.HStack():
- ui.Spacer(width=8)
- with ui.VStack(spacing=8):
- row_height = 24
- sub_width = ui.Pixel(50)
- sub_label_width = ui.Pixel(100)
-
- with ui.ZStack(height=0):
- ui.Rectangle(name="SubBackground1")
- with ui.VStack():
- ui.Spacer(height=8)
- with ui.HStack(height=0):
- ui.Spacer(width=8)
- ui.Label("Relinker search and replace", name="relink")
- ui.Spacer(height=12)
- with ui.HStack():
- ui.Spacer(width=8)
- with ui.VStack(spacing=8):
- with ui.HStack(height=row_height, spacing=8):
- ui.Spacer(width=sub_width)
- ui.Label("Search", width=sub_label_width)
- self._relinker_game_capture_folder_search_field = (
- ui.StringField()
- )
- self._relinker_game_capture_folder_search_field.model.set_value(
- str(game_capture_path)
- )
- with ui.HStack(height=row_height, spacing=8):
- ui.Spacer(width=sub_width)
- ui.Label("Replace", width=sub_label_width)
- self._relinker_game_capture_folder_replace_field = (
- ui.StringField()
- )
- self._relinker_game_capture_folder_replace_field.model.set_value( # noqa E501
- str(game_capture_path)
- )
- ui.Image(
- str(
- self._get_icon_path(
- "folder_open", from_base_extension=False
- )
- ),
- width=row_height,
- name="SavePath",
- mouse_released_fn=lambda x, y, b, m: self._on_relink_game_capture_folder( # noqa E501
- # noqa E501
- b,
- m,
- ),
- )
- with ui.HStack(height=row_height, spacing=8):
- ui.Spacer(width=ui.Percent(80))
- ui.Button(
- "Relink",
- name="relink",
- clicked_fn=self._on_relink_button_clicked,
- )
- ui.Spacer(width=8)
- ui.Spacer(height=8)
-
- ui.Spacer(width=8)
- ui.Spacer(height=8)
- else:
- self._label_game.text = ""
- self.CONTENT_ITEM_TYPE.MULTI_SELECTION = False
- with self._frame_buttons:
- with ui.ZStack(height=0):
- ui.Rectangle(name="SubBackground0")
- with ui.VStack():
- ui.Spacer(height=8)
- with ui.HStack():
- ui.Spacer(width=8)
- with ui.VStack(spacing=8):
- row_height = 24
- sub_width = ui.Pixel(50)
- sub_label_width = ui.Pixel(100)
-
- with ui.ZStack(height=0):
- ui.Rectangle(name="SubBackground1")
- with ui.VStack():
- ui.Spacer(height=8)
- with ui.HStack():
- ui.Spacer(width=8)
- with ui.VStack(spacing=8):
- with ui.HStack(height=row_height, spacing=8):
- ui.Spacer(width=sub_width)
- ui.Label("Game capture folder", width=sub_label_width)
- self._game_capture_folder_field = ui.StringField()
- self._game_capture_folder_field.model.add_end_edit_fn(
- self._on_game_capture_folder_edit
- )
- ui.Image(
- str(
- self._get_icon_path(
- "folder_open", from_base_extension=False
- )
- ),
- width=row_height,
- name="SavePath",
- mouse_released_fn=lambda x, y, b, m: self._on_game_capture_folder( # noqa E501
- # noqa E501
- b,
- m,
- ),
- )
- with ui.HStack(height=row_height, spacing=8):
- ui.Spacer(width=sub_width)
- ui.Label("Name", width=sub_label_width)
- self._game_name_field = ui.StringField()
- self._game_name_field.model.add_end_edit_fn(self._on_game_name_edit)
- ui.Spacer(width=8)
- ui.Spacer(height=8)
-
- ui.Spacer(width=8)
- ui.Spacer(height=8)
- self._core.set_current_game_capture_folder(contents_data[0])
-
- def create_ui(self):
- """Create the main UI"""
- with ui.Frame(style=self.style):
- with ui.VStack():
- self._create_ui()
- self._frame_buttons = ui.Frame(height=0)
-
- with self.get_top_frame():
- self._label_game = ui.Label("", name="vehicle")
-
- self.__create_relink_ui()
-
- def __create_relink_ui(self):
- window_name = "Relink check window"
- self._relink_window = ui.Window(
- window_name, name=window_name, width=900, height=600, visible=False, flags=ui.WINDOW_FLAGS_MODAL
- )
-
- with self._relink_window.frame:
- with ui.VStack(style=self.style):
- with ui.ScrollingFrame(
- horizontal_scrollbar_policy=ui.ScrollBarPolicy.SCROLLBAR_ALWAYS_OFF,
- vertical_scrollbar_policy=ui.ScrollBarPolicy.SCROLLBAR_ALWAYS_ON,
- style_type_name_override="TreeView",
- ):
- self._relink_tree = ui.TreeView(
- self._relink_tree_model,
- delegate=self._relink_tree_delegate,
- root_visible=False,
- header_visible=True,
- columns_resizable=True,
- )
- with ui.Frame(height=20):
- with ui.HStack():
- ui.Spacer()
- ui.Button(
- text="Relink",
- height=20,
- width=80,
- alignment=ui.Alignment.CENTER,
- clicked_fn=self._do_relink,
- )
- ui.Spacer()
-
- def _on_relink_game_capture_folder(self, b, m):
- if b != 0:
- return
- open_file_picker(self._relink_game_capture_folder_str_field, lambda *args: None)
-
- def _relink_game_capture_folder_str_field(self, path):
- if not path:
- return
- self._relinker_game_capture_folder_replace_field.model.set_value(path)
-
- def _on_relink_button_clicked(self):
- search_value = self._relinker_game_capture_folder_search_field.model.get_value_as_string()
- replace_value = self._relinker_game_capture_folder_replace_field.model.get_value_as_string()
- selection = self._core.get_selection()
- self._relink_tree_model.refresh(selection, search_value, replace_value)
- self._relink_window.visible = True
-
- def _do_relink(self):
- self._relink_tree_model.relink()
- self._relink_window.visible = False
- self._core.set_selection(None)
- self._core.refresh_content()
-
- def _on_game_name_edit(self, model):
- value = model.get_value_as_string()
- if not value.strip():
- carb.log_error("Please add a game name!")
- return
- game_path = self._game_capture_folder_field.model.get_value_as_string()
- if game_path.strip() and Path(game_path).exists():
- data = ContentDataAdd(title=value, path=game_path)
- self._core.set_current_game_capture_folder(data)
- else:
- self._core.set_current_game_capture_folder(None)
-
- def _on_game_capture_folder_edit(self, model):
- value = model.get_value_as_string()
- if not value.strip() or not Path(value).exists():
- carb.log_error("Please select a game capture folder!")
- return
- game_name = self._game_name_field.model.get_value_as_string()
- if game_name.strip():
- data = ContentDataAdd(title=game_name, path=value)
- self._core.set_current_game_capture_folder(data)
- else:
- self._core.set_current_game_capture_folder(None)
-
- def _on_game_capture_folder(self, b, m):
- if b != 0:
- return
-
- open_file_picker(self._set_game_capture_folder_str_field, lambda *args: None)
-
- def _set_game_capture_folder_str_field(self, path):
- if not path:
- return
- data = ContentDataAdd(title="MyGame", path=path)
- self._game_capture_folder_field.model.set_value(data.path)
- # set the game name automatically
- self._game_name_field.model.set_value(data.title)
- self._core.set_current_game_capture_folder(data)
-
- @property
- def calling_extension_path(self):
- current_path = Path(__file__).parent
- for _ in range(4):
- current_path = current_path.parent
- return current_path
diff --git a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/usd_file_picker.py b/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/usd_file_picker.py
deleted file mode 100644
index 8e6742daa..000000000
--- a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/usd_file_picker.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 pathlib import Path
-from typing import Callable
-
-import carb
-from lightspeed.common.constants import CAPTURE_FOLDER
-from omni.flux.utils.widget.file_pickers.file_picker import open_file_picker as _open_file_picker
-
-
-def __validate_selection(dirname: str, _: str):
- """
- The meat of the App is done in this callback when the user clicks 'Accept'. This is
- a potentially costly operation so we implement it as an async operation. The inputs
- are the filename and directory name. Together they form the fullpath to the selected
- file.
- """
- if not dirname or not Path(dirname).exists() or str(Path(dirname).stem) != CAPTURE_FOLDER:
- carb.log_error(f'Please select a folder named "{CAPTURE_FOLDER}"')
- return False
- return True
-
-
-def open_file_picker(callback: Callable, callback_cancel: Callable):
- _open_file_picker(
- "Select a capture directory",
- callback,
- callback_cancel,
- select_directory=True,
- validate_selection=__validate_selection,
- )
diff --git a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/utils.py b/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/utils.py
deleted file mode 100644
index 164339bc4..000000000
--- a/source/extensions/lightspeed.widget.new_game/lightspeed/widget/new_game/scripts/utils.py
+++ /dev/null
@@ -1,144 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import json
-from pathlib import Path
-from typing import Optional
-
-import carb
-import carb.tokens
-import omni.client
-from lightspeed.upscale.core import UpscaleModels, UpscalerCore
-from PIL import Image
-
-
-class GameCaptureFolderJson:
- def __get_dir(self) -> str:
- """Return the file"""
- token = carb.tokens.get_tokens_interface()
- directory = token.resolve("${app_documents}")
- # FilePickerDialog needs the capital drive. In case it's linux, the
- # first letter will be / and it's still OK.
- return str(Path(directory[:1].upper() + directory[1:]).resolve())
-
- def __get_file(self) -> str:
- """Return the file"""
- directory = self.__get_dir()
- return f"{directory}/lss_games.json"
-
- def append_path_to_file(self, path: str, name: str, save: bool = True):
- current_data = self.get_file_data()
-
- if path in current_data:
- del current_data[path]
- current_data[name] = {"path": path}
-
- if save:
- write_file(self.__get_file(), json.dumps(current_data, indent=4, sort_keys=True).encode("utf8"))
- return current_data
-
- def delete_names(self, names):
- current_data = self.get_file_data()
- for name in names:
- if name in current_data:
- del current_data[name]
- write_file(self.__get_file(), json.dumps(current_data, indent=4, sort_keys=True).encode("utf8"))
-
- def override_data_with(self, data):
- write_file(self.__get_file(), json.dumps(data, indent=4, sort_keys=True).encode("utf8"))
-
- def does_file_exist(self):
- file_path = self.__get_file()
- result, entry = omni.client.stat(file_path)
- if result != omni.client.Result.OK or not entry.flags & omni.client.ItemFlags.READABLE_FILE:
- carb.log_warn(f"Lightspeed game file doesn't exist: {file_path}")
- return False
- return True
-
- def get_file_data(self):
- if not self.does_file_exist():
- return {}
- file_path = self.__get_file()
- carb.log_info(f"Get Lightspeed game file from {file_path}")
- file_data = read_file(file_path)
- if file_data is None:
- return {}
- return json.loads(file_data)
-
-
-_INSTANCE = None
-
-
-def get_game_icon_from_capture_folder(capture_folder_path: str) -> Optional[str]:
- icons = list(Path(capture_folder_path).glob("*_icon.bmp"))
- return str(icons[0]) if icons else None
-
-
-def get_upscaled_game_icon_from_capture_folder(capture_folder_path: str) -> Optional[str]:
- default_icon = get_game_icon_from_capture_folder(capture_folder_path)
- if not default_icon:
- return None
- # look for the upscaled icon
- upscaled = default_icon.replace("_icon.bmp", "_upscaled_icon.png")
- upscaled_path = Path(upscaled)
- if not upscaled_path.exists():
- # first we convert the bmp to png without alpha
- png_file = default_icon.replace("_icon.bmp", "_icon.png")
- with Image.open(default_icon) as im1:
- im1 = im1.convert("RGB")
- im1.save(png_file)
- # we upscale
- UpscalerCore.perform_upscale(UpscaleModels.ESRGAN.value, png_file, str(upscaled_path))
- return str(upscaled_path)
-
-
-def get_instance():
- global _INSTANCE
- if _INSTANCE is None:
- _INSTANCE = GameCaptureFolderJson()
- return _INSTANCE # noqa R504
-
-
-def read_file(file_path) -> Optional[bytes]:
- """Read a file on the disk"""
- result, _, content = omni.client.read_file(file_path)
- if result == omni.client.Result.OK:
- data = memoryview(content).tobytes()
- else:
- try: # try local
- with open(file_path, "rb") as in_file:
- data = in_file.read()
- except IOError:
- carb.log_error(f"Cannot read {file_path}, error code: {result}.")
- return None
- return data # noqa R504
-
-
-def write_file(file_path, data, comment=None) -> bool:
- """Write a file on the disk"""
- json_bytes = bytes(data)
- result = omni.client.write_file(file_path, json_bytes)
- if result != omni.client.Result.OK:
- carb.log_error(f"Cannot write {file_path}, error code: {result}.")
- return False
- result, entry = omni.client.stat(file_path)
- if result == omni.client.Result.OK and entry.flags & omni.client.ItemFlags.IS_CHECKPOINTED:
- result, _ = omni.client.create_checkpoint(file_path, "" if comment is None else comment, force=True)
- if result != omni.client.Result.OK:
- carb.log_error(f"Can't create a checkpoint for file {file_path}")
- carb.log_info(f"File saved to {file_path}")
- return True
diff --git a/source/extensions/lightspeed.widget.new_game/premake5.lua b/source/extensions/lightspeed.widget.new_game/premake5.lua
deleted file mode 100644
index 044ce8148..000000000
--- a/source/extensions/lightspeed.widget.new_game/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
-local ext = get_current_extension_info()
-
-project_ext (ext)
-
-repo_build.prebuild_link {
- { "lightspeed", ext.target_dir.."/lightspeed" },
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "icons", ext.target_dir.."/icons" }
-}
diff --git a/source/extensions/lightspeed.widget.new_workspace/config/extension.toml b/source/extensions/lightspeed.widget.new_workspace/config/extension.toml
deleted file mode 100644
index 505ac9c67..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/config/extension.toml
+++ /dev/null
@@ -1,31 +0,0 @@
-[package]
-version = "0.1.3"
-authors = ["dbataille@nvidia.com"]
-repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit"
-changelog = "docs/CHANGELOG.md"
-readme = "docs/README.md"
-keywords = ["viewer", "widget", "workspace"]
-title = "Lightspeed Widget New Workspace"
-description = "Let the user create a new game workspace"
-icon = "data/icon.png"
-category = "internal"
-preview_image = "data/preview.png"
-
-[ui]
-name = "Lightspeed Widget New Workspace"
-
-[dependencies]
-"omni.client" = {}
-"lightspeed.common" = {}
-"lightspeed.layer_manager.core" = {}
-"lightspeed.widget.content_viewer" = {}
-"lightspeed.widget.game_captures" = {}
-"omni.flux.utils.widget" = {}
-"omni.kit.window.file" = {}
-"omni.kit.widget.filebrowser" = {}
-"omni.kit.window.filepicker" = {}
-"omni.ui" = {}
-"omni.kit.usd.layers" = {}
-
-[[python.module]]
-name = "lightspeed.widget.new_workspace"
diff --git a/source/extensions/lightspeed.widget.new_workspace/data/icon.png b/source/extensions/lightspeed.widget.new_workspace/data/icon.png
deleted file mode 100644
index 4068f06a1..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:67df76f6fc87594c2f309dd98d44826b42dd530000f63b616697e1dcc1728540
-size 1343
diff --git a/source/extensions/lightspeed.widget.new_workspace/data/preview.png b/source/extensions/lightspeed.widget.new_workspace/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.widget.new_workspace/docs/CHANGELOG.md b/source/extensions/lightspeed.widget.new_workspace/docs/CHANGELOG.md
deleted file mode 100644
index 2b991f91e..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/docs/CHANGELOG.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.3]
-- Use updated `lightspeed.layer_manager.core` extension
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2021-11-17
-### Added
-- Created
diff --git a/source/extensions/lightspeed.widget.new_workspace/docs/README.md b/source/extensions/lightspeed.widget.new_workspace/docs/README.md
deleted file mode 100644
index c45152c37..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.widget.new_workspace
diff --git a/source/extensions/lightspeed.widget.new_workspace/docs/index.rst b/source/extensions/lightspeed.widget.new_workspace/docs/index.rst
deleted file mode 100644
index d82ca8207..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.widget.new_workspace
-################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.widget.new_workspace
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.widget.new_workspace/icons/folder_open.svg b/source/extensions/lightspeed.widget.new_workspace/icons/folder_open.svg
deleted file mode 100644
index e5a522970..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/icons/folder_open.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/source/extensions/lightspeed.widget.new_workspace/icons/rig.svg b/source/extensions/lightspeed.widget.new_workspace/icons/rig.svg
deleted file mode 100644
index 7d5d5ee67..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/icons/rig.svg
+++ /dev/null
@@ -1,43 +0,0 @@
-
diff --git a/source/extensions/lightspeed.widget.new_workspace/premake5.lua b/source/extensions/lightspeed.widget.new_workspace/premake5.lua
deleted file mode 100644
index 3a6f7164a..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
-local ext = get_current_extension_info()
-
-project_ext (ext)
-
-repo_build.prebuild_link {
- {"python/lightspeed/", ext.target_dir.."/lightspeed"},
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "icons", ext.target_dir.."/icons" }
-}
diff --git a/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/__init__.py b/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/__init__.py
deleted file mode 100644
index a50f7a298..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .scripts import * # noqa F401
diff --git a/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/__init__.py b/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/__init__.py
deleted file mode 100644
index 2a4b35b86..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
diff --git a/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/core.py b/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/core.py
deleted file mode 100644
index 71a4e0fa2..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/core.py
+++ /dev/null
@@ -1,152 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import os
-import re
-from typing import Optional
-
-import carb
-import omni.client
-from lightspeed.common import constants as _constants
-from lightspeed.widget.game_captures.scripts.core import GameCapturesCore
-
-
-class GameWorkspaceCore(GameCapturesCore):
- class _Event(set):
- """
- A list of callable objects. Calling an instance of this will cause a
- call to each item in the list in ascending order by index.
- """
-
- def __call__(self, *args, **kwargs):
- """Called when the instance is “called” as a function"""
- # Call all the saved functions
- for f in self:
- f(*args, **kwargs)
-
- def __repr__(self):
- """
- Called by the repr() built-in function to compute the “official”
- string representation of an object.
- """
- return f"Event({set.__repr__(self)})"
-
- class _EventSubscription:
- """
- Event subscription.
-
- _Event has callback while this object exists.
- """
-
- def __init__(self, event, fn):
- """
- Save the function, the event, and add the function to the event.
- """
- self._fn = fn
- self._event = event
- event.add(self._fn)
-
- def __del__(self):
- """Called by GC."""
- self._event.remove(self._fn)
-
- def __init__(self):
- super().__init__()
- self.__current_use_existing_layer = False
- self.__current_replacement_layer_usd_path = None
- self.__on_current_use_existing_layer_changed = self._Event()
- self.__on_current_replacement_layer_usd_path_changed = self._Event()
-
- @property
- def default_attr(self):
- result = super().default_attr
- result.update({})
- return result
-
- def set_current_use_existing_layer(self, data: bool):
- self.__current_use_existing_layer = data
- self._current_use_existing_layer_changed()
-
- def get_current_use_existing_layer(self) -> bool:
- return self.__current_use_existing_layer
-
- def _current_use_existing_layer_changed(self):
- """Call the event object that has the list of functions"""
- self.__on_current_use_existing_layer_changed(self.__current_use_existing_layer)
-
- def subscribe_current_use_existing_layer_changed(self, fn):
- """
- Return the object that will automatically unsubscribe when destroyed.
- """
- return self._EventSubscription(self.__on_current_use_existing_layer_changed, fn)
-
- def set_current_replacement_layer_usd_path(self, data: Optional[str]):
- self.__current_replacement_layer_usd_path = data
- self._current_replacement_layer_usd_path_changed()
-
- def get_current_replacement_layer_usd_path(self) -> Optional[str]:
- return self.__current_replacement_layer_usd_path
-
- def _current_replacement_layer_usd_path_changed(self):
- """Call the event object that has the list of functions"""
- self.__on_current_replacement_layer_usd_path_changed(self.__current_replacement_layer_usd_path)
-
- def subscribe_current_replacement_layer_usd_path_changed(self, fn):
- """
- Return the object that will automatically unsubscribe when destroyed.
- """
- return self._EventSubscription(self.__on_current_replacement_layer_usd_path_changed, fn)
-
- def check_replacement_layer_path(self) -> bool:
- replacement_layer_path = self.get_current_replacement_layer_usd_path()
- if not replacement_layer_path:
- if self.get_current_use_existing_layer():
- carb.log_error("Please select an existing replacement layer")
- else:
- carb.log_error("Please set a path of where to create the usd replacement layer")
- return False
- directory = os.path.dirname(replacement_layer_path)
- if not directory:
- carb.log_error("Replacement layer path is wrong, please set a full path")
- return False
- result, entry = omni.client.stat(directory)
- if result == omni.client.Result.OK and entry.flags & omni.client.ItemFlags.CAN_HAVE_CHILDREN:
- valid_ext = False
- for ext in _constants.USD_EXTENSIONS:
- if replacement_layer_path.endswith(ext):
- valid_ext = True
- break
- if not valid_ext:
- carb.log_error(
- "Wrong replacement layer path extension. Your path should end with '.usd' or '.usda' or '.usdc'"
- )
- return False
- pat = re.compile(r"[A-Za-z.0-9\s_-]*")
- if not re.fullmatch(pat, os.path.basename(replacement_layer_path.strip())):
- carb.log_error("Special character are forbidden for the replacement layer path")
- return False
- if self.get_current_use_existing_layer():
- # check if this is writable
- result, entry = omni.client.stat(replacement_layer_path)
- if (
- result != omni.client.Result.OK
- or not entry.flags & omni.client.ItemFlags.WRITEABLE_FILE
- or not entry.flags & omni.client.ItemFlags.READABLE_FILE
- ):
- carb.log_error("Can't override the existing replacement layer. File is not writeable.")
- return False
- return True
diff --git a/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/new_core.py b/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/new_core.py
deleted file mode 100644
index 0f6a01f96..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/new_core.py
+++ /dev/null
@@ -1,180 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-import functools
-import typing
-
-import carb.settings
-import omni.kit.commands
-import omni.kit.window.file
-import omni.usd
-from lightspeed.layer_manager.core import LSS_LAYER_GAME_NAME, LayerManagerCore, LayerType
-from omni.kit.usd.layers import LayerUtils
-from omni.usd import handle_exception
-
-if typing.TYPE_CHECKING:
- from lightspeed.widget.content_viewer.scripts.core import ContentData
-
-from pxr import Sdf, Usd, UsdGeom
-
-
-class NewGameWorkspaceCore:
- def __init__(self):
- self.__default_attr = {"_stage_event_sub": None}
- for attr, value in self.__default_attr.items():
- setattr(self, attr, value)
-
- self._layer_manager = LayerManagerCore()
-
- self.__fns_to_execute_on_event = []
-
- @handle_exception
- async def ___deferred_setup_persepctive_camera(self):
- await omni.kit.app.get_app().next_update_async()
-
- # setup the session camera to match the capture camera
- stage = omni.usd.get_context().get_stage()
- capture_layer = self._layer_manager.get_layer(LayerType.capture)
- if capture_layer is None:
- carb.log_warn("Can't find a capture layer, won't be setting up the default camera to match game")
- return
- session_layer = stage.GetSessionLayer()
- current_edit_layer = Sdf.Find(LayerUtils.get_edit_target(stage))
- swap_edit_targets = current_edit_layer != session_layer
- try:
- if swap_edit_targets:
- LayerUtils.set_edit_target(stage, session_layer.identifier)
-
- carb.log_info("Setting up perspective camera from capture")
- Sdf.CopySpec(capture_layer, "/RootNode/Camera", session_layer, "/OmniverseKit_Persp")
- finally:
- if swap_edit_targets:
- LayerUtils.set_edit_target(stage, current_edit_layer.identifier)
-
- def load_game_workspace(self, path, callback=None):
- context = omni.usd.get_context()
- context.new_stage_with_callback(functools.partial(self.__load_game_workspace, path, callback=callback))
-
- def __load_game_workspace(self, path, result: bool, error: str, callback=None):
- if callback:
- self.__fns_to_execute_on_event.append(callback)
- # Crash, use omni.kit.window.file.open_stage
- # context = omni.usd.get_context()
- # context.open_stage(path)
- omni.kit.window.file.open_stage(path)
- self._layer_manager.set_edit_target_layer(LayerType.replacement)
- asyncio.ensure_future(self.___deferred_setup_persepctive_camera())
-
- def create_game_workspace(
- self, capture_data, use_existing_layer, existing_enhancement_layer_path, game, callback=None
- ):
- context = omni.usd.get_context()
- context.new_stage_with_callback(
- functools.partial(
- self.__create_game_workspace,
- capture_data,
- use_existing_layer,
- existing_enhancement_layer_path,
- game,
- callback=callback,
- )
- )
-
- def __copy_metadata_from_stage_to_stage(self, stage_source, stage_destination):
- # copy over layer-meta-data from capture layer
- UsdGeom.SetStageUpAxis(stage_destination, UsdGeom.GetStageUpAxis(stage_source))
- UsdGeom.SetStageMetersPerUnit(stage_destination, UsdGeom.GetStageMetersPerUnit(stage_source))
- time_codes = stage_source.GetTimeCodesPerSecond()
- stage_destination.SetTimeCodesPerSecond(time_codes)
-
- def __create_game_workspace(
- self,
- capture_data: "ContentData",
- use_existing_layer: bool,
- enhancement_layer_path: str,
- game: "ContentData",
- result: bool,
- error: str,
- callback=None,
- ):
- if callback:
- self.__fns_to_execute_on_event.append(callback)
- self._setup_stage_event()
- carb.log_info("Create game workspace")
-
- # copy over layer-meta-data from capture layer
- stage = omni.usd.get_context().get_stage()
- capture_stage = Usd.Stage.Open(capture_data.path)
- self.__copy_metadata_from_stage_to_stage(capture_stage, stage)
-
- # add the capture layer
- self._layer_manager.insert_sublayer(capture_data.path, LayerType.capture, add_custom_layer_data=False)
- self._layer_manager.lock_layer(LayerType.capture)
- asyncio.ensure_future(self.___deferred_setup_persepctive_camera())
-
- # add the replacement layer if exist
- if use_existing_layer:
- self._layer_manager.insert_sublayer(
- enhancement_layer_path, LayerType.replacement, sublayer_insert_position=0
- )
- else: # if not, we create it
- layer = self._layer_manager.create_new_sublayer(
- LayerType.replacement, path=enhancement_layer_path, sublayer_create_position=0
- )
- # replacement layer needs to have the same TimeCodesPerSecond as the capture layer
- # for reference deletion to work. See OM-42663 for more info.
- time_codes = capture_stage.GetTimeCodesPerSecond()
- replacement_stage = Usd.Stage.Open(layer.realPath)
- replacement_stage.SetTimeCodesPerSecond(time_codes)
- replacement_stage.Save()
- layer_instance = self._layer_manager.get_layer_instance(LayerType.replacement)
- if layer_instance is None:
- carb.log_error(f"Can't find a layer schema type {LayerType.replacement.value}")
- return
- layer_instance.set_custom_layer_data({LSS_LAYER_GAME_NAME: game.title})
-
- def _setup_stage_event(self):
- """We listen to stage event when we are running but turn it off otherwise"""
- self._stage_event_sub = (
- omni.usd.get_context()
- .get_stage_event_stream()
- .create_subscription_to_pop(self._on_stage_event, name="Load Game Workspace Core")
- )
-
- def _on_stage_event(self, event):
- if event.type == int(omni.usd.StageEventType.ASSETS_LOADED):
- if self.__fns_to_execute_on_event:
- for fn_to_execute_on_event in self.__fns_to_execute_on_event:
- fn_to_execute_on_event()
- self._stage_event_sub = None
- self.__fns_to_execute_on_event = []
-
- def destroy(self):
- self.__fns_to_execute_on_event = []
- for attr, value in self.__default_attr.items():
- m_attr = getattr(self, attr)
- if isinstance(m_attr, list):
- m_attrs = m_attr
- else:
- m_attrs = [m_attr]
- for m_attr in m_attrs:
- destroy = getattr(m_attr, "destroy", None)
- if callable(destroy):
- destroy()
- del m_attr
- setattr(self, attr, value)
diff --git a/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/ui.py b/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/ui.py
deleted file mode 100644
index c75375dca..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/ui.py
+++ /dev/null
@@ -1,170 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 pathlib import Path
-
-import omni.ui as ui # TODO: menu, switch to the new method when Kit switched
-from lightspeed.widget.game_captures.scripts.ui import GameCapturesViewer
-from lightspeed.widget.game_captures.scripts.utils import get_captures_directory
-from omni.flux.utils.widget.file_pickers.file_picker import open_file_picker as _open_file_picker
-
-from .utils import ReplacementPathUtils
-
-
-class GameWorkspaceViewer(GameCapturesViewer):
- @property
- def default_attr(self):
- result = super().default_attr
- result.update(
- {
- "_use_existing_layer": None,
- "_replacement_layer_usd_field": None,
- "_enhancement_layer_usd_path_label": None,
- }
- )
- return result
-
- @property
- def style(self):
- style = super().style
- style.update(
- {
- "Image::SavePath": {"color": 0x90FFFFFF},
- "Image::SavePath:hovered": {"color": 0xFFFFFFFF},
- "Rectangle::SubBackground1": {
- "background_color": 0x00333333,
- "border_width": 1.0,
- "border_color": 0x20FFFFFF,
- },
- }
- )
- return style
-
- def create_ui(self):
- """Create the main UI"""
- with ui.Frame(style=self.style):
- with ui.VStack():
- super().create_ui()
- with ui.ZStack(height=0):
- ui.Rectangle(name="SubBackground0")
- with ui.VStack():
- ui.Spacer(height=8)
- with ui.HStack():
- ui.Spacer(width=8)
- with ui.VStack(spacing=8):
- row_height = 24
- sub_width = ui.Pixel(50)
- sub_label_width = ui.Pixel(100)
- with ui.ZStack(height=0):
- ui.Rectangle(name="SubBackground1")
- with ui.VStack():
- ui.Spacer(height=8)
- with ui.HStack():
- ui.Spacer(width=8)
- with ui.VStack(spacing=8):
- with ui.HStack(height=row_height):
- ui.Label(
- "Use existing enhancements layer",
- tooltip=(
- "If true, you can import an existing " "enhancements layer."
- ),
- )
- self._use_existing_layer = ui.RadioCollection(width=36)
- ui.RadioButton(radio_collection=self._use_existing_layer, text="No")
- ui.RadioButton(
- radio_collection=self._use_existing_layer, text="Yes"
- )
- self._use_existing_layer.model.add_value_changed_fn(
- self.__update_use_existing_layer
- )
-
- with ui.VStack(spacing=8):
- with ui.HStack(height=row_height, spacing=8):
- ui.Spacer(width=sub_width)
- self._enhancement_layer_usd_path_label = ui.Label(
- "USD Path to create", width=sub_label_width
- )
- self._replacement_layer_usd_field = ui.StringField()
- self._replacement_layer_usd_field.model.add_value_changed_fn(
- self.__update_replacement_layer_usd_field
- )
- ui.Image(
- str(
- self._get_icon_path(
- "folder_open", from_base_extension=False
- )
- ),
- width=row_height,
- name="SavePath",
- mouse_released_fn=lambda x, y, b, m: self._on_existing_layer_usd_file( # noqa E501
- b, m
- ),
- )
-
- ui.Spacer(width=8)
- ui.Spacer(height=8)
-
- ui.Spacer(width=8)
- ui.Spacer(height=8)
-
- def __update_use_existing_layer(self, value_model):
- value = self._use_existing_layer.model.get_value_as_bool()
- self._core.set_current_use_existing_layer(value)
- self._enhancement_layer_usd_path_label.text = "USD Path to read" if value else "USD Path to create"
-
- def __update_replacement_layer_usd_field(self, value_model):
- value = self._replacement_layer_usd_field.model.get_value_as_string()
- self._core.set_current_replacement_layer_usd_path(value if value else None)
- current_game = self._core.get_current_game_capture_folder()
- replacement_path_utils = ReplacementPathUtils()
- replacement_path_utils.append_path_to_recent_file(value, current_game.title)
-
- def _on_existing_layer_usd_file(self, b, m):
- if b != 0:
- return
-
- current_game = self._core.get_current_game_capture_folder()
- captures_dir = get_captures_directory(current_game)
- replacement_path_utils = ReplacementPathUtils()
- data = replacement_path_utils.get_recent_file_data()
- if current_game.title in data:
- current_directory = str(Path(data[current_game.title]["last_path"]).resolve().parent)
- else:
- current_directory = captures_dir
-
- bookmarks = {current_game.title: str(Path(current_game.path).resolve().parent)}
-
- _open_file_picker(
- "Directory picker",
- self._set_existing_layer_usd_str_field,
- lambda *args: None,
- current_file=current_directory,
- select_directory=True,
- bookmarks=bookmarks,
- )
-
- def _set_existing_layer_usd_str_field(self, path):
- if not path:
- return
- self._replacement_layer_usd_field.model.set_value(path)
-
- @property
- def calling_extension_path(self):
- current_path = Path(__file__).parent
- for _ in range(4):
- current_path = current_path.parent
- return current_path
diff --git a/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/utils.py b/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/utils.py
deleted file mode 100644
index efd771afb..000000000
--- a/source/extensions/lightspeed.widget.new_workspace/python/lightspeed/widget/new_workspace/scripts/utils.py
+++ /dev/null
@@ -1,78 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import json
-from pathlib import Path
-
-import carb
-import carb.tokens
-
-
-class ReplacementPathUtils:
- def __get_recent_dir(self) -> str:
- """Return the file"""
- token = carb.tokens.get_tokens_interface()
- directory = token.resolve("${app_documents}")
- # FilePickerDialog needs the capital drive. In case it's linux, the
- # first letter will be / and it's still OK.
- return str(Path(directory[:1].upper() + directory[1:]).resolve())
-
- def __get_recent_file(self) -> str:
- """Return the file"""
- directory = self.__get_recent_dir()
- return f"{directory}/recent_replacement_paths.json"
-
- def save_recent_file(self, data):
- """Save the recent work files to the file"""
- file_path = self.__get_recent_file()
- with open(file_path, "w", encoding="utf-8") as json_file:
- json.dump(data, json_file, indent=2)
-
- carb.log_info(f"Recent replacement paths file tracker saved to {file_path}")
-
- def append_path_to_recent_file(self, last_path: str, game: str, save: bool = True):
- """Append a work file path to file"""
- current_data = self.get_recent_file_data()
-
- if game in current_data:
- del current_data[game]
- current_data[game] = {"last_path": last_path}
- current_data_max = list(current_data.keys())[:40]
-
- result = {}
- for current_path, current_data in current_data.items(): # noqa B020
- if current_path in current_data_max:
- result[current_path] = current_data # noqa B020
- if save:
- self.save_recent_file(result)
- return result
-
- def is_recent_file_exist(self):
- file_path = self.__get_recent_file()
- if not Path(file_path).exists():
- carb.log_info(f"Recent replacement paths file tracker doesn't exist: {file_path}")
- return False
- return True
-
- def get_recent_file_data(self):
- """Load the recent work files from the file"""
- if not self.is_recent_file_exist():
- return {}
- file_path = self.__get_recent_file()
- carb.log_info(f"Get recent replacement paths file(s) from {file_path}")
- with open(file_path, encoding="utf-8") as json_file:
- return json.load(json_file)
diff --git a/source/extensions/lightspeed.workspace/config/extension.toml b/source/extensions/lightspeed.workspace/config/extension.toml
deleted file mode 100644
index e5a69c4ee..000000000
--- a/source/extensions/lightspeed.workspace/config/extension.toml
+++ /dev/null
@@ -1,43 +0,0 @@
-[package]
-# Semantic Versionning is used: https://semver.org/
-version = "0.1.3"
-
-# Lists people or organizations that are considered the "authors" of the package.
-authors = ["Alex Dunn ", "Damien Bataille "]
-
-# The title and description fields are primarly for displaying extension info in UI
-title = "Lightspeed App Workspace"
-description="Set the workspace of the application."
-
-# Path (relative to the root) or content of readme markdown file for UI.
-readme = "docs/README.md"
-
-# URL of the extension source repository.
-repository="https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed.workspace"
-
-# One of categories for UI.
-category = "internal"
-
-# Keywords for the extension
-keywords = ["lightspeed", "workspace"]
-
-# Location of change log file in target (final) folder of extension, relative to the root.
-# More info on writing changelog: https://keepachangelog.com/en/1.0.0/
-changelog="docs/CHANGELOG.md"
-
-# Preview image and icon. Folder named "data" automatically goes in git lfs (see .gitattributes file).
-# Preview image is shown in "Overview" of Extensions window. Screenshot of an extension might be a good preview image.
-preview_image = "data/preview.png"
-
-# Icon is shown in Extensions window, it is recommended to be square, of size 256x256.
-icon = "data/icon.png"
-
-[dependencies]
-"omni.kit.mainwindow" = {}
-"omni.client" = {}
-"omni.ui" = {}
-"omni.kit.window.toolbar" = {}
-
-# Main python module this extension provides, it will be publicly available as "import omni.example.hello".
-[[python.module]]
-name = "lightspeed.workspace"
diff --git a/source/extensions/lightspeed.workspace/data/icon.png b/source/extensions/lightspeed.workspace/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed.workspace/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed.workspace/data/layout.default.json b/source/extensions/lightspeed.workspace/data/layout.default.json
deleted file mode 100644
index 5c7ab128f..000000000
--- a/source/extensions/lightspeed.workspace/data/layout.default.json
+++ /dev/null
@@ -1,361 +0,0 @@
-[
- {
- "dock_id": 3358485147,
- "children": [
- {
- "dock_id": 1,
- "position": "LEFT",
- "children": [
- {
- "dock_id": 3,
- "position": "TOP",
- "children": [
- {
- "title": "Main ToolBar",
- "width": 400.0,
- "height": 600.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": true,
- "selected_in_dock": false
- }
- ]
- },
- {
- "dock_id": 4,
- "position": "BOTTOM",
- "children": [
- {
- "dock_id": 5,
- "position": "TOP",
- "children": [
- {
- "title": "Viewport",
- "width": 1433.0,
- "height": 713.0,
- "position_x": 0.0,
- "position_y": 74.0,
- "dock_id": 0,
- "visible": true,
- "selected_in_dock": false
- }
- ]
- },
- {
- "dock_id": 6,
- "position": "BOTTOM",
- "children": [
- {
- "title": "Console",
- "width": 1433.0,
- "height": 314.0,
- "position_x": 0.0,
- "position_y": 791.0,
- "dock_id": 6,
- "visible": true,
- "selected_in_dock": false
- },
- {
- "title": "Content",
- "width": 1433.0,
- "height": 314.0,
- "position_x": 0.0,
- "position_y": 791.0,
- "dock_id": 6,
- "visible": true,
- "selected_in_dock": true,
- "dock_tab_bar_visible": true,
- "dock_tab_bar_enabled": true
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "dock_id": 2,
- "position": "RIGHT",
- "children": [
- {
- "dock_id": 7,
- "position": "TOP",
- "children": [
- {
- "title": "Stage",
- "width": 483.0,
- "height": 538.0,
- "position_x": 1437.0,
- "position_y": 26.0,
- "dock_id": 7,
- "visible": true,
- "selected_in_dock": true,
- "dock_tab_bar_visible": true,
- "dock_tab_bar_enabled": true
- },
- {
- "title": "Layer",
- "width": 483.0,
- "height": 538.0,
- "position_x": 1456.0,
- "position_y": 26.0,
- "dock_id": 7,
- "visible": true,
- "selected_in_dock": false
- },
- {
- "title": "Render Settings",
- "width": 483.0,
- "height": 538.0,
- "position_x": 60.0,
- "position_y": 60.0,
- "dock_id": 7,
- "visible": true,
- "selected_in_dock": false
- }
- ]
- },
- {
- "dock_id": 8,
- "position": "BOTTOM",
- "children": [
- {
- "title": "Property",
- "width": 483.0,
- "height": 537.0,
- "position_x": 1437.0,
- "position_y": 568.0,
- "dock_id": 8,
- "visible": true,
- "selected_in_dock": true,
- "dock_tab_bar_visible": true,
- "dock_tab_bar_enabled": true
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "title": "Lightspeed Welcome",
- "width": 1056.0,
- "height": 812.0,
- "position_x": 432.0,
- "position_y": 162.0,
- "dock_id": 0,
- "visible": true,
- "selected_in_dock": false
- },
- {
- "title": "Open File",
- "width": 1000.0,
- "height": 600.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Options",
- "width": 220.0,
- "height": 0.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Form Dialog",
- "width": 400.0,
- "height": 0.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Save File As...",
- "width": 1000.0,
- "height": 600.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Create Edit Layer",
- "width": 1000.0,
- "height": 600.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Filter",
- "width": 150.0,
- "height": 0.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Add Attribute...",
- "width": 400.0,
- "height": 600.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Select Reference...",
- "width": 1000.0,
- "height": 600.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Select Payload...",
- "width": 1000.0,
- "height": 600.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Select Asset...",
- "width": 1000.0,
- "height": 600.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Asset details",
- "width": 404.0,
- "height": 600.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Image bigger",
- "width": 400.0,
- "height": 400.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Loading",
- "width": 300.0,
- "height": 100.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Captured Traces Browser",
- "width": 800.0,
- "height": 710.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Snap Increment Settings Menu",
- "width": 400.0,
- "height": 0.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Lightspeed Capture Swapper",
- "width": 1056.0,
- "height": 812.3076782226562,
- "position_x": 432.0,
- "position_y": 162.34616088867188,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Preferences",
- "width": 1000.0,
- "height": 600.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Select Screenshot Directory",
- "width": 1000.0,
- "height": 600.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Select Template",
- "width": 1000.0,
- "height": 600.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Select Filename (Local Files Only)",
- "width": 1000.0,
- "height": 600.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- },
- {
- "title": "Statistics",
- "width": 400.0,
- "height": 600.0,
- "position_x": 3.4028234663852886e+38,
- "position_y": 3.4028234663852886e+38,
- "dock_id": 0,
- "visible": false,
- "selected_in_dock": false
- }
-]
diff --git a/source/extensions/lightspeed.workspace/data/preview.png b/source/extensions/lightspeed.workspace/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed.workspace/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed.workspace/docs/CHANGELOG.md b/source/extensions/lightspeed.workspace/docs/CHANGELOG.md
deleted file mode 100644
index ba14f8531..000000000
--- a/source/extensions/lightspeed.workspace/docs/CHANGELOG.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.3]
-### Changed
-- Changed repo link
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed.workspace/docs/README.md b/source/extensions/lightspeed.workspace/docs/README.md
deleted file mode 100644
index 1416f860b..000000000
--- a/source/extensions/lightspeed.workspace/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed.workspace
diff --git a/source/extensions/lightspeed.workspace/docs/index.rst b/source/extensions/lightspeed.workspace/docs/index.rst
deleted file mode 100644
index c588b85a7..000000000
--- a/source/extensions/lightspeed.workspace/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed.workspace
-###########################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed.workspace
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed.workspace/premake5.lua b/source/extensions/lightspeed.workspace/premake5.lua
deleted file mode 100644
index 8767ca6f3..000000000
--- a/source/extensions/lightspeed.workspace/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- { "python/lightspeed", ext.target_dir.."/lightspeed" },
-}
diff --git a/source/extensions/lightspeed.workspace/python/lightspeed/workspace/__init__.py b/source/extensions/lightspeed.workspace/python/lightspeed/workspace/__init__.py
deleted file mode 100644
index e45cb62b2..000000000
--- a/source/extensions/lightspeed.workspace/python/lightspeed/workspace/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .extension import *
diff --git a/source/extensions/lightspeed.workspace/python/lightspeed/workspace/extension.py b/source/extensions/lightspeed.workspace/python/lightspeed/workspace/extension.py
deleted file mode 100644
index 51894aa50..000000000
--- a/source/extensions/lightspeed.workspace/python/lightspeed/workspace/extension.py
+++ /dev/null
@@ -1,121 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import asyncio
-import json
-
-import carb
-import omni.client
-import omni.ext
-import omni.kit.app
-import omni.kit.window.toolbar
-import omni.ui as ui
-
-_INSTANCE = None
-
-
-class LightspeedWorkspace:
- class _Event(set):
- """
- A list of callable objects. Calling an instance of this will cause a
- call to each item in the list in ascending order by index.
- """
-
- def __call__(self, *args, **kwargs):
- """Called when the instance is “called” as a function"""
- # Call all the saved functions
- for f in self:
- f(*args, **kwargs)
-
- def __repr__(self):
- """
- Called by the repr() built-in function to compute the “official”
- string representation of an object.
- """
- return f"Event({set.__repr__(self)})"
-
- class _EventSubscription:
- """
- Event subscription.
-
- _Event has callback while this object exists.
- """
-
- def __init__(self, event, fn):
- """
- Save the function, the event, and add the function to the event.
- """
- self._fn = fn
- self._event = event
- event.add(self._fn)
-
- def __del__(self):
- """Called by GC."""
- self._event.remove(self._fn)
-
- def __init__(self, extension_path):
- self._extension_path = extension_path
- self.__on_workspace_restored = self._Event()
-
- def _workspace_restored(self):
- """Call the event object that has the list of functions"""
- self.__on_workspace_restored()
-
- def subscribe_workspace_restored(self, fn):
- """
- Return the object that will automatically unsubscribe when destroyed.
- Called when we click on a tool (change of the selected tool)
- """
- return self._EventSubscription(self.__on_workspace_restored, fn)
-
- def setup_workspace(self):
- workspace_file = f"{self._extension_path}/data/layout.default.json"
-
- result, _, content = omni.client.read_file(workspace_file)
-
- if result != omni.client.Result.OK:
- carb.log_error(f"Can't read the workspace file {workspace_file}, error code: {result}")
- return
-
- data = json.loads(memoryview(content).tobytes().decode("utf-8"))
- asyncio.ensure_future(self._load_layout(data))
-
- async def _load_layout(self, data):
- # few frames delay to avoid the conflict with the layout of omni.kit.mainwindow
- for _ in range(3):
- await omni.kit.app.get_app().next_update_async()
-
- ui.Workspace.restore_workspace(data)
- await omni.kit.app.get_app().next_update_async()
- self._workspace_restored()
-
-
-class LightspeedWorkspaceExtension(omni.ext.IExt):
- def on_startup(self, ext_id):
- carb.log_info("[lightspeed.workspace] Lightspeed Workspace startup")
- # first set up the layout
- extension_path = omni.kit.app.get_app().get_extension_manager().get_extension_path(ext_id)
- global _INSTANCE
- _INSTANCE = LightspeedWorkspace(extension_path)
- _INSTANCE.setup_workspace()
-
- def on_shutdown(self):
- carb.log_info("[lightspeed.workspace] Lightspeed Workspace shutdown")
-
-
-def get_instance():
- return _INSTANCE # noqa R504
diff --git a/source/extensions/lightspeed_example.app.resources/config/extension.toml b/source/extensions/lightspeed_example.app.resources/config/extension.toml
deleted file mode 100644
index d2b3c6f88..000000000
--- a/source/extensions/lightspeed_example.app.resources/config/extension.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-title = "Resources extension"
-description = "This Extension contains resources (images, icons) used by the app and splash screen."
-changelog = "docs/CHANGELOG.md"
-readme = "docs/README.md"
-icon = "data/icon.png"
-preview_image = "data/preview.png"
-authors = [ "Damien Bataille ",]
-version = "1.0.2"
-repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed_example.app.resources"
-category = "example"
-keywords = [ "remix",]
diff --git a/source/extensions/lightspeed_example.app.resources/data/icon.png b/source/extensions/lightspeed_example.app.resources/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed_example.app.resources/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed_example.app.resources/data/icons/account-circle.svg b/source/extensions/lightspeed_example.app.resources/data/icons/account-circle.svg
deleted file mode 100644
index 8886ba6f4..000000000
--- a/source/extensions/lightspeed_example.app.resources/data/icons/account-circle.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:1b550a26bd54d2bf8534d6228c47d0503d0eb3a1d74ba7eac209c0f49d4192eb
-size 505
diff --git a/source/extensions/lightspeed_example.app.resources/data/preview.png b/source/extensions/lightspeed_example.app.resources/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed_example.app.resources/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed_example.app.resources/docs/CHANGELOG.md b/source/extensions/lightspeed_example.app.resources/docs/CHANGELOG.md
deleted file mode 100644
index 449bc556e..000000000
--- a/source/extensions/lightspeed_example.app.resources/docs/CHANGELOG.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [1.0.2]
-### Changed
-- Changed repo link
-
-## [1.0.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed_example.app.resources/docs/README.md b/source/extensions/lightspeed_example.app.resources/docs/README.md
deleted file mode 100644
index cc46f22e9..000000000
--- a/source/extensions/lightspeed_example.app.resources/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed_example.app.resources
diff --git a/source/extensions/lightspeed_example.app.resources/docs/index.rst b/source/extensions/lightspeed_example.app.resources/docs/index.rst
deleted file mode 100644
index a28fcaf02..000000000
--- a/source/extensions/lightspeed_example.app.resources/docs/index.rst
+++ /dev/null
@@ -1,9 +0,0 @@
-lightspeed_example.app.resources
-################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
diff --git a/source/extensions/lightspeed_example.app.resources/premake5.lua b/source/extensions/lightspeed_example.app.resources/premake5.lua
deleted file mode 100644
index 2146b39c1..000000000
--- a/source/extensions/lightspeed_example.app.resources/premake5.lua
+++ /dev/null
@@ -1,10 +0,0 @@
--- Use folder name to build extension name and tag.
-local ext = get_current_extension_info()
-
-project_ext (ext)
-
--- Link only those files and folders into the extension target directory
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
-}
diff --git a/source/extensions/lightspeed_example.my_name.controller/config/extension.toml b/source/extensions/lightspeed_example.my_name.controller/config/extension.toml
deleted file mode 100644
index b279c89fb..000000000
--- a/source/extensions/lightspeed_example.my_name.controller/config/extension.toml
+++ /dev/null
@@ -1,21 +0,0 @@
-[package]
-version = "0.1.2"
-authors = ["dbataille@nvidia.com"]
-repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit"
-keywords = ["my_name"]
-title = "My Name"
-description = "My name is a cool extension"
-category = "example"
-changelog = "docs/CHANGELOG.md"
-readme = "docs/README.md"
-icon = "data/icon.png"
-preview_image = "data/preview.png"
-
-
-[dependencies]
-"lightspeed_example.my_name.core" = {}
-"lightspeed_example.my_name.menu" = {}
-"lightspeed_example.my_name.window" = {}
-
-[[python.module]]
-name = "lightspeed_example.my_name.controller"
diff --git a/source/extensions/lightspeed_example.my_name.controller/data/icon.png b/source/extensions/lightspeed_example.my_name.controller/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed_example.my_name.controller/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed_example.my_name.controller/data/preview.png b/source/extensions/lightspeed_example.my_name.controller/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed_example.my_name.controller/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed_example.my_name.controller/docs/CHANGELOG.md b/source/extensions/lightspeed_example.my_name.controller/docs/CHANGELOG.md
deleted file mode 100644
index 96a5c1394..000000000
--- a/source/extensions/lightspeed_example.my_name.controller/docs/CHANGELOG.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed_example.my_name.controller/docs/README.md b/source/extensions/lightspeed_example.my_name.controller/docs/README.md
deleted file mode 100644
index f5ea570ea..000000000
--- a/source/extensions/lightspeed_example.my_name.controller/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed_example.my_name.controller
diff --git a/source/extensions/lightspeed_example.my_name.controller/docs/index.rst b/source/extensions/lightspeed_example.my_name.controller/docs/index.rst
deleted file mode 100644
index 2750564cf..000000000
--- a/source/extensions/lightspeed_example.my_name.controller/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed_example.my_name.controller
-######################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed_example.my_name.controller
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed_example.my_name.controller/lightspeed_example/my_name/controller/__init__.py b/source/extensions/lightspeed_example.my_name.controller/lightspeed_example/my_name/controller/__init__.py
deleted file mode 100644
index 5fc560efe..000000000
--- a/source/extensions/lightspeed_example.my_name.controller/lightspeed_example/my_name/controller/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .extension import * # noqa F401
diff --git a/source/extensions/lightspeed_example.my_name.controller/lightspeed_example/my_name/controller/extension.py b/source/extensions/lightspeed_example.my_name.controller/lightspeed_example/my_name/controller/extension.py
deleted file mode 100644
index e40990cd7..000000000
--- a/source/extensions/lightspeed_example.my_name.controller/lightspeed_example/my_name/controller/extension.py
+++ /dev/null
@@ -1,61 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import carb
-import omni.ext
-
-from .my_name import MyName
-
-_INSTANCE = None
-
-
-def get_instance():
- """Expose the created instance of the tool"""
- return _INSTANCE
-
-
-class MyNameExtension(omni.ext.IExt):
- """Standard extension support class, necessary for extension management"""
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.default_attr = {}
- for attr, value in self.default_attr.items():
- setattr(self, attr, value)
-
- def on_startup(self, ext_id):
- global _INSTANCE
- carb.log_info("[lightspeed_example.my_name] startup")
- _INSTANCE = MyName()
-
- def on_shutdown(self):
- global _INSTANCE
- carb.log_info("[lightspeed_example.my_name] shutdown")
- for attr, value in self.default_attr.items():
- m_attr = getattr(self, attr)
- if isinstance(m_attr, list):
- m_attrs = m_attr
- else:
- m_attrs = [m_attr]
- for m_attr in m_attrs:
- destroy = getattr(m_attr, "destroy", None)
- if callable(destroy):
- destroy()
- del m_attr
- setattr(self, attr, value)
- _INSTANCE.destroy()
- _INSTANCE = None
diff --git a/source/extensions/lightspeed_example.my_name.controller/lightspeed_example/my_name/controller/my_name.py b/source/extensions/lightspeed_example.my_name.controller/lightspeed_example/my_name/controller/my_name.py
deleted file mode 100644
index 9e421c072..000000000
--- a/source/extensions/lightspeed_example.my_name.controller/lightspeed_example/my_name/controller/my_name.py
+++ /dev/null
@@ -1,81 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 lightspeed_example.my_name.core import create_core
-from lightspeed_example.my_name.menu import create_menu
-from lightspeed_example.my_name.window import create_window
-
-
-class MyName:
- def __init__(self):
- self.__default_attr = {
- "_core": None,
- "_window_setup": None,
- "_menu_setup": None,
- "_subscribe_button1_clicked": None,
- "_subscribe_button2_clicked": None,
- "_subscribe_menu1_clicked": None,
- "_subscribe_menu2_clicked": None,
- }
- for attr, value in self.__default_attr.items():
- setattr(self, attr, value)
-
- self._core = create_core()
-
- self.__create_ui()
- self.__create_menu()
-
- def __create_ui(self):
- """Create the main UI"""
- self._window_setup = create_window()
- self._subscribe_button1_clicked = self._window_setup.widget.subscribe_button1_clicked(self._on_button1_clicked)
- self._subscribe_button2_clicked = self._window_setup.widget.subscribe_button2_clicked(self._on_button2_clicked)
-
- def _on_button1_clicked(self):
- self._core.print_hello_1()
-
- def _on_button2_clicked(self):
- self._core.print_hello_2()
-
- def __create_menu(self):
- self._menu_setup = create_menu()
- self._subscribe_menu1_clicked = self._menu_setup.subscribe_menu1_clicked(self._on_menu1_clicked)
- self._subscribe_menu2_clicked = self._menu_setup.subscribe_menu2_clicked(self._on_menu2_clicked)
-
- def _on_menu1_clicked(self):
- self._toggle_window()
-
- def _on_menu2_clicked(self):
- print("menu2 clicked!")
-
- def _toggle_window(self):
- if self._window_setup.window:
- self._window_setup.window.visible = not self._window_setup.window.visible
-
- def destroy(self):
- for attr, value in self.__default_attr.items():
- m_attr = getattr(self, attr)
- if isinstance(m_attr, list):
- m_attrs = m_attr
- else:
- m_attrs = [m_attr]
- for m_attr in m_attrs:
- destroy = getattr(m_attr, "destroy", None)
- if callable(destroy):
- destroy()
- del m_attr
- setattr(self, attr, value)
diff --git a/source/extensions/lightspeed_example.my_name.controller/premake5.lua b/source/extensions/lightspeed_example.my_name.controller/premake5.lua
deleted file mode 100644
index fc8b80d90..000000000
--- a/source/extensions/lightspeed_example.my_name.controller/premake5.lua
+++ /dev/null
@@ -1,9 +0,0 @@
-local ext = get_current_extension_info()
-
-project_ext (ext)
-
-repo_build.prebuild_link {
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
- {"lightspeed_example/", ext.target_dir.."/lightspeed_example"},
-}
diff --git a/source/extensions/lightspeed_example.my_name.core/config/extension.toml b/source/extensions/lightspeed_example.my_name.core/config/extension.toml
deleted file mode 100644
index 1d5485741..000000000
--- a/source/extensions/lightspeed_example.my_name.core/config/extension.toml
+++ /dev/null
@@ -1,15 +0,0 @@
-[package]
-title = "Extension example to create the core"
-description = "This is the core example"
-changelog = "docs/CHANGELOG.md"
-readme = "docs/README.md"
-version = "1.0.3"
-authors = [ "Damien Bataille ",]
-repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed_example.my_name.core"
-category = "example"
-keywords = [ "remix",]
-preview_image = "data/preview.png"
-icon = "data/icon.png"
-
-[[python.module]]
-name = "lightspeed_example.my_name.core"
diff --git a/source/extensions/lightspeed_example.my_name.core/data/icon.png b/source/extensions/lightspeed_example.my_name.core/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed_example.my_name.core/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed_example.my_name.core/data/preview.png b/source/extensions/lightspeed_example.my_name.core/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed_example.my_name.core/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed_example.my_name.core/docs/CHANGELOG.md b/source/extensions/lightspeed_example.my_name.core/docs/CHANGELOG.md
deleted file mode 100644
index d711e5075..000000000
--- a/source/extensions/lightspeed_example.my_name.core/docs/CHANGELOG.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [1.0.3]
-### Changed
-- Changed repo link
-
-## [1.0.2]
-### Changed
-- Update to Kit 106
-
-## [1.0.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed_example.my_name.core/docs/README.md b/source/extensions/lightspeed_example.my_name.core/docs/README.md
deleted file mode 100644
index 41228e531..000000000
--- a/source/extensions/lightspeed_example.my_name.core/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed_example.my_name.core
diff --git a/source/extensions/lightspeed_example.my_name.core/docs/index.rst b/source/extensions/lightspeed_example.my_name.core/docs/index.rst
deleted file mode 100644
index d5fdb202f..000000000
--- a/source/extensions/lightspeed_example.my_name.core/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed_example.my_name.core
-################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed_example.my_name.core
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed_example.my_name.core/lightspeed_example/my_name/core/__init__.py b/source/extensions/lightspeed_example.my_name.core/lightspeed_example/my_name/core/__init__.py
deleted file mode 100644
index a00cd3496..000000000
--- a/source/extensions/lightspeed_example.my_name.core/lightspeed_example/my_name/core/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .core import create_core # noqa F401
diff --git a/source/extensions/lightspeed_example.my_name.core/lightspeed_example/my_name/core/core.py b/source/extensions/lightspeed_example.my_name.core/lightspeed_example/my_name/core/core.py
deleted file mode 100644
index fca4ea817..000000000
--- a/source/extensions/lightspeed_example.my_name.core/lightspeed_example/my_name/core/core.py
+++ /dev/null
@@ -1,28 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-
-class _SetupCore:
- def print_hello_1(self):
- print("Hello 1")
-
- def print_hello_2(self):
- print("Hello 2")
-
-
-def create_core():
- return _SetupCore()
diff --git a/source/extensions/lightspeed_example.my_name.core/premake5.lua b/source/extensions/lightspeed_example.my_name.core/premake5.lua
deleted file mode 100644
index b0aac3e04..000000000
--- a/source/extensions/lightspeed_example.my_name.core/premake5.lua
+++ /dev/null
@@ -1,11 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- {"lightspeed_example/", ext.target_dir.."/lightspeed_example"},
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
-}
-
diff --git a/source/extensions/lightspeed_example.my_name.menu/config/extension.toml b/source/extensions/lightspeed_example.my_name.menu/config/extension.toml
deleted file mode 100644
index 753ae62fb..000000000
--- a/source/extensions/lightspeed_example.my_name.menu/config/extension.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[package]
-title = "Extension example to create the menu"
-description = "This is the menu example"
-changelog = "docs/CHANGELOG.md"
-readme = "docs/README.md"
-icon = "data/icon.png"
-preview_image = "data/preview.png"
-version = "1.0.3"
-authors = [ "Damien Bataille ",]
-repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed_example.my_name.menu"
-category = "example"
-keywords = [ "remix",]
-
-[dependencies]
-"omni.kit.menu.utils" = {}
-
-[[python.module]]
-name = "lightspeed_example.my_name.menu"
diff --git a/source/extensions/lightspeed_example.my_name.menu/data/icon.png b/source/extensions/lightspeed_example.my_name.menu/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed_example.my_name.menu/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed_example.my_name.menu/data/preview.png b/source/extensions/lightspeed_example.my_name.menu/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed_example.my_name.menu/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed_example.my_name.menu/docs/CHANGELOG.md b/source/extensions/lightspeed_example.my_name.menu/docs/CHANGELOG.md
deleted file mode 100644
index d711e5075..000000000
--- a/source/extensions/lightspeed_example.my_name.menu/docs/CHANGELOG.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [1.0.3]
-### Changed
-- Changed repo link
-
-## [1.0.2]
-### Changed
-- Update to Kit 106
-
-## [1.0.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed_example.my_name.menu/docs/README.md b/source/extensions/lightspeed_example.my_name.menu/docs/README.md
deleted file mode 100644
index dd8033cce..000000000
--- a/source/extensions/lightspeed_example.my_name.menu/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed_example.my_name.menu
diff --git a/source/extensions/lightspeed_example.my_name.menu/docs/index.rst b/source/extensions/lightspeed_example.my_name.menu/docs/index.rst
deleted file mode 100644
index 2215985f1..000000000
--- a/source/extensions/lightspeed_example.my_name.menu/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed_example.my_name.menu
-################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed_example.my_name.menu
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed_example.my_name.menu/lightspeed_example/my_name/menu/__init__.py b/source/extensions/lightspeed_example.my_name.menu/lightspeed_example/my_name/menu/__init__.py
deleted file mode 100644
index c60b88dbf..000000000
--- a/source/extensions/lightspeed_example.my_name.menu/lightspeed_example/my_name/menu/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .setup_menu import create_menu # noqa F401
diff --git a/source/extensions/lightspeed_example.my_name.menu/lightspeed_example/my_name/menu/setup_menu.py b/source/extensions/lightspeed_example.my_name.menu/lightspeed_example/my_name/menu/setup_menu.py
deleted file mode 100644
index 659da89c0..000000000
--- a/source/extensions/lightspeed_example.my_name.menu/lightspeed_example/my_name/menu/setup_menu.py
+++ /dev/null
@@ -1,123 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import omni.kit.menu.utils as omni_utils
-from omni.kit.menu.utils import MenuItemDescription
-
-
-class _SetupMenu:
- class _Event(set):
- """
- A list of callable objects. Calling an instance of this will cause a
- call to each item in the list in ascending order by index.
- """
-
- def __call__(self, *args, **kwargs):
- """Called when the instance is “called” as a function"""
- # Call all the saved functions
- for f in self:
- f(*args, **kwargs)
-
- def __repr__(self):
- """
- Called by the repr() built-in function to compute the “official”
- string representation of an object.
- """
- return f"Event({set.__repr__(self)})"
-
- class _EventSubscription:
- """
- Event subscription.
-
- _Event has callback while this object exists.
- """
-
- def __init__(self, event, fn):
- """
- Save the function, the event, and add the function to the event.
- """
- self._fn = fn
- self._event = event
- event.add(self._fn)
-
- def __del__(self):
- """Called by GC."""
- self._event.remove(self._fn)
-
- def __init__(self):
- """Example widget"""
-
- self._default_attr = {"_menus": None}
- for attr, value in self._default_attr.items():
- setattr(self, attr, value)
- self.__create_menu()
-
- self.__on_menu1_clicked = self._Event()
- self.__on_menu2_clicked = self._Event()
-
- def _menu1_clicked(self):
- """Call the event object that has the list of functions"""
- self.__on_menu1_clicked()
-
- def subscribe_menu1_clicked(self, fn):
- """
- Return the object that will automatically unsubscribe when destroyed.
- """
- return self._EventSubscription(self.__on_menu1_clicked, fn)
-
- def _menu2_clicked(self):
- """Call the event object that has the list of functions"""
- self.__on_menu2_clicked()
-
- def subscribe_menu2_clicked(self, fn):
- """
- Return the object that will automatically unsubscribe when destroyed.
- """
- return self._EventSubscription(self.__on_menu2_clicked, fn)
-
- def __create_menu(self):
- """Create the menu to Save scenario"""
- self._menus = [
- MenuItemDescription(
- name="Lightspeed Example Menu1", onclick_fn=self._menu1_clicked, glyph="none.svg", appear_after="Save"
- ),
- MenuItemDescription(
- name="Lightspeed Example Menu2",
- onclick_fn=self._menu2_clicked,
- glyph="none.svg",
- appear_after="Lightspeed Example Menu1",
- ),
- ]
- omni_utils.add_menu_items(self._menus, "File")
-
- def destroy(self):
- for attr, value in self._default_attr.items():
- m_attr = getattr(self, attr)
- if isinstance(m_attr, list):
- m_attrs = m_attr
- else:
- m_attrs = [m_attr]
- for m_attr in m_attrs:
- destroy = getattr(m_attr, "destroy", None)
- if callable(destroy):
- destroy()
- del m_attr # noqa PLW4701
- setattr(self, attr, value)
-
-
-def create_menu():
- return _SetupMenu()
diff --git a/source/extensions/lightspeed_example.my_name.menu/premake5.lua b/source/extensions/lightspeed_example.my_name.menu/premake5.lua
deleted file mode 100644
index b0aac3e04..000000000
--- a/source/extensions/lightspeed_example.my_name.menu/premake5.lua
+++ /dev/null
@@ -1,11 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- {"lightspeed_example/", ext.target_dir.."/lightspeed_example"},
- { "data", ext.target_dir.."/data" },
- { "docs", ext.target_dir.."/docs" },
-}
-
diff --git a/source/extensions/lightspeed_example.my_name.widget/config/extension.toml b/source/extensions/lightspeed_example.my_name.widget/config/extension.toml
deleted file mode 100644
index 06c7e7d4b..000000000
--- a/source/extensions/lightspeed_example.my_name.widget/config/extension.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[package]
-title = "Extension example to create the ui widget"
-description = "This is the widget example"
-changelog = "docs/CHANGELOG.md"
-readme = "docs/README.md"
-icon = "data/icon.png"
-preview_image = "data/preview.png"
-version = "1.0.3"
-authors = [ "Damien Bataille ",]
-repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed_example.my_name.widget"
-category = "example"
-keywords = [ "remix",]
-
-[dependencies]
-"omni.ui" = {}
-
-[[python.module]]
-name = "lightspeed_example.my_name.widget"
diff --git a/source/extensions/lightspeed_example.my_name.widget/data/icon.png b/source/extensions/lightspeed_example.my_name.widget/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed_example.my_name.widget/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed_example.my_name.widget/data/preview.png b/source/extensions/lightspeed_example.my_name.widget/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed_example.my_name.widget/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed_example.my_name.widget/docs/CHANGELOG.md b/source/extensions/lightspeed_example.my_name.widget/docs/CHANGELOG.md
deleted file mode 100644
index d711e5075..000000000
--- a/source/extensions/lightspeed_example.my_name.widget/docs/CHANGELOG.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [1.0.3]
-### Changed
-- Changed repo link
-
-## [1.0.2]
-### Changed
-- Update to Kit 106
-
-## [1.0.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed_example.my_name.widget/docs/README.md b/source/extensions/lightspeed_example.my_name.widget/docs/README.md
deleted file mode 100644
index b4d6f4108..000000000
--- a/source/extensions/lightspeed_example.my_name.widget/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed_example.my_name.widget
diff --git a/source/extensions/lightspeed_example.my_name.widget/docs/index.rst b/source/extensions/lightspeed_example.my_name.widget/docs/index.rst
deleted file mode 100644
index d8739ee59..000000000
--- a/source/extensions/lightspeed_example.my_name.widget/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed_example.my_name.widget
-##################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed_example.my_name.widget
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed_example.my_name.widget/lightspeed_example/my_name/widget/__init__.py b/source/extensions/lightspeed_example.my_name.widget/lightspeed_example/my_name/widget/__init__.py
deleted file mode 100644
index 59b7f0d14..000000000
--- a/source/extensions/lightspeed_example.my_name.widget/lightspeed_example/my_name/widget/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .setup_widget import create_widget # noqa F401
diff --git a/source/extensions/lightspeed_example.my_name.widget/lightspeed_example/my_name/widget/setup_widget.py b/source/extensions/lightspeed_example.my_name.widget/lightspeed_example/my_name/widget/setup_widget.py
deleted file mode 100644
index 817c32116..000000000
--- a/source/extensions/lightspeed_example.my_name.widget/lightspeed_example/my_name/widget/setup_widget.py
+++ /dev/null
@@ -1,115 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import omni.ui as ui
-
-
-class _SetupWidget:
- class _Event(set):
- """
- A list of callable objects. Calling an instance of this will cause a
- call to each item in the list in ascending order by index.
- """
-
- def __call__(self, *args, **kwargs):
- """Called when the instance is “called” as a function"""
- # Call all the saved functions
- for f in self:
- f(*args, **kwargs)
-
- def __repr__(self):
- """
- Called by the repr() built-in function to compute the “official”
- string representation of an object.
- """
- return f"Event({set.__repr__(self)})"
-
- class _EventSubscription:
- """
- Event subscription.
-
- _Event has callback while this object exists.
- """
-
- def __init__(self, event, fn):
- """
- Save the function, the event, and add the function to the event.
- """
- self._fn = fn
- self._event = event
- event.add(self._fn)
-
- def __del__(self):
- """Called by GC."""
- self._event.remove(self._fn)
-
- def __init__(self):
- """Example widget"""
-
- self._default_attr = {"_button1": None, "_button2": None}
- for attr, value in self._default_attr.items():
- setattr(self, attr, value)
- self.__create_ui()
-
- self.__on_button1_clicked = self._Event()
- self.__on_button2_clicked = self._Event()
-
- def _button1_clicked(self):
- """Call the event object that has the list of functions"""
- self.__on_button1_clicked()
-
- def subscribe_button1_clicked(self, fn):
- """
- Return the object that will automatically unsubscribe when destroyed.
- """
- return self._EventSubscription(self.__on_button1_clicked, fn)
-
- def _button2_clicked(self):
- """Call the event object that has the list of functions"""
- self.__on_button2_clicked()
-
- def subscribe_button2_clicked(self, fn):
- """
- Return the object that will automatically unsubscribe when destroyed.
- """
- return self._EventSubscription(self.__on_button2_clicked, fn)
-
- def __create_ui(self):
- """Create the widget
- When someone clicks on the buttons, it will fired the subscriptions
- """
- with ui.VStack():
- self._button1 = ui.Button("Button1", clicked_fn=self._button1_clicked, name="Button1")
- self._button2 = ui.Button("Button2", clicked_fn=self._button2_clicked, name="Button2")
-
- def destroy(self):
- for attr, value in self._default_attr.items():
- m_attr = getattr(self, attr)
- if isinstance(m_attr, list):
- m_attrs = m_attr
- else:
- m_attrs = [m_attr]
- for m_attr in m_attrs:
- destroy = getattr(m_attr, "destroy", None)
- if callable(destroy):
- destroy()
- del m_attr
- setattr(self, attr, value)
-
-
-def create_widget():
- return _SetupWidget()
diff --git a/source/extensions/lightspeed_example.my_name.widget/premake5.lua b/source/extensions/lightspeed_example.my_name.widget/premake5.lua
deleted file mode 100644
index 227f4aa7c..000000000
--- a/source/extensions/lightspeed_example.my_name.widget/premake5.lua
+++ /dev/null
@@ -1,11 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-repo_build.prebuild_link {
- {"lightspeed_example/", ext.target_dir.."/lightspeed_example"},
- { "docs", ext.target_dir.."/docs" },
- { "data", ext.target_dir.."/data" }
-}
-
diff --git a/source/extensions/lightspeed_example.my_name.window/config/extension.toml b/source/extensions/lightspeed_example.my_name.window/config/extension.toml
deleted file mode 100644
index b08aaafef..000000000
--- a/source/extensions/lightspeed_example.my_name.window/config/extension.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-version = "0.1.2"
-authors = ["dbataille@nvidia.com"]
-repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit"
-keywords = ["window"]
-title = "Window"
-description = "Window example"
-category = "example"
-changelog = "docs/CHANGELOG.md"
-readme = "docs/README.md"
-icon = "data/icon.png"
-preview_image = "data/preview.png"
-
-
-[dependencies]
-"lightspeed_example.my_name.widget" = {}
-"omni.ui" = {}
-
-[[python.module]]
-name = "lightspeed_example.my_name.window"
diff --git a/source/extensions/lightspeed_example.my_name.window/data/icon.png b/source/extensions/lightspeed_example.my_name.window/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed_example.my_name.window/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed_example.my_name.window/data/preview.png b/source/extensions/lightspeed_example.my_name.window/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed_example.my_name.window/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed_example.my_name.window/docs/CHANGELOG.md b/source/extensions/lightspeed_example.my_name.window/docs/CHANGELOG.md
deleted file mode 100644
index 96a5c1394..000000000
--- a/source/extensions/lightspeed_example.my_name.window/docs/CHANGELOG.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [0.1.2]
-### Changed
-- Update to Kit 106
-
-## [0.1.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed_example.my_name.window/docs/README.md b/source/extensions/lightspeed_example.my_name.window/docs/README.md
deleted file mode 100644
index 5abe99333..000000000
--- a/source/extensions/lightspeed_example.my_name.window/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed_example.my_name.window
diff --git a/source/extensions/lightspeed_example.my_name.window/docs/index.rst b/source/extensions/lightspeed_example.my_name.window/docs/index.rst
deleted file mode 100644
index 7d3c8bd9a..000000000
--- a/source/extensions/lightspeed_example.my_name.window/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed_example.my_name.window
-##################################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed_example.my_name.window
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed_example.my_name.window/lightspeed_example/my_name/window/__init__.py b/source/extensions/lightspeed_example.my_name.window/lightspeed_example/my_name/window/__init__.py
deleted file mode 100644
index aa37416c2..000000000
--- a/source/extensions/lightspeed_example.my_name.window/lightspeed_example/my_name/window/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .setup_window import create_window # noqa F401
diff --git a/source/extensions/lightspeed_example.my_name.window/lightspeed_example/my_name/window/setup_window.py b/source/extensions/lightspeed_example.my_name.window/lightspeed_example/my_name/window/setup_window.py
deleted file mode 100644
index 3b9f54163..000000000
--- a/source/extensions/lightspeed_example.my_name.window/lightspeed_example/my_name/window/setup_window.py
+++ /dev/null
@@ -1,64 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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.
-"""
-
-import omni.ui as ui
-from lightspeed_example.my_name.widget import create_widget
-
-
-class _SetupWindow:
-
- WINDOW_NAME = "Window example"
-
- def __init__(self):
- """Window"""
- self.__default_attr = {"_window": None, "_widget": None}
- for attr, value in self.__default_attr.items():
- setattr(self, attr, value)
-
- self.__create_ui()
-
- @property
- def widget(self):
- return self._widget
-
- @property
- def window(self):
- return self._window
-
- def __create_ui(self):
- """Create the main UI"""
- self._window = ui.Window(self.WINDOW_NAME, name=self.WINDOW_NAME, width=400, height=300)
- with self._window.frame:
- self._widget = create_widget()
-
- def destroy(self):
- for attr, value in self.__default_attr.items():
- m_attr = getattr(self, attr)
- if isinstance(m_attr, list):
- m_attrs = m_attr
- else:
- m_attrs = [m_attr]
- for m_attr in m_attrs:
- destroy = getattr(m_attr, "destroy", None)
- if callable(destroy):
- destroy()
- del m_attr
- setattr(self, attr, value)
-
-
-def create_window():
- return _SetupWindow()
diff --git a/source/extensions/lightspeed_example.my_name.window/premake5.lua b/source/extensions/lightspeed_example.my_name.window/premake5.lua
deleted file mode 100644
index 9ca995202..000000000
--- a/source/extensions/lightspeed_example.my_name.window/premake5.lua
+++ /dev/null
@@ -1,9 +0,0 @@
-local ext = get_current_extension_info()
-
-project_ext (ext)
-
-repo_build.prebuild_link {
- {"lightspeed_example/", ext.target_dir.."/lightspeed_example"},
- { "docs", ext.target_dir.."/docs" },
- { "data", ext.target_dir.."/data" }
-}
diff --git a/source/extensions/lightspeed_example.style/config/extension.toml b/source/extensions/lightspeed_example.style/config/extension.toml
deleted file mode 100644
index efcc92abd..000000000
--- a/source/extensions/lightspeed_example.style/config/extension.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-title = "App Style"
-description = "Global Style for the App"
-changelog = "docs/CHANGELOG.md"
-readme = "docs/README.md"
-icon = "data/icon.png"
-preview_image = "data/preview.png"
-version = "1.0.3"
-authors = [ "Damien Bataille ",]
-repository = "https://gitlab-master.nvidia.com/lightspeedrtx/lightspeed-kit/-/tree/main/source/extensions/lightspeed_example.style"
-category = "example"
-keywords = [ "remix",]
-
-[dependencies]
-"lightspeed_example.app.resources" = {}
-"omni.ui" = {}
-
-[[python.module]]
-name = "lightspeed_example.style"
diff --git a/source/extensions/lightspeed_example.style/data/icon.png b/source/extensions/lightspeed_example.style/data/icon.png
deleted file mode 100644
index 7ce4a36fd..000000000
--- a/source/extensions/lightspeed_example.style/data/icon.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8e3882f41b9ac9bed5887720c8feb8bd50fd05dc278856fc4252ff55af6c2e6c
-size 15146
diff --git a/source/extensions/lightspeed_example.style/data/preview.png b/source/extensions/lightspeed_example.style/data/preview.png
deleted file mode 100644
index 997a2305f..000000000
--- a/source/extensions/lightspeed_example.style/data/preview.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bedb35a418e28f1823d99f62928076f09b6bc52d4b81c84c665684bbd8105703
-size 57028
diff --git a/source/extensions/lightspeed_example.style/docs/CHANGELOG.md b/source/extensions/lightspeed_example.style/docs/CHANGELOG.md
deleted file mode 100644
index d711e5075..000000000
--- a/source/extensions/lightspeed_example.style/docs/CHANGELOG.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Changelog
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-
-## [1.0.3]
-### Changed
-- Changed repo link
-
-## [1.0.2]
-### Changed
-- Update to Kit 106
-
-## [1.0.1]
-### Changed
-- Set Apache 2 license headers
-
-## [0.1.0] - 2022-03-18
-### Added
-- Created
diff --git a/source/extensions/lightspeed_example.style/docs/README.md b/source/extensions/lightspeed_example.style/docs/README.md
deleted file mode 100644
index 46160222d..000000000
--- a/source/extensions/lightspeed_example.style/docs/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# lightspeed_example.style
diff --git a/source/extensions/lightspeed_example.style/docs/index.rst b/source/extensions/lightspeed_example.style/docs/index.rst
deleted file mode 100644
index 49cd038c5..000000000
--- a/source/extensions/lightspeed_example.style/docs/index.rst
+++ /dev/null
@@ -1,18 +0,0 @@
-lightspeed_example.style
-###########################
-
-
-.. toctree::
- :maxdepth: 1
-
- README
- CHANGELOG
-
-
-.. automodule:: lightspeed_example.style
- :platform: Windows-x86_64, Linux-x86_64
- :members:
- :undoc-members:
- :show-inheritance:
- :imported-members:
- :exclude-members: contextmanager
diff --git a/source/extensions/lightspeed_example.style/lightspeed_example/style/__init__.py b/source/extensions/lightspeed_example.style/lightspeed_example/style/__init__.py
deleted file mode 100644
index 7089645ed..000000000
--- a/source/extensions/lightspeed_example.style/lightspeed_example/style/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 .global_style import * # noqa F401
diff --git a/source/extensions/lightspeed_example.style/lightspeed_example/style/global_style.py b/source/extensions/lightspeed_example.style/lightspeed_example/style/global_style.py
deleted file mode 100644
index 61fd53272..000000000
--- a/source/extensions/lightspeed_example.style/lightspeed_example/style/global_style.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"""
-* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-* SPDX-License-Identifier: Apache-2.0
-*
-* 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
-*
-* https://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 pathlib import Path
-from typing import Optional
-
-import omni.kit.app
-import omni.ui as ui
-
-EXT_RESOURCE_ID = (
- omni.kit.app.get_app().get_extension_manager().get_enabled_extension_id("lightspeed_example.app.resources")
-)
-EXTENSION_RESOURCES_FOLDER_PATH = Path(
- omni.kit.app.get_app().get_extension_manager().get_extension_path(EXT_RESOURCE_ID)
-)
-
-
-def get_icons(name: str) -> Optional[str]:
- """Get icon from the lightspeed_example.app.resources extension"""
- for icon in EXTENSION_RESOURCES_FOLDER_PATH.joinpath("data", "icons").iterdir():
- if icon.stem == name:
- return str(icon)
- return None
-
-
-style = ui.Style.get_instance()
-current_dict = style.default
-current_dict.update(
- {
- "Button::Button1": {"background_color": 0xFF0000FF, "border_radius": 1.0, "margin": 3.0, "padding": 3.0},
- "Button::Button2": {"background_color": 0xFF00FF00, "border_radius": 2.0, "margin": 1.0, "padding": 2.0},
- }
-)
-style.default = current_dict
diff --git a/source/extensions/lightspeed_example.style/premake5.lua b/source/extensions/lightspeed_example.style/premake5.lua
deleted file mode 100644
index 3e3384428..000000000
--- a/source/extensions/lightspeed_example.style/premake5.lua
+++ /dev/null
@@ -1,11 +0,0 @@
--- Use folder name to build extension name and tag. Version is specified explicitly.
-local ext = get_current_extension_info()
-
--- Link the current "target" folders into the extension target folder:
-project_ext (ext)
-
-repo_build.prebuild_link {
- {"lightspeed_example/", ext.target_dir.."/lightspeed_example"},
- { "docs", ext.target_dir.."/docs" },
- { "data", ext.target_dir.."/data" }
-}
diff --git a/source/extensions/omni.flux.asset_importer.widget/config/extension.toml b/source/extensions/omni.flux.asset_importer.widget/config/extension.toml
index 584e2d2fb..34d4602b9 100644
--- a/source/extensions/omni.flux.asset_importer.widget/config/extension.toml
+++ b/source/extensions/omni.flux.asset_importer.widget/config/extension.toml
@@ -1,6 +1,6 @@
[package]
# Semantic Versionning is used: https://semver.org/
-version = "2.5.12"
+version = "2.5.13"
# Lists people or organizations that are considered the "authors" of the package.
authors = ["Pierre-Olivier Trottier "]
diff --git a/source/extensions/omni.flux.asset_importer.widget/docs/CHANGELOG.md b/source/extensions/omni.flux.asset_importer.widget/docs/CHANGELOG.md
index 8a20c0115..cd1d64320 100644
--- a/source/extensions/omni.flux.asset_importer.widget/docs/CHANGELOG.md
+++ b/source/extensions/omni.flux.asset_importer.widget/docs/CHANGELOG.md
@@ -2,6 +2,10 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [2.5.13]
+## Changed
+- Changed texture validation to use lowercase on extension check
+
## [2.5.12]
## Changed
- Update to Kit 106.5
diff --git a/source/extensions/omni.flux.asset_importer.widget/omni/flux/asset_importer/widget/common/ingestion_checker.py b/source/extensions/omni.flux.asset_importer.widget/omni/flux/asset_importer/widget/common/ingestion_checker.py
index b8e738853..fab6ac022 100644
--- a/source/extensions/omni.flux.asset_importer.widget/omni/flux/asset_importer/widget/common/ingestion_checker.py
+++ b/source/extensions/omni.flux.asset_importer.widget/omni/flux/asset_importer/widget/common/ingestion_checker.py
@@ -144,7 +144,7 @@ def show_error_dialog(self, bad_exts, bad_dirs, supported_extensions, callback=N
def _validate_selection(filenames, supported_extensions=None, return_values=False):
file_paths = [_OmniUrl(filename) for filename in filenames]
- bad_exts = [pth for pth in file_paths if pth.suffix and pth.suffix not in supported_extensions]
+ bad_exts = [pth for pth in file_paths if pth.suffix and pth.suffix.lower() not in supported_extensions]
bad_dirs = [pth for pth in file_paths if pth.is_directory]
if return_values:
return (bad_exts, bad_dirs)
diff --git a/source/extensions/omni.flux.asset_importer.widget/omni/flux/asset_importer/widget/tests/e2e/texture_import_list/test_texture_import_list_widget.py b/source/extensions/omni.flux.asset_importer.widget/omni/flux/asset_importer/widget/tests/e2e/texture_import_list/test_texture_import_list_widget.py
index 4a219cb36..2dcc54dea 100644
--- a/source/extensions/omni.flux.asset_importer.widget/omni/flux/asset_importer/widget/tests/e2e/texture_import_list/test_texture_import_list_widget.py
+++ b/source/extensions/omni.flux.asset_importer.widget/omni/flux/asset_importer/widget/tests/e2e/texture_import_list/test_texture_import_list_widget.py
@@ -467,7 +467,7 @@ async def test_drop_valid_files(self):
delegate = TextureImportListDelegate()
base_path = Path(self.temp_dir.name)
- good_items = [base_path / "0.jpg", base_path / "1.jpg"]
+ good_items = [base_path / "0.jpg", base_path / "1.jpg", base_path / "2.JPG"]
for item in good_items:
item.touch()
@@ -494,7 +494,7 @@ async def test_drop_invalid_files(self):
delegate = TextureImportListDelegate()
base_path = Path(self.temp_dir.name)
- good_items = [base_path / "1.jpg", base_path / "2.usd"]
+ good_items = [base_path / "1.jpg", base_path / "2.usd", base_path / "3.USD"]
bad_items = [base_path / "3.nogood", base_path / "4.INVALID"]
for item in good_items:
item.touch()
diff --git a/source/extensions/omni.flux.commands/config/extension.toml b/source/extensions/omni.flux.commands/config/extension.toml
index ed7d3c35a..66c7f742f 100644
--- a/source/extensions/omni.flux.commands/config/extension.toml
+++ b/source/extensions/omni.flux.commands/config/extension.toml
@@ -1,6 +1,6 @@
[package]
# Semantic Versionning is used: https://semver.org/
-version = "1.0.6"
+version = "1.2.0"
# Lists people or organizations that are considered the "authors" of the package.
authors = ["Pierre-Olivier Trottier "]
@@ -31,9 +31,9 @@ icon = "data/icon.png"
[dependencies]
"omni.kit.commands" = {}
-"omni.usd" = {}
-"omni.kit.usd_undo" = {}
"omni.kit.usd.layers" = {}
+"omni.kit.usd_undo" = {}
+"omni.usd" = {}
[core]
# Load as early as possible
diff --git a/source/extensions/omni.flux.commands/docs/CHANGELOG.md b/source/extensions/omni.flux.commands/docs/CHANGELOG.md
index 4d62f8da7..3e1d26650 100644
--- a/source/extensions/omni.flux.commands/docs/CHANGELOG.md
+++ b/source/extensions/omni.flux.commands/docs/CHANGELOG.md
@@ -2,8 +2,16 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.2.0]
+### Changed
+- Added `CreateOrInsertSublayerCommand` custom command for to revert Kit 106.5 changes.
+
+## [1.1.0]
+### Changed
+- Added `SetVisibilitySelectedPrimsCommand` custom command for setting visibility on selected prims.
+
## [1.0.6]
-## Changed
+### Changed
- Update to Kit 106.5
## [1.0.5]
diff --git a/source/extensions/omni.flux.commands/omni/flux/commands/custom_commands.py b/source/extensions/omni.flux.commands/omni/flux/commands/custom_commands.py
index 557e789d9..b9a1e4ffc 100644
--- a/source/extensions/omni.flux.commands/omni/flux/commands/custom_commands.py
+++ b/source/extensions/omni.flux.commands/omni/flux/commands/custom_commands.py
@@ -15,17 +15,34 @@
* limitations under the License.
"""
+__all__ = [
+ "AttributeDef",
+ "SetDefaultPrimCommand",
+ "SetFluxXFormPrimCommand",
+ "RemoveOverrideCommand",
+ "SetVisibilitySelectedPrimsCommand",
+ "CreateOrInsertSublayerCommand",
+]
+
from typing import Any, Iterable, TypedDict
import carb
import omni.kit.commands
import omni.kit.undo
import omni.usd
+from omni.kit.usd.layers import LayerUtils
from omni.kit.usd_undo import UsdEditTargetUndo
-from omni.usd.commands import remove_prim_spec as _remove_prim_spec
+from omni.usd.commands import remove_prim_spec
from pxr import Sdf, Usd, UsdGeom
+class AttributeDef(TypedDict):
+ name: str
+ op: UsdGeom.XformOp
+ precision: UsdGeom.XformOp.Precision
+ value: Any | None
+
+
class SetDefaultPrimCommand(omni.kit.commands.Command):
"""
Sets a prim to be the default prim
@@ -57,13 +74,6 @@ def undo(self):
self._stage.SetDefaultPrim(None)
-class AttributeDef(TypedDict):
- name: str
- op: UsdGeom.XformOp
- precision: UsdGeom.XformOp.Precision
- value: Any | None
-
-
class SetFluxXFormPrimCommand(omni.kit.commands.Command):
"""
Set xforms on a prim undoable **Command**.
@@ -97,7 +107,7 @@ def _clean_prims(self, spec: Sdf.Spec):
if not spec or spec.properties or spec.nameChildren:
return
parent = spec.nameParent
- _remove_prim_spec(self._layer, spec.path)
+ remove_prim_spec(self._layer, spec.path)
self._clean_prims(parent)
def _delete_from_layer(self, attribute: Usd.Property):
@@ -297,4 +307,222 @@ def undo(self):
self._edit_target_undo.undo()
+class SetVisibilitySelectedPrimsCommand(omni.kit.commands.Command):
+ """
+ Sets the visibility of the selected primitives.
+ """
+
+ def __init__(self, selected_paths: list[str], value: bool, context_name: str = ""):
+ """
+ Args:
+ selected_paths (list[str]): A list of prim paths to set the visibility.
+ value (bool): The visibility value to set.
+ context_name (str): The context name to get the stage from.
+ """
+
+ self._timeline = omni.timeline.get_timeline_interface()
+ self._stage = omni.usd.get_context(context_name).get_stage()
+ self._selected_paths = [Sdf.Path(path) for path in selected_paths]
+ self._selected_paths = Sdf.Path.RemoveDescendentPaths(self._selected_paths)
+ self._value = value
+ self._previous_visibility = {}
+ self._action_taken = {}
+ self._current_time = None
+
+ def _get_prim_visibility(self, prim: Usd.Prim, time: float):
+ imageable = UsdGeom.Imageable(prim)
+ visibility_attr = imageable.GetVisibilityAttr()
+
+ time_sampled = visibility_attr.GetNumTimeSamples() > 1
+ if time_sampled:
+ curr_time_code = time * self._stage.GetTimeCodesPerSecond()
+ else:
+ curr_time_code = Usd.TimeCode.Default()
+
+ return imageable.ComputeVisibility(curr_time_code)
+
+ def _toggle_visibility(self, undo: bool):
+ if not undo:
+ self._current_time = self._timeline.get_current_time()
+
+ for selected_path in self._selected_paths:
+ if undo and not self._action_taken.get(selected_path):
+ continue
+
+ selected_prim = self._stage.GetPrimAtPath(selected_path)
+ if not selected_prim:
+ continue
+
+ if not undo:
+ # It needs to save parent visibility as toggling visibility may influence parents.
+ prefixes = selected_path.GetPrefixes()[:-1]
+ for path in prefixes:
+ parent = self._stage.GetPrimAtPath(path)
+ if not parent:
+ break
+
+ visibility = self._get_prim_visibility(parent, self._current_time)
+ if visibility != UsdGeom.Tokens.inherited:
+ self._previous_visibility[parent.GetPath()] = visibility
+ break
+
+ previous_visibility = self._get_prim_visibility(selected_prim, self._current_time)
+ target_visibility = self._value if not undo else not self._value
+ imageable = UsdGeom.Imageable(selected_prim)
+ if target_visibility:
+ imageable.MakeVisible()
+ else:
+ imageable.MakeInvisible()
+
+ self._action_taken[selected_path] = previous_visibility != self._get_prim_visibility(
+ selected_prim, self._current_time
+ )
+
+ if undo:
+ for path, visibility in self._previous_visibility.items():
+ prim = self._stage.GetPrimAtPath(path)
+ if not prim:
+ continue
+ imageable = UsdGeom.Imageable(prim)
+
+ if visibility == UsdGeom.Tokens.visible:
+ imageable.MakeVisible()
+ if visibility == UsdGeom.Tokens.invisible:
+ imageable.MakeInvisible()
+
+ def do(self):
+ self._toggle_visibility(False)
+
+ def undo(self):
+ self._toggle_visibility(True)
+
+
+class CreateOrInsertSublayerCommand(omni.kit.commands.Command):
+ """Creates or inserts a sublayer."""
+
+ def __init__(
+ self,
+ layer_identifier: str,
+ sublayer_position: int,
+ new_layer_path: str,
+ transfer_root_content: bool,
+ create_or_insert: bool,
+ layer_name: str = "",
+ usd_context: str | omni.usd.UsdContext = "",
+ ):
+ """
+ Args:
+ layer_identifier (str): The identifier of layer to create sublayer. It should be found by Sdf.Find.
+ sublayer_position (int): Sublayer position that the new sublayer is created before.
+ If position_before == -1, it will create layer at the end of sublayer list.
+ If position_before >= total_number_of_sublayers, it will create layer at the end of
+ sublayer list.
+ new_layer_path (str): Absolute path of new layer. If it's empty, it will create anonymous layer if
+ create_or_insert == True.
+ If create_or_insert == False and it's empty, it will fail to insert layer.
+ transfer_root_content (bool): True if we should move the root contents to the new layer.
+ create_or_insert (bool): If it's true, it will create layer from this path. It's insert, otherwise.
+ layer_name (str, optional): If it's to create anonymous layer (new_layer_path is empty), this name is used.
+ usd_context (Union[str, omni.usd.UsdContext]): Usd context name or instance. It uses default context if it's
+ empty.
+ """
+ self._usd_context = self._get_usd_context(usd_context)
+ self._selection = self._usd_context.get_selection()
+
+ self._layer_identifier = layer_identifier
+ self._sublayer_position = sublayer_position
+ self._new_layer_path = new_layer_path
+ self._create_or_insert = create_or_insert
+ if create_or_insert:
+ self._transfer_root_content = transfer_root_content
+ else:
+ self._transfer_root_content = False
+ self._new_layer_identifier = None
+ self._layer_name = layer_name
+ self._temp_layer = None
+ self._edit_target_identifier = None
+ self._prev_selected_paths = None
+
+ def _get_usd_context(self, context_name_or_instance: str | omni.usd.UsdContext = ""):
+ if not context_name_or_instance:
+ context_name_or_instance = ""
+
+ if isinstance(context_name_or_instance, str):
+ usd_context = omni.usd.get_context(context_name_or_instance)
+ elif isinstance(context_name_or_instance, omni.usd.UsdContext):
+ usd_context = context_name_or_instance
+ else:
+ usd_context = None
+
+ return usd_context
+
+ def do(self):
+ stage = self._usd_context.get_stage()
+ root = stage.GetRootLayer()
+
+ if stage.GetEditTarget().GetLayer():
+ self._edit_target_identifier = stage.GetEditTarget().GetLayer().identifier
+ else:
+ self._edit_target_identifier = root.identifier
+ self._prev_selected_paths = list(self._selection.get_selected_prim_paths())
+
+ parent_layer = Sdf.Find(self._layer_identifier)
+ if self._create_or_insert:
+ if self._transfer_root_content:
+ self._temp_layer = Sdf.Layer.CreateAnonymous()
+ self._temp_layer.TransferContent(root)
+
+ if parent_layer:
+ new_layer = LayerUtils.create_sublayer(parent_layer, self._sublayer_position, self._new_layer_path)
+ if new_layer:
+ # Copy Stage Axis
+ UsdGeom.SetStageUpAxis(Usd.Stage.Open(new_layer), UsdGeom.GetStageUpAxis(stage))
+ LayerUtils.set_custom_layer_name(new_layer, self._layer_name)
+
+ if self._transfer_root_content:
+ LayerUtils.transfer_layer_content(root, new_layer)
+ root.rootPrims.clear()
+
+ self._new_layer_identifier = new_layer.identifier
+ else:
+ self._new_layer_identifier = None
+ else:
+ layer = LayerUtils.insert_sublayer(parent_layer, self._sublayer_position, self._new_layer_path)
+ if layer:
+ self._new_layer_identifier = layer.identifier
+
+ return self._new_layer_identifier
+
+ def undo(self):
+ if self._new_layer_identifier:
+ stage = self._usd_context.get_stage()
+ with Sdf.ChangeBlock():
+ if self._transfer_root_content and self._temp_layer:
+ root = stage.GetRootLayer()
+ root.TransferContent(self._temp_layer)
+
+ layer_position_in_parent = LayerUtils.get_sublayer_position_in_parent(
+ self._layer_identifier, self._new_layer_identifier
+ )
+ if layer_position_in_parent != -1:
+ layer = Sdf.Find(self._layer_identifier)
+ if not layer:
+ return
+ layer_identifier = LayerUtils.remove_sublayer(layer, layer_position_in_parent)
+ LayerUtils.remove_layer_global_muteness(layer, layer_identifier)
+
+ # restore selected prims and layer
+ self._selection.set_selected_prim_paths(self._prev_selected_paths, False)
+ stage = self._usd_context.get_stage()
+
+ layer = Sdf.Find(self._edit_target_identifier)
+ if layer and not stage.IsLayerMuted(layer.identifier):
+ edit_target_layer = layer
+ else:
+ edit_target_layer = stage.GetRootLayer()
+ if stage.HasLocalLayer(edit_target_layer):
+ edit_target = stage.GetEditTargetForLocalLayer(edit_target_layer)
+ stage.SetEditTarget(edit_target)
+
+
omni.kit.commands.register_all_commands_in_module(__name__)
diff --git a/source/extensions/omni.flux.layer_tree.usd.widget/config/extension.toml b/source/extensions/omni.flux.layer_tree.usd.widget/config/extension.toml
index 4a2d969f2..de33f5e22 100644
--- a/source/extensions/omni.flux.layer_tree.usd.widget/config/extension.toml
+++ b/source/extensions/omni.flux.layer_tree.usd.widget/config/extension.toml
@@ -1,6 +1,6 @@
[package]
# Semantic Versionning is used: https://semver.org/
-version = "1.9.2"
+version = "1.9.3"
# Lists people or organizations that are considered the "authors" of the package.
authors =["Pierre-Olivier Trottier "]
@@ -30,12 +30,13 @@ preview_image = "data/images/preview.png"
icon = "data/images/icon.png"
[dependencies]
+"omni.flux.commands" = {} # Using custom commands
"omni.flux.layer_tree.usd.core" = {}
"omni.flux.utils.common" = {}
"omni.flux.utils.widget" = {}
"omni.kit.usd.layers" = {}
-"omni.kit.window.file_exporter" = {}
"omni.kit.widget.prompt" = {}
+"omni.kit.window.file_exporter" = {}
"omni.ui" = {}
"omni.usd" = {}
diff --git a/source/extensions/omni.flux.layer_tree.usd.widget/docs/CHANGELOG.md b/source/extensions/omni.flux.layer_tree.usd.widget/docs/CHANGELOG.md
index 986b9fd33..63bc1ca2e 100644
--- a/source/extensions/omni.flux.layer_tree.usd.widget/docs/CHANGELOG.md
+++ b/source/extensions/omni.flux.layer_tree.usd.widget/docs/CHANGELOG.md
@@ -2,27 +2,32 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.9.3]
+### Fixed
+- Fixed create/import layer buttons state after a refresh
+- Changed usages of the `CreateSublayer` command for `CreateOrInsertSublayer`
+
## [1.9.2]
-## Changed
+### Changed
- Update to Kit 106.5
## [1.9.1]
-## Changed
+### Changed
- Persist the selection through refreshes
-## Fixed
+### Fixed
- Fixed inconsistent muteness states
- Fixed stage events not triggering refresh
- Fixed widget being interactable while loading in progress
- Catch async exceptions in the refresh function
## [1.9.0]
-## Changed
+### Changed
- Improved UI for invalid edit targets
- Fixed refresh blocking the UI
## [1.8.3]
-## Changed
+### Changed
- update to use omni.kit.test public api
## [1.8.2]
diff --git a/source/extensions/omni.flux.layer_tree.usd.widget/omni/flux/layer_tree/usd/widget/layer_tree/model.py b/source/extensions/omni.flux.layer_tree.usd.widget/omni/flux/layer_tree/usd/widget/layer_tree/model.py
index dfcb499f1..2e925d238 100644
--- a/source/extensions/omni.flux.layer_tree.usd.widget/omni/flux/layer_tree/usd/widget/layer_tree/model.py
+++ b/source/extensions/omni.flux.layer_tree.usd.widget/omni/flux/layer_tree/usd/widget/layer_tree/model.py
@@ -196,8 +196,8 @@ def execute_command(path):
with undo.group():
# If the layer is already a sublayer, don't re-add it
if str(Path(path)) not in [str(Path(i.data["layer"].realPath)) for i in parent.children]:
- commands.execute(
- "CreateSublayerCommand",
+ success, new_layer_path = commands.execute(
+ "CreateOrInsertSublayer",
layer_identifier=parent.data["layer"].identifier,
sublayer_position=-1,
new_layer_path=str(path),
@@ -205,8 +205,8 @@ def execute_command(path):
create_or_insert=create_or_insert,
usd_context=self._context_name,
)
- if layer_created_callback is not None:
- layer_created_callback(path)
+ if success and layer_created_callback is not None:
+ layer_created_callback(new_layer_path)
if create_or_insert:
_open_file_picker(
diff --git a/source/extensions/omni.flux.layer_tree.usd.widget/omni/flux/layer_tree/usd/widget/setup_ui.py b/source/extensions/omni.flux.layer_tree.usd.widget/omni/flux/layer_tree/usd/widget/setup_ui.py
index 0d9516d04..047ce3afc 100644
--- a/source/extensions/omni.flux.layer_tree.usd.widget/omni/flux/layer_tree/usd/widget/setup_ui.py
+++ b/source/extensions/omni.flux.layer_tree.usd.widget/omni/flux/layer_tree/usd/widget/setup_ui.py
@@ -254,6 +254,9 @@ async def __refresh_async(self):
self._layer_tree_widget.selection = selection
self._ignore_selection_updates = False
+ # Update the import & create button states
+ self._update_button_state(selection)
+
def on_selection_changed(self, items: list[_ItemBase]):
if self._ignore_selection_updates:
return
diff --git a/source/extensions/omni.flux.property_widget_builder.model.usd/config/extension.toml b/source/extensions/omni.flux.property_widget_builder.model.usd/config/extension.toml
index 67c1ff9f6..2e1399f05 100644
--- a/source/extensions/omni.flux.property_widget_builder.model.usd/config/extension.toml
+++ b/source/extensions/omni.flux.property_widget_builder.model.usd/config/extension.toml
@@ -1,6 +1,6 @@
[package]
# Semantic Versionning is used: https://semver.org/
-version = "2.18.0"
+version = "2.18.1"
# Lists people or organizations that are considered the "authors" of the package.
authors = ["Damien Bataille "]
diff --git a/source/extensions/omni.flux.property_widget_builder.model.usd/docs/CHANGELOG.md b/source/extensions/omni.flux.property_widget_builder.model.usd/docs/CHANGELOG.md
index f4087183b..43f156c47 100644
--- a/source/extensions/omni.flux.property_widget_builder.model.usd/docs/CHANGELOG.md
+++ b/source/extensions/omni.flux.property_widget_builder.model.usd/docs/CHANGELOG.md
@@ -2,6 +2,10 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [2.18.1]
+### Fixed
+- Changed to using a ImageWithProvider to better display single channel textures
+
## [2.18.0]
## Added
- Added the ability to left-align property names
diff --git a/source/extensions/omni.flux.property_widget_builder.model.usd/omni/flux/property_widget_builder/model/usd/item_delegates/file_texture_picker.py b/source/extensions/omni.flux.property_widget_builder.model.usd/omni/flux/property_widget_builder/model/usd/item_delegates/file_texture_picker.py
index abb2b2989..5386a4143 100644
--- a/source/extensions/omni.flux.property_widget_builder.model.usd/omni/flux/property_widget_builder/model/usd/item_delegates/file_texture_picker.py
+++ b/source/extensions/omni.flux.property_widget_builder.model.usd/omni/flux/property_widget_builder/model/usd/item_delegates/file_texture_picker.py
@@ -291,7 +291,13 @@ def _build_image_preview_ui(self, resolved_path):
width=ui.Pixel(256),
)
with ui.CanvasFrame(style_type_name_override="ImagePreviewCanvas"):
- self._texture_viewer_widget = ui.Image(resolved_path)
+ with Image.open(resolved_path) as im:
+ provider = ui.ByteImageProvider()
+ channels = im.getdata().mode
+ if len(channels) == 1:
+ im = im.convert("RGBA")
+ provider.set_bytes_data(list(im.getdata()), [im.size[0], im.size[1]])
+ self._texture_viewer_widget = ui.ImageWithProvider(provider)
with ui.ScrollingFrame(name="WorkspaceBackground", width=ui.Pixel(300)):
with ui.HStack():
ui.Spacer(width=ui.Pixel(16))
diff --git a/source/extensions/omni.flux.stage_manager.plugin.interaction.usd/config/extension.toml b/source/extensions/omni.flux.stage_manager.plugin.interaction.usd/config/extension.toml
index 24fcb0225..e66c33000 100644
--- a/source/extensions/omni.flux.stage_manager.plugin.interaction.usd/config/extension.toml
+++ b/source/extensions/omni.flux.stage_manager.plugin.interaction.usd/config/extension.toml
@@ -1,6 +1,6 @@
[package]
# Semantic Versionning is used: https://semver.org/
-version = "1.14.0"
+version = "1.15.0"
# Lists people or organizations that are considered the "authors" of the package.
authors = ["Pierre-Olivier Trottier "]
diff --git a/source/extensions/omni.flux.stage_manager.plugin.interaction.usd/docs/CHANGELOG.md b/source/extensions/omni.flux.stage_manager.plugin.interaction.usd/docs/CHANGELOG.md
index 0a102e730..e82b2a377 100644
--- a/source/extensions/omni.flux.stage_manager.plugin.interaction.usd/docs/CHANGELOG.md
+++ b/source/extensions/omni.flux.stage_manager.plugin.interaction.usd/docs/CHANGELOG.md
@@ -1,6 +1,10 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.15.0]
+## Changed
+- Changed `usd_base.py` to use override-able `_get_selection()`
+
## [1.14.0]
## Added
- Added a materials interaction tab
diff --git a/source/extensions/omni.flux.stage_manager.plugin.interaction.usd/omni/flux/stage_manager/plugin/interaction/usd/base/usd_base.py b/source/extensions/omni.flux.stage_manager.plugin.interaction.usd/omni/flux/stage_manager/plugin/interaction/usd/base/usd_base.py
index 6dc0c1cc3..dfcd0f314 100644
--- a/source/extensions/omni.flux.stage_manager.plugin.interaction.usd/omni/flux/stage_manager/plugin/interaction/usd/base/usd_base.py
+++ b/source/extensions/omni.flux.stage_manager.plugin.interaction.usd/omni/flux/stage_manager/plugin/interaction/usd/base/usd_base.py
@@ -137,7 +137,8 @@ def _update_tree_selection(self):
if not self.synchronize_selection or not self._is_active:
return
- selection = omni.usd.get_context(self._context_name).get_selection().get_selected_prim_paths()
+ # Get USD selection
+ selection = self._get_selection()
if selection:
self._item_expansion_states.clear()
@@ -163,6 +164,9 @@ def is_selected_item(selected_prim_paths, item) -> bool:
self._update_expansion_states_deferred(scroll_to_selection_override=scroll_to_selection)
)
+ def _get_selection(self):
+ return omni.usd.get_context(self._context_name).get_selection().get_selected_prim_paths()
+
def _on_selection_changed(self, items: list[_StageManagerTreeItem]):
if self._selection_update_lock or not self.synchronize_selection:
return
@@ -171,9 +175,9 @@ def _on_selection_changed(self, items: list[_StageManagerTreeItem]):
self._ignore_selection_update = True
selection_prim_paths = [str(item.data.GetPath()) for item in items if item.data]
- selection = omni.usd.get_context(self._context_name).get_selection()
- if selection.get_selected_prim_paths() != selection_prim_paths:
- selection.set_selected_prim_paths(selection_prim_paths)
+ selection = self._get_selection()
+ if selection != selection_prim_paths:
+ omni.usd.get_context(self._context_name).get_selection().set_selected_prim_paths(selection_prim_paths)
def _on_layer_event_occurred(self, event_type: _layers.LayerEventType):
"""
diff --git a/source/extensions/omni.flux.stage_manager.plugin.widget.usd/config/extension.toml b/source/extensions/omni.flux.stage_manager.plugin.widget.usd/config/extension.toml
index f381bc447..6f6f71034 100644
--- a/source/extensions/omni.flux.stage_manager.plugin.widget.usd/config/extension.toml
+++ b/source/extensions/omni.flux.stage_manager.plugin.widget.usd/config/extension.toml
@@ -1,6 +1,6 @@
[package]
# Semantic Versionning is used: https://semver.org/
-version = "1.8.0"
+version = "1.9.0"
# Lists people or organizations that are considered the "authors" of the package.
authors = ["Pierre-Olivier Trottier "]
@@ -30,6 +30,7 @@ preview_image = "data/images/preview.png"
icon = "data/images/icon.png"
[dependencies]
+"omni.flux.commands" = {} # Using custom commands
"omni.flux.custom_tags.core" = {}
"omni.flux.custom_tags.window" = {}
"omni.flux.stage_manager.factory" = {}
diff --git a/source/extensions/omni.flux.stage_manager.plugin.widget.usd/docs/CHANGELOG.md b/source/extensions/omni.flux.stage_manager.plugin.widget.usd/docs/CHANGELOG.md
index 65c1a8d3d..56484550d 100644
--- a/source/extensions/omni.flux.stage_manager.plugin.widget.usd/docs/CHANGELOG.md
+++ b/source/extensions/omni.flux.stage_manager.plugin.widget.usd/docs/CHANGELOG.md
@@ -1,6 +1,10 @@
# Changelog
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.9.0]
+### Changed
+- Use newly created `SetVisibilitySelectedPrimsCommand` command to set all items to the same value instead of toggling
+
## [1.8.0]
### Added
- Use the new items' `build_widget` method instead of a label
diff --git a/source/extensions/omni.flux.stage_manager.plugin.widget.usd/omni/flux/stage_manager/plugin/widget/usd/action_is_visible.py b/source/extensions/omni.flux.stage_manager.plugin.widget.usd/omni/flux/stage_manager/plugin/widget/usd/action_is_visible.py
index d24539302..699c5b23d 100644
--- a/source/extensions/omni.flux.stage_manager.plugin.widget.usd/omni/flux/stage_manager/plugin/widget/usd/action_is_visible.py
+++ b/source/extensions/omni.flux.stage_manager.plugin.widget.usd/omni/flux/stage_manager/plugin/widget/usd/action_is_visible.py
@@ -72,6 +72,13 @@ def _on_icon_clicked(
self._item_clicked(button, True, model, item)
context = omni.usd.get_context(self._context_name)
+ target_value = (
+ UsdGeom.Imageable(item.data).ComputeVisibility(Usd.TimeCode.Default()) == UsdGeom.Tokens.invisible
+ )
+
omni.kit.commands.execute(
- "ToggleVisibilitySelectedPrims", selected_paths=context.get_selection().get_selected_prim_paths()
+ "SetVisibilitySelectedPrims",
+ selected_paths=context.get_selection().get_selected_prim_paths(),
+ value=target_value,
+ context_name=self._context_name,
)
diff --git a/source/extensions/omni.flux.tests.dependencies/config/extension.toml b/source/extensions/omni.flux.tests.dependencies/config/extension.toml
index b942c6a95..677820d3e 100644
--- a/source/extensions/omni.flux.tests.dependencies/config/extension.toml
+++ b/source/extensions/omni.flux.tests.dependencies/config/extension.toml
@@ -1,6 +1,6 @@
[package]
# Semantic Versionning is used: https://semver.org/
-version = "1.0.2"
+version = "1.1.0"
# Lists people or organizations that are considered the "authors" of the package.
authors = ["Pierre-Olivier Trottier "]
@@ -34,6 +34,7 @@ order = -1000
[dependencies]
"omni.flux.tests.settings" = {}
+"omni.flux.utils.tests" = {}
"omni.kit.ui_test" = {}
[settings]
diff --git a/source/extensions/omni.flux.tests.dependencies/docs/CHANGELOG.md b/source/extensions/omni.flux.tests.dependencies/docs/CHANGELOG.md
index a5f362439..fdda4a1ed 100644
--- a/source/extensions/omni.flux.tests.dependencies/docs/CHANGELOG.md
+++ b/source/extensions/omni.flux.tests.dependencies/docs/CHANGELOG.md
@@ -2,6 +2,10 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.1.0]
+## Added
+- Added `omni.flux.utils.tests` as a dependency
+
## [1.0.2]
## Changed
- Update to Kit 106.5
diff --git a/source/extensions/omni.flux.validator.mass.service/config/extension.toml b/source/extensions/omni.flux.validator.mass.service/config/extension.toml
index dc4d785fb..df1bc3402 100644
--- a/source/extensions/omni.flux.validator.mass.service/config/extension.toml
+++ b/source/extensions/omni.flux.validator.mass.service/config/extension.toml
@@ -1,6 +1,6 @@
[package]
# Semantic Versionning is used: https://semver.org/
-version = "1.1.1"
+version = "1.1.2"
# Lists people or organizations that are considered the "authors" of the package.
authors = ["Pierre-Olivier Trottier "]
@@ -42,7 +42,9 @@ name = "omni.flux.validator.mass.service"
[[test]]
dependencies = [
- "omni.flux.tests.dependencies"
+ "omni.flux.tests.dependencies",
+ "omni.flux.utils.widget",
+ "omni.services.core",
]
stdoutFailPatterns.exclude = [
diff --git a/source/extensions/omni.flux.validator.mass.service/docs/CHANGELOG.md b/source/extensions/omni.flux.validator.mass.service/docs/CHANGELOG.md
index 58db3453b..a7599e31e 100644
--- a/source/extensions/omni.flux.validator.mass.service/docs/CHANGELOG.md
+++ b/source/extensions/omni.flux.validator.mass.service/docs/CHANGELOG.md
@@ -2,6 +2,10 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.1.2]
+### Added
+- Added tests for all mass validator service endpoints
+
## [1.1.1]
### Fixed
- Fixed tests flakiness
diff --git a/source/extensions/lightspeed.asset_capture_localizer.core/lightspeed/asset_capture_localizer/core/__init__.py b/source/extensions/omni.flux.validator.mass.service/omni/flux/validator/mass/service/tests/__init__.py
similarity index 92%
rename from source/extensions/lightspeed.asset_capture_localizer.core/lightspeed/asset_capture_localizer/core/__init__.py
rename to source/extensions/omni.flux.validator.mass.service/omni/flux/validator/mass/service/tests/__init__.py
index 030b36db1..825a2adb4 100644
--- a/source/extensions/lightspeed.asset_capture_localizer.core/lightspeed/asset_capture_localizer/core/__init__.py
+++ b/source/extensions/omni.flux.validator.mass.service/omni/flux/validator/mass/service/tests/__init__.py
@@ -15,4 +15,4 @@
* limitations under the License.
"""
-from .core import * # noqa: F401
+from .e2e.test_service import TestMassValidatorService
diff --git a/source/extensions/omni.flux.validator.mass.service/omni/flux/validator/mass/service/tests/e2e/test_service.py b/source/extensions/omni.flux.validator.mass.service/omni/flux/validator/mass/service/tests/e2e/test_service.py
new file mode 100644
index 000000000..dd81f63b3
--- /dev/null
+++ b/source/extensions/omni.flux.validator.mass.service/omni/flux/validator/mass/service/tests/e2e/test_service.py
@@ -0,0 +1,70 @@
+"""
+* SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+* SPDX-License-Identifier: Apache-2.0
+*
+* 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
+*
+* https://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.
+"""
+
+import unittest
+
+import omni.usd
+from omni.flux.service.factory import get_instance as get_service_factory_instance
+from omni.flux.utils.common.api import send_request
+from omni.kit.test import AsyncTestCase
+from omni.services.core import main
+
+
+class TestMassValidatorService(AsyncTestCase):
+ # Before running each test
+ async def setUp(self):
+ self.context = omni.usd.get_context()
+
+ factory = get_service_factory_instance()
+
+ # Register the service in the app
+ self.service = factory.get_plugin_from_name("MassValidatorService")()
+ main.register_router(router=self.service.router, prefix=self.service.prefix)
+
+ # After running each test
+ async def tearDown(self):
+ main.deregister_router(router=self.service.router, prefix=self.service.prefix)
+
+ self.service = None
+
+ if self.context.can_close_stage():
+ await self.context.close_stage_async()
+
+ self.context = None
+ self.project_path = None
+
+ @unittest.skip("Not implemented yet")
+ async def test_add_item_to_model_queue_works_as_expected(self):
+ # Arrange
+ pass
+
+ # Act
+ response = await send_request("POST", f"{self.service.prefix}/queue/model")
+
+ # Assert
+ self.assertEqual(response, {})
+
+ @unittest.skip("Not implemented yet")
+ async def test_add_item_to_material_queue_works_as_expected(self):
+ # Arrange
+ pass
+
+ # Act
+ response = await send_request("POST", f"{self.service.prefix}/queue/material")
+
+ # Assert
+ self.assertEqual(response, {})
diff --git a/source/extensions/omni.flux.validator.plugin.check.usd/config/extension.toml b/source/extensions/omni.flux.validator.plugin.check.usd/config/extension.toml
index 9a8eb2971..8d264c800 100644
--- a/source/extensions/omni.flux.validator.plugin.check.usd/config/extension.toml
+++ b/source/extensions/omni.flux.validator.plugin.check.usd/config/extension.toml
@@ -1,6 +1,6 @@
[package]
# Semantic Versionning is used: https://semver.org/
-version = "3.14.1"
+version = "3.14.2"
# Lists people or organizations that are considered the "authors" of the package.
authors = ["Damien Bataille "]
@@ -32,7 +32,7 @@ icon = "data/images/icon.png"
[dependencies]
"omni.client" = {}
"omni.flux.asset_importer.core" = {}
-"omni.flux.commands" = {} # For SetDefaultPrim command
+"omni.flux.commands" = {} # For SetDefaultPrim & CreateOrInsertSublayer commands
"omni.flux.info_icon.widget" = {}
"omni.flux.lookdev.core" = {}
"omni.flux.pip_archive" = {} # Required for pydantic
diff --git a/source/extensions/omni.flux.validator.plugin.check.usd/docs/CHANGELOG.md b/source/extensions/omni.flux.validator.plugin.check.usd/docs/CHANGELOG.md
index 2885747e1..09043ff4e 100644
--- a/source/extensions/omni.flux.validator.plugin.check.usd/docs/CHANGELOG.md
+++ b/source/extensions/omni.flux.validator.plugin.check.usd/docs/CHANGELOG.md
@@ -2,6 +2,10 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [3.14.2]
+### Fixed
+- Changed usages of the `CreateSublayer` command for `CreateOrInsertSublayer`
+
## [3.14.1]
## Changed
- Update to Kit 106.5
diff --git a/source/extensions/omni.flux.validator.plugin.check.usd/omni/flux/validator/plugin/check/usd/texture/mass_texture_preview.py b/source/extensions/omni.flux.validator.plugin.check.usd/omni/flux/validator/plugin/check/usd/texture/mass_texture_preview.py
index 95c1d12e5..c8d256c34 100644
--- a/source/extensions/omni.flux.validator.plugin.check.usd/omni/flux/validator/plugin/check/usd/texture/mass_texture_preview.py
+++ b/source/extensions/omni.flux.validator.plugin.check.usd/omni/flux/validator/plugin/check/usd/texture/mass_texture_preview.py
@@ -111,7 +111,7 @@ async def __deferred_open_output_file():
# here we want to add the current stage as a layer, and assign materials with texture(s) to the same
# binding than the default material of the lookdev stage
omni.kit.commands.execute(
- "CreateSublayer",
+ "CreateOrInsertSublayer",
layer_identifier=stage.GetRootLayer().identifier,
sublayer_position=0,
new_layer_path=schema_data.temp_usd,