mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge pull request #4140 from pypeclub/feature/OP-3437_CelAction-conversion-to-op3
CelAction: refactory integration to current openpype
This commit is contained in:
commit
c7a4cf1062
27 changed files with 555 additions and 327 deletions
|
|
@ -0,0 +1,10 @@
|
|||
from .addon import (
|
||||
CELACTION_ROOT_DIR,
|
||||
CelactionAddon,
|
||||
)
|
||||
|
||||
|
||||
__all__ = (
|
||||
"CELACTION_ROOT_DIR",
|
||||
"CelactionAddon",
|
||||
)
|
||||
31
openpype/hosts/celaction/addon.py
Normal file
31
openpype/hosts/celaction/addon.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import os
|
||||
from openpype.modules import OpenPypeModule, IHostAddon
|
||||
|
||||
CELACTION_ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
class CelactionAddon(OpenPypeModule, IHostAddon):
|
||||
name = "celaction"
|
||||
host_name = "celaction"
|
||||
|
||||
def initialize(self, module_settings):
|
||||
self.enabled = True
|
||||
|
||||
def get_launch_hook_paths(self, app):
|
||||
if app.host_name != self.host_name:
|
||||
return []
|
||||
return [
|
||||
os.path.join(CELACTION_ROOT_DIR, "hooks")
|
||||
]
|
||||
|
||||
def add_implementation_envs(self, env, _app):
|
||||
# Set default values if are not already set via settings
|
||||
defaults = {
|
||||
"LOGLEVEL": "DEBUG"
|
||||
}
|
||||
for key, value in defaults.items():
|
||||
if not env.get(key):
|
||||
env[key] = value
|
||||
|
||||
def get_workfile_extensions(self):
|
||||
return [".scn"]
|
||||
|
|
@ -1 +0,0 @@
|
|||
kwargs = None
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
import os
|
||||
import sys
|
||||
import copy
|
||||
import argparse
|
||||
|
||||
import pyblish.api
|
||||
import pyblish.util
|
||||
|
||||
import openpype.hosts.celaction
|
||||
from openpype.lib import Logger
|
||||
from openpype.hosts.celaction import api as celaction
|
||||
from openpype.tools.utils import host_tools
|
||||
from openpype.pipeline import install_openpype_plugins
|
||||
|
||||
|
||||
log = Logger.get_logger("Celaction_cli_publisher")
|
||||
|
||||
publish_host = "celaction"
|
||||
|
||||
HOST_DIR = os.path.dirname(os.path.abspath(openpype.hosts.celaction.__file__))
|
||||
PLUGINS_DIR = os.path.join(HOST_DIR, "plugins")
|
||||
PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish")
|
||||
|
||||
|
||||
def cli():
|
||||
parser = argparse.ArgumentParser(prog="celaction_publish")
|
||||
|
||||
parser.add_argument("--currentFile",
|
||||
help="Pass file to Context as `currentFile`")
|
||||
|
||||
parser.add_argument("--chunk",
|
||||
help=("Render chanks on farm"))
|
||||
|
||||
parser.add_argument("--frameStart",
|
||||
help=("Start of frame range"))
|
||||
|
||||
parser.add_argument("--frameEnd",
|
||||
help=("End of frame range"))
|
||||
|
||||
parser.add_argument("--resolutionWidth",
|
||||
help=("Width of resolution"))
|
||||
|
||||
parser.add_argument("--resolutionHeight",
|
||||
help=("Height of resolution"))
|
||||
|
||||
celaction.kwargs = parser.parse_args(sys.argv[1:]).__dict__
|
||||
|
||||
|
||||
def _prepare_publish_environments():
|
||||
"""Prepares environments based on request data."""
|
||||
env = copy.deepcopy(os.environ)
|
||||
|
||||
project_name = os.getenv("AVALON_PROJECT")
|
||||
asset_name = os.getenv("AVALON_ASSET")
|
||||
|
||||
env["AVALON_PROJECT"] = project_name
|
||||
env["AVALON_ASSET"] = asset_name
|
||||
env["AVALON_TASK"] = os.getenv("AVALON_TASK")
|
||||
env["AVALON_WORKDIR"] = os.getenv("AVALON_WORKDIR")
|
||||
env["AVALON_APP"] = f"hosts.{publish_host}"
|
||||
env["AVALON_APP_NAME"] = "celaction/local"
|
||||
|
||||
env["PYBLISH_HOSTS"] = publish_host
|
||||
|
||||
os.environ.update(env)
|
||||
|
||||
|
||||
def main():
|
||||
# prepare all environments
|
||||
_prepare_publish_environments()
|
||||
|
||||
# Registers pype's Global pyblish plugins
|
||||
install_openpype_plugins()
|
||||
|
||||
if os.path.exists(PUBLISH_PATH):
|
||||
log.info(f"Registering path: {PUBLISH_PATH}")
|
||||
pyblish.api.register_plugin_path(PUBLISH_PATH)
|
||||
|
||||
pyblish.api.register_host(publish_host)
|
||||
|
||||
return host_tools.show_publish()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli()
|
||||
result = main()
|
||||
sys.exit(not bool(result))
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
import os
|
||||
import shutil
|
||||
import winreg
|
||||
from openpype.lib import PreLaunchHook
|
||||
from openpype.hosts.celaction import api as celaction
|
||||
|
||||
|
||||
class CelactionPrelaunchHook(PreLaunchHook):
|
||||
"""
|
||||
Bootstrap celacion with pype
|
||||
"""
|
||||
workfile_ext = "scn"
|
||||
app_groups = ["celaction"]
|
||||
platforms = ["windows"]
|
||||
|
||||
def execute(self):
|
||||
# Add workfile path to launch arguments
|
||||
workfile_path = self.workfile_path()
|
||||
if workfile_path:
|
||||
self.launch_context.launch_args.append(workfile_path)
|
||||
|
||||
project_name = self.data["project_name"]
|
||||
asset_name = self.data["asset_name"]
|
||||
task_name = self.data["task_name"]
|
||||
|
||||
# get publish version of celaction
|
||||
app = "celaction_publish"
|
||||
|
||||
# setting output parameters
|
||||
path = r"Software\CelAction\CelAction2D\User Settings"
|
||||
winreg.CreateKey(winreg.HKEY_CURRENT_USER, path)
|
||||
hKey = winreg.OpenKey(
|
||||
winreg.HKEY_CURRENT_USER,
|
||||
"Software\\CelAction\\CelAction2D\\User Settings", 0,
|
||||
winreg.KEY_ALL_ACCESS)
|
||||
|
||||
# TODO: this will need to be checked more thoroughly
|
||||
pype_exe = os.getenv("OPENPYPE_EXECUTABLE")
|
||||
|
||||
winreg.SetValueEx(hKey, "SubmitAppTitle", 0, winreg.REG_SZ, pype_exe)
|
||||
|
||||
parameters = [
|
||||
"launch",
|
||||
f"--app {app}",
|
||||
f"--project {project_name}",
|
||||
f"--asset {asset_name}",
|
||||
f"--task {task_name}",
|
||||
"--currentFile \\\"\"*SCENE*\"\\\"",
|
||||
"--chunk 10",
|
||||
"--frameStart *START*",
|
||||
"--frameEnd *END*",
|
||||
"--resolutionWidth *X*",
|
||||
"--resolutionHeight *Y*",
|
||||
# "--programDir \"'*PROGPATH*'\""
|
||||
]
|
||||
winreg.SetValueEx(hKey, "SubmitParametersTitle", 0, winreg.REG_SZ,
|
||||
" ".join(parameters))
|
||||
|
||||
# setting resolution parameters
|
||||
path = r"Software\CelAction\CelAction2D\User Settings\Dialogs"
|
||||
path += r"\SubmitOutput"
|
||||
winreg.CreateKey(winreg.HKEY_CURRENT_USER, path)
|
||||
hKey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0,
|
||||
winreg.KEY_ALL_ACCESS)
|
||||
winreg.SetValueEx(hKey, "SaveScene", 0, winreg.REG_DWORD, 1)
|
||||
winreg.SetValueEx(hKey, "CustomX", 0, winreg.REG_DWORD, 1920)
|
||||
winreg.SetValueEx(hKey, "CustomY", 0, winreg.REG_DWORD, 1080)
|
||||
|
||||
# making sure message dialogs don't appear when overwriting
|
||||
path = r"Software\CelAction\CelAction2D\User Settings\Messages"
|
||||
path += r"\OverwriteScene"
|
||||
winreg.CreateKey(winreg.HKEY_CURRENT_USER, path)
|
||||
hKey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0,
|
||||
winreg.KEY_ALL_ACCESS)
|
||||
winreg.SetValueEx(hKey, "Result", 0, winreg.REG_DWORD, 6)
|
||||
winreg.SetValueEx(hKey, "Valid", 0, winreg.REG_DWORD, 1)
|
||||
|
||||
path = r"Software\CelAction\CelAction2D\User Settings\Messages"
|
||||
path += r"\SceneSaved"
|
||||
winreg.CreateKey(winreg.HKEY_CURRENT_USER, path)
|
||||
hKey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0,
|
||||
winreg.KEY_ALL_ACCESS)
|
||||
winreg.SetValueEx(hKey, "Result", 0, winreg.REG_DWORD, 1)
|
||||
winreg.SetValueEx(hKey, "Valid", 0, winreg.REG_DWORD, 1)
|
||||
|
||||
def workfile_path(self):
|
||||
workfile_path = self.data["last_workfile_path"]
|
||||
|
||||
# copy workfile from template if doesnt exist any on path
|
||||
if not os.path.exists(workfile_path):
|
||||
# TODO add ability to set different template workfile path via
|
||||
# settings
|
||||
pype_celaction_dir = os.path.dirname(os.path.dirname(
|
||||
os.path.abspath(celaction.__file__)
|
||||
))
|
||||
template_path = os.path.join(
|
||||
pype_celaction_dir,
|
||||
"resources",
|
||||
"celaction_template_scene.scn"
|
||||
)
|
||||
|
||||
if not os.path.exists(template_path):
|
||||
self.log.warning(
|
||||
"Couldn't find workfile template file in {}".format(
|
||||
template_path
|
||||
)
|
||||
)
|
||||
return
|
||||
|
||||
self.log.info(
|
||||
f"Creating workfile from template: \"{template_path}\""
|
||||
)
|
||||
|
||||
# Copy template workfile to new destinantion
|
||||
shutil.copy2(
|
||||
os.path.normpath(template_path),
|
||||
os.path.normpath(workfile_path)
|
||||
)
|
||||
|
||||
self.log.info(f"Workfile to open: \"{workfile_path}\"")
|
||||
|
||||
return workfile_path
|
||||
137
openpype/hosts/celaction/hooks/pre_celaction_setup.py
Normal file
137
openpype/hosts/celaction/hooks/pre_celaction_setup.py
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
import os
|
||||
import shutil
|
||||
import winreg
|
||||
import subprocess
|
||||
from openpype.lib import PreLaunchHook, get_openpype_execute_args
|
||||
from openpype.hosts.celaction import scripts
|
||||
|
||||
CELACTION_SCRIPTS_DIR = os.path.dirname(
|
||||
os.path.abspath(scripts.__file__)
|
||||
)
|
||||
|
||||
|
||||
class CelactionPrelaunchHook(PreLaunchHook):
|
||||
"""
|
||||
Bootstrap celacion with pype
|
||||
"""
|
||||
app_groups = ["celaction"]
|
||||
platforms = ["windows"]
|
||||
|
||||
def execute(self):
|
||||
asset_doc = self.data["asset_doc"]
|
||||
width = asset_doc["data"]["resolutionWidth"]
|
||||
height = asset_doc["data"]["resolutionHeight"]
|
||||
|
||||
# Add workfile path to launch arguments
|
||||
workfile_path = self.workfile_path()
|
||||
if workfile_path:
|
||||
self.launch_context.launch_args.append(workfile_path)
|
||||
|
||||
# setting output parameters
|
||||
path_user_settings = "\\".join([
|
||||
"Software", "CelAction", "CelAction2D", "User Settings"
|
||||
])
|
||||
winreg.CreateKey(winreg.HKEY_CURRENT_USER, path_user_settings)
|
||||
hKey = winreg.OpenKey(
|
||||
winreg.HKEY_CURRENT_USER, path_user_settings, 0,
|
||||
winreg.KEY_ALL_ACCESS
|
||||
)
|
||||
|
||||
path_to_cli = os.path.join(CELACTION_SCRIPTS_DIR, "publish_cli.py")
|
||||
subproces_args = get_openpype_execute_args("run", path_to_cli)
|
||||
openpype_executable = subproces_args.pop(0)
|
||||
|
||||
winreg.SetValueEx(
|
||||
hKey,
|
||||
"SubmitAppTitle",
|
||||
0,
|
||||
winreg.REG_SZ,
|
||||
openpype_executable
|
||||
)
|
||||
|
||||
parameters = subproces_args + [
|
||||
"--currentFile", "*SCENE*",
|
||||
"--chunk", "*CHUNK*",
|
||||
"--frameStart", "*START*",
|
||||
"--frameEnd", "*END*",
|
||||
"--resolutionWidth", "*X*",
|
||||
"--resolutionHeight", "*Y*"
|
||||
]
|
||||
|
||||
winreg.SetValueEx(
|
||||
hKey, "SubmitParametersTitle", 0, winreg.REG_SZ,
|
||||
subprocess.list2cmdline(parameters)
|
||||
)
|
||||
|
||||
# setting resolution parameters
|
||||
path_submit = "\\".join([
|
||||
path_user_settings, "Dialogs", "SubmitOutput"
|
||||
])
|
||||
winreg.CreateKey(winreg.HKEY_CURRENT_USER, path_submit)
|
||||
hKey = winreg.OpenKey(
|
||||
winreg.HKEY_CURRENT_USER, path_submit, 0,
|
||||
winreg.KEY_ALL_ACCESS
|
||||
)
|
||||
winreg.SetValueEx(hKey, "SaveScene", 0, winreg.REG_DWORD, 1)
|
||||
winreg.SetValueEx(hKey, "CustomX", 0, winreg.REG_DWORD, width)
|
||||
winreg.SetValueEx(hKey, "CustomY", 0, winreg.REG_DWORD, height)
|
||||
|
||||
# making sure message dialogs don't appear when overwriting
|
||||
path_overwrite_scene = "\\".join([
|
||||
path_user_settings, "Messages", "OverwriteScene"
|
||||
])
|
||||
winreg.CreateKey(winreg.HKEY_CURRENT_USER, path_overwrite_scene)
|
||||
hKey = winreg.OpenKey(
|
||||
winreg.HKEY_CURRENT_USER, path_overwrite_scene, 0,
|
||||
winreg.KEY_ALL_ACCESS
|
||||
)
|
||||
winreg.SetValueEx(hKey, "Result", 0, winreg.REG_DWORD, 6)
|
||||
winreg.SetValueEx(hKey, "Valid", 0, winreg.REG_DWORD, 1)
|
||||
|
||||
# set scane as not saved
|
||||
path_scene_saved = "\\".join([
|
||||
path_user_settings, "Messages", "SceneSaved"
|
||||
])
|
||||
winreg.CreateKey(winreg.HKEY_CURRENT_USER, path_scene_saved)
|
||||
hKey = winreg.OpenKey(
|
||||
winreg.HKEY_CURRENT_USER, path_scene_saved, 0,
|
||||
winreg.KEY_ALL_ACCESS
|
||||
)
|
||||
winreg.SetValueEx(hKey, "Result", 0, winreg.REG_DWORD, 1)
|
||||
winreg.SetValueEx(hKey, "Valid", 0, winreg.REG_DWORD, 1)
|
||||
|
||||
def workfile_path(self):
|
||||
workfile_path = self.data["last_workfile_path"]
|
||||
|
||||
# copy workfile from template if doesnt exist any on path
|
||||
if not os.path.exists(workfile_path):
|
||||
# TODO add ability to set different template workfile path via
|
||||
# settings
|
||||
openpype_celaction_dir = os.path.dirname(CELACTION_SCRIPTS_DIR)
|
||||
template_path = os.path.join(
|
||||
openpype_celaction_dir,
|
||||
"resources",
|
||||
"celaction_template_scene.scn"
|
||||
)
|
||||
|
||||
if not os.path.exists(template_path):
|
||||
self.log.warning(
|
||||
"Couldn't find workfile template file in {}".format(
|
||||
template_path
|
||||
)
|
||||
)
|
||||
return
|
||||
|
||||
self.log.info(
|
||||
f"Creating workfile from template: \"{template_path}\""
|
||||
)
|
||||
|
||||
# Copy template workfile to new destinantion
|
||||
shutil.copy2(
|
||||
os.path.normpath(template_path),
|
||||
os.path.normpath(workfile_path)
|
||||
)
|
||||
|
||||
self.log.info(f"Workfile to open: \"{workfile_path}\"")
|
||||
|
||||
return workfile_path
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
import pyblish.api
|
||||
from openpype.hosts.celaction import api as celaction
|
||||
import argparse
|
||||
import sys
|
||||
from pprint import pformat
|
||||
|
||||
|
||||
class CollectCelactionCliKwargs(pyblish.api.Collector):
|
||||
|
|
@ -9,15 +11,31 @@ class CollectCelactionCliKwargs(pyblish.api.Collector):
|
|||
order = pyblish.api.Collector.order - 0.1
|
||||
|
||||
def process(self, context):
|
||||
kwargs = celaction.kwargs.copy()
|
||||
parser = argparse.ArgumentParser(prog="celaction")
|
||||
parser.add_argument("--currentFile",
|
||||
help="Pass file to Context as `currentFile`")
|
||||
parser.add_argument("--chunk",
|
||||
help=("Render chanks on farm"))
|
||||
parser.add_argument("--frameStart",
|
||||
help=("Start of frame range"))
|
||||
parser.add_argument("--frameEnd",
|
||||
help=("End of frame range"))
|
||||
parser.add_argument("--resolutionWidth",
|
||||
help=("Width of resolution"))
|
||||
parser.add_argument("--resolutionHeight",
|
||||
help=("Height of resolution"))
|
||||
passing_kwargs = parser.parse_args(sys.argv[1:]).__dict__
|
||||
|
||||
self.log.info("Storing kwargs: %s" % kwargs)
|
||||
context.set_data("kwargs", kwargs)
|
||||
self.log.info("Storing kwargs ...")
|
||||
self.log.debug("_ passing_kwargs: {}".format(pformat(passing_kwargs)))
|
||||
|
||||
# set kwargs to context data
|
||||
context.set_data("passingKwargs", passing_kwargs)
|
||||
|
||||
# get kwargs onto context data as keys with values
|
||||
for k, v in kwargs.items():
|
||||
for k, v in passing_kwargs.items():
|
||||
self.log.info(f"Setting `{k}` to instance.data with value: `{v}`")
|
||||
if k in ["frameStart", "frameEnd"]:
|
||||
context.data[k] = kwargs[k] = int(v)
|
||||
context.data[k] = passing_kwargs[k] = int(v)
|
||||
else:
|
||||
context.data[k] = v
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ class CollectCelactionInstances(pyblish.api.ContextPlugin):
|
|||
"version": version
|
||||
}
|
||||
|
||||
celaction_kwargs = context.data.get("kwargs", {})
|
||||
celaction_kwargs = context.data.get(
|
||||
"passingKwargs", {})
|
||||
|
||||
if celaction_kwargs:
|
||||
shared_instance_data.update(celaction_kwargs)
|
||||
|
|
@ -52,8 +53,8 @@ class CollectCelactionInstances(pyblish.api.ContextPlugin):
|
|||
"subset": subset,
|
||||
"label": scene_file,
|
||||
"family": family,
|
||||
"families": [family, "ftrack"],
|
||||
"representations": list()
|
||||
"families": [],
|
||||
"representations": []
|
||||
})
|
||||
|
||||
# adding basic script data
|
||||
|
|
@ -72,7 +73,6 @@ class CollectCelactionInstances(pyblish.api.ContextPlugin):
|
|||
self.log.info('Publishing Celaction workfile')
|
||||
|
||||
# render instance
|
||||
family = "render.farm"
|
||||
subset = f"render{task}Main"
|
||||
instance = context.create_instance(name=subset)
|
||||
# getting instance state
|
||||
|
|
@ -81,8 +81,8 @@ class CollectCelactionInstances(pyblish.api.ContextPlugin):
|
|||
# add assetEntity data into instance
|
||||
instance.data.update({
|
||||
"label": "{} - farm".format(subset),
|
||||
"family": family,
|
||||
"families": [family],
|
||||
"family": "render.farm",
|
||||
"families": [],
|
||||
"subset": subset
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -11,28 +11,31 @@ class CollectRenderPath(pyblish.api.InstancePlugin):
|
|||
families = ["render.farm"]
|
||||
|
||||
# Presets
|
||||
anatomy_render_key = None
|
||||
publish_render_metadata = None
|
||||
output_extension = "png"
|
||||
anatomy_template_key_render_files = None
|
||||
anatomy_template_key_metadata = None
|
||||
|
||||
def process(self, instance):
|
||||
anatomy = instance.context.data["anatomy"]
|
||||
anatomy_data = copy.deepcopy(instance.data["anatomyData"])
|
||||
anatomy_data["family"] = "render"
|
||||
padding = anatomy.templates.get("frame_padding", 4)
|
||||
anatomy_data.update({
|
||||
"frame": f"%0{padding}d",
|
||||
"representation": "png"
|
||||
"family": "render",
|
||||
"representation": self.output_extension,
|
||||
"ext": self.output_extension
|
||||
})
|
||||
|
||||
anatomy_filled = anatomy.format(anatomy_data)
|
||||
|
||||
# get anatomy rendering keys
|
||||
anatomy_render_key = self.anatomy_render_key or "render"
|
||||
publish_render_metadata = self.publish_render_metadata or "render"
|
||||
r_anatomy_key = self.anatomy_template_key_render_files
|
||||
m_anatomy_key = self.anatomy_template_key_metadata
|
||||
|
||||
# get folder and path for rendering images from celaction
|
||||
render_dir = anatomy_filled[anatomy_render_key]["folder"]
|
||||
render_path = anatomy_filled[anatomy_render_key]["path"]
|
||||
render_dir = anatomy_filled[r_anatomy_key]["folder"]
|
||||
render_path = anatomy_filled[r_anatomy_key]["path"]
|
||||
self.log.debug("__ render_path: `{}`".format(render_path))
|
||||
|
||||
# create dir if it doesnt exists
|
||||
try:
|
||||
|
|
@ -46,9 +49,9 @@ class CollectRenderPath(pyblish.api.InstancePlugin):
|
|||
instance.data["path"] = render_path
|
||||
|
||||
# get anatomy for published renders folder path
|
||||
if anatomy_filled.get(publish_render_metadata):
|
||||
if anatomy_filled.get(m_anatomy_key):
|
||||
instance.data["publishRenderMetadataFolder"] = anatomy_filled[
|
||||
publish_render_metadata]["folder"]
|
||||
m_anatomy_key]["folder"]
|
||||
self.log.info("Metadata render path: `{}`".format(
|
||||
instance.data["publishRenderMetadataFolder"]
|
||||
))
|
||||
|
|
|
|||
0
openpype/hosts/celaction/scripts/__init__.py
Normal file
0
openpype/hosts/celaction/scripts/__init__.py
Normal file
37
openpype/hosts/celaction/scripts/publish_cli.py
Normal file
37
openpype/hosts/celaction/scripts/publish_cli.py
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
import pyblish.api
|
||||
import pyblish.util
|
||||
|
||||
import openpype.hosts.celaction
|
||||
from openpype.lib import Logger
|
||||
from openpype.tools.utils import host_tools
|
||||
from openpype.pipeline import install_openpype_plugins
|
||||
|
||||
|
||||
log = Logger.get_logger("celaction")
|
||||
|
||||
PUBLISH_HOST = "celaction"
|
||||
HOST_DIR = os.path.dirname(os.path.abspath(openpype.hosts.celaction.__file__))
|
||||
PLUGINS_DIR = os.path.join(HOST_DIR, "plugins")
|
||||
PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish")
|
||||
|
||||
|
||||
def main():
|
||||
# Registers pype's Global pyblish plugins
|
||||
install_openpype_plugins()
|
||||
|
||||
if os.path.exists(PUBLISH_PATH):
|
||||
log.info(f"Registering path: {PUBLISH_PATH}")
|
||||
pyblish.api.register_plugin_path(PUBLISH_PATH)
|
||||
|
||||
pyblish.api.register_host(PUBLISH_HOST)
|
||||
pyblish.api.register_target("local")
|
||||
|
||||
return host_tools.show_publish()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
result = main()
|
||||
sys.exit(not bool(result))
|
||||
|
|
@ -2,16 +2,14 @@ import os
|
|||
import re
|
||||
import json
|
||||
import getpass
|
||||
|
||||
import requests
|
||||
import pyblish.api
|
||||
|
||||
|
||||
class ExtractCelactionDeadline(pyblish.api.InstancePlugin):
|
||||
class CelactionSubmitDeadline(pyblish.api.InstancePlugin):
|
||||
"""Submit CelAction2D scene to Deadline
|
||||
|
||||
Renders are submitted to a Deadline Web Service as
|
||||
supplied via settings key "DEADLINE_REST_URL".
|
||||
Renders are submitted to a Deadline Web Service.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -26,24 +24,18 @@ class ExtractCelactionDeadline(pyblish.api.InstancePlugin):
|
|||
deadline_pool_secondary = ""
|
||||
deadline_group = ""
|
||||
deadline_chunk_size = 1
|
||||
|
||||
enviro_filter = [
|
||||
"FTRACK_API_USER",
|
||||
"FTRACK_API_KEY",
|
||||
"FTRACK_SERVER"
|
||||
]
|
||||
deadline_job_delay = "00:00:08:00"
|
||||
|
||||
def process(self, instance):
|
||||
instance.data["toBeRenderedOn"] = "deadline"
|
||||
context = instance.context
|
||||
|
||||
deadline_url = (
|
||||
context.data["system_settings"]
|
||||
["modules"]
|
||||
["deadline"]
|
||||
["DEADLINE_REST_URL"]
|
||||
)
|
||||
assert deadline_url, "Requires DEADLINE_REST_URL"
|
||||
# get default deadline webservice url from deadline module
|
||||
deadline_url = instance.context.data["defaultDeadline"]
|
||||
# if custom one is set in instance, use that
|
||||
if instance.data.get("deadlineUrl"):
|
||||
deadline_url = instance.data.get("deadlineUrl")
|
||||
assert deadline_url, "Requires Deadline Webservice URL"
|
||||
|
||||
self.deadline_url = "{}/api/jobs".format(deadline_url)
|
||||
self._comment = context.data.get("comment", "")
|
||||
|
|
@ -82,6 +74,26 @@ class ExtractCelactionDeadline(pyblish.api.InstancePlugin):
|
|||
render_dir = os.path.normpath(os.path.dirname(render_path))
|
||||
render_path = os.path.normpath(render_path)
|
||||
script_name = os.path.basename(script_path)
|
||||
|
||||
for item in instance.context:
|
||||
if "workfile" in item.data["family"]:
|
||||
msg = "Workfile (scene) must be published along"
|
||||
assert item.data["publish"] is True, msg
|
||||
|
||||
template_data = item.data.get("anatomyData")
|
||||
rep = item.data.get("representations")[0].get("name")
|
||||
template_data["representation"] = rep
|
||||
template_data["ext"] = rep
|
||||
template_data["comment"] = None
|
||||
anatomy_filled = instance.context.data["anatomy"].format(
|
||||
template_data)
|
||||
template_filled = anatomy_filled["publish"]["path"]
|
||||
script_path = os.path.normpath(template_filled)
|
||||
|
||||
self.log.info(
|
||||
"Using published scene for render {}".format(script_path)
|
||||
)
|
||||
|
||||
jobname = "%s - %s" % (script_name, instance.name)
|
||||
|
||||
output_filename_0 = self.preview_fname(render_path)
|
||||
|
|
@ -98,7 +110,7 @@ class ExtractCelactionDeadline(pyblish.api.InstancePlugin):
|
|||
chunk_size = self.deadline_chunk_size
|
||||
|
||||
# search for %02d pattern in name, and padding number
|
||||
search_results = re.search(r"(.%0)(\d)(d)[._]", render_path).groups()
|
||||
search_results = re.search(r"(%0)(\d)(d)[._]", render_path).groups()
|
||||
split_patern = "".join(search_results)
|
||||
padding_number = int(search_results[1])
|
||||
|
||||
|
|
@ -145,10 +157,11 @@ class ExtractCelactionDeadline(pyblish.api.InstancePlugin):
|
|||
# frames from Deadline Monitor
|
||||
"OutputFilename0": output_filename_0.replace("\\", "/"),
|
||||
|
||||
# # Asset dependency to wait for at least the scene file to sync.
|
||||
# # Asset dependency to wait for at least
|
||||
# the scene file to sync.
|
||||
# "AssetDependency0": script_path
|
||||
"ScheduledType": "Once",
|
||||
"JobDelay": "00:00:08:00"
|
||||
"JobDelay": self.deadline_job_delay
|
||||
},
|
||||
"PluginInfo": {
|
||||
# Input
|
||||
|
|
@ -173,19 +186,6 @@ class ExtractCelactionDeadline(pyblish.api.InstancePlugin):
|
|||
plugin = payload["JobInfo"]["Plugin"]
|
||||
self.log.info("using render plugin : {}".format(plugin))
|
||||
|
||||
i = 0
|
||||
for key, values in dict(os.environ).items():
|
||||
if key.upper() in self.enviro_filter:
|
||||
payload["JobInfo"].update(
|
||||
{
|
||||
"EnvironmentKeyValue%d"
|
||||
% i: "{key}={value}".format(
|
||||
key=key, value=values
|
||||
)
|
||||
}
|
||||
)
|
||||
i += 1
|
||||
|
||||
self.log.info("Submitting..")
|
||||
self.log.info(json.dumps(payload, indent=4, sort_keys=True))
|
||||
|
||||
|
|
@ -193,10 +193,15 @@ class ExtractCelactionDeadline(pyblish.api.InstancePlugin):
|
|||
self.expected_files(instance, render_path)
|
||||
self.log.debug("__ expectedFiles: `{}`".format(
|
||||
instance.data["expectedFiles"]))
|
||||
|
||||
response = requests.post(self.deadline_url, json=payload)
|
||||
|
||||
if not response.ok:
|
||||
raise Exception(response.text)
|
||||
self.log.error(
|
||||
"Submission failed! [{}] {}".format(
|
||||
response.status_code, response.content))
|
||||
self.log.debug(payload)
|
||||
raise SystemExit(response.text)
|
||||
|
||||
return response
|
||||
|
||||
|
|
@ -234,32 +239,29 @@ class ExtractCelactionDeadline(pyblish.api.InstancePlugin):
|
|||
split_path = path.split(split_patern)
|
||||
hashes = "#" * int(search_results[1])
|
||||
return "".join([split_path[0], hashes, split_path[-1]])
|
||||
if "#" in path:
|
||||
self.log.debug("_ path: `{}`".format(path))
|
||||
return path
|
||||
else:
|
||||
return path
|
||||
|
||||
def expected_files(self,
|
||||
instance,
|
||||
path):
|
||||
self.log.debug("_ path: `{}`".format(path))
|
||||
return path
|
||||
|
||||
def expected_files(self, instance, filepath):
|
||||
""" Create expected files in instance data
|
||||
"""
|
||||
if not instance.data.get("expectedFiles"):
|
||||
instance.data["expectedFiles"] = list()
|
||||
instance.data["expectedFiles"] = []
|
||||
|
||||
dir = os.path.dirname(path)
|
||||
file = os.path.basename(path)
|
||||
dirpath = os.path.dirname(filepath)
|
||||
filename = os.path.basename(filepath)
|
||||
|
||||
if "#" in file:
|
||||
pparts = file.split("#")
|
||||
if "#" in filename:
|
||||
pparts = filename.split("#")
|
||||
padding = "%0{}d".format(len(pparts) - 1)
|
||||
file = pparts[0] + padding + pparts[-1]
|
||||
filename = pparts[0] + padding + pparts[-1]
|
||||
|
||||
if "%" not in file:
|
||||
instance.data["expectedFiles"].append(path)
|
||||
if "%" not in filename:
|
||||
instance.data["expectedFiles"].append(filepath)
|
||||
return
|
||||
|
||||
for i in range(self._frame_start, (self._frame_end + 1)):
|
||||
instance.data["expectedFiles"].append(
|
||||
os.path.join(dir, (file % i)).replace("\\", "/"))
|
||||
os.path.join(dirpath, (filename % i)).replace("\\", "/")
|
||||
)
|
||||
|
|
@ -241,6 +241,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
|
|||
environment["AVALON_ASSET"] = legacy_io.Session["AVALON_ASSET"]
|
||||
environment["AVALON_TASK"] = legacy_io.Session["AVALON_TASK"]
|
||||
environment["AVALON_APP_NAME"] = os.environ.get("AVALON_APP_NAME")
|
||||
environment["OPENPYPE_VERSION"] = os.environ.get("OPENPYPE_VERSION")
|
||||
environment["OPENPYPE_LOG_NO_COLORS"] = "1"
|
||||
environment["OPENPYPE_USERNAME"] = instance.context.data["user"]
|
||||
environment["OPENPYPE_PUBLISH_JOB"] = "1"
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 101 KiB |
|
|
@ -0,0 +1,38 @@
|
|||
[About]
|
||||
Type=label
|
||||
Label=About
|
||||
Category=About Plugin
|
||||
CategoryOrder=-1
|
||||
Index=0
|
||||
Default=Celaction Plugin for Deadline
|
||||
Description=Not configurable
|
||||
|
||||
[ConcurrentTasks]
|
||||
Type=label
|
||||
Label=ConcurrentTasks
|
||||
Category=About Plugin
|
||||
CategoryOrder=-1
|
||||
Index=0
|
||||
Default=True
|
||||
Description=Not configurable
|
||||
|
||||
[Executable]
|
||||
Type=filename
|
||||
Label=Executable
|
||||
Category=Config
|
||||
CategoryOrder=0
|
||||
CategoryIndex=0
|
||||
Description=The command executable to run
|
||||
Required=false
|
||||
DisableIfBlank=true
|
||||
|
||||
[RenderNameSeparator]
|
||||
Type=string
|
||||
Label=RenderNameSeparator
|
||||
Category=Config
|
||||
CategoryOrder=0
|
||||
CategoryIndex=1
|
||||
Description=The separator to use for naming
|
||||
Required=false
|
||||
DisableIfBlank=true
|
||||
Default=.
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
from System.Text.RegularExpressions import *
|
||||
|
||||
from Deadline.Plugins import *
|
||||
from Deadline.Scripting import *
|
||||
|
||||
import _winreg
|
||||
|
||||
######################################################################
|
||||
# This is the function that Deadline calls to get an instance of the
|
||||
# main DeadlinePlugin class.
|
||||
######################################################################
|
||||
|
||||
|
||||
def GetDeadlinePlugin():
|
||||
return CelActionPlugin()
|
||||
|
||||
|
||||
def CleanupDeadlinePlugin(deadlinePlugin):
|
||||
deadlinePlugin.Cleanup()
|
||||
|
||||
######################################################################
|
||||
# This is the main DeadlinePlugin class for the CelAction plugin.
|
||||
######################################################################
|
||||
|
||||
|
||||
class CelActionPlugin(DeadlinePlugin):
|
||||
|
||||
def __init__(self):
|
||||
self.InitializeProcessCallback += self.InitializeProcess
|
||||
self.RenderExecutableCallback += self.RenderExecutable
|
||||
self.RenderArgumentCallback += self.RenderArgument
|
||||
self.StartupDirectoryCallback += self.StartupDirectory
|
||||
|
||||
def Cleanup(self):
|
||||
for stdoutHandler in self.StdoutHandlers:
|
||||
del stdoutHandler.HandleCallback
|
||||
|
||||
del self.InitializeProcessCallback
|
||||
del self.RenderExecutableCallback
|
||||
del self.RenderArgumentCallback
|
||||
del self.StartupDirectoryCallback
|
||||
|
||||
def GetCelActionRegistryKey(self):
|
||||
# Modify registry for frame separation
|
||||
path = r'Software\CelAction\CelAction2D\User Settings'
|
||||
_winreg.CreateKey(_winreg.HKEY_CURRENT_USER, path)
|
||||
regKey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, path, 0,
|
||||
_winreg.KEY_ALL_ACCESS)
|
||||
return regKey
|
||||
|
||||
def GetSeparatorValue(self, regKey):
|
||||
useSeparator, _ = _winreg.QueryValueEx(
|
||||
regKey, 'RenderNameUseSeparator')
|
||||
separator, _ = _winreg.QueryValueEx(regKey, 'RenderNameSeparator')
|
||||
|
||||
return useSeparator, separator
|
||||
|
||||
def SetSeparatorValue(self, regKey, useSeparator, separator):
|
||||
_winreg.SetValueEx(regKey, 'RenderNameUseSeparator',
|
||||
0, _winreg.REG_DWORD, useSeparator)
|
||||
_winreg.SetValueEx(regKey, 'RenderNameSeparator',
|
||||
0, _winreg.REG_SZ, separator)
|
||||
|
||||
def InitializeProcess(self):
|
||||
# Set the plugin specific settings.
|
||||
self.SingleFramesOnly = False
|
||||
|
||||
# Set the process specific settings.
|
||||
self.StdoutHandling = True
|
||||
self.PopupHandling = True
|
||||
|
||||
# Ignore 'celaction' Pop-up dialog
|
||||
self.AddPopupIgnorer(".*Rendering.*")
|
||||
self.AddPopupIgnorer(".*AutoRender.*")
|
||||
|
||||
# Ignore 'celaction' Pop-up dialog
|
||||
self.AddPopupIgnorer(".*Wait.*")
|
||||
|
||||
# Ignore 'celaction' Pop-up dialog
|
||||
self.AddPopupIgnorer(".*Timeline Scrub.*")
|
||||
|
||||
celActionRegKey = self.GetCelActionRegistryKey()
|
||||
|
||||
self.SetSeparatorValue(celActionRegKey, 1, self.GetConfigEntryWithDefault(
|
||||
"RenderNameSeparator", ".").strip())
|
||||
|
||||
def RenderExecutable(self):
|
||||
return RepositoryUtils.CheckPathMapping(self.GetConfigEntry("Executable").strip())
|
||||
|
||||
def RenderArgument(self):
|
||||
arguments = RepositoryUtils.CheckPathMapping(
|
||||
self.GetPluginInfoEntry("Arguments").strip())
|
||||
arguments = arguments.replace(
|
||||
"<STARTFRAME>", str(self.GetStartFrame()))
|
||||
arguments = arguments.replace("<ENDFRAME>", str(self.GetEndFrame()))
|
||||
arguments = self.ReplacePaddedFrame(
|
||||
arguments, "<STARTFRAME%([0-9]+)>", self.GetStartFrame())
|
||||
arguments = self.ReplacePaddedFrame(
|
||||
arguments, "<ENDFRAME%([0-9]+)>", self.GetEndFrame())
|
||||
arguments = arguments.replace("<QUOTE>", "\"")
|
||||
return arguments
|
||||
|
||||
def StartupDirectory(self):
|
||||
return self.GetPluginInfoEntryWithDefault("StartupDirectory", "").strip()
|
||||
|
||||
def ReplacePaddedFrame(self, arguments, pattern, frame):
|
||||
frameRegex = Regex(pattern)
|
||||
while True:
|
||||
frameMatch = frameRegex.Match(arguments)
|
||||
if frameMatch.Success:
|
||||
paddingSize = int(frameMatch.Groups[1].Value)
|
||||
if paddingSize > 0:
|
||||
padding = StringUtils.ToZeroPaddedString(
|
||||
frame, paddingSize, False)
|
||||
else:
|
||||
padding = str(frame)
|
||||
arguments = arguments.replace(
|
||||
frameMatch.Groups[0].Value, padding)
|
||||
else:
|
||||
break
|
||||
|
||||
return arguments
|
||||
|
|
@ -291,6 +291,9 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
instance)
|
||||
|
||||
for src, dst in prepared["transfers"]:
|
||||
if src == dst:
|
||||
continue
|
||||
|
||||
# todo: add support for hardlink transfers
|
||||
file_transactions.add(src, dst)
|
||||
|
||||
|
|
|
|||
BIN
openpype/resources/app_icons/celaction.png
Normal file
BIN
openpype/resources/app_icons/celaction.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 40 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 36 KiB |
|
|
@ -1,13 +1,9 @@
|
|||
{
|
||||
"publish": {
|
||||
"ExtractCelactionDeadline": {
|
||||
"enabled": true,
|
||||
"deadline_department": "",
|
||||
"deadline_priority": 50,
|
||||
"deadline_pool": "",
|
||||
"deadline_pool_secondary": "",
|
||||
"deadline_group": "",
|
||||
"deadline_chunk_size": 10
|
||||
"CollectRenderPath": {
|
||||
"output_extension": "png",
|
||||
"anatomy_template_key_render_files": "render",
|
||||
"anatomy_template_key_metadata": "render"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -70,6 +70,16 @@
|
|||
"department": "",
|
||||
"multiprocess": true
|
||||
},
|
||||
"CelactionSubmitDeadline": {
|
||||
"enabled": true,
|
||||
"deadline_department": "",
|
||||
"deadline_priority": 50,
|
||||
"deadline_pool": "",
|
||||
"deadline_pool_secondary": "",
|
||||
"deadline_group": "",
|
||||
"deadline_chunk_size": 10,
|
||||
"deadline_job_delay": "00:00:00:00"
|
||||
},
|
||||
"ProcessSubmittedJobOnFarm": {
|
||||
"enabled": true,
|
||||
"deadline_department": "",
|
||||
|
|
|
|||
|
|
@ -1268,12 +1268,12 @@
|
|||
"CELACTION_TEMPLATE": "{OPENPYPE_REPOS_ROOT}/openpype/hosts/celaction/celaction_template_scene.scn"
|
||||
},
|
||||
"variants": {
|
||||
"local": {
|
||||
"current": {
|
||||
"enabled": true,
|
||||
"variant_label": "Local",
|
||||
"variant_label": "Current",
|
||||
"use_python_2": false,
|
||||
"executables": {
|
||||
"windows": [],
|
||||
"windows": ["C:/Program Files/CelAction/CelAction2D Studio/CelAction2D.exe"],
|
||||
"darwin": [],
|
||||
"linux": []
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,45 +14,24 @@
|
|||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
"checkbox_key": "enabled",
|
||||
"key": "ExtractCelactionDeadline",
|
||||
"label": "ExtractCelactionDeadline",
|
||||
"key": "CollectRenderPath",
|
||||
"label": "CollectRenderPath",
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Enabled"
|
||||
"type": "text",
|
||||
"key": "output_extension",
|
||||
"label": "Output render file extension"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_department",
|
||||
"label": "Deadline apartment"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "deadline_priority",
|
||||
"label": "Deadline priority"
|
||||
"key": "anatomy_template_key_render_files",
|
||||
"label": "Anatomy template key: render files"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_pool",
|
||||
"label": "Deadline pool"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_pool_secondary",
|
||||
"label": "Deadline pool (secondary)"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_group",
|
||||
"label": "Deadline Group"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "deadline_chunk_size",
|
||||
"label": "Deadline Chunk size"
|
||||
"key": "anatomy_template_key_metadata",
|
||||
"label": "Anatomy template key: metadata job file"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -387,6 +387,56 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
"checkbox_key": "enabled",
|
||||
"key": "CelactionSubmitDeadline",
|
||||
"label": "Celaction Submit Deadline",
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_department",
|
||||
"label": "Deadline apartment"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "deadline_priority",
|
||||
"label": "Deadline priority"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_pool",
|
||||
"label": "Deadline pool"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_pool_secondary",
|
||||
"label": "Deadline pool (secondary)"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_group",
|
||||
"label": "Deadline Group"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "deadline_chunk_size",
|
||||
"label": "Deadline Chunk size"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_job_delay",
|
||||
"label": "Delay job (timecode dd:hh:mm:ss)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@
|
|||
"name": "template_host_variant",
|
||||
"template_data": [
|
||||
{
|
||||
"app_variant_label": "Local",
|
||||
"app_variant": "local"
|
||||
"app_variant_label": "Current",
|
||||
"app_variant": "current"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ exclude =
|
|||
docs,
|
||||
*/vendor,
|
||||
website,
|
||||
openpype/vendor
|
||||
openpype/vendor,
|
||||
*deadline/repository/custom/plugins
|
||||
|
||||
max-complexity = 30
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue