Refactor
[erdslangetjie.git] / erdslangetjie / editor / editor.py
index 04c95d93593ccd063d2c4d2a569a3d6fbd24fa63..ef08b813e01f7c2d30c4dccbda827ba2bbe21df1 100644 (file)
@@ -1,24 +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.constants import TILE_SIZE, QUIET
+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=(800, 600))
+        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
@@ -36,22 +53,106 @@ class EditorWindow(FloatLayout):
         level_data.close()
         self.level_obj.load_tiles()
 
         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()
         bx, by = 0, 0
     def build(self):
         self.clear_widgets()
         tiles = self.level_obj.get_tiles()
         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)
+                self._draw_tile((bx, by), tile)
                 bx += TILE_SIZE
             by += TILE_SIZE
 
                 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'
-    if QUIET:
-        for hdlr in Logger.handlers[:]:
-            if not isinstance(hdlr, LoggerHistory):
-                Logger.removeHandler(hdlr)
     EditorApp(level).run()
 
 
     EditorApp(level).run()