From 0adcf3334ad5a119341132c777540a22a5f51f30 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 13 Sep 2021 13:35:24 +0200 Subject: [PATCH 01/27] Added new InventoryAction to import (localize) reference in Maya PYPE-1399 --- openpype/hosts/maya/api/__init__.py | 1 + .../plugins/inventory/import_reference.py | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 openpype/hosts/maya/plugins/inventory/import_reference.py diff --git a/openpype/hosts/maya/api/__init__.py b/openpype/hosts/maya/api/__init__.py index 9219da407f..1c8534d9a5 100644 --- a/openpype/hosts/maya/api/__init__.py +++ b/openpype/hosts/maya/api/__init__.py @@ -35,6 +35,7 @@ def install(): pyblish.register_plugin_path(PUBLISH_PATH) avalon.register_plugin_path(avalon.Loader, LOAD_PATH) avalon.register_plugin_path(avalon.Creator, CREATE_PATH) + avalon.register_plugin_path(avalon.InventoryAction, INVENTORY_PATH) log.info(PUBLISH_PATH) menu.install() diff --git a/openpype/hosts/maya/plugins/inventory/import_reference.py b/openpype/hosts/maya/plugins/inventory/import_reference.py new file mode 100644 index 0000000000..d389c8733e --- /dev/null +++ b/openpype/hosts/maya/plugins/inventory/import_reference.py @@ -0,0 +1,27 @@ +from maya import cmds + +from avalon import api + + +class ImportReference(api.InventoryAction): + """Imports selected reference inside the file.""" + + label = "Import Reference" + icon = "mouse-pointer" + color = "#d8d8d8" + + def process(self, containers): + references = cmds.ls(type="reference") + + for container in containers: + if container["loader"] != "ReferenceLoader": + print("Not a reference, skipping") + continue + + reference_name = container["namespace"] + "RN" + if reference_name in references: + print("Importing {}".format(reference_name)) + + ref_file = cmds.referenceQuery(reference_name, f=True) + + cmds.file(ref_file, importReference=True) From dfa3f76d2c71975ebcd26335f6d6077968ae0be1 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 13 Sep 2021 13:46:37 +0200 Subject: [PATCH 02/27] Added return to force refresh of SceneInventory window --- openpype/hosts/maya/plugins/inventory/import_reference.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/hosts/maya/plugins/inventory/import_reference.py b/openpype/hosts/maya/plugins/inventory/import_reference.py index d389c8733e..ac97096ee7 100644 --- a/openpype/hosts/maya/plugins/inventory/import_reference.py +++ b/openpype/hosts/maya/plugins/inventory/import_reference.py @@ -25,3 +25,5 @@ class ImportReference(api.InventoryAction): ref_file = cmds.referenceQuery(reference_name, f=True) cmds.file(ref_file, importReference=True) + + return "refresh" From 32d65315a0c9fb3f900fd1c3bae10510074fee8f Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 14 Sep 2021 15:54:48 +0200 Subject: [PATCH 03/27] Changed how reference nodes are resolved Added get_reference_node as public api method --- openpype/hosts/maya/api/plugin.py | 93 ++++++++++--------- .../plugins/inventory/import_reference.py | 20 ++-- 2 files changed, 60 insertions(+), 53 deletions(-) diff --git a/openpype/hosts/maya/api/plugin.py b/openpype/hosts/maya/api/plugin.py index 121f7a08a7..448cb814d9 100644 --- a/openpype/hosts/maya/api/plugin.py +++ b/openpype/hosts/maya/api/plugin.py @@ -4,6 +4,53 @@ import avalon.maya from openpype.api import PypeCreatorMixin +def get_reference_node(members, log=None): + """Get the reference node from the container members + Args: + members: list of node names + + Returns: + str: Reference node name. + + """ + + from maya import cmds + + # Collect the references without .placeHolderList[] attributes as + # unique entries (objects only) and skipping the sharedReferenceNode. + references = set() + for ref in cmds.ls(members, exactType="reference", objectsOnly=True): + + # Ignore any `:sharedReferenceNode` + if ref.rsplit(":", 1)[-1].startswith("sharedReferenceNode"): + continue + + # Ignore _UNKNOWN_REF_NODE_ (PLN-160) + if ref.rsplit(":", 1)[-1].startswith("_UNKNOWN_REF_NODE_"): + continue + + references.add(ref) + + assert references, "No reference node found in container" + + # Get highest reference node (least parents) + highest = min(references, + key=lambda x: len(get_reference_node_parents(x))) + + # Warn the user when we're taking the highest reference node + if len(references) > 1: + if not log: + from openpype.lib import PypeLogger + + log = PypeLogger().get_logger(__name__) + + log.warning("More than one reference node found in " + "container, using highest reference node: " + "%s (in: %s)", highest, list(references)) + + return highest + + def get_reference_node_parents(ref): """Return all parent reference nodes of reference node @@ -109,7 +156,7 @@ class ReferenceLoader(api.Loader): loader=self.__class__.__name__ )) else: - ref_node = self._get_reference_node(nodes) + ref_node = get_reference_node(nodes, self.log) loaded_containers.append(containerise( name=name, namespace=namespace, @@ -126,46 +173,6 @@ class ReferenceLoader(api.Loader): """To be implemented by subclass""" raise NotImplementedError("Must be implemented by subclass") - def _get_reference_node(self, members): - """Get the reference node from the container members - Args: - members: list of node names - - Returns: - str: Reference node name. - - """ - - from maya import cmds - - # Collect the references without .placeHolderList[] attributes as - # unique entries (objects only) and skipping the sharedReferenceNode. - references = set() - for ref in cmds.ls(members, exactType="reference", objectsOnly=True): - - # Ignore any `:sharedReferenceNode` - if ref.rsplit(":", 1)[-1].startswith("sharedReferenceNode"): - continue - - # Ignore _UNKNOWN_REF_NODE_ (PLN-160) - if ref.rsplit(":", 1)[-1].startswith("_UNKNOWN_REF_NODE_"): - continue - - references.add(ref) - - assert references, "No reference node found in container" - - # Get highest reference node (least parents) - highest = min(references, - key=lambda x: len(get_reference_node_parents(x))) - - # Warn the user when we're taking the highest reference node - if len(references) > 1: - self.log.warning("More than one reference node found in " - "container, using highest reference node: " - "%s (in: %s)", highest, list(references)) - - return highest def update(self, container, representation): @@ -178,7 +185,7 @@ class ReferenceLoader(api.Loader): # Get reference node from container members members = cmds.sets(node, query=True, nodesOnly=True) - reference_node = self._get_reference_node(members) + reference_node = get_reference_node(members, self.log) file_type = { "ma": "mayaAscii", @@ -274,7 +281,7 @@ class ReferenceLoader(api.Loader): # Assume asset has been referenced members = cmds.sets(node, query=True) - reference_node = self._get_reference_node(members) + reference_node = get_reference_node(members, self.log) assert reference_node, ("Imported container not supported; " "container must be referenced.") diff --git a/openpype/hosts/maya/plugins/inventory/import_reference.py b/openpype/hosts/maya/plugins/inventory/import_reference.py index ac97096ee7..2fa132a867 100644 --- a/openpype/hosts/maya/plugins/inventory/import_reference.py +++ b/openpype/hosts/maya/plugins/inventory/import_reference.py @@ -2,28 +2,28 @@ from maya import cmds from avalon import api +from openpype.hosts.maya.api.plugin import get_reference_node + class ImportReference(api.InventoryAction): - """Imports selected reference inside the file.""" + """Imports selected reference to inside of the file.""" label = "Import Reference" - icon = "mouse-pointer" + icon = "download" color = "#d8d8d8" def process(self, containers): references = cmds.ls(type="reference") - for container in containers: if container["loader"] != "ReferenceLoader": print("Not a reference, skipping") continue - reference_name = container["namespace"] + "RN" - if reference_name in references: - print("Importing {}".format(reference_name)) + node = container["objectName"] + members = cmds.sets(node, query=True, nodesOnly=True) + ref_node = get_reference_node(members) - ref_file = cmds.referenceQuery(reference_name, f=True) + ref_file = cmds.referenceQuery(ref_node, f=True) + cmds.file(ref_file, importReference=True) - cmds.file(ref_file, importReference=True) - - return "refresh" + return True # return anything to trigger model refresh From 4650669782a7bc8e904214bbb3b88632d597e5b7 Mon Sep 17 00:00:00 2001 From: "felix.wang" Date: Wed, 15 Sep 2021 14:14:13 -0700 Subject: [PATCH 04/27] Adding predefined project folders creation in PM #1989. --- .../project_manager/project_manager/window.py | 45 +++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/openpype/tools/project_manager/project_manager/window.py b/openpype/tools/project_manager/project_manager/window.py index 7c71f4b451..caea6f46ab 100644 --- a/openpype/tools/project_manager/project_manager/window.py +++ b/openpype/tools/project_manager/project_manager/window.py @@ -1,3 +1,4 @@ +import logging from Qt import QtWidgets, QtCore, QtGui from . import ( @@ -15,8 +16,11 @@ from openpype.lib import is_admin_password_required from openpype.widgets import PasswordDialog from openpype import resources +from openpype.api import get_project_basic_paths, create_project_folders from avalon.api import AvalonMongoDB +log = logging.getLogger(__name__) + class ProjectManagerWindow(QtWidgets.QWidget): """Main widget of Project Manager tool.""" @@ -28,6 +32,9 @@ class ProjectManagerWindow(QtWidgets.QWidget): self._password_dialog = None self._user_passed = False + # keep track of the current project PM is viewing + self._current_project = None + self.setWindowTitle("OpenPype Project Manager") self.setWindowIcon(QtGui.QIcon(resources.pype_icon_filepath())) @@ -82,11 +89,20 @@ class ProjectManagerWindow(QtWidgets.QWidget): add_asset_btn.setObjectName("IconBtn") add_task_btn.setObjectName("IconBtn") + add_misc_folders_label = QtWidgets.QLabel("Create misc. folders:", helper_btns_widget) + add_misc_folders_btn = QtWidgets.QPushButton( + ResourceCache.get_icon("asset", "default"), + "Create Misc. Folders", + helper_btns_widget + ) + helper_btns_layout = QtWidgets.QHBoxLayout(helper_btns_widget) helper_btns_layout.setContentsMargins(0, 0, 0, 0) helper_btns_layout.addWidget(helper_label) helper_btns_layout.addWidget(add_asset_btn) helper_btns_layout.addWidget(add_task_btn) + helper_btns_layout.addWidget(add_misc_folders_label) + helper_btns_layout.addWidget(add_misc_folders_btn) helper_btns_layout.addStretch(1) # Add widgets to top widget layout @@ -128,6 +144,7 @@ class ProjectManagerWindow(QtWidgets.QWidget): save_btn.clicked.connect(self._on_save_click) add_asset_btn.clicked.connect(self._on_add_asset) add_task_btn.clicked.connect(self._on_add_task) + add_misc_folders_btn.clicked.connect(self._on_add_misc_folders) self._project_model = project_model @@ -142,6 +159,7 @@ class ProjectManagerWindow(QtWidgets.QWidget): self._add_asset_btn = add_asset_btn self._add_task_btn = add_task_btn + self._add_misc_folders_btn = add_misc_folders_btn self.resize(1200, 600) self.setStyleSheet(load_stylesheet()) @@ -179,7 +197,9 @@ class ProjectManagerWindow(QtWidgets.QWidget): self._set_project(self._project_combobox.currentText()) def _on_project_change(self): - self._set_project(self._project_combobox.currentText()) + if self._project_combobox.currentIndex() != 0: + self._current_project = self._project_combobox.currentText() + self._set_project(self._current_project) def _on_project_refresh(self): self.refresh_projects() @@ -193,6 +213,23 @@ class ProjectManagerWindow(QtWidgets.QWidget): def _on_add_task(self): self.hierarchy_view.add_task() + def _on_add_misc_folders(self): + if not self._current_project: + return + + qm = QtWidgets.QMessageBox + ans = qm.question(self, '', "Confirm to create misc. project folders?", qm.Yes | qm.No) + if ans == qm.Yes: + try: + # Get paths based on presets + basic_paths = get_project_basic_paths(self._current_project) + if not basic_paths: + pass + # Invoking OpenPype API to create the project folders + create_project_folders(basic_paths, self._current_project) + except Exception as exc: + log.warning("Error creating.", exc_info=True) + def show_message(self, message): # TODO add nicer message pop self.message_label.setText(message) @@ -203,9 +240,9 @@ class ProjectManagerWindow(QtWidgets.QWidget): if dialog.result() != 1: return - project_name = dialog.project_name - self.show_message("Created project \"{}\"".format(project_name)) - self.refresh_projects(project_name) + self._current_project = dialog.project_name + self.show_message("Created project \"{}\"".format(self._current_project)) + self.refresh_projects(self._current_project) def _show_password_dialog(self): if self._password_dialog: From 1e6b82bf1137364aa115ad63b1e5ead14c91ad57 Mon Sep 17 00:00:00 2001 From: "felix.wang" Date: Wed, 15 Sep 2021 14:41:36 -0700 Subject: [PATCH 05/27] Make hound happy. --- .../project_manager/project_manager/window.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/openpype/tools/project_manager/project_manager/window.py b/openpype/tools/project_manager/project_manager/window.py index caea6f46ab..f8fbe2f288 100644 --- a/openpype/tools/project_manager/project_manager/window.py +++ b/openpype/tools/project_manager/project_manager/window.py @@ -89,7 +89,10 @@ class ProjectManagerWindow(QtWidgets.QWidget): add_asset_btn.setObjectName("IconBtn") add_task_btn.setObjectName("IconBtn") - add_misc_folders_label = QtWidgets.QLabel("Create misc. folders:", helper_btns_widget) + add_misc_folders_label = QtWidgets.QLabel( + "Create misc. folders:", + helper_btns_widget + ) add_misc_folders_btn = QtWidgets.QPushButton( ResourceCache.get_icon("asset", "default"), "Create Misc. Folders", @@ -218,7 +221,10 @@ class ProjectManagerWindow(QtWidgets.QWidget): return qm = QtWidgets.QMessageBox - ans = qm.question(self, '', "Confirm to create misc. project folders?", qm.Yes | qm.No) + ans = qm.question(self, + "", + "Confirm to create misc. project folders?", + qm.Yes | qm.No) if ans == qm.Yes: try: # Get paths based on presets @@ -228,7 +234,8 @@ class ProjectManagerWindow(QtWidgets.QWidget): # Invoking OpenPype API to create the project folders create_project_folders(basic_paths, self._current_project) except Exception as exc: - log.warning("Error creating.", exc_info=True) + log.warning("Failed to create misc folders: {}".format(exc), + exc_info=True) def show_message(self, message): # TODO add nicer message pop @@ -241,7 +248,9 @@ class ProjectManagerWindow(QtWidgets.QWidget): return self._current_project = dialog.project_name - self.show_message("Created project \"{}\"".format(self._current_project)) + self.show_message( + "Created project \"{}\"".format(self._current_project) + ) self.refresh_projects(self._current_project) def _show_password_dialog(self): From e9f9c387fb62e65d028c72a7f2d608be165e3912 Mon Sep 17 00:00:00 2001 From: "felix.wang" Date: Thu, 16 Sep 2021 15:09:28 -0700 Subject: [PATCH 06/27] addressing PR comments. --- .../project_manager/project_manager/window.py | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/openpype/tools/project_manager/project_manager/window.py b/openpype/tools/project_manager/project_manager/window.py index f8fbe2f288..57e373086f 100644 --- a/openpype/tools/project_manager/project_manager/window.py +++ b/openpype/tools/project_manager/project_manager/window.py @@ -16,11 +16,9 @@ from openpype.lib import is_admin_password_required from openpype.widgets import PasswordDialog from openpype import resources -from openpype.api import get_project_basic_paths, create_project_folders +from openpype.api import get_project_basic_paths, create_project_folders, Logger from avalon.api import AvalonMongoDB -log = logging.getLogger(__name__) - class ProjectManagerWindow(QtWidgets.QWidget): """Main widget of Project Manager tool.""" @@ -28,6 +26,8 @@ class ProjectManagerWindow(QtWidgets.QWidget): def __init__(self, parent=None): super(ProjectManagerWindow, self).__init__(parent) + self.log = Logger.get_logger(self.__class__.__name__) + self._initial_reset = False self._password_dialog = None self._user_passed = False @@ -64,12 +64,18 @@ class ProjectManagerWindow(QtWidgets.QWidget): create_project_btn = QtWidgets.QPushButton( "Create project...", project_widget ) + create_folders_btn = QtWidgets.QPushButton( + ResourceCache.get_icon("asset", "default"), + "Create Starting Folders", + project_widget + ) project_layout = QtWidgets.QHBoxLayout(project_widget) project_layout.setContentsMargins(0, 0, 0, 0) project_layout.addWidget(project_combobox, 0) project_layout.addWidget(refresh_projects_btn, 0) project_layout.addWidget(create_project_btn, 0) + project_layout.addWidget(create_folders_btn) project_layout.addStretch(1) # Helper buttons @@ -89,23 +95,11 @@ class ProjectManagerWindow(QtWidgets.QWidget): add_asset_btn.setObjectName("IconBtn") add_task_btn.setObjectName("IconBtn") - add_misc_folders_label = QtWidgets.QLabel( - "Create misc. folders:", - helper_btns_widget - ) - add_misc_folders_btn = QtWidgets.QPushButton( - ResourceCache.get_icon("asset", "default"), - "Create Misc. Folders", - helper_btns_widget - ) - helper_btns_layout = QtWidgets.QHBoxLayout(helper_btns_widget) helper_btns_layout.setContentsMargins(0, 0, 0, 0) helper_btns_layout.addWidget(helper_label) helper_btns_layout.addWidget(add_asset_btn) helper_btns_layout.addWidget(add_task_btn) - helper_btns_layout.addWidget(add_misc_folders_label) - helper_btns_layout.addWidget(add_misc_folders_btn) helper_btns_layout.addStretch(1) # Add widgets to top widget layout @@ -143,11 +137,11 @@ class ProjectManagerWindow(QtWidgets.QWidget): refresh_projects_btn.clicked.connect(self._on_project_refresh) create_project_btn.clicked.connect(self._on_project_create) + create_folders_btn.clicked.connect(self._on_add_misc_folders) project_combobox.currentIndexChanged.connect(self._on_project_change) save_btn.clicked.connect(self._on_save_click) add_asset_btn.clicked.connect(self._on_add_asset) add_task_btn.clicked.connect(self._on_add_task) - add_misc_folders_btn.clicked.connect(self._on_add_misc_folders) self._project_model = project_model @@ -159,10 +153,10 @@ class ProjectManagerWindow(QtWidgets.QWidget): self._refresh_projects_btn = refresh_projects_btn self._project_combobox = project_combobox self._create_project_btn = create_project_btn + self._create_folders_btn = create_folders_btn self._add_asset_btn = add_asset_btn self._add_task_btn = add_task_btn - self._add_misc_folders_btn = add_misc_folders_btn self.resize(1200, 600) self.setStyleSheet(load_stylesheet()) @@ -222,8 +216,8 @@ class ProjectManagerWindow(QtWidgets.QWidget): qm = QtWidgets.QMessageBox ans = qm.question(self, - "", - "Confirm to create misc. project folders?", + "OpenPype Project Manager", + "Confirm to create starting project folders?", qm.Yes | qm.No) if ans == qm.Yes: try: @@ -234,8 +228,8 @@ class ProjectManagerWindow(QtWidgets.QWidget): # Invoking OpenPype API to create the project folders create_project_folders(basic_paths, self._current_project) except Exception as exc: - log.warning("Failed to create misc folders: {}".format(exc), - exc_info=True) + self.log.warning("Cannot create starting folders: {}".format(exc), + exc_info=True) def show_message(self, message): # TODO add nicer message pop From bc05de97d554f136ded0a6d9c2be3dc8621fee34 Mon Sep 17 00:00:00 2001 From: "felix.wang" Date: Thu, 16 Sep 2021 15:17:15 -0700 Subject: [PATCH 07/27] Hound fixes. --- .../tools/project_manager/project_manager/window.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/openpype/tools/project_manager/project_manager/window.py b/openpype/tools/project_manager/project_manager/window.py index 57e373086f..21367287cd 100644 --- a/openpype/tools/project_manager/project_manager/window.py +++ b/openpype/tools/project_manager/project_manager/window.py @@ -1,4 +1,3 @@ -import logging from Qt import QtWidgets, QtCore, QtGui from . import ( @@ -16,7 +15,11 @@ from openpype.lib import is_admin_password_required from openpype.widgets import PasswordDialog from openpype import resources -from openpype.api import get_project_basic_paths, create_project_folders, Logger +from openpype.api import ( + get_project_basic_paths, + create_project_folders, + Logger +) from avalon.api import AvalonMongoDB @@ -228,8 +231,10 @@ class ProjectManagerWindow(QtWidgets.QWidget): # Invoking OpenPype API to create the project folders create_project_folders(basic_paths, self._current_project) except Exception as exc: - self.log.warning("Cannot create starting folders: {}".format(exc), - exc_info=True) + self.log.warning( + "Cannot create starting folders: {}".format(exc), + exc_info=True + ) def show_message(self, message): # TODO add nicer message pop From 284e2cca1850385077c0f16888eb51cb71ee50df Mon Sep 17 00:00:00 2001 From: "felix.wang" Date: Thu, 16 Sep 2021 16:30:16 -0700 Subject: [PATCH 08/27] Fix function name to be consistent. --- openpype/tools/project_manager/project_manager/window.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/tools/project_manager/project_manager/window.py b/openpype/tools/project_manager/project_manager/window.py index 21367287cd..a89aff1168 100644 --- a/openpype/tools/project_manager/project_manager/window.py +++ b/openpype/tools/project_manager/project_manager/window.py @@ -140,7 +140,7 @@ class ProjectManagerWindow(QtWidgets.QWidget): refresh_projects_btn.clicked.connect(self._on_project_refresh) create_project_btn.clicked.connect(self._on_project_create) - create_folders_btn.clicked.connect(self._on_add_misc_folders) + create_folders_btn.clicked.connect(self._on_create_folders) project_combobox.currentIndexChanged.connect(self._on_project_change) save_btn.clicked.connect(self._on_save_click) add_asset_btn.clicked.connect(self._on_add_asset) @@ -213,7 +213,7 @@ class ProjectManagerWindow(QtWidgets.QWidget): def _on_add_task(self): self.hierarchy_view.add_task() - def _on_add_misc_folders(self): + def _on_create_folders(self): if not self._current_project: return From e3ba7e9c15ee9f1e361390683db2bc877178b7c4 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 17 Sep 2021 12:53:08 +0200 Subject: [PATCH 09/27] Removal of unwanted change --- .../defaults/project_settings/nuke.json | 10 ++++++ .../schemas/schema_nuke_publish.json | 32 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/openpype/settings/defaults/project_settings/nuke.json b/openpype/settings/defaults/project_settings/nuke.json index 136f1d6b42..c1c3e77684 100644 --- a/openpype/settings/defaults/project_settings/nuke.json +++ b/openpype/settings/defaults/project_settings/nuke.json @@ -96,6 +96,16 @@ }, "ExtractSlateFrame": { "viewer_lut_raw": false + }, + "IncrementScriptVersion": { + "optional": true, + "active": true, + "families": [ + "workfile", + "render", + "render.local", + "render.farm" + ] } }, "load": { diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json index 782179cfd1..d354ff15f8 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json @@ -152,6 +152,38 @@ "label": "Viewer LUT raw" } ] + }, + { + "type": "splitter" + }, + { + "type": "label", + "label": "Integrators" + }, + { + "type": "dict", + "collapsible": false, + "key": "IncrementScriptVersion", + "label": "IncrementScriptVersion", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + }, + { + "type": "list", + "key": "families", + "object_type": "text", + "label": "Trigger on families" + } + ] } ] } From e402c9c51f83ac4abcda56c5b006e086e50acd4b Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 17 Sep 2021 16:18:36 +0200 Subject: [PATCH 10/27] Added possibility to configure of synchronization of workfile version with selected families --- .../plugins/publish/precollect_instances.py | 13 ++++----- .../defaults/project_settings/nuke.json | 8 +++++- .../schemas/schema_nuke_publish.json | 27 ++++++++++++++++--- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/precollect_instances.py b/openpype/hosts/nuke/plugins/publish/precollect_instances.py index c2c25d0627..d9aec14dc2 100644 --- a/openpype/hosts/nuke/plugins/publish/precollect_instances.py +++ b/openpype/hosts/nuke/plugins/publish/precollect_instances.py @@ -13,7 +13,7 @@ class PreCollectNukeInstances(pyblish.api.ContextPlugin): hosts = ["nuke", "nukeassist"] # presets - sync_workfile_version = False + sync_workfile_version_on_families = [] def process(self, context): asset_data = io.find_one({ @@ -120,11 +120,12 @@ class PreCollectNukeInstances(pyblish.api.ContextPlugin): # sync workfile version _families_test = [family] + families self.log.debug("__ _families_test: `{}`".format(_families_test)) - if not next((f for f in _families_test - if "prerender" in f), - None) and self.sync_workfile_version: - # get version to instance for integration - instance.data['version'] = instance.context.data['version'] + for family_test in _families_test: + if family_test in self.sync_workfile_version_on_families: + self.log.debug("Syncing version with workfile for '{}'" + .format(family_test)) + # get version to instance for integration + instance.data['version'] = instance.context.data['version'] instance.data.update({ "subset": subset, diff --git a/openpype/settings/defaults/project_settings/nuke.json b/openpype/settings/defaults/project_settings/nuke.json index 136f1d6b42..6ee7c2cd39 100644 --- a/openpype/settings/defaults/project_settings/nuke.json +++ b/openpype/settings/defaults/project_settings/nuke.json @@ -30,7 +30,13 @@ }, "publish": { "PreCollectNukeInstances": { - "sync_workfile_version": true + "sync_workfile_version_on_families": [ + "nukenodes", + "camera", + "gizmo", + "source", + "render" + ] }, "ValidateContainers": { "enabled": true, diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json index 782179cfd1..2772c5f3a6 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json @@ -16,9 +16,30 @@ "is_group": true, "children": [ { - "type": "boolean", - "key": "sync_workfile_version", - "label": "Sync Version from workfile" + "type": "enum", + "key": "sync_workfile_version_on_families", + "label": "Sync workfile version for families", + "multiselection": true, + "enum_items": [ + { + "nukenodes": "nukenodes" + }, + { + "camera": "camera" + }, + { + "gizmo": "gizmo" + }, + { + "source": "source" + }, + { + "prerender": "prerender" + }, + { + "render": "render" + } + ] } ] }, From e86675a5afa388b5f156019ff783e7ff6bb68180 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 20 Sep 2021 10:32:36 +0200 Subject: [PATCH 11/27] Removed unwanted configuration of families Plugin should run only when publishing workfile, configuration of families doesn't make sense. --- .../nuke/plugins/publish/increment_script_version.py | 2 +- openpype/settings/defaults/project_settings/nuke.json | 8 +------- .../projects_schema/schemas/schema_nuke_publish.json | 6 ------ 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/increment_script_version.py b/openpype/hosts/nuke/plugins/publish/increment_script_version.py index 47fccb9125..f55ed21ee2 100644 --- a/openpype/hosts/nuke/plugins/publish/increment_script_version.py +++ b/openpype/hosts/nuke/plugins/publish/increment_script_version.py @@ -9,7 +9,7 @@ class IncrementScriptVersion(pyblish.api.ContextPlugin): order = pyblish.api.IntegratorOrder + 0.9 label = "Increment Script Version" optional = True - families = ["workfile", "render", "render.local", "render.farm"] + families = ["workfile"] hosts = ['nuke'] def process(self, context): diff --git a/openpype/settings/defaults/project_settings/nuke.json b/openpype/settings/defaults/project_settings/nuke.json index c1c3e77684..467849cc36 100644 --- a/openpype/settings/defaults/project_settings/nuke.json +++ b/openpype/settings/defaults/project_settings/nuke.json @@ -99,13 +99,7 @@ }, "IncrementScriptVersion": { "optional": true, - "active": true, - "families": [ - "workfile", - "render", - "render.local", - "render.farm" - ] + "active": true } }, "load": { diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json index d354ff15f8..df5015b551 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json @@ -176,12 +176,6 @@ "type": "boolean", "key": "active", "label": "Active" - }, - { - "type": "list", - "key": "families", - "object_type": "text", - "label": "Trigger on families" } ] } From 2506d0f0d6e4e7a419f078f2b2b644a8f1a31627 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 20 Sep 2021 17:44:02 +0200 Subject: [PATCH 12/27] Changed setting schema to include enabled pill --- openpype/settings/defaults/project_settings/nuke.json | 1 + .../projects_schema/schemas/schema_nuke_publish.json | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_settings/nuke.json b/openpype/settings/defaults/project_settings/nuke.json index 467849cc36..fb10d30f67 100644 --- a/openpype/settings/defaults/project_settings/nuke.json +++ b/openpype/settings/defaults/project_settings/nuke.json @@ -98,6 +98,7 @@ "viewer_lut_raw": false }, "IncrementScriptVersion": { + "enabled": true, "optional": true, "active": true } diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json index df5015b551..f385f6149f 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json @@ -162,11 +162,17 @@ }, { "type": "dict", - "collapsible": false, + "collapsible": true, + "checkbox_key": "enabled", "key": "IncrementScriptVersion", "label": "IncrementScriptVersion", "is_group": true, "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, { "type": "boolean", "key": "optional", From 885b84fc1584d3648eefeedd08f2aa4dff35d904 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 20 Sep 2021 19:19:15 +0200 Subject: [PATCH 13/27] ftrack module does not check IFtrackEventHandlerPaths --- .../default_modules/ftrack/ftrack_module.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/openpype/modules/default_modules/ftrack/ftrack_module.py b/openpype/modules/default_modules/ftrack/ftrack_module.py index 3732e762b4..cfce38d125 100644 --- a/openpype/modules/default_modules/ftrack/ftrack_module.py +++ b/openpype/modules/default_modules/ftrack/ftrack_module.py @@ -8,8 +8,7 @@ from openpype_interfaces import ( ITrayModule, IPluginPaths, ILaunchHookPaths, - ISettingsChangeListener, - IFtrackEventHandlerPaths + ISettingsChangeListener ) from openpype.settings import SaveWarningExc @@ -81,9 +80,17 @@ class FtrackModule( def connect_with_modules(self, enabled_modules): for module in enabled_modules: - if not isinstance(module, IFtrackEventHandlerPaths): + if not hasattr(module, "get_event_handler_paths"): continue - paths_by_type = module.get_event_handler_paths() or {} + + try: + paths_by_type = module.get_event_handler_paths() + except Exception: + continue + + if not isinstance(paths_by_type, dict): + continue + for key, value in paths_by_type.items(): if not value: continue From 9bf53533cd4e1f4afe6b127241bb15d75e301800 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 20 Sep 2021 19:19:20 +0200 Subject: [PATCH 14/27] removed IFtrackEventHandlerPaths --- .../modules/default_modules/ftrack/interfaces.py | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 openpype/modules/default_modules/ftrack/interfaces.py diff --git a/openpype/modules/default_modules/ftrack/interfaces.py b/openpype/modules/default_modules/ftrack/interfaces.py deleted file mode 100644 index 16ce0d2e62..0000000000 --- a/openpype/modules/default_modules/ftrack/interfaces.py +++ /dev/null @@ -1,12 +0,0 @@ -from abc import abstractmethod -from openpype.modules import OpenPypeInterface - - -class IFtrackEventHandlerPaths(OpenPypeInterface): - """Other modules interface to return paths to ftrack event handlers. - - Expected output is dictionary with "server" and "user" keys. - """ - @abstractmethod - def get_event_handler_paths(self): - pass From db095da94a4dc1b22a893286476e633fdf3f1b00 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 20 Sep 2021 19:19:31 +0200 Subject: [PATCH 15/27] clockify is not using IFtrackEventHandlerPaths --- .../modules/default_modules/clockify/clockify_module.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/openpype/modules/default_modules/clockify/clockify_module.py b/openpype/modules/default_modules/clockify/clockify_module.py index 0de62d8ba4..5f3c247413 100644 --- a/openpype/modules/default_modules/clockify/clockify_module.py +++ b/openpype/modules/default_modules/clockify/clockify_module.py @@ -10,16 +10,14 @@ from .constants import ( from openpype.modules import OpenPypeModule from openpype_interfaces import ( ITrayModule, - IPluginPaths, - IFtrackEventHandlerPaths + IPluginPaths ) class ClockifyModule( OpenPypeModule, ITrayModule, - IPluginPaths, - IFtrackEventHandlerPaths + IPluginPaths ): name = "clockify" @@ -94,7 +92,7 @@ class ClockifyModule( } def get_event_handler_paths(self): - """Implementaton of IFtrackEventHandlerPaths to get plugin paths.""" + """Function for Ftrack module to add ftrack event handler paths.""" return { "user": [CLOCKIFY_FTRACK_USER_PATH], "server": [CLOCKIFY_FTRACK_SERVER_PATH] From ba6934946f585899da148c924359d30e262312a6 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 20 Sep 2021 19:20:21 +0200 Subject: [PATCH 16/27] removed unused functions --- openpype/modules/default_modules/ftrack/lib/__init__.py | 4 +--- openpype/modules/default_modules/ftrack/lib/settings.py | 9 --------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/openpype/modules/default_modules/ftrack/lib/__init__.py b/openpype/modules/default_modules/ftrack/lib/__init__.py index 9dc2d67279..433a1f7881 100644 --- a/openpype/modules/default_modules/ftrack/lib/__init__.py +++ b/openpype/modules/default_modules/ftrack/lib/__init__.py @@ -5,8 +5,7 @@ from .constants import ( CUST_ATTR_TOOLS, CUST_ATTR_APPLICATIONS ) -from . settings import ( - get_ftrack_url_from_settings, +from .settings import ( get_ftrack_event_mongo_info ) from .custom_attributes import ( @@ -31,7 +30,6 @@ __all__ = ( "CUST_ATTR_TOOLS", "CUST_ATTR_APPLICATIONS", - "get_ftrack_url_from_settings", "get_ftrack_event_mongo_info", "default_custom_attributes_definition", diff --git a/openpype/modules/default_modules/ftrack/lib/settings.py b/openpype/modules/default_modules/ftrack/lib/settings.py index 027356edc6..bf44981de0 100644 --- a/openpype/modules/default_modules/ftrack/lib/settings.py +++ b/openpype/modules/default_modules/ftrack/lib/settings.py @@ -1,13 +1,4 @@ import os -from openpype.api import get_system_settings - - -def get_ftrack_settings(): - return get_system_settings()["modules"]["ftrack"] - - -def get_ftrack_url_from_settings(): - return get_ftrack_settings()["ftrack_server"] def get_ftrack_event_mongo_info(): From 886188a489f739c6609c9c7df35d86c8c5a0eff5 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 20 Sep 2021 19:23:55 +0200 Subject: [PATCH 17/27] change expected method name to 'get_ftrack_event_handler_paths' --- openpype/modules/default_modules/clockify/clockify_module.py | 2 +- openpype/modules/default_modules/ftrack/ftrack_module.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/modules/default_modules/clockify/clockify_module.py b/openpype/modules/default_modules/clockify/clockify_module.py index 5f3c247413..932ce87c36 100644 --- a/openpype/modules/default_modules/clockify/clockify_module.py +++ b/openpype/modules/default_modules/clockify/clockify_module.py @@ -91,7 +91,7 @@ class ClockifyModule( "actions": [actions_path] } - def get_event_handler_paths(self): + def get_ftrack_event_handler_paths(self): """Function for Ftrack module to add ftrack event handler paths.""" return { "user": [CLOCKIFY_FTRACK_USER_PATH], diff --git a/openpype/modules/default_modules/ftrack/ftrack_module.py b/openpype/modules/default_modules/ftrack/ftrack_module.py index cfce38d125..c73f9b100d 100644 --- a/openpype/modules/default_modules/ftrack/ftrack_module.py +++ b/openpype/modules/default_modules/ftrack/ftrack_module.py @@ -80,11 +80,11 @@ class FtrackModule( def connect_with_modules(self, enabled_modules): for module in enabled_modules: - if not hasattr(module, "get_event_handler_paths"): + if not hasattr(module, "get_ftrack_event_handler_paths"): continue try: - paths_by_type = module.get_event_handler_paths() + paths_by_type = module.get_ftrack_event_handler_paths() except Exception: continue From 5b8832f4e3f1faa0d44a655fa4261f4ea2c5b94a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Sep 2021 22:23:38 +0000 Subject: [PATCH 18/27] Bump prismjs from 1.24.0 to 1.25.0 in /website Bumps [prismjs](https://github.com/PrismJS/prism) from 1.24.0 to 1.25.0. - [Release notes](https://github.com/PrismJS/prism/releases) - [Changelog](https://github.com/PrismJS/prism/blob/master/CHANGELOG.md) - [Commits](https://github.com/PrismJS/prism/compare/v1.24.0...v1.25.0) --- updated-dependencies: - dependency-name: prismjs dependency-type: indirect ... Signed-off-by: dependabot[bot] --- website/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/yarn.lock b/website/yarn.lock index b4c12edeb6..066d156d97 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -6594,9 +6594,9 @@ prism-react-renderer@^1.1.1: integrity sha512-GHqzxLYImx1iKN1jJURcuRoA/0ygCcNhfGw1IT8nPIMzarmKQ3Nc+JcG0gi8JXQzuh0C5ShE4npMIoqNin40hg== prismjs@^1.23.0: - version "1.24.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.24.0.tgz#0409c30068a6c52c89ef7f1089b3ca4de56be2ac" - integrity sha512-SqV5GRsNqnzCL8k5dfAjCNhUrF3pR0A9lTDSCUZeh/LIshheXJEaP0hwLz2t4XHivd2J/v2HR+gRnigzeKe3cQ== + version "1.25.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.25.0.tgz#6f822df1bdad965734b310b315a23315cf999756" + integrity sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg== process-nextick-args@~2.0.0: version "2.0.1" From e24b142962b90d25f1bf371292c2966cdf953f36 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 21 Sep 2021 12:53:23 +0200 Subject: [PATCH 19/27] added startup validations of ffmpeg and oiio tool --- start.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/start.py b/start.py index 00f9a50cbb..a02c06661f 100644 --- a/start.py +++ b/start.py @@ -96,6 +96,7 @@ Attributes: import os import re import sys +import platform import traceback import subprocess import site @@ -339,6 +340,60 @@ def set_modules_environments(): os.environ.update(env) +def is_tool(name): + try: + import os.errno as errno + except ImportError: + import errno + + try: + devnull = open(os.devnull, "w") + subprocess.Popen( + [name], stdout=devnull, stderr=devnull + ).communicate() + except OSError as exc: + if exc.errno == errno.ENOENT: + return False + return True + + +def _startup_validations(): + """Validations before OpenPype starts.""" + _validate_thirdparty_binaries() + + +def _validate_thirdparty_binaries(): + """Check existence of thirdpart executables.""" + low_platform = platform.system().lower() + binary_vendors_dir = os.path.join( + os.environ["OPENPYPE_ROOT"], + "vendor", + "bin" + ) + + error_msg = ( + "Missing binary dependency {}. Please fetch thirdparty dependencies." + ) + # Validate existence of FFmpeg + ffmpeg_dir = os.path.join(binary_vendors_dir, "ffmpeg", low_platform) + if low_platform == "windows": + ffmpeg_dir = os.path.join(ffmpeg_dir, "bin") + ffmpeg_executable = os.path.join(ffmpeg_dir, "ffmpeg") + if not is_tool(ffmpeg_executable): + raise RuntimeError(error_msg.format("FFmpeg")) + + # Validate existence of OpenImageIO (not on MacOs) + if low_platform != "darwin": + oiio_tool_path = os.path.join( + binary_vendors_dir, + "oiio", + low_platform, + "oiio_tool" + ) + if not is_tool(oiio_tool_path): + raise RuntimeError(error_msg.format("OpenImageIO")) + + def _process_arguments() -> tuple: """Process command line arguments. @@ -767,6 +822,11 @@ def boot(): # ------------------------------------------------------------------------ os.environ["OPENPYPE_ROOT"] = OPENPYPE_ROOT + # ------------------------------------------------------------------------ + # Do necessary startup validations + # ------------------------------------------------------------------------ + _startup_validations() + # ------------------------------------------------------------------------ # Play animation # ------------------------------------------------------------------------ From cda626d76fce511be8524b5358db6b37a977684f Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 21 Sep 2021 12:55:01 +0200 Subject: [PATCH 20/27] removed validator of ffmpeg --- .../publish/validate_ffmpeg_installed.py | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 openpype/plugins/publish/validate_ffmpeg_installed.py diff --git a/openpype/plugins/publish/validate_ffmpeg_installed.py b/openpype/plugins/publish/validate_ffmpeg_installed.py deleted file mode 100644 index a5390a07b2..0000000000 --- a/openpype/plugins/publish/validate_ffmpeg_installed.py +++ /dev/null @@ -1,34 +0,0 @@ -import pyblish.api -import os -import subprocess -import openpype.lib -try: - import os.errno as errno -except ImportError: - import errno - - -class ValidateFFmpegInstalled(pyblish.api.ContextPlugin): - """Validate availability of ffmpeg tool in PATH""" - - order = pyblish.api.ValidatorOrder - label = 'Validate ffmpeg installation' - optional = True - - def is_tool(self, name): - try: - devnull = open(os.devnull, "w") - subprocess.Popen( - [name], stdout=devnull, stderr=devnull - ).communicate() - except OSError as e: - if e.errno == errno.ENOENT: - return False - return True - - def process(self, context): - ffmpeg_path = openpype.lib.get_ffmpeg_tool_path("ffmpeg") - self.log.info("ffmpeg path: `{}`".format(ffmpeg_path)) - if self.is_tool("{}".format(ffmpeg_path)) is False: - self.log.error("ffmpeg not found in PATH") - raise RuntimeError('ffmpeg not installed.') From 7fe3fd1d11a66de9dbfbc479bd91cd0cb7d35013 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 21 Sep 2021 14:06:25 +0200 Subject: [PATCH 21/27] show tkinter message box if validation crashes --- start.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/start.py b/start.py index a02c06661f..8b4ee97b09 100644 --- a/start.py +++ b/start.py @@ -359,7 +359,23 @@ def is_tool(name): def _startup_validations(): """Validations before OpenPype starts.""" - _validate_thirdparty_binaries() + try: + _validate_thirdparty_binaries() + except Exception as exc: + if os.environ.get("OPENPYPE_HEADLESS_MODE"): + raise + + from tkinter import Tk + from tkinter.messagebox import showerror + + root = Tk() + root.withdraw() + showerror( + "Startup validations didn't pass", + str(exc) + ) + root.destroy() + sys.exit(1) def _validate_thirdparty_binaries(): From ce07679ead6414639f81872eee75f4f7b9c6e6a5 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Sep 2021 18:02:38 +0200 Subject: [PATCH 22/27] fixing global plugin orders --- openpype/hosts/hiero/plugins/publish/precollect_instances.py | 2 +- openpype/hosts/hiero/plugins/publish/precollect_workfile.py | 2 ++ openpype/plugins/publish/collect_hierarchy.py | 2 +- openpype/plugins/publish/collect_otio_frame_ranges.py | 2 +- openpype/plugins/publish/collect_otio_review.py | 2 +- openpype/plugins/publish/collect_otio_subset_resources.py | 2 +- 6 files changed, 7 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/hiero/plugins/publish/precollect_instances.py b/openpype/hosts/hiero/plugins/publish/precollect_instances.py index 936ea2be58..85b4e273d5 100644 --- a/openpype/hosts/hiero/plugins/publish/precollect_instances.py +++ b/openpype/hosts/hiero/plugins/publish/precollect_instances.py @@ -131,7 +131,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin): self.create_shot_instance(context, **data) self.log.info("Creating instance: {}".format(instance)) - self.log.debug( + self.log.info( "_ instance.data: {}".format(pformat(instance.data))) if not with_audio: diff --git a/openpype/hosts/hiero/plugins/publish/precollect_workfile.py b/openpype/hosts/hiero/plugins/publish/precollect_workfile.py index ff5d516065..4f164acc91 100644 --- a/openpype/hosts/hiero/plugins/publish/precollect_workfile.py +++ b/openpype/hosts/hiero/plugins/publish/precollect_workfile.py @@ -7,6 +7,8 @@ from pprint import pformat from openpype.hosts.hiero.otio import hiero_export from Qt.QtGui import QPixmap import tempfile +reload(hiero_export) + class PrecollectWorkfile(pyblish.api.ContextPlugin): """Inject the current working file into context""" diff --git a/openpype/plugins/publish/collect_hierarchy.py b/openpype/plugins/publish/collect_hierarchy.py index 1aa10fcb9b..f7d1c6b4be 100644 --- a/openpype/plugins/publish/collect_hierarchy.py +++ b/openpype/plugins/publish/collect_hierarchy.py @@ -13,7 +13,7 @@ class CollectHierarchy(pyblish.api.ContextPlugin): """ label = "Collect Hierarchy" - order = pyblish.api.CollectorOrder - 0.57 + order = pyblish.api.CollectorOrder - 0.47 families = ["shot"] hosts = ["resolve", "hiero"] diff --git a/openpype/plugins/publish/collect_otio_frame_ranges.py b/openpype/plugins/publish/collect_otio_frame_ranges.py index e1b8b95a46..a35ef47e79 100644 --- a/openpype/plugins/publish/collect_otio_frame_ranges.py +++ b/openpype/plugins/publish/collect_otio_frame_ranges.py @@ -18,7 +18,7 @@ class CollectOcioFrameRanges(pyblish.api.InstancePlugin): Adding timeline and source ranges to instance data""" label = "Collect OTIO Frame Ranges" - order = pyblish.api.CollectorOrder - 0.58 + order = pyblish.api.CollectorOrder - 0.48 families = ["shot", "clip"] hosts = ["resolve", "hiero"] diff --git a/openpype/plugins/publish/collect_otio_review.py b/openpype/plugins/publish/collect_otio_review.py index e78ccc032c..10ceafdcca 100644 --- a/openpype/plugins/publish/collect_otio_review.py +++ b/openpype/plugins/publish/collect_otio_review.py @@ -20,7 +20,7 @@ class CollectOcioReview(pyblish.api.InstancePlugin): """Get matching otio track from defined review layer""" label = "Collect OTIO Review" - order = pyblish.api.CollectorOrder - 0.57 + order = pyblish.api.CollectorOrder - 0.47 families = ["clip"] hosts = ["resolve", "hiero"] diff --git a/openpype/plugins/publish/collect_otio_subset_resources.py b/openpype/plugins/publish/collect_otio_subset_resources.py index 010430a303..dd670ff850 100644 --- a/openpype/plugins/publish/collect_otio_subset_resources.py +++ b/openpype/plugins/publish/collect_otio_subset_resources.py @@ -18,7 +18,7 @@ class CollectOcioSubsetResources(pyblish.api.InstancePlugin): """Get Resources for a subset version""" label = "Collect OTIO Subset Resources" - order = pyblish.api.CollectorOrder - 0.57 + order = pyblish.api.CollectorOrder - 0.47 families = ["clip"] hosts = ["resolve", "hiero"] From 0abede9e5d06bbd5431574159dcfab7fd2a89b24 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Sep 2021 18:24:32 +0200 Subject: [PATCH 23/27] hiero: otio is not ignoring disabled and offline clips --- openpype/hosts/hiero/otio/hiero_export.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/hiero/otio/hiero_export.py b/openpype/hosts/hiero/otio/hiero_export.py index ccc05d5fd7..af4322e3d9 100644 --- a/openpype/hosts/hiero/otio/hiero_export.py +++ b/openpype/hosts/hiero/otio/hiero_export.py @@ -378,6 +378,17 @@ def add_otio_metadata(otio_item, media_source, **kwargs): def create_otio_timeline(): + def set_prev_item(itemindex, track_item): + # Add Gap if needed + if itemindex == 0: + # if it is first track item at track then add + # it to previouse item + return track_item + + else: + # get previouse item + return track_item.parent().items()[itemindex - 1] + # get current timeline self.timeline = hiero.ui.activeSequence() self.project_fps = self.timeline.framerate().toFloat() @@ -396,14 +407,6 @@ def create_otio_timeline(): type(track), track.name()) for itemindex, track_item in enumerate(track): - # skip offline track items - if not track_item.isMediaPresent(): - continue - - # skip if track item is disabled - if not track_item.isEnabled(): - continue - # Add Gap if needed if itemindex == 0: # if it is first track item at track then add From 8cd3821ee4e000863bc7337dda5e486bea6103cd Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Sep 2021 18:26:45 +0200 Subject: [PATCH 24/27] hound: suggestion --- openpype/hosts/hiero/plugins/publish/precollect_workfile.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/hiero/plugins/publish/precollect_workfile.py b/openpype/hosts/hiero/plugins/publish/precollect_workfile.py index 4f164acc91..7db155048f 100644 --- a/openpype/hosts/hiero/plugins/publish/precollect_workfile.py +++ b/openpype/hosts/hiero/plugins/publish/precollect_workfile.py @@ -7,7 +7,6 @@ from pprint import pformat from openpype.hosts.hiero.otio import hiero_export from Qt.QtGui import QPixmap import tempfile -reload(hiero_export) class PrecollectWorkfile(pyblish.api.ContextPlugin): From 0b4cd5885801487f92f622335f4c774738bcc8f7 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 22 Sep 2021 10:48:48 +0200 Subject: [PATCH 25/27] fix oiio executable name --- start.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/start.py b/start.py index 8b4ee97b09..451db03a54 100644 --- a/start.py +++ b/start.py @@ -404,7 +404,7 @@ def _validate_thirdparty_binaries(): binary_vendors_dir, "oiio", low_platform, - "oiio_tool" + "oiiotool" ) if not is_tool(oiio_tool_path): raise RuntimeError(error_msg.format("OpenImageIO")) From 81f743bd21fcb16254c08f759fac209b5a3b8931 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 22 Sep 2021 11:28:32 +0200 Subject: [PATCH 26/27] tkinter message is visible in taskbar --- start.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/start.py b/start.py index 451db03a54..f3adabd942 100644 --- a/start.py +++ b/start.py @@ -365,16 +365,20 @@ def _startup_validations(): if os.environ.get("OPENPYPE_HEADLESS_MODE"): raise - from tkinter import Tk + import tkinter from tkinter.messagebox import showerror - root = Tk() - root.withdraw() + root = tkinter.Tk() + root.attributes("-alpha", 0.0) + root.wm_state("iconic") + if platform.system().lower() != "windows": + root.withdraw() + showerror( "Startup validations didn't pass", str(exc) ) - root.destroy() + root.withdraw() sys.exit(1) From 48e120b25c687886d6ad45f52d69906f4fda63ba Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 22 Sep 2021 13:32:37 +0200 Subject: [PATCH 27/27] fix typo --- .../modules/default_modules/timers_manager/timers_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/default_modules/timers_manager/timers_manager.py b/openpype/modules/default_modules/timers_manager/timers_manager.py index e2c421bcfe..47ba0b4059 100644 --- a/openpype/modules/default_modules/timers_manager/timers_manager.py +++ b/openpype/modules/default_modules/timers_manager/timers_manager.py @@ -209,7 +209,7 @@ class TimersManager(OpenPypeModule, ITrayService, IIdleManager): self.widget_user_idle.refresh_context() self.is_running = False - self.timer_stopper(None) + self.timer_stopped(None) def connect_with_modules(self, enabled_modules): for module in enabled_modules: