added flipping and rotating tiles in brushes in level editor
authorHolger Schemel <info@artsoft.org>
Sun, 14 May 2023 22:04:43 +0000 (00:04 +0200)
committerHolger Schemel <info@artsoft.org>
Sun, 14 May 2023 22:04:43 +0000 (00:04 +0200)
src/editor.c
src/game_mm/export.h
src/game_mm/mm_tools.c

index b0eb01b412c6ce11fc00d46d090f616a2be70cfa..c01689237136127918ef39267e0e587b895e1c9f 100644 (file)
@@ -12356,10 +12356,308 @@ static void SelectArea(int from_x, int from_y, int to_x, int to_y,
                                 MAX_CB_NUM_LINES *     \
                                 MAX_CB_PART_SIZE)
 
-static short getFlippedTile(short tile, int mode)
+static int getFlippedTileX(int element)
 {
-  // flip tile (yet to be added)
-  return tile;
+  switch (element)
+  {
+    case EL_BD_BUTTERFLY_LEFT:         return EL_BD_BUTTERFLY_RIGHT;
+    case EL_BD_BUTTERFLY_RIGHT:                return EL_BD_BUTTERFLY_LEFT;
+
+    case EL_BD_FIREFLY_LEFT:           return EL_BD_FIREFLY_RIGHT;
+    case EL_BD_FIREFLY_RIGHT:          return EL_BD_FIREFLY_LEFT;
+
+    case EL_BUG_LEFT:                  return EL_BUG_RIGHT;
+    case EL_BUG_RIGHT:                 return EL_BUG_LEFT;
+
+    case EL_SPACESHIP_LEFT:            return EL_SPACESHIP_RIGHT;
+    case EL_SPACESHIP_RIGHT:           return EL_SPACESHIP_LEFT;
+
+    case EL_PACMAN_LEFT:               return EL_PACMAN_RIGHT;
+    case EL_PACMAN_RIGHT:              return EL_PACMAN_LEFT;
+
+    case EL_ARROW_LEFT:                        return EL_ARROW_RIGHT;
+    case EL_ARROW_RIGHT:               return EL_ARROW_LEFT;
+
+    case EL_MOLE_LEFT:                 return EL_MOLE_RIGHT;
+    case EL_MOLE_RIGHT:                        return EL_MOLE_LEFT;
+
+    case EL_BALLOON_SWITCH_LEFT:       return EL_BALLOON_SWITCH_RIGHT;
+    case EL_BALLOON_SWITCH_RIGHT:      return EL_BALLOON_SWITCH_LEFT;
+
+    case EL_YAMYAM_LEFT:               return EL_YAMYAM_RIGHT;
+    case EL_YAMYAM_RIGHT:              return EL_YAMYAM_LEFT;
+
+    case EL_SP_PORT_LEFT:              return EL_SP_PORT_RIGHT;
+    case EL_SP_PORT_RIGHT:             return EL_SP_PORT_LEFT;
+
+    case EL_SP_GRAVITY_PORT_LEFT:      return EL_SP_GRAVITY_PORT_RIGHT;
+    case EL_SP_GRAVITY_PORT_RIGHT:     return EL_SP_GRAVITY_PORT_LEFT;
+
+    case EL_SP_GRAVITY_ON_PORT_LEFT:   return EL_SP_GRAVITY_ON_PORT_RIGHT;
+    case EL_SP_GRAVITY_ON_PORT_RIGHT:  return EL_SP_GRAVITY_ON_PORT_LEFT;
+
+    case EL_SP_GRAVITY_OFF_PORT_LEFT:  return EL_SP_GRAVITY_OFF_PORT_RIGHT;
+    case EL_SP_GRAVITY_OFF_PORT_RIGHT: return EL_SP_GRAVITY_OFF_PORT_LEFT;
+
+    case EL_CONVEYOR_BELT_1_LEFT:      return EL_CONVEYOR_BELT_1_RIGHT;
+    case EL_CONVEYOR_BELT_1_RIGHT:     return EL_CONVEYOR_BELT_1_LEFT;
+
+    case EL_CONVEYOR_BELT_2_LEFT:      return EL_CONVEYOR_BELT_2_RIGHT;
+    case EL_CONVEYOR_BELT_2_RIGHT:     return EL_CONVEYOR_BELT_2_LEFT;
+
+    case EL_CONVEYOR_BELT_3_LEFT:      return EL_CONVEYOR_BELT_3_RIGHT;
+    case EL_CONVEYOR_BELT_3_RIGHT:     return EL_CONVEYOR_BELT_3_LEFT;
+
+    case EL_CONVEYOR_BELT_4_LEFT:      return EL_CONVEYOR_BELT_4_RIGHT;
+    case EL_CONVEYOR_BELT_4_RIGHT:     return EL_CONVEYOR_BELT_4_LEFT;
+
+    case EL_SPRING_LEFT:               return EL_SPRING_RIGHT;
+    case EL_SPRING_RIGHT:              return EL_SPRING_LEFT;
+
+    case EL_SP_CHIP_LEFT:              return EL_SP_CHIP_RIGHT;
+    case EL_SP_CHIP_RIGHT:             return EL_SP_CHIP_LEFT;
+
+    case EL_TUBE_VERTICAL_LEFT:                return EL_TUBE_VERTICAL_RIGHT;
+    case EL_TUBE_VERTICAL_RIGHT:       return EL_TUBE_VERTICAL_LEFT;
+    case EL_TUBE_LEFT_UP:              return EL_TUBE_RIGHT_UP;
+    case EL_TUBE_LEFT_DOWN:            return EL_TUBE_RIGHT_DOWN;
+    case EL_TUBE_RIGHT_UP:             return EL_TUBE_LEFT_UP;
+    case EL_TUBE_RIGHT_DOWN:           return EL_TUBE_LEFT_DOWN;
+
+    case EL_DC_STEELWALL_1_LEFT:       return EL_DC_STEELWALL_1_RIGHT;
+    case EL_DC_STEELWALL_1_RIGHT:      return EL_DC_STEELWALL_1_LEFT;
+    case EL_DC_STEELWALL_1_TOPLEFT:    return EL_DC_STEELWALL_1_TOPRIGHT;
+    case EL_DC_STEELWALL_1_TOPRIGHT:   return EL_DC_STEELWALL_1_TOPLEFT;
+    case EL_DC_STEELWALL_1_BOTTOMLEFT: return EL_DC_STEELWALL_1_BOTTOMRIGHT;
+    case EL_DC_STEELWALL_1_BOTTOMRIGHT:        return EL_DC_STEELWALL_1_BOTTOMLEFT;
+    case EL_DC_STEELWALL_1_TOPLEFT_2:  return EL_DC_STEELWALL_1_TOPRIGHT_2;
+    case EL_DC_STEELWALL_1_TOPRIGHT_2: return EL_DC_STEELWALL_1_TOPLEFT_2;
+    case EL_DC_STEELWALL_1_BOTTOMLEFT_2: return EL_DC_STEELWALL_1_BOTTOMRIGHT_2;
+    case EL_DC_STEELWALL_1_BOTTOMRIGHT_2: return EL_DC_STEELWALL_1_BOTTOMLEFT_2;
+
+    case EL_DC_STEELWALL_2_LEFT:       return EL_DC_STEELWALL_2_RIGHT;
+    case EL_DC_STEELWALL_2_RIGHT:      return EL_DC_STEELWALL_2_LEFT;
+
+    case EL_ACID_POOL_TOPLEFT:         return EL_ACID_POOL_TOPRIGHT;
+    case EL_ACID_POOL_TOPRIGHT:                return EL_ACID_POOL_TOPLEFT;
+    case EL_ACID_POOL_BOTTOMLEFT:      return EL_ACID_POOL_BOTTOMRIGHT;
+    case EL_ACID_POOL_BOTTOMRIGHT:     return EL_ACID_POOL_BOTTOMLEFT;
+  }
+
+  return element;
+}
+
+static int getFlippedTileY(int element)
+{
+  switch (element)
+  {
+    case EL_BD_BUTTERFLY_UP:           return EL_BD_BUTTERFLY_DOWN;
+    case EL_BD_BUTTERFLY_DOWN:         return EL_BD_BUTTERFLY_UP;
+
+    case EL_BD_FIREFLY_UP:             return EL_BD_FIREFLY_DOWN;
+    case EL_BD_FIREFLY_DOWN:           return EL_BD_FIREFLY_UP;
+
+    case EL_BUG_UP:                    return EL_BUG_DOWN;
+    case EL_BUG_DOWN:                  return EL_BUG_UP;
+
+    case EL_SPACESHIP_UP:              return EL_SPACESHIP_DOWN;
+    case EL_SPACESHIP_DOWN:            return EL_SPACESHIP_UP;
+
+    case EL_PACMAN_UP:                 return EL_PACMAN_DOWN;
+    case EL_PACMAN_DOWN:               return EL_PACMAN_UP;
+
+    case EL_ARROW_UP:                  return EL_ARROW_DOWN;
+    case EL_ARROW_DOWN:                        return EL_ARROW_UP;
+
+    case EL_MOLE_UP:                   return EL_MOLE_DOWN;
+    case EL_MOLE_DOWN:                 return EL_MOLE_UP;
+
+    case EL_BALLOON_SWITCH_UP:         return EL_BALLOON_SWITCH_DOWN;
+    case EL_BALLOON_SWITCH_DOWN:       return EL_BALLOON_SWITCH_UP;
+
+    case EL_YAMYAM_UP:                 return EL_YAMYAM_DOWN;
+    case EL_YAMYAM_DOWN:               return EL_YAMYAM_UP;
+
+    case EL_SP_PORT_UP:                        return EL_SP_PORT_DOWN;
+    case EL_SP_PORT_DOWN:              return EL_SP_PORT_UP;
+
+    case EL_SP_GRAVITY_PORT_UP:                return EL_SP_GRAVITY_PORT_DOWN;
+    case EL_SP_GRAVITY_PORT_DOWN:      return EL_SP_GRAVITY_PORT_UP;
+
+    case EL_SP_GRAVITY_ON_PORT_UP:     return EL_SP_GRAVITY_ON_PORT_DOWN;
+    case EL_SP_GRAVITY_ON_PORT_DOWN:   return EL_SP_GRAVITY_ON_PORT_UP;
+
+    case EL_SP_GRAVITY_OFF_PORT_UP:    return EL_SP_GRAVITY_OFF_PORT_DOWN;
+    case EL_SP_GRAVITY_OFF_PORT_DOWN:  return EL_SP_GRAVITY_OFF_PORT_UP;
+
+    case EL_SP_CHIP_TOP:               return EL_SP_CHIP_BOTTOM;
+    case EL_SP_CHIP_BOTTOM:            return EL_SP_CHIP_TOP;
+
+    case EL_TUBE_HORIZONTAL_UP:                return EL_TUBE_HORIZONTAL_DOWN;
+    case EL_TUBE_HORIZONTAL_DOWN:      return EL_TUBE_HORIZONTAL_UP;
+    case EL_TUBE_LEFT_UP:              return EL_TUBE_LEFT_DOWN;
+    case EL_TUBE_LEFT_DOWN:            return EL_TUBE_LEFT_UP;
+    case EL_TUBE_RIGHT_UP:             return EL_TUBE_RIGHT_DOWN;
+    case EL_TUBE_RIGHT_DOWN:           return EL_TUBE_RIGHT_UP;
+
+    case EL_DC_STEELWALL_1_TOP:                return EL_DC_STEELWALL_1_BOTTOM;
+    case EL_DC_STEELWALL_1_BOTTOM:     return EL_DC_STEELWALL_1_TOP;
+    case EL_DC_STEELWALL_1_TOPLEFT:    return EL_DC_STEELWALL_1_BOTTOMLEFT;
+    case EL_DC_STEELWALL_1_TOPRIGHT:   return EL_DC_STEELWALL_1_BOTTOMRIGHT;
+    case EL_DC_STEELWALL_1_BOTTOMLEFT: return EL_DC_STEELWALL_1_TOPLEFT;
+    case EL_DC_STEELWALL_1_BOTTOMRIGHT:        return EL_DC_STEELWALL_1_TOPRIGHT;
+    case EL_DC_STEELWALL_1_TOPLEFT_2:  return EL_DC_STEELWALL_1_BOTTOMLEFT_2;
+    case EL_DC_STEELWALL_1_TOPRIGHT_2: return EL_DC_STEELWALL_1_BOTTOMRIGHT_2;
+    case EL_DC_STEELWALL_1_BOTTOMLEFT_2: return EL_DC_STEELWALL_1_TOPLEFT_2;
+    case EL_DC_STEELWALL_1_BOTTOMRIGHT_2: return EL_DC_STEELWALL_1_TOPRIGHT_2;
+
+    case EL_DC_STEELWALL_2_TOP:                return EL_DC_STEELWALL_2_BOTTOM;
+    case EL_DC_STEELWALL_2_BOTTOM:     return EL_DC_STEELWALL_2_TOP;
+
+    case EL_EMC_WALL_1:                        return EL_EMC_WALL_3;
+    case EL_EMC_WALL_3:                        return EL_EMC_WALL_1;
+  }
+
+  return element;
+}
+
+static int getFlippedTileXY(int element)
+{
+  switch (element)
+  {
+    case EL_BD_BUTTERFLY_LEFT:         return EL_BD_BUTTERFLY_UP;
+    case EL_BD_BUTTERFLY_RIGHT:                return EL_BD_BUTTERFLY_DOWN;
+    case EL_BD_BUTTERFLY_UP:           return EL_BD_BUTTERFLY_LEFT;
+    case EL_BD_BUTTERFLY_DOWN:         return EL_BD_BUTTERFLY_RIGHT;
+
+    case EL_BD_FIREFLY_LEFT:           return EL_BD_FIREFLY_UP;
+    case EL_BD_FIREFLY_RIGHT:          return EL_BD_FIREFLY_DOWN;
+    case EL_BD_FIREFLY_UP:             return EL_BD_FIREFLY_LEFT;
+    case EL_BD_FIREFLY_DOWN:           return EL_BD_FIREFLY_RIGHT;
+
+    case EL_BUG_LEFT:                  return EL_BUG_UP;
+    case EL_BUG_RIGHT:                 return EL_BUG_DOWN;
+    case EL_BUG_UP:                    return EL_BUG_LEFT;
+    case EL_BUG_DOWN:                  return EL_BUG_RIGHT;
+
+    case EL_SPACESHIP_LEFT:            return EL_SPACESHIP_UP;
+    case EL_SPACESHIP_RIGHT:           return EL_SPACESHIP_DOWN;
+    case EL_SPACESHIP_UP:              return EL_SPACESHIP_LEFT;
+    case EL_SPACESHIP_DOWN:            return EL_SPACESHIP_RIGHT;
+
+    case EL_PACMAN_LEFT:               return EL_PACMAN_UP;
+    case EL_PACMAN_RIGHT:              return EL_PACMAN_DOWN;
+    case EL_PACMAN_UP:                 return EL_PACMAN_LEFT;
+    case EL_PACMAN_DOWN:               return EL_PACMAN_RIGHT;
+
+    case EL_ARROW_LEFT:                        return EL_ARROW_UP;
+    case EL_ARROW_RIGHT:               return EL_ARROW_DOWN;
+    case EL_ARROW_UP:                  return EL_ARROW_LEFT;
+    case EL_ARROW_DOWN:                        return EL_ARROW_RIGHT;
+
+    case EL_MOLE_LEFT:                 return EL_MOLE_UP;
+    case EL_MOLE_RIGHT:                        return EL_MOLE_DOWN;
+    case EL_MOLE_UP:                   return EL_MOLE_LEFT;
+    case EL_MOLE_DOWN:                 return EL_MOLE_RIGHT;
+
+    case EL_BALLOON_SWITCH_LEFT:       return EL_BALLOON_SWITCH_UP;
+    case EL_BALLOON_SWITCH_RIGHT:      return EL_BALLOON_SWITCH_DOWN;
+    case EL_BALLOON_SWITCH_UP:         return EL_BALLOON_SWITCH_LEFT;
+    case EL_BALLOON_SWITCH_DOWN:       return EL_BALLOON_SWITCH_RIGHT;
+
+    case EL_YAMYAM_LEFT:               return EL_YAMYAM_UP;
+    case EL_YAMYAM_RIGHT:              return EL_YAMYAM_DOWN;
+    case EL_YAMYAM_UP:                 return EL_YAMYAM_LEFT;
+    case EL_YAMYAM_DOWN:               return EL_YAMYAM_RIGHT;
+
+    case EL_SP_PORT_LEFT:              return EL_SP_PORT_UP;
+    case EL_SP_PORT_RIGHT:             return EL_SP_PORT_DOWN;
+    case EL_SP_PORT_UP:                        return EL_SP_PORT_LEFT;
+    case EL_SP_PORT_DOWN:              return EL_SP_PORT_RIGHT;
+
+    case EL_SP_GRAVITY_PORT_LEFT:      return EL_SP_GRAVITY_PORT_UP;
+    case EL_SP_GRAVITY_PORT_RIGHT:     return EL_SP_GRAVITY_PORT_DOWN;
+    case EL_SP_GRAVITY_PORT_UP:                return EL_SP_GRAVITY_PORT_LEFT;
+    case EL_SP_GRAVITY_PORT_DOWN:      return EL_SP_GRAVITY_PORT_RIGHT;
+
+    case EL_SP_GRAVITY_ON_PORT_LEFT:   return EL_SP_GRAVITY_ON_PORT_UP;
+    case EL_SP_GRAVITY_ON_PORT_RIGHT:  return EL_SP_GRAVITY_ON_PORT_DOWN;
+    case EL_SP_GRAVITY_ON_PORT_UP:     return EL_SP_GRAVITY_ON_PORT_LEFT;
+    case EL_SP_GRAVITY_ON_PORT_DOWN:   return EL_SP_GRAVITY_ON_PORT_RIGHT;
+
+    case EL_SP_GRAVITY_OFF_PORT_LEFT:  return EL_SP_GRAVITY_OFF_PORT_UP;
+    case EL_SP_GRAVITY_OFF_PORT_RIGHT: return EL_SP_GRAVITY_OFF_PORT_DOWN;
+    case EL_SP_GRAVITY_OFF_PORT_UP:    return EL_SP_GRAVITY_OFF_PORT_LEFT;
+    case EL_SP_GRAVITY_OFF_PORT_DOWN:  return EL_SP_GRAVITY_OFF_PORT_RIGHT;
+
+    case EL_SP_CHIP_LEFT:              return EL_SP_CHIP_TOP;
+    case EL_SP_CHIP_RIGHT:             return EL_SP_CHIP_BOTTOM;
+    case EL_SP_CHIP_TOP:               return EL_SP_CHIP_LEFT;
+    case EL_SP_CHIP_BOTTOM:            return EL_SP_CHIP_RIGHT;
+
+    case EL_TUBE_VERTICAL:             return EL_TUBE_HORIZONTAL;
+    case EL_TUBE_HORIZONTAL:           return EL_TUBE_VERTICAL;
+    case EL_TUBE_VERTICAL_LEFT:                return EL_TUBE_HORIZONTAL_UP;
+    case EL_TUBE_VERTICAL_RIGHT:       return EL_TUBE_HORIZONTAL_DOWN;
+    case EL_TUBE_HORIZONTAL_UP:                return EL_TUBE_VERTICAL_LEFT;
+    case EL_TUBE_HORIZONTAL_DOWN:      return EL_TUBE_VERTICAL_RIGHT;
+    case EL_TUBE_LEFT_DOWN:            return EL_TUBE_RIGHT_UP;
+    case EL_TUBE_RIGHT_UP:             return EL_TUBE_LEFT_DOWN;
+
+    case EL_DC_STEELWALL_1_LEFT:       return EL_DC_STEELWALL_1_TOP;
+    case EL_DC_STEELWALL_1_RIGHT:      return EL_DC_STEELWALL_1_BOTTOM;
+    case EL_DC_STEELWALL_1_TOP:                return EL_DC_STEELWALL_1_LEFT;
+    case EL_DC_STEELWALL_1_BOTTOM:     return EL_DC_STEELWALL_1_RIGHT;
+    case EL_DC_STEELWALL_1_HORIZONTAL: return EL_DC_STEELWALL_1_VERTICAL;
+    case EL_DC_STEELWALL_1_VERTICAL:   return EL_DC_STEELWALL_1_HORIZONTAL;
+    case EL_DC_STEELWALL_1_TOPRIGHT:   return EL_DC_STEELWALL_1_BOTTOMLEFT;
+    case EL_DC_STEELWALL_1_BOTTOMLEFT: return EL_DC_STEELWALL_1_TOPRIGHT;
+    case EL_DC_STEELWALL_1_TOPRIGHT_2: return EL_DC_STEELWALL_1_BOTTOMLEFT_2;
+    case EL_DC_STEELWALL_1_BOTTOMLEFT_2: return EL_DC_STEELWALL_1_TOPRIGHT_2;
+
+    case EL_DC_STEELWALL_2_LEFT:       return EL_DC_STEELWALL_2_TOP;
+    case EL_DC_STEELWALL_2_RIGHT:      return EL_DC_STEELWALL_2_BOTTOM;
+    case EL_DC_STEELWALL_2_TOP:                return EL_DC_STEELWALL_2_LEFT;
+    case EL_DC_STEELWALL_2_BOTTOM:     return EL_DC_STEELWALL_2_RIGHT;
+    case EL_DC_STEELWALL_2_HORIZONTAL: return EL_DC_STEELWALL_2_VERTICAL;
+    case EL_DC_STEELWALL_2_VERTICAL:   return EL_DC_STEELWALL_2_HORIZONTAL;
+
+    case EL_EXPANDABLE_WALL_HORIZONTAL:        return EL_EXPANDABLE_WALL_VERTICAL;
+    case EL_EXPANDABLE_WALL_VERTICAL:  return EL_EXPANDABLE_WALL_HORIZONTAL;
+
+    case EL_EXPANDABLE_STEELWALL_HORIZONTAL:   return EL_EXPANDABLE_STEELWALL_VERTICAL;
+    case EL_EXPANDABLE_STEELWALL_VERTICAL:     return EL_EXPANDABLE_STEELWALL_HORIZONTAL;
+  }
+
+  return element;
+}
+
+static int getFlippedTile(int element, int mode)
+{
+  if (IS_MM_ELEMENT(element))
+  {
+    // get MM game element
+    element = map_element_RND_to_MM(element);
+
+    // get flipped game element
+    element = (mode == CB_FLIP_BRUSH_X  ? getFlippedTileX_MM(element) :
+              mode == CB_FLIP_BRUSH_Y  ? getFlippedTileY_MM(element) :
+              mode == CB_FLIP_BRUSH_XY ? getFlippedTileXY_MM(element) :
+              element);
+
+    // get RND game element again
+    element = map_element_MM_to_RND(element);
+  }
+  else
+  {
+    // get flipped game element
+    element = (mode == CB_FLIP_BRUSH_X  ? getFlippedTileX(element) :
+              mode == CB_FLIP_BRUSH_Y  ? getFlippedTileY(element) :
+              mode == CB_FLIP_BRUSH_XY ? getFlippedTileXY(element) :
+              element);
+  }
+
+  return element;
 }
 
 static void SwapFlippedTiles(short *tile1, short *tile2, int mode)
@@ -12736,7 +13034,7 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
   else if (mode == CB_FLIP_BRUSH_X)
   {
     for (y = 0; y < brush_height; y++)
-      for (x = 0; x < brush_width / 2; x++)
+      for (x = 0; x < (brush_width + 1) / 2; x++)
        SwapFlippedTiles(&brush_buffer[x][y],
                         &brush_buffer[brush_width - x - 1][y], mode);
 
@@ -12744,7 +13042,7 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
   }
   else if (mode == CB_FLIP_BRUSH_Y)
   {
-    for (y = 0; y < brush_height / 2; y++)
+    for (y = 0; y < (brush_height + 1) / 2; y++)
       for (x = 0; x < brush_width; x++)
        SwapFlippedTiles(&brush_buffer[x][y],
                         &brush_buffer[x][brush_height - y - 1], mode);
@@ -12755,8 +13053,8 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
   {
     CopyBrushExt(0, 0, 0, 0, 0, CB_DELETE_OLD_CURSOR);
 
-    for (y = 1; y < MAX(brush_width, brush_height); y++)
-      for (x = 0; x < y; x++)
+    for (y = 0; y < MAX(brush_width, brush_height); y++)
+      for (x = 0; x <= y; x++)
        SwapFlippedTiles(&brush_buffer[x][y],
                         &brush_buffer[y][x], mode);
 
index 11ee725812ad71272b5b37bfe2f738f08c22a2f0..184ce216cbbba739aac087e1e672cb05a4c44109 100644 (file)
@@ -252,6 +252,10 @@ void SaveNativeLevel_MM(char *);
 int getFieldbufferOffsetX_MM(void);
 int getFieldbufferOffsetY_MM(void);
 
+int getFlippedTileX_MM(int);
+int getFlippedTileY_MM(int);
+int getFlippedTileXY_MM(int);
+
 void BlitScreenToBitmap_MM(Bitmap *);
 void RedrawPlayfield_MM(void);
 
index 6a2067a43204cf7dd7b3d8a84f2c83aea8b7be69..aa9c2a5d0aab5cbdeed125d1961bdd6b7d417cc7 100644 (file)
@@ -1222,6 +1222,103 @@ int get_rotated_element(int element, int step)
   return base_element + (element_phase + step + num_elements) % num_elements;
 }
 
+static boolean has_full_rotation(int element)
+{
+  return (IS_BEAMER(element) ||
+         IS_MCDUFFIN(element) ||
+         IS_LASER(element) ||
+         IS_RECEIVER(element) ||
+         IS_PACMAN(element));
+}
+
+#define MM_FLIP_X                      0
+#define MM_FLIP_Y                      1
+#define MM_FLIP_XY                     2
+
+static int getFlippedTileExt_MM(int element, int mode)
+{
+  if (IS_WALL(element))
+  {
+    int base = WALL_BASE(element);
+    int bits = WALL_BITS(element);
+
+    if (mode == MM_FLIP_X)
+    {
+      bits = ((bits & 1) << 1 |
+             (bits & 2) >> 1 |
+             (bits & 4) << 1 |
+             (bits & 8) >> 1);
+    }
+    else if (mode == MM_FLIP_Y)
+    {
+      bits = ((bits & 1) << 2 |
+             (bits & 2) << 2 |
+             (bits & 4) >> 2 |
+             (bits & 8) >> 2);
+    }
+    else if (mode == MM_FLIP_XY)
+    {
+      bits = ((bits & 1) << 0 |
+             (bits & 2) << 1 |
+             (bits & 4) >> 1 |
+             (bits & 8) >> 0);
+    }
+
+    element = base | bits;
+  }
+  else
+  {
+    int base_element = get_base_element(element);
+    int num_elements = get_num_elements(element);
+    int element_phase = element - base_element;
+
+    if (IS_GRID_STEEL(element) || IS_GRID_WOOD(element))
+    {
+      if ((mode == MM_FLIP_XY && element_phase < 2) ||
+         (mode != MM_FLIP_XY && element_phase > 1))
+       element_phase ^= 1;
+    }
+    else
+    {
+      int num_elements_flip = num_elements;
+
+      if (has_full_rotation(element))
+      {
+       if (mode == MM_FLIP_X)
+         num_elements_flip = num_elements / 2;
+       else if (mode == MM_FLIP_XY)
+         num_elements_flip = num_elements * 3 / 4;
+      }
+      else
+      {
+       if (mode == MM_FLIP_XY)
+         num_elements_flip = num_elements / 2;
+      }
+
+      element_phase = num_elements_flip - element_phase;
+    }
+
+    element = base_element + (element_phase + num_elements) % num_elements;
+  }
+
+  return element;
+}
+
+int getFlippedTileX_MM(int element)
+{
+  return getFlippedTileExt_MM(element, MM_FLIP_X);
+}
+
+int getFlippedTileY_MM(int element)
+{
+  return getFlippedTileExt_MM(element, MM_FLIP_Y);
+}
+
+int getFlippedTileXY_MM(int element)
+{
+  return getFlippedTileExt_MM(element, MM_FLIP_XY);
+}
+
 int map_wall_from_base_element(int element)
 {
   switch (element)