Skip to content

Commit 58adaf9

Browse files
committed
Updating Maya FBX and Turntable publish
Maya FBX publish now works properly with templates, no longer exports to a work location and goes directly to the publish location
1 parent cc2a6df commit 58adaf9

File tree

14 files changed

+294
-225
lines changed

14 files changed

+294
-225
lines changed

core/templates.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -438,13 +438,7 @@ paths:
438438
# The location of published maya files
439439
maya_asset_publish:
440440
definition: '@asset_root/publish/maya/{name}.v{version}.{maya_extension}'
441-
# use maya_asset_work
442-
# maya_scenes: "shotgun/maya_scenes/{name}[.v{version}].mb"
443-
# use maya_asset_publish
444-
# maya_scenes_publish: "shotgun/maya_publish/{name}[.v{version}].mb"
445441
# The location of FBX exports for Unreal
446-
maya_asset_fbx_export:
447-
definition: '@asset_root/work/fbx/{name}.v{version}.fbx'
448442
maya_asset_fbx_publish:
449443
definition: '@asset_root/publish/fbx/{name}.v{version}.fbx'
450444
# The location of turntable review output rendered in Unreal

env/includes/settings/tk-multi-publish2.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,17 @@ settings.tk-multi-publish2.maya.asset_step:
180180
- name: Publish to Shotgun
181181
hook: "{self}/publish_file.py:{config}/tk-multi-publish2/tk-maya/basic/publish_fbx.py"
182182
settings:
183-
Work Template: maya_asset_fbx_export
184183
Publish Template: maya_asset_fbx_publish
185184
- name: Publish and Submit for Review
186185
hook: "{self}/publish_file.py:{config}/tk-multi-publish2/tk-maya/basic/publish_turntable.py"
187186
settings:
188187
Work Template: maya_ue4_turntable_render
189188
Publish Template: maya_ue4_turntable_publish
189+
Unreal Engine Version: "4.20"
190+
Unreal Project Path: "{config}/tk-multi-publish2/tk-maya/unreal/resources/{unreal_engine_version}/turntable/turntable.uproject"
191+
Turntable Map Path: "/Game/turntable/level/turntable.umap"
192+
Sequence Path: "/Game/turntable/sequence/turntable_sequence.turntable_sequence"
193+
Turntable Assets Path: "/Game/maya_turntable_assets/" # note the trailing '/' must be included
190194
help_url: *help_url
191195
location: "@apps.tk-multi-publish2.location"
192196

hooks/tk-multi-publish2/tk-maya/basic/publish_fbx.py

Lines changed: 61 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ def description(self):
3737
contain simple html for formatting.
3838
"""
3939

40-
loader_url = "https://support.shotgunsoftware.com/hc/en-us/articles/219033078"
41-
4240
return """
4341
<p>This plugin exports the Asset for the current session as an FBX file.
4442
The scene will be exported to the path defined by this plugin's configured
@@ -80,19 +78,7 @@ def settings(self):
8078
}
8179
}
8280

83-
work_template_setting = {
84-
"Work Template": {
85-
"type": "template",
86-
"default": None,
87-
"description": "Template path for exported FBX files. Should"
88-
"correspond to a template defined in "
89-
"templates.yml.",
90-
}
91-
}
92-
93-
# update the base settings
9481
base_settings.update(maya_publish_settings)
95-
base_settings.update(work_template_setting)
9682

9783
return base_settings
9884

@@ -133,29 +119,39 @@ def accept(self, settings, item):
133119
:returns: dictionary with boolean keys accepted, required and enabled
134120
"""
135121

136-
# if a publish template is configured, disable context change. This
137-
# is a temporary measure until the publisher handles context switching
138-
# natively.
139-
if settings.get("Publish Template").value:
140-
item.context_change_allowed = False
122+
accepted = True
123+
publisher = self.parent
124+
template_name = settings["Publish Template"].value
141125

142-
path = _session_path()
126+
# ensure a work file template is available on the parent item
127+
work_template = item.parent.properties.get("work_template")
128+
if not work_template:
129+
self.logger.debug(
130+
"A work template is required for the session item in order to "
131+
"publish an FBX file. Not accepting FBX item."
132+
)
133+
accepted = False
143134

144-
if not path:
145-
# the session has not been saved before (no path determined).
146-
# provide a save button. the session will need to be saved before
147-
# validation will succeed.
148-
self.logger.warn(
149-
"The Maya session has not been saved.",
150-
extra=_get_save_as_action()
135+
# ensure the publish template is defined and valid and that we also have
136+
publish_template = publisher.get_template_by_name(template_name)
137+
if not publish_template:
138+
self.logger.debug(
139+
"The valid publish template could not be determined for the "
140+
"FBX item. Not accepting the item."
151141
)
142+
accepted = False
143+
144+
# we've validated the publish template. add it to the item properties
145+
# for use in subsequent methods
146+
item.properties["publish_template"] = publish_template
147+
148+
# because a publish template is configured, disable context change. This
149+
# is a temporary measure until the publisher handles context switching
150+
# natively.
151+
item.context_change_allowed = False
152152

153-
self.logger.info(
154-
"Maya '%s' plugin accepted the current Maya session." %
155-
(self.name,)
156-
)
157153
return {
158-
"accepted": True,
154+
"accepted": accepted,
159155
"checked": True
160156
}
161157

@@ -171,7 +167,6 @@ def validate(self, settings, item):
171167
:returns: True if item is valid, False otherwise.
172168
"""
173169

174-
publisher = self.parent
175170
path = _session_path()
176171

177172
# ---- ensure the session has been saved
@@ -186,90 +181,39 @@ def validate(self, settings, item):
186181
)
187182
raise Exception(error_msg)
188183

189-
# ensure we have an updated project root
190-
project_root = cmds.workspace(q=True, rootDirectory=True)
191-
item.properties["project_root"] = project_root
192-
193-
# log if no project root could be determined.
194-
if not project_root:
195-
self.logger.info(
196-
"Your session is not part of a maya project.",
197-
extra={
198-
"action_button": {
199-
"label": "Set Project",
200-
"tooltip": "Set the maya project",
201-
"callback": lambda: mel.eval('setProject ""')
202-
}
203-
}
204-
)
205-
206-
# ---- check the session against any attached work template
207-
208-
# get the path in a normalized state. no trailing separator,
209-
# separators are appropriate for current os, no double separators,
210-
# etc.
184+
# get the normalized path
211185
path = sgtk.util.ShotgunPath.normalize(path)
212186

213-
# if the session item has a known work template, see if the path
214-
# matches. if not, warn the user and provide a way to save the file to
215-
# a different path
216-
work_template_setting = settings.get("Work Template")
217-
work_template = publisher.get_template_by_name(work_template_setting.value)
218-
if work_template:
219-
item.properties["work_template"] = work_template
220-
self.logger.debug(
221-
"Work template configured as {}.".format(work_template))
222-
else:
223-
self.logger.debug("No work template configured.")
224-
return False
187+
# get the configured work file template
188+
work_template = item.parent.properties.get("work_template")
189+
publish_template = item.properties.get("publish_template")
225190

226-
# ---- see if the version can be bumped post-publish
191+
# get the current scene path and extract fields from it using the work
192+
# template:
193+
work_fields = work_template.get_fields(path)
227194

228-
# check to see if the next version of the work file already exists on
229-
# disk. if so, warn the user and provide the ability to jump to save
230-
# to that version now
231-
(next_version_path, version) = self._get_next_version_info(path, item)
232-
if next_version_path and os.path.exists(next_version_path):
233-
234-
# determine the next available version_number. just keep asking for
235-
# the next one until we get one that doesn't exist.
236-
while os.path.exists(next_version_path):
237-
(next_version_path, version) = self._get_next_version_info(
238-
next_version_path, item)
239-
240-
error_msg = "The next version of this file already exists on disk."
241-
self.logger.error(
242-
error_msg,
243-
extra={
244-
"action_button": {
245-
"label": "Save to v%s" % (version,),
246-
"tooltip": "Save to the next available version number, "
247-
"v%s" % (version,),
248-
"callback": lambda: _save_session(next_version_path)
249-
}
250-
}
251-
)
195+
# ensure the fields work for the publish template
196+
missing_keys = publish_template.missing_keys(work_fields)
197+
if missing_keys:
198+
error_msg = "Work file '%s' missing keys required for the " \
199+
"publish template: %s" % (path, missing_keys)
200+
self.logger.error(error_msg)
252201
raise Exception(error_msg)
253202

254-
# ---- populate the necessary properties and call base class validation
255-
256-
# populate the publish template on the item if found
257-
publish_template_setting = settings.get("Publish Template")
258-
publish_template = publisher.engine.get_template_by_name(
259-
publish_template_setting.value)
260-
if publish_template:
261-
item.properties["publish_template"] = publish_template
262-
else:
263-
self.logger.debug("No published template configured.")
264-
return False
203+
# create the publish path by applying the fields. store it in the item's
204+
# properties. This is the path we'll create and then publish in the base
205+
# publish plugin. Also set the publish_path to be explicit.
206+
item.properties["path"] = publish_template.apply_fields(work_fields)
207+
item.properties["publish_path"] = item.properties["path"]
208+
item.properties["publish_type"] = "Maya FBX"
265209

266-
# set the session path on the item for use by the base plugin validation
267-
# step. NOTE: this path could change prior to the publish phase.
268-
item.properties["path"] = path
210+
# use the work file's version number when publishing
211+
if "version" in work_fields:
212+
item.properties["publish_version"] = work_fields["version"]
269213

270214
# maya_path will be used for version numbering based on the Maya scene file
271-
item.properties["maya_path"] = path
272-
item.properties["publish_type"] = "Maya FBX"
215+
# item.properties["maya_path"] = path
216+
# item.properties["publish_type"] = "Maya FBX"
273217

274218
# run the base class validation
275219
return super(MayaFBXPublishPlugin, self).validate(settings, item)
@@ -284,81 +228,32 @@ def publish(self, settings, item):
284228
:param item: Item to process
285229
"""
286230

287-
# get the path in a normalized state. no trailing separator, separators
288-
# are appropriate for current os, no double separators, etc.
289-
path = sgtk.util.ShotgunPath.normalize(_session_path())
290-
291-
# ensure the session is saved
292-
_save_session(path)
293-
294-
# Derive the work path from the work template
295-
work_path = _get_work_path(path, item.properties["work_template"])
296-
297-
# Remove the filename from the work path
298-
path_components = os.path.split(work_path)
299-
destination_path = path_components[0]
300-
filename = path_components[1]
231+
publisher = self.parent
301232

302-
# Ensure that the destination path exists before rendering the sequence
303-
self.parent.ensure_folder_exists(destination_path)
233+
# get the path to create and publish
234+
publish_path = item.properties["path"]
304235

305-
# Replace file extension with .fbx
306-
fbx_name = os.path.splitext(filename)[0] + ".fbx"
307-
fbx_output_path = os.path.join(destination_path, fbx_name)
236+
# ensure the publish folder exists:
237+
publish_folder = os.path.dirname(publish_path)
238+
self.parent.ensure_folder_exists(publish_folder)
308239

309240
# Export scene to FBX
310241
try:
311-
self.logger.info("Exporting scene to FBX {}".format(fbx_output_path))
242+
self.logger.info("Exporting scene to FBX {}".format(publish_path))
312243
cmds.FBXResetExport()
313244
cmds.FBXExportSmoothingGroups('-v', True)
314245
# Mel script equivalent: mel.eval('FBXExport -f "fbx_output_path"')
315-
cmds.FBXExport('-f', fbx_output_path)
246+
cmds.FBXExport('-f', publish_path)
316247
except:
317248
self.logger.error("Could not export scene to FBX")
318249
return False
319250

320251
# The file to publish is the FBX exported to the FBX output path
321-
item.properties["path"] = fbx_output_path
252+
# item.properties["path"] = fbx_output_path
322253

323254
# let the base class register the publish
324255
super(MayaFBXPublishPlugin, self).publish(settings, item)
325256

326-
def finalize(self, settings, item):
327-
"""
328-
Execute the finalization pass. This pass executes once all the publish
329-
tasks have completed, and can for example be used to version up files.
330-
331-
:param settings: Dictionary of Settings. The keys are strings, matching
332-
the keys returned in the settings property. The values are `Setting`
333-
instances.
334-
:param item: Item to process
335-
"""
336-
337-
# do the base class finalization
338-
super(MayaFBXPublishPlugin, self).finalize(settings, item)
339-
340-
# bump the session file to the next version
341-
self._save_to_next_version(item.properties["maya_path"], item, _save_session)
342-
343-
def _get_work_path(path, work_template):
344-
"""
345-
Return the equivalent work path with the filename from path applied to the work template
346-
:param path: An absulote path with a filename
347-
:param work_template: A template to use to get the work path
348-
:returns a work path:
349-
"""
350-
# Get the filename from the path
351-
filename = os.path.split(path)[1]
352-
353-
# Retrieve the name field from the filename excluding the extension
354-
work_path_fields = {"name" : os.path.splitext(filename)[0]}
355-
356-
# Apply the name to the work template
357-
work_path = work_template.apply_fields(work_path_fields)
358-
work_path = os.path.normpath(work_path)
359-
360-
return work_path
361-
362257
def _session_path():
363258
"""
364259
Return the path to the current session

hooks/tk-multi-publish2/tk-maya/basic/publish_session.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
1-
# Copyright (c) 2017 Shotgun Software Inc.
2-
#
3-
# CONFIDENTIAL AND PROPRIETARY
4-
#
5-
# This work is provided "AS IS" and subject to the Shotgun Pipeline Toolkit
6-
# Source Code License included in this distribution package. See LICENSE.
7-
# By accessing, using, copying or modifying this work you indicate your
8-
# agreement to the Shotgun Pipeline Toolkit Source Code License. All rights
9-
# not expressly granted therein are reserved by Shotgun Software Inc.
1+
# This file is based on templates provided and copyrighted by Autodesk, Inc.
2+
# This file has been modified by Epic Games, Inc. and is subject to the license
3+
# file included in this repository.
104

115
import os
126
import maya.cmds as cmds

0 commit comments

Comments
 (0)