From cf3cc7a0a00c140802810d1bef336859bb0bbdf6 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Wed, 18 Aug 2021 17:26:21 +0200 Subject: [PATCH 01/10] add maya ascii xgen export --- openpype/hosts/maya/plugins/create/create_xgen.py | 11 +++++++++++ openpype/hosts/maya/plugins/load/load_reference.py | 3 ++- .../maya/plugins/publish/extract_maya_scene_raw.py | 3 ++- .../hosts/maya/plugins/publish/extract_pointcache.py | 3 ++- openpype/plugins/publish/integrate_new.py | 3 ++- 5 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 openpype/hosts/maya/plugins/create/create_xgen.py diff --git a/openpype/hosts/maya/plugins/create/create_xgen.py b/openpype/hosts/maya/plugins/create/create_xgen.py new file mode 100644 index 00000000000..39539729523 --- /dev/null +++ b/openpype/hosts/maya/plugins/create/create_xgen.py @@ -0,0 +1,11 @@ +from openpype.hosts.maya.api import plugin + + +class CreateXgen(plugin.Creator): + """Xgen interactive export""" + + name = "xgen" + label = "Xgen Interactive" + family = "xgen" + icon = "pagelines" + defaults = ['Main'] diff --git a/openpype/hosts/maya/plugins/load/load_reference.py b/openpype/hosts/maya/plugins/load/load_reference.py index 96269f27714..d5952ed267d 100644 --- a/openpype/hosts/maya/plugins/load/load_reference.py +++ b/openpype/hosts/maya/plugins/load/load_reference.py @@ -17,7 +17,8 @@ class ReferenceLoader(openpype.hosts.maya.api.plugin.ReferenceLoader): "layout", "camera", "rig", - "camerarig"] + "camerarig", + "xgen"] representations = ["ma", "abc", "fbx", "mb"] label = "Reference" diff --git a/openpype/hosts/maya/plugins/publish/extract_maya_scene_raw.py b/openpype/hosts/maya/plugins/publish/extract_maya_scene_raw.py index c85bc0387d0..3c2b70900df 100644 --- a/openpype/hosts/maya/plugins/publish/extract_maya_scene_raw.py +++ b/openpype/hosts/maya/plugins/publish/extract_maya_scene_raw.py @@ -19,7 +19,8 @@ class ExtractMayaSceneRaw(openpype.api.Extractor): families = ["mayaAscii", "setdress", "layout", - "camerarig"] + "camerarig", + "xgen"] scene_type = "ma" def process(self, instance): diff --git a/openpype/hosts/maya/plugins/publish/extract_pointcache.py b/openpype/hosts/maya/plugins/publish/extract_pointcache.py index ba716c0d18e..5595ab001f7 100644 --- a/openpype/hosts/maya/plugins/publish/extract_pointcache.py +++ b/openpype/hosts/maya/plugins/publish/extract_pointcache.py @@ -19,7 +19,8 @@ class ExtractAlembic(openpype.api.Extractor): hosts = ["maya"] families = ["pointcache", "model", - "vrayproxy"] + "vrayproxy", + "xgen"] def process(self, instance): diff --git a/openpype/plugins/publish/integrate_new.py b/openpype/plugins/publish/integrate_new.py index 3504206fe16..67e9f9ca190 100644 --- a/openpype/plugins/publish/integrate_new.py +++ b/openpype/plugins/publish/integrate_new.py @@ -97,7 +97,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "background", "camerarig", "redshiftproxy", - "effect" + "effect", + "xgen" ] exclude_families = ["clip"] db_representation_context_keys = [ From 0aa35cc18b74764d6490340d5f8d13643c55ae77 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Wed, 18 Aug 2021 18:14:42 +0200 Subject: [PATCH 02/10] export grooms to alembic curves --- .../plugins/publish/extract_pointcache.py | 3 +- .../plugins/publish/extract_xgen_cache.py | 69 +++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 openpype/hosts/maya/plugins/publish/extract_xgen_cache.py diff --git a/openpype/hosts/maya/plugins/publish/extract_pointcache.py b/openpype/hosts/maya/plugins/publish/extract_pointcache.py index 5595ab001f7..ba716c0d18e 100644 --- a/openpype/hosts/maya/plugins/publish/extract_pointcache.py +++ b/openpype/hosts/maya/plugins/publish/extract_pointcache.py @@ -19,8 +19,7 @@ class ExtractAlembic(openpype.api.Extractor): hosts = ["maya"] families = ["pointcache", "model", - "vrayproxy", - "xgen"] + "vrayproxy"] def process(self, instance): diff --git a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py new file mode 100644 index 00000000000..a0bfca902cf --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py @@ -0,0 +1,69 @@ +import os + +from maya import cmds + +import avalon.maya +import openpype.api +from openpype.hosts.maya.api.lib import extract_alembic + + +class ExtractXgenCache(openpype.api.Extractor): + """Produce an alembic of just xgen interactive groom + + """ + + label = "Extract Xgen Cache" + hosts = ["maya"] + families = ["xgen"] + + def process(self, instance): + + # Collect the out set nodes + out_descriptions = [node for node in instance if cmds.nodeType(node) == "xgmSplineDescription"] + + self.log.info(out_descriptions) + + out_description = out_descriptions[0] + self.log.info(out_description) + + # Include all descendants + # nodes = roots + cmds.listRelatives(roots, + # allDescendents=True, + # fullPath=True) or [] + + # Collect the start and end including handles + # start = instance.data["frameStart"] + # end = instance.data["frameEnd"] + start = 1 + end = 1 + # handles = instance.data.get("handles", 0) or 0 + # if handles: + # start -= handles + # end += handles + + self.log.info("Extracting Xgen Cache..") + dirname = self.staging_dir(instance) + + parent_dir = self.staging_dir(instance) + filename = "{name}.abc".format(**instance.data) + path = os.path.join(parent_dir, filename) + + with avalon.maya.suspended_refresh(): + with avalon.maya.maintained_selection(): + command = ('-file ' + path + ' -df "ogawa" -fr ' + str(start) + ' ' + str(end) + ' -step 1 -mxf -wfw') + for desc in out_descriptions: + command += (" -obj " + desc) + cmds.xgmSplineCache(export=True, j=command) + + if "representations" not in instance.data: + instance.data["representations"] = [] + + representation = { + 'name': 'abc', + 'ext': 'abc', + 'files': filename, + "stagingDir": dirname, + } + instance.data["representations"].append(representation) + + self.log.info("Extracted {} to {}".format(instance, dirname)) From 07ebf273c13768fe4f4b968e0211a090118d7556 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Wed, 18 Aug 2021 18:21:33 +0200 Subject: [PATCH 03/10] format command --- .../hosts/maya/plugins/publish/extract_xgen_cache.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py index a0bfca902cf..acea7fa382b 100644 --- a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py @@ -50,7 +50,15 @@ def process(self, instance): with avalon.maya.suspended_refresh(): with avalon.maya.maintained_selection(): - command = ('-file ' + path + ' -df "ogawa" -fr ' + str(start) + ' ' + str(end) + ' -step 1 -mxf -wfw') + command = ( + '-file ' + + path + + ' -df "ogawa" -fr ' + + str(start) + + ' ' + + str(end) + + ' -step 1 -mxf -wfw' + ) for desc in out_descriptions: command += (" -obj " + desc) cmds.xgmSplineCache(export=True, j=command) From 3a8fe722f2da2b276137bc58544c9c63e4f45b5b Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Thu, 19 Aug 2021 14:42:00 +0200 Subject: [PATCH 04/10] add simple xgen docs --- website/docs/artist_hosts_maya.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/website/docs/artist_hosts_maya.md b/website/docs/artist_hosts_maya.md index 6fbd59ae1e1..2b31de37ce1 100644 --- a/website/docs/artist_hosts_maya.md +++ b/website/docs/artist_hosts_maya.md @@ -701,6 +701,27 @@ under `input_SET`). This mechanism uses *cbId* attribute on those shapes. If match is found shapes are connected using their `outMesh` and `outMesh`. Thus you can easily connect existing animation to loaded rig. ::: +## Working with Xgen in OpenPype + +OpenPype support publishing and loading of Xgen interactive grooms. You can publish +them as mayaAscii files with scalps that can be loaded into another maya scene, or as +alembic caches. + +### Publishing Xgen Grooms + +To prepare xgen for publishing just select all the descriptions that should be published together and the create Xgen Subset in the scene using - **OpenPype menu** → **Create**... and select **Xgen Interactive**. Leave Use selection checked. + +For actual publishing of your groom to go **OpenPype → Publish** and then press ▶ to publish. This will export `.ma` file containing your grooms with any geometries they are attached to and also a baked cache in `.abc` format + + +### Loading Xgen + +You can use published xgens by loading them using OpenPype Publisher. You can choose to reference or import xgen. We don't have any automatic mesh linking at the moment and it is expected, that groom is published with a scalp, that can then be manually attached to your animated mesh for example. + +The alembic representation can be loaded too and it contains the groom converted to curves. Keep in mind that the density of the alembic directly depends on your viewport xgen density at the point of export. + + + ## Using Redshift Proxies OpenPype supports working with Redshift Proxy files. You can create Redshift Proxy from almost From 4b71f21d6063b344f67b8edca70749a0b217eb32 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Thu, 19 Aug 2021 15:06:13 +0200 Subject: [PATCH 05/10] add tip --- website/docs/artist_hosts_maya.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/website/docs/artist_hosts_maya.md b/website/docs/artist_hosts_maya.md index 2b31de37ce1..6387da4adc9 100644 --- a/website/docs/artist_hosts_maya.md +++ b/website/docs/artist_hosts_maya.md @@ -714,6 +714,11 @@ To prepare xgen for publishing just select all the descriptions that should be p For actual publishing of your groom to go **OpenPype → Publish** and then press ▶ to publish. This will export `.ma` file containing your grooms with any geometries they are attached to and also a baked cache in `.abc` format +:::tip adding more descriptions +You can add multiple xgen desctiption into the subset you are about to publish, simply by +adding them to the maya set that was created for you. Please make sure that only xgen description nodes are present inside of the set and not the scalp geometry. +::: + ### Loading Xgen You can use published xgens by loading them using OpenPype Publisher. You can choose to reference or import xgen. We don't have any automatic mesh linking at the moment and it is expected, that groom is published with a scalp, that can then be manually attached to your animated mesh for example. From d5691b884dc2790c0c566b79805bc4d8dd7eb922 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Thu, 19 Aug 2021 15:10:11 +0200 Subject: [PATCH 06/10] remove trailing whitespace --- .../hosts/maya/plugins/publish/extract_xgen_cache.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py index acea7fa382b..a294920fcb7 100644 --- a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py @@ -51,11 +51,11 @@ def process(self, instance): with avalon.maya.suspended_refresh(): with avalon.maya.maintained_selection(): command = ( - '-file ' - + path - + ' -df "ogawa" -fr ' - + str(start) - + ' ' + '-file ' + + path + + ' -df "ogawa" -fr ' + + str(start) + + ' ' + str(end) + ' -step 1 -mxf -wfw' ) From 66f00827419a454d39ea2e73872c266ac12f5a1c Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Thu, 19 Aug 2021 15:13:55 +0200 Subject: [PATCH 07/10] cleanup --- .../plugins/publish/extract_xgen_cache.py | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py index a294920fcb7..77f1056e8f8 100644 --- a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py @@ -4,7 +4,6 @@ import avalon.maya import openpype.api -from openpype.hosts.maya.api.lib import extract_alembic class ExtractXgenCache(openpype.api.Extractor): @@ -19,27 +18,11 @@ class ExtractXgenCache(openpype.api.Extractor): def process(self, instance): # Collect the out set nodes - out_descriptions = [node for node in instance if cmds.nodeType(node) == "xgmSplineDescription"] + out_descriptions = [(node for node in instance + if cmds.nodeType(node) == "xgmSplineDescription")] - self.log.info(out_descriptions) - - out_description = out_descriptions[0] - self.log.info(out_description) - - # Include all descendants - # nodes = roots + cmds.listRelatives(roots, - # allDescendents=True, - # fullPath=True) or [] - - # Collect the start and end including handles - # start = instance.data["frameStart"] - # end = instance.data["frameEnd"] start = 1 end = 1 - # handles = instance.data.get("handles", 0) or 0 - # if handles: - # start -= handles - # end += handles self.log.info("Extracting Xgen Cache..") dirname = self.staging_dir(instance) From b13c5ed60a69715f624fd8ed422c65f642b6c943 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Thu, 19 Aug 2021 15:29:45 +0200 Subject: [PATCH 08/10] set abc cache export as optional --- openpype/hosts/maya/plugins/publish/extract_xgen_cache.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py index 77f1056e8f8..e0e48476257 100644 --- a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py @@ -11,9 +11,10 @@ class ExtractXgenCache(openpype.api.Extractor): """ - label = "Extract Xgen Cache" + label = "Extract Xgen ABC Cache" hosts = ["maya"] families = ["xgen"] + optional = true def process(self, instance): From a37c85341a03604d78c8209594d58dba6fd71f9f Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Thu, 19 Aug 2021 16:43:21 +0200 Subject: [PATCH 09/10] Update openpype/hosts/maya/plugins/publish/extract_xgen_cache.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Samohel <33513211+antirotor@users.noreply.github.com> --- openpype/hosts/maya/plugins/publish/extract_xgen_cache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py index e0e48476257..b15c9decc28 100644 --- a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py @@ -14,7 +14,7 @@ class ExtractXgenCache(openpype.api.Extractor): label = "Extract Xgen ABC Cache" hosts = ["maya"] families = ["xgen"] - optional = true + optional = True def process(self, instance): From f3d7e02555426d25d53d544651c9730fdbe0ca41 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Thu, 19 Aug 2021 16:43:44 +0200 Subject: [PATCH 10/10] Update openpype/hosts/maya/plugins/publish/extract_xgen_cache.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Samohel <33513211+antirotor@users.noreply.github.com> --- openpype/hosts/maya/plugins/publish/extract_xgen_cache.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py index b15c9decc28..d69911c4040 100644 --- a/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_xgen_cache.py @@ -19,8 +19,8 @@ class ExtractXgenCache(openpype.api.Extractor): def process(self, instance): # Collect the out set nodes - out_descriptions = [(node for node in instance - if cmds.nodeType(node) == "xgmSplineDescription")] + out_descriptions = [node for node in instance + if cmds.nodeType(node) == "xgmSplineDescription"] start = 1 end = 1