changeset 355:9589e1db4433

Allow copying polygon 6 into terrain objects
author Neil Muller <drnlmuller@gmail.com>
date Fri, 06 Sep 2013 17:32:25 +0200
parents 55752fc7b753
children 582a96e5fdac
files tools/area_editor.py
diffstat 1 files changed, 97 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/tools/area_editor.py	Fri Sep 06 17:29:50 2013 +0200
+++ b/tools/area_editor.py	Fri Sep 06 17:32:25 2013 +0200
@@ -49,10 +49,17 @@
                               MENU_BUTTON_HEIGHT // 2)
 
 
+class TestWorld(object):
+
+    def __init__(self):
+        self.level_state = {}
+
+
 class EditorLevel(Level):
 
     def __init__(self, name, x=800, y=600):
-        super(EditorLevel, self).__init__(name, None)
+        world = TestWorld()
+        super(EditorLevel, self).__init__(name, world)
         self.x = x
         self.y = y
         # Lookup initiliasition info from the objects
@@ -262,10 +269,12 @@
 
 class EditClassDialog(Dialog):
 
-    def __init__(self, classname, cls, data, delete=False):
+    def __init__(self, classname, cls, data, level_widget,
+                 delete=False):
         super(EditClassDialog, self).__init__()
+        self.level_widget = level_widget
         self.classname = classname
-        self.rect = pygame.rect.Rect(0, 0, 800, 550)
+        self.rect = pygame.rect.Rect(0, 0, 900, 550)
         title = Label("Editing %s" % classname)
         title.rect = pygame.rect.Rect(100, 10, 600, 25)
         self.add(title)
@@ -273,6 +282,8 @@
         y = 40
         self.fields = {}
         index = 0
+        self.poly_field = None
+        self.needs_cleanup = False
         for requirement, hint in self.requires:
             label = Label(requirement)
             label.rect = pygame.rect.Rect(40, y, 200, 25)
@@ -292,11 +303,18 @@
                     except IndexError:
                         # Assumed to be arguments with the default value
                         pass
+            if hint.startswith('polygon'):
+                self.poly_field = field
             self.fields[requirement] = field
             hintlabel = Label(hint)
-            hintlabel.rect = pygame.rect.Rect(640, y, 100, 25)
+            hintlabel.rect = pygame.rect.Rect(640, y, 250, 25)
             self.add(hintlabel)
             y += 30
+        if self.poly_field:
+            y += 20
+            button = Button('Use Polygon 6', action=self.get_poly)
+            button.rect = pygame.rect.Rect(350, y, 250, 30)
+            self.add(button)
         buttons = []
         if delete:
             labels = ['OK', 'Delete', 'Cancel']
@@ -309,6 +327,25 @@
         row.rect = pygame.rect.Rect(250, 500, 700, 50)
         self.add(row)
 
+    def get_poly(self):
+        try:
+            data = self.level_widget.level.polygons[6][:]
+        except KeyError:
+            data = []
+        if data:
+            # We unclose the polygon, because that's what pymunk
+            # wants
+            if data[0] == data[-1] and len(data) > 1:
+                data.pop()
+            data = [list(x) for x in data]
+            self.needs_cleanup = True
+            self.poly_field.set_text('%s' % data)
+
+    def cleanup(self):
+        if self.needs_cleanup:
+            self.level_widget.level.polygons[6] = []
+            self.level_widget.invalidate()
+
     def get_data(self):
         result = {}
         result['classname'] = self.classname
@@ -322,6 +359,22 @@
                 continue
             if val == 'name':
                 result['name'] = text
+            elif self.fields[val] == self.poly_field and text:
+                # Evil, but faster than good
+                try:
+                    l = eval(text)
+                    args.append(' - - %s' % l[0])
+                    for coord in l[1:]:
+                        args.append('   - %s' % coord)
+                except Exception:
+                    alert("Invalid polygon %s" % text)
+                    self.needs_cleanup = False
+                    return None
+                # Check for convexity
+                hull = pymunk.util.convex_hull(l)
+                if hull != l:
+                    alert("Invalid polygon %s - not convex" % text)
+                    return None
             else:
                 args.append(' - ' + text)
         data = "args:\n" + '\n'.join(args)
@@ -504,24 +557,25 @@
 
     def _edit_class(self, classname, cls, data):
         # Dialog for class properties
-        dialog = EditClassDialog(classname, cls, data)
+        dialog = EditClassDialog(classname, cls, data, self)
         if dialog.present() == 'OK':
-            return dialog.get_data()
+            return dialog
         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)
+        dialog = EditClassDialog(classname, cls, data, self, 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)
+                        if self.level.try_new_object(classname, target,
+                                                     edited, data):
+                            dialog.cleanup()
                         break
         elif res == 'Delete':
             for target in [self.level._game_objects, self.level._enemies]:
@@ -554,11 +608,13 @@
             return
         if res == 'OK':
             cls = self.level.get_class(choice['classname'])
-            edited = self._edit_class(choice['classname'], cls, choice)
-            if edited is not None:
-                self.level.try_new_object(choice["classname"],
-                                          self.level._game_objects,
-                                          edited, choice)
+            edit_dlg = self._edit_class(choice['classname'], cls, choice)
+            if edit_dlg is not None:
+                edited = edit_dlg.get_data()
+                if self.level.try_new_object(choice["classname"],
+                                             self.level._game_objects,
+                                             edited, choice):
+                    edit_dlg.cleanup()
         elif res == 'Delete':
             self.level._game_objects.remove(choice)
             self.level.reset_objs()
@@ -571,10 +627,13 @@
             return
         if res == 'OK':
             cls = self.level.get_class(choice['classname'], ne)
-            edited = self._edit_class(choice['classname'], cls, choice)
-            if edited is not None:
-                self.level.try_new_object(choice["classname"],
-                                          self.level._enemies, edited, choice)
+            edit_dlg = self._edit_class(choice['classname'], cls, choice)
+            if edit_dlg is not None:
+                edited = edit_dlg.get_data()
+                if self.level.try_new_object(choice["classname"],
+                                             self.level._enemies,
+                                             edited, choice):
+                    edit_dlg.cleanup()
         elif res == 'Delete':
             self.level._enemies.remove(choice)
             self.level.reset_objs()
@@ -606,10 +665,13 @@
         if res == 'OK' and choice is not None:
             classname = choice['classname']
             cls = choice['class']
-            new_cls = self._edit_class(classname, cls, None)
-            if new_cls is not None:
-                self.level.try_new_object(classname, self.level._game_objects,
-                                          new_cls, None)
+            edit_dlg = self._edit_class(classname, cls, None)
+            if edit_dlg is not None:
+                new_cls = edit_dlg.get_data()
+                if self.level.try_new_object(classname,
+                                             self.level._game_objects,
+                                             new_cls, None):
+                    edit_dlg.cleanup()
 
     def add_enemy(self):
         classes = ne.get_editable_enemies()
@@ -619,10 +681,12 @@
         if res == 'OK' and choice is not None:
             classname = choice['classname']
             cls = choice['class']
-            new_cls = self._edit_class(classname, cls, None)
-            if new_cls is not None:
-                self.level.try_new_object(classname, self.level._enemies,
-                                          new_cls, None)
+            edit_dlg = self._edit_class(classname, cls, None)
+            if edit_dlg is not None:
+                new_cls = edit_dlg.get_data()
+                if self.level.try_new_object(classname, self.level._enemies,
+                                             new_cls, None):
+                    edit_dlg.cleanup()
 
     def add_puzzler(self):
         classes = np.get_editable_puzzlers()
@@ -632,10 +696,13 @@
         if res == 'OK' and choice is not None:
             classname = choice['classname']
             cls = choice['class']
-            new_cls = self._edit_class(classname, cls, None)
-            if new_cls is not None:
-                self.level.try_new_object(classname, self.level._game_objects,
-                                          new_cls, None)
+            edit_dlg = self._edit_class(classname, cls, None)
+            if edit_dlg is not None:
+                new_cls = edit_dlg.get_data()
+                if self.level.try_new_object(classname,
+                                             self.level._game_objects,
+                                             new_cls, None):
+                    edit_dlg.cleanup()
 
 
 class HighLightButton(Button):