mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-02 00:44:52 +01:00
Merge branch 'develop' into enhancement/OP-3751_Renaming_plugin_to_Ayon
This commit is contained in:
commit
0503bc76e0
60 changed files with 2920 additions and 376 deletions
|
|
@ -45,3 +45,6 @@ jobs:
|
|||
token: ${{ secrets.YNPUT_BOT_TOKEN }}
|
||||
user_email: ${{ secrets.CI_EMAIL }}
|
||||
user_name: ${{ secrets.CI_USER }}
|
||||
cu_api_key: ${{ secrets.CLICKUP_API_KEY }}
|
||||
cu_team_id: ${{ secrets.CLICKUP_TEAM_ID }}
|
||||
cu_field_id: ${{ secrets.CLICKUP_RELEASE_FIELD_ID }}
|
||||
|
|
|
|||
943
CHANGELOG.md
943
CHANGELOG.md
|
|
@ -1,5 +1,948 @@
|
|||
# Changelog
|
||||
|
||||
|
||||
## [3.15.4](https://github.com/ynput/OpenPype/tree/3.15.4)
|
||||
|
||||
|
||||
[Full Changelog](https://github.com/ynput/OpenPype/compare/3.15.3...3.15.4)
|
||||
|
||||
### **🆕 New features**
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Cant assign shaders to the ass file - OP-4859 <a href="https://github.com/ynput/OpenPype/pull/4460">#4460</a></summary>
|
||||
|
||||
<strong>Support AiStandIn nodes for look assignment.
|
||||
|
||||
</strong>Using operators we assign shaders and attribute/parameters to nodes within standins. Initially there is only support for a limited mount of attributes but we can add support as needed;
|
||||
```
|
||||
primaryVisibility
|
||||
castsShadows
|
||||
receiveShadows
|
||||
aiSelfShadows
|
||||
aiOpaque
|
||||
aiMatte
|
||||
aiVisibleInDiffuseTransmission
|
||||
aiVisibleInSpecularTransmission
|
||||
aiVisibleInVolume
|
||||
aiVisibleInDiffuseReflection
|
||||
aiVisibleInSpecularReflection
|
||||
aiSubdivUvSmoothing
|
||||
aiDispHeight
|
||||
aiDispPadding
|
||||
aiDispZeroValue
|
||||
aiStepSize
|
||||
aiVolumePadding
|
||||
aiSubdivType
|
||||
aiSubdivIterations
|
||||
```
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: GPU cache representation <a href="https://github.com/ynput/OpenPype/pull/4649">#4649</a></summary>
|
||||
|
||||
Implement GPU cache for model, animation and pointcache.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Houdini: Implement review family with opengl node <a href="https://github.com/ynput/OpenPype/pull/3839">#3839</a></summary>
|
||||
|
||||
<strong>Implements a first pass for Reviews publishing in Houdini. Resolves #2720
|
||||
|
||||
</strong>Uses the `opengl` ROP node to produce PNG images.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Camera focal length visible in review - OP-3278 <a href="https://github.com/ynput/OpenPype/pull/4531">#4531</a></summary>
|
||||
|
||||
<strong>Camera focal length visible in review.
|
||||
|
||||
</strong>Support camera focal length in review; static and dynamic.Resolves #3220
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Defining plugins to load on Maya start - OP-4994 <a href="https://github.com/ynput/OpenPype/pull/4714">#4714</a></summary>
|
||||
|
||||
Feature to define plugins to load on Maya launch.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Nuke, DL: Returning Suspended Publishing attribute <a href="https://github.com/ynput/OpenPype/pull/4715">#4715</a></summary>
|
||||
|
||||
Old Nuke Publisher's feature for suspended publishing job on render farm was added back to the current Publisher.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Settings UI: Allow setting a size hint for text fields <a href="https://github.com/ynput/OpenPype/pull/4821">#4821</a></summary>
|
||||
|
||||
Text entity have `minimum_lines_count` which allows to change minimum size hint of UI input.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>TrayPublisher: Move 'BatchMovieCreator' settings to 'create' subcategory <a href="https://github.com/ynput/OpenPype/pull/4827">#4827</a></summary>
|
||||
|
||||
Moved settings for `BatchMoviewCreator` into subcategory `create` in settings. Changes are made to match other hosts settings chema and structure.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
### **🚀 Enhancements**
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya looks: support for native Redshift texture format <a href="https://github.com/ynput/OpenPype/pull/2971">#2971</a></summary>
|
||||
|
||||
<strong>Add support for native Redshift textures handling. Closes #2599
|
||||
|
||||
</strong>Uses Redshift's Texture Processor executable to convert textures being used in renders to the Redshift ".rstexbin" format.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: custom namespace for references <a href="https://github.com/ynput/OpenPype/pull/4511">#4511</a></summary>
|
||||
|
||||
<strong>Adding an option in Project Settings > Maya > Loader plugins to set custom namespace. If no namespace is set, the default one is used.
|
||||
|
||||
</strong>
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Set correct framerange with handles on file opening <a href="https://github.com/ynput/OpenPype/pull/4664">#4664</a></summary>
|
||||
|
||||
Set the range of playback from the asset data, counting handles, to get the correct data when calling the "collect_animation_data" function.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Fix camera update <a href="https://github.com/ynput/OpenPype/pull/4751">#4751</a></summary>
|
||||
|
||||
Fix resetting any modelPanel to a different camera when loading a camera and updating.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Remove single assembly validation for animation instances <a href="https://github.com/ynput/OpenPype/pull/4840">#4840</a></summary>
|
||||
|
||||
Rig groups may now be parented to others groups when `includeParentHierarchy` attribute on the instance is "off".
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Optional control of display lights on playblast. <a href="https://github.com/ynput/OpenPype/pull/4145">#4145</a></summary>
|
||||
|
||||
<strong>Optional control of display lights on playblast.
|
||||
|
||||
</strong>Giving control to what display lights are on the playblasts.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Kitsu: note family requirements <a href="https://github.com/ynput/OpenPype/pull/4551">#4551</a></summary>
|
||||
|
||||
<strong>Allowing to add family requirements to `IntegrateKitsuNote` task status change.
|
||||
|
||||
</strong>Adds a `Family requirements` setting to `Integrate Kitsu Note`, so you can add requirements to determine if kitsu task status should be changed based on which families are published or not. For instance you could have the status change only if another subset than workfile is published (but workfile can still be included) by adding an item set to `Not equal` and `workfile`.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Deactivate closed Kitsu projects on OP <a href="https://github.com/ynput/OpenPype/pull/4619">#4619</a></summary>
|
||||
|
||||
Deactivate project on OP when the project is closed on Kitsu.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Suggestion to change capture labels. <a href="https://github.com/ynput/OpenPype/pull/4691">#4691</a></summary>
|
||||
|
||||
Change capture labels.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Houdini: Change node type for OpenPypeContext `null` -> `subnet` <a href="https://github.com/ynput/OpenPype/pull/4745">#4745</a></summary>
|
||||
|
||||
Change the node type for OpenPype's hidden context node in Houdini from `null` to `subnet`. This fixes #4734
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>General: Extract burnin hosts filters <a href="https://github.com/ynput/OpenPype/pull/4749">#4749</a></summary>
|
||||
|
||||
Removed hosts filter from ExtractBurnin plugin. Instance without representations won't cause crash but just skip the instance. We've discovered because Blender already has review but did not create burnins.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Global: Improve speed of Collect Custom Staging Directory <a href="https://github.com/ynput/OpenPype/pull/4768">#4768</a></summary>
|
||||
|
||||
Improve speed of Collect Custom Staging Directory.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>General: Anatomy templates formatting <a href="https://github.com/ynput/OpenPype/pull/4773">#4773</a></summary>
|
||||
|
||||
Added option to format only single template from anatomy instead of formatting all of them all the time. Formatting of all templates is causing slowdowns e.g. during publishing of hundreds of instances.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Harmony: Handle zip files with deeper structure <a href="https://github.com/ynput/OpenPype/pull/4782">#4782</a></summary>
|
||||
|
||||
External Harmony zip files might contain one additional level with scene name.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Unreal: Use common logic to configure executable <a href="https://github.com/ynput/OpenPype/pull/4788">#4788</a></summary>
|
||||
|
||||
Unreal Editor location and version was autodetected. This easied configuration in some cases but was not flexible enought. This PR is changing the way Unreal Editor location is set, unifying it with the logic other hosts are using.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Github: Grammar tweaks + uppercase issue title <a href="https://github.com/ynput/OpenPype/pull/4813">#4813</a></summary>
|
||||
|
||||
Tweak some of the grammar in the issue form templates.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Houdini: Allow creation of publish instances via Houdini TAB menu <a href="https://github.com/ynput/OpenPype/pull/4831">#4831</a></summary>
|
||||
|
||||
Register the available Creator's as houdini tools so an artist can add publish instances via the Houdini TAB node search menu from within the network editor.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
### **🐛 Bug fixes**
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Fix Collect Render for V-Ray, Redshift and Renderman for missing colorspace <a href="https://github.com/ynput/OpenPype/pull/4650">#4650</a></summary>
|
||||
|
||||
Fix Collect Render not working for Redshift, V-Ray and Renderman due to missing `colorspace` argument to `RenderProduct` dataclass.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Xgen fixes <a href="https://github.com/ynput/OpenPype/pull/4707">#4707</a></summary>
|
||||
|
||||
Fix for Xgen extraction of world parented nodes and validation for required namespace.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Fix extract review and thumbnail for Maya 2020 <a href="https://github.com/ynput/OpenPype/pull/4744">#4744</a></summary>
|
||||
|
||||
Fix playblasting in Maya 2020 with override viewport options enabled. Fixes #4730.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: local variable 'arnold_standins' referenced before assignment - OP-5542 <a href="https://github.com/ynput/OpenPype/pull/4778">#4778</a></summary>
|
||||
|
||||
MayaLookAssigner erroring when MTOA is not loaded:
|
||||
```
|
||||
# Traceback (most recent call last):
|
||||
# File "\openpype\hosts\maya\tools\mayalookassigner\app.py", line 272, in on_process_selected
|
||||
# nodes = list(set(item["nodes"]).difference(arnold_standins))
|
||||
# UnboundLocalError: local variable 'arnold_standins' referenced before assignment
|
||||
```
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Fix getting view and display in Maya 2020 - OP-5035 <a href="https://github.com/ynput/OpenPype/pull/4795">#4795</a></summary>
|
||||
|
||||
The `view_transform` returns a different format in Maya 2020. Fixes #4540 (hopefully).
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Fix Look Maya 2020 Py2 support for Extract Look <a href="https://github.com/ynput/OpenPype/pull/4808">#4808</a></summary>
|
||||
|
||||
Fix Extract Look supporting python 2.7 for Maya 2020.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Fix Validate Mesh Overlapping UVs plugin <a href="https://github.com/ynput/OpenPype/pull/4816">#4816</a></summary>
|
||||
|
||||
Fix typo in the code where a maya command returns a `list` instead of `str`.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Fix tile rendering with Vray - OP-5566 <a href="https://github.com/ynput/OpenPype/pull/4832">#4832</a></summary>
|
||||
|
||||
Fixes tile rendering with Vray.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Deadline: checking existing frames fails when there is number in file name <a href="https://github.com/ynput/OpenPype/pull/4698">#4698</a></summary>
|
||||
|
||||
Previous implementation of validator failed on files with any other number in rendered file names.Used regular expression pattern now handles numbers in the file names (eg "Main_beauty.v001.1001.exr", "Main_beauty_v001.1001.exr", "Main_beauty.1001.1001.exr") but not numbers behind frames (eg. "Main_beauty.1001.v001.exr")
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Validate Render Settings. <a href="https://github.com/ynput/OpenPype/pull/4735">#4735</a></summary>
|
||||
|
||||
Fixes error message when using attribute validation.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>General: Hero version sites recalculation <a href="https://github.com/ynput/OpenPype/pull/4737">#4737</a></summary>
|
||||
|
||||
Sites recalculation in integrate hero version did expect that it is integrated exactly same amount of files as in previous integration. This is not the case in many cases, so the sites recalculation happens in a different way, first are prepared all sites from previous representation files, and all of them are added to each file in new representation.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Houdini: Fix collect current file <a href="https://github.com/ynput/OpenPype/pull/4739">#4739</a></summary>
|
||||
|
||||
Fixes the Workfile publishing getting added into every instance being published from Houdini
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Global: Fix Extract Burnin + Colorspace functions for conflicting python environments with PYTHONHOME <a href="https://github.com/ynput/OpenPype/pull/4740">#4740</a></summary>
|
||||
|
||||
This fixes the running of openpype processes from e.g. a host with conflicting python versions that had `PYTHONHOME` said additionally to `PYTHONPATH`, like e.g. Houdini Py3.7 together with OpenPype Py3.9 when using Extract Burnin for a review in #3839This fix applies to Extract Burnin and some of the colorspace functions that use `run_openpype_process`
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Harmony: render what is in timeline in Harmony locally <a href="https://github.com/ynput/OpenPype/pull/4741">#4741</a></summary>
|
||||
|
||||
Previously it wasn't possible to render according to what was set in Timeline in scene start/end, just by what it was set in whole timeline.This allows artist to override what is in DB with what they require (with disabled `Validate Scene Settings`). Now artist can extend scene by additional frames, that shouldn't be rendered, but which might be desired.Removed explicit set scene settings (eg. applying frames and resolution directly to the scene after launch), added separate menu item to allow artist to do it themselves.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Extract Review settings add Use Background Gradient <a href="https://github.com/ynput/OpenPype/pull/4747">#4747</a></summary>
|
||||
|
||||
Add Display Gradient Background toggle in settings to fix support for setting flat background color for reviews.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Nuke: publisher is offering review on write families on demand <a href="https://github.com/ynput/OpenPype/pull/4755">#4755</a></summary>
|
||||
|
||||
Original idea where reviewable toggle will be offered in publisher on demand is fixed and now `review` attribute can be disabled in settings.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Workfiles: keep Browse always enabled <a href="https://github.com/ynput/OpenPype/pull/4766">#4766</a></summary>
|
||||
|
||||
Browse might make sense even if there are no workfiles present, actually in that case it makes the most sense (eg. I want to locate workfile from outside - from Desktop for example).
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Global: label key in instance data is optional <a href="https://github.com/ynput/OpenPype/pull/4779">#4779</a></summary>
|
||||
|
||||
Collect OTIO review plugin is not crashing if `label` key is missing in instance data.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Loader: Fix missing variable <a href="https://github.com/ynput/OpenPype/pull/4781">#4781</a></summary>
|
||||
|
||||
There is missing variable `handles` in loader tool after https://github.com/ynput/OpenPype/pull/4746. The variable was renamed to `handles_label` and is initialized to `None` if handles are not available.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Nuke: Workfile Template builder fixes <a href="https://github.com/ynput/OpenPype/pull/4783">#4783</a></summary>
|
||||
|
||||
Popup window after Nuke start is not showing. Knobs with X/Y coordination on nodes where were converted from placeholders are not added if `keepPlaceholders` is witched off.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Add family filter 'review' to burnin profile with focal length <a href="https://github.com/ynput/OpenPype/pull/4791">#4791</a></summary>
|
||||
|
||||
Avoid profile burnin with `focalLength` key for renders, but use only for playblast reviews.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>add farm instance to the render collector in 3dsMax <a href="https://github.com/ynput/OpenPype/pull/4794">#4794</a></summary>
|
||||
|
||||
bug fix for the failure of submitting publish job in 3dsmax
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Publisher: Plugin active attribute is respected <a href="https://github.com/ynput/OpenPype/pull/4798">#4798</a></summary>
|
||||
|
||||
Publisher consider plugin's `active` attribute, so the plugin is not processed when `active` is set to `False`. But we use the attribute in `OptionalPyblishPluginMixin` for different purposes, so I've added hack bypass of the active state validation when plugin inherit from the mixin. This is temporary solution which cannot be changed until all hosts use Publisher otherwise global plugins would be broken. Also plugins which have `enabled` set to `False` are filtered out -> this happened only when automated settings were applied and the settings contained `"enabled"` key se to `False`.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Nuke: settings and optional attribute in publisher for some validators <a href="https://github.com/ynput/OpenPype/pull/4811">#4811</a></summary>
|
||||
|
||||
New publisher is supporting optional switch for plugins which is offered in Publisher in Right panel. Some plugins were missing this switch and also settings which would offer the optionality.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Settings: Version settings popup fix <a href="https://github.com/ynput/OpenPype/pull/4822">#4822</a></summary>
|
||||
|
||||
Version completer popup have issues on some platforms, this should fix those edge cases. Also fixed issue when completer stayed shown fater reset (save).
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Hiero/Nuke: adding monitorOut key to settings <a href="https://github.com/ynput/OpenPype/pull/4826">#4826</a></summary>
|
||||
|
||||
New versions of Hiero were introduced with new colorspace property for Monitor Out. It have been added into project settings. Also added new config names into settings enumerator option.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Nuke: removed default workfile template builder preset <a href="https://github.com/ynput/OpenPype/pull/4835">#4835</a></summary>
|
||||
|
||||
Default for workfile template builder should have been empty.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>TVPaint: Review can be made from any instance <a href="https://github.com/ynput/OpenPype/pull/4843">#4843</a></summary>
|
||||
|
||||
Add `"review"` tag to output of extract sequence if instance is marked for review. At this moment only instances with family `"review"` were able to define input for `ExtractReview` plugin which is not right.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
### **🔀 Refactored code**
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Deadline: Remove unused FramesPerTask job info submission <a href="https://github.com/ynput/OpenPype/pull/4657">#4657</a></summary>
|
||||
|
||||
Remove unused `FramesPerTask` job info submission to Deadline.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Remove pymel dependency <a href="https://github.com/ynput/OpenPype/pull/4724">#4724</a></summary>
|
||||
|
||||
Refactors code written using `pymel` to use standard maya python libraries instead like `maya.cmds` or `maya.api.OpenMaya`
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Remove "preview" data from representation <a href="https://github.com/ynput/OpenPype/pull/4759">#4759</a></summary>
|
||||
|
||||
Remove "preview" data from representation
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Collect Review cleanup code for attached subsets <a href="https://github.com/ynput/OpenPype/pull/4720">#4720</a></summary>
|
||||
|
||||
Refactor some code for Maya: Collect Review for attached subsets.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Refactor: Remove `handles`, `edit_in` and `edit_out` backwards compatibility <a href="https://github.com/ynput/OpenPype/pull/4746">#4746</a></summary>
|
||||
|
||||
Removes backward compatibiliy fallback for data called `handles`, `edit_in` and `edit_out`.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
### **📃 Documentation**
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Bump webpack from 5.69.1 to 5.76.1 in /website <a href="https://github.com/ynput/OpenPype/pull/4624">#4624</a></summary>
|
||||
|
||||
Bumps [webpack](https://github.com/webpack/webpack) from 5.69.1 to 5.76.1.
|
||||
<details>
|
||||
<summary>Release notes</summary>
|
||||
<p><em>Sourced from <a href="https://github.com/webpack/webpack/releases">webpack's releases</a>.</em></p>
|
||||
<blockquote>
|
||||
<h2>v5.76.1</h2>
|
||||
<h2>Fixed</h2>
|
||||
<ul>
|
||||
<li>Added <code>assert/strict</code> built-in to <code>NodeTargetPlugin</code></li>
|
||||
</ul>
|
||||
<h2>Revert</h2>
|
||||
<ul>
|
||||
<li>Improve performance of <code>hashRegExp</code> lookup by <a href="https://github.com/ryanwilsonperkin"><code>@ryanwilsonperkin</code></a> in <a href="https://redirect.github.com/webpack/webpack/pull/16759">webpack/webpack#16759</a></li>
|
||||
</ul>
|
||||
<h2>v5.76.0</h2>
|
||||
<h2>Bugfixes</h2>
|
||||
<ul>
|
||||
<li>Avoid cross-realm object access by <a href="https://github.com/Jack-Works"><code>@Jack-Works</code></a> in <a href="https://redirect.github.com/webpack/webpack/pull/16500">webpack/webpack#16500</a></li>
|
||||
<li>Improve hash performance via conditional initialization by <a href="https://github.com/lvivski"><code>@lvivski</code></a> in <a href="https://redirect.github.com/webpack/webpack/pull/16491">webpack/webpack#16491</a></li>
|
||||
<li>Serialize <code>generatedCode</code> info to fix bug in asset module cache restoration by <a href="https://github.com/ryanwilsonperkin"><code>@ryanwilsonperkin</code></a> in <a href="https://redirect.github.com/webpack/webpack/pull/16703">webpack/webpack#16703</a></li>
|
||||
<li>Improve performance of <code>hashRegExp</code> lookup by <a href="https://github.com/ryanwilsonperkin"><code>@ryanwilsonperkin</code></a> in <a href="https://redirect.github.com/webpack/webpack/pull/16759">webpack/webpack#16759</a></li>
|
||||
</ul>
|
||||
<h2>Features</h2>
|
||||
<ul>
|
||||
<li>add <code>target</code> to <code>LoaderContext</code> type by <a href="https://github.com/askoufis"><code>@askoufis</code></a> in <a href="https://redirect.github.com/webpack/webpack/pull/16781">webpack/webpack#16781</a></li>
|
||||
</ul>
|
||||
<h2>Security</h2>
|
||||
<ul>
|
||||
<li><a href="https://github.com/advisories/GHSA-3rfm-jhwj-7488">CVE-2022-37603</a> fixed by <a href="https://github.com/akhilgkrishnan"><code>@akhilgkrishnan</code></a> in <a href="https://redirect.github.com/webpack/webpack/pull/16446">webpack/webpack#16446</a></li>
|
||||
</ul>
|
||||
<h2>Repo Changes</h2>
|
||||
<ul>
|
||||
<li>Fix HTML5 logo in README by <a href="https://github.com/jakebailey"><code>@jakebailey</code></a> in <a href="https://redirect.github.com/webpack/webpack/pull/16614">webpack/webpack#16614</a></li>
|
||||
<li>Replace TypeScript logo in README by <a href="https://github.com/jakebailey"><code>@jakebailey</code></a> in <a href="https://redirect.github.com/webpack/webpack/pull/16613">webpack/webpack#16613</a></li>
|
||||
<li>Update actions/cache dependencies by <a href="https://github.com/piwysocki"><code>@piwysocki</code></a> in <a href="https://redirect.github.com/webpack/webpack/pull/16493">webpack/webpack#16493</a></li>
|
||||
</ul>
|
||||
<h2>New Contributors</h2>
|
||||
<ul>
|
||||
<li><a href="https://github.com/Jack-Works"><code>@Jack-Works</code></a> made their first contribution in <a href="https://redirect.github.com/webpack/webpack/pull/16500">webpack/webpack#16500</a></li>
|
||||
<li><a href="https://github.com/lvivski"><code>@lvivski</code></a> made their first contribution in <a href="https://redirect.github.com/webpack/webpack/pull/16491">webpack/webpack#16491</a></li>
|
||||
<li><a href="https://github.com/jakebailey"><code>@jakebailey</code></a> made their first contribution in <a href="https://redirect.github.com/webpack/webpack/pull/16614">webpack/webpack#16614</a></li>
|
||||
<li><a href="https://github.com/akhilgkrishnan"><code>@akhilgkrishnan</code></a> made their first contribution in <a href="https://redirect.github.com/webpack/webpack/pull/16446">webpack/webpack#16446</a></li>
|
||||
<li><a href="https://github.com/ryanwilsonperkin"><code>@ryanwilsonperkin</code></a> made their first contribution in <a href="https://redirect.github.com/webpack/webpack/pull/16703">webpack/webpack#16703</a></li>
|
||||
<li><a href="https://github.com/piwysocki"><code>@piwysocki</code></a> made their first contribution in <a href="https://redirect.github.com/webpack/webpack/pull/16493">webpack/webpack#16493</a></li>
|
||||
<li><a href="https://github.com/askoufis"><code>@askoufis</code></a> made their first contribution in <a href="https://redirect.github.com/webpack/webpack/pull/16781">webpack/webpack#16781</a></li>
|
||||
</ul>
|
||||
<p><strong>Full Changelog</strong>: <a href="https://github.com/webpack/webpack/compare/v5.75.0...v5.76.0">https://github.com/webpack/webpack/compare/v5.75.0...v5.76.0</a></p>
|
||||
<h2>v5.75.0</h2>
|
||||
<h1>Bugfixes</h1>
|
||||
<ul>
|
||||
<li><code>experiments.*</code> normalize to <code>false</code> when opt-out</li>
|
||||
<li>avoid <code>NaN%</code></li>
|
||||
<li>show the correct error when using a conflicting chunk name in code</li>
|
||||
<li>HMR code tests existance of <code>window</code> before trying to access it</li>
|
||||
<li>fix <code>eval-nosources-*</code> actually exclude sources</li>
|
||||
<li>fix race condition where no module is returned from processing module</li>
|
||||
<li>fix position of standalong semicolon in runtime code</li>
|
||||
</ul>
|
||||
<h1>Features</h1>
|
||||
<ul>
|
||||
<li>add support for <code>@import</code> to extenal CSS when using experimental CSS in node</li>
|
||||
</ul>
|
||||
<!-- raw HTML omitted -->
|
||||
</blockquote>
|
||||
<p>... (truncated)</p>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Commits</summary>
|
||||
<ul>
|
||||
<li><a href="https://github.com/webpack/webpack/commit/21be52b681c477f8ebc41c1b0e7a7a8ac4fa7008"><code>21be52b</code></a> Merge pull request <a href="https://redirect.github.com/webpack/webpack/issues/16804">#16804</a> from webpack/chore-patch-release</li>
|
||||
<li><a href="https://github.com/webpack/webpack/commit/1cce945dd6c3576d37d3940a0233fd087ce3f6ff"><code>1cce945</code></a> chore(release): 5.76.1</li>
|
||||
<li><a href="https://github.com/webpack/webpack/commit/e76ad9e724410f10209caa2ba86875ca8cf5ed61"><code>e76ad9e</code></a> Merge pull request <a href="https://redirect.github.com/webpack/webpack/issues/16803">#16803</a> from ryanwilsonperkin/revert-16759-real-content-has...</li>
|
||||
<li><a href="https://github.com/webpack/webpack/commit/52b1b0e4ada7c11e7f1b4f3d69b50684938c684e"><code>52b1b0e</code></a> Revert "Improve performance of hashRegExp lookup"</li>
|
||||
<li><a href="https://github.com/webpack/webpack/commit/c989143379d344543e4161fec60f3a21beb9e3ce"><code>c989143</code></a> Merge pull request <a href="https://redirect.github.com/webpack/webpack/issues/16766">#16766</a> from piranna/patch-1</li>
|
||||
<li><a href="https://github.com/webpack/webpack/commit/710eaf4ddaea505e040a24beeb45a769f9e3761b"><code>710eaf4</code></a> Merge pull request <a href="https://redirect.github.com/webpack/webpack/issues/16789">#16789</a> from dmichon-msft/contenthash-hashsalt</li>
|
||||
<li><a href="https://github.com/webpack/webpack/commit/5d6446822aff579a5d3d9503ec2a16437d2f71d1"><code>5d64468</code></a> Merge pull request <a href="https://redirect.github.com/webpack/webpack/issues/16792">#16792</a> from webpack/update-version</li>
|
||||
<li><a href="https://github.com/webpack/webpack/commit/67af5ec1f05fb7cf06be6acf27353aef105ddcbc"><code>67af5ec</code></a> chore(release): 5.76.0</li>
|
||||
<li><a href="https://github.com/webpack/webpack/commit/97b1718720c33f1b17302a74c5284b01e02ec001"><code>97b1718</code></a> Merge pull request <a href="https://redirect.github.com/webpack/webpack/issues/16781">#16781</a> from askoufis/loader-context-target-type</li>
|
||||
<li><a href="https://github.com/webpack/webpack/commit/b84efe6224b276bf72e4c5e2f4e76acddfaeef07"><code>b84efe6</code></a> Merge pull request <a href="https://redirect.github.com/webpack/webpack/issues/16759">#16759</a> from ryanwilsonperkin/real-content-hash-regex-perf</li>
|
||||
<li>Additional commits viewable in <a href="https://github.com/webpack/webpack/compare/v5.69.1...v5.76.1">compare view</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Maintainer changes</summary>
|
||||
<p>This version was pushed to npm by <a href="https://www.npmjs.com/~evilebottnawi">evilebottnawi</a>, a new releaser for webpack since your current version.</p>
|
||||
</details>
|
||||
<br />
|
||||
|
||||
|
||||
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
|
||||
|
||||
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.
|
||||
|
||||
[//]: # (dependabot-automerge-start)
|
||||
[//]: # (dependabot-automerge-end)
|
||||
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary>Dependabot commands and options</summary>
|
||||
<br />
|
||||
|
||||
You can trigger Dependabot actions by commenting on this PR:
|
||||
- `@dependabot rebase` will rebase this PR
|
||||
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
|
||||
- `@dependabot merge` will merge this PR after your CI passes on it
|
||||
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
|
||||
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
|
||||
- `@dependabot reopen` will reopen this PR if it is closed
|
||||
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
|
||||
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
|
||||
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
|
||||
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
|
||||
- `@dependabot use these labels` will set the current labels as the default for future PRs for this repo and language
|
||||
- `@dependabot use these reviewers` will set the current reviewers as the default for future PRs for this repo and language
|
||||
- `@dependabot use these assignees` will set the current assignees as the default for future PRs for this repo and language
|
||||
- `@dependabot use this milestone` will set the current milestone as the default for future PRs for this repo and language
|
||||
|
||||
You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ynput/OpenPype/network/alerts).
|
||||
|
||||
</details>
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Documentation: Add Extract Burnin documentation <a href="https://github.com/ynput/OpenPype/pull/4765">#4765</a></summary>
|
||||
|
||||
Add documentation for Extract Burnin global plugin settings.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Documentation: Move publisher related tips to publisher area <a href="https://github.com/ynput/OpenPype/pull/4772">#4772</a></summary>
|
||||
|
||||
Move publisher related tips for After Effects artist documentation to the correct position.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Documentation: Add extra terminology to the key concepts glossary <a href="https://github.com/ynput/OpenPype/pull/4838">#4838</a></summary>
|
||||
|
||||
Tweak some of the key concepts in the documentation.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
### **Merged pull requests**
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya: Refactor Extract Look with dedicated processors for maketx <a href="https://github.com/ynput/OpenPype/pull/4711">#4711</a></summary>
|
||||
|
||||
Refactor Maya extract look to fix some issues:
|
||||
- [x] Allow Extraction with maketx with OCIO Color Management enabled in Maya.
|
||||
- [x] Fix file hashing so it includes arguments to maketx, so that when arguments change it correctly generates a new hash
|
||||
- [x] Fix maketx destination colorspace when OCIO is enabled
|
||||
- [x] Use pre-collected colorspaces of the resources instead of trying to retrieve again in Extract Look
|
||||
- [x] Fix colorspace attributes being reinterpreted by maya on export (fix remapping) - goal is to resolve #2337
|
||||
- [x] Fix support for checking config path of maya default OCIO config (due to using `lib.get_color_management_preferences` which remaps that path)
|
||||
- [x] Merged in #2971 to refactor MakeTX into TextureProcessor and also support generating Redshift `.rstexbin` files. - goal is to resolve #2599
|
||||
- [x] Allow custom arguments to `maketx` from OpenPype Settings like mentioned here by @fabiaserra for arguments like: `--monochrome-detect`, `--opaque-detect`, `--checknan`.
|
||||
- [x] Actually fix the code and make it work. :) (I'll try to keep below checkboxes in sync with my code changes)
|
||||
- [x] Publishing without texture processor should work (no maketx + no rstexbin)
|
||||
- [x] Publishing with maketx should work
|
||||
- [x] Publishing with rstexbin should work
|
||||
- [x] Test it. (This is just me doing some test-runs, please still test the PR!)
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Maya template builder load all assets linked to the shot <a href="https://github.com/ynput/OpenPype/pull/4761">#4761</a></summary>
|
||||
|
||||
Problem
|
||||
All the assets of the ftrack project are loaded and not those linked to the shot
|
||||
|
||||
How get error
|
||||
Open maya in the context of shot, then build a new scene with the "Build Workfile from template" button in "OpenPype" menu.
|
||||

|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Global: Do not force instance data with frame ranges of the asset <a href="https://github.com/ynput/OpenPype/pull/4383">#4383</a></summary>
|
||||
|
||||
<strong>This aims to resolve #4317
|
||||
|
||||
</strong>
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Cosmetics: Fix some grammar in docstrings and messages (and some code) <a href="https://github.com/ynput/OpenPype/pull/4752">#4752</a></summary>
|
||||
|
||||
Tweak some grammar in codebase
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Deadline: Submit publish job fails due root work hardcode - OP-5528 <a href="https://github.com/ynput/OpenPype/pull/4775">#4775</a></summary>
|
||||
|
||||
Generating config templates was hardcoded to `root[work]`. This PR fixes that.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>CreateContext: Added option to remove Unknown attributes <a href="https://github.com/ynput/OpenPype/pull/4776">#4776</a></summary>
|
||||
|
||||
Added option to remove attributes with UnkownAttrDef on instances. Pop of key will also remove the attribute definition from attribute values, so they're not recreated again.
|
||||
|
||||
|
||||
___
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
|
||||
## [3.15.3](https://github.com/ynput/OpenPype/tree/3.15.3)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ RUN yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.n
|
|||
|
||||
# we need to build our own patchelf
|
||||
WORKDIR /temp-patchelf
|
||||
RUN git clone https://github.com/NixOS/patchelf.git . \
|
||||
RUN git clone -b 0.17.0 --single-branch https://github.com/NixOS/patchelf.git . \
|
||||
&& source scl_source enable devtoolset-7 \
|
||||
&& ./bootstrap.sh \
|
||||
&& ./configure \
|
||||
|
|
|
|||
|
|
@ -42,13 +42,5 @@ class AddLastWorkfileToLaunchArgs(PreLaunchHook):
|
|||
self.log.info("Current context does not have any workfile yet.")
|
||||
return
|
||||
|
||||
# Determine whether to open workfile post initialization.
|
||||
if self.host_name == "maya":
|
||||
key = "open_workfile_post_initialization"
|
||||
if self.data["project_settings"]["maya"][key]:
|
||||
self.log.debug("Opening workfile post initialization.")
|
||||
self.data["env"]["OPENPYPE_" + key.upper()] = "1"
|
||||
return
|
||||
|
||||
# Add path to workfile to arguments
|
||||
self.launch_context.launch_args.append(last_workfile)
|
||||
|
|
|
|||
|
|
@ -53,10 +53,10 @@ class CollectWorkfile(pyblish.api.ContextPlugin):
|
|||
"active": True,
|
||||
"asset": asset_entity["name"],
|
||||
"task": task,
|
||||
"frameStart": asset_entity["data"]["frameStart"],
|
||||
"frameEnd": asset_entity["data"]["frameEnd"],
|
||||
"handleStart": asset_entity["data"]["handleStart"],
|
||||
"handleEnd": asset_entity["data"]["handleEnd"],
|
||||
"frameStart": context.data['frameStart'],
|
||||
"frameEnd": context.data['frameEnd'],
|
||||
"handleStart": context.data['handleStart'],
|
||||
"handleEnd": context.data['handleEnd'],
|
||||
"fps": asset_entity["data"]["fps"],
|
||||
"resolutionWidth": asset_entity["data"].get(
|
||||
"resolutionWidth",
|
||||
|
|
|
|||
|
|
@ -104,3 +104,6 @@ class AbcLoader(load.LoaderPlugin):
|
|||
|
||||
node = container["node"]
|
||||
node.destroy()
|
||||
|
||||
def switch(self, container, representation):
|
||||
self.update(container, representation)
|
||||
|
|
|
|||
|
|
@ -73,3 +73,6 @@ class AbcArchiveLoader(load.LoaderPlugin):
|
|||
|
||||
node = container["node"]
|
||||
node.destroy()
|
||||
|
||||
def switch(self, container, representation):
|
||||
self.update(container, representation)
|
||||
|
|
|
|||
|
|
@ -106,3 +106,6 @@ class BgeoLoader(load.LoaderPlugin):
|
|||
|
||||
node = container["node"]
|
||||
node.destroy()
|
||||
|
||||
def switch(self, container, representation):
|
||||
self.update(container, representation)
|
||||
|
|
|
|||
|
|
@ -192,3 +192,6 @@ class CameraLoader(load.LoaderPlugin):
|
|||
|
||||
new_node.moveToGoodPosition()
|
||||
return new_node
|
||||
|
||||
def switch(self, container, representation):
|
||||
self.update(container, representation)
|
||||
|
|
|
|||
|
|
@ -125,3 +125,6 @@ class ImageLoader(load.LoaderPlugin):
|
|||
prefix, padding, suffix = first_fname.rsplit(".", 2)
|
||||
fname = ".".join([prefix, "$F{}".format(len(padding)), suffix])
|
||||
return os.path.join(root, fname).replace("\\", "/")
|
||||
|
||||
def switch(self, container, representation):
|
||||
self.update(container, representation)
|
||||
|
|
|
|||
|
|
@ -79,3 +79,6 @@ class USDSublayerLoader(load.LoaderPlugin):
|
|||
|
||||
node = container["node"]
|
||||
node.destroy()
|
||||
|
||||
def switch(self, container, representation):
|
||||
self.update(container, representation)
|
||||
|
|
|
|||
|
|
@ -79,3 +79,6 @@ class USDReferenceLoader(load.LoaderPlugin):
|
|||
|
||||
node = container["node"]
|
||||
node.destroy()
|
||||
|
||||
def switch(self, container, representation):
|
||||
self.update(container, representation)
|
||||
|
|
|
|||
|
|
@ -102,3 +102,6 @@ class VdbLoader(load.LoaderPlugin):
|
|||
|
||||
node = container["node"]
|
||||
node.destroy()
|
||||
|
||||
def switch(self, container, representation):
|
||||
self.update(container, representation)
|
||||
|
|
|
|||
|
|
@ -128,14 +128,14 @@ class AvalonURIOutputProcessor(base.OutputProcessorBase):
|
|||
if not asset_doc:
|
||||
raise RuntimeError("Invalid asset name: '%s'" % asset)
|
||||
|
||||
formatted_anatomy = anatomy.format({
|
||||
template_obj = anatomy.templates_obj["publish"]["path"]
|
||||
path = template_obj.format_strict({
|
||||
"project": PROJECT,
|
||||
"asset": asset_doc["name"],
|
||||
"subset": subset,
|
||||
"representation": ext,
|
||||
"version": 0 # stub version zero
|
||||
})
|
||||
path = formatted_anatomy["publish"]["path"]
|
||||
|
||||
# Remove the version folder
|
||||
subset_folder = os.path.dirname(os.path.dirname(path))
|
||||
|
|
|
|||
24
openpype/hosts/max/hooks/force_startup_script.py
Normal file
24
openpype/hosts/max/hooks/force_startup_script.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Pre-launch to force 3ds max startup script."""
|
||||
from openpype.lib import PreLaunchHook
|
||||
import os
|
||||
|
||||
|
||||
class ForceStartupScript(PreLaunchHook):
|
||||
"""Inject OpenPype environment to 3ds max.
|
||||
|
||||
Note that this works in combination whit 3dsmax startup script that
|
||||
is translating it back to PYTHONPATH for cases when 3dsmax drops PYTHONPATH
|
||||
environment.
|
||||
|
||||
Hook `GlobalHostDataHook` must be executed before this hook.
|
||||
"""
|
||||
app_groups = ["3dsmax"]
|
||||
order = 11
|
||||
|
||||
def execute(self):
|
||||
startup_args = [
|
||||
"-U",
|
||||
"MAXScript",
|
||||
f"{os.getenv('OPENPYPE_ROOT')}\\openpype\\hosts\\max\\startup\\startup.ms"] # noqa
|
||||
self.launch_context.launch_args.append(startup_args)
|
||||
|
|
@ -32,12 +32,17 @@ from openpype.pipeline import (
|
|||
load_container,
|
||||
registered_host,
|
||||
)
|
||||
from openpype.pipeline.create import (
|
||||
legacy_create,
|
||||
get_legacy_creator_by_name,
|
||||
)
|
||||
from openpype.pipeline.context_tools import (
|
||||
get_current_asset_name,
|
||||
get_current_project_asset,
|
||||
get_current_project_name,
|
||||
get_current_task_name
|
||||
)
|
||||
from openpype.lib.profiles_filtering import filter_profiles
|
||||
|
||||
|
||||
self = sys.modules[__name__]
|
||||
|
|
@ -117,6 +122,18 @@ FLOAT_FPS = {23.98, 23.976, 29.97, 47.952, 59.94}
|
|||
|
||||
RENDERLIKE_INSTANCE_FAMILIES = ["rendering", "vrayscene"]
|
||||
|
||||
DISPLAY_LIGHTS_VALUES = [
|
||||
"project_settings", "default", "all", "selected", "flat", "none"
|
||||
]
|
||||
DISPLAY_LIGHTS_LABELS = [
|
||||
"Use Project Settings",
|
||||
"Default Lighting",
|
||||
"All Lights",
|
||||
"Selected Lights",
|
||||
"Flat Lighting",
|
||||
"No Lights"
|
||||
]
|
||||
|
||||
|
||||
def get_main_window():
|
||||
"""Acquire Maya's main window"""
|
||||
|
|
@ -2140,17 +2157,23 @@ def set_scene_resolution(width, height, pixelAspect):
|
|||
cmds.setAttr("%s.pixelAspect" % control_node, pixelAspect)
|
||||
|
||||
|
||||
def get_frame_range():
|
||||
"""Get the current assets frame range and handles."""
|
||||
def get_frame_range(include_animation_range=False):
|
||||
"""Get the current assets frame range and handles.
|
||||
|
||||
Args:
|
||||
include_animation_range (bool, optional): Whether to include
|
||||
`animationStart` and `animationEnd` keys to define the outer
|
||||
range of the timeline. It is excluded by default.
|
||||
|
||||
Returns:
|
||||
dict: Asset's expected frame range values.
|
||||
|
||||
"""
|
||||
|
||||
# Set frame start/end
|
||||
project_name = get_current_project_name()
|
||||
task_name = get_current_task_name()
|
||||
asset_name = get_current_asset_name()
|
||||
asset = get_asset_by_name(project_name, asset_name)
|
||||
settings = get_project_settings(project_name)
|
||||
include_handles_settings = settings["maya"]["include_handles"]
|
||||
current_task = asset.get("data").get("tasks").get(task_name)
|
||||
|
||||
frame_start = asset["data"].get("frameStart")
|
||||
frame_end = asset["data"].get("frameEnd")
|
||||
|
|
@ -2162,32 +2185,39 @@ def get_frame_range():
|
|||
handle_start = asset["data"].get("handleStart") or 0
|
||||
handle_end = asset["data"].get("handleEnd") or 0
|
||||
|
||||
animation_start = frame_start
|
||||
animation_end = frame_end
|
||||
|
||||
include_handles = include_handles_settings["include_handles_default"]
|
||||
for item in include_handles_settings["per_task_type"]:
|
||||
if current_task["type"] in item["task_type"]:
|
||||
include_handles = item["include_handles"]
|
||||
break
|
||||
if include_handles:
|
||||
animation_start -= int(handle_start)
|
||||
animation_end += int(handle_end)
|
||||
|
||||
cmds.playbackOptions(
|
||||
minTime=frame_start,
|
||||
maxTime=frame_end,
|
||||
animationStartTime=animation_start,
|
||||
animationEndTime=animation_end
|
||||
)
|
||||
cmds.currentTime(frame_start)
|
||||
|
||||
return {
|
||||
frame_range = {
|
||||
"frameStart": frame_start,
|
||||
"frameEnd": frame_end,
|
||||
"handleStart": handle_start,
|
||||
"handleEnd": handle_end
|
||||
}
|
||||
if include_animation_range:
|
||||
# The animation range values are only included to define whether
|
||||
# the Maya time slider should include the handles or not.
|
||||
# Some usages of this function use the full dictionary to define
|
||||
# instance attributes for which we want to exclude the animation
|
||||
# keys. That is why these are excluded by default.
|
||||
task_name = get_current_task_name()
|
||||
settings = get_project_settings(project_name)
|
||||
include_handles_settings = settings["maya"]["include_handles"]
|
||||
current_task = asset.get("data").get("tasks").get(task_name)
|
||||
|
||||
animation_start = frame_start
|
||||
animation_end = frame_end
|
||||
|
||||
include_handles = include_handles_settings["include_handles_default"]
|
||||
for item in include_handles_settings["per_task_type"]:
|
||||
if current_task["type"] in item["task_type"]:
|
||||
include_handles = item["include_handles"]
|
||||
break
|
||||
if include_handles:
|
||||
animation_start -= int(handle_start)
|
||||
animation_end += int(handle_end)
|
||||
|
||||
frame_range["animationStart"] = animation_start
|
||||
frame_range["animationEnd"] = animation_end
|
||||
|
||||
return frame_range
|
||||
|
||||
|
||||
def reset_frame_range(playback=True, render=True, fps=True):
|
||||
|
|
@ -2206,18 +2236,23 @@ def reset_frame_range(playback=True, render=True, fps=True):
|
|||
)
|
||||
set_scene_fps(fps)
|
||||
|
||||
frame_range = get_frame_range()
|
||||
frame_range = get_frame_range(include_animation_range=True)
|
||||
if not frame_range:
|
||||
# No frame range data found for asset
|
||||
return
|
||||
|
||||
frame_start = frame_range["frameStart"] - int(frame_range["handleStart"])
|
||||
frame_end = frame_range["frameEnd"] + int(frame_range["handleEnd"])
|
||||
frame_start = frame_range["frameStart"]
|
||||
frame_end = frame_range["frameEnd"]
|
||||
animation_start = frame_range["animationStart"]
|
||||
animation_end = frame_range["animationEnd"]
|
||||
|
||||
if playback:
|
||||
cmds.playbackOptions(minTime=frame_start)
|
||||
cmds.playbackOptions(maxTime=frame_end)
|
||||
cmds.playbackOptions(animationStartTime=frame_start)
|
||||
cmds.playbackOptions(animationEndTime=frame_end)
|
||||
cmds.playbackOptions(minTime=frame_start)
|
||||
cmds.playbackOptions(maxTime=frame_end)
|
||||
cmds.playbackOptions(
|
||||
minTime=frame_start,
|
||||
maxTime=frame_end,
|
||||
animationStartTime=animation_start,
|
||||
animationEndTime=animation_end
|
||||
)
|
||||
cmds.currentTime(frame_start)
|
||||
|
||||
if render:
|
||||
|
|
@ -3855,3 +3890,98 @@ def get_all_children(nodes):
|
|||
iterator.next() # noqa: B305
|
||||
|
||||
return list(traversed)
|
||||
|
||||
|
||||
def get_capture_preset(task_name, task_type, subset, project_settings, log):
|
||||
"""Get capture preset for playblasting.
|
||||
|
||||
Logic for transitioning from old style capture preset to new capture preset
|
||||
profiles.
|
||||
|
||||
Args:
|
||||
task_name (str): Task name.
|
||||
take_type (str): Task type.
|
||||
subset (str): Subset name.
|
||||
project_settings (dict): Project settings.
|
||||
log (object): Logging object.
|
||||
"""
|
||||
capture_preset = None
|
||||
filtering_criteria = {
|
||||
"hosts": "maya",
|
||||
"families": "review",
|
||||
"task_names": task_name,
|
||||
"task_types": task_type,
|
||||
"subset": subset
|
||||
}
|
||||
|
||||
plugin_settings = project_settings["maya"]["publish"]["ExtractPlayblast"]
|
||||
if plugin_settings["profiles"]:
|
||||
profile = filter_profiles(
|
||||
plugin_settings["profiles"],
|
||||
filtering_criteria,
|
||||
logger=log
|
||||
)
|
||||
capture_preset = profile.get("capture_preset")
|
||||
else:
|
||||
log.warning("No profiles present for Extract Playblast")
|
||||
|
||||
# Backward compatibility for deprecated Extract Playblast settings
|
||||
# without profiles.
|
||||
if capture_preset is None:
|
||||
log.debug(
|
||||
"Falling back to deprecated Extract Playblast capture preset "
|
||||
"because no new style playblast profiles are defined."
|
||||
)
|
||||
capture_preset = plugin_settings["capture_preset"]
|
||||
|
||||
return capture_preset or {}
|
||||
|
||||
|
||||
def create_rig_animation_instance(nodes, context, namespace, log=None):
|
||||
"""Create an animation publish instance for loaded rigs.
|
||||
|
||||
See the RecreateRigAnimationInstance inventory action on how to use this
|
||||
for loaded rig containers.
|
||||
|
||||
Arguments:
|
||||
nodes (list): Member nodes of the rig instance.
|
||||
context (dict): Representation context of the rig container
|
||||
namespace (str): Namespace of the rig container
|
||||
log (logging.Logger, optional): Logger to log to if provided
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
"""
|
||||
output = next((node for node in nodes if
|
||||
node.endswith("out_SET")), None)
|
||||
controls = next((node for node in nodes if
|
||||
node.endswith("controls_SET")), None)
|
||||
|
||||
assert output, "No out_SET in rig, this is a bug."
|
||||
assert controls, "No controls_SET in rig, this is a bug."
|
||||
|
||||
# Find the roots amongst the loaded nodes
|
||||
roots = (
|
||||
cmds.ls(nodes, assemblies=True, long=True) or
|
||||
get_highest_in_hierarchy(nodes)
|
||||
)
|
||||
assert roots, "No root nodes in rig, this is a bug."
|
||||
|
||||
asset = legacy_io.Session["AVALON_ASSET"]
|
||||
dependency = str(context["representation"]["_id"])
|
||||
|
||||
if log:
|
||||
log.info("Creating subset: {}".format(namespace))
|
||||
|
||||
# Create the animation instance
|
||||
creator_plugin = get_legacy_creator_by_name("CreateAnimation")
|
||||
with maintained_selection():
|
||||
cmds.select([output, controls] + roots, noExpand=True)
|
||||
legacy_create(
|
||||
creator_plugin,
|
||||
name=namespace,
|
||||
asset=asset,
|
||||
options={"useSelection": True},
|
||||
data={"dependencies": dependency}
|
||||
)
|
||||
|
|
|
|||
29
openpype/hosts/maya/hooks/pre_auto_load_plugins.py
Normal file
29
openpype/hosts/maya/hooks/pre_auto_load_plugins.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
from openpype.lib import PreLaunchHook
|
||||
|
||||
|
||||
class MayaPreAutoLoadPlugins(PreLaunchHook):
|
||||
"""Define -noAutoloadPlugins command flag."""
|
||||
|
||||
# Before AddLastWorkfileToLaunchArgs
|
||||
order = 9
|
||||
app_groups = ["maya"]
|
||||
|
||||
def execute(self):
|
||||
|
||||
# Ignore if there's no last workfile to start.
|
||||
if not self.data.get("start_last_workfile"):
|
||||
return
|
||||
|
||||
maya_settings = self.data["project_settings"]["maya"]
|
||||
enabled = maya_settings["explicit_plugins_loading"]["enabled"]
|
||||
if enabled:
|
||||
# Force disable the `AddLastWorkfileToLaunchArgs`.
|
||||
self.data.pop("start_last_workfile")
|
||||
|
||||
# Force post initialization so our dedicated plug-in load can run
|
||||
# prior to Maya opening a scene file.
|
||||
key = "OPENPYPE_OPEN_WORKFILE_POST_INITIALIZATION"
|
||||
self.launch_context.env[key] = "1"
|
||||
|
||||
self.log.debug("Explicit plugins loading.")
|
||||
self.launch_context.launch_args.append("-noAutoloadPlugins")
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
from openpype.lib import PreLaunchHook
|
||||
|
||||
|
||||
class MayaPreOpenWorkfilePostInitialization(PreLaunchHook):
|
||||
"""Define whether open last workfile should run post initialize."""
|
||||
|
||||
# Before AddLastWorkfileToLaunchArgs.
|
||||
order = 9
|
||||
app_groups = ["maya"]
|
||||
|
||||
def execute(self):
|
||||
|
||||
# Ignore if there's no last workfile to start.
|
||||
if not self.data.get("start_last_workfile"):
|
||||
return
|
||||
|
||||
maya_settings = self.data["project_settings"]["maya"]
|
||||
enabled = maya_settings["open_workfile_post_initialization"]
|
||||
if enabled:
|
||||
# Force disable the `AddLastWorkfileToLaunchArgs`.
|
||||
self.data.pop("start_last_workfile")
|
||||
|
||||
self.log.debug("Opening workfile post initialization.")
|
||||
key = "OPENPYPE_OPEN_WORKFILE_POST_INITIALIZATION"
|
||||
self.launch_context.env[key] = "1"
|
||||
|
|
@ -7,6 +7,12 @@ from openpype.hosts.maya.api import (
|
|||
class CreateAnimation(plugin.Creator):
|
||||
"""Animation output for character rigs"""
|
||||
|
||||
# We hide the animation creator from the UI since the creation of it
|
||||
# is automated upon loading a rig. There's an inventory action to recreate
|
||||
# it for loaded rigs if by chance someone deleted the animation instance.
|
||||
# Note: This setting is actually applied from project settings
|
||||
enabled = False
|
||||
|
||||
name = "animationDefault"
|
||||
label = "Animation"
|
||||
family = "animation"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
import os
|
||||
from collections import OrderedDict
|
||||
import json
|
||||
|
||||
from openpype.hosts.maya.api import (
|
||||
lib,
|
||||
plugin
|
||||
)
|
||||
from openpype.settings import get_project_settings
|
||||
from openpype.pipeline import get_current_project_name, get_current_task_name
|
||||
from openpype.client import get_asset_by_name
|
||||
|
||||
|
||||
class CreateReview(plugin.Creator):
|
||||
|
|
@ -32,6 +38,23 @@ class CreateReview(plugin.Creator):
|
|||
super(CreateReview, self).__init__(*args, **kwargs)
|
||||
data = OrderedDict(**self.data)
|
||||
|
||||
project_name = get_current_project_name()
|
||||
asset_doc = get_asset_by_name(project_name, data["asset"])
|
||||
task_name = get_current_task_name()
|
||||
preset = lib.get_capture_preset(
|
||||
task_name,
|
||||
asset_doc["data"]["tasks"][task_name]["type"],
|
||||
data["subset"],
|
||||
get_project_settings(project_name),
|
||||
self.log
|
||||
)
|
||||
if os.environ.get("OPENPYPE_DEBUG") == "1":
|
||||
self.log.debug(
|
||||
"Using preset: {}".format(
|
||||
json.dumps(preset, indent=4, sort_keys=True)
|
||||
)
|
||||
)
|
||||
|
||||
# Option for using Maya or asset frame range in settings.
|
||||
frame_range = lib.get_frame_range()
|
||||
if self.useMayaTimeline:
|
||||
|
|
@ -40,12 +63,14 @@ class CreateReview(plugin.Creator):
|
|||
data[key] = value
|
||||
|
||||
data["fps"] = lib.collect_animation_data(fps=True)["fps"]
|
||||
data["review_width"] = self.Width
|
||||
data["review_height"] = self.Height
|
||||
data["isolate"] = self.isolate
|
||||
|
||||
data["keepImages"] = self.keepImages
|
||||
data["imagePlane"] = self.imagePlane
|
||||
data["transparency"] = self.transparency
|
||||
data["panZoom"] = self.panZoom
|
||||
data["review_width"] = preset["Resolution"]["width"]
|
||||
data["review_height"] = preset["Resolution"]["height"]
|
||||
data["isolate"] = preset["Generic"]["isolate_view"]
|
||||
data["imagePlane"] = preset["Viewport Options"]["imagePlane"]
|
||||
data["panZoom"] = preset["Generic"]["pan_zoom"]
|
||||
data["displayLights"] = lib.DISPLAY_LIGHTS_LABELS
|
||||
|
||||
self.data = data
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
from openpype.pipeline import (
|
||||
InventoryAction,
|
||||
get_representation_context
|
||||
)
|
||||
from openpype.hosts.maya.api.lib import (
|
||||
create_rig_animation_instance,
|
||||
get_container_members,
|
||||
)
|
||||
|
||||
|
||||
class RecreateRigAnimationInstance(InventoryAction):
|
||||
"""Recreate animation publish instance for loaded rigs"""
|
||||
|
||||
label = "Recreate rig animation instance"
|
||||
icon = "wrench"
|
||||
color = "#888888"
|
||||
|
||||
@staticmethod
|
||||
def is_compatible(container):
|
||||
return (
|
||||
container.get("loader") == "ReferenceLoader"
|
||||
and container.get("name", "").startswith("rig")
|
||||
)
|
||||
|
||||
def process(self, containers):
|
||||
|
||||
for container in containers:
|
||||
# todo: delete an existing entry if it exist or skip creation
|
||||
|
||||
namespace = container["namespace"]
|
||||
representation_id = container["representation"]
|
||||
context = get_representation_context(representation_id)
|
||||
nodes = get_container_members(container)
|
||||
|
||||
create_rig_animation_instance(nodes, context, namespace)
|
||||
|
|
@ -4,16 +4,12 @@ import contextlib
|
|||
from maya import cmds
|
||||
|
||||
from openpype.settings import get_project_settings
|
||||
from openpype.pipeline import legacy_io
|
||||
from openpype.pipeline.create import (
|
||||
legacy_create,
|
||||
get_legacy_creator_by_name,
|
||||
)
|
||||
import openpype.hosts.maya.api.plugin
|
||||
from openpype.hosts.maya.api.lib import (
|
||||
maintained_selection,
|
||||
get_container_members,
|
||||
parent_nodes
|
||||
parent_nodes,
|
||||
create_rig_animation_instance
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -114,9 +110,6 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
|
|||
icon = "code-fork"
|
||||
color = "orange"
|
||||
|
||||
# Name of creator class that will be used to create animation instance
|
||||
animation_creator_name = "CreateAnimation"
|
||||
|
||||
def process_reference(self, context, name, namespace, options):
|
||||
import maya.cmds as cmds
|
||||
|
||||
|
|
@ -220,37 +213,10 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
|
|||
self._lock_camera_transforms(members)
|
||||
|
||||
def _post_process_rig(self, name, namespace, context, options):
|
||||
|
||||
output = next((node for node in self if
|
||||
node.endswith("out_SET")), None)
|
||||
controls = next((node for node in self if
|
||||
node.endswith("controls_SET")), None)
|
||||
|
||||
assert output, "No out_SET in rig, this is a bug."
|
||||
assert controls, "No controls_SET in rig, this is a bug."
|
||||
|
||||
# Find the roots amongst the loaded nodes
|
||||
roots = cmds.ls(self[:], assemblies=True, long=True)
|
||||
assert roots, "No root nodes in rig, this is a bug."
|
||||
|
||||
asset = legacy_io.Session["AVALON_ASSET"]
|
||||
dependency = str(context["representation"]["_id"])
|
||||
|
||||
self.log.info("Creating subset: {}".format(namespace))
|
||||
|
||||
# Create the animation instance
|
||||
creator_plugin = get_legacy_creator_by_name(
|
||||
self.animation_creator_name
|
||||
nodes = self[:]
|
||||
create_rig_animation_instance(
|
||||
nodes, context, namespace, log=self.log
|
||||
)
|
||||
with maintained_selection():
|
||||
cmds.select([output, controls] + roots, noExpand=True)
|
||||
legacy_create(
|
||||
creator_plugin,
|
||||
name=namespace,
|
||||
asset=asset,
|
||||
options={"useSelection": True},
|
||||
data={"dependencies": dependency}
|
||||
)
|
||||
|
||||
def _lock_camera_transforms(self, nodes):
|
||||
cameras = cmds.ls(nodes, type="camera")
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import pyblish.api
|
|||
|
||||
from openpype.client import get_subset_by_name
|
||||
from openpype.pipeline import legacy_io, KnownPublishError
|
||||
from openpype.hosts.maya.api.lib import get_attribute_input
|
||||
from openpype.hosts.maya.api import lib
|
||||
|
||||
|
||||
class CollectReview(pyblish.api.InstancePlugin):
|
||||
|
|
@ -29,26 +29,37 @@ class CollectReview(pyblish.api.InstancePlugin):
|
|||
|
||||
# get cameras
|
||||
members = instance.data['setMembers']
|
||||
cameras = cmds.ls(members, long=True,
|
||||
dag=True, cameras=True)
|
||||
self.log.debug('members: {}'.format(members))
|
||||
|
||||
# validate required settings
|
||||
if len(cameras) == 0:
|
||||
raise KnownPublishError("No camera found in review "
|
||||
"instance: {}".format(instance))
|
||||
elif len(cameras) > 2:
|
||||
raise KnownPublishError(
|
||||
"Only a single camera is allowed for a review instance but "
|
||||
"more than one camera found in review instance: {}. "
|
||||
"Cameras found: {}".format(instance, ", ".join(cameras)))
|
||||
|
||||
camera = cameras[0]
|
||||
self.log.debug('camera: {}'.format(camera))
|
||||
cameras = cmds.ls(members, long=True, dag=True, cameras=True)
|
||||
camera = cameras[0] if cameras else None
|
||||
|
||||
context = instance.context
|
||||
objectset = context.data['objectsets']
|
||||
|
||||
# Convert enum attribute index to string for Display Lights.
|
||||
index = instance.data.get("displayLights", 0)
|
||||
display_lights = lib.DISPLAY_LIGHTS_VALUES[index]
|
||||
if display_lights == "project_settings":
|
||||
settings = instance.context.data["project_settings"]
|
||||
settings = settings["maya"]["publish"]["ExtractPlayblast"]
|
||||
settings = settings["capture_preset"]["Viewport Options"]
|
||||
display_lights = settings["displayLights"]
|
||||
|
||||
# Collect camera focal length.
|
||||
burninDataMembers = instance.data.get("burninDataMembers", {})
|
||||
if camera is not None:
|
||||
attr = camera + ".focalLength"
|
||||
if lib.get_attribute_input(attr):
|
||||
start = instance.data["frameStart"]
|
||||
end = instance.data["frameEnd"] + 1
|
||||
time_range = range(int(start), int(end))
|
||||
focal_length = [cmds.getAttr(attr, time=t) for t in time_range]
|
||||
else:
|
||||
focal_length = cmds.getAttr(attr)
|
||||
|
||||
burninDataMembers["focalLength"] = focal_length
|
||||
|
||||
# Account for nested instances like model.
|
||||
reviewable_subsets = list(set(members) & set(objectset))
|
||||
if reviewable_subsets:
|
||||
if len(reviewable_subsets) > 1:
|
||||
|
|
@ -75,11 +86,14 @@ class CollectReview(pyblish.api.InstancePlugin):
|
|||
else:
|
||||
data['families'] = ['review']
|
||||
|
||||
data["cameras"] = cameras
|
||||
data['review_camera'] = camera
|
||||
data['frameStartFtrack'] = instance.data["frameStartHandle"]
|
||||
data['frameEndFtrack'] = instance.data["frameEndHandle"]
|
||||
data['frameStartHandle'] = instance.data["frameStartHandle"]
|
||||
data['frameEndHandle'] = instance.data["frameEndHandle"]
|
||||
data['handleStart'] = instance.data["handleStart"]
|
||||
data['handleEnd'] = instance.data["handleEnd"]
|
||||
data["frameStart"] = instance.data["frameStart"]
|
||||
data["frameEnd"] = instance.data["frameEnd"]
|
||||
data['step'] = instance.data['step']
|
||||
|
|
@ -89,6 +103,8 @@ class CollectReview(pyblish.api.InstancePlugin):
|
|||
data["isolate"] = instance.data["isolate"]
|
||||
data["panZoom"] = instance.data.get("panZoom", False)
|
||||
data["panel"] = instance.data["panel"]
|
||||
data["displayLights"] = display_lights
|
||||
data["burninDataMembers"] = burninDataMembers
|
||||
|
||||
# The review instance must be active
|
||||
cmds.setAttr(str(instance) + '.active', 1)
|
||||
|
|
@ -109,11 +125,14 @@ class CollectReview(pyblish.api.InstancePlugin):
|
|||
self.log.debug("Existing subsets found, keep legacy name.")
|
||||
instance.data['subset'] = legacy_subset_name
|
||||
|
||||
instance.data["cameras"] = cameras
|
||||
instance.data['review_camera'] = camera
|
||||
instance.data['frameStartFtrack'] = \
|
||||
instance.data["frameStartHandle"]
|
||||
instance.data['frameEndFtrack'] = \
|
||||
instance.data["frameEndHandle"]
|
||||
instance.data["displayLights"] = display_lights
|
||||
instance.data["burninDataMembers"] = burninDataMembers
|
||||
|
||||
# make ftrack publishable
|
||||
instance.data.setdefault("families", []).append('ftrack')
|
||||
|
|
@ -155,20 +174,3 @@ class CollectReview(pyblish.api.InstancePlugin):
|
|||
audio_data.append(get_audio_node_data(node))
|
||||
|
||||
instance.data["audio"] = audio_data
|
||||
|
||||
# Collect focal length.
|
||||
attr = camera + ".focalLength"
|
||||
if get_attribute_input(attr):
|
||||
start = instance.data["frameStart"]
|
||||
end = instance.data["frameEnd"] + 1
|
||||
focal_length = [
|
||||
cmds.getAttr(attr, time=t) for t in range(int(start), int(end))
|
||||
]
|
||||
else:
|
||||
focal_length = cmds.getAttr(attr)
|
||||
|
||||
key = "focalLength"
|
||||
try:
|
||||
instance.data["burninDataMembers"][key] = focal_length
|
||||
except KeyError:
|
||||
instance.data["burninDataMembers"] = {key: focal_length}
|
||||
|
|
|
|||
|
|
@ -34,13 +34,15 @@ class ExtractPlayblast(publish.Extractor):
|
|||
families = ["review"]
|
||||
optional = True
|
||||
capture_preset = {}
|
||||
profiles = None
|
||||
|
||||
def _capture(self, preset):
|
||||
self.log.info(
|
||||
"Using preset:\n{}".format(
|
||||
json.dumps(preset, sort_keys=True, indent=4)
|
||||
if os.environ.get("OPENPYPE_DEBUG") == "1":
|
||||
self.log.debug(
|
||||
"Using preset: {}".format(
|
||||
json.dumps(preset, indent=4, sort_keys=True)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
path = capture.capture(log=self.log, **preset)
|
||||
self.log.debug("playblast path {}".format(path))
|
||||
|
|
@ -65,12 +67,25 @@ class ExtractPlayblast(publish.Extractor):
|
|||
# get cameras
|
||||
camera = instance.data["review_camera"]
|
||||
|
||||
preset = lib.load_capture_preset(data=self.capture_preset)
|
||||
# Grab capture presets from the project settings
|
||||
capture_presets = self.capture_preset
|
||||
task_data = instance.data["anatomyData"].get("task", {})
|
||||
capture_preset = lib.get_capture_preset(
|
||||
task_data.get("name"),
|
||||
task_data.get("type"),
|
||||
instance.data["subset"],
|
||||
instance.context.data["project_settings"],
|
||||
self.log
|
||||
)
|
||||
|
||||
preset = lib.load_capture_preset(data=capture_preset)
|
||||
|
||||
# "isolate_view" will already have been applied at creation, so we'll
|
||||
# ignore it here.
|
||||
preset.pop("isolate_view")
|
||||
|
||||
# Set resolution variables from capture presets
|
||||
width_preset = capture_presets["Resolution"]["width"]
|
||||
height_preset = capture_presets["Resolution"]["height"]
|
||||
width_preset = capture_preset["Resolution"]["width"]
|
||||
height_preset = capture_preset["Resolution"]["height"]
|
||||
|
||||
# Set resolution variables from asset values
|
||||
asset_data = instance.data["assetEntity"]["data"]
|
||||
asset_width = asset_data.get("resolutionWidth")
|
||||
|
|
@ -115,14 +130,19 @@ class ExtractPlayblast(publish.Extractor):
|
|||
cmds.currentTime(refreshFrameInt - 1, edit=True)
|
||||
cmds.currentTime(refreshFrameInt, edit=True)
|
||||
|
||||
# Use displayLights setting from instance
|
||||
key = "displayLights"
|
||||
preset["viewport_options"][key] = instance.data[key]
|
||||
|
||||
# Override transparency if requested.
|
||||
transparency = instance.data.get("transparency", 0)
|
||||
if transparency != 0:
|
||||
preset["viewport2_options"]["transparencyAlgorithm"] = transparency
|
||||
|
||||
# Isolate view is requested by having objects in the set besides a
|
||||
# camera.
|
||||
if preset.pop("isolate_view", False) and instance.data.get("isolate"):
|
||||
# camera. If there is only 1 member it'll be the camera because we
|
||||
# validate to have 1 camera only.
|
||||
if instance.data["isolate"] and len(instance.data["setMembers"]) > 1:
|
||||
preset["isolate"] = instance.data["setMembers"]
|
||||
|
||||
# Show/Hide image planes on request.
|
||||
|
|
@ -157,7 +177,7 @@ class ExtractPlayblast(publish.Extractor):
|
|||
)
|
||||
|
||||
override_viewport_options = (
|
||||
capture_presets["Viewport Options"]["override_viewport_options"]
|
||||
capture_preset["Viewport Options"]["override_viewport_options"]
|
||||
)
|
||||
|
||||
# Force viewer to False in call to capture because we have our own
|
||||
|
|
@ -233,8 +253,8 @@ class ExtractPlayblast(publish.Extractor):
|
|||
collected_files = collected_files[0]
|
||||
|
||||
representation = {
|
||||
"name": self.capture_preset["Codec"]["compression"],
|
||||
"ext": self.capture_preset["Codec"]["compression"],
|
||||
"name": capture_preset["Codec"]["compression"],
|
||||
"ext": capture_preset["Codec"]["compression"],
|
||||
"files": collected_files,
|
||||
"stagingDir": stagingdir,
|
||||
"frameStart": start,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
import glob
|
||||
import tempfile
|
||||
import json
|
||||
|
||||
import capture
|
||||
|
||||
|
|
@ -27,22 +28,25 @@ class ExtractThumbnail(publish.Extractor):
|
|||
|
||||
camera = instance.data["review_camera"]
|
||||
|
||||
maya_setting = instance.context.data["project_settings"]["maya"]
|
||||
plugin_setting = maya_setting["publish"]["ExtractPlayblast"]
|
||||
capture_preset = plugin_setting["capture_preset"]
|
||||
task_data = instance.data["anatomyData"].get("task", {})
|
||||
capture_preset = lib.get_capture_preset(
|
||||
task_data.get("name"),
|
||||
task_data.get("type"),
|
||||
instance.data["subset"],
|
||||
instance.context.data["project_settings"],
|
||||
self.log
|
||||
)
|
||||
|
||||
preset = lib.load_capture_preset(data=capture_preset)
|
||||
|
||||
# "isolate_view" will already have been applied at creation, so we'll
|
||||
# ignore it here.
|
||||
preset.pop("isolate_view")
|
||||
|
||||
override_viewport_options = (
|
||||
capture_preset["Viewport Options"]["override_viewport_options"]
|
||||
)
|
||||
|
||||
try:
|
||||
preset = lib.load_capture_preset(data=capture_preset)
|
||||
except KeyError as ke:
|
||||
self.log.error("Error loading capture presets: {}".format(str(ke)))
|
||||
preset = {}
|
||||
self.log.info("Using viewport preset: {}".format(preset))
|
||||
|
||||
# preset["off_screen"] = False
|
||||
|
||||
preset["camera"] = camera
|
||||
preset["start_frame"] = instance.data["frameStart"]
|
||||
preset["end_frame"] = instance.data["frameStart"]
|
||||
|
|
@ -58,10 +62,9 @@ class ExtractThumbnail(publish.Extractor):
|
|||
"overscan": 1.0,
|
||||
"depthOfField": cmds.getAttr("{0}.depthOfField".format(camera)),
|
||||
}
|
||||
capture_presets = capture_preset
|
||||
# Set resolution variables from capture presets
|
||||
width_preset = capture_presets["Resolution"]["width"]
|
||||
height_preset = capture_presets["Resolution"]["height"]
|
||||
width_preset = capture_preset["Resolution"]["width"]
|
||||
height_preset = capture_preset["Resolution"]["height"]
|
||||
# Set resolution variables from asset values
|
||||
asset_data = instance.data["assetEntity"]["data"]
|
||||
asset_width = asset_data.get("resolutionWidth")
|
||||
|
|
@ -104,14 +107,19 @@ class ExtractThumbnail(publish.Extractor):
|
|||
cmds.currentTime(refreshFrameInt - 1, edit=True)
|
||||
cmds.currentTime(refreshFrameInt, edit=True)
|
||||
|
||||
# Use displayLights setting from instance
|
||||
key = "displayLights"
|
||||
preset["viewport_options"][key] = instance.data[key]
|
||||
|
||||
# Override transparency if requested.
|
||||
transparency = instance.data.get("transparency", 0)
|
||||
if transparency != 0:
|
||||
preset["viewport2_options"]["transparencyAlgorithm"] = transparency
|
||||
|
||||
# Isolate view is requested by having objects in the set besides a
|
||||
# camera.
|
||||
if preset.pop("isolate_view", False) and instance.data.get("isolate"):
|
||||
# camera. If there is only 1 member it'll be the camera because we
|
||||
# validate to have 1 camera only.
|
||||
if instance.data["isolate"] and len(instance.data["setMembers"]) > 1:
|
||||
preset["isolate"] = instance.data["setMembers"]
|
||||
|
||||
# Show or Hide Image Plane
|
||||
|
|
@ -139,6 +147,13 @@ class ExtractThumbnail(publish.Extractor):
|
|||
preset.update(panel_preset)
|
||||
cmds.setFocus(panel)
|
||||
|
||||
if os.environ.get("OPENPYPE_DEBUG") == "1":
|
||||
self.log.debug(
|
||||
"Using preset: {}".format(
|
||||
json.dumps(preset, indent=4, sort_keys=True)
|
||||
)
|
||||
)
|
||||
|
||||
path = capture.capture(**preset)
|
||||
playblast = self._fix_playblast_output_path(path)
|
||||
|
||||
|
|
|
|||
|
|
@ -65,9 +65,10 @@ class ExtractXgen(publish.Extractor):
|
|||
)
|
||||
cmds.delete(set(children) - set(shapes))
|
||||
|
||||
duplicate_transform = cmds.parent(
|
||||
duplicate_transform, world=True
|
||||
)[0]
|
||||
if cmds.listRelatives(duplicate_transform, parent=True):
|
||||
duplicate_transform = cmds.parent(
|
||||
duplicate_transform, world=True
|
||||
)[0]
|
||||
|
||||
duplicate_nodes.append(duplicate_transform)
|
||||
|
||||
|
|
|
|||
30
openpype/hosts/maya/plugins/publish/validate_review.py
Normal file
30
openpype/hosts/maya/plugins/publish/validate_review.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import pyblish.api
|
||||
|
||||
from openpype.pipeline.publish import (
|
||||
ValidateContentsOrder, PublishValidationError
|
||||
)
|
||||
|
||||
|
||||
class ValidateReview(pyblish.api.InstancePlugin):
|
||||
"""Validate review."""
|
||||
|
||||
order = ValidateContentsOrder
|
||||
label = "Validate Review"
|
||||
families = ["review"]
|
||||
|
||||
def process(self, instance):
|
||||
cameras = instance.data["cameras"]
|
||||
|
||||
# validate required settings
|
||||
if len(cameras) == 0:
|
||||
raise PublishValidationError(
|
||||
"No camera found in review instance: {}".format(instance)
|
||||
)
|
||||
elif len(cameras) > 2:
|
||||
raise PublishValidationError(
|
||||
"Only a single camera is allowed for a review instance but "
|
||||
"more than one camera found in review instance: {}. "
|
||||
"Cameras found: {}".format(instance, ", ".join(cameras))
|
||||
)
|
||||
|
||||
self.log.debug('camera: {}'.format(instance.data["review_camera"]))
|
||||
|
|
@ -57,3 +57,16 @@ class ValidateXgen(pyblish.api.InstancePlugin):
|
|||
json.dumps(inactive_modifiers, indent=4, sort_keys=True)
|
||||
)
|
||||
)
|
||||
|
||||
# We need a namespace else there will be a naming conflict when
|
||||
# extracting because of stripping namespaces and parenting to world.
|
||||
node_names = [instance.data["xgmPalette"]]
|
||||
for _, connections in instance.data["xgenConnections"].items():
|
||||
node_names.append(connections["transform"].split(".")[0])
|
||||
|
||||
non_namespaced_nodes = [n for n in node_names if ":" not in n]
|
||||
if non_namespaced_nodes:
|
||||
raise PublishValidationError(
|
||||
"Could not find namespace on {}. Namespace is required for"
|
||||
" xgen publishing.".format(non_namespaced_nodes)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import os
|
||||
from functools import partial
|
||||
|
||||
from openpype.settings import get_project_settings
|
||||
from openpype.pipeline import install_host
|
||||
|
|
@ -13,24 +12,41 @@ install_host(host)
|
|||
|
||||
print("Starting OpenPype usersetup...")
|
||||
|
||||
project_settings = get_project_settings(os.environ['AVALON_PROJECT'])
|
||||
|
||||
# Loading plugins explicitly.
|
||||
explicit_plugins_loading = project_settings["maya"]["explicit_plugins_loading"]
|
||||
if explicit_plugins_loading["enabled"]:
|
||||
def _explicit_load_plugins():
|
||||
for plugin in explicit_plugins_loading["plugins_to_load"]:
|
||||
if plugin["enabled"]:
|
||||
print("Loading plug-in: " + plugin["name"])
|
||||
try:
|
||||
cmds.loadPlugin(plugin["name"], quiet=True)
|
||||
except RuntimeError as e:
|
||||
print(e)
|
||||
|
||||
# We need to load plugins deferred as loading them directly does not work
|
||||
# correctly due to Maya's initialization.
|
||||
cmds.evalDeferred(
|
||||
_explicit_load_plugins,
|
||||
lowestPriority=True
|
||||
)
|
||||
|
||||
# Open Workfile Post Initialization.
|
||||
key = "OPENPYPE_OPEN_WORKFILE_POST_INITIALIZATION"
|
||||
if bool(int(os.environ.get(key, "0"))):
|
||||
def _log_and_open():
|
||||
path = os.environ["AVALON_LAST_WORKFILE"]
|
||||
print("Opening \"{}\"".format(path))
|
||||
cmds.file(path, open=True, force=True)
|
||||
cmds.evalDeferred(
|
||||
partial(
|
||||
cmds.file,
|
||||
os.environ["AVALON_LAST_WORKFILE"],
|
||||
open=True,
|
||||
force=True
|
||||
),
|
||||
_log_and_open,
|
||||
lowestPriority=True
|
||||
)
|
||||
|
||||
|
||||
# Build a shelf.
|
||||
settings = get_project_settings(os.environ['AVALON_PROJECT'])
|
||||
shelf_preset = settings['maya'].get('project_shelf')
|
||||
shelf_preset = project_settings['maya'].get('project_shelf')
|
||||
|
||||
if shelf_preset:
|
||||
project = os.environ["AVALON_PROJECT"]
|
||||
|
|
|
|||
97
openpype/hosts/maya/tools/mayalookassigner/alembic.py
Normal file
97
openpype/hosts/maya/tools/mayalookassigner/alembic.py
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Tools for loading looks to vray proxies."""
|
||||
import os
|
||||
from collections import defaultdict
|
||||
import logging
|
||||
|
||||
import six
|
||||
|
||||
import alembic.Abc
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_alembic_paths_by_property(filename, attr, verbose=False):
|
||||
# type: (str, str, bool) -> dict
|
||||
"""Return attribute value per objects in the Alembic file.
|
||||
|
||||
Reads an Alembic archive hierarchy and retrieves the
|
||||
value from the `attr` properties on the objects.
|
||||
|
||||
Args:
|
||||
filename (str): Full path to Alembic archive to read.
|
||||
attr (str): Id attribute.
|
||||
verbose (bool): Whether to verbosely log missing attributes.
|
||||
|
||||
Returns:
|
||||
dict: Mapping of node full path with its id
|
||||
|
||||
"""
|
||||
# Normalize alembic path
|
||||
filename = os.path.normpath(filename)
|
||||
filename = filename.replace("\\", "/")
|
||||
filename = str(filename) # path must be string
|
||||
|
||||
try:
|
||||
archive = alembic.Abc.IArchive(filename)
|
||||
except RuntimeError:
|
||||
# invalid alembic file - probably vrmesh
|
||||
log.warning("{} is not an alembic file".format(filename))
|
||||
return {}
|
||||
root = archive.getTop()
|
||||
|
||||
iterator = list(root.children)
|
||||
obj_ids = {}
|
||||
|
||||
for obj in iterator:
|
||||
name = obj.getFullName()
|
||||
|
||||
# include children for coming iterations
|
||||
iterator.extend(obj.children)
|
||||
|
||||
props = obj.getProperties()
|
||||
if props.getNumProperties() == 0:
|
||||
# Skip those without properties, e.g. '/materials' in a gpuCache
|
||||
continue
|
||||
|
||||
# THe custom attribute is under the properties' first container under
|
||||
# the ".arbGeomParams"
|
||||
prop = props.getProperty(0) # get base property
|
||||
|
||||
_property = None
|
||||
try:
|
||||
geo_params = prop.getProperty('.arbGeomParams')
|
||||
_property = geo_params.getProperty(attr)
|
||||
except KeyError:
|
||||
if verbose:
|
||||
log.debug("Missing attr on: {0}".format(name))
|
||||
continue
|
||||
|
||||
if not _property.isConstant():
|
||||
log.warning("Id not constant on: {0}".format(name))
|
||||
|
||||
# Get first value sample
|
||||
value = _property.getValue()[0]
|
||||
|
||||
obj_ids[name] = value
|
||||
|
||||
return obj_ids
|
||||
|
||||
|
||||
def get_alembic_ids_cache(path):
|
||||
# type: (str) -> dict
|
||||
"""Build a id to node mapping in Alembic file.
|
||||
|
||||
Nodes without IDs are ignored.
|
||||
|
||||
Returns:
|
||||
dict: Mapping of id to nodes in the Alembic.
|
||||
|
||||
"""
|
||||
node_ids = get_alembic_paths_by_property(path, attr="cbId")
|
||||
id_nodes = defaultdict(list)
|
||||
for node, _id in six.iteritems(node_ids):
|
||||
id_nodes[_id].append(node)
|
||||
|
||||
return dict(six.iteritems(id_nodes))
|
||||
|
|
@ -9,6 +9,7 @@ from openpype.pipeline import legacy_io
|
|||
from openpype.client import get_last_version_by_subset_name
|
||||
from openpype.hosts.maya import api
|
||||
from . import lib
|
||||
from .alembic import get_alembic_ids_cache
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
|
@ -68,6 +69,11 @@ def get_nodes_by_id(standin):
|
|||
(dict): Dictionary with node full name/path and id.
|
||||
"""
|
||||
path = cmds.getAttr(standin + ".dso")
|
||||
|
||||
if path.endswith(".abc"):
|
||||
# Support alembic files directly
|
||||
return get_alembic_ids_cache(path)
|
||||
|
||||
json_path = None
|
||||
for f in os.listdir(os.path.dirname(path)):
|
||||
if f.endswith(".json"):
|
||||
|
|
|
|||
|
|
@ -1,108 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Tools for loading looks to vray proxies."""
|
||||
import os
|
||||
from collections import defaultdict
|
||||
import logging
|
||||
|
||||
import six
|
||||
|
||||
import alembic.Abc
|
||||
from maya import cmds
|
||||
|
||||
from openpype.client import get_last_version_by_subset_name
|
||||
from openpype.pipeline import legacy_io
|
||||
import openpype.hosts.maya.lib as maya_lib
|
||||
from . import lib
|
||||
from .alembic import get_alembic_ids_cache
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_alembic_paths_by_property(filename, attr, verbose=False):
|
||||
# type: (str, str, bool) -> dict
|
||||
"""Return attribute value per objects in the Alembic file.
|
||||
|
||||
Reads an Alembic archive hierarchy and retrieves the
|
||||
value from the `attr` properties on the objects.
|
||||
|
||||
Args:
|
||||
filename (str): Full path to Alembic archive to read.
|
||||
attr (str): Id attribute.
|
||||
verbose (bool): Whether to verbosely log missing attributes.
|
||||
|
||||
Returns:
|
||||
dict: Mapping of node full path with its id
|
||||
|
||||
"""
|
||||
# Normalize alembic path
|
||||
filename = os.path.normpath(filename)
|
||||
filename = filename.replace("\\", "/")
|
||||
filename = str(filename) # path must be string
|
||||
|
||||
try:
|
||||
archive = alembic.Abc.IArchive(filename)
|
||||
except RuntimeError:
|
||||
# invalid alembic file - probably vrmesh
|
||||
log.warning("{} is not an alembic file".format(filename))
|
||||
return {}
|
||||
root = archive.getTop()
|
||||
|
||||
iterator = list(root.children)
|
||||
obj_ids = {}
|
||||
|
||||
for obj in iterator:
|
||||
name = obj.getFullName()
|
||||
|
||||
# include children for coming iterations
|
||||
iterator.extend(obj.children)
|
||||
|
||||
props = obj.getProperties()
|
||||
if props.getNumProperties() == 0:
|
||||
# Skip those without properties, e.g. '/materials' in a gpuCache
|
||||
continue
|
||||
|
||||
# THe custom attribute is under the properties' first container under
|
||||
# the ".arbGeomParams"
|
||||
prop = props.getProperty(0) # get base property
|
||||
|
||||
_property = None
|
||||
try:
|
||||
geo_params = prop.getProperty('.arbGeomParams')
|
||||
_property = geo_params.getProperty(attr)
|
||||
except KeyError:
|
||||
if verbose:
|
||||
log.debug("Missing attr on: {0}".format(name))
|
||||
continue
|
||||
|
||||
if not _property.isConstant():
|
||||
log.warning("Id not constant on: {0}".format(name))
|
||||
|
||||
# Get first value sample
|
||||
value = _property.getValue()[0]
|
||||
|
||||
obj_ids[name] = value
|
||||
|
||||
return obj_ids
|
||||
|
||||
|
||||
def get_alembic_ids_cache(path):
|
||||
# type: (str) -> dict
|
||||
"""Build a id to node mapping in Alembic file.
|
||||
|
||||
Nodes without IDs are ignored.
|
||||
|
||||
Returns:
|
||||
dict: Mapping of id to nodes in the Alembic.
|
||||
|
||||
"""
|
||||
node_ids = get_alembic_paths_by_property(path, attr="cbId")
|
||||
id_nodes = defaultdict(list)
|
||||
for node, _id in six.iteritems(node_ids):
|
||||
id_nodes[_id].append(node)
|
||||
|
||||
return dict(six.iteritems(id_nodes))
|
||||
|
||||
|
||||
def assign_vrayproxy_shaders(vrayproxy, assignments):
|
||||
# type: (str, dict) -> None
|
||||
"""Assign shaders to content of Vray Proxy.
|
||||
|
|
|
|||
|
|
@ -27,11 +27,12 @@ class ExtractWorkfileUrl(pyblish.api.ContextPlugin):
|
|||
rep_name = instance.data.get("representations")[0].get("name")
|
||||
template_data["representation"] = rep_name
|
||||
template_data["ext"] = rep_name
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
template_filled = anatomy_filled["publish"]["path"]
|
||||
template_obj = anatomy.templates_obj["publish"]["path"]
|
||||
template_filled = template_obj.format_strict(template_data)
|
||||
filepath = os.path.normpath(template_filled)
|
||||
self.log.info("Using published scene for render {}".format(
|
||||
filepath))
|
||||
break
|
||||
|
||||
if not filepath:
|
||||
self.log.info("Texture batch doesn't contain workfile.")
|
||||
|
|
|
|||
|
|
@ -61,10 +61,10 @@ class UnrealPrelaunchHook(PreLaunchHook):
|
|||
project_name=project_doc["name"]
|
||||
)
|
||||
# Fill templates
|
||||
filled_anatomy = anatomy.format(workdir_data)
|
||||
template_obj = anatomy.templates_obj[workfile_template_key]["file"]
|
||||
|
||||
# Return filename
|
||||
return filled_anatomy[workfile_template_key]["file"]
|
||||
return template_obj.format_strict(workdir_data)
|
||||
|
||||
def exec_plugin_install(self, engine_path: Path, env: dict = None):
|
||||
# set up the QThread and worker with necessary signals
|
||||
|
|
|
|||
|
|
@ -327,7 +327,8 @@ def get_usd_master_path(asset, subset, representation):
|
|||
else:
|
||||
asset_doc = get_asset_by_name(project_name, asset, fields=["name"])
|
||||
|
||||
formatted_result = anatomy.format(
|
||||
template_obj = anatomy.templates_obj["publish"]["path"]
|
||||
path = template_obj.format_strict(
|
||||
{
|
||||
"project": {
|
||||
"name": project_name,
|
||||
|
|
@ -340,7 +341,6 @@ def get_usd_master_path(asset, subset, representation):
|
|||
}
|
||||
)
|
||||
|
||||
path = formatted_result["publish"]["path"]
|
||||
# Remove the version folder
|
||||
subset_folder = os.path.dirname(os.path.dirname(path))
|
||||
master_folder = os.path.join(subset_folder, "master")
|
||||
|
|
|
|||
|
|
@ -534,8 +534,8 @@ class AbstractSubmitDeadline(pyblish.api.InstancePlugin):
|
|||
template_data["comment"] = None
|
||||
|
||||
anatomy = instance.context.data['anatomy']
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
template_filled = anatomy_filled["publish"]["path"]
|
||||
template_obj = anatomy.templates_obj["publish"]["path"]
|
||||
template_filled = template_obj.format_strict(template_data)
|
||||
file_path = os.path.normpath(template_filled)
|
||||
|
||||
self.log.info("Using published scene for render {}".format(file_path))
|
||||
|
|
|
|||
|
|
@ -1202,10 +1202,11 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
|
|||
template_data["family"] = "render"
|
||||
template_data["version"] = version
|
||||
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
|
||||
if "folder" in anatomy.templates["render"]:
|
||||
publish_folder = anatomy_filled["render"]["folder"]
|
||||
render_templates = anatomy.templates_obj["render"]
|
||||
if "folder" in render_templates:
|
||||
publish_folder = render_templates["folder"].format_strict(
|
||||
template_data
|
||||
)
|
||||
else:
|
||||
# solve deprecated situation when `folder` key is not underneath
|
||||
# `publish` anatomy
|
||||
|
|
@ -1215,8 +1216,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
|
|||
" key underneath `publish` (in global of for project `{}`)."
|
||||
).format(project_name))
|
||||
|
||||
file_path = anatomy_filled["render"]["path"]
|
||||
# Directory
|
||||
file_path = render_templates["path"].format_strict(template_data)
|
||||
publish_folder = os.path.dirname(file_path)
|
||||
|
||||
return publish_folder
|
||||
|
|
|
|||
|
|
@ -463,9 +463,7 @@ def get_workdir_from_session(session=None, template_key=None):
|
|||
session = legacy_io.Session
|
||||
project_name = session["AVALON_PROJECT"]
|
||||
host_name = session["AVALON_APP"]
|
||||
anatomy = Anatomy(project_name)
|
||||
template_data = get_template_data_from_session(session)
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
|
||||
if not template_key:
|
||||
task_type = template_data["task"]["type"]
|
||||
|
|
@ -474,7 +472,10 @@ def get_workdir_from_session(session=None, template_key=None):
|
|||
host_name,
|
||||
project_name=project_name
|
||||
)
|
||||
path = anatomy_filled[template_key]["folder"]
|
||||
|
||||
anatomy = Anatomy(project_name)
|
||||
template_obj = anatomy.templates_obj[template_key]["folder"]
|
||||
path = template_obj.format_strict(template_data)
|
||||
if path:
|
||||
path = os.path.normpath(path)
|
||||
return path
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
"""Functions useful for delivery of published representations."""
|
||||
import os
|
||||
import copy
|
||||
import shutil
|
||||
import glob
|
||||
import clique
|
||||
|
|
@ -146,12 +147,11 @@ def deliver_single_file(
|
|||
report_items["Source file was not found"].append(msg)
|
||||
return report_items, 0
|
||||
|
||||
anatomy_filled = anatomy.format(anatomy_data)
|
||||
if format_dict:
|
||||
template_result = anatomy_filled["delivery"][template_name]
|
||||
delivery_path = template_result.rootless.format(**format_dict)
|
||||
else:
|
||||
delivery_path = anatomy_filled["delivery"][template_name]
|
||||
anatomy_data = copy.deepcopy(anatomy_data)
|
||||
anatomy_data["root"] = format_dict["root"]
|
||||
template_obj = anatomy.templates_obj["delivery"][template_name]
|
||||
delivery_path = template_obj.format_strict(anatomy_data)
|
||||
|
||||
# Backwards compatibility when extension contained `.`
|
||||
delivery_path = delivery_path.replace("..", ".")
|
||||
|
|
@ -269,14 +269,12 @@ def deliver_sequence(
|
|||
|
||||
frame_indicator = "@####@"
|
||||
|
||||
anatomy_data = copy.deepcopy(anatomy_data)
|
||||
anatomy_data["frame"] = frame_indicator
|
||||
anatomy_filled = anatomy.format(anatomy_data)
|
||||
|
||||
if format_dict:
|
||||
template_result = anatomy_filled["delivery"][template_name]
|
||||
delivery_path = template_result.rootless.format(**format_dict)
|
||||
else:
|
||||
delivery_path = anatomy_filled["delivery"][template_name]
|
||||
anatomy_data["root"] = format_dict["root"]
|
||||
template_obj = anatomy.templates_obj["delivery"][template_name]
|
||||
delivery_path = template_obj.format_strict(anatomy_data)
|
||||
|
||||
delivery_path = os.path.normpath(delivery_path.replace("\\", "/"))
|
||||
delivery_folder = os.path.dirname(delivery_path)
|
||||
|
|
|
|||
|
|
@ -132,9 +132,9 @@ def get_workdir_with_workdir_data(
|
|||
project_settings
|
||||
)
|
||||
|
||||
anatomy_filled = anatomy.format(workdir_data)
|
||||
template_obj = anatomy.templates_obj[template_key]["folder"]
|
||||
# Output is TemplateResult object which contain useful data
|
||||
output = anatomy_filled[template_key]["folder"]
|
||||
output = template_obj.format_strict(workdir_data)
|
||||
if output:
|
||||
return output.normalized()
|
||||
return output
|
||||
|
|
|
|||
|
|
@ -83,10 +83,11 @@ class CollectResourcesPath(pyblish.api.InstancePlugin):
|
|||
"hierarchy": instance.data["hierarchy"]
|
||||
})
|
||||
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
|
||||
if "folder" in anatomy.templates["publish"]:
|
||||
publish_folder = anatomy_filled["publish"]["folder"]
|
||||
publish_templates = anatomy.templates_obj["publish"]
|
||||
if "folder" in publish_templates:
|
||||
publish_folder = publish_templates["folder"].format_strict(
|
||||
template_data
|
||||
)
|
||||
else:
|
||||
# solve deprecated situation when `folder` key is not underneath
|
||||
# `publish` anatomy
|
||||
|
|
@ -95,8 +96,7 @@ class CollectResourcesPath(pyblish.api.InstancePlugin):
|
|||
" key underneath `publish` (in global of for project `{}`)."
|
||||
).format(anatomy.project_name))
|
||||
|
||||
file_path = anatomy_filled["publish"]["path"]
|
||||
# Directory
|
||||
file_path = publish_templates["path"].format_strict(template_data)
|
||||
publish_folder = os.path.dirname(file_path)
|
||||
|
||||
publish_folder = os.path.normpath(publish_folder)
|
||||
|
|
|
|||
|
|
@ -665,8 +665,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
# - template_data (Dict[str, Any]): source data used to fill template
|
||||
# - to add required data to 'repre_context' not used for
|
||||
# formatting
|
||||
# - anatomy_filled (Dict[str, Any]): filled anatomy of last file
|
||||
# - to fill 'publishDir' on instance.data -> not ideal
|
||||
path_template_obj = anatomy.templates_obj[template_name]["path"]
|
||||
|
||||
# Treat template with 'orignalBasename' in special way
|
||||
if "{originalBasename}" in template:
|
||||
|
|
@ -700,8 +699,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
template_data["originalBasename"], _ = os.path.splitext(
|
||||
src_file_name)
|
||||
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
dst = anatomy_filled[template_name]["path"]
|
||||
dst = path_template_obj.format_strict(template_data)
|
||||
src = os.path.join(stagingdir, src_file_name)
|
||||
transfers.append((src, dst))
|
||||
if repre_context is None:
|
||||
|
|
@ -761,8 +759,9 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
template_data["udim"] = index
|
||||
else:
|
||||
template_data["frame"] = index
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
template_filled = anatomy_filled[template_name]["path"]
|
||||
template_filled = path_template_obj.format_strict(
|
||||
template_data
|
||||
)
|
||||
dst_filepaths.append(template_filled)
|
||||
if repre_context is None:
|
||||
self.log.debug(
|
||||
|
|
@ -798,8 +797,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
if is_udim:
|
||||
template_data["udim"] = repre["udim"][0]
|
||||
# Construct destination filepath from template
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
template_filled = anatomy_filled[template_name]["path"]
|
||||
template_filled = path_template_obj.format_strict(template_data)
|
||||
repre_context = template_filled.used_values
|
||||
dst = os.path.normpath(template_filled)
|
||||
|
||||
|
|
@ -810,11 +808,9 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
# todo: Are we sure the assumption each representation
|
||||
# ends up in the same folder is valid?
|
||||
if not instance.data.get("publishDir"):
|
||||
instance.data["publishDir"] = (
|
||||
anatomy_filled
|
||||
[template_name]
|
||||
["folder"]
|
||||
)
|
||||
template_obj = anatomy.templates_obj[template_name]["folder"]
|
||||
template_filled = template_obj.format_strict(template_data)
|
||||
instance.data["publishDir"] = template_filled
|
||||
|
||||
for key in self.db_representation_context_keys:
|
||||
# Also add these values to the context even if not used by the
|
||||
|
|
|
|||
|
|
@ -291,6 +291,7 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
))
|
||||
try:
|
||||
src_to_dst_file_paths = []
|
||||
path_template_obj = anatomy.templates_obj[template_key]["path"]
|
||||
for repre_info in published_repres.values():
|
||||
|
||||
# Skip if new repre does not have published repre files
|
||||
|
|
@ -303,9 +304,7 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
anatomy_data.pop("version", None)
|
||||
|
||||
# Get filled path to repre context
|
||||
anatomy_filled = anatomy.format(anatomy_data)
|
||||
template_filled = anatomy_filled[template_key]["path"]
|
||||
|
||||
template_filled = path_template_obj.format_strict(anatomy_data)
|
||||
repre_data = {
|
||||
"path": str(template_filled),
|
||||
"template": hero_template
|
||||
|
|
@ -343,8 +342,9 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
# Get head and tail for collection
|
||||
frame_splitter = "_-_FRAME_SPLIT_-_"
|
||||
anatomy_data["frame"] = frame_splitter
|
||||
_anatomy_filled = anatomy.format(anatomy_data)
|
||||
_template_filled = _anatomy_filled[template_key]["path"]
|
||||
_template_filled = path_template_obj.format_strict(
|
||||
anatomy_data
|
||||
)
|
||||
head, tail = _template_filled.split(frame_splitter)
|
||||
padding = int(
|
||||
anatomy.templates[template_key]["frame_padding"]
|
||||
|
|
@ -520,24 +520,24 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
|
|||
})
|
||||
|
||||
if "folder" in anatomy.templates[template_key]:
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
publish_folder = anatomy_filled[template_key]["folder"]
|
||||
template_obj = anatomy.templates_obj[template_key]["folder"]
|
||||
publish_folder = template_obj.format_strict(template_data)
|
||||
else:
|
||||
# This is for cases of Deprecated anatomy without `folder`
|
||||
# TODO remove when all clients have solved this issue
|
||||
template_data.update({
|
||||
"frame": "FRAME_TEMP",
|
||||
"representation": "TEMP"
|
||||
})
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
# solve deprecated situation when `folder` key is not underneath
|
||||
# `publish` anatomy
|
||||
self.log.warning((
|
||||
"Deprecation warning: Anatomy does not have set `folder`"
|
||||
" key underneath `publish` (in global of for project `{}`)."
|
||||
).format(anatomy.project_name))
|
||||
# solve deprecated situation when `folder` key is not underneath
|
||||
# `publish` anatomy
|
||||
template_data.update({
|
||||
"frame": "FRAME_TEMP",
|
||||
"representation": "TEMP"
|
||||
})
|
||||
template_obj = anatomy.templates_obj[template_key]["path"]
|
||||
file_path = template_obj.format_strict(template_data)
|
||||
|
||||
file_path = anatomy_filled[template_key]["path"]
|
||||
# Directory
|
||||
publish_folder = os.path.dirname(file_path)
|
||||
|
||||
|
|
|
|||
|
|
@ -480,8 +480,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
|
|||
else:
|
||||
template_data["udim"] = src_padding_exp % i
|
||||
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
template_filled = anatomy_filled[template_name]["path"]
|
||||
template_obj = anatomy.templates_obj[template_name]["path"]
|
||||
template_filled = template_obj.format_strict(template_data)
|
||||
if repre_context is None:
|
||||
repre_context = template_filled.used_values
|
||||
test_dest_files.append(
|
||||
|
|
@ -587,8 +587,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
|
|||
if repre.get("udim"):
|
||||
template_data["udim"] = repre["udim"][0]
|
||||
src = os.path.join(stagingdir, fname)
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
template_filled = anatomy_filled[template_name]["path"]
|
||||
template_obj = anatomy.templates_obj[template_name]["path"]
|
||||
template_filled = template_obj.format_strict(template_data)
|
||||
repre_context = template_filled.used_values
|
||||
dst = os.path.normpath(template_filled)
|
||||
|
||||
|
|
@ -600,9 +600,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
|
|||
|
||||
if not instance.data.get("publishDir"):
|
||||
instance.data["publishDir"] = (
|
||||
anatomy_filled
|
||||
[template_name]
|
||||
["folder"]
|
||||
anatomy.templates_obj[template_name]["folder"]
|
||||
.format_strict(template_data)
|
||||
)
|
||||
if repre.get("udim"):
|
||||
repre_context["udim"] = repre.get("udim") # store list
|
||||
|
|
|
|||
|
|
@ -271,9 +271,9 @@ class IntegrateThumbnails(pyblish.api.ContextPlugin):
|
|||
"thumbnail_type": "thumbnail"
|
||||
})
|
||||
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
thumbnail_template = anatomy.templates["publish"]["thumbnail"]
|
||||
template_filled = anatomy_filled["publish"]["thumbnail"]
|
||||
template_obj = anatomy.templates_obj["publish"]["thumbnail"]
|
||||
template_filled = template_obj.format_strict(template_data)
|
||||
thumbnail_template = template_filled.template
|
||||
|
||||
dst_full_path = os.path.normpath(str(template_filled))
|
||||
self.log.debug("Copying file .. {} -> {}".format(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,414 @@
|
|||
{
|
||||
"open_workfile_post_initialization": false,
|
||||
"explicit_plugins_loading": {
|
||||
"enabled": false,
|
||||
"plugins_to_load": [
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "AbcBullet"
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"name": "AbcExport"
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"name": "AbcImport"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "animImportExport"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "ArubaTessellator"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "ATFPlugin"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "atomImportExport"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "AutodeskPacketFile"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "autoLoader"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "bifmeshio"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "bifrostGraph"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "bifrostshellnode"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "bifrostvisplugin"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "blast2Cmd"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "bluePencil"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "Boss"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "bullet"
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"name": "cacheEvaluator"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "cgfxShader"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "cleanPerFaceAssignment"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "clearcoat"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "convertToComponentTags"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "curveWarp"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "ddsFloatReader"
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"name": "deformerEvaluator"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "dgProfiler"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "drawUfe"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "dx11Shader"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "fbxmaya"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "fltTranslator"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "freeze"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "Fur"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "gameFbxExporter"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "gameInputDevice"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "GamePipeline"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "gameVertexCount"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "geometryReport"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "geometryTools"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "glslShader"
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"name": "GPUBuiltInDeformer"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "gpuCache"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "hairPhysicalShader"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "ik2Bsolver"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "ikSpringSolver"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "invertShape"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "lges"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "lookdevKit"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "MASH"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "matrixNodes"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "mayaCharacterization"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "mayaHIK"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "MayaMuscle"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "mayaUsdPlugin"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "mayaVnnPlugin"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "melProfiler"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "meshReorder"
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"name": "modelingToolkit"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "mtoa"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "mtoh"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "nearestPointOnMesh"
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"name": "objExport"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "OneClick"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "OpenEXRLoader"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "pgYetiMaya"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "pgyetiVrayMaya"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "polyBoolean"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "poseInterpolator"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "quatNodes"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "randomizerDevice"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "redshift4maya"
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"name": "renderSetup"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "retargeterNodes"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "RokokoMotionLibrary"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "rotateHelper"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "sceneAssembly"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "shaderFXPlugin"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "shotCamera"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "snapTransform"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "stage"
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"name": "stereoCamera"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "stlTranslator"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "studioImport"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "Substance"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "substancelink"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "substancemaya"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "substanceworkflow"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "svgFileTranslator"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "sweep"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "testify"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "tiffFloatReader"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "timeSliderBookmark"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "Turtle"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "Type"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "udpDevice"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "ufeSupport"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "Unfold3D"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "VectorRender"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "vrayformaya"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "vrayvolumegrid"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "xgenToolkit"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"name": "xgenVray"
|
||||
}
|
||||
]
|
||||
},
|
||||
"imageio": {
|
||||
"ocio_config": {
|
||||
"enabled": false,
|
||||
|
|
@ -145,7 +554,7 @@
|
|||
"publish_mip_map": true
|
||||
},
|
||||
"CreateAnimation": {
|
||||
"enabled": true,
|
||||
"enabled": false,
|
||||
"write_color_sets": false,
|
||||
"write_face_sets": false,
|
||||
"include_parent_hierarchy": false,
|
||||
|
|
@ -911,7 +1320,8 @@
|
|||
"displayFilmOrigin": false,
|
||||
"overscan": 1.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"profiles": []
|
||||
},
|
||||
"ExtractMayaSceneRaw": {
|
||||
"enabled": true,
|
||||
|
|
@ -1049,7 +1459,7 @@
|
|||
]
|
||||
},
|
||||
"reference_loader": {
|
||||
"namespace": "{asset_name}_{subset}_##",
|
||||
"namespace": "{asset_name}_{subset}_##_",
|
||||
"group_name": "_GRP"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -119,9 +119,7 @@
|
|||
"label": "3ds max",
|
||||
"icon": "{}/app_icons/3dsmax.png",
|
||||
"host_name": "max",
|
||||
"environment": {
|
||||
"ADSK_3DSMAX_STARTUPSCRIPTS_ADDON_DIR": "{OPENPYPE_ROOT}\\openpype\\hosts\\max\\startup"
|
||||
},
|
||||
"environment": {},
|
||||
"variants": {
|
||||
"2023": {
|
||||
"use_python_2": false,
|
||||
|
|
@ -133,9 +131,7 @@
|
|||
"linux": []
|
||||
},
|
||||
"arguments": {
|
||||
"windows": [
|
||||
"-U MAXScript {OPENPYPE_ROOT}\\openpype\\hosts\\max\\startup\\startup.ms"
|
||||
],
|
||||
"windows": [],
|
||||
"darwin": [],
|
||||
"linux": []
|
||||
},
|
||||
|
|
|
|||
|
|
@ -11,8 +11,10 @@ class ColorEntity(InputEntity):
|
|||
|
||||
def _item_initialization(self):
|
||||
self.valid_value_types = (list, )
|
||||
self.value_on_not_set = [0, 0, 0, 255]
|
||||
self.use_alpha = self.schema_data.get("use_alpha", True)
|
||||
self.value_on_not_set = self.convert_to_valid_type(
|
||||
self.schema_data.get("default", [0, 0, 0, 255])
|
||||
)
|
||||
|
||||
def set_override_state(self, *args, **kwargs):
|
||||
super(ColorEntity, self).set_override_state(*args, **kwargs)
|
||||
|
|
|
|||
|
|
@ -442,7 +442,9 @@ class TextEntity(InputEntity):
|
|||
|
||||
def _item_initialization(self):
|
||||
self.valid_value_types = (STRING_TYPE, )
|
||||
self.value_on_not_set = ""
|
||||
self.value_on_not_set = self.convert_to_valid_type(
|
||||
self.schema_data.get("default", "")
|
||||
)
|
||||
|
||||
# GUI attributes
|
||||
self.multiline = self.schema_data.get("multiline", False)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,41 @@
|
|||
"key": "open_workfile_post_initialization",
|
||||
"label": "Open Workfile Post Initialization"
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"key": "explicit_plugins_loading",
|
||||
"label": "Explicit Plugins Loading",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"checkbox_key": "enabled",
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"key": "plugins_to_load",
|
||||
"label": "Plugins To Load",
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "name",
|
||||
"label": "Name"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "imageio",
|
||||
"type": "dict",
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
{
|
||||
"type": "dict",
|
||||
"key": "capture_preset",
|
||||
"label": "DEPRECATED! Please use \"Profiles\" below.",
|
||||
"collapsed": false,
|
||||
"children": [
|
||||
{
|
||||
"type": "dict",
|
||||
|
|
@ -176,7 +178,7 @@
|
|||
{ "all": "All Lights"},
|
||||
{ "selected": "Selected Lights"},
|
||||
{ "flat": "Flat Lighting"},
|
||||
{ "nolights": "No Lights"}
|
||||
{ "none": "No Lights"}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -626,6 +628,747 @@
|
|||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"key": "profiles",
|
||||
"label": "Profiles",
|
||||
"object_type": {
|
||||
"type": "dict",
|
||||
"children": [
|
||||
{
|
||||
"key": "task_types",
|
||||
"label": "Task types",
|
||||
"type": "task-types-enum"
|
||||
},
|
||||
{
|
||||
"key": "task_names",
|
||||
"label": "Task names",
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
},
|
||||
{
|
||||
"key": "subsets",
|
||||
"label": "Subset names",
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"key": "capture_preset",
|
||||
"children": [
|
||||
{
|
||||
"type": "dict",
|
||||
"key": "Codec",
|
||||
"children": [
|
||||
{
|
||||
"type": "label",
|
||||
"label": "<b>Codec</b>"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "compression",
|
||||
"label": "Encoding",
|
||||
"default": "png"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "format",
|
||||
"label": "Format",
|
||||
"default": "image"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "quality",
|
||||
"label": "Quality",
|
||||
"decimal": 0,
|
||||
"minimum": 0,
|
||||
"maximum": 100,
|
||||
"default": 95
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"key": "Display Options",
|
||||
"children": [
|
||||
{
|
||||
"type": "label",
|
||||
"label": "<b>Display Options</b>"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "override_display",
|
||||
"label": "Override display options",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"key": "background",
|
||||
"label": "Background Color: ",
|
||||
"default": [125, 125, 125, 255]
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "displayGradient",
|
||||
"label": "Display background gradient",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"key": "backgroundBottom",
|
||||
"label": "Background Bottom: ",
|
||||
"default": [125, 125, 125, 255]
|
||||
},
|
||||
{
|
||||
"type": "color",
|
||||
"key": "backgroundTop",
|
||||
"label": "Background Top: ",
|
||||
"default": [125, 125, 125, 255]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"key": "Generic",
|
||||
"children": [
|
||||
{
|
||||
"type": "label",
|
||||
"label": "<b>Generic</b>"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "isolate_view",
|
||||
"label": " Isolate view",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "off_screen",
|
||||
"label": " Off Screen",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "pan_zoom",
|
||||
"label": " 2D Pan/Zoom",
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"key": "Renderer",
|
||||
"children": [
|
||||
{
|
||||
"type": "label",
|
||||
"label": "<b>Renderer</b>"
|
||||
},
|
||||
{
|
||||
"type": "enum",
|
||||
"key": "rendererName",
|
||||
"label": "Renderer name",
|
||||
"enum_items": [
|
||||
{ "vp2Renderer": "Viewport 2.0" }
|
||||
],
|
||||
"default": "vp2Renderer"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"key": "Resolution",
|
||||
"children": [
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"label": "<b>Resolution</b>"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "width",
|
||||
"label": " Width",
|
||||
"decimal": 0,
|
||||
"minimum": 0,
|
||||
"maximum": 99999,
|
||||
"default": 0
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "height",
|
||||
"label": "Height",
|
||||
"decimal": 0,
|
||||
"minimum": 0,
|
||||
"maximum": 99999,
|
||||
"default": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
"key": "Viewport Options",
|
||||
"label": "Viewport Options",
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "override_viewport_options",
|
||||
"label": "Override Viewport Options",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"type": "enum",
|
||||
"key": "displayLights",
|
||||
"label": "Display Lights",
|
||||
"enum_items": [
|
||||
{ "default": "Default Lighting"},
|
||||
{ "all": "All Lights"},
|
||||
{ "selected": "Selected Lights"},
|
||||
{ "flat": "Flat Lighting"},
|
||||
{ "nolights": "No Lights"}
|
||||
],
|
||||
"default": "default"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "displayTextures",
|
||||
"label": "Display Textures",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "textureMaxResolution",
|
||||
"label": "Texture Clamp Resolution",
|
||||
"decimal": 0,
|
||||
"default": 1024
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"label": "<b>Display</b>"
|
||||
},
|
||||
{
|
||||
"type":"boolean",
|
||||
"key": "renderDepthOfField",
|
||||
"label": "Depth of Field",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "shadows",
|
||||
"label": "Display Shadows",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "twoSidedLighting",
|
||||
"label": "Two Sided Lighting",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "lineAAEnable",
|
||||
"label": "Enable Anti-Aliasing",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "multiSample",
|
||||
"label": "Anti Aliasing Samples",
|
||||
"decimal": 0,
|
||||
"minimum": 0,
|
||||
"maximum": 32,
|
||||
"default": 8
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "useDefaultMaterial",
|
||||
"label": "Use Default Material",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "wireframeOnShaded",
|
||||
"label": "Wireframe On Shaded",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "xray",
|
||||
"label": "X-Ray",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "jointXray",
|
||||
"label": "X-Ray Joints",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "backfaceCulling",
|
||||
"label": "Backface Culling",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "ssaoEnable",
|
||||
"label": "Screen Space Ambient Occlusion",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "ssaoAmount",
|
||||
"label": "SSAO Amount",
|
||||
"default": 1
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "ssaoRadius",
|
||||
"label": "SSAO Radius",
|
||||
"default": 16
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "ssaoFilterRadius",
|
||||
"label": "SSAO Filter Radius",
|
||||
"decimal": 0,
|
||||
"minimum": 1,
|
||||
"maximum": 32,
|
||||
"default": 16
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "ssaoSamples",
|
||||
"label": "SSAO Samples",
|
||||
"decimal": 0,
|
||||
"minimum": 8,
|
||||
"maximum": 32,
|
||||
"default": 16
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "fogging",
|
||||
"label": "Enable Hardware Fog",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "enum",
|
||||
"key": "hwFogFalloff",
|
||||
"label": "Hardware Falloff",
|
||||
"enum_items": [
|
||||
{ "0": "Linear"},
|
||||
{ "1": "Exponential"},
|
||||
{ "2": "Exponential Squared"}
|
||||
],
|
||||
"default": "0"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "hwFogDensity",
|
||||
"label": "Fog Density",
|
||||
"decimal": 2,
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"default": 0
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "hwFogStart",
|
||||
"label": "Fog Start",
|
||||
"default": 0
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "hwFogEnd",
|
||||
"label": "Fog End",
|
||||
"default": 100
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "hwFogAlpha",
|
||||
"label": "Fog Alpha",
|
||||
"default": 0
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "hwFogColorR",
|
||||
"label": "Fog Color R",
|
||||
"decimal": 2,
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"default": 1
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "hwFogColorG",
|
||||
"label": "Fog Color G",
|
||||
"decimal": 2,
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"default": 1
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "hwFogColorB",
|
||||
"label": "Fog Color B",
|
||||
"decimal": 2,
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"default": 1
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "motionBlurEnable",
|
||||
"label": "Enable Motion Blur",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "motionBlurSampleCount",
|
||||
"label": "Motion Blur Sample Count",
|
||||
"decimal": 0,
|
||||
"minimum": 8,
|
||||
"maximum": 32,
|
||||
"default": 8
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "motionBlurShutterOpenFraction",
|
||||
"label": "Shutter Open Fraction",
|
||||
"decimal": 3,
|
||||
"minimum": 0.01,
|
||||
"maximum": 32,
|
||||
"default": 0.2
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"label": "<b>Show</b>"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "cameras",
|
||||
"label": "Cameras",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "clipGhosts",
|
||||
"label": "Clip Ghosts",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "deformers",
|
||||
"label": "Deformers",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "dimensions",
|
||||
"label": "Dimensions",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "dynamicConstraints",
|
||||
"label": "Dynamic Constraints",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "dynamics",
|
||||
"label": "Dynamics",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "fluids",
|
||||
"label": "Fluids",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "follicles",
|
||||
"label": "Follicles",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "greasePencils",
|
||||
"label": "Grease Pencil",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "grid",
|
||||
"label": "Grid",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "hairSystems",
|
||||
"label": "Hair Systems",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "handles",
|
||||
"label": "Handles",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "headsUpDisplay",
|
||||
"label": "HUD",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "ikHandles",
|
||||
"label": "IK Handles",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "imagePlane",
|
||||
"label": "Image Planes",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "joints",
|
||||
"label": "Joints",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "lights",
|
||||
"label": "Lights",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "locators",
|
||||
"label": "Locators",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "manipulators",
|
||||
"label": "Manipulators",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "motionTrails",
|
||||
"label": "Motion Trails",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "nCloths",
|
||||
"label": "nCloths",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "nParticles",
|
||||
"label": "nParticles",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "nRigids",
|
||||
"label": "nRigids",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "controlVertices",
|
||||
"label": "NURBS CVs",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "nurbsCurves",
|
||||
"label": "NURBS Curves",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "hulls",
|
||||
"label": "NURBS Hulls",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "nurbsSurfaces",
|
||||
"label": "NURBS Surfaces",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "particleInstancers",
|
||||
"label": "Particle Instancers",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "pivots",
|
||||
"label": "Pivots",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "planes",
|
||||
"label": "Planes",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "pluginShapes",
|
||||
"label": "Plugin Shapes",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "polymeshes",
|
||||
"label": "Polygons",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "strokes",
|
||||
"label": "Strokes",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "subdivSurfaces",
|
||||
"label": "Subdiv Surfaces",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "textures",
|
||||
"label": "Texture Placements",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "dict-modifiable",
|
||||
"key": "pluginObjects",
|
||||
"label": "Plugin Objects",
|
||||
"object_type": "boolean"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
"key": "Camera Options",
|
||||
"label": "Camera Options",
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "displayGateMask",
|
||||
"label": "Display Gate Mask",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "displayResolution",
|
||||
"label": "Display Resolution",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "displayFilmGate",
|
||||
"label": "Display Film Gate",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "displayFieldChart",
|
||||
"label": "Display Field Chart",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "displaySafeAction",
|
||||
"label": "Display Safe Action",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "displaySafeTitle",
|
||||
"label": "Display Safe Title",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "displayFilmPivot",
|
||||
"label": "Display Film Pivot",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "displayFilmOrigin",
|
||||
"label": "Display Film Origin",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "overscan",
|
||||
"label": "Overscan",
|
||||
"decimal": 1,
|
||||
"minimum": 0,
|
||||
"maximum": 10,
|
||||
"default": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1050,8 +1050,8 @@ class ProjectPushItemProcess:
|
|||
repre_format_data["ext"] = ext[1:]
|
||||
break
|
||||
|
||||
tmp_result = anatomy.format(formatting_data)
|
||||
folder_path = tmp_result[template_name]["folder"]
|
||||
template_obj = anatomy.templates_obj[template_name]["folder"]
|
||||
folder_path = template_obj.format_strict(formatting_data)
|
||||
repre_context = folder_path.used_values
|
||||
folder_path_rootless = folder_path.rootless
|
||||
repre_filepaths = []
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ class TextureCopy:
|
|||
"hierarchy": hierarchy
|
||||
}
|
||||
anatomy = Anatomy(project_name)
|
||||
anatomy_filled = anatomy.format(template_data)
|
||||
return anatomy_filled['texture']['path']
|
||||
template_obj = anatomy.templates_obj["texture"]["path"]
|
||||
return template_obj.format_strict(template_data)
|
||||
|
||||
def _get_version(self, path):
|
||||
versions = [0]
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ class CommentMatcher(object):
|
|||
temp_data["version"] = "<<version>>"
|
||||
temp_data["ext"] = "<<ext>>"
|
||||
|
||||
formatted = anatomy.format(temp_data)
|
||||
fname_pattern = formatted[template_key]["file"]
|
||||
template_obj = anatomy.templates_obj[template_key]["file"]
|
||||
fname_pattern = template_obj.format_strict(temp_data)
|
||||
fname_pattern = re.escape(fname_pattern)
|
||||
|
||||
# Replace comment and version with something we can match with regex
|
||||
|
|
@ -375,8 +375,8 @@ class SaveAsDialog(QtWidgets.QDialog):
|
|||
|
||||
data["ext"] = data["ext"].lstrip(".")
|
||||
|
||||
anatomy_filled = self.anatomy.format(data)
|
||||
return anatomy_filled[self.template_key]["file"]
|
||||
template_obj = self.anatomy.templates_obj[self.template_key]["file"]
|
||||
return template_obj.format_strict(data)
|
||||
|
||||
def refresh(self):
|
||||
extensions = list(self._extensions)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Package declaring Pype version."""
|
||||
__version__ = "3.15.4-nightly.3"
|
||||
__version__ = "3.15.4"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "OpenPype"
|
||||
version = "3.15.3" # OpenPype
|
||||
version = "3.15.4" # OpenPype
|
||||
description = "Open VFX and Animation pipeline with support."
|
||||
authors = ["OpenPype Team <info@openpype.io>"]
|
||||
license = "MIT License"
|
||||
|
|
|
|||
|
|
@ -274,3 +274,14 @@ Fill in the necessary fields (the optional fields are regex filters)
|
|||
- Build your workfile
|
||||
|
||||

|
||||
|
||||
## Explicit Plugins Loading
|
||||
You can define which plugins to load on launch of Maya here; `project_settings/maya/explicit_plugins_loading`. This can help improve Maya's launch speed, if you know which plugins are needed.
|
||||
|
||||
By default only the required plugins are enabled. You can also add any plugin to the list to enable on launch.
|
||||
|
||||
:::note technical
|
||||
When enabling this feature, the workfile will be launched post initialization no matter the setting on `project_settings/maya/open_workfile_post_initialization`. This is to avoid any issues with references needing plugins.
|
||||
|
||||
Renderfarm integration is not supported for this feature.
|
||||
:::
|
||||
|
|
|
|||
|
|
@ -238,12 +238,12 @@ For resolution and frame range, use **OpenPype → Set Frame Range** and
|
|||
|
||||
Creating and publishing rigs with OpenPype follows similar workflow as with
|
||||
other data types. Create your rig and mark parts of your hierarchy in sets to
|
||||
help OpenPype validators and extractors to check it and publish it.
|
||||
help OpenPype validators and extractors to check and publish it.
|
||||
|
||||
### Preparing rig for publish
|
||||
|
||||
When creating rigs, it is recommended (and it is in fact enforced by validators)
|
||||
to separate bones or driving objects, their controllers and geometry so they are
|
||||
to separate bones or driven objects, their controllers and geometry so they are
|
||||
easily managed. Currently OpenPype doesn't allow to publish model at the same time as
|
||||
its rig so for demonstration purposes, I'll first create simple model for robotic
|
||||
arm, just made out of simple boxes and I'll publish it.
|
||||
|
|
@ -252,41 +252,48 @@ arm, just made out of simple boxes and I'll publish it.
|
|||
|
||||
For more information about publishing models, see [Publishing models](artist_hosts_maya.md#publishing-models).
|
||||
|
||||
Now lets start with empty scene. Load your model - **OpenPype → Load...**, right
|
||||
Now let's start with empty scene. Load your model - **OpenPype → Load...**, right
|
||||
click on it and select **Reference (abc)**.
|
||||
|
||||
I've created few bones and their controllers in two separate
|
||||
groups - `rig_GRP` and `controls_GRP`. Naming is not important - just adhere to
|
||||
your naming conventions.
|
||||
I've created a few bones in `rig_GRP`, their controllers in `controls_GRP` and
|
||||
placed the rig's output geometry in `geometry_GRP`. Naming of the groups is not important - just adhere to
|
||||
your naming conventions. Then I parented everything into a single top group named `arm_rig`.
|
||||
|
||||
Then I've put everything into `arm_rig` group.
|
||||
|
||||
When you've prepared your hierarchy, it's time to create *Rig instance* in OpenPype.
|
||||
Select your whole rig hierarchy and go **OpenPype → Create...**. Select **Rig**.
|
||||
Set is created in your scene to mark rig parts for export. Notice that it has
|
||||
two subsets - `controls_SET` and `out_SET`. Put your controls into `controls_SET`
|
||||
With the prepared hierarchy it is time to create a *Rig instance* in OpenPype.
|
||||
Select the top group of your rig and go to **OpenPype → Create...**. Select **Rig**.
|
||||
A publish set for your rig is created in your scene to mark rig parts for export.
|
||||
Notice that it has two subsets - `controls_SET` and `out_SET`. Put your controls into `controls_SET`
|
||||
and geometry to `out_SET`. You should end up with something like this:
|
||||
|
||||

|
||||
|
||||
:::note controls_SET and out_SET contents
|
||||
It is totally allowed to put the `geometry_GRP` in the `out_SET` as opposed to
|
||||
the individual meshes - it's even **recommended**. However, the `controls_SET`
|
||||
requires the individual controls in it that the artist is supposed to animate
|
||||
and manipulate so the publish validators can accurately check the rig's
|
||||
controls.
|
||||
:::
|
||||
|
||||
### Publishing rigs
|
||||
|
||||
Publishing rig is done in same way as publishing everything else. Save your scene
|
||||
and go **OpenPype → Publish**. When you run validation you'll mostly run at first into
|
||||
few issues. Although number of them will seem to be intimidating at first, you'll
|
||||
find out they are mostly minor things easily fixed.
|
||||
Publishing rigs is done in a same way as publishing everything else. Save your scene
|
||||
and go **OpenPype → Publish**. When you run validation you'll most likely run into
|
||||
a few issues at first. Although a number of them will seem to be intimidating you
|
||||
will find out they are mostly minor things, easily fixed and are there to optimize
|
||||
your rig for consistency and safe usage by the artist.
|
||||
|
||||
* **Non Duplicate Instance Members (ID)** - This will most likely fail because when
|
||||
- **Non Duplicate Instance Members (ID)** - This will most likely fail because when
|
||||
creating rigs, we usually duplicate few parts of it to reuse them. But duplication
|
||||
will duplicate also ID of original object and OpenPype needs every object to have
|
||||
unique ID. This is easily fixed by **Repair** action next to validator name. click
|
||||
on little up arrow on right side of validator name and select **Repair** form menu.
|
||||
|
||||
* **Joints Hidden** - This is enforcing joints (bones) to be hidden for user as
|
||||
- **Joints Hidden** - This is enforcing joints (bones) to be hidden for user as
|
||||
animator usually doesn't need to see them and they clutter his viewports. So
|
||||
well behaving rig should have them hidden. **Repair** action will help here also.
|
||||
|
||||
* **Rig Controllers** will check if there are no transforms on unlocked attributes
|
||||
- **Rig Controllers** will check if there are no transforms on unlocked attributes
|
||||
of controllers. This is needed because animator should have ease way to reset rig
|
||||
to it's default position. It also check that those attributes doesn't have any
|
||||
incoming connections from other parts of scene to ensure that published rig doesn't
|
||||
|
|
@ -297,6 +304,19 @@ have any missing dependencies.
|
|||
You can load rig with [Loader](artist_tools_loader). Go **OpenPype → Load...**,
|
||||
select your rig, right click on it and **Reference** it.
|
||||
|
||||
### Animation instances
|
||||
|
||||
Whenever you load a rig an animation publish instance is automatically created
|
||||
for it. This means that if you load a rig you don't need to create a pointcache
|
||||
instance yourself to publish the geometry. This is all cleanly prepared for you
|
||||
when loading a published rig.
|
||||
|
||||
:::tip Missing animation instance for your loaded rig?
|
||||
Did you accidentally delete the animation instance for a loaded rig? You can
|
||||
recreate it using the [**Recreate rig animation instance**](artist_hosts_maya.md#recreate-rig-animation-instance)
|
||||
inventory action.
|
||||
:::
|
||||
|
||||
## Point caches
|
||||
OpenPype is using Alembic format for point caches. Workflow is very similar as
|
||||
other data types.
|
||||
|
|
@ -646,3 +666,15 @@ Select 1 container of type `animation` or `pointcache`, then 1+ container of any
|
|||
The action searches the selected containers for 1 animation container of type `animation` or `pointcache`. This animation container will be connected to the rest of the selected containers. Matching geometries between containers is done by comparing the attribute `cbId`.
|
||||
|
||||
The connection between geometries is done with a live blendshape.
|
||||
|
||||
### Recreate rig animation instance
|
||||
|
||||
This action can regenerate an animation instance for a loaded rig, for example
|
||||
for when it was accidentally deleted by the user.
|
||||
|
||||

|
||||
|
||||
#### Usage
|
||||
|
||||
Select 1 or more container of type `rig` for which you want to recreate the
|
||||
animation instance.
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ Create an Xgen instance to publish. This needs to contain only **one Xgen collec
|
|||
|
||||
You can create multiple Xgen instances if you have multiple collections to publish.
|
||||
|
||||
:::note
|
||||
The Xgen publishing requires a namespace on the Xgen collection (palette) and the geometry used.
|
||||
:::
|
||||
|
||||
### Publish
|
||||
|
||||
The publishing process will grab geometry used for Xgen along with any external files used in the collection's descriptions. This creates an isolated Maya file with just the Xgen collection's dependencies, so you can use any nested geometry when creating the Xgen description. An Xgen version will consist of:
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
Loading…
Add table
Add a link
Reference in a new issue