diff --git a/openpype/hosts/maya/api/fbx.py b/openpype/hosts/maya/api/fbx.py index 260241f5fc..bd0e77e427 100644 --- a/openpype/hosts/maya/api/fbx.py +++ b/openpype/hosts/maya/api/fbx.py @@ -63,6 +63,7 @@ class FBXExtractor: "embeddedTextures": bool, "inputConnections": bool, "upAxis": str, # x, y or z, + "referencedAssetsContent": bool, "triangulate": bool } @@ -104,7 +105,8 @@ class FBXExtractor: "embeddedTextures": False, "inputConnections": True, "upAxis": "y", - "triangulate": False + "referencedAssetsContent": False, + "triangulate": False, } def __init__(self, log=None): diff --git a/openpype/hosts/maya/plugins/create/create_rig.py b/openpype/hosts/maya/plugins/create/create_rig.py index 345ab6c00d..9b67c84980 100644 --- a/openpype/hosts/maya/plugins/create/create_rig.py +++ b/openpype/hosts/maya/plugins/create/create_rig.py @@ -1,6 +1,7 @@ from maya import cmds from openpype.hosts.maya.api import plugin +from openpype.lib import BoolDef class CreateRig(plugin.MayaCreator): @@ -12,6 +13,7 @@ class CreateRig(plugin.MayaCreator): icon = "wheelchair" def create(self, subset_name, instance_data, pre_create_data): + instance_data["fbx_enabled"] = pre_create_data.get("fbx_enabled") instance = super(CreateRig, self).create(subset_name, instance_data, @@ -20,6 +22,24 @@ class CreateRig(plugin.MayaCreator): instance_node = instance.get("instance_node") self.log.info("Creating Rig instance set up ...") + # change name controls = cmds.sets(name=subset_name + "_controls_SET", empty=True) + # change name pointcache = cmds.sets(name=subset_name + "_out_SET", empty=True) - cmds.sets([controls, pointcache], forceElement=instance_node) + if pre_create_data.get("fbx_enabled"): + skeleton = cmds.sets(name=subset_name + "_skeleton_SET", empty=True) + skeleton_mesh = cmds.sets(name=subset_name + "_skeletonMesh_SET", empty=True) + cmds.sets([controls, pointcache, + skeleton, skeleton_mesh], forceElement=instance_node) + else: + cmds.sets([controls, pointcache], forceElement=instance_node) + + def get_pre_create_attr_defs(self): + attrs = super(CreateRig, self).get_pre_create_attr_defs() + + return attrs + [ + BoolDef("fbx_enabled", + label="Fbx Export", + default=False), + + ] diff --git a/openpype/hosts/maya/plugins/publish/collect_rig_for_fbx.py b/openpype/hosts/maya/plugins/publish/collect_rig_for_fbx.py new file mode 100644 index 0000000000..c57045a052 --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/collect_rig_for_fbx.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +from maya import cmds # noqa +import pyblish.api + + +class CollectRigFbx(pyblish.api.InstancePlugin): + """Collect Unreal Skeletal Mesh.""" + + order = pyblish.api.CollectorOrder + 0.2 + label = "Collect rig for fbx" + families = ["rig"] + + def process(self, instance): + if not instance.data.get("fbx_enabled"): + self.log.debug("Skipping collecting rig data for fbx..") + return + + frame = cmds.currentTime(query=True) + instance.data["frameStart"] = frame + instance.data["frameEnd"] = frame + skeleton_sets = [ + i for i in instance[:] + if i.lower().endswith("skeleton_set") + ] + + skeleton_mesh_sets = [ + i for i in instance[:] + if i.lower().endswith("skeletonmesh_set") + ] + if skeleton_sets or skeleton_mesh_sets: + instance.data["families"] += ["fbx"] + instance.data["geometries"] = [] + instance.data["control_rigs"] = [] + instance.data["skeleton_mesh"] = [] + for skeleton_set in skeleton_sets: + skeleton_content = cmds.ls( + cmds.sets(skeleton_set, query=True), long=True) + if skeleton_content: + instance.data["control_rigs"] += skeleton_content + + for skeleton_mesh_set in skeleton_mesh_sets: + skeleton_mesh_content = cmds.ls( + cmds.sets(skeleton_mesh_set, query=True), long=True) + if skeleton_mesh_content: + instance.data["skeleton_mesh"] += skeleton_mesh_content diff --git a/openpype/hosts/maya/plugins/publish/extract_rig_fbx.py b/openpype/hosts/maya/plugins/publish/extract_rig_fbx.py new file mode 100644 index 0000000000..da1a458c9e --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/extract_rig_fbx.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +import os + +from maya import cmds # noqa +import maya.mel as mel # noqa +import pyblish.api + +from openpype.pipeline import publish +from openpype.hosts.maya.api.lib import maintained_selection +from openpype.hosts.maya.api import fbx + + +class ExtractRigFBX(publish.Extractor): + """Extract Rig in FBX format from Maya. + + This extracts the rig in fbx with the constraints + and referenced asset content included. + This also optionally extract animated rig in fbx with + geometries included. + + """ + order = pyblish.api.ExtractorOrder + label = "Extract Rig (FBX)" + families = ["rig"] + + def process(self, instance): + if not instance.data.get("fbx_enabled"): + self.log.debug("fbx extractor has been disable.." + "Skipping the action...") + return + + # Define output path + staging_dir = self.staging_dir(instance) + filename = "{0}.fbx".format(instance.name) + path = os.path.join(staging_dir, filename) + + # The export requires forward slashes because we need + # to format it into a string in a mel expression + path = path.replace('\\', '/') + + self.log.debug("Extracting FBX to: {0}".format(path)) + + control_rigs = instance.data.get("control_rigs",[]) + skeletal_mesh = instance.data.get("skeleton_mesh", []) + members = control_rigs + skeletal_mesh + self._to_extract(instance, path, members) + + + if "representations" not in instance.data: + instance.data["representations"] = [] + + representation = { + 'name': 'fbx', + 'ext': 'fbx', + 'files': filename, + "stagingDir": staging_dir, + } + instance.data["representations"].append(representation) + + self.log.debug("Extract FBX successful to: {0}".format(path)) + if skeletal_mesh: + self._to_extract(instance, path, skeletal_mesh) + representation = { + 'name': 'fbxanim', + 'ext': 'fbx', + 'files': filename, + "stagingDir": staging_dir, + "outputName": "fbxanim" + } + instance.data["representations"].append(representation) + self.log.debug("Extract animated FBX successful to: {0}".format(path)) + + def _to_extract(self, instance, path, members): + fbx_exporter = fbx.FBXExtractor(log=self.log) + control_rigs = instance.data.get("control_rigs",[]) + skeletal_mesh = instance.data.get("skeleton_mesh", []) + static_sets = control_rigs + skeletal_mesh + if members == static_sets: + instance.data["constraints"] = True + instance.data["referencedAssetsContent"] = True + if members == skeletal_mesh: + instance.data["constraints"] = True + instance.data["referencedAssetsContent"] = True + instance.data["animationOnly"] = True + + fbx_exporter.set_options_from_instance(instance) + + # Export + with maintained_selection(): + fbx_exporter.export(members, path) + cmds.select(members, r=1, noExpand=True) + mel.eval('FBXExport -f "{}" -s'.format(path))