Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Farm rendering changes #165

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion client/ayon_unreal/plugins/create/create_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ def create_instance(
instance_data,
pre_create_data)

def update_instance(self, instance, instance_data, pre_create_data):
instance_data["label"] = f'instance_data.get("folderPath") - {instance_data.get("productName")}'
super(CreateRender, self).update_instance(
instance,
instance_data,
pre_create_data)


def create_with_new_sequence(
self, product_name, instance_data, pre_create_data
):
Expand Down Expand Up @@ -236,6 +244,10 @@ def create_from_existing_sequence(
selected_asset_path, master_seq, master_lvl, seq_data)

def create(self, product_name, instance_data, pre_create_data):
instance_data["label"] = f'{instance_data.get("folderPath")} - {product_name}'
if not instance_data.get("creator_attributes"):
instance_data["creator_attributes"] = {}
instance_data["creator_attributes"]["render_target"] = pre_create_data.get("render_target")
if pre_create_data.get("create_seq"):
self.create_with_new_sequence(
product_name, instance_data, pre_create_data)
Expand Down Expand Up @@ -299,6 +311,29 @@ def get_instance_attr_defs(self):
return [
EnumDef(
"render_target", items=rendering_targets,
label="Render target"
label="Render target",
default="local"
),
BoolDef(
"review",
label="Generate review",
default=True
),
]

def _on_value_changed(self, event):
for changed_item in event["changes"]:
instance = changed_item["instance"]
changes = changed_item["changes"]
if (
instance is not None
and "folderPath" in changes
and instance.creator_identifier == self.identifier
):
instance.data["label"] = (
f'{instance.data.get("folderPath")} - '
f'{instance.data.get("productName")}'
)

def register_callbacks(self):
self.create_context.add_value_changed_callback(self._on_value_changed)
1 change: 0 additions & 1 deletion client/ayon_unreal/plugins/publish/collect_render_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ class CollectRenderFiles(pyblish.api.InstancePlugin):
add them as representation.
"""
order = pyblish.api.CollectorOrder + 0.001
hosts = ["unreal"]
families = ["render.local"]
label = "Collect Render Files"

Expand Down
92 changes: 0 additions & 92 deletions client/ayon_unreal/plugins/publish/collect_render_instances.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

import pyblish.api

from ayon_core.pipeline import publish
from ayon_core.pipeline import publish, PublishError
from ayon_core.pipeline.publish import RenderInstance

from ayon_unreal.api import pipeline

from ayon_unreal.api.pipeline import UNREAL_VERSION
from ayon_unreal.api.rendering import (
SUPPORTED_EXTENSION_MAP,
Expand All @@ -30,12 +32,76 @@ class UnrealRenderInstance(RenderInstance):
render_queue_path = attr.ib(default=None)


class CollectUnrealRemoteRender(publish.AbstractCollectRender):

order = pyblish.api.CollectorOrder + 0.405
label = "Collect Farm Expected files"
hosts = ["unreal"]
families = ["render.farm"]
class CreateFarmRenderInstances(publish.AbstractCollectRender):

order = pyblish.api.CollectorOrder + 0.21
label = "Create Farm Render Instances"

def preparing_rendering_instance(self, instance):
context = instance.context

data = instance.data
data["remove"] = True

ar = unreal.AssetRegistryHelpers.get_asset_registry()

sequence = ar.get_asset_by_object_path(
data.get("sequence")).get_asset()

sequences = [{
"sequence": sequence,
"output": data.get("output"),
"frame_range": (
data.get("frameStart"), data.get("frameEnd"))
}]

for s in sequences:
self.log.debug(f"Processing: {s.get('sequence').get_name()}")
subscenes = pipeline.get_subsequences(s.get('sequence'))

if subscenes:
for ss in subscenes:
sequences.append({
"sequence": ss.get_sequence(),
"output": (f"{s.get('output')}/"
f"{ss.get_sequence().get_name()}"),
"frame_range": (
ss.get_start_frame(), ss.get_end_frame() - 1)
})
else:
# Avoid creating instances for camera sequences
if "_camera" not in s.get('sequence').get_name():
seq = s.get('sequence')
seq_name = seq.get_name()

product_type = "render"
new_product_name = f"{data.get('productName')}_{seq_name}"
new_instance = context.create_instance(
new_product_name
)
new_instance[:] = seq_name

new_data = new_instance.data

new_data["folderPath"] = instance.data["folderPath"]
new_data["setMembers"] = seq_name
new_data["productName"] = new_product_name
new_data["productType"] = product_type
new_data["family"] = product_type
new_data["families"] = [product_type, "review"]
new_data["parent"] = data.get("parent")
new_data["level"] = data.get("level")
new_data["output"] = s['output']
new_data["fps"] = seq.get_display_rate().numerator
new_data["frameStart"] = int(s.get('frame_range')[0])
new_data["frameEnd"] = int(s.get('frame_range')[1])
new_data["sequence"] = seq.get_path_name()
new_data["master_sequence"] = data["master_sequence"]
new_data["master_level"] = data["master_level"]
new_data["review"] = instance.data.get("review", False)
new_data["farm"] = instance.data.get("farm", False)

self.log.debug(f"new instance data: {new_data}")

def get_instances(self, context):
instances = []
Expand Down Expand Up @@ -70,40 +136,51 @@ def get_instances(self, context):
fps = f"{output_fps.denominator}.{output_fps.numerator}"

for inst in context:
instance_families = inst.data.get("families", [])
product_name = inst.data["productName"]

if not inst.data.get("active", True):
continue

family = inst.data["family"]
if family not in ["render"]:
continue

# skip if locar render instances
if "render.local" in instance_families:
continue

if not inst.data.get("farm", False):
self.log.info("Skipping local render instance")
continue

render_queue_path = (
project_settings["unreal"]["render_queue_path"]
)
if not unreal.EditorAssetLibrary.does_asset_exist(
render_queue_path):
# TODO temporary until C++ blueprint is created as it is not
# possible to create renderQueue
# TODO: temporary until C++ blueprint is created as it is not
# possible to create renderQueue. Also, we could
# use Render Graph from UE 5.4

master_level = inst.data["master_level"]
sequence = inst.data["sequence"]
msg = (f"Please create `Movie Pipeline Queue` "
f"at `{render_queue_path}`. "
f"Set it Sequence to `{sequence}`, "
f"Map to `{master_level}` and "
f"Settings to `{config_path}` ")
raise RuntimeError(msg)
raise PublishError(msg)

instance_families = inst.data.get("families", [])
product_name = inst.data["productName"]
# backward compatibility
task_name = inst.data.get("task") or inst.data.get("task_name")
self.log.info(f"task_name::{task_name}")
self.log.debug(f"Task name:{task_name}")

ar = unreal.AssetRegistryHelpers.get_asset_registry()
sequence = (ar.get_asset_by_object_path(inst.data["sequence"]).
get_asset())
if not sequence:
raise RuntimeError(f"Cannot find {inst.data['sequence']}")
raise PublishError(f"Cannot find {inst.data['sequence']}")

# current frame range - might be different from created
frame_start = sequence.get_playback_start()
Expand All @@ -123,13 +200,18 @@ def get_instances(self, context):

publish_attributes = {}

instance = UnrealRenderInstance(
try:
review = bool(inst.data["creator_attributes"].get("review"))
except KeyError:
review = inst.data.get("review", False)

new_instance = UnrealRenderInstance(
family="render",
families=["render.farm"],
version=version,
time="",
source=current_file,
label="{} - {}".format(product_name, family),
label=f"{product_name} - {family}",
productName=product_name,
productType="render",
folderPath=inst.data["folderPath"],
Expand All @@ -144,7 +226,7 @@ def get_instances(self, context):
tileRendering=False,
tilesX=0,
tilesY=0,
review="review" in instance_families,
review=review,
frameStart=frame_start,
frameEnd=frame_end,
frameStep=1,
Expand All @@ -156,14 +238,15 @@ def get_instances(self, context):
config_path=config_path,
master_level=inst.data["master_level"],
render_queue_path=render_queue_path,
deadline=inst.data.get("deadline")
deadline=inst.data.get("deadline"),
)
instance.farm = True
new_instance.farm = True

instances.append(instance)
instances.append(new_instance)
instances_to_remove.append(inst)

for instance in instances_to_remove:
self.log.debug(f"Removing instance: {instance}")
context.remove(instance)
return instances

Expand All @@ -176,14 +259,14 @@ def _get_expected_file_name(self, file_name_format, ext,
frame_placeholder)
return f"{file_name_format}.{ext}"

def get_expected_files(self, render_instance):
def get_expected_files(self, render_instance: UnrealRenderInstance):
"""
Returns list of rendered files that should be created by
Deadline. These are not published directly, they are source
for later 'submit_publish_job'.

Args:
render_instance (RenderInstance): to pull anatomy and parts used
render_instance (UnrealRenderInstance): to pull anatomy and parts used
in url

Returns:
Expand Down Expand Up @@ -211,7 +294,7 @@ def _get_output_dir(self, render_instance):
"""
Returns dir path of rendered files, used in submit_publish_job
for metadata.json location.
Should be in separate folder inside of work area.
Should be in separate folder inside work area.

Args:
render_instance (RenderInstance):
Expand Down
Loading
Loading