mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 16:34:53 +01:00
Merge branch 'develop' into bugfix/1587-hiero-published-whole-edit-mov
This commit is contained in:
commit
71fc0fceef
27 changed files with 992 additions and 202 deletions
|
|
@ -190,7 +190,7 @@ def get_track_items(
|
|||
if not item.isEnabled():
|
||||
continue
|
||||
if track_item_name:
|
||||
if item.name() in track_item_name:
|
||||
if track_item_name in item.name():
|
||||
return item
|
||||
# make sure only track items with correct track names are added
|
||||
if track_name and track_name in track.name():
|
||||
|
|
@ -949,6 +949,54 @@ def sync_clip_name_to_data_asset(track_items_list):
|
|||
print("asset was changed in clip: {}".format(ti_name))
|
||||
|
||||
|
||||
def check_inventory_versions():
|
||||
"""
|
||||
Actual version color idetifier of Loaded containers
|
||||
|
||||
Check all track items and filter only
|
||||
Loader nodes for its version. It will get all versions from database
|
||||
and check if the node is having actual version. If not then it will color
|
||||
it to red.
|
||||
"""
|
||||
from . import parse_container
|
||||
from avalon import io
|
||||
|
||||
# presets
|
||||
clip_color_last = "green"
|
||||
clip_color = "red"
|
||||
|
||||
# get all track items from current timeline
|
||||
for track_item in get_track_items():
|
||||
container = parse_container(track_item)
|
||||
|
||||
if container:
|
||||
# get representation from io
|
||||
representation = io.find_one({
|
||||
"type": "representation",
|
||||
"_id": io.ObjectId(container["representation"])
|
||||
})
|
||||
|
||||
# Get start frame from version data
|
||||
version = io.find_one({
|
||||
"type": "version",
|
||||
"_id": representation["parent"]
|
||||
})
|
||||
|
||||
# get all versions in list
|
||||
versions = io.find({
|
||||
"type": "version",
|
||||
"parent": version["parent"]
|
||||
}).distinct('name')
|
||||
|
||||
max_version = max(versions)
|
||||
|
||||
# set clip colour
|
||||
if version.get("name") == max_version:
|
||||
track_item.source().binItem().setColor(clip_color_last)
|
||||
else:
|
||||
track_item.source().binItem().setColor(clip_color)
|
||||
|
||||
|
||||
def selection_changed_timeline(event):
|
||||
"""Callback on timeline to check if asset in data is the same as clip name.
|
||||
|
||||
|
|
@ -958,9 +1006,15 @@ def selection_changed_timeline(event):
|
|||
timeline_editor = event.sender
|
||||
selection = timeline_editor.selection()
|
||||
|
||||
selection = [ti for ti in selection
|
||||
if isinstance(ti, hiero.core.TrackItem)]
|
||||
|
||||
# run checking function
|
||||
sync_clip_name_to_data_asset(selection)
|
||||
|
||||
# also mark old versions of loaded containers
|
||||
check_inventory_versions()
|
||||
|
||||
|
||||
def before_project_save(event):
|
||||
track_items = get_track_items(
|
||||
|
|
@ -972,3 +1026,6 @@ def before_project_save(event):
|
|||
|
||||
# run checking function
|
||||
sync_clip_name_to_data_asset(track_items)
|
||||
|
||||
# also mark old versions of loaded containers
|
||||
check_inventory_versions()
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
from avalon.api import CreatorError
|
||||
from avalon.tvpaint import (
|
||||
pipeline,
|
||||
lib,
|
||||
CommunicationWrapper
|
||||
)
|
||||
from openpype.hosts.tvpaint.api import plugin
|
||||
from openpype.lib import prepare_template_data
|
||||
|
||||
|
||||
class CreateRenderlayer(plugin.Creator):
|
||||
|
|
@ -15,13 +17,31 @@ class CreateRenderlayer(plugin.Creator):
|
|||
defaults = ["Main"]
|
||||
|
||||
rename_group = True
|
||||
render_pass = "beauty"
|
||||
|
||||
subset_template = "{family}_{name}"
|
||||
rename_script_template = (
|
||||
"tv_layercolor \"setcolor\""
|
||||
" {clip_id} {group_id} {r} {g} {b} \"{name}\""
|
||||
)
|
||||
|
||||
dynamic_subset_keys = ["render_pass", "render_layer", "group"]
|
||||
|
||||
@classmethod
|
||||
def get_dynamic_data(
|
||||
cls, variant, task_name, asset_id, project_name, host_name
|
||||
):
|
||||
dynamic_data = super(CreateRenderlayer, cls).get_dynamic_data(
|
||||
variant, task_name, asset_id, project_name, host_name
|
||||
)
|
||||
# Use render pass name from creator's plugin
|
||||
dynamic_data["render_pass"] = cls.render_pass
|
||||
# Add variant to render layer
|
||||
dynamic_data["render_layer"] = variant
|
||||
# Change family for subset name fill
|
||||
dynamic_data["family"] = "render"
|
||||
|
||||
return dynamic_data
|
||||
|
||||
@classmethod
|
||||
def get_default_variant(cls):
|
||||
"""Default value for variant in Creator tool.
|
||||
|
|
@ -70,34 +90,44 @@ class CreateRenderlayer(plugin.Creator):
|
|||
|
||||
# Raise if there is no selection
|
||||
if not group_ids:
|
||||
raise AssertionError("Nothing is selected.")
|
||||
raise CreatorError("Nothing is selected.")
|
||||
|
||||
# This creator should run only on one group
|
||||
if len(group_ids) > 1:
|
||||
raise AssertionError("More than one group is in selection.")
|
||||
raise CreatorError("More than one group is in selection.")
|
||||
|
||||
group_id = tuple(group_ids)[0]
|
||||
# If group id is `0` it is `default` group which is invalid
|
||||
if group_id == 0:
|
||||
raise AssertionError(
|
||||
raise CreatorError(
|
||||
"Selection is not in group. Can't mark selection as Beauty."
|
||||
)
|
||||
|
||||
self.log.debug(f"Selected group id is \"{group_id}\".")
|
||||
self.data["group_id"] = group_id
|
||||
|
||||
family = self.data["family"]
|
||||
# Extract entered name
|
||||
name = self.data["subset"][len(family):]
|
||||
self.log.info(f"Extracted name from subset name \"{name}\".")
|
||||
self.data["name"] = name
|
||||
group_data = lib.groups_data()
|
||||
group_name = None
|
||||
for group in group_data:
|
||||
if group["group_id"] == group_id:
|
||||
group_name = group["name"]
|
||||
break
|
||||
|
||||
# Change subset name by template
|
||||
subset_name = self.subset_template.format(**{
|
||||
"family": self.family,
|
||||
"name": name
|
||||
})
|
||||
self.log.info(f"New subset name \"{subset_name}\".")
|
||||
if group_name is None:
|
||||
raise AssertionError(
|
||||
"Couldn't find group by id \"{}\"".format(group_id)
|
||||
)
|
||||
|
||||
subset_name_fill_data = {
|
||||
"group": group_name
|
||||
}
|
||||
|
||||
family = self.family = self.data["family"]
|
||||
|
||||
# Fill dynamic key 'group'
|
||||
subset_name = self.data["subset"].format(
|
||||
**prepare_template_data(subset_name_fill_data)
|
||||
)
|
||||
self.data["subset"] = subset_name
|
||||
|
||||
# Check for instances of same group
|
||||
|
|
@ -153,7 +183,7 @@ class CreateRenderlayer(plugin.Creator):
|
|||
|
||||
# Rename TVPaint group (keep color same)
|
||||
# - groups can't contain spaces
|
||||
new_group_name = name.replace(" ", "_")
|
||||
new_group_name = self.data["variant"].replace(" ", "_")
|
||||
rename_script = self.rename_script_template.format(
|
||||
clip_id=selected_group["clip_id"],
|
||||
group_id=selected_group["group_id"],
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
from avalon.api import CreatorError
|
||||
from avalon.tvpaint import (
|
||||
pipeline,
|
||||
lib,
|
||||
CommunicationWrapper
|
||||
)
|
||||
from openpype.hosts.tvpaint.api import plugin
|
||||
from openpype.lib import prepare_template_data
|
||||
|
||||
|
||||
class CreateRenderPass(plugin.Creator):
|
||||
|
|
@ -18,7 +20,19 @@ class CreateRenderPass(plugin.Creator):
|
|||
icon = "cube"
|
||||
defaults = ["Main"]
|
||||
|
||||
subset_template = "{family}_{render_layer}_{pass}"
|
||||
dynamic_subset_keys = ["render_pass", "render_layer"]
|
||||
|
||||
@classmethod
|
||||
def get_dynamic_data(
|
||||
cls, variant, task_name, asset_id, project_name, host_name
|
||||
):
|
||||
dynamic_data = super(CreateRenderPass, cls).get_dynamic_data(
|
||||
variant, task_name, asset_id, project_name, host_name
|
||||
)
|
||||
dynamic_data["render_pass"] = variant
|
||||
dynamic_data["family"] = "render"
|
||||
|
||||
return dynamic_data
|
||||
|
||||
@classmethod
|
||||
def get_default_variant(cls):
|
||||
|
|
@ -66,11 +80,11 @@ class CreateRenderPass(plugin.Creator):
|
|||
|
||||
# Raise if nothing is selected
|
||||
if not selected_layers:
|
||||
raise AssertionError("Nothing is selected.")
|
||||
raise CreatorError("Nothing is selected.")
|
||||
|
||||
# Raise if layers from multiple groups are selected
|
||||
if len(group_ids) != 1:
|
||||
raise AssertionError("More than one group is in selection.")
|
||||
raise CreatorError("More than one group is in selection.")
|
||||
|
||||
group_id = tuple(group_ids)[0]
|
||||
self.log.debug(f"Selected group id is \"{group_id}\".")
|
||||
|
|
@ -87,34 +101,40 @@ class CreateRenderPass(plugin.Creator):
|
|||
|
||||
# Beauty is required for this creator so raise if was not found
|
||||
if beauty_instance is None:
|
||||
raise AssertionError("Beauty pass does not exist yet.")
|
||||
raise CreatorError("Beauty pass does not exist yet.")
|
||||
|
||||
render_layer = beauty_instance["name"]
|
||||
subset_name = self.data["subset"]
|
||||
|
||||
subset_name_fill_data = {}
|
||||
|
||||
# Backwards compatibility
|
||||
# - beauty may be created with older creator where variant was not
|
||||
# stored
|
||||
if "variant" not in beauty_instance:
|
||||
render_layer = beauty_instance["name"]
|
||||
else:
|
||||
render_layer = beauty_instance["variant"]
|
||||
|
||||
subset_name_fill_data["render_layer"] = render_layer
|
||||
|
||||
# Format dynamic keys in subset name
|
||||
new_subset_name = subset_name.format(
|
||||
**prepare_template_data(subset_name_fill_data)
|
||||
)
|
||||
self.data["subset"] = new_subset_name
|
||||
self.log.info(f"New subset name is \"{new_subset_name}\".")
|
||||
|
||||
# Extract entered name
|
||||
family = self.data["family"]
|
||||
name = self.data["subset"]
|
||||
# Is this right way how to get name?
|
||||
name = name[len(family):]
|
||||
self.log.info(f"Extracted name from subset name \"{name}\".")
|
||||
variant = self.data["variant"]
|
||||
|
||||
self.data["group_id"] = group_id
|
||||
self.data["pass"] = name
|
||||
self.data["pass"] = variant
|
||||
self.data["render_layer"] = render_layer
|
||||
|
||||
# Collect selected layer ids to be stored into instance
|
||||
layer_names = [layer["name"] for layer in selected_layers]
|
||||
self.data["layer_names"] = layer_names
|
||||
|
||||
# Replace `beauty` in beauty's subset name with entered name
|
||||
subset_name = self.subset_template.format(**{
|
||||
"family": family,
|
||||
"render_layer": render_layer,
|
||||
"pass": name
|
||||
})
|
||||
self.data["subset"] = subset_name
|
||||
self.log.info(f"New subset name is \"{subset_name}\".")
|
||||
|
||||
# Check if same instance already exists
|
||||
existing_instance = None
|
||||
existing_instance_idx = None
|
||||
|
|
@ -122,7 +142,7 @@ class CreateRenderPass(plugin.Creator):
|
|||
if (
|
||||
instance["family"] == family
|
||||
and instance["group_id"] == group_id
|
||||
and instance["pass"] == name
|
||||
and instance["pass"] == variant
|
||||
):
|
||||
existing_instance = instance
|
||||
existing_instance_idx = idx
|
||||
|
|
@ -131,7 +151,7 @@ class CreateRenderPass(plugin.Creator):
|
|||
if existing_instance is not None:
|
||||
self.log.info(
|
||||
f"Render pass instance for group id {group_id}"
|
||||
f" and name \"{name}\" already exists, overriding."
|
||||
f" and name \"{variant}\" already exists, overriding."
|
||||
)
|
||||
instances[existing_instance_idx] = self.data
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import copy
|
|||
import pyblish.api
|
||||
from avalon import io
|
||||
|
||||
from openpype.lib import get_subset_name
|
||||
|
||||
|
||||
class CollectInstances(pyblish.api.ContextPlugin):
|
||||
label = "Collect Instances"
|
||||
|
|
@ -62,9 +64,38 @@ class CollectInstances(pyblish.api.ContextPlugin):
|
|||
# Different instance creation based on family
|
||||
instance = None
|
||||
if family == "review":
|
||||
# Change subset name
|
||||
# Change subset name of review instance
|
||||
|
||||
# Collect asset doc to get asset id
|
||||
# - not sure if it's good idea to require asset id in
|
||||
# get_subset_name?
|
||||
asset_name = context.data["workfile_context"]["asset"]
|
||||
asset_doc = io.find_one(
|
||||
{
|
||||
"type": "asset",
|
||||
"name": asset_name
|
||||
},
|
||||
{"_id": 1}
|
||||
)
|
||||
asset_id = None
|
||||
if asset_doc:
|
||||
asset_id = asset_doc["_id"]
|
||||
|
||||
# Project name from workfile context
|
||||
project_name = context.data["workfile_context"]["project"]
|
||||
# Host name from environemnt variable
|
||||
host_name = os.environ["AVALON_APP"]
|
||||
# Use empty variant value
|
||||
variant = ""
|
||||
task_name = io.Session["AVALON_TASK"]
|
||||
new_subset_name = "{}{}".format(family, task_name.capitalize())
|
||||
new_subset_name = get_subset_name(
|
||||
family,
|
||||
variant,
|
||||
task_name,
|
||||
asset_id,
|
||||
project_name,
|
||||
host_name
|
||||
)
|
||||
instance_data["subset"] = new_subset_name
|
||||
|
||||
instance = context.create_instance(**instance_data)
|
||||
|
|
@ -119,19 +150,23 @@ class CollectInstances(pyblish.api.ContextPlugin):
|
|||
name = instance_data["name"]
|
||||
# Change label
|
||||
subset_name = instance_data["subset"]
|
||||
instance_data["label"] = "{}_Beauty".format(name)
|
||||
|
||||
# Change subset name
|
||||
# Final family of an instance will be `render`
|
||||
new_family = "render"
|
||||
task_name = io.Session["AVALON_TASK"]
|
||||
new_subset_name = "{}{}_{}_Beauty".format(
|
||||
new_family, task_name.capitalize(), name
|
||||
)
|
||||
instance_data["subset"] = new_subset_name
|
||||
self.log.debug("Changed subset name \"{}\"->\"{}\"".format(
|
||||
subset_name, new_subset_name
|
||||
))
|
||||
# Backwards compatibility
|
||||
# - subset names were not stored as final subset names during creation
|
||||
if "variant" not in instance_data:
|
||||
instance_data["label"] = "{}_Beauty".format(name)
|
||||
|
||||
# Change subset name
|
||||
# Final family of an instance will be `render`
|
||||
new_family = "render"
|
||||
task_name = io.Session["AVALON_TASK"]
|
||||
new_subset_name = "{}{}_{}_Beauty".format(
|
||||
new_family, task_name.capitalize(), name
|
||||
)
|
||||
instance_data["subset"] = new_subset_name
|
||||
self.log.debug("Changed subset name \"{}\"->\"{}\"".format(
|
||||
subset_name, new_subset_name
|
||||
))
|
||||
|
||||
# Get all layers for the layer
|
||||
layers_data = context.data["layersData"]
|
||||
|
|
@ -163,20 +198,23 @@ class CollectInstances(pyblish.api.ContextPlugin):
|
|||
)
|
||||
# Change label
|
||||
render_layer = instance_data["render_layer"]
|
||||
instance_data["label"] = "{}_{}".format(render_layer, pass_name)
|
||||
|
||||
# Change subset name
|
||||
# Final family of an instance will be `render`
|
||||
new_family = "render"
|
||||
old_subset_name = instance_data["subset"]
|
||||
task_name = io.Session["AVALON_TASK"]
|
||||
new_subset_name = "{}{}_{}_{}".format(
|
||||
new_family, task_name.capitalize(), render_layer, pass_name
|
||||
)
|
||||
instance_data["subset"] = new_subset_name
|
||||
self.log.debug("Changed subset name \"{}\"->\"{}\"".format(
|
||||
old_subset_name, new_subset_name
|
||||
))
|
||||
# Backwards compatibility
|
||||
# - subset names were not stored as final subset names during creation
|
||||
if "variant" not in instance_data:
|
||||
instance_data["label"] = "{}_{}".format(render_layer, pass_name)
|
||||
# Change subset name
|
||||
# Final family of an instance will be `render`
|
||||
new_family = "render"
|
||||
old_subset_name = instance_data["subset"]
|
||||
task_name = io.Session["AVALON_TASK"]
|
||||
new_subset_name = "{}{}_{}_{}".format(
|
||||
new_family, task_name.capitalize(), render_layer, pass_name
|
||||
)
|
||||
instance_data["subset"] = new_subset_name
|
||||
self.log.debug("Changed subset name \"{}\"->\"{}\"".format(
|
||||
old_subset_name, new_subset_name
|
||||
))
|
||||
|
||||
layers_data = context.data["layersData"]
|
||||
layers_by_name = {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import json
|
|||
import pyblish.api
|
||||
from avalon import io
|
||||
|
||||
from openpype.lib import get_subset_name
|
||||
|
||||
|
||||
class CollectWorkfile(pyblish.api.ContextPlugin):
|
||||
label = "Collect Workfile"
|
||||
|
|
@ -20,8 +22,38 @@ class CollectWorkfile(pyblish.api.ContextPlugin):
|
|||
basename, ext = os.path.splitext(filename)
|
||||
instance = context.create_instance(name=basename)
|
||||
|
||||
# Get subset name of workfile instance
|
||||
# Collect asset doc to get asset id
|
||||
# - not sure if it's good idea to require asset id in
|
||||
# get_subset_name?
|
||||
family = "workfile"
|
||||
asset_name = context.data["workfile_context"]["asset"]
|
||||
asset_doc = io.find_one(
|
||||
{
|
||||
"type": "asset",
|
||||
"name": asset_name
|
||||
},
|
||||
{"_id": 1}
|
||||
)
|
||||
asset_id = None
|
||||
if asset_doc:
|
||||
asset_id = asset_doc["_id"]
|
||||
|
||||
# Project name from workfile context
|
||||
project_name = context.data["workfile_context"]["project"]
|
||||
# Host name from environemnt variable
|
||||
host_name = os.environ["AVALON_APP"]
|
||||
# Use empty variant value
|
||||
variant = ""
|
||||
task_name = io.Session["AVALON_TASK"]
|
||||
subset_name = "workfile" + task_name.capitalize()
|
||||
subset_name = get_subset_name(
|
||||
family,
|
||||
variant,
|
||||
task_name,
|
||||
asset_id,
|
||||
project_name,
|
||||
host_name
|
||||
)
|
||||
|
||||
# Create Workfile instance
|
||||
instance.data.update({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue