Fix crash in outliner on cursor hover
[blender.git] / release / scripts / modules / blend_render_info.py
1 #!/usr/bin/env python3
2
3 # ##### BEGIN GPL LICENSE BLOCK #####
4 #
5 #  This program is free software; you can redistribute it and/or
6 #  modify it under the terms of the GNU General Public License
7 #  as published by the Free Software Foundation; either version 2
8 #  of the License, or (at your option) any later version.
9 #
10 #  This program is distributed in the hope that it will be useful,
11 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #  GNU General Public License for more details.
14 #
15 #  You should have received a copy of the GNU General Public License
16 #  along with this program; if not, write to the Free Software Foundation,
17 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 #
19 # ##### END GPL LICENSE BLOCK #####
20
21 # <pep8 compliant>
22
23 # This module can get render info without running from inside blender.
24 #
25 # This struct won't change according to Ton.
26 # Note that the size differs on 32/64bit
27 #
28 # typedef struct BHead {
29 #     int code, len;
30 #     void *old;
31 #     int SDNAnr, nr;
32 # } BHead;
33
34
35 def read_blend_rend_chunk(path):
36
37     import struct
38
39     blendfile = open(path, "rb")
40
41     head = blendfile.read(7)
42
43     if head[0:2] == b'\x1f\x8b':  # gzip magic
44         import gzip
45         blendfile.seek(0)
46         blendfile = gzip.open(blendfile, "rb")
47         head = blendfile.read(7)
48
49     if head != b'BLENDER':
50         print("not a blend file:", path)
51         blendfile.close()
52         return []
53
54     is_64_bit = (blendfile.read(1) == b'-')
55
56     # true for PPC, false for X86
57     is_big_endian = (blendfile.read(1) == b'V')
58
59     # Now read the bhead chunk!!!
60     blendfile.read(3)  # skip the version
61
62     scenes = []
63
64     sizeof_bhead = 24 if is_64_bit else 20
65
66     while blendfile.read(4) == b'REND':
67         sizeof_bhead_left = sizeof_bhead - 4
68
69         struct.unpack('>i' if is_big_endian else '<i', blendfile.read(4))[0]
70         sizeof_bhead_left -= 4
71
72         # We don't care about the rest of the bhead struct
73         blendfile.read(sizeof_bhead_left)
74
75         # Now we want the scene name, start and end frame. this is 32bites long
76         start_frame, end_frame = struct.unpack('>2i' if is_big_endian else '<2i', blendfile.read(8))
77
78         scene_name = blendfile.read(64)
79
80         scene_name = scene_name[:scene_name.index(b'\0')]
81
82         try:
83             scene_name = str(scene_name, "utf8")
84         except TypeError:
85             pass
86
87         scenes.append((start_frame, end_frame, scene_name))
88
89     blendfile.close()
90
91     return scenes
92
93
94 def main():
95     import sys
96     for arg in sys.argv[1:]:
97         if arg.lower().endswith('.blend'):
98             for value in read_blend_rend_chunk(arg):
99                 print("%d %d %s" % value)
100
101
102 if __name__ == '__main__':
103     main()