Remove plugins for instancer family - there is no instancer family?

This commit is contained in:
Roy Nieterau 2024-03-20 01:01:39 +01:00
parent 11e89c100e
commit d223be1a88
2 changed files with 0 additions and 242 deletions

View file

@ -1,75 +0,0 @@
import maya.cmds as cmds
import pyblish.api
from ayon_core.hosts.maya.api import lib
from ayon_core.pipeline.publish import PublishValidationError
class ValidateInstancerContent(pyblish.api.InstancePlugin):
"""Validates that all meshes in the instance have object IDs.
This skips a check on intermediate objects because we consider them
not important.
"""
order = pyblish.api.ValidatorOrder
label = 'Instancer Content'
families = ['instancer']
def process(self, instance):
error = False
members = instance.data['setMembers']
export_members = instance.data['exactExportMembers']
self.log.debug("Contents {0}".format(members))
if not len(members) == len(cmds.ls(members, type="instancer")):
self.log.error("Instancer can only contain instancers")
error = True
# TODO: Implement better check for particles are cached
if not cmds.ls(export_members, type="nucleus"):
self.log.error("Instancer must have a connected nucleus")
error = True
if not cmds.ls(export_members, type="cacheFile"):
self.log.error("Instancer must be cached")
error = True
hidden = self.check_geometry_hidden(export_members)
if not hidden:
error = True
self.log.error("Instancer input geometry must be hidden "
"the scene. Invalid: {0}".format(hidden))
# Ensure all in one group
parents = cmds.listRelatives(members,
allParents=True,
fullPath=True) or []
roots = list(set(cmds.ls(parents, assemblies=True, long=True)))
if len(roots) > 1:
self.log.error("Instancer should all be contained in a single "
"group. Current roots: {0}".format(roots))
error = True
if error:
raise PublishValidationError(
"Instancer Content is invalid. See log.")
def check_geometry_hidden(self, export_members):
# Ensure all instanced geometry is hidden
shapes = cmds.ls(export_members,
dag=True,
shapes=True,
noIntermediate=True)
meshes = cmds.ls(shapes, type="mesh")
visible = [node for node in meshes
if lib.is_visible(node,
displayLayer=False,
intermediateObject=False)]
if visible:
return False
return True

View file

@ -1,167 +0,0 @@
import os
import re
import pyblish.api
from ayon_core.pipeline.publish import PublishValidationError
def is_cache_resource(resource):
"""Return whether resource is a cacheFile resource"""
required = set(["maya", "node", "cacheFile"])
tags = resource.get("tags", [])
return required.issubset(tags)
def valdidate_files(files):
for f in files:
assert os.path.exists(f)
assert f.endswith(".mcx") or f.endswith(".mcc")
return True
def filter_ticks(files):
tick_files = set()
ticks = set()
for path in files:
match = re.match(".+Tick([0-9]+).mcx$", os.path.basename(path))
if match:
tick_files.add(path)
num = match.group(1)
ticks.add(int(num))
return tick_files, ticks
class ValidateInstancerFrameRanges(pyblish.api.InstancePlugin):
"""Validates all instancer particle systems are cached correctly.
This means they should have the files/frames as required by the start-end
frame (including handles).
This also checks the files exist and checks the "ticks" (substeps) files.
"""
order = pyblish.api.ValidatorOrder
label = 'Instancer Cache Frame Ranges'
families = ['instancer']
@classmethod
def get_invalid(cls, instance):
import pyseq
start_frame = instance.data.get("frameStart", 0)
end_frame = instance.data.get("frameEnd", 0)
required = range(int(start_frame), int(end_frame) + 1)
invalid = list()
resources = instance.data.get("resources", [])
for resource in resources:
if not is_cache_resource(resource):
continue
node = resource['node']
all_files = resource['files'][:]
all_lookup = set(all_files)
# The first file is usually the .xml description file.
xml = all_files.pop(0)
assert xml.endswith(".xml")
# Ensure all files exist (including ticks)
# The remainder file paths should be the .mcx or .mcc files
valdidate_files(all_files)
# Maya particle caches support substeps by saving out additional
# files that end with a Tick60.mcx, Tick120.mcx, etc. suffix.
# To avoid `pyseq` getting confused we filter those out and then
# for each file (except the last frame) check that at least all
# ticks exist.
tick_files, ticks = filter_ticks(all_files)
if tick_files:
files = [f for f in all_files if f not in tick_files]
else:
files = all_files
sequences = pyseq.get_sequences(files)
if len(sequences) != 1:
invalid.append(node)
cls.log.warning("More than one sequence found? "
"{0} {1}".format(node, files))
cls.log.warning("Found caches: {0}".format(sequences))
continue
sequence = sequences[0]
cls.log.debug("Found sequence: {0}".format(sequence))
start = sequence.start()
end = sequence.end()
if start > start_frame or end < end_frame:
invalid.append(node)
cls.log.warning("Sequence does not have enough "
"frames: {0}-{1} (requires: {2}-{3})"
"".format(start, end,
start_frame,
end_frame))
continue
# Ensure all frames are present
missing = set(sequence.missing())
if missing:
required_missing = [x for x in required if x in missing]
if required_missing:
invalid.append(node)
cls.log.warning("Sequence is missing required frames: "
"{0}".format(required_missing))
continue
# Ensure all tick files (substep) exist for the files in the folder
# for the frames required by the time range.
if ticks:
ticks = list(sorted(ticks))
cls.log.debug("Found ticks: {0} "
"(substeps: {1})".format(ticks, len(ticks)))
# Check all frames except the last since we don't
# require subframes after our time range.
tick_check_frames = set(required[:-1])
# Check all frames
for item in sequence:
frame = item.frame
if not frame:
invalid.append(node)
cls.log.error("Path is not a frame in sequence: "
"{0}".format(item))
continue
# Not required for our time range
if frame not in tick_check_frames:
continue
path = item.path
for num in ticks:
base, ext = os.path.splitext(path)
tick_file = base + "Tick{0}".format(num) + ext
if tick_file not in all_lookup:
invalid.append(node)
cls.log.warning("Tick file found that is not "
"in cache query filenames: "
"{0}".format(tick_file))
return invalid
def process(self, instance):
invalid = self.get_invalid(instance)
if invalid:
self.log.error("Invalid nodes: {0}".format(invalid))
raise PublishValidationError(
("Invalid particle caches in instance. "
"See logs for details."))