diff --git a/client/ayon_core/hosts/aftereffects/plugins/publish/collect_render.py b/client/ayon_core/hosts/aftereffects/plugins/publish/collect_render.py index a8a316ea80..32e3b4f3c3 100644 --- a/client/ayon_core/hosts/aftereffects/plugins/publish/collect_render.py +++ b/client/ayon_core/hosts/aftereffects/plugins/publish/collect_render.py @@ -98,7 +98,7 @@ class CollectAERender(publish.AbstractCollectRender): source=current_file, label="{} - {}".format(subset_name, family), subset=subset_name, - asset=inst.data["asset"], + folderPath=inst.data["folderPath"], task=task_name, attachTo=False, setMembers='', @@ -175,7 +175,7 @@ class CollectAERender(publish.AbstractCollectRender): version_str = "v{:03d}".format(render_instance.version) if "#" not in file_name: # single frame (mov)W path = os.path.join(base_dir, "{}_{}_{}.{}".format( - render_instance.asset, + render_instance.folderPath, render_instance.subset, version_str, ext @@ -184,7 +184,7 @@ class CollectAERender(publish.AbstractCollectRender): else: for frame in range(start, end + 1): path = os.path.join(base_dir, "{}_{}_{}.{}.{}".format( - render_instance.asset, + render_instance.folderPath, render_instance.subset, version_str, str(frame).zfill(self.padding_width), diff --git a/client/ayon_core/hosts/aftereffects/plugins/publish/collect_workfile.py b/client/ayon_core/hosts/aftereffects/plugins/publish/collect_workfile.py index 538d646ab4..107643f56c 100644 --- a/client/ayon_core/hosts/aftereffects/plugins/publish/collect_workfile.py +++ b/client/ayon_core/hosts/aftereffects/plugins/publish/collect_workfile.py @@ -50,11 +50,11 @@ class CollectWorkfile(pyblish.api.ContextPlugin): asset_entity = context.data["assetEntity"] project_entity = context.data["projectEntity"] - asset_name = get_asset_name_identifier(asset_entity) + folder_path = get_asset_name_identifier(asset_entity) instance_data = { "active": True, - "asset": asset_name, + "folderPath": folder_path, "task": task, "frameStart": context.data['frameStart'], "frameEnd": context.data['frameEnd'], diff --git a/client/ayon_core/hosts/aftereffects/plugins/publish/validate_instance_asset.py b/client/ayon_core/hosts/aftereffects/plugins/publish/validate_instance_asset.py index c3938ecbda..e8f2e29a2f 100644 --- a/client/ayon_core/hosts/aftereffects/plugins/publish/validate_instance_asset.py +++ b/client/ayon_core/hosts/aftereffects/plugins/publish/validate_instance_asset.py @@ -30,7 +30,7 @@ class ValidateInstanceAssetRepair(pyblish.api.Action): for instance in instances: data = stub.read(instance[0]) - data["asset"] = get_current_asset_name() + data["folderPath"] = get_current_asset_name() stub.imprint(instance[0].instance_id, data) @@ -53,7 +53,7 @@ class ValidateInstanceAsset(pyblish.api.InstancePlugin): order = ValidateContentsOrder def process(self, instance): - instance_asset = instance.data["asset"] + instance_asset = instance.data["folderPath"] current_asset = get_current_asset_name() msg = ( f"Instance asset {instance_asset} is not the same " diff --git a/client/ayon_core/hosts/blender/api/render_lib.py b/client/ayon_core/hosts/blender/api/render_lib.py index 35aa1f12c9..91913f7913 100644 --- a/client/ayon_core/hosts/blender/api/render_lib.py +++ b/client/ayon_core/hosts/blender/api/render_lib.py @@ -47,6 +47,22 @@ def get_multilayer(settings): ["multilayer_exr"]) +def get_renderer(settings): + """Get renderer from blender settings.""" + + return (settings["blender"] + ["RenderSettings"] + ["renderer"]) + + +def get_compositing(settings): + """Get compositing from blender settings.""" + + return (settings["blender"] + ["RenderSettings"] + ["compositing"]) + + def get_render_product(output_path, name, aov_sep): """ Generate the path to the render product. Blender interprets the `#` @@ -91,66 +107,120 @@ def set_render_format(ext, multilayer): image_settings.file_format = "TIFF" -def set_render_passes(settings): - aov_list = (settings["blender"] - ["RenderSettings"] - ["aov_list"]) - - custom_passes = (settings["blender"] - ["RenderSettings"] - ["custom_passes"]) +def set_render_passes(settings, renderer): + aov_list = set(settings["blender"]["RenderSettings"]["aov_list"]) + custom_passes = settings["blender"]["RenderSettings"]["custom_passes"] + # Common passes for both renderers vl = bpy.context.view_layer + # Data Passes vl.use_pass_combined = "combined" in aov_list vl.use_pass_z = "z" in aov_list vl.use_pass_mist = "mist" in aov_list vl.use_pass_normal = "normal" in aov_list + + # Light Passes vl.use_pass_diffuse_direct = "diffuse_light" in aov_list vl.use_pass_diffuse_color = "diffuse_color" in aov_list vl.use_pass_glossy_direct = "specular_light" in aov_list vl.use_pass_glossy_color = "specular_color" in aov_list - vl.eevee.use_pass_volume_direct = "volume_light" in aov_list vl.use_pass_emit = "emission" in aov_list vl.use_pass_environment = "environment" in aov_list - vl.use_pass_shadow = "shadow" in aov_list vl.use_pass_ambient_occlusion = "ao" in aov_list - cycles = vl.cycles + # Cryptomatte Passes + vl.use_pass_cryptomatte_object = "cryptomatte_object" in aov_list + vl.use_pass_cryptomatte_material = "cryptomatte_material" in aov_list + vl.use_pass_cryptomatte_asset = "cryptomatte_asset" in aov_list - cycles.denoising_store_passes = "denoising" in aov_list - cycles.use_pass_volume_direct = "volume_direct" in aov_list - cycles.use_pass_volume_indirect = "volume_indirect" in aov_list + if renderer == "BLENDER_EEVEE": + # Eevee exclusive passes + eevee = vl.eevee + + # Light Passes + vl.use_pass_shadow = "shadow" in aov_list + eevee.use_pass_volume_direct = "volume_light" in aov_list + + # Effects Passes + eevee.use_pass_bloom = "bloom" in aov_list + eevee.use_pass_transparent = "transparent" in aov_list + + # Cryptomatte Passes + vl.use_pass_cryptomatte_accurate = "cryptomatte_accurate" in aov_list + elif renderer == "CYCLES": + # Cycles exclusive passes + cycles = vl.cycles + + # Data Passes + vl.use_pass_position = "position" in aov_list + vl.use_pass_vector = "vector" in aov_list + vl.use_pass_uv = "uv" in aov_list + cycles.denoising_store_passes = "denoising" in aov_list + vl.use_pass_object_index = "object_index" in aov_list + vl.use_pass_material_index = "material_index" in aov_list + cycles.pass_debug_sample_count = "sample_count" in aov_list + + # Light Passes + vl.use_pass_diffuse_indirect = "diffuse_indirect" in aov_list + vl.use_pass_glossy_indirect = "specular_indirect" in aov_list + vl.use_pass_transmission_direct = "transmission_direct" in aov_list + vl.use_pass_transmission_indirect = "transmission_indirect" in aov_list + vl.use_pass_transmission_color = "transmission_color" in aov_list + cycles.use_pass_volume_direct = "volume_light" in aov_list + cycles.use_pass_volume_indirect = "volume_indirect" in aov_list + cycles.use_pass_shadow_catcher = "shadow" in aov_list aovs_names = [aov.name for aov in vl.aovs] for cp in custom_passes: - cp_name = cp[0] + cp_name = cp["attribute"] if cp_name not in aovs_names: aov = vl.aovs.add() aov.name = cp_name else: aov = vl.aovs[cp_name] - aov.type = cp[1].get("type", "VALUE") + aov.type = cp["value"] - return aov_list, custom_passes + return list(aov_list), custom_passes -def set_node_tree(output_path, name, aov_sep, ext, multilayer): +def _create_aov_slot(name, aov_sep, slots, rpass_name, multi_exr, output_path): + filename = f"{name}{aov_sep}{rpass_name}.####" + slot = slots.new(rpass_name if multi_exr else filename) + filepath = str(output_path / filename.lstrip("/")) + + return slot, filepath + + +def set_node_tree( + output_path, render_product, name, aov_sep, ext, multilayer, compositing +): # Set the scene to use the compositor node tree to render bpy.context.scene.use_nodes = True tree = bpy.context.scene.node_tree - # Get the Render Layers node - rl_node = None + comp_layer_type = "CompositorNodeRLayers" + output_type = "CompositorNodeOutputFile" + compositor_type = "CompositorNodeComposite" + + # Get the Render Layer, Composite and the previous output nodes + render_layer_node = None + composite_node = None + old_output_node = None for node in tree.nodes: - if node.bl_idname == "CompositorNodeRLayers": - rl_node = node + if node.bl_idname == comp_layer_type: + render_layer_node = node + elif node.bl_idname == compositor_type: + composite_node = node + elif node.bl_idname == output_type and "AYON" in node.name: + old_output_node = node + if render_layer_node and composite_node and old_output_node: break # If there's not a Render Layers node, we create it - if not rl_node: - rl_node = tree.nodes.new("CompositorNodeRLayers") + if not render_layer_node: + render_layer_node = tree.nodes.new(comp_layer_type) # Get the enabled output sockets, that are the active passes for the # render. @@ -158,48 +228,81 @@ def set_node_tree(output_path, name, aov_sep, ext, multilayer): exclude_sockets = ["Image", "Alpha", "Noisy Image"] passes = [ socket - for socket in rl_node.outputs + for socket in render_layer_node.outputs if socket.enabled and socket.name not in exclude_sockets ] - # Remove all output nodes - for node in tree.nodes: - if node.bl_idname == "CompositorNodeOutputFile": - tree.nodes.remove(node) - # Create a new output node - output = tree.nodes.new("CompositorNodeOutputFile") + output = tree.nodes.new(output_type) image_settings = bpy.context.scene.render.image_settings output.format.file_format = image_settings.file_format + slots = None + # In case of a multilayer exr, we don't need to use the output node, # because the blender render already outputs a multilayer exr. - if ext == "exr" and multilayer: - output.layer_slots.clear() - return [] + multi_exr = ext == "exr" and multilayer + slots = output.layer_slots if multi_exr else output.file_slots + output.base_path = render_product if multi_exr else str(output_path) - output.file_slots.clear() - output.base_path = str(output_path) + slots.clear() aov_file_products = [] + old_links = { + link.from_socket.name: link for link in tree.links + if link.to_node == old_output_node} + + # Create a new socket for the beauty output + pass_name = "rgba" if multi_exr else "beauty" + slot, _ = _create_aov_slot( + name, aov_sep, slots, pass_name, multi_exr, output_path) + tree.links.new(render_layer_node.outputs["Image"], slot) + + if compositing: + # Create a new socket for the composite output + pass_name = "composite" + comp_socket, filepath = _create_aov_slot( + name, aov_sep, slots, pass_name, multi_exr, output_path) + aov_file_products.append(("Composite", filepath)) + # For each active render pass, we add a new socket to the output node # and link it - for render_pass in passes: - filepath = f"{name}{aov_sep}{render_pass.name}.####" + for rpass in passes: + slot, filepath = _create_aov_slot( + name, aov_sep, slots, rpass.name, multi_exr, output_path) + aov_file_products.append((rpass.name, filepath)) - output.file_slots.new(filepath) + # If the rpass was not connected with the old output node, we connect + # it with the new one. + if not old_links.get(rpass.name): + tree.links.new(rpass, slot) - filename = str(output_path / filepath.lstrip("/")) + for link in list(old_links.values()): + # Check if the socket is still available in the new output node. + socket = output.inputs.get(link.to_socket.name) + # If it is, we connect it with the new output node. + if socket: + tree.links.new(link.from_socket, socket) + # Then, we remove the old link. + tree.links.remove(link) - aov_file_products.append((render_pass.name, filename)) + # If there's a composite node, we connect its input with the new output + if compositing and composite_node: + for link in tree.links: + if link.to_node == composite_node: + tree.links.new(link.from_socket, comp_socket) + break - node_input = output.inputs[-1] + if old_output_node: + output.location = old_output_node.location + tree.nodes.remove(old_output_node) - tree.links.new(render_pass, node_input) + output.name = "AYON File Output" + output.label = "AYON File Output" - return aov_file_products + return [] if multi_exr else aov_file_products def imprint_render_settings(node, data): @@ -228,17 +331,23 @@ def prepare_rendering(asset_group): aov_sep = get_aov_separator(settings) ext = get_image_format(settings) multilayer = get_multilayer(settings) + renderer = get_renderer(settings) + compositing = get_compositing(settings) set_render_format(ext, multilayer) - aov_list, custom_passes = set_render_passes(settings) + bpy.context.scene.render.engine = renderer + aov_list, custom_passes = set_render_passes(settings, renderer) output_path = Path.joinpath(dirpath, render_folder, file_name) render_product = get_render_product(output_path, name, aov_sep) aov_file_product = set_node_tree( - output_path, name, aov_sep, ext, multilayer) + output_path, render_product, name, aov_sep, + ext, multilayer, compositing) - bpy.context.scene.render.filepath = render_product + # Clear the render filepath, so that the output is handled only by the + # output node in the compositor. + bpy.context.scene.render.filepath = "" render_settings = { "render_folder": render_folder, diff --git a/client/ayon_core/hosts/blender/plugins/create/create_action.py b/client/ayon_core/hosts/blender/plugins/create/create_action.py index 2331daf7b7..82047fb5c6 100644 --- a/client/ayon_core/hosts/blender/plugins/create/create_action.py +++ b/client/ayon_core/hosts/blender/plugins/create/create_action.py @@ -22,7 +22,9 @@ class CreateAction(plugin.BaseCreator): ) # Get instance name - name = plugin.prepare_scene_name(instance_data["asset"], subset_name) + name = plugin.prepare_scene_name( + instance_data["folderPath"], subset_name + ) if pre_create_data.get("use_selection"): for obj in lib.get_selection(): diff --git a/client/ayon_core/hosts/blender/plugins/create/create_render.py b/client/ayon_core/hosts/blender/plugins/create/create_render.py index 82337a47f2..3f07f37d2f 100644 --- a/client/ayon_core/hosts/blender/plugins/create/create_render.py +++ b/client/ayon_core/hosts/blender/plugins/create/create_render.py @@ -1,8 +1,10 @@ """Create render.""" import bpy +from ayon_core.lib import version_up from ayon_core.hosts.blender.api import plugin from ayon_core.hosts.blender.api.render_lib import prepare_rendering +from ayon_core.hosts.blender.api.workio import save_file class CreateRenderlayer(plugin.BaseCreator): @@ -37,6 +39,7 @@ class CreateRenderlayer(plugin.BaseCreator): # settings. Even the validator to check that the file is saved will # detect the file as saved, even if it isn't. The only solution for # now it is to force the file to be saved. - bpy.ops.wm.save_as_mainfile(filepath=bpy.data.filepath) + filepath = version_up(bpy.data.filepath) + save_file(filepath, copy=False) return collection diff --git a/client/ayon_core/hosts/blender/plugins/publish/validate_deadline_publish.py b/client/ayon_core/hosts/blender/plugins/publish/validate_deadline_publish.py index b9310f9da0..b37db44cd4 100644 --- a/client/ayon_core/hosts/blender/plugins/publish/validate_deadline_publish.py +++ b/client/ayon_core/hosts/blender/plugins/publish/validate_deadline_publish.py @@ -28,15 +28,27 @@ class ValidateDeadlinePublish(pyblish.api.InstancePlugin, def process(self, instance): if not self.is_active(instance.data): return + + tree = bpy.context.scene.node_tree + output_type = "CompositorNodeOutputFile" + output_node = None + # Remove all output nodes that inlcude "AYON" in the name. + # There should be only one. + for node in tree.nodes: + if node.bl_idname == output_type and "AYON" in node.name: + output_node = node + break + if not output_node: + raise PublishValidationError( + "No output node found in the compositor tree." + ) filepath = bpy.data.filepath file = os.path.basename(filepath) filename, ext = os.path.splitext(file) - if filename not in bpy.context.scene.render.filepath: + if filename not in output_node.base_path: raise PublishValidationError( - "Render output folder " - "doesn't match the blender scene name! " - "Use Repair action to " - "fix the folder file path." + "Render output folder doesn't match the blender scene name! " + "Use Repair action to fix the folder file path." ) @classmethod diff --git a/client/ayon_core/hosts/celaction/plugins/publish/collect_celaction_instances.py b/client/ayon_core/hosts/celaction/plugins/publish/collect_celaction_instances.py index d0f4c59290..ef471dbd05 100644 --- a/client/ayon_core/hosts/celaction/plugins/publish/collect_celaction_instances.py +++ b/client/ayon_core/hosts/celaction/plugins/publish/collect_celaction_instances.py @@ -22,7 +22,7 @@ class CollectCelactionInstances(pyblish.api.ContextPlugin): asset_name = get_asset_name_identifier(asset_entity) shared_instance_data = { - "asset": asset_name, + "folderPath": asset_name, "frameStart": asset_entity["data"]["frameStart"], "frameEnd": asset_entity["data"]["frameEnd"], "handleStart": asset_entity["data"]["handleStart"], diff --git a/client/ayon_core/hosts/flame/plugins/publish/collect_timeline_otio.py b/client/ayon_core/hosts/flame/plugins/publish/collect_timeline_otio.py index 6a3e99aa55..2fcfb55e7c 100644 --- a/client/ayon_core/hosts/flame/plugins/publish/collect_timeline_otio.py +++ b/client/ayon_core/hosts/flame/plugins/publish/collect_timeline_otio.py @@ -34,7 +34,7 @@ class CollecTimelineOTIO(pyblish.api.ContextPlugin): project_settings=context.data["project_settings"] ) - asset_name = get_asset_name_identifier(asset_doc) + folder_path = get_asset_name_identifier(asset_doc) # adding otio timeline to context with opfapi.maintained_segment_selection(sequence) as selected_seg: @@ -42,7 +42,7 @@ class CollecTimelineOTIO(pyblish.api.ContextPlugin): instance_data = { "name": subset_name, - "asset": asset_name, + "folderPath": folder_path, "subset": subset_name, "family": "workfile", "families": [] diff --git a/client/ayon_core/hosts/flame/plugins/publish/extract_subset_resources.py b/client/ayon_core/hosts/flame/plugins/publish/extract_subset_resources.py index 9e55dbce96..cae08cd76b 100644 --- a/client/ayon_core/hosts/flame/plugins/publish/extract_subset_resources.py +++ b/client/ayon_core/hosts/flame/plugins/publish/extract_subset_resources.py @@ -55,7 +55,7 @@ class ExtractProductResources(publish.Extractor): # flame objects segment = instance.data["item"] - asset_name = instance.data["asset"] + folder_path = instance.data["folderPath"] segment_name = segment.name.get_value() clip_path = instance.data["path"] sequence_clip = instance.context.data["flameSequence"] @@ -249,7 +249,7 @@ class ExtractProductResources(publish.Extractor): out_mark = in_mark + source_duration_handles exporting_clip = self.import_clip(clip_path) exporting_clip.name.set_value("{}_{}".format( - asset_name, segment_name)) + folder_path, segment_name)) # add xml tags modifications modify_xml_data.update({ diff --git a/client/ayon_core/hosts/flame/plugins/publish/integrate_batch_group.py b/client/ayon_core/hosts/flame/plugins/publish/integrate_batch_group.py index 3458bd3002..e36d2a22d5 100644 --- a/client/ayon_core/hosts/flame/plugins/publish/integrate_batch_group.py +++ b/client/ayon_core/hosts/flame/plugins/publish/integrate_batch_group.py @@ -168,10 +168,10 @@ class IntegrateBatchGroup(pyblish.api.InstancePlugin): handle_start = instance.data["handleStart"] handle_end = instance.data["handleEnd"] frame_duration = (frame_end - frame_start) + 1 - asset_name = instance.data["asset"] + folder_path = instance.data["folderPath"] task_name = task_data["name"] - batchgroup_name = "{}_{}".format(asset_name, task_name) + batchgroup_name = "{}_{}".format(folder_path, task_name) batch_data = { "shematic_reels": [ diff --git a/client/ayon_core/hosts/fusion/plugins/publish/collect_render.py b/client/ayon_core/hosts/fusion/plugins/publish/collect_render.py index f8870da1c5..0a0e4b38af 100644 --- a/client/ayon_core/hosts/fusion/plugins/publish/collect_render.py +++ b/client/ayon_core/hosts/fusion/plugins/publish/collect_render.py @@ -68,7 +68,7 @@ class CollectFusionRender( source=current_file, label=inst.data["label"], subset=subset_name, - asset=inst.data["asset"], + folderPath=inst.data["folderPath"], task=task_name, attachTo=False, setMembers='', diff --git a/client/ayon_core/hosts/fusion/plugins/publish/extract_render_local.py b/client/ayon_core/hosts/fusion/plugins/publish/extract_render_local.py index eea232ac29..23a8cdb8a0 100644 --- a/client/ayon_core/hosts/fusion/plugins/publish/extract_render_local.py +++ b/client/ayon_core/hosts/fusion/plugins/publish/extract_render_local.py @@ -72,7 +72,7 @@ class FusionRenderLocal( self.log.info( "Rendered '{nm}' for asset '{ast}' under the task '{tsk}'".format( nm=instance.data["name"], - ast=instance.data["asset"], + ast=instance.data["folderPath"], tsk=instance.data["task"], ) ) diff --git a/client/ayon_core/hosts/fusion/plugins/publish/validate_unique_subsets.py b/client/ayon_core/hosts/fusion/plugins/publish/validate_unique_subsets.py index 619b52077e..3131400de9 100644 --- a/client/ayon_core/hosts/fusion/plugins/publish/validate_unique_subsets.py +++ b/client/ayon_core/hosts/fusion/plugins/publish/validate_unique_subsets.py @@ -21,7 +21,9 @@ class ValidateUniqueSubsets(pyblish.api.ContextPlugin): # Collect instances per subset per asset instances_per_subset_asset = defaultdict(lambda: defaultdict(list)) for instance in context: - asset = instance.data.get("asset", context.data.get("asset")) + asset = instance.data.get( + "folderPath", context.data.get("folderPath") + ) subset = instance.data.get("subset", context.data.get("subset")) instances_per_subset_asset[asset][subset].append(instance) diff --git a/client/ayon_core/hosts/harmony/plugins/publish/collect_farm_render.py b/client/ayon_core/hosts/harmony/plugins/publish/collect_farm_render.py index faeff7bddd..6a9c349185 100644 --- a/client/ayon_core/hosts/harmony/plugins/publish/collect_farm_render.py +++ b/client/ayon_core/hosts/harmony/plugins/publish/collect_farm_render.py @@ -98,7 +98,7 @@ class CollectFarmRender(publish.AbstractCollectRender): self_name = self.__class__.__name__ - asset_name = context.data["asset"] + folder_path = context.data["folderPath"] for node in context.data["allNodes"]: data = harmony.read(node) @@ -142,7 +142,7 @@ class CollectFarmRender(publish.AbstractCollectRender): source=context.data["currentFile"], label=node.split("/")[1], subset=subset_name, - asset=asset_name, + folderPath=folder_path, task=task_name, attachTo=False, setMembers=[node], diff --git a/client/ayon_core/hosts/harmony/plugins/publish/collect_palettes.py b/client/ayon_core/hosts/harmony/plugins/publish/collect_palettes.py index 9343fab86d..66b1ee6085 100644 --- a/client/ayon_core/hosts/harmony/plugins/publish/collect_palettes.py +++ b/client/ayon_core/hosts/harmony/plugins/publish/collect_palettes.py @@ -31,7 +31,7 @@ class CollectPalettes(pyblish.api.ContextPlugin): if (not any([re.search(pattern, task_name) for pattern in self.allowed_tasks])): return - asset_name = context.data["asset"] + folder_path = context.data["folderPath"] for name, id in palettes.items(): instance = context.create_instance(name) @@ -39,7 +39,7 @@ class CollectPalettes(pyblish.api.ContextPlugin): "id": id, "family": "harmony.palette", 'families': [], - "asset": asset_name, + "folderPath": folder_path, "subset": "{}{}".format("palette", name) }) self.log.info( diff --git a/client/ayon_core/hosts/harmony/plugins/publish/collect_workfile.py b/client/ayon_core/hosts/harmony/plugins/publish/collect_workfile.py index 4be2a0fc26..1ea1f15124 100644 --- a/client/ayon_core/hosts/harmony/plugins/publish/collect_workfile.py +++ b/client/ayon_core/hosts/harmony/plugins/publish/collect_workfile.py @@ -36,5 +36,5 @@ class CollectWorkfile(pyblish.api.ContextPlugin): "family": family, "families": [family], "representations": [], - "asset": context.data["asset"] + "folderPath": context.data["folderPath"] }) diff --git a/client/ayon_core/hosts/harmony/plugins/publish/validate_instances.py b/client/ayon_core/hosts/harmony/plugins/publish/validate_instances.py index a57a863d6f..fdba834de6 100644 --- a/client/ayon_core/hosts/harmony/plugins/publish/validate_instances.py +++ b/client/ayon_core/hosts/harmony/plugins/publish/validate_instances.py @@ -27,9 +27,10 @@ class ValidateInstanceRepair(pyblish.api.Action): # Apply pyblish.logic to get the instances for the plug-in instances = pyblish.api.instances_by_plugin(failed, plugin) + folder_path = get_current_asset_name() for instance in instances: data = harmony.read(instance.data["setMembers"][0]) - data["asset"] = get_current_asset_name() + data["folderPath"] = folder_path harmony.imprint(instance.data["setMembers"][0], data) @@ -42,7 +43,7 @@ class ValidateInstance(pyblish.api.InstancePlugin): order = ValidateContentsOrder def process(self, instance): - instance_asset = instance.data["asset"] + instance_asset = instance.data["folderPath"] current_asset = get_current_asset_name() msg = ( "Instance asset is not the same as current asset:" diff --git a/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py b/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py index d7f646ebc9..3bd5b88942 100644 --- a/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py +++ b/client/ayon_core/hosts/hiero/plugins/publish/collect_clip_effects.py @@ -118,9 +118,9 @@ class CollectClipEffects(pyblish.api.InstancePlugin): data["subset"] = name data["family"] = family data["families"] = [family] - data["name"] = data["subset"] + "_" + data["asset"] + data["name"] = data["subset"] + "_" + data["folderPath"] data["label"] = "{} - {}".format( - data['asset'], data["subset"] + data["folderPath"], data["subset"] ) data["effects"] = effects diff --git a/client/ayon_core/hosts/hiero/plugins/publish/collect_frame_tag_instances.py b/client/ayon_core/hosts/hiero/plugins/publish/collect_frame_tag_instances.py index b981d89eef..6f99e6be29 100644 --- a/client/ayon_core/hosts/hiero/plugins/publish/collect_frame_tag_instances.py +++ b/client/ayon_core/hosts/hiero/plugins/publish/collect_frame_tag_instances.py @@ -102,7 +102,7 @@ class CollectFrameTagInstances(pyblish.api.ContextPlugin): # first collect all available subset tag frames subset_data = {} context_asset_doc = context.data["assetEntity"] - context_asset_name = get_asset_name_identifier(context_asset_doc) + context_folder_path = get_asset_name_identifier(context_asset_doc) for tag_data in sequence_tags: frame = int(tag_data["start"]) @@ -120,7 +120,7 @@ class CollectFrameTagInstances(pyblish.api.ContextPlugin): subset_data[subset] = { "frames": [frame], "format": tag_data["format"], - "asset": context_asset_name + "folderPath": context_folder_path } return subset_data @@ -133,7 +133,7 @@ class CollectFrameTagInstances(pyblish.api.ContextPlugin): "label": "{} {}".format(name, subset_data["frames"]), "family": "image", "families": ["frame"], - "asset": subset_data["asset"], + "folderPath": subset_data["folderPath"], "subset": name, "format": subset_data["format"], "frames": subset_data["frames"] diff --git a/client/ayon_core/hosts/hiero/plugins/publish/extract_clip_effects.py b/client/ayon_core/hosts/hiero/plugins/publish/extract_clip_effects.py index afff41fc74..d1edfed0d7 100644 --- a/client/ayon_core/hosts/hiero/plugins/publish/extract_clip_effects.py +++ b/client/ayon_core/hosts/hiero/plugins/publish/extract_clip_effects.py @@ -57,7 +57,7 @@ class ExtractClipEffects(publish.Extractor): "sourceStart", "sourceStartH", "sourceEnd", "sourceEndH", "frameStart", "frameEnd", "clipIn", "clipOut", "clipInH", "clipOutH", - "asset", "version" + "folderPath", "version" ] # pass data to version diff --git a/client/ayon_core/hosts/hiero/plugins/publish/precollect_instances.py b/client/ayon_core/hosts/hiero/plugins/publish/precollect_instances.py index 6344d76cd0..e6381af939 100644 --- a/client/ayon_core/hosts/hiero/plugins/publish/precollect_instances.py +++ b/client/ayon_core/hosts/hiero/plugins/publish/precollect_instances.py @@ -101,7 +101,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin): data.update({ "name": "{}_{}".format(asset, subset), "label": label, - "asset": asset, + "folderPath": asset, "asset_name": asset_name, "item": track_item, "families": families, @@ -192,7 +192,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin): if not hierarchy_data: return - asset = data["asset"] + asset = data["folderPath"] asset_name = data["asset_name"] # insert family into families @@ -244,7 +244,6 @@ class PrecollectInstances(pyblish.api.ContextPlugin): if not master_layer: return - asset = data.get("asset") item = data.get("item") clip_name = item.name() @@ -252,7 +251,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin): if not self.test_any_audio(item): return - asset = data["asset"] + asset = data["folderPath"] asset_name = data["asset_name"] # insert family into families diff --git a/client/ayon_core/hosts/hiero/plugins/publish/precollect_workfile.py b/client/ayon_core/hosts/hiero/plugins/publish/precollect_workfile.py index e9e2aae653..15dd0dee26 100644 --- a/client/ayon_core/hosts/hiero/plugins/publish/precollect_workfile.py +++ b/client/ayon_core/hosts/hiero/plugins/publish/precollect_workfile.py @@ -17,7 +17,7 @@ class PrecollectWorkfile(pyblish.api.ContextPlugin): order = pyblish.api.CollectorOrder - 0.491 def process(self, context): - asset = context.data["asset"] + asset = context.data["folderPath"] asset_name = asset.split("/")[-1] active_timeline = hiero.ui.activeSequence() @@ -64,7 +64,7 @@ class PrecollectWorkfile(pyblish.api.ContextPlugin): "label": "{} - {}Main".format( asset, family), "name": "{}_{}".format(asset_name, family), - "asset": context.data["asset"], + "folderPath": context.data["folderPath"], # TODO use 'get_subset_name' "subset": "{}{}Main".format(asset_name, family.capitalize()), "item": project, diff --git a/client/ayon_core/hosts/houdini/plugins/publish/collect_instances.py b/client/ayon_core/hosts/houdini/plugins/publish/collect_instances.py index 5869d201c0..67e8f147d7 100644 --- a/client/ayon_core/hosts/houdini/plugins/publish/collect_instances.py +++ b/client/ayon_core/hosts/houdini/plugins/publish/collect_instances.py @@ -75,7 +75,7 @@ class CollectInstances(pyblish.api.ContextPlugin): # Create nice name if the instance has a frame range. label = data.get("name", node.name()) - label += " (%s)" % data["asset"] # include asset in name + label += " (%s)" % data["folderPath"] # include folder in name instance = context.create_instance(label) diff --git a/client/ayon_core/hosts/houdini/plugins/publish/collect_usd_bootstrap.py b/client/ayon_core/hosts/houdini/plugins/publish/collect_usd_bootstrap.py index 7342c8f621..791b530eed 100644 --- a/client/ayon_core/hosts/houdini/plugins/publish/collect_usd_bootstrap.py +++ b/client/ayon_core/hosts/houdini/plugins/publish/collect_usd_bootstrap.py @@ -55,7 +55,7 @@ class CollectUsdBootstrap(pyblish.api.InstancePlugin): self.log.debug("Add bootstrap for: %s" % bootstrap) project_name = instance.context.data["projectName"] - asset_name = instance.data["asset"] + asset_name = instance.data["folderPath"] asset_doc = get_asset_by_name(project_name, asset_name) assert asset_doc, "Asset must exist: %s" % asset_name @@ -95,7 +95,7 @@ class CollectUsdBootstrap(pyblish.api.InstancePlugin): new.data["optional"] = False # Copy some data from the instance for which we bootstrap - for key in ["asset"]: + for key in ["folderPath"]: new.data[key] = instance.data[key] def _subset_exists(self, project_name, instance, subset_name, asset_doc): @@ -107,7 +107,7 @@ class CollectUsdBootstrap(pyblish.api.InstancePlugin): for inst in context: if ( inst.data["subset"] == subset_name - and inst.data["asset"] == asset_doc_name + and inst.data["folderPath"] == asset_doc_name ): return True diff --git a/client/ayon_core/hosts/houdini/plugins/publish/collect_usd_layers.py b/client/ayon_core/hosts/houdini/plugins/publish/collect_usd_layers.py index e36cd875ba..70dc28e925 100644 --- a/client/ayon_core/hosts/houdini/plugins/publish/collect_usd_layers.py +++ b/client/ayon_core/hosts/houdini/plugins/publish/collect_usd_layers.py @@ -55,7 +55,7 @@ class CollectUsdLayers(pyblish.api.InstancePlugin): layer_inst.data["families"] = [family] layer_inst.data["subset"] = "__stub__" layer_inst.data["label"] = label - layer_inst.data["asset"] = instance.data["asset"] + layer_inst.data["folderPath"] = instance.data["folderPath"] layer_inst.data["instance_node"] = instance.data["instance_node"] # include same USD ROP layer_inst.append(rop_node) diff --git a/client/ayon_core/hosts/houdini/plugins/publish/extract_usd_layered.py b/client/ayon_core/hosts/houdini/plugins/publish/extract_usd_layered.py index 7160e3d282..56c335f50e 100644 --- a/client/ayon_core/hosts/houdini/plugins/publish/extract_usd_layered.py +++ b/client/ayon_core/hosts/houdini/plugins/publish/extract_usd_layered.py @@ -285,7 +285,7 @@ class ExtractUSDLayered(publish.Extractor): # to detect whether we should make this into a new publish # version. If not, skip it. asset = get_asset_by_name( - project_name, dependency.data["asset"], fields=["_id"] + project_name, dependency.data["folderPath"], fields=["_id"] ) subset = get_subset_by_name( project_name, diff --git a/client/ayon_core/hosts/houdini/plugins/publish/validate_usd_shade_model_exists.py b/client/ayon_core/hosts/houdini/plugins/publish/validate_usd_shade_model_exists.py index 8fa20ace02..c8b9ed9bab 100644 --- a/client/ayon_core/hosts/houdini/plugins/publish/validate_usd_shade_model_exists.py +++ b/client/ayon_core/hosts/houdini/plugins/publish/validate_usd_shade_model_exists.py @@ -18,7 +18,7 @@ class ValidateUSDShadeModelExists(pyblish.api.InstancePlugin): def process(self, instance): project_name = instance.context.data["projectName"] - asset_name = instance.data["asset"] + asset_name = instance.data["folderPath"] subset = instance.data["subset"] # Assume shading variation starts after a dot separator diff --git a/client/ayon_core/hosts/max/plugins/create/create_workfile.py b/client/ayon_core/hosts/max/plugins/create/create_workfile.py new file mode 100644 index 0000000000..27864c28d5 --- /dev/null +++ b/client/ayon_core/hosts/max/plugins/create/create_workfile.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +"""Creator plugin for creating workfiles.""" +from ayon_core.pipeline import CreatedInstance, AutoCreator +from ayon_core.client import get_asset_by_name, get_asset_name_identifier +from ayon_core.hosts.max.api import plugin +from ayon_core.hosts.max.api.lib import read, imprint +from pymxs import runtime as rt + + +class CreateWorkfile(plugin.MaxCreatorBase, AutoCreator): + """Workfile auto-creator.""" + identifier = "io.ayon.creators.max.workfile" + label = "Workfile" + family = "workfile" + icon = "fa5.file" + + default_variant = "Main" + + def create(self): + variant = self.default_variant + current_instance = next( + ( + instance for instance in self.create_context.instances + if instance.creator_identifier == self.identifier + ), None) + project_name = self.project_name + asset_name = self.create_context.get_current_asset_name() + task_name = self.create_context.get_current_task_name() + host_name = self.create_context.host_name + + if current_instance is None: + asset_doc = get_asset_by_name(project_name, asset_name) + subset_name = self.get_subset_name( + variant, task_name, asset_doc, project_name, host_name + ) + data = { + "folderPath": asset_name, + "task": task_name, + "variant": variant + } + + data.update( + self.get_dynamic_data( + variant, task_name, asset_doc, + project_name, host_name, current_instance) + ) + self.log.info("Auto-creating workfile instance...") + instance_node = self.create_node(subset_name) + data["instance_node"] = instance_node.name + current_instance = CreatedInstance( + self.family, subset_name, data, self + ) + self._add_instance_to_context(current_instance) + imprint(instance_node.name, current_instance.data) + elif ( + current_instance["folderPath"] != asset_name + or current_instance["task"] != task_name + ): + # Update instance context if is not the same + asset_doc = get_asset_by_name(project_name, asset_name) + subset_name = self.get_subset_name( + variant, task_name, asset_doc, project_name, host_name + ) + asset_name = get_asset_name_identifier(asset_doc) + + current_instance["folderPath"] = asset_name + current_instance["task"] = task_name + current_instance["subset"] = subset_name + + def collect_instances(self): + self.cache_subsets(self.collection_shared_data) + for instance in self.collection_shared_data["max_cached_subsets"].get(self.identifier, []): # noqa + if not rt.getNodeByName(instance): + continue + created_instance = CreatedInstance.from_existing( + read(rt.GetNodeByName(instance)), self + ) + self._add_instance_to_context(created_instance) + + def update_instances(self, update_list): + for created_inst, _ in update_list: + instance_node = created_inst.get("instance_node") + imprint( + instance_node, + created_inst.data_to_store() + ) + + def remove_instances(self, instances): + """Remove specified instance from the scene. + + This is only removing `id` parameter so instance is no longer + instance, because it might contain valuable data for artist. + + """ + for instance in instances: + instance_node = rt.GetNodeByName( + instance.data.get("instance_node")) + if instance_node: + rt.Delete(instance_node) + + self._remove_instance_from_context(instance) + + def create_node(self, subset_name): + if rt.getNodeByName(subset_name): + node = rt.getNodeByName(subset_name) + return node + node = rt.Container(name=subset_name) + node.isHidden = True + return node diff --git a/client/ayon_core/hosts/max/plugins/publish/collect_current_file.py b/client/ayon_core/hosts/max/plugins/publish/collect_current_file.py new file mode 100644 index 0000000000..6f8b8dda4b --- /dev/null +++ b/client/ayon_core/hosts/max/plugins/publish/collect_current_file.py @@ -0,0 +1,23 @@ +import os +import pyblish.api + +from pymxs import runtime as rt + + +class CollectCurrentFile(pyblish.api.ContextPlugin): + """Inject the current working file.""" + + order = pyblish.api.CollectorOrder - 0.5 + label = "Max Current File" + hosts = ['max'] + + def process(self, context): + """Inject the current working file""" + folder = rt.maxFilePath + file = rt.maxFileName + if not folder or not file: + self.log.error("Scene is not saved.") + current_file = os.path.join(folder, file) + + context.data["currentFile"] = current_file + self.log.debug("Scene path: {}".format(current_file)) diff --git a/client/ayon_core/hosts/max/plugins/publish/collect_members.py b/client/ayon_core/hosts/max/plugins/publish/collect_members.py index 2970cf0e24..f3fde00fe0 100644 --- a/client/ayon_core/hosts/max/plugins/publish/collect_members.py +++ b/client/ayon_core/hosts/max/plugins/publish/collect_members.py @@ -12,7 +12,9 @@ class CollectMembers(pyblish.api.InstancePlugin): hosts = ['max'] def process(self, instance): - + if instance.data["family"] == "workfile": + self.log.debug("Skipping Collecting Members for workfile family.") + return if instance.data.get("instance_node"): container = rt.GetNodeByName(instance.data["instance_node"]) instance.data["members"] = [ diff --git a/client/ayon_core/hosts/max/plugins/publish/collect_render.py b/client/ayon_core/hosts/max/plugins/publish/collect_render.py index a97e8a154e..66226e24fa 100644 --- a/client/ayon_core/hosts/max/plugins/publish/collect_render.py +++ b/client/ayon_core/hosts/max/plugins/publish/collect_render.py @@ -94,7 +94,7 @@ class CollectRender(pyblish.api.InstancePlugin): renderer = str(renderer_class).split(":")[0] # also need to get the render dir for conversion data = { - "asset": instance.data["asset"], + "folderPath": instance.data["folderPath"], "subset": str(instance.name), "publish": True, "maxversion": str(get_max_version()), diff --git a/client/ayon_core/hosts/max/plugins/publish/collect_workfile.py b/client/ayon_core/hosts/max/plugins/publish/collect_workfile.py index 0eb4bb731e..6eec0f7292 100644 --- a/client/ayon_core/hosts/max/plugins/publish/collect_workfile.py +++ b/client/ayon_core/hosts/max/plugins/publish/collect_workfile.py @@ -6,57 +6,41 @@ import pyblish.api from pymxs import runtime as rt -class CollectWorkfile(pyblish.api.ContextPlugin): +class CollectWorkfile(pyblish.api.InstancePlugin): """Inject the current working file into context""" order = pyblish.api.CollectorOrder - 0.01 label = "Collect 3dsmax Workfile" hosts = ['max'] + families = ["workfile"] - def process(self, context): + def process(self, instance): """Inject the current working file.""" + context = instance.context folder = rt.maxFilePath file = rt.maxFileName if not folder or not file: self.log.error("Scene is not saved.") - current_file = os.path.join(folder, file) - - context.data['currentFile'] = current_file - - filename, ext = os.path.splitext(file) - - task = context.data["task"] + ext = os.path.splitext(file)[-1].lstrip(".") data = {} - # create instance - instance = context.create_instance(name=filename) - subset = 'workfile' + task.capitalize() - data.update({ - "subset": subset, - "asset": context.data["asset"], - "label": subset, - "publish": True, - "family": 'workfile', - "families": ['workfile'], - "setMembers": [current_file], - "frameStart": context.data['frameStart'], - "frameEnd": context.data['frameEnd'], - "handleStart": context.data['handleStart'], - "handleEnd": context.data['handleEnd'] + "setMembers": context.data["currentFile"], + "frameStart": context.data["frameStart"], + "frameEnd": context.data["frameEnd"], + "handleStart": context.data["handleStart"], + "handleEnd": context.data["handleEnd"] }) - data['representations'] = [{ - 'name': ext.lstrip("."), - 'ext': ext.lstrip("."), - 'files': file, + data["representations"] = [{ + "name": ext, + "ext": ext, + "files": file, "stagingDir": folder, }] instance.data.update(data) - - self.log.info('Collected instance: {}'.format(file)) - self.log.info('Scene path: {}'.format(current_file)) - self.log.info('staging Dir: {}'.format(folder)) - self.log.info('subset: {}'.format(subset)) + self.log.debug("Collected data: {}".format(data)) + self.log.debug("Collected instance: {}".format(file)) + self.log.debug("staging Dir: {}".format(folder)) diff --git a/client/ayon_core/hosts/maya/api/action.py b/client/ayon_core/hosts/maya/api/action.py index 1edca82ee4..4beb1e3e5b 100644 --- a/client/ayon_core/hosts/maya/api/action.py +++ b/client/ayon_core/hosts/maya/api/action.py @@ -15,7 +15,7 @@ class GenerateUUIDsOnInvalidAction(pyblish.api.Action): receive new UUIDs are actually invalid. Requires: - - instance.data["asset"] + - instance.data["folderPath"] """ @@ -78,7 +78,7 @@ class GenerateUUIDsOnInvalidAction(pyblish.api.Action): # should be always available, but kept a way to query it by name. asset_doc = instance.data.get("assetEntity") if not asset_doc: - asset_name = instance.data["asset"] + asset_name = instance.data["folderPath"] project_name = instance.context.data["projectName"] self.log.info(( "Asset is not stored on instance." diff --git a/client/ayon_core/hosts/maya/api/lib.py b/client/ayon_core/hosts/maya/api/lib.py index b38439144e..77b18fb394 100644 --- a/client/ayon_core/hosts/maya/api/lib.py +++ b/client/ayon_core/hosts/maya/api/lib.py @@ -24,7 +24,8 @@ from ayon_core.client import ( get_asset_by_name, get_subsets, get_last_versions, - get_representation_by_name + get_representation_by_name, + get_asset_name_identifier, ) from ayon_core.settings import get_project_settings from ayon_core.pipeline import ( @@ -3152,11 +3153,11 @@ def fix_incompatible_containers(): def update_content_on_context_change(): """ - This will update scene content to match new asset on context change + This will update scene content to match new folder on context change """ scene_sets = cmds.listSets(allSets=True) asset_doc = get_current_project_asset() - new_asset = asset_doc["name"] + new_folder_path = get_asset_name_identifier(asset_doc) new_data = asset_doc["data"] for s in scene_sets: try: @@ -3165,10 +3166,14 @@ def update_content_on_context_change(): }: attr = cmds.listAttr(s) print(s) - if "asset" in attr: - print(" - setting asset to: [ {} ]".format(new_asset)) - cmds.setAttr("{}.asset".format(s), - new_asset, type="string") + if "folderPath" in attr: + print( + " - setting folder to: [ {} ]".format(new_folder_path) + ) + cmds.setAttr( + "{}.folderPath".format(s), + new_folder_path, type="string" + ) if "frameStart" in attr: cmds.setAttr("{}.frameStart".format(s), new_data["frameStart"]) diff --git a/client/ayon_core/hosts/maya/plugins/publish/collect_render.py b/client/ayon_core/hosts/maya/plugins/publish/collect_render.py index 4ea91ccb0d..d5392fba4a 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/collect_render.py +++ b/client/ayon_core/hosts/maya/plugins/publish/collect_render.py @@ -307,7 +307,7 @@ class CollectMayaRender(pyblish.api.InstancePlugin): _instance.data["version"] = context.data["version"] # Define nice label - label = "{0} ({1})".format(layer_name, instance.data["asset"]) + label = "{0} ({1})".format(layer_name, instance.data["folderPath"]) label += " [{0}-{1}]".format( int(data["frameStartHandle"]), int(data["frameEndHandle"]) ) diff --git a/client/ayon_core/hosts/maya/plugins/publish/collect_vrayscene.py b/client/ayon_core/hosts/maya/plugins/publish/collect_vrayscene.py index db008cc2be..979f49f7fe 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/collect_vrayscene.py +++ b/client/ayon_core/hosts/maya/plugins/publish/collect_vrayscene.py @@ -99,7 +99,7 @@ class CollectVrayScene(pyblish.api.InstancePlugin): instance.data.update(data) # Define nice label - label = "{0} ({1})".format(layer_name, instance.data["asset"]) + label = "{0} ({1})".format(layer_name, instance.data["folderPath"]) label += " [{0}-{1}]".format( int(data["frameStartHandle"]), int(data["frameEndHandle"]) ) diff --git a/client/ayon_core/hosts/maya/plugins/publish/extract_unreal_skeletalmesh_fbx.py b/client/ayon_core/hosts/maya/plugins/publish/extract_unreal_skeletalmesh_fbx.py index 7b44c92194..edbb5f845e 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/extract_unreal_skeletalmesh_fbx.py +++ b/client/ayon_core/hosts/maya/plugins/publish/extract_unreal_skeletalmesh_fbx.py @@ -61,7 +61,7 @@ class ExtractUnrealSkeletalMeshFbx(publish.Extractor): # we rely on hierarchy under one root. original_parent = to_extract[0].split("|")[1] - parent_node = instance.data.get("asset") + parent_node = instance.data.get("folderPath") # this needs to be done for AYON # WARNING: since AYON supports duplicity of asset names, # this needs to be refactored throughout the pipeline. diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_instance_in_context.py b/client/ayon_core/hosts/maya/plugins/publish/validate_instance_in_context.py index c683c1b30f..43b4f06e3f 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_instance_in_context.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_instance_in_context.py @@ -37,7 +37,7 @@ class ValidateInstanceInContext(pyblish.api.InstancePlugin, if not self.is_active(instance.data): return - asset = instance.data.get("asset") + asset = instance.data.get("folderPath") context_asset = self.get_context_asset(instance) if asset != context_asset: raise PublishValidationError( @@ -74,4 +74,4 @@ class ValidateInstanceInContext(pyblish.api.InstancePlugin, @staticmethod def get_context_asset(instance): - return instance.context.data["asset"] + return instance.context.data["folderPath"] diff --git a/client/ayon_core/hosts/maya/plugins/publish/validate_shader_name.py b/client/ayon_core/hosts/maya/plugins/publish/validate_shader_name.py index cb7f975535..86ca0ca400 100644 --- a/client/ayon_core/hosts/maya/plugins/publish/validate_shader_name.py +++ b/client/ayon_core/hosts/maya/plugins/publish/validate_shader_name.py @@ -51,7 +51,7 @@ class ValidateShaderName(pyblish.api.InstancePlugin, descendants = cmds.ls(descendants, noIntermediate=True, long=True) shapes = cmds.ls(descendants, type=["nurbsSurface", "mesh"], long=True) - asset_name = instance.data.get("asset") + asset_name = instance.data.get("folderPath") # Check the number of connected shadingEngines per shape regex_compile = re.compile(cls.regex) diff --git a/client/ayon_core/hosts/nuke/plugins/publish/validate_asset_context.py b/client/ayon_core/hosts/nuke/plugins/publish/validate_asset_context.py index b4814c6a00..52ef4a58d4 100644 --- a/client/ayon_core/hosts/nuke/plugins/publish/validate_asset_context.py +++ b/client/ayon_core/hosts/nuke/plugins/publish/validate_asset_context.py @@ -23,10 +23,10 @@ class ValidateCorrectAssetContext( current asset (shot). This validator checks if this is so. It is optional so it can be disabled when needed. - Checking `asset` and `task` keys. + Checking `folderPath` and `task` keys. """ order = ValidateContentsOrder - label = "Validate asset context" + label = "Validate Folder context" hosts = ["nuke"] actions = [ RepairAction, @@ -85,7 +85,7 @@ class ValidateCorrectAssetContext( """Get invalid keys from instance data and context data.""" invalid_keys = [] - testing_keys = ["asset", "task"] + testing_keys = ["folderPath", "task"] for _key in testing_keys: if _key not in instance.data: invalid_keys.append(_key) diff --git a/client/ayon_core/hosts/photoshop/api/ws_stub.py b/client/ayon_core/hosts/photoshop/api/ws_stub.py index f53f7e04d9..78cb5fac5d 100644 --- a/client/ayon_core/hosts/photoshop/api/ws_stub.py +++ b/client/ayon_core/hosts/photoshop/api/ws_stub.py @@ -120,7 +120,7 @@ class PhotoshopServerStub: "subset":"imageBG", "family":"image", "id":"ayon.create.instance", - "asset":"Town", + "folderPath":"Town", "uuid": "8" }] - for created instances OR @@ -421,7 +421,7 @@ class PhotoshopServerStub: example: {"8":{"active":true,"subset":"imageBG", "family":"image","id":"ayon.create.instance", - "asset":"Town"}} + "folderPath":"/Town"}} 8 is layer(group) id - used for deletion, update etc. """ res = self.websocketserver.call(self.client.call('Photoshop.read')) diff --git a/client/ayon_core/hosts/photoshop/plugins/publish/collect_auto_image.py b/client/ayon_core/hosts/photoshop/plugins/publish/collect_auto_image.py index 051a3da0a1..479d9139af 100644 --- a/client/ayon_core/hosts/photoshop/plugins/publish/collect_auto_image.py +++ b/client/ayon_core/hosts/photoshop/plugins/publish/collect_auto_image.py @@ -28,7 +28,7 @@ class CollectAutoImage(pyblish.api.ContextPlugin): task_name = context.data["task"] host_name = context.data["hostName"] asset_doc = context.data["assetEntity"] - asset_name = get_asset_name_identifier(asset_doc) + folder_path = get_asset_name_identifier(asset_doc) auto_creator = proj_settings.get( "photoshop", {}).get( @@ -86,7 +86,7 @@ class CollectAutoImage(pyblish.api.ContextPlugin): instance = context.create_instance(subset_name) instance.data["family"] = family - instance.data["asset"] = asset_name + instance.data["folderPath"] = folder_path instance.data["subset"] = subset_name instance.data["ids"] = publishable_ids instance.data["publish"] = True diff --git a/client/ayon_core/hosts/photoshop/plugins/publish/collect_auto_review.py b/client/ayon_core/hosts/photoshop/plugins/publish/collect_auto_review.py index c8d4ddf111..e31508e641 100644 --- a/client/ayon_core/hosts/photoshop/plugins/publish/collect_auto_review.py +++ b/client/ayon_core/hosts/photoshop/plugins/publish/collect_auto_review.py @@ -67,7 +67,7 @@ class CollectAutoReview(pyblish.api.ContextPlugin): host_name = context.data["hostName"] asset_doc = context.data["assetEntity"] - asset_name = get_asset_name_identifier(asset_doc) + folder_path = get_asset_name_identifier(asset_doc) subset_name = get_subset_name( family, @@ -87,7 +87,7 @@ class CollectAutoReview(pyblish.api.ContextPlugin): "family": family, "families": [], "representations": [], - "asset": asset_name, + "folderPath": folder_path, "publish": self.publish }) diff --git a/client/ayon_core/hosts/photoshop/plugins/publish/collect_auto_workfile.py b/client/ayon_core/hosts/photoshop/plugins/publish/collect_auto_workfile.py index 365fd0a684..12fc31a2f2 100644 --- a/client/ayon_core/hosts/photoshop/plugins/publish/collect_auto_workfile.py +++ b/client/ayon_core/hosts/photoshop/plugins/publish/collect_auto_workfile.py @@ -71,7 +71,7 @@ class CollectAutoWorkfile(pyblish.api.ContextPlugin): host_name = context.data["hostName"] asset_doc = context.data["assetEntity"] - asset_name = get_asset_name_identifier(asset_doc) + folder_path = get_asset_name_identifier(asset_doc) subset_name = get_subset_name( family, variant, @@ -91,7 +91,7 @@ class CollectAutoWorkfile(pyblish.api.ContextPlugin): "family": family, "families": [], "representations": [], - "asset": asset_name + "folderPath": folder_path }) # creating representation diff --git a/client/ayon_core/hosts/photoshop/plugins/publish/collect_batch_data.py b/client/ayon_core/hosts/photoshop/plugins/publish/collect_batch_data.py index 464b6e3999..a32b5f8fa5 100644 --- a/client/ayon_core/hosts/photoshop/plugins/publish/collect_batch_data.py +++ b/client/ayon_core/hosts/photoshop/plugins/publish/collect_batch_data.py @@ -2,7 +2,7 @@ Provides: context -> Loaded batch file. - - asset + - folderPath - task (task name) - taskType - project_name @@ -71,7 +71,7 @@ class CollectBatchData(pyblish.api.ContextPlugin): os.environ["AYON_FOLDER_PATH"] = asset_name os.environ["AYON_TASK_NAME"] = task_name - context.data["asset"] = asset_name + context.data["folderPath"] = asset_name context.data["task"] = task_name context.data["taskType"] = task_type context.data["project_name"] = project_name diff --git a/client/ayon_core/hosts/photoshop/plugins/publish/collect_color_coded_instances.py b/client/ayon_core/hosts/photoshop/plugins/publish/collect_color_coded_instances.py index fa0ad4aac5..2d3a9f4848 100644 --- a/client/ayon_core/hosts/photoshop/plugins/publish/collect_color_coded_instances.py +++ b/client/ayon_core/hosts/photoshop/plugins/publish/collect_color_coded_instances.py @@ -56,7 +56,7 @@ class CollectColorCodedInstances(pyblish.api.ContextPlugin): existing_subset_names = self._get_existing_subset_names(context) # from CollectBatchData - asset_name = context.data["asset"] + asset_name = context.data["folderPath"] task_name = context.data["task"] variant = context.data["variant"] project_name = context.data["projectEntity"]["name"] @@ -163,7 +163,7 @@ class CollectColorCodedInstances(pyblish.api.ContextPlugin): instance = context.create_instance(layer.name) instance.data["family"] = family instance.data["publish"] = True - instance.data["asset"] = asset + instance.data["folderPath"] = asset instance.data["task"] = task_name instance.data["subset"] = subset instance.data["layer"] = layer diff --git a/client/ayon_core/hosts/photoshop/plugins/publish/validate_instance_asset.py b/client/ayon_core/hosts/photoshop/plugins/publish/validate_instance_asset.py index dc0f2efd52..67a7303316 100644 --- a/client/ayon_core/hosts/photoshop/plugins/publish/validate_instance_asset.py +++ b/client/ayon_core/hosts/photoshop/plugins/publish/validate_instance_asset.py @@ -31,7 +31,7 @@ class ValidateInstanceAssetRepair(pyblish.api.Action): current_asset_name = get_current_asset_name() for instance in instances: data = stub.read(instance[0]) - data["asset"] = current_asset_name + data["folderPath"] = current_asset_name stub.imprint(instance[0], data) @@ -54,7 +54,7 @@ class ValidateInstanceAsset(OptionalPyblishPluginMixin, order = ValidateContentsOrder def process(self, instance): - instance_asset = instance.data["asset"] + instance_asset = instance.data["folderPath"] current_asset = get_current_asset_name() if instance_asset != current_asset: diff --git a/client/ayon_core/hosts/resolve/api/lib.py b/client/ayon_core/hosts/resolve/api/lib.py index 2c648bb4cc..5eb88afdcb 100644 --- a/client/ayon_core/hosts/resolve/api/lib.py +++ b/client/ayon_core/hosts/resolve/api/lib.py @@ -519,7 +519,7 @@ def imprint(timeline_item, data=None): Examples: data = { - 'asset': 'sq020sh0280', + 'folderPath': 'sq020sh0280', 'family': 'render', 'subset': 'subsetMain' } diff --git a/client/ayon_core/hosts/resolve/plugins/publish/precollect_instances.py b/client/ayon_core/hosts/resolve/plugins/publish/precollect_instances.py index 89546373ad..78c5fbbbf7 100644 --- a/client/ayon_core/hosts/resolve/plugins/publish/precollect_instances.py +++ b/client/ayon_core/hosts/resolve/plugins/publish/precollect_instances.py @@ -69,7 +69,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin): data.update({ "name": "{}_{}".format(asset, subset), "label": "{} {}".format(asset, subset), - "asset": asset, + "folderPath": asset, "item": timeline_item, "publish": get_publish_attribute(timeline_item), "fps": context.data["fps"], @@ -127,7 +127,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin): if not hierarchy_data: return - asset = data["asset"] + asset = data["folderPath"] subset = "shotMain" # insert family into families @@ -137,7 +137,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin): "name": "{}_{}".format(asset, subset), "label": "{} {}".format(asset, subset), "subset": subset, - "asset": asset, + "folderPath": asset, "family": family, "families": [], "publish": get_publish_attribute(timeline_item) diff --git a/client/ayon_core/hosts/resolve/plugins/publish/precollect_workfile.py b/client/ayon_core/hosts/resolve/plugins/publish/precollect_workfile.py index 5f8cf6b5d9..814b1e159f 100644 --- a/client/ayon_core/hosts/resolve/plugins/publish/precollect_workfile.py +++ b/client/ayon_core/hosts/resolve/plugins/publish/precollect_workfile.py @@ -28,7 +28,7 @@ class PrecollectWorkfile(pyblish.api.ContextPlugin): instance_data = { "name": "{}_{}".format(asset_name, subset), "label": "{} {}".format(current_asset_name, subset), - "asset": current_asset_name, + "folderPath": current_asset_name, "subset": subset, "item": project, "family": "workfile", diff --git a/client/ayon_core/hosts/substancepainter/plugins/publish/collect_textureset_images.py b/client/ayon_core/hosts/substancepainter/plugins/publish/collect_textureset_images.py index b8279c99cd..03e17192d2 100644 --- a/client/ayon_core/hosts/substancepainter/plugins/publish/collect_textureset_images.py +++ b/client/ayon_core/hosts/substancepainter/plugins/publish/collect_textureset_images.py @@ -27,8 +27,8 @@ class CollectTextureSet(pyblish.api.InstancePlugin): config = self.get_export_config(instance) asset_doc = get_asset_by_name( - project_name=instance.context.data["projectName"], - asset_name=instance.data["asset"] + instance.context.data["projectName"], + instance.data["folderPath"] ) instance.data["exportConfig"] = config diff --git a/client/ayon_core/hosts/traypublisher/plugins/create/create_online.py b/client/ayon_core/hosts/traypublisher/plugins/create/create_online.py index db11d30afe..36d2fba976 100644 --- a/client/ayon_core/hosts/traypublisher/plugins/create/create_online.py +++ b/client/ayon_core/hosts/traypublisher/plugins/create/create_online.py @@ -53,7 +53,7 @@ class OnlineCreator(TrayPublishCreator): # disable check for existing subset with the same name """ asset = get_asset_by_name( - self.project_name, instance_data["asset"], fields=["_id"]) + self.project_name, instance_data["folderPath"], fields=["_id"]) if get_subset_by_name( self.project_name, origin_basename, asset["_id"], diff --git a/client/ayon_core/hosts/traypublisher/plugins/publish/collect_shot_instances.py b/client/ayon_core/hosts/traypublisher/plugins/publish/collect_shot_instances.py index b19eb36168..d489528c57 100644 --- a/client/ayon_core/hosts/traypublisher/plugins/publish/collect_shot_instances.py +++ b/client/ayon_core/hosts/traypublisher/plugins/publish/collect_shot_instances.py @@ -17,7 +17,7 @@ class CollectShotInstance(pyblish.api.InstancePlugin): families = ["shot"] SHARED_KEYS = [ - "asset", + "folderPath", "fps", "handleStart", "handleEnd", @@ -132,7 +132,7 @@ class CollectShotInstance(pyblish.api.InstancePlugin): "sourceIn": _cr_attrs["sourceIn"], "sourceOut": _cr_attrs["sourceOut"], "workfileFrameStart": workfile_start_frame, - "asset": _cr_attrs["folderPath"], + "folderPath": _cr_attrs["folderPath"], } def _solve_hierarchy_context(self, instance): @@ -170,7 +170,7 @@ class CollectShotInstance(pyblish.api.InstancePlugin): parents = instance.data.get('parents', []) # Split by '/' for AYON where asset is a path - asset_name = instance.data["asset"].split("/")[-1] + asset_name = instance.data["folderPath"].split("/")[-1] actual = {asset_name: in_info} for parent in reversed(parents): diff --git a/client/ayon_core/hosts/traypublisher/plugins/publish/validate_existing_version.py b/client/ayon_core/hosts/traypublisher/plugins/publish/validate_existing_version.py index 6a85f92ce1..b75ae674e8 100644 --- a/client/ayon_core/hosts/traypublisher/plugins/publish/validate_existing_version.py +++ b/client/ayon_core/hosts/traypublisher/plugins/publish/validate_existing_version.py @@ -40,7 +40,7 @@ class ValidateExistingVersion( formatting_data = { "subset_name": subset_name, - "asset_name": instance.data["asset"], + "asset_name": instance.data["folderPath"], "version": version } raise PublishXmlValidationError( diff --git a/client/ayon_core/hosts/tvpaint/plugins/publish/collect_workfile_data.py b/client/ayon_core/hosts/tvpaint/plugins/publish/collect_workfile_data.py index a6b6f05dc9..1cf21a1fae 100644 --- a/client/ayon_core/hosts/tvpaint/plugins/publish/collect_workfile_data.py +++ b/client/ayon_core/hosts/tvpaint/plugins/publish/collect_workfile_data.py @@ -65,7 +65,7 @@ class CollectWorkfileData(pyblish.api.ContextPlugin): # Collect and store current context to have reference current_context = { "project_name": context.data["projectName"], - "asset_name": context.data["asset"], + "asset_name": context.data["folderPath"], "task_name": context.data["task"] } self.log.debug("Current context is: {}".format(current_context)) @@ -105,7 +105,7 @@ class CollectWorkfileData(pyblish.api.ContextPlugin): )) # Store context asset name - context.data["asset"] = asset_name + context.data["folderPath"] = asset_name context.data["task"] = task_name self.log.info( "Context is set to Asset: \"{}\" and Task: \"{}\"".format( diff --git a/client/ayon_core/hosts/tvpaint/plugins/publish/validate_asset_name.py b/client/ayon_core/hosts/tvpaint/plugins/publish/validate_asset_name.py index 62603a460b..927d601e34 100644 --- a/client/ayon_core/hosts/tvpaint/plugins/publish/validate_asset_name.py +++ b/client/ayon_core/hosts/tvpaint/plugins/publish/validate_asset_name.py @@ -20,7 +20,7 @@ class FixAssetNames(pyblish.api.Action): on = "failed" def process(self, context, plugin): - context_asset_name = context.data["asset"] + context_asset_name = context.data["folderPath"] old_instance_items = list_instances() new_instance_items = [] for instance_item in old_instance_items: @@ -51,9 +51,9 @@ class ValidateAssetName( def process(self, context): if not self.is_active(context.data): return - context_asset_name = context.data["asset"] + context_asset_name = context.data["folderPath"] for instance in context: - asset_name = instance.data.get("asset") + asset_name = instance.data.get("folderPath") if asset_name and asset_name == context_asset_name: continue diff --git a/client/ayon_core/hosts/unreal/plugins/publish/collect_render_instances.py b/client/ayon_core/hosts/unreal/plugins/publish/collect_render_instances.py index 8641094610..8bbf5a5c62 100644 --- a/client/ayon_core/hosts/unreal/plugins/publish/collect_render_instances.py +++ b/client/ayon_core/hosts/unreal/plugins/publish/collect_render_instances.py @@ -64,7 +64,7 @@ class CollectRenderInstances(pyblish.api.InstancePlugin): new_data = new_instance.data - new_data["asset"] = seq_name + new_data["folderPath"] = seq_name new_data["setMembers"] = seq_name new_data["family"] = "render" new_data["families"] = ["render", "review"] diff --git a/client/ayon_core/modules/deadline/plugins/publish/submit_houdini_render_deadline.py b/client/ayon_core/modules/deadline/plugins/publish/submit_houdini_render_deadline.py index 45209d00f6..45c252dd56 100644 --- a/client/ayon_core/modules/deadline/plugins/publish/submit_houdini_render_deadline.py +++ b/client/ayon_core/modules/deadline/plugins/publish/submit_houdini_render_deadline.py @@ -44,7 +44,10 @@ class VrayRenderPluginInfo(): @attr.s class RedshiftRenderPluginInfo(): SceneFile = attr.ib(default=None) - Version = attr.ib(default=None) + # Use "1" as the default Redshift version just because it + # default fallback version in Deadline's Redshift plugin + # if no version was specified + Version = attr.ib(default="1") class HoudiniSubmitDeadline( diff --git a/client/ayon_core/modules/deadline/plugins/publish/submit_publish_cache_job.py b/client/ayon_core/modules/deadline/plugins/publish/submit_publish_cache_job.py index 54d4fb47fc..0b0e293943 100644 --- a/client/ayon_core/modules/deadline/plugins/publish/submit_publish_cache_job.py +++ b/client/ayon_core/modules/deadline/plugins/publish/submit_publish_cache_job.py @@ -112,7 +112,7 @@ class ProcessSubmittedCacheJobOnFarm(pyblish.api.InstancePlugin, output_dir = self._get_publish_folder( anatomy, deepcopy(instance.data["anatomyData"]), - instance.data.get("asset"), + instance.data.get("folderPath"), instance.data["subset"], instance.context, instance.data["family"], @@ -126,7 +126,7 @@ class ProcessSubmittedCacheJobOnFarm(pyblish.api.InstancePlugin, environment = { "AYON_PROJECT_NAME": instance.context.data["projectName"], - "AYON_FOLDER_PATH": instance.context.data["asset"], + "AYON_FOLDER_PATH": instance.context.data["folderPath"], "AYON_TASK_NAME": instance.context.data["task"], "AYON_USERNAME": instance.context.data["user"], "AYON_LOG_NO_COLORS": "1", @@ -359,7 +359,7 @@ class ProcessSubmittedCacheJobOnFarm(pyblish.api.InstancePlugin, # publish job file publish_job = { - "asset": instance_skeleton_data["asset"], + "folderPath": instance_skeleton_data["folderPath"], "frameStart": instance_skeleton_data["frameStart"], "frameEnd": instance_skeleton_data["frameEnd"], "fps": instance_skeleton_data["fps"], diff --git a/client/ayon_core/modules/deadline/plugins/publish/submit_publish_job.py b/client/ayon_core/modules/deadline/plugins/publish/submit_publish_job.py index 4023846817..77094fd8bd 100644 --- a/client/ayon_core/modules/deadline/plugins/publish/submit_publish_job.py +++ b/client/ayon_core/modules/deadline/plugins/publish/submit_publish_job.py @@ -189,7 +189,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin, output_dir = self._get_publish_folder( anatomy, deepcopy(instance.data["anatomyData"]), - instance.data.get("asset"), + instance.data.get("folderPath"), instances[0]["subset"], instance.context, instances[0]["family"], @@ -203,7 +203,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin, environment = { "AYON_PROJECT_NAME": instance.context.data["projectName"], - "AYON_FOLDER_PATH": instance.context.data["asset"], + "AYON_FOLDER_PATH": instance.context.data["folderPath"], "AYON_TASK_NAME": instance.context.data["task"], "AYON_USERNAME": instance.context.data["user"], "AYON_LOG_NO_COLORS": "1", @@ -475,7 +475,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin, # publish job file publish_job = { - "asset": instance_skeleton_data["asset"], + "folderPath": instance_skeleton_data["folderPath"], "frameStart": instance_skeleton_data["frameStart"], "frameEnd": instance_skeleton_data["frameEnd"], "fps": instance_skeleton_data["fps"], diff --git a/client/ayon_core/modules/royalrender/__init__.py b/client/ayon_core/modules/royalrender/__init__.py index cc92e3b50d..121530beda 100644 --- a/client/ayon_core/modules/royalrender/__init__.py +++ b/client/ayon_core/modules/royalrender/__init__.py @@ -1,6 +1,6 @@ -from .royal_render_module import RoyalRenderModule +from .addon import RoyalRenderAddon __all__ = ( - "RoyalRenderModule", + "RoyalRenderAddon", ) diff --git a/client/ayon_core/modules/royalrender/addon.py b/client/ayon_core/modules/royalrender/addon.py new file mode 100644 index 0000000000..e69cf9feec --- /dev/null +++ b/client/ayon_core/modules/royalrender/addon.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +"""Module providing support for Royal Render.""" +import os + +from ayon_core.addon import AYONAddon, IPluginPaths + + +class RoyalRenderAddon(AYONAddon, IPluginPaths): + """Class providing basic Royal Render implementation logic.""" + name = "royalrender" + + # _rr_api = None + # @property + # def rr_api(self): + # if not self._rr_api: + # # import royal render modules + # from .api import Api + # self._rr_api = Api(self.settings) + # return self._rr_api + + def initialize(self, studio_settings): + # type: (dict) -> None + self.enabled = self.name in studio_settings + + @staticmethod + def get_plugin_paths(): + # type: () -> dict + """Royal Render plugin paths. + + Returns: + dict: Dictionary of plugin paths for RR. + """ + current_dir = os.path.dirname(os.path.abspath(__file__)) + return { + "publish": [os.path.join(current_dir, "plugins", "publish")] + } diff --git a/client/ayon_core/modules/royalrender/lib.py b/client/ayon_core/modules/royalrender/lib.py index 5343a5f06f..60c0427d99 100644 --- a/client/ayon_core/modules/royalrender/lib.py +++ b/client/ayon_core/modules/royalrender/lib.py @@ -108,9 +108,7 @@ class BaseCreateRoyalRenderJob(pyblish.api.InstancePlugin, context = instance.context - self._rr_root = self._resolve_rr_path(context, instance.data.get( - "rrPathName")) # noqa - self.log.debug(self._rr_root) + self._rr_root = instance.data.get("rrPathName") if not self._rr_root: raise KnownPublishError( ("Missing RoyalRender root. " @@ -210,35 +208,6 @@ class BaseCreateRoyalRenderJob(pyblish.api.InstancePlugin, """Host specific mapping for RRJob""" raise NotImplementedError - @staticmethod - def _resolve_rr_path(context, rr_path_name): - # type: (pyblish.api.Context, str) -> str - rr_settings = ( - context.data - ["system_settings"] - ["modules"] - ["royalrender"] - ) - try: - default_servers = rr_settings["rr_paths"] - project_servers = ( - context.data - ["project_settings"] - ["royalrender"] - ["rr_paths"] - ) - rr_servers = { - k: default_servers[k] - for k in project_servers - if k in default_servers - } - - except (AttributeError, KeyError): - # Handle situation were we had only one url for royal render. - return context.data["defaultRRPath"][platform.system().lower()] - - return rr_servers[rr_path_name][platform.system().lower()] - def expected_files(self, instance, path, start_frame, end_frame): """Get expected files. @@ -350,7 +319,7 @@ class BaseCreateRoyalRenderJob(pyblish.api.InstancePlugin, add_kwargs = { "project": anatomy_data["project"]["name"], - "asset": instance.context.data["asset"], + "asset": instance.context.data["folderPath"], "task": anatomy_data["task"]["name"], "app": instance.context.data.get("appName"), "envgroup": "farm" diff --git a/client/ayon_core/modules/royalrender/plugins/publish/collect_rr_path_from_instance.py b/client/ayon_core/modules/royalrender/plugins/publish/collect_rr_path_from_instance.py index e978ce5bed..d860df4684 100644 --- a/client/ayon_core/modules/royalrender/plugins/publish/collect_rr_path_from_instance.py +++ b/client/ayon_core/modules/royalrender/plugins/publish/collect_rr_path_from_instance.py @@ -18,30 +18,24 @@ class CollectRRPathFromInstance(pyblish.api.InstancePlugin): def _collect_rr_path_name(instance): # type: (pyblish.api.Instance) -> str """Get Royal Render pat name from render instance.""" - rr_settings = ( - instance.context.data - ["system_settings"] - ["modules"] - ["royalrender"] - ) - if not instance.data.get("rrPaths"): + + # TODO there are no "rrPaths" on instance, if Publisher should expose + # this (eg. artist could select specific server) it must be added + # to publisher + instance_rr_paths = instance.data.get("rrPaths") + if instance_rr_paths is None: return "default" - try: - default_servers = rr_settings["rr_paths"] - project_servers = ( - instance.context.data - ["project_settings"] - ["royalrender"] - ["rr_paths"] - ) - rr_servers = { - k: default_servers[k] - for k in project_servers - if k in default_servers - } - except (AttributeError, KeyError): - # Handle situation were we had only one url for royal render. - return rr_settings["rr_paths"]["default"] + rr_settings = instance.context.data["project_settings"]["royalrender"] + rr_paths = rr_settings["rr_paths"] + selected_paths = rr_settings["selected_rr_paths"] - return list(rr_servers.keys())[int(instance.data.get("rrPaths"))] + rr_servers = { + path_key + for path_key in selected_paths + if path_key in rr_paths + } + for instance_rr_path in instance_rr_paths: + if instance_rr_path in rr_servers: + return instance_rr_path + return "default" diff --git a/client/ayon_core/modules/royalrender/plugins/publish/collect_sequences_from_job.py b/client/ayon_core/modules/royalrender/plugins/publish/collect_sequences_from_job.py index cd34ba9bb3..4460e11004 100644 --- a/client/ayon_core/modules/royalrender/plugins/publish/collect_sequences_from_job.py +++ b/client/ayon_core/modules/royalrender/plugins/publish/collect_sequences_from_job.py @@ -189,8 +189,8 @@ class CollectSequencesFromJob(pyblish.api.ContextPlugin): "family": families[0], # backwards compatibility / pyblish "families": list(families), "subset": subset, - "asset": data.get( - "asset", context.data["asset"] + "folderPath": data.get( + "folderPath", context.data["folderPath"] ), "stagingDir": root, "frameStart": start, diff --git a/client/ayon_core/modules/royalrender/plugins/publish/create_publish_royalrender_job.py b/client/ayon_core/modules/royalrender/plugins/publish/create_publish_royalrender_job.py index 910abfcb15..256c8b7a83 100644 --- a/client/ayon_core/modules/royalrender/plugins/publish/create_publish_royalrender_job.py +++ b/client/ayon_core/modules/royalrender/plugins/publish/create_publish_royalrender_job.py @@ -132,7 +132,7 @@ class CreatePublishRoyalRenderJob(pyblish.api.InstancePlugin, # publish job file publish_job = { - "asset": instance_skeleton_data["asset"], + "folderPath": instance_skeleton_data["folderPath"], "frameStart": instance_skeleton_data["frameStart"], "frameEnd": instance_skeleton_data["frameEnd"], "fps": instance_skeleton_data["fps"], @@ -180,7 +180,7 @@ class CreatePublishRoyalRenderJob(pyblish.api.InstancePlugin, environment = RREnvList({ "AYON_PROJECT_NAME": anatomy_data["project"]["name"], - "AYON_FOLDER_PATH": instance.context.data["asset"], + "AYON_FOLDER_PATH": instance.context.data["folderPath"], "AYON_TASK_NAME": anatomy_data["task"]["name"], "AYON_USERNAME": anatomy_data["user"] }) @@ -216,7 +216,7 @@ class CreatePublishRoyalRenderJob(pyblish.api.InstancePlugin, SeqEnd=1, SeqStep=1, SeqFileOffset=0, - Version=self._sanitize_version(os.environ.get("OPENPYPE_VERSION")), + Version=os.environ["AYON_BUNDLE_NAME"], SceneName=abs_metadata_path, # command line arguments CustomAddCmdFlags=" ".join(args), @@ -243,26 +243,3 @@ class CreatePublishRoyalRenderJob(pyblish.api.InstancePlugin, job.WaitForPreIDs += jobs_pre_ids return job - - def _sanitize_version(self, version): - """Returns version in format MAJOR.MINORPATCH - - 3.15.7-nightly.2 >> 3.157 - """ - VERSION_REGEX = re.compile( - r"(?P0|[1-9]\d*)" - r"\.(?P0|[1-9]\d*)" - r"\.(?P0|[1-9]\d*)" - r"(?:-(?P[a-zA-Z\d\-.]*))?" - r"(?:\+(?P[a-zA-Z\d\-.]*))?" - ) - - valid_parts = VERSION_REGEX.findall(version) - if len(valid_parts) != 1: - # Return invalid version with filled 'origin' attribute - return version - - # Unpack found version - major, minor, patch, pre, post = valid_parts[0] - - return "{}.{}{}".format(major, minor, patch) diff --git a/client/ayon_core/modules/royalrender/plugins/publish/submit_jobs_to_royalrender.py b/client/ayon_core/modules/royalrender/plugins/publish/submit_jobs_to_royalrender.py index a76bdfc26c..dcec2ac810 100644 --- a/client/ayon_core/modules/royalrender/plugins/publish/submit_jobs_to_royalrender.py +++ b/client/ayon_core/modules/royalrender/plugins/publish/submit_jobs_to_royalrender.py @@ -25,16 +25,6 @@ class SubmitJobsToRoyalRender(pyblish.api.ContextPlugin): self._submission_parameters = [] def process(self, context): - rr_settings = ( - context.data - ["system_settings"] - ["modules"] - ["royalrender"] - ) - - if rr_settings["enabled"] is not True: - self.log.warning("RoyalRender modules is disabled.") - return # iterate over all instances and try to find RRJobs jobs = [] @@ -51,7 +41,7 @@ class SubmitJobsToRoyalRender(pyblish.api.ContextPlugin): instance_rr_path = instance.data["rrPathName"] if jobs: - self._rr_root = self._resolve_rr_path(context, instance_rr_path) + self._rr_root = instance_rr_path if not self._rr_root: raise KnownPublishError( ("Missing RoyalRender root. " @@ -100,32 +90,3 @@ class SubmitJobsToRoyalRender(pyblish.api.ContextPlugin): def get_submission_parameters(self): return [SubmitterParameter("RequiredMemory", "0")] - - @staticmethod - def _resolve_rr_path(context, rr_path_name): - # type: (pyblish.api.Context, str) -> str - rr_settings = ( - context.data - ["system_settings"] - ["modules"] - ["royalrender"] - ) - try: - default_servers = rr_settings["rr_paths"] - project_servers = ( - context.data - ["project_settings"] - ["royalrender"] - ["rr_paths"] - ) - rr_servers = { - k: default_servers[k] - for k in project_servers - if k in default_servers - } - - except (AttributeError, KeyError): - # Handle situation were we had only one url for royal render. - return context.data["defaultRRPath"][platform.system().lower()] - - return rr_servers[rr_path_name][platform.system().lower()] diff --git a/client/ayon_core/modules/royalrender/royal_render_module.py b/client/ayon_core/modules/royalrender/royal_render_module.py deleted file mode 100644 index 66b09832d8..0000000000 --- a/client/ayon_core/modules/royalrender/royal_render_module.py +++ /dev/null @@ -1,45 +0,0 @@ -# -*- coding: utf-8 -*- -"""Module providing support for Royal Render.""" -import os -import ayon_core.modules -from ayon_core.modules import OpenPypeModule, IPluginPaths - - -class RoyalRenderModule(OpenPypeModule, IPluginPaths): - """Class providing basic Royal Render implementation logic.""" - name = "royalrender" - - @property - def api(self): - if not self._api: - # import royal render modules - from . import api as rr_api - self._api = rr_api.Api(self.settings) - - return self._api - - def __init__(self, manager, settings): - # type: (ayon_core.addon.AddonsManager, dict) -> None - self.rr_paths = {} - self._api = None - self.settings = settings - super(RoyalRenderModule, self).__init__(manager, settings) - - def initialize(self, module_settings): - # type: (dict) -> None - rr_settings = module_settings[self.name] - self.enabled = rr_settings["enabled"] - self.rr_paths = rr_settings.get("rr_paths") - - @staticmethod - def get_plugin_paths(): - # type: () -> dict - """Royal Render plugin paths. - - Returns: - dict: Dictionary of plugin paths for RR. - """ - current_dir = os.path.dirname(os.path.abspath(__file__)) - return { - "publish": [os.path.join(current_dir, "plugins", "publish")] - } diff --git a/client/ayon_core/modules/timers_manager/plugins/publish/start_timer.py b/client/ayon_core/modules/timers_manager/plugins/publish/start_timer.py index 51f707ecf6..a3eb49ee70 100644 --- a/client/ayon_core/modules/timers_manager/plugins/publish/start_timer.py +++ b/client/ayon_core/modules/timers_manager/plugins/publish/start_timer.py @@ -24,7 +24,7 @@ class StartTimer(pyblish.api.ContextPlugin): return project_name = context.data["projectName"] - asset_name = context.data.get("asset") + asset_name = context.data.get("folderPath") task_name = context.data.get("task") if not project_name or not asset_name or not task_name: self.log.info(( diff --git a/client/ayon_core/pipeline/create/README.md b/client/ayon_core/pipeline/create/README.md index 074cd24364..5e3bd7dc1a 100644 --- a/client/ayon_core/pipeline/create/README.md +++ b/client/ayon_core/pipeline/create/README.md @@ -48,7 +48,7 @@ Family tells how should be instance processed and subset what name will publishe : {...}, ... }, - ## Additional data related to instance (`asset`, `task`, etc.) + ## Additional data related to instance (`folderPath`, `task`, etc.) ... } ``` diff --git a/client/ayon_core/pipeline/create/legacy_create.py b/client/ayon_core/pipeline/create/legacy_create.py index b0e94ca225..bc1528b9cd 100644 --- a/client/ayon_core/pipeline/create/legacy_create.py +++ b/client/ayon_core/pipeline/create/legacy_create.py @@ -28,7 +28,7 @@ class LegacyCreator(object): log = logging.getLogger("LegacyCreator") log.propagate = True - def __init__(self, name, asset, options=None, data=None): + def __init__(self, name, folder_path, options=None, data=None): self.name = name # For backwards compatibility self.options = options @@ -37,7 +37,7 @@ class LegacyCreator(object): # TODO use 'AYON_INSTANCE_ID' when all hosts support it self.data["id"] = AVALON_INSTANCE_ID self.data["family"] = self.family - self.data["asset"] = asset + self.data["folderPath"] = folder_path self.data["subset"] = name self.data["active"] = True diff --git a/client/ayon_core/pipeline/create/utils.py b/client/ayon_core/pipeline/create/utils.py index 0547c20c0a..c2655f319f 100644 --- a/client/ayon_core/pipeline/create/utils.py +++ b/client/ayon_core/pipeline/create/utils.py @@ -32,7 +32,7 @@ def get_last_versions_for_instances( subset_names_by_asset_name = collections.defaultdict(set) instances_by_hierarchy = {} for instance in instances: - asset_name = instance.data.get("asset") + asset_name = instance.data.get("folderPath") subset_name = instance.subset_name if not asset_name or not subset_name: if use_value_for_missing: diff --git a/client/ayon_core/pipeline/farm/pyblish_functions.py b/client/ayon_core/pipeline/farm/pyblish_functions.py index 389d3d27ed..4652d34011 100644 --- a/client/ayon_core/pipeline/farm/pyblish_functions.py +++ b/client/ayon_core/pipeline/farm/pyblish_functions.py @@ -197,7 +197,7 @@ def create_skeleton_instance( if data.get("extendFrames", False): time_data.start, time_data.end = extend_frames( - data["asset"], + data["folderPath"], data["subset"], time_data.start, time_data.end, @@ -228,7 +228,7 @@ def create_skeleton_instance( "family": family, "subset": data["subset"], "families": families, - "asset": data["asset"], + "folderPath": data["folderPath"], "frameStart": time_data.start, "frameEnd": time_data.end, "handleStart": time_data.handle_start, @@ -777,7 +777,7 @@ def create_skeleton_instance_cache(instance): if data.get("extendFrames", False): time_data.start, time_data.end = extend_frames( - data["asset"], + data["folderPath"], data["subset"], time_data.start, time_data.end, @@ -805,7 +805,7 @@ def create_skeleton_instance_cache(instance): "family": family, "subset": data["subset"], "families": families, - "asset": data["asset"], + "folderPath": data["folderPath"], "frameStart": time_data.start, "frameEnd": time_data.end, "handleStart": time_data.handle_start, @@ -1011,7 +1011,7 @@ def copy_extend_frames(instance, representation): version = get_last_version_by_subset_name( project_name, instance.data.get("subset"), - asset_name=instance.data.get("asset") + asset_name=instance.data.get("folderPath") ) # get its files based on extension diff --git a/client/ayon_core/pipeline/publish/abstract_collect_render.py b/client/ayon_core/pipeline/publish/abstract_collect_render.py index 764532cadb..6ca1d81bc7 100644 --- a/client/ayon_core/pipeline/publish/abstract_collect_render.py +++ b/client/ayon_core/pipeline/publish/abstract_collect_render.py @@ -30,7 +30,7 @@ class RenderInstance(object): label = attr.ib() # label to show in GUI subset = attr.ib() # subset name task = attr.ib() # task name - asset = attr.ib() # asset name + folderPath = attr.ib() # folder path attachTo = attr.ib() # subset name to attach render to setMembers = attr.ib() # list of nodes/members producing render output publish = attr.ib() # bool, True to publish instance diff --git a/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py b/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py index 336ac02b8e..f6326bb9e8 100644 --- a/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py +++ b/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py @@ -3,7 +3,7 @@ Requires: context -> anatomyData context -> projectEntity context -> assetEntity - instance -> asset + instance -> folderPath instance -> subset instance -> family @@ -68,7 +68,7 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin): instances_with_missing_asset_doc = collections.defaultdict(list) for instance in context: instance_asset_doc = instance.data.get("assetEntity") - _asset_name = instance.data["asset"] + _asset_name = instance.data["folderPath"] # There is possibility that assetEntity on instance is already set # which can happen in standalone publisher @@ -296,7 +296,7 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin): if hierarchy: parent_name = hierarchy.split("/")[-1] - asset_name = instance.data["asset"].split("/")[-1] + asset_name = instance.data["folderPath"].split("/")[-1] anatomy_data.update({ "asset": asset_name, "hierarchy": hierarchy, @@ -337,7 +337,7 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin): # Try to find task data based on hierarchy context and asset name hierarchy_context = instance.context.data.get("hierarchyContext") - asset_name = instance.data.get("asset") + asset_name = instance.data.get("folderPath") if not hierarchy_context or not asset_name: return diff --git a/client/ayon_core/plugins/publish/collect_audio.py b/client/ayon_core/plugins/publish/collect_audio.py index 6da3fd0685..f0efd546e7 100644 --- a/client/ayon_core/plugins/publish/collect_audio.py +++ b/client/ayon_core/plugins/publish/collect_audio.py @@ -66,7 +66,7 @@ class CollectAudio(pyblish.api.ContextPlugin): # Add audio to instance if exists. instances_by_asset_name = collections.defaultdict(list) for instance in filtered_instances: - asset_name = instance.data["asset"] + asset_name = instance.data["folderPath"] instances_by_asset_name[asset_name].append(instance) asset_names = set(instances_by_asset_name.keys()) diff --git a/client/ayon_core/plugins/publish/collect_context_entities.py b/client/ayon_core/plugins/publish/collect_context_entities.py index 30bb184ef5..64ef73e2d9 100644 --- a/client/ayon_core/plugins/publish/collect_context_entities.py +++ b/client/ayon_core/plugins/publish/collect_context_entities.py @@ -25,7 +25,7 @@ class CollectContextEntities(pyblish.api.ContextPlugin): def process(self, context): project_name = context.data["projectName"] - asset_name = context.data["asset"] + asset_name = context.data["folderPath"] task_name = context.data["task"] project_entity = get_project(project_name) diff --git a/client/ayon_core/plugins/publish/collect_current_context.py b/client/ayon_core/plugins/publish/collect_current_context.py index 90b9fcdcbd..418ca8eff6 100644 --- a/client/ayon_core/plugins/publish/collect_current_context.py +++ b/client/ayon_core/plugins/publish/collect_current_context.py @@ -1,7 +1,7 @@ """ Provides: context -> projectName (str) - context -> asset (str) + context -> folderPath (str) context -> task (str) """ @@ -21,7 +21,7 @@ class CollectCurrentContext(pyblish.api.ContextPlugin): def process(self, context): # Check if values are already set project_name = context.data.get("projectName") - asset_name = context.data.get("asset") + asset_name = context.data.get("folderPath") task_name = context.data.get("task") current_context = get_current_context() @@ -29,13 +29,12 @@ class CollectCurrentContext(pyblish.api.ContextPlugin): context.data["projectName"] = current_context["project_name"] if not asset_name: - context.data["asset"] = current_context["asset_name"] + context.data["folderPath"] = current_context["asset_name"] if not task_name: context.data["task"] = current_context["task_name"] # QUESTION should we be explicit with keys? (the same on instances) - # - 'asset' -> 'assetName' # - 'task' -> 'taskName' self.log.info(( @@ -45,6 +44,6 @@ class CollectCurrentContext(pyblish.api.ContextPlugin): "Task: {task_name}" ).format( project_name=context.data["projectName"], - asset_name=context.data["asset"], + asset_name=context.data["folderPath"], task_name=context.data["task"] )) diff --git a/client/ayon_core/plugins/publish/collect_frames_fix.py b/client/ayon_core/plugins/publish/collect_frames_fix.py index 4903991d40..6996844eda 100644 --- a/client/ayon_core/plugins/publish/collect_frames_fix.py +++ b/client/ayon_core/plugins/publish/collect_frames_fix.py @@ -41,7 +41,7 @@ class CollectFramesFixDef( instance.data["frames_to_fix"] = frames_to_fix subset_name = instance.data["subset"] - asset_name = instance.data["asset"] + asset_name = instance.data["folderPath"] project_entity = instance.data["projectEntity"] project_name = project_entity["name"] diff --git a/client/ayon_core/plugins/publish/collect_from_create_context.py b/client/ayon_core/plugins/publish/collect_from_create_context.py index 66ca5745b2..7152446de8 100644 --- a/client/ayon_core/plugins/publish/collect_from_create_context.py +++ b/client/ayon_core/plugins/publish/collect_from_create_context.py @@ -38,7 +38,6 @@ class CollectFromCreateContext(pyblish.api.ContextPlugin): for created_instance in create_context.instances: instance_data = created_instance.data_to_store() - instance_data["asset"] = instance_data.pop("folderPath") if instance_data["active"]: thumbnail_path = thumbnail_paths_by_instance_id.get( created_instance.id @@ -80,7 +79,7 @@ class CollectFromCreateContext(pyblish.api.ContextPlugin): instance = context.create_instance(subset) instance.data.update({ "subset": subset, - "asset": in_data["asset"], + "folderPath": in_data["folderPath"], "task": in_data["task"], "label": in_data.get("label") or subset, "name": subset, diff --git a/client/ayon_core/plugins/publish/collect_hierarchy.py b/client/ayon_core/plugins/publish/collect_hierarchy.py index 32f10ba4c8..d7077d030a 100644 --- a/client/ayon_core/plugins/publish/collect_hierarchy.py +++ b/client/ayon_core/plugins/publish/collect_hierarchy.py @@ -62,7 +62,7 @@ class CollectHierarchy(pyblish.api.ContextPlugin): "pixelAspect": instance.data["pixelAspect"] } # Split by '/' for AYON where asset is a path - name = instance.data["asset"].split("/")[-1] + name = instance.data["folderPath"].split("/")[-1] actual = {name: shot_data} for parent in reversed(instance.data["parents"]): diff --git a/client/ayon_core/plugins/publish/collect_rendered_files.py b/client/ayon_core/plugins/publish/collect_rendered_files.py index 9a316b69a4..fcea773208 100644 --- a/client/ayon_core/plugins/publish/collect_rendered_files.py +++ b/client/ayon_core/plugins/publish/collect_rendered_files.py @@ -71,14 +71,19 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): """ # validate basic necessary data data_err = "invalid json file - missing data" - required = ["asset", "user", "comment", + required = ["user", "comment", "job", "instances", "version"] assert all(elem in data.keys() for elem in required), data_err + if "folderPath" not in data and "asset" not in data: + raise AssertionError(data_err) + + if "folderPath" not in data: + data["folderPath"] = data.pop("asset") # set context by first json file ctx = self._context.data - ctx["asset"] = ctx.get("asset") or data.get("asset") + ctx["folderPath"] = ctx.get("folderPath") or data.get("folderPath") ctx["intent"] = ctx.get("intent") or data.get("intent") ctx["comment"] = ctx.get("comment") or data.get("comment") ctx["user"] = ctx.get("user") or data.get("user") @@ -87,7 +92,7 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): # basic sanity check to see if we are working in same context # if some other json file has different context, bail out. ctx_err = "inconsistent contexts in json files - %s" - assert ctx.get("asset") == data.get("asset"), ctx_err % "asset" + assert ctx.get("folderPath") == data.get("folderPath"), ctx_err % "folderPath" assert ctx.get("intent") == data.get("intent"), ctx_err % "intent" assert ctx.get("comment") == data.get("comment"), ctx_err % "comment" assert ctx.get("user") == data.get("user"), ctx_err % "user" diff --git a/client/ayon_core/plugins/publish/extract_hierarchy_to_ayon.py b/client/ayon_core/plugins/publish/extract_hierarchy_to_ayon.py index 0851b28134..7ceaf7d2ad 100644 --- a/client/ayon_core/plugins/publish/extract_hierarchy_to_ayon.py +++ b/client/ayon_core/plugins/publish/extract_hierarchy_to_ayon.py @@ -45,7 +45,7 @@ class ExtractHierarchyToAYON(pyblish.api.ContextPlugin): continue # Skip if instance asset does not match - instance_asset_name = instance.data.get("asset") + instance_asset_name = instance.data.get("folderPath") instances_by_asset_name[instance_asset_name].append(instance) project_doc = context.data["projectEntity"] @@ -189,7 +189,7 @@ class ExtractHierarchyToAYON(pyblish.api.ContextPlugin): active_folder_paths = set() for instance in context: if instance.data.get("publish") is not False: - active_folder_paths.add(instance.data.get("asset")) + active_folder_paths.add(instance.data.get("folderPath")) active_folder_paths.discard(None) diff --git a/client/ayon_core/plugins/publish/extract_otio_audio_tracks.py b/client/ayon_core/plugins/publish/extract_otio_audio_tracks.py index c6bdb59f59..dd45f3fc1a 100644 --- a/client/ayon_core/plugins/publish/extract_otio_audio_tracks.py +++ b/client/ayon_core/plugins/publish/extract_otio_audio_tracks.py @@ -68,7 +68,7 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin): def add_audio_to_instances(self, audio_file, instances): created_files = [] for inst in instances: - name = inst.data["asset"] + name = inst.data["folderPath"] recycling_file = [f for f in created_files if name in f] diff --git a/client/ayon_core/plugins/publish/integrate_thumbnail.py b/client/ayon_core/plugins/publish/integrate_thumbnail.py index dd3fdd5073..03bc8d2d3d 100644 --- a/client/ayon_core/plugins/publish/integrate_thumbnail.py +++ b/client/ayon_core/plugins/publish/integrate_thumbnail.py @@ -196,12 +196,13 @@ class IntegrateThumbnailsAYON(pyblish.api.ContextPlugin): )) asset_entity = instance.data["assetEntity"] + folder_path = instance.data["folderPath"] thumbnail_info_by_entity_id[asset_entity["_id"]] = { "thumbnail_id": thumbnail_id, "entity_type": "asset", } - self.log.debug("Setting thumbnail for asset \"{}\" <{}>".format( - asset_entity["name"], version_id + self.log.debug("Setting thumbnail for folder \"{}\" <{}>".format( + folder_path, version_id )) op_session = OperationsSession() diff --git a/client/ayon_core/plugins/publish/validate_editorial_asset_name.py b/client/ayon_core/plugins/publish/validate_editorial_asset_name.py index d40263d7f3..dd1a19f602 100644 --- a/client/ayon_core/plugins/publish/validate_editorial_asset_name.py +++ b/client/ayon_core/plugins/publish/validate_editorial_asset_name.py @@ -113,7 +113,7 @@ class ValidateEditorialAssetName(pyblish.api.ContextPlugin): def get_parents(self, context): return_dict = {} for instance in context: - asset = instance.data["asset"] + asset = instance.data["folderPath"] families = instance.data.get("families", []) + [ instance.data["family"] ] diff --git a/client/ayon_core/plugins/publish/validate_unique_subsets.py b/client/ayon_core/plugins/publish/validate_unique_subsets.py index 75d12f8e01..5e0e90cff6 100644 --- a/client/ayon_core/plugins/publish/validate_unique_subsets.py +++ b/client/ayon_core/plugins/publish/validate_unique_subsets.py @@ -36,7 +36,7 @@ class ValidateSubsetUniqueness(pyblish.api.ContextPlugin): continue # Ignore instance without asset data - asset = instance.data.get("asset") + asset = instance.data.get("folderPath") if asset is None: self.log.warning("Instance found without `asset` data: " "{}".format(instance.name)) diff --git a/client/ayon_core/settings/ayon_settings.py b/client/ayon_core/settings/ayon_settings.py index 013752da4f..503dcc926d 100644 --- a/client/ayon_core/settings/ayon_settings.py +++ b/client/ayon_core/settings/ayon_settings.py @@ -62,34 +62,13 @@ def _convert_general(ayon_settings, output, default_settings): } -def _convert_royalrender_system_settings( - ayon_settings, output, addon_versions, default_settings -): - enabled = addon_versions.get("royalrender") is not None - rr_settings = default_settings["modules"]["royalrender"] - rr_settings["enabled"] = enabled - if enabled: - ayon_royalrender = ayon_settings["royalrender"] - rr_settings["rr_paths"] = { - item["name"]: item["value"] - for item in ayon_royalrender["rr_paths"] - } - output["modules"]["royalrender"] = rr_settings - - def _convert_modules_system( ayon_settings, output, addon_versions, default_settings ): - # TODO add all modules - # TODO add 'enabled' values - for func in ( - _convert_royalrender_system_settings, - ): - func(ayon_settings, output, addon_versions, default_settings) - for key in { "timers_manager", "clockify", + "royalrender", "deadline", }: if addon_versions.get(key): diff --git a/client/ayon_core/settings/defaults/project_settings/blender.json b/client/ayon_core/settings/defaults/project_settings/blender.json index 385e97ef91..48f3ef8ef0 100644 --- a/client/ayon_core/settings/defaults/project_settings/blender.json +++ b/client/ayon_core/settings/defaults/project_settings/blender.json @@ -22,7 +22,8 @@ "aov_separator": "underscore", "image_format": "exr", "multilayer_exr": true, - "aov_list": [], + "renderer": "CYCLES", + "aov_list": ["combined"], "custom_passes": [] }, "workfile_builder": { diff --git a/server_addon/blender/server/settings/render_settings.py b/server_addon/blender/server/settings/render_settings.py index f91ba1627a..f992ea6fcc 100644 --- a/server_addon/blender/server/settings/render_settings.py +++ b/server_addon/blender/server/settings/render_settings.py @@ -23,6 +23,13 @@ def image_format_enum(): ] +def renderers_enum(): + return [ + {"value": "CYCLES", "label": "Cycles"}, + {"value": "BLENDER_EEVEE", "label": "Eevee"}, + ] + + def aov_list_enum(): return [ {"value": "empty", "label": "< none >"}, @@ -30,18 +37,52 @@ def aov_list_enum(): {"value": "z", "label": "Z"}, {"value": "mist", "label": "Mist"}, {"value": "normal", "label": "Normal"}, - {"value": "diffuse_light", "label": "Diffuse Light"}, + {"value": "position", "label": "Position (Cycles Only)"}, + {"value": "vector", "label": "Vector (Cycles Only)"}, + {"value": "uv", "label": "UV (Cycles Only)"}, + {"value": "denoising", "label": "Denoising Data (Cycles Only)"}, + {"value": "object_index", "label": "Object Index (Cycles Only)"}, + {"value": "material_index", "label": "Material Index (Cycles Only)"}, + {"value": "sample_count", "label": "Sample Count (Cycles Only)"}, + {"value": "diffuse_light", "label": "Diffuse Light/Direct"}, + { + "value": "diffuse_indirect", + "label": "Diffuse Indirect (Cycles Only)" + }, {"value": "diffuse_color", "label": "Diffuse Color"}, - {"value": "specular_light", "label": "Specular Light"}, - {"value": "specular_color", "label": "Specular Color"}, - {"value": "volume_light", "label": "Volume Light"}, + {"value": "specular_light", "label": "Specular (Glossy) Light/Direct"}, + { + "value": "specular_indirect", + "label": "Specular (Glossy) Indirect (Cycles Only)" + }, + {"value": "specular_color", "label": "Specular (Glossy) Color"}, + { + "value": "transmission_light", + "label": "Transmission Light/Direct (Cycles Only)" + }, + { + "value": "transmission_indirect", + "label": "Transmission Indirect (Cycles Only)" + }, + { + "value": "transmission_color", + "label": "Transmission Color (Cycles Only)" + }, + {"value": "volume_light", "label": "Volume Light/Direct"}, + {"value": "volume_indirect", "label": "Volume Indirect (Cycles Only)"}, {"value": "emission", "label": "Emission"}, {"value": "environment", "label": "Environment"}, - {"value": "shadow", "label": "Shadow"}, + {"value": "shadow", "label": "Shadow/Shadow Catcher"}, {"value": "ao", "label": "Ambient Occlusion"}, - {"value": "denoising", "label": "Denoising"}, - {"value": "volume_direct", "label": "Direct Volumetric Scattering"}, - {"value": "volume_indirect", "label": "Indirect Volumetric Scattering"} + {"value": "bloom", "label": "Bloom (Eevee Only)"}, + {"value": "transparent", "label": "Transparent (Eevee Only)"}, + {"value": "cryptomatte_object", "label": "Cryptomatte Object"}, + {"value": "cryptomatte_material", "label": "Cryptomatte Material"}, + {"value": "cryptomatte_asset", "label": "Cryptomatte Asset"}, + { + "value": "cryptomatte_accurate", + "label": "Cryptomatte Accurate Mode (Eevee Only)" + }, ] @@ -81,6 +122,14 @@ class RenderSettingsModel(BaseSettingsModel): multilayer_exr: bool = SettingsField( title="Multilayer (EXR)" ) + renderer: str = SettingsField( + "CYCLES", + title="Renderer", + enum_resolver=renderers_enum + ) + compositing: bool = SettingsField( + title="Enable Compositing" + ) aov_list: list[str] = SettingsField( default_factory=list, enum_resolver=aov_list_enum, @@ -102,6 +151,8 @@ DEFAULT_RENDER_SETTINGS = { "aov_separator": "underscore", "image_format": "exr", "multilayer_exr": True, - "aov_list": [], + "renderer": "CYCLES", + "compositing": True, + "aov_list": ["combined"], "custom_passes": [] } diff --git a/server_addon/blender/server/version.py b/server_addon/blender/server/version.py index 1276d0254f..0a8da88258 100644 --- a/server_addon/blender/server/version.py +++ b/server_addon/blender/server/version.py @@ -1 +1 @@ -__version__ = "0.1.5" +__version__ = "0.1.6"