changeset 275:2abb61878bb1

Add a 'select object' with pop-up for easier editing
author Neil Muller <drnlmuller@gmail.com>
date Thu, 05 Sep 2013 12:04:14 +0200
parents 988cf7c8b402
children 3153196517fc
files tools/area_editor.py
diffstat 1 files changed, 65 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/tools/area_editor.py	Thu Sep 05 12:03:34 2013 +0200
+++ b/tools/area_editor.py	Thu Sep 05 12:04:14 2013 +0200
@@ -55,10 +55,17 @@
         super(EditorLevel, self).__init__(name)
         self.x = x
         self.y = y
+        # Lookup initiliasition info from the objects
+        self.lookup = {}
 
     def round_point(self, pos):
         return (10 * (pos[0] // 10), 10 * (pos[1] // 10))
 
+    def load(self, space):
+        super(EditorLevel, self).load(space)
+        # Needed to fill in the lookup dict
+        self.reset_objs()
+
     def point_to_pymunk(self, pos):
         # inverse of point_to_pygame
         # (this is also the same as point_to_pygame, but a additional
@@ -179,9 +186,11 @@
         self.overlay_drawables = []
         self._glue = np.PuzzleGlue()
         for game_object_dict in self._game_objects:
-            self._create_game_object(pymunk.Space(), **game_object_dict)
+            obj = self._create_game_object(pymunk.Space(), **game_object_dict)
+            self.lookup[obj] = game_object_dict
         for enemy_dict in self._enemies:
-            self._create_enemy(pymunk.Space(), **enemy_dict)
+            obj = self._create_enemy(pymunk.Space(), **enemy_dict)
+            self.lookup[obj] = enemy_dict
 
     def get_class(self, classname, mod=None):
         # Get the class given the classname
@@ -212,6 +221,14 @@
             alert("Failed to update object %s: %s" % (classname, e))
         return False
 
+    def find_obj_at_pos(self, mouse_pos):
+        pymunk_pos = self.point_to_pymunk(mouse_pos)
+        # Search visible objects
+        for obj in self.drawables:
+            if obj.get_shape().point_query(pymunk_pos):
+                return obj
+        return None
+
 
 class ObjectTable(TableView):
 
@@ -245,7 +262,7 @@
 
 class EditClassDialog(Dialog):
 
-    def __init__(self, classname, cls, data):
+    def __init__(self, classname, cls, data, delete=False):
         super(EditClassDialog, self).__init__()
         self.classname = classname
         self.rect = pygame.rect.Rect(0, 0, 800, 550)
@@ -281,7 +298,11 @@
             self.add(hintlabel)
             y += 30
         buttons = []
-        for text in ['OK', 'Cancel']:
+        if delete:
+            labels = ['OK', 'Delete', 'Cancel']
+        else:
+            labels = ['OK', 'Cancel']
+        for text in labels:
             but = Button(text, action=lambda x=text: self.dismiss(x))
             buttons.append(but)
         row = Row(buttons)
@@ -322,6 +343,7 @@
         self._draw_objects = False
         self._draw_enemies = False
         self._draw_lines = False
+        self.sel_mode = False
         self._start_pos = None
 
     def _level_coordinates(self, pos):
@@ -432,7 +454,12 @@
             self.invalidate()
 
     def mouse_down(self, ev):
-        if ev.button == 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 ev.button == 1:
             if self._draw_lines:
                 if self._start_pos is None:
                     self._start_pos = ev.pos
@@ -478,6 +505,27 @@
             return dialog.get_data()
         return None
 
+    def _edit_selected(self, obj):
+        data = self.level.lookup[obj]
+        cls = obj.__class__
+        classname = obj.__class__.__name__
+        dialog = EditClassDialog(classname, cls, data, True)
+        res = dialog.present()
+        if res == 'OK':
+            edited = dialog.get_data()
+            if edited is not None:
+                for target in [self.level._game_objects, self.level._enemies]:
+                    if data in target:
+                        self.level.try_new_object(classname, target,
+                                                  edited, data)
+                        break
+        elif res == 'Delete':
+            for target in [self.level._game_objects, self.level._enemies]:
+                if data in target:
+                    target.remove(data)
+                    self.level.reset_objs()
+                    break
+
     def _make_edit_dialog(self, entries):
         # Dialog to hold the editor
         edit_box = Dialog()
@@ -742,6 +790,14 @@
         y += MENU_BUTTON_HEIGHT + MENU_PAD
 
         y += MENU_PAD
+        sel_mode_but = Button('Select Object',
+                              action=self.sel_mode)
+        sel_mode_but.rect = BUTTON_RECT.copy()
+        sel_mode_but.rect.move_ip(MENU_LEFT, y)
+        widgets.append(sel_mode_but)
+        y += MENU_BUTTON_HEIGHT + MENU_PAD
+
+        y += MENU_PAD
         switch_but = Button('Switch to Drawing', action=self.switch_to_draw)
         switch_but.rect = BUTTON_RECT.copy()
         switch_but.rect.move_ip(MENU_LEFT, y)
@@ -798,10 +854,14 @@
 
     def _populate_menu(self):
         self.level_widget.change_poly(None)
+        self.level_widget.sel_mode = False
         for widget in self._dMenus[self._menu_mode]:
             self.add(widget)
         self.invalidate()
 
+    def sel_mode(self):
+        self.level_widget.sel_mode = not self.level_widget.sel_mode
+
     def mouse_move(self, ev):
         self.level_widget.mouse_move(ev)