Workaround for motion blur

This commit is contained in:
Toke Stuart Jepsen 2023-01-30 10:15:04 +00:00
parent 40cf86ea97
commit 1f08a27343
2 changed files with 146 additions and 63 deletions

View file

@ -1,11 +1,14 @@
import os
import shutil
import copy
from maya import cmds
import pyblish.api
from openpype.hosts.maya.api import current_file
from openpype.hosts.maya.api.lib import extract_alembic
from openpype.pipeline import publish
from openpype.lib import StringTemplate
class ExtractWorkfileXgen(publish.Extractor):
@ -18,9 +21,22 @@ class ExtractWorkfileXgen(publish.Extractor):
hosts = ["maya"]
def process(self, instance):
transfers = []
# Validate there is any palettes in the scene.
if not cmds.ls(type="xgmPalette"):
self.log.debug(
"No collections found in the scene. Abort Xgen extraction."
)
return
else:
import xgenm
# Validate to extract only when we are publishing a renderlayer as
# well.
renderlayer = False
start_frame = None
end_frame = None
for i in instance.context:
is_renderlayer = (
"renderlayer" in i.data.get("families", []) or
@ -28,6 +44,17 @@ class ExtractWorkfileXgen(publish.Extractor):
)
if is_renderlayer and i.data["publish"]:
renderlayer = True
if start_frame is None:
start_frame = i.data["frameStart"]
if end_frame is None:
end_frame = i.data["frameEnd"]
if i.data["frameStart"] < start_frame:
start_frame = i.data["frameStart"]
if i.data["frameEnd"] > end_frame:
end_frame = i.data["frameEnd"]
break
if not renderlayer:
@ -37,6 +64,51 @@ class ExtractWorkfileXgen(publish.Extractor):
)
return
# We decrement start frame and increment end frame so motion blur will
# render correctly.
start_frame -= 1
end_frame += 1
# Extract patches alembic.
basename, _ = os.path.splitext(current_file())
dirname = os.path.dirname(current_file())
kwargs = {"attrPrefix": ["xgen"], "stripNamespaces": True}
alembic_files = []
for palette in cmds.ls(type="xgmPalette"):
patch_names = []
for description in xgenm.descriptions(palette):
for name in xgenm.boundGeometry(palette, description):
patch_names.append(name)
alembic_file = os.path.join(
dirname,
"{}__{}.abc".format(basename, palette.replace(":", "__ns__"))
)
extract_alembic(
alembic_file,
root=patch_names,
selection=False,
startFrame=float(start_frame),
endFrame=float(end_frame),
verbose=True,
**kwargs
)
alembic_files.append(alembic_file)
template_data = copy.deepcopy(instance.data["anatomyData"])
published_maya_path = StringTemplate(
instance.context.data["anatomy"].templates["publish"]["file"]
).format(template_data)
published_basename, _ = os.path.splitext(published_maya_path)
for source in alembic_files:
destination = os.path.join(
os.path.dirname(instance.data["resourcesDir"]),
os.path.basename(source.replace(basename, published_basename))
)
transfers.append((source, destination))
# Validate that we are using the published workfile.
deadline_settings = instance.context.get("deadline")
if deadline_settings:
publish_settings = deadline_settings["publish"]
@ -76,8 +148,9 @@ class ExtractWorkfileXgen(publish.Extractor):
with open(destination, "r") as f:
for line in [line.rstrip() for line in f]:
if line.startswith("\txgProjectPath"):
path = os.path.dirname(instance.data["resourcesDir"])
line = "\txgProjectPath\t\t{}/".format(
instance.data["resourcesDir"].replace("\\", "/")
path.replace("\\", "/")
)
lines.append(line)
@ -88,31 +161,30 @@ class ExtractWorkfileXgen(publish.Extractor):
sources.append(destination)
# Add resource files to workfile instance.
transfers = []
for source in sources:
basename = os.path.basename(source)
destination = os.path.join(instance.data["resourcesDir"], basename)
destination = os.path.join(
os.path.dirname(instance.data["resourcesDir"]), basename
)
transfers.append((source, destination))
import xgenm
destination_dir = os.path.join(
instance.data["resourcesDir"], "collections"
)
for palette in cmds.ls(type="xgmPalette"):
relative_data_path = xgenm.getAttr(
"xgDataPath", palette.replace("|", "")
).split(os.pathsep)[0]
absolute_data_path = relative_data_path.replace(
"${PROJECT}",
xgenm.getAttr("xgProjectPath", palette.replace("|", ""))
)
for root, _, files in os.walk(absolute_data_path):
for file in files:
source = os.path.join(root, file).replace("\\", "/")
destination = os.path.join(
instance.data["resourcesDir"],
relative_data_path.replace("${PROJECT}", ""),
source.replace(absolute_data_path, "")[1:]
)
transfers.append((source, destination.replace("\\", "/")))
project_path = xgenm.getAttr("xgProjectPath", palette)
data_path = xgenm.getAttr("xgDataPath", palette)
data_path = data_path.replace("${PROJECT}", project_path)
for path in data_path.split(os.pathsep):
for root, _, files in os.walk(path):
for f in files:
source = os.path.join(root, f)
destination = "{}/{}{}".format(
destination_dir,
palette.replace(":", "__ns__"),
source.replace(path, "")
)
transfers.append((source, destination))
for source, destination in transfers:
self.log.debug("Transfer: {} > {}".format(source, destination))
@ -120,21 +192,26 @@ class ExtractWorkfileXgen(publish.Extractor):
instance.data["transfers"] = transfers
# Set palette attributes in preparation for workfile publish.
attrs = ["xgFileName", "xgBaseFile"]
attrs = {"xgFileName": None, "xgBaseFile": ""}
data = {}
for palette in cmds.ls(type="xgmPalette"):
for attr in attrs:
value = cmds.getAttr(palette + "." + attr)
if value:
new_value = "resources/{}".format(value)
node_attr = "{}.{}".format(palette, attr)
self.log.info(
"Setting \"{}\" on \"{}\"".format(new_value, node_attr)
)
cmds.setAttr(node_attr, new_value, type="string")
try:
data[palette][attr] = value
except KeyError:
data[palette] = {attr: value}
attrs["xgFileName"] = "resources/{}.xgen".format(
palette.replace(":", "__ns__")
)
for attr, value in attrs.items():
node_attr = palette + "." + attr
old_value = cmds.getAttr(node_attr)
try:
data[palette][attr] = old_value
except KeyError:
data[palette] = {attr: old_value}
cmds.setAttr(node_attr, value, type="string")
self.log.info(
"Setting \"{}\" on \"{}\"".format(value, node_attr)
)
cmds.setAttr(palette + "." + "xgExportAsDelta", False)
instance.data["xgenAttributes"] = data

View file

@ -1,5 +1,6 @@
import os
import copy
import tempfile
from maya import cmds
import xgenm
@ -16,6 +17,7 @@ class ExtractXgenCache(publish.Extractor):
- Duplicate nodes used for patches.
- Export palette and import onto duplicate nodes.
- Export/Publish duplicate nodes and palette.
- Export duplicate palette to .xgen file and add to publish.
- Publish all xgen files as resources.
"""
@ -32,29 +34,6 @@ class ExtractXgenCache(publish.Extractor):
maya_filename = "{}.{}".format(instance.data["name"], self.scene_type)
maya_filepath = os.path.join(staging_dir, maya_filename)
# Get published xgen file name.
template_data = copy.deepcopy(instance.data["anatomyData"])
template_data.update({"ext": "xgen"})
templates = instance.context.data["anatomy"].templates["publish"]
xgen_filename = StringTemplate(templates["file"]).format(template_data)
name = instance.data["xgmPalette"].replace(":", "__").replace("|", "")
xgen_filename = xgen_filename.replace(".xgen", "__" + name + ".xgen")
# Export xgen palette files.
xgen_path = os.path.join(staging_dir, xgen_filename).replace("\\", "/")
xgenm.exportPalette(
instance.data["xgmPalette"].replace("|", ""), xgen_path
)
self.log.info("Extracted to {}".format(xgen_path))
representation = {
"name": name,
"ext": "xgen",
"files": xgen_filename,
"stagingDir": staging_dir,
}
instance.data["representations"].append(representation)
# Collect nodes to export.
duplicate_nodes = []
for node, connections in instance.data["xgenConnections"].items():
@ -74,17 +53,43 @@ class ExtractXgenCache(publish.Extractor):
duplicate_nodes.append(duplicate_transform)
# Export temp xgen palette files.
temp_xgen_path = os.path.join(
tempfile.gettempdir(), "temp.xgen"
).replace("\\", "/")
xgenm.exportPalette(
instance.data["xgmPalette"].replace("|", ""), temp_xgen_path
)
self.log.info("Extracted to {}".format(temp_xgen_path))
# Import xgen onto the duplicate.
with maintained_selection():
cmds.select(duplicate_nodes)
palette = xgenm.importPalette(xgen_path, [])
palette = xgenm.importPalette(temp_xgen_path, [])
attribute_data = {
"{}.xgFileName".format(palette): xgen_filename
# Get published xgen file name.
template_data = copy.deepcopy(instance.data["anatomyData"])
template_data.update({"ext": "xgen"})
templates = instance.context.data["anatomy"].templates["publish"]
xgen_filename = StringTemplate(templates["file"]).format(template_data)
# Export duplicated palette.
xgen_path = os.path.join(staging_dir, xgen_filename).replace("\\", "/")
xgenm.exportPalette(palette, xgen_path)
representation = {
"name": "xgen",
"ext": "xgen",
"files": xgen_filename,
"stagingDir": staging_dir,
}
instance.data["representations"].append(representation)
# Export Maya file.
type = "mayaAscii" if self.scene_type == "ma" else "mayaBinary"
attribute_data = {
"{}.xgFileName".format(palette): xgen_filename
}
with attribute_values(attribute_data):
with maintained_selection():
cmds.select(duplicate_nodes + [palette])
@ -106,12 +111,13 @@ class ExtractXgenCache(publish.Extractor):
"name": self.scene_type,
"ext": self.scene_type,
"files": maya_filename,
"stagingDir": staging_dir,
"data": {"xgenName": palette}
"stagingDir": staging_dir
}
instance.data["representations"].append(representation)
# Clean up.
cmds.delete(duplicate_nodes + [palette])
os.remove(temp_xgen_path)
# Collect all files under palette root as resources.
data_path = xgenm.getAttr(