mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge pull request #3357 from pypeclub/feature/OP-3420_Trigger-callback-on-workfile-open
Hosts: More options for in-host callbacks
This commit is contained in:
commit
c782c61c3c
5 changed files with 126 additions and 20 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
@ -33,6 +31,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 +45,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)
|
||||
|
|
@ -74,6 +92,7 @@ def install_host(host):
|
|||
_is_installed = True
|
||||
|
||||
legacy_io.install()
|
||||
modules_manager = _get_modules_manager()
|
||||
|
||||
missing = list()
|
||||
for key in ("AVALON_PROJECT", "AVALON_ASSET"):
|
||||
|
|
@ -95,8 +114,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()
|
||||
|
|
@ -112,7 +129,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 +148,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)
|
||||
|
|
@ -168,10 +192,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()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
import logging
|
||||
import shutil
|
||||
import copy
|
||||
|
||||
import Qt
|
||||
from Qt import QtWidgets, QtCore
|
||||
|
|
@ -90,7 +91,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 +101,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 +389,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 +401,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,
|
||||
|
|
@ -430,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():
|
||||
|
|
@ -453,8 +473,21 @@ class FilesWidget(QtWidgets.QWidget):
|
|||
# Save current scene, continue to open file
|
||||
host.save_file(current_file)
|
||||
|
||||
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",
|
||||
event_data_before,
|
||||
source="workfiles.tool"
|
||||
)
|
||||
self._enter_session()
|
||||
host.open_file(filepath)
|
||||
emit_event(
|
||||
"workfile.open.after",
|
||||
event_data_after,
|
||||
source="workfiles.tool"
|
||||
)
|
||||
self.file_opened.emit()
|
||||
|
||||
def save_changes_prompt(self):
|
||||
|
|
@ -567,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"
|
||||
)
|
||||
|
||||
|
|
@ -602,15 +640,20 @@ 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
|
||||
)
|
||||
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"
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue