box tool
authorFrank DeMarco <if.self.end@gmail.com>
Mon, 18 Feb 2019 07:21:51 +0000 (02:21 -0500)
committerFrank DeMarco <if.self.end@gmail.com>
Mon, 18 Feb 2019 07:21:51 +0000 (02:21 -0500)
PictureProcessing.py

index f75ec1b..0e964d7 100644 (file)
@@ -146,11 +146,13 @@ class Editor(GameChild):
         self.at_tile_bar = False
         self.at_tile_edit = False
         self.at_palette = False
+        self.at_box = False
         self.level_index = 0
         self.tile_index = 0
         self.palette_index = 0
         self.loaded = False
         self.menu_hidden = False
+        self.paint_pressed = False
 
     def reset(self):
         self.deactivate()
@@ -159,6 +161,7 @@ class Editor(GameChild):
         self.active = True
         if not self.loaded:
             self.load()
+        self.paint_pressed = False
 
     def load(self):
         self.read_levels()
@@ -216,6 +219,7 @@ class Editor(GameChild):
             *([self.TILE_SIZE * self.TILE_BAR_SCALE] * 2))
         self.paint_cursor = self.get_cursor(*([self.CANVAS_SCALE] * 2))
         self.palette_cursor = self.get_cursor()
+        self.box_cursor = self.get_cursor()
         new_tile = self.new_tile = Surface([self.TILE_SIZE] * 2)
         new_tile.fill((255, 255, 255))
         for x in xrange(new_tile.get_width()):
@@ -225,8 +229,12 @@ class Editor(GameChild):
                 elif 3 <= y <= 4 and x != 0 and x != 7:
                     new_tile.set_at((x, y), (0, 0, 0))
         self.build_default_palette()
+        self.box = FlashingCursor(self, *([self.get_level_tile_size()] * 2))
         self.loaded = True
 
+    def get_level_tile_size(self):
+        return self.TILE_SIZE * PictureProcessing.SCALE
+
     def build_default_palette(self):
         self.default_palette = [Color(255, 255, 255), Color(0, 0, 0)]
         for hue in xrange(0, 360 - 45, 45):
@@ -321,20 +329,23 @@ class Editor(GameChild):
                 elif self.at_palette:
                     self.at_palette = False
                     self.at_tile_edit = True
+                elif self.at_box:
+                    self.at_box = False
+                    self.at_view = True
             if compare(event, "right"):
                 if self.at_tile_bar:
                     self.tile_index += 1
                     if self.tile_index == Interface.MAX_TILE_COUNT or \
                        self.tile_index > len(self.get_current_level().tiles):
                         self.tile_index = 0
+                if self.at_tile_edit or self.at_box:
+                    dx = 1
                 if self.at_tile_edit:
                     if self.brush_position.x == self.TILE_SIZE - 1:
                         self.at_tile_edit = False
                         self.at_palette = True
                         if self.palette_index_is_at_left():
                             self.wrap_palette_index()
-                    else:
-                        dx = 1
                 elif self.at_palette:
                     if self.palette_index_is_at_left():
                         self.at_palette = False
@@ -342,10 +353,13 @@ class Editor(GameChild):
                     else:
                         self.wrap_palette_index()
             elif compare(event, "down"):
-                if self.at_tile_edit:
+                if self.at_tile_edit or self.at_box:
                     dy = 1
                 if self.at_palette:
                     self.palette_index += 1
+                if self.at_view:
+                    self.at_view = False
+                    self.at_box = True
             elif compare(event, "left"):
                 if self.at_tile_bar:
                     self.tile_index -= 1
@@ -353,14 +367,14 @@ class Editor(GameChild):
                         self.tile_index = min(
                             Interface.MAX_TILE_COUNT - 1,
                             len(self.get_current_level().tiles))
+                if self.at_tile_edit or self.at_box:
+                    dx = -1
                 if self.at_tile_edit:
                     if self.brush_position.x == 0:
                         self.at_tile_edit = False
                         self.at_palette = True
                         if not self.palette_index_is_at_left():
                             self.wrap_palette_index()
-                    else:
-                        dx = -1
                 elif self.at_palette:
                     if not self.palette_index_is_at_left():
                         self.at_palette = False
@@ -371,20 +385,92 @@ class Editor(GameChild):
                 if self.at_view:
                     self.at_view = False
                     self.at_tile_bar = True
-                if self.at_tile_edit:
+                if self.at_tile_edit or self.at_box:
                     dy = -1
                 if self.at_palette:
                     self.palette_index -= 1
             elif compare(event, "paint"):
-                self.painting[self.brush_position.x][self.brush_position.y] = \
-                    not self.painting[self.brush_position.x][self.brush_position.y]
+                self.paint_pressed = True
+                if self.at_box:
+                    self.set_box_anchor()
+                if self.at_tile_edit and self.palette_index < len(self.get_full_palette()):
+                    self.paint_tile()
+            elif compare(event, "paint", cancel=True):
+                self.paint_pressed = False
+                if self.at_box:
+                    self.stamp()
+                    self.box.size = Vector(*([self.get_level_tile_size()] * 2))
             if dx != 0 or dy != 0:
-                self.move_brush_position(dx, dy)
+                if self.at_box:
+                    if self.paint_pressed:
+                        self.grow_box(x=dx, y=dy)
+                    else:
+                        self.move_box(x=dx, y=dy)
+                if self.at_tile_edit:
+                    self.move_brush_position(dx, dy)
+                    if self.paint_pressed and self.palette_index < len(self.get_full_palette()):
+                        self.paint_tile()
             if self.palette_index >= self.get_palette_cell_count():
                 self.palette_index = 0
             elif self.palette_index < 0:
                 self.palette_index = self.get_palette_cell_count() - 1
 
+    def stamp(self):
+        size = self.get_level_tile_size()
+        x = self.box.location.left / size
+        y = self.box.location.top / size
+        w = self.box.location.w / size
+        h = self.box.location.h / size
+        for xi in xrange(x, x + w):
+            for yi in xrange(y, y + h):
+                self.get_current_level().grid[xi][yi] = self.tile_index
+
+    def set_box_anchor(self):
+        size = self.get_level_tile_size()
+        self.box_anchor = Vector(self.box.location.left / size,
+                                 self.box.location.top / size)
+        self.box_corner = Vector(*self.box_anchor)
+
+    def grow_box(self, x=0, y=0):
+        size = self.get_level_tile_size()
+        dsr = self.get_display_surface().get_rect()
+        self.box_corner.x += x
+        if self.box_corner.x < 0:
+            self.box_corner.x = 0
+        elif self.box_corner.x >= dsr.right / size:
+            self.box_corner.x = dsr.right / size - 1
+        self.box_corner.y += y
+        if self.box_corner.y < 0:
+            self.box_corner.y = 0
+        elif self.box_corner.y >= dsr.bottom / size:
+            self.box_corner.y = dsr.bottom / size - 1
+        self.box.size = Vector((abs(self.box_corner.x - self.box_anchor.x) + 1) * size,
+                               (abs(self.box_corner.y - self.box_anchor.y) + 1) * size)
+        self.box.location.topleft = \
+            min(self.box_corner.x, self.box_anchor.x) * size, \
+            min(self.box_corner.y, self.box_anchor.y) * size
+
+    def move_box(self, x=0, y=0):
+        size = self.get_level_tile_size()
+        dsr = self.get_display_surface().get_rect()
+        self.box.move(x * size, y * size)
+        if self.box.location.right > dsr.right + self.box.thickness or \
+           self.box.location.left < -self.box.thickness:
+            self.box.move(dx=-x * dsr.w)
+        elif self.box.location.bottom > dsr.bottom + self.box.thickness or \
+             self.box.location.top < -self.box.thickness:
+            self.box.move(dy=-y * dsr.h)
+
+    def paint_tile(self):
+        original = self.get_current_tile()
+        scaled = self.get_current_level().tiles[self.tile_index]
+        x, y = self.brush_position
+        color = self.get_full_palette()[self.palette_index]
+        original.set_at((x, y), color)
+        scale = PictureProcessing.SCALE
+        scaled.fill(color, (x * scale, y * scale, scale, scale))
+        self.get_current_level().set_preview()
+
     def wrap_palette_index(self):
         count = self.get_palette_cell_count()
         if count % 2 and self.palette_index == count / 2:
@@ -534,14 +620,19 @@ class Editor(GameChild):
                         top = color_left_height * (self.palette_index - (length / 2 + length % 2))
                     self.palette_cursor.location.topleft = left - 1, palette_rect.top + top - 1
                     self.palette_cursor.update()
+            if self.at_box:
+                self.box.update()
 
     def get_full_palette(self):
         return self.default_palette + self.get_current_colors()
 
+    def get_current_tile(self):
+        return self.get_current_level().original_tiles[self.tile_index]
+
     def get_current_colors(self):
         colors = []
         if not self.add_tile_selected():
-            tile = self.get_current_level().original_tiles[self.tile_index]
+            tile = self.get_current_tile()
             for x in xrange(0, tile.get_width()):
                 for y in xrange(0, tile.get_height()):
                     color = tile.get_at((x, y))
@@ -559,6 +650,7 @@ class FlashingCursor(Sprite):
         self.set_flashing(flashing)
         self.set_size(width, height)
         self.hue = 0
+        self.thickness = self.THICKNESS
         self.set_frame()
 
     def set_flashing(self, state):
@@ -568,8 +660,7 @@ class FlashingCursor(Sprite):
         self.size = Vector(width, height)
 
     def set_frame(self):
-        thickness = self.THICKNESS
-        offset = thickness / 2
+        offset = self.thickness / 2
         surface = Surface((self.size.x + offset * 2, self.size.y + offset * 2))
         rect = offset, offset, self.size.x, self.size.y
         cursor = Sprite(self)
@@ -582,11 +673,14 @@ class FlashingCursor(Sprite):
             surface.fill((255, 0, 0))
             surface.set_colorkey((255, 0, 0))
             color = 0, 0, 0
-        draw.rect(surface, color, rect, thickness)
+        draw.rect(surface, color, rect, self.thickness)
         draw.rect(surface, (255, 255, 255), rect, 1)
         self.clear_frames()
         self.add_frame(surface)
 
+    def grow(self, dx=0, dy=0):
+        self.size += dx, dy
+
     def update(self):
         self.set_frame()
         Sprite.update(self)
@@ -845,6 +939,7 @@ class Level(Animation):
         self.original_tiles.append(surface)
         self.tiles.append(scale(surface, [surface.get_width() * \
                                           PictureProcessing.SCALE] * 2))
+        self.set_swap_status()
 
     def set_entire_grid(self, index=None):
         self.grid = []