From 2890c950f5b58fd7654497aae22016d2d1df56ca Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 16 Jun 2022 16:46:31 +0200 Subject: [PATCH 1/7] trigger open events --- openpype/tools/workfiles/files_widget.py | 45 ++++++++++++++++++++---- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/openpype/tools/workfiles/files_widget.py b/openpype/tools/workfiles/files_widget.py index 68fe8301c9..709f05b26b 100644 --- a/openpype/tools/workfiles/files_widget.py +++ b/openpype/tools/workfiles/files_widget.py @@ -90,7 +90,9 @@ class FilesWidget(QtWidgets.QWidget): self._task_type = None # Pype's anatomy object for current project - self.anatomy = Anatomy(legacy_io.Session["AVALON_PROJECT"]) + project_name = legacy_io.Session["AVALON_PROJECT"] + self.anatomy = Anatomy(project_name) + self.project_name = project_name # Template key used to get work template from anatomy templates self.template_key = "work" @@ -98,6 +100,7 @@ class FilesWidget(QtWidgets.QWidget): self._workfiles_root = None self._workdir_path = None self.host = registered_host() + self.host_name = os.environ["AVALON_APP"] # Whether to automatically select the latest modified # file on a refresh of the files model. @@ -385,8 +388,9 @@ class FilesWidget(QtWidgets.QWidget): return None if self._asset_doc is None: - project_name = legacy_io.active_project() - self._asset_doc = get_asset_by_id(project_name, self._asset_id) + self._asset_doc = get_asset_by_id( + self.project_name, self._asset_id + ) return self._asset_doc @@ -396,8 +400,8 @@ class FilesWidget(QtWidgets.QWidget): session = legacy_io.Session.copy() self.template_key = get_workfile_template_key( self._task_type, - session["AVALON_APP"], - project_name=session["AVALON_PROJECT"] + self.host_name, + project_name=self.project_name ) changes = compute_session_changes( session, @@ -453,8 +457,35 @@ class FilesWidget(QtWidgets.QWidget): # Save current scene, continue to open file host.save_file(current_file) + asset_name = None + asset_doc = self._get_asset_doc() + if asset_doc: + asset_name = asset_doc["name"] + + emit_event( + "workfile.open.before", + { + "filepath": filepath, + "project_name": self.project_name, + "asset_name": asset_name, + "task_name": self._task_name, + "host_name": self.host_name + }, + source="workfiles.tool" + ) self._enter_session() host.open_file(filepath) + emit_event( + "workfile.open.after", + { + "filepath": filepath, + "project_name": self.project_name, + "asset_name": asset_name, + "task_name": self._task_name, + "host_name": self.host_name + }, + source="workfiles.tool" + ) self.file_opened.emit() def save_changes_prompt(self): @@ -602,10 +633,10 @@ class FilesWidget(QtWidgets.QWidget): # Create extra folders create_workdir_extra_folders( self._workdir_path, - legacy_io.Session["AVALON_APP"], + self.host_name, self._task_type, self._task_name, - legacy_io.Session["AVALON_PROJECT"] + self.project_name ) # Trigger after save events emit_event( From ee4b635edd51523e46864e00c5ec873e477e3e3b Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 16 Jun 2022 16:51:55 +0200 Subject: [PATCH 2/7] trigger open workfile events in workfiles tool --- openpype/tools/workfiles/files_widget.py | 54 +++++++++++++++--------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/openpype/tools/workfiles/files_widget.py b/openpype/tools/workfiles/files_widget.py index 709f05b26b..a7e54471dc 100644 --- a/openpype/tools/workfiles/files_widget.py +++ b/openpype/tools/workfiles/files_widget.py @@ -1,6 +1,7 @@ import os import logging import shutil +import copy import Qt from Qt import QtWidgets, QtCore @@ -434,6 +435,21 @@ class FilesWidget(QtWidgets.QWidget): template_key=self.template_key ) + def _get_event_context_data(self): + asset_id = None + asset_name = None + asset_doc = self._get_asset_doc() + if asset_doc: + asset_id = asset_doc["_id"] + asset_name = asset_doc["name"] + return { + "project_name": self.project_name, + "asset_id": asset_id, + "asset_name": asset_name, + "task_name": self._task_name, + "host_name": self.host_name + } + def open_file(self, filepath): host = self.host if host.has_unsaved_changes(): @@ -457,33 +473,19 @@ class FilesWidget(QtWidgets.QWidget): # Save current scene, continue to open file host.save_file(current_file) - asset_name = None - asset_doc = self._get_asset_doc() - if asset_doc: - asset_name = asset_doc["name"] - + event_data_before = self._get_event_context_data() + event_data_before["filepath"] = filepath + event_data_after = copy.deepcopy(event_data_before) emit_event( "workfile.open.before", - { - "filepath": filepath, - "project_name": self.project_name, - "asset_name": asset_name, - "task_name": self._task_name, - "host_name": self.host_name - }, + event_data_before, source="workfiles.tool" ) self._enter_session() host.open_file(filepath) emit_event( "workfile.open.after", - { - "filepath": filepath, - "project_name": self.project_name, - "asset_name": asset_name, - "task_name": self._task_name, - "host_name": self.host_name - }, + event_data_after, source="workfiles.tool" ) self.file_opened.emit() @@ -598,9 +600,14 @@ class FilesWidget(QtWidgets.QWidget): src_path = self._get_selected_filepath() # Trigger before save event + event_data_before = self._get_event_context_data() + event_data_before.update({ + "filename": work_filename, + "workdir_path": self._workdir_path + }) emit_event( "workfile.save.before", - {"filename": work_filename, "workdir_path": self._workdir_path}, + event_data_before, source="workfiles.tool" ) @@ -638,10 +645,15 @@ class FilesWidget(QtWidgets.QWidget): self._task_name, self.project_name ) + event_data_after = self._get_event_context_data() + event_data_after.update({ + "filename": work_filename, + "workdir_path": self._workdir_path + }) # Trigger after save events emit_event( "workfile.save.after", - {"filename": work_filename, "workdir_path": self._workdir_path}, + event_data_after, source="workfiles.tool" ) From 94f9d6309822431dc00218687207cefcc4397b11 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 16 Jun 2022 17:05:26 +0200 Subject: [PATCH 3/7] modules have method that can be called on host installation --- openpype/modules/base.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/openpype/modules/base.py b/openpype/modules/base.py index bca64b19f8..b9ccec13cc 100644 --- a/openpype/modules/base.py +++ b/openpype/modules/base.py @@ -463,6 +463,25 @@ class OpenPypeModule: pass + def on_host_install(self, host, host_name, project_name): + """Host was installed which gives option to handle in-host logic. + + It is a good option to register in-host event callbacks which are + specific for the module. The module is kept in memory for rest of + the process. + + Arguments may change in future. E.g. 'host_name' should be possible + to receive from 'host' object. + + Args: + host (ModuleType): Access to installed/registered host object. + host_name (str): Name of host. + project_name (str): Project name which is main part of host + context. + """ + + pass + def cli(self, module_click_group): """Add commands to click group. From 0c28a29650491603a04ad9f9178e7cdc81c9f73b Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 16 Jun 2022 17:05:48 +0200 Subject: [PATCH 4/7] trigger on_host_install method on host installation --- openpype/pipeline/context_tools.py | 33 ++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/openpype/pipeline/context_tools.py b/openpype/pipeline/context_tools.py index c6e09cfba1..8643c3d69d 100644 --- a/openpype/pipeline/context_tools.py +++ b/openpype/pipeline/context_tools.py @@ -33,6 +33,9 @@ from . import ( _is_installed = False _registered_root = {"_": ""} _registered_host = {"_": None} +# Keep modules manager (and it's modules) in memory +# - that gives option to register modules' callbacks +_modules_manager = None log = logging.getLogger(__name__) @@ -44,6 +47,23 @@ PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish") LOAD_PATH = os.path.join(PLUGINS_DIR, "load") +def _get_modules_manager(): + """Get or create modules manager for host installation. + + This is not meant for public usage. Reason is to keep modules + in memory of process to be able trigger their event callbacks if they + need any. + + Returns: + ModulesManager: Manager wrapping discovered modules. + """ + + global _modules_manager + if _modules_manager is None: + _modules_manager = ModulesManager() + return _modules_manager + + def register_root(path): """Register currently active root""" log.info("Registering root: %s" % path) @@ -70,10 +90,12 @@ def install_host(host): avalon host-interface. """ global _is_installed + global _modules_manager _is_installed = True legacy_io.install() + modules_manager = _get_modules_manager() missing = list() for key in ("AVALON_PROJECT", "AVALON_ASSET"): @@ -112,7 +134,14 @@ def install_host(host): else: pyblish.api.register_target("local") - install_openpype_plugins() + project_name = os.environ.get("AVALON_PROJECT") + host_name = os.environ.get("AVALON_APP") + + # Give option to handle host installation + for module in modules_manager.get_enabled_modules(): + module.on_host_install(host, host_name, project_name) + + install_openpype_plugins(project_name, host_name) def install_openpype_plugins(project_name=None, host_name=None): @@ -124,7 +153,7 @@ def install_openpype_plugins(project_name=None, host_name=None): pyblish.api.register_discovery_filter(filter_pyblish_plugins) register_loader_plugin_path(LOAD_PATH) - modules_manager = ModulesManager() + modules_manager = _get_modules_manager() publish_plugin_dirs = modules_manager.collect_plugin_paths()["publish"] for path in publish_plugin_dirs: pyblish.api.register_plugin_path(path) From 89a7d438b4b37e0903ae33f54de58bb04a03b9c4 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 16 Jun 2022 17:42:46 +0200 Subject: [PATCH 5/7] added human readable keys into taskChanged topic data --- openpype/lib/avalon_context.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openpype/lib/avalon_context.py b/openpype/lib/avalon_context.py index 9d8a92cfe9..243e89e00d 100644 --- a/openpype/lib/avalon_context.py +++ b/openpype/lib/avalon_context.py @@ -797,8 +797,14 @@ def update_current_task(task=None, asset=None, app=None, template_key=None): else: os.environ[key] = value + data = changes.copy() + # Convert env keys to human readable keys + data["project_name"] = legacy_io.Session["AVALON_PROJECT"] + data["asset_name"] = legacy_io.Session["AVALON_ASSET"] + data["task_name"] = legacy_io.Session["AVALON_TASK"] + # Emit session change - emit_event("taskChanged", changes.copy()) + emit_event("taskChanged", data) return changes From cbb876c155fb6f31356d74404f7763689e09a6d7 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 16 Jun 2022 17:43:18 +0200 Subject: [PATCH 6/7] moved timer change on task change to timers manager module --- .../modules/timers_manager/timers_manager.py | 18 ++++++++++++++++++ openpype/pipeline/context_tools.py | 8 -------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/openpype/modules/timers_manager/timers_manager.py b/openpype/modules/timers_manager/timers_manager.py index 3f77a2b7dc..3cf1614316 100644 --- a/openpype/modules/timers_manager/timers_manager.py +++ b/openpype/modules/timers_manager/timers_manager.py @@ -7,6 +7,7 @@ from openpype_interfaces import ( ITrayService, ILaunchHookPaths ) +from openpype.lib.events import register_event_callback from openpype.pipeline import AvalonMongoDB from .exceptions import InvalidContextError @@ -422,3 +423,20 @@ class TimersManager(OpenPypeModule, ITrayService, ILaunchHookPaths): } return requests.post(rest_api_url, json=data) + + def on_host_install(self, host, host_name, project_name): + self.log.debug("Installing task changed callback") + register_event_callback("taskChanged", self._on_host_task_change) + + def _on_host_task_change(self, event): + project_name = event["project_name"] + asset_name = event["asset_name"] + task_name = event["task_name"] + self.log.debug(( + "Sending message that timer should change to" + " Project: {} Asset: {} Task: {}" + ).format(project_name, asset_name, task_name)) + + self.start_timer_with_webserver( + project_name, asset_name, task_name, self.log + ) diff --git a/openpype/pipeline/context_tools.py b/openpype/pipeline/context_tools.py index 8643c3d69d..3e63eeba27 100644 --- a/openpype/pipeline/context_tools.py +++ b/openpype/pipeline/context_tools.py @@ -16,9 +16,7 @@ from openpype.modules import load_modules, ModulesManager from openpype.settings import get_project_settings from openpype.lib import ( Anatomy, - register_event_callback, filter_pyblish_plugins, - change_timer_to_current_context, ) from . import ( @@ -117,8 +115,6 @@ def install_host(host): register_host(host) - register_event_callback("taskChanged", _on_task_change) - def modified_emit(obj, record): """Method replacing `emit` in Pyblish's MessageHandler.""" record.msg = record.getMessage() @@ -197,10 +193,6 @@ def install_openpype_plugins(project_name=None, host_name=None): register_inventory_action(path) -def _on_task_change(): - change_timer_to_current_context() - - def uninstall_host(): """Undo all of what `install()` did""" host = registered_host() From 8b1576aed2b74dd5e01842d2a87bc04c77f755f6 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 20 Jun 2022 11:22:05 +0200 Subject: [PATCH 7/7] remove unused line --- openpype/pipeline/context_tools.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/pipeline/context_tools.py b/openpype/pipeline/context_tools.py index 3e63eeba27..4a147c230b 100644 --- a/openpype/pipeline/context_tools.py +++ b/openpype/pipeline/context_tools.py @@ -88,7 +88,6 @@ def install_host(host): avalon host-interface. """ global _is_installed - global _modules_manager _is_installed = True