From 61451d3e6b03fc5b8c3a26cd1c79e71945407bd2 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 9 Oct 2020 15:46:34 +0200 Subject: [PATCH] feat(tvpaint): basic integration --- pype/hooks/tvpaint/prelaunch.py | 110 +++++++++++++++++++++++++++ pype/hosts/tvpaint/__init__.py | 1 + pype/hosts/tvpaint/template.tvpp | Bin 0 -> 62370 bytes pype/resources/app_icons/tvpaint.png | Bin 0 -> 11859 bytes 4 files changed, 111 insertions(+) create mode 100644 pype/hooks/tvpaint/prelaunch.py create mode 100644 pype/hosts/tvpaint/__init__.py create mode 100644 pype/hosts/tvpaint/template.tvpp create mode 100644 pype/resources/app_icons/tvpaint.png diff --git a/pype/hooks/tvpaint/prelaunch.py b/pype/hooks/tvpaint/prelaunch.py new file mode 100644 index 0000000000..b8233e9c93 --- /dev/null +++ b/pype/hooks/tvpaint/prelaunch.py @@ -0,0 +1,110 @@ +import os +import shutil +from pype.lib import PypeHook +from pype.api import ( + Anatomy, + Logger +) +import getpass +import avalon.api + + +class TvpaintPrelaunchHook(PypeHook): + """ + Workfile preparation hook + """ + workfile_ext = "tvpp" + + def __init__(self, logger=None): + if not logger: + self.log = Logger().get_logger(self.__class__.__name__) + else: + self.log = logger + + self.signature = "( {} )".format(self.__class__.__name__) + + def execute(self, *args, env: dict = None) -> bool: + if not env: + env = os.environ + + # get context variables + project_name = env["AVALON_PROJECT"] + asset_name = env["AVALON_ASSET"] + task_name = env["AVALON_TASK"] + workdir = env["AVALON_WORKDIR"] + + # get workfile path + workfile_path = self.get_anatomy_filled( + workdir, project_name, asset_name, task_name) + + # create workdir if doesn't exist + os.makedirs(workdir, exist_ok=True) + self.log.info(f"Work dir is: `{workdir}`") + + # get last version of workfile + workfile_last = env.get("AVALON_LAST_WORKFILE") + self.log.debug(f"_ workfile_last: `{workfile_last}`") + + if workfile_last: + workfile = workfile_last + workfile_path = os.path.join(workdir, workfile) + + # copy workfile from template if doesnt exist any on path + if not os.path.isfile(workfile_path): + # try to get path from environment or use default + # from `pype.celation` dir + template_path = env.get("TVPAINT_TEMPLATE") or os.path.join( + env.get("PYPE_MODULE_ROOT"), + "pype/hosts/tvpaint/template.tvpp" + ) + self.log.info( + f"Creating workfile from template: `{template_path}`") + shutil.copy2( + os.path.normpath(template_path), + os.path.normpath(workfile_path) + ) + + self.log.info(f"Workfile to open: `{workfile_path}`") + + # adding compulsory environment var for openting file + env["PYPE_TVPAINT_PROJECT_FILE"] = workfile_path + + return True + + def get_anatomy_filled(self, workdir, project_name, asset_name, task_name): + host_name = "tvpaint" + dbcon = avalon.api.AvalonMongoDB() + dbcon.install() + dbcon.Session["AVALON_PROJECT"] = project_name + project_document = dbcon.find_one({"type": "project"}) + asset_document = dbcon.find_one({ + "type": "asset", + "name": asset_name + }) + dbcon.uninstall() + + asset_doc_parents = asset_document["data"].get("parents") + hierarchy = "/".join(asset_doc_parents) + + data = { + "project": { + "name": project_document["name"], + "code": project_document["data"].get("code") + }, + "task": task_name, + "asset": asset_name, + "app": host_name, + "hierarchy": hierarchy + } + anatomy = Anatomy(project_name) + extensions = avalon.api.HOST_WORKFILE_EXTENSIONS[host_name] + file_template = anatomy.templates["work"]["file"] + data.update({ + "version": 1, + "user": os.environ.get("PYPE_USERNAME") or getpass.getuser(), + "ext": extensions[0] + }) + + return avalon.api.last_workfile( + workdir, file_template, data, extensions, True + ) diff --git a/pype/hosts/tvpaint/__init__.py b/pype/hosts/tvpaint/__init__.py new file mode 100644 index 0000000000..8c93d93738 --- /dev/null +++ b/pype/hosts/tvpaint/__init__.py @@ -0,0 +1 @@ +kwargs = None diff --git a/pype/hosts/tvpaint/template.tvpp b/pype/hosts/tvpaint/template.tvpp new file mode 100644 index 0000000000000000000000000000000000000000..4bf05d35955c9e7c074a5af0f182d9f1b78bea8a GIT binary patch literal 62370 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 UA)46aA1n^MmsOFekunYWADD4edH?_b literal 0 HcmV?d00001