mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge branch 'release/2.14.1' into develop
This commit is contained in:
commit
f58e5a1d45
19 changed files with 953 additions and 64 deletions
|
|
@ -2,7 +2,8 @@ pr-wo-labels=False
|
|||
exclude-labels=duplicate,question,invalid,wontfix,weekly-digest
|
||||
author=False
|
||||
unreleased=True
|
||||
since-tag=2.11.0
|
||||
since-tag=2.13.6
|
||||
release-branch=master
|
||||
enhancement-label=**Enhancements:**
|
||||
issues=False
|
||||
pulls=False
|
||||
|
|
|
|||
46
CHANGELOG.md
46
CHANGELOG.md
|
|
@ -1,5 +1,48 @@
|
|||
# Changelog
|
||||
|
||||
## [2.14.0](https://github.com/pypeclub/pype/tree/2.14.0) (2020-11-24)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.13.7...2.14.0)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- Shot asset build trigger status [\#736](https://github.com/pypeclub/pype/pull/736)
|
||||
- Maya: add camera rig publishing option [\#721](https://github.com/pypeclub/pype/pull/721)
|
||||
- Sort instances by label in pyblish gui [\#719](https://github.com/pypeclub/pype/pull/719)
|
||||
- Synchronize ftrack hierarchical and shot attributes [\#716](https://github.com/pypeclub/pype/pull/716)
|
||||
- 686 standalonepublisher editorial from image sequences [\#699](https://github.com/pypeclub/pype/pull/699)
|
||||
- TV Paint: initial implementation of creators and local rendering [\#693](https://github.com/pypeclub/pype/pull/693)
|
||||
- Render publish plugins abstraction [\#687](https://github.com/pypeclub/pype/pull/687)
|
||||
- Ask user to select non-default camera from scene or create a new. [\#678](https://github.com/pypeclub/pype/pull/678)
|
||||
- TVPaint: image loader with options [\#675](https://github.com/pypeclub/pype/pull/675)
|
||||
- Maya: Camera name can be added to burnins. [\#674](https://github.com/pypeclub/pype/pull/674)
|
||||
- After Effects: base integration with loaders [\#667](https://github.com/pypeclub/pype/pull/667)
|
||||
- Harmony: Javascript refactoring and overall stability improvements [\#666](https://github.com/pypeclub/pype/pull/666)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- TVPaint extract review fix [\#740](https://github.com/pypeclub/pype/pull/740)
|
||||
- After Effects: Review were not being sent to ftrack [\#738](https://github.com/pypeclub/pype/pull/738)
|
||||
- Asset fetch second fix [\#726](https://github.com/pypeclub/pype/pull/726)
|
||||
- Maya: vray proxy was not loading [\#722](https://github.com/pypeclub/pype/pull/722)
|
||||
- Maya: Vray expected file fixes [\#682](https://github.com/pypeclub/pype/pull/682)
|
||||
|
||||
**Deprecated:**
|
||||
|
||||
- Removed artist view from pyblish gui [\#717](https://github.com/pypeclub/pype/pull/717)
|
||||
- Maya: disable legacy override check for cameras [\#715](https://github.com/pypeclub/pype/pull/715)
|
||||
|
||||
|
||||
## [2.13.7](https://github.com/pypeclub/pype/tree/2.13.7) (2020-11-19)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.13.6...2.13.7)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- fix\(SP\): getting fps from context instead of nonexistent entity [\#729](https://github.com/pypeclub/pype/pull/729)
|
||||
|
||||
# Changelog
|
||||
|
||||
## [2.13.6](https://github.com/pypeclub/pype/tree/2.13.6) (2020-11-15)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.13.5...2.13.6)
|
||||
|
|
@ -789,4 +832,7 @@ A large cleanup release. Most of the change are under the hood.
|
|||
- _(avalon)_ subsets in maya 2019 weren't behaving correctly in the outliner
|
||||
|
||||
|
||||
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
|
||||
|
||||
|
||||
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
|
||||
|
|
|
|||
360
HISTORY.md
360
HISTORY.md
|
|
@ -1,3 +1,360 @@
|
|||
# Changelog
|
||||
|
||||
## [2.13.6](https://github.com/pypeclub/pype/tree/2.13.6) (2020-11-15)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.13.5...2.13.6)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Maya workfile version wasn't syncing with renders properly [\#711](https://github.com/pypeclub/pype/pull/711)
|
||||
- Maya: Fix for publishing multiple cameras with review from the same scene [\#710](https://github.com/pypeclub/pype/pull/710)
|
||||
|
||||
## [2.13.5](https://github.com/pypeclub/pype/tree/2.13.5) (2020-11-12)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.13.4...2.13.5)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- 3.0 lib refactor [\#664](https://github.com/pypeclub/pype/issues/664)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Wrong thumbnail file was picked when publishing sequence in standalone publisher [\#703](https://github.com/pypeclub/pype/pull/703)
|
||||
- Fix: Burnin data pass and FFmpeg tool check [\#701](https://github.com/pypeclub/pype/pull/701)
|
||||
|
||||
## [2.13.4](https://github.com/pypeclub/pype/tree/2.13.4) (2020-11-09)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.13.3...2.13.4)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- AfterEffects integration with Websocket [\#663](https://github.com/pypeclub/pype/issues/663)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Photoshop uhiding hidden layers [\#688](https://github.com/pypeclub/pype/issues/688)
|
||||
- \#688 - Fix publishing hidden layers [\#692](https://github.com/pypeclub/pype/pull/692)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Nuke Favorite directories "shot dir" "project dir" - not working [\#684](https://github.com/pypeclub/pype/issues/684)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Nuke Favorite directories "shot dir" "project dir" - not working \#684 [\#685](https://github.com/pypeclub/pype/pull/685)
|
||||
|
||||
## [2.13.3](https://github.com/pypeclub/pype/tree/2.13.3) (2020-11-03)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.13.2...2.13.3)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- TV paint base integration [\#612](https://github.com/pypeclub/pype/issues/612)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Fix ffmpeg executable path with spaces [\#680](https://github.com/pypeclub/pype/pull/680)
|
||||
- Hotfix: Added default version number [\#679](https://github.com/pypeclub/pype/pull/679)
|
||||
|
||||
## [2.13.2](https://github.com/pypeclub/pype/tree/2.13.2) (2020-10-28)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.13.1...2.13.2)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Nuke: wrong conditions when fixing legacy write nodes [\#665](https://github.com/pypeclub/pype/pull/665)
|
||||
|
||||
## [2.13.1](https://github.com/pypeclub/pype/tree/2.13.1) (2020-10-23)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.13.0...2.13.1)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- move maya look assigner to pype menu [\#292](https://github.com/pypeclub/pype/issues/292)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Layer name is not propagating to metadata in Photoshop [\#654](https://github.com/pypeclub/pype/issues/654)
|
||||
- Loader in Photoshop fails with "can't set attribute" [\#650](https://github.com/pypeclub/pype/issues/650)
|
||||
- Nuke Load mp4 wrong frame range [\#661](https://github.com/pypeclub/pype/issues/661)
|
||||
- Hiero: Review video file adding one frame to the end [\#659](https://github.com/pypeclub/pype/issues/659)
|
||||
|
||||
## [2.13.0](https://github.com/pypeclub/pype/tree/2.13.0) (2020-10-18)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.12.5...2.13.0)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- Deadline Output Folder [\#636](https://github.com/pypeclub/pype/issues/636)
|
||||
- Nuke Camera Loader [\#565](https://github.com/pypeclub/pype/issues/565)
|
||||
- Deadline publish job shows publishing output folder [\#649](https://github.com/pypeclub/pype/pull/649)
|
||||
- Get latest version in lib [\#642](https://github.com/pypeclub/pype/pull/642)
|
||||
- Improved publishing of multiple representation from SP [\#638](https://github.com/pypeclub/pype/pull/638)
|
||||
- Launch TvPaint shot work file from within Ftrack [\#631](https://github.com/pypeclub/pype/pull/631)
|
||||
- Add mp4 support for RV action. [\#628](https://github.com/pypeclub/pype/pull/628)
|
||||
- Maya: allow renders to have version synced with workfile [\#618](https://github.com/pypeclub/pype/pull/618)
|
||||
- Renaming nukestudio host folder to hiero [\#617](https://github.com/pypeclub/pype/pull/617)
|
||||
- Harmony: More efficient publishing [\#615](https://github.com/pypeclub/pype/pull/615)
|
||||
- Ftrack server action improvement [\#608](https://github.com/pypeclub/pype/pull/608)
|
||||
- Deadline user defaults to pype username if present [\#607](https://github.com/pypeclub/pype/pull/607)
|
||||
- Standalone publisher now has icon [\#606](https://github.com/pypeclub/pype/pull/606)
|
||||
- Nuke render write targeting knob improvement [\#603](https://github.com/pypeclub/pype/pull/603)
|
||||
- Animated pyblish gui [\#602](https://github.com/pypeclub/pype/pull/602)
|
||||
- Maya: Deadline - make use of asset dependencies optional [\#591](https://github.com/pypeclub/pype/pull/591)
|
||||
- Nuke: Publishing, loading and updating alembic cameras [\#575](https://github.com/pypeclub/pype/pull/575)
|
||||
- Maya: add look assigner to pype menu even if scriptsmenu is not available [\#573](https://github.com/pypeclub/pype/pull/573)
|
||||
- Store task types in the database [\#572](https://github.com/pypeclub/pype/pull/572)
|
||||
- Maya: Tiled EXRs to scanline EXRs render option [\#512](https://github.com/pypeclub/pype/pull/512)
|
||||
- Fusion basic integration [\#452](https://github.com/pypeclub/pype/pull/452)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Burnin script did not propagate ffmpeg output [\#640](https://github.com/pypeclub/pype/issues/640)
|
||||
- Pyblish-pype spacer in terminal wasn't transparent [\#646](https://github.com/pypeclub/pype/pull/646)
|
||||
- Lib subprocess without logger [\#645](https://github.com/pypeclub/pype/pull/645)
|
||||
- Nuke: prevent crash if we only have single frame in sequence [\#644](https://github.com/pypeclub/pype/pull/644)
|
||||
- Burnin script logs better output [\#641](https://github.com/pypeclub/pype/pull/641)
|
||||
- Missing audio on farm submission. [\#639](https://github.com/pypeclub/pype/pull/639)
|
||||
- review from imagesequence error [\#633](https://github.com/pypeclub/pype/pull/633)
|
||||
- Hiero: wrong order of fps clip instance data collecting [\#627](https://github.com/pypeclub/pype/pull/627)
|
||||
- Add source for review instances. [\#625](https://github.com/pypeclub/pype/pull/625)
|
||||
- Task processing in event sync [\#623](https://github.com/pypeclub/pype/pull/623)
|
||||
- sync to avalon doesn t remove renamed task [\#619](https://github.com/pypeclub/pype/pull/619)
|
||||
- Intent publish setting wasn't working with default value [\#562](https://github.com/pypeclub/pype/pull/562)
|
||||
- Maya: Updating a look where the shader name changed, leaves the geo without a shader [\#514](https://github.com/pypeclub/pype/pull/514)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Avalon module without Qt [\#581](https://github.com/pypeclub/pype/pull/581)
|
||||
- Ftrack module without Qt [\#577](https://github.com/pypeclub/pype/pull/577)
|
||||
|
||||
## [2.12.5](https://github.com/pypeclub/pype/tree/2.12.5) (2020-10-14)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.12.4...2.12.5)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- Launch TvPaint shot work file from within Ftrack [\#629](https://github.com/pypeclub/pype/issues/629)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Harmony: Disable application launch logic [\#637](https://github.com/pypeclub/pype/pull/637)
|
||||
|
||||
## [2.12.4](https://github.com/pypeclub/pype/tree/2.12.4) (2020-10-08)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.12.3...2.12.4)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- convert nukestudio to hiero host [\#616](https://github.com/pypeclub/pype/issues/616)
|
||||
- Fusion basic integration [\#451](https://github.com/pypeclub/pype/issues/451)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Sync to avalon doesn't remove renamed task [\#605](https://github.com/pypeclub/pype/issues/605)
|
||||
- NukeStudio: FPS collecting into clip instances [\#624](https://github.com/pypeclub/pype/pull/624)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- NukeStudio: small fixes [\#622](https://github.com/pypeclub/pype/pull/622)
|
||||
- NukeStudio: broken order of plugins [\#620](https://github.com/pypeclub/pype/pull/620)
|
||||
|
||||
## [2.12.3](https://github.com/pypeclub/pype/tree/2.12.3) (2020-10-06)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.12.2...2.12.3)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- Nuke Publish Camera [\#567](https://github.com/pypeclub/pype/issues/567)
|
||||
- Harmony: open xstage file no matter of its name [\#526](https://github.com/pypeclub/pype/issues/526)
|
||||
- Stop integration of unwanted data [\#387](https://github.com/pypeclub/pype/issues/387)
|
||||
- Move avalon-launcher functionality to pype [\#229](https://github.com/pypeclub/pype/issues/229)
|
||||
- avalon workfiles api [\#214](https://github.com/pypeclub/pype/issues/214)
|
||||
- Store task types [\#180](https://github.com/pypeclub/pype/issues/180)
|
||||
- Avalon Mongo Connection split [\#136](https://github.com/pypeclub/pype/issues/136)
|
||||
- nk camera workflow [\#71](https://github.com/pypeclub/pype/issues/71)
|
||||
- Hiero integration added [\#590](https://github.com/pypeclub/pype/pull/590)
|
||||
- Anatomy instance data collection is substantially faster for many instances [\#560](https://github.com/pypeclub/pype/pull/560)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- test issue [\#596](https://github.com/pypeclub/pype/issues/596)
|
||||
- Harmony: empty scene contamination [\#583](https://github.com/pypeclub/pype/issues/583)
|
||||
- Edit publishing in SP doesn't respect shot selection for publishing [\#542](https://github.com/pypeclub/pype/issues/542)
|
||||
- Pathlib breaks compatibility with python2 hosts [\#281](https://github.com/pypeclub/pype/issues/281)
|
||||
- Updating a look where the shader name changed leaves the geo without a shader [\#237](https://github.com/pypeclub/pype/issues/237)
|
||||
- Better error handling [\#84](https://github.com/pypeclub/pype/issues/84)
|
||||
- Harmony: function signature [\#609](https://github.com/pypeclub/pype/pull/609)
|
||||
- Nuke: gizmo publishing error [\#594](https://github.com/pypeclub/pype/pull/594)
|
||||
- Harmony: fix clashing namespace of called js functions [\#584](https://github.com/pypeclub/pype/pull/584)
|
||||
- Maya: fix maya scene type preset exception [\#569](https://github.com/pypeclub/pype/pull/569)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Nuke Gizmo publishing [\#597](https://github.com/pypeclub/pype/issues/597)
|
||||
- nuke gizmo publishing error [\#592](https://github.com/pypeclub/pype/issues/592)
|
||||
- Publish EDL [\#579](https://github.com/pypeclub/pype/issues/579)
|
||||
- Publish render from SP [\#576](https://github.com/pypeclub/pype/issues/576)
|
||||
- rename ftrack custom attribute group to `pype` [\#184](https://github.com/pypeclub/pype/issues/184)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Audio file existence check [\#614](https://github.com/pypeclub/pype/pull/614)
|
||||
- NKS small fixes [\#587](https://github.com/pypeclub/pype/pull/587)
|
||||
- Standalone publisher editorial plugins interfering [\#580](https://github.com/pypeclub/pype/pull/580)
|
||||
|
||||
## [2.12.2](https://github.com/pypeclub/pype/tree/2.12.2) (2020-09-25)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.12.1...2.12.2)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- pype config GUI [\#241](https://github.com/pypeclub/pype/issues/241)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Harmony: Saving heavy scenes will crash [\#507](https://github.com/pypeclub/pype/issues/507)
|
||||
- Extract review a representation name with `\*\_burnin` [\#388](https://github.com/pypeclub/pype/issues/388)
|
||||
- Hierarchy data was not considering active isntances [\#551](https://github.com/pypeclub/pype/pull/551)
|
||||
|
||||
## [2.12.1](https://github.com/pypeclub/pype/tree/2.12.1) (2020-09-15)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.12.0...2.12.1)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Pype: changelog.md is outdated [\#503](https://github.com/pypeclub/pype/issues/503)
|
||||
- dependency security alert ! [\#484](https://github.com/pypeclub/pype/issues/484)
|
||||
- Maya: RenderSetup is missing update [\#106](https://github.com/pypeclub/pype/issues/106)
|
||||
- \<pyblish plugin\> extract effects creates new instance [\#78](https://github.com/pypeclub/pype/issues/78)
|
||||
|
||||
## [2.12.0](https://github.com/pypeclub/pype/tree/2.12.0) (2020-09-10)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.11.8...2.12.0)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- Less mongo connections [\#509](https://github.com/pypeclub/pype/pull/509)
|
||||
- Nuke: adding image loader [\#499](https://github.com/pypeclub/pype/pull/499)
|
||||
- Move launcher window to top if launcher action is clicked [\#450](https://github.com/pypeclub/pype/pull/450)
|
||||
- Maya: better tile rendering support in Pype [\#446](https://github.com/pypeclub/pype/pull/446)
|
||||
- Implementation of non QML launcher [\#443](https://github.com/pypeclub/pype/pull/443)
|
||||
- Optional skip review on renders. [\#441](https://github.com/pypeclub/pype/pull/441)
|
||||
- Ftrack: Option to push status from task to latest version [\#440](https://github.com/pypeclub/pype/pull/440)
|
||||
- Properly containerize image plane loads. [\#434](https://github.com/pypeclub/pype/pull/434)
|
||||
- Option to keep the review files. [\#426](https://github.com/pypeclub/pype/pull/426)
|
||||
- Isolate view on instance members. [\#425](https://github.com/pypeclub/pype/pull/425)
|
||||
- Maya: Publishing of tile renderings on Deadline [\#398](https://github.com/pypeclub/pype/pull/398)
|
||||
- Feature/little bit better logging gui [\#383](https://github.com/pypeclub/pype/pull/383)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Maya: Fix tile order for Draft Tile Assembler [\#511](https://github.com/pypeclub/pype/pull/511)
|
||||
- Remove extra dash [\#501](https://github.com/pypeclub/pype/pull/501)
|
||||
- Fix: strip dot from repre names in single frame renders [\#498](https://github.com/pypeclub/pype/pull/498)
|
||||
- Better handling of destination during integrating [\#485](https://github.com/pypeclub/pype/pull/485)
|
||||
- Fix: allow thumbnail creation for single frame renders [\#460](https://github.com/pypeclub/pype/pull/460)
|
||||
- added missing argument to launch\_application in ftrack app handler [\#453](https://github.com/pypeclub/pype/pull/453)
|
||||
- Burnins: Copy bit rate of input video to match quality. [\#448](https://github.com/pypeclub/pype/pull/448)
|
||||
- Standalone publisher is now independent from tray [\#442](https://github.com/pypeclub/pype/pull/442)
|
||||
- Bugfix/empty enumerator attributes [\#436](https://github.com/pypeclub/pype/pull/436)
|
||||
- Fixed wrong order of "other" category collapssing in publisher [\#435](https://github.com/pypeclub/pype/pull/435)
|
||||
- Multiple reviews where being overwritten to one. [\#424](https://github.com/pypeclub/pype/pull/424)
|
||||
- Cleanup plugin fail on instances without staging dir [\#420](https://github.com/pypeclub/pype/pull/420)
|
||||
- deprecated -intra parameter in ffmpeg to new `-g` [\#417](https://github.com/pypeclub/pype/pull/417)
|
||||
- Delivery action can now work with entered path [\#397](https://github.com/pypeclub/pype/pull/397)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Review on instance.data [\#473](https://github.com/pypeclub/pype/pull/473)
|
||||
|
||||
## [2.11.8](https://github.com/pypeclub/pype/tree/2.11.8) (2020-08-27)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.11.7...2.11.8)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- DWAA support for Maya [\#382](https://github.com/pypeclub/pype/issues/382)
|
||||
- Isolate View on Playblast [\#367](https://github.com/pypeclub/pype/issues/367)
|
||||
- Maya: Tile rendering [\#297](https://github.com/pypeclub/pype/issues/297)
|
||||
- single pype instance running [\#47](https://github.com/pypeclub/pype/issues/47)
|
||||
- PYPE-649: projects don't guarantee backwards compatible environment [\#8](https://github.com/pypeclub/pype/issues/8)
|
||||
- PYPE-663: separate venv for each deployed version [\#7](https://github.com/pypeclub/pype/issues/7)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- pyblish pype - other group is collapsed before plugins are done [\#431](https://github.com/pypeclub/pype/issues/431)
|
||||
- Alpha white edges in harmony on PNGs [\#412](https://github.com/pypeclub/pype/issues/412)
|
||||
- harmony image loader picks wrong representations [\#404](https://github.com/pypeclub/pype/issues/404)
|
||||
- Clockify crash when response contain symbol not allowed by UTF-8 [\#81](https://github.com/pypeclub/pype/issues/81)
|
||||
|
||||
## [2.11.7](https://github.com/pypeclub/pype/tree/2.11.7) (2020-08-21)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.11.6...2.11.7)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Clean Up Baked Movie [\#369](https://github.com/pypeclub/pype/issues/369)
|
||||
- celaction last workfile [\#459](https://github.com/pypeclub/pype/pull/459)
|
||||
|
||||
## [2.11.6](https://github.com/pypeclub/pype/tree/2.11.6) (2020-08-18)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.11.5...2.11.6)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- publisher app [\#56](https://github.com/pypeclub/pype/issues/56)
|
||||
|
||||
## [2.11.5](https://github.com/pypeclub/pype/tree/2.11.5) (2020-08-13)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.11.4...2.11.5)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- Switch from master to equivalent [\#220](https://github.com/pypeclub/pype/issues/220)
|
||||
- Standalone publisher now only groups sequence if the extension is known [\#439](https://github.com/pypeclub/pype/pull/439)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Logs have been disable for editorial by default to speed up publishing [\#433](https://github.com/pypeclub/pype/pull/433)
|
||||
- additional fixes for celaction [\#430](https://github.com/pypeclub/pype/pull/430)
|
||||
- Harmony: invalid variable scope in validate scene settings [\#428](https://github.com/pypeclub/pype/pull/428)
|
||||
- new representation name for audio was not accepted [\#427](https://github.com/pypeclub/pype/pull/427)
|
||||
|
||||
## [2.11.4](https://github.com/pypeclub/pype/tree/2.11.4) (2020-08-10)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.11.3...2.11.4)
|
||||
|
||||
**Enhancements:**
|
||||
|
||||
- WebSocket server [\#135](https://github.com/pypeclub/pype/issues/135)
|
||||
- standalonepublisher: editorial family features expansion \[master branch\] [\#411](https://github.com/pypeclub/pype/pull/411)
|
||||
|
||||
## [2.11.3](https://github.com/pypeclub/pype/tree/2.11.3) (2020-08-04)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.11.2...2.11.3)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Harmony: publishing performance issues [\#408](https://github.com/pypeclub/pype/pull/408)
|
||||
|
||||
## [2.11.2](https://github.com/pypeclub/pype/tree/2.11.2) (2020-07-31)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.11.1...2.11.2)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Ftrack to Avalon bug [\#406](https://github.com/pypeclub/pype/issues/406)
|
||||
|
||||
## [2.11.1](https://github.com/pypeclub/pype/tree/2.11.1) (2020-07-29)
|
||||
|
||||
[Full Changelog](https://github.com/pypeclub/pype/compare/2.11.0...2.11.1)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Celaction: metadata json folder fixes on path [\#393](https://github.com/pypeclub/pype/pull/393)
|
||||
- CelAction - version up method taken fro pype.lib [\#391](https://github.com/pypeclub/pype/pull/391)
|
||||
|
||||
<a name="2.11.0"></a>
|
||||
## 2.11.0 ##
|
||||
|
||||
|
|
@ -430,3 +787,6 @@ A large cleanup release. Most of the change are under the hood.
|
|||
- work directory was sometimes not being created correctly
|
||||
- major pype.lib cleanup. Removing of unused functions, merging those that were doing the same and general house cleaning.
|
||||
- _(avalon)_ subsets in maya 2019 weren't behaving correctly in the outliner
|
||||
|
||||
|
||||
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
|
||||
|
|
|
|||
|
|
@ -266,8 +266,8 @@ class AExpectedFiles:
|
|||
|
||||
def _generate_single_file_sequence(self, layer_data):
|
||||
expected_files = []
|
||||
file_prefix = layer_data["filePrefix"]
|
||||
for cam in layer_data["cameras"]:
|
||||
file_prefix = layer_data["filePrefix"]
|
||||
mappings = (
|
||||
(R_SUBSTITUTE_SCENE_TOKEN, layer_data["sceneName"]),
|
||||
(R_SUBSTITUTE_LAYER_TOKEN, layer_data["layerName"]),
|
||||
|
|
@ -299,9 +299,9 @@ class AExpectedFiles:
|
|||
def _generate_aov_file_sequences(self, layer_data):
|
||||
expected_files = []
|
||||
aov_file_list = {}
|
||||
file_prefix = layer_data["filePrefix"]
|
||||
for aov in layer_data["enabledAOVs"]:
|
||||
for cam in layer_data["cameras"]:
|
||||
file_prefix = layer_data["filePrefix"]
|
||||
|
||||
mappings = (
|
||||
(R_SUBSTITUTE_SCENE_TOKEN, layer_data["sceneName"]),
|
||||
|
|
@ -418,13 +418,12 @@ class AExpectedFiles:
|
|||
if connections:
|
||||
for connection in connections:
|
||||
if connection:
|
||||
node_name = connection.split(".")[0]
|
||||
if cmds.nodeType(node_name) == "renderLayer":
|
||||
attr_name = "%s.value" % ".".join(
|
||||
connection.split(".")[:-1]
|
||||
)
|
||||
if node_name == layer:
|
||||
yield cmds.getAttr(attr_name)
|
||||
# node_name = connection.split(".")[0]
|
||||
|
||||
attr_name = "%s.value" % ".".join(
|
||||
connection.split(".")[:-1]
|
||||
)
|
||||
yield cmds.getAttr(attr_name)
|
||||
|
||||
def get_render_attribute(self, attr):
|
||||
"""Get attribute from render options.
|
||||
|
|
@ -572,11 +571,17 @@ class ExpectedFilesVray(AExpectedFiles):
|
|||
expected_files = super(ExpectedFilesVray, self).get_files()
|
||||
|
||||
layer_data = self._get_layer_data()
|
||||
# remove 'beauty' from filenames as vray doesn't output it
|
||||
update = {}
|
||||
if layer_data.get("enabledAOVs"):
|
||||
expected_files[0][u"beauty"] = self._generate_single_file_sequence(
|
||||
layer_data
|
||||
) # noqa: E501
|
||||
for aov, seq in expected_files[0].items():
|
||||
if aov.startswith("beauty"):
|
||||
new_list = []
|
||||
for f in seq:
|
||||
new_list.append(f.replace("_beauty", ""))
|
||||
update[aov] = new_list
|
||||
|
||||
expected_files[0].update(update)
|
||||
return expected_files
|
||||
|
||||
def get_aovs(self):
|
||||
|
|
@ -630,28 +635,49 @@ class ExpectedFilesVray(AExpectedFiles):
|
|||
# todo: find how vray set format for AOVs
|
||||
enabled_aovs.append(
|
||||
(self._get_vray_aov_name(aov), default_ext))
|
||||
enabled_aovs.append(
|
||||
(u"beauty", default_ext)
|
||||
)
|
||||
return enabled_aovs
|
||||
|
||||
def _get_vray_aov_name(self, node):
|
||||
"""Get AOVs name from Vray.
|
||||
|
||||
# Get render element pass type
|
||||
vray_node_attr = next(
|
||||
attr
|
||||
for attr in cmds.listAttr(node)
|
||||
if attr.startswith("vray_name")
|
||||
)
|
||||
pass_type = vray_node_attr.rsplit("_", 1)[-1]
|
||||
Args:
|
||||
node (str): aov node name.
|
||||
|
||||
# Support V-Ray extratex explicit name (if set by user)
|
||||
if pass_type == "extratex":
|
||||
explicit_attr = "{}.vray_explicit_name_extratex".format(node)
|
||||
explicit_name = cmds.getAttr(explicit_attr)
|
||||
if explicit_name:
|
||||
return explicit_name
|
||||
Returns:
|
||||
str: aov name.
|
||||
|
||||
# Node type is in the attribute name but we need to check if value
|
||||
# of the attribute as it can be changed
|
||||
return cmds.getAttr("{}.{}".format(node, vray_node_attr))
|
||||
"""
|
||||
vray_name = None
|
||||
vray_explicit_name = None
|
||||
vray_file_name = None
|
||||
for attr in cmds.listAttr(node):
|
||||
if attr.startswith("vray_filename"):
|
||||
vray_file_name = cmds.getAttr("{}.{}".format(node, attr))
|
||||
elif attr.startswith("vray_name"):
|
||||
vray_name = cmds.getAttr("{}.{}".format(node, attr))
|
||||
elif attr.startswith("vray_explicit_name"):
|
||||
vray_explicit_name = cmds.getAttr("{}.{}".format(node, attr))
|
||||
|
||||
if vray_file_name is not None and vray_file_name != "":
|
||||
final_name = vray_file_name
|
||||
elif vray_explicit_name is not None and vray_explicit_name != "":
|
||||
final_name = vray_explicit_name
|
||||
elif vray_name is not None and vray_name != "":
|
||||
final_name = vray_name
|
||||
else:
|
||||
continue
|
||||
# special case for Material Select elements - these are named
|
||||
# based on the materia they are connected to.
|
||||
if "vray_mtl_mtlselect" in cmds.listAttr(node):
|
||||
connections = cmds.listConnections(
|
||||
"{}.vray_mtl_mtlselect".format(node))
|
||||
if connections:
|
||||
final_name += '_{}'.format(str(connections[0]))
|
||||
|
||||
return final_name
|
||||
|
||||
|
||||
class ExpectedFilesRedshift(AExpectedFiles):
|
||||
|
|
|
|||
|
|
@ -520,6 +520,7 @@ class AbstractSubmitDeadline(pyblish.api.InstancePlugin):
|
|||
f.replace(orig_scene, new_scene)
|
||||
)
|
||||
new_exp[aov] = replaced_files
|
||||
# [] might be too much here, TODO
|
||||
self._instance.data["expectedFiles"] = [new_exp]
|
||||
else:
|
||||
new_exp = []
|
||||
|
|
@ -527,7 +528,8 @@ class AbstractSubmitDeadline(pyblish.api.InstancePlugin):
|
|||
new_exp.append(
|
||||
f.replace(orig_scene, new_scene)
|
||||
)
|
||||
self._instance.data["expectedFiles"] = [new_exp]
|
||||
self._instance.data["expectedFiles"] = new_exp
|
||||
|
||||
self.log.info("Scene name was switched {} -> {}".format(
|
||||
orig_scene, new_scene
|
||||
))
|
||||
|
|
|
|||
|
|
@ -252,6 +252,9 @@ class AfterEffectsServerStub():
|
|||
Args:
|
||||
item_id (int):
|
||||
|
||||
Returns:
|
||||
(namedtuple)
|
||||
|
||||
"""
|
||||
res = self.websocketserver.call(self.client.call
|
||||
('AfterEffects.get_work_area',
|
||||
|
|
@ -305,6 +308,35 @@ class AfterEffectsServerStub():
|
|||
image_path=project_path,
|
||||
as_copy=as_copy))
|
||||
|
||||
def get_render_info(self):
|
||||
""" Get render queue info for render purposes
|
||||
|
||||
Returns:
|
||||
(namedtuple): with 'file_name' field
|
||||
"""
|
||||
res = self.websocketserver.call(self.client.call
|
||||
('AfterEffects.get_render_info'))
|
||||
|
||||
records = self._to_records(res)
|
||||
if records:
|
||||
return records.pop()
|
||||
|
||||
log.debug("Render queue needs to have file extension in 'Output to'")
|
||||
|
||||
def get_audio_url(self, item_id):
|
||||
""" Get audio layer absolute url for comp
|
||||
|
||||
Args:
|
||||
item_id (int): composition id
|
||||
Returns:
|
||||
(str): absolute path url
|
||||
"""
|
||||
res = self.websocketserver.call(self.client.call
|
||||
('AfterEffects.get_audio_url',
|
||||
item_id=item_id))
|
||||
|
||||
return res
|
||||
|
||||
def close(self):
|
||||
self.client.close()
|
||||
|
||||
|
|
|
|||
27
pype/plugins/aftereffects/publish/collect_audio.py
Normal file
27
pype/plugins/aftereffects/publish/collect_audio.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import os
|
||||
|
||||
import pyblish.api
|
||||
|
||||
from avalon import aftereffects
|
||||
|
||||
|
||||
class CollectAudio(pyblish.api.ContextPlugin):
|
||||
"""Inject audio file url for rendered composition into context.
|
||||
Needs to run AFTER 'collect_render'. Use collected comp_id to check
|
||||
if there is an AVLayer in this composition
|
||||
"""
|
||||
|
||||
order = pyblish.api.CollectorOrder + 0.499
|
||||
label = "Collect Audio"
|
||||
hosts = ["aftereffects"]
|
||||
|
||||
def process(self, context):
|
||||
for instance in context:
|
||||
if instance.data["family"] == 'render.farm':
|
||||
comp_id = instance.data["comp_id"]
|
||||
if not comp_id:
|
||||
self.log.debug("No comp_id filled in instance")
|
||||
return
|
||||
context.data["audioFile"] = os.path.normpath(
|
||||
aftereffects.stub().get_audio_url(comp_id)
|
||||
).replace("\\", "/")
|
||||
|
|
@ -11,6 +11,7 @@ from avalon import aftereffects
|
|||
class AERenderInstance(RenderInstance):
|
||||
# extend generic, composition name is needed
|
||||
comp_name = attr.ib(default=None)
|
||||
comp_id = attr.ib(default=None)
|
||||
|
||||
|
||||
class CollectAERender(abstract_collect_render.AbstractCollectRender):
|
||||
|
|
@ -39,13 +40,11 @@ class CollectAERender(abstract_collect_render.AbstractCollectRender):
|
|||
continue
|
||||
|
||||
work_area_info = aftereffects.stub().get_work_area(int(item_id))
|
||||
frameStart = round(float(work_area_info.workAreaStart) *
|
||||
float(work_area_info.frameRate))
|
||||
frameStart = work_area_info.workAreaStart
|
||||
|
||||
frameEnd = round(float(work_area_info.workAreaStart) *
|
||||
float(work_area_info.frameRate) +
|
||||
frameEnd = round(work_area_info.workAreaStart +
|
||||
float(work_area_info.workAreaDuration) *
|
||||
float(work_area_info.frameRate))
|
||||
float(work_area_info.frameRate)) - 1
|
||||
|
||||
if inst["family"] == "render" and inst["active"]:
|
||||
instance = AERenderInstance(
|
||||
|
|
@ -83,6 +82,7 @@ class CollectAERender(abstract_collect_render.AbstractCollectRender):
|
|||
raise ValueError("There is no composition for item {}".
|
||||
format(item_id))
|
||||
instance.comp_name = comp.name
|
||||
instance.comp_id = item_id
|
||||
instance._anatomy = context.data["anatomy"]
|
||||
instance.anatomyData = context.data["anatomyData"]
|
||||
|
||||
|
|
@ -108,18 +108,29 @@ class CollectAERender(abstract_collect_render.AbstractCollectRender):
|
|||
start = render_instance.frameStart
|
||||
end = render_instance.frameEnd
|
||||
|
||||
# pull file name from Render Queue Output module
|
||||
render_q = aftereffects.stub().get_render_info()
|
||||
_, ext = os.path.splitext(os.path.basename(render_q.file_name))
|
||||
base_dir = self._get_output_dir(render_instance)
|
||||
expected_files = []
|
||||
for frame in range(start, end + 1):
|
||||
path = os.path.join(base_dir, "{}_{}_{}.{}.{}".format(
|
||||
render_instance.asset,
|
||||
render_instance.subset,
|
||||
"v{:03d}".format(render_instance.version),
|
||||
str(frame).zfill(self.padding_width),
|
||||
self.rendered_extension
|
||||
))
|
||||
if "#" not in render_q.file_name: # single frame (mov)W
|
||||
path = os.path.join(base_dir, "{}_{}_{}.{}".format(
|
||||
render_instance.asset,
|
||||
render_instance.subset,
|
||||
"v{:03d}".format(render_instance.version),
|
||||
ext.replace('.', '')
|
||||
))
|
||||
expected_files.append(path)
|
||||
|
||||
else:
|
||||
for frame in range(start, end + 1):
|
||||
path = os.path.join(base_dir, "{}_{}_{}.{}.{}".format(
|
||||
render_instance.asset,
|
||||
render_instance.subset,
|
||||
"v{:03d}".format(render_instance.version),
|
||||
str(frame).zfill(self.padding_width),
|
||||
ext.replace('.', '')
|
||||
))
|
||||
expected_files.append(path)
|
||||
return expected_files
|
||||
|
||||
def _get_output_dir(self, render_instance):
|
||||
|
|
|
|||
14
pype/plugins/aftereffects/publish/extract_save_scene.py
Normal file
14
pype/plugins/aftereffects/publish/extract_save_scene.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import pype.api
|
||||
from avalon import aftereffects
|
||||
|
||||
|
||||
class ExtractSaveScene(pype.api.Extractor):
|
||||
"""Save scene before extraction."""
|
||||
|
||||
order = pype.api.Extractor.order - 0.49
|
||||
label = "Extract Save Scene"
|
||||
hosts = ["aftereffects"]
|
||||
families = ["workfile"]
|
||||
|
||||
def process(self, instance):
|
||||
aftereffects.stub().save()
|
||||
|
|
@ -18,15 +18,18 @@ class DeadlinePluginInfo():
|
|||
ProjectPath = attr.ib(default=None)
|
||||
AWSAssetFile0 = attr.ib(default=None)
|
||||
Version = attr.ib(default=None)
|
||||
MultiProcess = attr.ib(default=None)
|
||||
|
||||
|
||||
class AfterEffectsSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline):
|
||||
|
||||
label = "Submit AE to Deadline"
|
||||
order = pyblish.api.IntegratorOrder
|
||||
order = pyblish.api.IntegratorOrder + 0.1
|
||||
hosts = ["aftereffects"]
|
||||
families = ["render.farm"] # cannot be "render' as that is integrated
|
||||
use_published = False
|
||||
use_published = True
|
||||
|
||||
chunk_size = 1000000
|
||||
|
||||
def get_job_info(self):
|
||||
dln_job_info = DeadlineJobInfo(Plugin="AfterEffects")
|
||||
|
|
@ -39,9 +42,12 @@ class AfterEffectsSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline
|
|||
dln_job_info.Plugin = "AfterEffects"
|
||||
dln_job_info.UserName = context.data.get(
|
||||
"deadlineUser", getpass.getuser())
|
||||
frame_range = "{}-{}".format(self._instance.data["frameStart"],
|
||||
self._instance.data["frameEnd"])
|
||||
dln_job_info.Frames = frame_range
|
||||
if self._instance.data["frameEnd"] > self._instance.data["frameStart"]:
|
||||
frame_range = "{}-{}".format(self._instance.data["frameStart"],
|
||||
self._instance.data["frameEnd"])
|
||||
dln_job_info.Frames = frame_range
|
||||
|
||||
dln_job_info.ChunkSize = self.chunk_size
|
||||
dln_job_info.OutputFilename = \
|
||||
os.path.basename(self._instance.data["expectedFiles"][0])
|
||||
dln_job_info.OutputDirectory = \
|
||||
|
|
@ -77,21 +83,25 @@ class AfterEffectsSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline
|
|||
script_path = context.data["currentFile"]
|
||||
|
||||
render_path = self._instance.data["expectedFiles"][0]
|
||||
# replace frame info ('000001') with Deadline's required '[#######]'
|
||||
# expects filename in format project_asset_subset_version.FRAME.ext
|
||||
render_dir = os.path.dirname(render_path)
|
||||
file_name = os.path.basename(render_path)
|
||||
arr = file_name.split('.')
|
||||
assert len(arr) == 3, \
|
||||
"Unable to parse frames from {}".format(file_name)
|
||||
hashed = '[{}]'.format(len(arr[1]) * "#")
|
||||
|
||||
render_path = os.path.join(render_dir,
|
||||
'{}.{}.{}'.format(arr[0], hashed, arr[2]))
|
||||
if len(self._instance.data["expectedFiles"]) > 1:
|
||||
# replace frame ('000001') with Deadline's required '[#######]'
|
||||
# expects filename in format project_asset_subset_version.FRAME.ext
|
||||
render_dir = os.path.dirname(render_path)
|
||||
file_name = os.path.basename(render_path)
|
||||
arr = file_name.split('.')
|
||||
assert len(arr) == 3, \
|
||||
"Unable to parse frames from {}".format(file_name)
|
||||
hashed = '[{}]'.format(len(arr[1]) * "#")
|
||||
|
||||
render_path = os.path.join(render_dir,
|
||||
'{}.{}.{}'.format(arr[0], hashed,
|
||||
arr[2]))
|
||||
|
||||
deadline_plugin_info.MultiProcess = True
|
||||
deadline_plugin_info.Comp = self._instance.data["comp_name"]
|
||||
deadline_plugin_info.Version = "17.5"
|
||||
deadline_plugin_info.SceneFile = script_path
|
||||
deadline_plugin_info.SceneFile = self.scene_path
|
||||
deadline_plugin_info.Output = render_path.replace("\\", "/")
|
||||
|
||||
return attr.asdict(deadline_plugin_info)
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ class CollectFtrackApi(pyblish.api.ContextPlugin):
|
|||
task_entity = None
|
||||
self.log.warning("Task name is not set.")
|
||||
|
||||
context.data["ftrackPythonModule"] = ftrack_api
|
||||
context.data["ftrackProject"] = project_entity
|
||||
context.data["ftrackEntity"] = asset_entity
|
||||
context.data["ftrackTask"] = task_entity
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ class IntegrateHierarchyToFtrack(pyblish.api.ContextPlugin):
|
|||
order = pyblish.api.IntegratorOrder - 0.04
|
||||
label = 'Integrate Hierarchy To Ftrack'
|
||||
families = ["shot"]
|
||||
hosts = ["hiero"]
|
||||
optional = False
|
||||
|
||||
def process(self, context):
|
||||
|
|
|
|||
331
pype/plugins/ftrack/publish/integrate_hierarchy_ftrack_SP.py
Normal file
331
pype/plugins/ftrack/publish/integrate_hierarchy_ftrack_SP.py
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
import sys
|
||||
import six
|
||||
import collections
|
||||
import pyblish.api
|
||||
from avalon import io
|
||||
|
||||
from pype.modules.ftrack.lib.avalon_sync import (
|
||||
CUST_ATTR_AUTO_SYNC,
|
||||
get_pype_attr
|
||||
)
|
||||
|
||||
|
||||
class IntegrateHierarchyToFtrack(pyblish.api.ContextPlugin):
|
||||
"""
|
||||
Create entities in ftrack based on collected data from premiere
|
||||
Example of entry data:
|
||||
{
|
||||
"ProjectXS": {
|
||||
"entity_type": "Project",
|
||||
"custom_attributes": {
|
||||
"fps": 24,...
|
||||
},
|
||||
"tasks": [
|
||||
"Compositing",
|
||||
"Lighting",... *task must exist as task type in project schema*
|
||||
],
|
||||
"childs": {
|
||||
"sq01": {
|
||||
"entity_type": "Sequence",
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
order = pyblish.api.IntegratorOrder - 0.04
|
||||
label = 'Integrate Hierarchy To Ftrack'
|
||||
families = ["shot"]
|
||||
hosts = ["standalonepublisher"]
|
||||
optional = False
|
||||
|
||||
def process(self, context):
|
||||
self.context = context
|
||||
if "hierarchyContext" not in self.context.data:
|
||||
return
|
||||
|
||||
hierarchy_context = self.context.data["hierarchyContext"]
|
||||
|
||||
self.session = self.context.data["ftrackSession"]
|
||||
project_name = self.context.data["projectEntity"]["name"]
|
||||
query = 'Project where full_name is "{}"'.format(project_name)
|
||||
project = self.session.query(query).one()
|
||||
auto_sync_state = project[
|
||||
"custom_attributes"][CUST_ATTR_AUTO_SYNC]
|
||||
|
||||
if not io.Session:
|
||||
io.install()
|
||||
|
||||
self.ft_project = None
|
||||
|
||||
input_data = hierarchy_context
|
||||
|
||||
# disable termporarily ftrack project's autosyncing
|
||||
if auto_sync_state:
|
||||
self.auto_sync_off(project)
|
||||
|
||||
try:
|
||||
# import ftrack hierarchy
|
||||
self.import_to_ftrack(input_data)
|
||||
except Exception:
|
||||
raise
|
||||
finally:
|
||||
if auto_sync_state:
|
||||
self.auto_sync_on(project)
|
||||
|
||||
def import_to_ftrack(self, input_data, parent=None):
|
||||
# Prequery hiearchical custom attributes
|
||||
hier_custom_attributes = get_pype_attr(self.session)[1]
|
||||
hier_attr_by_key = {
|
||||
attr["key"]: attr
|
||||
for attr in hier_custom_attributes
|
||||
}
|
||||
# Get ftrack api module (as they are different per python version)
|
||||
ftrack_api = self.context.data["ftrackPythonModule"]
|
||||
|
||||
for entity_name in input_data:
|
||||
entity_data = input_data[entity_name]
|
||||
entity_type = entity_data['entity_type']
|
||||
self.log.debug(entity_data)
|
||||
self.log.debug(entity_type)
|
||||
|
||||
if entity_type.lower() == 'project':
|
||||
query = 'Project where full_name is "{}"'.format(entity_name)
|
||||
entity = self.session.query(query).one()
|
||||
self.ft_project = entity
|
||||
self.task_types = self.get_all_task_types(entity)
|
||||
|
||||
elif self.ft_project is None or parent is None:
|
||||
raise AssertionError(
|
||||
"Collected items are not in right order!"
|
||||
)
|
||||
|
||||
# try to find if entity already exists
|
||||
else:
|
||||
query = (
|
||||
'TypedContext where name is "{0}" and '
|
||||
'project_id is "{1}"'
|
||||
).format(entity_name, self.ft_project["id"])
|
||||
try:
|
||||
entity = self.session.query(query).one()
|
||||
except Exception:
|
||||
entity = None
|
||||
|
||||
# Create entity if not exists
|
||||
if entity is None:
|
||||
entity = self.create_entity(
|
||||
name=entity_name,
|
||||
type=entity_type,
|
||||
parent=parent
|
||||
)
|
||||
# self.log.info('entity: {}'.format(dict(entity)))
|
||||
# CUSTOM ATTRIBUTES
|
||||
custom_attributes = entity_data.get('custom_attributes', [])
|
||||
instances = [
|
||||
i for i in self.context if i.data['asset'] in entity['name']
|
||||
]
|
||||
for key in custom_attributes:
|
||||
hier_attr = hier_attr_by_key.get(key)
|
||||
# Use simple method if key is not hierarchical
|
||||
if not hier_attr:
|
||||
assert (key in entity['custom_attributes']), (
|
||||
'Missing custom attribute key: `{0}` in attrs: '
|
||||
'`{1}`'.format(key, entity['custom_attributes'].keys())
|
||||
)
|
||||
|
||||
entity['custom_attributes'][key] = custom_attributes[key]
|
||||
|
||||
else:
|
||||
# Use ftrack operations method to set hiearchical
|
||||
# attribute value.
|
||||
# - this is because there may be non hiearchical custom
|
||||
# attributes with different properties
|
||||
entity_key = collections.OrderedDict({
|
||||
"configuration_id": hier_attr["id"],
|
||||
"entity_id": entity["id"]
|
||||
})
|
||||
self.session.recorded_operations.push(
|
||||
ftrack_api.operation.UpdateEntityOperation(
|
||||
"ContextCustomAttributeValue",
|
||||
entity_key,
|
||||
"value",
|
||||
ftrack_api.symbol.NOT_SET,
|
||||
custom_attributes[key]
|
||||
)
|
||||
)
|
||||
|
||||
for instance in instances:
|
||||
instance.data['ftrackEntity'] = entity
|
||||
|
||||
try:
|
||||
self.session.commit()
|
||||
except Exception:
|
||||
tp, value, tb = sys.exc_info()
|
||||
self.session.rollback()
|
||||
self.session._configure_locations()
|
||||
six.reraise(tp, value, tb)
|
||||
|
||||
# TASKS
|
||||
tasks = entity_data.get('tasks', [])
|
||||
existing_tasks = []
|
||||
tasks_to_create = []
|
||||
for child in entity['children']:
|
||||
if child.entity_type.lower() == 'task':
|
||||
existing_tasks.append(child['name'].lower())
|
||||
# existing_tasks.append(child['type']['name'])
|
||||
|
||||
for task_name in tasks:
|
||||
task_type = tasks[task_name]["type"]
|
||||
if task_name.lower() in existing_tasks:
|
||||
print("Task {} already exists".format(task_name))
|
||||
continue
|
||||
tasks_to_create.append((task_name, task_type))
|
||||
|
||||
for task_name, task_type in tasks_to_create:
|
||||
self.create_task(
|
||||
name=task_name,
|
||||
task_type=task_type,
|
||||
parent=entity
|
||||
)
|
||||
try:
|
||||
self.session.commit()
|
||||
except Exception:
|
||||
tp, value, tb = sys.exc_info()
|
||||
self.session.rollback()
|
||||
self.session._configure_locations()
|
||||
six.reraise(tp, value, tb)
|
||||
|
||||
# Incoming links.
|
||||
self.create_links(entity_data, entity)
|
||||
try:
|
||||
self.session.commit()
|
||||
except Exception:
|
||||
tp, value, tb = sys.exc_info()
|
||||
self.session.rollback()
|
||||
self.session._configure_locations()
|
||||
six.reraise(tp, value, tb)
|
||||
|
||||
# Create notes.
|
||||
user = self.session.query(
|
||||
"User where username is \"{}\"".format(self.session.api_user)
|
||||
).first()
|
||||
if user:
|
||||
for comment in entity_data.get("comments", []):
|
||||
entity.create_note(comment, user)
|
||||
else:
|
||||
self.log.warning(
|
||||
"Was not able to query current User {}".format(
|
||||
self.session.api_user
|
||||
)
|
||||
)
|
||||
try:
|
||||
self.session.commit()
|
||||
except Exception:
|
||||
tp, value, tb = sys.exc_info()
|
||||
self.session.rollback()
|
||||
self.session._configure_locations()
|
||||
six.reraise(tp, value, tb)
|
||||
|
||||
# Import children.
|
||||
if 'childs' in entity_data:
|
||||
self.import_to_ftrack(
|
||||
entity_data['childs'], entity)
|
||||
|
||||
def create_links(self, entity_data, entity):
|
||||
# Clear existing links.
|
||||
for link in entity.get("incoming_links", []):
|
||||
self.session.delete(link)
|
||||
try:
|
||||
self.session.commit()
|
||||
except Exception:
|
||||
tp, value, tb = sys.exc_info()
|
||||
self.session.rollback()
|
||||
self.session._configure_locations()
|
||||
six.reraise(tp, value, tb)
|
||||
|
||||
# Create new links.
|
||||
for input in entity_data.get("inputs", []):
|
||||
input_id = io.find_one({"_id": input})["data"]["ftrackId"]
|
||||
assetbuild = self.session.get("AssetBuild", input_id)
|
||||
self.log.debug(
|
||||
"Creating link from {0} to {1}".format(
|
||||
assetbuild["name"], entity["name"]
|
||||
)
|
||||
)
|
||||
self.session.create(
|
||||
"TypedContextLink", {"from": assetbuild, "to": entity}
|
||||
)
|
||||
|
||||
def get_all_task_types(self, project):
|
||||
tasks = {}
|
||||
proj_template = project['project_schema']
|
||||
temp_task_types = proj_template['_task_type_schema']['types']
|
||||
|
||||
for type in temp_task_types:
|
||||
if type['name'] not in tasks:
|
||||
tasks[type['name']] = type
|
||||
|
||||
return tasks
|
||||
|
||||
def create_task(self, name, task_type, parent):
|
||||
task = self.session.create('Task', {
|
||||
'name': name,
|
||||
'parent': parent
|
||||
})
|
||||
# TODO not secured!!! - check if task_type exists
|
||||
self.log.info(task_type)
|
||||
self.log.info(self.task_types)
|
||||
task['type'] = self.task_types[task_type]
|
||||
|
||||
try:
|
||||
self.session.commit()
|
||||
except Exception:
|
||||
tp, value, tb = sys.exc_info()
|
||||
self.session.rollback()
|
||||
self.session._configure_locations()
|
||||
six.reraise(tp, value, tb)
|
||||
|
||||
return task
|
||||
|
||||
def create_entity(self, name, type, parent):
|
||||
entity = self.session.create(type, {
|
||||
'name': name,
|
||||
'parent': parent
|
||||
})
|
||||
try:
|
||||
self.session.commit()
|
||||
except Exception:
|
||||
tp, value, tb = sys.exc_info()
|
||||
self.session.rollback()
|
||||
self.session._configure_locations()
|
||||
six.reraise(tp, value, tb)
|
||||
|
||||
return entity
|
||||
|
||||
def auto_sync_off(self, project):
|
||||
project["custom_attributes"][CUST_ATTR_AUTO_SYNC] = False
|
||||
|
||||
self.log.info("Ftrack autosync swithed off")
|
||||
|
||||
try:
|
||||
self.session.commit()
|
||||
except Exception:
|
||||
tp, value, tb = sys.exc_info()
|
||||
self.session.rollback()
|
||||
self.session._configure_locations()
|
||||
six.reraise(tp, value, tb)
|
||||
|
||||
def auto_sync_on(self, project):
|
||||
|
||||
project["custom_attributes"][CUST_ATTR_AUTO_SYNC] = True
|
||||
|
||||
self.log.info("Ftrack autosync swithed on")
|
||||
|
||||
try:
|
||||
self.session.commit()
|
||||
except Exception:
|
||||
tp, value, tb = sys.exc_info()
|
||||
self.session.rollback()
|
||||
self.session._configure_locations()
|
||||
six.reraise(tp, value, tb)
|
||||
|
|
@ -280,6 +280,15 @@ class ExtractReview(pyblish.api.InstancePlugin):
|
|||
|
||||
handles_are_set = handle_start > 0 or handle_end > 0
|
||||
|
||||
with_audio = True
|
||||
if (
|
||||
# Check if has `no-audio` tag
|
||||
"no-audio" in output_def["tags"]
|
||||
# Check if instance has ny audio in data
|
||||
or not instance.data.get("audio")
|
||||
):
|
||||
with_audio = False
|
||||
|
||||
return {
|
||||
"fps": float(instance.data["fps"]),
|
||||
"frame_start": frame_start,
|
||||
|
|
@ -295,6 +304,7 @@ class ExtractReview(pyblish.api.InstancePlugin):
|
|||
"resolution_height": instance.data.get("resolutionHeight"),
|
||||
"origin_repre": repre,
|
||||
"input_is_sequence": self.input_is_sequence(repre),
|
||||
"with_audio": with_audio,
|
||||
"without_handles": without_handles,
|
||||
"handles_are_set": handles_are_set
|
||||
}
|
||||
|
|
@ -389,7 +399,7 @@ class ExtractReview(pyblish.api.InstancePlugin):
|
|||
ffmpeg_output_args.append("-shortest")
|
||||
|
||||
# Add audio arguments if there are any. Skipped when output are images.
|
||||
if not temp_data["output_ext_is_image"]:
|
||||
if not temp_data["output_ext_is_image"] and temp_data["with_audio"]:
|
||||
audio_in_args, audio_filters, audio_out_args = self.audio_args(
|
||||
instance, temp_data
|
||||
)
|
||||
|
|
|
|||
|
|
@ -600,6 +600,13 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
|
|||
"files": os.path.basename(remainder),
|
||||
"stagingDir": os.path.dirname(remainder),
|
||||
}
|
||||
if "render" in instance.get("families"):
|
||||
rep.update({
|
||||
"fps": instance.get("fps"),
|
||||
"tags": ["review"]
|
||||
})
|
||||
self._solve_families(instance, True)
|
||||
|
||||
if remainder in bake_render_path:
|
||||
rep.update({
|
||||
"fps": instance.get("fps"),
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ class ExtractReviewCutUp(pype.api.Extractor):
|
|||
def process(self, instance):
|
||||
inst_data = instance.data
|
||||
asset = inst_data['asset']
|
||||
item = inst_data['item']
|
||||
event_number = int(item.eventNumber())
|
||||
|
||||
# get representation and loop them
|
||||
representations = inst_data["representations"]
|
||||
|
|
@ -97,7 +99,12 @@ class ExtractReviewCutUp(pype.api.Extractor):
|
|||
index = 0
|
||||
for image in collection:
|
||||
dst_file_num = frame_start + index
|
||||
dst_file_name = head + str(padding % dst_file_num) + tail
|
||||
dst_file_name = "".join([
|
||||
str(event_number),
|
||||
head,
|
||||
str(padding % dst_file_num),
|
||||
tail
|
||||
])
|
||||
src = os.path.join(staging_dir, image)
|
||||
dst = os.path.join(full_output_dir, dst_file_name)
|
||||
self.log.info("Creating temp hardlinks: {}".format(dst))
|
||||
|
|
|
|||
|
|
@ -350,7 +350,7 @@ class ExtractLook(pype.api.Extractor):
|
|||
if existing and not force:
|
||||
self.log.info("Found hash in database, preparing hardlink..")
|
||||
source = next((p for p in existing if os.path.exists(p)), None)
|
||||
if filepath:
|
||||
if source:
|
||||
return source, HARDLINK, texture_hash
|
||||
else:
|
||||
self.log.warning(
|
||||
|
|
|
|||
|
|
@ -162,6 +162,9 @@ class LoadImage(pipeline.Loader):
|
|||
"""
|
||||
# Create new containers first
|
||||
context = get_representation_context(representation)
|
||||
# Change `fname` to new representation
|
||||
self.fname = self.filepath_from_context(context)
|
||||
|
||||
name = container["name"]
|
||||
namespace = container["namespace"]
|
||||
new_container = self.load(context, name, namespace, {})
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
__version__ = "2.14.0"
|
||||
__version__ = "2.14.1"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue