Merge branch 'develop' into release/3.15.x

This commit is contained in:
Jakub Trllo 2022-12-20 12:13:47 +01:00
commit ee16161f89
23 changed files with 495 additions and 68 deletions

View file

@ -1,5 +1,73 @@
# Changelog
## [3.14.9](https://github.com/pypeclub/OpenPype/tree/3.14.9)
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.8...3.14.9)
### 📖 Documentation
- Documentation: Testing on Deadline [\#4185](https://github.com/pypeclub/OpenPype/pull/4185)
- Consistent Python version [\#4160](https://github.com/pypeclub/OpenPype/pull/4160)
**🆕 New features**
- Feature/op 4397 gl tf extractor for maya [\#4192](https://github.com/pypeclub/OpenPype/pull/4192)
- Maya: Extractor for Unreal SkeletalMesh [\#4174](https://github.com/pypeclub/OpenPype/pull/4174)
- 3dsmax: integration [\#4168](https://github.com/pypeclub/OpenPype/pull/4168)
- Blender: Extract Alembic Animations [\#4128](https://github.com/pypeclub/OpenPype/pull/4128)
- Unreal: Load Alembic Animations [\#4127](https://github.com/pypeclub/OpenPype/pull/4127)
**🚀 Enhancements**
- Houdini: Use new interface class name for publish host [\#4220](https://github.com/pypeclub/OpenPype/pull/4220)
- General: Default command for headless mode is interactive [\#4203](https://github.com/pypeclub/OpenPype/pull/4203)
- Maya: Enhanced ASS publishing [\#4196](https://github.com/pypeclub/OpenPype/pull/4196)
- Feature/op 3924 implement ass extractor [\#4188](https://github.com/pypeclub/OpenPype/pull/4188)
- File transactions: Source path is destination path [\#4184](https://github.com/pypeclub/OpenPype/pull/4184)
- Deadline: improve environment processing [\#4182](https://github.com/pypeclub/OpenPype/pull/4182)
- General: Comment per instance in Publisher [\#4178](https://github.com/pypeclub/OpenPype/pull/4178)
- Ensure Mongo database directory exists in Windows. [\#4166](https://github.com/pypeclub/OpenPype/pull/4166)
- Note about unrestricted execution on Windows. [\#4161](https://github.com/pypeclub/OpenPype/pull/4161)
- Maya: Enable thumbnail transparency on extraction. [\#4147](https://github.com/pypeclub/OpenPype/pull/4147)
- Maya: Disable viewport Pan/Zoom on playblast extraction. [\#4146](https://github.com/pypeclub/OpenPype/pull/4146)
- Maya: Optional viewport refresh on pointcache extraction [\#4144](https://github.com/pypeclub/OpenPype/pull/4144)
- CelAction: refactory integration to current openpype [\#4140](https://github.com/pypeclub/OpenPype/pull/4140)
- Maya: create and publish bounding box geometry [\#4131](https://github.com/pypeclub/OpenPype/pull/4131)
- Changed the UOpenPypePublishInstance to use the UDataAsset class [\#4124](https://github.com/pypeclub/OpenPype/pull/4124)
- General: Collection Audio speed up [\#4110](https://github.com/pypeclub/OpenPype/pull/4110)
- Maya: keep existing AOVs when creating render instance [\#4087](https://github.com/pypeclub/OpenPype/pull/4087)
- General: Oiio conversion multipart fix [\#4060](https://github.com/pypeclub/OpenPype/pull/4060)
**🐛 Bug fixes**
- Publisher: Signal type issues in Python 2 DCCs [\#4230](https://github.com/pypeclub/OpenPype/pull/4230)
- Blender: Fix Layout Family Versioning [\#4228](https://github.com/pypeclub/OpenPype/pull/4228)
- Blender: Fix Create Camera "Use selection" [\#4226](https://github.com/pypeclub/OpenPype/pull/4226)
- TrayPublisher - join needs list [\#4224](https://github.com/pypeclub/OpenPype/pull/4224)
- General: Event callbacks pass event to callbacks as expected [\#4210](https://github.com/pypeclub/OpenPype/pull/4210)
- Build:Revert .toml update of Gazu [\#4207](https://github.com/pypeclub/OpenPype/pull/4207)
- Nuke: fixed imageio node overrides subset filter [\#4202](https://github.com/pypeclub/OpenPype/pull/4202)
- Maya: pointcache [\#4201](https://github.com/pypeclub/OpenPype/pull/4201)
- Unreal: Support for Unreal Engine 5.1 [\#4199](https://github.com/pypeclub/OpenPype/pull/4199)
- General: Integrate thumbnail looks for thumbnail to multiple places [\#4181](https://github.com/pypeclub/OpenPype/pull/4181)
- Various minor bugfixes [\#4172](https://github.com/pypeclub/OpenPype/pull/4172)
- Nuke/Hiero: Remove tkinter library paths before launch [\#4171](https://github.com/pypeclub/OpenPype/pull/4171)
- Flame: vertical alignment of layers [\#4169](https://github.com/pypeclub/OpenPype/pull/4169)
- Nuke: correct detection of viewer and display [\#4165](https://github.com/pypeclub/OpenPype/pull/4165)
- Settings UI: Don't create QApplication if already exists [\#4156](https://github.com/pypeclub/OpenPype/pull/4156)
- General: Extract review handle start offset of sequences [\#4152](https://github.com/pypeclub/OpenPype/pull/4152)
- Maya: Maintain time connections on Alembic update. [\#4143](https://github.com/pypeclub/OpenPype/pull/4143)
**🔀 Refactored code**
- General: Use qtpy in modules and hosts UIs which are running in OpenPype process [\#4225](https://github.com/pypeclub/OpenPype/pull/4225)
- Tools: Use qtpy instead of Qt in standalone tools [\#4223](https://github.com/pypeclub/OpenPype/pull/4223)
- General: Use qtpy in settings UI [\#4215](https://github.com/pypeclub/OpenPype/pull/4215)
**Merged pull requests:**
- layout publish more than one container issue [\#4098](https://github.com/pypeclub/OpenPype/pull/4098)
## [3.14.8](https://github.com/pypeclub/OpenPype/tree/3.14.8)
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.7...3.14.8)
@ -21,7 +89,6 @@
- Maya: Looks - add all connections [\#4135](https://github.com/pypeclub/OpenPype/pull/4135)
- General: Fix variable check in collect anatomy instance data [\#4117](https://github.com/pypeclub/OpenPype/pull/4117)
## [3.14.7](https://github.com/pypeclub/OpenPype/tree/3.14.7)
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.6...3.14.7)

View file

@ -1,5 +1,74 @@
# Changelog
## [3.14.9](https://github.com/pypeclub/OpenPype/tree/3.14.9)
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.8...3.14.9)
### 📖 Documentation
- Documentation: Testing on Deadline [\#4185](https://github.com/pypeclub/OpenPype/pull/4185)
- Consistent Python version [\#4160](https://github.com/pypeclub/OpenPype/pull/4160)
**🆕 New features**
- Feature/op 4397 gl tf extractor for maya [\#4192](https://github.com/pypeclub/OpenPype/pull/4192)
- Maya: Extractor for Unreal SkeletalMesh [\#4174](https://github.com/pypeclub/OpenPype/pull/4174)
- 3dsmax: integration [\#4168](https://github.com/pypeclub/OpenPype/pull/4168)
- Blender: Extract Alembic Animations [\#4128](https://github.com/pypeclub/OpenPype/pull/4128)
- Unreal: Load Alembic Animations [\#4127](https://github.com/pypeclub/OpenPype/pull/4127)
**🚀 Enhancements**
- Houdini: Use new interface class name for publish host [\#4220](https://github.com/pypeclub/OpenPype/pull/4220)
- General: Default command for headless mode is interactive [\#4203](https://github.com/pypeclub/OpenPype/pull/4203)
- Maya: Enhanced ASS publishing [\#4196](https://github.com/pypeclub/OpenPype/pull/4196)
- Feature/op 3924 implement ass extractor [\#4188](https://github.com/pypeclub/OpenPype/pull/4188)
- File transactions: Source path is destination path [\#4184](https://github.com/pypeclub/OpenPype/pull/4184)
- Deadline: improve environment processing [\#4182](https://github.com/pypeclub/OpenPype/pull/4182)
- General: Comment per instance in Publisher [\#4178](https://github.com/pypeclub/OpenPype/pull/4178)
- Ensure Mongo database directory exists in Windows. [\#4166](https://github.com/pypeclub/OpenPype/pull/4166)
- Note about unrestricted execution on Windows. [\#4161](https://github.com/pypeclub/OpenPype/pull/4161)
- Maya: Enable thumbnail transparency on extraction. [\#4147](https://github.com/pypeclub/OpenPype/pull/4147)
- Maya: Disable viewport Pan/Zoom on playblast extraction. [\#4146](https://github.com/pypeclub/OpenPype/pull/4146)
- Maya: Optional viewport refresh on pointcache extraction [\#4144](https://github.com/pypeclub/OpenPype/pull/4144)
- CelAction: refactory integration to current openpype [\#4140](https://github.com/pypeclub/OpenPype/pull/4140)
- Maya: create and publish bounding box geometry [\#4131](https://github.com/pypeclub/OpenPype/pull/4131)
- Changed the UOpenPypePublishInstance to use the UDataAsset class [\#4124](https://github.com/pypeclub/OpenPype/pull/4124)
- General: Collection Audio speed up [\#4110](https://github.com/pypeclub/OpenPype/pull/4110)
- Maya: keep existing AOVs when creating render instance [\#4087](https://github.com/pypeclub/OpenPype/pull/4087)
- General: Oiio conversion multipart fix [\#4060](https://github.com/pypeclub/OpenPype/pull/4060)
**🐛 Bug fixes**
- Publisher: Signal type issues in Python 2 DCCs [\#4230](https://github.com/pypeclub/OpenPype/pull/4230)
- Blender: Fix Layout Family Versioning [\#4228](https://github.com/pypeclub/OpenPype/pull/4228)
- Blender: Fix Create Camera "Use selection" [\#4226](https://github.com/pypeclub/OpenPype/pull/4226)
- TrayPublisher - join needs list [\#4224](https://github.com/pypeclub/OpenPype/pull/4224)
- General: Event callbacks pass event to callbacks as expected [\#4210](https://github.com/pypeclub/OpenPype/pull/4210)
- Build:Revert .toml update of Gazu [\#4207](https://github.com/pypeclub/OpenPype/pull/4207)
- Nuke: fixed imageio node overrides subset filter [\#4202](https://github.com/pypeclub/OpenPype/pull/4202)
- Maya: pointcache [\#4201](https://github.com/pypeclub/OpenPype/pull/4201)
- Unreal: Support for Unreal Engine 5.1 [\#4199](https://github.com/pypeclub/OpenPype/pull/4199)
- General: Integrate thumbnail looks for thumbnail to multiple places [\#4181](https://github.com/pypeclub/OpenPype/pull/4181)
- Various minor bugfixes [\#4172](https://github.com/pypeclub/OpenPype/pull/4172)
- Nuke/Hiero: Remove tkinter library paths before launch [\#4171](https://github.com/pypeclub/OpenPype/pull/4171)
- Flame: vertical alignment of layers [\#4169](https://github.com/pypeclub/OpenPype/pull/4169)
- Nuke: correct detection of viewer and display [\#4165](https://github.com/pypeclub/OpenPype/pull/4165)
- Settings UI: Don't create QApplication if already exists [\#4156](https://github.com/pypeclub/OpenPype/pull/4156)
- General: Extract review handle start offset of sequences [\#4152](https://github.com/pypeclub/OpenPype/pull/4152)
- Maya: Maintain time connections on Alembic update. [\#4143](https://github.com/pypeclub/OpenPype/pull/4143)
**🔀 Refactored code**
- General: Use qtpy in modules and hosts UIs which are running in OpenPype process [\#4225](https://github.com/pypeclub/OpenPype/pull/4225)
- Tools: Use qtpy instead of Qt in standalone tools [\#4223](https://github.com/pypeclub/OpenPype/pull/4223)
- General: Use qtpy in settings UI [\#4215](https://github.com/pypeclub/OpenPype/pull/4215)
**Merged pull requests:**
- layout publish more than one container issue [\#4098](https://github.com/pypeclub/OpenPype/pull/4098)
## [3.14.8](https://github.com/pypeclub/OpenPype/tree/3.14.8)
[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.14.7...3.14.8)

View file

@ -0,0 +1,82 @@
import bpy
from openpype.hosts.blender.api import plugin
def append_workfile(context, fname, do_import):
asset = context['asset']['name']
subset = context['subset']['name']
group_name = plugin.asset_name(asset, subset)
# We need to preserve the original names of the scenes, otherwise,
# if there are duplicate names in the current workfile, the imported
# scenes will be renamed by Blender to avoid conflicts.
original_scene_names = []
with bpy.data.libraries.load(fname) as (data_from, data_to):
for attr in dir(data_to):
if attr == "scenes":
for scene in data_from.scenes:
original_scene_names.append(scene)
setattr(data_to, attr, getattr(data_from, attr))
current_scene = bpy.context.scene
for scene, s_name in zip(data_to.scenes, original_scene_names):
scene.name = f"{group_name}_{s_name}"
if do_import:
collection = bpy.data.collections.new(f"{group_name}_{s_name}")
for obj in scene.objects:
collection.objects.link(obj)
current_scene.collection.children.link(collection)
for coll in scene.collection.children:
collection.children.link(coll)
class AppendBlendLoader(plugin.AssetLoader):
"""Append workfile in Blender (unmanaged)
Warning:
The loaded content will be unmanaged and is *not* visible in the
scene inventory. It's purely intended to merge content into your scene
so you could also use it as a new base.
"""
representations = ["blend"]
families = ["*"]
label = "Append Workfile"
order = 9
icon = "arrow-circle-down"
color = "#775555"
def load(self, context, name=None, namespace=None, data=None):
append_workfile(context, self.fname, False)
# We do not containerize imported content, it remains unmanaged
return
class ImportBlendLoader(plugin.AssetLoader):
"""Import workfile in the current Blender scene (unmanaged)
Warning:
The loaded content will be unmanaged and is *not* visible in the
scene inventory. It's purely intended to merge content into your scene
so you could also use it as a new base.
"""
representations = ["blend"]
families = ["*"]
label = "Import Workfile"
order = 9
icon = "arrow-circle-down"
color = "#775555"
def load(self, context, name=None, namespace=None, data=None):
append_workfile(context, self.fname, True)
# We do not containerize imported content, it remains unmanaged
return

View file

@ -1,5 +1,5 @@
import os
from Qt import QtWidgets
from qtpy import QtWidgets
from copy import deepcopy
from pprint import pformat
from openpype.tools.utils.host_tools import HostToolsHelper

View file

@ -5,10 +5,10 @@ from copy import deepcopy
from xml.etree import ElementTree as ET
import qargparse
from Qt import QtCore, QtWidgets
from qtpy import QtCore, QtWidgets
from openpype import style
from openpype.lib import Logger
from openpype.lib import Logger, StringTemplate
from openpype.pipeline import LegacyCreator, LoaderPlugin
from openpype.settings import get_current_project_settings
@ -775,6 +775,11 @@ class OpenClipSolver(flib.MediaInfoFile):
self.feed_colorspace = feed_data.get("colorspace")
self.log.debug("feed_version_name: {}".format(self.feed_version_name))
# layer rename variables
self.layer_rename_template = feed_data["layer_rename_template"]
self.layer_rename_patterns = feed_data["layer_rename_patterns"]
self.context_data = feed_data["context_data"]
# derivate other feed variables
self.feed_basename = os.path.basename(feed_path)
self.feed_dir = os.path.dirname(feed_path)
@ -813,9 +818,11 @@ class OpenClipSolver(flib.MediaInfoFile):
def _create_new_open_clip(self):
self.log.info("Building new openClip")
self.log.debug(">> self.clip_data: {}".format(self.clip_data))
for tmp_xml_track in self.clip_data.iter("track"):
# solve track (layer) name
self._rename_track_name(tmp_xml_track)
tmp_xml_feeds = tmp_xml_track.find('feeds')
tmp_xml_feeds.set('currentVersion', self.feed_version_name)
@ -850,6 +857,48 @@ class OpenClipSolver(flib.MediaInfoFile):
if uid == track_uid:
return xml_track
def _rename_track_name(self, xml_track_data):
layer_uid = xml_track_data.get("uid")
name_obj = xml_track_data.find("name")
layer_name = name_obj.text
if (
self.layer_rename_patterns
and not any(
re.search(lp_.lower(), layer_name.lower())
for lp_ in self.layer_rename_patterns
)
):
return
formating_data = self._update_formating_data(
layerName=layer_name,
layerUID=layer_uid
)
name_obj.text = StringTemplate(
self.layer_rename_template
).format(formating_data)
def _update_formating_data(self, **kwargs):
""" Updating formating data for layer rename
Attributes:
key=value (optional): will be included to formating data
as {key: value}
Returns:
dict: anatomy context data for formating
"""
self.log.debug(">> self.clip_data: {}".format(self.clip_data))
clip_name_obj = self.clip_data.find("name")
data = {
"originalBasename": clip_name_obj.text
}
# include version context data
data.update(self.context_data)
# include input kwargs data
data.update(kwargs)
return data
def _update_open_clip(self):
self.log.info("Updating openClip ..")
@ -857,11 +906,12 @@ class OpenClipSolver(flib.MediaInfoFile):
out_xml = out_xml.getroot()
self.log.debug(">> out_xml: {}".format(out_xml))
self.log.debug(">> self.clip_data: {}".format(self.clip_data))
# loop tmp tracks
updated_any = False
for tmp_xml_track in self.clip_data.iter("track"):
# solve track (layer) name
self._rename_track_name(tmp_xml_track)
# get tmp track uid
tmp_track_uid = tmp_xml_track.get("uid")
self.log.debug(">> tmp_track_uid: {}".format(tmp_track_uid))

View file

@ -1,3 +1,4 @@
from copy import deepcopy
import os
import flame
from pprint import pformat
@ -25,6 +26,14 @@ class LoadClip(opfapi.ClipLoader):
reel_name = "Loaded"
clip_name_template = "{asset}_{subset}<_{output}>"
""" Anatomy keys from version context data and dynamically added:
- {layerName} - original layer name token
- {layerUID} - original layer UID token
- {originalBasename} - original clip name taken from file
"""
layer_rename_template = "{asset}_{subset}<_{output}>"
layer_rename_patterns = []
def load(self, context, name, namespace, options):
# get flame objects
@ -38,8 +47,16 @@ class LoadClip(opfapi.ClipLoader):
version_name = version.get("name", None)
colorspace = self.get_colorspace(context)
# in case output is not in context replace key to representation
if not context["representation"]["context"].get("output"):
self.clip_name_template = self.clip_name_template.replace(
"output", "representation")
self.layer_rename_template = self.layer_rename_template.replace(
"output", "representation")
formating_data = deepcopy(context["representation"]["context"])
clip_name = StringTemplate(self.clip_name_template).format(
context["representation"]["context"])
formating_data)
# convert colorspace with ocio to flame mapping
# in imageio flame section
@ -62,6 +79,9 @@ class LoadClip(opfapi.ClipLoader):
"path": self.fname.replace("\\", "/"),
"colorspace": colorspace,
"version": "v{:0>3}".format(version_name),
"layer_rename_template": self.layer_rename_template,
"layer_rename_patterns": self.layer_rename_patterns,
"context_data": formating_data
}
self.log.debug(pformat(
loading_context

View file

@ -25,6 +25,14 @@ class LoadClipBatch(opfapi.ClipLoader):
reel_name = "OP_LoadedReel"
clip_name_template = "{batch}_{asset}_{subset}<_{output}>"
""" Anatomy keys from version context data and dynamically added:
- {layerName} - original layer name token
- {layerUID} - original layer UID token
- {originalBasename} - original clip name taken from file
"""
layer_rename_template = "{asset}_{subset}<_{output}>"
layer_rename_patterns = []
def load(self, context, name, namespace, options):
# get flame objects
@ -39,7 +47,10 @@ class LoadClipBatch(opfapi.ClipLoader):
# in case output is not in context replace key to representation
if not context["representation"]["context"].get("output"):
self.clip_name_template.replace("output", "representation")
self.clip_name_template = self.clip_name_template.replace(
"output", "representation")
self.layer_rename_template = self.layer_rename_template.replace(
"output", "representation")
formating_data = deepcopy(context["representation"]["context"])
formating_data["batch"] = self.batch.name.get_value()
@ -69,6 +80,9 @@ class LoadClipBatch(opfapi.ClipLoader):
"path": self.fname.replace("\\", "/"),
"colorspace": colorspace,
"version": "v{:0>3}".format(version_name),
"layer_rename_template": self.layer_rename_template,
"layer_rename_patterns": self.layer_rename_patterns,
"context_data": formating_data
}
self.log.debug(pformat(
loading_context

View file

@ -1,4 +1,4 @@
from Qt import QtWidgets, QtCore
from qtpy import QtWidgets, QtCore
import uiwidgets
import app_utils

View file

@ -1,4 +1,4 @@
from Qt import QtWidgets, QtCore
from qtpy import QtWidgets, QtCore
class FlameLabel(QtWidgets.QLabel):

View file

@ -1,6 +1,6 @@
from __future__ import print_function
import sys
from Qt import QtWidgets
from qtpy import QtWidgets
from pprint import pformat
import atexit

View file

@ -1,7 +1,7 @@
import logging
from scriptsmenu import scriptsmenu
from Qt import QtWidgets
from qtpy import QtWidgets
log = logging.getLogger(__name__)

View file

@ -15,7 +15,11 @@ import secrets
import shutil
import hiero
from Qt import QtWidgets, QtCore, QtXml
from qtpy import QtWidgets, QtCore
try:
from PySide import QtXml
except ImportError:
from PySide2 import QtXml
from openpype.client import get_project
from openpype.settings import get_project_settings

View file

@ -43,7 +43,7 @@ def menu_install():
"""
from Qt import QtGui
from qtpy import QtGui
from . import (
publish, launch_workfiles_app, reload_config,
apply_colorspace_project, apply_colorspace_clips

View file

@ -5,7 +5,7 @@ from copy import deepcopy
import hiero
from Qt import QtWidgets, QtCore
from qtpy import QtWidgets, QtCore
import qargparse
from openpype.settings import get_current_project_settings

View file

@ -3,7 +3,7 @@ import tempfile
from pprint import pformat
import pyblish.api
from Qt.QtGui import QPixmap
from qtpy.QtGui import QPixmap
import hiero.ui

View file

@ -10,7 +10,7 @@ from collections import OrderedDict
import clique
import nuke
from Qt import QtCore, QtWidgets
from qtpy import QtCore, QtWidgets
from openpype.client import (
get_project,
@ -81,7 +81,6 @@ class Context:
def get_main_window():
"""Acquire Nuke's main window"""
if Context.main_window is None:
from Qt import QtWidgets
top_widgets = QtWidgets.QApplication.topLevelWidgets()
name = "Foundry::UI::DockMainWindow"
@ -611,7 +610,10 @@ def get_created_node_imageio_setting_legacy(nodeclass, creator, subset):
if (
onode["subsets"]
and not any(re.search(s, subset) for s in onode["subsets"])
and not any(
re.search(s.lower(), subset.lower())
for s in onode["subsets"]
)
):
continue
@ -694,7 +696,8 @@ def get_imageio_node_override_setting(
# find matching override node
override_imageio_node = None
for onode in override_nodes:
log.info(onode)
log.debug("__ onode: {}".format(onode))
log.debug("__ subset: {}".format(subset))
if node_class not in onode["nukeNodeClass"]:
continue
@ -703,7 +706,10 @@ def get_imageio_node_override_setting(
if (
onode["subsets"]
and not any(re.search(s, subset) for s in onode["subsets"])
and not any(
re.search(s.lower(), subset.lower())
for s in onode["subsets"]
)
):
continue

View file

@ -786,23 +786,15 @@ class ModulesManager:
).format(expected_keys, " | ".join(msg_items)))
return output
def collect_creator_plugin_paths(self, host_name):
"""Helper to collect creator plugin paths from modules.
Args:
host_name (str): For which host are creators meants.
Returns:
list: List of creator plugin paths.
"""
# Output structure
def _collect_plugin_paths(self, method_name, *args, **kwargs):
output = []
for module in self.get_enabled_modules():
# Skip module that do not inherit from `IPluginPaths`
if not isinstance(module, IPluginPaths):
continue
paths = module.get_creator_plugin_paths(host_name)
method = getattr(module, method_name)
paths = method(*args, **kwargs)
if paths:
# Convert to list if value is not list
if not isinstance(paths, (list, tuple, set)):
@ -810,6 +802,53 @@ class ModulesManager:
output.extend(paths)
return output
def collect_create_plugin_paths(self, host_name):
"""Helper to collect creator plugin paths from modules.
Args:
host_name (str): For which host are creators meant.
Returns:
list: List of creator plugin paths.
"""
return self._collect_plugin_paths(
"get_create_plugin_paths",
host_name
)
collect_creator_plugin_paths = collect_create_plugin_paths
def collect_load_plugin_paths(self, host_name):
"""Helper to collect load plugin paths from modules.
Args:
host_name (str): For which host are load plugins meant.
Returns:
list: List of load plugin paths.
"""
return self._collect_plugin_paths(
"get_load_plugin_paths",
host_name
)
def collect_publish_plugin_paths(self, host_name):
"""Helper to collect load plugin paths from modules.
Args:
host_name (str): For which host are load plugins meant.
Returns:
list: List of pyblish plugin paths.
"""
return self._collect_plugin_paths(
"get_publish_plugin_paths",
host_name
)
def get_host_module(self, host_name):
"""Find host module by host name.

View file

@ -188,7 +188,6 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline):
# Adding file dependencies.
if self.asset_dependencies:
dependencies = instance.context.data["fileDependencies"]
dependencies.append(context.data["currentFile"])
for dependency in dependencies:
job_info.AssetDependency += dependency
@ -299,7 +298,7 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline):
# Add export job as dependency --------------------------------------
if export_job:
job_info, _ = payload
job_info.JobDependency = export_job
job_info.JobDependencies = export_job
if instance.data.get("tileRendering"):
# Prepare tiles data
@ -436,7 +435,7 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline):
frame_assembly_job_info.ExtraInfo[0] = file_hash
frame_assembly_job_info.ExtraInfo[1] = file
frame_assembly_job_info.JobDependency = tile_job_id
frame_assembly_job_info.JobDependencies = tile_job_id
# write assembly job config files
now = datetime.now()

View file

@ -24,7 +24,7 @@ class OpenPypeInterface:
Child classes of OpenPypeInterface may be used as mixin in different
OpenPype modules which means they have to have implemented methods defined
in the interface. By default interface does not have any abstract parts.
in the interface. By default, interface does not have any abstract parts.
"""
pass
@ -44,40 +44,78 @@ class IPluginPaths(OpenPypeInterface):
def get_plugin_paths(self):
pass
def get_creator_plugin_paths(self, host_name):
"""Retreive creator plugin paths.
def _get_plugin_paths_by_type(self, plugin_type):
paths = self.get_plugin_paths()
if not paths or plugin_type not in paths:
return []
Give addons ability to add creator plugin paths based on host name.
paths = paths[plugin_type]
if not paths:
return []
NOTES:
- Default implementation uses 'get_plugin_paths' and always return
all creator plugins.
- Host name may help to organize plugins by host, but each creator
alsomay have host filtering.
if not isinstance(paths, (list, tuple, set)):
paths = [paths]
return paths
def get_create_plugin_paths(self, host_name):
"""Receive create plugin paths.
Give addons ability to add create plugin paths based on host name.
Notes:
Default implementation uses 'get_plugin_paths' and always return
all create plugin paths.
Args:
host_name (str): For which host are the plugins meant.
"""
paths = self.get_plugin_paths()
if not paths or "create" not in paths:
return []
if hasattr(self, "get_creator_plugin_paths"):
# TODO remove in 3.16
self.log.warning((
"DEPRECATION WARNING: Using method 'get_creator_plugin_paths'"
" which was renamed to 'get_create_plugin_paths'."
))
return self.get_creator_plugin_paths(host_name)
return self._get_plugin_paths_by_type("create")
create_paths = paths["create"]
if not create_paths:
return []
def get_load_plugin_paths(self, host_name):
"""Receive load plugin paths.
if not isinstance(create_paths, (list, tuple, set)):
create_paths = [create_paths]
return create_paths
Give addons ability to add load plugin paths based on host name.
Notes:
Default implementation uses 'get_plugin_paths' and always return
all load plugin paths.
Args:
host_name (str): For which host are the plugins meant.
"""
return self._get_plugin_paths_by_type("load")
def get_publish_plugin_paths(self, host_name):
"""Receive publish plugin paths.
Give addons ability to add publish plugin paths based on host name.
Notes:
Default implementation uses 'get_plugin_paths' and always return
all publish plugin paths.
Args:
host_name (str): For which host are the plugins meant.
"""
return self._get_plugin_paths_by_type("publish")
class ILaunchHookPaths(OpenPypeInterface):
"""Module has launch hook paths to return.
Modules does not have to inherit from this interface (changed 8.11.2022).
Module just have to have implemented 'get_launch_hook_paths' to be able use
the advantage.
Modules don't have to inherit from this interface (changed 8.11.2022).
Module just have to have implemented 'get_launch_hook_paths' to be able to
use the advantage.
Expected result is list of paths.
["path/to/launch_hooks_dir"]

View file

@ -158,17 +158,24 @@ 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 = _get_modules_manager()
publish_plugin_dirs = modules_manager.collect_plugin_paths()["publish"]
for path in publish_plugin_dirs:
pyblish.api.register_plugin_path(path)
if host_name is None:
host_name = os.environ.get("AVALON_APP")
creator_paths = modules_manager.collect_creator_plugin_paths(host_name)
for creator_path in creator_paths:
register_creator_plugin_path(creator_path)
modules_manager = _get_modules_manager()
publish_plugin_dirs = modules_manager.collect_publish_plugin_paths(
host_name)
for path in publish_plugin_dirs:
pyblish.api.register_plugin_path(path)
create_plugin_paths = modules_manager.collect_create_plugin_paths(
host_name)
for path in create_plugin_paths:
register_creator_plugin_path(path)
load_plugin_paths = modules_manager.collect_load_plugin_paths(
host_name)
for path in load_plugin_paths:
register_loader_plugin_path(path)
if project_name is None:
project_name = os.environ.get("AVALON_PROJECT")

View file

@ -119,7 +119,12 @@
],
"reel_group_name": "OpenPype_Reels",
"reel_name": "Loaded",
"clip_name_template": "{asset}_{subset}<_{output}>"
"clip_name_template": "{asset}_{subset}<_{output}>",
"layer_rename_template": "{asset}_{subset}<_{output}>",
"layer_rename_patterns": [
"rgb",
"rgba"
]
},
"LoadClipBatch": {
"enabled": true,
@ -142,7 +147,12 @@
"exr16fpdwaa"
],
"reel_name": "OP_LoadedReel",
"clip_name_template": "{batch}_{asset}_{subset}<_{output}>"
"clip_name_template": "{batch}_{asset}_{subset}<_{output}>",
"layer_rename_template": "{asset}_{subset}<_{output}>",
"layer_rename_patterns": [
"rgb",
"rgba"
]
}
}
}

View file

@ -512,6 +512,17 @@
"type": "text",
"key": "clip_name_template",
"label": "Clip name template"
},
{
"type": "text",
"key": "layer_rename_template",
"label": "Layer name template"
},
{
"type": "list",
"key": "layer_rename_patterns",
"label": "Layer rename patters",
"object_type": "text"
}
]
},
@ -554,6 +565,17 @@
"type": "text",
"key": "clip_name_template",
"label": "Clip name template"
},
{
"type": "text",
"key": "layer_rename_template",
"label": "Layer name template"
},
{
"type": "list",
"key": "layer_rename_patterns",
"label": "Layer rename patters",
"object_type": "text"
}
]
}

View file

@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
"""Package declaring Pype version."""
__version__ = "3.14.9-nightly.4"
__version__ = "3.14.10-nightly.1"