1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """ submodule for xml map parsing """
24 from __future__ import print_function
25
26 from builtins import str
27 from builtins import object
28 from fife import fife
29
30 from fife.extensions.serializers import ET
31 from fife.extensions.serializers import SerializerError, InvalidFormat
32 from fife.extensions.serializers import NameClash, NotFound, WrongFileType
33 from fife.extensions.serializers.xmlanimation import loadXMLAnimation
34
36 """ The B{XMLObjectSaver} serializes a fife.Object instance by saving
37 it back to its XML file
38
39 @note:
40 - this code does NOT allow the creation of a new xml file
41 - this code does NOT touch atlas or animation definitions
42 - this code does NOT allow saving to non-well-formed xml files
43 - this code DOES save blocking & static flag, as well as
44 image offsets
45
46 @type engine: fife
47 @ivar engine: pointer to initialized fife engine instance
48 @type img_manager: fife.ImageManager
49 @ivar img_manager: pointer to fife image manager
50 @type compat: bool
51 @ivar compat: flag to either use outdated xml definitions or new approach
52 @type debug: bool
53 @ivar debug: flag to activate/deactivate debug output
54 @type vfs: fife.VFS
55 @ivar vfs: pointer to fife vfs
56 @type change: bool
57 @ivar change: flag if object data differs from file data
58 """
59 PROCESSING_INSTRUCTION = '<?fife type="object"?>'
60 - def __init__(self, engine, debug=False, compat=True):
61 """
62
63 @type engine: fife
64 @param engine: intialized fife engine
65 """
66 self.compat = compat
67 self.debug = debug
68 self.engine = engine
69 self.img_manager = engine.getImageManager()
70 self.vfs = self.engine.getVFS()
71 self.change = False
72
73 - def save(self, object):
74 """ saves the data of a fife.Object to its xml file
75
76 @type object: fife.Object
77 @param object: the object which should be saved
78 @rtype bool
79 @return flag whether the saving was successful or not
80 """
81 self.change = False
82 result = False
83
84 file = object.getFilename()
85 if not file:
86 raise SerializerError("Object cannot be saved, no file found %s" % object)
87 return result
88
89 if not self.vfs.exists(file):
90 raise NotFound("File not within vfs: %s" % file)
91 return result
92
93 file_handle = self.vfs.open(file)
94 file_handle.thisown = 1
95 tree = ET.parse(file_handle)
96 root = tree.getroot()
97
98 object_id = object.getId()
99 blocking = object.isBlocking()
100 static = object.isStatic()
101
102 cost_id = object.getCostId()
103 cost = object.getCost()
104 cellstack_pos = object.getCellStackPosition()
105
106 if self.debug:
107 print("XML tree dump: (pre-save)")
108 ET.dump(root)
109 print("Object data: ")
110 print("\tid", object_id)
111 print("\tblocking", blocking)
112 print("\tstatic", static)
113 print("\tcost id", cost_id)
114 print("\tcost", cost)
115
116
117 if root.tag != 'assets':
118 self.compat = True
119
120
121 if self.compat:
122 objects = [root,]
123
124 else:
125 objects = root.findall("object")
126
127 for obj in objects:
128 _id = obj.get("id")
129 if _id != object_id:
130 if self.debug:
131 print("...ommitting object %s " % _id)
132 continue
133
134 if int(obj.attrib['blocking']) != int(blocking):
135 self.change = True
136 if int(obj.attrib['static']) != int(static):
137 self.change = True
138 if str(obj.attrib['cost_id']) != str(cost_id):
139 self.change = True
140 if float(obj.attrib['cost']) != float(cost):
141 self.change = True
142 if int(obj.attrib['cellstack_position']) != int(cellstack_pos):
143 self.change = True
144
145 obj.attrib['blocking'] = str(int(blocking))
146 obj.attrib['static'] = str(int(static))
147 obj.attrib['cost_id'] = str(cost_id)
148 obj.attrib['cost'] = str(cost)
149 obj.attrib['cellstack_position'] = str(cellstack_pos)
150
151 if self.debug and self.change:
152 print("\tSet new data in xml tree: ")
153 print("\t\tblocking: ", obj.attrib['blocking'])
154 print("\t\tstatic: ", obj.attrib['static'])
155
156 images = obj.findall("image")
157 actions = obj.findall("action")
158
159 if self.debug:
160 print("\tAttempting to save image data: ")
161 print("\t...found these image elements: ")
162 print("\t", images)
163 print("object dump: ")
164 print(ET.dump(obj))
165
166 self.save_images(images, object)
167 self.save_actions(actions, object)
168
169 if not self.change:
170 return result
171
172 xmlcontent = ET.tostring(root)
173
174 if self.debug:
175 print("XML tree dump: (post-manipulation)")
176 ET.dump(root)
177
178
179 file = open(file, 'w')
180 file.write(XMLObjectSaver.PROCESSING_INSTRUCTION+'\n')
181 file.write(xmlcontent + "\n")
182 file.close()
183 result = True
184 return result
185
187 """ save action definitions
188
189 @type actions: list
190 @param actions: list of <action> elements
191 @type object: fife.Object
192 @param object: the object which should be saved
193 """
194 for element in actions:
195
196 if 'animation_id' not in element.attrib:
197 break
198
199 animation_id = element.attrib['animation_id']
200 self.save_animation(animation_id, object)
201
203 """ save animation definitions for the given id
204
205 @type animation_id: str
206 @param animation_id: id of the animation data structure
207 @type object: fife.Object
208 @param object: the object which should be saved
209 """
210 pass
211
213 """ save image definitions
214
215 @type images: list
216 @param images: list of <image> elements
217 @type object: fife.Object
218 @param object: the object which should be saved
219 """
220 visual = object.get2dGfxVisual()
221 angles = visual.getStaticImageAngles()
222 if self.debug:
223 print("\t\tobject angles: ", angles)
224
225 for element in images:
226 angle = int(element.get("direction"))
227 if angle not in angles: continue
228
229 index = visual.getStaticImageIndexByAngle(angle)
230 image = self.img_manager.get(index)
231 x_offset = image.getXShift()
232 y_offset = image.getYShift()
233
234 if 'x_offset' not in element.attrib or int(element.attrib['x_offset']) != x_offset:
235 self.change = True
236 if 'y_offset' not in element.attrib or int(element.attrib['y_offset']) != y_offset:
237 self.change = True
238
239 element.attrib['x_offset'] = str(x_offset)
240 element.attrib['y_offset'] = str(y_offset)
241
242 if self.debug and self.change:
243 print("\tSet new data in xml tree: (<image>) ")
244 print("\t\tx offset: ", element.attrib['x_offset'])
245 print("\t\ty offset: ", element.attrib['y_offset'])
246
248 """
249
250 """
252 """
253
254 """
255 self.engine = engine
256 self.imgMgr = engine.getImageManager()
257 self.anim_pool = None
258 self.model = engine.getModel()
259 self.vfs = engine.getVFS()
260 self.source = None
261 self.filename = ''
262
264 """
265
266 """
267 self.source = location
268 self.filename = self.source
269 self.node = None
270 self.file = None
271 if hasattr(location, 'node'):
272 self.node = location.node
273 else:
274 isobjectfile = True
275 f = self.vfs.open(self.filename)
276 f.thisown = 1
277
278 obj_identifier = '<?fife type="object"?>'
279 try:
280 s = f.readString(len(obj_identifier))
281 except fife.IndexOverflow:
282 isobjectfile = False
283
284 if isobjectfile and not s.startswith(obj_identifier):
285 isobjectfile = False
286
287 if not isobjectfile:
288 return
289
290
291
292 raise WrongFileType('Tried to open non-object file %s with XMLObjectLoader.' % self.filename)
293
294 self.do_load_resource(f)
295
297 """
298
299 """
300 if file:
301 tree = ET.parse(file)
302 self.node = tree.getroot()
303 self.parse_object(self.node)
304
306 """
307
308 """
309 if self.node.tag != 'object':
310 raise InvalidFormat('Expected <object> tag, but found <%s>.' % self.node.tag)
311
312 _id = object.get('id')
313 if not _id:
314 raise InvalidFormat('<object> declared without an id attribute.')
315 _id = str(_id)
316
317 nspace = object.get('namespace')
318 if not nspace:
319 raise InvalidFormat('<object> %s declared without a namespace attribute.' % str(_id))
320 nspace = str(nspace)
321
322 obj = None
323 parent = object.get('parent', None)
324 if parent:
325 query = self.metamodel.getObjects('id', str(parent))
326 if len(query) == 0:
327 raise NotFound('No objects found with identifier %s.' % str(parent))
328 elif len(query) > 1:
329 raise NameClash('%d objects found with identifier %s.' % (len(query), str(parent)))
330 parent = query[0]
331
332
333 if not bool(self.model.getObject(_id, nspace)):
334 obj = self.model.createObject(_id, nspace, parent)
335 else:
336 print(NameClash('Tried to create already existing object \n\t...ignoring: %s, %s' % (_id, nspace)))
337 return
338
339 obj.setFilename(self.source)
340 fife.ObjectVisual.create(obj)
341 obj.setBlocking(bool( int(object.get('blocking', False)) ))
342 obj.setStatic(bool( int(object.get('static', False)) ))
343
344 pather = object.get('pather', 'RoutePather')
345 obj.setPather( self.model.getPather(pather) )
346
347 self.parse_images(object, obj)
348 self.parse_actions(object, obj)
349
351 """
352
353 """
354 for image in objelt.findall('image'):
355 source = image.get('source')
356 if not source:
357 raise InvalidFormat('<image> declared without a source attribute.')
358
359
360 path = self.filename.split('/')
361 path.pop()
362 path.append(str(source))
363
364 img = self.imgMgr.create('/'.join(path))
365 img.setXShift(int( image.get('x_offset', 0) ))
366 img.setYShift(int( image.get('y_offset', 0) ))
367
368 object.get2dGfxVisual().addStaticImage(int( image.get('direction', 0) ), img.getHandle())
369
382
401