source: trunk/game/local_loaders/xmlmap.py @ 310

Revision 310, 12.9 KB checked in by eliedebrauwer, 10 years ago (diff)

Ticket #66: Patch by saritor (& eliedebrauwer), implements saritors rework of teleporting, at this point it implements the within-a-map teleport successfully, but cross map teleport still has in issue which probably has to do with the setup of the PC. comment[s:trac, t:66]

Line 
1#!/usr/bin/python
2
3#   This program is free software: you can redistribute it and/or modify
4#   it under the terms of the GNU General Public License as published by
5#   the Free Software Foundation, either version 3 of the License, or
6#   (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, see <http://www.gnu.org/licenses/>.
15
16# Most of this code was copied from the FIFE file xmlmap.py
17# It is part of the local code base now so we can customize what happens
18# as we read map files
19
20import fife 
21try:
22    import xml.etree.cElementTree as ET
23except:
24    import xml.etree.ElementTree as ET
25
26import loaders
27from serializers import *
28import time
29
30FORMAT = '1.0'
31
32class XMLMapLoader(fife.ResourceLoader):
33    def __init__(self, engine, data, callback):
34        """ The XMLMapLoader parses the xml map using several section.
35        Each section fires a callback (if given) which can e. g. be
36        used to show a progress bar.
37       
38        The callback sends two values, a string and a float (which shows
39        the overall process): callback(string, float)
40       
41        Inputs:
42            engine = FIFE engine
43            data = Engine object for PARPG data
44            callback = function callback
45        """
46        fife.ResourceLoader.__init__(self)
47        self.thisown = 0
48       
49        self.callback = callback
50
51        self.engine = engine
52        self.data = data
53        self.vfs = self.engine.getVFS()
54        self.model = self.engine.getModel()
55        self.pool = self.engine.getImagePool()
56        self.anim_pool = self.engine.getAnimationPool()
57        self.map = None
58        self.source = None
59        self.time_to_load = 0
60
61        self.nspace = None
62
63    def _err(self, msg):
64        raise SyntaxError(''.join(['File: ', self.source, ' . ', msg]))
65
66    def loadResource(self, location):
67        start_time = time.time()
68        self.source = location.getFilename()
69        f = self.vfs.open(self.source)
70        f.thisown = 1
71        tree = ET.parse(f)
72        root = tree.getroot()
73           
74        map = self.parseMap(root)
75        self.time_to_load = time.time() - start_time
76        return map
77
78    def parseMap(self, map_elt):
79        if not map_elt:
80            self._err('No <map> element found at top level of map file definition.')
81        id,format = map_elt.get('id'),map_elt.get('format')
82
83        if not format == FORMAT: self._err(''.join(['This file has format ', format, ' but this loader has format ', FORMAT]))
84        if not id: self._err('Map declared without an identifier.')
85
86        map = None
87        try:
88            self.map = self.model.createMap(str(id))
89            self.map.setResourceFile(self.source)
90        except fife.Exception, e: # NameClash appears as general fife.Exception; any ideas?
91            print e.getMessage()
92            print ''.join(['File: ', self.source, '. The map ', str(id), ' already exists! Ignoring map definition.'])
93            return None
94
95        # xml-specific directory imports. This is used by xml savers.
96        self.map.importDirs = []
97
98        if self.callback is not None:
99            self.callback('created map', float(0.25) )
100
101        self.parseImports(map_elt, self.map)
102       
103        self.parseLayers(map_elt, self.map)   
104       
105        self.parseCameras(map_elt, self.map)
106
107        return self.map
108
109    def parseImports(self, map_elt, map):
110        parsedImports = {}
111
112        if self.callback:       
113            tmplist = map_elt.findall('import')
114            i = float(0)
115       
116        for item in map_elt.findall('import'):
117            file = item.get('file')
118            if file:
119                file = reverse_root_subfile(self.source, file)
120            dir = item.get('dir')
121            if dir:
122                dir = reverse_root_subfile(self.source, dir)
123
124            # Don't parse duplicate imports
125            if (dir,file) in parsedImports:
126                print "Duplicate import:" ,(dir,file)
127                continue
128            parsedImports[(dir,file)] = 1
129
130            if file and dir:
131                loaders.loadImportFile('/'.join(dir, file), self.engine)
132            elif file:
133                loaders.loadImportFile(file, self.engine)
134            elif dir:
135                loaders.loadImportDirRec(dir, self.engine)
136                map.importDirs.append(dir)
137            else:
138                print 'Empty import statement?'
139               
140            if self.callback:
141                i += 1               
142                self.callback('loaded imports', float( i / float(len(tmplist)) * 0.25 + 0.25 ) )
143
144
145    def parseLayers(self, map_elt, map):
146        if self.callback is not None:       
147            tmplist = map_elt.findall('layer')
148            i = float(0)
149
150        for layer in map_elt.findall('layer'):
151            id = layer.get('id')
152            grid_type = layer.get('grid_type')
153            x_scale = layer.get('x_scale')
154            y_scale = layer.get('y_scale')
155            rotation = layer.get('rotation')
156            x_offset = layer.get('x_offset')
157            y_offset = layer.get('y_offset')
158            pathing = layer.get('pathing')
159
160            if not x_scale: x_scale = 1.0
161            if not y_scale: y_scale = 1.0
162            if not rotation: rotation = 0.0
163            if not x_offset: x_offset = 0.0
164            if not y_offset: y_offset = 0.0
165            if not pathing: pathing = "cell_edges_only"
166
167            if not id: self._err('<layer> declared with no id attribute.')
168            if not grid_type: self._err(''.join(['Layer ', str(id), ' has no grid_type attribute.']))
169
170            allow_diagonals = pathing == "cell_edges_and_diagonals"
171            cellgrid = self.model.getCellGrid(grid_type)
172            if not cellgrid: self._err('<layer> declared with invalid cellgrid type. (%s)' % grid_type)
173
174            cellgrid.setRotation(float(rotation))
175            cellgrid.setXScale(float(x_scale))
176            cellgrid.setYScale(float(y_scale))
177            cellgrid.setXShift(float(x_offset))
178            cellgrid.setYShift(float(y_offset))
179
180            layer_obj = None
181            try:
182                layer_obj = map.createLayer(str(id), cellgrid)
183            except fife.Exception, e:
184                print e.getMessage()
185                print 'The layer ' + str(id) + ' already exists! Ignoring this layer.'
186                continue
187
188            strgy = fife.CELL_EDGES_ONLY
189            if pathing == "cell_edges_and_diagonals":
190                strgy = fife.CELL_EDGES_AND_DIAGONALS
191            if pathing == "freeform":
192                strgy = fife.FREEFORM
193            layer_obj.setPathingStrategy(strgy)
194
195            self.parseInstances(layer, layer_obj)
196
197            if self.callback is not None:
198                i += 1
199                self.callback('loaded layer :' + str(id), float( i / float(len(tmplist)) * 0.25 + 0.5 ) )
200
201        # cleanup
202        if self.callback is not None:
203            del tmplist
204            del i
205
206    def parseInstances(self, layerelt, layer):
207        instelt = layerelt.find('instances')
208
209        instances = instelt.findall('i')
210        instances.extend(instelt.findall('inst'))
211        instances.extend(instelt.findall('instance'))
212        for instance in instances:
213
214            objectID = instance.get('object')
215            if not objectID:
216                objectID = instance.get('obj')
217            if not objectID:
218                objectID = instance.get('o')
219
220            if not objectID: self._err('<instance> does not specify an object attribute.')
221
222            nspace = instance.get('namespace')
223            if not nspace:
224                nspace = instance.get('ns')
225            if not nspace:
226                nspace = self.nspace
227
228            if not nspace: self._err('<instance> %s does not specify an object namespace, and no default is available.' % str(objectID))
229
230            self.nspace = nspace
231
232            object = self.model.getObject(str(objectID), str(nspace))
233            if not object:
234                print ''.join(['Object with id=', str(objectID), ' ns=', str(nspace), ' could not be found. Omitting...'])
235                continue
236
237            x = instance.get('x')
238            y = instance.get('y')
239            z = instance.get('z')
240            stackpos = instance.get('stackpos')
241            id = instance.get('id')
242
243            if x:
244                x = float(x)
245                self.x = x
246            else:
247                self.x = self.x + 1
248                x = self.x
249
250            if y:
251                y = float(y)
252                self.y = y
253            else:
254                y = self.y
255
256            if z:
257                z = float(z)
258            else:
259                z = 0.0
260
261            if not id:
262                id = ''
263            else:
264                id = str(id)
265
266            inst = layer.createInstance(object, fife.ExactModelCoordinate(x,y,z), str(id))
267
268            rotation = instance.get('r')
269            if not rotation:
270                rotation = instance.get('rotation')
271            if not rotation:
272                angles = object.get2dGfxVisual().getStaticImageAngles()
273                if angles:
274                    rotation = angles[0]
275                else:
276                    rotation = 0
277            else:
278                rotation = int(rotation)
279            inst.setRotation(rotation)
280
281            fife.InstanceVisual.create(inst)
282            if (stackpos):
283                inst.get2dGfxVisual().setStackPosition(int(stackpos))
284
285            if (object.getAction('default')):
286                target = fife.Location(layer)
287                inst.act('default', target, True)
288               
289            #Check for PARPG specific object attributes
290            object_type = instance.get('object_type')
291            if ( object_type ):
292                inst_dict = {}
293                inst_dict["type"] = object_type
294                inst_dict["id"] = id
295                inst_dict["xpos"] = x
296                inst_dict["ypos"] = y
297                inst_dict["gfx"] = objectID
298                inst_dict["is_open"] = instance.get('is_open')
299                inst_dict["locked"] = instance.get('locked')
300                inst_dict["name"] = instance.get('name')
301                inst_dict["text"] = instance.get('text')
302                inst_dict["target_map_name"] = instance.get('target_map_name')
303                inst_dict["target_map"] = instance.get('target_map')
304                inst_dict["target_pos"] = (instance.get('target_x'), instance.get('target_y'))
305                self.data.createObject( layer, inst_dict, inst )
306               
307    def parseCameras(self, map_elt, map):
308        if self.callback:       
309            tmplist = map_elt.findall('camera')
310            i = float(0)
311
312        for camera in map_elt.findall('camera'):
313            id = camera.get('id')
314            zoom = camera.get('zoom')
315            tilt = camera.get('tilt')
316            rotation = camera.get('rotation')
317            ref_layer_id = camera.get('ref_layer_id')
318            ref_cell_width = camera.get('ref_cell_width')
319            ref_cell_height = camera.get('ref_cell_height')
320            viewport = camera.get('viewport')
321
322            if not zoom: zoom = 1
323            if not tilt: tilt = 0
324            if not rotation: rotation = 0
325
326            if not id: self._err('Camera declared without an id.')
327            if not ref_layer_id: self._err(''.join(['Camera ', str(id), ' declared with no reference layer.']))
328            if not (ref_cell_width and ref_cell_height): self._err(''.join(['Camera ', str(id), ' declared without reference cell dimensions.']))
329
330            try:
331                if viewport:
332                    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))
333                else:
334                    screen = self.engine.getRenderBackend()
335                    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))
336
337                cam.setCellImageDimensions(int(ref_cell_width), int(ref_cell_height))
338                cam.setRotation(float(rotation))
339                cam.setTilt(float(tilt))
340                cam.setZoom(float(zoom))
341            except fife.Exception, e:
342                print e.getMessage()
343               
344            if self.callback:
345                i += 1
346                self.callback('loaded camera: ' +  str(id), float( i / len(tmplist) * 0.25 + 0.75 ) )   
347           
Note: See TracBrowser for help on using the repository browser.