4
4
5
5
import sgtk
6
6
import os
7
+ import sys
7
8
import unreal
8
9
import datetime
9
10
11
+
12
+ # Local storage path field for known Oses.
13
+ _OS_LOCAL_STORAGE_PATH_FIELD = {
14
+ "darwin" : "mac_path" ,
15
+ "win32" : "windows_path" ,
16
+ "linux" : "linux_path" ,
17
+ "linux2" : "linux_path" ,
18
+ }[sys .platform ]
19
+
20
+
10
21
HookBaseClass = sgtk .get_hook_baseclass ()
11
22
12
23
@@ -70,7 +81,12 @@ def settings(self):
70
81
"description" : "Template path for published work files. Should"
71
82
"correspond to a template defined in "
72
83
"templates.yml." ,
73
- }
84
+ },
85
+ "Publish Folder" : {
86
+ "type" : "string" ,
87
+ "default" : None ,
88
+ "description" : "Optional folder to use as a root for publishes"
89
+ },
74
90
}
75
91
76
92
# update the base settings
@@ -89,6 +105,151 @@ def item_filters(self):
89
105
"""
90
106
return ["unreal.asset.StaticMesh" ]
91
107
108
+ def create_settings_widget (self , parent ):
109
+ """
110
+ Creates a Qt widget, for the supplied parent widget (a container widget
111
+ on the right side of the publish UI).
112
+
113
+ :param parent: The parent to use for the widget being created.
114
+ :returns: A :class:`QtGui.QFrame` that displays editable widgets for
115
+ modifying the plugin's settings.
116
+ """
117
+ # defer Qt-related imports
118
+ from sgtk .platform .qt import QtGui , QtCore
119
+
120
+ # Create a QFrame with all our widgets
121
+ settings_frame = QtGui .QFrame (parent )
122
+ # Create our widgets, we add them as properties on the QFrame so we can
123
+ # retrieve them easily. Qt uses camelCase so our xxxx_xxxx names can't
124
+ # clash with existing Qt properties.
125
+
126
+ # Show this plugin description
127
+ settings_frame .description_label = QtGui .QLabel (self .description )
128
+ settings_frame .description_label .setWordWrap (True )
129
+ settings_frame .description_label .setOpenExternalLinks (True )
130
+ settings_frame .description_label .setTextFormat (QtCore .Qt .RichText )
131
+
132
+ # Unreal setttings
133
+ settings_frame .unreal_publish_folder_label = QtGui .QLabel ("Publish folder:" )
134
+ storage_roots = self .parent .shotgun .find (
135
+ "LocalStorage" ,
136
+ [],
137
+ ["code" , _OS_LOCAL_STORAGE_PATH_FIELD ]
138
+ )
139
+ settings_frame .storage_roots_widget = QtGui .QComboBox ()
140
+ settings_frame .storage_roots_widget .addItem ("Current Unreal Project" )
141
+ for storage_root in storage_roots :
142
+ if storage_root [_OS_LOCAL_STORAGE_PATH_FIELD ]:
143
+ settings_frame .storage_roots_widget .addItem (
144
+ "%s (%s)" % (
145
+ storage_root ["code" ],
146
+ storage_root [_OS_LOCAL_STORAGE_PATH_FIELD ]
147
+ ),
148
+ userData = storage_root ,
149
+ )
150
+ # Create the layout to use within the QFrame
151
+ settings_layout = QtGui .QVBoxLayout ()
152
+ settings_layout .addWidget (settings_frame .description_label )
153
+ settings_layout .addWidget (settings_frame .unreal_publish_folder_label )
154
+ settings_layout .addWidget (settings_frame .storage_roots_widget )
155
+
156
+ settings_layout .addStretch ()
157
+ settings_frame .setLayout (settings_layout )
158
+ return settings_frame
159
+
160
+ def get_ui_settings (self , widget ):
161
+ """
162
+ Method called by the publisher to retrieve setting values from the UI.
163
+
164
+ :returns: A dictionary with setting values.
165
+ """
166
+ # defer Qt-related imports
167
+ from sgtk .platform .qt import QtCore
168
+
169
+ self .logger .info ("Getting settings from UI" )
170
+
171
+ # Please note that we don't have to return all settings here, just the
172
+ # settings which are editable in the UI.
173
+ storage_index = widget .storage_roots_widget .currentIndex ()
174
+ publish_folder = None
175
+ if storage_index > 0 : # Something selected and not the first entry
176
+ storage = widget .storage_roots_widget .itemData (storage_index , role = QtCore .Qt .UserRole )
177
+ publish_folder = storage [_OS_LOCAL_STORAGE_PATH_FIELD ]
178
+
179
+ settings = {
180
+ "Publish Folder" : publish_folder ,
181
+ }
182
+ return settings
183
+
184
+ def set_ui_settings (self , widget , settings ):
185
+ """
186
+ Method called by the publisher to populate the UI with the setting values.
187
+
188
+ :param widget: A QFrame we created in `create_settings_widget`.
189
+ :param settings: A list of dictionaries.
190
+ :raises NotImplementedError: if editing multiple items.
191
+ """
192
+ # defer Qt-related imports
193
+ from sgtk .platform .qt import QtCore
194
+
195
+ self .logger .info ("Setting UI settings" )
196
+ if len (settings ) > 1 :
197
+ # We do not allow editing multiple items
198
+ raise NotImplementedError
199
+ cur_settings = settings [0 ]
200
+ # Note: the template is validated in the accept method, no need to check it here.
201
+ publish_template_setting = cur_settings .get ("Publish Template" )
202
+ publisher = self .parent
203
+ publish_template = publisher .get_template_by_name (publish_template_setting )
204
+ if isinstance (publish_template , sgtk .TemplatePath ):
205
+ widget .unreal_publish_folder_label .setEnabled (False )
206
+ widget .storage_roots_widget .setEnabled (False )
207
+ folder_index = 0
208
+ publish_folder = cur_settings ["Publish Folder" ]
209
+ if publish_folder :
210
+ for i in range (widget .storage_roots_widget .count ()):
211
+ data = widget .storage_roots_widget .itemData (i , role = QtCore .Qt .UserRole )
212
+ if data and data [_OS_LOCAL_STORAGE_PATH_FIELD ] == publish_folder :
213
+ folder_index = i
214
+ break
215
+ self .logger .debug ("Index for %s is %s" % (publish_folder , folder_index ))
216
+ widget .storage_roots_widget .setCurrentIndex (folder_index )
217
+
218
+ def load_saved_ui_settings (self , settings ):
219
+ """
220
+ Load saved settings and update the given settings dictionary with them.
221
+
222
+ :param settings: A dictionary where keys are settings names and
223
+ values Settings instances.
224
+ """
225
+ # Retrieve SG utils framework settings module and instantiate a manager
226
+ fw = self .load_framework ("tk-framework-shotgunutils_v5.x.x" )
227
+ module = fw .import_module ("settings" )
228
+ settings_manager = module .UserSettings (self .parent )
229
+
230
+ # Retrieve saved settings
231
+ settings ["Publish Folder" ].value = settings_manager .retrieve (
232
+ "publish2.publish_folder" ,
233
+ settings ["Publish Folder" ].value ,
234
+ settings_manager .SCOPE_PROJECT
235
+ )
236
+ self .logger .debug ("Loaded settings %s" % settings ["Publish Folder" ])
237
+
238
+ def save_ui_settings (self , settings ):
239
+ """
240
+ Save UI settings.
241
+
242
+ :param settings: A dictionary of Settings instances.
243
+ """
244
+ # Retrieve SG utils framework settings module and instantiate a manager
245
+ fw = self .load_framework ("tk-framework-shotgunutils_v5.x.x" )
246
+ module = fw .import_module ("settings" )
247
+ settings_manager = module .UserSettings (self .parent )
248
+
249
+ # Save settings
250
+ publish_folder = settings ["Publish Folder" ].value
251
+ settings_manager .store ("publish2.publish_folder" , publish_folder , settings_manager .SCOPE_PROJECT )
252
+
92
253
def accept (self , settings , item ):
93
254
"""
94
255
Method called by the publisher to determine if an item is of any
@@ -132,6 +293,7 @@ def accept(self, settings, item):
132
293
# for use in subsequent methods
133
294
item .properties ["publish_template" ] = publish_template
134
295
296
+ self .load_saved_ui_settings (settings )
135
297
return {
136
298
"accepted" : accepted ,
137
299
"checked" : True
@@ -172,10 +334,7 @@ def validate(self, settings, item):
172
334
self .logger .debug ("Asset path or name not configured." )
173
335
return False
174
336
175
- publish_template = item .properties .get ("publish_template" )
176
- if not publish_template :
177
- self .logger .debug ("No publish template configured." )
178
- return False
337
+ publish_template = item .properties ["publish_template" ]
179
338
180
339
# Add the Unreal asset name to the fields
181
340
fields = {"name" : asset_name }
@@ -194,10 +353,22 @@ def validate(self, settings, item):
194
353
# which should be project root + publish template
195
354
publish_path = publish_template .apply_fields (fields )
196
355
publish_path = os .path .normpath (publish_path )
356
+ if not os .path .isabs (publish_path ):
357
+ # If the path is not absolute, prepend the publish folder setting.
358
+ publish_folder = settings ["Publish Folder" ].value
359
+ if not publish_folder :
360
+ publish_folder = unreal .Paths .project_saved_dir ()
361
+ publish_path = os .path .abspath (
362
+ os .path .join (
363
+ publish_folder ,
364
+ publish_path
365
+ )
366
+ )
367
+ item .properties ["publish_path" ] = publish_path
197
368
item .properties ["path" ] = publish_path
198
369
199
- # Remove the filename from the work path
200
- destination_path = os .path .split (publish_path )[ 0 ]
370
+ # Remove the filename from the publish path
371
+ destination_path = os .path .dirname (publish_path )
201
372
202
373
# Stash the destination path in properties
203
374
item .properties ["destination_path" ] = destination_path
@@ -207,7 +378,7 @@ def validate(self, settings, item):
207
378
208
379
# run the base class validation
209
380
# return super(UnrealAssetPublishPlugin, self).validate(settings, item)
210
-
381
+ self . save_ui_settings ( settings )
211
382
return True
212
383
213
384
def publish (self , settings , item ):
0 commit comments