| 
									
										
										
										
											2011-02-01 12:47:50 +00:00
										 |  |  | # ##### BEGIN GPL LICENSE BLOCK ##### | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | #  This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  | #  modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  | #  as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  | #  of the License, or (at your option) any later version. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | #  This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | #  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | #  GNU General Public License for more details. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | #  You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | #  along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  | #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # ##### END GPL LICENSE BLOCK ##### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # <pep8 compliant> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | Example Usage: | 
					
						
							| 
									
										
										
										
											2011-02-03 11:02:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ./blender.bin --background --python source/tests/batch_import.py -- \ | 
					
						
							|  |  |  |     --operator="bpy.ops.import_scene.obj" \ | 
					
						
							|  |  |  |     --path="/fe/obj" \ | 
					
						
							|  |  |  |     --match="*.obj" \ | 
					
						
							|  |  |  |     --start=0 --end=10 \ | 
					
						
							|  |  |  |     --save_path=/tmp/test | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ./blender.bin --background --python source/tests/batch_import.py -- \ | 
					
						
							|  |  |  |     --operator="bpy.ops.import_scene.autodesk_3ds" \ | 
					
						
							|  |  |  |     --path="/fe/" \ | 
					
						
							|  |  |  |     --match="*.3ds" \ | 
					
						
							|  |  |  |     --start=0 --end=1000 \ | 
					
						
							|  |  |  |     --save_path=/tmp/test | 
					
						
							| 
									
										
										
										
											2011-03-20 06:02:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | ./blender.bin --background --addons io_curve_svg --python source/tests/batch_import.py -- \ | 
					
						
							|  |  |  |     --operator="bpy.ops.import_curve.svg" \ | 
					
						
							|  |  |  |     --path="/usr/" \ | 
					
						
							|  |  |  |     --match="*.svg" \ | 
					
						
							|  |  |  |     --start=0 --end=1000 \ | 
					
						
							|  |  |  |     --save_path=/tmp/test | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-01 12:47:50 +00:00
										 |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-16 02:25:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-03 11:02:02 +00:00
										 |  |  | def clear_scene(): | 
					
						
							|  |  |  |     import bpy | 
					
						
							|  |  |  |     unique_obs = set() | 
					
						
							|  |  |  |     for scene in bpy.data.scenes: | 
					
						
							|  |  |  |         for obj in scene.objects[:]: | 
					
						
							|  |  |  |             scene.objects.unlink(obj) | 
					
						
							|  |  |  |             unique_obs.add(obj) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # remove obdata, for now only worry about the startup scene | 
					
						
							|  |  |  |     for bpy_data_iter in (bpy.data.objects, bpy.data.meshes, bpy.data.lamps, bpy.data.cameras): | 
					
						
							|  |  |  |         for id_data in bpy_data_iter: | 
					
						
							|  |  |  |             bpy_data_iter.remove(id_data) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-01 12:47:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def batch_import(operator="", | 
					
						
							| 
									
										
										
										
											2012-10-08 10:03:01 +00:00
										 |  |  |                  path="", | 
					
						
							|  |  |  |                  save_path="", | 
					
						
							|  |  |  |                  match="", | 
					
						
							|  |  |  |                  start=0, | 
					
						
							|  |  |  |                  end=sys.maxsize, | 
					
						
							|  |  |  |                  ): | 
					
						
							| 
									
										
										
										
											2011-03-20 06:02:47 +00:00
										 |  |  |     import addon_utils | 
					
						
							|  |  |  |     _reset_all = addon_utils.reset_all  # XXX, hack | 
					
						
							| 
									
										
										
										
											2011-02-01 12:47:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     import fnmatch | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     path = os.path.normpath(path) | 
					
						
							|  |  |  |     path = os.path.abspath(path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     match_upper = match.upper() | 
					
						
							|  |  |  |     pattern_match = lambda a: fnmatch.fnmatchcase(a.upper(), match_upper) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def file_generator(path): | 
					
						
							|  |  |  |         for dirpath, dirnames, filenames in os.walk(path): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # skip '.svn' | 
					
						
							|  |  |  |             if dirpath.startswith("."): | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for filename in filenames: | 
					
						
							|  |  |  |                 if pattern_match(filename): | 
					
						
							|  |  |  |                     yield os.path.join(dirpath, filename) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     print("Collecting %r files in %s" % (match, path), end="") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     files = list(file_generator(path)) | 
					
						
							|  |  |  |     files_len = len(files) | 
					
						
							|  |  |  |     end = min(end, len(files)) | 
					
						
							|  |  |  |     print(" found %d" % files_len, end="") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     files.sort() | 
					
						
							|  |  |  |     files = files[start:end] | 
					
						
							|  |  |  |     if len(files) != files_len: | 
					
						
							|  |  |  |         print(" using a subset in (%d, %d), total %d" % (start, end, len(files)), end="") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     import bpy | 
					
						
							|  |  |  |     op = eval(operator) | 
					
						
							| 
									
										
										
										
											2011-03-20 09:38:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     tot_done = 0 | 
					
						
							|  |  |  |     tot_fail = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-01 12:47:50 +00:00
										 |  |  |     for i, f in enumerate(files): | 
					
						
							|  |  |  |         print("    %s(filepath=%r) # %d of %d" % (operator, f, i + start, len(files))) | 
					
						
							| 
									
										
										
										
											2011-03-20 06:02:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-19 03:04:51 +00:00
										 |  |  |         # hack so loading the new file doesn't undo our loaded addons | 
					
						
							| 
									
										
										
										
											2011-03-20 06:02:47 +00:00
										 |  |  |         addon_utils.reset_all = lambda: None  # XXX, hack | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-01 12:47:50 +00:00
										 |  |  |         bpy.ops.wm.read_factory_settings() | 
					
						
							| 
									
										
										
										
											2011-03-20 06:02:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         addon_utils.reset_all = _reset_all  # XXX, hack | 
					
						
							| 
									
										
										
										
											2011-02-03 11:02:02 +00:00
										 |  |  |         clear_scene() | 
					
						
							| 
									
										
										
										
											2011-02-01 12:47:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-20 09:38:25 +00:00
										 |  |  |         result = op(filepath=f) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if 'FINISHED' in result: | 
					
						
							|  |  |  |             tot_done += 1 | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             tot_fail += 1 | 
					
						
							| 
									
										
										
										
											2011-02-01 12:47:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if save_path: | 
					
						
							|  |  |  |             fout = os.path.join(save_path, os.path.relpath(f, path)) | 
					
						
							|  |  |  |             fout_blend = os.path.splitext(fout)[0] + ".blend" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             print("\tSaving: %r" % fout_blend) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             fout_dir = os.path.dirname(fout_blend) | 
					
						
							| 
									
										
										
										
											2013-02-07 04:04:12 +00:00
										 |  |  |             os.makedirs(fout_dir, exist_ok=True) | 
					
						
							| 
									
										
										
										
											2011-02-01 12:47:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             bpy.ops.wm.save_as_mainfile(filepath=fout_blend) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-20 09:38:25 +00:00
										 |  |  |     print("finished, done:%d,  fail:%d" % (tot_done, tot_fail)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-01 12:47:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def main(): | 
					
						
							|  |  |  |     import optparse | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # get the args passed to blender after "--", all of which are ignored by blender specifically | 
					
						
							|  |  |  |     # so python may receive its own arguments | 
					
						
							|  |  |  |     argv = sys.argv | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if "--" not in argv: | 
					
						
							|  |  |  |         argv = []  # as if no args are passed | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         argv = argv[argv.index("--") + 1:]  # get all args after "--" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # When --help or no args are given, print this help | 
					
						
							|  |  |  |     usage_text = "Run blender in background mode with this script:" | 
					
						
							|  |  |  |     usage_text += "  blender --background --python " + __file__ + " -- [options]" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     parser = optparse.OptionParser(usage=usage_text) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Example background utility, add some text and renders or saves it (with options) | 
					
						
							|  |  |  |     # Possible types are: string, int, long, choice, float and complex. | 
					
						
							|  |  |  |     parser.add_option("-o", "--operator", dest="operator", help="This text will be used to render an image", type="string") | 
					
						
							|  |  |  |     parser.add_option("-p", "--path", dest="path", help="Path to use for searching for files", type='string') | 
					
						
							|  |  |  |     parser.add_option("-m", "--match", dest="match", help="Wildcard to match filename", type="string") | 
					
						
							|  |  |  |     parser.add_option("-s", "--save_path", dest="save_path", help="Save the input file to a blend file in a new location", metavar='string') | 
					
						
							|  |  |  |     parser.add_option("-S", "--start", dest="start", help="From collected files, start with this index", metavar='int') | 
					
						
							|  |  |  |     parser.add_option("-E", "--end", dest="end", help="From collected files, end with this index", metavar='int') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     options, args = parser.parse_args(argv)  # In this example we wont use the args | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not argv: | 
					
						
							|  |  |  |         parser.print_help() | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not options.operator: | 
					
						
							|  |  |  |         print("Error: --operator=\"some string\" argument not given, aborting.") | 
					
						
							|  |  |  |         parser.print_help() | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if options.start is None: | 
					
						
							|  |  |  |         options.start = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if options.end is None: | 
					
						
							|  |  |  |         options.end = sys.maxsize | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Run the example function | 
					
						
							|  |  |  |     batch_import(operator=options.operator, | 
					
						
							|  |  |  |                  path=options.path, | 
					
						
							|  |  |  |                  save_path=options.save_path, | 
					
						
							|  |  |  |                  match=options.match, | 
					
						
							|  |  |  |                  start=int(options.start), | 
					
						
							|  |  |  |                  end=int(options.end), | 
					
						
							|  |  |  |                  ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     print("batch job finished, exiting") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     main() |