Refactor
[erdslangetjie.git] / erdslangetjie / editor / editor.py
index c2d2745559801cada06ce3fe2f042c4edfbf9ca9..ef08b813e01f7c2d30c4dccbda827ba2bbe21df1 100644 (file)
@@ -1,23 +1,41 @@
 import sys
 import os
 import sys
 import os
-import kivy
 
 
-kivy.require('1.6.0')
+from erdslangetjie.constants import TILE_SIZE
 
 from kivy.app import App
 
 from kivy.app import App
-from kivy.logger import Logger, LoggerHistory
 from kivy.uix.widget import Widget
 from kivy.uix.floatlayout import FloatLayout
 from kivy.graphics import Color, Rectangle
 from kivy.uix.widget import Widget
 from kivy.uix.floatlayout import FloatLayout
 from kivy.graphics import Color, Rectangle
+from kivy.uix.label import Label
+from kivy.uix.popup import Popup
+from kivy.utils import platform
+from kivy.config import Config
 
 from erdslangetjie.data import filepath, load
 
 from erdslangetjie.data import filepath, load
-from erdslangetjie.level import Level
+from erdslangetjie.level import (Level, WALL, GATE, BUTTON,
+        FLOOR, ENTRY, EXIT)
+
+
+if platform() != 'android':
+    Config.set('graphics', 'width', '1326')
+    Config.set('graphics', 'height', '760')
+
+
+tool_map = {
+        'button': BUTTON,
+        'gate': GATE,
+        'wall': WALL,
+        'floor': FLOOR,
+        'add entry': ENTRY,
+        'add exit': EXIT
+        }
 
 
 class EditorWindow(FloatLayout):
 
     def __init__(self, level):
 
 
 class EditorWindow(FloatLayout):
 
     def __init__(self, level):
-        super(EditorWindow, self).__init__(size=(960, 960))
+        super(EditorWindow, self).__init__(size=(1326, 760))
         if os.path.exists(filepath(level)):
             level_data = load(level)
             self.level = level
         if os.path.exists(filepath(level)):
             level_data = load(level)
             self.level = level
@@ -31,26 +49,109 @@ class EditorWindow(FloatLayout):
                 self.level = level
             else:
                 self.level = 'levels/' + level
                 self.level = level
             else:
                 self.level = 'levels/' + level
-        self.level_obj = Level()
-        self.level_obj.load(level_data)
+        self.level_obj = Level(level_data)
         level_data.close()
         level_data.close()
+        self.level_obj.load_tiles()
+
+        self.tool = None
+        self.tool_widgets = []
 
     def build(self):
         self.clear_widgets()
         tiles = self.level_obj.get_tiles()
 
     def build(self):
         self.clear_widgets()
         tiles = self.level_obj.get_tiles()
-        tile_size = 24
         bx, by = 0, 0
         bx, by = 0, 0
+        self.nodes = {}
         for tile_line in tiles:
             bx = 0
             for tile in tile_line:
         for tile_line in tiles:
             bx = 0
             for tile in tile_line:
-                node = Widget(size=(tile_size, tile_size), pos=(bx, by))
-                with node.canvas:
-                    Color(1, 1, 1)
-                    Rectangle(pos=node.pos, size=node.size,
-                            texture=tile.texture)
-                self.add_widget(node)
-                bx += tile_size
-            by += tile_size
+                self._draw_tile((bx, by), tile)
+                bx += TILE_SIZE
+            by += TILE_SIZE
+
+        name = Label(text="Level: [color=00ffcc]%s[/color]" % self.level,
+                markup=True, font_size=24, pos=(500, 360))
+        self.add_widget(name)
+
+        self.draw_toolbar()
+        self.draw_save_button()
+
+    def _draw_tile(self, tile_pos, tile):
+        if tile_pos in self.nodes:
+            self.remove_widget(self.nodes[tile_pos])
+        node = Widget(size=(TILE_SIZE, TILE_SIZE), pos=tile_pos)
+        node.bind(on_touch_down=self.change_node)
+        node.bind(on_touch_move=self.change_node)
+        with node.canvas:
+            Color(1, 1, 1)
+            Rectangle(pos=node.pos, size=node.size, texture=tile.texture)
+        self.add_widget(node)
+        self.nodes[tile_pos] = node
+
+    def draw_toolbar(self):
+        for widget in self.tool_widgets:
+            widget.unbind(on_ref_press=self.change_tool)
+            self.remove_widget(widget)
+        self.tool_widgets = []
+        y = 300
+        for tool in sorted(tool_map):
+            if self.tool == tool:
+                color = '00cccc'
+            else:
+                color = 'cccccc'
+            tool_label = Label(text='[color=%s][ref=%s]%s[/ref][/color]' %
+                    (color, tool, tool), markup=True, font_size=24,
+                    pos=(500, y))
+            y -= 50
+            tool_label.bind(on_ref_press=self.change_tool)
+            self.add_widget(tool_label)
+            self.tool_widgets.append(tool_label)
+
+    def draw_save_button(self):
+        save_label = Label(text='[color=ffffff][ref=save]Save[/ref][/color]',
+                markup=True, font_size=24, pos=(500, -100))
+        save_label.bind(on_ref_press=self.do_save)
+        self.add_widget(save_label)
+
+    def do_save(self, label, ref):
+        try:
+            self.level_obj.validate()
+        except RuntimeError as err:
+            print err
+            popup = Popup(title='Error',
+                    content=Label(text='Level not valid: %s' % err),
+                    size_hint=(.5, .5))
+            popup.open()
+            return
+        save_data = self.level_obj.get_level_data()
+        savefile = file(filepath(self.level), 'w')
+        savefile.write(save_data)
+        savefile.write('\n')
+        savefile.close()
+        popup = Popup(title='Success',
+                content=Label(text='Level saved to %s' % self.level),
+                size_hint=(.5, .5))
+        popup.open()
+
+    def change_tool(self, label, ref):
+        self.tool = ref
+        self.draw_toolbar()
+
+    def contained(self, node, pos):
+        if pos[0] < node.pos[0] or pos[0] > node.pos[0] + TILE_SIZE:
+            return False
+        if pos[1] < node.pos[1] or pos[1] > node.pos[1] + TILE_SIZE:
+            return False
+        return True
+
+    def change_node(self, node, touch):
+        if self.tool and self.contained(node, touch.pos):
+            tile_pos = (node.pos[0] / TILE_SIZE, node.pos[1] / TILE_SIZE)
+            action = tool_map[self.tool]
+            if self.level_obj.get_tile_type(tile_pos) != action:
+                self.level_obj.set_tile_type(tile_pos, action)
+                for map_pos, new_tile in self.level_obj.get_changed_tiles():
+                    node_pos = (map_pos[0] * TILE_SIZE, map_pos[1] * TILE_SIZE)
+                    self._draw_tile(node_pos, new_tile)
 
 
 class EditorApp(App):
 
 
 class EditorApp(App):
@@ -70,10 +171,6 @@ def main():
         level = sys.argv[1]
     else:
         level = 'level1.txt'
         level = sys.argv[1]
     else:
         level = 'level1.txt'
-    # Uncomment to silence excessive logging
-    #for hdlr in Logger.handlers[:]:
-    #    if not isinstance(hdlr, LoggerHistory):
-    #        Logger.removeHandler(hdlr)
     EditorApp(level).run()
 
 
     EditorApp(level).run()