X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Feditor.c;h=89df2f00c393705b993f821afc328e404478c947;hb=52618d96636faf28e6520f5283e164f750d382f0;hp=8338bbb37973bb5fa8cb3456982e1484c53d1455;hpb=f0b6179ac5fd4ff548d4263488373408f92874e8;p=rocksndiamonds.git diff --git a/src/editor.c b/src/editor.c index 8338bbb3..89df2f00 100644 --- a/src/editor.c +++ b/src/editor.c @@ -3462,7 +3462,7 @@ static struct int gadget_id_align; int *value; int area_xsize, area_ysize; - char *text_left, *text_right, *text_below, *infotext; + char *text_left, *text_right, *text_above, *text_below, *infotext; } drawingarea_info[ED_NUM_DRAWING_AREAS] = { // ---------- level playfield content --------------------------------------- @@ -3473,7 +3473,7 @@ static struct GADGET_ID_DRAWING_LEVEL, GADGET_ID_NONE, NULL, -1, -1, // these values are not constant, but can change at runtime - NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL, NULL }, // ---------- yam yam content ----------------------------------------------- @@ -3483,56 +3483,56 @@ static struct ED_AREA_YAMYAM_CONTENT_XOFF(0), ED_AREA_YAMYAM_CONTENT_YOFF(0), GADGET_ID_YAMYAM_CONTENT_0, GADGET_ID_NONE, &level.yamyam_content[0].e[0][0], 3, 3, - NULL, NULL, "1", NULL + NULL, NULL, NULL, "1", NULL }, { ED_AREA_YAMYAM_CONTENT_XPOS, ED_AREA_YAMYAM_CONTENT_YPOS, ED_AREA_YAMYAM_CONTENT_XOFF(1), ED_AREA_YAMYAM_CONTENT_YOFF(1), GADGET_ID_YAMYAM_CONTENT_1, GADGET_ID_NONE, &level.yamyam_content[1].e[0][0], 3, 3, - NULL, NULL, "2", NULL + NULL, NULL, NULL, "2", NULL }, { ED_AREA_YAMYAM_CONTENT_XPOS, ED_AREA_YAMYAM_CONTENT_YPOS, ED_AREA_YAMYAM_CONTENT_XOFF(2), ED_AREA_YAMYAM_CONTENT_YOFF(2), GADGET_ID_YAMYAM_CONTENT_2, GADGET_ID_NONE, &level.yamyam_content[2].e[0][0], 3, 3, - NULL, NULL, "3", NULL + NULL, NULL, NULL, "3", NULL }, { ED_AREA_YAMYAM_CONTENT_XPOS, ED_AREA_YAMYAM_CONTENT_YPOS, ED_AREA_YAMYAM_CONTENT_XOFF(3), ED_AREA_YAMYAM_CONTENT_YOFF(3), GADGET_ID_YAMYAM_CONTENT_3, GADGET_ID_NONE, &level.yamyam_content[3].e[0][0], 3, 3, - NULL, NULL, "4", NULL + NULL, NULL, NULL, "4", NULL }, { ED_AREA_YAMYAM_CONTENT_XPOS, ED_AREA_YAMYAM_CONTENT_YPOS, ED_AREA_YAMYAM_CONTENT_XOFF(4), ED_AREA_YAMYAM_CONTENT_YOFF(4), GADGET_ID_YAMYAM_CONTENT_4, GADGET_ID_NONE, &level.yamyam_content[4].e[0][0], 3, 3, - NULL, NULL, "5", NULL + NULL, NULL, NULL, "5", NULL }, { ED_AREA_YAMYAM_CONTENT_XPOS, ED_AREA_YAMYAM_CONTENT_YPOS, ED_AREA_YAMYAM_CONTENT_XOFF(5), ED_AREA_YAMYAM_CONTENT_YOFF(5), GADGET_ID_YAMYAM_CONTENT_5, GADGET_ID_NONE, &level.yamyam_content[5].e[0][0], 3, 3, - NULL, NULL, "6", NULL + NULL, NULL, NULL, "6", NULL }, { ED_AREA_YAMYAM_CONTENT_XPOS, ED_AREA_YAMYAM_CONTENT_YPOS, ED_AREA_YAMYAM_CONTENT_XOFF(6), ED_AREA_YAMYAM_CONTENT_YOFF(6), GADGET_ID_YAMYAM_CONTENT_6, GADGET_ID_NONE, &level.yamyam_content[6].e[0][0], 3, 3, - NULL, NULL, "7", NULL + NULL, NULL, NULL, "7", NULL }, { ED_AREA_YAMYAM_CONTENT_XPOS, ED_AREA_YAMYAM_CONTENT_YPOS, ED_AREA_YAMYAM_CONTENT_XOFF(7), ED_AREA_YAMYAM_CONTENT_YOFF(7), GADGET_ID_YAMYAM_CONTENT_7, GADGET_ID_NONE, &level.yamyam_content[7].e[0][0], 3, 3, - NULL, NULL, "8", NULL + NULL, NULL, NULL, "8", NULL }, // ---------- magic ball content -------------------------------------------- @@ -3542,56 +3542,56 @@ static struct ED_AREA_MAGIC_BALL_CONTENT_XOFF(0), ED_AREA_MAGIC_BALL_CONTENT_YOFF(0), GADGET_ID_MAGIC_BALL_CONTENT_0, GADGET_ID_NONE, &level.ball_content[0].e[0][0], 3, 3, - NULL, NULL, "1", NULL + NULL, NULL, NULL, "1", NULL }, { ED_AREA_MAGIC_BALL_CONTENT_XPOS, ED_AREA_MAGIC_BALL_CONTENT_YPOS, ED_AREA_MAGIC_BALL_CONTENT_XOFF(1), ED_AREA_MAGIC_BALL_CONTENT_YOFF(1), GADGET_ID_MAGIC_BALL_CONTENT_1, GADGET_ID_NONE, &level.ball_content[1].e[0][0], 3, 3, - NULL, NULL, "2", NULL + NULL, NULL, NULL, "2", NULL }, { ED_AREA_MAGIC_BALL_CONTENT_XPOS, ED_AREA_MAGIC_BALL_CONTENT_YPOS, ED_AREA_MAGIC_BALL_CONTENT_XOFF(2), ED_AREA_MAGIC_BALL_CONTENT_YOFF(2), GADGET_ID_MAGIC_BALL_CONTENT_2, GADGET_ID_NONE, &level.ball_content[2].e[0][0], 3, 3, - NULL, NULL, "3", NULL + NULL, NULL, NULL, "3", NULL }, { ED_AREA_MAGIC_BALL_CONTENT_XPOS, ED_AREA_MAGIC_BALL_CONTENT_YPOS, ED_AREA_MAGIC_BALL_CONTENT_XOFF(3), ED_AREA_MAGIC_BALL_CONTENT_YOFF(3), GADGET_ID_MAGIC_BALL_CONTENT_3, GADGET_ID_NONE, &level.ball_content[3].e[0][0], 3, 3, - NULL, NULL, "4", NULL + NULL, NULL, NULL, "4", NULL }, { ED_AREA_MAGIC_BALL_CONTENT_XPOS, ED_AREA_MAGIC_BALL_CONTENT_YPOS, ED_AREA_MAGIC_BALL_CONTENT_XOFF(4), ED_AREA_MAGIC_BALL_CONTENT_YOFF(4), GADGET_ID_MAGIC_BALL_CONTENT_4, GADGET_ID_NONE, &level.ball_content[4].e[0][0], 3, 3, - NULL, NULL, "5", NULL + NULL, NULL, NULL, "5", NULL }, { ED_AREA_MAGIC_BALL_CONTENT_XPOS, ED_AREA_MAGIC_BALL_CONTENT_YPOS, ED_AREA_MAGIC_BALL_CONTENT_XOFF(5), ED_AREA_MAGIC_BALL_CONTENT_YOFF(5), GADGET_ID_MAGIC_BALL_CONTENT_5, GADGET_ID_NONE, &level.ball_content[5].e[0][0], 3, 3, - NULL, NULL, "6", NULL + NULL, NULL, NULL, "6", NULL }, { ED_AREA_MAGIC_BALL_CONTENT_XPOS, ED_AREA_MAGIC_BALL_CONTENT_YPOS, ED_AREA_MAGIC_BALL_CONTENT_XOFF(6), ED_AREA_MAGIC_BALL_CONTENT_YOFF(6), GADGET_ID_MAGIC_BALL_CONTENT_6, GADGET_ID_NONE, &level.ball_content[6].e[0][0], 3, 3, - NULL, NULL, "7", NULL + NULL, NULL, NULL, "7", NULL }, { ED_AREA_MAGIC_BALL_CONTENT_XPOS, ED_AREA_MAGIC_BALL_CONTENT_YPOS, ED_AREA_MAGIC_BALL_CONTENT_XOFF(7), ED_AREA_MAGIC_BALL_CONTENT_YOFF(7), GADGET_ID_MAGIC_BALL_CONTENT_7, GADGET_ID_NONE, &level.ball_content[7].e[0][0], 3, 3, - NULL, NULL, "8", NULL + NULL, NULL, NULL, "8", NULL }, // ---------- android content ----------------------------------------------- @@ -3601,7 +3601,7 @@ static struct ED_AREA_1X1_SETTINGS_XOFF, ED_AREA_1X1_SETTINGS_YOFF, GADGET_ID_ANDROID_CONTENT, GADGET_ID_NONE, &level.android_clone_element[0], MAX_ANDROID_ELEMENTS, 1, - "elements:", NULL, NULL, "elements android can clone" + "elements:", NULL, NULL, NULL, "elements android can clone" }, // ---------- amoeba content ------------------------------------------------ @@ -3611,7 +3611,7 @@ static struct ED_AREA_1X1_SETTINGS_XOFF, ED_AREA_1X1_SETTINGS_YOFF, GADGET_ID_AMOEBA_CONTENT, GADGET_ID_NONE, &level.amoeba_content, 1, 1, - "content:", NULL, NULL, "amoeba content" + "content:", NULL, NULL, NULL, "amoeba content" }, // ---------- level start element ------------------------------------------- @@ -3621,7 +3621,7 @@ static struct 0, ED_AREA_1X1_SETTINGS_YOFF, GADGET_ID_START_ELEMENT, GADGET_ID_USE_START_ELEMENT, &level.start_element[0], 1, 1, - NULL, NULL, NULL, "level start element" + NULL, NULL, NULL, NULL, "level start element" }, // ---------- player artwork element ---------------------------------------- @@ -3631,7 +3631,7 @@ static struct 0, ED_AREA_1X1_SETTINGS_YOFF, GADGET_ID_ARTWORK_ELEMENT, GADGET_ID_USE_ARTWORK_ELEMENT, &level.artwork_element[0], 1, 1, - NULL, NULL, NULL, "element for player artwork" + NULL, NULL, NULL, NULL, "element for player artwork" }, // ---------- player explosion element -------------------------------------- @@ -3641,7 +3641,7 @@ static struct 0, ED_AREA_1X1_SETTINGS_YOFF, GADGET_ID_EXPLOSION_ELEMENT, GADGET_ID_USE_EXPLOSION_ELEMENT, &level.explosion_element[0], 1, 1, - NULL, NULL, NULL, "element for player explosion" + NULL, NULL, NULL, NULL, "element for player explosion" }, // ---------- player initial inventory -------------------------------------- @@ -3651,7 +3651,7 @@ static struct 0, ED_AREA_1X1_SETTINGS_YOFF, GADGET_ID_INVENTORY_CONTENT, GADGET_ID_USE_INITIAL_INVENTORY, &level.initial_inventory_content[0][0], MAX_INITIAL_INVENTORY_SIZE, 1, - NULL, NULL, NULL, "content for initial inventory" + NULL, NULL, NULL, NULL, "content for initial inventory" }, // ---------- element settings: configure 1 (custom elements) --------------- @@ -3663,7 +3663,7 @@ static struct 0, ED_AREA_1X1_SETTINGS_YOFF, GADGET_ID_CUSTOM_GRAPHIC, GADGET_ID_CUSTOM_USE_GRAPHIC, &custom_element.gfx_element_initial,1, 1, - NULL, NULL, NULL, "custom graphic element" + NULL, NULL, NULL, NULL, "custom graphic element" }, // ---------- element settings: configure 2 (custom elements) --------------- @@ -3675,7 +3675,7 @@ static struct 0, ED_AREA_3X3_SETTINGS_YOFF, GADGET_ID_CUSTOM_CONTENT, GADGET_ID_NONE, // align three rows &custom_element.content.e[0][0], 3, 3, - "content:", NULL, NULL, NULL + "content:", NULL, NULL, NULL, NULL }, // ---------- custom enter and leave element (when moving) ------------------ @@ -3685,14 +3685,14 @@ static struct ED_AREA_1X1_SETTINGS_XOFF, ED_AREA_1X1_SETTINGS_YOFF, GADGET_ID_CUSTOM_MOVE_ENTER, GADGET_ID_NONE, &custom_element.move_enter_element, 1, 1, - "can dig:", " ", NULL, "element that can be digged/collected" + "can dig:", " ", NULL, NULL, "element that can be digged/collected" }, { -1, ED_AREA_1X1_SETTINGS_YPOS(3), 0, ED_AREA_1X1_SETTINGS_YOFF, GADGET_ID_CUSTOM_MOVE_LEAVE, GADGET_ID_CUSTOM_MOVE_LEAVE_TYPE, &custom_element.move_leave_element, 1, 1, - NULL, NULL, NULL, "element that will be left behind" + NULL, NULL, NULL, NULL, "element that will be left behind" }, // ---------- element settings: advanced (custom elements) ------------------ @@ -3704,7 +3704,7 @@ static struct 0, ED_AREA_1X1_SETTINGS_YOFF, GADGET_ID_CUSTOM_CHANGE_TARGET, GADGET_ID_CUSTOM_CAN_CHANGE, &custom_element_change.target_element, 1, 1, - NULL, "after/when:", NULL, "new target element after change" + NULL, "after/when:", NULL, NULL, "new target element after change" }, // ---------- custom change content (extended change target) ---------------- @@ -3714,7 +3714,7 @@ static struct 0, ED_AREA_3X3_SETTINGS_YOFF, GADGET_ID_CUSTOM_CHANGE_CONTENT, GADGET_ID_NONE, // align three rows &custom_element_change.target_content.e[0][0], 3, 3, - NULL, NULL, NULL, "new extended elements after change" + NULL, NULL, NULL, NULL, "new extended elements after change" }, // ---------- custom change trigger (element causing change) ---------------- @@ -3724,7 +3724,7 @@ static struct 0, ED_AREA_1X1_SETTINGS_YOFF, GADGET_ID_CUSTOM_CHANGE_TRIGGER, GADGET_ID_CHANGE_OTHER_ACTION, &custom_element_change.initial_trigger_element, 1, 1, - NULL, NULL, NULL, "other element triggering change" + NULL, NULL, NULL, NULL, "other element triggering change" }, // ---------- custom change action (element used for action) ---------------- @@ -3734,7 +3734,7 @@ static struct 0, ED_AREA_1X1_SETTINGS_YOFF, GADGET_ID_CUSTOM_CHANGE_ACTION, GADGET_ID_ACTION_ARG, &custom_element_change.action_element, 1, 1, - NULL, NULL, NULL, "element used as action parameter" + NULL, NULL, NULL, NULL, "element used as action parameter" }, // ---------- group element content ----------------------------------------- @@ -3744,7 +3744,7 @@ static struct ED_AREA_1X1_SETTINGS_XOFF, ED_AREA_1X1_SETTINGS_YOFF, GADGET_ID_GROUP_CONTENT, GADGET_ID_NONE, &group_element_info.element[0], MAX_ELEMENTS_IN_GROUP, 1, - "content:", NULL, NULL, NULL + "content:", NULL, NULL, NULL, NULL }, // ---------- random background (for random painting) ----------------------- @@ -3754,7 +3754,7 @@ static struct 0, ED_AREA_1X1_LSETTINGS_YOFF, GADGET_ID_RANDOM_BACKGROUND, GADGET_ID_RANDOM_RESTRICTED, &random_placement_background_element, 1, 1, - NULL, NULL, NULL, "random placement background" + NULL, NULL, NULL, NULL, "random placement background" }, }; @@ -7293,8 +7293,10 @@ static void MapDrawingArea(int id) int xoffset_below = getTextWidth(drawingarea_info[id].text_below, font_nr); int x_left = gi->x - xoffset_left; int x_right = gi->x + gi->width + ED_DRAWINGAREA_TEXT_DISTANCE; + int x_above = gi->x - ED_DRAWINGAREA_BORDER_SIZE; int x_below = gi->x + (gi->width - xoffset_below) / 2; int y_side = gi->y + (gi->height - font_height) / 2; + int y_above = gi->y - font_height - ED_DRAWINGAREA_TEXT_DISTANCE; int y_below = gi->y + gi->height + ED_DRAWINGAREA_TEXT_DISTANCE; if (drawingarea_info[id].text_left) @@ -7303,6 +7305,9 @@ static void MapDrawingArea(int id) if (drawingarea_info[id].text_right) DrawText(x_right, y_side, drawingarea_info[id].text_right, font_nr); + if (drawingarea_info[id].text_above) + DrawText(x_above, y_above, drawingarea_info[id].text_above, font_nr); + if (drawingarea_info[id].text_below) DrawText(x_below, y_below, drawingarea_info[id].text_below, font_nr); @@ -7715,6 +7720,17 @@ static boolean PrepareSavingIntoPersonalLevelSet(void) leveldir_current = getTreeInfoFromIdentifier(leveldir_first, getLoginName()); + // this may happen if "setup.internal.create_user_levelset" is FALSE + // or if file "levelinfo.conf" is missing in personal user level set + if (leveldir_current == NULL) + { + Request("Cannot find personal level set?!", REQ_CONFIRM); + + leveldir_current = leveldir_former; + + return FALSE; + } + // find unused level number for (new_level_nr = leveldir_current->first_level; ; new_level_nr++) { @@ -8325,6 +8341,9 @@ static void CopyCustomElementPropertiesToGame(int element) // copy change events also to special level editor variable custom_element = element_info[element]; custom_element_change = *element_info[element].change; + + // needed here to restore runtime value "element_info[element].gfx_element" + InitElementPropertiesGfxElement(); } static void CopyGroupElementPropertiesToGame(int element) @@ -8338,6 +8357,9 @@ static void CopyGroupElementPropertiesToGame(int element) element_info[element] = custom_element; *element_info[element].group = group_element_info; + + // needed here to restore runtime value "element_info[element].gfx_element" + InitElementPropertiesGfxElement(); } static void CopyClassicElementPropertiesToGame(int element) @@ -8402,6 +8424,9 @@ static void InitZoomLevelSettings(int zoom_tilesize) ed_tilesize = setup.auto_setup.editor_zoom_tilesize; ed_tilesize_default = DEFAULT_EDITOR_TILESIZE; + // make sure that tile size is always a power of 2 + ed_tilesize = (1 << log_2(ed_tilesize)); + if (level.game_engine_type == GAME_ENGINE_TYPE_MM) { ed_tilesize = DEFAULT_EDITOR_TILESIZE_MM; @@ -8503,29 +8528,31 @@ static boolean useEditorDoorAnimation(void) return (door_1_viewport_unchanged && door_1_contains_toolbox); } +static void DrawEditorDoorBackground(int graphic, int x, int y, + int width, int height) +{ + struct GraphicInfo *g = &graphic_info[graphic]; + + if (g->bitmap != NULL) + BlitBitmap(g->bitmap, drawto, g->src_x, g->src_y, + MIN(width, g->width), MIN(height, g->height), x, y); + else + ClearRectangle(drawto, x, y, width, height); +} + static void DrawEditorDoorContent(void) { // needed for gadgets drawn on background (like palette scrollbar) SetDoorBackgroundImage(IMG_UNDEFINED); // copy default editor door content to main double buffer - BlitBitmap(graphic_info[IMG_BACKGROUND_PALETTE].bitmap, drawto, - graphic_info[IMG_BACKGROUND_PALETTE].src_x, - graphic_info[IMG_BACKGROUND_PALETTE].src_y, - MIN(DXSIZE, graphic_info[IMG_BACKGROUND_PALETTE].width), - MIN(DYSIZE, graphic_info[IMG_BACKGROUND_PALETTE].height), - DX, DY); + DrawEditorDoorBackground(IMG_BACKGROUND_PALETTE, DX, DY, DXSIZE, DYSIZE); // draw bigger door DrawSpecialEditorDoor(); // draw new control window - BlitBitmap(graphic_info[IMG_BACKGROUND_TOOLBOX].bitmap, drawto, - graphic_info[IMG_BACKGROUND_TOOLBOX].src_x, - graphic_info[IMG_BACKGROUND_TOOLBOX].src_y, - MIN(EXSIZE, graphic_info[IMG_BACKGROUND_TOOLBOX].width), - MIN(EYSIZE, graphic_info[IMG_BACKGROUND_TOOLBOX].height), - EX, EY); + DrawEditorDoorBackground(IMG_BACKGROUND_TOOLBOX, EX, EY, EXSIZE, EYSIZE); // draw all toolbox gadgets to editor doors MapControlButtons(); @@ -8544,7 +8571,7 @@ void DrawLevelEd(void) FadeSoundsAndMusic(); - if (CheckIfGlobalBorderOrPlayfieldViewportHasChanged()) + if (CheckFadeAll()) fade_mask = REDRAW_ALL; FadeOut(fade_mask); @@ -9750,10 +9777,43 @@ static void SetAutomaticNumberOfGemsNeeded(void) { int element = Feld[x][y]; - if (IS_GEM(element) || - element == EL_MM_KETTLE || - element == EL_DF_CELL) - level.gems_needed++; + 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; + } } } @@ -10841,7 +10901,6 @@ static void SetElementIntelliDraw(int x, int y, int new_element, }; static int last_x = -1; static int last_y = -1; - int old_element = IntelliDrawBuffer[x][y]; if (new_element == EL_UNDEFINED) { @@ -10851,6 +10910,8 @@ static void SetElementIntelliDraw(int x, int y, int new_element, return; } + int old_element = IntelliDrawBuffer[x][y]; + if (IS_TUBE(new_element)) { int last_element_new = EL_UNDEFINED; @@ -11625,11 +11686,21 @@ static void ResetIntelliDraw(void) static boolean draw_mode_hires = FALSE; +static boolean isHiresTileElement(int element) +{ + return (IS_MM_WALL(element) || element == EL_EMPTY); +} + +static boolean isHiresDrawElement(int element) +{ + return (IS_MM_WALL_EDITOR(element) || element == EL_EMPTY); +} + static void SetDrawModeHiRes(int element) { draw_mode_hires = (level.game_engine_type == GAME_ENGINE_TYPE_MM && - (IS_MM_WALL_EDITOR(element) || element == EL_EMPTY)); + isHiresDrawElement(element)); } static boolean getDrawModeHiRes(void) @@ -11947,27 +12018,28 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, char text[MAX_CB_TEXT_SIZE + 1] = ""; int width = (draw_with_brush ? brush_width : lev_fieldx); int height = (draw_with_brush ? brush_height : lev_fieldy); + char *format = "%s%03d"; + + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + if ((draw_with_brush ? brush_buffer[x][y] : Feld[x][y]) > 999) + format = "%s%04d"; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { int element = (draw_with_brush ? brush_buffer[x][y] : Feld[x][y]); - int element_mapped = element; char *prefix = (mode == CB_DUMP_BRUSH || mode == CB_BRUSH_TO_CLIPBOARD ? "`" : "¸"); - if (IS_CUSTOM_ELEMENT(element)) - element_mapped = EL_CUSTOM_START; - else if (IS_GROUP_ELEMENT(element)) - element_mapped = EL_GROUP_START; - else if (element >= NUM_FILE_ELEMENTS) - element_mapped = EL_UNKNOWN; + if (element >= NUM_FILE_ELEMENTS) + element = EL_UNKNOWN; // copy brush to level sketch text buffer for the R'n'D forum: - // - large tiles: `xxx (0x60 ASCII) - // - small tiles: ¸xxx (0xb8 ISO-8859-1, 0xc2b8 UTF-8) - snprintf(part, MAX_CB_PART_SIZE + 1, "%s%03d", prefix, element_mapped); + // - large tiles: `xxx or `xxxx (0x60 ASCII) + // - small tiles: ¸xxx or ¸xxxx (0xb8 ISO-8859-1, 0xc2b8 UTF-8) + snprintf(part, MAX_CB_PART_SIZE + 1, format, prefix, element); strcat(text, part); } @@ -12014,11 +12086,13 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, char *clipboard_text = SDL_GetClipboardText(); char *ptr = clipboard_text; + boolean allow_new_row = FALSE; boolean stop = FALSE; while (*ptr && !stop) { boolean prefix_found = FALSE; + boolean start_new_row = FALSE; // level sketch element number prefixes (may be multi-byte characters) char *prefix_list[] = { "`", "¸" }; @@ -12047,19 +12121,10 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, } } - // continue with next character if prefix not found - if (!prefix_found) - { - ptr++; // !!! FIX THIS for real UTF-8 handling !!! - - continue; - } - - // continue with next character if prefix not found - if (strlen(ptr) < 3) - break; - - if (ptr[0] >= '0' && ptr[0] <= '9' && + // check if prefix found and followed by (at least) three digits + if (prefix_found && + strlen(ptr) >= 3 && + ptr[0] >= '0' && ptr[0] <= '9' && ptr[1] >= '0' && ptr[1] <= '9' && ptr[2] >= '0' && ptr[2] <= '9') { @@ -12069,6 +12134,13 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, ptr += 3; + // level sketch element number might consist of four digits + if (ptr[0] >= '0' && ptr[0] <= '9') + { + element = element * 10 + (ptr[0] - '0'); + ptr++; + } + if (element >= NUM_FILE_ELEMENTS) element = EL_UNKNOWN; @@ -12079,14 +12151,28 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, x++; - if (x >= MAX_LEV_FIELDX || *ptr == '\n') - { - x = 0; - y++; + if (x >= MAX_LEV_FIELDX) + start_new_row = TRUE; - if (y >= MAX_LEV_FIELDY) - stop = TRUE; - } + allow_new_row = TRUE; + } + else + { + if ((*ptr == '\n' || *ptr == '\r') && allow_new_row) + start_new_row = TRUE; + + ptr++; // !!! FIX THIS for real UTF-8 handling !!! + } + + if (start_new_row) + { + x = 0; + y++; + + if (y >= MAX_LEV_FIELDY) + stop = TRUE; + + allow_new_row = FALSE; } } @@ -12291,6 +12377,16 @@ void CopyBrushToClipboard_Small(void) CopyBrushExt(0, 0, 0, 0, 0, CB_BRUSH_TO_CLIPBOARD_SMALL); } +void UndoLevelEditorOperation(void) +{ + ClickOnGadget(level_editor_gadget[GADGET_ID_UNDO], -1); +} + +void RedoLevelEditorOperation(void) +{ + ClickOnGadget(level_editor_gadget[GADGET_ID_UNDO], 3); +} + static void FloodFill(int from_x, int from_y, int fill_element) { FloodFillLevel(from_x, from_y, fill_element, Feld, lev_fieldx, lev_fieldy); @@ -12670,9 +12766,13 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) } else if (!button_press_event) { + int old_element = (IN_LEV_FIELD(lx, ly) ? Feld[lx][ly] : EL_UNDEFINED); + boolean hires_drawing = (level.game_engine_type == GAME_ENGINE_TYPE_MM && + isHiresTileElement(old_element) && + isHiresDrawElement(new_element)); + // prevent handling events for every pixel position when moving mouse - if ((sx == last_sx && sy == last_sy && - !IS_MM_WALL_EDITOR(new_element) && new_element != EL_EMPTY) || + if ((sx == last_sx && sy == last_sy && !hires_drawing) || (sx2 == last_sx2 && sy2 == last_sy2)) return; } @@ -12742,13 +12842,37 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) { SetDrawModeHiRes(new_element); - if (new_element == EL_PLAYER_1) + if (ELEM_IS_PLAYER(new_element)) { // remove player at old position for (y = 0; y < lev_fieldy; y++) + { for (x = 0; x < lev_fieldx; x++) - if (Feld[x][y] == EL_PLAYER_1) - SetElement(x, y, EL_EMPTY); + { + int old_element = Feld[x][y]; + + if (ELEM_IS_PLAYER(old_element)) + { + int replaced_with_element = + (old_element == EL_SOKOBAN_FIELD_PLAYER && + new_element == EL_PLAYER_1 ? EL_SOKOBAN_FIELD_EMPTY : + + old_element == EL_SOKOBAN_FIELD_PLAYER && + new_element == old_element ? EL_SOKOBAN_FIELD_EMPTY : + + new_element == EL_SOKOBAN_FIELD_PLAYER && + old_element == EL_PLAYER_1 ? EL_EMPTY : + + new_element >= EL_PLAYER_1 && + new_element <= EL_PLAYER_4 && + new_element == old_element ? EL_EMPTY : + + old_element); + + SetElement(x, y, replaced_with_element); + } + } + } } SetElementButton(lx, ly, dx, dy, new_element, button); @@ -13690,6 +13814,10 @@ static void HandleControlButtons(struct GadgetInfo *gi) button == 2 ? ed_tilesize_default : button == 3 ? ed_tilesize / 2 : ed_tilesize); + // when using touch device, cycle through all zoom tilesizes + if (runtime.uses_touch_device && ed_tilesize > TILESIZE) + ed_tilesize = MICRO_TILESIZE; + // limit zoom level by upper and lower bound ed_tilesize = MIN(MAX(MICRO_TILESIZE, ed_tilesize), TILESIZE); @@ -13724,7 +13852,9 @@ static void HandleControlButtons(struct GadgetInfo *gi) break; case GADGET_ID_UNDO: - if (button == 1 && GetKeyModState() & (KMOD_Shift|KMOD_Control)) + if (button < 0) // keep button value (even if modifier keys are pressed) + button = -button; + else if (button == 1 && GetKeyModState() & (KMOD_Shift | KMOD_Control)) button = 3; if (button == 1 && undo_buffer_steps == 0) @@ -13975,7 +14105,6 @@ static void HandleControlButtons(struct GadgetInfo *gi) void HandleLevelEditorKeyInput(Key key) { char letter = getCharFromKey(key); - int button = MB_LEFTBUTTON; if (drawing_function == GADGET_ID_TEXT && DrawLevelText(0, 0, 0, TEXT_QUERY_TYPING) == TRUE) @@ -13988,150 +14117,141 @@ void HandleLevelEditorKeyInput(Key key) DrawLevelText(0, 0, 0, TEXT_NEWLINE); else if (key == KSYM_Escape) DrawLevelText(0, 0, 0, TEXT_END); + + return; } - else if (button_status == MB_RELEASED) - { - int id = GADGET_ID_NONE; - int new_element_shift = element_shift; - int step = ED_ELEMENTLIST_BUTTONS_VERT - 1; - int i; - switch (key) - { - case KSYM_Left: - id = GADGET_ID_SCROLL_LEFT; - break; - case KSYM_Right: - id = GADGET_ID_SCROLL_RIGHT; - break; - case KSYM_Up: - id = GADGET_ID_SCROLL_UP; - break; - case KSYM_Down: - id = GADGET_ID_SCROLL_DOWN; - break; + int id = GADGET_ID_NONE; + int new_element_shift = element_shift; + int step = ED_ELEMENTLIST_BUTTONS_VERT - 1; + int button = MB_LEFTBUTTON; + int i; - case KSYM_Page_Up: - case KSYM_Page_Down: - step *= (key == KSYM_Page_Up ? -1 : +1); - element_shift += step * ED_ELEMENTLIST_BUTTONS_HORIZ; + switch (key) + { + case KSYM_Left: + id = GADGET_ID_SCROLL_LEFT; + break; + case KSYM_Right: + id = GADGET_ID_SCROLL_RIGHT; + break; + case KSYM_Up: + id = GADGET_ID_SCROLL_UP; + break; + case KSYM_Down: + id = GADGET_ID_SCROLL_DOWN; + break; - 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; + case KSYM_Page_Up: + case KSYM_Page_Down: + step *= (key == KSYM_Page_Up ? -1 : +1); + element_shift += step * ED_ELEMENTLIST_BUTTONS_HORIZ; - ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_VERTICAL], - GDI_SCROLLBAR_ITEM_POSITION, - element_shift / ED_ELEMENTLIST_BUTTONS_HORIZ, GDI_END); + 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; - ModifyEditorElementList(); + ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_VERTICAL], + GDI_SCROLLBAR_ITEM_POSITION, + element_shift / ED_ELEMENTLIST_BUTTONS_HORIZ, GDI_END); - break; + ModifyEditorElementList(); - case KSYM_Home: - case KSYM_End: - element_shift = (key == KSYM_Home ? 0 : - num_editor_elements - ED_NUM_ELEMENTLIST_BUTTONS); + break; - ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_VERTICAL], - GDI_SCROLLBAR_ITEM_POSITION, - element_shift / ED_ELEMENTLIST_BUTTONS_HORIZ, GDI_END); + case KSYM_Home: + case KSYM_End: + element_shift = (key == KSYM_Home ? 0 : + num_editor_elements - ED_NUM_ELEMENTLIST_BUTTONS); - ModifyEditorElementList(); + ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_VERTICAL], + GDI_SCROLLBAR_ITEM_POSITION, + element_shift / ED_ELEMENTLIST_BUTTONS_HORIZ, GDI_END); - break; + ModifyEditorElementList(); - case KSYM_Insert: - case KSYM_Delete: + break; - // this is needed to prevent interference with running "True X-Mouse" - if (GetKeyModStateFromEvents() & KMOD_Control) - break; + case KSYM_Insert: + case KSYM_Delete: - // check for last or next editor cascade block in element list - for (i = 0; i < num_editor_elements; i++) - { - if ((key == KSYM_Insert && i == element_shift) || - (key == KSYM_Delete && new_element_shift > element_shift)) - break; + // this is needed to prevent interference with running "True X-Mouse" + if (GetKeyModStateFromEvents() & KMOD_Control) + break; - // jump to next cascade block (or to start of element list) - if (i == 0 || IS_EDITOR_CASCADE(editor_elements[i])) - new_element_shift = i; - } + // check for last or next editor cascade block in element list + for (i = 0; i < num_editor_elements; i++) + { + if ((key == KSYM_Insert && i == element_shift) || + (key == KSYM_Delete && new_element_shift > element_shift)) + break; - if (i < num_editor_elements) - element_shift = new_element_shift; + // jump to next cascade block (or to start of element list) + if (i == 0 || IS_EDITOR_CASCADE(editor_elements[i])) + new_element_shift = i; + } - if (element_shift > num_editor_elements - ED_NUM_ELEMENTLIST_BUTTONS) - element_shift = num_editor_elements - ED_NUM_ELEMENTLIST_BUTTONS; + if (i < num_editor_elements) + element_shift = new_element_shift; - ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_VERTICAL], - GDI_SCROLLBAR_ITEM_POSITION, - element_shift / ED_ELEMENTLIST_BUTTONS_HORIZ, GDI_END); + if (element_shift > num_editor_elements - ED_NUM_ELEMENTLIST_BUTTONS) + element_shift = num_editor_elements - ED_NUM_ELEMENTLIST_BUTTONS; - ModifyEditorElementList(); + ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_VERTICAL], + GDI_SCROLLBAR_ITEM_POSITION, + element_shift / ED_ELEMENTLIST_BUTTONS_HORIZ, GDI_END); - break; + ModifyEditorElementList(); - case KSYM_Escape: - if (edit_mode == ED_MODE_DRAWING) - { - RequestExitLevelEditor(setup.ask_on_escape_editor, TRUE); - } - else if (edit_mode == ED_MODE_INFO) - { - HandleControlButtons(level_editor_gadget[GADGET_ID_INFO]); - } - else if (edit_mode == ED_MODE_PROPERTIES) - { - HandleControlButtons(level_editor_gadget[GADGET_ID_PROPERTIES]); - } - else if (edit_mode == ED_MODE_PALETTE) - { - HandleControlButtons(level_editor_gadget[GADGET_ID_PALETTE]); - } - else // should never happen - { - ChangeEditModeWindow(ED_MODE_DRAWING); - } + break; - break; + case KSYM_Escape: + if (edit_mode == ED_MODE_DRAWING) + RequestExitLevelEditor(setup.ask_on_escape_editor, TRUE); + else if (edit_mode == ED_MODE_INFO) + HandleControlButtons(level_editor_gadget[GADGET_ID_INFO]); + else if (edit_mode == ED_MODE_PROPERTIES) + HandleControlButtons(level_editor_gadget[GADGET_ID_PROPERTIES]); + else if (edit_mode == ED_MODE_PALETTE) + HandleControlButtons(level_editor_gadget[GADGET_ID_PALETTE]); + else // should never happen + ChangeEditModeWindow(ED_MODE_DRAWING); - default: - break; - } + break; - if (id != GADGET_ID_NONE) - ClickOnGadget(level_editor_gadget[id], button); - else if (letter == '1' || letter == '?') - ClickOnGadget(level_editor_gadget[GADGET_ID_ELEMENT_LEFT], button); - else if (letter == '2') - ClickOnGadget(level_editor_gadget[GADGET_ID_ELEMENT_MIDDLE], button); - else if (letter == '3') - ClickOnGadget(level_editor_gadget[GADGET_ID_ELEMENT_RIGHT], button); - else if (letter == '.') - ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS], button); - else if (letter == 'U') - ClickOnGadget(level_editor_gadget[GADGET_ID_UNDO], 3); - else if (letter == '-' || key == KSYM_KP_Subtract) - ClickOnGadget(level_editor_gadget[GADGET_ID_ZOOM], 3); - else if (letter == '0' || key == KSYM_KP_0) - ClickOnGadget(level_editor_gadget[GADGET_ID_ZOOM], 2); - else if (letter == '+' || key == KSYM_KP_Add || - letter == '=') // ("Shift-=" is "+" on US keyboards) - ClickOnGadget(level_editor_gadget[GADGET_ID_ZOOM], 1); - else if (key == KSYM_Return || - key == KSYM_space || - key == setup.shortcut.toggle_pause) - ClickOnGadget(level_editor_gadget[GADGET_ID_TEST], button); - else - for (i = 0; i < ED_NUM_CTRL_BUTTONS; i++) - if (letter && letter == controlbutton_info[i].shortcut) - if (!anyTextGadgetActive()) - ClickOnGadget(level_editor_gadget[i], button); + default: + break; } + + if (id != GADGET_ID_NONE) + ClickOnGadget(level_editor_gadget[id], button); + else if (letter == '1' || letter == '?') + ClickOnGadget(level_editor_gadget[GADGET_ID_ELEMENT_LEFT], button); + else if (letter == '2') + ClickOnGadget(level_editor_gadget[GADGET_ID_ELEMENT_MIDDLE], button); + else if (letter == '3') + ClickOnGadget(level_editor_gadget[GADGET_ID_ELEMENT_RIGHT], button); + else if (letter == '.') + ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS], button); + else if (letter == 'U') + ClickOnGadget(level_editor_gadget[GADGET_ID_UNDO], 3); + else if (letter == '-' || key == KSYM_KP_Subtract) + ClickOnGadget(level_editor_gadget[GADGET_ID_ZOOM], 3); + else if (letter == '0' || key == KSYM_KP_0) + ClickOnGadget(level_editor_gadget[GADGET_ID_ZOOM], 2); + else if (letter == '+' || key == KSYM_KP_Add || + letter == '=') // ("Shift-=" is "+" on US keyboards) + ClickOnGadget(level_editor_gadget[GADGET_ID_ZOOM], 1); + else if (key == KSYM_Return || + key == KSYM_space || + key == setup.shortcut.toggle_pause) + ClickOnGadget(level_editor_gadget[GADGET_ID_TEST], button); + else + for (i = 0; i < ED_NUM_CTRL_BUTTONS; i++) + if (letter && letter == controlbutton_info[i].shortcut) + if (!anyTextGadgetActive()) + ClickOnGadget(level_editor_gadget[i], button); } void HandleLevelEditorIdle(void)