mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-02 00:44:52 +01:00
Merge branch 'bugfix/OP-2513_Houdini-Camera-Loader-fix-mismatch-for-Maya-cameras-render-gates-using-aspect-ratio' of https://github.com/ynput/OpenPype into bugfix/OP-2513_Houdini-Camera-Loader-fix-mismatch-for-Maya-cameras-render-gates-using-aspect-ratio
This commit is contained in:
commit
613498894b
70 changed files with 542 additions and 293 deletions
|
|
@ -663,10 +663,13 @@ def convert_v4_representation_to_v3(representation):
|
|||
if isinstance(context, six.string_types):
|
||||
context = json.loads(context)
|
||||
|
||||
if "folder" in context:
|
||||
_c_folder = context.pop("folder")
|
||||
if "asset" not in context and "folder" in context:
|
||||
_c_folder = context["folder"]
|
||||
context["asset"] = _c_folder["name"]
|
||||
|
||||
elif "asset" in context and "folder" not in context:
|
||||
context["folder"] = {"name": context["asset"]}
|
||||
|
||||
if "product" in context:
|
||||
_c_product = context.pop("product")
|
||||
context["family"] = _c_product["type"]
|
||||
|
|
@ -959,9 +962,11 @@ def convert_create_representation_to_v4(representation, con):
|
|||
converted_representation["files"] = new_files
|
||||
|
||||
context = representation["context"]
|
||||
context["folder"] = {
|
||||
"name": context.pop("asset", None)
|
||||
}
|
||||
if "folder" not in context:
|
||||
context["folder"] = {
|
||||
"name": context.get("asset")
|
||||
}
|
||||
|
||||
context["product"] = {
|
||||
"type": context.pop("family", None),
|
||||
"name": context.pop("subset", None),
|
||||
|
|
@ -1285,7 +1290,7 @@ def convert_update_representation_to_v4(
|
|||
|
||||
if "context" in update_data:
|
||||
context = update_data["context"]
|
||||
if "asset" in context:
|
||||
if "folder" not in context and "asset" in context:
|
||||
context["folder"] = {"name": context.pop("asset")}
|
||||
|
||||
if "family" in context or "subset" in context:
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ class BlendLoader(plugin.AssetLoader):
|
|||
context: Full parenthood of representation to load
|
||||
options: Additional settings dictionary
|
||||
"""
|
||||
libpath = self.fname
|
||||
libpath = self.filepath_from_context(context)
|
||||
asset = context["asset"]["name"]
|
||||
subset = context["subset"]["name"]
|
||||
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ class AbcCameraLoader(plugin.AssetLoader):
|
|||
asset_group = bpy.data.objects.new(group_name, object_data=None)
|
||||
avalon_container.objects.link(asset_group)
|
||||
|
||||
objects = self._process(libpath, asset_group, group_name)
|
||||
self._process(libpath, asset_group, group_name)
|
||||
|
||||
objects = []
|
||||
nodes = list(asset_group.children)
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ class FbxCameraLoader(plugin.AssetLoader):
|
|||
asset_group = bpy.data.objects.new(group_name, object_data=None)
|
||||
avalon_container.objects.link(asset_group)
|
||||
|
||||
objects = self._process(libpath, asset_group, group_name)
|
||||
self._process(libpath, asset_group, group_name)
|
||||
|
||||
objects = []
|
||||
nodes = list(asset_group.children)
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@ class ExtractABC(publish.Extractor):
|
|||
filename = f"{instance.name}.abc"
|
||||
filepath = os.path.join(stagingdir, filename)
|
||||
|
||||
context = bpy.context
|
||||
|
||||
# Perform extraction
|
||||
self.log.info("Performing extraction..")
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ class ExtractAnimationABC(publish.Extractor):
|
|||
filename = f"{instance.name}.abc"
|
||||
filepath = os.path.join(stagingdir, filename)
|
||||
|
||||
context = bpy.context
|
||||
|
||||
# Perform extraction
|
||||
self.log.info("Performing extraction..")
|
||||
|
||||
|
|
|
|||
|
|
@ -21,16 +21,11 @@ class ExtractCameraABC(publish.Extractor):
|
|||
filename = f"{instance.name}.abc"
|
||||
filepath = os.path.join(stagingdir, filename)
|
||||
|
||||
context = bpy.context
|
||||
|
||||
# Perform extraction
|
||||
self.log.info("Performing extraction..")
|
||||
|
||||
plugin.deselect_all()
|
||||
|
||||
selected = []
|
||||
active = None
|
||||
|
||||
asset_group = None
|
||||
for obj in instance:
|
||||
if obj.get(AVALON_PROPERTY):
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ class LoadClip(opfapi.ClipLoader):
|
|||
self.fpd = fproject.current_workspace.desktop
|
||||
|
||||
# load clip to timeline and get main variables
|
||||
namespace = namespace
|
||||
version = context['version']
|
||||
version_data = version.get("data", {})
|
||||
version_name = version.get("name", None)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ class LoadClipBatch(opfapi.ClipLoader):
|
|||
self.batch = options.get("batch") or flame.batch
|
||||
|
||||
# load clip to timeline and get main variables
|
||||
namespace = namespace
|
||||
version = context['version']
|
||||
version_data = version.get("data", {})
|
||||
version_name = version.get("name", None)
|
||||
|
|
|
|||
|
|
@ -325,7 +325,6 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin):
|
|||
def _create_shot_instance(self, context, clip_name, **data):
|
||||
master_layer = data.get("heroTrack")
|
||||
hierarchy_data = data.get("hierarchyData")
|
||||
asset = data.get("asset")
|
||||
|
||||
if not master_layer:
|
||||
return
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ class TemplateLoader(load.LoaderPlugin):
|
|||
node = harmony.find_node_by_name(node_name, "GROUP")
|
||||
self_name = self.__class__.__name__
|
||||
|
||||
update_and_replace = False
|
||||
if is_representation_from_latest(representation):
|
||||
self._set_green(node)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -317,20 +317,6 @@ class Spacer(QtWidgets.QWidget):
|
|||
self.setLayout(layout)
|
||||
|
||||
|
||||
def get_reference_node_parents(ref):
|
||||
"""Return all parent reference nodes of reference node
|
||||
|
||||
Args:
|
||||
ref (str): reference node.
|
||||
|
||||
Returns:
|
||||
list: The upstream parent reference nodes.
|
||||
|
||||
"""
|
||||
parents = []
|
||||
return parents
|
||||
|
||||
|
||||
class SequenceLoader(LoaderPlugin):
|
||||
"""A basic SequenceLoader for Resolve
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ class CollectClipEffects(pyblish.api.InstancePlugin):
|
|||
if review and review_track_index == _track_index:
|
||||
continue
|
||||
for sitem in sub_track_items:
|
||||
effect = None
|
||||
# make sure this subtrack item is relative of track item
|
||||
if ((track_item not in sitem.linkedItems())
|
||||
and (len(sitem.linkedItems()) > 0)):
|
||||
|
|
@ -53,7 +52,6 @@ class CollectClipEffects(pyblish.api.InstancePlugin):
|
|||
continue
|
||||
|
||||
effect = self.add_effect(_track_index, sitem)
|
||||
|
||||
if effect:
|
||||
effects.update(effect)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import attr
|
||||
import hou
|
||||
from openpype.hosts.houdini.api.lib import get_color_management_preferences
|
||||
|
||||
from openpype.pipeline.colorspace import get_display_view_colorspace_name
|
||||
|
||||
@attr.s
|
||||
class LayerMetadata(object):
|
||||
|
|
@ -54,3 +54,16 @@ class ARenderProduct(object):
|
|||
)
|
||||
]
|
||||
return colorspace_data
|
||||
|
||||
|
||||
def get_default_display_view_colorspace():
|
||||
"""Returns the colorspace attribute of the default (display, view) pair.
|
||||
|
||||
It's used for 'ociocolorspace' parm in OpenGL Node."""
|
||||
|
||||
prefs = get_color_management_preferences()
|
||||
return get_display_view_colorspace_name(
|
||||
config_path=prefs["config"],
|
||||
display=prefs["display"],
|
||||
view=prefs["view"]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
from openpype.hosts.houdini.api import plugin
|
||||
from openpype.lib import EnumDef, BoolDef, NumberDef
|
||||
|
||||
import os
|
||||
import hou
|
||||
|
||||
|
||||
class CreateReview(plugin.HoudiniCreator):
|
||||
"""Review with OpenGL ROP"""
|
||||
|
|
@ -13,7 +16,6 @@ class CreateReview(plugin.HoudiniCreator):
|
|||
icon = "video-camera"
|
||||
|
||||
def create(self, subset_name, instance_data, pre_create_data):
|
||||
import hou
|
||||
|
||||
instance_data.pop("active", None)
|
||||
instance_data.update({"node_type": "opengl"})
|
||||
|
|
@ -82,6 +84,11 @@ class CreateReview(plugin.HoudiniCreator):
|
|||
|
||||
instance_node.setParms(parms)
|
||||
|
||||
# Set OCIO Colorspace to the default output colorspace
|
||||
# if there's OCIO
|
||||
if os.getenv("OCIO"):
|
||||
self.set_colorcorrect_to_default_view_space(instance_node)
|
||||
|
||||
to_lock = ["id", "family"]
|
||||
|
||||
self.lock_parameters(instance_node, to_lock)
|
||||
|
|
@ -123,3 +130,23 @@ class CreateReview(plugin.HoudiniCreator):
|
|||
minimum=0.0001,
|
||||
decimals=3)
|
||||
]
|
||||
|
||||
def set_colorcorrect_to_default_view_space(self,
|
||||
instance_node):
|
||||
"""Set ociocolorspace to the default output space."""
|
||||
from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace # noqa
|
||||
|
||||
# set Color Correction parameter to OpenColorIO
|
||||
instance_node.setParms({"colorcorrect": 2})
|
||||
|
||||
# Get default view space for ociocolorspace parm.
|
||||
default_view_space = get_default_display_view_colorspace()
|
||||
instance_node.setParms(
|
||||
{"ociocolorspace": default_view_space}
|
||||
)
|
||||
|
||||
self.log.debug(
|
||||
"'OCIO Colorspace' parm on '{}' has been set to "
|
||||
"the default view color space '{}'"
|
||||
.format(instance_node, default_view_space)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ class BgeoLoader(load.LoaderPlugin):
|
|||
|
||||
# Create a new geo node
|
||||
container = obj.createNode("geo", node_name=node_name)
|
||||
is_sequence = bool(context["representation"]["context"].get("frame"))
|
||||
|
||||
# Remove the file node, it only loads static meshes
|
||||
# Houdini 17 has removed the file node from the geo node
|
||||
|
|
|
|||
|
|
@ -80,14 +80,9 @@ class CollectVrayROPRenderProducts(pyblish.api.InstancePlugin):
|
|||
def get_beauty_render_product(self, prefix, suffix="<reName>"):
|
||||
"""Return the beauty output filename if render element enabled
|
||||
"""
|
||||
# Remove aov suffix from the product: `prefix.aov_suffix` -> `prefix`
|
||||
aov_parm = ".{}".format(suffix)
|
||||
beauty_product = None
|
||||
if aov_parm in prefix:
|
||||
beauty_product = prefix.replace(aov_parm, "")
|
||||
else:
|
||||
beauty_product = prefix
|
||||
|
||||
return beauty_product
|
||||
return prefix.replace(aov_parm, "")
|
||||
|
||||
def get_render_element_name(self, node, prefix, suffix="<reName>"):
|
||||
"""Return the output filename using the AOV prefix and suffix
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import pyblish.api
|
||||
from openpype.pipeline import (
|
||||
PublishValidationError,
|
||||
OptionalPyblishPluginMixin
|
||||
)
|
||||
from openpype.pipeline.publish import RepairAction
|
||||
from openpype.hosts.houdini.api.action import SelectROPAction
|
||||
|
||||
import os
|
||||
import hou
|
||||
|
||||
|
||||
class SetDefaultViewSpaceAction(RepairAction):
|
||||
label = "Set default view colorspace"
|
||||
icon = "mdi.monitor"
|
||||
|
||||
|
||||
class ValidateReviewColorspace(pyblish.api.InstancePlugin,
|
||||
OptionalPyblishPluginMixin):
|
||||
"""Validate Review Colorspace parameters.
|
||||
|
||||
It checks if 'OCIO Colorspace' parameter was set to valid value.
|
||||
"""
|
||||
|
||||
order = pyblish.api.ValidatorOrder + 0.1
|
||||
families = ["review"]
|
||||
hosts = ["houdini"]
|
||||
label = "Validate Review Colorspace"
|
||||
actions = [SetDefaultViewSpaceAction, SelectROPAction]
|
||||
|
||||
optional = True
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
if not self.is_active(instance.data):
|
||||
return
|
||||
|
||||
if os.getenv("OCIO") is None:
|
||||
self.log.debug(
|
||||
"Using Houdini's Default Color Management, "
|
||||
" skipping check.."
|
||||
)
|
||||
return
|
||||
|
||||
rop_node = hou.node(instance.data["instance_node"])
|
||||
if rop_node.evalParm("colorcorrect") != 2:
|
||||
# any colorspace settings other than default requires
|
||||
# 'Color Correct' parm to be set to 'OpenColorIO'
|
||||
raise PublishValidationError(
|
||||
"'Color Correction' parm on '{}' ROP must be set to"
|
||||
" 'OpenColorIO'".format(rop_node.path())
|
||||
)
|
||||
|
||||
if rop_node.evalParm("ociocolorspace") not in \
|
||||
hou.Color.ocio_spaces():
|
||||
|
||||
raise PublishValidationError(
|
||||
"Invalid value: Colorspace name doesn't exist.\n"
|
||||
"Check 'OCIO Colorspace' parameter on '{}' ROP"
|
||||
.format(rop_node.path())
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def repair(cls, instance):
|
||||
"""Set Default View Space Action.
|
||||
|
||||
It is a helper action more than a repair action,
|
||||
used to set colorspace on opengl node to the default view.
|
||||
"""
|
||||
from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace # noqa
|
||||
|
||||
rop_node = hou.node(instance.data["instance_node"])
|
||||
|
||||
if rop_node.evalParm("colorcorrect") != 2:
|
||||
rop_node.setParms({"colorcorrect": 2})
|
||||
cls.log.debug(
|
||||
"'Color Correction' parm on '{}' has been set to"
|
||||
" 'OpenColorIO'".format(rop_node.path())
|
||||
)
|
||||
|
||||
# Get default view colorspace name
|
||||
default_view_space = get_default_display_view_colorspace()
|
||||
|
||||
rop_node.setParms({"ociocolorspace": default_view_space})
|
||||
cls.log.info(
|
||||
"'OCIO Colorspace' parm on '{}' has been set to "
|
||||
"the default view color space '{}'"
|
||||
.format(rop_node, default_view_space)
|
||||
)
|
||||
|
|
@ -37,13 +37,10 @@ class RenderSettings(object):
|
|||
def set_render_camera(self, selection):
|
||||
for sel in selection:
|
||||
# to avoid Attribute Error from pymxs wrapper
|
||||
found = False
|
||||
if rt.classOf(sel) in rt.Camera.classes:
|
||||
found = True
|
||||
rt.viewport.setCamera(sel)
|
||||
break
|
||||
if not found:
|
||||
raise RuntimeError("Active Camera not found")
|
||||
return
|
||||
raise RuntimeError("Active Camera not found")
|
||||
|
||||
def render_output(self, container):
|
||||
folder = rt.maxFilePath
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ class CreateRender(plugin.MaxCreator):
|
|||
|
||||
def create(self, subset_name, instance_data, pre_create_data):
|
||||
from pymxs import runtime as rt
|
||||
sel_obj = list(rt.selection)
|
||||
file = rt.maxFileName
|
||||
filename, _ = os.path.splitext(file)
|
||||
instance_data["AssetName"] = filename
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ class CollectRender(pyblish.api.InstancePlugin):
|
|||
asset = get_current_asset_name()
|
||||
|
||||
files_by_aov = RenderProducts().get_beauty(instance.name)
|
||||
folder = folder.replace("\\", "/")
|
||||
aovs = RenderProducts().get_aovs(instance.name)
|
||||
files_by_aov.update(aovs)
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ class ExtractCameraAlembic(publish.Extractor, OptionalPyblishPluginMixin):
|
|||
start = float(instance.data.get("frameStartHandle", 1))
|
||||
end = float(instance.data.get("frameEndHandle", 1))
|
||||
|
||||
container = instance.data["instance_node"]
|
||||
|
||||
self.log.info("Extracting Camera ...")
|
||||
|
||||
stagingdir = self.staging_dir(instance)
|
||||
|
|
|
|||
|
|
@ -19,9 +19,8 @@ class ExtractCameraFbx(publish.Extractor, OptionalPyblishPluginMixin):
|
|||
def process(self, instance):
|
||||
if not self.is_active(instance.data):
|
||||
return
|
||||
container = instance.data["instance_node"]
|
||||
|
||||
self.log.info("Extracting Camera ...")
|
||||
self.log.debug("Extracting Camera ...")
|
||||
stagingdir = self.staging_dir(instance)
|
||||
filename = "{name}.fbx".format(**instance.data)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,10 +18,9 @@ class ExtractMaxSceneRaw(publish.Extractor, OptionalPyblishPluginMixin):
|
|||
def process(self, instance):
|
||||
if not self.is_active(instance.data):
|
||||
return
|
||||
container = instance.data["instance_node"]
|
||||
|
||||
# publish the raw scene for camera
|
||||
self.log.info("Extracting Raw Max Scene ...")
|
||||
self.log.debug("Extracting Raw Max Scene ...")
|
||||
|
||||
stagingdir = self.staging_dir(instance)
|
||||
filename = "{name}.max".format(**instance.data)
|
||||
|
|
|
|||
|
|
@ -20,9 +20,7 @@ class ExtractModel(publish.Extractor, OptionalPyblishPluginMixin):
|
|||
if not self.is_active(instance.data):
|
||||
return
|
||||
|
||||
container = instance.data["instance_node"]
|
||||
|
||||
self.log.info("Extracting Geometry ...")
|
||||
self.log.debug("Extracting Geometry ...")
|
||||
|
||||
stagingdir = self.staging_dir(instance)
|
||||
filename = "{name}.abc".format(**instance.data)
|
||||
|
|
|
|||
|
|
@ -20,10 +20,7 @@ class ExtractModelFbx(publish.Extractor, OptionalPyblishPluginMixin):
|
|||
if not self.is_active(instance.data):
|
||||
return
|
||||
|
||||
container = instance.data["instance_node"]
|
||||
|
||||
|
||||
self.log.info("Extracting Geometry ...")
|
||||
self.log.debug("Extracting Geometry ...")
|
||||
|
||||
stagingdir = self.staging_dir(instance)
|
||||
filename = "{name}.fbx".format(**instance.data)
|
||||
|
|
|
|||
|
|
@ -20,9 +20,7 @@ class ExtractModelObj(publish.Extractor, OptionalPyblishPluginMixin):
|
|||
if not self.is_active(instance.data):
|
||||
return
|
||||
|
||||
container = instance.data["instance_node"]
|
||||
|
||||
self.log.info("Extracting Geometry ...")
|
||||
self.log.debug("Extracting Geometry ...")
|
||||
|
||||
stagingdir = self.staging_dir(instance)
|
||||
filename = "{name}.obj".format(**instance.data)
|
||||
|
|
|
|||
|
|
@ -54,8 +54,6 @@ class ExtractAlembic(publish.Extractor):
|
|||
start = float(instance.data.get("frameStartHandle", 1))
|
||||
end = float(instance.data.get("frameEndHandle", 1))
|
||||
|
||||
container = instance.data["instance_node"]
|
||||
|
||||
self.log.debug("Extracting pointcache ...")
|
||||
|
||||
parent_dir = self.staging_dir(instance)
|
||||
|
|
|
|||
|
|
@ -16,11 +16,10 @@ class ExtractRedshiftProxy(publish.Extractor):
|
|||
families = ["redshiftproxy"]
|
||||
|
||||
def process(self, instance):
|
||||
container = instance.data["instance_node"]
|
||||
start = int(instance.context.data.get("frameStart"))
|
||||
end = int(instance.context.data.get("frameEnd"))
|
||||
|
||||
self.log.info("Extracting Redshift Proxy...")
|
||||
self.log.debug("Extracting Redshift Proxy...")
|
||||
stagingdir = self.staging_dir(instance)
|
||||
rs_filename = "{name}.rs".format(**instance.data)
|
||||
rs_filepath = os.path.join(stagingdir, rs_filename)
|
||||
|
|
|
|||
|
|
@ -6,11 +6,6 @@ from openpype.pipeline import (
|
|||
from pymxs import runtime as rt
|
||||
from openpype.hosts.max.api.lib import reset_scene_resolution
|
||||
|
||||
from openpype.pipeline.context_tools import (
|
||||
get_current_project_asset,
|
||||
get_current_project
|
||||
)
|
||||
|
||||
|
||||
class ValidateResolutionSetting(pyblish.api.InstancePlugin,
|
||||
OptionalPyblishPluginMixin):
|
||||
|
|
@ -43,22 +38,16 @@ class ValidateResolutionSetting(pyblish.api.InstancePlugin,
|
|||
"on asset or shot.")
|
||||
|
||||
def get_db_resolution(self, instance):
|
||||
data = ["data.resolutionWidth", "data.resolutionHeight"]
|
||||
project_resolution = get_current_project(fields=data)
|
||||
project_resolution_data = project_resolution["data"]
|
||||
asset_resolution = get_current_project_asset(fields=data)
|
||||
asset_resolution_data = asset_resolution["data"]
|
||||
# Set project resolution
|
||||
project_width = int(
|
||||
project_resolution_data.get("resolutionWidth", 1920))
|
||||
project_height = int(
|
||||
project_resolution_data.get("resolutionHeight", 1080))
|
||||
width = int(
|
||||
asset_resolution_data.get("resolutionWidth", project_width))
|
||||
height = int(
|
||||
asset_resolution_data.get("resolutionHeight", project_height))
|
||||
asset_doc = instance.data["assetEntity"]
|
||||
project_doc = instance.context.data["projectEntity"]
|
||||
for data in [asset_doc["data"], project_doc["data"]]:
|
||||
if "resolutionWidth" in data and "resolutionHeight" in data:
|
||||
width = data["resolutionWidth"]
|
||||
height = data["resolutionHeight"]
|
||||
return int(width), int(height)
|
||||
|
||||
return width, height
|
||||
# Defaults if not found in asset document or project document
|
||||
return 1920, 1080
|
||||
|
||||
@classmethod
|
||||
def repair(cls, instance):
|
||||
|
|
|
|||
|
|
@ -177,12 +177,7 @@ class RenderSettings(object):
|
|||
# list all the aovs
|
||||
all_rs_aovs = cmds.ls(type='RedshiftAOV')
|
||||
for rs_aov in redshift_aovs:
|
||||
rs_layername = rs_aov
|
||||
if " " in rs_aov:
|
||||
rs_renderlayer = rs_aov.replace(" ", "")
|
||||
rs_layername = "rsAov_{}".format(rs_renderlayer)
|
||||
else:
|
||||
rs_layername = "rsAov_{}".format(rs_aov)
|
||||
rs_layername = "rsAov_{}".format(rs_aov.replace(" ", ""))
|
||||
if rs_layername in all_rs_aovs:
|
||||
continue
|
||||
cmds.rsCreateAov(type=rs_aov)
|
||||
|
|
@ -317,7 +312,7 @@ class RenderSettings(object):
|
|||
separators = [cmds.menuItem(i, query=True, label=True) for i in items] # noqa: E501
|
||||
try:
|
||||
sep_idx = separators.index(aov_separator)
|
||||
except ValueError as e:
|
||||
except ValueError:
|
||||
six.reraise(
|
||||
CreatorError,
|
||||
CreatorError(
|
||||
|
|
|
|||
|
|
@ -683,7 +683,6 @@ class ReferenceLoader(Loader):
|
|||
loaded_containers.append(container)
|
||||
self._organize_containers(nodes, container)
|
||||
c += 1
|
||||
namespace = None
|
||||
|
||||
return loaded_containers
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ class ImportReference(InventoryAction):
|
|||
color = "#d8d8d8"
|
||||
|
||||
def process(self, containers):
|
||||
references = cmds.ls(type="reference")
|
||||
for container in containers:
|
||||
if container["loader"] != "ReferenceLoader":
|
||||
print("Not a reference, skipping")
|
||||
|
|
|
|||
|
|
@ -43,8 +43,6 @@ class MultiverseUsdLoader(load.LoaderPlugin):
|
|||
import multiverse
|
||||
|
||||
# Create the shape
|
||||
shape = None
|
||||
transform = None
|
||||
with maintained_selection():
|
||||
cmds.namespace(addNamespace=namespace)
|
||||
with namespaced(namespace, new=False):
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
|
|||
cmds.setAttr("{}.selectHandleZ".format(group_name), cz)
|
||||
|
||||
if family == "rig":
|
||||
self._post_process_rig(name, namespace, context, options)
|
||||
self._post_process_rig(namespace, context, options)
|
||||
else:
|
||||
if "translate" in options:
|
||||
if not attach_to_root and new_nodes:
|
||||
|
|
@ -229,7 +229,7 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
|
|||
members = get_container_members(container)
|
||||
self._lock_camera_transforms(members)
|
||||
|
||||
def _post_process_rig(self, name, namespace, context, options):
|
||||
def _post_process_rig(self, namespace, context, options):
|
||||
|
||||
nodes = self[:]
|
||||
create_rig_animation_instance(
|
||||
|
|
|
|||
|
|
@ -53,8 +53,6 @@ class XgenLoader(openpype.hosts.maya.api.plugin.ReferenceLoader):
|
|||
)
|
||||
|
||||
# Reference xgen. Xgen does not like being referenced in under a group.
|
||||
new_nodes = []
|
||||
|
||||
with maintained_selection():
|
||||
nodes = cmds.file(
|
||||
maya_filepath,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,16 @@ from openpype.hosts.maya.api import lib
|
|||
from openpype.hosts.maya.api.pipeline import containerise
|
||||
|
||||
|
||||
# Do not reset these values on update but only apply on first load
|
||||
# to preserve any potential local overrides
|
||||
SKIP_UPDATE_ATTRS = {
|
||||
"displayOutput",
|
||||
"viewportDensity",
|
||||
"viewportWidth",
|
||||
"viewportLength",
|
||||
}
|
||||
|
||||
|
||||
def set_attribute(node, attr, value):
|
||||
"""Wrapper of set attribute which ignores None values"""
|
||||
if value is None:
|
||||
|
|
@ -205,6 +215,8 @@ class YetiCacheLoader(load.LoaderPlugin):
|
|||
yeti_node = yeti_nodes[0]
|
||||
|
||||
for attr, value in node_settings["attrs"].items():
|
||||
if attr in SKIP_UPDATE_ATTRS:
|
||||
continue
|
||||
set_attribute(attr, value, yeti_node)
|
||||
|
||||
cmds.setAttr("{}.representation".format(container_node),
|
||||
|
|
@ -311,7 +323,6 @@ class YetiCacheLoader(load.LoaderPlugin):
|
|||
# Update attributes with defaults
|
||||
attributes = node_settings["attrs"]
|
||||
attributes.update({
|
||||
"viewportDensity": 0.1,
|
||||
"verbosity": 2,
|
||||
"fileMode": 1,
|
||||
|
||||
|
|
@ -321,6 +332,9 @@ class YetiCacheLoader(load.LoaderPlugin):
|
|||
"visibleInRefractions": True
|
||||
})
|
||||
|
||||
if "viewportDensity" not in attributes:
|
||||
attributes["viewportDensity"] = 0.1
|
||||
|
||||
# Apply attributes to pgYetiMaya node
|
||||
for attr, value in attributes.items():
|
||||
set_attribute(attr, value, yeti_node)
|
||||
|
|
|
|||
|
|
@ -281,7 +281,6 @@ class CollectMultiverseLookData(pyblish.api.InstancePlugin):
|
|||
long=True)
|
||||
nodes.update(nodes_of_interest)
|
||||
|
||||
files = []
|
||||
sets = {}
|
||||
instance.data["resources"] = []
|
||||
publishMipMap = instance.data["publishMipMap"]
|
||||
|
|
|
|||
|
|
@ -4,12 +4,23 @@ import pyblish.api
|
|||
|
||||
from openpype.hosts.maya.api import lib
|
||||
|
||||
SETTINGS = {"renderDensity",
|
||||
"renderWidth",
|
||||
"renderLength",
|
||||
"increaseRenderBounds",
|
||||
"imageSearchPath",
|
||||
"cbId"}
|
||||
|
||||
SETTINGS = {
|
||||
# Preview
|
||||
"displayOutput",
|
||||
"colorR", "colorG", "colorB",
|
||||
"viewportDensity",
|
||||
"viewportWidth",
|
||||
"viewportLength",
|
||||
# Render attributes
|
||||
"renderDensity",
|
||||
"renderWidth",
|
||||
"renderLength",
|
||||
"increaseRenderBounds",
|
||||
"imageSearchPath",
|
||||
# Pipeline specific
|
||||
"cbId"
|
||||
}
|
||||
|
||||
|
||||
class CollectYetiCache(pyblish.api.InstancePlugin):
|
||||
|
|
@ -39,10 +50,6 @@ class CollectYetiCache(pyblish.api.InstancePlugin):
|
|||
# Get yeti nodes and their transforms
|
||||
yeti_shapes = cmds.ls(instance, type="pgYetiMaya")
|
||||
for shape in yeti_shapes:
|
||||
shape_data = {"transform": None,
|
||||
"name": shape,
|
||||
"cbId": lib.get_id(shape),
|
||||
"attrs": None}
|
||||
|
||||
# Get specific node attributes
|
||||
attr_data = {}
|
||||
|
|
@ -58,9 +65,12 @@ class CollectYetiCache(pyblish.api.InstancePlugin):
|
|||
parent = cmds.listRelatives(shape, parent=True)[0]
|
||||
transform_data = {"name": parent, "cbId": lib.get_id(parent)}
|
||||
|
||||
# Store collected data
|
||||
shape_data["attrs"] = attr_data
|
||||
shape_data["transform"] = transform_data
|
||||
shape_data = {
|
||||
"transform": transform_data,
|
||||
"name": shape,
|
||||
"cbId": lib.get_id(shape),
|
||||
"attrs": attr_data,
|
||||
}
|
||||
|
||||
settings["nodes"].append(shape_data)
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ class ExtractImportReference(publish.Extractor,
|
|||
tmp_format = "_tmp"
|
||||
|
||||
@classmethod
|
||||
def apply_settings(cls, project_setting, system_settings):
|
||||
cls.active = project_setting["deadline"]["publish"]["MayaSubmitDeadline"]["import_reference"] # noqa
|
||||
def apply_settings(cls, project_settings):
|
||||
cls.active = project_settings["deadline"]["publish"]["MayaSubmitDeadline"]["import_reference"] # noqa
|
||||
|
||||
def process(self, instance):
|
||||
if not self.is_active(instance.data):
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class ValidateMayaUnits(pyblish.api.ContextPlugin):
|
|||
)
|
||||
|
||||
@classmethod
|
||||
def apply_settings(cls, project_settings, system_settings):
|
||||
def apply_settings(cls, project_settings):
|
||||
"""Apply project settings to creator"""
|
||||
settings = (
|
||||
project_settings["maya"]["publish"]["ValidateMayaUnits"]
|
||||
|
|
|
|||
|
|
@ -90,15 +90,13 @@ class AssetOutliner(QtWidgets.QWidget):
|
|||
def get_all_assets(self):
|
||||
"""Add all items from the current scene"""
|
||||
|
||||
items = []
|
||||
with preserve_expanded_rows(self.view):
|
||||
with preserve_selection(self.view):
|
||||
self.clear()
|
||||
nodes = commands.get_all_asset_nodes()
|
||||
items = commands.create_items_from_nodes(nodes)
|
||||
self.add_items(items)
|
||||
|
||||
return len(items) > 0
|
||||
return len(items) > 0
|
||||
|
||||
def get_selected_assets(self):
|
||||
"""Add all selected items from the current scene"""
|
||||
|
|
|
|||
|
|
@ -112,8 +112,6 @@ class AlembicCameraLoader(load.LoaderPlugin):
|
|||
version_doc = get_version_by_id(project_name, representation["parent"])
|
||||
|
||||
object_name = container['objectName']
|
||||
# get corresponding node
|
||||
camera_node = nuke.toNode(object_name)
|
||||
|
||||
# get main variables
|
||||
version_data = version_doc.get("data", {})
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ class ExtractReviewDataLut(publish.Extractor):
|
|||
hosts = ["nuke"]
|
||||
|
||||
def process(self, instance):
|
||||
families = instance.data["families"]
|
||||
self.log.info("Creating staging dir...")
|
||||
if "representations" in instance.data:
|
||||
staging_dir = instance.data[
|
||||
|
|
|
|||
|
|
@ -91,8 +91,6 @@ class ExtractThumbnail(publish.Extractor):
|
|||
|
||||
if collection:
|
||||
# get path
|
||||
fname = os.path.basename(collection.format(
|
||||
"{head}{padding}{tail}"))
|
||||
fhead = collection.format("{head}")
|
||||
|
||||
thumb_fname = list(collection)[mid_frame]
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ class CollectAutoImage(pyblish.api.ContextPlugin):
|
|||
targets = ["automated"]
|
||||
|
||||
def process(self, context):
|
||||
family = "image"
|
||||
for instance in context:
|
||||
creator_identifier = instance.data.get("creator_identifier")
|
||||
if creator_identifier and creator_identifier == "auto_image":
|
||||
|
|
|
|||
|
|
@ -413,8 +413,6 @@ class ClipLoader:
|
|||
if self.with_handles:
|
||||
source_in -= handle_start
|
||||
source_out += handle_end
|
||||
handle_start = 0
|
||||
handle_end = 0
|
||||
|
||||
# make track item from source in bin as item
|
||||
timeline_item = lib.create_timeline_item(
|
||||
|
|
@ -433,14 +431,6 @@ class ClipLoader:
|
|||
self.data["path"], self.active_bin)
|
||||
_clip_property = media_pool_item.GetClipProperty
|
||||
|
||||
# get handles
|
||||
handle_start = self.data["versionData"].get("handleStart")
|
||||
handle_end = self.data["versionData"].get("handleEnd")
|
||||
if handle_start is None:
|
||||
handle_start = int(self.data["assetData"]["handleStart"])
|
||||
if handle_end is None:
|
||||
handle_end = int(self.data["assetData"]["handleEnd"])
|
||||
|
||||
source_in = int(_clip_property("Start"))
|
||||
source_out = int(_clip_property("End"))
|
||||
|
||||
|
|
|
|||
|
|
@ -49,8 +49,6 @@ class ExtractThumbnailSP(pyblish.api.InstancePlugin):
|
|||
else:
|
||||
first_filename = files
|
||||
|
||||
staging_dir = None
|
||||
|
||||
# Convert to jpeg if not yet
|
||||
full_input_path = os.path.join(
|
||||
thumbnail_repre["stagingDir"], first_filename
|
||||
|
|
|
|||
|
|
@ -2,16 +2,18 @@ import pyblish.api
|
|||
from openpype.pipeline import OptionalPyblishPluginMixin
|
||||
|
||||
|
||||
class CollectFrameDataFromAssetEntity(pyblish.api.InstancePlugin,
|
||||
OptionalPyblishPluginMixin):
|
||||
"""Collect Frame Range data From Asset Entity
|
||||
class CollectMissingFrameDataFromAssetEntity(
|
||||
pyblish.api.InstancePlugin,
|
||||
OptionalPyblishPluginMixin
|
||||
):
|
||||
"""Collect Missing Frame Range data From Asset Entity
|
||||
|
||||
Frame range data will only be collected if the keys
|
||||
are not yet collected for the instance.
|
||||
"""
|
||||
|
||||
order = pyblish.api.CollectorOrder + 0.491
|
||||
label = "Collect Frame Data From Asset Entity"
|
||||
label = "Collect Missing Frame Data From Asset Entity"
|
||||
families = ["plate", "pointcache",
|
||||
"vdbcache", "online",
|
||||
"render"]
|
||||
|
|
@ -15,7 +15,7 @@ class ValidateFrameRange(OptionalPyblishPluginMixin,
|
|||
|
||||
label = "Validate Frame Range"
|
||||
hosts = ["traypublisher"]
|
||||
families = ["render"]
|
||||
families = ["render", "plate"]
|
||||
order = ValidateContentsOrder
|
||||
|
||||
optional = True
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ class LoadImage(plugin.Loader):
|
|||
george_script = "\n".join(george_script_lines)
|
||||
execute_george_through_file(george_script)
|
||||
|
||||
def _remove_container(self, container, members=None):
|
||||
def _remove_container(self, container):
|
||||
if not container:
|
||||
return
|
||||
representation = container["representation"]
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ class ExtractSequence(pyblish.api.Extractor):
|
|||
"ignoreLayersTransparency", False
|
||||
)
|
||||
|
||||
family_lowered = instance.data["family"].lower()
|
||||
mark_in = instance.context.data["sceneMarkIn"]
|
||||
mark_out = instance.context.data["sceneMarkOut"]
|
||||
|
||||
|
|
@ -76,11 +75,9 @@ class ExtractSequence(pyblish.api.Extractor):
|
|||
|
||||
# Frame start/end may be stored as float
|
||||
frame_start = int(instance.data["frameStart"])
|
||||
frame_end = int(instance.data["frameEnd"])
|
||||
|
||||
# Handles are not stored per instance but on Context
|
||||
handle_start = instance.context.data["handleStart"]
|
||||
handle_end = instance.context.data["handleEnd"]
|
||||
|
||||
scene_bg_color = instance.context.data["sceneBgColor"]
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,8 @@ class ExtractUAsset(publish.Extractor):
|
|||
"umap" if "umap" in instance.data.get("families") else "uasset")
|
||||
ar = unreal.AssetRegistryHelpers.get_asset_registry()
|
||||
|
||||
self.log.info("Performing extraction..")
|
||||
self.log.debug("Performing extraction..")
|
||||
staging_dir = self.staging_dir(instance)
|
||||
filename = f"{instance.name}.{extension}"
|
||||
|
||||
members = instance.data.get("members", [])
|
||||
|
||||
|
|
|
|||
|
|
@ -724,7 +724,7 @@ def get_ffprobe_data(path_to_file, logger=None):
|
|||
"""
|
||||
if not logger:
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.info(
|
||||
logger.debug(
|
||||
"Getting information about input \"{}\".".format(path_to_file)
|
||||
)
|
||||
ffprobe_args = get_ffmpeg_tool_args("ffprobe")
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ class IntegrateFtrackApi(pyblish.api.InstancePlugin):
|
|||
def process(self, instance):
|
||||
component_list = instance.data.get("ftrackComponentsList")
|
||||
if not component_list:
|
||||
self.log.info(
|
||||
"Instance don't have components to integrate to Ftrack."
|
||||
self.log.debug(
|
||||
"Instance doesn't have components to integrate to Ftrack."
|
||||
" Skipping."
|
||||
)
|
||||
return
|
||||
|
|
@ -37,7 +37,7 @@ class IntegrateFtrackApi(pyblish.api.InstancePlugin):
|
|||
task_entity, parent_entity = self.get_instance_entities(
|
||||
instance, context)
|
||||
if parent_entity is None:
|
||||
self.log.info((
|
||||
self.log.debug((
|
||||
"Skipping ftrack integration. Instance \"{}\" does not"
|
||||
" have specified ftrack entities."
|
||||
).format(str(instance)))
|
||||
|
|
@ -323,7 +323,7 @@ class IntegrateFtrackApi(pyblish.api.InstancePlugin):
|
|||
"type_id": asset_type_id,
|
||||
"context_id": parent_id
|
||||
}
|
||||
self.log.info("Created new Asset with data: {}.".format(asset_data))
|
||||
self.log.debug("Created new Asset with data: {}.".format(asset_data))
|
||||
session.create("Asset", asset_data)
|
||||
session.commit()
|
||||
return self._query_asset(session, asset_name, asset_type_id, parent_id)
|
||||
|
|
@ -384,7 +384,7 @@ class IntegrateFtrackApi(pyblish.api.InstancePlugin):
|
|||
if comment:
|
||||
new_asset_version_data["comment"] = comment
|
||||
|
||||
self.log.info("Created new AssetVersion with data {}".format(
|
||||
self.log.debug("Created new AssetVersion with data {}".format(
|
||||
new_asset_version_data
|
||||
))
|
||||
session.create("AssetVersion", new_asset_version_data)
|
||||
|
|
@ -555,7 +555,7 @@ class IntegrateFtrackApi(pyblish.api.InstancePlugin):
|
|||
location=location
|
||||
)
|
||||
data["component"] = component_entity
|
||||
self.log.info(
|
||||
self.log.debug(
|
||||
(
|
||||
"Created new Component with path: {0}, data: {1},"
|
||||
" metadata: {2}, location: {3}"
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class IntegrateFtrackDescription(pyblish.api.InstancePlugin):
|
|||
|
||||
comment = instance.data["comment"]
|
||||
if not comment:
|
||||
self.log.info("Comment is not set.")
|
||||
self.log.debug("Comment is not set.")
|
||||
else:
|
||||
self.log.debug("Comment is set to `{}`".format(comment))
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class IntegrateFtrackNote(pyblish.api.InstancePlugin):
|
|||
app_label = context.data["appLabel"]
|
||||
comment = instance.data["comment"]
|
||||
if not comment:
|
||||
self.log.info("Comment is not set.")
|
||||
self.log.debug("Comment is not set.")
|
||||
else:
|
||||
self.log.debug("Comment is set to `{}`".format(comment))
|
||||
|
||||
|
|
@ -127,14 +127,14 @@ class IntegrateFtrackNote(pyblish.api.InstancePlugin):
|
|||
|
||||
note_text = StringTemplate.format_template(template, format_data)
|
||||
if not note_text.solved:
|
||||
self.log.warning((
|
||||
self.log.debug((
|
||||
"Note template require more keys then can be provided."
|
||||
"\nTemplate: {}\nMissing values for keys:{}\nData: {}"
|
||||
).format(template, note_text.missing_keys, format_data))
|
||||
continue
|
||||
|
||||
if not note_text:
|
||||
self.log.info((
|
||||
self.log.debug((
|
||||
"Note for AssetVersion {} would be empty. Skipping."
|
||||
"\nTemplate: {}\nData: {}"
|
||||
).format(asset_version["id"], template, format_data))
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ class IntegrateKitsuNote(pyblish.api.ContextPlugin):
|
|||
publish_comment = self.format_publish_comment(instance)
|
||||
|
||||
if not publish_comment:
|
||||
self.log.info("Comment is not set.")
|
||||
self.log.debug("Comment is not set.")
|
||||
else:
|
||||
self.log.debug("Comment is `{}`".format(publish_comment))
|
||||
|
||||
|
|
|
|||
|
|
@ -13,12 +13,17 @@ from openpype.lib import (
|
|||
Logger
|
||||
)
|
||||
from openpype.pipeline import Anatomy
|
||||
from openpype.lib.transcoding import VIDEO_EXTENSIONS, IMAGE_EXTENSIONS
|
||||
|
||||
|
||||
log = Logger.get_logger(__name__)
|
||||
|
||||
|
||||
class CashedData:
|
||||
remapping = None
|
||||
class CachedData:
|
||||
remapping = {}
|
||||
allowed_exts = {
|
||||
ext.lstrip(".") for ext in IMAGE_EXTENSIONS.union(VIDEO_EXTENSIONS)
|
||||
}
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
|
|
@ -546,15 +551,15 @@ def get_remapped_colorspace_to_native(
|
|||
Union[str, None]: native colorspace name defined in remapping or None
|
||||
"""
|
||||
|
||||
CashedData.remapping.setdefault(host_name, {})
|
||||
if CashedData.remapping[host_name].get("to_native") is None:
|
||||
CachedData.remapping.setdefault(host_name, {})
|
||||
if CachedData.remapping[host_name].get("to_native") is None:
|
||||
remapping_rules = imageio_host_settings["remapping"]["rules"]
|
||||
CashedData.remapping[host_name]["to_native"] = {
|
||||
CachedData.remapping[host_name]["to_native"] = {
|
||||
rule["ocio_name"]: rule["host_native_name"]
|
||||
for rule in remapping_rules
|
||||
}
|
||||
|
||||
return CashedData.remapping[host_name]["to_native"].get(
|
||||
return CachedData.remapping[host_name]["to_native"].get(
|
||||
ocio_colorspace_name)
|
||||
|
||||
|
||||
|
|
@ -572,15 +577,15 @@ def get_remapped_colorspace_from_native(
|
|||
Union[str, None]: Ocio colorspace name defined in remapping or None.
|
||||
"""
|
||||
|
||||
CashedData.remapping.setdefault(host_name, {})
|
||||
if CashedData.remapping[host_name].get("from_native") is None:
|
||||
CachedData.remapping.setdefault(host_name, {})
|
||||
if CachedData.remapping[host_name].get("from_native") is None:
|
||||
remapping_rules = imageio_host_settings["remapping"]["rules"]
|
||||
CashedData.remapping[host_name]["from_native"] = {
|
||||
CachedData.remapping[host_name]["from_native"] = {
|
||||
rule["host_native_name"]: rule["ocio_name"]
|
||||
for rule in remapping_rules
|
||||
}
|
||||
|
||||
return CashedData.remapping[host_name]["from_native"].get(
|
||||
return CachedData.remapping[host_name]["from_native"].get(
|
||||
host_native_colorspace_name)
|
||||
|
||||
|
||||
|
|
@ -601,3 +606,173 @@ def _get_imageio_settings(project_settings, host_name):
|
|||
imageio_host = project_settings.get(host_name, {}).get("imageio", {})
|
||||
|
||||
return imageio_global, imageio_host
|
||||
|
||||
|
||||
def get_colorspace_settings_from_publish_context(context_data):
|
||||
"""Returns solved settings for the host context.
|
||||
|
||||
Args:
|
||||
context_data (publish.Context.data): publishing context data
|
||||
|
||||
Returns:
|
||||
tuple | bool: config, file rules or None
|
||||
"""
|
||||
if "imageioSettings" in context_data and context_data["imageioSettings"]:
|
||||
return context_data["imageioSettings"]
|
||||
|
||||
project_name = context_data["projectName"]
|
||||
host_name = context_data["hostName"]
|
||||
anatomy_data = context_data["anatomyData"]
|
||||
project_settings_ = context_data["project_settings"]
|
||||
|
||||
config_data = get_imageio_config(
|
||||
project_name, host_name,
|
||||
project_settings=project_settings_,
|
||||
anatomy_data=anatomy_data
|
||||
)
|
||||
|
||||
# caching invalid state, so it's not recalculated all the time
|
||||
file_rules = None
|
||||
if config_data:
|
||||
file_rules = get_imageio_file_rules(
|
||||
project_name, host_name,
|
||||
project_settings=project_settings_
|
||||
)
|
||||
|
||||
# caching settings for future instance processing
|
||||
context_data["imageioSettings"] = (config_data, file_rules)
|
||||
|
||||
return config_data, file_rules
|
||||
|
||||
|
||||
def set_colorspace_data_to_representation(
|
||||
representation, context_data,
|
||||
colorspace=None,
|
||||
log=None
|
||||
):
|
||||
"""Sets colorspace data to representation.
|
||||
|
||||
Args:
|
||||
representation (dict): publishing representation
|
||||
context_data (publish.Context.data): publishing context data
|
||||
colorspace (str, optional): colorspace name. Defaults to None.
|
||||
log (logging.Logger, optional): logger instance. Defaults to None.
|
||||
|
||||
Example:
|
||||
```
|
||||
{
|
||||
# for other publish plugins and loaders
|
||||
"colorspace": "linear",
|
||||
"config": {
|
||||
# for future references in case need
|
||||
"path": "/abs/path/to/config.ocio",
|
||||
# for other plugins within remote publish cases
|
||||
"template": "{project[root]}/path/to/config.ocio"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
"""
|
||||
log = log or Logger.get_logger(__name__)
|
||||
|
||||
file_ext = representation["ext"]
|
||||
|
||||
# check if `file_ext` in lower case is in CachedData.allowed_exts
|
||||
if file_ext.lstrip(".").lower() not in CachedData.allowed_exts:
|
||||
log.debug(
|
||||
"Extension '{}' is not in allowed extensions.".format(file_ext)
|
||||
)
|
||||
return
|
||||
|
||||
# get colorspace settings
|
||||
config_data, file_rules = get_colorspace_settings_from_publish_context(
|
||||
context_data)
|
||||
|
||||
# in case host color management is not enabled
|
||||
if not config_data:
|
||||
log.warning("Host's colorspace management is disabled.")
|
||||
return
|
||||
|
||||
log.debug("Config data is: `{}`".format(config_data))
|
||||
|
||||
project_name = context_data["projectName"]
|
||||
host_name = context_data["hostName"]
|
||||
project_settings = context_data["project_settings"]
|
||||
|
||||
# get one filename
|
||||
filename = representation["files"]
|
||||
if isinstance(filename, list):
|
||||
filename = filename[0]
|
||||
|
||||
# get matching colorspace from rules
|
||||
colorspace = colorspace or get_imageio_colorspace_from_filepath(
|
||||
filename, host_name, project_name,
|
||||
config_data=config_data,
|
||||
file_rules=file_rules,
|
||||
project_settings=project_settings
|
||||
)
|
||||
|
||||
# infuse data to representation
|
||||
if colorspace:
|
||||
colorspace_data = {
|
||||
"colorspace": colorspace,
|
||||
"config": config_data
|
||||
}
|
||||
|
||||
# update data key
|
||||
representation["colorspaceData"] = colorspace_data
|
||||
|
||||
|
||||
def get_display_view_colorspace_name(config_path, display, view):
|
||||
"""Returns the colorspace attribute of the (display, view) pair.
|
||||
|
||||
Args:
|
||||
config_path (str): path string leading to config.ocio
|
||||
display (str): display name e.g. "ACES"
|
||||
view (str): view name e.g. "sRGB"
|
||||
|
||||
Returns:
|
||||
view color space name (str) e.g. "Output - sRGB"
|
||||
"""
|
||||
|
||||
if not compatibility_check():
|
||||
# python environment is not compatible with PyOpenColorIO
|
||||
# needs to be run in subprocess
|
||||
return get_display_view_colorspace_subprocess(config_path,
|
||||
display, view)
|
||||
|
||||
from openpype.scripts.ocio_wrapper import _get_display_view_colorspace_name # noqa
|
||||
|
||||
return _get_display_view_colorspace_name(config_path, display, view)
|
||||
|
||||
|
||||
def get_display_view_colorspace_subprocess(config_path, display, view):
|
||||
"""Returns the colorspace attribute of the (display, view) pair
|
||||
via subprocess.
|
||||
|
||||
Args:
|
||||
config_path (str): path string leading to config.ocio
|
||||
display (str): display name e.g. "ACES"
|
||||
view (str): view name e.g. "sRGB"
|
||||
|
||||
Returns:
|
||||
view color space name (str) e.g. "Output - sRGB"
|
||||
"""
|
||||
|
||||
with _make_temp_json_file() as tmp_json_path:
|
||||
# Prepare subprocess arguments
|
||||
args = [
|
||||
"run", get_ocio_config_script_path(),
|
||||
"config", "get_display_view_colorspace_name",
|
||||
"--in_path", config_path,
|
||||
"--out_path", tmp_json_path,
|
||||
"--display", display,
|
||||
"--view", view
|
||||
]
|
||||
log.debug("Executing: {}".format(" ".join(args)))
|
||||
|
||||
run_openpype_process(*args, logger=log)
|
||||
|
||||
# return default view colorspace name
|
||||
with open(tmp_json_path, "r") as f:
|
||||
return json.load(f)
|
||||
|
|
|
|||
|
|
@ -234,6 +234,19 @@ class LoaderPlugin(list):
|
|||
"""
|
||||
return cls.options or []
|
||||
|
||||
@property
|
||||
def fname(self):
|
||||
"""Backwards compatibility with deprecation warning"""
|
||||
|
||||
self.log.warning((
|
||||
"DEPRECATION WARNING: Source - Loader plugin {}."
|
||||
" The 'fname' property on the Loader plugin will be removed in"
|
||||
" future versions of OpenPype. Planned version to drop the support"
|
||||
" is 3.16.6 or 3.17.0."
|
||||
).format(self.__class__.__name__))
|
||||
if hasattr(self, "_fname"):
|
||||
return self._fname
|
||||
|
||||
|
||||
class SubsetLoaderPlugin(LoaderPlugin):
|
||||
"""Load subset into host application
|
||||
|
|
|
|||
|
|
@ -318,7 +318,8 @@ def load_with_repre_context(
|
|||
|
||||
# Backwards compatibility: Originally the loader's __init__ required the
|
||||
# representation context to set `fname` attribute to the filename to load
|
||||
loader.fname = get_representation_path_from_context(repre_context)
|
||||
# Deprecated - to be removed in OpenPype 3.16.6 or 3.17.0.
|
||||
loader._fname = get_representation_path_from_context(repre_context)
|
||||
|
||||
return loader.load(repre_context, name, namespace, options)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import inspect
|
||||
from abc import ABCMeta
|
||||
from pprint import pformat
|
||||
import pyblish.api
|
||||
from pyblish.plugin import MetaPlugin, ExplicitMetaPlugin
|
||||
from openpype.lib.transcoding import VIDEO_EXTENSIONS, IMAGE_EXTENSIONS
|
||||
|
|
@ -14,9 +13,8 @@ from .lib import (
|
|||
)
|
||||
|
||||
from openpype.pipeline.colorspace import (
|
||||
get_imageio_colorspace_from_filepath,
|
||||
get_imageio_config,
|
||||
get_imageio_file_rules
|
||||
get_colorspace_settings_from_publish_context,
|
||||
set_colorspace_data_to_representation
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -306,12 +304,8 @@ class ColormanagedPyblishPluginMixin(object):
|
|||
matching colorspace from rules. Finally, it infuses this
|
||||
data into the representation.
|
||||
"""
|
||||
allowed_ext = set(
|
||||
ext.lstrip(".") for ext in IMAGE_EXTENSIONS.union(VIDEO_EXTENSIONS)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_colorspace_settings(context):
|
||||
def get_colorspace_settings(self, context):
|
||||
"""Returns solved settings for the host context.
|
||||
|
||||
Args:
|
||||
|
|
@ -320,50 +314,18 @@ class ColormanagedPyblishPluginMixin(object):
|
|||
Returns:
|
||||
tuple | bool: config, file rules or None
|
||||
"""
|
||||
if "imageioSettings" in context.data:
|
||||
return context.data["imageioSettings"]
|
||||
|
||||
project_name = context.data["projectName"]
|
||||
host_name = context.data["hostName"]
|
||||
anatomy_data = context.data["anatomyData"]
|
||||
project_settings_ = context.data["project_settings"]
|
||||
|
||||
config_data = get_imageio_config(
|
||||
project_name, host_name,
|
||||
project_settings=project_settings_,
|
||||
anatomy_data=anatomy_data
|
||||
)
|
||||
|
||||
# in case host color management is not enabled
|
||||
if not config_data:
|
||||
return None
|
||||
|
||||
file_rules = get_imageio_file_rules(
|
||||
project_name, host_name,
|
||||
project_settings=project_settings_
|
||||
)
|
||||
|
||||
# caching settings for future instance processing
|
||||
context.data["imageioSettings"] = (config_data, file_rules)
|
||||
|
||||
return config_data, file_rules
|
||||
return get_colorspace_settings_from_publish_context(context.data)
|
||||
|
||||
def set_representation_colorspace(
|
||||
self, representation, context,
|
||||
colorspace=None,
|
||||
colorspace_settings=None
|
||||
):
|
||||
"""Sets colorspace data to representation.
|
||||
|
||||
Args:
|
||||
representation (dict): publishing representation
|
||||
context (publish.Context): publishing context
|
||||
config_data (dict): host resolved config data
|
||||
file_rules (dict): host resolved file rules data
|
||||
colorspace (str, optional): colorspace name. Defaults to None.
|
||||
colorspace_settings (tuple[dict, dict], optional):
|
||||
Settings for config_data and file_rules.
|
||||
Defaults to None.
|
||||
|
||||
Example:
|
||||
```
|
||||
|
|
@ -380,64 +342,10 @@ class ColormanagedPyblishPluginMixin(object):
|
|||
```
|
||||
|
||||
"""
|
||||
ext = representation["ext"]
|
||||
# check extension
|
||||
self.log.debug("__ ext: `{}`".format(ext))
|
||||
|
||||
# check if ext in lower case is in self.allowed_ext
|
||||
if ext.lstrip(".").lower() not in self.allowed_ext:
|
||||
self.log.debug(
|
||||
"Extension '{}' is not in allowed extensions.".format(ext)
|
||||
)
|
||||
return
|
||||
|
||||
if colorspace_settings is None:
|
||||
colorspace_settings = self.get_colorspace_settings(context)
|
||||
|
||||
# in case host color management is not enabled
|
||||
if not colorspace_settings:
|
||||
self.log.warning("Host's colorspace management is disabled.")
|
||||
return
|
||||
|
||||
# unpack colorspace settings
|
||||
config_data, file_rules = colorspace_settings
|
||||
|
||||
if not config_data:
|
||||
# warn in case no colorspace path was defined
|
||||
self.log.warning("No colorspace management was defined")
|
||||
return
|
||||
|
||||
self.log.debug("Config data is: `{}`".format(config_data))
|
||||
|
||||
project_name = context.data["projectName"]
|
||||
host_name = context.data["hostName"]
|
||||
project_settings = context.data["project_settings"]
|
||||
|
||||
# get one filename
|
||||
filename = representation["files"]
|
||||
if isinstance(filename, list):
|
||||
filename = filename[0]
|
||||
|
||||
self.log.debug("__ filename: `{}`".format(filename))
|
||||
|
||||
# get matching colorspace from rules
|
||||
colorspace = colorspace or get_imageio_colorspace_from_filepath(
|
||||
filename, host_name, project_name,
|
||||
config_data=config_data,
|
||||
file_rules=file_rules,
|
||||
project_settings=project_settings
|
||||
# using cached settings if available
|
||||
set_colorspace_data_to_representation(
|
||||
representation, context.data,
|
||||
colorspace,
|
||||
log=self.log
|
||||
)
|
||||
self.log.debug("__ colorspace: `{}`".format(colorspace))
|
||||
|
||||
# infuse data to representation
|
||||
if colorspace:
|
||||
colorspace_data = {
|
||||
"colorspace": colorspace,
|
||||
"config": config_data
|
||||
}
|
||||
|
||||
# update data key
|
||||
representation["colorspaceData"] = colorspace_data
|
||||
|
||||
self.log.debug("__ colorspace_data: `{}`".format(
|
||||
pformat(colorspace_data)))
|
||||
|
|
|
|||
|
|
@ -50,4 +50,7 @@ class CollectSequenceFrameData(pyblish.api.InstancePlugin):
|
|||
return {
|
||||
"frameStart": repres_frames[0],
|
||||
"frameEnd": repres_frames[-1],
|
||||
"handleStart": 0,
|
||||
"handleEnd": 0,
|
||||
"fps": instance.context.data["assetEntity"]["data"]["fps"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -174,5 +174,79 @@ def _get_views_data(config_path):
|
|||
return data
|
||||
|
||||
|
||||
def _get_display_view_colorspace_name(config_path, display, view):
|
||||
"""Returns the colorspace attribute of the (display, view) pair.
|
||||
|
||||
Args:
|
||||
config_path (str): path string leading to config.ocio
|
||||
display (str): display name e.g. "ACES"
|
||||
view (str): view name e.g. "sRGB"
|
||||
|
||||
|
||||
Raises:
|
||||
IOError: Input config does not exist.
|
||||
|
||||
Returns:
|
||||
view color space name (str) e.g. "Output - sRGB"
|
||||
"""
|
||||
|
||||
config_path = Path(config_path)
|
||||
|
||||
if not config_path.is_file():
|
||||
raise IOError("Input path should be `config.ocio` file")
|
||||
|
||||
config = ocio.Config.CreateFromFile(str(config_path))
|
||||
colorspace = config.getDisplayViewColorSpaceName(display, view)
|
||||
|
||||
return colorspace
|
||||
|
||||
|
||||
@config.command(
|
||||
name="get_display_view_colorspace_name",
|
||||
help=(
|
||||
"return default view colorspace name "
|
||||
"for the given display and view "
|
||||
"--path input arg is required"
|
||||
)
|
||||
)
|
||||
@click.option("--in_path", required=True,
|
||||
help="path where to read ocio config file",
|
||||
type=click.Path(exists=True))
|
||||
@click.option("--out_path", required=True,
|
||||
help="path where to write output json file",
|
||||
type=click.Path())
|
||||
@click.option("--display", required=True,
|
||||
help="display name",
|
||||
type=click.STRING)
|
||||
@click.option("--view", required=True,
|
||||
help="view name",
|
||||
type=click.STRING)
|
||||
def get_display_view_colorspace_name(in_path, out_path,
|
||||
display, view):
|
||||
"""Aggregate view colorspace name to file.
|
||||
|
||||
Wrapper command for processes without access to OpenColorIO
|
||||
|
||||
Args:
|
||||
in_path (str): config file path string
|
||||
out_path (str): temp json file path string
|
||||
display (str): display name e.g. "ACES"
|
||||
view (str): view name e.g. "sRGB"
|
||||
|
||||
Example of use:
|
||||
> pyton.exe ./ocio_wrapper.py config \
|
||||
get_display_view_colorspace_name --in_path=<path> \
|
||||
--out_path=<path> --display=<display> --view=<view>
|
||||
"""
|
||||
|
||||
out_data = _get_display_view_colorspace_name(in_path,
|
||||
display,
|
||||
view)
|
||||
|
||||
with open(out_path, "w") as f:
|
||||
json.dump(out_data, f)
|
||||
|
||||
print(f"Display view colorspace saved to '{out_path}'")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -93,6 +93,11 @@
|
|||
"$JOB"
|
||||
]
|
||||
},
|
||||
"ValidateReviewColorspace": {
|
||||
"enabled": true,
|
||||
"optional": true,
|
||||
"active": true
|
||||
},
|
||||
"ValidateContainers": {
|
||||
"enabled": true,
|
||||
"optional": true,
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@
|
|||
"type": "schema_template",
|
||||
"name": "template_publish_plugin",
|
||||
"template_data": [
|
||||
{
|
||||
"key": "ValidateReviewColorspace",
|
||||
"label": "Validate Review Colorspace"
|
||||
},
|
||||
{
|
||||
"key": "ValidateContainers",
|
||||
"label": "ValidateContainers"
|
||||
|
|
@ -47,4 +51,4 @@
|
|||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ class ScreenMarquee(QtWidgets.QDialog):
|
|||
fade_anim.setEndValue(50)
|
||||
fade_anim.setDuration(200)
|
||||
fade_anim.setEasingCurve(QtCore.QEasingCurve.OutCubic)
|
||||
fade_anim.start(QtCore.QAbstractAnimation.DeleteWhenStopped)
|
||||
|
||||
fade_anim.valueChanged.connect(self._on_fade_anim)
|
||||
|
||||
|
|
@ -46,7 +45,7 @@ class ScreenMarquee(QtWidgets.QDialog):
|
|||
for screen in QtWidgets.QApplication.screens():
|
||||
screen.geometryChanged.connect(self._fit_screen_geometry)
|
||||
|
||||
self._opacity = fade_anim.currentValue()
|
||||
self._opacity = fade_anim.startValue()
|
||||
self._click_pos = None
|
||||
self._capture_rect = None
|
||||
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ class ValidateWorkfilePathsModel(BaseSettingsModel):
|
|||
)
|
||||
|
||||
|
||||
class ValidateContainersModel(BaseSettingsModel):
|
||||
class BasicValidateModel(BaseSettingsModel):
|
||||
enabled: bool = Field(title="Enabled")
|
||||
optional: bool = Field(title="Optional")
|
||||
active: bool = Field(title="Active")
|
||||
|
|
@ -130,8 +130,11 @@ class PublishPluginsModel(BaseSettingsModel):
|
|||
ValidateWorkfilePaths: ValidateWorkfilePathsModel = Field(
|
||||
default_factory=ValidateWorkfilePathsModel,
|
||||
title="Validate workfile paths settings.")
|
||||
ValidateContainers: ValidateContainersModel = Field(
|
||||
default_factory=ValidateContainersModel,
|
||||
ValidateReviewColorspace: BasicValidateModel = Field(
|
||||
default_factory=BasicValidateModel,
|
||||
title="Validate Review Colorspace.")
|
||||
ValidateContainers: BasicValidateModel = Field(
|
||||
default_factory=BasicValidateModel,
|
||||
title="Validate Latest Containers.")
|
||||
|
||||
|
||||
|
|
@ -148,6 +151,11 @@ DEFAULT_HOUDINI_PUBLISH_SETTINGS = {
|
|||
"$JOB"
|
||||
]
|
||||
},
|
||||
"ValidateReviewColorspace": {
|
||||
"enabled": True,
|
||||
"optional": True,
|
||||
"active": True
|
||||
},
|
||||
"ValidateContainers": {
|
||||
"enabled": True,
|
||||
"optional": True,
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
__version__ = "0.1.1"
|
||||
__version__ = "0.1.2"
|
||||
|
|
|
|||
|
|
@ -28,10 +28,9 @@ class TestPipelineColorspace(TestPipeline):
|
|||
cd to OpenPype repo root dir
|
||||
poetry run python ./start.py runtests ../tests/unit/openpype/pipeline
|
||||
"""
|
||||
|
||||
TEST_FILES = [
|
||||
(
|
||||
"1Lf-mFxev7xiwZCWfImlRcw7Fj8XgNQMh",
|
||||
"1csqimz8bbNcNgxtEXklLz6GRv91D3KgA",
|
||||
"test_pipeline_colorspace.zip",
|
||||
""
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue