Makefile for convenience on *nix systems.
[blender.git] / source / tests / batch_import.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20
21 """
22 Example Usage:
23   blender --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
24 """
25
26 import os
27 import sys
28
29
30 def batch_import(operator="",
31                    path="",
32                    save_path="",
33                    match="",
34                    start=0,
35                    end=sys.maxsize,
36                    ):
37
38     print(list(globals().keys()))
39     import fnmatch
40
41     path = os.path.normpath(path)
42     path = os.path.abspath(path)
43
44     match_upper = match.upper()
45     pattern_match = lambda a: fnmatch.fnmatchcase(a.upper(), match_upper)
46
47     def file_generator(path):
48         for dirpath, dirnames, filenames in os.walk(path):
49
50             # skip '.svn'
51             if dirpath.startswith("."):
52                 continue
53
54             for filename in filenames:
55                 if pattern_match(filename):
56                     yield os.path.join(dirpath, filename)
57
58     print("Collecting %r files in %s" % (match, path), end="")
59
60     files = list(file_generator(path))
61     files_len = len(files)
62     end = min(end, len(files))
63     print(" found %d" % files_len, end="")
64
65     files.sort()
66     files = files[start:end]
67     if len(files) != files_len:
68         print(" using a subset in (%d, %d), total %d" % (start, end, len(files)), end="")
69
70     print("")
71
72     import bpy
73     op = eval(operator)
74     for i, f in enumerate(files):
75         print("    %s(filepath=%r) # %d of %d" % (operator, f, i + start, len(files)))
76         bpy.ops.wm.read_factory_settings()
77
78         op(filepath=f)
79
80         if save_path:
81             fout = os.path.join(save_path, os.path.relpath(f, path))
82             fout_blend = os.path.splitext(fout)[0] + ".blend"
83
84             print("\tSaving: %r" % fout_blend)
85
86             fout_dir = os.path.dirname(fout_blend)
87             if not os.path.exists(fout_dir):
88                 os.makedirs(fout_dir)
89
90             bpy.ops.wm.save_as_mainfile(filepath=fout_blend)
91
92
93 def main():
94     import optparse
95
96     # get the args passed to blender after "--", all of which are ignored by blender specifically
97     # so python may receive its own arguments
98     argv = sys.argv
99
100     if "--" not in argv:
101         argv = []  # as if no args are passed
102     else:
103         argv = argv[argv.index("--") + 1:]  # get all args after "--"
104
105     # When --help or no args are given, print this help
106     usage_text = "Run blender in background mode with this script:"
107     usage_text += "  blender --background --python " + __file__ + " -- [options]"
108
109     parser = optparse.OptionParser(usage=usage_text)
110
111     # Example background utility, add some text and renders or saves it (with options)
112     # Possible types are: string, int, long, choice, float and complex.
113     parser.add_option("-o", "--operator", dest="operator", help="This text will be used to render an image", type="string")
114     parser.add_option("-p", "--path", dest="path", help="Path to use for searching for files", type='string')
115     parser.add_option("-m", "--match", dest="match", help="Wildcard to match filename", type="string")
116     parser.add_option("-s", "--save_path", dest="save_path", help="Save the input file to a blend file in a new location", metavar='string')
117     parser.add_option("-S", "--start", dest="start", help="From collected files, start with this index", metavar='int')
118     parser.add_option("-E", "--end", dest="end", help="From collected files, end with this index", metavar='int')
119
120     options, args = parser.parse_args(argv)  # In this example we wont use the args
121
122     if not argv:
123         parser.print_help()
124         return
125
126     if not options.operator:
127         print("Error: --operator=\"some string\" argument not given, aborting.")
128         parser.print_help()
129         return
130
131     if options.start is None:
132         options.start = 0
133
134     if options.end is None:
135         options.end = sys.maxsize
136
137     # Run the example function
138     batch_import(operator=options.operator,
139                  path=options.path,
140                  save_path=options.save_path,
141                  match=options.match,
142                  start=int(options.start),
143                  end=int(options.end),
144                  )
145
146     print("batch job finished, exiting")
147
148
149 if __name__ == "__main__":
150     main()