added editing empty space element settings in level editor
[rocksndiamonds.git] / src / editor.c
index 9fb3157e1f0bc922e6a0c0eee212335fdfca4d82..1fd4b463ce1280b3a93fdf5c69aa2aefac166ae0 100644 (file)
@@ -2009,6 +2009,9 @@ static struct ValueTextInfo options_change_direct_action[] =
   { CE_HEADLINE_SPECIAL_EVENTS,        "[mouse events]"                },
   { CE_CLICKED_BY_MOUSE,       "clicked by mouse"              },
   { CE_PRESSED_BY_MOUSE,       "pressed by mouse"              },
+  { CE_UNDEFINED,              " "                             },
+  { CE_HEADLINE_SPECIAL_EVENTS,        "[static states]"               },
+  { CE_NEXT_TO_PLAYER,         "next to player"                },
 
   { -1,                                NULL                            }
 };
@@ -2042,6 +2045,10 @@ static struct ValueTextInfo options_change_other_action[] =
   { CE_HEADLINE_SPECIAL_EVENTS,        "[mouse events]"                },
   { CE_MOUSE_CLICKED_ON_X,     "mouse clicked on"              },
   { CE_MOUSE_PRESSED_ON_X,     "mouse pressed on"              },
+  { CE_UNDEFINED,              " "                             },
+  { CE_HEADLINE_SPECIAL_EVENTS,        "[static states]"               },
+  { CE_PLAYER_NEXT_TO_X,       "player next to"                },
+  { CE_NEXT_TO_X,              "next to"                       },
 
   { -1,                                NULL                            }
 };
@@ -5265,6 +5272,41 @@ static int *editor_el_group_ptr = editor_el_group;
 static int num_editor_hl_group = ARRAY_SIZE(editor_hl_group);
 static int num_editor_el_group = ARRAY_SIZE(editor_el_group);
 
+static int editor_hl_empty_space[] =
+{
+  EL_INTERNAL_CASCADE_ES_ACTIVE,
+  EL_CHAR('E'),
+  EL_CHAR('S'),
+  EL_EMPTY,
+};
+
+static int editor_el_empty_space[] =
+{
+  EL_EMPTY_SPACE_1,
+  EL_EMPTY_SPACE_2,
+  EL_EMPTY_SPACE_3,
+  EL_EMPTY_SPACE_4,
+
+  EL_EMPTY_SPACE_5,
+  EL_EMPTY_SPACE_6,
+  EL_EMPTY_SPACE_7,
+  EL_EMPTY_SPACE_8,
+
+  EL_EMPTY_SPACE_9,
+  EL_EMPTY_SPACE_10,
+  EL_EMPTY_SPACE_11,
+  EL_EMPTY_SPACE_12,
+
+  EL_EMPTY_SPACE_13,
+  EL_EMPTY_SPACE_14,
+  EL_EMPTY_SPACE_15,
+  EL_EMPTY_SPACE_16
+};
+static int *editor_hl_empty_space_ptr = editor_hl_empty_space;
+static int *editor_el_empty_space_ptr = editor_el_empty_space;
+static int num_editor_hl_empty_space = ARRAY_SIZE(editor_hl_empty_space);
+static int num_editor_el_empty_space = ARRAY_SIZE(editor_el_empty_space);
+
 static int editor_hl_reference[] =
 {
   EL_INTERNAL_CASCADE_REF_ACTIVE,
@@ -5477,6 +5519,12 @@ editor_elements_info[] =
     &editor_hl_group_ptr,              &num_editor_hl_group,
     &editor_el_group_ptr,              &num_editor_el_group
   },
+  {
+    &setup_editor_el_custom,
+    &setup.editor_cascade.el_es,
+    &editor_hl_empty_space_ptr,                &num_editor_hl_empty_space,
+    &editor_el_empty_space_ptr,                &num_editor_el_empty_space
+  },
   {
     &setup_editor_el_custom,
     &setup.editor_cascade.el_ref,
@@ -8205,7 +8253,8 @@ static void CopyCustomElementPropertiesToEditor(int element)
 
   // set "change by direct action" selectbox help value
   custom_element_change.direct_action =
-    (HAS_CHANGE_EVENT(element, CE_TOUCHED_BY_PLAYER) ? CE_TOUCHED_BY_PLAYER :
+    (HAS_CHANGE_EVENT(element, CE_NEXT_TO_PLAYER) ? CE_NEXT_TO_PLAYER :
+     HAS_CHANGE_EVENT(element, CE_TOUCHED_BY_PLAYER) ? CE_TOUCHED_BY_PLAYER :
      HAS_CHANGE_EVENT(element, CE_PRESSED_BY_PLAYER) ? CE_PRESSED_BY_PLAYER :
      HAS_CHANGE_EVENT(element, CE_SWITCHED_BY_PLAYER) ? CE_SWITCHED_BY_PLAYER :
      HAS_CHANGE_EVENT(element, CE_SNAPPED_BY_PLAYER) ? CE_SNAPPED_BY_PLAYER :
@@ -8229,7 +8278,8 @@ static void CopyCustomElementPropertiesToEditor(int element)
 
   // set "change by other element action" selectbox help value
   custom_element_change.other_action =
-    (HAS_CHANGE_EVENT(element, CE_PLAYER_TOUCHES_X) ? CE_PLAYER_TOUCHES_X :
+    (HAS_CHANGE_EVENT(element, CE_PLAYER_NEXT_TO_X) ? CE_PLAYER_NEXT_TO_X :
+     HAS_CHANGE_EVENT(element, CE_PLAYER_TOUCHES_X) ? CE_PLAYER_TOUCHES_X :
      HAS_CHANGE_EVENT(element, CE_PLAYER_PRESSES_X) ? CE_PLAYER_PRESSES_X :
      HAS_CHANGE_EVENT(element, CE_PLAYER_SWITCHES_X) ? CE_PLAYER_SWITCHES_X :
      HAS_CHANGE_EVENT(element, CE_PLAYER_SNAPS_X) ? CE_PLAYER_SNAPS_X :
@@ -8239,6 +8289,7 @@ static void CopyCustomElementPropertiesToEditor(int element)
      HAS_CHANGE_EVENT(element, CE_PLAYER_DIGS_X) ? CE_PLAYER_DIGS_X :
      HAS_CHANGE_EVENT(element, CE_PLAYER_COLLECTS_X) ? CE_PLAYER_COLLECTS_X :
      HAS_CHANGE_EVENT(element, CE_PLAYER_DROPS_X) ? CE_PLAYER_DROPS_X :
+     HAS_CHANGE_EVENT(element, CE_NEXT_TO_X) ? CE_NEXT_TO_X :
      HAS_CHANGE_EVENT(element, CE_TOUCHING_X) ? CE_TOUCHING_X :
      HAS_CHANGE_EVENT(element, CE_HITTING_X) ? CE_HITTING_X :
      HAS_CHANGE_EVENT(element, CE_DIGGING_X) ? CE_DIGGING_X :
@@ -8263,9 +8314,14 @@ static void CopyGroupElementPropertiesToEditor(int element)
   custom_element = element_info[element];      // needed for description
 }
 
+static void CopyEmptyElementPropertiesToEditor(int element)
+{
+  custom_element = element_info[element];
+}
+
 static void CopyClassicElementPropertiesToEditor(int element)
 {
-  if (ELEM_IS_PLAYER(element) || COULD_MOVE_INTO_ACID(element))
+  if (IS_PLAYER_ELEMENT(element) || COULD_MOVE_INTO_ACID(element))
     custom_element_properties[EP_CAN_MOVE_INTO_ACID] =
       getMoveIntoAcidProperty(&level, element);
 
@@ -8280,6 +8336,8 @@ static void CopyElementPropertiesToEditor(int element)
     CopyCustomElementPropertiesToEditor(element);
   else if (IS_GROUP_ELEMENT(element))
     CopyGroupElementPropertiesToEditor(element);
+  else if (IS_EMPTY_ELEMENT(element))
+    CopyEmptyElementPropertiesToEditor(element);
   else
     CopyClassicElementPropertiesToEditor(element);
 }
@@ -8367,6 +8425,7 @@ static void CopyCustomElementPropertiesToGame(int element)
   // ---------- element settings: advanced (custom elements) ------------------
 
   // set player change event from checkbox and selectbox
+  custom_element_change_events[CE_NEXT_TO_PLAYER] = FALSE;
   custom_element_change_events[CE_TOUCHED_BY_PLAYER] = FALSE;
   custom_element_change_events[CE_PRESSED_BY_PLAYER] = FALSE;
   custom_element_change_events[CE_SWITCHED_BY_PLAYER] = FALSE;
@@ -8391,6 +8450,7 @@ static void CopyCustomElementPropertiesToGame(int element)
     custom_element_change_events[CE_BY_DIRECT_ACTION];
 
   // set other element action change event from checkbox and selectbox
+  custom_element_change_events[CE_PLAYER_NEXT_TO_X] = FALSE;
   custom_element_change_events[CE_PLAYER_TOUCHES_X] = FALSE;
   custom_element_change_events[CE_PLAYER_PRESSES_X] = FALSE;
   custom_element_change_events[CE_PLAYER_SWITCHES_X] = FALSE;
@@ -8401,6 +8461,7 @@ static void CopyCustomElementPropertiesToGame(int element)
   custom_element_change_events[CE_PLAYER_DIGS_X] = FALSE;
   custom_element_change_events[CE_PLAYER_COLLECTS_X] = FALSE;
   custom_element_change_events[CE_PLAYER_DROPS_X] = FALSE;
+  custom_element_change_events[CE_NEXT_TO_X] = FALSE;
   custom_element_change_events[CE_TOUCHING_X] = FALSE;
   custom_element_change_events[CE_HITTING_X] = FALSE;
   custom_element_change_events[CE_DIGGING_X] = FALSE;
@@ -8449,9 +8510,24 @@ static void CopyGroupElementPropertiesToGame(int element)
   InitElementPropertiesGfxElement();
 }
 
+static void CopyEmptyElementPropertiesToGame(int element)
+{
+  // mark that this empty element has been modified
+  custom_element.modified_settings = TRUE;
+  level.changed = TRUE;
+
+  if (level.use_custom_template)
+    AskToCopyAndModifyLevelTemplate();
+
+  element_info[element] = custom_element;
+
+  // needed here to restore runtime value "element_info[element].gfx_element"
+  InitElementPropertiesGfxElement();
+}
+
 static void CopyClassicElementPropertiesToGame(int element)
 {
-  if (ELEM_IS_PLAYER(element) || COULD_MOVE_INTO_ACID(element))
+  if (IS_PLAYER_ELEMENT(element) || COULD_MOVE_INTO_ACID(element))
     setMoveIntoAcidProperty(&level, element,
                            custom_element_properties[EP_CAN_MOVE_INTO_ACID]);
 
@@ -8466,6 +8542,8 @@ static void CopyElementPropertiesToGame(int element)
     CopyCustomElementPropertiesToGame(element);
   else if (IS_GROUP_ELEMENT(element))
     CopyGroupElementPropertiesToGame(element);
+  else if (IS_EMPTY_ELEMENT(element))
+    CopyEmptyElementPropertiesToGame(element);
   else
     CopyClassicElementPropertiesToGame(element);
 }
@@ -9121,7 +9199,7 @@ static void DrawPropertiesTabulatorGadgets(void)
   int i;
 
   // draw two config tabulators for player elements
-  if (ELEM_IS_PLAYER(properties_element))
+  if (IS_PLAYER_ELEMENT(properties_element))
     id_last = ED_TEXTBUTTON_ID_PROPERTIES_CONFIG_2;
 
   // draw two config and one "change" tabulator for custom elements
@@ -9136,7 +9214,7 @@ static void DrawPropertiesTabulatorGadgets(void)
 
     // use "config 1" and "config 2" instead of "config" for players and CEs
     if (i == ED_TEXTBUTTON_ID_PROPERTIES_CONFIG &&
-       (ELEM_IS_PLAYER(properties_element) ||
+       (IS_PLAYER_ELEMENT(properties_element) ||
         IS_CUSTOM_ELEMENT(properties_element)))
       continue;
 
@@ -9829,11 +9907,12 @@ static boolean checkPropertiesConfig(int element)
   if (IS_GEM(element) ||
       IS_CUSTOM_ELEMENT(element) ||
       IS_GROUP_ELEMENT(element) ||
+      IS_EMPTY_ELEMENT(element) ||
       IS_BALLOON_ELEMENT(element) ||
       IS_ENVELOPE(element) ||
       IS_MM_MCDUFFIN(element) ||
       IS_DF_LASER(element) ||
-      ELEM_IS_PLAYER(element) ||
+      IS_PLAYER_ELEMENT(element) ||
       HAS_EDITOR_CONTENT(element) ||
       CAN_GROW(element) ||
       COULD_MOVE_INTO_ACID(element) ||
@@ -9990,7 +10069,7 @@ static void DrawPropertiesConfig(void)
       DrawAndroidElementArea(properties_element);
   }
 
-  if (ELEM_IS_PLAYER(properties_element))
+  if (IS_PLAYER_ELEMENT(properties_element))
   {
     int player_nr = GET_PLAYER_NR(properties_element);
 
@@ -10070,7 +10149,7 @@ static void DrawPropertiesConfig(void)
     MapCheckbuttonGadget(ED_CHECKBUTTON_ID_EM_EXPLODES_BY_FIRE);
 
   if (COULD_MOVE_INTO_ACID(properties_element) &&
-      !ELEM_IS_PLAYER(properties_element) &&
+      !IS_PLAYER_ELEMENT(properties_element) &&
       (!IS_CUSTOM_ELEMENT(properties_element) ||
        edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_2))
   {
@@ -10252,6 +10331,23 @@ static void DrawPropertiesConfig(void)
 
     draw_footer_line = TRUE;
   }
+  else if (IS_EMPTY_ELEMENT(properties_element))
+  {
+    // draw stickybutton gadget
+    MapCheckbuttonGadget(ED_CHECKBUTTON_ID_STICK_ELEMENT);
+
+    // draw checkbutton gadgets
+    MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC);
+    MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE_1);
+
+    // draw textbutton gadgets
+    MapTextbuttonGadget(ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE_1);
+
+    // draw drawing area gadgets
+    MapDrawingArea(ED_DRAWING_ID_CUSTOM_GRAPHIC);
+
+    draw_footer_line = TRUE;
+  }
 
   // draw little footer border line above CE/GE use/save template gadgets
   if (draw_footer_line)
@@ -10408,12 +10504,12 @@ static void DrawPropertiesWindow(void)
     edit_mode_properties = ED_MODE_PROPERTIES_CONFIG_2;
 
   if (edit_mode_properties > ED_MODE_PROPERTIES_CONFIG &&
-      !ELEM_IS_PLAYER(properties_element) &&
+      !IS_PLAYER_ELEMENT(properties_element) &&
       !IS_CUSTOM_ELEMENT(properties_element))
     edit_mode_properties = ED_MODE_PROPERTIES_CONFIG;
 
   if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG &&
-      (ELEM_IS_PLAYER(properties_element) ||
+      (IS_PLAYER_ELEMENT(properties_element) ||
        IS_CUSTOM_ELEMENT(properties_element)))
     edit_mode_properties = ED_MODE_PROPERTIES_CONFIG_1;
 
@@ -12321,7 +12417,7 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
        {
          int element = Tile[x][y];
 
-         if (!IS_EM_ELEMENT(element) && !ELEM_IS_PLAYER(element))
+         if (!IS_EM_ELEMENT(element) && !IS_PLAYER_ELEMENT(element))
            use_em_engine = FALSE;
 
          if (!IS_SP_ELEMENT(element))
@@ -13004,7 +13100,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
        {
          SetDrawModeHiRes(new_element);
 
-         if (ELEM_IS_PLAYER(new_element))
+         if (IS_PLAYER_ELEMENT(new_element))
          {
            // remove player at old position
            for (y = 0; y < lev_fieldy; y++)
@@ -13013,7 +13109,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
              {
                int old_element = Tile[x][y];
 
-               if (ELEM_IS_PLAYER(old_element))
+               if (IS_PLAYER_ELEMENT(old_element))
                {
                  int replaced_with_element =
                    (old_element == EL_SOKOBAN_FIELD_PLAYER &&
@@ -13644,9 +13740,11 @@ static void HandleCheckbuttons(struct GadgetInfo *gi)
     boolean template_related_changes_found = FALSE;
     int i;
 
-    // check if any custom or group elements have been changed
+    // check if any custom, group or empty elements have been changed
     for (i = 0; i < NUM_FILE_ELEMENTS; i++)
-      if ((IS_CUSTOM_ELEMENT(i) || IS_GROUP_ELEMENT(i)) &&
+      if ((IS_CUSTOM_ELEMENT(i) ||
+          IS_GROUP_ELEMENT(i) ||
+          IS_EMPTY_ELEMENT(i)) &&
          element_info[i].modified_settings)
        template_related_changes_found = TRUE;