mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 13:24:54 +01:00
Merge pull request #2689 from pypeclub/feature/OP-2518_Webpublisher-Photoshop-publisher-to-create-a-beauty-png
Webpublisher: Photoshop create a beauty png
This commit is contained in:
commit
e0b27e52f0
10 changed files with 207 additions and 151 deletions
|
|
@ -186,9 +186,26 @@ class PhotoshopServerStub:
|
|||
Returns:
|
||||
<list of PSItem>
|
||||
"""
|
||||
parent_ids = set([lay.id for lay in layers])
|
||||
|
||||
return self._get_layers_in_layers(parent_ids)
|
||||
|
||||
def get_layers_in_layers_ids(self, layers_ids):
|
||||
"""Return all layers that belong to layers (might be groups).
|
||||
|
||||
Args:
|
||||
layers <list of PSItem>:
|
||||
|
||||
Returns:
|
||||
<list of PSItem>
|
||||
"""
|
||||
parent_ids = set(layers_ids)
|
||||
|
||||
return self._get_layers_in_layers(parent_ids)
|
||||
|
||||
def _get_layers_in_layers(self, parent_ids):
|
||||
all_layers = self.get_layers()
|
||||
ret = []
|
||||
parent_ids = set([lay.id for lay in layers])
|
||||
|
||||
for layer in all_layers:
|
||||
parents = set(layer.parents)
|
||||
|
|
|
|||
|
|
@ -8,12 +8,15 @@ from openpype.lib.plugin_tools import parse_json, get_batch_asset_task_info
|
|||
from openpype.hosts.photoshop import api as photoshop
|
||||
|
||||
|
||||
class CollectRemoteInstances(pyblish.api.ContextPlugin):
|
||||
class CollectColorCodedInstances(pyblish.api.ContextPlugin):
|
||||
"""Creates instances for configured color code of a layer.
|
||||
|
||||
Used in remote publishing when artists marks publishable layers by color-
|
||||
coding.
|
||||
|
||||
Can add group for all publishable layers to allow creation of flattened
|
||||
image. (Cannot contain special background layer as it cannot be grouped!)
|
||||
|
||||
Identifier:
|
||||
id (str): "pyblish.avalon.instance"
|
||||
"""
|
||||
|
|
@ -26,50 +29,38 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin):
|
|||
|
||||
# configurable by Settings
|
||||
color_code_mapping = []
|
||||
# TODO check if could be set globally, probably doesn't make sense when
|
||||
# flattened template cannot
|
||||
subset_template_name = ""
|
||||
create_flatten_image = False
|
||||
# probably not possible to configure this globally
|
||||
flatten_subset_template = ""
|
||||
|
||||
def process(self, context):
|
||||
self.log.info("CollectRemoteInstances")
|
||||
self.log.info("CollectColorCodedInstances")
|
||||
self.log.debug("mapping:: {}".format(self.color_code_mapping))
|
||||
|
||||
# parse variant if used in webpublishing, comes from webpublisher batch
|
||||
batch_dir = os.environ.get("OPENPYPE_PUBLISH_DATA")
|
||||
task_data = None
|
||||
if batch_dir and os.path.exists(batch_dir):
|
||||
# TODO check if batch manifest is same as tasks manifests
|
||||
task_data = parse_json(os.path.join(batch_dir,
|
||||
"manifest.json"))
|
||||
if not task_data:
|
||||
raise ValueError(
|
||||
"Cannot parse batch meta in {} folder".format(batch_dir))
|
||||
variant = task_data["variant"]
|
||||
existing_subset_names = self._get_existing_subset_names(context)
|
||||
asset_name, task_name, variant = self._parse_batch()
|
||||
|
||||
stub = photoshop.stub()
|
||||
layers = stub.get_layers()
|
||||
|
||||
existing_subset_names = []
|
||||
for instance in context:
|
||||
if instance.data.get('publish'):
|
||||
existing_subset_names.append(instance.data.get('subset'))
|
||||
|
||||
asset, task_name, task_type = get_batch_asset_task_info(
|
||||
task_data["context"])
|
||||
|
||||
if not task_name:
|
||||
task_name = task_type
|
||||
|
||||
instance_names = []
|
||||
publishable_layers = []
|
||||
created_instances = []
|
||||
for layer in layers:
|
||||
self.log.debug("Layer:: {}".format(layer))
|
||||
if layer.parents:
|
||||
self.log.debug("!!! Not a top layer, skip")
|
||||
continue
|
||||
|
||||
if not layer.visible:
|
||||
self.log.debug("Not visible, skip")
|
||||
continue
|
||||
|
||||
resolved_family, resolved_subset_template = self._resolve_mapping(
|
||||
layer
|
||||
)
|
||||
self.log.info("resolved_family {}".format(resolved_family))
|
||||
self.log.info("resolved_subset_template {}".format(
|
||||
resolved_subset_template))
|
||||
|
||||
if not resolved_subset_template or not resolved_family:
|
||||
self.log.debug("!!! Not found family or template, skip")
|
||||
|
|
@ -90,24 +81,81 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin):
|
|||
"Subset {} already created, skipping.".format(subset))
|
||||
continue
|
||||
|
||||
instance = context.create_instance(layer.name)
|
||||
instance.append(layer)
|
||||
instance.data["family"] = resolved_family
|
||||
instance.data["publish"] = layer.visible
|
||||
instance.data["asset"] = asset
|
||||
instance.data["task"] = task_name
|
||||
instance.data["subset"] = subset
|
||||
instance = self._create_instance(context, layer, resolved_family,
|
||||
asset_name, subset, task_name)
|
||||
existing_subset_names.append(subset)
|
||||
publishable_layers.append(layer)
|
||||
created_instances.append(instance)
|
||||
|
||||
instance_names.append(layer.name)
|
||||
if self.create_flatten_image and publishable_layers:
|
||||
self.log.debug("create_flatten_image")
|
||||
if not self.flatten_subset_template:
|
||||
self.log.warning("No template for flatten image")
|
||||
return
|
||||
|
||||
fill_pairs.pop("layer")
|
||||
subset = self.flatten_subset_template.format(
|
||||
**prepare_template_data(fill_pairs))
|
||||
|
||||
first_layer = publishable_layers[0] # dummy layer
|
||||
first_layer.name = subset
|
||||
family = created_instances[0].data["family"] # inherit family
|
||||
instance = self._create_instance(context, first_layer,
|
||||
family,
|
||||
asset_name, subset, task_name)
|
||||
instance.data["ids"] = [layer.id for layer in publishable_layers]
|
||||
created_instances.append(instance)
|
||||
|
||||
for instance in created_instances:
|
||||
# Produce diagnostic message for any graphical
|
||||
# user interface interested in visualising it.
|
||||
self.log.info("Found: \"%s\" " % instance.data["name"])
|
||||
self.log.info("instance: {} ".format(instance.data))
|
||||
|
||||
if len(instance_names) != len(set(instance_names)):
|
||||
self.log.warning("Duplicate instances found. " +
|
||||
"Remove unwanted via SubsetManager")
|
||||
def _get_existing_subset_names(self, context):
|
||||
"""Collect manually created instances from workfile.
|
||||
|
||||
Shouldn't be any as Webpublisher bypass publishing via Openpype, but
|
||||
might be some if workfile published through OP is reused.
|
||||
"""
|
||||
existing_subset_names = []
|
||||
for instance in context:
|
||||
if instance.data.get('publish'):
|
||||
existing_subset_names.append(instance.data.get('subset'))
|
||||
|
||||
return existing_subset_names
|
||||
|
||||
def _parse_batch(self):
|
||||
"""Parses asset_name, task_name, variant from batch manifest."""
|
||||
batch_dir = os.environ.get("OPENPYPE_PUBLISH_DATA")
|
||||
task_data = None
|
||||
if batch_dir and os.path.exists(batch_dir):
|
||||
task_data = parse_json(os.path.join(batch_dir,
|
||||
"manifest.json"))
|
||||
if not task_data:
|
||||
raise ValueError(
|
||||
"Cannot parse batch meta in {} folder".format(batch_dir))
|
||||
variant = task_data["variant"]
|
||||
|
||||
asset, task_name, task_type = get_batch_asset_task_info(
|
||||
task_data["context"])
|
||||
|
||||
if not task_name:
|
||||
task_name = task_type
|
||||
|
||||
return asset, task_name, variant
|
||||
|
||||
def _create_instance(self, context, layer, family,
|
||||
asset, subset, task_name):
|
||||
instance = context.create_instance(layer.name)
|
||||
instance.data["family"] = family
|
||||
instance.data["publish"] = True
|
||||
instance.data["asset"] = asset
|
||||
instance.data["task"] = task_name
|
||||
instance.data["subset"] = subset
|
||||
instance.data["layer"] = layer
|
||||
|
||||
return instance
|
||||
|
||||
def _resolve_mapping(self, layer):
|
||||
"""Matches 'layer' color code and name to mapping.
|
||||
|
|
@ -147,4 +195,7 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin):
|
|||
if family_list:
|
||||
family = family_list.pop()
|
||||
|
||||
self.log.debug("resolved_family {}".format(family))
|
||||
self.log.debug("resolved_subset_template {}".format(
|
||||
resolved_subset_template))
|
||||
return family, resolved_subset_template
|
||||
|
|
@ -43,7 +43,7 @@ class CollectInstances(pyblish.api.ContextPlugin):
|
|||
# continue
|
||||
|
||||
instance = context.create_instance(layer_data["subset"])
|
||||
instance.append(layer)
|
||||
instance.data["layer"] = layer
|
||||
instance.data.update(layer_data)
|
||||
instance.data["families"] = self.families_mapping[
|
||||
layer_data["family"]
|
||||
|
|
|
|||
|
|
@ -27,8 +27,13 @@ class ExtractImage(openpype.api.Extractor):
|
|||
self.log.info("Extracting %s" % str(list(instance)))
|
||||
with photoshop.maintained_visibility():
|
||||
# Hide all other layers.
|
||||
layer = instance.data.get("layer")
|
||||
ids = set([layer.id])
|
||||
add_ids = instance.data.pop("ids", None)
|
||||
if add_ids:
|
||||
ids.update(set(add_ids))
|
||||
extract_ids = set([ll.id for ll in stub.
|
||||
get_layers_in_layers([instance[0]])])
|
||||
get_layers_in_layers_ids(ids)])
|
||||
|
||||
for layer in stub.get_layers():
|
||||
# limit unnecessary calls to client
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class ExtractReview(openpype.api.Extractor):
|
|||
for image_instance in instance.context:
|
||||
if image_instance.data["family"] != "image":
|
||||
continue
|
||||
layers.append(image_instance[0])
|
||||
layers.append(image_instance.data.get("layer"))
|
||||
|
||||
# Perform extraction
|
||||
output_image = "{}.jpg".format(
|
||||
|
|
|
|||
|
|
@ -248,6 +248,8 @@ class HarmonySubmitDeadline(
|
|||
secondary_pool = ""
|
||||
priority = 50
|
||||
chunk_size = 1000000
|
||||
group = "none"
|
||||
department = ""
|
||||
|
||||
def get_job_info(self):
|
||||
job_info = DeadlineJobInfo("Harmony")
|
||||
|
|
@ -264,6 +266,8 @@ class HarmonySubmitDeadline(
|
|||
job_info.SecondaryPool = self.secondary_pool
|
||||
job_info.ChunkSize = self.chunk_size
|
||||
job_info.BatchName = os.path.basename(self._instance.data["source"])
|
||||
job_info.Department = self.department
|
||||
job_info.Group = self.group
|
||||
|
||||
keys = [
|
||||
"FTRACK_API_KEY",
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@
|
|||
],
|
||||
"celaction": [
|
||||
".*"
|
||||
],
|
||||
"harmony": [
|
||||
".*"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,15 +7,10 @@
|
|||
}
|
||||
},
|
||||
"publish": {
|
||||
"CollectRemoteInstances": {
|
||||
"color_code_mapping": [
|
||||
{
|
||||
"color_code": [],
|
||||
"layer_name_regex": [],
|
||||
"family": "image",
|
||||
"subset_template_name": ""
|
||||
}
|
||||
]
|
||||
"CollectColorCodedInstances": {
|
||||
"create_flatten_image": false,
|
||||
"flatten_subset_template": "",
|
||||
"color_code_mapping": []
|
||||
},
|
||||
"ValidateContainers": {
|
||||
"enabled": true,
|
||||
|
|
|
|||
|
|
@ -71,106 +71,11 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
"key": "ProcessSubmittedJobOnFarm",
|
||||
"label": "ProcessSubmittedJobOnFarm",
|
||||
"checkbox_key": "enabled",
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_department",
|
||||
"label": "Deadline department"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_pool",
|
||||
"label": "Deadline Pool"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_group",
|
||||
"label": "Deadline Group"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "deadline_chunk_size",
|
||||
"label": "Deadline Chunk Size"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "deadline_priority",
|
||||
"label": "Deadline Priotity"
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "publishing_script",
|
||||
"label": "Publishing script path"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"key": "skip_integration_repre_list",
|
||||
"label": "Skip integration of representation with ext",
|
||||
"object_type": {
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"key": "aov_filter",
|
||||
"label": "Reviewable subsets filter",
|
||||
"children": [
|
||||
{
|
||||
"type": "list",
|
||||
"key": "maya",
|
||||
"label": "Maya",
|
||||
"object_type": {
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"key": "nuke",
|
||||
"label": "Nuke",
|
||||
"object_type": {
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"key": "aftereffects",
|
||||
"label": "After Effects",
|
||||
"object_type": {
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"key": "celaction",
|
||||
"label": "Celaction",
|
||||
"object_type": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
"key": "MayaSubmitDeadline",
|
||||
"label": "Submit Maya job to Deadline",
|
||||
"label": "Maya Submit to Deadline",
|
||||
"checkbox_key": "enabled",
|
||||
"children": [
|
||||
{
|
||||
|
|
@ -464,6 +369,72 @@
|
|||
"label": "Department"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "dict",
|
||||
"collapsible": true,
|
||||
"key": "ProcessSubmittedJobOnFarm",
|
||||
"label": "ProcessSubmittedJobOnFarm",
|
||||
"checkbox_key": "enabled",
|
||||
"is_group": true,
|
||||
"children": [
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "enabled",
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_department",
|
||||
"label": "Deadline department"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_pool",
|
||||
"label": "Deadline Pool"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "deadline_group",
|
||||
"label": "Deadline Group"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "deadline_chunk_size",
|
||||
"label": "Deadline Chunk Size"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "deadline_priority",
|
||||
"label": "Deadline Priotity"
|
||||
},
|
||||
{
|
||||
"type": "splitter"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "publishing_script",
|
||||
"label": "Publishing script path"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
"key": "skip_integration_repre_list",
|
||||
"label": "Skip integration of representation with ext",
|
||||
"object_type": {
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "dict-modifiable",
|
||||
"docstring": "Regular expression to filter for which subset review should be created in publish job.",
|
||||
"key": "aov_filter",
|
||||
"label": "Reviewable subsets filter",
|
||||
"object_type": {
|
||||
"type": "list",
|
||||
"object_type": "text"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,12 +37,22 @@
|
|||
"type": "dict",
|
||||
"collapsible": true,
|
||||
"is_group": true,
|
||||
"key": "CollectRemoteInstances",
|
||||
"label": "Collect Instances for Webpublish",
|
||||
"key": "CollectColorCodedInstances",
|
||||
"label": "Collect Color Coded Instances",
|
||||
"children": [
|
||||
{
|
||||
"type": "label",
|
||||
"label": "Set color for publishable layers, set publishable families."
|
||||
"label": "Set color for publishable layers, set its resulting family and template for subset name. Can create flatten image from published instances"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"key": "create_flatten_image",
|
||||
"label": "Create flatten image"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "flatten_subset_template",
|
||||
"label": "Subset template for flatten image"
|
||||
},
|
||||
{
|
||||
"type": "list",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue