use f.area where possible over python function and use len(mface) over len(mface.v)
[blender.git] / release / scripts / flt_filewalker.py
1 #!BPY
2
3 # flt_filewalker.py is an utility module for OpenFlight IO scripts for blender.
4 # Copyright (C) 2005 Greg MacDonald
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19
20 import Blender
21 from struct import *
22 import re
23
24 class FltIn:
25     def begin_record(self):
26         if self.repeat == True:
27             self.repeat = False
28         else:
29             self.position += self.length
30         try:
31             self.file.seek(self.position)
32             input = self.file.read(4)
33         except:
34             print 'Parse Error!'
35             return False
36             
37         if not input:
38             self.close_file()
39             return False
40             
41         self.opcode = unpack('>h', input[:2])[0]
42         self.length = unpack('>H', input[-2:])[0]
43         
44         self.next_position = self.position + self.length
45         
46         return True
47
48     def repeat_record(self):
49         self.repeat = True
50
51     def get_opcode(self):
52         return self.opcode
53
54     def get_level(self):
55         return self.level
56
57     def up_level(self):
58         self.level += 1
59
60     def down_level(self):
61         self.level -= 1
62
63     def read_string(self, length):
64         s = ''
65         if self.file.tell() + length <= self.next_position:
66             start = self.file.tell()
67             for i in range(length):
68                 char = self.file.read(1)
69                 if char == '\x00':
70                     break
71                 s = s + char
72             
73             self.file.seek(start+length)
74 #        else:
75 #            print 'Warning: string truncated'
76
77         return s
78     
79     def read_int(self):
80         if self.file.tell() + 4 <= self.next_position:
81             return unpack('>i', self.file.read(4))[0]
82         else:
83             #print 'Warning: int truncated'
84             return 0
85
86     def read_uint(self):
87         if self.file.tell() + 4 <= self.next_position:
88             return unpack('>I', self.file.read(4))[0]
89         else:
90             #print 'Warning: uint truncated'
91             return 0
92
93     def read_double(self):
94         if self.file.tell() + 8 <= self.next_position:
95             return unpack('>d', self.file.read(8))[0]
96         else:
97             #print 'Warning: double truncated'
98             return 0.0
99
100     def read_float(self):
101         if self.file.tell() + 4 <= self.next_position:
102             return unpack('>f', self.file.read(4))[0]
103         else:
104             #print 'Warning: float truncated'
105             return 0.0
106
107     def read_ushort(self):
108         if self.file.tell() + 2 <= self.next_position:
109             return unpack('>H', self.file.read(2))[0]
110         else:
111             #print 'Warning: ushort truncated'
112             return 0
113
114     def read_short(self):
115         if self.file.tell() + 2 <= self.next_position:
116             return unpack('>h', self.file.read(2))[0]
117         else:
118             #print 'Warning: short trunated'
119             return 0
120
121     def read_uchar(self):
122         if self.file.tell() + 1 <= self.next_position:
123             return unpack('>B', self.file.read(1))[0]
124         else:
125             #print 'Warning: uchar truncated'
126             return 0
127
128     def read_char(self):
129         if self.file.tell() + 1 <= self.next_position:
130             return unpack('>b', self.file.read(1))[0]
131         else:
132             #print 'Warning: char truncated'
133             return 0
134
135     def read_ahead(self, i):
136         if self.file.tell() + i <= self.next_position:
137             self.file.seek(i, 1)
138 #        else:
139 #            print 'Warning: attempt to seek past record'      
140
141     def get_length(self):
142         return self.length
143
144     def close_file(self):
145         self.file.close()
146
147     def __init__(self, filename):
148         self.file = open(filename, 'rb')
149         self.position = 0
150         self.next_position = 100000
151         self.opcode = 0
152         self.length = 0
153         self.level = 0
154         self.repeat = False # Repeat the last record.
155         
156 class FltOut:
157     # Length includes terminating null
158     def write_string(self, string, length):
159         if len(string) > length - 1:
160             str_len = length - 1
161         else:
162             str_len = len(string)
163
164         pad_len = length - str_len
165
166         self.file.write(string[:str_len])
167
168         self.pad(pad_len)
169
170     def write_int(self, a):
171         self.file.write( pack('>i', a) )
172
173     def write_uint(self, a):
174         self.file.write( pack('>I', a) )
175
176     def write_double(self, a):
177         self.file.write( pack('>d', a) )
178
179     def write_float(self, a):
180         self.file.write( pack('>f', a) )
181
182     def write_ushort(self, a):
183         self.file.write( pack('>H', a) )
184
185     def write_short(self, a):
186         self.file.write( pack('>h', a) )
187
188     def write_uchar(self, a):
189         self.file.write( pack('>B', a) )
190
191     def write_char(self, a):
192         self.file.write( pack('>b', a) )
193
194     def pad(self, reps):
195         for i in range(reps):
196             self.file.write('\x00')
197
198     def close_file(self):
199         self.file.close()
200
201     def __init__(self, filename):
202         self.file = open(filename, 'wb')
203
204 class FileFinder:
205     def add_file_to_search_path(self, filename):
206         dir = Blender.sys.dirname(filename)
207         if dir != None and dir != '':
208             self.search_dirs.append(dir)
209
210     def strip_path(self, full_path):
211         # One of my flt files had a windows path with unix seperation. Basename
212         # returned the whole path + filename, which isn't expected. So my
213         # attempt to fix it is to replace all / or \ with the platform specific
214         # dir seperator.
215         #
216         # note: \\\\ is actually just one \ indirected twice, once for python
217         #       then again for re.sub
218         if Blender.sys.sep == '\\':
219             full_path = re.sub('/', '\\\\', full_path)
220         elif Blender.sys.sep == '/':
221             full_path = re.sub('\\\\', '/', full_path)
222             
223         filename = Blender.sys.basename(full_path)
224         return filename
225
226     def find(self, full_path):
227         if full_path == '':
228             return None
229
230         # Seperate out the path.
231         dirname = Blender.sys.dirname(full_path)
232
233         # Try it first.
234         if Blender.sys.exists(full_path):
235             if not dirname in self.search_dirs:
236                 self.search_dirs.append(dirname)
237             return full_path
238
239         # Maybe it's relative.
240         for path in self.search_dirs:
241             rel_full_path = Blender.sys.join(path, full_path)
242             if Blender.sys.exists(rel_full_path):
243                 return rel_full_path
244
245         # Search previous directories that have worked.
246         filename = self.strip_path(full_path)
247         for path in self.search_dirs:
248             t = Blender.sys.join(path, filename)
249             if Blender.sys.exists(t):
250                 return t
251
252         # Ask user where it is.
253         self.user_input = Blender.Draw.PupStrInput(filename + "? ", '', 100)
254         if self.user_input != None:
255             t = Blender.sys.join(self.user_input, filename)
256             if Blender.sys.exists(t):
257                 user_dirname = Blender.sys.dirname(t)
258                 if not user_dirname in self.search_dirs:
259                     self.search_dirs.append(user_dirname)
260                 return t
261
262         # Couldn't find it.
263         return None
264
265     def __init__(self):
266         self.user_input = ''
267         self.current_file = ''
268         self.search_dirs = []
269         
270         dir = Blender.Get('texturesdir')
271         if dir != None and dir != '':
272             self.search_dirs.append(dir)
273         
274         dir = Blender.sys.dirname(Blender.Get('filename'))
275         if dir != None and dir != '':
276             print dir
277             self.search_dirs.append(dir)
278