added count of similar elements to element properties page in level editor
[rocksndiamonds.git] / src / editor.c
index b202aaf890b047abf42b8dee34dd4e30ccb8cafc..8f4a9d1ecfb81dc228723bae53935bc7bc05327e 100644 (file)
@@ -687,6 +687,8 @@ enum
   GADGET_ID_DF_LASER_RED,
   GADGET_ID_DF_LASER_GREEN,
   GADGET_ID_DF_LASER_BLUE,
+  GADGET_ID_ROTATE_MM_BALL_CONTENT,
+  GADGET_ID_EXPLODE_MM_BALL,
   GADGET_ID_CUSTOM_INDESTRUCTIBLE,
   GADGET_ID_CUSTOM_CAN_EXPLODE,
   GADGET_ID_CUSTOM_EXPLODE_FIRE,
@@ -1000,6 +1002,8 @@ enum
   ED_CHECKBUTTON_ID_DF_LASER_RED,
   ED_CHECKBUTTON_ID_DF_LASER_GREEN,
   ED_CHECKBUTTON_ID_DF_LASER_BLUE,
+  ED_CHECKBUTTON_ID_ROTATE_MM_BALL_CONTENT,
+  ED_CHECKBUTTON_ID_EXPLODE_MM_BALL,
   ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC,
   ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE_1,
   ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE,
@@ -1759,7 +1763,7 @@ static struct
   int gadget_id;
   int xsize, ysize;
   char *value;
-  char *text_above, *infotext;
+  char *text_above, *text_above_cropped, *infotext;
 } textarea_info[ED_NUM_TEXTAREAS] =
 {
   {
@@ -1767,7 +1771,7 @@ static struct
     GADGET_ID_ENVELOPE_INFO,
     MAX_ENVELOPE_XSIZE, MAX_ENVELOPE_YSIZE,
     NULL,
-    "Envelope Content:", "Envelope Content"
+    "Envelope Content:", "Envelope Content (cropped):", "Envelope Content"
   }
 };
 
@@ -3378,6 +3382,20 @@ static struct
     NULL, NULL,
     "blue",                            "use blue color components in laser"
   },
+  {
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(5),
+    GADGET_ID_ROTATE_MM_BALL_CONTENT,  GADGET_ID_NONE,
+    &level.rotate_mm_ball_content,
+    NULL, NULL,
+    "randomly rotate created content", "randomly rotate newly created content"
+  },
+  {
+    ED_ELEMENT_SETTINGS_XPOS(0),       ED_ELEMENT_SETTINGS_YPOS(6),
+    GADGET_ID_EXPLODE_MM_BALL,         GADGET_ID_NONE,
+    &level.explode_mm_ball,
+    NULL, NULL,
+    "explode ball instead of melting", "use explosion to release ball content"
+  },
 
   // ---------- element settings: configure 1 (custom elements) ---------------
 
@@ -7509,9 +7527,13 @@ static void MapTextAreaGadget(int id)
   int yoffset_above = font_height + ED_GADGET_LINE_DISTANCE;
   int x_above = ED_SETTINGS_X(textarea_info[id].x);
   int y_above = ED_SETTINGS_Y(textarea_info[id].y) - yoffset_above;
+  char *text_above = textarea_info[id].text_above;
+
+  if (gi->textarea.cropped && textarea_info[id].text_above_cropped)
+    text_above = textarea_info[id].text_above_cropped;
 
-  if (textarea_info[id].text_above)
-    DrawTextS(x_above, y_above, font_nr, textarea_info[id].text_above);
+  if (text_above)
+    DrawTextS(x_above, y_above, font_nr, text_above);
 
   ModifyGadget(gi, GDI_TEXT_VALUE, textarea_info[id].value, GDI_END);
 
@@ -9649,7 +9671,9 @@ static void DrawEnvelopeTextArea(int envelope_nr)
   struct GadgetInfo *gi = level_editor_gadget[textarea_info[id].gadget_id];
 
   UnmapGadget(gi);
-  DrawBackground(gi->x, gi->y, gi->width, gi->height);
+
+  DrawBackground(gi->x, gi->y,
+                gi->textarea.crop_width, gi->textarea.crop_height);
 
   if (envelope_nr != -1)
     textarea_info[id].value = level.envelope[envelope_nr].text;
@@ -9723,13 +9747,15 @@ static void DrawPropertiesInfo(void)
     { -1,                      NULL                                    }
   };
   char *filename = getElementDescriptionFilename(properties_element);
-  char *percentage_text = "In this level: ";
+  char *num_elements_text = "In this level: ";
+  char *num_similar_text = "Similar tiles: ";
   char *properties_text = "Standard properties: ";
   char *description_text = "Description:";
   char *no_description_text = "No description available.";
   char *none_text = "None";
   float percentage;
   int num_elements_in_level;
+  int num_similar_in_level;
   int num_standard_properties = 0;
   int font1_nr = FONT_TEXT_1;
   int font2_nr = FONT_TEXT_2;
@@ -9738,7 +9764,8 @@ static void DrawPropertiesInfo(void)
   int font2_height = getFontHeight(font2_nr);
   int line1_height = font1_height + ED_GADGET_LINE_DISTANCE;
   int font2_yoffset = (font1_height - font2_height) / 2;
-  int percentage_text_len = strlen(percentage_text) * font1_width;
+  int num_elements_text_len = strlen(num_elements_text) * font1_width;
+  int num_similar_text_len = strlen(num_similar_text) * font1_width;
   int properties_text_len = strlen(properties_text) * font1_width;
   int xpos = ED_ELEMENT_SETTINGS_X(0);
   int ypos = ED_ELEMENT_SETTINGS_Y(0) + ED_GADGET_SMALL_DISTANCE;
@@ -9764,15 +9791,40 @@ static void DrawPropertiesInfo(void)
        num_elements_in_level++;
   percentage = num_elements_in_level * 100.0 / (lev_fieldx * lev_fieldy);
 
-  DrawTextS(xpos, ypos, font1_nr, percentage_text);
+  DrawTextS(xpos, ypos, font1_nr, num_elements_text);
 
   if (num_elements_in_level > 0)
-    DrawTextF(xpos + percentage_text_len, ypos + font2_yoffset, font2_nr,
+    DrawTextF(xpos + num_elements_text_len, ypos + font2_yoffset, font2_nr,
              "%d (%.2f %%)", num_elements_in_level, percentage);
   else
-    DrawTextF(xpos + percentage_text_len, ypos + font2_yoffset, font2_nr,
+    DrawTextF(xpos + num_elements_text_len, ypos + font2_yoffset, font2_nr,
              none_text);
 
+  // ----- print number of similar elements / percentage of them in level
+
+  num_similar_in_level = 0;
+  for (y = 0; y < lev_fieldy; y++)
+    for (x = 0; x < lev_fieldx; x++)
+      if (strEqual(element_info[Tile[x][y]].class_name,
+                  element_info[properties_element].class_name))
+       num_similar_in_level++;
+
+  if (num_similar_in_level != num_elements_in_level)
+  {
+    ypos += 1 * MAX(font1_height, font2_height);
+
+    percentage = num_similar_in_level * 100.0 / (lev_fieldx * lev_fieldy);
+
+    DrawTextS(xpos, ypos, font1_nr, num_similar_text);
+
+    if (num_similar_in_level > 0)
+      DrawTextF(xpos + num_similar_text_len, ypos + font2_yoffset, font2_nr,
+               "%d (%.2f %%)", num_similar_in_level, percentage);
+    else
+      DrawTextF(xpos + num_similar_text_len, ypos + font2_yoffset, font2_nr,
+               none_text);
+  }
+
   ypos += 2 * MAX(font1_height, font2_height);
 
   // ----- print standard properties of this element
@@ -9821,6 +9873,7 @@ static void DrawPropertiesInfo(void)
 #define TEXT_DURATION          "Duration when activated"
 #define TEXT_DELAY_ON          "Delay before activating"
 #define TEXT_DELAY_OFF         "Delay before deactivating"
+#define TEXT_DELAY_CHANGING    "Delay before changing"
 #define TEXT_DELAY_EXPLODING   "Delay before exploding"
 #define TEXT_DELAY_MOVING      "Delay before moving"
 #define TEXT_BALL_DELAY                "Element generation delay"
@@ -9952,7 +10005,7 @@ static struct
   { EL_EMC_MAGNIFIER,  &level.magnify_time,            TEXT_DURATION   },
   { EL_MM_FUSE_ACTIVE, &level.mm_time_fuse,            TEXT_DELAY_OFF  },
   { EL_MM_BOMB,                &level.mm_time_bomb,            TEXT_DELAY_EXPLODING },
-  { EL_MM_GRAY_BALL,   &level.mm_time_ball,            TEXT_DELAY_ON   },
+  { EL_MM_GRAY_BALL,   &level.mm_time_ball,            TEXT_DELAY_CHANGING },
   { EL_MM_STEEL_BLOCK, &level.mm_time_block,           TEXT_DELAY_MOVING },
   { EL_MM_WOODEN_BLOCK,        &level.mm_time_block,           TEXT_DELAY_MOVING },
 
@@ -10131,6 +10184,8 @@ static void DrawPropertiesConfig(void)
     {
       MapCounterButtons(ED_COUNTER_ID_MM_BALL_CONTENT);
       MapSelectboxGadget(ED_SELECTBOX_ID_MM_BALL_CHOICE_MODE);
+      MapCheckbuttonGadget(ED_CHECKBUTTON_ID_ROTATE_MM_BALL_CONTENT);
+      MapCheckbuttonGadget(ED_CHECKBUTTON_ID_EXPLODE_MM_BALL);
 
       DrawMMBallContentArea();
     }
@@ -11109,7 +11164,7 @@ static void MergeAndCloseNeighbourElements(int x1, int y1, int *element1,
   SetElementSimple(x2, y2, *element2, change_level);
 }
 
-static void SetElementIntelliDraw(int x, int y, int new_element,
+static void SetElementIntelliDraw(int x, int y, int dx, int dy, int new_element,
                                  boolean change_level, int button)
 {
   struct XY *xy = xy_directions;
@@ -11881,7 +11936,10 @@ static void SetElementIntelliDraw(int x, int y, int new_element,
     }
   }
 
-  SetElementSimple(x, y, new_element, change_level);
+  if (IS_MM_WALL_EDITOR(new_element))
+    SetElementSimpleExt(x, y, dx, dy, new_element, change_level);
+  else
+    SetElementSimple(x, y, new_element, change_level);
 
   last_x = x;
   last_y = y;
@@ -11895,7 +11953,7 @@ static void ResetIntelliDraw(void)
     for (y = 0; y < lev_fieldy; y++)
       IntelliDrawBuffer[x][y] = Tile[x][y];
 
-  SetElementIntelliDraw(-1, -1, EL_UNDEFINED, FALSE, -1);
+  SetElementIntelliDraw(-1, -1, -1, -1, EL_UNDEFINED, FALSE, -1);
 }
 
 static boolean draw_mode_hires = FALSE;
@@ -11937,8 +11995,8 @@ static void SetElementExt(int x, int y, int dx, int dy, int element,
 {
   if (element < 0)
     SetElementSimple(x, y, Tile[x][y], change_level);
-  else if (GetKeyModState() & KMOD_Shift && !IS_MM_WALL_EDITOR(element))
-    SetElementIntelliDraw(x, y, element, change_level, button);
+  else if (GetKeyModState() & KMOD_Shift)
+    SetElementIntelliDraw(x, y, dx, dy, element, change_level, button);
   else
     SetElementSimpleExt(x, y, dx, dy, element, change_level);
 }
@@ -12979,6 +13037,10 @@ static void CopyLevelTemplateToUserLevelSet(char *levelset_subdir)
 static void HandleDrawingAreas(struct GadgetInfo *gi)
 {
   static boolean started_inside_drawing_area = FALSE;
+  static int last_sx = -1;
+  static int last_sy = -1;
+  static int last_sx2 = -1;
+  static int last_sy2 = -1;
   int id = gi->custom_id;
   int type_id = gi->custom_type_id;
   boolean button_press_event;
@@ -13042,10 +13104,6 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
 
   if (!button_press_event && !button_release_event)
   {
-    static int last_sx = -1;
-    static int last_sy = -1;
-    static int last_sx2 = -1;
-    static int last_sy2 = -1;
     int old_element = (IN_LEV_FIELD(lx, ly) ? Tile[lx][ly] : EL_UNDEFINED);
     boolean hires_drawing = (level.game_engine_type == GAME_ENGINE_TYPE_MM &&
                             isHiresTileElement(old_element) &&
@@ -13055,13 +13113,13 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
     if ((sx == last_sx && sy == last_sy && !hires_drawing) ||
        (sx2 == last_sx2 && sy2 == last_sy2))
       return;
-
-    last_sx = sx;
-    last_sy = sy;
-    last_sx2 = sx2;
-    last_sy2 = sy2;
   }
 
+  last_sx = sx;
+  last_sy = sy;
+  last_sx2 = sx2;
+  last_sy2 = sy2;
+
   if (button_press_event)
     started_inside_drawing_area = inside_drawing_area;