Mercurial > fife-parpg
comparison engine/python/fife/extensions/serializers/xmlmap.py @ 378:64738befdf3b
bringing in the changes from the build_system_rework branch in preparation for the 0.3.0 release. This commit will require the Jan2010 devkit. Clients will also need to be modified to the new way to import fife.
author | vtchill@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Mon, 11 Jan 2010 23:34:52 +0000 |
parents | |
children | 9d94f4676d17 |
comparison
equal
deleted
inserted
replaced
377:fe6fb0e0ed23 | 378:64738befdf3b |
---|---|
1 # -*- coding: utf-8 -*- | |
2 | |
3 # #################################################################### | |
4 # Copyright (C) 2005-2009 by the FIFE team | |
5 # http://www.fifengine.de | |
6 # This file is part of FIFE. | |
7 # | |
8 # FIFE is free software; you can redistribute it and/or | |
9 # modify it under the terms of the GNU Lesser General Public | |
10 # License as published by the Free Software Foundation; either | |
11 # version 2.1 of the License, or (at your option) any later version. | |
12 # | |
13 # This library is distributed in the hope that it will be useful, | |
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 # Lesser General Public License for more details. | |
17 # | |
18 # You should have received a copy of the GNU Lesser General Public | |
19 # License along with this library; if not, write to the | |
20 # Free Software Foundation, Inc., | |
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 # #################################################################### | |
23 | |
24 from fife import fife | |
25 try: | |
26 import xml.etree.cElementTree as ET | |
27 except: | |
28 import xml.etree.ElementTree as ET | |
29 | |
30 from fife.extensions.serializers import * | |
31 | |
32 import time | |
33 | |
34 FORMAT = '1.0' | |
35 | |
36 class XMLMapLoader(fife.ResourceLoader): | |
37 def __init__(self, engine, callback): | |
38 """ The XMLMapLoader parses the xml map using several section. | |
39 Each section fires a callback (if given) which can e. g. be | |
40 used to show a progress bar. | |
41 | |
42 The callback sends two values, a string and a float (which shows | |
43 the overall process): callback(string, float) | |
44 | |
45 @param engine : a pointer to fife.engine | |
46 @param callback: a callback with two arguments, optional | |
47 """ | |
48 fife.ResourceLoader.__init__(self) | |
49 self.thisown = 0 | |
50 | |
51 self.callback = callback | |
52 | |
53 self.engine = engine | |
54 self.vfs = self.engine.getVFS() | |
55 self.model = self.engine.getModel() | |
56 self.pool = self.engine.getImagePool() | |
57 self.anim_pool = self.engine.getAnimationPool() | |
58 self.map = None | |
59 self.source = None | |
60 self.time_to_load = 0 | |
61 | |
62 self.nspace = None | |
63 | |
64 def _err(self, msg): | |
65 raise SyntaxError(''.join(['File: ', self.source, ' . ', msg])) | |
66 | |
67 def loadResource(self, location): | |
68 start_time = time.time() | |
69 self.source = location.getFilename() | |
70 f = self.vfs.open(self.source) | |
71 f.thisown = 1 | |
72 tree = ET.parse(f) | |
73 root = tree.getroot() | |
74 | |
75 map = self.parse_map(root) | |
76 self.time_to_load = time.time() - start_time | |
77 return map | |
78 | |
79 def parse_map(self, mapelt): | |
80 if not mapelt: | |
81 self._err('No <map> element found at top level of map file definition.') | |
82 id,format = mapelt.get('id'),mapelt.get('format') | |
83 | |
84 if not format == FORMAT: self._err(''.join(['This file has format ', format, ' but this loader has format ', FORMAT])) | |
85 if not id: self._err('Map declared without an identifier.') | |
86 | |
87 map = None | |
88 try: | |
89 self.map = self.model.createMap(str(id)) | |
90 self.map.setResourceFile(self.source) | |
91 except fife.Exception, e: # NameClash appears as general fife.Exception; any ideas? | |
92 print e.getMessage() | |
93 print ''.join(['File: ', self.source, '. The map ', str(id), ' already exists! Ignoring map definition.']) | |
94 return None | |
95 | |
96 # xml-specific directory imports. This is used by xml savers. | |
97 self.map.importDirs = [] | |
98 | |
99 if self.callback is not None: | |
100 self.callback('created map', float(0.25) ) | |
101 | |
102 self.parse_imports(mapelt, self.map) | |
103 | |
104 self.parse_layers(mapelt, self.map) | |
105 | |
106 self.parse_cameras(mapelt, self.map) | |
107 | |
108 return self.map | |
109 | |
110 def parse_imports(self, mapelt, map): | |
111 parsedImports = {} | |
112 from fife.extensions import loaders | |
113 if self.callback: | |
114 tmplist = mapelt.findall('import') | |
115 i = float(0) | |
116 | |
117 for item in mapelt.findall('import'): | |
118 file = item.get('file') | |
119 if file: | |
120 file = reverse_root_subfile(self.source, file) | |
121 dir = item.get('dir') | |
122 if dir: | |
123 dir = reverse_root_subfile(self.source, dir) | |
124 | |
125 # Don't parse duplicate imports | |
126 if (dir,file) in parsedImports: | |
127 print "Duplicate import:" ,(dir,file) | |
128 continue | |
129 parsedImports[(dir,file)] = 1 | |
130 | |
131 if file and dir: | |
132 loaders.loadImportFile('/'.join(dir, file), self.engine) | |
133 elif file: | |
134 loaders.loadImportFile(file, self.engine) | |
135 elif dir: | |
136 loaders.loadImportDirRec(dir, self.engine) | |
137 map.importDirs.append(dir) | |
138 else: | |
139 print 'Empty import statement?' | |
140 | |
141 if self.callback: | |
142 i += 1 | |
143 self.callback('loaded imports', float( i / float(len(tmplist)) * 0.25 + 0.25 ) ) | |
144 | |
145 | |
146 def parse_layers(self, mapelt, map): | |
147 if self.callback is not None: | |
148 tmplist = mapelt.findall('layer') | |
149 i = float(0) | |
150 | |
151 for layer in mapelt.findall('layer'): | |
152 id = layer.get('id') | |
153 grid_type = layer.get('grid_type') | |
154 x_scale = layer.get('x_scale') | |
155 y_scale = layer.get('y_scale') | |
156 rotation = layer.get('rotation') | |
157 x_offset = layer.get('x_offset') | |
158 y_offset = layer.get('y_offset') | |
159 pathing = layer.get('pathing') | |
160 transparency = layer.get('transparency') | |
161 | |
162 if not x_scale: x_scale = 1.0 | |
163 if not y_scale: y_scale = 1.0 | |
164 if not rotation: rotation = 0.0 | |
165 if not x_offset: x_offset = 0.0 | |
166 if not y_offset: y_offset = 0.0 | |
167 if not pathing: pathing = "cell_edges_only" | |
168 if not transparency: | |
169 transparency = 0 | |
170 else: | |
171 transparency = int(transparency) | |
172 | |
173 if not id: self._err('<layer> declared with no id attribute.') | |
174 if not grid_type: self._err(''.join(['Layer ', str(id), ' has no grid_type attribute.'])) | |
175 | |
176 cellgrid = self.model.getCellGrid(grid_type) | |
177 if not cellgrid: self._err('<layer> declared with invalid cellgrid type. (%s)' % grid_type) | |
178 | |
179 cellgrid.setRotation(float(rotation)) | |
180 cellgrid.setXScale(float(x_scale)) | |
181 cellgrid.setYScale(float(y_scale)) | |
182 cellgrid.setXShift(float(x_offset)) | |
183 cellgrid.setYShift(float(y_offset)) | |
184 | |
185 layer_obj = None | |
186 try: | |
187 layer_obj = map.createLayer(str(id), cellgrid) | |
188 except fife.Exception, e: | |
189 print e.getMessage() | |
190 print 'The layer ' + str(id) + ' already exists! Ignoring this layer.' | |
191 continue | |
192 | |
193 strgy = fife.CELL_EDGES_ONLY | |
194 if pathing == "cell_edges_and_diagonals": | |
195 strgy = fife.CELL_EDGES_AND_DIAGONALS | |
196 if pathing == "freeform": | |
197 strgy = fife.FREEFORM | |
198 layer_obj.setPathingStrategy(strgy) | |
199 | |
200 layer_obj.setLayerTransparency(transparency) | |
201 | |
202 self.parse_instances(layer, layer_obj) | |
203 | |
204 if self.callback is not None: | |
205 i += 1 | |
206 self.callback('loaded layer :' + str(id), float( i / float(len(tmplist)) * 0.25 + 0.5 ) ) | |
207 | |
208 # cleanup | |
209 if self.callback is not None: | |
210 del tmplist | |
211 del i | |
212 | |
213 def parse_instances(self, layerelt, layer): | |
214 instelt = layerelt.find('instances') | |
215 | |
216 instances = instelt.findall('i') | |
217 instances.extend(instelt.findall('inst')) | |
218 instances.extend(instelt.findall('instance')) | |
219 for instance in instances: | |
220 | |
221 objectID = instance.get('object') | |
222 if not objectID: | |
223 objectID = instance.get('obj') | |
224 if not objectID: | |
225 objectID = instance.get('o') | |
226 | |
227 if not objectID: self._err('<instance> does not specify an object attribute.') | |
228 | |
229 nspace = instance.get('namespace') | |
230 if not nspace: | |
231 nspace = instance.get('ns') | |
232 if not nspace: | |
233 nspace = self.nspace | |
234 | |
235 if not nspace: self._err('<instance> %s does not specify an object namespace, and no default is available.' % str(objectID)) | |
236 | |
237 self.nspace = nspace | |
238 | |
239 object = self.model.getObject(str(objectID), str(nspace)) | |
240 if not object: | |
241 print ''.join(['Object with id=', str(objectID), ' ns=', str(nspace), ' could not be found. Omitting...']) | |
242 continue | |
243 | |
244 x = instance.get('x') | |
245 y = instance.get('y') | |
246 z = instance.get('z') | |
247 stackpos = instance.get('stackpos') | |
248 id = instance.get('id') | |
249 | |
250 if x: | |
251 x = float(x) | |
252 self.x = x | |
253 else: | |
254 self.x = self.x + 1 | |
255 x = self.x | |
256 | |
257 if y: | |
258 y = float(y) | |
259 self.y = y | |
260 else: | |
261 y = self.y | |
262 | |
263 if z: | |
264 z = float(z) | |
265 else: | |
266 z = 0.0 | |
267 | |
268 if not id: | |
269 id = '' | |
270 else: | |
271 id = str(id) | |
272 | |
273 inst = layer.createInstance(object, fife.ExactModelCoordinate(x,y,z), str(id)) | |
274 | |
275 rotation = instance.get('r') | |
276 if not rotation: | |
277 rotation = instance.get('rotation') | |
278 if not rotation: | |
279 angles = object.get2dGfxVisual().getStaticImageAngles() | |
280 if angles: | |
281 rotation = angles[0] | |
282 else: | |
283 rotation = 0 | |
284 else: | |
285 rotation = int(rotation) | |
286 inst.setRotation(rotation) | |
287 | |
288 fife.InstanceVisual.create(inst) | |
289 if (stackpos): | |
290 inst.get2dGfxVisual().setStackPosition(int(stackpos)) | |
291 | |
292 if (object.getAction('default')): | |
293 target = fife.Location(layer) | |
294 inst.act('default', target, True) | |
295 | |
296 def parse_cameras(self, mapelt, map): | |
297 if self.callback: | |
298 tmplist = mapelt.findall('camera') | |
299 i = float(0) | |
300 | |
301 for camera in mapelt.findall('camera'): | |
302 id = camera.get('id') | |
303 zoom = camera.get('zoom') | |
304 tilt = camera.get('tilt') | |
305 rotation = camera.get('rotation') | |
306 ref_layer_id = camera.get('ref_layer_id') | |
307 ref_cell_width = camera.get('ref_cell_width') | |
308 ref_cell_height = camera.get('ref_cell_height') | |
309 viewport = camera.get('viewport') | |
310 | |
311 if not zoom: zoom = 1 | |
312 if not tilt: tilt = 0 | |
313 if not rotation: rotation = 0 | |
314 | |
315 if not id: self._err('Camera declared without an id.') | |
316 if not ref_layer_id: self._err(''.join(['Camera ', str(id), ' declared with no reference layer.'])) | |
317 if not (ref_cell_width and ref_cell_height): self._err(''.join(['Camera ', str(id), ' declared without reference cell dimensions.'])) | |
318 | |
319 try: | |
320 if viewport: | |
321 cam = self.engine.getView().addCamera(str(id), map.getLayer(str(ref_layer_id)),fife.Rect(*[int(c) for c in viewport.split(',')]),fife.ExactModelCoordinate(0,0,0)) | |
322 else: | |
323 screen = self.engine.getRenderBackend() | |
324 cam = self.engine.getView().addCamera(str(id), map.getLayer(str(ref_layer_id)),fife.Rect(0,0,screen.getScreenWidth(),screen.getScreenHeight()),fife.ExactModelCoordinate(0,0,0)) | |
325 | |
326 cam.setCellImageDimensions(int(ref_cell_width), int(ref_cell_height)) | |
327 cam.setRotation(float(rotation)) | |
328 cam.setTilt(float(tilt)) | |
329 cam.setZoom(float(zoom)) | |
330 except fife.Exception, e: | |
331 print e.getMessage() | |
332 | |
333 if self.callback: | |
334 i += 1 | |
335 self.callback('loaded camera: ' + str(id), float( i / len(tmplist) * 0.25 + 0.75 ) ) | |
336 |