changeset 407:314ddad2d6d2

Move points button
author Neil Muller <drnlmuller@gmail.com>
date Sat, 07 Sep 2013 12:10:42 +0200
parents 7fcde01ea50e
children d04981e24fda
files tools/area_editor.py
diffstat 1 files changed, 97 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/tools/area_editor.py	Sat Sep 07 11:16:59 2013 +0200
+++ b/tools/area_editor.py	Sat Sep 07 12:10:42 2013 +0200
@@ -53,6 +53,11 @@
 
     def __init__(self):
         self.level_state = {}
+        self.inventory = {}
+
+
+def distance(tup1, tup2):
+    return (tup1[0] - tup2[0]) ** 2 + (tup1[1] - tup2[1]) ** 2
 
 
 class EditorLevel(Level):
@@ -64,6 +69,7 @@
         self.y = y
         # Lookup initiliasition info from the objects
         self.lookup = {}
+        self._move_poly = None
 
     def round_point(self, pos):
         return (10 * (pos[0] // 10), 10 * (pos[1] // 10))
@@ -103,7 +109,7 @@
         min_dist = 9999999
         new_pos = point1
         for cand in [pos0, pos90, pos45, pos135, pos225, pos305]:
-            dist = (pos[0] - cand[0]) ** 2 + (pos[1] - cand[1]) ** 2
+            dist = distance(pos, cand)
             if dist < min_dist:
                 new_pos = cand
                 min_dist = dist
@@ -148,7 +154,7 @@
         poss = None
         for cand in candidates:
             if self.fix_poly_angle(index, self.point_to_pygame(cand)) == cand:
-                dist = (first[0] - cand[0]) ** 2 + (first[1] - cand[1]) ** 2
+                dist = distance(first, cand)
                 if dist < min_dist:
                     poss = cand
         if poss is not None:
@@ -162,23 +168,35 @@
         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):
+    def draw(self, mouse_pos, mouse_poly, filled, draw_cand_line, start_pos,
+             move_point_mode, move_point):
         self._draw_background(True)
         # Draw polygons as needed for the editor
         if filled:
             self._draw_exterior(True)
         for index, polygon in self.polygons.items():
             color = POLY_COLORS[index]
-            if len(polygon) > 1:
+            if move_point_mode and index == self._move_poly:
+                pointlist = [p for p in polygon]
+                pointlist = [self.point_to_pygame(p) if p != move_point else
+                             mouse_pos for p in pointlist]
+                pygame.draw.lines(self._surface, color, False, pointlist, 2)
+            elif len(polygon) > 1:
                 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:
+            elif index == mouse_poly and 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))
+        line_found = False  # Hack for sane behaviour if lines overlap
         for line in self.lines:
             pointlist = [self.point_to_pygame(p) for p in line]
+            if move_point_mode and not self._move_poly and not line_found:
+                if move_point in line:
+                    line_found = True
+                    pointlist.remove(self.point_to_pygame(move_point))
+                    pointlist.append(mouse_pos)
             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)
@@ -236,6 +254,41 @@
                 return obj
         return None
 
+    def find_vertex(self, mouse_pos):
+        # search for vertexes closest to where we've killed
+        mindist = 400
+        move_point = None
+        search_point = self.point_to_pymunk(mouse_pos)
+        for index, polygon in self.polygons.items():
+            for point in polygon:
+                dist = distance(point, search_point)
+                if dist < mindist:
+                    mindist = dist
+                    move_point = point
+                    self._move_poly = index
+        # Also check lines
+        for line in self.lines:
+            for point in line:
+                dist = distance(point, search_point)
+                if dist < mindist:
+                    mindist = dist
+                    move_point = point
+                    self._move_poly = None
+        return move_point
+
+    def replace_vertex(self, old_point, new_point):
+        new_point = self.point_to_pymunk(new_point)
+        if self._move_poly:
+            new_polygon = [p if p != old_point else new_point for p in
+                           self.polygons[self._move_poly]]
+            self.polygons[self._move_poly] = new_polygon
+        else:
+            for line in self.lines:
+                if old_point in line:
+                    line.remove(old_point)
+                    line.append(new_point)
+                    break
+
 
 class ObjectTable(TableView):
 
@@ -399,6 +452,8 @@
         self.sel_mode = False
         self._start_pos = None
         self._parent = parent
+        self._move_point_mode = False
+        self._move_point = False
 
     def _level_coordinates(self, pos):
         # Move positions to level values
@@ -436,10 +491,13 @@
         elif self._draw_lines:
             # Interior wall mode
             mouse_pos = self._level_coordinates(self.mouse_pos)
+        elif self._move_point_mode:
+            mouse_pos = self._level_coordinates(self.mouse_pos)
         else:
             mouse_pos = None
         level_surface = level.draw(mouse_pos, self.cur_poly, self.filled_mode,
-                                   self._draw_lines, self._start_pos)
+                                   self._draw_lines, self._start_pos,
+                                   self._move_point_mode, self._move_point)
         if self._draw_objects:
             for thing in self.level.drawables:
                 if not isinstance(thing, ne.Enemy):
@@ -464,6 +522,7 @@
         self._draw_lines = True
         self.filled_mode = False
         self._start_pos = None
+        self._move_point_mode = False
 
     def key_down(self, ev):
         if ev.key == pgl.K_LEFT:
@@ -485,6 +544,13 @@
         elif ev.key == pgl.K_c:
             self.close_poly()
 
+    def set_move_mode(self):
+        self._draw_lines = False
+        self._move_point_mode = True
+        self.filled_mode = False
+        self._parent.reset_lit_buttons()
+        self._move_point = None
+
     def set_filled(self):
         closed, _ = self.level.all_closed()
         if closed:
@@ -492,13 +558,15 @@
             self._parent.reset_lit_buttons()
             self.filled_mode = True
             self._draw_lines = False
+            self._move_point_mode = 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 old_pos != self.mouse_pos and (self.cur_poly or self._draw_lines):
+        if old_pos != self.mouse_pos and (self.cur_poly or self._draw_lines
+           or self._move_point_mode):
             self.invalidate()
 
     def mouse_drag(self, ev):
@@ -511,11 +579,20 @@
             self.invalidate()
 
     def mouse_down(self, ev):
+        corrected_pos = ev.pos[0] + self.pos[0], ev.pos[1] + self.pos[1]
         if self.sel_mode and ev.button == 1:
-            corrected_pos = ev.pos[0] + self.pos[0], ev.pos[1] + self.pos[1]
             obj = self.level.find_obj_at_pos(corrected_pos)
             if obj is not None:
                 self._edit_selected(obj)
+        elif self._move_point_mode and ev.button == 1:
+            if self._move_point:
+                # Place the current point
+                self.level.replace_vertex(self._move_point, corrected_pos)
+                self._move_point = None
+                self.invalidate()
+            else:
+                # find the current point
+                self._move_point = self.level.find_vertex(corrected_pos)
         elif ev.button == 1:
             if self._draw_lines:
                 if self._start_pos is None:
@@ -779,6 +856,14 @@
         widgets.append(end_poly_but)
         y += MENU_BUTTON_HEIGHT + MENU_PAD
 
+        self.move_point_but = HighLightButton("Move Point", self,
+                                              action=self.move_point)
+        self.move_point_but.rect = BUTTON_RECT.copy()
+        self.move_point_but.rect.move_ip(MENU_LEFT, y)
+        widgets.append(self.move_point_but)
+        self._light_buttons.append(self.move_point_but)
+        y += MENU_BUTTON_HEIGHT + MENU_PAD
+
         self.draw_line_but = HighLightButton("Draw interior wall", self,
                                              action=self.set_line_mode)
         self.draw_line_but.rect = BUTTON_RECT.copy()
@@ -970,6 +1055,10 @@
     def mouse_move(self, ev):
         self.level_widget.mouse_move(ev)
 
+    def move_point(self):
+        self.level_widget.set_move_mode()
+        self.move_point_but.highlight()
+
     def draw(self, surface):
         # Update checkbox state
         if self._menu_mode == 'drawing':