Editor now changes the map
[erdslangetjie.git] / erdslangetjie / editor / editor.py
1 import sys
2 import os
3
4 from erdslangetjie.constants import TILE_SIZE
5
6 from kivy.app import App
7 from kivy.uix.widget import Widget
8 from kivy.uix.floatlayout import FloatLayout
9 from kivy.graphics import Color, Rectangle
10 from kivy.uix.label import Label
11 from kivy.utils import platform
12 from kivy.config import Config
13
14 from erdslangetjie.data import filepath, load
15 from erdslangetjie.level import (Level, WALL, GATE, BUTTON,
16         FLOOR, ENTRY, EXIT)
17
18
19 if platform() != 'android':
20     Config.set('graphics', 'width', '1326')
21     Config.set('graphics', 'height', '760')
22
23
24 tool_map = {
25         'button': BUTTON,
26         'gate': GATE,
27         'wall': WALL,
28         'floor': FLOOR,
29         'add entry': ENTRY,
30         'add exit': EXIT
31         }
32
33
34 class EditorWindow(FloatLayout):
35
36     def __init__(self, level):
37         super(EditorWindow, self).__init__(size=(1326, 760))
38         if os.path.exists(filepath(level)):
39             level_data = load(level)
40             self.level = level
41         elif os.path.exists(filepath('levels/' + level)):
42             level_data = load('levels/' + level)
43             self.level = 'levels/' + level
44         else:
45             print 'Unable to find %s - treating this as a new level' % level
46             level_data = load('levels/blank.txt')
47             if 'levels/' in level:
48                 self.level = level
49             else:
50                 self.level = 'levels/' + level
51         self.level_obj = Level(level_data)
52         level_data.close()
53         self.level_obj.load_tiles()
54
55         self.tool = None
56         self.tool_widgets = []
57
58     def build(self):
59         self.clear_widgets()
60         tiles = self.level_obj.get_tiles()
61         bx, by = 0, 0
62         self.nodes = {}
63         for tile_line in tiles:
64             bx = 0
65             for tile in tile_line:
66                 self._draw_tile((bx, by), tile)
67                 bx += TILE_SIZE
68             by += TILE_SIZE
69
70         name = Label(text="Level: [color=00ffcc]%s[/color]" % self.level,
71                 markup=True, font_size=24, pos=(500, 360))
72         self.add_widget(name)
73
74         self.draw_toolbar()
75         self.draw_save_button()
76
77     def _draw_tile(self, tile_pos, tile):
78         node = Widget(size=(TILE_SIZE, TILE_SIZE), pos=tile_pos)
79         node.bind(on_touch_down=self.change_node)
80         node.bind(on_touch_move=self.change_node)
81         with node.canvas:
82             Color(1, 1, 1)
83             Rectangle(pos=node.pos, size=node.size, texture=tile.texture)
84         self.add_widget(node)
85         self.nodes[tile_pos] = node
86
87     def draw_toolbar(self):
88         for widget in self.tool_widgets:
89             widget.unbind(on_ref_press=self.change_tool)
90             self.remove_widget(widget)
91         self.tool_widgets = []
92         y = 300
93         for tool in sorted(tool_map):
94             if self.tool == tool:
95                 color = '00cccc'
96             else:
97                 color = 'cccccc'
98             tool_label = Label(text='[color=%s][ref=%s]%s[/ref][/color]' %
99                     (color, tool, tool), markup=True, font_size=24,
100                     pos=(500, y))
101             y -= 50
102             tool_label.bind(on_ref_press=self.change_tool)
103             self.add_widget(tool_label)
104             self.tool_widgets.append(tool_label)
105
106     def draw_save_button(self):
107         save_label = Label(text='[color=ffffff][ref=save]Save[/ref][/color]',
108                 markup=True, font_size=24, pos=(500, -100))
109         save_label.bind(on_ref_press=self.do_save)
110         self.add_widget(save_label)
111
112     def do_save(self, label, ref):
113         pass
114
115     def change_tool(self, label, ref):
116         self.tool = ref
117         self.draw_toolbar()
118
119     def contained(self, node, pos):
120         if pos[0] < node.pos[0] or pos[0] > node.pos[0] + TILE_SIZE:
121             return False
122         if pos[1] < node.pos[1] or pos[1] > node.pos[1] + TILE_SIZE:
123             return False
124         return True
125
126     def change_node(self, node, touch):
127         if self.tool and self.contained(node, touch.pos):
128             tile_pos = (node.pos[0] / TILE_SIZE, node.pos[1] / TILE_SIZE)
129             action = tool_map[self.tool]
130             if self.level_obj.get_tile_type(tile_pos) != action:
131                 self.level_obj.set_tile_type(tile_pos, action)
132                 for map_pos, new_tile in self.level_obj.get_changed_tiles():
133                     node_pos = (map_pos[0] * TILE_SIZE, map_pos[1] * TILE_SIZE)
134                     old_node = self.nodes[node_pos]
135                     self.remove_widget(old_node)
136                     self._draw_tile(node_pos, new_tile)
137
138
139 class EditorApp(App):
140
141     def __init__(self, level):
142         self.level = level
143         super(EditorApp, self).__init__()
144
145     def build(self):
146         editor = EditorWindow(self.level)
147         editor.build()
148         return editor
149
150
151 def main():
152     if len(sys.argv) > 1:
153         level = sys.argv[1]
154     else:
155         level = 'level1.txt'
156     EditorApp(level).run()
157
158
159 if __name__ == '__main__':
160     main()