X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Feditor.c;h=e5d956709d9408f9c96090a185d2677de2669727;hp=833dce2ec7996d81f106a9d3522178bb274753bc;hb=HEAD;hpb=13fc9c40050cdd760fd457a9c83d0611f95fcd1e diff --git a/src/editor.c b/src/editor.c index 833dce2e..671ac61d 100644 --- a/src/editor.c +++ b/src/editor.c @@ -382,7 +382,7 @@ enum GADGET_ID_PICK_ELEMENT, GADGET_ID_UNDO, - GADGET_ID_INFO, + GADGET_ID_CONF, GADGET_ID_SAVE, GADGET_ID_CLEAR, GADGET_ID_TEST, @@ -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, @@ -598,9 +603,9 @@ enum // textbutton identifiers - GADGET_ID_LEVELINFO_LEVEL, - GADGET_ID_LEVELINFO_LEVELSET, - GADGET_ID_LEVELINFO_EDITOR, + GADGET_ID_LEVELCONFIG_LEVEL, + GADGET_ID_LEVELCONFIG_LEVELSET, + GADGET_ID_LEVELCONFIG_EDITOR, GADGET_ID_PROPERTIES_INFO, GADGET_ID_PROPERTIES_CONFIG, GADGET_ID_PROPERTIES_CONFIG_1, @@ -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, @@ -904,9 +913,9 @@ enum // values for textbutton gadgets enum { - ED_TEXTBUTTON_ID_LEVELINFO_LEVEL, - ED_TEXTBUTTON_ID_LEVELINFO_LEVELSET, - ED_TEXTBUTTON_ID_LEVELINFO_EDITOR, + ED_TEXTBUTTON_ID_LEVELCONFIG_LEVEL, + ED_TEXTBUTTON_ID_LEVELCONFIG_LEVELSET, + ED_TEXTBUTTON_ID_LEVELCONFIG_EDITOR, ED_TEXTBUTTON_ID_PROPERTIES_INFO, ED_TEXTBUTTON_ID_PROPERTIES_CONFIG, ED_TEXTBUTTON_ID_PROPERTIES_CONFIG_1, @@ -921,8 +930,8 @@ enum ED_NUM_TEXTBUTTONS }; -#define ED_TAB_BUTTON_ID_LEVELINFO_FIRST ED_TEXTBUTTON_ID_LEVELINFO_LEVEL -#define ED_TAB_BUTTON_ID_LEVELINFO_LAST ED_TEXTBUTTON_ID_LEVELINFO_EDITOR +#define ED_TAB_BUTTON_ID_LEVELCONFIG_FIRST ED_TEXTBUTTON_ID_LEVELCONFIG_LEVEL +#define ED_TAB_BUTTON_ID_LEVELCONFIG_LAST ED_TEXTBUTTON_ID_LEVELCONFIG_EDITOR #define ED_TAB_BUTTON_ID_PROPERTIES_FIRST ED_TEXTBUTTON_ID_PROPERTIES_INFO #define ED_TAB_BUTTON_ID_PROPERTIES_LAST ED_TEXTBUTTON_ID_PROPERTIES_CHANGE @@ -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, @@ -1114,14 +1126,14 @@ enum // screens in the level editor #define ED_MODE_DRAWING 0 -#define ED_MODE_INFO 1 +#define ED_MODE_LEVELCONFIG 1 #define ED_MODE_PROPERTIES 2 #define ED_MODE_PALETTE 3 // sub-screens in the global settings section -#define ED_MODE_LEVELINFO_LEVEL ED_TEXTBUTTON_ID_LEVELINFO_LEVEL -#define ED_MODE_LEVELINFO_LEVELSET ED_TEXTBUTTON_ID_LEVELINFO_LEVELSET -#define ED_MODE_LEVELINFO_EDITOR ED_TEXTBUTTON_ID_LEVELINFO_EDITOR +#define ED_MODE_LEVELCONFIG_LEVEL ED_TEXTBUTTON_ID_LEVELCONFIG_LEVEL +#define ED_MODE_LEVELCONFIG_LEVELSET ED_TEXTBUTTON_ID_LEVELCONFIG_LEVELSET +#define ED_MODE_LEVELCONFIG_EDITOR ED_TEXTBUTTON_ID_LEVELCONFIG_EDITOR // sub-screens in the element properties section #define ED_MODE_PROPERTIES_INFO ED_TEXTBUTTON_ID_PROPERTIES_INFO @@ -1262,9 +1274,9 @@ static struct "undo/redo last operation", 'u' }, { - IMG_GFX_EDITOR_BUTTON_CONF, GADGET_ID_INFO, + IMG_GFX_EDITOR_BUTTON_CONF, GADGET_ID_CONF, &editor.button.conf, GD_TYPE_NORMAL_BUTTON, - "properties of level", 'I' + "level and editor settings", 'I' }, { IMG_GFX_EDITOR_BUTTON_SAVE, GADGET_ID_SAVE, @@ -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" } }; @@ -2445,6 +2465,7 @@ static struct ValueTextInfo options_group_choice_mode[] = { ANIM_LINEAR, "linear" }, { ANIM_PINGPONG, "pingpong" }, { ANIM_PINGPONG2, "pingpong 2" }, + { ANIM_LEVEL_NR, "level number" }, { -1, NULL } }; @@ -2555,6 +2576,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) --------------- @@ -2786,21 +2815,21 @@ static struct { ED_LEVEL_TABS_XPOS(0), ED_LEVEL_TABS_YPOS(0), - GADGET_ID_LEVELINFO_LEVEL, GADGET_ID_NONE, + GADGET_ID_LEVELCONFIG_LEVEL, GADGET_ID_NONE, 8, "Level", - NULL, NULL, NULL, "Configure level properties" + NULL, NULL, NULL, "Configure level settings" }, { -1, -1, - GADGET_ID_LEVELINFO_LEVELSET, GADGET_ID_LEVELINFO_LEVEL, + GADGET_ID_LEVELCONFIG_LEVELSET, GADGET_ID_LEVELCONFIG_LEVEL, 8, "Levelset", NULL, NULL, NULL, "Update this or create new level set" }, { -1, -1, - GADGET_ID_LEVELINFO_EDITOR, GADGET_ID_LEVELINFO_LEVELSET, + GADGET_ID_LEVELCONFIG_EDITOR, GADGET_ID_LEVELCONFIG_LEVELSET, 8, "Editor", - NULL, NULL, NULL, "Configure editor properties" + NULL, NULL, NULL, "Configure editor settings" }, // ---------- element settings (tabs) --------------------------------------- @@ -3354,6 +3383,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 +3783,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 +3801,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 +3915,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; @@ -3896,7 +3949,7 @@ static void AdjustElementListScrollbar(void); static void RedrawDrawingElements(void); static void DrawDrawingWindowExt(boolean); static void DrawDrawingWindow(void); -static void DrawLevelInfoWindow(void); +static void DrawLevelConfigWindow(void); static void DrawPropertiesWindow(void); static void DrawPaletteWindow(void); static void UpdateCustomElementGraphicGadgets(void); @@ -3921,6 +3974,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 @@ -3940,7 +3994,7 @@ static int undo_buffer_steps = 0; static int redo_buffer_steps = 0; static int edit_mode; -static int edit_mode_levelinfo; +static int edit_mode_levelconfig; static int edit_mode_properties; static int element_shift = 0; @@ -4610,7 +4664,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; @@ -4639,8 +4698,8 @@ static int editor_el_deflektor[] = EL_DF_MIRROR_START, EL_DF_MIRROR_ROTATING_START, + EL_DF_MIRROR_FIXED_START, EL_DF_CELL, - EL_DF_MINE, EL_DF_FIBRE_OPTIC_RED_1, EL_DF_FIBRE_OPTIC_YELLOW_1, @@ -4655,7 +4714,12 @@ static int editor_el_deflektor[] = EL_DF_STEEL_WALL, EL_DF_WOODEN_WALL, EL_DF_REFRACTOR, - EL_EMPTY + EL_DF_MINE, + + EL_DF_SLOPE_1, + EL_DF_SLOPE_2, + EL_DF_SLOPE_3, + EL_DF_SLOPE_4 }; static int *editor_hl_deflektor_ptr = editor_hl_deflektor; static int *editor_el_deflektor_ptr = editor_el_deflektor; @@ -5685,9 +5749,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; @@ -5707,14 +5780,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 @@ -5892,10 +5969,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 @@ -6502,11 +6579,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 ? @@ -6646,7 +6721,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]); @@ -6654,8 +6728,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; @@ -6702,7 +6775,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; @@ -6729,8 +6802,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'; @@ -6773,14 +6844,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'; @@ -6824,11 +6893,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 { @@ -6844,9 +6914,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] + @@ -6899,7 +6966,7 @@ static void CreateTextbuttonGadgets(void) { int id = textbutton_info[i].gadget_id; int is_tab_button = - ((id >= GADGET_ID_LEVELINFO_LEVEL && id <= GADGET_ID_LEVELINFO_EDITOR) || + ((id >= GADGET_ID_LEVELCONFIG_LEVEL && id <= GADGET_ID_LEVELCONFIG_EDITOR) || (id >= GADGET_ID_PROPERTIES_INFO && id <= GADGET_ID_PROPERTIES_CHANGE)); int graphic = (is_tab_button ? IMG_EDITOR_TABBUTTON : IMG_EDITOR_TEXTBUTTON); @@ -6915,7 +6982,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); @@ -6923,8 +6990,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'; @@ -6977,7 +7042,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 @@ -6992,8 +7056,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_RELEASED; // determine horizontal position to the right of specified gadget if (graphicbutton_info[i].gadget_id_align != GADGET_ID_NONE) @@ -7085,7 +7148,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) { @@ -7109,8 +7172,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, @@ -7146,11 +7207,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; @@ -7167,6 +7225,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) @@ -7218,16 +7277,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); @@ -7296,6 +7353,8 @@ void CreateLevelEditorGadgets(void) use_permanent_palette = !editor.palette.show_as_separate_screen; + InitGadgetScreenBorders(-1, INFOTEXT_YPOS); + ReinitializeElementList(); CreateControlButtons(); @@ -7488,9 +7547,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); @@ -7619,7 +7682,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; @@ -7702,6 +7765,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); @@ -7790,8 +7861,8 @@ static void DrawEditModeWindowExt(boolean remap_toolbox_gadgets) RedrawDrawingElements(); } - if (edit_mode == ED_MODE_INFO) - DrawLevelInfoWindow(); + if (edit_mode == ED_MODE_LEVELCONFIG) + DrawLevelConfigWindow(); else if (edit_mode == ED_MODE_PROPERTIES) DrawPropertiesWindow(); else if (edit_mode == ED_MODE_PALETTE) @@ -7891,7 +7962,7 @@ static boolean PrepareSavingIntoPersonalLevelSet(void) return TRUE; } -static void ModifyLevelInfoForSavingIntoPersonalLevelSet(char *former_name) +static void ModifyLevelConfigForSavingIntoPersonalLevelSet(char *former_name) { static char *filename_levelinfo = NULL, *mod_name = NULL; FILE *file; @@ -8124,6 +8195,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; @@ -8734,6 +8811,15 @@ static void DrawEditorDoorContent(void) // draw all toolbox gadgets to editor doors MapControlButtons(); + // when returning from test game to properties page, redraw toolbox gadgets + if (edit_mode == ED_MODE_PROPERTIES) + { + UnmapLevelEditorToolboxDrawingGadgets(); + UnmapLevelEditorToolboxCustomGadgets(); + + MapLevelEditorToolboxCustomGadgetsIfNeeded(); + } + // draw all palette gadgets to editor doors ModifyEditorElementList(); RedrawDrawingElements(); @@ -8776,7 +8862,7 @@ void DrawLevelEd(void) else { edit_mode = ED_MODE_DRAWING; - edit_mode_levelinfo = ED_MODE_LEVELINFO_LEVEL; + edit_mode_levelconfig = ED_MODE_LEVELCONFIG_LEVEL; edit_mode_properties = ED_MODE_PROPERTIES_INFO; ResetUndoBuffer(); @@ -8832,8 +8918,8 @@ static void AdjustDrawingAreaGadgets(void) if (suppressBorderElement()) { - ed_xsize = max_ed_fieldx; - ed_ysize = max_ed_fieldy; + ed_xsize = lev_fieldx; + ed_ysize = lev_fieldy; } // check if we need any scrollbars @@ -9159,7 +9245,7 @@ static int getTabulatorBarHeight(void) static Pixel getTabulatorBarColor(void) { - struct GadgetInfo *gd_gi1 = level_editor_gadget[GADGET_ID_LEVELINFO_LEVEL]; + 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; @@ -9167,19 +9253,19 @@ static Pixel getTabulatorBarColor(void) return GetPixel(gd->bitmap, gd_x, gd_y); } -static void DrawLevelInfoTabulatorGadgets(void) +static void DrawLevelConfigTabulatorGadgets(void) { - struct GadgetInfo *gd_gi1 = level_editor_gadget[GADGET_ID_LEVELINFO_LEVEL]; + struct GadgetInfo *gd_gi1 = level_editor_gadget[GADGET_ID_LEVELCONFIG_LEVEL]; Pixel tab_color = getTabulatorBarColor(); - int id_first = ED_TAB_BUTTON_ID_LEVELINFO_FIRST; - int id_last = ED_TAB_BUTTON_ID_LEVELINFO_LAST; + int id_first = ED_TAB_BUTTON_ID_LEVELCONFIG_FIRST; + int id_last = ED_TAB_BUTTON_ID_LEVELCONFIG_LAST; 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_levelinfo); + boolean active = (i != edit_mode_levelconfig); // draw background line below tabulator button ClearRectangleOnBackground(drawto, gi->x, gi->y + gi->height, gi->width, 1); @@ -9268,7 +9354,7 @@ static int PrintElementDescriptionFromFile(char *filename, int font_nr, TRUE, FALSE, FALSE); } -static void DrawLevelInfoLevel(void) +static void DrawLevelConfigLevel(void) { int i; @@ -9297,7 +9383,7 @@ static char *getLevelSubdirFromSaveMode(int save_mode) return leveldir_current->subdir; } -static void DrawLevelInfoLevelSet_DirectoryInfo(void) +static void DrawLevelConfigLevelSet_DirectoryInfo(void) { char *directory_text = "Level set directory:"; char *directory_name = getLevelSubdirFromSaveMode(levelset_save_mode); @@ -9312,7 +9398,7 @@ static void DrawLevelInfoLevelSet_DirectoryInfo(void) PrintInfoText(directory_name, font2_nr, x, y); } -static void DrawLevelInfoLevelSet(void) +static void DrawLevelConfigLevelSet(void) { boolean artwork_exists = checkIfCustomArtworkExistsForCurrentLevelSet(); boolean template_exists = fileExists(getLocalLevelTemplateFilename()); @@ -9345,10 +9431,10 @@ static void DrawLevelInfoLevelSet(void) MapTextbuttonGadget(ED_TEXTBUTTON_ID_SAVE_LEVELSET); // draw info text - DrawLevelInfoLevelSet_DirectoryInfo(); + DrawLevelConfigLevelSet_DirectoryInfo(); } -static void DrawLevelInfoEditor(void) +static void DrawLevelConfigEditor(void) { int i; @@ -9371,7 +9457,7 @@ static void DrawLevelInfoEditor(void) MapTextbuttonGadget(ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE_2); } -static void DrawLevelInfoWindow(void) +static void DrawLevelConfigWindow(void) { char *text = "Global Settings"; int font_nr = FONT_TITLE_1; @@ -9390,14 +9476,14 @@ static void DrawLevelInfoWindow(void) DrawText(sx, sy, text, font_nr); - DrawLevelInfoTabulatorGadgets(); + DrawLevelConfigTabulatorGadgets(); - if (edit_mode_levelinfo == ED_MODE_LEVELINFO_LEVEL) - DrawLevelInfoLevel(); - else if (edit_mode_levelinfo == ED_MODE_LEVELINFO_LEVELSET) - DrawLevelInfoLevelSet(); - else if (edit_mode_levelinfo == ED_MODE_LEVELINFO_EDITOR) - DrawLevelInfoEditor(); + 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(); } static void DrawCustomContentArea(void) @@ -9512,7 +9598,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; @@ -9540,7 +9626,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; @@ -9597,13 +9683,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; @@ -9677,13 +9790,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; @@ -9692,7 +9808,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; @@ -9711,22 +9828,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 @@ -9775,6 +9936,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" @@ -9839,9 +10001,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 }, @@ -9906,7 +10068,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 }, @@ -9923,6 +10085,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) || @@ -10079,7 +10242,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)) @@ -10220,13 +10392,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; @@ -10334,7 +10507,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); @@ -10451,12 +10624,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); @@ -10532,9 +10705,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(); @@ -11054,7 +11225,7 @@ 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) { struct XY *xy = xy_directions; @@ -11537,6 +11708,12 @@ static void SetElementIntelliDraw(int x, int y, int new_element, EL_DF_RECEIVER_DOWN, EL_DF_RECEIVER_LEFT }, + { + EL_DF_SLOPE_1, + EL_DF_SLOPE_4, + EL_DF_SLOPE_3, + EL_DF_SLOPE_2 + }, { -1, @@ -11753,6 +11930,24 @@ static void SetElementIntelliDraw(int x, int y, int new_element, EL_DF_MIRROR_ROTATING_3, EL_DF_MIRROR_ROTATING_2 }, + { + EL_DF_MIRROR_FIXED_1, + EL_DF_MIRROR_FIXED_16, + EL_DF_MIRROR_FIXED_15, + EL_DF_MIRROR_FIXED_14, + EL_DF_MIRROR_FIXED_13, + EL_DF_MIRROR_FIXED_12, + EL_DF_MIRROR_FIXED_11, + EL_DF_MIRROR_FIXED_10, + EL_DF_MIRROR_FIXED_9, + EL_DF_MIRROR_FIXED_8, + EL_DF_MIRROR_FIXED_7, + EL_DF_MIRROR_FIXED_6, + EL_DF_MIRROR_FIXED_5, + EL_DF_MIRROR_FIXED_4, + EL_DF_MIRROR_FIXED_3, + EL_DF_MIRROR_FIXED_2 + }, { -1, @@ -11826,7 +12021,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; @@ -11840,7 +12038,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; @@ -11855,6 +12053,14 @@ 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 get_number_of_bits(MM_WALL_BITS(element)); + + return 1; +} + static void SetDrawModeHiRes(int element) { draw_mode_hires = @@ -11882,8 +12088,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); } @@ -12085,7 +12291,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 @@ -12142,6 +12348,9 @@ static void SelectArea(int from_x, int from_y, int to_x, int to_y, #define CB_BRUSH_TO_CLIPBOARD 7 #define CB_BRUSH_TO_CLIPBOARD_SMALL 8 #define CB_UPDATE_BRUSH_POSITION 9 +#define CB_FLIP_BRUSH_X 10 +#define CB_FLIP_BRUSH_Y 11 +#define CB_FLIP_BRUSH_XY 12 #define MAX_CB_PART_SIZE 10 #define MAX_CB_LINE_SIZE (MAX_LEV_FIELDX + 1) // text plus newline @@ -12150,6 +12359,185 @@ static void SelectArea(int from_x, int from_y, int to_x, int to_y, MAX_CB_NUM_LINES * \ MAX_CB_PART_SIZE) +static int getFlippedTileExt(int map[], int element) +{ + int i; + + for (i = 0; map[i] != -1; i++) + if (map[i] == element) + return map[i ^ 1]; // get flipped element by flipping LSB of index + + return element; +} + +static int getFlippedTileX(int element) +{ + int map[] = + { + EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY_RIGHT, + EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY_RIGHT, + EL_BUG_LEFT, EL_BUG_RIGHT, + EL_SPACESHIP_LEFT, EL_SPACESHIP_RIGHT, + EL_PACMAN_LEFT, EL_PACMAN_RIGHT, + EL_ARROW_LEFT, EL_ARROW_RIGHT, + EL_MOLE_LEFT, EL_MOLE_RIGHT, + EL_BALLOON_SWITCH_LEFT, EL_BALLOON_SWITCH_RIGHT, + EL_YAMYAM_LEFT, EL_YAMYAM_RIGHT, + EL_SP_PORT_LEFT, EL_SP_PORT_RIGHT, + EL_SP_GRAVITY_PORT_LEFT, EL_SP_GRAVITY_PORT_RIGHT, + EL_SP_GRAVITY_ON_PORT_LEFT, EL_SP_GRAVITY_ON_PORT_RIGHT, + EL_SP_GRAVITY_OFF_PORT_LEFT, EL_SP_GRAVITY_OFF_PORT_RIGHT, + EL_CONVEYOR_BELT_1_LEFT, EL_CONVEYOR_BELT_1_RIGHT, + EL_CONVEYOR_BELT_2_LEFT, EL_CONVEYOR_BELT_2_RIGHT, + EL_CONVEYOR_BELT_3_LEFT, EL_CONVEYOR_BELT_3_RIGHT, + EL_CONVEYOR_BELT_4_LEFT, EL_CONVEYOR_BELT_4_RIGHT, + EL_SPRING_LEFT, EL_SPRING_RIGHT, + EL_SP_CHIP_LEFT, EL_SP_CHIP_RIGHT, + EL_TUBE_VERTICAL_LEFT, EL_TUBE_VERTICAL_RIGHT, + EL_TUBE_LEFT_UP, EL_TUBE_RIGHT_UP, + EL_TUBE_LEFT_DOWN, EL_TUBE_RIGHT_DOWN, + EL_DC_STEELWALL_1_LEFT, EL_DC_STEELWALL_1_RIGHT, + EL_DC_STEELWALL_1_TOPLEFT, EL_DC_STEELWALL_1_TOPRIGHT, + EL_DC_STEELWALL_1_BOTTOMLEFT, EL_DC_STEELWALL_1_BOTTOMRIGHT, + EL_DC_STEELWALL_1_TOPLEFT_2, EL_DC_STEELWALL_1_TOPRIGHT_2, + EL_DC_STEELWALL_1_BOTTOMLEFT_2, EL_DC_STEELWALL_1_BOTTOMRIGHT_2, + EL_DC_STEELWALL_2_LEFT, EL_DC_STEELWALL_2_RIGHT, + EL_ACID_POOL_TOPLEFT, EL_ACID_POOL_TOPRIGHT, + EL_ACID_POOL_BOTTOMLEFT, EL_ACID_POOL_BOTTOMRIGHT, + + -1 + }; + + return getFlippedTileExt(map, element); +} + +static int getFlippedTileY(int element) +{ + int map[] = + { + EL_BD_BUTTERFLY_UP, EL_BD_BUTTERFLY_DOWN, + EL_BD_FIREFLY_UP, EL_BD_FIREFLY_DOWN, + EL_BUG_UP, EL_BUG_DOWN, + EL_SPACESHIP_UP, EL_SPACESHIP_DOWN, + EL_PACMAN_UP, EL_PACMAN_DOWN, + EL_ARROW_UP, EL_ARROW_DOWN, + EL_MOLE_UP, EL_MOLE_DOWN, + EL_BALLOON_SWITCH_UP, EL_BALLOON_SWITCH_DOWN, + EL_YAMYAM_UP, EL_YAMYAM_DOWN, + EL_SP_PORT_UP, EL_SP_PORT_DOWN, + EL_SP_GRAVITY_PORT_UP, EL_SP_GRAVITY_PORT_DOWN, + EL_SP_GRAVITY_ON_PORT_UP, EL_SP_GRAVITY_ON_PORT_DOWN, + EL_SP_GRAVITY_OFF_PORT_UP, EL_SP_GRAVITY_OFF_PORT_DOWN, + EL_SP_CHIP_TOP, EL_SP_CHIP_BOTTOM, + EL_TUBE_HORIZONTAL_UP, EL_TUBE_HORIZONTAL_DOWN, + EL_TUBE_LEFT_UP, EL_TUBE_LEFT_DOWN, + EL_TUBE_RIGHT_UP, EL_TUBE_RIGHT_DOWN, + EL_DC_STEELWALL_1_TOP, EL_DC_STEELWALL_1_BOTTOM, + EL_DC_STEELWALL_1_TOPLEFT, EL_DC_STEELWALL_1_BOTTOMLEFT, + EL_DC_STEELWALL_1_TOPRIGHT, EL_DC_STEELWALL_1_BOTTOMRIGHT, + EL_DC_STEELWALL_1_TOPLEFT_2, EL_DC_STEELWALL_1_BOTTOMLEFT_2, + EL_DC_STEELWALL_1_TOPRIGHT_2, EL_DC_STEELWALL_1_BOTTOMRIGHT_2, + EL_DC_STEELWALL_2_TOP, EL_DC_STEELWALL_2_BOTTOM, + EL_EMC_WALL_1, EL_EMC_WALL_3, + + -1 + }; + + return getFlippedTileExt(map, element); +} + +static int getFlippedTileXY(int element) +{ + int map[] = + { + EL_BD_BUTTERFLY_LEFT, EL_BD_BUTTERFLY_UP, + EL_BD_BUTTERFLY_RIGHT, EL_BD_BUTTERFLY_DOWN, + EL_BD_FIREFLY_LEFT, EL_BD_FIREFLY_UP, + EL_BD_FIREFLY_RIGHT, EL_BD_FIREFLY_DOWN, + EL_BUG_LEFT, EL_BUG_UP, + EL_BUG_RIGHT, EL_BUG_DOWN, + EL_SPACESHIP_LEFT, EL_SPACESHIP_UP, + EL_SPACESHIP_RIGHT, EL_SPACESHIP_DOWN, + EL_PACMAN_LEFT, EL_PACMAN_UP, + EL_PACMAN_RIGHT, EL_PACMAN_DOWN, + EL_ARROW_LEFT, EL_ARROW_UP, + EL_ARROW_RIGHT, EL_ARROW_DOWN, + EL_MOLE_LEFT, EL_MOLE_UP, + EL_MOLE_RIGHT, EL_MOLE_DOWN, + EL_BALLOON_SWITCH_LEFT, EL_BALLOON_SWITCH_UP, + EL_BALLOON_SWITCH_RIGHT, EL_BALLOON_SWITCH_DOWN, + EL_YAMYAM_LEFT, EL_YAMYAM_UP, + EL_YAMYAM_RIGHT, EL_YAMYAM_DOWN, + EL_SP_PORT_LEFT, EL_SP_PORT_UP, + EL_SP_PORT_RIGHT, EL_SP_PORT_DOWN, + EL_SP_GRAVITY_PORT_LEFT, EL_SP_GRAVITY_PORT_UP, + EL_SP_GRAVITY_PORT_RIGHT, EL_SP_GRAVITY_PORT_DOWN, + EL_SP_GRAVITY_ON_PORT_LEFT, EL_SP_GRAVITY_ON_PORT_UP, + EL_SP_GRAVITY_ON_PORT_RIGHT, EL_SP_GRAVITY_ON_PORT_DOWN, + EL_SP_GRAVITY_OFF_PORT_LEFT, EL_SP_GRAVITY_OFF_PORT_UP, + EL_SP_GRAVITY_OFF_PORT_RIGHT, EL_SP_GRAVITY_OFF_PORT_DOWN, + EL_SP_CHIP_LEFT, EL_SP_CHIP_TOP, + EL_SP_CHIP_RIGHT, EL_SP_CHIP_BOTTOM, + EL_TUBE_VERTICAL, EL_TUBE_HORIZONTAL, + EL_TUBE_VERTICAL_LEFT, EL_TUBE_HORIZONTAL_UP, + EL_TUBE_VERTICAL_RIGHT, EL_TUBE_HORIZONTAL_DOWN, + EL_TUBE_LEFT_DOWN, EL_TUBE_RIGHT_UP, + EL_DC_STEELWALL_1_LEFT, EL_DC_STEELWALL_1_TOP, + EL_DC_STEELWALL_1_RIGHT, EL_DC_STEELWALL_1_BOTTOM, + EL_DC_STEELWALL_1_HORIZONTAL, EL_DC_STEELWALL_1_VERTICAL, + EL_DC_STEELWALL_1_TOPRIGHT, EL_DC_STEELWALL_1_BOTTOMLEFT, + EL_DC_STEELWALL_1_TOPRIGHT_2, EL_DC_STEELWALL_1_BOTTOMLEFT_2, + EL_DC_STEELWALL_2_LEFT, EL_DC_STEELWALL_2_TOP, + EL_DC_STEELWALL_2_RIGHT, EL_DC_STEELWALL_2_BOTTOM, + EL_DC_STEELWALL_2_HORIZONTAL, EL_DC_STEELWALL_2_VERTICAL, + EL_EXPANDABLE_WALL_HORIZONTAL, EL_EXPANDABLE_WALL_VERTICAL, + EL_EXPANDABLE_STEELWALL_HORIZONTAL, EL_EXPANDABLE_STEELWALL_VERTICAL, + + -1 + }; + + return getFlippedTileExt(map, element); +} + +static int getFlippedTile(int element, int mode) +{ + if (IS_MM_ELEMENT(element)) + { + // get MM game element + element = map_element_RND_to_MM(element); + + // get flipped game element + element = (mode == CB_FLIP_BRUSH_X ? getFlippedTileX_MM(element) : + mode == CB_FLIP_BRUSH_Y ? getFlippedTileY_MM(element) : + mode == CB_FLIP_BRUSH_XY ? getFlippedTileXY_MM(element) : + element); + + // get RND game element again + element = map_element_MM_to_RND(element); + } + else + { + // get flipped game element + element = (mode == CB_FLIP_BRUSH_X ? getFlippedTileX(element) : + mode == CB_FLIP_BRUSH_Y ? getFlippedTileY(element) : + mode == CB_FLIP_BRUSH_XY ? getFlippedTileXY(element) : + element); + } + + return element; +} + +static void SwapFlippedTiles(short *tile1, short *tile2, int mode) +{ + // flip tiles + short tile1_flipped = getFlippedTile(*tile1, mode); + short tile2_flipped = getFlippedTile(*tile2, mode); + + // swap tiles + *tile1 = tile2_flipped; + *tile2 = tile1_flipped; +} + static void DrawBrushElement(int sx, int sy, int element, boolean change_level) { DrawLineElement(sx, sy, element, change_level); @@ -12510,6 +12898,37 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, delete_old_brush = TRUE; } + else if (mode == CB_FLIP_BRUSH_X) + { + for (y = 0; y < brush_height; y++) + for (x = 0; x < (brush_width + 1) / 2; x++) + SwapFlippedTiles(&brush_buffer[x][y], + &brush_buffer[brush_width - x - 1][y], mode); + + CopyBrushExt(last_cursor_x, last_cursor_y, 0, 0, 0, CB_BRUSH_TO_CURSOR); + } + else if (mode == CB_FLIP_BRUSH_Y) + { + for (y = 0; y < (brush_height + 1) / 2; y++) + for (x = 0; x < brush_width; x++) + SwapFlippedTiles(&brush_buffer[x][y], + &brush_buffer[x][brush_height - y - 1], mode); + + CopyBrushExt(last_cursor_x, last_cursor_y, 0, 0, 0, CB_BRUSH_TO_CURSOR); + } + else if (mode == CB_FLIP_BRUSH_XY) + { + CopyBrushExt(0, 0, 0, 0, 0, CB_DELETE_OLD_CURSOR); + + for (y = 0; y < MAX(brush_width, brush_height); y++) + for (x = 0; x <= y; x++) + SwapFlippedTiles(&brush_buffer[x][y], + &brush_buffer[y][x], mode); + + swap_numbers(&brush_width, &brush_height); + + CopyBrushExt(last_cursor_x, last_cursor_y, 0, 0, 0, CB_BRUSH_TO_CURSOR); + } if (mode == CB_UPDATE_BRUSH_POSITION) { @@ -12544,6 +12963,22 @@ static void DeleteBrushFromCursor(void) CopyBrushExt(0, 0, 0, 0, 0, CB_DELETE_OLD_CURSOR); } +static void FlipBrushX(void) +{ + CopyBrushExt(0, 0, 0, 0, 0, CB_FLIP_BRUSH_X); +} + +static void FlipBrushY(void) +{ + CopyBrushExt(0, 0, 0, 0, 0, CB_FLIP_BRUSH_Y); +} + +static void RotateBrush(void) +{ + CopyBrushExt(0, 0, 0, 0, 0, CB_FLIP_BRUSH_XY); + CopyBrushExt(0, 0, 0, 0, 0, CB_FLIP_BRUSH_X); +} + void DumpBrush(void) { CopyBrushExt(0, 0, 0, 0, 0, CB_DUMP_BRUSH); @@ -12621,7 +13056,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 @@ -12872,7 +13307,8 @@ static void WrapLevel(int dx, int dy) CopyLevelToUndoBuffer(UNDO_ACCUMULATE); } -static void DrawAreaElementHighlight(boolean highlighted) +static void DrawAreaElementHighlight(boolean highlighted, + boolean highlighted_similar) { DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos); @@ -12885,26 +13321,69 @@ static void DrawAreaElementHighlight(boolean highlighted) { for (y = 0; y < ed_fieldy; y++) { + boolean highlight = FALSE; int lx = x + level_xpos; int ly = y + level_ypos; if (!IN_LEV_FIELD(lx, ly)) continue; - if (Tile[lx][ly] != new_element1) + // check if element is the same + if (Tile[lx][ly] == new_element1) + highlight = TRUE; + + // check if element is similar + if (highlighted_similar && + strEqual(element_info[Tile[lx][ly]].class_name, + element_info[new_element1].class_name)) + highlight = TRUE; + + // check if element is matching MM style wall + if (IS_MM_WALL(Tile[lx][ly]) && + map_mm_wall_element(Tile[lx][ly]) == new_element1) + highlight = TRUE; + + if (!highlight) continue; - int sx = SX + x * ed_tilesize; - int sy = SY + y * ed_tilesize; - int from_sx = sx; - int from_sy = sy; - int to_sx = sx + ed_tilesize - 1; - int to_sy = sy + ed_tilesize - 1; - - DrawSimpleWhiteLine(drawto, from_sx, from_sy, to_sx, from_sy); - DrawSimpleWhiteLine(drawto, to_sx, from_sy, to_sx, to_sy); - DrawSimpleWhiteLine(drawto, to_sx, to_sy, from_sx, to_sy); - DrawSimpleWhiteLine(drawto, from_sx, to_sy, from_sx, from_sy); + if (IS_MM_WALL(Tile[lx][ly]) && !highlighted_similar) + { + int i; + + for (i = 0; i < 4; i++) + { + if (!(MM_WALL_BITS(Tile[lx][ly]) & (1 << i))) + continue; + + int xx = x * 2 + (i % 2); + int yy = y * 2 + (i / 2); + int sx = SX + xx * ed_tilesize / 2; + int sy = SY + yy * ed_tilesize / 2; + int from_sx = sx; + int from_sy = sy; + int to_sx = sx + ed_tilesize / 2 - 1; + int to_sy = sy + ed_tilesize / 2 - 1; + + DrawSimpleWhiteLine(drawto, from_sx, from_sy, to_sx, from_sy); + DrawSimpleWhiteLine(drawto, to_sx, from_sy, to_sx, to_sy); + DrawSimpleWhiteLine(drawto, to_sx, to_sy, from_sx, to_sy); + DrawSimpleWhiteLine(drawto, from_sx, to_sy, from_sx, from_sy); + } + } + else + { + int sx = SX + x * ed_tilesize; + int sy = SY + y * ed_tilesize; + int from_sx = sx; + int from_sy = sy; + int to_sx = sx + ed_tilesize - 1; + int to_sy = sy + ed_tilesize - 1; + + DrawSimpleWhiteLine(drawto, from_sx, from_sy, to_sx, from_sy); + DrawSimpleWhiteLine(drawto, to_sx, from_sy, to_sx, to_sy); + DrawSimpleWhiteLine(drawto, to_sx, to_sy, from_sx, to_sy); + DrawSimpleWhiteLine(drawto, from_sx, to_sy, from_sx, from_sy); + } } } } @@ -12924,8 +13403,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; @@ -12945,8 +13426,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); @@ -12958,6 +13437,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; @@ -12986,14 +13468,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 && @@ -13020,9 +13495,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); @@ -13058,10 +13530,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) { @@ -13071,7 +13542,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++) @@ -13080,7 +13551,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 && @@ -13100,6 +13572,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); + } } } } @@ -13146,22 +13624,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; @@ -13344,11 +13819,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; @@ -13356,6 +13831,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); @@ -13433,7 +13912,7 @@ static void HandleSelectboxGadgets(struct GadgetInfo *gi) if (type_id == ED_SELECTBOX_ID_LEVELSET_SAVE_MODE) { - DrawLevelInfoWindow(); + DrawLevelConfigWindow(); } else if (type_id == ED_SELECTBOX_ID_SELECT_CHANGE_PAGE) { @@ -13478,12 +13957,12 @@ static void HandleTextbuttonGadgets(struct GadgetInfo *gi) int type_id = gi->custom_type_id; int i; - if (type_id >= ED_TAB_BUTTON_ID_LEVELINFO_FIRST && - type_id <= ED_TAB_BUTTON_ID_LEVELINFO_LAST) + if (type_id >= ED_TAB_BUTTON_ID_LEVELCONFIG_FIRST && + type_id <= ED_TAB_BUTTON_ID_LEVELCONFIG_LAST) { - edit_mode_levelinfo = gi->custom_type_id; + edit_mode_levelconfig = gi->custom_type_id; - DrawLevelInfoWindow(); + DrawLevelConfigWindow(); } else if (type_id >= ED_TAB_BUTTON_ID_PROPERTIES_FIRST && type_id <= ED_TAB_BUTTON_ID_PROPERTIES_LAST) @@ -14139,12 +14618,12 @@ static void HandleControlButtons(struct GadgetInfo *gi) break; - case GADGET_ID_INFO: - if (edit_mode != ED_MODE_INFO) + case GADGET_ID_CONF: + if (edit_mode != ED_MODE_LEVELCONFIG) { last_edit_mode = edit_mode; - ChangeEditModeWindow(ED_MODE_INFO); + ChangeEditModeWindow(ED_MODE_LEVELCONFIG); } else { @@ -14185,7 +14664,7 @@ static void HandleControlButtons(struct GadgetInfo *gi) Request("Save this level and kill the old?", REQ_ASK)) { if (leveldir_former->readonly) - ModifyLevelInfoForSavingIntoPersonalLevelSet(leveldir_former->name); + ModifyLevelConfigForSavingIntoPersonalLevelSet(leveldir_former->name); SetAutomaticNumberOfGemsNeeded(); @@ -14250,7 +14729,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)) { @@ -14440,8 +14920,8 @@ void HandleLevelEditorKeyInput(Key key) 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_LEVELCONFIG) + HandleControlButtons(level_editor_gadget[GADGET_ID_CONF]); else if (edit_mode == ED_MODE_PROPERTIES) HandleControlButtons(level_editor_gadget[GADGET_ID_PROPERTIES]); else if (edit_mode == ED_MODE_PALETTE) @@ -14483,6 +14963,16 @@ void HandleLevelEditorKeyInput(Key key) if (letter && letter == controlbutton_info[i].shortcut) if (!anyTextGadgetActive()) ClickOnGadget(level_editor_gadget[i], button); + + if (draw_with_brush) + { + if (letter == 'x') + FlipBrushX(); + else if (letter == 'y') + FlipBrushY(); + else if (letter == 'z') + RotateBrush(); + } } static void HandleLevelEditorIdle_Properties(void) @@ -14516,16 +15006,20 @@ static void HandleLevelEditorIdle_Properties(void) static void HandleLevelEditorIdle_Drawing(void) { static boolean last_highlighted = FALSE; + static boolean last_highlighted_similar = FALSE; boolean highlighted = (GetKeyModState() & KMOD_Alt); + boolean highlighted_similar = (GetKeyModState() & KMOD_Shift); - if (highlighted != last_highlighted) + if (highlighted != last_highlighted || + (highlighted && highlighted_similar != last_highlighted_similar)) { - DrawAreaElementHighlight(highlighted); - - last_highlighted = highlighted; + DrawAreaElementHighlight(highlighted, highlighted_similar); redraw_mask |= REDRAW_FIELD; } + + last_highlighted = highlighted; + last_highlighted_similar = highlighted_similar; } void HandleLevelEditorIdle(void) @@ -14544,7 +15038,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) @@ -14559,6 +15052,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) @@ -14602,7 +15097,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; @@ -14615,7 +15109,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 @@ -14652,10 +15145,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; @@ -14786,7 +15283,7 @@ void RequestExitLevelEditor(boolean ask_if_level_has_changed, vp_door_2->height == VYSIZE) CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY); else - SetDoorState(DOOR_CLOSE_2); + SetDoorState(DOOR_CLOSE_ALL); BackToFront();