diff --git a/CHANGELOG.md b/CHANGELOG.md index c616b70e3c..455c7aa900 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,17 +1,32 @@ # Changelog -## [3.14.4-nightly.1](https://github.com/pypeclub/OpenPype/tree/HEAD) +## [3.14.4-nightly.2](https://github.com/pypeclub/OpenPype/tree/HEAD) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.3...HEAD) +**🚀 Enhancements** + +- General: Set root environments before DCC launch [\#3947](https://github.com/pypeclub/OpenPype/pull/3947) +- Maya: Moved plugin from global to maya [\#3939](https://github.com/pypeclub/OpenPype/pull/3939) +- Publisher: Instances can be marked as stored [\#3846](https://github.com/pypeclub/OpenPype/pull/3846) + **🐛 Bug fixes** +- Photoshop: missed sync published version of workfile with workfile [\#3946](https://github.com/pypeclub/OpenPype/pull/3946) +- Maya: fix regression of Renderman Deadline hack [\#3943](https://github.com/pypeclub/OpenPype/pull/3943) +- AttributeDefs: Fix crashing multivalue of files widget [\#3937](https://github.com/pypeclub/OpenPype/pull/3937) - Publisher: Files Drag n Drop cleanup [\#3888](https://github.com/pypeclub/OpenPype/pull/3888) +- Maya: Render settings validation attribute check tweak logging [\#3821](https://github.com/pypeclub/OpenPype/pull/3821) **🔀 Refactored code** - General: import 'Logger' from 'openpype.lib' [\#3926](https://github.com/pypeclub/OpenPype/pull/3926) +**Merged pull requests:** + +- Photoshop: create single frame image in Ftrack as review [\#3908](https://github.com/pypeclub/OpenPype/pull/3908) +- Maya: Warn correctly about nodes in render instance with unexpected names [\#3816](https://github.com/pypeclub/OpenPype/pull/3816) + ## [3.14.3](https://github.com/pypeclub/OpenPype/tree/3.14.3) (2022-10-03) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.14.3-nightly.7...3.14.3) @@ -28,6 +43,7 @@ - Flame: make migratable projects after creation [\#3860](https://github.com/pypeclub/OpenPype/pull/3860) - Photoshop: synchronize image version with workfile [\#3854](https://github.com/pypeclub/OpenPype/pull/3854) - General: Transcoding handle float2 attr type [\#3849](https://github.com/pypeclub/OpenPype/pull/3849) +- General: Simple script for getting license information about used packages [\#3843](https://github.com/pypeclub/OpenPype/pull/3843) - General: Workfile template build enhancements [\#3838](https://github.com/pypeclub/OpenPype/pull/3838) - General: lock task workfiles when they are working on [\#3810](https://github.com/pypeclub/OpenPype/pull/3810) @@ -44,7 +60,6 @@ - Tray Publisher: skip plugin if otioTimeline is missing [\#3856](https://github.com/pypeclub/OpenPype/pull/3856) - Flame: retimed attributes are integrated with settings [\#3855](https://github.com/pypeclub/OpenPype/pull/3855) - Maya: Extract Playblast fix textures + labelize viewport show settings [\#3852](https://github.com/pypeclub/OpenPype/pull/3852) -- Maya: Publishing data key change [\#3811](https://github.com/pypeclub/OpenPype/pull/3811) **🔀 Refactored code** @@ -53,8 +68,8 @@ - Unreal: Use new Extractor location [\#3917](https://github.com/pypeclub/OpenPype/pull/3917) - Flame: Use new Extractor location [\#3916](https://github.com/pypeclub/OpenPype/pull/3916) - Houdini: Use new Extractor location [\#3894](https://github.com/pypeclub/OpenPype/pull/3894) -- Harmony: Use new Extractor location [\#3893](https://github.com/pypeclub/OpenPype/pull/3893) - Hiero: Use new Extractor location [\#3851](https://github.com/pypeclub/OpenPype/pull/3851) +- Maya: Remove old legacy \(ftrack\) plug-ins that are of no use anymore [\#3819](https://github.com/pypeclub/OpenPype/pull/3819) - Nuke: Use new Extractor location [\#3799](https://github.com/pypeclub/OpenPype/pull/3799) **Merged pull requests:** @@ -73,33 +88,27 @@ - Flame: OpenPype submenu to batch and media manager [\#3825](https://github.com/pypeclub/OpenPype/pull/3825) - General: Better pixmap scaling [\#3809](https://github.com/pypeclub/OpenPype/pull/3809) - Photoshop: attempt to speed up ExtractImage [\#3793](https://github.com/pypeclub/OpenPype/pull/3793) -- SyncServer: Added cli commands for sync server [\#3765](https://github.com/pypeclub/OpenPype/pull/3765) **🐛 Bug fixes** - General: Fix Pattern access in client code [\#3828](https://github.com/pypeclub/OpenPype/pull/3828) - Launcher: Skip opening last work file works for groups [\#3822](https://github.com/pypeclub/OpenPype/pull/3822) +- Maya: Publishing data key change [\#3811](https://github.com/pypeclub/OpenPype/pull/3811) - Igniter: Fix status handling when version is already installed [\#3804](https://github.com/pypeclub/OpenPype/pull/3804) - Resolve: Addon import is Python 2 compatible [\#3798](https://github.com/pypeclub/OpenPype/pull/3798) +- Hiero: retimed clip publishing is working [\#3792](https://github.com/pypeclub/OpenPype/pull/3792) - nuke: validate write node is not failing due wrong type [\#3780](https://github.com/pypeclub/OpenPype/pull/3780) - Fix - changed format of version string in pyproject.toml [\#3777](https://github.com/pypeclub/OpenPype/pull/3777) **🔀 Refactored code** -- Maya: Remove old legacy \(ftrack\) plug-ins that are of no use anymore [\#3819](https://github.com/pypeclub/OpenPype/pull/3819) - Photoshop: Use new Extractor location [\#3789](https://github.com/pypeclub/OpenPype/pull/3789) - Blender: Use new Extractor location [\#3787](https://github.com/pypeclub/OpenPype/pull/3787) - AfterEffects: Use new Extractor location [\#3784](https://github.com/pypeclub/OpenPype/pull/3784) -- General: Remove unused teshost [\#3773](https://github.com/pypeclub/OpenPype/pull/3773) -- General: Copied 'Extractor' plugin to publish pipeline [\#3771](https://github.com/pypeclub/OpenPype/pull/3771) -- General: Move queries of asset and representation links [\#3770](https://github.com/pypeclub/OpenPype/pull/3770) -- General: Move create project folders to pipeline [\#3768](https://github.com/pypeclub/OpenPype/pull/3768) -- General: Create project function moved to client code [\#3766](https://github.com/pypeclub/OpenPype/pull/3766) **Merged pull requests:** - Standalone Publisher: Ignore empty labels, then still use name like other asset models [\#3779](https://github.com/pypeclub/OpenPype/pull/3779) -- Kitsu - sync\_all\_project - add list ignore\_projects [\#3776](https://github.com/pypeclub/OpenPype/pull/3776) ## [3.14.1](https://github.com/pypeclub/OpenPype/tree/3.14.1) (2022-08-30) diff --git a/openpype/client/entity_links.py b/openpype/client/entity_links.py index 66214f469c..e42ac58aff 100644 --- a/openpype/client/entity_links.py +++ b/openpype/client/entity_links.py @@ -2,6 +2,7 @@ from .mongo import get_project_connection from .entities import ( get_assets, get_asset_by_id, + get_version_by_id, get_representation_by_id, convert_id, ) @@ -127,12 +128,20 @@ def get_linked_representation_id( if not version_id: return [] + version_doc = get_version_by_id( + project_name, version_id, fields=["type", "version_id"] + ) + if version_doc["type"] == "hero_version": + version_id = version_doc["version_id"] + if max_depth is None: max_depth = 0 match = { "_id": version_id, - "type": {"$in": ["version", "hero_version"]} + # Links are not stored to hero versions at this moment so filter + # is limited to just versions + "type": "version" } graph_lookup = { @@ -187,7 +196,7 @@ def _process_referenced_pipeline_result(result, link_type): referenced_version_ids = set() correctly_linked_ids = set() for item in result: - input_links = item["data"].get("inputLinks") + input_links = item.get("data", {}).get("inputLinks") if not input_links: continue @@ -203,7 +212,7 @@ def _process_referenced_pipeline_result(result, link_type): continue for output in sorted(outputs_recursive, key=lambda o: o["depth"]): - output_links = output["data"].get("inputLinks") + output_links = output.get("data", {}).get("inputLinks") if not output_links: continue diff --git a/openpype/hosts/houdini/plugins/publish/validate_workfile_paths.py b/openpype/hosts/houdini/plugins/publish/validate_workfile_paths.py index 79b3e894e5..0bd78ff38a 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_workfile_paths.py +++ b/openpype/hosts/houdini/plugins/publish/validate_workfile_paths.py @@ -35,6 +35,9 @@ class ValidateWorkfilePaths(pyblish.api.InstancePlugin): def get_invalid(cls): invalid = [] for param, _ in hou.fileReferences(): + if param is None: + continue + # skip nodes we are not interested in if param.node().type().name() not in cls.node_types: continue diff --git a/openpype/plugins/publish/validate_unique_names.py b/openpype/hosts/maya/plugins/publish/validate_unique_names.py similarity index 94% rename from openpype/plugins/publish/validate_unique_names.py rename to openpype/hosts/maya/plugins/publish/validate_unique_names.py index 33a460f7cc..05776ee0f3 100644 --- a/openpype/plugins/publish/validate_unique_names.py +++ b/openpype/hosts/maya/plugins/publish/validate_unique_names.py @@ -1,7 +1,6 @@ from maya import cmds import pyblish.api -import openpype.api import openpype.hosts.maya.api.action from openpype.pipeline.publish import ValidateContentsOrder @@ -24,7 +23,7 @@ class ValidateUniqueNames(pyblish.api.Validator): """Returns the invalid transforms in the instance. Returns: - list: Non unique name transforms + list: Non-unique name transforms. """ diff --git a/openpype/hosts/traypublisher/api/plugin.py b/openpype/hosts/traypublisher/api/plugin.py index 3bf1638651..89c25389cb 100644 --- a/openpype/hosts/traypublisher/api/plugin.py +++ b/openpype/hosts/traypublisher/api/plugin.py @@ -86,6 +86,8 @@ class TrayPublishCreator(Creator): # Host implementation of storing metadata about instance HostContext.add_instance(new_instance.data_to_store()) + new_instance.mark_as_stored() + # Add instance to current context self._add_instance_to_context(new_instance) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index a7e43cb2f2..c1cf4dab44 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -166,7 +166,10 @@ class AttributeValues: return self._data.pop(key, default) def reset_values(self): - self._data = [] + self._data = {} + + def mark_as_stored(self): + self._origin_data = copy.deepcopy(self._data) @property def attr_defs(self): @@ -303,6 +306,9 @@ class PublishAttributes: for name in self._plugin_names_order: yield name + def mark_as_stored(self): + self._origin_data = copy.deepcopy(self._data) + def data_to_store(self): """Convert attribute values to "data to store".""" @@ -646,6 +652,25 @@ class CreatedInstance: changes[key] = (old_value, None) return changes + def mark_as_stored(self): + """Should be called when instance data are stored. + + Origin data are replaced by current data so changes are cleared. + """ + + orig_keys = set(self._orig_data.keys()) + for key, value in self._data.items(): + orig_keys.discard(key) + if key in ("creator_attributes", "publish_attributes"): + continue + self._orig_data[key] = copy.deepcopy(value) + + for key in orig_keys: + self._orig_data.pop(key) + + self.creator_attributes.mark_as_stored() + self.publish_attributes.mark_as_stored() + @property def creator_attributes(self): return self._data["creator_attributes"] @@ -659,6 +684,18 @@ class CreatedInstance: return self._data["publish_attributes"] def data_to_store(self): + """Collect data that contain json parsable types. + + It is possible to recreate the instance using these data. + + Todo: + We probably don't need OrderedDict. When data are loaded they + are not ordered anymore. + + Returns: + OrderedDict: Ordered dictionary with instance data. + """ + output = collections.OrderedDict() for key, value in self._data.items(): if key in ("creator_attributes", "publish_attributes"): diff --git a/openpype/tools/loader/widgets.py b/openpype/tools/loader/widgets.py index c028aa4174..d37ce500e0 100644 --- a/openpype/tools/loader/widgets.py +++ b/openpype/tools/loader/widgets.py @@ -1256,7 +1256,11 @@ class RepresentationWidget(QtWidgets.QWidget): repre_doc["parent"] for repre_doc in repre_docs ] - version_docs = get_versions(project_name, version_ids=version_ids) + version_docs = get_versions( + project_name, + version_ids=version_ids, + hero=True + ) version_docs_by_id = {} version_docs_by_subset_id = collections.defaultdict(list) diff --git a/openpype/tools/tray/pype_tray.py b/openpype/tools/tray/pype_tray.py index 8a24b3eaa6..3842a4e216 100644 --- a/openpype/tools/tray/pype_tray.py +++ b/openpype/tools/tray/pype_tray.py @@ -775,12 +775,26 @@ class PypeTrayStarter(QtCore.QObject): def main(): log = Logger.get_logger(__name__) app = QtWidgets.QApplication.instance() + + high_dpi_scale_attr = None if not app: + # 'AA_EnableHighDpiScaling' must be set before app instance creation + high_dpi_scale_attr = getattr( + QtCore.Qt, "AA_EnableHighDpiScaling", None + ) + if high_dpi_scale_attr is not None: + QtWidgets.QApplication.setAttribute(high_dpi_scale_attr) + app = QtWidgets.QApplication([]) + if high_dpi_scale_attr is None: + log.debug(( + "Attribute 'AA_EnableHighDpiScaling' was not set." + " UI quality may be affected." + )) + for attr_name in ( - "AA_EnableHighDpiScaling", - "AA_UseHighDpiPixmaps" + "AA_UseHighDpiPixmaps", ): attr = getattr(QtCore.Qt, attr_name, None) if attr is None: diff --git a/openpype/version.py b/openpype/version.py index 50864c0f1c..1bd566aa9b 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.14.4-nightly.1" +__version__ = "3.14.4-nightly.2"