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