-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexport_locations.py
312 lines (222 loc) · 10.2 KB
/
export_locations.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
import bpy, os, platform
from bpy.types import Menu, Panel, Operator, UIList
from bpy.props import EnumProperty
class PAK_OT_AddPath(Operator):
"""Create a new Export Location"""
bl_idname = "scene.pak_addpath"
bl_label = "Add"
def execute(self, context):
try:
addon_prefs = context.preferences.addons[__package__].preferences
file_data = bpy.data.objects[addon_prefs.pak_filedata_name].PAK_FileData
except:
return {'CANCELLED'}
new_path = file_data.locations.add()
new_path.name = "Location " + str(len(file_data.locations))
new_path.path = ""
return {'FINISHED'}
class PAK_OT_DeletePath(Operator):
"""
Delete the selected export location from the list. This will
also set the export location of all textures that used this to 'None'
"""
bl_idname = "scene.pak_deletepath"
bl_label = "Remove"
def execute(self, context):
try:
addon_prefs = context.preferences.addons[__package__].preferences
file_data = bpy.data.objects[addon_prefs.pak_filedata_name].PAK_FileData
except:
return {'CANCELLED'}
sel_index = file_data.locations_list_index
# Ensure that any objects with a matching preset are set to None.
# The index needs increasing by one as it doesnt include 'None'
images = bpy.data.images
for img in images:
if img.PAK_Img.export_location == str(sel_index + 1):
img.PAK_Img.export_location = '0'
# TODO: Ensure the selection interface is updated so it gets the new value!
# TODO: Ensure this is as efficient as it can be for large scenes
# Once everything has been set, remove it.
file_data.locations.remove(sel_index)
# ensure the selected list index is within the list bounds
if len(file_data.locations) > 0 and sel_index != 0:
file_data.locations_list_index -= 1
return {'FINISHED'}
class PAK_OT_AddExportLocTag(Operator):
"""Add a new export location tag to the currently selected location. These are used to auto-name file structures with information about the export like file name, time, etc"""
bl_idname = "scene.pak_add_export_loc_tag"
bl_label = "Add Export Location Tag"
path_tags: EnumProperty(
name = "Add Path Tag",
description = "",
items = (
('bundle_name', 'Bundle Name', 'Adds a folder with the name of the image bundle being exported (NOTE - The bundle must have more than one image)'),
('blend_file_name', 'Blend File Name', 'Adds a folder with the blend file name.'),
('export_date_ymd', 'Export Date (Year-Month-Day)', 'Adds a folder with the date of the export.'),
('export_date_dmy', 'Export Date (Day-Month-Year)', 'Adds a folder with the date of the export.'),
('export_date_mdy', 'Export Date (Month-Year-Day)', 'Adds a folder with the date of the export.'),
('export_time_hm', 'Export Time (Hour-Minute)', 'Adds a folder with the time of the export.'),
('export_time_hms', 'Export Time (Hour-Minute-Second)', 'Adds a folder with the time of the export.'),
),
)
def execute(self, context):
try:
addon_prefs = context.preferences.addons[__package__].preferences
file_data = bpy.data.objects[addon_prefs.pak_filedata_name].PAK_FileData
except:
return {'CANCELLED'}
# get the selected path
path_index = file_data.locations_list_index
new_path = file_data.locations[path_index].path
end_path = ""
# directory failsafe
if platform.system() == 'Windows':
if new_path.endswith("\\") == False and new_path.endswith("//") == False:
new_path += "\\"
end_path = "\\"
else:
if new_path.endswith("/") == False:
new_path += "/"
end_path = "\\"
# insert the selected option into the currently selected path
new_path += "^"
new_path += self.path_tags
new_path += "^" + end_path
file_data.locations[path_index].path = new_path
return {'FINISHED'}
class PAK_UL_ExportLocationList(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
layout.prop(item, "name", text="", emboss=False)
class PAK_PT_Location(Panel):
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
bl_label = "Export Locations"
bl_parent_id = "PROPERTIES_PT_Pak"
bl_order = 2
def draw(self, context):
preferences = context.preferences
addon_prefs = preferences.addons[__package__].preferences
layout = self.layout
try:
file_data = bpy.data.objects[addon_prefs.pak_filedata_name].PAK_FileData
except KeyError:
return
location_list = layout.row(align= True)
location_list.template_list("PAK_UL_ExportLocationList", "default", file_data,
"locations", file_data, "locations_list_index",
rows = 3, maxrows = 6)
location_list.separator()
location_ops = location_list.column(align= True)
location_ops.operator("scene.pak_addpath", text= "", icon = "ADD")
location_ops.operator("scene.pak_deletepath", text= "", icon = "REMOVE")
location_info = layout.column(align = False)
location_info.use_property_split = True
location_info.use_property_decorate = False
location_info.separator()
count = 0
for i, item in enumerate(file_data.locations, 1):
count += 1
if file_data.locations_list_index > -1 and file_data.locations_list_index < count:
location_info.prop(file_data.locations[file_data.locations_list_index], "path")
# location_info.separator()
location_info.operator_menu_enum("scene.pak_add_export_loc_tag", "path_tags")
def CreateFilePath(file_path, replace_invalid_chars = True):
"""
Extracts and calculates a final path with which to export the target to.
"""
if file_path == "":
raise Exception('WARNING: This location preset has no path defined, please define it!')
elif file_path.find('//') != -1:
file_path = bpy.path.abspath(file_path)
# If Windows, split the drive indicator
drive_indicator = ""
if platform.system() == 'Windows':
drive_index = file_path.find("\\")
if drive_index != -1:
drive_split = file_path.split("\\", 1)
drive_indicator = drive_split[0]
file_path = drive_split[1]
# directory failsafe
if platform.system() == 'Windows':
if file_path.endswith("\\") == False:
file_path += "\\"
else:
if file_path.endswith("/") == False:
file_path += "/"
if replace_invalid_chars is True:
file_path = SubstitutePathCharacters(file_path)
# Windows drive indicator re-stitch
if drive_indicator != "":
file_path = drive_indicator + "\\" + file_path
# Build the file path
if not os.path.exists(file_path):
os.makedirs(file_path)
return file_path
def SubstituteNameCharacters(path):
# Replaces invalid directory characters in names
result = path
if platform.system() == 'Windows':
invalid_characters = ["\\", "/", "*", "?", "\"", "<", ">", "|", ":"]
for char in invalid_characters:
result = result.replace(char, "_")
elif platform.system() == 'Darwin':
invalid_characters = [":", "/"]
for char in invalid_characters:
result = result.replace(char, "_")
elif platform.system() == 'linux' or platform.system() == 'linux2':
invalid_characters = [":", "/"]
for char in invalid_characters:
result = result.replace(char, "_")
return result
def SubstitutePathCharacters(path):
# Replaces invalid directory characters in full export paths
result = path
if platform.system() == 'Windows':
invalid_characters = ["*", "?", "<", ">", "|", ":"]
for char in invalid_characters:
result = result.replace(char, "_")
elif platform.system() == 'Darwin':
invalid_characters = [":"]
for char in invalid_characters:
result = result.replace(char, "_")
elif platform.system() == 'linux' or platform.system() == 'linux2':
invalid_characters = [":"]
for char in invalid_characters:
result = result.replace(char, "_")
return result
def ReplacePathTags(file_path, replace_invalid_chars, bundle, export_time):
"""
Searches for and substitutes the tags in a path name. USE THIS AFTER CreateFilePath().
"""
if file_path.find('^bundle_name^'):
bundle_name = ""
if len(bundle.pak_items) > 0:
bundle_name = bundle.name
if replace_invalid_chars is True:
bundle_name = SubstituteNameCharacters(bundle_name)
file_path = file_path.replace('^bundle_name^', bundle_name)
if file_path.find('^blend_file_name^'):
blend_name = bpy.path.basename(bpy.context.blend_data.filepath)
blend_name = blend_name.replace(".blend", "")
if replace_invalid_chars is True:
blend_name = SubstituteNameCharacters(blend_name)
file_path = file_path.replace('^blend_file_name^', blend_name)
# DATE AND TIME
if file_path.find('export_date_ymd'):
time = export_time.strftime('%Y-%m-%d')
file_path = file_path.replace('^export_date_ymd^', time)
if file_path.find('export_date_dmy'):
time = export_time.strftime('%d-%m-%Y')
file_path = file_path.replace('^export_date_dmy^', time)
if file_path.find('export_date_mdy'):
time = export_time.strftime('%m-%d-%Y')
file_path = file_path.replace('^export_date_mdy^', time)
if file_path.find('export_time_hm'):
time = export_time.strftime('%H.%M')
file_path = file_path.replace('^export_time_hm^', time)
if file_path.find('export_time_hms'):
time = export_time.strftime('%H.%M.%S')
file_path = file_path.replace('^export_time_hms^', time)
return file_path