mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge pull request #5541 from ynput/enhancement/OP-6154_Publishing-Luts
This commit is contained in:
commit
6f22344fb5
13 changed files with 1202 additions and 21 deletions
350
openpype/hosts/nuke/plugins/load/load_ociolook.py
Normal file
350
openpype/hosts/nuke/plugins/load/load_ociolook.py
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
import os
|
||||
import json
|
||||
import secrets
|
||||
import nuke
|
||||
import six
|
||||
|
||||
from openpype.client import (
|
||||
get_version_by_id,
|
||||
get_last_version_by_subset_id
|
||||
)
|
||||
from openpype.pipeline import (
|
||||
load,
|
||||
get_current_project_name,
|
||||
get_representation_path,
|
||||
)
|
||||
from openpype.hosts.nuke.api import (
|
||||
containerise,
|
||||
viewer_update_and_undo_stop,
|
||||
update_container,
|
||||
)
|
||||
|
||||
|
||||
class LoadOcioLookNodes(load.LoaderPlugin):
|
||||
"""Loading Ocio look to the nuke.Node graph"""
|
||||
|
||||
families = ["ociolook"]
|
||||
representations = ["*"]
|
||||
extensions = {"json"}
|
||||
|
||||
label = "Load OcioLook [nodes]"
|
||||
order = 0
|
||||
icon = "cc"
|
||||
color = "white"
|
||||
ignore_attr = ["useLifetime"]
|
||||
|
||||
# plugin attributes
|
||||
current_node_color = "0x4ecd91ff"
|
||||
old_node_color = "0xd88467ff"
|
||||
|
||||
# json file variables
|
||||
schema_version = 1
|
||||
|
||||
def load(self, context, name, namespace, data):
|
||||
"""
|
||||
Loading function to get the soft effects to particular read node
|
||||
|
||||
Arguments:
|
||||
context (dict): context of version
|
||||
name (str): name of the version
|
||||
namespace (str): asset name
|
||||
data (dict): compulsory attribute > not used
|
||||
|
||||
Returns:
|
||||
nuke.Node: containerized nuke.Node object
|
||||
"""
|
||||
namespace = namespace or context['asset']['name']
|
||||
suffix = secrets.token_hex(nbytes=4)
|
||||
object_name = "{}_{}_{}".format(
|
||||
name, namespace, suffix)
|
||||
|
||||
# getting file path
|
||||
filepath = self.filepath_from_context(context)
|
||||
|
||||
json_f = self._load_json_data(filepath)
|
||||
|
||||
group_node = self._create_group_node(
|
||||
object_name, filepath, json_f["data"])
|
||||
|
||||
self._node_version_color(context["version"], group_node)
|
||||
|
||||
self.log.info(
|
||||
"Loaded lut setup: `{}`".format(group_node["name"].value()))
|
||||
|
||||
return containerise(
|
||||
node=group_node,
|
||||
name=name,
|
||||
namespace=namespace,
|
||||
context=context,
|
||||
loader=self.__class__.__name__,
|
||||
data={
|
||||
"objectName": object_name,
|
||||
}
|
||||
)
|
||||
|
||||
def _create_group_node(
|
||||
self,
|
||||
object_name,
|
||||
filepath,
|
||||
data
|
||||
):
|
||||
"""Creates group node with all the nodes inside.
|
||||
|
||||
Creating mainly `OCIOFileTransform` nodes with `OCIOColorSpace` nodes
|
||||
in between - in case those are needed.
|
||||
|
||||
Arguments:
|
||||
object_name (str): name of the group node
|
||||
filepath (str): path to json file
|
||||
data (dict): data from json file
|
||||
|
||||
Returns:
|
||||
nuke.Node: group node with all the nodes inside
|
||||
"""
|
||||
# get corresponding node
|
||||
|
||||
root_working_colorspace = nuke.root()["workingSpaceLUT"].value()
|
||||
|
||||
dir_path = os.path.dirname(filepath)
|
||||
all_files = os.listdir(dir_path)
|
||||
|
||||
ocio_working_colorspace = _colorspace_name_by_type(
|
||||
data["ocioLookWorkingSpace"])
|
||||
|
||||
# adding nodes to node graph
|
||||
# just in case we are in group lets jump out of it
|
||||
nuke.endGroup()
|
||||
|
||||
input_node = None
|
||||
output_node = None
|
||||
group_node = nuke.toNode(object_name)
|
||||
if group_node:
|
||||
# remove all nodes between Input and Output nodes
|
||||
for node in group_node.nodes():
|
||||
if node.Class() not in ["Input", "Output"]:
|
||||
nuke.delete(node)
|
||||
elif node.Class() == "Input":
|
||||
input_node = node
|
||||
elif node.Class() == "Output":
|
||||
output_node = node
|
||||
else:
|
||||
group_node = nuke.createNode(
|
||||
"Group",
|
||||
"name {}_1".format(object_name),
|
||||
inpanel=False
|
||||
)
|
||||
|
||||
# adding content to the group node
|
||||
with group_node:
|
||||
pre_colorspace = root_working_colorspace
|
||||
|
||||
# reusing input node if it exists during update
|
||||
if input_node:
|
||||
pre_node = input_node
|
||||
else:
|
||||
pre_node = nuke.createNode("Input")
|
||||
pre_node["name"].setValue("rgb")
|
||||
|
||||
# Compare script working colorspace with ocio working colorspace
|
||||
# found in json file and convert to json's if needed
|
||||
if pre_colorspace != ocio_working_colorspace:
|
||||
pre_node = _add_ocio_colorspace_node(
|
||||
pre_node,
|
||||
pre_colorspace,
|
||||
ocio_working_colorspace
|
||||
)
|
||||
pre_colorspace = ocio_working_colorspace
|
||||
|
||||
for ocio_item in data["ocioLookItems"]:
|
||||
input_space = _colorspace_name_by_type(
|
||||
ocio_item["input_colorspace"])
|
||||
output_space = _colorspace_name_by_type(
|
||||
ocio_item["output_colorspace"])
|
||||
|
||||
# making sure we are set to correct colorspace for otio item
|
||||
if pre_colorspace != input_space:
|
||||
pre_node = _add_ocio_colorspace_node(
|
||||
pre_node,
|
||||
pre_colorspace,
|
||||
input_space
|
||||
)
|
||||
|
||||
node = nuke.createNode("OCIOFileTransform")
|
||||
|
||||
# file path from lut representation
|
||||
extension = ocio_item["ext"]
|
||||
item_name = ocio_item["name"]
|
||||
|
||||
item_lut_file = next(
|
||||
(
|
||||
file for file in all_files
|
||||
if file.endswith(extension)
|
||||
),
|
||||
None
|
||||
)
|
||||
if not item_lut_file:
|
||||
raise ValueError(
|
||||
"File with extension '{}' not "
|
||||
"found in directory".format(extension)
|
||||
)
|
||||
|
||||
item_lut_path = os.path.join(
|
||||
dir_path, item_lut_file).replace("\\", "/")
|
||||
node["file"].setValue(item_lut_path)
|
||||
node["name"].setValue(item_name)
|
||||
node["direction"].setValue(ocio_item["direction"])
|
||||
node["interpolation"].setValue(ocio_item["interpolation"])
|
||||
node["working_space"].setValue(input_space)
|
||||
|
||||
pre_node.autoplace()
|
||||
node.setInput(0, pre_node)
|
||||
node.autoplace()
|
||||
# pass output space into pre_colorspace for next iteration
|
||||
# or for output node comparison
|
||||
pre_colorspace = output_space
|
||||
pre_node = node
|
||||
|
||||
# making sure we are back in script working colorspace
|
||||
if pre_colorspace != root_working_colorspace:
|
||||
pre_node = _add_ocio_colorspace_node(
|
||||
pre_node,
|
||||
pre_colorspace,
|
||||
root_working_colorspace
|
||||
)
|
||||
|
||||
# reusing output node if it exists during update
|
||||
if not output_node:
|
||||
output = nuke.createNode("Output")
|
||||
else:
|
||||
output = output_node
|
||||
|
||||
output.setInput(0, pre_node)
|
||||
|
||||
return group_node
|
||||
|
||||
def update(self, container, representation):
|
||||
|
||||
project_name = get_current_project_name()
|
||||
version_doc = get_version_by_id(project_name, representation["parent"])
|
||||
|
||||
object_name = container['objectName']
|
||||
|
||||
filepath = get_representation_path(representation)
|
||||
|
||||
json_f = self._load_json_data(filepath)
|
||||
|
||||
group_node = self._create_group_node(
|
||||
object_name,
|
||||
filepath,
|
||||
json_f["data"]
|
||||
)
|
||||
|
||||
self._node_version_color(version_doc, group_node)
|
||||
|
||||
self.log.info("Updated lut setup: `{}`".format(
|
||||
group_node["name"].value()))
|
||||
|
||||
return update_container(
|
||||
group_node, {"representation": str(representation["_id"])})
|
||||
|
||||
def _load_json_data(self, filepath):
|
||||
# getting data from json file with unicode conversion
|
||||
with open(filepath, "r") as _file:
|
||||
json_f = {self._bytify(key): self._bytify(value)
|
||||
for key, value in json.load(_file).items()}
|
||||
|
||||
# check if the version in json_f is the same as plugin version
|
||||
if json_f["version"] != self.schema_version:
|
||||
raise KeyError(
|
||||
"Version of json file is not the same as plugin version")
|
||||
|
||||
return json_f
|
||||
|
||||
def _bytify(self, input):
|
||||
"""
|
||||
Converts unicode strings to strings
|
||||
It goes through all dictionary
|
||||
|
||||
Arguments:
|
||||
input (dict/str): input
|
||||
|
||||
Returns:
|
||||
dict: with fixed values and keys
|
||||
|
||||
"""
|
||||
|
||||
if isinstance(input, dict):
|
||||
return {self._bytify(key): self._bytify(value)
|
||||
for key, value in input.items()}
|
||||
elif isinstance(input, list):
|
||||
return [self._bytify(element) for element in input]
|
||||
elif isinstance(input, six.text_type):
|
||||
return str(input)
|
||||
else:
|
||||
return input
|
||||
|
||||
def switch(self, container, representation):
|
||||
self.update(container, representation)
|
||||
|
||||
def remove(self, container):
|
||||
node = nuke.toNode(container['objectName'])
|
||||
with viewer_update_and_undo_stop():
|
||||
nuke.delete(node)
|
||||
|
||||
def _node_version_color(self, version, node):
|
||||
""" Coloring a node by correct color by actual version"""
|
||||
|
||||
project_name = get_current_project_name()
|
||||
last_version_doc = get_last_version_by_subset_id(
|
||||
project_name, version["parent"], fields=["_id"]
|
||||
)
|
||||
|
||||
# change color of node
|
||||
if version["_id"] == last_version_doc["_id"]:
|
||||
color_value = self.current_node_color
|
||||
else:
|
||||
color_value = self.old_node_color
|
||||
node["tile_color"].setValue(int(color_value, 16))
|
||||
|
||||
|
||||
def _colorspace_name_by_type(colorspace_data):
|
||||
"""
|
||||
Returns colorspace name by type
|
||||
|
||||
Arguments:
|
||||
colorspace_data (dict): colorspace data
|
||||
|
||||
Returns:
|
||||
str: colorspace name
|
||||
"""
|
||||
if colorspace_data["type"] == "colorspaces":
|
||||
return colorspace_data["name"]
|
||||
elif colorspace_data["type"] == "roles":
|
||||
return colorspace_data["colorspace"]
|
||||
else:
|
||||
raise KeyError("Unknown colorspace type: {}".format(
|
||||
colorspace_data["type"]))
|
||||
|
||||
|
||||
def _add_ocio_colorspace_node(pre_node, input_space, output_space):
|
||||
"""
|
||||
Adds OCIOColorSpace node to the node graph
|
||||
|
||||
Arguments:
|
||||
pre_node (nuke.Node): node to connect to
|
||||
input_space (str): input colorspace
|
||||
output_space (str): output colorspace
|
||||
|
||||
Returns:
|
||||
nuke.Node: node with OCIOColorSpace node
|
||||
"""
|
||||
node = nuke.createNode("OCIOColorSpace")
|
||||
node.setInput(0, pre_node)
|
||||
node["in_colorspace"].setValue(input_space)
|
||||
node["out_colorspace"].setValue(output_space)
|
||||
|
||||
pre_node.autoplace()
|
||||
node.setInput(0, pre_node)
|
||||
node.autoplace()
|
||||
|
||||
return node
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Creator of colorspace look files.
|
||||
|
||||
This creator is used to publish colorspace look files thanks to
|
||||
production type `ociolook`. All files are published as representation.
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
from openpype.client import get_asset_by_name
|
||||
from openpype.lib.attribute_definitions import (
|
||||
FileDef, EnumDef, TextDef, UISeparatorDef
|
||||
)
|
||||
from openpype.pipeline import (
|
||||
CreatedInstance,
|
||||
CreatorError
|
||||
)
|
||||
from openpype.pipeline import colorspace
|
||||
from openpype.hosts.traypublisher.api.plugin import TrayPublishCreator
|
||||
|
||||
|
||||
class CreateColorspaceLook(TrayPublishCreator):
|
||||
"""Creates colorspace look files."""
|
||||
|
||||
identifier = "io.openpype.creators.traypublisher.colorspace_look"
|
||||
label = "Colorspace Look"
|
||||
family = "ociolook"
|
||||
description = "Publishes color space look file."
|
||||
extensions = [".cc", ".cube", ".3dl", ".spi1d", ".spi3d", ".csp", ".lut"]
|
||||
enabled = False
|
||||
|
||||
colorspace_items = [
|
||||
(None, "Not set")
|
||||
]
|
||||
colorspace_attr_show = False
|
||||
config_items = None
|
||||
config_data = None
|
||||
|
||||
def get_detail_description(self):
|
||||
return """# Colorspace Look
|
||||
|
||||
This creator publishes color space look file (LUT).
|
||||
"""
|
||||
|
||||
def get_icon(self):
|
||||
return "mdi.format-color-fill"
|
||||
|
||||
def create(self, subset_name, instance_data, pre_create_data):
|
||||
repr_file = pre_create_data.get("luts_file")
|
||||
if not repr_file:
|
||||
raise CreatorError("No files specified")
|
||||
|
||||
files = repr_file.get("filenames")
|
||||
if not files:
|
||||
# this should never happen
|
||||
raise CreatorError("Missing files from representation")
|
||||
|
||||
asset_doc = get_asset_by_name(
|
||||
self.project_name, instance_data["asset"])
|
||||
|
||||
subset_name = self.get_subset_name(
|
||||
variant=instance_data["variant"],
|
||||
task_name=instance_data["task"] or "Not set",
|
||||
project_name=self.project_name,
|
||||
asset_doc=asset_doc,
|
||||
)
|
||||
|
||||
instance_data["creator_attributes"] = {
|
||||
"abs_lut_path": (
|
||||
Path(repr_file["directory"]) / files[0]).as_posix()
|
||||
}
|
||||
|
||||
# Create new instance
|
||||
new_instance = CreatedInstance(self.family, subset_name,
|
||||
instance_data, self)
|
||||
new_instance.transient_data["config_items"] = self.config_items
|
||||
new_instance.transient_data["config_data"] = self.config_data
|
||||
|
||||
self._store_new_instance(new_instance)
|
||||
|
||||
def collect_instances(self):
|
||||
super().collect_instances()
|
||||
for instance in self.create_context.instances:
|
||||
if instance.creator_identifier == self.identifier:
|
||||
instance.transient_data["config_items"] = self.config_items
|
||||
instance.transient_data["config_data"] = self.config_data
|
||||
|
||||
def get_instance_attr_defs(self):
|
||||
return [
|
||||
EnumDef(
|
||||
"working_colorspace",
|
||||
self.colorspace_items,
|
||||
default="Not set",
|
||||
label="Working Colorspace",
|
||||
),
|
||||
UISeparatorDef(
|
||||
label="Advanced1"
|
||||
),
|
||||
TextDef(
|
||||
"abs_lut_path",
|
||||
label="LUT Path",
|
||||
),
|
||||
EnumDef(
|
||||
"input_colorspace",
|
||||
self.colorspace_items,
|
||||
default="Not set",
|
||||
label="Input Colorspace",
|
||||
),
|
||||
EnumDef(
|
||||
"direction",
|
||||
[
|
||||
(None, "Not set"),
|
||||
("forward", "Forward"),
|
||||
("inverse", "Inverse")
|
||||
],
|
||||
default="Not set",
|
||||
label="Direction"
|
||||
),
|
||||
EnumDef(
|
||||
"interpolation",
|
||||
[
|
||||
(None, "Not set"),
|
||||
("linear", "Linear"),
|
||||
("tetrahedral", "Tetrahedral"),
|
||||
("best", "Best"),
|
||||
("nearest", "Nearest")
|
||||
],
|
||||
default="Not set",
|
||||
label="Interpolation"
|
||||
),
|
||||
EnumDef(
|
||||
"output_colorspace",
|
||||
self.colorspace_items,
|
||||
default="Not set",
|
||||
label="Output Colorspace",
|
||||
),
|
||||
]
|
||||
|
||||
def get_pre_create_attr_defs(self):
|
||||
return [
|
||||
FileDef(
|
||||
"luts_file",
|
||||
folders=False,
|
||||
extensions=self.extensions,
|
||||
allow_sequences=False,
|
||||
single_item=True,
|
||||
label="Look Files",
|
||||
)
|
||||
]
|
||||
|
||||
def apply_settings(self, project_settings, system_settings):
|
||||
host = self.create_context.host
|
||||
host_name = host.name
|
||||
project_name = host.get_current_project_name()
|
||||
config_data = colorspace.get_imageio_config(
|
||||
project_name, host_name,
|
||||
project_settings=project_settings
|
||||
)
|
||||
|
||||
if not config_data:
|
||||
self.enabled = False
|
||||
return
|
||||
|
||||
filepath = config_data["path"]
|
||||
config_items = colorspace.get_ocio_config_colorspaces(filepath)
|
||||
labeled_colorspaces = colorspace.get_colorspaces_enumerator_items(
|
||||
config_items,
|
||||
include_aliases=True,
|
||||
include_roles=True
|
||||
)
|
||||
self.config_items = config_items
|
||||
self.config_data = config_data
|
||||
self.colorspace_items.extend(labeled_colorspaces)
|
||||
self.enabled = True
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
import os
|
||||
from pprint import pformat
|
||||
import pyblish.api
|
||||
from openpype.pipeline import publish
|
||||
from openpype.pipeline import colorspace
|
||||
|
||||
|
||||
class CollectColorspaceLook(pyblish.api.InstancePlugin,
|
||||
publish.OpenPypePyblishPluginMixin):
|
||||
"""Collect OCIO colorspace look from LUT file
|
||||
"""
|
||||
|
||||
label = "Collect Colorspace Look"
|
||||
order = pyblish.api.CollectorOrder
|
||||
hosts = ["traypublisher"]
|
||||
families = ["ociolook"]
|
||||
|
||||
def process(self, instance):
|
||||
creator_attrs = instance.data["creator_attributes"]
|
||||
|
||||
lut_repre_name = "LUTfile"
|
||||
file_url = creator_attrs["abs_lut_path"]
|
||||
file_name = os.path.basename(file_url)
|
||||
base_name, ext = os.path.splitext(file_name)
|
||||
|
||||
# set output name with base_name which was cleared
|
||||
# of all symbols and all parts were capitalized
|
||||
output_name = (base_name.replace("_", " ")
|
||||
.replace(".", " ")
|
||||
.replace("-", " ")
|
||||
.title()
|
||||
.replace(" ", ""))
|
||||
|
||||
# get config items
|
||||
config_items = instance.data["transientData"]["config_items"]
|
||||
config_data = instance.data["transientData"]["config_data"]
|
||||
|
||||
# get colorspace items
|
||||
converted_color_data = {}
|
||||
for colorspace_key in [
|
||||
"working_colorspace",
|
||||
"input_colorspace",
|
||||
"output_colorspace"
|
||||
]:
|
||||
if creator_attrs[colorspace_key]:
|
||||
color_data = colorspace.convert_colorspace_enumerator_item(
|
||||
creator_attrs[colorspace_key], config_items)
|
||||
converted_color_data[colorspace_key] = color_data
|
||||
else:
|
||||
converted_color_data[colorspace_key] = None
|
||||
|
||||
# add colorspace to config data
|
||||
if converted_color_data["working_colorspace"]:
|
||||
config_data["colorspace"] = (
|
||||
converted_color_data["working_colorspace"]["name"]
|
||||
)
|
||||
|
||||
# create lut representation data
|
||||
lut_repre = {
|
||||
"name": lut_repre_name,
|
||||
"output": output_name,
|
||||
"ext": ext.lstrip("."),
|
||||
"files": file_name,
|
||||
"stagingDir": os.path.dirname(file_url),
|
||||
"tags": []
|
||||
}
|
||||
instance.data.update({
|
||||
"representations": [lut_repre],
|
||||
"source": file_url,
|
||||
"ocioLookWorkingSpace": converted_color_data["working_colorspace"],
|
||||
"ocioLookItems": [
|
||||
{
|
||||
"name": lut_repre_name,
|
||||
"ext": ext.lstrip("."),
|
||||
"input_colorspace": converted_color_data[
|
||||
"input_colorspace"],
|
||||
"output_colorspace": converted_color_data[
|
||||
"output_colorspace"],
|
||||
"direction": creator_attrs["direction"],
|
||||
"interpolation": creator_attrs["interpolation"],
|
||||
"config_data": config_data
|
||||
}
|
||||
],
|
||||
})
|
||||
|
||||
self.log.debug(pformat(instance.data))
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
import pyblish.api
|
||||
from openpype.pipeline import registered_host
|
||||
from openpype.pipeline import publish
|
||||
from openpype.pipeline import (
|
||||
publish,
|
||||
registered_host
|
||||
)
|
||||
from openpype.lib import EnumDef
|
||||
from openpype.pipeline import colorspace
|
||||
|
||||
|
|
@ -13,11 +15,14 @@ class CollectColorspace(pyblish.api.InstancePlugin,
|
|||
label = "Choose representation colorspace"
|
||||
order = pyblish.api.CollectorOrder + 0.49
|
||||
hosts = ["traypublisher"]
|
||||
families = ["render", "plate", "reference", "image", "online"]
|
||||
enabled = False
|
||||
|
||||
colorspace_items = [
|
||||
(None, "Don't override")
|
||||
]
|
||||
colorspace_attr_show = False
|
||||
config_items = None
|
||||
|
||||
def process(self, instance):
|
||||
values = self.get_attr_values_from_data(instance.data)
|
||||
|
|
@ -48,10 +53,14 @@ class CollectColorspace(pyblish.api.InstancePlugin,
|
|||
if config_data:
|
||||
filepath = config_data["path"]
|
||||
config_items = colorspace.get_ocio_config_colorspaces(filepath)
|
||||
cls.colorspace_items.extend((
|
||||
(name, name) for name in config_items.keys()
|
||||
))
|
||||
cls.colorspace_attr_show = True
|
||||
labeled_colorspaces = colorspace.get_colorspaces_enumerator_items(
|
||||
config_items,
|
||||
include_aliases=True,
|
||||
include_roles=True
|
||||
)
|
||||
cls.config_items = config_items
|
||||
cls.colorspace_items.extend(labeled_colorspaces)
|
||||
cls.enabled = True
|
||||
|
||||
@classmethod
|
||||
def get_attribute_defs(cls):
|
||||
|
|
@ -60,7 +69,6 @@ class CollectColorspace(pyblish.api.InstancePlugin,
|
|||
"colorspace",
|
||||
cls.colorspace_items,
|
||||
default="Don't override",
|
||||
label="Override Colorspace",
|
||||
hidden=not cls.colorspace_attr_show
|
||||
label="Override Colorspace"
|
||||
)
|
||||
]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
import os
|
||||
import json
|
||||
import pyblish.api
|
||||
from openpype.pipeline import publish
|
||||
|
||||
|
||||
class ExtractColorspaceLook(publish.Extractor,
|
||||
publish.OpenPypePyblishPluginMixin):
|
||||
"""Extract OCIO colorspace look from LUT file
|
||||
"""
|
||||
|
||||
label = "Extract Colorspace Look"
|
||||
order = pyblish.api.ExtractorOrder
|
||||
hosts = ["traypublisher"]
|
||||
families = ["ociolook"]
|
||||
|
||||
def process(self, instance):
|
||||
ociolook_items = instance.data["ocioLookItems"]
|
||||
ociolook_working_color = instance.data["ocioLookWorkingSpace"]
|
||||
staging_dir = self.staging_dir(instance)
|
||||
|
||||
# create ociolook file attributes
|
||||
ociolook_file_name = "ocioLookFile.json"
|
||||
ociolook_file_content = {
|
||||
"version": 1,
|
||||
"data": {
|
||||
"ocioLookItems": ociolook_items,
|
||||
"ocioLookWorkingSpace": ociolook_working_color
|
||||
}
|
||||
}
|
||||
|
||||
# write ociolook content into json file saved in staging dir
|
||||
file_url = os.path.join(staging_dir, ociolook_file_name)
|
||||
with open(file_url, "w") as f_:
|
||||
json.dump(ociolook_file_content, f_, indent=4)
|
||||
|
||||
# create lut representation data
|
||||
ociolook_repre = {
|
||||
"name": "ocioLookFile",
|
||||
"ext": "json",
|
||||
"files": ociolook_file_name,
|
||||
"stagingDir": staging_dir,
|
||||
"tags": []
|
||||
}
|
||||
instance.data["representations"].append(ociolook_repre)
|
||||
|
|
@ -18,6 +18,7 @@ class ValidateColorspace(pyblish.api.InstancePlugin,
|
|||
label = "Validate representation colorspace"
|
||||
order = pyblish.api.ValidatorOrder
|
||||
hosts = ["traypublisher"]
|
||||
families = ["render", "plate", "reference", "image", "online"]
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
import pyblish.api
|
||||
|
||||
from openpype.pipeline import (
|
||||
publish,
|
||||
PublishValidationError
|
||||
)
|
||||
|
||||
|
||||
class ValidateColorspaceLook(pyblish.api.InstancePlugin,
|
||||
publish.OpenPypePyblishPluginMixin):
|
||||
"""Validate colorspace look attributes"""
|
||||
|
||||
label = "Validate colorspace look attributes"
|
||||
order = pyblish.api.ValidatorOrder
|
||||
hosts = ["traypublisher"]
|
||||
families = ["ociolook"]
|
||||
|
||||
def process(self, instance):
|
||||
create_context = instance.context.data["create_context"]
|
||||
created_instance = create_context.get_instance_by_id(
|
||||
instance.data["instance_id"])
|
||||
creator_defs = created_instance.creator_attribute_defs
|
||||
|
||||
ociolook_working_color = instance.data.get("ocioLookWorkingSpace")
|
||||
ociolook_items = instance.data.get("ocioLookItems", [])
|
||||
|
||||
creator_defs_by_key = {_def.key: _def.label for _def in creator_defs}
|
||||
|
||||
not_set_keys = {}
|
||||
if not ociolook_working_color:
|
||||
not_set_keys["working_colorspace"] = creator_defs_by_key[
|
||||
"working_colorspace"]
|
||||
|
||||
for ociolook_item in ociolook_items:
|
||||
item_not_set_keys = self.validate_colorspace_set_attrs(
|
||||
ociolook_item, creator_defs_by_key)
|
||||
if item_not_set_keys:
|
||||
not_set_keys[ociolook_item["name"]] = item_not_set_keys
|
||||
|
||||
if not_set_keys:
|
||||
message = (
|
||||
"Colorspace look attributes are not set: \n"
|
||||
)
|
||||
for key, value in not_set_keys.items():
|
||||
if isinstance(value, list):
|
||||
values_string = "\n\t- ".join(value)
|
||||
message += f"\n\t{key}:\n\t- {values_string}"
|
||||
else:
|
||||
message += f"\n\t{value}"
|
||||
|
||||
raise PublishValidationError(
|
||||
title="Colorspace Look attributes",
|
||||
message=message,
|
||||
description=message
|
||||
)
|
||||
|
||||
def validate_colorspace_set_attrs(
|
||||
self,
|
||||
ociolook_item,
|
||||
creator_defs_by_key
|
||||
):
|
||||
"""Validate colorspace look attributes"""
|
||||
|
||||
self.log.debug(f"Validate colorspace look attributes: {ociolook_item}")
|
||||
|
||||
check_keys = [
|
||||
"input_colorspace",
|
||||
"output_colorspace",
|
||||
"direction",
|
||||
"interpolation"
|
||||
]
|
||||
|
||||
not_set_keys = []
|
||||
for key in check_keys:
|
||||
if ociolook_item[key]:
|
||||
# key is set and it is correct
|
||||
continue
|
||||
|
||||
def_label = creator_defs_by_key.get(key)
|
||||
|
||||
if not def_label:
|
||||
# raise since key is not recognized by creator defs
|
||||
raise KeyError(
|
||||
f"Colorspace look attribute '{key}' is not "
|
||||
f"recognized by creator attributes: {creator_defs_by_key}"
|
||||
)
|
||||
not_set_keys.append(def_label)
|
||||
|
||||
return not_set_keys
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
from copy import deepcopy
|
||||
import re
|
||||
import os
|
||||
import json
|
||||
|
|
@ -7,6 +6,7 @@ import functools
|
|||
import platform
|
||||
import tempfile
|
||||
import warnings
|
||||
from copy import deepcopy
|
||||
|
||||
from openpype import PACKAGE_DIR
|
||||
from openpype.settings import get_project_settings
|
||||
|
|
@ -356,7 +356,10 @@ def parse_colorspace_from_filepath(
|
|||
"Must provide `config_path` if `colorspaces` is not provided."
|
||||
)
|
||||
|
||||
colorspaces = colorspaces or get_ocio_config_colorspaces(config_path)
|
||||
colorspaces = (
|
||||
colorspaces
|
||||
or get_ocio_config_colorspaces(config_path)["colorspaces"]
|
||||
)
|
||||
underscored_colorspaces = {
|
||||
key.replace(" ", "_"): key for key in colorspaces
|
||||
if " " in key
|
||||
|
|
@ -393,7 +396,7 @@ def validate_imageio_colorspace_in_config(config_path, colorspace_name):
|
|||
Returns:
|
||||
bool: True if exists
|
||||
"""
|
||||
colorspaces = get_ocio_config_colorspaces(config_path)
|
||||
colorspaces = get_ocio_config_colorspaces(config_path)["colorspaces"]
|
||||
if colorspace_name not in colorspaces:
|
||||
raise KeyError(
|
||||
"Missing colorspace '{}' in config file '{}'".format(
|
||||
|
|
@ -530,6 +533,157 @@ def get_ocio_config_colorspaces(config_path):
|
|||
return CachedData.ocio_config_colorspaces[config_path]
|
||||
|
||||
|
||||
def convert_colorspace_enumerator_item(
|
||||
colorspace_enum_item,
|
||||
config_items
|
||||
):
|
||||
"""Convert colorspace enumerator item to dictionary
|
||||
|
||||
Args:
|
||||
colorspace_item (str): colorspace and family in couple
|
||||
config_items (dict[str,dict]): colorspace data
|
||||
|
||||
Returns:
|
||||
dict: colorspace data
|
||||
"""
|
||||
if "::" not in colorspace_enum_item:
|
||||
return None
|
||||
|
||||
# split string with `::` separator and set first as key and second as value
|
||||
item_type, item_name = colorspace_enum_item.split("::")
|
||||
|
||||
item_data = None
|
||||
if item_type == "aliases":
|
||||
# loop through all colorspaces and find matching alias
|
||||
for name, _data in config_items.get("colorspaces", {}).items():
|
||||
if item_name in _data.get("aliases", []):
|
||||
item_data = deepcopy(_data)
|
||||
item_data.update({
|
||||
"name": name,
|
||||
"type": "colorspace"
|
||||
})
|
||||
break
|
||||
else:
|
||||
# find matching colorspace item found in labeled_colorspaces
|
||||
item_data = config_items.get(item_type, {}).get(item_name)
|
||||
if item_data:
|
||||
item_data = deepcopy(item_data)
|
||||
item_data.update({
|
||||
"name": item_name,
|
||||
"type": item_type
|
||||
})
|
||||
|
||||
# raise exception if item is not found
|
||||
if not item_data:
|
||||
message_config_keys = ", ".join(
|
||||
"'{}':{}".format(
|
||||
key,
|
||||
set(config_items.get(key, {}).keys())
|
||||
) for key in config_items.keys()
|
||||
)
|
||||
raise KeyError(
|
||||
"Missing colorspace item '{}' in config data: [{}]".format(
|
||||
colorspace_enum_item, message_config_keys
|
||||
)
|
||||
)
|
||||
|
||||
return item_data
|
||||
|
||||
|
||||
def get_colorspaces_enumerator_items(
|
||||
config_items,
|
||||
include_aliases=False,
|
||||
include_looks=False,
|
||||
include_roles=False,
|
||||
include_display_views=False
|
||||
):
|
||||
"""Get all colorspace data with labels
|
||||
|
||||
Wrapper function for aggregating all names and its families.
|
||||
Families can be used for building menu and submenus in gui.
|
||||
|
||||
Args:
|
||||
config_items (dict[str,dict]): colorspace data coming from
|
||||
`get_ocio_config_colorspaces` function
|
||||
include_aliases (bool): include aliases in result
|
||||
include_looks (bool): include looks in result
|
||||
include_roles (bool): include roles in result
|
||||
|
||||
Returns:
|
||||
list[tuple[str,str]]: colorspace and family in couple
|
||||
"""
|
||||
labeled_colorspaces = []
|
||||
aliases = set()
|
||||
colorspaces = set()
|
||||
looks = set()
|
||||
roles = set()
|
||||
display_views = set()
|
||||
for items_type, colorspace_items in config_items.items():
|
||||
if items_type == "colorspaces":
|
||||
for color_name, color_data in colorspace_items.items():
|
||||
if color_data.get("aliases"):
|
||||
aliases.update([
|
||||
(
|
||||
"aliases::{}".format(alias_name),
|
||||
"[alias] {} ({})".format(alias_name, color_name)
|
||||
)
|
||||
for alias_name in color_data["aliases"]
|
||||
])
|
||||
colorspaces.add((
|
||||
"{}::{}".format(items_type, color_name),
|
||||
"[colorspace] {}".format(color_name)
|
||||
))
|
||||
|
||||
elif items_type == "looks":
|
||||
looks.update([
|
||||
(
|
||||
"{}::{}".format(items_type, name),
|
||||
"[look] {} ({})".format(name, role_data["process_space"])
|
||||
)
|
||||
for name, role_data in colorspace_items.items()
|
||||
])
|
||||
|
||||
elif items_type == "displays_views":
|
||||
display_views.update([
|
||||
(
|
||||
"{}::{}".format(items_type, name),
|
||||
"[view (display)] {}".format(name)
|
||||
)
|
||||
for name, _ in colorspace_items.items()
|
||||
])
|
||||
|
||||
elif items_type == "roles":
|
||||
roles.update([
|
||||
(
|
||||
"{}::{}".format(items_type, name),
|
||||
"[role] {} ({})".format(name, role_data["colorspace"])
|
||||
)
|
||||
for name, role_data in colorspace_items.items()
|
||||
])
|
||||
|
||||
if roles and include_roles:
|
||||
roles = sorted(roles, key=lambda x: x[0])
|
||||
labeled_colorspaces.extend(roles)
|
||||
|
||||
# add colorspaces as second so it is not first in menu
|
||||
colorspaces = sorted(colorspaces, key=lambda x: x[0])
|
||||
labeled_colorspaces.extend(colorspaces)
|
||||
|
||||
if aliases and include_aliases:
|
||||
aliases = sorted(aliases, key=lambda x: x[0])
|
||||
labeled_colorspaces.extend(aliases)
|
||||
|
||||
if looks and include_looks:
|
||||
looks = sorted(looks, key=lambda x: x[0])
|
||||
labeled_colorspaces.extend(looks)
|
||||
|
||||
if display_views and include_display_views:
|
||||
display_views = sorted(display_views, key=lambda x: x[0])
|
||||
labeled_colorspaces.extend(display_views)
|
||||
|
||||
return labeled_colorspaces
|
||||
|
||||
|
||||
# TODO: remove this in future - backward compatibility
|
||||
@deprecated("_get_wrapped_with_subprocess")
|
||||
def get_colorspace_data_subprocess(config_path):
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
"rig",
|
||||
"plate",
|
||||
"look",
|
||||
"ociolook",
|
||||
"audio",
|
||||
"yetiRig",
|
||||
"yeticache",
|
||||
|
|
|
|||
|
|
@ -106,11 +106,47 @@ def _get_colorspace_data(config_path):
|
|||
|
||||
config = ocio.Config().CreateFromFile(str(config_path))
|
||||
|
||||
return {
|
||||
c_.getName(): c_.getFamily()
|
||||
for c_ in config.getColorSpaces()
|
||||
colorspace_data = {
|
||||
"roles": {},
|
||||
"colorspaces": {
|
||||
color.getName(): {
|
||||
"family": color.getFamily(),
|
||||
"categories": list(color.getCategories()),
|
||||
"aliases": list(color.getAliases()),
|
||||
"equalitygroup": color.getEqualityGroup(),
|
||||
}
|
||||
for color in config.getColorSpaces()
|
||||
},
|
||||
"displays_views": {
|
||||
f"{view} ({display})": {
|
||||
"display": display,
|
||||
"view": view
|
||||
|
||||
}
|
||||
for display in config.getDisplays()
|
||||
for view in config.getViews(display)
|
||||
},
|
||||
"looks": {}
|
||||
}
|
||||
|
||||
# add looks
|
||||
looks = config.getLooks()
|
||||
if looks:
|
||||
colorspace_data["looks"] = {
|
||||
look.getName(): {"process_space": look.getProcessSpace()}
|
||||
for look in looks
|
||||
}
|
||||
|
||||
# add roles
|
||||
roles = config.getRoles()
|
||||
if roles:
|
||||
colorspace_data["roles"] = {
|
||||
role: {"colorspace": colorspace}
|
||||
for (role, colorspace) in roles
|
||||
}
|
||||
|
||||
return colorspace_data
|
||||
|
||||
|
||||
@config.command(
|
||||
name="get_views",
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class TestPipelinePublishPlugins(TestPipeline):
|
|||
# files are the same as those used in `test_pipeline_colorspace`
|
||||
TEST_FILES = [
|
||||
(
|
||||
"1Lf-mFxev7xiwZCWfImlRcw7Fj8XgNQMh",
|
||||
"1csqimz8bbNcNgxtEXklLz6GRv91D3KgA",
|
||||
"test_pipeline_colorspace.zip",
|
||||
""
|
||||
)
|
||||
|
|
@ -123,8 +123,7 @@ class TestPipelinePublishPlugins(TestPipeline):
|
|||
|
||||
def test_get_colorspace_settings(self, context, config_path_asset):
|
||||
expected_config_template = (
|
||||
"{root[work]}/{project[name]}"
|
||||
"/{hierarchy}/{asset}/config/aces.ocio"
|
||||
"{root[work]}/{project[name]}/config/aces.ocio"
|
||||
)
|
||||
expected_file_rules = {
|
||||
"comp_review": {
|
||||
|
|
@ -177,16 +176,16 @@ class TestPipelinePublishPlugins(TestPipeline):
|
|||
# load plugin function for testing
|
||||
plugin = publish_plugins.ColormanagedPyblishPluginMixin()
|
||||
plugin.log = log
|
||||
context.data["imageioSettings"] = (config_data_nuke, file_rules_nuke)
|
||||
plugin.set_representation_colorspace(
|
||||
representation_nuke, context,
|
||||
colorspace_settings=(config_data_nuke, file_rules_nuke)
|
||||
representation_nuke, context
|
||||
)
|
||||
# load plugin function for testing
|
||||
plugin = publish_plugins.ColormanagedPyblishPluginMixin()
|
||||
plugin.log = log
|
||||
context.data["imageioSettings"] = (config_data_hiero, file_rules_hiero)
|
||||
plugin.set_representation_colorspace(
|
||||
representation_hiero, context,
|
||||
colorspace_settings=(config_data_hiero, file_rules_hiero)
|
||||
representation_hiero, context
|
||||
)
|
||||
|
||||
colorspace_data_nuke = representation_nuke.get("colorspaceData")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,118 @@
|
|||
import unittest
|
||||
from openpype.pipeline.colorspace import convert_colorspace_enumerator_item
|
||||
|
||||
|
||||
class TestConvertColorspaceEnumeratorItem(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.config_items = {
|
||||
"colorspaces": {
|
||||
"sRGB": {
|
||||
"aliases": ["sRGB_1"],
|
||||
"family": "colorspace",
|
||||
"categories": ["colors"],
|
||||
"equalitygroup": "equalitygroup",
|
||||
},
|
||||
"Rec.709": {
|
||||
"aliases": ["rec709_1", "rec709_2"],
|
||||
},
|
||||
},
|
||||
"looks": {
|
||||
"sRGB_to_Rec.709": {
|
||||
"process_space": "sRGB",
|
||||
},
|
||||
},
|
||||
"displays_views": {
|
||||
"sRGB (ACES)": {
|
||||
"view": "sRGB",
|
||||
"display": "ACES",
|
||||
},
|
||||
"Rec.709 (ACES)": {
|
||||
"view": "Rec.709",
|
||||
"display": "ACES",
|
||||
},
|
||||
},
|
||||
"roles": {
|
||||
"compositing_linear": {
|
||||
"colorspace": "linear",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
def test_valid_item(self):
|
||||
colorspace_item_data = convert_colorspace_enumerator_item(
|
||||
"colorspaces::sRGB", self.config_items)
|
||||
self.assertEqual(
|
||||
colorspace_item_data,
|
||||
{
|
||||
"name": "sRGB",
|
||||
"type": "colorspaces",
|
||||
"aliases": ["sRGB_1"],
|
||||
"family": "colorspace",
|
||||
"categories": ["colors"],
|
||||
"equalitygroup": "equalitygroup"
|
||||
}
|
||||
)
|
||||
|
||||
alias_item_data = convert_colorspace_enumerator_item(
|
||||
"aliases::rec709_1", self.config_items)
|
||||
self.assertEqual(
|
||||
alias_item_data,
|
||||
{
|
||||
"aliases": ["rec709_1", "rec709_2"],
|
||||
"name": "Rec.709",
|
||||
"type": "colorspace"
|
||||
}
|
||||
)
|
||||
|
||||
display_view_item_data = convert_colorspace_enumerator_item(
|
||||
"displays_views::sRGB (ACES)", self.config_items)
|
||||
self.assertEqual(
|
||||
display_view_item_data,
|
||||
{
|
||||
"type": "displays_views",
|
||||
"name": "sRGB (ACES)",
|
||||
"view": "sRGB",
|
||||
"display": "ACES"
|
||||
}
|
||||
)
|
||||
|
||||
role_item_data = convert_colorspace_enumerator_item(
|
||||
"roles::compositing_linear", self.config_items)
|
||||
self.assertEqual(
|
||||
role_item_data,
|
||||
{
|
||||
"name": "compositing_linear",
|
||||
"type": "roles",
|
||||
"colorspace": "linear"
|
||||
}
|
||||
)
|
||||
|
||||
look_item_data = convert_colorspace_enumerator_item(
|
||||
"looks::sRGB_to_Rec.709", self.config_items)
|
||||
self.assertEqual(
|
||||
look_item_data,
|
||||
{
|
||||
"type": "looks",
|
||||
"name": "sRGB_to_Rec.709",
|
||||
"process_space": "sRGB"
|
||||
}
|
||||
)
|
||||
|
||||
def test_invalid_item(self):
|
||||
config_items = {
|
||||
"RGB": {
|
||||
"sRGB": {"red": 255, "green": 255, "blue": 255},
|
||||
"AdobeRGB": {"red": 255, "green": 255, "blue": 255},
|
||||
}
|
||||
}
|
||||
with self.assertRaises(KeyError):
|
||||
convert_colorspace_enumerator_item("RGB::invalid", config_items)
|
||||
|
||||
def test_missing_config_data(self):
|
||||
config_items = {}
|
||||
with self.assertRaises(KeyError):
|
||||
convert_colorspace_enumerator_item("RGB::sRGB", config_items)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
import unittest
|
||||
|
||||
from openpype.pipeline.colorspace import get_colorspaces_enumerator_items
|
||||
|
||||
|
||||
class TestGetColorspacesEnumeratorItems(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.config_items = {
|
||||
"colorspaces": {
|
||||
"sRGB": {
|
||||
"aliases": ["sRGB_1"],
|
||||
},
|
||||
"Rec.709": {
|
||||
"aliases": ["rec709_1", "rec709_2"],
|
||||
},
|
||||
},
|
||||
"looks": {
|
||||
"sRGB_to_Rec.709": {
|
||||
"process_space": "sRGB",
|
||||
},
|
||||
},
|
||||
"displays_views": {
|
||||
"sRGB (ACES)": {
|
||||
"view": "sRGB",
|
||||
"display": "ACES",
|
||||
},
|
||||
"Rec.709 (ACES)": {
|
||||
"view": "Rec.709",
|
||||
"display": "ACES",
|
||||
},
|
||||
},
|
||||
"roles": {
|
||||
"compositing_linear": {
|
||||
"colorspace": "linear",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
def test_colorspaces(self):
|
||||
result = get_colorspaces_enumerator_items(self.config_items)
|
||||
expected = [
|
||||
("colorspaces::Rec.709", "[colorspace] Rec.709"),
|
||||
("colorspaces::sRGB", "[colorspace] sRGB"),
|
||||
]
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_aliases(self):
|
||||
result = get_colorspaces_enumerator_items(
|
||||
self.config_items, include_aliases=True)
|
||||
expected = [
|
||||
("colorspaces::Rec.709", "[colorspace] Rec.709"),
|
||||
("colorspaces::sRGB", "[colorspace] sRGB"),
|
||||
("aliases::rec709_1", "[alias] rec709_1 (Rec.709)"),
|
||||
("aliases::rec709_2", "[alias] rec709_2 (Rec.709)"),
|
||||
("aliases::sRGB_1", "[alias] sRGB_1 (sRGB)"),
|
||||
]
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_looks(self):
|
||||
result = get_colorspaces_enumerator_items(
|
||||
self.config_items, include_looks=True)
|
||||
expected = [
|
||||
("colorspaces::Rec.709", "[colorspace] Rec.709"),
|
||||
("colorspaces::sRGB", "[colorspace] sRGB"),
|
||||
("looks::sRGB_to_Rec.709", "[look] sRGB_to_Rec.709 (sRGB)"),
|
||||
]
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_display_views(self):
|
||||
result = get_colorspaces_enumerator_items(
|
||||
self.config_items, include_display_views=True)
|
||||
expected = [
|
||||
("colorspaces::Rec.709", "[colorspace] Rec.709"),
|
||||
("colorspaces::sRGB", "[colorspace] sRGB"),
|
||||
("displays_views::Rec.709 (ACES)", "[view (display)] Rec.709 (ACES)"), # noqa: E501
|
||||
("displays_views::sRGB (ACES)", "[view (display)] sRGB (ACES)"),
|
||||
|
||||
]
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_roles(self):
|
||||
result = get_colorspaces_enumerator_items(
|
||||
self.config_items, include_roles=True)
|
||||
expected = [
|
||||
("roles::compositing_linear", "[role] compositing_linear (linear)"), # noqa: E501
|
||||
("colorspaces::Rec.709", "[colorspace] Rec.709"),
|
||||
("colorspaces::sRGB", "[colorspace] sRGB"),
|
||||
]
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_all(self):
|
||||
message_config_keys = ", ".join(
|
||||
"'{}':{}".format(
|
||||
key,
|
||||
set(self.config_items.get(key, {}).keys())
|
||||
) for key in self.config_items.keys()
|
||||
)
|
||||
print("Testing with config: [{}]".format(message_config_keys))
|
||||
result = get_colorspaces_enumerator_items(
|
||||
self.config_items,
|
||||
include_aliases=True,
|
||||
include_looks=True,
|
||||
include_roles=True,
|
||||
include_display_views=True,
|
||||
)
|
||||
expected = [
|
||||
("roles::compositing_linear", "[role] compositing_linear (linear)"), # noqa: E501
|
||||
("colorspaces::Rec.709", "[colorspace] Rec.709"),
|
||||
("colorspaces::sRGB", "[colorspace] sRGB"),
|
||||
("aliases::rec709_1", "[alias] rec709_1 (Rec.709)"),
|
||||
("aliases::rec709_2", "[alias] rec709_2 (Rec.709)"),
|
||||
("aliases::sRGB_1", "[alias] sRGB_1 (sRGB)"),
|
||||
("looks::sRGB_to_Rec.709", "[look] sRGB_to_Rec.709 (sRGB)"),
|
||||
("displays_views::Rec.709 (ACES)", "[view (display)] Rec.709 (ACES)"), # noqa: E501
|
||||
("displays_views::sRGB (ACES)", "[view (display)] sRGB (ACES)"),
|
||||
]
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue