diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 132e960885..2e854061d5 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -35,6 +35,7 @@ body:
label: Version
description: What version are you running? Look to OpenPype Tray
options:
+ - 3.18.3-nightly.1
- 3.18.2
- 3.18.2-nightly.6
- 3.18.2-nightly.5
@@ -134,7 +135,6 @@ body:
- 3.15.6-nightly.3
- 3.15.6-nightly.2
- 3.15.6-nightly.1
- - 3.15.5
validations:
required: true
- type: dropdown
diff --git a/openpype/hosts/houdini/plugins/create/create_redshift_rop.py b/openpype/hosts/houdini/plugins/create/create_redshift_rop.py
index 1b8826a932..9d1c7bc90d 100644
--- a/openpype/hosts/houdini/plugins/create/create_redshift_rop.py
+++ b/openpype/hosts/houdini/plugins/create/create_redshift_rop.py
@@ -15,6 +15,9 @@ class CreateRedshiftROP(plugin.HoudiniCreator):
icon = "magic"
ext = "exr"
+ # Default to split export and render jobs
+ split_render = True
+
def create(self, subset_name, instance_data, pre_create_data):
instance_data.pop("active", None)
@@ -36,12 +39,15 @@ class CreateRedshiftROP(plugin.HoudiniCreator):
# Also create the linked Redshift IPR Rop
try:
ipr_rop = instance_node.parent().createNode(
- "Redshift_IPR", node_name=basename + "_IPR"
+ "Redshift_IPR", node_name=f"{basename}_IPR"
)
- except hou.OperationFailed:
+ except hou.OperationFailed as e:
raise plugin.OpenPypeCreatorError(
- ("Cannot create Redshift node. Is Redshift "
- "installed and enabled?"))
+ (
+ "Cannot create Redshift node. Is Redshift "
+ "installed and enabled?"
+ )
+ ) from e
# Move it to directly under the Redshift ROP
ipr_rop.setPosition(instance_node.position() + hou.Vector2(0, -1))
@@ -74,8 +80,15 @@ class CreateRedshiftROP(plugin.HoudiniCreator):
for node in self.selected_nodes:
if node.type().name() == "cam":
camera = node.path()
- parms.update({
- "RS_renderCamera": camera or ""})
+ parms["RS_renderCamera"] = camera or ""
+
+ export_dir = hou.text.expandString("$HIP/pyblish/rs/")
+ rs_filepath = f"{export_dir}{subset_name}/{subset_name}.$F4.rs"
+ parms["RS_archive_file"] = rs_filepath
+
+ if pre_create_data.get("split_render", self.split_render):
+ parms["RS_archive_enable"] = 1
+
instance_node.setParms(parms)
# Lock some Avalon attributes
@@ -102,6 +115,9 @@ class CreateRedshiftROP(plugin.HoudiniCreator):
BoolDef("farm",
label="Submitting to Farm",
default=True),
+ BoolDef("split_render",
+ label="Split export and render jobs",
+ default=self.split_render),
EnumDef("image_format",
image_format_enum,
default=self.ext,
diff --git a/openpype/hosts/houdini/plugins/publish/collect_redshift_rop.py b/openpype/hosts/houdini/plugins/publish/collect_redshift_rop.py
index 0acddab011..aec7e07fbc 100644
--- a/openpype/hosts/houdini/plugins/publish/collect_redshift_rop.py
+++ b/openpype/hosts/houdini/plugins/publish/collect_redshift_rop.py
@@ -31,7 +31,6 @@ class CollectRedshiftROPRenderProducts(pyblish.api.InstancePlugin):
families = ["redshift_rop"]
def process(self, instance):
-
rop = hou.node(instance.data.get("instance_node"))
# Collect chunkSize
@@ -43,13 +42,29 @@ class CollectRedshiftROPRenderProducts(pyblish.api.InstancePlugin):
default_prefix = evalParmNoFrame(rop, "RS_outputFileNamePrefix")
beauty_suffix = rop.evalParm("RS_outputBeautyAOVSuffix")
- render_products = []
+ # Store whether we are splitting the render job (export + render)
+ split_render = bool(rop.parm("RS_archive_enable").eval())
+ instance.data["splitRender"] = split_render
+ export_products = []
+ if split_render:
+ export_prefix = evalParmNoFrame(
+ rop, "RS_archive_file", pad_character="0"
+ )
+ beauty_export_product = self.get_render_product_name(
+ prefix=export_prefix,
+ suffix=None)
+ export_products.append(beauty_export_product)
+ self.log.debug(
+ "Found export product: {}".format(beauty_export_product)
+ )
+ instance.data["ifdFile"] = beauty_export_product
+ instance.data["exportFiles"] = list(export_products)
# Default beauty AOV
beauty_product = self.get_render_product_name(
prefix=default_prefix, suffix=beauty_suffix
)
- render_products.append(beauty_product)
+ render_products = [beauty_product]
files_by_aov = {
"_": self.generate_expected_files(instance,
beauty_product)}
@@ -59,11 +74,11 @@ class CollectRedshiftROPRenderProducts(pyblish.api.InstancePlugin):
i = index + 1
# Skip disabled AOVs
- if not rop.evalParm("RS_aovEnable_%s" % i):
+ if not rop.evalParm(f"RS_aovEnable_{i}"):
continue
- aov_suffix = rop.evalParm("RS_aovSuffix_%s" % i)
- aov_prefix = evalParmNoFrame(rop, "RS_aovCustomPrefix_%s" % i)
+ aov_suffix = rop.evalParm(f"RS_aovSuffix_{i}")
+ aov_prefix = evalParmNoFrame(rop, f"RS_aovCustomPrefix_{i}")
if not aov_prefix:
aov_prefix = default_prefix
@@ -85,7 +100,7 @@ class CollectRedshiftROPRenderProducts(pyblish.api.InstancePlugin):
instance.data["attachTo"] = [] # stub required data
if "expectedFiles" not in instance.data:
- instance.data["expectedFiles"] = list()
+ instance.data["expectedFiles"] = []
instance.data["expectedFiles"].append(files_by_aov)
# update the colorspace data
diff --git a/openpype/hosts/maya/plugins/load/load_redshift_proxy.py b/openpype/hosts/maya/plugins/load/load_redshift_proxy.py
index b3fbfb2ed9..40385f34d6 100644
--- a/openpype/hosts/maya/plugins/load/load_redshift_proxy.py
+++ b/openpype/hosts/maya/plugins/load/load_redshift_proxy.py
@@ -137,6 +137,11 @@ class RedshiftProxyLoader(load.LoaderPlugin):
cmds.connectAttr("{}.outMesh".format(rs_mesh),
"{}.inMesh".format(mesh_shape))
+ # TODO: use the assigned shading group as shaders if existed
+ # assign default shader to redshift proxy
+ if cmds.ls("initialShadingGroup", type="shadingEngine"):
+ cmds.sets(mesh_shape, forceElement="initialShadingGroup")
+
group_node = cmds.group(empty=True, name="{}_GRP".format(name))
mesh_transform = cmds.listRelatives(mesh_shape,
parent=True, fullPath=True)
diff --git a/openpype/modules/deadline/plugins/publish/collect_pools.py b/openpype/modules/deadline/plugins/publish/collect_pools.py
index a25b149f11..9ee079b892 100644
--- a/openpype/modules/deadline/plugins/publish/collect_pools.py
+++ b/openpype/modules/deadline/plugins/publish/collect_pools.py
@@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
-"""Collect Deadline pools. Choose default one from Settings
-
-"""
import pyblish.api
from openpype.lib import TextDef
from openpype.pipeline.publish import OpenPypePyblishPluginMixin
@@ -9,11 +6,35 @@ from openpype.pipeline.publish import OpenPypePyblishPluginMixin
class CollectDeadlinePools(pyblish.api.InstancePlugin,
OpenPypePyblishPluginMixin):
- """Collect pools from instance if present, from Setting otherwise."""
+ """Collect pools from instance or Publisher attributes, from Setting
+ otherwise.
+
+ Pools are used to control which DL workers could render the job.
+
+ Pools might be set:
+ - directly on the instance (set directly in DCC)
+ - from Publisher attributes
+ - from defaults from Settings.
+
+ Publisher attributes could be shown even for instances that should be
+ rendered locally as visibility is driven by product type of the instance
+ (which will be `render` most likely).
+ (Might be resolved in the future and class attribute 'families' should
+ be cleaned up.)
+
+ """
order = pyblish.api.CollectorOrder + 0.420
label = "Collect Deadline Pools"
- families = ["rendering",
+ hosts = ["aftereffects",
+ "fusion",
+ "harmony"
+ "nuke",
+ "maya",
+ "max"]
+
+ families = ["render",
+ "rendering",
"render.farm",
"renderFarm",
"renderlayer",
@@ -30,7 +51,6 @@ class CollectDeadlinePools(pyblish.api.InstancePlugin,
cls.secondary_pool = settings.get("secondary_pool", None)
def process(self, instance):
-
attr_values = self.get_attr_values_from_data(instance.data)
if not instance.data.get("primaryPool"):
instance.data["primaryPool"] = (
@@ -60,8 +80,12 @@ class CollectDeadlinePools(pyblish.api.InstancePlugin,
return [
TextDef("primaryPool",
label="Primary Pool",
- default=cls.primary_pool),
+ default=cls.primary_pool,
+ tooltip="Deadline primary pool, "
+ "applicable for farm rendering"),
TextDef("secondaryPool",
label="Secondary Pool",
- default=cls.secondary_pool)
+ default=cls.secondary_pool,
+ tooltip="Deadline secondary pool, "
+ "applicable for farm rendering")
]
diff --git a/openpype/modules/deadline/plugins/publish/submit_houdini_render_deadline.py b/openpype/modules/deadline/plugins/publish/submit_houdini_render_deadline.py
index c8960185b2..bf7fb45a8b 100644
--- a/openpype/modules/deadline/plugins/publish/submit_houdini_render_deadline.py
+++ b/openpype/modules/deadline/plugins/publish/submit_houdini_render_deadline.py
@@ -15,6 +15,7 @@ from openpype.lib import (
NumberDef
)
+
@attr.s
class DeadlinePluginInfo():
SceneFile = attr.ib(default=None)
@@ -41,6 +42,12 @@ class VrayRenderPluginInfo():
SeparateFilesPerFrame = attr.ib(default=True)
+@attr.s
+class RedshiftRenderPluginInfo():
+ SceneFile = attr.ib(default=None)
+ Version = attr.ib(default=None)
+
+
class HoudiniSubmitDeadline(
abstract_submit_deadline.AbstractSubmitDeadline,
OpenPypePyblishPluginMixin
@@ -262,6 +269,25 @@ class HoudiniSubmitDeadline(
plugin_info = VrayRenderPluginInfo(
InputFilename=instance.data["ifdFile"],
)
+ elif family == "redshift_rop":
+ plugin_info = RedshiftRenderPluginInfo(
+ SceneFile=instance.data["ifdFile"]
+ )
+ # Note: To use different versions of Redshift on Deadline
+ # set the `REDSHIFT_VERSION` env variable in the Tools
+ # settings in the AYON Application plugin. You will also
+ # need to set that version in `Redshift.param` file
+ # of the Redshift Deadline plugin:
+ # [Redshift_Executable_*]
+ # where * is the version number.
+ if os.getenv("REDSHIFT_VERSION"):
+ plugin_info.Version = os.getenv("REDSHIFT_VERSION")
+ else:
+ self.log.warning((
+ "REDSHIFT_VERSION env variable is not set"
+ " - using version configured in Deadline"
+ ))
+
else:
self.log.error(
"Family '%s' not supported yet to split render job",
diff --git a/openpype/pipeline/publish/lib.py b/openpype/pipeline/publish/lib.py
index 4ea2f932f1..40cb94e2bf 100644
--- a/openpype/pipeline/publish/lib.py
+++ b/openpype/pipeline/publish/lib.py
@@ -58,41 +58,13 @@ def get_template_name_profiles(
if not project_settings:
project_settings = get_project_settings(project_name)
- profiles = (
+ return copy.deepcopy(
project_settings
["global"]
["tools"]
["publish"]
["template_name_profiles"]
)
- if profiles:
- return copy.deepcopy(profiles)
-
- # Use legacy approach for cases new settings are not filled yet for the
- # project
- legacy_profiles = (
- project_settings
- ["global"]
- ["publish"]
- ["IntegrateAssetNew"]
- ["template_name_profiles"]
- )
- if legacy_profiles:
- if not logger:
- logger = Logger.get_logger("get_template_name_profiles")
-
- logger.warning((
- "Project \"{}\" is using legacy access to publish template."
- " It is recommended to move settings to new location"
- " 'project_settings/global/tools/publish/template_name_profiles'."
- ).format(project_name))
-
- # Replace "tasks" key with "task_names"
- profiles = []
- for profile in copy.deepcopy(legacy_profiles):
- profile["task_names"] = profile.pop("tasks", [])
- profiles.append(profile)
- return profiles
def get_hero_template_name_profiles(
@@ -121,36 +93,13 @@ def get_hero_template_name_profiles(
if not project_settings:
project_settings = get_project_settings(project_name)
- profiles = (
+ return copy.deepcopy(
project_settings
["global"]
["tools"]
["publish"]
["hero_template_name_profiles"]
)
- if profiles:
- return copy.deepcopy(profiles)
-
- # Use legacy approach for cases new settings are not filled yet for the
- # project
- legacy_profiles = copy.deepcopy(
- project_settings
- ["global"]
- ["publish"]
- ["IntegrateHeroVersion"]
- ["template_name_profiles"]
- )
- if legacy_profiles:
- if not logger:
- logger = Logger.get_logger("get_hero_template_name_profiles")
-
- logger.warning((
- "Project \"{}\" is using legacy access to hero publish template."
- " It is recommended to move settings to new location"
- " 'project_settings/global/tools/publish/"
- "hero_template_name_profiles'."
- ).format(project_name))
- return legacy_profiles
def get_publish_template_name(
diff --git a/openpype/plugins/publish/integrate_hero_version.py b/openpype/plugins/publish/integrate_hero_version.py
index 9f0f7fe7f3..59dc6b5c64 100644
--- a/openpype/plugins/publish/integrate_hero_version.py
+++ b/openpype/plugins/publish/integrate_hero_version.py
@@ -54,7 +54,6 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
# permissions error on files (files were used or user didn't have perms)
# *but all other plugins must be sucessfully completed
- template_name_profiles = []
_default_template_name = "hero"
def process(self, instance):
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json
index ac2d9e190d..64f292a140 100644
--- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json
+++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json
@@ -1023,49 +1023,6 @@
{
"type": "label",
"label": "NOTE: Hero publish template profiles settings were moved to Tools/Publish/Hero template name profiles. Please move values there."
- },
- {
- "type": "list",
- "key": "template_name_profiles",
- "label": "Template name profiles (DEPRECATED)",
- "use_label_wrap": true,
- "object_type": {
- "type": "dict",
- "children": [
- {
- "key": "families",
- "label": "Families",
- "type": "list",
- "object_type": "text"
- },
- {
- "type": "hosts-enum",
- "key": "hosts",
- "label": "Hosts",
- "multiselection": true
- },
- {
- "key": "task_types",
- "label": "Task types",
- "type": "task-types-enum"
- },
- {
- "key": "task_names",
- "label": "Task names",
- "type": "list",
- "object_type": "text"
- },
- {
- "type": "separator"
- },
- {
- "type": "text",
- "key": "template_name",
- "label": "Template name",
- "tooltip": "Name of template from Anatomy templates"
- }
- ]
- }
}
]
},
diff --git a/pyproject.toml b/pyproject.toml
index 38236f88bc..ee8e8017e3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -181,3 +181,8 @@ reportMissingTypeStubs = false
[tool.poetry.extras]
docs = ["Sphinx", "furo", "sphinxcontrib-napoleon"]
+
+[tool.pydocstyle]
+inherit = false
+convetion = "google"
+match = "(?!test_).*\\.py"
diff --git a/server_addon/core/server/settings/publish_plugins.py b/server_addon/core/server/settings/publish_plugins.py
index ef52416369..0c9b9c96ef 100644
--- a/server_addon/core/server/settings/publish_plugins.py
+++ b/server_addon/core/server/settings/publish_plugins.py
@@ -697,13 +697,6 @@ class IntegrateHeroVersionModel(BaseSettingsModel):
optional: bool = Field(False, title="Optional")
active: bool = Field(True, title="Active")
families: list[str] = Field(default_factory=list, title="Families")
- # TODO remove when removed from client code
- template_name_profiles: list[IntegrateHeroTemplateNameProfileModel] = (
- Field(
- default_factory=list,
- title="Template name profiles"
- )
- )
class CleanUpModel(BaseSettingsModel):
@@ -1049,19 +1042,6 @@ DEFAULT_PUBLISH_VALUES = {
"layout",
"mayaScene",
"simpleUnrealTexture"
- ],
- "template_name_profiles": [
- {
- "product_types": [
- "simpleUnrealTexture"
- ],
- "hosts": [
- "standalonepublisher"
- ],
- "task_types": [],
- "task_names": [],
- "template_name": "simpleUnrealTextureHero"
- }
]
},
"CleanUp": {
diff --git a/server_addon/deadline/server/version.py b/server_addon/deadline/server/version.py
index 1276d0254f..0a8da88258 100644
--- a/server_addon/deadline/server/version.py
+++ b/server_addon/deadline/server/version.py
@@ -1 +1 @@
-__version__ = "0.1.5"
+__version__ = "0.1.6"
diff --git a/server_addon/houdini/server/version.py b/server_addon/houdini/server/version.py
index 6232f7ab18..5635676f6b 100644
--- a/server_addon/houdini/server/version.py
+++ b/server_addon/houdini/server/version.py
@@ -1 +1 @@
-__version__ = "0.2.10"
+__version__ = "0.2.11"
diff --git a/setup.cfg b/setup.cfg
index ead9b25164..f0f754fb24 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -16,10 +16,6 @@ max-complexity = 30
[pylint.'MESSAGES CONTROL']
disable = no-member
-[pydocstyle]
-convention = google
-ignore = D107
-
[coverage:run]
branch = True
omit = /tests