+ if (suppressBorderElement())
+ {
+ ed_xsize = lev_fieldx;
+ ed_ysize = lev_fieldy;
+ }
+
+ // check if we need any scrollbars
+ horizontal_scrollbar_needed = (ed_xsize > max_ed_fieldx);
+ vertical_scrollbar_needed = (ed_ysize > max_ed_fieldy);
+
+ // check if we have a smaller editor field because of scrollbars
+ max_ed_fieldx = getMaxEdFieldX(vertical_scrollbar_needed);
+ max_ed_fieldy = getMaxEdFieldY(horizontal_scrollbar_needed);
+
+ // check again if we now need more scrollbars because of less space
+ horizontal_scrollbar_needed = (ed_xsize > max_ed_fieldx);
+ vertical_scrollbar_needed = (ed_ysize > max_ed_fieldy);
+
+ // check if editor field gets even smaller after adding new scrollbars
+ max_ed_fieldx = getMaxEdFieldX(vertical_scrollbar_needed);
+ max_ed_fieldy = getMaxEdFieldY(horizontal_scrollbar_needed);
+
+ ed_fieldx = (ed_xsize > max_ed_fieldx ? max_ed_fieldx : ed_xsize);
+ ed_fieldy = (ed_ysize > max_ed_fieldy ? max_ed_fieldy : ed_ysize);
+
+ x = SX + ed_fieldx * ed_tilesize;
+ y = SY + ed_fieldy * ed_tilesize;
+
+ width = ed_fieldx * ed_tilesize - 2 * ED_SCROLLBUTTON_XSIZE;
+ height = ed_fieldy * ed_tilesize - 2 * ED_SCROLLBUTTON_YSIZE;
+
+ // adjust drawing area gadget
+ ModifyGadget(level_editor_gadget[GADGET_ID_DRAWING_LEVEL],
+ GDI_AREA_SIZE, ed_fieldx, ed_fieldy,
+ GDI_ITEM_SIZE, ed_tilesize, ed_tilesize,
+ GDI_END);
+
+ // adjust horizontal scrollbar gadgets
+ ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_LEFT],
+ GDI_Y, y,
+ GDI_END);
+ ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_RIGHT],
+ GDI_X, x - ED_SCROLLBUTTON_XSIZE,
+ GDI_Y, y,
+ GDI_END);
+ ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_HORIZONTAL],
+ GDI_Y, y,
+ GDI_WIDTH, width,
+ GDI_SCROLLBAR_ITEMS_VISIBLE, ed_fieldx,
+ GDI_END);
+
+ // adjust vertical scrollbar gadgets
+ ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_UP],
+ GDI_X, x,
+ GDI_END);
+ ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_DOWN],
+ GDI_X, x,
+ GDI_Y, y - ED_SCROLLBUTTON_YSIZE,
+ GDI_END);
+ ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_VERTICAL],
+ GDI_X, x,
+ GDI_HEIGHT, height,
+ GDI_SCROLLBAR_ITEMS_VISIBLE, ed_fieldy,
+ GDI_END);
+}
+
+static void AdjustLevelScrollPosition(void)
+{
+ if (level_xpos < -1)
+ level_xpos = -1;
+ if (level_xpos > lev_fieldx - ed_fieldx + 1)
+ level_xpos = lev_fieldx - ed_fieldx + 1;
+ if (lev_fieldx < ed_fieldx - 2)
+ level_xpos = -1;
+
+ if (level_ypos < -1)
+ level_ypos = -1;
+ if (level_ypos > lev_fieldy - ed_fieldy + 1)
+ level_ypos = lev_fieldy - ed_fieldy + 1;
+ if (lev_fieldy < ed_fieldy - 2)
+ level_ypos = -1;
+
+ if (suppressBorderElement())
+ {
+ level_xpos = 0;
+ level_ypos = 0;
+ }
+}
+
+static void AdjustEditorScrollbar(int id)
+{
+ struct GadgetInfo *gi = level_editor_gadget[id];
+ int items_max, items_visible, item_position;
+
+ if (id == GADGET_ID_SCROLL_HORIZONTAL)
+ {
+ items_max = MAX(lev_fieldx + 2, ed_fieldx);
+ items_visible = ed_fieldx;
+ item_position = level_xpos + 1;
+ }
+ else
+ {
+ items_max = MAX(lev_fieldy + 2, ed_fieldy);
+ items_visible = ed_fieldy;
+ item_position = level_ypos + 1;
+ }
+
+ if (item_position > items_max - items_visible)
+ item_position = items_max - items_visible;
+
+ ModifyGadget(gi, GDI_SCROLLBAR_ITEMS_MAX, items_max,
+ GDI_SCROLLBAR_ITEM_POSITION, item_position, GDI_END);
+}
+
+static void AdjustElementListScrollbar(void)
+{
+ struct GadgetInfo *gi = level_editor_gadget[GADGET_ID_SCROLL_LIST_VERTICAL];
+ int items_max, items_visible, item_position;
+
+ // correct position of element list scrollbar
+ if (element_shift < 0)
+ element_shift = 0;
+ if (element_shift > num_editor_elements - ED_NUM_ELEMENTLIST_BUTTONS)
+ element_shift = num_editor_elements - ED_NUM_ELEMENTLIST_BUTTONS;
+
+ items_max = num_editor_elements / ED_ELEMENTLIST_BUTTONS_HORIZ;
+ items_visible = ED_ELEMENTLIST_BUTTONS_VERT;
+ item_position = element_shift / ED_ELEMENTLIST_BUTTONS_HORIZ;
+
+ ModifyGadget(gi, GDI_SCROLLBAR_ITEMS_MAX, items_max,
+ GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
+ GDI_SCROLLBAR_ITEM_POSITION, item_position, GDI_END);
+}
+
+static void ModifyEditorCounterValue(int counter_id, int new_value)
+{
+ int *counter_value = counterbutton_info[counter_id].value;
+ int gadget_id = counterbutton_info[counter_id].gadget_id_text;
+ struct GadgetInfo *gi = level_editor_gadget[gadget_id];
+
+ ModifyGadget(gi, GDI_NUMBER_VALUE, new_value, GDI_END);
+
+ if (counter_value != NULL)
+ *counter_value = gi->textinput.number_value;
+}
+
+static void ModifyEditorCounterLimits(int counter_id, int min, int max)
+{
+ int gadget_id = counterbutton_info[counter_id].gadget_id_text;
+ struct GadgetInfo *gi = level_editor_gadget[gadget_id];
+
+ ModifyGadget(gi, GDI_NUMBER_MIN, min, GDI_NUMBER_MAX, max, GDI_END);
+
+ if (counter_id >= ED_COUNTER_ID_ELEMENT_VALUE1 &&
+ counter_id <= ED_COUNTER_ID_ELEMENT_VALUE4)
+ {
+ int gadget_id_up = counterbutton_info[counter_id].gadget_id_up;
+ struct GadgetInfo *gi_up = level_editor_gadget[gadget_id_up];
+
+ ModifyGadget(gi, GDI_TEXT_SIZE, (max < 10 ? 1 : 3), GDI_END);
+ ModifyGadget(gi_up, GDI_X, gi->x + gi->width + ED_GADGET_SMALL_DISTANCE,
+ GDI_END);
+ }
+}
+
+static void ModifyEditorSelectboxValue(int selectbox_id, int new_value)
+{
+ int gadget_id = selectbox_info[selectbox_id].gadget_id;
+ struct GadgetInfo *gi = level_editor_gadget[gadget_id];
+ int new_index_value = setSelectboxValue(selectbox_id, new_value);
+
+ ModifyGadget(gi, GDI_SELECTBOX_INDEX, new_index_value, GDI_END);
+}
+
+static void ModifyEditorSelectboxOptions(int selectbox_id,
+ struct ValueTextInfo *options)
+{
+ int gadget_id = selectbox_info[selectbox_id].gadget_id;
+ struct GadgetInfo *gi = level_editor_gadget[gadget_id];
+
+ selectbox_info[selectbox_id].options = options;
+
+ // set index to zero -- list may be shorter now (correct later, if needed)
+ ModifyGadget(gi, GDI_SELECTBOX_INDEX, 0,
+ GDI_SELECTBOX_OPTIONS, options, GDI_END);
+}
+
+static void ModifyEditorDrawingArea(int drawingarea_id, int xsize, int ysize)
+{
+ int gadget_id = drawingarea_info[drawingarea_id].gadget_id;
+ struct GadgetInfo *gi = level_editor_gadget[gadget_id];
+
+ drawingarea_info[drawingarea_id].area_xsize = xsize;
+ drawingarea_info[drawingarea_id].area_ysize = ysize;
+
+ ModifyGadget(gi, GDI_AREA_SIZE, xsize, ysize, GDI_END);
+}
+
+static void ModifyEditorElementList(void)
+{
+ int i;
+
+ if (!use_permanent_palette && edit_mode != ED_MODE_PALETTE)
+ return;
+
+ for (i = 0; i < ED_NUM_ELEMENTLIST_BUTTONS; i++)
+ {
+ int gadget_id = GADGET_ID_ELEMENTLIST_FIRST + i;
+ struct GadgetInfo *gi = level_editor_gadget[gadget_id];
+ struct GadgetDesign *gd = &gi->deco.design;
+ int element = editor_elements[element_shift + i];
+ int tile_size = BUTTON_TILE_SIZE(editor.palette.tile_size);
+
+ UnmapGadget(gi);
+
+ getEditorGraphicSource(element, tile_size, &gd->bitmap, &gd->x, &gd->y);
+
+ ModifyGadget(gi, GDI_INFO_TEXT, getElementInfoText(element), GDI_END);
+
+ MapGadget(gi);
+ }
+}
+
+static void DrawDrawingElementGraphic(int element, struct XYTileSize *pos)
+{
+ int graphic = el2edimg(element);
+ int tile_size = BUTTON_TILE_SIZE(pos->tile_size);
+
+ if (pos->x == -1 &&
+ pos->y == -1)
+ return;
+
+ DrawSizedGraphicExt(drawto, DX + pos->x, DY + pos->y, graphic, 0, tile_size);
+}
+
+static void ModifyDrawingElementButton(int element, int id)
+{
+ struct GadgetInfo *gi = level_editor_gadget[id];
+ Bitmap *deco_bitmap;
+ int deco_x, deco_y;
+ int tile_size = gi->deco.width;
+
+ getEditorGraphicSource(element, tile_size, &deco_bitmap, &deco_x, &deco_y);
+
+ ModifyGadget(gi, GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y, GDI_END);
+}
+
+static void PickDrawingElement(int button, int element)
+{
+ struct
+ {
+ int *new_element;
+ struct XYTileSize *pos;
+ int id;
+ } de, drawing_elements[] =
+ {
+ { &new_element1, &editor.palette.element_left, GADGET_ID_ELEMENT_LEFT },
+ { &new_element2, &editor.palette.element_middle, GADGET_ID_ELEMENT_MIDDLE },
+ { &new_element3, &editor.palette.element_right, GADGET_ID_ELEMENT_RIGHT },
+ };
+
+ if (button < 1 || button > 3)
+ return;
+
+ if (IS_MM_WALL(element))
+ element = map_mm_wall_element(element);
+
+ de = drawing_elements[button - 1];
+
+ *de.new_element = element; // update global drawing element variable
+
+ DrawDrawingElementGraphic(element, de.pos);
+ ModifyDrawingElementButton(element, de.id);
+
+ redraw_mask |= REDRAW_DOOR_1;
+}
+
+static void RedrawDrawingElements(void)
+{
+ PickDrawingElement(1, new_element1);
+ PickDrawingElement(2, new_element2);
+ PickDrawingElement(3, new_element3);
+}
+
+static void DrawDrawingWindowExt(boolean remap_toolbox_gadgets)
+{
+ stick_element_properties_window = FALSE;
+
+ SetMainBackgroundImage(IMG_UNDEFINED);
+ ClearField();
+
+ UnmapLevelEditorFieldGadgets();
+
+ AdjustDrawingAreaGadgets();
+ AdjustLevelScrollPosition();
+ AdjustEditorScrollbar(GADGET_ID_SCROLL_HORIZONTAL);
+ AdjustEditorScrollbar(GADGET_ID_SCROLL_VERTICAL);
+
+ DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+
+ MapMainDrawingArea();
+
+ if (remap_toolbox_gadgets)
+ {
+ UnmapLevelEditorToolboxCustomGadgets();
+ MapLevelEditorToolboxDrawingGadgets();
+ }
+}
+
+static void DrawDrawingWindow(void)
+{
+ DrawDrawingWindowExt(TRUE);
+}
+
+static int getTabulatorBarWidth(void)
+{
+ struct GadgetInfo *gd_gi1 = level_editor_gadget[GADGET_ID_PROPERTIES_INFO];
+ struct GadgetInfo *gd_gi4 = level_editor_gadget[GADGET_ID_PROPERTIES_CHANGE];
+
+ return gd_gi4->x - gd_gi1->x + gd_gi4->width;
+}
+
+static int getTabulatorBarHeight(void)
+{
+ return ED_TAB_BAR_HEIGHT;
+}
+
+static Pixel getTabulatorBarColor(void)
+{
+ struct GadgetInfo *gd_gi1 = level_editor_gadget[GADGET_ID_LEVELCONFIG_LEVEL];
+ struct GadgetDesign *gd = &gd_gi1->alt_design[GD_BUTTON_UNPRESSED];
+ int gd_x = gd->x + gd_gi1->border.width / 2;
+ int gd_y = gd->y + gd_gi1->height - 1;
+
+ return GetPixel(gd->bitmap, gd_x, gd_y);
+}
+
+static void DrawEngineConfigTabulatorGadgets(void)
+{
+ struct GadgetInfo *gd_gi1 = level_editor_gadget[GADGET_ID_ENGINECONFIG_CONFIG];
+ Pixel tab_color = getTabulatorBarColor();
+ int id_first = ED_TEXTBUTTON_ID_ENGINECONFIG_CONFIG;
+ int id_last = ED_TEXTBUTTON_ID_ENGINECONFIG_COLORS;
+ int i;
+
+ for (i = id_first; i <= id_last; i++)
+ {
+ int gadget_id = textbutton_info[i].gadget_id;
+ struct GadgetInfo *gi = level_editor_gadget[gadget_id];
+ boolean active = (i != edit_mode_engineconfig);
+
+ // draw background line below tabulator button
+ ClearRectangleOnBackground(drawto, gi->x, gi->y + gi->height, gi->width, 1);
+
+ // draw solid line below inactive tabulator buttons
+ if (!active && tab_color != BLACK_PIXEL) // black => transparent
+ FillRectangle(drawto, gi->x, gi->y + gi->height, gi->width,
+ ED_GADGET_TINY_DISTANCE, tab_color);
+
+ ModifyGadget(gi, GDI_ACTIVE, active, GDI_END);
+ MapTextbuttonGadget(i);
+ }
+
+ // draw little border line below tabulator buttons
+ if (tab_color != BLACK_PIXEL) // black => transparent
+ FillRectangle(drawto, gd_gi1->x, gd_gi1->y + gd_gi1->height +
+ ED_GADGET_TINY_DISTANCE,
+ getTabulatorBarWidth(), getTabulatorBarHeight(), tab_color);
+}
+
+static void DrawLevelConfigTabulatorGadgets(void)
+{
+ struct GadgetInfo *gd_gi1 = level_editor_gadget[GADGET_ID_LEVELCONFIG_LEVEL];
+ Pixel tab_color = getTabulatorBarColor();
+ int id_first = ED_TEXTBUTTON_ID_LEVELCONFIG_LEVEL;
+ int id_last = ED_TEXTBUTTON_ID_LEVELCONFIG_EDITOR;
+ int i;
+
+ // draw additional "engine" tabulator when using native BD engine
+ if (level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ id_last = ED_TEXTBUTTON_ID_LEVELCONFIG_ENGINE;
+
+ for (i = id_first; i <= id_last; i++)
+ {
+ int gadget_id = textbutton_info[i].gadget_id;
+ struct GadgetInfo *gi = level_editor_gadget[gadget_id];
+ boolean active = (i != edit_mode_levelconfig);
+
+ // draw background line below tabulator button
+ ClearRectangleOnBackground(drawto, gi->x, gi->y + gi->height, gi->width, 1);
+
+ // draw solid line below inactive tabulator buttons
+ if (!active && tab_color != BLACK_PIXEL) // black => transparent
+ FillRectangle(drawto, gi->x, gi->y + gi->height, gi->width,
+ ED_GADGET_TINY_DISTANCE, tab_color);
+
+ ModifyGadget(gi, GDI_ACTIVE, active, GDI_END);
+ MapTextbuttonGadget(i);
+ }
+
+ // draw little border line below tabulator buttons
+ if (tab_color != BLACK_PIXEL) // black => transparent
+ FillRectangle(drawto, gd_gi1->x, gd_gi1->y + gd_gi1->height +
+ ED_GADGET_TINY_DISTANCE,
+ getTabulatorBarWidth(), getTabulatorBarHeight(), tab_color);
+
+ // draw second row of engine related tabulators when using native BD engine
+ if (edit_mode_levelconfig == ED_MODE_LEVELCONFIG_ENGINE)
+ DrawEngineConfigTabulatorGadgets();
+}
+
+static void DrawPropertiesTabulatorGadgets(void)
+{
+ struct GadgetInfo *gd_gi1 = level_editor_gadget[GADGET_ID_PROPERTIES_INFO];
+ struct GadgetDesign *gd = &gd_gi1->alt_design[GD_BUTTON_UNPRESSED];
+ int gd_x = gd->x + gd_gi1->border.width / 2;
+ int gd_y = gd->y + gd_gi1->height - 1;
+ Pixel tab_color = GetPixel(gd->bitmap, gd_x, gd_y);
+ int id_first = ED_TEXTBUTTON_ID_PROPERTIES_INFO;
+ int id_last = ED_TEXTBUTTON_ID_PROPERTIES_CONFIG;
+ int i;
+
+ // draw two config tabulators for player elements
+ if (IS_PLAYER_ELEMENT(properties_element))
+ id_last = ED_TEXTBUTTON_ID_PROPERTIES_CONFIG_2;
+
+ // draw two config and one "change" tabulator for custom elements
+ if (IS_CUSTOM_ELEMENT(properties_element))
+ id_last = ED_TEXTBUTTON_ID_PROPERTIES_CHANGE;
+
+ for (i = id_first; i <= id_last; i++)
+ {
+ int gadget_id = textbutton_info[i].gadget_id;
+ struct GadgetInfo *gi = level_editor_gadget[gadget_id];
+ boolean active = (i != edit_mode_properties);
+
+ // use "config 1" and "config 2" instead of "config" for players and CEs
+ if (i == ED_TEXTBUTTON_ID_PROPERTIES_CONFIG &&
+ (IS_PLAYER_ELEMENT(properties_element) ||
+ IS_CUSTOM_ELEMENT(properties_element)))
+ continue;
+
+ // draw background line below tabulator button
+ ClearRectangleOnBackground(drawto, gi->x, gi->y + gi->height, gi->width, 1);
+
+ // draw solid line below inactive tabulator buttons
+ if (!active && tab_color != BLACK_PIXEL) // black => transparent
+ FillRectangle(drawto, gi->x, gi->y + gi->height, gi->width,
+ ED_GADGET_TINY_DISTANCE, tab_color);
+
+ ModifyGadget(gi, GDI_ACTIVE, active, GDI_END);
+ MapTextbuttonGadget(i);
+ }
+
+ // draw little border line below tabulator buttons
+ if (tab_color != BLACK_PIXEL) // black => transparent
+ FillRectangle(drawto, gd_gi1->x, gd_gi1->y + gd_gi1->height +
+ ED_GADGET_TINY_DISTANCE,
+ getTabulatorBarWidth(), getTabulatorBarHeight(), tab_color);
+}
+
+static void PrintInfoText(char *text, int font_nr, int xpos, int ypos)
+{
+ DrawText(SX + xpos, SY + ypos, text, font_nr);
+}
+
+static int PrintElementDescriptionFromFile(char *filename, int font_nr,
+ int xpos, int ypos)
+{
+ int font_width = getFontWidth(font_nr);
+ int font_height = getFontHeight(font_nr);
+ int max_chars_per_line = (SXSIZE - 2 * xpos) / font_width;
+ int max_lines_drawable = (SYSIZE - ypos) / font_height - 1;
+
+ return DrawTextFile(SX + xpos, SY + ypos, filename, font_nr,
+ max_chars_per_line, -1, max_lines_drawable, 0, -1,
+ TRUE, FALSE, FALSE);
+}
+
+static void DrawLevelConfigLevel(void)
+{
+ int i;
+
+ // draw counter gadgets
+ for (i = ED_COUNTER_ID_LEVEL_FIRST; i <= ED_COUNTER_ID_LEVEL_LAST; i++)
+ MapCounterButtons(i);
+
+ // draw checkbutton gadgets
+ for (i = ED_CHECKBUTTON_ID_LEVEL_FIRST; i<= ED_CHECKBUTTON_ID_LEVEL_LAST; i++)
+ MapCheckbuttonGadget(i);
+
+ // draw selectbox gadgets
+ for (i = ED_SELECTBOX_ID_LEVEL_FIRST; i <= ED_SELECTBOX_ID_LEVEL_LAST; i++)
+ MapSelectboxGadget(i);
+
+ // draw text input gadgets
+ for (i = ED_TEXTINPUT_ID_LEVEL_FIRST; i <= ED_TEXTINPUT_ID_LEVEL_LAST; i++)
+ MapTextInputGadget(i);
+}
+
+static char *getLevelSubdirFromSaveMode(int save_mode)
+{
+ if (save_mode == LEVELSET_SAVE_MODE_CREATE)
+ return getNewUserLevelSubdir();
+
+ return leveldir_current->subdir;
+}
+
+static void DrawLevelConfigLevelSet_DirectoryInfo(void)
+{
+ char *directory_text = "Level set directory:";
+ char *directory_name = getLevelSubdirFromSaveMode(levelset_save_mode);
+ int font1_nr = FONT_TEXT_1;
+ int font2_nr = FONT_TEXT_2;
+ int font1_height = getFontHeight(font1_nr);
+ int yoffset_above = font1_height + ED_GADGET_LINE_DISTANCE;
+ int x = ED_LEVEL_SETTINGS_X(0);
+ int y = ED_LEVEL_SETTINGS_Y(6);
+
+ PrintInfoText(directory_text, font1_nr, x, y - yoffset_above);
+ PrintInfoText(directory_name, font2_nr, x, y);
+}
+
+static void DrawLevelConfigLevelSet(void)
+{
+ boolean artwork_exists = checkIfCustomArtworkExistsForCurrentLevelSet();
+ boolean template_exists = fileExists(getLocalLevelTemplateFilename());
+ int i;
+
+ // draw counter gadgets
+ for (i = ED_COUNTER_ID_LEVELSET_FIRST; i <= ED_COUNTER_ID_LEVELSET_LAST; i++)
+ MapCounterButtons(i);
+
+ // draw checkbutton gadgets
+ for (i = ED_CHECKBUTTON_ID_LEVELSET_FIRST; i <= ED_CHECKBUTTON_ID_LEVELSET_LAST; i++)
+ {
+ if (levelset_save_mode == LEVELSET_SAVE_MODE_UPDATE ||
+ (i == ED_CHECKBUTTON_ID_USE_LEVELSET_ARTWORK && !artwork_exists) ||
+ (i == ED_CHECKBUTTON_ID_COPY_LEVEL_TEMPLATE && !template_exists))
+ continue;
+
+ MapCheckbuttonGadget(i);
+ }
+
+ // draw selectbox gadgets
+ for (i = ED_SELECTBOX_ID_LEVELSET_FIRST; i <= ED_SELECTBOX_ID_LEVELSET_LAST; i++)
+ MapSelectboxGadget(i);
+
+ // draw text input gadgets
+ for (i = ED_TEXTINPUT_ID_LEVELSET_FIRST; i <= ED_TEXTINPUT_ID_LEVELSET_LAST; i++)
+ MapTextInputGadget(i);
+
+ // draw textbutton gadgets
+ MapTextbuttonGadget(ED_TEXTBUTTON_ID_SAVE_LEVELSET);
+
+ // draw info text
+ DrawLevelConfigLevelSet_DirectoryInfo();
+}
+
+static void DrawLevelConfigEditor(void)
+{
+ int i;
+
+ // draw counter gadgets
+ for (i = ED_COUNTER_ID_EDITOR_FIRST; i <= ED_COUNTER_ID_EDITOR_LAST; i++)
+ MapCounterButtons(i);
+
+ // draw checkbutton gadgets
+ for (i = ED_CHECKBUTTON_ID_EDITOR_FIRST; i <= ED_CHECKBUTTON_ID_EDITOR_LAST; i++)
+ MapCheckbuttonGadget(i);
+
+ // draw radiobutton gadgets
+ for (i = ED_RADIOBUTTON_ID_EDITOR_FIRST; i <= ED_RADIOBUTTON_ID_EDITOR_LAST; i++)
+ MapRadiobuttonGadget(i);
+
+ // draw drawing area
+ MapDrawingArea(ED_DRAWING_ID_RANDOM_BACKGROUND);
+
+ // draw textbutton gadgets
+ MapTextbuttonGadget(ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE_2);
+}
+
+static void DrawEngineConfigConfig(void)
+{
+ int i;
+
+ // draw counter gadgets
+ if (level.bd_scheduling_type == GD_SCHEDULING_MILLISECONDS)
+ {
+ MapCounterButtons(ED_COUNTER_ID_BD_CYCLE_DELAY_MS);
+ MapCounterButtons(ED_COUNTER_ID_BD_HATCHING_DELAY_CYCLES);
+ }
+ else
+ {
+ MapCounterButtons(ED_COUNTER_ID_BD_CYCLE_DELAY_C64);
+ MapCounterButtons(ED_COUNTER_ID_BD_HATCHING_DELAY_SECONDS);
+ }
+
+ // draw checkbutton gadgets
+ for (i = ED_CHECKBUTTON_ID_ENGINE_FIRST; i <= ED_CHECKBUTTON_ID_ENGINE_LAST; i++)
+ MapCheckbuttonGadget(i);
+
+ // draw selectbox gadgets
+ for (i = ED_SELECTBOX_ID_ENGINE_FIRST; i <= ED_SELECTBOX_ID_ENGINE_LAST; i++)
+ MapSelectboxGadget(i);
+}
+
+static int GetCommonColorType_BD(void)
+{
+ int bd_color_type = *bd_color[0] >> 24;
+ int i;
+
+ // check if all colors have the same color type
+ for (i = 1; i < MAX_BD_COLORS; i++)
+ if ((*bd_color[i] >> 24) != bd_color_type)
+ return GD_COLOR_TYPE_RGB;
+
+ return bd_color_type;
+}
+
+void SetDefaultLevelColorType_BD(void)
+{
+ bd_color_type_default = GetCommonColorType_BD();
+
+ level.bd_color_type = bd_color_type_default;
+}
+
+void SetDefaultLevelColors_BD(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_BD_COLORS; i++)
+ bd_color_default[i] = *bd_color[i];
+}
+
+void SetRandomLevelColors_BD(int bd_color_type)
+{
+ struct LevelInfo_BD *level_bd = level.native_bd_level;
+ GdCave *cave = level_bd->cave;
+
+ // create random cave colors
+ gd_cave_set_random_colors(cave, bd_color_type);
+
+ // copy colors to level editor
+ level.bd_color_b = cave->colorb;
+ level.bd_color_0 = cave->color0;
+ level.bd_color_1 = cave->color1;
+ level.bd_color_2 = cave->color2;
+ level.bd_color_3 = cave->color3;
+ level.bd_color_4 = cave->color4;
+ level.bd_color_5 = cave->color5;
+}
+
+static void DrawColorBox_BD(int nr)
+{
+ int id = ED_SELECTBOX_ID_COLORS_FIRST + nr;
+ struct GadgetInfo *gi = level_editor_gadget[selectbox_info[id].gadget_id];
+ int graphic = IMG_EDITOR_CHECKBOX;
+ struct GraphicInfo *gd = &graphic_info[graphic];
+ int offset = ED_GADGET_TEXT_DISTANCE;
+ int x1 = gi->x - offset - gd->width;
+ int y1 = gi->y;
+ int x2 = x1 + offset;
+ int y2 = y1 + offset;
+ int xsize1 = gd->width;
+ int ysize1 = gd->height;
+ int xsize2 = xsize1 - 2 * offset;
+ int ysize2 = ysize1 - 2 * offset;
+ int bd_color_x = *bd_color[nr];
+ int r = gd_color_get_r(bd_color_x);
+ int g = gd_color_get_g(bd_color_x);
+ int b = gd_color_get_b(bd_color_x);
+ Pixel color = SDL_MapRGB(drawto->surface->format, r, g, b);
+
+ BlitBitmap(gd->bitmap, drawto, gd->src_x, gd->src_y, xsize1, ysize1, x1, y1);
+ FillRectangle(drawto, x2, y2, xsize2, ysize2, color);
+}
+
+static void DrawEngineConfigColors(void)
+{
+ int i;
+
+ if (bd_color_type_changed)
+ {
+ if (level.bd_color_type != GD_COLOR_TYPE_RGB && level.bd_color_type != GetCommonColorType_BD())
+ {
+ // color type switched to non-RGB colors, but using different color type => reset colors
+
+ if (level.bd_color_type == bd_color_type_default)
+ {
+ // color type switched to same color type as default colors => reset to defaults
+ for (i = 0; i < MAX_BD_COLORS; i++)
+ *bd_color[i] = bd_color_default[i];
+ }
+ else
+ {
+ // color type switched to different color type as default colors => use random colors
+ SetRandomLevelColors_BD(level.bd_color_type);
+ }
+ }
+
+ bd_color_type_changed = FALSE;
+ }
+
+ // copy level colors to either C64-style color index or color text
+ for (i = 0; i < MAX_BD_COLORS; i++)
+ {
+ int bd_color_x = (level.bd_color_type == GD_COLOR_TYPE_C64 ? *bd_color[i] & 0x0f :
+ level.bd_color_type == GD_COLOR_TYPE_RGB ? gd_color_get_rgb(*bd_color[i]) :
+ *bd_color[i]);
+
+ if (level.bd_color_type == GD_COLOR_TYPE_C64)
+ bd_color_c64[i] = bd_color_x;
+ else
+ snprintf(bd_color_text[i], sizeof(bd_color_text[i]), "%s", gd_color_get_string(bd_color_x));
+ }
+
+ MapSelectboxGadget(ED_SELECTBOX_ID_BD_COLOR_TYPE);
+
+ if (level.bd_color_type == GD_COLOR_TYPE_C64)
+ {
+ // draw selectbox gadgets
+ for (i = ED_SELECTBOX_ID_COLORS_FIRST; i <= ED_SELECTBOX_ID_COLORS_LAST; i++)
+ MapSelectboxGadget(i);
+ }
+ else
+ {
+ // draw text input gadgets
+ for (i = ED_TEXTINPUT_ID_COLORS_FIRST; i <= ED_TEXTINPUT_ID_COLORS_LAST; i++)
+ MapTextInputGadget(i);
+ }
+
+ for (i = 0; i < MAX_BD_COLORS; i++)
+ DrawColorBox_BD(i);
+
+ MapTextbuttonGadget(ED_TEXTBUTTON_ID_BD_SET_RANDOM_COLORS);
+}
+
+static void DrawLevelConfigEngine(void)
+{
+ if (edit_mode_engineconfig == ED_MODE_ENGINECONFIG_CONFIG)
+ DrawEngineConfigConfig();
+ else if (edit_mode_engineconfig == ED_MODE_ENGINECONFIG_COLORS)
+ DrawEngineConfigColors();
+}
+
+static void DrawLevelConfigWindow(void)
+{
+ char *text = "Global Settings";
+ int font_nr = FONT_TITLE_1;
+ struct MenuPosInfo *pos = &editor.settings.headline;
+ int sx = SX + ALIGNED_XPOS(pos->x, getTextWidth(text, font_nr), pos->align);
+ int sy = SY + pos->y;
+
+ stick_element_properties_window = FALSE;
+
+ // make sure that previous level config edit mode exists for this level
+ if (edit_mode_levelconfig == ED_MODE_LEVELCONFIG_ENGINE &&
+ level.game_engine_type != GAME_ENGINE_TYPE_BD)
+ edit_mode_levelconfig = ED_MODE_LEVELCONFIG_LEVEL;
+
+ SetAutomaticNumberOfGemsNeeded();
+
+ UnmapLevelEditorFieldGadgets();
+
+ SetMainBackgroundImage(IMG_BACKGROUND_EDITOR);
+ ClearField();
+
+ DrawText(sx, sy, text, font_nr);
+
+ DrawLevelConfigTabulatorGadgets();
+
+ if (edit_mode_levelconfig == ED_MODE_LEVELCONFIG_LEVEL)
+ DrawLevelConfigLevel();
+ else if (edit_mode_levelconfig == ED_MODE_LEVELCONFIG_LEVELSET)
+ DrawLevelConfigLevelSet();
+ else if (edit_mode_levelconfig == ED_MODE_LEVELCONFIG_EDITOR)
+ DrawLevelConfigEditor();
+ else if (edit_mode_levelconfig == ED_MODE_LEVELCONFIG_ENGINE)
+ DrawLevelConfigEngine();
+}
+
+static void DrawCustomContentArea(void)
+{
+ int id = ED_DRAWING_ID_CUSTOM_CONTENT;
+ struct GadgetInfo *gi = level_editor_gadget[drawingarea_info[id].gadget_id];
+ int x1 = right_gadget_border[GADGET_ID_CUSTOM_DEADLINESS];
+ int x2 = right_gadget_border[GADGET_ID_CUSTOM_EXPLOSION_TYPE];
+ int x3 = right_gadget_border[GADGET_ID_CUSTOM_EXPLODE_IMPACT];
+ int xoffset = ED_GADGET_SPACE_DISTANCE;
+
+ // add distance for potential left text (without drawing area border)
+ x2 += getTextWidthForGadget(drawingarea_info[id].text_left);
+
+ ModifyGadget(gi, GDI_X, MAX(x1, MAX(x2, x3)) + xoffset, GDI_END);
+
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_CONTENT);
+}
+
+static void DrawCustomChangeContentArea(void)
+{
+ int id = ED_DRAWING_ID_CUSTOM_CHANGE_CONTENT;
+ struct GadgetInfo *gi = level_editor_gadget[drawingarea_info[id].gadget_id];
+ int x1 = right_gadget_border[GADGET_ID_CHANGE_USE_CONTENT];
+ int x2 = right_gadget_border[GADGET_ID_CHANGE_REPLACE_WHEN];
+ int x3 = right_gadget_border[GADGET_ID_CHANGE_ONLY_COMPLETE];
+ int xoffset = ED_GADGET_SPACE_DISTANCE;
+
+ ModifyGadget(gi, GDI_X, MAX(x1, MAX(x2, x3)) + xoffset, GDI_END);
+
+ MapDrawingArea(id);
+}
+
+static void RemoveElementContentArea(int id, int font_height)
+{
+ int border_size = ED_DRAWINGAREA_BORDER_SIZE;
+
+ DrawBackground(SX + ED_AREA_SETTINGS_X(drawingarea_info[id]) - border_size,
+ SY + ED_AREA_SETTINGS_Y(drawingarea_info[id]) - border_size,
+ 3 * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size,
+ 3 * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size +
+ ED_GADGET_TEXT_DISTANCE + font_height);
+}
+
+static void DrawYamYamContentAreas(void)
+{
+ int font_nr = FONT_TEXT_1;
+ int font_height = getFontHeight(font_nr);
+ int tilesize = ED_DRAWINGAREA_TILE_SIZE;
+ int yoffset = (tilesize - font_height) / 2;
+ int x = SX + ED_AREA_YAMYAM_CONTENT_X(3) + 4 * tilesize;
+ int y = SY + ED_AREA_YAMYAM_CONTENT_Y(3) + yoffset;
+ int i;
+
+ // display counter to choose number of element content areas
+ MapCounterButtons(ED_COUNTER_ID_YAMYAM_CONTENT);
+
+ for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
+ {
+ int id = ED_DRAWING_ID_YAMYAM_CONTENT_0 + i;
+
+ if (i < level.num_yamyam_contents)
+ {
+ MapDrawingArea(id);
+ }
+ else
+ {
+ UnmapDrawingArea(id);
+
+ // delete content areas in case of reducing number of them
+ RemoveElementContentArea(id, font_height);
+ }
+ }
+
+ DrawText(x, y + 0 * tilesize, "content", font_nr);
+ DrawText(x, y + 1 * tilesize, "when", font_nr);
+ DrawText(x, y + 2 * tilesize, "smashed", font_nr);
+}
+
+static void DrawMagicBallContentAreas(void)
+{
+ int font_nr = FONT_TEXT_1;
+ int font_height = getFontHeight(font_nr);
+ int tilesize = ED_DRAWINGAREA_TILE_SIZE;
+ int yoffset = (tilesize - font_height) / 2;
+ int x = SX + ED_AREA_MAGIC_BALL_CONTENT_X(3) + 4 * tilesize;
+ int y = SY + ED_AREA_MAGIC_BALL_CONTENT_Y(3) + yoffset;
+ int i;
+
+ // display counter to choose number of element content areas
+ MapCounterButtons(ED_COUNTER_ID_BALL_CONTENT);
+
+ for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
+ {
+ int id = ED_DRAWING_ID_MAGIC_BALL_CONTENT_0 + i;
+
+ if (i < level.num_ball_contents)
+ {
+ MapDrawingArea(id);
+ }
+ else
+ {
+ UnmapDrawingArea(id);
+
+ // delete content areas in case of reducing number of them
+ RemoveElementContentArea(id, font_height);
+ }
+ }
+
+ DrawText(x, y + 0 * tilesize, "generated", font_nr);
+ DrawText(x, y + 1 * tilesize, "when", font_nr);
+ DrawText(x, y + 2 * tilesize, "active", font_nr);
+}
+
+static void DrawAndroidElementArea(void)
+{
+ int id = ED_DRAWING_ID_ANDROID_CONTENT;
+ int num_elements = level.num_android_clone_elements;
+ int border_size = ED_DRAWINGAREA_BORDER_SIZE;
+ int sx = SX + ED_AREA_SETTINGS_X(drawingarea_info[id]) - border_size;
+ int sy = SY + ED_AREA_SETTINGS_Y(drawingarea_info[id]) - border_size;
+ int xsize = MAX_ANDROID_ELEMENTS;
+ int ysize = 1;
+
+ // display counter to choose number of element areas
+ MapCounterButtons(ED_COUNTER_ID_ANDROID_CONTENT);
+
+ if (drawingarea_info[id].text_left != NULL)
+ sx += getTextWidthForDrawingArea(drawingarea_info[id].text_left);
+
+ UnmapDrawingArea(id);
+
+ ModifyEditorDrawingArea(id, num_elements, 1);
+
+ // delete content areas in case of reducing number of them
+ DrawBackground(sx, sy,
+ xsize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size,
+ ysize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size);
+
+ MapDrawingArea(id);
+}
+
+static void DrawGroupElementArea(void)
+{
+ int id = ED_DRAWING_ID_GROUP_CONTENT;
+ int num_elements = group_element_info.num_elements;
+ int border_size = ED_DRAWINGAREA_BORDER_SIZE;
+ int sx = SX + ED_AREA_SETTINGS_X(drawingarea_info[id]) - border_size;
+ int sy = SY + ED_AREA_SETTINGS_Y(drawingarea_info[id]) - border_size;
+ int xsize = MAX_ELEMENTS_IN_GROUP;
+ int ysize = 1;
+
+ if (drawingarea_info[id].text_left != NULL)
+ sx += getTextWidthForDrawingArea(drawingarea_info[id].text_left);
+
+ UnmapDrawingArea(id);
+
+ ModifyEditorDrawingArea(id, num_elements, 1);
+
+ // delete content areas in case of reducing number of them
+ DrawBackground(sx, sy,
+ xsize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size,
+ ysize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size);
+
+ MapDrawingArea(id);
+}
+
+static void DrawPlayerInitialInventoryArea(int element)
+{
+ int id = ED_DRAWING_ID_INVENTORY_CONTENT;
+ int player_nr = GET_PLAYER_NR(element);
+ int num_elements = level.initial_inventory_size[player_nr];
+ int border_size = ED_DRAWINGAREA_BORDER_SIZE;
+ int sx = SX + ED_AREA_SETTINGS_X(drawingarea_info[id]) - border_size;
+ int sy = SY + ED_AREA_SETTINGS_Y(drawingarea_info[id]) - border_size;
+ int xsize = MAX_INITIAL_INVENTORY_SIZE;
+ int ysize = 1;
+
+ // determine horizontal position to the right of specified gadget
+ if (drawingarea_info[id].gadget_id_align != GADGET_ID_NONE)
+ sx = (right_gadget_border[drawingarea_info[id].gadget_id_align] +
+ ED_DRAWINGAREA_TEXT_DISTANCE);
+
+ // determine horizontal offset for leading text
+ if (drawingarea_info[id].text_left != NULL)
+ sx += getTextWidthForDrawingArea(drawingarea_info[id].text_left);
+
+ UnmapDrawingArea(id);
+
+ ModifyEditorDrawingArea(id, num_elements, 1);
+
+ // delete content areas in case of reducing number of them
+ DrawBackground(sx, sy,
+ xsize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size,
+ ysize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size);
+
+ MapDrawingArea(id);
+}
+
+static void DrawMMBallContentArea(void)
+{
+ int id = ED_DRAWING_ID_MM_BALL_CONTENT;
+ int num_elements = level.num_mm_ball_contents;
+ int border_size = ED_DRAWINGAREA_BORDER_SIZE;
+ int sx = SX + ED_AREA_SETTINGS_X(drawingarea_info[id]) - border_size;
+ int sy = SY + ED_AREA_SETTINGS_Y(drawingarea_info[id]) - border_size;
+ int xsize = MAX_MM_BALL_CONTENTS;
+ int ysize = 1;
+
+ if (drawingarea_info[id].text_left != NULL)
+ sx += getTextWidthForDrawingArea(drawingarea_info[id].text_left);
+
+ UnmapDrawingArea(id);
+
+ ModifyEditorDrawingArea(id, num_elements, 1);
+
+ // delete content areas in case of reducing number of them
+ DrawBackground(sx, sy,
+ xsize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size,
+ ysize * ED_DRAWINGAREA_TILE_SIZE + 2 * border_size);
+
+ MapDrawingArea(id);
+}
+
+static void DrawEnvelopeTextArea(int envelope_nr)
+{
+ int id = ED_TEXTAREA_ID_ENVELOPE_INFO;
+ struct GadgetInfo *gi = level_editor_gadget[textarea_info[id].gadget_id];
+
+ UnmapGadget(gi);
+
+ 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;
+
+ ModifyGadget(gi, GDI_AREA_SIZE,
+ *counterbutton_info[ED_COUNTER_ID_ENVELOPE_XSIZE].value,
+ *counterbutton_info[ED_COUNTER_ID_ENVELOPE_YSIZE].value,
+ GDI_END);
+
+ MapTextAreaGadget(ED_TEXTAREA_ID_ENVELOPE_INFO);
+}
+
+static void DrawPropertiesInfo(void)
+{
+ static struct
+ {
+ int value;
+ char *text;
+ }
+ properties[] =
+ {
+ // configurable properties
+
+ { EP_WALKABLE_OVER, "- player can walk over it" },
+ { EP_WALKABLE_INSIDE, "- player can walk inside it" },
+ { EP_WALKABLE_UNDER, "- player can walk under it" },
+ { EP_PASSABLE_OVER, "- player can pass over it" },
+ { EP_PASSABLE_INSIDE, "- player can pass through it" },
+ { EP_PASSABLE_UNDER, "- player can pass under it" },
+ { EP_PROTECTED, "- player is protected by it" },
+
+ { EP_DIGGABLE, "- can be digged away" },
+ { EP_COLLECTIBLE, "- can be collected" },
+ { EP_DROPPABLE, "- can be dropped after collecting" },
+ { EP_THROWABLE, "- can be thrown after collecting" },
+ { EP_PUSHABLE, "- can be pushed" },
+
+ { EP_CAN_FALL, "- can fall" },
+ { EP_CAN_MOVE, "- can move" },
+
+ { EP_CAN_SMASH_PLAYER, "- can smash player" },
+#if 0
+ { EP_CAN_SMASH_ENEMIES, "- can smash good and bad guys" },
+#endif
+ { EP_CAN_SMASH_EVERYTHING, "- can smash everything smashable" },
+
+ { EP_SLIPPERY, "- slippery for falling elements" },
+ { EP_EM_SLIPPERY_WALL, "- slippery for some gems (EM style)" },
+
+ { EP_DONT_RUN_INTO, "- deadly when running into" },
+ { EP_DONT_COLLIDE_WITH, "- deadly when colliding with" },
+ { EP_DONT_GET_HIT_BY, "- deadly when getting hit by" },
+ { EP_DONT_TOUCH, "- deadly when touching" },
+
+ { EP_INDESTRUCTIBLE, "- indestructible" },
+
+ { EP_CAN_EXPLODE_BY_FIRE, "- can explode by fire or explosions" },
+ { EP_CAN_EXPLODE_SMASHED, "- can explode when smashed" },
+ { EP_CAN_EXPLODE_IMPACT, "- can explode on impact" },
+
+ { EP_CAN_CHANGE, "- can change to other element" },
+
+ // pre-defined properties
+ { EP_CAN_PASS_MAGIC_WALL, "- can pass magic walls" },
+ { EP_CAN_PASS_DC_MAGIC_WALL,"- can pass magic walls (DC style)" },
+ { EP_SWITCHABLE, "- can be switched" },
+#if 0
+ { EP_HAS_EDITOR_CONTENT, "- can contain other elements" },
+#endif
+
+ { -1, NULL }
+ };
+ char *filename = getElementDescriptionFilename(properties_element);
+ 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 = 0;
+ int num_similar_in_level = 0;
+ int num_hires_tiles_in_level = 0;
+ int num_standard_properties = 0;
+ int font1_nr = FONT_TEXT_1;
+ int font2_nr = FONT_TEXT_2;
+ int font1_width = getFontWidth(font1_nr);
+ int font1_height = getFontHeight(font1_nr);
+ int font2_height = getFontHeight(font2_nr);
+ int line1_height = font1_height + ED_GADGET_LINE_DISTANCE;
+ int font2_yoffset = (font1_height - font2_height) / 2;
+ 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;
+ int i, x, y;
+
+ if (setup.editor.show_element_token)
+ {
+ int font3_nr = FONT_TEXT_3;
+ int font3_height = getFontHeight(font3_nr);
+
+ DrawTextF(xpos, ypos, font3_nr,
+ "[%s]", element_info[properties_element].token_name);
+
+ ypos += 2 * font3_height;
+ }
+
+ // ----- print number of elements / percentage of this element in level
+
+ for (y = 0; y < lev_fieldy; y++)
+ {
+ for (x = 0; x < lev_fieldx; x++)
+ {
+ if (Tile[x][y] == properties_element)
+ {
+ num_elements_in_level++;
+ }
+ else if (IS_MM_WALL(Tile[x][y]) &&
+ map_mm_wall_element(Tile[x][y]) == properties_element)
+ {
+ num_hires_tiles_in_level += numHiresTiles(Tile[x][y]);
+ }
+ }
+ }
+
+ percentage = num_elements_in_level * 100.0 / (lev_fieldx * lev_fieldy);
+
+ DrawTextS(xpos, ypos, font1_nr, num_elements_text);
+
+ if (num_hires_tiles_in_level > 0)
+ DrawTextF(xpos + num_elements_text_len, ypos + font2_yoffset, font2_nr,
+ "%d wall tiles", num_hires_tiles_in_level);
+ else if (num_elements_in_level > 0)
+ DrawTextF(xpos + num_elements_text_len, ypos + font2_yoffset, font2_nr,
+ "%d (%.2f %%)", num_elements_in_level, percentage);
+ else
+ DrawTextF(xpos + num_elements_text_len, ypos + font2_yoffset, font2_nr,
+ none_text);
+
+ // ----- print number of similar elements / percentage of them in level
+
+ 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
+
+ DrawTextS(xpos, ypos, font1_nr, properties_text);
+
+ ypos += line1_height;
+
+ for (i = 0; properties[i].value != -1; i++)
+ {
+ if (!HAS_PROPERTY(properties_element, properties[i].value))
+ continue;
+
+ DrawTextS(xpos, ypos, font2_nr, properties[i].text);
+
+ ypos += font2_height;
+
+ num_standard_properties++;
+ }
+
+ if (num_standard_properties == 0)
+ {
+ DrawTextS(xpos + properties_text_len, ypos - line1_height + font2_yoffset,
+ font2_nr, none_text);
+
+ ypos -= (line1_height - font1_height);
+ }
+
+ ypos += MAX(font1_height, font2_height);
+
+ // ----- print special description of this element
+
+ PrintInfoText(description_text, font1_nr, xpos, ypos);
+
+ ypos += line1_height;
+
+ if (PrintElementDescriptionFromFile(filename, font2_nr, xpos, ypos) == 0)
+ PrintInfoText(no_description_text, font1_nr, xpos, ypos - line1_height);
+}
+
+#define TEXT_COLLECTING "Score for collecting"
+#define TEXT_COLLECTING_EXTRA "Score for extra diamonds"
+#define TEXT_SMASHING "Score for smashing"
+#define TEXT_SLURPING "Score for slurping robot"
+#define TEXT_CRACKING "Score for cracking"
+#define TEXT_AMOEBA_SPEED "Speed of amoeba growth"
+#define TEXT_AMOEBA_THRESHOED "Size for turning to rocks"
+#define TEXT_AMOEBA_SLOW_TIME "Slow growth time (seconds)"
+#define TEXT_AMOEBA_SLOW_RATE "Slow growth rate (percent)"
+#define TEXT_AMOEBA_FAST_RATE "Fast growth rate (percent)"
+#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"
+#define TEXT_MOVE_SPEED "Speed of android moving"
+#define TEXT_CLONE_SPEED "Speed of android cloning"
+#define TEXT_GAME_OF_LIFE_1 "Min neighbours to survive"
+#define TEXT_GAME_OF_LIFE_2 "Max neighbours to survive"
+#define TEXT_GAME_OF_LIFE_3 "Min neighbours to create"
+#define TEXT_GAME_OF_LIFE_4 "Max neighbours to create"
+#define TEXT_TIME_BONUS "Extra time to solve level"
+#define TEXT_TIME_PENALTY "Time penalty if destroyed"
+#define TEXT_PERMEABILITY_RATE "slime permeability rate"
+#define TEXT_PERMEABILITY_BITS "slime permeability bits"
+#define TEXT_RANDOM_SEED "slime random number seed"
+#define TEXT_ACID_SPREAD_RATE "Spread rate (percent)"
+#define TEXT_BITER_MOVE_DELAY "Move delay (BD frames)"
+#define TEXT_REPLICATION_DELAY "Create delay (BD frames)"
+#define TEXT_HAMMER_BREAK_DELAY "Delay for breaking walls"
+#define TEXT_HAMMER_REAPPEAR_DELAY "Delay for reappearing walls"
+#define TEXT_SKELETONS_NEEDED "Skeletons needed to use pot"
+#define TEXT_SKELETONS_WORTH "Counts as this many diamonds"
+#define TEXT_AUTO_TURN_DELAY "Creatures auto turn delay"
+#define TEXT_GRAVITY_DELAY "Gravity switch change delay"
+
+static struct
+{
+ int element;
+ int *value;
+ char *text;
+ int min_value;
+ int max_value;
+} elements_with_counter[] =
+{
+ { EL_EMERALD, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_BD_DIAMOND, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_BD_DIAMOND, &level.score[SC_DIAMOND_EXTRA], TEXT_COLLECTING_EXTRA },
+ { EL_EMERALD_YELLOW, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_EMERALD_RED, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_EMERALD_PURPLE, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_SP_INFOTRON, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_DIAMOND, &level.score[SC_DIAMOND], TEXT_COLLECTING },
+ { EL_CRYSTAL, &level.score[SC_CRYSTAL], TEXT_COLLECTING },
+ { EL_PEARL, &level.score[SC_PEARL], TEXT_COLLECTING },
+ { EL_BUG, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BUG_RIGHT, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BUG_UP, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BUG_LEFT, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BUG_DOWN, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BD_BUTTERFLY, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BD_BUTTERFLY_RIGHT, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BD_BUTTERFLY_UP, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BD_BUTTERFLY_LEFT, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_BD_BUTTERFLY_DOWN, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_SP_ELECTRON, &level.score[SC_BUG], TEXT_SMASHING },
+ { EL_SPACESHIP, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_SPACESHIP_RIGHT, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_SPACESHIP_UP, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_SPACESHIP_LEFT, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_SPACESHIP_DOWN, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_BD_FIREFLY, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_BD_FIREFLY_RIGHT, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_BD_FIREFLY_UP, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_BD_FIREFLY_LEFT, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_BD_FIREFLY_DOWN, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_SP_SNIKSNAK, &level.score[SC_SPACESHIP], TEXT_SMASHING },
+ { EL_YAMYAM, &level.score[SC_YAMYAM], TEXT_SMASHING },
+ { EL_YAMYAM_LEFT, &level.score[SC_YAMYAM], TEXT_SMASHING },
+ { EL_YAMYAM_RIGHT, &level.score[SC_YAMYAM], TEXT_SMASHING },
+ { EL_YAMYAM_UP, &level.score[SC_YAMYAM], TEXT_SMASHING },
+ { EL_YAMYAM_DOWN, &level.score[SC_YAMYAM], TEXT_SMASHING },
+ { EL_DARK_YAMYAM, &level.score[SC_YAMYAM], TEXT_SMASHING },
+ { EL_ROBOT, &level.score[SC_ROBOT], TEXT_SMASHING },
+ { EL_PACMAN, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_PACMAN_RIGHT, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_PACMAN_UP, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_PACMAN_LEFT, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_PACMAN_DOWN, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_NUT, &level.score[SC_NUT], TEXT_CRACKING },
+ { EL_DYNAMITE, &level.score[SC_DYNAMITE], TEXT_COLLECTING },
+ { EL_EM_DYNAMITE, &level.score[SC_DYNAMITE], TEXT_COLLECTING },
+ { EL_DYNABOMB_INCREASE_NUMBER,&level.score[SC_DYNAMITE], TEXT_COLLECTING },
+ { EL_DYNABOMB_INCREASE_SIZE, &level.score[SC_DYNAMITE], TEXT_COLLECTING },
+ { EL_DYNABOMB_INCREASE_POWER, &level.score[SC_DYNAMITE], TEXT_COLLECTING },
+ { EL_SHIELD_NORMAL, &level.score[SC_SHIELD], TEXT_COLLECTING },
+ { EL_SHIELD_DEADLY, &level.score[SC_SHIELD], TEXT_COLLECTING },
+ { EL_EXTRA_TIME, &level.extra_time_score, TEXT_COLLECTING },
+ { EL_KEY_1, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_KEY_2, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_KEY_3, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_KEY_4, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EM_KEY_1, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EM_KEY_2, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EM_KEY_3, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EM_KEY_4, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EMC_KEY_5, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EMC_KEY_6, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EMC_KEY_7, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_EMC_KEY_8, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_DC_KEY_WHITE, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_MM_KETTLE, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_DF_CELL, &level.score[SC_EMERALD], TEXT_COLLECTING },
+ { EL_MM_KEY, &level.score[SC_KEY], TEXT_COLLECTING },
+ { EL_MM_LIGHTBALL, &level.score[SC_ELEM_BONUS], TEXT_COLLECTING },
+ { EL_MM_PACMAN, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_MM_PACMAN_RIGHT, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_MM_PACMAN_UP, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_MM_PACMAN_LEFT, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_MM_PACMAN_DOWN, &level.score[SC_PACMAN], TEXT_SMASHING },
+ { EL_AMOEBA_WET, &level.amoeba_speed, TEXT_AMOEBA_SPEED },
+ { EL_AMOEBA_DRY, &level.amoeba_speed, TEXT_AMOEBA_SPEED },
+ { EL_AMOEBA_FULL, &level.amoeba_speed, TEXT_AMOEBA_SPEED },
+ { EL_BD_AMOEBA, &level.amoeba_speed, TEXT_AMOEBA_SPEED },
+ { EL_EMC_DRIPPER, &level.amoeba_speed, TEXT_AMOEBA_SPEED },
+ { EL_BD_AMOEBA, &level.bd_amoeba_threshold_too_big, TEXT_AMOEBA_THRESHOED },
+ { EL_BD_AMOEBA, &level.bd_amoeba_slow_growth_time, TEXT_AMOEBA_SLOW_TIME },
+ { EL_BD_AMOEBA, &level.bd_amoeba_slow_growth_rate, TEXT_AMOEBA_SLOW_RATE,
+ 0, 100 },
+ { EL_BD_AMOEBA, &level.bd_amoeba_fast_growth_rate, TEXT_AMOEBA_FAST_RATE,
+ 0, 100 },
+ { EL_BD_AMOEBA_2, &level.bd_amoeba_2_threshold_too_big, TEXT_AMOEBA_THRESHOED },
+ { EL_BD_AMOEBA_2, &level.bd_amoeba_2_slow_growth_time, TEXT_AMOEBA_SLOW_TIME },
+ { EL_BD_AMOEBA_2, &level.bd_amoeba_2_slow_growth_rate, TEXT_AMOEBA_SLOW_RATE,
+ 0, 100 },
+ { EL_BD_AMOEBA_2, &level.bd_amoeba_2_fast_growth_rate, TEXT_AMOEBA_FAST_RATE,
+ 0, 100 },
+ { EL_MAGIC_WALL, &level.time_magic_wall, TEXT_DURATION },
+ { EL_BD_MAGIC_WALL, &level.time_magic_wall, TEXT_DURATION },
+ { EL_DC_MAGIC_WALL, &level.time_magic_wall, TEXT_DURATION },
+ { EL_ROBOT_WHEEL, &level.time_wheel, TEXT_DURATION },
+ { EL_TIMEGATE_SWITCH, &level.time_timegate, TEXT_DURATION },
+ { EL_DC_TIMEGATE_SWITCH, &level.time_timegate, TEXT_DURATION },
+ { EL_LIGHT_SWITCH, &level.time_light, TEXT_DURATION },
+ { EL_LIGHT_SWITCH_ACTIVE, &level.time_light, TEXT_DURATION },
+ { EL_SHIELD_NORMAL, &level.shield_normal_time, TEXT_DURATION },
+ { EL_SHIELD_DEADLY, &level.shield_deadly_time, TEXT_DURATION },
+ { EL_BD_CLOCK, &level.bd_clock_extra_time, TEXT_TIME_BONUS,
+ -100, 100 },
+ { EL_BD_VOODOO_DOLL, &level.bd_voodoo_penalty_time, TEXT_TIME_PENALTY,
+ 0, 100 },
+ { EL_BD_SLIME, &level.bd_slime_permeability_rate, TEXT_PERMEABILITY_RATE,
+ 0, 100 },
+ { EL_BD_SLIME, &level.bd_slime_permeability_bits_c64, TEXT_PERMEABILITY_BITS,
+ 0, 255 },
+ { EL_BD_SLIME, &level.bd_slime_random_seed_c64, TEXT_RANDOM_SEED,
+ -1, 65535 },
+ { EL_BD_ACID, &level.bd_acid_spread_rate, TEXT_ACID_SPREAD_RATE,
+ 0, 100 },
+ { EL_BD_BITER, &level.bd_biter_move_delay, TEXT_BITER_MOVE_DELAY,
+ 0, 3 },
+ { EL_BD_BITER_RIGHT, &level.bd_biter_move_delay, TEXT_BITER_MOVE_DELAY,
+ 0, 3 },
+ { EL_BD_BITER_UP, &level.bd_biter_move_delay, TEXT_BITER_MOVE_DELAY,
+ 0, 3 },
+ { EL_BD_BITER_LEFT, &level.bd_biter_move_delay, TEXT_BITER_MOVE_DELAY,
+ 0, 3 },
+ { EL_BD_BITER_DOWN, &level.bd_biter_move_delay, TEXT_BITER_MOVE_DELAY,
+ 0, 3 },
+ { EL_BD_REPLICATOR, &level.bd_replicator_create_delay, TEXT_REPLICATION_DELAY,
+ 0, 100 },
+ { EL_BD_PNEUMATIC_HAMMER, &level.bd_hammer_walls_break_delay, TEXT_HAMMER_BREAK_DELAY,
+ 1, 100 },
+ { EL_BD_PNEUMATIC_HAMMER, &level.bd_hammer_walls_reappear_delay, TEXT_HAMMER_REAPPEAR_DELAY,
+ 1, 200 },
+ { EL_BD_POT, &level.bd_num_skeletons_needed_for_pot, TEXT_SKELETONS_NEEDED,
+ 0, 50 },
+ { EL_BD_SKELETON, &level.bd_num_skeletons_needed_for_pot, TEXT_SKELETONS_NEEDED,
+ 0, 50 },
+ { EL_BD_SKELETON, &level.bd_skeleton_worth_num_diamonds, TEXT_SKELETONS_WORTH,
+ 0, 10 },
+ { EL_BD_CREATURE_SWITCH, &level.bd_creatures_auto_turn_delay, TEXT_AUTO_TURN_DELAY },
+ { EL_BD_GRAVITY_SWITCH, &level.bd_gravity_switch_delay, TEXT_GRAVITY_DELAY,
+ 1, 60 },
+ { EL_EXTRA_TIME, &level.extra_time, TEXT_TIME_BONUS },
+ { EL_TIME_ORB_FULL, &level.time_orb_time, TEXT_TIME_BONUS },
+ { EL_GAME_OF_LIFE, &level.game_of_life[0], TEXT_GAME_OF_LIFE_1,0,8 },
+ { EL_GAME_OF_LIFE, &level.game_of_life[1], TEXT_GAME_OF_LIFE_2,0,8 },
+ { EL_GAME_OF_LIFE, &level.game_of_life[2], TEXT_GAME_OF_LIFE_3,0,8 },
+ { EL_GAME_OF_LIFE, &level.game_of_life[3], TEXT_GAME_OF_LIFE_4,0,8 },
+ { EL_BIOMAZE, &level.biomaze[0], TEXT_GAME_OF_LIFE_1,0,8 },
+ { EL_BIOMAZE, &level.biomaze[1], TEXT_GAME_OF_LIFE_2,0,8 },
+ { EL_BIOMAZE, &level.biomaze[2], TEXT_GAME_OF_LIFE_3,0,8 },
+ { EL_BIOMAZE, &level.biomaze[3], TEXT_GAME_OF_LIFE_4,0,8 },
+ { EL_EMC_ANDROID, &level.android_move_time, TEXT_MOVE_SPEED },
+ { EL_EMC_ANDROID, &level.android_clone_time, TEXT_CLONE_SPEED },
+ { EL_EMC_MAGIC_BALL, &level.ball_time, TEXT_BALL_DELAY },
+ { EL_EMC_LENSES, &level.lenses_score, TEXT_COLLECTING },
+ { EL_EMC_MAGNIFIER, &level.magnify_score, TEXT_COLLECTING },
+ { EL_SPRING, &level.slurp_score, TEXT_SLURPING },
+ { EL_SPRING_LEFT, &level.slurp_score, TEXT_SLURPING },
+ { EL_SPRING_RIGHT, &level.slurp_score, TEXT_SLURPING },
+ { EL_EMC_LENSES, &level.lenses_time, TEXT_DURATION },
+ { 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_CHANGING },
+ { EL_MM_STEEL_BLOCK, &level.mm_time_block, TEXT_DELAY_MOVING },
+ { EL_MM_WOODEN_BLOCK, &level.mm_time_block, TEXT_DELAY_MOVING },
+
+ { -1, NULL, NULL }
+};
+
+static boolean checkPropertiesConfig(int element)
+{
+ int i;
+
+ // special case: empty space customization only available in R'n'D game engine
+ if (element == EL_EMPTY_SPACE && level.game_engine_type != GAME_ENGINE_TYPE_RND)
+ return FALSE;
+
+ // special case: BD style rock customization only available in BD game engine
+ if (element == EL_BD_ROCK && level.game_engine_type != GAME_ENGINE_TYPE_BD)
+ return FALSE;
+
+ 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_ENVELOPE(element) ||
+ IS_MM_MCDUFFIN(element) ||
+ IS_DF_LASER(element) ||
+ IS_PLAYER_ELEMENT(element) ||
+ IS_BD_PLAYER_ELEMENT(element) ||
+ IS_BD_FIREFLY(properties_element) ||
+ IS_BD_FIREFLY_2(properties_element) ||
+ IS_BD_BUTTERFLY(properties_element) ||
+ IS_BD_BUTTERFLY_2(properties_element) ||
+ IS_BD_STONEFLY(properties_element) ||
+ IS_BD_DRAGONFLY(properties_element) ||
+ IS_BD_EXPANDABLE_WALL(properties_element) ||
+ IS_BD_EXPANDABLE_STEELWALL(properties_element) ||
+ IS_BD_CONVEYOR_BELT(properties_element) ||
+ IS_BD_CONVEYOR_BELT_SWITCH(properties_element) ||
+ IS_SOKOBAN_OBJECT_OR_FIELD(element) ||
+ HAS_EDITOR_CONTENT(element) ||
+ CAN_GROW(element) ||
+ COULD_MOVE_INTO_ACID(element) ||
+ MAYBE_DONT_COLLIDE_WITH(element) ||
+ element == EL_BD_SAND ||
+ element == EL_BD_ROCK ||
+ element == EL_BD_MEGA_ROCK ||
+ element == EL_BD_BOMB ||
+ element == EL_BD_ROCKET_LAUNCHER ||
+ element == EL_BD_NITRO_PACK ||
+ element == EL_BD_SWEET ||
+ element == EL_BD_VOODOO_DOLL ||
+ element == EL_BD_WATER ||
+ element == EL_BD_GRAVITY_SWITCH)
+ {
+ return TRUE;
+ }
+ else
+ {
+ for (i = 0; elements_with_counter[i].element != -1; i++)
+ if (elements_with_counter[i].element == element)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void SetAutomaticNumberOfGemsNeeded(void)
+{
+ int x, y;
+
+ if (!level.auto_count_gems)
+ return;
+
+ level.gems_needed = 0;
+
+ for (x = 0; x < lev_fieldx; x++)
+ {
+ for (y = 0; y < lev_fieldy; y++)
+ {
+ int element = Tile[x][y];
+
+ switch (element)
+ {
+ case EL_EMERALD:
+ case EL_EMERALD_YELLOW:
+ case EL_EMERALD_RED:
+ case EL_EMERALD_PURPLE:
+ case EL_BD_DIAMOND:
+ case EL_WALL_EMERALD:
+ case EL_WALL_EMERALD_YELLOW:
+ case EL_WALL_EMERALD_RED:
+ case EL_WALL_EMERALD_PURPLE:
+ case EL_WALL_BD_DIAMOND:
+ case EL_NUT:
+ case EL_SP_INFOTRON:
+ case EL_MM_KETTLE:
+ case EL_DF_CELL:
+ level.gems_needed++;
+ break;
+
+ case EL_DIAMOND:
+ case EL_WALL_DIAMOND:
+ level.gems_needed += 3;
+ break;
+
+ case EL_PEARL:
+ case EL_WALL_PEARL:
+ level.gems_needed += 5;
+ break;
+
+ case EL_CRYSTAL:
+ case EL_WALL_CRYSTAL:
+ level.gems_needed += 8;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ ModifyEditorCounterValue(ED_COUNTER_ID_LEVEL_GEMSLIMIT, level.gems_needed);
+}
+
+static void DrawPropertiesConfig(void)
+{
+ boolean draw_footer_line = FALSE;
+ int max_num_element_counters = 4;
+ int num_element_counters = 0;
+ int i;
+
+ if (!checkPropertiesConfig(properties_element))
+ {
+ int xpos = ED_ELEMENT_SETTINGS_X(0);
+ int ypos = ED_ELEMENT_SETTINGS_Y(0) + ED_GADGET_SMALL_DISTANCE;
+
+ PrintInfoText("No configuration options available.", FONT_TEXT_1, xpos, ypos);
+
+ return;
+ }
+
+ // check if there are elements where a value can be chosen for
+ for (i = 0; elements_with_counter[i].element != -1; i++)
+ {
+ if (elements_with_counter[i].element != properties_element)
+ continue;
+
+ // special case: score for extra diamonds only available in BD game engine
+ if (elements_with_counter[i].element == EL_BD_DIAMOND &&
+ elements_with_counter[i].value == &level.score[SC_DIAMOND_EXTRA] &&
+ level.game_engine_type != GAME_ENGINE_TYPE_BD)
+ continue;
+
+ // special case: some amoeba counters only available in BD game engine
+ if (elements_with_counter[i].element == EL_BD_AMOEBA &&
+ elements_with_counter[i].value != &level.amoeba_speed &&
+ level.game_engine_type != GAME_ENGINE_TYPE_BD)
+ continue;
+
+ // special case: score for smashing only available in R'n'D game engine
+ if ((IS_BD_FIREFLY(elements_with_counter[i].element) ||
+ IS_BD_BUTTERFLY(elements_with_counter[i].element)) &&
+ (elements_with_counter[i].value == &level.score[SC_BUG] ||
+ elements_with_counter[i].value == &level.score[SC_SPACESHIP]) &&
+ level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ continue;
+
+ // special case: some amoeba counters only available in R'n'D game engine
+ if (elements_with_counter[i].element == EL_BD_AMOEBA &&
+ elements_with_counter[i].value == &level.amoeba_speed &&
+ level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ continue;
+
+ int counter_id = ED_COUNTER_ID_ELEMENT_VALUE1 + num_element_counters;
+
+ counterbutton_info[counter_id].y =
+ ED_ELEMENT_SETTINGS_YPOS((HAS_EDITOR_CONTENT(properties_element) ? 1 : 0) +
+ (CAN_GROW(properties_element) ? 1 : 0) +
+ (COULD_MOVE_INTO_ACID(properties_element) ? 1 : 0) +
+ (MAYBE_DONT_COLLIDE_WITH(properties_element) ? 1 : 0) +
+ (properties_element == EL_BD_VOODOO_DOLL ? 4 : 0) +
+ (properties_element == EL_BD_SLIME ? 1 : 0) +
+ (properties_element == EL_BD_ACID ? 1 : 0) +
+ (properties_element == EL_BD_REPLICATOR ? 1 : 0) +
+ (properties_element == EL_BD_CREATURE_SWITCH ? 1 : 0) +
+ (properties_element == EL_BD_GRAVITY_SWITCH ? 2 : 0) +
+ (properties_element == EL_EMC_MAGIC_BALL ? 2 : 0) +
+ num_element_counters);
+
+ // special case: set magic wall counter for BD game engine separately
+ if (properties_element == EL_BD_MAGIC_WALL && level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ counterbutton_info[counter_id].y = ED_ELEMENT_SETTINGS_YPOS(1);
+
+ // special case: set amoeba counters for BD game engine separately
+ if ((properties_element == EL_BD_AMOEBA && level.game_engine_type == GAME_ENGINE_TYPE_BD) ||
+ (properties_element == EL_BD_AMOEBA_2))
+ counterbutton_info[counter_id].y = ED_ELEMENT_SETTINGS_YPOS(3 + num_element_counters);
+
+ // special case: set position for delay counter for reappearing hammered walls
+ if (properties_element == EL_BD_PNEUMATIC_HAMMER && num_element_counters > 0)
+ counterbutton_info[counter_id].y += 1;
+
+ counterbutton_info[counter_id].value = elements_with_counter[i].value;
+ counterbutton_info[counter_id].text_right = elements_with_counter[i].text;
+ counterbutton_info[counter_id].min_value = elements_with_counter[i].min_value;
+ counterbutton_info[counter_id].max_value = elements_with_counter[i].max_value;
+
+ // default: counter values between 0 and 999
+ if (counterbutton_info[counter_id].max_value == 0)
+ counterbutton_info[counter_id].max_value = 999;
+
+ MapCounterButtons(counter_id);
+
+ num_element_counters++;
+ if (num_element_counters >= max_num_element_counters)
+ break;
+ }
+
+ if (properties_element == EL_BD_MAGIC_WALL && level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ {
+ // draw stickybutton gadget
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_STICK_ELEMENT);
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_MAGIC_WALL_ZERO_INFINITE);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_MAGIC_WALL_WAIT_HATCHING);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_MAGIC_WALL_STOPS_AMOEBA);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_MAGIC_WALL_BREAK_SCAN);
+
+ MapDrawingArea(ED_DRAWING_ID_BD_MAGIC_WALL_DIAMOND_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_MAGIC_WALL_ROCK_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_MAGIC_WALL_MEGA_ROCK_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_MAGIC_WALL_NUT_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_MAGIC_WALL_NITRO_PACK_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_MAGIC_WALL_FLYING_DIAMOND_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_MAGIC_WALL_FLYING_ROCK_TO);
+ }
+
+ if (HAS_EDITOR_CONTENT(properties_element))
+ {
+ // draw stickybutton gadget
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_STICK_ELEMENT);
+
+ if (properties_element == EL_BD_AMOEBA && level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_AMOEBA_WAIT_FOR_HATCHING);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_AMOEBA_START_IMMEDIATELY);
+
+ MapDrawingArea(ED_DRAWING_ID_BD_AMOEBA_CONTENT_TOO_BIG);
+ MapDrawingArea(ED_DRAWING_ID_BD_AMOEBA_CONTENT_ENCLOSED);
+ }
+ else if (properties_element == EL_BD_AMOEBA_2)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_AMOEBA_WAIT_FOR_HATCHING);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_AMOEBA_START_IMMEDIATELY);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_AMOEBA_2_EXPLODE_BY_AMOEBA);
+
+ MapDrawingArea(ED_DRAWING_ID_BD_AMOEBA_2_CONTENT_TOO_BIG);
+ MapDrawingArea(ED_DRAWING_ID_BD_AMOEBA_2_CONTENT_ENCLOSED);
+ MapDrawingArea(ED_DRAWING_ID_BD_AMOEBA_2_CONTENT_EXPLODING);
+ MapDrawingArea(ED_DRAWING_ID_BD_AMOEBA_2_CONTENT_LOOKS_LIKE);
+ }
+ else if (IS_AMOEBOID(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_AMOEBA_CONTENT);
+ }
+ else if (properties_element == EL_BD_ACID)
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_ACID_EATS_ELEMENT);
+ MapDrawingArea(ED_DRAWING_ID_BD_ACID_TURNS_TO_ELEMENT);
+ }
+ else if (IS_BD_BITER(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_BITER_EATS_ELEMENT);
+ }
+ else if (properties_element == EL_BD_BLADDER)
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_BLADDER_CONVERTS_BY_ELEMENT);
+ }
+ else if (properties_element == EL_YAMYAM ||
+ properties_element == EL_YAMYAM_LEFT ||
+ properties_element == EL_YAMYAM_RIGHT ||
+ properties_element == EL_YAMYAM_UP ||
+ properties_element == EL_YAMYAM_DOWN)
+ {
+ DrawYamYamContentAreas();
+ }
+ else if (properties_element == EL_EMC_MAGIC_BALL)
+ {
+ DrawMagicBallContentAreas();
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_RANDOM_BALL_CONTENT);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_INITIAL_BALL_ACTIVE);
+ }
+ else if (properties_element == EL_EMC_ANDROID)
+ {
+ DrawAndroidElementArea();
+ }
+ else if (properties_element == EL_MM_GRAY_BALL)
+ {
+ 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();
+ }
+ }
+
+ if (IS_PLAYER_ELEMENT(properties_element))
+ {
+ int player_nr = GET_PLAYER_NR(properties_element);
+
+ // these properties can be set for every player individually
+
+ if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_1)
+ {
+ drawingarea_info[ED_DRAWING_ID_START_ELEMENT].value =
+ &level.start_element[player_nr];
+ drawingarea_info[ED_DRAWING_ID_ARTWORK_ELEMENT].value =
+ &level.artwork_element[player_nr];
+ drawingarea_info[ED_DRAWING_ID_EXPLOSION_ELEMENT].value =
+ &level.explosion_element[player_nr];
+
+ checkbutton_info[ED_CHECKBUTTON_ID_USE_START_ELEMENT].value =
+ &level.use_start_element[player_nr];
+ checkbutton_info[ED_CHECKBUTTON_ID_USE_ARTWORK_ELEMENT].value =
+ &level.use_artwork_element[player_nr];
+ checkbutton_info[ED_CHECKBUTTON_ID_USE_EXPLOSION_ELEMENT].value =
+ &level.use_explosion_element[player_nr];
+ checkbutton_info[ED_CHECKBUTTON_ID_INITIAL_GRAVITY].value =
+ &level.initial_player_gravity[player_nr];
+
+ selectbox_info[ED_SELECTBOX_ID_PLAYER_SPEED].value =
+ &level.initial_player_stepsize[player_nr];
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID);
+ MapCheckbuttonGadget(properties_element == EL_SP_MURPHY ?
+ ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD :
+ ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BLOCK_SNAP_FIELD);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CONTINUOUS_SNAPPING);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_INSTANT_RELOCATION);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_SHIFTED_RELOCATION);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_LAZY_RELOCATION);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_START_ELEMENT);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_ARTWORK_ELEMENT);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_EXPLOSION_ELEMENT);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_INITIAL_GRAVITY);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_PASS_TO_WALKABLE);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_SOLVED_BY_ONE_PLAYER);
+
+ MapDrawingArea(ED_DRAWING_ID_START_ELEMENT);
+ MapDrawingArea(ED_DRAWING_ID_ARTWORK_ELEMENT);
+ MapDrawingArea(ED_DRAWING_ID_EXPLOSION_ELEMENT);
+
+ MapSelectboxGadget(ED_SELECTBOX_ID_PLAYER_SPEED);
+ }
+ else if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_2)
+ {
+ drawingarea_info[ED_DRAWING_ID_INVENTORY_CONTENT].value =
+ &level.initial_inventory_content[player_nr][0];
+
+ counterbutton_info[ED_COUNTER_ID_INVENTORY_SIZE].value =
+ &level.initial_inventory_size[player_nr];
+
+ checkbutton_info[ED_CHECKBUTTON_ID_USE_INITIAL_INVENTORY].value =
+ &level.use_initial_inventory[player_nr];
+
+ // draw checkbutton gadgets
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_INITIAL_INVENTORY);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_FINISH_DIG_COLLECT);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_KEEP_WALKABLE_CE);
+
+ // draw counter gadgets
+ MapCounterButtons(ED_COUNTER_ID_INVENTORY_SIZE);
+
+ // draw drawing area gadgets
+ DrawPlayerInitialInventoryArea(properties_element);
+ }
+ }
+
+ if (IS_BD_PLAYER_ELEMENT(properties_element))
+ {
+ counterbutton_info[ED_COUNTER_ID_BD_PUSHING_PROB].y =
+ ED_ELEMENT_SETTINGS_YPOS(2);
+ counterbutton_info[ED_COUNTER_ID_BD_PUSHING_PROB_WITH_SWEET].y =
+ ED_ELEMENT_SETTINGS_YPOS(3);
+ checkbutton_info[ED_CHECKBUTTON_ID_BD_PUSH_MEGA_ROCK_WITH_SWEET].y =
+ ED_ELEMENT_SETTINGS_YPOS(4);
+
+ // draw checkbutton gadgets
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_DIAGONAL_MOVEMENTS);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_TOPMOST_PLAYER_ACTIVE);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_PUSH_MEGA_ROCK_WITH_SWEET);
+
+ // draw counter gadgets
+ MapCounterButtons(ED_COUNTER_ID_BD_PUSHING_PROB);
+ MapCounterButtons(ED_COUNTER_ID_BD_PUSHING_PROB_WITH_SWEET);
+
+ // draw drawing area gadgets
+ MapDrawingArea(ED_DRAWING_ID_BD_SNAP_ELEMENT);
+ }
+
+ if (properties_element == EL_BD_SAND)
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_SAND_LOOKS_LIKE);
+ }
+
+ if (properties_element == EL_BD_ROCK && level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ {
+ counterbutton_info[ED_COUNTER_ID_BD_PUSHING_PROB].y =
+ ED_ELEMENT_SETTINGS_YPOS(0);
+ counterbutton_info[ED_COUNTER_ID_BD_PUSHING_PROB_WITH_SWEET].y =
+ ED_ELEMENT_SETTINGS_YPOS(1);
+
+ MapCounterButtons(ED_COUNTER_ID_BD_PUSHING_PROB);
+ MapCounterButtons(ED_COUNTER_ID_BD_PUSHING_PROB_WITH_SWEET);
+
+ MapDrawingArea(ED_DRAWING_ID_BD_ROCK_TURNS_TO_ON_FALLING);
+ MapDrawingArea(ED_DRAWING_ID_BD_ROCK_TURNS_TO_ON_IMPACT);
+ }
+
+ if (properties_element == EL_BD_DIAMOND && level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_DIAMOND_TURNS_TO_ON_FALLING);
+ MapDrawingArea(ED_DRAWING_ID_BD_DIAMOND_TURNS_TO_ON_IMPACT);
+ }
+
+ if (level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ {
+ if (IS_BD_FIREFLY(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_FIREFLY_EXPLODES_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_EXPLOSION_TURNS_TO);
+ }
+ else if (IS_BD_FIREFLY_2(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_FIREFLY_2_EXPLODES_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_EXPLOSION_TURNS_TO);
+ }
+ else if (IS_BD_BUTTERFLY(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_BUTTERFLY_EXPLODES_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_DIAMOND_BIRTH_TURNS_TO);
+ }
+ else if (IS_BD_BUTTERFLY_2(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_BUTTERFLY_2_EXPLODES_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_DIAMOND_BIRTH_TURNS_TO);
+ }
+ else if (IS_BD_STONEFLY(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_STONEFLY_EXPLODES_TO);
+ }
+ else if (IS_BD_DRAGONFLY(properties_element))
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_DRAGONFLY_EXPLODES_TO);
+ MapDrawingArea(ED_DRAWING_ID_BD_EXPLOSION_TURNS_TO);
+ }
+ else if (properties_element == EL_BD_BOMB)
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_BOMB_EXPLOSION_TURNS_TO);
+ }
+ else if (properties_element == EL_BD_NITRO_PACK)
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_NITRO_EXPLOSION_TURNS_TO);
+ }
+ }
+
+ if (properties_element == EL_BD_MEGA_ROCK ||
+ properties_element == EL_BD_SWEET)
+ {
+ counterbutton_info[ED_COUNTER_ID_BD_PUSHING_PROB_WITH_SWEET].y =
+ ED_ELEMENT_SETTINGS_YPOS(0);
+ checkbutton_info[ED_CHECKBUTTON_ID_BD_PUSH_MEGA_ROCK_WITH_SWEET].y =
+ ED_ELEMENT_SETTINGS_YPOS(1);
+
+ MapCounterButtons(ED_COUNTER_ID_BD_PUSHING_PROB_WITH_SWEET);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_PUSH_MEGA_ROCK_WITH_SWEET);
+ }
+
+ if (properties_element == EL_BD_VOODOO_DOLL)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_VOODOO_COLLECTS_DIAMONDS);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_VOODOO_HURT_KILLS_PLAYER);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_VOODOO_DIES_BY_ROCK);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_VOODOO_VANISH_BY_EXPLOSION);
+ }
+
+ if (properties_element == EL_BD_SLIME)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_SLIME_IS_PREDICTABLE);
+
+ MapDrawingArea(ED_DRAWING_ID_BD_SLIME_EATS_ELEMENT_1);
+ MapDrawingArea(ED_DRAWING_ID_BD_SLIME_CONVERTS_TO_ELEMENT_1);
+ MapDrawingArea(ED_DRAWING_ID_BD_SLIME_EATS_ELEMENT_2);
+ MapDrawingArea(ED_DRAWING_ID_BD_SLIME_CONVERTS_TO_ELEMENT_2);
+ MapDrawingArea(ED_DRAWING_ID_BD_SLIME_EATS_ELEMENT_3);
+ MapDrawingArea(ED_DRAWING_ID_BD_SLIME_CONVERTS_TO_ELEMENT_3);
+ }
+
+ if (IS_BD_EXPANDABLE_WALL(properties_element) ||
+ IS_BD_EXPANDABLE_STEELWALL(properties_element))
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_CHANGE_EXPANDING_WALL);
+
+ if (IS_BD_EXPANDABLE_WALL(properties_element))
+ MapDrawingArea(ED_DRAWING_ID_BD_EXPANDING_WALL_LOOKS_LIKE);
+ }
+
+ if (properties_element == EL_BD_REPLICATOR)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_REPLICATORS_ACTIVE);
+ }
+
+ if (IS_BD_CONVEYOR_BELT(properties_element) ||
+ IS_BD_CONVEYOR_BELT_SWITCH(properties_element))
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_CONVEYOR_BELTS_ACTIVE);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_CONVEYOR_BELTS_CHANGED);
+ }
+
+ if (properties_element == EL_BD_WATER)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_WATER_CANNOT_FLOW_DOWN);
+ }
+
+ if (properties_element == EL_BD_PNEUMATIC_HAMMER)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_HAMMER_WALLS_REAPPEAR);
+ }
+
+ if (properties_element == EL_BD_ROCKET_LAUNCHER)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_INFINITE_ROCKETS);
+ }
+
+ if (properties_element == EL_BD_CREATURE_SWITCH)
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_CREATURES_START_BACKWARDS);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_CREATURES_TURN_ON_HATCHING);
+ }
+
+ if (properties_element == EL_BD_GRAVITY_SWITCH)
+ {
+ MapSelectboxGadget(ED_SELECTBOX_ID_BD_GRAVITY_DIRECTION);
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_GRAVITY_SWITCH_ACTIVE);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_BD_GRAVITY_AFFECTS_ALL);
+ }
+
+ if (properties_element == EL_BD_NUT)
+ {
+ MapDrawingArea(ED_DRAWING_ID_BD_NUT_CONTENT);
+ }
+
+ // special case: slippery walls option for gems only available in R'n'D game engine
+ if (IS_GEM(properties_element) && level.game_engine_type == GAME_ENGINE_TYPE_RND)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_EM_SLIPPERY_GEMS);
+
+ if (properties_element == EL_EM_DYNAMITE)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_EM_EXPLODES_BY_FIRE);
+
+ if (level.game_engine_type == GAME_ENGINE_TYPE_RND &&
+ COULD_MOVE_INTO_ACID(properties_element) &&
+ !IS_PLAYER_ELEMENT(properties_element) &&
+ (!IS_CUSTOM_ELEMENT(properties_element) ||
+ edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_2))
+ {
+ // set position for checkbutton for "can move into acid"
+ checkbutton_info[ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID].x =
+ ED_ELEMENT_SETTINGS_XPOS(IS_CUSTOM_ELEMENT(properties_element) ? 1 : 0);
+ checkbutton_info[ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID].y =
+ ED_ELEMENT_SETTINGS_YPOS(IS_CUSTOM_ELEMENT(properties_element) ? 7 :
+ IS_BALLOON_ELEMENT(properties_element) ||
+ HAS_EDITOR_CONTENT(properties_element) ? 1 : 0);
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID);
+ }
+
+ if (MAYBE_DONT_COLLIDE_WITH(properties_element))
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH);
+
+ if (properties_element == EL_SPRING ||
+ properties_element == EL_SPRING_LEFT ||
+ properties_element == EL_SPRING_RIGHT)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_SPRING_BUG);
+
+ if (properties_element == EL_TIME_ORB_FULL)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_TIME_ORB_BUG);
+
+ if (properties_element == EL_GAME_OF_LIFE ||
+ properties_element == EL_BIOMAZE)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_LIFE_BUGS);
+
+ if (CAN_GROW(properties_element) && level.game_engine_type != GAME_ENGINE_TYPE_BD)
+ {
+ checkbutton_info[ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE].y =
+ ED_ELEMENT_SETTINGS_YPOS(HAS_EDITOR_CONTENT(properties_element) ? 1 : 0);
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE);
+ }
+
+ if (properties_element == EL_SOKOBAN_FIELD_EMPTY)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_SB_FIELDS_NEEDED);
+
+ if (properties_element == EL_SOKOBAN_OBJECT)
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_SB_OBJECTS_NEEDED);
+
+ if (properties_element == EL_SOKOBAN_OBJECT ||
+ properties_element == EL_SOKOBAN_FIELD_EMPTY ||
+ properties_element == EL_SOKOBAN_FIELD_FULL)
+ {
+ checkbutton_info[ED_CHECKBUTTON_ID_AUTO_EXIT_SOKOBAN].y =
+ ED_ELEMENT_SETTINGS_XPOS(properties_element == EL_SOKOBAN_FIELD_FULL ?
+ 0 : 1);
+
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_AUTO_EXIT_SOKOBAN);
+ }
+
+ if (IS_BALLOON_ELEMENT(properties_element))
+ MapSelectboxGadget(ED_SELECTBOX_ID_WIND_DIRECTION);
+
+ if (IS_ENVELOPE(properties_element) ||
+ IS_MM_ENVELOPE(properties_element))
+ {
+ int counter1_id = ED_COUNTER_ID_ENVELOPE_XSIZE;
+ int counter2_id = ED_COUNTER_ID_ENVELOPE_YSIZE;
+ int button1_id = ED_CHECKBUTTON_ID_ENVELOPE_AUTOWRAP;
+ int button2_id = ED_CHECKBUTTON_ID_ENVELOPE_CENTERED;
+ int envelope_nr = ENVELOPE_NR(properties_element);
+
+ counterbutton_info[counter1_id].value = &level.envelope[envelope_nr].xsize;
+ counterbutton_info[counter2_id].value = &level.envelope[envelope_nr].ysize;
+
+ checkbutton_info[button1_id].value = &level.envelope[envelope_nr].autowrap;
+ checkbutton_info[button2_id].value = &level.envelope[envelope_nr].centered;
+
+ // display counter to choose size of envelope text area
+ MapCounterButtons(counter1_id);
+ MapCounterButtons(counter2_id);
+
+ // display checkbuttons to choose auto-wrap and alignment properties
+ MapCheckbuttonGadget(button1_id);
+ MapCheckbuttonGadget(button2_id);
+
+ DrawEnvelopeTextArea(envelope_nr);
+ }
+
+ if (IS_MM_MCDUFFIN(properties_element))
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_MM_LASER_RED);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_MM_LASER_GREEN);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_MM_LASER_BLUE);
+ }
+
+ if (IS_DF_LASER(properties_element))
+ {
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_DF_LASER_RED);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_DF_LASER_GREEN);
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_DF_LASER_BLUE);
+ }
+
+ if (IS_CUSTOM_ELEMENT(properties_element))
+ {
+ // draw stickybutton gadget
+ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_STICK_ELEMENT);
+
+ if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_1)
+ {
+ // draw checkbutton gadgets
+ for (i = ED_CHECKBUTTON_ID_CUSTOM1_FIRST;
+ i <= ED_CHECKBUTTON_ID_CUSTOM1_LAST; i++)
+ MapCheckbuttonGadget(i);
+
+ // draw counter gadgets
+ for (i = ED_COUNTER_ID_CUSTOM1_FIRST;
+ i <= ED_COUNTER_ID_CUSTOM1_LAST; i++)
+ MapCounterButtons(i);
+
+ // draw selectbox gadgets
+ for (i = ED_SELECTBOX_ID_CUSTOM1_FIRST;
+ i <= ED_SELECTBOX_ID_CUSTOM1_LAST; i++)
+ MapSelectboxGadget(i);
+
+ // draw textbutton gadgets
+ MapTextbuttonGadget(ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE_1);
+
+ // draw text input gadgets
+ MapTextInputGadget(ED_TEXTINPUT_ID_ELEMENT_NAME);
+
+ // draw drawing area gadgets
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_GRAPHIC);
+
+ draw_footer_line = TRUE;
+ }
+ else if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG_2)
+ {
+ // draw checkbutton gadgets
+ for (i = ED_CHECKBUTTON_ID_CUSTOM2_FIRST;
+ i <= ED_CHECKBUTTON_ID_CUSTOM2_LAST; i++)
+ MapCheckbuttonGadget(i);
+
+ // draw counter gadgets
+ for (i = ED_COUNTER_ID_CUSTOM2_FIRST;
+ i <= ED_COUNTER_ID_CUSTOM2_LAST; i++)
+ MapCounterButtons(i);
+
+ // draw selectbox gadgets
+ for (i = ED_SELECTBOX_ID_CUSTOM2_FIRST;
+ i <= ED_SELECTBOX_ID_CUSTOM2_LAST; i++)
+ MapSelectboxGadget(i);
+
+ // draw drawing area gadgets
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_MOVE_ENTER);
+ MapDrawingArea(ED_DRAWING_ID_CUSTOM_MOVE_LEAVE);
+ DrawCustomContentArea();
+ }
+ }
+ else if (IS_GROUP_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);