mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-02 00:44:52 +01:00
♻️ switch the use to collected instance members
This commit is contained in:
parent
37ce7fbc09
commit
b52527b55f
14 changed files with 231 additions and 269 deletions
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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"] = []
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue