diff tools/area_editor.py @ 241:ec567098cf41

Merge
author David Sharpe
date Wed, 04 Sep 2013 01:23:43 +0200
parents 42c565c5ce76
children 06c52529e2ed
line wrap: on
line diff
--- a/tools/area_editor.py	Wed Sep 04 01:23:32 2013 +0200
+++ b/tools/area_editor.py	Wed Sep 04 01:23:43 2013 +0200
@@ -23,11 +23,13 @@
 
 from albow.root import RootWidget
 from albow.widget import Widget
-from albow.controls import Button
+from albow.controls import Button, Label, CheckBox
 from albow.dialogs import alert
 
+from nagslang.options import parse_args
 from nagslang.constants import SCREEN
-from nagslang.level import Level, POLY_COLORS
+from nagslang.level import Level, POLY_COLORS, LINE_COLOR
+from nagslang.enemies import Enemy
 
 
 # layout constants
@@ -60,13 +62,10 @@
             point = self.point_to_pymunk(self.round_point(pos))
             self.polygons[poly_index].append(point)
         else:
-            add_pos = self.fix_angle(poly_index, pos)
+            add_pos = self.fix_poly_angle(poly_index, pos)
             self.polygons[poly_index].append(add_pos)
 
-    def fix_angle(self, index, pos):
-        # Last point
-        point1 = self.point_to_pygame(self.polygons[index][-1])
-        pos = self.round_point(pos)
+    def _fix_angle(self, point1, pos):
         # We want the line (point1 to pos) to be an angle of
         # 0, 45, 90, 135, 180, 225, 270, 305
         # However, we only need to consider half the circle
@@ -87,6 +86,17 @@
                 min_dist = dist
         return self.point_to_pymunk(new_pos)
 
+    def fix_line_angle(self, start_pos, pos):
+        start_pos = self.round_point(start_pos)
+        pos = self.round_point(pos)
+        return self._fix_angle(start_pos, pos)
+
+    def fix_poly_angle(self, index, pos):
+        # Last point
+        point1 = self.point_to_pygame(self.polygons[index][-1])
+        pos = self.round_point(pos)
+        return self._fix_angle(point1, pos)
+
     def delete_point(self, index):
         if index in self.polygons and len(self.polygons[index]) > 0:
             self.polygons[index].pop()
@@ -100,7 +110,7 @@
             # Too small
             return False
         first = self.polygons[index][0]
-        if self.fix_angle(index, self.point_to_pygame(first)) == first:
+        if self.fix_poly_angle(index, self.point_to_pygame(first)) == first:
             self.add_point(index, self.point_to_pygame(first))
             return True
         candidates = [(first[0] + 10 * i, first[1]) for
@@ -114,7 +124,7 @@
         min_dist = 99999
         poss = None
         for cand in candidates:
-            if self.fix_angle(index, self.point_to_pygame(cand)) == cand:
+            if self.fix_poly_angle(index, self.point_to_pygame(cand)) == cand:
                 dist = (first[0] - cand[0]) ** 2 + (first[1] - cand[1]) ** 2
                 if dist < min_dist:
                     poss = cand
@@ -124,7 +134,12 @@
             return True
         return False
 
-    def draw(self, surface, topleft, mouse_pos, mouse_poly, filled):
+    def add_line(self, start_pos, end_pos):
+        endpoint = self.fix_line_angle(start_pos, end_pos)
+        startpoint = self.point_to_pymunk(self.round_point(start_pos))
+        self.lines.append([startpoint, endpoint])
+
+    def draw(self, mouse_pos, mouse_poly, filled, draw_cand_line, start_pos):
         self._draw_background(True)
         # Draw polygons as needed for the editor
         if filled:
@@ -135,12 +150,19 @@
                 pointlist = [self.point_to_pygame(p) for p in polygon]
                 pygame.draw.lines(self._surface, color, False, pointlist, 2)
             if index == mouse_poly and mouse_pos:
-                endpoint = self.fix_angle(index, mouse_pos)
+                endpoint = self.fix_poly_angle(index, mouse_pos)
                 pygame.draw.line(self._surface, color,
                                  self.point_to_pygame(polygon[-1]),
                                  self.point_to_pygame(endpoint))
-        surface_area = pygame.rect.Rect(topleft, SCREEN)
-        surface.blit(self._surface, (0, 0), surface_area)
+        for line in self.lines:
+            pointlist = [self.point_to_pygame(p) for p in line]
+            pygame.draw.lines(self._surface, LINE_COLOR, False, pointlist, 2)
+        if draw_cand_line and start_pos and mouse_pos:
+            endpoint = self.fix_line_angle(start_pos, mouse_pos)
+            pointlist = [self.round_point(start_pos),
+                         self.point_to_pygame(endpoint)]
+            pygame.draw.lines(self._surface, LINE_COLOR, False, pointlist, 1)
+        return self._surface.copy()
 
 
 class LevelWidget(Widget):
@@ -154,6 +176,10 @@
         self.mouse_pos = None
         self.cur_poly = None
         self._mouse_drag = False
+        self._draw_objects = False
+        self._draw_enemies = False
+        self._draw_lines = False
+        self._start_pos = None
 
     def _level_coordinates(self, pos):
         # Move positions to level values
@@ -173,21 +199,51 @@
             new_pos[1] = self.pos[1]
         self.pos = tuple(new_pos)
 
+    def set_objects(self, value):
+        if self._draw_objects != value:
+            self._draw_objects = value
+            self.invalidate()
+
+    def set_enemies(self, value):
+        if self._draw_enemies != value:
+            self._draw_enemies = value
+            self.invalidate()
+
     def draw(self, surface):
         if (self.cur_poly is not None and self.cur_poly in self.level.polygons
                 and len(self.level.polygons[self.cur_poly])):
             # We have an active polygon
             mouse_pos = self._level_coordinates(self.mouse_pos)
+        elif self._draw_lines:
+            # Interior wall mode
+            mouse_pos = self._level_coordinates(self.mouse_pos)
         else:
             mouse_pos = None
-        level.draw(surface, self.pos, mouse_pos, self.cur_poly,
-                   self.filled_mode)
+        level_surface = level.draw(mouse_pos, self.cur_poly, self.filled_mode,
+                                   self._draw_lines, self._start_pos)
+        if self._draw_objects:
+            for thing in self.level.drawables:
+                if not isinstance(thing, Enemy):
+                    thing.render(level_surface)
+        if self._draw_enemies:
+            for thing in self.level.drawables:
+                if isinstance(thing, Enemy):
+                    thing.render(level_surface)
+        surface_area = pygame.rect.Rect(self.pos, SCREEN)
+        surface.blit(level_surface, (0, 0), surface_area)
 
     def change_poly(self, new_poly):
         self.cur_poly = new_poly
+        self._draw_lines = False
         if self.cur_poly is not None:
             self.filled_mode = False
 
+    def line_mode(self):
+        self.cur_poly = None
+        self._draw_lines = True
+        self.filled_mode = False
+        self._start_pos = None
+
     def key_down(self, ev):
         if ev.key == pgl.K_LEFT:
             self._move_view((-10, 0))
@@ -213,13 +269,14 @@
         if closed:
             self.cur_poly = None
             self.filled_mode = True
+            self._draw_lines = False
         else:
             alert('Not all polygons closed, so not filling')
 
     def mouse_move(self, ev):
         old_pos = self.mouse_pos
         self.mouse_pos = ev.pos
-        if self.cur_poly and old_pos != self.mouse_pos:
+        if old_pos != self.mouse_pos and (self.cur_poly or self._draw_lines):
             self.invalidate()
 
     def mouse_drag(self, ev):
@@ -233,8 +290,16 @@
 
     def mouse_down(self, ev):
         if ev.button == 1:
-            print "Click: %r" % (
-                self.level.point_to_pymunk(self._level_coordinates(ev.pos)),)
+            if self._draw_lines:
+                if self._start_pos is None:
+                    self._start_pos = ev.pos
+                else:
+                    self.level.add_line(self._start_pos, ev.pos)
+                    self._start_pos = None
+            else:
+                print "Click: %r" % (
+                    self.level.point_to_pymunk(
+                        self._level_coordinates(ev.pos)),)
         if ev.button == 4:  # Scroll up
             self._move_view((0, -10))
         elif ev.button == 5:  # Scroll down
@@ -304,12 +369,21 @@
 
         button_rect = pygame.rect.Rect(0, 0, MENU_WIDTH, MENU_BUTTON_HEIGHT)
 
+        check_rect = pygame.rect.Rect(0, 0, MENU_BUTTON_HEIGHT // 2,
+                                      MENU_BUTTON_HEIGHT // 2)
+
         end_poly_but = PolyButton(None, self.level_widget)
         end_poly_but.rect = button_rect.copy()
         end_poly_but.rect.move_ip(MENU_LEFT, y)
         self.add(end_poly_but)
         y += MENU_BUTTON_HEIGHT + MENU_PAD
 
+        draw_line = Button("Draw interior wall", self.level_widget.line_mode)
+        draw_line.rect = button_rect.copy()
+        draw_line.rect.move_ip(MENU_LEFT, y)
+        self.add(draw_line)
+        y += MENU_BUTTON_HEIGHT + MENU_PAD
+
         fill_but = Button('Fill exterior', action=self.level_widget.set_filled)
         fill_but.rect = button_rect.copy()
         fill_but.rect.move_ip(MENU_LEFT, y)
@@ -329,6 +403,25 @@
         self.add(close_poly_but)
         y += MENU_BUTTON_HEIGHT + MENU_PAD
 
+        white = pygame.color.Color("white")
+        self.show_objs = CheckBox(fg_color=white)
+        self.show_objs.rect = check_rect.copy()
+        self.show_objs.rect.move_ip(MENU_LEFT, y)
+        label = Label("Show Objects", fg_color=white)
+        label.rect.move_ip(MENU_LEFT + MENU_BUTTON_HEIGHT // 2 + MENU_PAD, y)
+        self.add(self.show_objs)
+        self.add(label)
+        y += label.rect.height + MENU_PAD
+
+        self.show_enemies = CheckBox(fg_color=white)
+        self.show_enemies.rect = check_rect.copy()
+        self.show_enemies.rect.move_ip(MENU_LEFT, y)
+        label = Label("Show enemy start pos", fg_color=white)
+        label.rect.move_ip(MENU_LEFT + MENU_BUTTON_HEIGHT // 2 + MENU_PAD, y)
+        self.add(self.show_enemies)
+        self.add(label)
+        y += label.rect.height + MENU_PAD
+
         quit_but = Button('Quit', action=self.quit)
         quit_but.rect = button_rect.copy()
         quit_but.rect.move_ip(MENU_LEFT, y)
@@ -355,11 +448,19 @@
     def mouse_move(self, ev):
         self.level_widget.mouse_move(ev)
 
+    def draw(self, surface):
+        # Update checkbox state
+        self.level_widget.set_objects(self.show_objs.value)
+        self.level_widget.set_enemies(self.show_enemies.value)
+        super(EditorApp, self).draw(surface)
+
 
 if __name__ == "__main__":
     if len(sys.argv) not in [2, 4]:
         print 'Please supply a levelname or levelname and level size'
         sys.exit()
+    # Need to ensure we have defaults for rendering
+    parse_args([])
     pygame.display.init()
     pygame.font.init()
     pygame.display.set_mode((SCREEN[0] + MENU_WIDTH, SCREEN[1]),