+ for (i=0; i < NUM_FILE_ELEMENTS; i++)
+ {
+ struct ElementInfo *ei = &element_info[i];
+
+ for(y=0; y<3; y++)
+ for(x=0; x<3; x++)
+ if (ei->content[x][y] == element_from)
+ ei->content[x][y] = element_to;
+
+ for (j=0; j < ei->num_change_pages; j++)
+ {
+ struct ElementChangeInfo *change = &ei->change_page[j];
+
+ if (change->target_element == element_from)
+ change->target_element = element_to;
+
+ if (change->trigger_element == element_from)
+ change->trigger_element = element_to;
+
+ for(y=0; y<3; y++)
+ for(x=0; x<3; x++)
+ if (change->content[x][y] == element_from)
+ change->content[x][y] = element_to;
+ }
+ }
+}
+
+static void replace_custom_element_in_playfield(int element_from,
+ int element_to)
+{
+ int x, y;
+
+ for(x=0; x < lev_fieldx; x++)
+ for(y=0; y < lev_fieldy; y++)
+ if (Feld[x][y] == element_from)
+ Feld[x][y] = element_to;
+}
+
+static void CopyCustomElement(int element_old, int element_new, int copy_mode)
+{
+ if (copy_mode == GADGET_ID_CUSTOM_COPY_FROM)
+ {
+ copy_custom_element_settings(element_new, element_old);
+ }
+ else if (copy_mode == GADGET_ID_CUSTOM_COPY_TO)
+ {
+ copy_custom_element_settings(element_old, element_new);
+ }
+ else if (copy_mode == GADGET_ID_CUSTOM_EXCHANGE)
+ {
+ copy_custom_element_settings(element_old, EL_DUMMY);
+ copy_custom_element_settings(element_new, element_old);
+ copy_custom_element_settings(EL_DUMMY, element_new);
+
+ replace_custom_element_in_settings(element_old, EL_DUMMY);
+ replace_custom_element_in_settings(element_new, element_old);
+ replace_custom_element_in_settings(EL_DUMMY, element_new);
+
+ replace_custom_element_in_playfield(element_old, EL_DUMMY);
+ replace_custom_element_in_playfield(element_new, element_old);
+ replace_custom_element_in_playfield(EL_DUMMY, element_new);
+ }
+
+ UpdateCustomElementGraphicGadgets();
+ DrawPropertiesWindow();
+}
+
+static void CopyCustomElementPropertiesToEditor(int element)
+{
+ int i;
+ int current_change_page = element_info[element].current_change_page;
+
+ /* dynamically (re)build selectbox for selecting change page */
+ for (i=0; i < element_info[element].num_change_pages; i++)
+ {
+ sprintf(options_change_page_strings[i], "%d", i + 1);
+
+ options_change_page[i].value = i;
+ options_change_page[i].text = options_change_page_strings[i];
+ }
+
+ options_change_page[i].value = -1;
+ options_change_page[i].text = NULL;
+
+ /* needed here to initialize combined element properties */
+ InitElementPropertiesEngine(level.game_version);
+
+ element_info[element].change =
+ &element_info[element].change_page[current_change_page];
+
+ custom_element = element_info[element];
+ custom_element_change = *element_info[element].change;
+
+ /* needed to initially set selectbox value variables to reliable defaults */
+ for (i=0; i < ED_NUM_SELECTBOX; i++)
+ setSelectboxValue(i, *selectbox_info[i].value);
+
+ for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
+ custom_element_properties[i] = HAS_PROPERTY(element, i);
+
+ for (i=0; i < NUM_CHANGE_EVENTS; i++)
+ custom_element_change_events[i] = HAS_CHANGE_EVENT(element, i);
+
+ /* ---------- element settings: configure (custom elements) ------------- */
+
+ /* set accessible layer selectbox help value */
+ custom_element.access_type =
+ (IS_WALKABLE(element) ? EP_WALKABLE :
+ IS_PASSABLE(element) ? EP_PASSABLE :
+ custom_element.access_type);
+ custom_element.access_layer =
+ (IS_ACCESSIBLE_OVER(element) ? EP_ACCESSIBLE_OVER :
+ IS_ACCESSIBLE_INSIDE(element) ? EP_ACCESSIBLE_INSIDE :
+ IS_ACCESSIBLE_UNDER(element) ? EP_ACCESSIBLE_UNDER :
+ custom_element.access_layer);
+ custom_element_properties[EP_ACCESSIBLE] =
+ (IS_ACCESSIBLE_OVER(element) ||
+ IS_ACCESSIBLE_INSIDE(element) ||
+ IS_ACCESSIBLE_UNDER(element));
+
+ /* set walk-to-object action selectbox help value */
+ custom_element.walk_to_action =
+ (IS_DIGGABLE(element) ? EP_DIGGABLE :
+ IS_COLLECTIBLE_ONLY(element) ? EP_COLLECTIBLE_ONLY :
+ IS_DROPPABLE(element) ? EP_DROPPABLE :
+ IS_PUSHABLE(element) ? EP_PUSHABLE :
+ custom_element.walk_to_action);
+ custom_element_properties[EP_WALK_TO_OBJECT] =
+ (IS_DIGGABLE(element) ||
+ IS_COLLECTIBLE_ONLY(element) ||
+ IS_DROPPABLE(element) ||
+ IS_PUSHABLE(element));
+
+ /* set smash targets selectbox help value */
+ custom_element.smash_targets =
+ (CAN_SMASH_EVERYTHING(element) ? EP_CAN_SMASH_EVERYTHING :
+ CAN_SMASH_ENEMIES(element) ? EP_CAN_SMASH_ENEMIES :
+ CAN_SMASH_PLAYER(element) ? EP_CAN_SMASH_PLAYER :
+ custom_element.smash_targets);
+ custom_element_properties[EP_CAN_SMASH] =
+ (CAN_SMASH_EVERYTHING(element) ||
+ CAN_SMASH_ENEMIES(element) ||
+ CAN_SMASH_PLAYER(element));
+
+ /* set deadliness selectbox help value */
+ custom_element.deadliness =
+ (DONT_TOUCH(element) ? EP_DONT_TOUCH :
+ DONT_COLLIDE_WITH(element) ? EP_DONT_COLLIDE_WITH :
+ DONT_RUN_INTO(element) ? EP_DONT_RUN_INTO :
+ custom_element.deadliness);
+ custom_element_properties[EP_DEADLY] =
+ (DONT_TOUCH(element) ||
+ DONT_COLLIDE_WITH(element) ||
+ DONT_RUN_INTO(element));
+
+ /* set consistency selectbox help value */
+ custom_element.consistency =
+ (IS_INDESTRUCTIBLE(element) ? EP_INDESTRUCTIBLE :
+ CAN_EXPLODE_1X1(element) ? EP_CAN_EXPLODE_1X1 :
+ CAN_EXPLODE_3X3(element) ? EP_CAN_EXPLODE_3X3 :
+ custom_element.consistency);
+ custom_element_properties[EP_EXPLODE_RESULT] =
+ (IS_INDESTRUCTIBLE(element) ||
+ CAN_EXPLODE_1X1(element) ||
+ CAN_EXPLODE_3X3(element));
+
+ /* special case: sub-settings dependent from main setting */
+ if (CAN_EXPLODE_BY_FIRE(element))
+ custom_element.can_explode_by_fire = TRUE;
+ if (CAN_EXPLODE_SMASHED(element))
+ custom_element.can_explode_smashed = TRUE;
+ if (CAN_EXPLODE_IMPACT(element))
+ custom_element.can_explode_impact = TRUE;
+
+ /* ---------- element settings: advanced (custom elements) --------------- */
+
+ /* 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_PRESSED_BY_PLAYER) ? CE_PRESSED_BY_PLAYER :
+ HAS_CHANGE_EVENT(element, CE_PUSHED_BY_PLAYER) ? CE_PUSHED_BY_PLAYER :
+ HAS_CHANGE_EVENT(element, CE_ENTERED_BY_PLAYER) ? CE_ENTERED_BY_PLAYER :
+ HAS_CHANGE_EVENT(element, CE_LEFT_BY_PLAYER) ? CE_LEFT_BY_PLAYER :
+ HAS_CHANGE_EVENT(element, CE_DROPPED_BY_PLAYER) ? CE_DROPPED_BY_PLAYER :
+ HAS_CHANGE_EVENT(element, CE_SWITCHED) ? CE_SWITCHED :
+ HAS_CHANGE_EVENT(element, CE_COLLISION) ? CE_COLLISION :
+ HAS_CHANGE_EVENT(element, CE_IMPACT) ? CE_IMPACT :
+ HAS_CHANGE_EVENT(element, CE_SMASHED) ? CE_SMASHED :
+ custom_element_change.direct_action);
+
+ /* set "change by other element action" selectbox help value */
+ custom_element_change.other_action =
+ (HAS_CHANGE_EVENT(element, CE_OTHER_GETS_TOUCHED) ? CE_OTHER_GETS_TOUCHED :
+ HAS_CHANGE_EVENT(element, CE_OTHER_GETS_PRESSED) ? CE_OTHER_GETS_PRESSED :
+ HAS_CHANGE_EVENT(element, CE_OTHER_GETS_PUSHED) ? CE_OTHER_GETS_PUSHED :
+ HAS_CHANGE_EVENT(element, CE_OTHER_GETS_ENTERED) ? CE_OTHER_GETS_ENTERED :
+ HAS_CHANGE_EVENT(element, CE_OTHER_GETS_LEFT) ? CE_OTHER_GETS_LEFT :
+ HAS_CHANGE_EVENT(element, CE_OTHER_GETS_DIGGED) ? CE_OTHER_GETS_DIGGED :
+ HAS_CHANGE_EVENT(element, CE_OTHER_GETS_COLLECTED) ? CE_OTHER_GETS_COLLECTED :
+ HAS_CHANGE_EVENT(element, CE_OTHER_GETS_DROPPED) ? CE_OTHER_GETS_DROPPED :
+ HAS_CHANGE_EVENT(element, CE_OTHER_IS_TOUCHING) ? CE_OTHER_IS_TOUCHING :
+ HAS_CHANGE_EVENT(element, CE_OTHER_IS_SWITCHING) ? CE_OTHER_IS_SWITCHING :
+ HAS_CHANGE_EVENT(element, CE_OTHER_IS_CHANGING) ? CE_OTHER_IS_CHANGING :
+ HAS_CHANGE_EVENT(element, CE_OTHER_IS_EXPLODING) ? CE_OTHER_IS_EXPLODING :
+ custom_element_change.other_action);
+}
+
+static void CopyCustomElementPropertiesToGame(int element)
+{
+ int i;
+ int access_type_and_layer;
+
+ /* mark that this custom element has been modified */
+ custom_element.modified_settings = TRUE;
+
+ if (level.use_custom_template)
+ {
+ if (Request("Copy and modify level tem- plate ?", REQ_ASK))
+ {
+ level.use_custom_template = FALSE;
+ ModifyGadget(level_editor_gadget[GADGET_ID_CUSTOM_USE_TEMPLATE],
+ GDI_CHECKED, FALSE, GDI_END);
+ }
+ else
+ {
+ LoadLevelTemplate(-1); /* this resets all element modifications ... */
+
+ DrawEditModeWindow(); /* ... and copies them to 'custom_element' */
+ }
+ }
+
+ element_info[element] = custom_element;
+ *element_info[element].change = custom_element_change;
+
+ /* ---------- element settings: configure (custom elements) ------------- */
+
+ /* set accessible property from checkbox and selectbox */
+ custom_element_properties[EP_WALKABLE_OVER] = FALSE;
+ custom_element_properties[EP_WALKABLE_INSIDE] = FALSE;
+ custom_element_properties[EP_WALKABLE_UNDER] = FALSE;
+ custom_element_properties[EP_PASSABLE_OVER] = FALSE;
+ custom_element_properties[EP_PASSABLE_INSIDE] = FALSE;
+ custom_element_properties[EP_PASSABLE_UNDER] = FALSE;
+ access_type_and_layer = ((custom_element.access_type == EP_WALKABLE ?
+ EP_WALKABLE_OVER : EP_PASSABLE_OVER) +
+ (custom_element.access_layer - EP_ACCESSIBLE_OVER));
+ custom_element_properties[access_type_and_layer] =
+ custom_element_properties[EP_ACCESSIBLE];
+
+ /* set walk-to-object property from checkbox and selectbox */
+ custom_element_properties[EP_DIGGABLE] = FALSE;
+ custom_element_properties[EP_COLLECTIBLE_ONLY] = FALSE;
+ custom_element_properties[EP_DROPPABLE] = FALSE;
+ custom_element_properties[EP_PUSHABLE] = FALSE;
+ custom_element_properties[custom_element.walk_to_action] =
+ custom_element_properties[EP_WALK_TO_OBJECT];
+
+ /* set smash property from checkbox and selectbox */
+ custom_element_properties[EP_CAN_SMASH_PLAYER] = FALSE;
+ custom_element_properties[EP_CAN_SMASH_ENEMIES] = FALSE;
+ custom_element_properties[EP_CAN_SMASH_EVERYTHING] = FALSE;
+ custom_element_properties[custom_element.smash_targets] =
+ custom_element_properties[EP_CAN_SMASH];
+
+ /* set deadliness property from checkbox and selectbox */
+ custom_element_properties[EP_DONT_RUN_INTO] = FALSE;
+ custom_element_properties[EP_DONT_COLLIDE_WITH] = FALSE;
+ custom_element_properties[EP_DONT_TOUCH] = FALSE;
+ custom_element_properties[custom_element.deadliness] =
+ custom_element_properties[EP_DEADLY];
+
+ /* set consistency property from checkbox and selectbox */
+ custom_element_properties[EP_INDESTRUCTIBLE] = FALSE;
+ custom_element_properties[EP_CAN_EXPLODE_1X1] = FALSE;
+ custom_element_properties[EP_CAN_EXPLODE_3X3] = FALSE;
+ custom_element_properties[EP_CAN_EXPLODE_BY_FIRE] = FALSE;
+ custom_element_properties[EP_CAN_EXPLODE_SMASHED] = FALSE;
+ custom_element_properties[EP_CAN_EXPLODE_IMPACT] = FALSE;
+ custom_element_properties[custom_element.consistency] =
+ custom_element_properties[EP_EXPLODE_RESULT];
+
+ /* special case: sub-settings dependent from main setting */
+ if (custom_element_properties[EP_CAN_EXPLODE_3X3] ||
+ custom_element_properties[EP_CAN_EXPLODE_1X1])
+ {
+ custom_element_properties[EP_CAN_EXPLODE_BY_FIRE] =
+ custom_element.can_explode_by_fire;
+ custom_element_properties[EP_CAN_EXPLODE_SMASHED] =
+ custom_element.can_explode_smashed;
+ custom_element_properties[EP_CAN_EXPLODE_IMPACT] =
+ custom_element.can_explode_impact;
+ }
+
+ /* ---------- element settings: advanced (custom elements) --------------- */
+
+ /* set player change event from checkbox and selectbox */
+ custom_element_change_events[CE_TOUCHED_BY_PLAYER] = FALSE;
+ custom_element_change_events[CE_PRESSED_BY_PLAYER] = FALSE;
+ custom_element_change_events[CE_PUSHED_BY_PLAYER] = FALSE;
+ custom_element_change_events[CE_ENTERED_BY_PLAYER] = FALSE;
+ custom_element_change_events[CE_LEFT_BY_PLAYER] = FALSE;
+ custom_element_change_events[CE_DROPPED_BY_PLAYER] = FALSE;
+ custom_element_change_events[CE_SWITCHED] = FALSE;
+ custom_element_change_events[CE_COLLISION] = FALSE;
+ custom_element_change_events[CE_IMPACT] = FALSE;
+ custom_element_change_events[CE_SMASHED] = FALSE;
+ custom_element_change_events[custom_element_change.direct_action] =
+ custom_element_change_events[CE_BY_DIRECT_ACTION];
+
+ /* set other element action change event from checkbox and selectbox */
+ custom_element_change_events[CE_OTHER_GETS_TOUCHED] = FALSE;
+ custom_element_change_events[CE_OTHER_GETS_PRESSED] = FALSE;
+ custom_element_change_events[CE_OTHER_GETS_PUSHED] = FALSE;
+ custom_element_change_events[CE_OTHER_GETS_ENTERED] = FALSE;
+ custom_element_change_events[CE_OTHER_GETS_LEFT] = FALSE;
+ custom_element_change_events[CE_OTHER_GETS_DIGGED] = FALSE;
+ custom_element_change_events[CE_OTHER_GETS_COLLECTED] = FALSE;
+ custom_element_change_events[CE_OTHER_GETS_DROPPED] = FALSE;
+ custom_element_change_events[CE_OTHER_IS_TOUCHING] = FALSE;
+ custom_element_change_events[CE_OTHER_IS_SWITCHING] = FALSE;
+ custom_element_change_events[CE_OTHER_IS_CHANGING] = FALSE;
+ custom_element_change_events[CE_OTHER_IS_EXPLODING] = FALSE;
+ custom_element_change_events[custom_element_change.other_action] =
+ custom_element_change_events[CE_BY_OTHER_ACTION];
+
+ for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
+ SET_PROPERTY(element, i, custom_element_properties[i]);
+
+ for (i=0; i < NUM_CHANGE_EVENTS; i++)
+ SET_CHANGE_EVENT(element, i, custom_element_change_events[i]);
+
+ /* copy change events also to special level editor variable */
+ custom_element = element_info[element];
+ custom_element_change = *element_info[element].change;
+}
+
+void DrawLevelEd()
+{
+ CloseDoor(DOOR_CLOSE_ALL);
+ OpenDoor(DOOR_OPEN_2 | DOOR_NO_DELAY);
+
+ if (level_editor_test_game)
+ {
+ CopyPlayfield(level.field, Feld);
+ CopyPlayfield(FieldBackup, level.field);
+
+ level_editor_test_game = FALSE;
+ }
+ else
+ {
+ edit_mode = ED_MODE_DRAWING;
+ edit_mode_properties = ED_MODE_PROPERTIES_INFO;
+
+ ResetUndoBuffer();
+
+ level_xpos = -1;
+ level_ypos = -1;
+ }
+
+ /* copy default editor door content to main double buffer */
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ DOOR_GFX_PAGEX6, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
+
+#if 0
+ /* draw mouse button brush elements */
+ RedrawDrawingElements();
+#endif
+
+ /* draw bigger door */
+ DrawSpecialEditorDoor();
+
+ /* draw new control window */
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ DOOR_GFX_PAGEX8, 236, EXSIZE, EYSIZE, EX, EY);
+
+ redraw_mask |= REDRAW_ALL;
+
+ ReinitializeElementListButtons(); /* only needed after setup changes */
+#if 0
+ ModifyEditorElementList(); /* may be needed for custom elements */
+#endif
+
+ UnmapTapeButtons();
+ MapControlButtons();
+
+ DrawEditModeWindow();
+
+ /* copy actual editor door content to door double buffer for OpenDoor() */
+ BlitBitmap(drawto, bitmap_db_door,
+ DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+
+ OpenDoor(DOOR_OPEN_1);
+}
+
+static void AdjustDrawingAreaGadgets()
+{
+ int ed_xsize = lev_fieldx + 2;
+ int ed_ysize = lev_fieldy + 2;
+ int max_ed_fieldx = MAX_ED_FIELDX;
+ int max_ed_fieldy = MAX_ED_FIELDY;
+ boolean horizontal_scrollbar_needed;
+ boolean vertical_scrollbar_needed;
+ int x, y, width, height;
+ int xoffset, yoffset;
+
+ /* check if we need any scrollbars */
+ horizontal_scrollbar_needed = (ed_xsize > max_ed_fieldx);
+ vertical_scrollbar_needed = (ed_ysize > max_ed_fieldy);