Blender V2.61 - r43446

batch_import.py

Go to the documentation of this file.
00001 # ##### BEGIN GPL LICENSE BLOCK #####
00002 #
00003 #  This program is free software; you can redistribute it and/or
00004 #  modify it under the terms of the GNU General Public License
00005 #  as published by the Free Software Foundation; either version 2
00006 #  of the License, or (at your option) any later version.
00007 #
00008 #  This program is distributed in the hope that it will be useful,
00009 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 #  GNU General Public License for more details.
00012 #
00013 #  You should have received a copy of the GNU General Public License
00014 #  along with this program; if not, write to the Free Software Foundation,
00015 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00016 #
00017 # ##### END GPL LICENSE BLOCK #####
00018 
00019 # <pep8 compliant>
00020 
00021 """
00022 Example Usage:
00023 
00024 ./blender.bin --background --python source/tests/batch_import.py -- \
00025     --operator="bpy.ops.import_scene.obj" \
00026     --path="/fe/obj" \
00027     --match="*.obj" \
00028     --start=0 --end=10 \
00029     --save_path=/tmp/test
00030 
00031 ./blender.bin --background --python source/tests/batch_import.py -- \
00032     --operator="bpy.ops.import_scene.autodesk_3ds" \
00033     --path="/fe/" \
00034     --match="*.3ds" \
00035     --start=0 --end=1000 \
00036     --save_path=/tmp/test
00037 
00038 ./blender.bin --background --addons io_curve_svg --python source/tests/batch_import.py -- \
00039     --operator="bpy.ops.import_curve.svg" \
00040     --path="/usr/" \
00041     --match="*.svg" \
00042     --start=0 --end=1000 \
00043     --save_path=/tmp/test
00044 
00045 """
00046 
00047 import os
00048 import sys
00049 
00050 
00051 def clear_scene():
00052     import bpy
00053     unique_obs = set()
00054     for scene in bpy.data.scenes:
00055         for obj in scene.objects[:]:
00056             scene.objects.unlink(obj)
00057             unique_obs.add(obj)
00058 
00059     # remove obdata, for now only worry about the startup scene
00060     for bpy_data_iter in (bpy.data.objects, bpy.data.meshes, bpy.data.lamps, bpy.data.cameras):
00061         for id_data in bpy_data_iter:
00062             bpy_data_iter.remove(id_data)
00063 
00064 
00065 def batch_import(operator="",
00066                    path="",
00067                    save_path="",
00068                    match="",
00069                    start=0,
00070                    end=sys.maxsize,
00071                    ):
00072     import addon_utils
00073     _reset_all = addon_utils.reset_all  # XXX, hack
00074 
00075     import fnmatch
00076 
00077     path = os.path.normpath(path)
00078     path = os.path.abspath(path)
00079 
00080     match_upper = match.upper()
00081     pattern_match = lambda a: fnmatch.fnmatchcase(a.upper(), match_upper)
00082 
00083     def file_generator(path):
00084         for dirpath, dirnames, filenames in os.walk(path):
00085 
00086             # skip '.svn'
00087             if dirpath.startswith("."):
00088                 continue
00089 
00090             for filename in filenames:
00091                 if pattern_match(filename):
00092                     yield os.path.join(dirpath, filename)
00093 
00094     print("Collecting %r files in %s" % (match, path), end="")
00095 
00096     files = list(file_generator(path))
00097     files_len = len(files)
00098     end = min(end, len(files))
00099     print(" found %d" % files_len, end="")
00100 
00101     files.sort()
00102     files = files[start:end]
00103     if len(files) != files_len:
00104         print(" using a subset in (%d, %d), total %d" % (start, end, len(files)), end="")
00105 
00106     import bpy
00107     op = eval(operator)
00108 
00109     tot_done = 0
00110     tot_fail = 0
00111 
00112     for i, f in enumerate(files):
00113         print("    %s(filepath=%r) # %d of %d" % (operator, f, i + start, len(files)))
00114 
00115         # hack so loading the new file doesnt undo our loaded addons
00116         addon_utils.reset_all = lambda: None  # XXX, hack
00117 
00118         bpy.ops.wm.read_factory_settings()
00119 
00120         addon_utils.reset_all = _reset_all  # XXX, hack
00121         clear_scene()
00122 
00123         result = op(filepath=f)
00124 
00125         if 'FINISHED' in result:
00126             tot_done += 1
00127         else:
00128             tot_fail += 1
00129 
00130         if save_path:
00131             fout = os.path.join(save_path, os.path.relpath(f, path))
00132             fout_blend = os.path.splitext(fout)[0] + ".blend"
00133 
00134             print("\tSaving: %r" % fout_blend)
00135 
00136             fout_dir = os.path.dirname(fout_blend)
00137             if not os.path.exists(fout_dir):
00138                 os.makedirs(fout_dir)
00139 
00140             bpy.ops.wm.save_as_mainfile(filepath=fout_blend)
00141 
00142     print("finished, done:%d,  fail:%d" % (tot_done, tot_fail))
00143 
00144 
00145 def main():
00146     import optparse
00147 
00148     # get the args passed to blender after "--", all of which are ignored by blender specifically
00149     # so python may receive its own arguments
00150     argv = sys.argv
00151 
00152     if "--" not in argv:
00153         argv = []  # as if no args are passed
00154     else:
00155         argv = argv[argv.index("--") + 1:]  # get all args after "--"
00156 
00157     # When --help or no args are given, print this help
00158     usage_text = "Run blender in background mode with this script:"
00159     usage_text += "  blender --background --python " + __file__ + " -- [options]"
00160 
00161     parser = optparse.OptionParser(usage=usage_text)
00162 
00163     # Example background utility, add some text and renders or saves it (with options)
00164     # Possible types are: string, int, long, choice, float and complex.
00165     parser.add_option("-o", "--operator", dest="operator", help="This text will be used to render an image", type="string")
00166     parser.add_option("-p", "--path", dest="path", help="Path to use for searching for files", type='string')
00167     parser.add_option("-m", "--match", dest="match", help="Wildcard to match filename", type="string")
00168     parser.add_option("-s", "--save_path", dest="save_path", help="Save the input file to a blend file in a new location", metavar='string')
00169     parser.add_option("-S", "--start", dest="start", help="From collected files, start with this index", metavar='int')
00170     parser.add_option("-E", "--end", dest="end", help="From collected files, end with this index", metavar='int')
00171 
00172     options, args = parser.parse_args(argv)  # In this example we wont use the args
00173 
00174     if not argv:
00175         parser.print_help()
00176         return
00177 
00178     if not options.operator:
00179         print("Error: --operator=\"some string\" argument not given, aborting.")
00180         parser.print_help()
00181         return
00182 
00183     if options.start is None:
00184         options.start = 0
00185 
00186     if options.end is None:
00187         options.end = sys.maxsize
00188 
00189     # Run the example function
00190     batch_import(operator=options.operator,
00191                  path=options.path,
00192                  save_path=options.save_path,
00193                  match=options.match,
00194                  start=int(options.start),
00195                  end=int(options.end),
00196                  )
00197 
00198     print("batch job finished, exiting")
00199 
00200 
00201 if __name__ == "__main__":
00202     main()