1+
12# ***** BEGIN GPL LICENSE BLOCK *****
23#
34#
2122bl_info = {
2223 "name" : "Spritify" ,
2324 "author" : "Jason van Gumster (Fweeb)" ,
24- "version" : (0 , 6 , 1 ),
25- "blender" : (2 , 66 , 0 ),
25+ "version" : (0 , 6 , 3 ),
26+ "blender" : (2 , 80 , 0 ),
2627 "location" : "Render > Spritify" ,
2728 "description" : "Converts rendered frames into a sprite sheet once render is complete" ,
2829 "warning" : "Requires ImageMagick" ,
3132 "category" : "Render" }
3233
3334
34- import bpy , os , subprocess
35+ import bpy , os , subprocess , math
3536from bpy .app .handlers import persistent
3637
3738
3839class SpriteSheetProperties (bpy .types .PropertyGroup ):
39- filepath = bpy .props .StringProperty (
40+ filepath : bpy .props .StringProperty (
4041 name = "Sprite Sheet Filepath" ,
4142 description = "Save location for sprite sheet (should be PNG format)" ,
4243 subtype = 'FILE_PATH' ,
43- default = os .path .join (bpy .context .user_preferences .filepaths .render_output_directory , "sprites.png" ))
44- quality = bpy .props .IntProperty (
44+ default = os .path .join (bpy .context .preferences .filepaths .render_output_directory , "sprites.png" ))
45+ quality : bpy .props .IntProperty (
4546 name = "Quality" ,
4647 description = "Quality setting for sprite sheet image" ,
4748 subtype = 'PERCENTAGE' ,
4849 max = 100 ,
4950 default = 100 )
50- is_rows = bpy .props .EnumProperty (
51+ is_rows : bpy .props .EnumProperty (
5152 name = "Rows/Columns" ,
5253 description = "Choose if tiles will be arranged by rows or columns" ,
5354 items = (('ROWS' , "Rows" , "Rows" ), ('COLUMNS' , "Columns" , "Columns" )),
5455 default = 'ROWS' )
55- tiles = bpy .props .IntProperty (
56+ tiles : bpy .props .IntProperty (
5657 name = "Tiles" ,
5758 description = "Number of tiles in the chosen direction (rows or columns)" ,
5859 default = 8 )
59- offset_x = bpy .props .IntProperty (
60+ files : bpy .props .IntProperty (
61+ name = "File count" ,
62+ description = "Number of files to split sheet into" ,
63+ default = 1 )
64+ offset_x : bpy .props .IntProperty (
6065 name = "Offset X" ,
6166 description = "Horizontal offset between tiles (in pixels)" ,
6267 default = 2 )
63- offset_y = bpy .props .IntProperty (
68+ offset_y : bpy .props .IntProperty (
6469 name = "Offset Y" ,
6570 description = "Vertical offset between tiles (in pixels)" ,
6671 default = 2 )
67- bg_color = bpy .props .FloatVectorProperty (
72+ bg_color : bpy .props .FloatVectorProperty (
6873 name = "Background Color" ,
6974 description = "Fill color for sprite backgrounds" ,
7075 subtype = 'COLOR' ,
7176 size = 4 ,
7277 min = 0.0 ,
7378 max = 1.0 ,
7479 default = (0.0 , 0.0 , 0.0 , 0.0 ))
75- auto_sprite = bpy .props .BoolProperty (
80+ auto_sprite : bpy .props .BoolProperty (
7681 name = "AutoSpritify" ,
7782 description = "Automatically create a spritesheet when rendering is complete" ,
7883 default = True )
79- auto_gif = bpy .props .BoolProperty (
84+ auto_gif : bpy .props .BoolProperty (
8085 name = "AutoGIF" ,
8186 description = "Automatically create an animated GIF when rendering is complete" ,
8287 default = True )
@@ -95,36 +100,60 @@ def find_bin_path_windows():
95100
96101 except WindowsError :
97102 return None
98-
103+
104+ print (value )
99105 return value
100106
101107
102108@persistent
103109def spritify (scene ):
104- if scene .spritesheet .auto_sprite == True :
105- print ("Making sprite sheet" )
106- # Remove existing spritesheet if it's already there
107- if os .path .exists (bpy .path .abspath (scene .spritesheet .filepath )):
108- os .remove (bpy .path .abspath (scene .spritesheet .filepath ))
109-
110- if scene .spritesheet .is_rows == 'ROWS' :
111- tile_setting = str (scene .spritesheet .tiles ) + "x"
112- else :
113- tile_setting = "x" + str (scene .spritesheet .tiles )
114-
115- subprocess .call ([
116- "montage" ,
117- bpy .path .abspath (scene .render .filepath ) + "*" , #XXX Assumes the files in the render path are only for the rendered animation
118- "-tile" , tile_setting ,
119- "-geometry" , str (scene .render .resolution_x ) + "x" + str (scene .render .resolution_y ) \
120- + "+" + str (scene .spritesheet .offset_x ) + "+" + str (scene .spritesheet .offset_y ),
121- "-background" , "rgba(" + \
122- str (scene .spritesheet .bg_color [0 ] * 100 ) + "%, " + \
123- str (scene .spritesheet .bg_color [1 ] * 100 ) + "%, " + \
124- str (scene .spritesheet .bg_color [2 ] * 100 ) + "%, " + \
125- str (scene .spritesheet .bg_color [3 ]) + ")" ,
126- "-quality" , str (scene .spritesheet .quality ),
127- bpy .path .abspath (scene .spritesheet .filepath )])
110+ if scene .spritesheet .auto_sprite == True :
111+ print ("Making sprite sheet" )
112+ # Remove existing spritesheet if it's already there
113+ if os .path .exists (bpy .path .abspath (scene .spritesheet .filepath )):
114+ os .remove (bpy .path .abspath (scene .spritesheet .filepath ))
115+
116+ if scene .spritesheet .is_rows == 'ROWS' :
117+ tile_setting = str (scene .spritesheet .tiles ) + "x"
118+ else :
119+ tile_setting = "x" + str (scene .spritesheet .tiles )
120+
121+ # Preload images
122+ images = []
123+ for dirname , dirnames , filenames in os .walk (bpy .path .abspath (scene .render .filepath )):
124+ for filename in filenames :
125+ images .append (os .path .join (dirname , filename ))
126+
127+ # Calc number of images per file
128+ per_file = math .ceil (len (images ) / scene .spritesheet .files )
129+ offset = 0
130+ index = 0
131+
132+ #While is faster than for+range
133+ while offset < len (images ):
134+ current_images = images [offset :offset + per_file ]
135+ filename = scene .spritesheet .filepath
136+ if scene .spritesheet .files > 1 :
137+ filename = scene .spritesheet .filepath [:- 4 ] + "-" + str (index ) + scene .spritesheet .filepath [- 4 :]
138+
139+ montage_call = [
140+ "montage" ,
141+ "-tile" , tile_setting ,
142+ "-geometry" , str (scene .render .resolution_x ) + "x" + str (scene .render .resolution_y ) \
143+ + "+" + str (scene .spritesheet .offset_x ) + "+" + str (scene .spritesheet .offset_y ),
144+ "-background" , "rgba(" + \
145+ str (scene .spritesheet .bg_color [0 ] * 100 ) + "%, " + \
146+ str (scene .spritesheet .bg_color [1 ] * 100 ) + "%, " + \
147+ str (scene .spritesheet .bg_color [2 ] * 100 ) + "%, " + \
148+ str (scene .spritesheet .bg_color [3 ]) + ")" ,
149+ "-quality" , str (scene .spritesheet .quality )
150+ ]
151+ montage_call .extend (current_images )
152+ montage_call .append (bpy .path .abspath (filename ))
153+
154+ subprocess .call (montage_call )
155+ offset += per_file
156+ index += 1
128157
129158
130159@persistent
@@ -142,7 +171,7 @@ def gifify(scene):
142171
143172 if bin_path :
144173 convert_path = os .path .join (bin_path , "convert" )
145-
174+
146175 subprocess .call ([
147176 convert_path ,
148177 "-delay" , "1x" + str (scene .render .fps ),
@@ -215,28 +244,28 @@ def draw(self, context):
215244
216245 layout .prop (context .scene .spritesheet , "filepath" )
217246 box = layout .box ()
218- split = box .split (percentage = 0.5 )
247+ split = box .split (factor = 0.5 )
219248 col = split .column ()
220249 col .operator ("render.spritify" , text = "Generate Sprite Sheet" )
221250 col = split .column ()
222251 col .prop (context .scene .spritesheet , "auto_sprite" )
223- split = box .split (percentage = 0.5 )
252+ split = box .split (factor = 0.5 )
224253 col = split .column (align = True )
225254 col .row ().prop (context .scene .spritesheet , "is_rows" , expand = True )
226255 col .prop (context .scene .spritesheet , "tiles" )
227- sub = col .split (percentage = 0.5 )
256+ sub = col .split (factor = 0.5 )
228257 sub .prop (context .scene .spritesheet , "offset_x" )
229258 sub .prop (context .scene .spritesheet , "offset_y" )
230259 col = split .column ()
231260 col .prop (context .scene .spritesheet , "bg_color" )
232261 col .prop (context .scene .spritesheet , "quality" , slider = True )
233262 box = layout .box ()
234- split = box .split (percentage = 0.5 )
263+ split = box .split (factor = 0.5 )
235264 col = split .column ()
236265 col .operator ("render.gifify" , text = "Generate Animated GIF" )
237266 col = split .column ()
238267 col .prop (context .scene .spritesheet , "auto_gif" )
239- box .label ("Animated GIF uses the spritesheet filepath" )
268+ box .label (text = "Animated GIF uses the spritesheet filepath" )
240269
241270
242271
0 commit comments