X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Feditor.c;h=edd8b12f224f50c3dc0f07097b0ccd34bd6d2c94;hb=ce7a1e6952d05d6eecdae03ea3110f8ca6807cb3;hp=e5d956709d9408f9c96090a185d2677de2669727;hpb=0c5427e607bcc1b34dde35616d39c768fc4be184;p=rocksndiamonds.git diff --git a/src/editor.c b/src/editor.c index e5d95670..edd8b12f 100644 --- a/src/editor.c +++ b/src/editor.c @@ -459,6 +459,9 @@ enum GADGET_ID_INVENTORY_SIZE_DOWN, GADGET_ID_INVENTORY_SIZE_TEXT, GADGET_ID_INVENTORY_SIZE_UP, + GADGET_ID_MM_BALL_CONTENT_DOWN, + GADGET_ID_MM_BALL_CONTENT_TEXT, + GADGET_ID_MM_BALL_CONTENT_UP, GADGET_ID_CUSTOM_SCORE_DOWN, GADGET_ID_CUSTOM_SCORE_TEXT, GADGET_ID_CUSTOM_SCORE_UP, @@ -539,6 +542,7 @@ enum GADGET_ID_ARTWORK_ELEMENT, GADGET_ID_EXPLOSION_ELEMENT, GADGET_ID_INVENTORY_CONTENT, + GADGET_ID_MM_BALL_CONTENT, GADGET_ID_CUSTOM_GRAPHIC, GADGET_ID_CUSTOM_CONTENT, GADGET_ID_CUSTOM_MOVE_ENTER, @@ -570,6 +574,7 @@ enum GADGET_ID_LEVELSET_SAVE_MODE, GADGET_ID_WIND_DIRECTION, GADGET_ID_PLAYER_SPEED, + GADGET_ID_MM_BALL_CHOICE_MODE, GADGET_ID_CUSTOM_WALK_TO_ACTION, GADGET_ID_CUSTOM_EXPLOSION_TYPE, GADGET_ID_CUSTOM_DEADLINESS, @@ -682,6 +687,8 @@ enum GADGET_ID_DF_LASER_RED, GADGET_ID_DF_LASER_GREEN, GADGET_ID_DF_LASER_BLUE, + GADGET_ID_ROTATE_MM_BALL_CONTENT, + GADGET_ID_EXPLODE_MM_BALL, GADGET_ID_CUSTOM_INDESTRUCTIBLE, GADGET_ID_CUSTOM_CAN_EXPLODE, GADGET_ID_CUSTOM_EXPLODE_FIRE, @@ -750,6 +757,7 @@ enum ED_COUNTER_ID_ENVELOPE_XSIZE, ED_COUNTER_ID_ENVELOPE_YSIZE, ED_COUNTER_ID_INVENTORY_SIZE, + ED_COUNTER_ID_MM_BALL_CONTENT, ED_COUNTER_ID_CUSTOM_SCORE, ED_COUNTER_ID_CUSTOM_GEMCOUNT, ED_COUNTER_ID_CUSTOM_VALUE_FIX, @@ -856,6 +864,7 @@ enum ED_SELECTBOX_ID_LEVELSET_SAVE_MODE, ED_SELECTBOX_ID_WIND_DIRECTION, ED_SELECTBOX_ID_PLAYER_SPEED, + ED_SELECTBOX_ID_MM_BALL_CHOICE_MODE, ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE, ED_SELECTBOX_ID_CUSTOM_ACCESS_LAYER, ED_SELECTBOX_ID_CUSTOM_ACCESS_PROTECTED, @@ -993,6 +1002,8 @@ enum ED_CHECKBUTTON_ID_DF_LASER_RED, ED_CHECKBUTTON_ID_DF_LASER_GREEN, ED_CHECKBUTTON_ID_DF_LASER_BLUE, + ED_CHECKBUTTON_ID_ROTATE_MM_BALL_CONTENT, + ED_CHECKBUTTON_ID_EXPLODE_MM_BALL, ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC, ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE_1, ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE, @@ -1079,6 +1090,7 @@ enum ED_DRAWING_ID_ARTWORK_ELEMENT, ED_DRAWING_ID_EXPLOSION_ELEMENT, ED_DRAWING_ID_INVENTORY_CONTENT, + ED_DRAWING_ID_MM_BALL_CONTENT, ED_DRAWING_ID_CUSTOM_GRAPHIC, ED_DRAWING_ID_CUSTOM_CONTENT, ED_DRAWING_ID_CUSTOM_MOVE_ENTER, @@ -1533,6 +1545,14 @@ static struct &level.initial_inventory_size[0], NULL, NULL, "number of inventory elements" }, + { + ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(3), + MIN_ELEMENTS_IN_GROUP, MAX_MM_BALL_CONTENTS, + GADGET_ID_MM_BALL_CONTENT_DOWN, GADGET_ID_MM_BALL_CONTENT_UP, + GADGET_ID_MM_BALL_CONTENT_TEXT, GADGET_ID_NONE, + &level.num_mm_ball_contents, + NULL, NULL, "number of content elements" + }, // ---------- element settings: configure 1 (custom elements) --------------- @@ -1743,7 +1763,7 @@ static struct int gadget_id; int xsize, ysize; char *value; - char *text_above, *infotext; + char *text_above, *text_above_cropped, *infotext; } textarea_info[ED_NUM_TEXTAREAS] = { { @@ -1751,7 +1771,7 @@ static struct GADGET_ID_ENVELOPE_INFO, MAX_ENVELOPE_XSIZE, MAX_ENVELOPE_YSIZE, NULL, - "Envelope Content:", "Envelope Content" + "Envelope Content:", "Envelope Content (cropped):", "Envelope Content" } }; @@ -2079,38 +2099,38 @@ static struct ValueTextInfo options_change_trigger_player[] = static struct ValueTextInfo options_change_trigger_page[] = { - { (1 << 0), "1" }, - { (1 << 1), "2" }, - { (1 << 2), "3" }, - { (1 << 3), "4" }, - { (1 << 4), "5" }, - { (1 << 5), "6" }, - { (1 << 6), "7" }, - { (1 << 7), "8" }, - { (1 << 8), "9" }, - { (1 << 9), "10" }, - { (1 << 10), "11" }, - { (1 << 11), "12" }, - { (1 << 12), "13" }, - { (1 << 13), "14" }, - { (1 << 14), "15" }, - { (1 << 15), "16" }, - { (1 << 16), "17" }, - { (1 << 17), "18" }, - { (1 << 18), "19" }, - { (1 << 19), "20" }, - { (1 << 20), "21" }, - { (1 << 21), "22" }, - { (1 << 22), "23" }, - { (1 << 23), "24" }, - { (1 << 24), "25" }, - { (1 << 25), "26" }, - { (1 << 26), "27" }, - { (1 << 27), "28" }, - { (1 << 28), "29" }, - { (1 << 29), "30" }, - { (1 << 30), "31" }, - { (1 << 31), "32" }, + { (1u << 0), "1" }, + { (1u << 1), "2" }, + { (1u << 2), "3" }, + { (1u << 3), "4" }, + { (1u << 4), "5" }, + { (1u << 5), "6" }, + { (1u << 6), "7" }, + { (1u << 7), "8" }, + { (1u << 8), "9" }, + { (1u << 9), "10" }, + { (1u << 10), "11" }, + { (1u << 11), "12" }, + { (1u << 12), "13" }, + { (1u << 13), "14" }, + { (1u << 14), "15" }, + { (1u << 15), "16" }, + { (1u << 16), "17" }, + { (1u << 17), "18" }, + { (1u << 18), "19" }, + { (1u << 19), "20" }, + { (1u << 20), "21" }, + { (1u << 21), "22" }, + { (1u << 22), "23" }, + { (1u << 23), "24" }, + { (1u << 24), "25" }, + { (1u << 25), "26" }, + { (1u << 26), "27" }, + { (1u << 27), "28" }, + { (1u << 28), "29" }, + { (1u << 29), "30" }, + { (1u << 30), "31" }, + { (1u << 31), "32" }, { CH_PAGE_ANY, "any" }, { -1, NULL } @@ -2555,6 +2575,14 @@ static struct &level.initial_player_stepsize[0], NULL, "initial player speed:", NULL, "initial player speed" }, + { + ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(4), + GADGET_ID_MM_BALL_CHOICE_MODE, GADGET_ID_NONE, + -1, + options_group_choice_mode, + &level.mm_ball_choice_mode, + NULL, "choice type:", NULL, "type of content choice" + }, // ---------- element settings: configure 1 (custom elements) --------------- @@ -3354,6 +3382,20 @@ static struct NULL, NULL, "blue", "use blue color components in laser" }, + { + ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(5), + GADGET_ID_ROTATE_MM_BALL_CONTENT, GADGET_ID_NONE, + &level.rotate_mm_ball_content, + NULL, NULL, + "randomly rotate created content", "randomly rotate newly created content" + }, + { + ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(6), + GADGET_ID_EXPLODE_MM_BALL, GADGET_ID_NONE, + &level.explode_mm_ball, + NULL, NULL, + "explode ball instead of melting", "use explosion to release ball content" + }, // ---------- element settings: configure 1 (custom elements) --------------- @@ -3740,6 +3782,16 @@ static struct NULL, NULL, NULL, NULL, "content for initial inventory" }, + // ---------- gray ball content ----------------------------------------- + + { + ED_AREA_1X1_SETTINGS_XPOS(0), ED_AREA_1X1_SETTINGS_YPOS(2), + ED_AREA_1X1_SETTINGS_XOFF, ED_AREA_1X1_SETTINGS_YOFF, + GADGET_ID_MM_BALL_CONTENT, GADGET_ID_NONE, + &level.mm_ball_content[0], MAX_MM_BALL_CONTENTS, 1, + "content:", NULL, NULL, NULL, "content for gray ball" + }, + // ---------- element settings: configure 1 (custom elements) --------------- // ---------- custom graphic ------------------------------------------------ @@ -3748,7 +3800,7 @@ static struct -1, ED_AREA_1X1_SETTINGS_YPOS(1), 0, ED_AREA_1X1_SETTINGS_YOFF, GADGET_ID_CUSTOM_GRAPHIC, GADGET_ID_CUSTOM_USE_GRAPHIC, - &custom_element.gfx_element_initial,1, 1, + &custom_element.gfx_element_initial, 1, 1, NULL, NULL, NULL, NULL, "custom graphic element" }, @@ -3862,7 +3914,7 @@ static int level_xpos = -1, level_ypos = -1; static int ed_tilesize = DEFAULT_EDITOR_TILESIZE; static int ed_tilesize_default = DEFAULT_EDITOR_TILESIZE; -#define IN_ED_FIELD(x,y) IN_FIELD(x, y, ed_fieldx, ed_fieldy) +#define IN_ED_FIELD(x, y) IN_FIELD(x, y, ed_fieldx, ed_fieldy) // drawing elements on the three mouse buttons static int new_element1 = EL_WALL; @@ -3921,6 +3973,7 @@ static boolean getDrawModeHiRes(void); static int getTabulatorBarWidth(void); static int getTabulatorBarHeight(void); static Pixel getTabulatorBarColor(void); +static int numHiresTiles(int); static int num_editor_gadgets = 0; // dynamically determined @@ -4610,7 +4663,12 @@ static int editor_el_mirror_magic[] = EL_MM_WOODEN_GRID_FIXED_1, EL_MM_WOODEN_GRID_FIXED_2, EL_MM_WOODEN_GRID_FIXED_3, - EL_MM_WOODEN_GRID_FIXED_4 + EL_MM_WOODEN_GRID_FIXED_4, + + EL_MM_ENVELOPE_1, + EL_MM_ENVELOPE_2, + EL_MM_ENVELOPE_3, + EL_MM_ENVELOPE_4 }; static int *editor_hl_mirror_magic_ptr = editor_hl_mirror_magic; static int *editor_el_mirror_magic_ptr = editor_el_mirror_magic; @@ -5557,6 +5615,14 @@ editor_elements_info[] = } }; +static struct XY xy_directions[] = +{ + { -1, 0 }, + { +1, 0 }, + { 0, -1 }, + { 0, +1 } +}; + // ---------------------------------------------------------------------------- // functions @@ -5677,9 +5743,18 @@ static void InitDynamicEditorElementList(int **elements, int *num_elements) // find all elements used in current level for (y = 0; y < lev_fieldy; y++) + { for (x = 0; x < lev_fieldx; x++) - if (Tile[x][y] < NUM_FILE_ELEMENTS) // should always be true + { + if (Tile[x][y] >= NUM_FILE_ELEMENTS) // should never happen + continue; + + if (IS_MM_WALL(Tile[x][y])) + element_found[map_mm_wall_element(Tile[x][y])] = TRUE; + else element_found[Tile[x][y]] = TRUE; + } + } *num_elements = 0; @@ -5699,14 +5774,18 @@ static void InitDynamicEditorElementList(int **elements, int *num_elements) *num_elements = 0; - // add all elements used in current level (non-custom/group elements) + // add all elements used in current level (non-custom/group/empty elements) for (i = 0; i < NUM_FILE_ELEMENTS; i++) - if (element_found[i] && !(IS_CUSTOM_ELEMENT(i) || IS_GROUP_ELEMENT(i))) + if (element_found[i] && !(IS_CUSTOM_ELEMENT(i) || + IS_GROUP_ELEMENT(i) || + IS_EMPTY_ELEMENT(i))) (*elements)[(*num_elements)++] = i; - // add all elements used in current level (custom/group elements) + // add all elements used in current level (custom/group/empty elements) for (i = 0; i < NUM_FILE_ELEMENTS; i++) - if (element_found[i] && (IS_CUSTOM_ELEMENT(i) || IS_GROUP_ELEMENT(i))) + if (element_found[i] && (IS_CUSTOM_ELEMENT(i) || + IS_GROUP_ELEMENT(i) || + IS_EMPTY_ELEMENT(i))) (*elements)[(*num_elements)++] = i; while (*num_elements % 4) // pad with empty elements, if needed @@ -5884,10 +5963,10 @@ static void ReinitializeElementList(void) // determine size of element list for (i = 0; editor_elements_info[i].setup_value != NULL; i++) { - boolean found_inactive_cascade = FALSE; - if (*editor_elements_info[i].setup_value) { + boolean found_inactive_cascade = FALSE; + if (setup.editor.el_headlines) { // required for correct padding of palette headline buttons @@ -6494,11 +6573,9 @@ static void CreateCounterButtons(void) int graphic; struct GraphicInfo *gd; int gd_x1, gd_x2, gd_y1, gd_y2; - unsigned int event_mask; + unsigned int event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED; char infotext[max_infotext_len + 1]; - event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED; - if (i == ED_COUNTER_ID_SELECT_LEVEL) { graphic = (j == 0 ? @@ -6638,7 +6715,6 @@ static void CreateDrawingAreas(void) for (i = 0; i < ED_NUM_DRAWING_AREAS; i++) { struct GadgetInfo *gi; - unsigned int event_mask; int id = drawingarea_info[i].gadget_id; int x = SX + ED_AREA_SETTINGS_X(drawingarea_info[i]); int y = SY + ED_AREA_SETTINGS_Y(drawingarea_info[i]); @@ -6646,8 +6722,7 @@ static void CreateDrawingAreas(void) int area_ysize = drawingarea_info[i].area_ysize; int item_size = (id == GADGET_ID_DRAWING_LEVEL ? ed_tilesize : ED_DRAWINGAREA_TILE_SIZE); - - event_mask = + unsigned int event_mask = GD_EVENT_PRESSED | GD_EVENT_RELEASED | GD_EVENT_MOVING | GD_EVENT_OFF_BORDERS | GD_EVENT_PIXEL_PRECISE; @@ -6694,7 +6769,7 @@ static void CreateTextInputGadgets(void) int gd_x2 = gd->src_x + gd->active_xoffset; int gd_y2 = gd->src_y + gd->active_yoffset; struct GadgetInfo *gi; - unsigned int event_mask; + unsigned int event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING; char infotext[MAX_OUTPUT_LINESIZE + 1]; int id = textinput_info[i].gadget_id; int x, y; @@ -6721,8 +6796,6 @@ static void CreateTextInputGadgets(void) y = ED_SETTINGS_Y(textinput_info[i].y); } - event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING; - sprintf(infotext, "Enter %s", textinput_info[i].infotext); infotext[max_infotext_len] = '\0'; @@ -6765,14 +6838,12 @@ static void CreateTextAreaGadgets(void) int gd_x2 = gd->src_x + gd->active_xoffset; int gd_y2 = gd->src_y + gd->active_yoffset; struct GadgetInfo *gi; - unsigned int event_mask; + unsigned int event_mask = GD_EVENT_TEXT_LEAVING; char infotext[MAX_OUTPUT_LINESIZE + 1]; int id = textarea_info[i].gadget_id; int area_xsize = textarea_info[i].xsize; int area_ysize = textarea_info[i].ysize; - event_mask = GD_EVENT_TEXT_LEAVING; - sprintf(infotext, "Enter %s", textarea_info[i].infotext); infotext[max_infotext_len] = '\0'; @@ -6816,11 +6887,12 @@ static void CreateSelectboxGadgets(void) int gd_y2 = gd->src_y + gd->active_yoffset; int selectbox_button_xsize = gd2->width; struct GadgetInfo *gi; - unsigned int event_mask; char infotext[MAX_OUTPUT_LINESIZE + 1]; int id = selectbox_info[i].gadget_id; int x = SX + ED_SETTINGS_X(selectbox_info[i].x); int y = SY + ED_SETTINGS_Y(selectbox_info[i].y); + unsigned int event_mask = + GD_EVENT_RELEASED | GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING; if (selectbox_info[i].size == -1) // dynamically determine size { @@ -6836,9 +6908,6 @@ static void CreateSelectboxGadgets(void) selectbox_info[i].size++; // add one character empty space } - event_mask = GD_EVENT_RELEASED | - GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING; - // determine horizontal position to the right of specified gadget if (selectbox_info[i].gadget_id_align != GADGET_ID_NONE) x = (right_gadget_border[selectbox_info[i].gadget_id_align] + @@ -6907,7 +6976,7 @@ static void CreateTextbuttonGadgets(void) int border_xsize = gd->border_size + gd->draw_xoffset; int border_ysize = gd->border_size; struct GadgetInfo *gi; - unsigned int event_mask; + unsigned int event_mask = GD_EVENT_RELEASED; char infotext[MAX_OUTPUT_LINESIZE + 1]; int x = SX + ED_SETTINGS_X(textbutton_info[i].x); int y = SY + ED_SETTINGS_Y(textbutton_info[i].y); @@ -6915,8 +6984,6 @@ static void CreateTextbuttonGadgets(void) if (textbutton_info[i].size == -1) // dynamically determine size textbutton_info[i].size = strlen(textbutton_info[i].text); - event_mask = GD_EVENT_RELEASED; - sprintf(infotext, "%s", textbutton_info[i].infotext); infotext[max_infotext_len] = '\0'; @@ -6969,7 +7036,6 @@ static void CreateTextbuttonGadgets(void) static void CreateGraphicbuttonGadgets(void) { struct GadgetInfo *gi; - unsigned int event_mask; int i; // create buttons for scrolling of drawing area and element list @@ -6984,8 +7050,7 @@ static void CreateGraphicbuttonGadgets(void) int gd_y1 = gd->src_y; int gd_x2 = gd->src_x + gd->pressed_xoffset; int gd_y2 = gd->src_y + gd->pressed_yoffset; - - event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED; + unsigned int event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED; // determine horizontal position to the right of specified gadget if (graphicbutton_info[i].gadget_id_align != GADGET_ID_NONE) @@ -7077,7 +7142,7 @@ static void CreateScrollbarGadgets(void) int gd_y2 = gd->src_y + gd->pressed_yoffset; struct GadgetInfo *gi; int items_max, items_visible, item_position; - unsigned int event_mask; + unsigned int event_mask = GD_EVENT_MOVING | GD_EVENT_OFF_BORDERS; if (i == ED_SCROLLBAR_ID_LIST_VERTICAL) { @@ -7101,8 +7166,6 @@ static void CreateScrollbarGadgets(void) } } - event_mask = GD_EVENT_MOVING | GD_EVENT_OFF_BORDERS; - gi = CreateGadget(GDI_CUSTOM_ID, id, GDI_CUSTOM_TYPE_ID, i, GDI_IMAGE_ID, graphic, @@ -7138,11 +7201,8 @@ static void CreateScrollbarGadgets(void) static void CreateCheckbuttonGadgets(void) { struct GadgetInfo *gi; - unsigned int event_mask; int i; - event_mask = GD_EVENT_PRESSED; - for (i = 0; i < ED_NUM_CHECKBUTTONS; i++) { int id = checkbutton_info[i].gadget_id; @@ -7159,6 +7219,7 @@ static void CreateCheckbuttonGadgets(void) int gd_y2a = gd->src_y + gd->active_yoffset + gd->pressed_yoffset; int x = SX + ED_SETTINGS_X(checkbutton_info[i].x); int y = SY + ED_SETTINGS_Y(checkbutton_info[i].y); + unsigned int event_mask = GD_EVENT_PRESSED; // determine horizontal position to the right of specified gadget if (checkbutton_info[i].gadget_id_align != GADGET_ID_NONE) @@ -7210,16 +7271,14 @@ static void CreateRadiobuttonGadgets(void) int gd_x2a = gd->src_x + gd->active_xoffset + gd->pressed_xoffset; int gd_y2a = gd->src_y + gd->active_yoffset + gd->pressed_yoffset; struct GadgetInfo *gi; - unsigned int event_mask; int i; - event_mask = GD_EVENT_PRESSED; - for (i = 0; i < ED_NUM_RADIOBUTTONS; i++) { int id = radiobutton_info[i].gadget_id; int x = SX + ED_SETTINGS_X(radiobutton_info[i].x); int y = SY + ED_SETTINGS_Y(radiobutton_info[i].y); + unsigned int event_mask = GD_EVENT_PRESSED; int checked = (*radiobutton_info[i].value == radiobutton_info[i].checked_value); @@ -7288,6 +7347,8 @@ void CreateLevelEditorGadgets(void) use_permanent_palette = !editor.palette.show_as_separate_screen; + InitGadgetScreenBorders(-1, INFOTEXT_YPOS); + ReinitializeElementList(); CreateControlButtons(); @@ -7480,9 +7541,13 @@ static void MapTextAreaGadget(int id) int yoffset_above = font_height + ED_GADGET_LINE_DISTANCE; int x_above = ED_SETTINGS_X(textarea_info[id].x); int y_above = ED_SETTINGS_Y(textarea_info[id].y) - yoffset_above; + char *text_above = textarea_info[id].text_above; + + if (gi->textarea.cropped && textarea_info[id].text_above_cropped) + text_above = textarea_info[id].text_above_cropped; - if (textarea_info[id].text_above) - DrawTextS(x_above, y_above, font_nr, textarea_info[id].text_above); + if (text_above) + DrawTextS(x_above, y_above, font_nr, text_above); ModifyGadget(gi, GDI_TEXT_VALUE, textarea_info[id].value, GDI_END); @@ -7611,7 +7676,7 @@ static void MapCheckbuttonGadget(int id) // set position for gadgets with dynamically determined position if (checkbutton_info[id].x != -1) // do not change dynamic positions - ModifyGadget(gi, GDI_X, SX + ED_SETTINGS_X(checkbutton_info[id].x),GDI_END); + ModifyGadget(gi, GDI_X, SX + ED_SETTINGS_X(checkbutton_info[id].x), GDI_END); ModifyGadget(gi, GDI_Y, SY + ED_SETTINGS_Y(checkbutton_info[id].y), GDI_END); x_left = gi->x - xoffset_left; @@ -7694,6 +7759,14 @@ static void MapLevelEditorToolboxCustomGadgets(void) MapOrUnmapLevelEditorToolboxCustomGadgets(TRUE); } +static void MapLevelEditorToolboxCustomGadgetsIfNeeded(void) +{ + if (IS_CUSTOM_ELEMENT(properties_element) || + IS_GROUP_ELEMENT(properties_element) || + IS_EMPTY_ELEMENT(properties_element)) + MapLevelEditorToolboxCustomGadgets(); +} + static void UnmapLevelEditorToolboxCustomGadgets(void) { MapOrUnmapLevelEditorToolboxCustomGadgets(FALSE); @@ -8116,6 +8189,12 @@ static boolean CopyCustomElement(int element_old, int element_new, return FALSE; } + else if (IS_EMPTY_ELEMENT(element_old) && !IS_EMPTY_ELEMENT(element_new)) + { + Request("Please choose empty element!", REQ_CONFIRM); + + return FALSE; + } else { level.changed = TRUE; @@ -9504,7 +9583,7 @@ static void DrawMagicBallContentAreas(void) DrawText(x, y + 2 * tilesize, "active", font_nr); } -static void DrawAndroidElementArea(int element) +static void DrawAndroidElementArea(void) { int id = ED_DRAWING_ID_ANDROID_CONTENT; int num_elements = level.num_android_clone_elements; @@ -9532,7 +9611,7 @@ static void DrawAndroidElementArea(int element) MapDrawingArea(id); } -static void DrawGroupElementArea(int element) +static void DrawGroupElementArea(void) { int id = ED_DRAWING_ID_GROUP_CONTENT; int num_elements = group_element_info.num_elements; @@ -9589,13 +9668,40 @@ static void DrawPlayerInitialInventoryArea(int element) 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->width, gi->height); + + DrawBackground(gi->x, gi->y, + gi->textarea.crop_width, gi->textarea.crop_height); if (envelope_nr != -1) textarea_info[id].value = level.envelope[envelope_nr].text; @@ -9669,13 +9775,16 @@ static void DrawPropertiesInfo(void) { -1, NULL } }; char *filename = getElementDescriptionFilename(properties_element); - char *percentage_text = "In this level: "; + char *num_elements_text = "In this level: "; + char *num_similar_text = "Similar tiles: "; char *properties_text = "Standard properties: "; char *description_text = "Description:"; char *no_description_text = "No description available."; char *none_text = "None"; float percentage; - int num_elements_in_level; + int num_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; @@ -9684,7 +9793,8 @@ static void DrawPropertiesInfo(void) int font2_height = getFontHeight(font2_nr); int line1_height = font1_height + ED_GADGET_LINE_DISTANCE; int font2_yoffset = (font1_height - font2_height) / 2; - int percentage_text_len = strlen(percentage_text) * font1_width; + int num_elements_text_len = strlen(num_elements_text) * font1_width; + int num_similar_text_len = strlen(num_similar_text) * font1_width; int properties_text_len = strlen(properties_text) * font1_width; int xpos = ED_ELEMENT_SETTINGS_X(0); int ypos = ED_ELEMENT_SETTINGS_Y(0) + ED_GADGET_SMALL_DISTANCE; @@ -9703,22 +9813,66 @@ static void DrawPropertiesInfo(void) // ----- print number of elements / percentage of this element in level - num_elements_in_level = 0; - for (y = 0; y < lev_fieldy; y++) + 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, percentage_text); + DrawTextS(xpos, ypos, font1_nr, num_elements_text); - if (num_elements_in_level > 0) - DrawTextF(xpos + percentage_text_len, ypos + font2_yoffset, font2_nr, + 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 + percentage_text_len, ypos + font2_yoffset, font2_nr, + DrawTextF(xpos + num_elements_text_len, ypos + font2_yoffset, font2_nr, none_text); + // ----- print number of similar elements / percentage of them in level + + 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 @@ -9767,6 +9921,7 @@ static void DrawPropertiesInfo(void) #define TEXT_DURATION "Duration when activated" #define TEXT_DELAY_ON "Delay before activating" #define TEXT_DELAY_OFF "Delay before deactivating" +#define TEXT_DELAY_CHANGING "Delay before changing" #define TEXT_DELAY_EXPLODING "Delay before exploding" #define TEXT_DELAY_MOVING "Delay before moving" #define TEXT_BALL_DELAY "Element generation delay" @@ -9831,9 +9986,9 @@ static struct { 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_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 }, @@ -9898,7 +10053,7 @@ static struct { EL_EMC_MAGNIFIER, &level.magnify_time, TEXT_DURATION }, { EL_MM_FUSE_ACTIVE, &level.mm_time_fuse, TEXT_DELAY_OFF }, { EL_MM_BOMB, &level.mm_time_bomb, TEXT_DELAY_EXPLODING }, - { EL_MM_GRAY_BALL, &level.mm_time_ball, TEXT_DELAY_ON }, + { EL_MM_GRAY_BALL, &level.mm_time_ball, TEXT_DELAY_CHANGING }, { EL_MM_STEEL_BLOCK, &level.mm_time_block, TEXT_DELAY_MOVING }, { EL_MM_WOODEN_BLOCK, &level.mm_time_block, TEXT_DELAY_MOVING }, @@ -9915,6 +10070,7 @@ static boolean checkPropertiesConfig(int 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) || @@ -10071,7 +10227,16 @@ static void DrawPropertiesConfig(void) MapCheckbuttonGadget(ED_CHECKBUTTON_ID_INITIAL_BALL_ACTIVE); } else if (properties_element == EL_EMC_ANDROID) - DrawAndroidElementArea(properties_element); + 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)) @@ -10212,13 +10377,14 @@ static void DrawPropertiesConfig(void) if (IS_BALLOON_ELEMENT(properties_element)) MapSelectboxGadget(ED_SELECTBOX_ID_WIND_DIRECTION); - if (IS_ENVELOPE(properties_element)) + 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 = properties_element - EL_ENVELOPE_1; + 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; @@ -10326,7 +10492,7 @@ static void DrawPropertiesConfig(void) MapTextbuttonGadget(ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE_1); // draw drawing area gadgets - DrawGroupElementArea(properties_element); + DrawGroupElementArea(); // draw text input gadgets MapTextInputGadget(ED_TEXTINPUT_ID_ELEMENT_NAME); @@ -10443,12 +10609,12 @@ static void DrawEditorElementName(int x, int y, int font_nr) int font_height = getFontHeight(font_nr); int max_text_width = SXSIZE - x - ED_ELEMENT_SETTINGS_X(0); int max_chars_per_line = max_text_width / font_width; - char buffer[max_chars_per_line + 1]; if (strlen(element_name) <= max_chars_per_line) DrawTextS(x, y, font_nr, element_name); else { + char buffer[max_chars_per_line + 1]; int next_pos = max_chars_per_line; strncpy(buffer, element_name, max_chars_per_line); @@ -10524,9 +10690,7 @@ static void DrawPropertiesWindow(void) UnmapLevelEditorToolboxDrawingGadgets(); UnmapLevelEditorToolboxCustomGadgets(); - if (IS_CUSTOM_ELEMENT(properties_element) || - IS_GROUP_ELEMENT(properties_element)) - MapLevelEditorToolboxCustomGadgets(); + MapLevelEditorToolboxCustomGadgetsIfNeeded(); SetMainBackgroundImage(IMG_BACKGROUND_EDITOR); ClearField(); @@ -10835,13 +10999,7 @@ static int getChipFromOpenDirectionNotEmpty(int direction, int element_old) static int getClosedTube(int x, int y) { - static int xy[4][2] = - { - { -1, 0 }, - { +1, 0 }, - { 0, -1 }, - { 0, +1 } - }; + struct XY *xy = xy_directions; int element_old = IntelliDrawBuffer[x][y]; int direction_old = getOpenDirectionFromTube(element_old); int direction_new = MV_NONE; @@ -10849,8 +11007,8 @@ static int getClosedTube(int x, int y) for (i = 0; i < NUM_DIRECTIONS; i++) { - int xx = x + xy[i][0]; - int yy = y + xy[i][1]; + int xx = x + xy[i].x; + int yy = y + xy[i].y; int dir = MV_DIR_FROM_BIT(i); int dir_opposite = MV_DIR_OPPOSITE(dir); @@ -10865,13 +11023,7 @@ static int getClosedTube(int x, int y) static int getClosedBelt(int x, int y) { - static int xy[4][2] = - { - { -1, 0 }, - { +1, 0 }, - { 0, -1 }, - { 0, +1 } - }; + struct XY *xy = xy_directions; int element_old = IntelliDrawBuffer[x][y]; int nr = getBeltNrFromBeltElement(element_old); int direction_old = getOpenDirectionFromBelt(element_old); @@ -10880,8 +11032,8 @@ static int getClosedBelt(int x, int y) for (i = MV_BIT_LEFT; i <= MV_BIT_RIGHT; i++) { - int xx = x + xy[i][0]; - int yy = y + xy[i][1]; + int xx = x + xy[i].x; + int yy = y + xy[i].y; int dir = MV_DIR_FROM_BIT(i); int dir_opposite = MV_DIR_OPPOSITE(dir); @@ -10896,13 +11048,7 @@ static int getClosedBelt(int x, int y) static int getClosedPool(int x, int y) { - static int xy[4][2] = - { - { -1, 0 }, - { +1, 0 }, - { 0, -1 }, - { 0, +1 } - }; + struct XY *xy = xy_directions; int element_old = IntelliDrawBuffer[x][y]; int direction_old = getOpenDirectionFromPool(element_old); int direction_new = MV_NONE; @@ -10910,8 +11056,8 @@ static int getClosedPool(int x, int y) for (i = 0; i < NUM_DIRECTIONS; i++) { - int xx = x + xy[i][0]; - int yy = y + xy[i][1]; + int xx = x + xy[i].x; + int yy = y + xy[i].y; int dir = MV_DIR_FROM_BIT(i); int dir_opposite = MV_DIR_OPPOSITE(dir); @@ -10927,13 +11073,7 @@ static int getClosedPool(int x, int y) static int getClosedPillar(int x, int y) { - static int xy[4][2] = - { - { -1, 0 }, - { +1, 0 }, - { 0, -1 }, - { 0, +1 } - }; + struct XY *xy = xy_directions; int element_old = IntelliDrawBuffer[x][y]; int direction_old = getOpenDirectionFromPillar(element_old); int direction_new = MV_NONE; @@ -10941,8 +11081,8 @@ static int getClosedPillar(int x, int y) for (i = MV_BIT_UP; i <= MV_BIT_DOWN; i++) { - int xx = x + xy[i][0]; - int yy = y + xy[i][1]; + int xx = x + xy[i].x; + int yy = y + xy[i].y; int dir = MV_DIR_FROM_BIT(i); int dir_opposite = MV_DIR_OPPOSITE(dir); @@ -10957,13 +11097,7 @@ static int getClosedPillar(int x, int y) static int getClosedSteel2(int x, int y) { - static int xy[4][2] = - { - { -1, 0 }, - { +1, 0 }, - { 0, -1 }, - { 0, +1 } - }; + struct XY *xy = xy_directions; int element_old = IntelliDrawBuffer[x][y]; int direction_old = getOpenDirectionFromSteel2(element_old); int direction_new = MV_NONE; @@ -10971,8 +11105,8 @@ static int getClosedSteel2(int x, int y) for (i = 0; i < NUM_DIRECTIONS; i++) { - int xx = x + xy[i][0]; - int yy = y + xy[i][1]; + int xx = x + xy[i].x; + int yy = y + xy[i].y; int dir = MV_DIR_FROM_BIT(i); int dir_opposite = MV_DIR_OPPOSITE(dir); @@ -10987,13 +11121,7 @@ static int getClosedSteel2(int x, int y) static int getClosedChip(int x, int y) { - static int xy[4][2] = - { - { -1, 0 }, - { +1, 0 }, - { 0, -1 }, - { 0, +1 } - }; + struct XY *xy = xy_directions; int element_old = IntelliDrawBuffer[x][y]; int direction_old = getOpenDirectionFromChip(element_old); int direction_new = MV_NONE; @@ -11001,8 +11129,8 @@ static int getClosedChip(int x, int y) for (i = 0; i < NUM_DIRECTIONS; i++) { - int xx = x + xy[i][0]; - int yy = y + xy[i][1]; + int xx = x + xy[i].x; + int yy = y + xy[i].y; int dir = MV_DIR_FROM_BIT(i); int dir_opposite = MV_DIR_OPPOSITE(dir); @@ -11082,16 +11210,10 @@ static void MergeAndCloseNeighbourElements(int x1, int y1, int *element1, SetElementSimple(x2, y2, *element2, change_level); } -static void SetElementIntelliDraw(int x, int y, int new_element, +static void SetElementIntelliDraw(int x, int y, int dx, int dy, int new_element, boolean change_level, int button) { - static int xy[4][2] = - { - { -1, 0 }, - { +1, 0 }, - { 0, -1 }, - { 0, +1 } - }; + struct XY *xy = xy_directions; static int last_x = -1; static int last_y = -1; @@ -11117,8 +11239,8 @@ static void SetElementIntelliDraw(int x, int y, int new_element, for (i = 0; i < NUM_DIRECTIONS; i++) { - int xx = x + xy[i][0]; - int yy = y + xy[i][1]; + int xx = x + xy[i].x; + int yy = y + xy[i].y; if (last_x == xx && last_y == yy && IN_LEV_FIELD(last_x, last_y) && IS_TUBE(IntelliDrawBuffer[last_x][last_y])) @@ -11155,8 +11277,8 @@ static void SetElementIntelliDraw(int x, int y, int new_element, for (i = MV_BIT_LEFT; i <= MV_BIT_RIGHT; i++) { - int xx = x + xy[i][0]; - int yy = y + xy[i][1]; + int xx = x + xy[i].x; + int yy = y + xy[i].y; if (last_x == xx && last_y == yy && IN_LEV_FIELD(last_x, last_y) && IS_BELT(IntelliDrawBuffer[last_x][last_y])) @@ -11193,8 +11315,8 @@ static void SetElementIntelliDraw(int x, int y, int new_element, for (i = 0; i < NUM_DIRECTIONS; i++) { - int xx = x + xy[i][0]; - int yy = y + xy[i][1]; + int xx = x + xy[i].x; + int yy = y + xy[i].y; if (last_x == xx && last_y == yy && IN_LEV_FIELD(last_x, last_y) && IS_ACID_POOL_OR_ACID(IntelliDrawBuffer[last_x][last_y])) @@ -11236,8 +11358,8 @@ static void SetElementIntelliDraw(int x, int y, int new_element, for (i = MV_BIT_UP; i <= MV_BIT_DOWN; i++) { - int xx = x + xy[i][0]; - int yy = y + xy[i][1]; + int xx = x + xy[i].x; + int yy = y + xy[i].y; if (last_x == xx && last_y == yy && IN_LEV_FIELD(last_x, last_y) && IS_EMC_PILLAR(IntelliDrawBuffer[last_x][last_y])) @@ -11273,8 +11395,8 @@ static void SetElementIntelliDraw(int x, int y, int new_element, for (i = 0; i < NUM_DIRECTIONS; i++) { - int xx = x + xy[i][0]; - int yy = y + xy[i][1]; + int xx = x + xy[i].x; + int yy = y + xy[i].y; if (last_x == xx && last_y == yy && IN_LEV_FIELD(last_x, last_y) && IS_DC_STEELWALL_2(IntelliDrawBuffer[last_x][last_y])) @@ -11308,8 +11430,8 @@ static void SetElementIntelliDraw(int x, int y, int new_element, for (i = 0; i < NUM_DIRECTIONS; i++) { - int xx = x + xy[i][0]; - int yy = y + xy[i][1]; + int xx = x + xy[i].x; + int yy = y + xy[i].y; if (last_x == xx && last_y == yy && IN_LEV_FIELD(last_x, last_y) && IS_SP_CHIP(IntelliDrawBuffer[last_x][last_y])) @@ -11369,8 +11491,8 @@ static void SetElementIntelliDraw(int x, int y, int new_element, for (i = 0; i < NUM_DIRECTIONS; i++) { - int xx = x + xy[i][0]; - int yy = y + xy[i][1]; + int xx = x + xy[i].x; + int yy = y + xy[i].y; if (last_x == xx && last_y == yy && IN_LEV_FIELD(last_x, last_y) && IS_IN_GROUP_EL(IntelliDrawBuffer[last_x][last_y], new_element)) @@ -11860,7 +11982,10 @@ static void SetElementIntelliDraw(int x, int y, int new_element, } } - SetElementSimple(x, y, new_element, change_level); + if (IS_MM_WALL_EDITOR(new_element)) + SetElementSimpleExt(x, y, dx, dy, new_element, change_level); + else + SetElementSimple(x, y, new_element, change_level); last_x = x; last_y = y; @@ -11874,7 +11999,7 @@ static void ResetIntelliDraw(void) for (y = 0; y < lev_fieldy; y++) IntelliDrawBuffer[x][y] = Tile[x][y]; - SetElementIntelliDraw(-1, -1, EL_UNDEFINED, FALSE, -1); + SetElementIntelliDraw(-1, -1, -1, -1, EL_UNDEFINED, FALSE, -1); } static boolean draw_mode_hires = FALSE; @@ -11889,6 +12014,23 @@ static boolean isHiresDrawElement(int element) return (IS_MM_WALL_EDITOR(element) || element == EL_EMPTY); } +static int numHiresTiles(int element) +{ + if (!IS_MM_WALL(element)) + return 1; + + int bits = MM_WALL_BITS(element); + int num_bits = 0; + + while (bits) + { + bits &= bits - 1; + num_bits++; + } + + return num_bits; +} + static void SetDrawModeHiRes(int element) { draw_mode_hires = @@ -11916,8 +12058,8 @@ static void SetElementExt(int x, int y, int dx, int dy, int element, { if (element < 0) SetElementSimple(x, y, Tile[x][y], change_level); - else if (GetKeyModState() & KMOD_Shift && !IS_MM_WALL_EDITOR(element)) - SetElementIntelliDraw(x, y, element, change_level, button); + else if (GetKeyModState() & KMOD_Shift) + SetElementIntelliDraw(x, y, dx, dy, element, change_level, button); else SetElementSimpleExt(x, y, dx, dy, element, change_level); } @@ -12119,7 +12261,7 @@ static void DrawCircle(int from_x, int from_y, int to_x, int to_y, DrawArcExt(from_x, from_y, to_x2, to_y2, element, change_level); DrawArcExt(from_x, from_y, mirror_to_x2, to_y2, element, change_level); DrawArcExt(from_x, from_y, to_x2, mirror_to_y2, element, change_level); - DrawArcExt(from_x, from_y, mirror_to_x2, mirror_to_y2, element,change_level); + DrawArcExt(from_x, from_y, mirror_to_x2, mirror_to_y2, element, change_level); } #endif @@ -12655,7 +12797,7 @@ static int DrawLevelText(int sx, int sy, char letter, int mode) static int start_sx; static int last_sx, last_sy; static boolean typing = FALSE; - int letter_element = EL_CHAR_ASCII0 + letter; + int letter_element; int lx = 0, ly = 0; // map lower case letters to upper case and convert special characters @@ -12958,8 +13100,10 @@ static void CopyLevelTemplateToUserLevelSet(char *levelset_subdir) static void HandleDrawingAreas(struct GadgetInfo *gi) { static boolean started_inside_drawing_area = FALSE; - static int last_sx = -1, last_sy = -1; - static int last_sx2 = -1, last_sy2 = -1; + static int last_sx = -1; + static int last_sy = -1; + static int last_sx2 = -1; + static int last_sy2 = -1; int id = gi->custom_id; int type_id = gi->custom_type_id; boolean button_press_event; @@ -12979,8 +13123,6 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) int dx = sx2 % 2; int dy = sy2 % 2; int lx = 0, ly = 0; - int min_lx = 0, min_ly = 0; - int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1; int x, y; button_press_event = (gi->event.type == GD_EVENT_PRESSED); @@ -12992,6 +13134,9 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) if (draw_level) { + int min_lx = 0, min_ly = 0; + int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1; + // get positions inside level field lx = sx + level_xpos; ly = sy + level_ypos; @@ -13020,14 +13165,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) sy2 = sy * 2 + dy; } - if (button_release_event) - { - last_sx = -1; - last_sy = -1; - last_sx2 = -1; - last_sy2 = -1; - } - else if (!button_press_event) + if (!button_press_event && !button_release_event) { int old_element = (IN_LEV_FIELD(lx, ly) ? Tile[lx][ly] : EL_UNDEFINED); boolean hires_drawing = (level.game_engine_type == GAME_ENGINE_TYPE_MM && @@ -13054,9 +13192,6 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) if (!IS_VALID_BUTTON(button)) return; - if (!button && !button_release_event) - return; - // handle info callback for each invocation of action callback gi->callback_info(gi); @@ -13092,10 +13227,9 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) if (edit_mode == ED_MODE_DRAWING && draw_with_brush && !inside_drawing_area) DeleteBrushFromCursor(); - } - if (!button || button_release_event) break; + } if (draw_with_brush) { @@ -13105,7 +13239,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) { SetDrawModeHiRes(new_element); - if (IS_PLAYER_ELEMENT(new_element)) + if (IS_PLAYER_ELEMENT(new_element) || IS_MM_MCDUFFIN(new_element)) { // remove player at old position for (y = 0; y < lev_fieldy; y++) @@ -13114,7 +13248,8 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) { int old_element = Tile[x][y]; - if (IS_PLAYER_ELEMENT(old_element)) + if (IS_PLAYER_ELEMENT(old_element) && + IS_PLAYER_ELEMENT(new_element)) { int replaced_with_element = (old_element == EL_SOKOBAN_FIELD_PLAYER && @@ -13134,6 +13269,12 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) SetElement(x, y, replaced_with_element); } + else if (IS_MM_MCDUFFIN(old_element) && + IS_MM_MCDUFFIN(new_element)) + { + // remove McDuffin at old position + SetElement(x, y, EL_EMPTY); + } } } } @@ -13180,22 +13321,19 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) if (button_release_event) CopyLevelToUndoBuffer(UNDO_IMMEDIATE); - if (button) - { - SetDrawModeHiRes(new_element); + SetDrawModeHiRes(new_element); - if (getDrawModeHiRes()) - { - sx = sx2; - sy = sy2; - } + if (getDrawModeHiRes()) + { + sx = sx2; + sy = sy2; + } - if (!button_press_event) - DrawLine(last_sx, last_sy, sx, sy, new_element, TRUE); + if (!button_press_event) + DrawLine(last_sx, last_sy, sx, sy, new_element, TRUE); - last_sx = sx; - last_sy = sy; - } + last_sx = sx; + last_sy = sy; } break; @@ -13378,11 +13516,11 @@ static void HandleCounterButtons(struct GadgetInfo *gi) break; case ED_COUNTER_ID_ANDROID_CONTENT: - DrawAndroidElementArea(properties_element); + DrawAndroidElementArea(); break; case ED_COUNTER_ID_GROUP_CONTENT: - DrawGroupElementArea(properties_element); + DrawGroupElementArea(); CopyGroupElementPropertiesToGame(properties_element); break; @@ -13390,6 +13528,10 @@ static void HandleCounterButtons(struct GadgetInfo *gi) DrawPlayerInitialInventoryArea(properties_element); break; + case ED_COUNTER_ID_MM_BALL_CONTENT: + DrawMMBallContentArea(); + break; + case ED_COUNTER_ID_ENVELOPE_XSIZE: case ED_COUNTER_ID_ENVELOPE_YSIZE: DrawEnvelopeTextArea(-1); @@ -14284,7 +14426,8 @@ static void HandleControlButtons(struct GadgetInfo *gi) id <= GADGET_ID_ELEMENTLIST_LAST) { int element_position = id - GADGET_ID_ELEMENTLIST_FIRST; - int new_element = editor_elements[element_position + element_shift]; + + new_element = editor_elements[element_position + element_shift]; if (IS_EDITOR_CASCADE(new_element)) { @@ -14524,11 +14667,12 @@ static void HandleLevelEditorIdle_Properties(void) int element_border = graphic_info[IMG_EDITOR_ELEMENT_BORDER].border_size; int x = editor.settings.element_graphic.x + element_border; int y = editor.settings.element_graphic.y + element_border; - static unsigned int action_delay = 0; - unsigned int action_delay_value = GameFrameDelay; + static DelayCounter action_delay = { 0 }; int i; - if (!DelayReached(&action_delay, action_delay_value)) + action_delay.value = GameFrameDelay; + + if (!DelayReached(&action_delay)) return; for (i = 0; i < ED_NUM_SELECTBOX; i++) @@ -14577,7 +14721,6 @@ static void ClearEditorGadgetInfoText(void) void PrintEditorGadgetInfoText(struct GadgetInfo *gi) { char infotext[MAX_OUTPUT_LINESIZE + 1]; - char shortcut[MAX_OUTPUT_LINESIZE + 1]; int max_infotext_len = getMaxInfoTextLength(); if (gi == NULL || strlen(gi->info_text) == 0) @@ -14592,6 +14735,8 @@ void PrintEditorGadgetInfoText(struct GadgetInfo *gi) if (key) { + char shortcut[MAX_OUTPUT_LINESIZE + 1]; + if (gi->custom_id == GADGET_ID_SINGLE_ITEMS) sprintf(shortcut, " ('.' or '%c')", key); else if (gi->custom_id == GADGET_ID_PICK_ELEMENT) @@ -14635,7 +14780,6 @@ void HandleEditorGadgetInfoText(void *ptr) static void HandleDrawingAreaInfo(struct GadgetInfo *gi) { - static int start_lx, start_ly; int id = gi->custom_id; int type_id = gi->custom_type_id; int sx = gi->event.x; @@ -14648,7 +14792,6 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi) int actual_drawing_function = drawing_function; int max_infotext_len = getMaxInfoTextLength(); char infotext[MAX_OUTPUT_LINESIZE + 1]; - char *text; infotext[0] = '\0'; // start with empty info text @@ -14685,10 +14828,14 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi) sy = ly - level_ypos; } - if (IN_ED_FIELD(sx,sy) && IN_LEV_FIELD(lx, ly)) + if (IN_ED_FIELD(sx, sy) && IN_LEV_FIELD(lx, ly)) { if (button_status) // if (gi->state == GD_BUTTON_PRESSED) { + static int start_lx = 0; + static int start_ly = 0; + char *text; + if (gi->event.type == GD_EVENT_PRESSED) { start_lx = lx;