source: trunk/game/editor/savers.py @ 317

Revision 317, 6.6 KB checked in by barra_parpg, 10 years ago (diff)

Patch by sirren & mvbarracuda:

  • New player character animations
  • Changed PC object id to player for consistency reasons (agentxmlgen.py uses the folder name for the object id)
  • Renamed parpg-editor >> parpg_editor (use underscores as space characters!)
  • SVL eol-style >> native fixes
  • Property svn:eol-style set to native
Line 
1#!python
2
3# This file is part of PARPG.
4# PARPG is free software: you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# PARPG is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with PARPG.  If not, see <http://www.gnu.org/licenses/>.
16
17import fife
18import loaders
19from serializers import root_subfile
20
21from xml.etree.ElementTree import Element, SubElement, tostring
22
23class Saver(object):
24    """Serialize a FIFE map object to an XML file"""
25
26    def __init__(self, filepath, engine):
27        self.filepath = filepath
28        self.engine = engine
29        self.namespace = ''
30
31    def write_map(self, map, import_list):
32        """Write the specified map to an XML file"""
33
34        self.map = map
35        attrib = {
36            'id': map.getId(),
37            'format': "1.0"
38        }
39        self.map_element = Element('map', attrib)
40
41        # serialize FIFE details
42        self.write_imports(import_list)
43        self.write_layers()
44        self.write_cameras()
45
46        # finally write out the XML file
47        file(self.filepath, 'w').write(
48            """<?xml version="1.0" encoding="ascii"?>%s\n"""
49                % (tostring(self.map_element),))
50
51    def write_imports(self, import_list):
52        """Serialize imports"""
53        map = self.map
54        for import_dir in import_list:
55            self.write_importdir(
56                root_subfile(map.getResourceFile(), import_dir))
57
58        imports = []
59        for layer in map.getLayers():
60            for instance in layer.getInstances():
61                file = instance.getObject().getResourceFile()
62                if (file in imports): continue
63                if self.have_superdir(file, import_list): continue
64                imports.append(file)
65                self.write_import(
66                    root_subfile(map.getResourceFile(), file))
67
68    def have_superdir(self, file, import_list):
69        """Returns true, if file is in directories given in import_list"""
70        for dir in import_list:
71            have = True
72            # TODO use os.path.split here
73            for test in zip(dir.split(os.path.sep), file.split(os.path.sep)):
74                if test[0] != test[1]: have = False
75            if have: return True
76
77        return False
78
79    def write_import(self, filename):
80        """Write an import filename"""
81        self.map_element.append(Element('import', { 'file': filename }))
82
83    def write_import_dir(import_dir):
84        """Write an import dir"""
85        self.map_element.append(Element('import', { 'dir': import_dir }))
86
87    def write_layers(self):
88        """Write a layer"""
89        for layer in self.map.getLayers():
90            cellgrid = layer.getCellGrid()
91            attrib = {
92                'id': layer.getId(),
93                'grid_type': cellgrid.getType(),
94                'x_scale': str(cellgrid.getXScale()),
95                'y_scale': str(cellgrid.getYScale()),
96                'rotation': str(cellgrid.getRotation()),
97                'x_offset': str(cellgrid.getXShift()),
98                'y_offset': str(cellgrid.getYShift()),
99                'pathing': self.pathing_val_to_str(layer.getPathingStrategy()),
100                'transparency': str(layer.getLayerTransparency()),
101            }
102            layer_element = SubElement(self.map_element, 'layer', attrib)
103            self.write_instances(layer_element, layer)
104
105    def write_instances(self, layer_element, layer):
106        """Write out the instances in a layer"""
107        instances_element = SubElement(layer_element, 'instances')
108        for inst in layer.getInstances():
109            position = inst.getLocationRef().getExactLayerCoordinates()
110            attrib = {
111                'o': inst.getObject().getId(),
112                'x': str(position.x),
113                'y': str(position.y),
114                'z': str(position.z),
115                'r': str(inst.getRotation()),
116            }
117            namespace = inst.getObject().getNamespace()
118            if namespace != self.namespace:
119                attrib['ns'] = inst.getObject().getNamespace()
120                self.namespace = namespace
121            inst_id = inst.getId()
122            if inst_id:
123                attrib['id'] = inst_id
124
125            if inst_id is not None and inst_id in loaders.data.objects:
126                for key in loaders.data.objects[inst_id]:
127                    if key not in attrib and loaders.data.objects[inst_id][key]:
128                        print key
129                        attrib[key] = str(loaders.data.objects[inst_id][key])
130                        print key, attrib[key]
131
132            # the local_loader loader sets object_type as type, we have to
133            # correct for that here but really we should fix that there
134            if attrib.get('type'):
135                attrib['object_type'] = attrib['type']
136                del attrib['type']
137
138            instances_element.append(Element('i', attrib))
139
140    def write_cameras(self):
141        """Write out the cameras specified in a map"""
142        cameras = self.engine.getView().getCameras()
143
144        for cam in cameras:
145            if cam.getLocationRef().getMap().getId() != self.map.getId(): continue
146            cell_dimensions = cam.getCellImageDimensions()
147            viewport = cam.getViewPort()
148
149            attrib = {
150                'id': cam.getId(),
151                'zoom': str(cam.getZoom()),
152                'tilt': str(cam.getTilt()),
153                'rotation': str(cam.getRotation()),
154                'ref_layer_id': cam.getLocation().getLayer().getId(),
155                'ref_cell_width': str(cell_dimensions.x),
156                'ref_cell_height': str(cell_dimensions.y),
157            }
158
159            if viewport != self.engine.getRenderBackend().getArea():
160                attrib['viewport'] = '%d,%d,%d,%d' % (viewport.x, viewport.y, viewport.w, viewport.h)
161            self.map_element.append(Element('camera', attrib))
162
163    def pathing_val_to_str(self, val):
164        """Convert a pathing value to a string"""
165        if val == fife.CELL_EDGES_AND_DIAGONALS:
166            return "cell_edges_and_diagonals"
167        if val == fife.FREEFORM:
168            return "freeform"
169        return "cell_edges_only"
170
171def saveMapFile(path, engine, map, **kwargs):
172    """Saves a map"""
173    map.setResourceFile(path) #wtf is this
174    saver = Saver(path, engine)
175    saver.write_map(map, kwargs.get('importList'))
Note: See TracBrowser for help on using the repository browser.