This repository has been archived by the owner on Sep 2, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 128
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4376 from moonyuet/feature/OP-4244-Data-Exchange-…
…Cameras
- Loading branch information
Showing
9 changed files
with
388 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# -*- coding: utf-8 -*- | ||
"""Creator plugin for creating camera.""" | ||
from openpype.hosts.max.api import plugin | ||
from openpype.pipeline import CreatedInstance | ||
|
||
|
||
class CreateCamera(plugin.MaxCreator): | ||
identifier = "io.openpype.creators.max.camera" | ||
label = "Camera" | ||
family = "camera" | ||
icon = "gear" | ||
|
||
def create(self, subset_name, instance_data, pre_create_data): | ||
from pymxs import runtime as rt | ||
sel_obj = list(rt.selection) | ||
instance = super(CreateCamera, self).create( | ||
subset_name, | ||
instance_data, | ||
pre_create_data) # type: CreatedInstance | ||
container = rt.getNodeByName(instance.data.get("instance_node")) | ||
# TODO: Disable "Add to Containers?" Panel | ||
# parent the selected cameras into the container | ||
for obj in sel_obj: | ||
obj.parent = container | ||
# for additional work on the node: | ||
# instance_node = rt.getNodeByName(instance.get("instance_node")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import os | ||
from openpype.pipeline import ( | ||
load | ||
) | ||
|
||
|
||
class FbxLoader(load.LoaderPlugin): | ||
"""Fbx Loader""" | ||
|
||
families = ["camera"] | ||
representations = ["fbx"] | ||
order = -9 | ||
icon = "code-fork" | ||
color = "white" | ||
|
||
def load(self, context, name=None, namespace=None, data=None): | ||
from pymxs import runtime as rt | ||
|
||
filepath = os.path.normpath(self.fname) | ||
|
||
fbx_import_cmd = ( | ||
f""" | ||
FBXImporterSetParam "Animation" true | ||
FBXImporterSetParam "Cameras" true | ||
FBXImporterSetParam "AxisConversionMethod" true | ||
FbxExporterSetParam "UpAxis" "Y" | ||
FbxExporterSetParam "Preserveinstances" true | ||
importFile @"{filepath}" #noPrompt using:FBXIMP | ||
""") | ||
|
||
self.log.debug(f"Executing command: {fbx_import_cmd}") | ||
rt.execute(fbx_import_cmd) | ||
|
||
container_name = f"{name}_CON" | ||
|
||
asset = rt.getNodeByName(f"{name}") | ||
# rename the container with "_CON" | ||
container = rt.container(name=container_name) | ||
asset.Parent = container | ||
|
||
return container | ||
|
||
def remove(self, container): | ||
from pymxs import runtime as rt | ||
|
||
node = container["node"] | ||
rt.delete(node) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import os | ||
from openpype.pipeline import ( | ||
load | ||
) | ||
|
||
|
||
class MaxSceneLoader(load.LoaderPlugin): | ||
"""Max Scene Loader""" | ||
|
||
families = ["camera"] | ||
representations = ["max"] | ||
order = -8 | ||
icon = "code-fork" | ||
color = "green" | ||
|
||
def load(self, context, name=None, namespace=None, data=None): | ||
from pymxs import runtime as rt | ||
path = os.path.normpath(self.fname) | ||
# import the max scene by using "merge file" | ||
path = path.replace('\\', '/') | ||
|
||
merge_before = { | ||
c for c in rt.rootNode.Children | ||
if rt.classOf(c) == rt.Container | ||
} | ||
rt.mergeMaxFile(path) | ||
|
||
merge_after = { | ||
c for c in rt.rootNode.Children | ||
if rt.classOf(c) == rt.Container | ||
} | ||
max_containers = merge_after.difference(merge_before) | ||
|
||
if len(max_containers) != 1: | ||
self.log.error("Something failed when loading.") | ||
|
||
max_container = max_containers.pop() | ||
container_name = f"{name}_CON" | ||
# rename the container with "_CON" | ||
# get the original container | ||
container = rt.container(name=container_name) | ||
max_container.Parent = container | ||
|
||
return container | ||
|
||
def remove(self, container): | ||
from pymxs import runtime as rt | ||
|
||
node = container["node"] | ||
rt.delete(node) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import os | ||
import pyblish.api | ||
from openpype.pipeline import ( | ||
publish, | ||
OptionalPyblishPluginMixin | ||
) | ||
from pymxs import runtime as rt | ||
from openpype.hosts.max.api import ( | ||
maintained_selection, | ||
get_all_children | ||
) | ||
|
||
|
||
class ExtractCameraAlembic(publish.Extractor, | ||
OptionalPyblishPluginMixin): | ||
""" | ||
Extract Camera with AlembicExport | ||
""" | ||
|
||
order = pyblish.api.ExtractorOrder - 0.1 | ||
label = "Extract Alembic Camera" | ||
hosts = ["max"] | ||
families = ["camera"] | ||
optional = True | ||
|
||
def process(self, instance): | ||
if not self.is_active(instance.data): | ||
return | ||
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) | ||
filename = "{name}.abc".format(**instance.data) | ||
path = os.path.join(stagingdir, filename) | ||
|
||
# We run the render | ||
self.log.info("Writing alembic '%s' to '%s'" % (filename, | ||
stagingdir)) | ||
|
||
export_cmd = ( | ||
f""" | ||
AlembicExport.ArchiveType = #ogawa | ||
AlembicExport.CoordinateSystem = #maya | ||
AlembicExport.StartFrame = {start} | ||
AlembicExport.EndFrame = {end} | ||
AlembicExport.CustomAttributes = true | ||
exportFile @"{path}" #noPrompt selectedOnly:on using:AlembicExport | ||
""") | ||
|
||
self.log.debug(f"Executing command: {export_cmd}") | ||
|
||
with maintained_selection(): | ||
# select and export | ||
rt.select(get_all_children(rt.getNodeByName(container))) | ||
rt.execute(export_cmd) | ||
|
||
self.log.info("Performing Extraction ...") | ||
if "representations" not in instance.data: | ||
instance.data["representations"] = [] | ||
|
||
representation = { | ||
'name': 'abc', | ||
'ext': 'abc', | ||
'files': filename, | ||
"stagingDir": stagingdir, | ||
} | ||
instance.data["representations"].append(representation) | ||
self.log.info("Extracted instance '%s' to: %s" % (instance.name, | ||
path)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import os | ||
import pyblish.api | ||
from openpype.pipeline import ( | ||
publish, | ||
OptionalPyblishPluginMixin | ||
) | ||
from pymxs import runtime as rt | ||
from openpype.hosts.max.api import ( | ||
maintained_selection, | ||
get_all_children | ||
) | ||
|
||
|
||
class ExtractCameraFbx(publish.Extractor, | ||
OptionalPyblishPluginMixin): | ||
""" | ||
Extract Camera with FbxExporter | ||
""" | ||
|
||
order = pyblish.api.ExtractorOrder - 0.2 | ||
label = "Extract Fbx Camera" | ||
hosts = ["max"] | ||
families = ["camera"] | ||
optional = True | ||
|
||
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)) | ||
|
||
# Need to export: | ||
# Animation = True | ||
# Cameras = True | ||
# AxisConversionMethod | ||
fbx_export_cmd = ( | ||
f""" | ||
FBXExporterSetParam "Animation" true | ||
FBXExporterSetParam "Cameras" true | ||
FBXExporterSetParam "AxisConversionMethod" "Animation" | ||
FbxExporterSetParam "UpAxis" "Y" | ||
FbxExporterSetParam "Preserveinstances" true | ||
exportFile @"{filepath}" #noPrompt selectedOnly:true using:FBXEXP | ||
""") | ||
|
||
self.log.debug(f"Executing command: {fbx_export_cmd}") | ||
|
||
with maintained_selection(): | ||
# select and export | ||
rt.select(get_all_children(rt.getNodeByName(container))) | ||
rt.execute(fbx_export_cmd) | ||
|
||
self.log.info("Performing Extraction ...") | ||
if "representations" not in instance.data: | ||
instance.data["representations"] = [] | ||
|
||
representation = { | ||
'name': 'fbx', | ||
'ext': 'fbx', | ||
'files': filename, | ||
"stagingDir": stagingdir, | ||
} | ||
instance.data["representations"].append(representation) | ||
self.log.info("Extracted instance '%s' to: %s" % (instance.name, | ||
filepath)) |
60 changes: 60 additions & 0 deletions
60
openpype/hosts/max/plugins/publish/extract_max_scene_raw.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import os | ||
import pyblish.api | ||
from openpype.pipeline import ( | ||
publish, | ||
OptionalPyblishPluginMixin | ||
) | ||
from pymxs import runtime as rt | ||
from openpype.hosts.max.api import ( | ||
maintained_selection, | ||
get_all_children | ||
) | ||
|
||
|
||
class ExtractMaxSceneRaw(publish.Extractor, | ||
OptionalPyblishPluginMixin): | ||
""" | ||
Extract Raw Max Scene with SaveSelected | ||
""" | ||
|
||
order = pyblish.api.ExtractorOrder - 0.2 | ||
label = "Extract Max Scene (Raw)" | ||
hosts = ["max"] | ||
families = ["camera"] | ||
optional = True | ||
|
||
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 ...") | ||
|
||
stagingdir = self.staging_dir(instance) | ||
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)) | ||
|
||
if "representations" not in instance.data: | ||
instance.data["representations"] = [] | ||
|
||
# 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') | ||
|
||
self.log.info("Performing Extraction ...") | ||
|
||
representation = { | ||
'name': 'max', | ||
'ext': 'max', | ||
'files': filename, | ||
"stagingDir": stagingdir, | ||
} | ||
instance.data["representations"].append(representation) | ||
self.log.info("Extracted instance '%s' to: %s" % (instance.name, | ||
max_path)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.