♻️ switch the use to collected instance members

This commit is contained in:
Ondrej Samohel 2023-05-03 18:49:43 +02:00
parent 37ce7fbc09
commit b52527b55f
No known key found for this signature in database
GPG key ID: 02376E18990A97C6
14 changed files with 231 additions and 269 deletions

View file

@ -6,8 +6,7 @@ from openpype.pipeline import (
)
from pymxs import runtime as rt
from openpype.hosts.max.api import (
maintained_selection,
get_all_children
maintained_selection
)
@ -29,8 +28,6 @@ class ExtractCameraAlembic(publish.Extractor,
start = float(instance.data.get("frameStartHandle", 1))
end = float(instance.data.get("frameEndHandle", 1))
container = instance.data["instance_node"]
self.log.info("Extracting Camera ...")
stagingdir = self.staging_dir(instance)
@ -38,8 +35,7 @@ class ExtractCameraAlembic(publish.Extractor,
path = os.path.join(stagingdir, filename)
# We run the render
self.log.info("Writing alembic '%s' to '%s'" % (filename,
stagingdir))
self.log.info(f"Writing alembic '{filename}' to '{stagingdir}'")
export_cmd = (
f"""
@ -57,8 +53,8 @@ exportFile @"{path}" #noPrompt selectedOnly:on using:AlembicExport
with maintained_selection():
# select and export
rt.select(get_all_children(rt.getNodeByName(container)))
rt.execute(export_cmd)
rt.Select(instance.data["members"])
rt.Execute(export_cmd)
self.log.info("Performing Extraction ...")
if "representations" not in instance.data:
@ -71,5 +67,4 @@ exportFile @"{path}" #noPrompt selectedOnly:on using:AlembicExport
"stagingDir": stagingdir,
}
instance.data["representations"].append(representation)
self.log.info("Extracted instance '%s' to: %s" % (instance.name,
path))
self.log.info(f"Extracted instance '{instance.name}' to: {path}")

View file

@ -6,8 +6,7 @@ from openpype.pipeline import (
)
from pymxs import runtime as rt
from openpype.hosts.max.api import (
maintained_selection,
get_all_children
maintained_selection
)
@ -26,15 +25,13 @@ class ExtractCameraFbx(publish.Extractor,
def process(self, instance):
if not self.is_active(instance.data):
return
container = instance.data["instance_node"]
self.log.info("Extracting Camera ...")
stagingdir = self.staging_dir(instance)
filename = "{name}.fbx".format(**instance.data)
filepath = os.path.join(stagingdir, filename)
self.log.info("Writing fbx file '%s' to '%s'" % (filename,
filepath))
self.log.info(f"Writing fbx file '{filename}' to '{filepath}'")
# Need to export:
# Animation = True
@ -57,8 +54,8 @@ exportFile @"{filepath}" #noPrompt selectedOnly:true using:FBXEXP
with maintained_selection():
# select and export
rt.select(get_all_children(rt.getNodeByName(container)))
rt.execute(fbx_export_cmd)
rt.Select(instance.data["members"])
rt.Execute(fbx_export_cmd)
self.log.info("Performing Extraction ...")
if "representations" not in instance.data:
@ -71,5 +68,4 @@ exportFile @"{filepath}" #noPrompt selectedOnly:true using:FBXEXP
"stagingDir": stagingdir,
}
instance.data["representations"].append(representation)
self.log.info("Extracted instance '%s' to: %s" % (instance.name,
filepath))
self.log.info(f"Extracted instance '{instance.name}' to: {filepath}")

View file

@ -6,8 +6,7 @@ from openpype.pipeline import (
)
from pymxs import runtime as rt
from openpype.hosts.max.api import (
maintained_selection,
get_all_children
maintained_selection
)
@ -28,7 +27,6 @@ class ExtractMaxSceneRaw(publish.Extractor,
def process(self, instance):
if not self.is_active(instance.data):
return
container = instance.data["instance_node"]
# publish the raw scene for camera
self.log.info("Extracting Raw Max Scene ...")
@ -37,8 +35,7 @@ class ExtractMaxSceneRaw(publish.Extractor,
filename = "{name}.max".format(**instance.data)
max_path = os.path.join(stagingdir, filename)
self.log.info("Writing max file '%s' to '%s'" % (filename,
max_path))
self.log.info(f"Writing max file '{filename}' to '{max_path}'")
if "representations" not in instance.data:
instance.data["representations"] = []
@ -46,8 +43,8 @@ class ExtractMaxSceneRaw(publish.Extractor,
# saving max scene
with maintained_selection():
# need to figure out how to select the camera
rt.select(get_all_children(rt.getNodeByName(container)))
rt.execute(f'saveNodes selection "{max_path}" quiet:true')
rt.Select(instance.data["members"])
rt.Execute(f'saveNodes selection "{max_path}" quiet:true')
self.log.info("Performing Extraction ...")
@ -58,5 +55,4 @@ class ExtractMaxSceneRaw(publish.Extractor,
"stagingDir": stagingdir,
}
instance.data["representations"].append(representation)
self.log.info("Extracted instance '%s' to: %s" % (instance.name,
max_path))
self.log.info(f"Extracted instance '{instance.name}' to: {max_path}")

View file

@ -6,8 +6,7 @@ from openpype.pipeline import (
)
from pymxs import runtime as rt
from openpype.hosts.max.api import (
maintained_selection,
get_all_children
maintained_selection
)
@ -27,8 +26,6 @@ class ExtractModel(publish.Extractor,
if not self.is_active(instance.data):
return
container = instance.data["instance_node"]
self.log.info("Extracting Geometry ...")
stagingdir = self.staging_dir(instance)
@ -36,8 +33,7 @@ class ExtractModel(publish.Extractor,
filepath = os.path.join(stagingdir, filename)
# We run the render
self.log.info("Writing alembic '%s' to '%s'" % (filename,
stagingdir))
self.log.info(f"Writing alembic '{filename}' to '{stagingdir}'")
export_cmd = (
f"""
@ -56,8 +52,8 @@ exportFile @"{filepath}" #noPrompt selectedOnly:on using:AlembicExport
with maintained_selection():
# select and export
rt.select(get_all_children(rt.getNodeByName(container)))
rt.execute(export_cmd)
rt.Select(instance.data["members"])
rt.Execute(export_cmd)
self.log.info("Performing Extraction ...")
if "representations" not in instance.data:
@ -70,5 +66,4 @@ exportFile @"{filepath}" #noPrompt selectedOnly:on using:AlembicExport
"stagingDir": stagingdir,
}
instance.data["representations"].append(representation)
self.log.info("Extracted instance '%s' to: %s" % (instance.name,
filepath))
self.log.info(f"Extracted instance '{instance.name}' to: {filepath}")

View file

@ -6,8 +6,7 @@ from openpype.pipeline import (
)
from pymxs import runtime as rt
from openpype.hosts.max.api import (
maintained_selection,
get_all_children
maintained_selection
)
@ -27,16 +26,13 @@ class ExtractModelFbx(publish.Extractor,
if not self.is_active(instance.data):
return
container = instance.data["instance_node"]
self.log.info("Extracting Geometry ...")
stagingdir = self.staging_dir(instance)
filename = "{name}.fbx".format(**instance.data)
filepath = os.path.join(stagingdir,
filename)
self.log.info("Writing FBX '%s' to '%s'" % (filepath,
stagingdir))
self.log.info(f"Writing FBX '{filepath}' to '{stagingdir}'")
export_fbx_cmd = (
f"""
@ -56,8 +52,8 @@ exportFile @"{filepath}" #noPrompt selectedOnly:true using:FBXEXP
with maintained_selection():
# select and export
rt.select(get_all_children(rt.getNodeByName(container)))
rt.execute(export_fbx_cmd)
rt.Select(instance.data["members"])
rt.Execute(export_fbx_cmd)
self.log.info("Performing Extraction ...")
if "representations" not in instance.data:
@ -70,5 +66,4 @@ exportFile @"{filepath}" #noPrompt selectedOnly:true using:FBXEXP
"stagingDir": stagingdir,
}
instance.data["representations"].append(representation)
self.log.info("Extracted instance '%s' to: %s" % (instance.name,
filepath))
self.log.info(f"Extracted instance '{instance.name}' to: {filepath}")

View file

@ -6,8 +6,7 @@ from openpype.pipeline import (
)
from pymxs import runtime as rt
from openpype.hosts.max.api import (
maintained_selection,
get_all_children
maintained_selection
)
@ -27,21 +26,18 @@ class ExtractModelObj(publish.Extractor,
if not self.is_active(instance.data):
return
container = instance.data["instance_node"]
self.log.info("Extracting Geometry ...")
stagingdir = self.staging_dir(instance)
filename = "{name}.obj".format(**instance.data)
filepath = os.path.join(stagingdir,
filename)
self.log.info("Writing OBJ '%s' to '%s'" % (filepath,
stagingdir))
self.log.info(f"Writing OBJ '{filepath}' to '{stagingdir}'")
with maintained_selection():
# select and export
rt.select(get_all_children(rt.getNodeByName(container)))
rt.execute(f'exportFile @"{filepath}" #noPrompt selectedOnly:true using:ObjExp') # noqa
rt.Select(instance.data["members"])
rt.Execute(f'exportFile @"{filepath}" #noPrompt selectedOnly:true using:ObjExp') # noqa
self.log.info("Performing Extraction ...")
if "representations" not in instance.data:
@ -55,5 +51,4 @@ class ExtractModelObj(publish.Extractor,
}
instance.data["representations"].append(representation)
self.log.info("Extracted instance '%s' to: %s" % (instance.name,
filepath))
self.log.info(f"Extracted instance '{instance.name}' to: {filepath}")

View file

@ -26,31 +26,27 @@ class ExtractModelUSD(publish.Extractor,
if not self.is_active(instance.data):
return
container = instance.data["instance_node"]
self.log.info("Extracting Geometry ...")
stagingdir = self.staging_dir(instance)
asset_filename = "{name}.usda".format(**instance.data)
asset_filepath = os.path.join(stagingdir,
asset_filename)
self.log.info("Writing USD '%s' to '%s'" % (asset_filepath,
stagingdir))
self.log.info(f"Writing USD '{asset_filepath}' to '{stagingdir}'")
log_filename = "{name}.txt".format(**instance.data)
log_filepath = os.path.join(stagingdir,
log_filename)
self.log.info("Writing log '%s' to '%s'" % (log_filepath,
stagingdir))
self.log.info(f"Writing log '{log_filepath}' to '{stagingdir}'")
# get the nodes which need to be exported
export_options = self.get_export_options(log_filepath)
with maintained_selection():
# select and export
node_list = self.get_node_list(container)
node_list = instance.data["members"]
rt.USDExporter.ExportFile(asset_filepath,
exportOptions=export_options,
contentSource=rt.name("selected"),
contentSource=rt.Name("selected"),
nodeList=node_list)
self.log.info("Performing Extraction ...")
@ -73,25 +69,10 @@ class ExtractModelUSD(publish.Extractor,
}
instance.data["representations"].append(log_representation)
self.log.info("Extracted instance '%s' to: %s" % (instance.name,
asset_filepath))
self.log.info(f"Extracted instance '{instance.name}' to: {asset_filepath}")
def get_node_list(self, container):
"""
Get the target nodes which are
the children of the container
"""
node_list = []
container_node = rt.getNodeByName(container)
target_node = container_node.Children
rt.select(target_node)
for sel in rt.selection:
node_list.append(sel)
return node_list
def get_export_options(self, log_path):
@staticmethod
def get_export_options(log_path):
"""Set Export Options for USD Exporter"""
export_options = rt.USDExporter.createOptions()
@ -101,13 +82,13 @@ class ExtractModelUSD(publish.Extractor,
export_options.Lights = False
export_options.Cameras = False
export_options.Materials = False
export_options.MeshFormat = rt.name('fromScene')
export_options.FileFormat = rt.name('ascii')
export_options.UpAxis = rt.name('y')
export_options.LogLevel = rt.name('info')
export_options.MeshFormat = rt.Name('fromScene')
export_options.FileFormat = rt.Name('ascii')
export_options.UpAxis = rt.Name('y')
export_options.LogLevel = rt.Name('info')
export_options.LogPath = log_path
export_options.PreserveEdgeOrientation = True
export_options.TimeMode = rt.name('current')
export_options.TimeMode = rt.Name('current')
rt.USDexporter.UIOptions = export_options

View file

@ -42,8 +42,7 @@ import pyblish.api
from openpype.pipeline import publish
from pymxs import runtime as rt
from openpype.hosts.max.api import (
maintained_selection,
get_all_children
maintained_selection
)
@ -57,17 +56,14 @@ class ExtractAlembic(publish.Extractor):
start = float(instance.data.get("frameStartHandle", 1))
end = float(instance.data.get("frameEndHandle", 1))
container = instance.data["instance_node"]
self.log.info("Extracting pointcache ...")
parent_dir = self.staging_dir(instance)
file_name = "{name}.abc".format(**instance.data)
path = os.path.join(parent_dir, file_name)
# We run the render
self.log.info("Writing alembic '%s' to '%s'" % (file_name,
parent_dir))
self.log.info(
f"Writing alembic '{file_name}' to '{parent_dir}'")
abc_export_cmd = (
f"""
@ -85,8 +81,8 @@ exportFile @"{path}" #noPrompt selectedOnly:on using:AlembicExport
with maintained_selection():
# select and export
rt.select(get_all_children(rt.getNodeByName(container)))
rt.execute(abc_export_cmd)
rt.Select(instance.data["members"])
rt.Execute(abc_export_cmd)
if "representations" not in instance.data:
instance.data["representations"] = []

View file

@ -9,13 +9,6 @@ from openpype.settings import get_project_settings
from openpype.pipeline import legacy_io
def get_setting(project_setting=None):
project_setting = get_project_settings(
legacy_io.Session["AVALON_PROJECT"]
)
return (project_setting["max"]["PointCloud"])
class ExtractPointCloud(publish.Extractor):
"""
Extract PRT format with tyFlow operators
@ -24,19 +17,20 @@ class ExtractPointCloud(publish.Extractor):
Currently only works for the default partition setting
Args:
export_particle(): sets up all job arguments for attributes
to be exported in MAXscript
self.export_particle(): sets up all job arguments for attributes
to be exported in MAXscript
get_operators(): get the export_particle operator
self.get_operators(): get the export_particle operator
get_custom_attr(): get all custom channel attributes from Openpype
setting and sets it as job arguments before exporting
self.get_custom_attr(): get all custom channel attributes from Openpype
setting and sets it as job arguments before exporting
get_files(): get the files with tyFlow naming convention
before publishing
self.get_files(): get the files with tyFlow naming convention
before publishing
partition_output_name(): get the naming with partition settings.
get_partition(): get partition value
self.partition_output_name(): get the naming with partition settings.
self.get_partition(): get partition value
"""
@ -46,6 +40,7 @@ class ExtractPointCloud(publish.Extractor):
families = ["pointcloud"]
def process(self, instance):
self.settings = self.get_setting(instance)
start = int(instance.context.data.get("frameStart"))
end = int(instance.context.data.get("frameEnd"))
container = instance.data["instance_node"]
@ -56,12 +51,12 @@ class ExtractPointCloud(publish.Extractor):
path = os.path.join(stagingdir, filename)
with maintained_selection():
job_args = self.export_particle(container,
job_args = self.export_particle(instance.data["members"],
start,
end,
path)
for job in job_args:
rt.execute(job)
rt.Execute(job)
self.log.info("Performing Extraction ...")
if "representations" not in instance.data:
@ -69,7 +64,7 @@ class ExtractPointCloud(publish.Extractor):
self.log.info("Writing PRT with TyFlow Plugin...")
filenames = self.get_files(container, path, start, end)
self.log.debug("filenames: {0}".format(filenames))
self.log.debug(f"filenames: {filenames}")
partition = self.partition_output_name(container)
@ -81,67 +76,87 @@ class ExtractPointCloud(publish.Extractor):
"outputName": partition # partition value
}
instance.data["representations"].append(representation)
self.log.info("Extracted instance '%s' to: %s" % (instance.name,
path))
self.log.info(f"Extracted instance '{instance.name}' to: {path}")
def export_particle(self,
container,
members,
start,
end,
filepath):
"""Sets up all job arguments for attributes.
Those attributes are to be exported in MAX Script.
Args:
members (list): Member nodes of the instance.
start (int): Start frame.
end (int): End frame.
filepath (str): Path to PRT file.
Returns:
list of arguments for MAX Script.
"""
job_args = []
opt_list = self.get_operators(container)
opt_list = self.get_operators(members)
for operator in opt_list:
start_frame = "{0}.frameStart={1}".format(operator,
start)
start_frame = f"{operator}.frameStart={start}"
job_args.append(start_frame)
end_frame = "{0}.frameEnd={1}".format(operator,
end)
end_frame = f"{operator}.frameEnd={end}"
job_args.append(end_frame)
filepath = filepath.replace("\\", "/")
prt_filename = '{0}.PRTFilename="{1}"'.format(operator,
filepath)
prt_filename = f"{operator}.PRTFilename={filepath}"
job_args.append(prt_filename)
# Partition
mode = "{0}.PRTPartitionsMode=2".format(operator)
mode = f"{operator}.PRTPartitionsMode=2"
job_args.append(mode)
additional_args = self.get_custom_attr(operator)
for args in additional_args:
job_args.append(args)
prt_export = "{0}.exportPRT()".format(operator)
job_args.extend(iter(additional_args))
prt_export = f"{operator}.exportPRT()"
job_args.append(prt_export)
return job_args
def get_operators(self, container):
"""Get Export Particles Operator"""
@staticmethod
def get_operators(members):
"""Get Export Particles Operator.
Args:
members (list): Instance members.
Returns:
list of particle operators
"""
opt_list = []
node = rt.getNodebyName(container)
selection_list = list(node.Children)
for sel in selection_list:
obj = sel.baseobject
for member in members:
obj = member.baseobject
# TODO: to see if it can be used maxscript instead
anim_names = rt.getsubanimnames(obj)
anim_names = rt.GetSubAnimNames(obj)
for anim_name in anim_names:
sub_anim = rt.getsubanim(obj, anim_name)
boolean = rt.isProperty(sub_anim, "Export_Particles")
event_name = sub_anim.name
sub_anim = rt.GetSubAnim(obj, anim_name)
boolean = rt.IsProperty(sub_anim, "Export_Particles")
if boolean:
opt = "${0}.{1}.export_particles".format(sel.name,
event_name)
event_name = sub_anim.Name
opt = f"${member.Name}.{event_name}.export_particles"
opt_list.append(opt)
return opt_list
@staticmethod
def get_setting(instance):
project_setting = get_project_settings(
instance.context.data["projectName"]
)
return project_setting["max"]["PointCloud"]
def get_custom_attr(self, operator):
"""Get Custom Attributes"""
custom_attr_list = []
attr_settings = get_setting()["attribute"]
attr_settings = self.settings["attribute"]
for key, value in attr_settings.items():
custom_attr = "{0}.PRTChannels_{1}=True".format(operator,
value)
@ -157,14 +172,25 @@ class ExtractPointCloud(publish.Extractor):
path,
start_frame,
end_frame):
"""
Note:
Set the filenames accordingly to the tyFlow file
naming extension for the publishing purpose
"""Get file names for tyFlow.
Actual File Output from tyFlow:
Set the filenames accordingly to the tyFlow file
naming extension for the publishing purpose
Actual File Output from tyFlow::
<SceneFile>__part<PartitionStart>of<PartitionCount>.<frame>.prt
e.g. tyFlow_cloth_CCCS_blobbyFill_001__part1of1_00004.prt
Args:
container: Instance node.
path (str): Output directory.
start_frame (int): Start frame.
end_frame (int): End frame.
Returns:
list of filenames
"""
filenames = []
filename = os.path.basename(path)
@ -181,27 +207,36 @@ class ExtractPointCloud(publish.Extractor):
return filenames
def partition_output_name(self, container):
"""
Notes:
Partition output name set for mapping
the published file output
"""Get partition output name.
Partition output name set for mapping
the published file output.
Todo:
Customizes the setting for the output.
Args:
container: Instance node.
Returns:
str: Partition name.
todo:
Customizes the setting for the output
"""
partition_count, partition_start = self.get_partition(container)
partition = "_part{:03}of{}".format(partition_start,
partition_count)
return partition
return f"_part{partition_start:03}of{partition_count}"
def get_partition(self, container):
"""
Get Partition Value
"""Get Partition value.
Args:
container: Instance node.
"""
opt_list = self.get_operators(container)
# TODO: This looks strange? Iterating over
# the opt_list but returning from inside?
for operator in opt_list:
count = rt.execute(f'{operator}.PRTPartitionsCount')
start = rt.execute(f'{operator}.PRTPartitionsFrom')
count = rt.Execute(f'{operator}.PRTPartitionsCount')
start = rt.Execute(f'{operator}.PRTPartitionsFrom')
return count, start

View file

@ -18,30 +18,24 @@ class ValidateCameraContent(pyblish.api.InstancePlugin):
"$Physical_Camera", "$Target"]
def process(self, instance):
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError("Camera instance must only include"
"camera (and camera target)")
if invalid := self.get_invalid(instance):
raise PublishValidationError(("Camera instance must only include"
"camera (and camera target). "
f"Invalid content {invalid}"))
def get_invalid(self, instance):
"""
Get invalid nodes if the instance is not camera
"""
invalid = list()
invalid = []
container = instance.data["instance_node"]
self.log.info("Validating look content for "
"{}".format(container))
self.log.info(f"Validating camera content for {container}")
con = rt.getNodeByName(container)
selection_list = list(con.Children)
selection_list = instance.data["members"]
for sel in selection_list:
# to avoid Attribute Error from pymxs wrapper
sel_tmp = str(sel)
found = False
for cam in self.camera_type:
if sel_tmp.startswith(cam):
found = True
break
found = any(sel_tmp.startswith(cam) for cam in self.camera_type)
if not found:
self.log.error("Camera not found")
invalid.append(sel)

View file

@ -17,28 +17,26 @@ class ValidateModelContent(pyblish.api.InstancePlugin):
label = "Model Contents"
def process(self, instance):
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError("Model instance must only include"
"Geometry and Editable Mesh")
if invalid := self.get_invalid(instance):
raise PublishValidationError(("Model instance must only include"
"Geometry and Editable Mesh. "
f"Invalid types on: {invalid}"))
def get_invalid(self, instance):
"""
Get invalid nodes if the instance is not camera
"""
invalid = list()
invalid = []
container = instance.data["instance_node"]
self.log.info("Validating look content for "
"{}".format(container))
self.log.info(f"Validating model content for {container}")
con = rt.getNodeByName(container)
selection_list = list(con.Children) or rt.getCurrentSelection()
selection_list = instance.data["members"]
for sel in selection_list:
if rt.classOf(sel) in rt.Camera.classes:
if rt.ClassOf(sel) in rt.Camera.classes:
invalid.append(sel)
if rt.classOf(sel) in rt.Light.classes:
if rt.ClassOf(sel) in rt.Light.classes:
invalid.append(sel)
if rt.classOf(sel) in rt.Shape.classes:
if rt.ClassOf(sel) in rt.Shape.classes:
invalid.append(sel)
return invalid

View file

@ -18,6 +18,5 @@ class ValidateMaxContents(pyblish.api.InstancePlugin):
label = "Max Scene Contents"
def process(self, instance):
container = rt.getNodeByName(instance.data["instance_node"])
if not list(container.Children):
if not instance.data["members"]:
raise PublishValidationError("No content found in the container")

View file

@ -9,11 +9,11 @@ def get_setting(project_setting=None):
project_setting = get_project_settings(
legacy_io.Session["AVALON_PROJECT"]
)
return (project_setting["max"]["PointCloud"])
return project_setting["max"]["PointCloud"]
class ValidatePointCloud(pyblish.api.InstancePlugin):
"""Validate that workfile was saved."""
"""Validate that work file was saved."""
order = pyblish.api.ValidatorOrder
families = ["pointcloud"]
@ -34,39 +34,37 @@ class ValidatePointCloud(pyblish.api.InstancePlugin):
of export_particle operator
"""
invalid = self.get_tyFlow_object(instance)
if invalid:
raise PublishValidationError("Non tyFlow object "
"found: {}".format(invalid))
invalid = self.get_tyFlow_operator(instance)
if invalid:
raise PublishValidationError("tyFlow ExportParticle operator "
"not found: {}".format(invalid))
report = []
if invalid := self.get_tyflow_object(instance):
report.append(f"Non tyFlow object found: {invalid}")
invalid = self.validate_export_mode(instance)
if invalid:
raise PublishValidationError("The export mode is not at PRT")
if invalid := self.get_tyflow_operator(instance):
report.append(
f"tyFlow ExportParticle operator not found: {invalid}")
invalid = self.validate_partition_value(instance)
if invalid:
raise PublishValidationError("tyFlow Partition setting is "
"not at the default value")
invalid = self.validate_custom_attribute(instance)
if invalid:
raise PublishValidationError("Custom Attribute not found "
":{}".format(invalid))
if self.validate_export_mode(instance):
report.append("The export mode is not at PRT")
def get_tyFlow_object(self, instance):
if self.validate_partition_value(instance):
report.append(("tyFlow Partition setting is "
"not at the default value"))
if invalid := self.validate_custom_attribute(instance):
report.append(("Custom Attribute not found "
f":{invalid}"))
if report:
raise PublishValidationError
def get_tyflow_object(self, instance):
invalid = []
container = instance.data["instance_node"]
self.log.info("Validating tyFlow container "
"for {}".format(container))
self.log.info(f"Validating tyFlow container for {container}")
con = rt.getNodeByName(container)
selection_list = list(con.Children)
selection_list = instance.data["members"]
for sel in selection_list:
sel_tmp = str(sel)
if rt.classOf(sel) in [rt.tyFlow,
if rt.ClassOf(sel) in [rt.tyFlow,
rt.Editable_Mesh]:
if "tyFlow" not in sel_tmp:
invalid.append(sel)
@ -75,23 +73,20 @@ class ValidatePointCloud(pyblish.api.InstancePlugin):
return invalid
def get_tyFlow_operator(self, instance):
def get_tyflow_operator(self, instance):
invalid = []
container = instance.data["instance_node"]
self.log.info("Validating tyFlow object "
"for {}".format(container))
con = rt.getNodeByName(container)
selection_list = list(con.Children)
self.log.info(f"Validating tyFlow object for {container}")
selection_list = instance.data["members"]
bool_list = []
for sel in selection_list:
obj = sel.baseobject
anim_names = rt.getsubanimnames(obj)
anim_names = rt.GetSubAnimNames(obj)
for anim_name in anim_names:
# get all the names of the related tyFlow nodes
sub_anim = rt.getsubanim(obj, anim_name)
sub_anim = rt.GetSubAnim(obj, anim_name)
# check if there is export particle operator
boolean = rt.isProperty(sub_anim, "Export_Particles")
boolean = rt.IsProperty(sub_anim, "Export_Particles")
bool_list.append(str(boolean))
# if the export_particles property is not there
# it means there is not a "Export Particle" operator
@ -104,21 +99,18 @@ class ValidatePointCloud(pyblish.api.InstancePlugin):
def validate_custom_attribute(self, instance):
invalid = []
container = instance.data["instance_node"]
self.log.info("Validating tyFlow custom "
"attributes for {}".format(container))
self.log.info(
f"Validating tyFlow custom attributes for {container}")
con = rt.getNodeByName(container)
selection_list = list(con.Children)
selection_list = instance.data["members"]
for sel in selection_list:
obj = sel.baseobject
anim_names = rt.getsubanimnames(obj)
anim_names = rt.GetSubAnimNames(obj)
for anim_name in anim_names:
# get all the names of the related tyFlow nodes
sub_anim = rt.getsubanim(obj, anim_name)
# check if there is export particle operator
boolean = rt.isProperty(sub_anim, "Export_Particles")
event_name = sub_anim.name
if boolean:
sub_anim = rt.GetSubAnim(obj, anim_name)
if rt.IsProperty(sub_anim, "Export_Particles"):
event_name = sub_anim.name
opt = "${0}.{1}.export_particles".format(sel.name,
event_name)
attributes = get_setting()["attribute"]
@ -126,39 +118,36 @@ class ValidatePointCloud(pyblish.api.InstancePlugin):
custom_attr = "{0}.PRTChannels_{1}".format(opt,
value)
try:
rt.execute(custom_attr)
rt.Execute(custom_attr)
except RuntimeError:
invalid.add(key)
invalid.append(key)
return invalid
def validate_partition_value(self, instance):
invalid = []
container = instance.data["instance_node"]
self.log.info("Validating tyFlow partition "
"value for {}".format(container))
self.log.info(
f"Validating tyFlow partition value for {container}")
con = rt.getNodeByName(container)
selection_list = list(con.Children)
selection_list = instance.data["members"]
for sel in selection_list:
obj = sel.baseobject
anim_names = rt.getsubanimnames(obj)
anim_names = rt.GetSubAnimNames(obj)
for anim_name in anim_names:
# get all the names of the related tyFlow nodes
sub_anim = rt.getsubanim(obj, anim_name)
# check if there is export particle operator
boolean = rt.isProperty(sub_anim, "Export_Particles")
event_name = sub_anim.name
if boolean:
sub_anim = rt.GetSubAnim(obj, anim_name)
if rt.IsProperty(sub_anim, "Export_Particles"):
event_name = sub_anim.name
opt = "${0}.{1}.export_particles".format(sel.name,
event_name)
count = rt.execute(f'{opt}.PRTPartitionsCount')
count = rt.Execute(f'{opt}.PRTPartitionsCount')
if count != 100:
invalid.append(count)
start = rt.execute(f'{opt}.PRTPartitionsFrom')
start = rt.Execute(f'{opt}.PRTPartitionsFrom')
if start != 1:
invalid.append(start)
end = rt.execute(f'{opt}.PRTPartitionsTo')
end = rt.Execute(f'{opt}.PRTPartitionsTo')
if end != 1:
invalid.append(end)
@ -167,24 +156,23 @@ class ValidatePointCloud(pyblish.api.InstancePlugin):
def validate_export_mode(self, instance):
invalid = []
container = instance.data["instance_node"]
self.log.info("Validating tyFlow export "
"mode for {}".format(container))
self.log.info(
f"Validating tyFlow export mode for {container}")
con = rt.getNodeByName(container)
con = rt.GetNodeByName(container)
selection_list = list(con.Children)
for sel in selection_list:
obj = sel.baseobject
anim_names = rt.getsubanimnames(obj)
anim_names = rt.GetSubAnimNames(obj)
for anim_name in anim_names:
# get all the names of the related tyFlow nodes
sub_anim = rt.getsubanim(obj, anim_name)
sub_anim = rt.GetSubAnim(obj, anim_name)
# check if there is export particle operator
boolean = rt.isProperty(sub_anim, "Export_Particles")
boolean = rt.IsProperty(sub_anim, "Export_Particles")
event_name = sub_anim.name
if boolean:
opt = "${0}.{1}.export_particles".format(sel.name,
event_name)
export_mode = rt.execute(f'{opt}.exportMode')
opt = f"${sel.name}.{event_name}.export_particles"
export_mode = rt.Execute(f'{opt}.exportMode')
if export_mode != 1:
invalid.append(export_mode)

View file

@ -14,21 +14,20 @@ class ValidateUSDPlugin(pyblish.api.InstancePlugin):
label = "USD Plugin"
def process(self, instance):
plugin_mgr = rt.pluginManager
plugin_mgr = rt.PluginManager
plugin_count = plugin_mgr.pluginDllCount
plugin_info = self.get_plugins(plugin_mgr,
plugin_count)
usd_import = "usdimport.dli"
if usd_import not in plugin_info:
raise PublishValidationError("USD Plugin {}"
" not found".format(usd_import))
raise PublishValidationError(f"USD Plugin {usd_import} not found")
usd_export = "usdexport.dle"
if usd_export not in plugin_info:
raise PublishValidationError("USD Plugin {}"
" not found".format(usd_export))
raise PublishValidationError(f"USD Plugin {usd_export} not found")
def get_plugins(self, manager, count):
plugin_info_list = list()
@staticmethod
def get_plugins(manager, count):
plugin_info_list = []
for p in range(1, count + 1):
plugin_info = manager.pluginDllName(p)
plugin_info_list.append(plugin_info)