X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Feditor.c;h=0eea3c6da24218245c1a3c75980280f089e1b789;hb=c2a639c0b2c1a9a2bd14de86932a47429ae918a4;hp=5e657368d04a413c88d26d4cbcbb4e7727d416bb;hpb=ec178b8090e5767eeaa8ab33515c3dcfb954028b;p=rocksndiamonds.git diff --git a/src/editor.c b/src/editor.c index 5e657368..0eea3c6d 100644 --- a/src/editor.c +++ b/src/editor.c @@ -24,6 +24,9 @@ #include "tape.h" +#define INFOTEXT_UNKNOWN_ELEMENT "unknown" + + /* ----------------------------------------------------------------------------- screen and artwork graphic pixel position definitions @@ -39,24 +42,41 @@ #define ED_WIN_MB_RIGHT_YPOS ED_WIN_MB_LEFT_YPOS /* values for the control window */ -#define ED_CTRL_BUTTONS_GFX_YPOS 236 -#define ED_CTRL_BUTTONS_ALT_GFX_YPOS 142 +#define ED_CTRL_NO_BUTTONS_GFX_XPOS 6 +#define ED_CTRL_NO_BUTTONS_GFX_YPOS 286 +#define ED_CTRL1_BUTTONS_GFX_YPOS 236 +#define ED_CTRL2_BUTTONS_GFX_YPOS 236 +#define ED_CTRL3_BUTTONS_GFX_YPOS 324 +#define ED_CTRL1_BUTTONS_ALT_GFX_YPOS 142 +#define ED_CTRL3_BUTTONS_ALT_GFX_YPOS 302 -#define ED_CTRL1_BUTTONS_HORIZ 4 -#define ED_CTRL1_BUTTONS_VERT 4 #define ED_CTRL1_BUTTON_XSIZE 22 #define ED_CTRL1_BUTTON_YSIZE 22 #define ED_CTRL1_BUTTONS_XPOS 6 #define ED_CTRL1_BUTTONS_YPOS 6 -#define ED_CTRL2_BUTTONS_HORIZ 3 -#define ED_CTRL2_BUTTONS_VERT 2 #define ED_CTRL2_BUTTON_XSIZE 30 #define ED_CTRL2_BUTTON_YSIZE 20 #define ED_CTRL2_BUTTONS_XPOS 5 #define ED_CTRL2_BUTTONS_YPOS 99 +#define ED_CTRL3_BUTTON_XSIZE 22 +#define ED_CTRL3_BUTTON_YSIZE 22 +#define ED_CTRL3_BUTTONS_XPOS 6 +#define ED_CTRL3_BUTTONS_YPOS 6 + +#define ED_CTRL1_BUTTONS_HORIZ 4 +#define ED_CTRL1_BUTTONS_VERT 4 +#define ED_CTRL2_BUTTONS_HORIZ 3 +#define ED_CTRL2_BUTTONS_VERT 2 +#define ED_CTRL3_BUTTONS_HORIZ 3 +#define ED_CTRL3_BUTTONS_VERT 1 + #define ED_NUM_CTRL1_BUTTONS (ED_CTRL1_BUTTONS_HORIZ * ED_CTRL1_BUTTONS_VERT) #define ED_NUM_CTRL2_BUTTONS (ED_CTRL2_BUTTONS_HORIZ * ED_CTRL2_BUTTONS_VERT) -#define ED_NUM_CTRL_BUTTONS (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS) +#define ED_NUM_CTRL3_BUTTONS (ED_CTRL3_BUTTONS_HORIZ * ED_CTRL3_BUTTONS_VERT) +#define ED_NUM_CTRL1_2_BUTTONS (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS) +#define ED_NUM_CTRL_BUTTONS (ED_NUM_CTRL1_BUTTONS + \ + ED_NUM_CTRL2_BUTTONS + \ + ED_NUM_CTRL3_BUTTONS) /* values for the element list */ #define ED_ELEMENTLIST_XPOS 5 @@ -131,7 +151,7 @@ ED_GADGET_DISTANCE) /* extended custom change target */ #define ED_AREA_ELEM_CONTENT6_XPOS (29 * MINI_TILEX) -#define ED_AREA_ELEM_CONTENT6_YPOS (ED_SETTINGS_YPOS(9) + \ +#define ED_AREA_ELEM_CONTENT6_YPOS (ED_SETTINGS_YPOS(10) + \ ED_GADGET_DISTANCE - MINI_TILEY) /* values for random placement background drawing area */ @@ -280,6 +300,7 @@ #define GADGET_ID_GRAB_BRUSH (GADGET_ID_TOOLBOX_FIRST + 13) #define GADGET_ID_WRAP_DOWN (GADGET_ID_TOOLBOX_FIRST + 14) #define GADGET_ID_PICK_ELEMENT (GADGET_ID_TOOLBOX_FIRST + 15) + #define GADGET_ID_UNDO (GADGET_ID_TOOLBOX_FIRST + 16) #define GADGET_ID_INFO (GADGET_ID_TOOLBOX_FIRST + 17) #define GADGET_ID_SAVE (GADGET_ID_TOOLBOX_FIRST + 18) @@ -287,8 +308,12 @@ #define GADGET_ID_TEST (GADGET_ID_TOOLBOX_FIRST + 20) #define GADGET_ID_EXIT (GADGET_ID_TOOLBOX_FIRST + 21) +#define GADGET_ID_CUSTOM_COPY_FROM (GADGET_ID_TOOLBOX_FIRST + 22) +#define GADGET_ID_CUSTOM_COPY_TO (GADGET_ID_TOOLBOX_FIRST + 23) +#define GADGET_ID_CUSTOM_EXCHANGE (GADGET_ID_TOOLBOX_FIRST + 24) + /* counter button identifiers */ -#define GADGET_ID_COUNTER_FIRST (GADGET_ID_TOOLBOX_FIRST + 22) +#define GADGET_ID_COUNTER_FIRST (GADGET_ID_TOOLBOX_FIRST + 25) #define GADGET_ID_SELECT_LEVEL_DOWN (GADGET_ID_COUNTER_FIRST + 0) #define GADGET_ID_SELECT_LEVEL_TEXT (GADGET_ID_COUNTER_FIRST + 1) @@ -399,11 +424,12 @@ #define GADGET_ID_CHANGE_TIME_UNITS (GADGET_ID_SELECTBOX_FIRST + 10) #define GADGET_ID_CHANGE_DIRECT_ACTION (GADGET_ID_SELECTBOX_FIRST + 11) #define GADGET_ID_CHANGE_OTHER_ACTION (GADGET_ID_SELECTBOX_FIRST + 12) -#define GADGET_ID_CHANGE_POWER (GADGET_ID_SELECTBOX_FIRST + 13) -#define GADGET_ID_SELECT_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 14) +#define GADGET_ID_CHANGE_SIDES (GADGET_ID_SELECTBOX_FIRST + 13) +#define GADGET_ID_CHANGE_POWER (GADGET_ID_SELECTBOX_FIRST + 14) +#define GADGET_ID_SELECT_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 15) /* textbutton identifiers */ -#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 15) +#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 16) #define GADGET_ID_PROPERTIES_INFO (GADGET_ID_TEXTBUTTON_FIRST + 0) #define GADGET_ID_PROPERTIES_CONFIG (GADGET_ID_TEXTBUTTON_FIRST + 1) @@ -567,10 +593,11 @@ #define ED_SELECTBOX_ID_CHANGE_TIME_UNITS 10 #define ED_SELECTBOX_ID_CHANGE_DIRECT_ACTION 11 #define ED_SELECTBOX_ID_CHANGE_OTHER_ACTION 12 -#define ED_SELECTBOX_ID_CHANGE_POWER 13 -#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE 14 +#define ED_SELECTBOX_ID_CHANGE_SIDES 13 +#define ED_SELECTBOX_ID_CHANGE_POWER 14 +#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE 15 -#define ED_NUM_SELECTBOX 15 +#define ED_NUM_SELECTBOX 16 #define ED_SELECTBOX_ID_CUSTOM_FIRST ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE #define ED_SELECTBOX_ID_CUSTOM_LAST ED_SELECTBOX_ID_CUSTOM_CONSISTENCY @@ -731,28 +758,33 @@ static struct char *text; } control_info[ED_NUM_CTRL_BUTTONS] = { - { 's', "draw single items" }, - { 'd', "draw connected items" }, - { 'l', "draw lines" }, - { 'a', "draw arcs" }, - { 'r', "draw outline rectangles" }, - { 'R', "draw filled rectangles" }, - { '\0', "wrap (rotate) level up" }, - { 't', "enter text elements" }, - { 'f', "flood fill" }, - { '\0', "wrap (rotate) level left" }, - { '?', "properties of drawing element" }, - { '\0', "wrap (rotate) level right" }, - { '\0', "random element placement" }, - { 'b', "grab brush" }, - { '\0', "wrap (rotate) level down" }, - { ',', "pick drawing element" }, - { 'U', "undo last operation" }, - { 'I', "level properties" }, - { 'S', "save level" }, - { 'C', "clear level" }, - { 'T', "test level" }, - { 'E', "exit level editor" } + { 's', "draw single items" }, + { 'd', "draw connected items" }, + { 'l', "draw lines" }, + { 'a', "draw arcs" }, + { 'r', "draw outline rectangles" }, + { 'R', "draw filled rectangles" }, + { '\0', "wrap (rotate) level up" }, + { 't', "enter text elements" }, + { 'f', "flood fill" }, + { '\0', "wrap (rotate) level left" }, + { '?', "properties of drawing element" }, + { '\0', "wrap (rotate) level right" }, + { '\0', "random element placement" }, + { 'b', "grab brush" }, + { '\0', "wrap (rotate) level down" }, + { ',', "pick drawing element" }, + + { 'U', "undo last operation" }, + { 'I', "level properties" }, + { 'S', "save level" }, + { 'C', "clear level" }, + { 'T', "test level" }, + { 'E', "exit level editor" }, + + { '\0', "copy settings from other element" }, + { '\0', "copy settings to other element" }, + { '\0', "exchange settings with other element" }, }; static int random_placement_value = 10; @@ -858,7 +890,7 @@ static struct MIN_ENVELOPE_XSIZE, MAX_ENVELOPE_XSIZE, GADGET_ID_ENVELOPE_XSIZE_DOWN, GADGET_ID_ENVELOPE_XSIZE_UP, GADGET_ID_ENVELOPE_XSIZE_TEXT, GADGET_ID_NONE, - &level.envelope_xsize, + NULL, NULL, NULL, "width", }, { @@ -866,7 +898,7 @@ static struct MIN_ENVELOPE_YSIZE, MAX_ENVELOPE_YSIZE, GADGET_ID_ENVELOPE_YSIZE_DOWN, GADGET_ID_ENVELOPE_YSIZE_UP, GADGET_ID_ENVELOPE_YSIZE_TEXT, GADGET_ID_ENVELOPE_XSIZE_UP, - &level.envelope_ysize, + NULL, NULL, " ", "height", }, @@ -940,12 +972,12 @@ static struct NULL, "+random", NULL }, { - ED_SETTINGS_XPOS(3), ED_SETTINGS_YPOS(11), + ED_SETTINGS_XPOS(3), ED_SETTINGS_YPOS(12), 0, 100, GADGET_ID_CHANGE_CONT_RND_DOWN, GADGET_ID_CHANGE_CONT_RND_UP, GADGET_ID_CHANGE_CONT_RND_TEXT, GADGET_ID_NONE, &custom_element_change.random, - NULL, "use random change:", "(%)" + NULL, "use random replace:", "%" }, }; @@ -994,7 +1026,7 @@ static struct ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(2), GADGET_ID_ENVELOPE_INFO, MAX_ENVELOPE_XSIZE, MAX_ENVELOPE_YSIZE, - level.envelope, + NULL, "Envelope Info:", "Envelope Info" } }; @@ -1038,6 +1070,7 @@ static struct ValueTextInfo options_move_pattern[] = { MV_ALONG_RIGHT_SIDE, "along right side" }, { MV_TURNING_LEFT, "turning left" }, { MV_TURNING_RIGHT, "turning right" }, + { MV_WHEN_PUSHED, "when pushed" }, { -1, NULL } }; @@ -1099,18 +1132,21 @@ static struct ValueTextInfo options_consistency[] = static struct ValueTextInfo options_time_units[] = { - { FRAMES_PER_SECOND, "seconds" }, { 1, "frames" }, + { FRAMES_PER_SECOND, "seconds" }, { -1, NULL } }; static struct ValueTextInfo options_change_direct_action[] = { - { CE_TOUCHED_BY_PLAYER, "player touches it" }, - { CE_PRESSED_BY_PLAYER, "player presses it" }, - { CE_PUSHED_BY_PLAYER, "player pushes it" }, - { CE_DROPPED_BY_PLAYER, "player drops it" }, - { CE_COLLISION, "collision" }, + { CE_TOUCHED_BY_PLAYER, "touched by player ..." }, + { CE_PRESSED_BY_PLAYER, "pressed by player ..." }, + { CE_PUSHED_BY_PLAYER, "pushed by player ..." }, + { CE_ENTERED_BY_PLAYER, "entered by player ..." }, + { CE_LEFT_BY_PLAYER, "left by player ..." }, + { CE_DROPPED_BY_PLAYER, "dropped by player" }, + { CE_SWITCHED, "switched ..." }, + { CE_COLLISION, "collision ..." }, { CE_IMPACT, "impact" }, { CE_SMASHED, "smashed" }, { -1, NULL } @@ -1118,17 +1154,33 @@ static struct ValueTextInfo options_change_direct_action[] = static struct ValueTextInfo options_change_other_action[] = { - { CE_OTHER_GETS_TOUCHED, "player touches" }, - { CE_OTHER_GETS_PRESSED, "player presses" }, - { CE_OTHER_GETS_PUSHED, "player pushes" }, + { CE_OTHER_GETS_TOUCHED, "player touches ..." }, + { CE_OTHER_GETS_PRESSED, "player presses ..." }, + { CE_OTHER_GETS_PUSHED, "player pushes ..." }, + { CE_OTHER_GETS_ENTERED, "player enters ..." }, + { CE_OTHER_GETS_LEFT, "player leaves ..." }, + { CE_OTHER_GETS_DIGGED, "player digs" }, { CE_OTHER_GETS_COLLECTED, "player collects" }, { CE_OTHER_GETS_DROPPED, "player drops" }, - { CE_OTHER_IS_TOUCHING, "it touches" }, + { CE_OTHER_IS_TOUCHING, "touching ..." }, + { CE_OTHER_IS_SWITCHING, "switch of ..." }, { CE_OTHER_IS_CHANGING, "change of" }, { CE_OTHER_IS_EXPLODING, "explosion of" }, { -1, NULL } }; +static struct ValueTextInfo options_change_sides[] = +{ + { CH_SIDE_LEFT, "left side" }, + { CH_SIDE_RIGHT, "right side" }, + { CH_SIDE_TOP, "top side" }, + { CH_SIDE_BOTTOM, "bottom side" }, + { CH_SIDE_LEFT_RIGHT, "left/right side" }, + { CH_SIDE_TOP_BOTTOM, "top/bottom side" }, + { CH_SIDE_ANY, "all sides" }, + { -1, NULL } +}; + static struct ValueTextInfo options_change_power[] = { { CP_NON_DESTRUCTIVE, "empty" }, @@ -1264,7 +1316,15 @@ static struct NULL, "element:", "type of other element action" }, { - ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(9), + ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(7), + GADGET_ID_CHANGE_SIDES, GADGET_ID_NONE, + -1, + options_change_sides, + &custom_element_change.sides, + "... at", NULL, "element side that causes change" + }, + { + ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(10), GADGET_ID_CHANGE_POWER, GADGET_ID_NONE, -1, options_change_power, @@ -1272,7 +1332,7 @@ static struct "replace when", NULL, "which elements can be replaced" }, { - ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(13), + ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(14), GADGET_ID_SELECT_CHANGE_PAGE, GADGET_ID_NONE, 3, options_change_page, @@ -1310,19 +1370,19 @@ static struct NULL, NULL, "Advanced element configuration" }, { - -1, ED_SETTINGS_YPOS(12), + -1, ED_SETTINGS_YPOS(13), GADGET_ID_SAVE_AS_TEMPLATE, GADGET_ID_CUSTOM_USE_TEMPLATE, -1, "Save as template", " ", NULL, "Save current settings as new template" }, { - -1, ED_SETTINGS_YPOS(13), + -1, ED_SETTINGS_YPOS(14), GADGET_ID_ADD_CHANGE_PAGE, GADGET_ID_NEXT_CHANGE_PAGE, -1, "New", " ", NULL, "Add new config page" }, { - -1, ED_SETTINGS_YPOS(13), + -1, ED_SETTINGS_YPOS(14), GADGET_ID_DEL_CHANGE_PAGE, GADGET_ID_ADD_CHANGE_PAGE, -1, "Delete", NULL, NULL, "Delete current config page" @@ -1341,14 +1401,14 @@ static struct { { ED_BUTTON_MINUS_XPOS, ED_BUTTON_COUNT_YPOS, - ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(13), + ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(14), ED_BUTTON_COUNT_XSIZE, ED_BUTTON_COUNT_YSIZE, GADGET_ID_PREV_CHANGE_PAGE, GADGET_ID_NONE, NULL, NULL, "select previous config page" }, { ED_BUTTON_PLUS_XPOS, ED_BUTTON_COUNT_YPOS, - -1, ED_SETTINGS_YPOS(13), + -1, ED_SETTINGS_YPOS(14), ED_BUTTON_COUNT_XSIZE, ED_BUTTON_COUNT_YSIZE, GADGET_ID_NEXT_CHANGE_PAGE, GADGET_ID_SELECT_CHANGE_PAGE, NULL, "config page", "select next config page" @@ -1484,7 +1544,7 @@ static struct { -1, ED_COUNTER_YPOS(6) - MINI_TILEY, GADGET_ID_GRAVITY, GADGET_ID_DOUBLE_SPEED, - &level.gravity, + &level.initial_gravity, " ", "gravity", "set level gravity" }, { @@ -1614,31 +1674,31 @@ static struct NULL, NULL, "element changes by other element" }, { - ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(7), + ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(8), GADGET_ID_CHANGE_USE_EXPLOSION, GADGET_ID_NONE, &custom_element_change.explode, NULL, "explode instead of change", "element explodes instead of change" }, { - ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(8), + ED_SETTINGS_XPOS(1), ED_SETTINGS_YPOS(9), GADGET_ID_CHANGE_USE_CONTENT, GADGET_ID_NONE, &custom_element_change.use_content, NULL, "use extended change target:","element changes to more elements" }, { - ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(10), + ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(11), GADGET_ID_CHANGE_ONLY_COMPLETE, GADGET_ID_NONE, &custom_element_change.only_complete, - NULL, "only use complete change", "only use complete extended content" + NULL, "replace all or nothing", "only replace when all can be changed" }, { - ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(11), + ED_SETTINGS_XPOS(2), ED_SETTINGS_YPOS(12), GADGET_ID_CHANGE_USE_RANDOM, GADGET_ID_NONE, &custom_element_change.use_random_change, - NULL, NULL, "use random value for new content" + NULL, NULL, "use percentage for random replace" }, { - ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(12), + ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(13), GADGET_ID_CUSTOM_USE_TEMPLATE, GADGET_ID_NONE, &level.use_custom_template, NULL, "use template", "use template for custom properties" @@ -1812,6 +1872,7 @@ static void RedrawDrawingElements(); static void DrawDrawingWindow(); static void DrawLevelInfoWindow(); static void DrawPropertiesWindow(); +static void UpdateCustomElementGraphicGadgets(); static boolean checkPropertiesConfig(); static void CopyLevelToUndoBuffer(int); static void HandleDrawingAreas(struct GadgetInfo *); @@ -1889,6 +1950,8 @@ static int editor_el_boulderdash[] = EL_BD_FIREFLY_DOWN, EL_EMPTY, }; +static int *editor_hl_boulderdash_ptr = editor_hl_boulderdash; +static int *editor_el_boulderdash_ptr = editor_el_boulderdash; static int num_editor_hl_boulderdash = SIZEOF_ARRAY_INT(editor_hl_boulderdash); static int num_editor_el_boulderdash = SIZEOF_ARRAY_INT(editor_el_boulderdash); @@ -1972,10 +2035,17 @@ static int editor_el_emerald_mine[] = EL_AMOEBA_WET, EL_AMOEBA_DRY, +#if 1 + EL_EM_KEY_1, + EL_EM_KEY_2, + EL_EM_KEY_3, + EL_EM_KEY_4, +#else EL_EM_KEY_1_FILE, EL_EM_KEY_2_FILE, EL_EM_KEY_3_FILE, EL_EM_KEY_4_FILE, +#endif EL_EM_GATE_1, EL_EM_GATE_2, @@ -1987,6 +2057,8 @@ static int editor_el_emerald_mine[] = EL_EM_GATE_3_GRAY, EL_EM_GATE_4_GRAY, }; +static int *editor_hl_emerald_mine_ptr = editor_hl_emerald_mine; +static int *editor_el_emerald_mine_ptr = editor_el_emerald_mine; static int num_editor_hl_emerald_mine=SIZEOF_ARRAY_INT(editor_hl_emerald_mine); static int num_editor_el_emerald_mine=SIZEOF_ARRAY_INT(editor_el_emerald_mine); @@ -2055,17 +2127,17 @@ static int editor_el_more[] = EL_PIG, EL_DRAGON, - EL_EMPTY, + EL_BUG, EL_MOLE_UP, - EL_EMPTY, - EL_EMPTY, + EL_BD_BUTTERFLY, + EL_BD_FIREFLY, EL_MOLE_LEFT, EL_EMPTY, EL_MOLE_RIGHT, - EL_EMPTY, + EL_PACMAN, - EL_EMPTY, + EL_SPACESHIP, EL_MOLE_DOWN, EL_BALLOON, EL_BALLOON_SWITCH_ANY, @@ -2095,6 +2167,8 @@ static int editor_el_more[] = EL_EMC_WALL_6, EL_EMC_WALL_7, }; +static int *editor_hl_more_ptr = editor_hl_more; +static int *editor_el_more_ptr = editor_el_more; static int num_editor_hl_more = SIZEOF_ARRAY_INT(editor_hl_more); static int num_editor_el_more = SIZEOF_ARRAY_INT(editor_el_more); @@ -2118,6 +2192,8 @@ static int editor_el_sokoban[] = EL_SOKOBAN_FIELD_FULL, EL_STEELWALL, }; +static int *editor_hl_sokoban_ptr = editor_hl_sokoban; +static int *editor_el_sokoban_ptr = editor_el_sokoban; static int num_editor_hl_sokoban = SIZEOF_ARRAY_INT(editor_hl_sokoban); static int num_editor_el_sokoban = SIZEOF_ARRAY_INT(editor_el_sokoban); @@ -2136,7 +2212,11 @@ static int editor_hl_supaplex[] = static int editor_el_supaplex[] = { +#if 1 + EL_EMPTY, +#else EL_SP_EMPTY, +#endif EL_SP_ZONK, EL_SP_BASE, EL_SP_MURPHY, @@ -2186,6 +2266,8 @@ static int editor_el_supaplex[] = EL_SP_CHIP_TOP, EL_SP_CHIP_BOTTOM, }; +static int *editor_hl_supaplex_ptr = editor_hl_supaplex; +static int *editor_el_supaplex_ptr = editor_el_supaplex; static int num_editor_hl_supaplex = SIZEOF_ARRAY_INT(editor_hl_supaplex); static int num_editor_el_supaplex = SIZEOF_ARRAY_INT(editor_el_supaplex); @@ -2252,7 +2334,12 @@ static int editor_el_diamond_caves[] = EL_SWITCHGATE_OPEN, EL_SWITCHGATE_CLOSED, EL_SWITCHGATE_SWITCH_UP, - EL_ENVELOPE, + EL_EMPTY, + + EL_ENVELOPE_1, + EL_ENVELOPE_2, + EL_ENVELOPE_3, + EL_ENVELOPE_4, EL_TIMEGATE_CLOSED, EL_TIMEGATE_OPEN, @@ -2274,6 +2361,8 @@ static int editor_el_diamond_caves[] = EL_EXTRA_TIME, EL_EMPTY, }; +static int *editor_hl_diamond_caves_ptr = editor_hl_diamond_caves; +static int *editor_el_diamond_caves_ptr = editor_el_diamond_caves; static int num_editor_hl_diamond_caves = SIZEOF_ARRAY_INT(editor_hl_diamond_caves); static int num_editor_el_diamond_caves = SIZEOF_ARRAY_INT(editor_el_diamond_caves); @@ -2322,6 +2411,8 @@ static int editor_el_dx_boulderdash[] = EL_EMPTY, EL_EMPTY }; +static int *editor_hl_dx_boulderdash_ptr = editor_hl_dx_boulderdash; +static int *editor_el_dx_boulderdash_ptr = editor_el_dx_boulderdash; static int num_editor_hl_dx_boulderdash = SIZEOF_ARRAY_INT(editor_hl_dx_boulderdash); static int num_editor_el_dx_boulderdash = SIZEOF_ARRAY_INT(editor_el_dx_boulderdash); @@ -2425,6 +2516,8 @@ static int editor_el_chars[] = EL_CHAR(FONT_ASCII_CURSOR), EL_CHAR(' ') }; +static int *editor_hl_chars_ptr = editor_hl_chars; +static int *editor_el_chars_ptr = editor_el_chars; static int num_editor_hl_chars = SIZEOF_ARRAY_INT(editor_hl_chars); static int num_editor_el_chars = SIZEOF_ARRAY_INT(editor_el_chars); @@ -2613,6 +2706,8 @@ static int editor_el_custom[] = EL_CUSTOM_START + 126, EL_CUSTOM_START + 127 }; +static int *editor_hl_custom_ptr = editor_hl_custom; +static int *editor_el_custom_ptr = editor_el_custom; static int num_editor_hl_custom = SIZEOF_ARRAY_INT(editor_hl_custom); static int num_editor_el_custom = SIZEOF_ARRAY_INT(editor_el_custom); @@ -2782,9 +2877,44 @@ static int editor_el_custom_more[] = EL_CUSTOM_START + 254, EL_CUSTOM_START + 255 }; +static int *editor_hl_custom_more_ptr = editor_hl_custom_more; +static int *editor_el_custom_more_ptr = editor_el_custom_more; static int num_editor_hl_custom_more = SIZEOF_ARRAY_INT(editor_hl_custom_more); static int num_editor_el_custom_more = SIZEOF_ARRAY_INT(editor_el_custom_more); +static int editor_hl_user_defined[] = +{ + EL_CHAR('U'), + EL_CHAR('S'), + EL_CHAR('E'), + EL_CHAR('R'), + + EL_CHAR('D'), + EL_CHAR('E'), + EL_CHAR('F'), + EL_CHAR('I'), + + EL_CHAR('-'), + EL_CHAR('N'), + EL_CHAR('E'), + EL_CHAR('D'), +}; + +static int *editor_hl_user_defined_ptr = editor_hl_user_defined; +static int *editor_el_user_defined_ptr = NULL; +static int num_editor_hl_user_defined=SIZEOF_ARRAY_INT(editor_hl_user_defined); +static int num_editor_el_user_defined = 0; + +static int editor_hl_empty[] = { }; +static int editor_el_empty[ED_NUM_ELEMENTLIST_BUTTONS]; + +static int *editor_hl_empty_ptr = editor_hl_empty; +static int *editor_el_empty_ptr = editor_el_empty; +static int num_editor_hl_empty = 0; +static int num_editor_el_empty = 0; /* dynamically determined, if needed */ + +static boolean use_el_empty = FALSE; + static int *editor_elements = NULL; /* dynamically allocated */ static int num_editor_elements = 0; /* dynamically determined */ @@ -2792,10 +2922,10 @@ static struct { boolean *setup_value; - int *headline_list; + int **headline_list; int *headline_list_size; - int *element_list; + int **element_list; int *element_list_size; boolean last_setup_value; @@ -2804,53 +2934,63 @@ editor_elements_info[] = { { &setup.editor.el_boulderdash, - editor_hl_boulderdash, &num_editor_hl_boulderdash, - editor_el_boulderdash, &num_editor_el_boulderdash + &editor_hl_boulderdash_ptr, &num_editor_hl_boulderdash, + &editor_el_boulderdash_ptr, &num_editor_el_boulderdash }, { &setup.editor.el_emerald_mine, - editor_hl_emerald_mine, &num_editor_hl_emerald_mine, - editor_el_emerald_mine, &num_editor_el_emerald_mine + &editor_hl_emerald_mine_ptr, &num_editor_hl_emerald_mine, + &editor_el_emerald_mine_ptr, &num_editor_el_emerald_mine }, { &setup.editor.el_more, - editor_hl_more, &num_editor_hl_more, - editor_el_more, &num_editor_el_more + &editor_hl_more_ptr, &num_editor_hl_more, + &editor_el_more_ptr, &num_editor_el_more }, { &setup.editor.el_sokoban, - editor_hl_sokoban, &num_editor_hl_sokoban, - editor_el_sokoban, &num_editor_el_sokoban + &editor_hl_sokoban_ptr, &num_editor_hl_sokoban, + &editor_el_sokoban_ptr, &num_editor_el_sokoban }, { &setup.editor.el_supaplex, - editor_hl_supaplex, &num_editor_hl_supaplex, - editor_el_supaplex, &num_editor_el_supaplex + &editor_hl_supaplex_ptr, &num_editor_hl_supaplex, + &editor_el_supaplex_ptr, &num_editor_el_supaplex }, { &setup.editor.el_diamond_caves, - editor_hl_diamond_caves, &num_editor_hl_diamond_caves, - editor_el_diamond_caves, &num_editor_el_diamond_caves + &editor_hl_diamond_caves_ptr, &num_editor_hl_diamond_caves, + &editor_el_diamond_caves_ptr, &num_editor_el_diamond_caves }, { &setup.editor.el_dx_boulderdash, - editor_hl_dx_boulderdash, &num_editor_hl_dx_boulderdash, - editor_el_dx_boulderdash, &num_editor_el_dx_boulderdash + &editor_hl_dx_boulderdash_ptr, &num_editor_hl_dx_boulderdash, + &editor_el_dx_boulderdash_ptr, &num_editor_el_dx_boulderdash }, { &setup.editor.el_chars, - editor_hl_chars, &num_editor_hl_chars, - editor_el_chars, &num_editor_el_chars + &editor_hl_chars_ptr, &num_editor_hl_chars, + &editor_el_chars_ptr, &num_editor_el_chars }, { &setup.editor.el_custom, - editor_hl_custom, &num_editor_hl_custom, - editor_el_custom, &num_editor_el_custom + &editor_hl_custom_ptr, &num_editor_hl_custom, + &editor_el_custom_ptr, &num_editor_el_custom }, { &setup.editor.el_custom_more, - editor_hl_custom_more, &num_editor_hl_custom_more, - editor_el_custom_more, &num_editor_el_custom_more + &editor_hl_custom_more_ptr, &num_editor_hl_custom_more, + &editor_el_custom_more_ptr, &num_editor_el_custom_more + }, + { + &setup.editor.el_user_defined, + &editor_hl_user_defined_ptr, &num_editor_hl_user_defined, + &editor_el_user_defined_ptr, &num_editor_el_user_defined + }, + { + &use_el_empty, + &editor_hl_empty_ptr, &num_editor_hl_empty, + &editor_el_empty_ptr, &num_editor_el_empty, }, { NULL, @@ -2866,15 +3006,91 @@ editor_elements_info[] = ----------------------------------------------------------------------------- */ +static int getMaxInfoTextLength() +{ + return (SXSIZE / getFontWidth(FONT_TEXT_2)); +} + +static int getTextWidthForGadget(char *text) +{ + if (text == NULL) + return 0; + + return (getTextWidth(text, FONT_TEXT_1) + ED_GADGET_TEXT_DISTANCE); +} + +static int getTextWidthForDrawingArea(char *text) +{ + if (text == NULL) + return 0; + + return (getTextWidth(text, FONT_TEXT_1) + ED_DRAWINGAREA_TEXT_DISTANCE); +} + +static int getRightGadgetBorder(struct GadgetInfo *gi, char *text) +{ + return (gi->x + gi->width + getTextWidthForGadget(text)); +} + +static char *getElementInfoText(int element) +{ + char *info_text = NULL; + + if (element < NUM_FILE_ELEMENTS) + { + if (strlen(element_info[element].description) > 0) + info_text = element_info[element].description; + else if (element_info[element].custom_description != NULL) + info_text = element_info[element].custom_description; + else if (element_info[element].editor_description != NULL) + info_text = element_info[element].editor_description; + } + + if (info_text == NULL) + info_text = INFOTEXT_UNKNOWN_ELEMENT; + + return info_text; +} + static void ReinitializeElementList() { + static boolean initialized = FALSE; int pos = 0; int i, j; if (editor_elements != NULL) free(editor_elements); + if (!initialized) + { + /* initialize optional user defined element list */ + LoadUserDefinedEditorElementList(&editor_el_user_defined_ptr, + &num_editor_el_user_defined); + + /* initialize list of empty elements (used for padding, if needed) */ + for (i=0; i < ED_NUM_ELEMENTLIST_BUTTONS; i++) + editor_el_empty[i] = EL_EMPTY; + + /* do some sanity checks for each element from element list */ + for (i=0; editor_elements_info[i].setup_value != NULL; i++) + { + for (j=0; j < *editor_elements_info[i].element_list_size; j++) + { + int element = (*editor_elements_info[i].element_list)[j]; + + if (element >= NUM_FILE_ELEMENTS) + Error(ERR_WARN, "editor element %d is runtime element", element); + + if (strcmp(getElementInfoText(element), INFOTEXT_UNKNOWN_ELEMENT) == 0) + Error(ERR_WARN, "no element description for element %d", element); + } + } + + initialized = TRUE; + } + num_editor_elements = 0; + use_el_empty = FALSE; /* determine size of element list */ for (i=0; editor_elements_info[i].setup_value != NULL; i++) @@ -2890,11 +3106,11 @@ static void ReinitializeElementList() if (num_editor_elements < ED_NUM_ELEMENTLIST_BUTTONS) { - /* workaround: offer at least as many elements as element buttons exist */ - int list_nr = 1; /* see above: editor_elements_info for Emerald Mine */ + /* offer at least as many elements as element buttons exist */ + use_el_empty = TRUE; + num_editor_el_empty = ED_NUM_ELEMENTLIST_BUTTONS - num_editor_elements; - *editor_elements_info[list_nr].setup_value = TRUE; - num_editor_elements += *editor_elements_info[list_nr].element_list_size; + num_editor_elements += num_editor_el_empty; } editor_elements = checked_malloc(num_editor_elements * sizeof(int)); @@ -2906,10 +3122,10 @@ static void ReinitializeElementList() { if (setup.editor.el_headlines) for (j=0; j < *editor_elements_info[i].headline_list_size; j++) - editor_elements[pos++] = editor_elements_info[i].headline_list[j]; + editor_elements[pos++] = (*editor_elements_info[i].headline_list)[j]; for (j=0; j < *editor_elements_info[i].element_list_size; j++) - editor_elements[pos++] = editor_elements_info[i].element_list[j]; + editor_elements[pos++] = (*editor_elements_info[i].element_list)[j]; } } @@ -2920,6 +3136,35 @@ static void ReinitializeElementList() element_shift = num_editor_elements - ED_NUM_ELEMENTLIST_BUTTONS; } +void PrintEditorElementList() +{ + boolean *stop = &setup.editor.el_user_defined; + int i, j; + + for (i=0; editor_elements_info[i].setup_value != stop; i++) + { + for (j=0; j < *editor_elements_info[i].headline_list_size; j++) + { + int element = (*editor_elements_info[i].headline_list)[j]; + + printf("# %s\n", element_info[element].token_name); + } + + if (j > 0) + printf("#\n"); + + for (j=0; j < *editor_elements_info[i].element_list_size; j++) + { + int element = (*editor_elements_info[i].element_list)[j]; + + printf("# %s\n", element_info[element].token_name); + } + + if (j > 0) + printf("#\n"); + } +} + static void ReinitializeElementListButtons() { static boolean last_setup_value_headlines = FALSE; @@ -2952,56 +3197,6 @@ static void ReinitializeElementListButtons() initialization_needed = FALSE; } -static int getMaxInfoTextLength() -{ - return (SXSIZE / getFontWidth(FONT_TEXT_2)); -} - -static int getTextWidthForGadget(char *text) -{ - if (text == NULL) - return 0; - - return (getTextWidth(text, FONT_TEXT_1) + ED_GADGET_TEXT_DISTANCE); -} - -static int getTextWidthForDrawingArea(char *text) -{ - if (text == NULL) - return 0; - - return (getTextWidth(text, FONT_TEXT_1) + ED_DRAWINGAREA_TEXT_DISTANCE); -} - -static int getRightGadgetBorder(struct GadgetInfo *gi, char *text) -{ - return (gi->x + gi->width + getTextWidthForGadget(text)); -} - -static char *getElementInfoText(int element) -{ - char *info_text = NULL; - - if (element < NUM_FILE_ELEMENTS) - { - if (strlen(element_info[element].description) > 0) - info_text = element_info[element].description; - else if (element_info[element].custom_description != NULL) - info_text = element_info[element].custom_description; - else if (element_info[element].editor_description != NULL) - info_text = element_info[element].editor_description; - } - - if (info_text == NULL) - { - info_text = "unknown"; - - Error(ERR_WARN, "no element description for element %d", element); - } - - return info_text; -} - static void DrawElementBorder(int dest_x, int dest_y, int width, int height, boolean input) { @@ -3106,7 +3301,7 @@ static void CreateControlButtons() int i; /* create toolbox buttons */ - for (i=0; iwidth, gi->height, gi->x, gi->y); + + redraw_mask |= REDRAW_DOOR_3; + } + } + } +} + +static void MapLevelEditorToolboxDrawingGadgets() +{ + MapOrUnmapLevelEditorToolboxDrawingGadgets(TRUE); +} + +static void UnmapLevelEditorToolboxDrawingGadgets() +{ + MapOrUnmapLevelEditorToolboxDrawingGadgets(FALSE); +} + static void UnmapDrawingArea(int id) { UnmapGadget(level_editor_gadget[id]); } -void UnmapLevelEditorWindowGadgets() +static void UnmapLevelEditorWindowGadgets() { int i; - for (i=0; ix < SX + SXSIZE) UnmapGadget(level_editor_gadget[i]); } @@ -4336,7 +4622,7 @@ void UnmapLevelEditorGadgets() { int i; - for (i=0; idescription[i] = ei_from->description[i]; + + /* ---------- copy element properties ---------- */ + Properties[element_to][EP_BITFIELD_BASE] = + Properties[element_from][EP_BITFIELD_BASE]; + + /* ---------- copy custom property values ---------- */ + + ei_to->use_gfx_element = ei_from->use_gfx_element; + ei_to->gfx_element = ei_from->gfx_element; + + ei_to->collect_score = ei_from->collect_score; + ei_to->collect_count = ei_from->collect_count; + + ei_to->push_delay_fixed = ei_from->push_delay_fixed; + ei_to->push_delay_random = ei_from->push_delay_random; + ei_to->move_delay_fixed = ei_from->move_delay_fixed; + ei_to->move_delay_random = ei_from->move_delay_random; + + ei_to->move_pattern = ei_from->move_pattern; + ei_to->move_direction_initial = ei_from->move_direction_initial; + ei_to->move_stepsize = ei_from->move_stepsize; + + ei_to->slippery_type = ei_from->slippery_type; + + for(y=0; y<3; y++) + for(x=0; x<3; x++) + ei_to->content[x][y] = ei_from->content[x][y]; + + ei_to->num_change_pages = ei_from->num_change_pages; + setElementChangePages(ei_to, ei_to->num_change_pages); + + for (i=0; i < ei_to->num_change_pages; i++) + { + struct ElementChangeInfo *change_to = &ei_to->change_page[i]; + struct ElementChangeInfo *change_from = &ei_from->change_page[i]; + + /* always start with reliable default values */ + setElementChangeInfoToDefaults(change_to); + + change_to->events = change_from->events; + + change_to->target_element = change_from->target_element; + + change_to->delay_fixed = change_from->delay_fixed; + change_to->delay_random = change_from->delay_random; + change_to->delay_frames = change_from->delay_frames; + + change_to->trigger_element = change_from->trigger_element; + + change_to->explode = change_from->explode; + change_to->use_content = change_from->use_content; + change_to->only_complete = change_from->only_complete; + change_to->use_random_change = change_from->use_random_change; + + change_to->random = change_from->random; + change_to->power = change_from->power; + + for(y=0; y<3; y++) + for(x=0; x<3; x++) + change_to->content[x][y] = change_from->content[x][y]; + + change_to->can_change = change_from->can_change; + + change_to->sides = change_from->sides; + } + + /* mark this custom element as modified */ + ei_to->modified_settings = TRUE; +} + +static void replace_custom_element_in_settings(int element_from, + int element_to) +{ + int i, j, x, y; + + for (i=0; i < NUM_FILE_ELEMENTS; i++) + { + struct ElementInfo *ei = &element_info[i]; + + for(y=0; y<3; y++) + for(x=0; x<3; x++) + if (ei->content[x][y] == element_from) + ei->content[x][y] = element_to; + + for (j=0; j < ei->num_change_pages; j++) + { + struct ElementChangeInfo *change = &ei->change_page[j]; + + if (change->target_element == element_from) + change->target_element = element_to; + + if (change->trigger_element == element_from) + change->trigger_element = element_to; + + for(y=0; y<3; y++) + for(x=0; x<3; x++) + if (change->content[x][y] == element_from) + change->content[x][y] = element_to; + } + } +} + +static void replace_custom_element_in_playfield(int element_from, + int element_to) +{ + int x, y; + + for(x=0; x < lev_fieldx; x++) + for(y=0; y < lev_fieldy; y++) + if (Feld[x][y] == element_from) + Feld[x][y] = element_to; +} + +static void CopyCustomElement(int element_old, int element_new, int copy_mode) +{ + if (copy_mode == GADGET_ID_CUSTOM_COPY_FROM) + { + copy_custom_element_settings(element_new, element_old); + } + else if (copy_mode == GADGET_ID_CUSTOM_COPY_TO) + { + copy_custom_element_settings(element_old, element_new); + } + else if (copy_mode == GADGET_ID_CUSTOM_EXCHANGE) + { + copy_custom_element_settings(element_old, EL_DUMMY); + copy_custom_element_settings(element_new, element_old); + copy_custom_element_settings(EL_DUMMY, element_new); + + replace_custom_element_in_settings(element_old, EL_DUMMY); + replace_custom_element_in_settings(element_new, element_old); + replace_custom_element_in_settings(EL_DUMMY, element_new); + + replace_custom_element_in_playfield(element_old, EL_DUMMY); + replace_custom_element_in_playfield(element_new, element_old); + replace_custom_element_in_playfield(EL_DUMMY, element_new); + } + + UpdateCustomElementGraphicGadgets(); + DrawPropertiesWindow(); +} + +static void CopyCustomElementPropertiesToEditor(int element) +{ + int i; + int current_change_page = element_info[element].current_change_page; + + /* dynamically (re)build selectbox for selecting change page */ + for (i=0; i < element_info[element].num_change_pages; i++) + { + sprintf(options_change_page_strings[i], "%d", i + 1); options_change_page[i].value = i; options_change_page[i].text = options_change_page_strings[i]; @@ -4526,7 +4963,10 @@ static void CopyCustomElementPropertiesToEditor(int element) (HAS_CHANGE_EVENT(element, CE_TOUCHED_BY_PLAYER) ? CE_TOUCHED_BY_PLAYER : HAS_CHANGE_EVENT(element, CE_PRESSED_BY_PLAYER) ? CE_PRESSED_BY_PLAYER : HAS_CHANGE_EVENT(element, CE_PUSHED_BY_PLAYER) ? CE_PUSHED_BY_PLAYER : + HAS_CHANGE_EVENT(element, CE_ENTERED_BY_PLAYER) ? CE_ENTERED_BY_PLAYER : + HAS_CHANGE_EVENT(element, CE_LEFT_BY_PLAYER) ? CE_LEFT_BY_PLAYER : HAS_CHANGE_EVENT(element, CE_DROPPED_BY_PLAYER) ? CE_DROPPED_BY_PLAYER : + HAS_CHANGE_EVENT(element, CE_SWITCHED) ? CE_SWITCHED : HAS_CHANGE_EVENT(element, CE_COLLISION) ? CE_COLLISION : HAS_CHANGE_EVENT(element, CE_IMPACT) ? CE_IMPACT : HAS_CHANGE_EVENT(element, CE_SMASHED) ? CE_SMASHED : @@ -4534,13 +4974,16 @@ static void CopyCustomElementPropertiesToEditor(int element) /* set "change by other element action" selectbox help value */ custom_element_change.other_action = - ( - HAS_CHANGE_EVENT(element, CE_OTHER_GETS_TOUCHED) ? CE_OTHER_GETS_TOUCHED : + (HAS_CHANGE_EVENT(element, CE_OTHER_GETS_TOUCHED) ? CE_OTHER_GETS_TOUCHED : HAS_CHANGE_EVENT(element, CE_OTHER_GETS_PRESSED) ? CE_OTHER_GETS_PRESSED : HAS_CHANGE_EVENT(element, CE_OTHER_GETS_PUSHED) ? CE_OTHER_GETS_PUSHED : + HAS_CHANGE_EVENT(element, CE_OTHER_GETS_ENTERED) ? CE_OTHER_GETS_ENTERED : + HAS_CHANGE_EVENT(element, CE_OTHER_GETS_LEFT) ? CE_OTHER_GETS_LEFT : + HAS_CHANGE_EVENT(element, CE_OTHER_GETS_DIGGED) ? CE_OTHER_GETS_DIGGED : HAS_CHANGE_EVENT(element, CE_OTHER_GETS_COLLECTED) ? CE_OTHER_GETS_COLLECTED : HAS_CHANGE_EVENT(element, CE_OTHER_GETS_DROPPED) ? CE_OTHER_GETS_DROPPED : HAS_CHANGE_EVENT(element, CE_OTHER_IS_TOUCHING) ? CE_OTHER_IS_TOUCHING : + HAS_CHANGE_EVENT(element, CE_OTHER_IS_SWITCHING) ? CE_OTHER_IS_SWITCHING : HAS_CHANGE_EVENT(element, CE_OTHER_IS_CHANGING) ? CE_OTHER_IS_CHANGING : HAS_CHANGE_EVENT(element, CE_OTHER_IS_EXPLODING) ? CE_OTHER_IS_EXPLODING : custom_element_change.other_action); @@ -4638,7 +5081,10 @@ static void CopyCustomElementPropertiesToGame(int element) custom_element_change_events[CE_TOUCHED_BY_PLAYER] = FALSE; custom_element_change_events[CE_PRESSED_BY_PLAYER] = FALSE; custom_element_change_events[CE_PUSHED_BY_PLAYER] = FALSE; + custom_element_change_events[CE_ENTERED_BY_PLAYER] = FALSE; + custom_element_change_events[CE_LEFT_BY_PLAYER] = FALSE; custom_element_change_events[CE_DROPPED_BY_PLAYER] = FALSE; + custom_element_change_events[CE_SWITCHED] = FALSE; custom_element_change_events[CE_COLLISION] = FALSE; custom_element_change_events[CE_IMPACT] = FALSE; custom_element_change_events[CE_SMASHED] = FALSE; @@ -4646,14 +5092,18 @@ static void CopyCustomElementPropertiesToGame(int element) custom_element_change_events[CE_BY_DIRECT_ACTION]; /* set other element action change event from checkbox and selectbox */ - custom_element_change_events[CE_OTHER_IS_TOUCHING] = FALSE; - custom_element_change_events[CE_OTHER_IS_CHANGING] = FALSE; - custom_element_change_events[CE_OTHER_IS_EXPLODING] = FALSE; custom_element_change_events[CE_OTHER_GETS_TOUCHED] = FALSE; custom_element_change_events[CE_OTHER_GETS_PRESSED] = FALSE; custom_element_change_events[CE_OTHER_GETS_PUSHED] = FALSE; + custom_element_change_events[CE_OTHER_GETS_ENTERED] = FALSE; + custom_element_change_events[CE_OTHER_GETS_LEFT] = FALSE; + custom_element_change_events[CE_OTHER_GETS_DIGGED] = FALSE; custom_element_change_events[CE_OTHER_GETS_COLLECTED] = FALSE; custom_element_change_events[CE_OTHER_GETS_DROPPED] = FALSE; + custom_element_change_events[CE_OTHER_IS_TOUCHING] = FALSE; + custom_element_change_events[CE_OTHER_IS_SWITCHING] = FALSE; + custom_element_change_events[CE_OTHER_IS_CHANGING] = FALSE; + custom_element_change_events[CE_OTHER_IS_EXPLODING] = FALSE; custom_element_change_events[custom_element_change.other_action] = custom_element_change_events[CE_BY_OTHER_ACTION]; @@ -4920,7 +5370,9 @@ static void DrawDrawingWindow() SetMainBackgroundImage(IMG_UNDEFINED); ClearWindow(); + UnmapLevelEditorWindowGadgets(); + UnmapLevelEditorToolboxCustomGadgets(); AdjustDrawingAreaGadgets(); AdjustLevelScrollPosition(); @@ -4928,7 +5380,9 @@ static void DrawDrawingWindow() AdjustEditorScrollbar(GADGET_ID_SCROLL_VERTICAL); DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos); + MapMainDrawingArea(); + MapLevelEditorToolboxDrawingGadgets(); } static void DrawLevelInfoWindow() @@ -5030,7 +5484,7 @@ static void DrawElementContentAreas() DrawText(x, y + 2 * MINI_TILEY, "smashed", FONT_TEXT_1); } -static void DrawEnvelopeTextArea() +static void DrawEnvelopeTextArea(int envelope_nr) { int id = ED_TEXTAREA_ID_ENVELOPE_INFO; struct GadgetInfo *gi = level_editor_gadget[textarea_info[id].gadget_id]; @@ -5038,8 +5492,14 @@ static void DrawEnvelopeTextArea() UnmapGadget(gi); DrawBackground(gi->x, gi->y, gi->width, gi->height); - ModifyGadget(gi, GDI_AREA_SIZE, level.envelope_xsize, level.envelope_ysize, + if (envelope_nr != -1) + textarea_info[id].value = level.envelope_text[envelope_nr]; + + ModifyGadget(gi, GDI_AREA_SIZE, + *counterbutton_info[ED_COUNTER_ID_ENVELOPE_XSIZE].value, + *counterbutton_info[ED_COUNTER_ID_ENVELOPE_YSIZE].value, GDI_END); + MapTextAreaGadget(ED_TEXTAREA_ID_ENVELOPE_INFO); } @@ -5070,6 +5530,264 @@ char *getElementDescriptionFilename(int element) return NULL; } +#if 1 +static boolean PrintInfoText(char *text, int font_nr, int start_line) +{ + int font_height = getFontHeight(font_nr); + int pad_x = ED_SETTINGS_XPOS(0); + int pad_y = ED_SETTINGS_YPOS(0) + ED_BORDER_SIZE; + int sx = SX + pad_x; + int sy = SY + pad_y; + int max_lines_per_screen = (SYSIZE - pad_y) / font_height - 1; + + if (start_line >= max_lines_per_screen) + return FALSE; + + DrawText(sx, sy + start_line * font_height, text, font_nr); + + return TRUE; +} + +#if 1 + +static int PrintElementDescriptionFromFile(char *filename, int start_line) +{ + int font_nr = FONT_TEXT_2; + int font_width = getFontWidth(font_nr); + int font_height = getFontHeight(font_nr); + int pad_x = ED_SETTINGS_XPOS(0); + int pad_y = ED_SETTINGS_YPOS(0) + ED_BORDER_SIZE; + int sx = SX + pad_x; + int sy = SY + pad_y; + int max_chars_per_line = (SXSIZE - 2 * pad_x) / font_width; + int max_lines_per_screen = (SYSIZE - pad_y) / font_height - 1; + int current_line = start_line; + char line[MAX_LINE_LEN]; + char buffer[max_chars_per_line + 1]; + int buffer_len; + FILE *file; + + if (current_line >= max_lines_per_screen) + return 0; + + if (filename == NULL) + return 0; + + if (!(file = fopen(filename, MODE_READ))) + return 0; + + buffer[0] = '\0'; + buffer_len = 0; + + while(!feof(file) && current_line < max_lines_per_screen) + { + char *line_ptr; + boolean last_line_was_empty = TRUE; + + /* read next line of input file */ + if (!fgets(line, MAX_LINE_LEN, file)) + break; + + /* skip comments (lines directly beginning with '#') */ + if (line[0] == '#') + continue; + + /* cut trailing newline from input line */ + for (line_ptr = line; *line_ptr; line_ptr++) + { + if (*line_ptr == '\n' || *line_ptr == '\r') + { + *line_ptr = '\0'; + break; + } + } + + if (strlen(line) == 0) /* special case: force empty line */ + strcpy(line, "\n"); + + line_ptr = line; + + while (*line_ptr && current_line < max_lines_per_screen) + { + boolean buffer_filled = RenderLineToBuffer(&line_ptr, + buffer, &buffer_len, + last_line_was_empty, + max_chars_per_line); + if (buffer_filled) + { + DrawText(sx, sy + current_line * font_height, buffer, font_nr); + current_line++; + + last_line_was_empty = (buffer_len == 0); + + buffer[0] = '\0'; + buffer_len = 0; + } + } + } + + fclose(file); + + if (buffer_len > 0 && current_line < max_lines_per_screen) + { + DrawText(sx, sy + current_line * font_height, buffer, font_nr); + current_line++; + } + + return (current_line - start_line); +} + +#else + +static int PrintElementDescriptionFromFile(char *filename, int start_line) +{ + int font_nr = FONT_TEXT_2; + int font_width = getFontWidth(font_nr); + int font_height = getFontHeight(font_nr); + int pad_x = ED_SETTINGS_XPOS(0); + int pad_y = ED_SETTINGS_YPOS(0) + ED_BORDER_SIZE; + int sx = SX + pad_x; + int sy = SY + pad_y; + int max_chars_per_line = (SXSIZE - 2 * pad_x) / font_width; + int max_lines_per_screen = (SYSIZE - pad_y) / font_height - 1; + int current_line = start_line; + char line[MAX_LINE_LEN]; + char buffer[max_chars_per_line + 1]; + int buffer_len; + FILE *file; + + if (filename == NULL) + return 0; + + if (!(file = fopen(filename, MODE_READ))) + return 0; + + buffer[0] = '\0'; + buffer_len = 0; + + while(!feof(file)) + { + char *line_ptr, *word_ptr; + boolean last_line_was_empty = TRUE; + + /* read next line of input file */ + if (!fgets(line, MAX_LINE_LEN, file)) + break; + + /* skip comments (lines directly beginning with '#') */ + if (line[0] == '#') + continue; + + /* cut trailing newline from input line */ + for (line_ptr = line; *line_ptr; line_ptr++) + { + if (*line_ptr == '\n' || *line_ptr == '\r') + { + *line_ptr = '\0'; + break; + } + } + + if (strlen(line) == 0) /* special case: force empty line */ + strcpy(line, "\n"); + + word_ptr = line; + + while (*word_ptr) + { + boolean print_buffer = FALSE; + int word_len; + + /* skip leading whitespaces */ + while (*word_ptr == ' ' || *word_ptr == '\t') + word_ptr++; + + line_ptr = word_ptr; + word_len = 0; + + /* look for end of next word */ + while (*line_ptr != ' ' && *line_ptr != '\t' && *line_ptr != '\0') + { + line_ptr++; + word_len++; + } + + if (word_len == 0) + { + continue; + } + else if (*word_ptr == '\n') /* special case: force empty line */ + { + if (buffer_len == 0) + word_ptr++; + + /* prevent printing of multiple empty lines */ + if (buffer_len > 0 || !last_line_was_empty) + print_buffer = TRUE; + } + else if (word_len < max_chars_per_line - buffer_len) + { + /* word fits into text buffer -- add word */ + + if (buffer_len > 0) + buffer[buffer_len++] = ' '; + + strncpy(&buffer[buffer_len], word_ptr, word_len); + buffer_len += word_len; + buffer[buffer_len] = '\0'; + word_ptr += word_len; + } + else if (buffer_len > 0) + { + /* not enough space left for word in text buffer -- print buffer */ + + print_buffer = TRUE; + } + else + { + /* word does not fit at all into empty text buffer -- cut word */ + + strncpy(buffer, word_ptr, max_chars_per_line); + buffer[max_chars_per_line] = '\0'; + word_ptr += max_chars_per_line; + print_buffer = TRUE; + } + + if (print_buffer) + { + if (current_line >= max_lines_per_screen) + { + fclose(file); + + return (current_line - start_line); + } + + DrawText(sx, sy + current_line * font_height, buffer, font_nr); + current_line++; + + last_line_was_empty = (buffer_len == 0); + + buffer[0] = '\0'; + buffer_len = 0; + print_buffer = FALSE; + } + } + } + + fclose(file); + + if (buffer_len > 0 && current_line < max_lines_per_screen) + { + DrawText(sx, sy + current_line * font_height, buffer, font_nr); + current_line++; + } + + return (current_line - start_line); +} +#endif + +#else + static boolean PrintInfoText(char *text, int font_nr, int screen_line) { int font_height = getFontHeight(font_nr); @@ -5136,6 +5854,10 @@ static int PrintElementDescriptionFromFile(char *filename, int screen_line) word_ptr = line; +#if 0 + printf("::: got line '%s'...\n", line); +#endif + while (*word_ptr) { boolean print_buffer = FALSE; @@ -5198,8 +5920,16 @@ static int PrintElementDescriptionFromFile(char *filename, int screen_line) if (print_buffer) { +#if 0 + printf("::: printing '%s'...\n", buffer); +#endif + if (!PrintInfoText(buffer, font_nr, screen_line + lines_printed)) + { + fclose(file); + return lines_printed; + } last_line_was_empty = (buffer_len == 0); lines_printed++; @@ -5219,6 +5949,7 @@ static int PrintElementDescriptionFromFile(char *filename, int screen_line) return lines_printed; } +#endif static void DrawPropertiesTabulatorGadgets() { @@ -5298,7 +6029,7 @@ static void DrawPropertiesInfo() { EP_DONT_COLLIDE_WITH, "- deadly when colliding with" }, { EP_DONT_TOUCH, "- deadly when touching" }, - { EP_INDESTRUCTIBLE, "- undestructible" }, + { EP_INDESTRUCTIBLE, "- indestructible" }, { EP_CAN_EXPLODE_BY_FIRE, "- can explode by fire or explosions" }, { EP_CAN_EXPLODE_SMASHED, "- can explode when smashed" }, @@ -5327,6 +6058,15 @@ static void DrawPropertiesInfo() int screen_line = 0; int i, x, y; +#if DEBUG + if (IS_CUSTOM_ELEMENT(properties_element)) + { + DrawTextF(pad_x, pad_y + screen_line++ * font2_height, FONT_TEXT_3, + "[Custom Element %d]", properties_element - EL_CUSTOM_START + 1); + screen_line++; + } +#endif + /* ----- print number of elements / percentage of this element in level */ num_elements_in_level = 0; @@ -5336,7 +6076,7 @@ static void DrawPropertiesInfo() num_elements_in_level++; percentage = num_elements_in_level * 100.0 / (lev_fieldx * lev_fieldy); - DrawTextF(pad_x, pad_y + screen_line * font2_height, font1_nr, + DrawTextS(pad_x, pad_y + screen_line * font2_height, font1_nr, percentage_text); DrawTextF(pad_x + strlen(percentage_text) * font1_width, pad_y + screen_line++ * font2_height, font2_nr, @@ -5346,7 +6086,7 @@ static void DrawPropertiesInfo() /* ----- print standard properties of this element */ - DrawTextF(pad_x, pad_y + screen_line++ * font2_height, font1_nr, + DrawTextS(pad_x, pad_y + screen_line++ * font2_height, font1_nr, properties_text); for (i=0; properties[i].value != -1; i++) @@ -5354,13 +6094,13 @@ static void DrawPropertiesInfo() if (!HAS_PROPERTY(properties_element, properties[i].value)) continue; - DrawTextF(pad_x, pad_y + screen_line++ * font2_height, font2_nr, + DrawTextS(pad_x, pad_y + screen_line++ * font2_height, font2_nr, properties[i].text); num_standard_properties++; } if (num_standard_properties == 0) - DrawTextF(pad_x + strlen(properties_text) * font1_width, + DrawTextS(pad_x + strlen(properties_text) * font1_width, pad_y + (screen_line - 1) * font2_height, font2_nr, "none"); screen_line++; @@ -5431,10 +6171,17 @@ static struct { EL_KEY_2, &level.score[SC_KEY], TEXT_COLLECTING }, { EL_KEY_3, &level.score[SC_KEY], TEXT_COLLECTING }, { EL_KEY_4, &level.score[SC_KEY], TEXT_COLLECTING }, +#if 1 + { EL_EM_KEY_1, &level.score[SC_KEY], TEXT_COLLECTING }, + { EL_EM_KEY_2, &level.score[SC_KEY], TEXT_COLLECTING }, + { EL_EM_KEY_3, &level.score[SC_KEY], TEXT_COLLECTING }, + { EL_EM_KEY_4, &level.score[SC_KEY], TEXT_COLLECTING }, +#else { EL_EM_KEY_1_FILE, &level.score[SC_KEY], TEXT_COLLECTING }, { EL_EM_KEY_2_FILE, &level.score[SC_KEY], TEXT_COLLECTING }, { EL_EM_KEY_3_FILE, &level.score[SC_KEY], TEXT_COLLECTING }, { EL_EM_KEY_4_FILE, &level.score[SC_KEY], TEXT_COLLECTING }, +#endif { EL_AMOEBA_WET, &level.amoeba_speed, TEXT_SPEED }, { EL_AMOEBA_DRY, &level.amoeba_speed, TEXT_SPEED }, { EL_AMOEBA_FULL, &level.amoeba_speed, TEXT_SPEED }, @@ -5450,8 +6197,8 @@ static boolean checkPropertiesConfig() if (IS_GEM(properties_element) || IS_CUSTOM_ELEMENT(properties_element) || - HAS_CONTENT(properties_element) || - properties_element == EL_ENVELOPE) + IS_ENVELOPE(properties_element) || + HAS_CONTENT(properties_element)) return TRUE; else for (i=0; elements_with_counter[i].element != -1; i++) @@ -5503,13 +6250,20 @@ static void DrawPropertiesConfig() if (IS_GEM(properties_element)) MapCheckbuttonGadget(ED_CHECKBUTTON_ID_EM_SLIPPERY_GEMS); - if (properties_element == EL_ENVELOPE) + if (IS_ENVELOPE(properties_element)) { + int counter1_id = ED_COUNTER_ID_ENVELOPE_XSIZE; + int counter2_id = ED_COUNTER_ID_ENVELOPE_YSIZE; + int envelope_nr = properties_element - EL_ENVELOPE_1; + + counterbutton_info[counter1_id].value = &level.envelope_xsize[envelope_nr]; + counterbutton_info[counter2_id].value = &level.envelope_ysize[envelope_nr]; + /* display counter to choose size of envelope text area */ MapCounterButtons(ED_COUNTER_ID_ENVELOPE_XSIZE); MapCounterButtons(ED_COUNTER_ID_ENVELOPE_YSIZE); - DrawEnvelopeTextArea(); + DrawEnvelopeTextArea(envelope_nr); } if (IS_CUSTOM_ELEMENT(properties_element)) @@ -5597,7 +6351,7 @@ static void DrawElementName(int x, int y, int element) char buffer[max_chars_per_line + 1]; if (strlen(element_name) <= max_chars_per_line) - DrawTextF(x, y, font_nr, element_name); + DrawTextS(x, y, font_nr, element_name); else { int next_pos = max_chars_per_line; @@ -5622,12 +6376,12 @@ static void DrawElementName(int x, int y, int element) } } - DrawTextF(x, y - font_height / 2, font_nr, buffer); + DrawTextS(x, y - font_height / 2, font_nr, buffer); strncpy(buffer, &element_name[next_pos], max_chars_per_line); buffer[max_chars_per_line] = '\0'; - DrawTextF(x, y + font_height / 2, font_nr, buffer); + DrawTextS(x, y + font_height / 2, font_nr, buffer); } } @@ -5647,6 +6401,11 @@ static void DrawPropertiesWindow() CopyCustomElementPropertiesToEditor(properties_element); UnmapLevelEditorWindowGadgets(); + UnmapLevelEditorToolboxDrawingGadgets(); + UnmapLevelEditorToolboxCustomGadgets(); + + if (IS_CUSTOM_ELEMENT(properties_element)) + MapLevelEditorToolboxCustomGadgets(); SetMainBackgroundImage(IMG_BACKGROUND_EDITOR); ClearWindow(); @@ -6625,7 +7384,7 @@ static void HandleCounterButtons(struct GadgetInfo *gi) case ED_COUNTER_ID_ENVELOPE_XSIZE: case ED_COUNTER_ID_ENVELOPE_YSIZE: - DrawEnvelopeTextArea(); + DrawEnvelopeTextArea(-1); break; case ED_COUNTER_ID_LEVEL_XSIZE: @@ -6813,6 +7572,9 @@ static void HandleCheckbuttons(struct GadgetInfo *gi) static void HandleControlButtons(struct GadgetInfo *gi) { + static int last_level_drawing_function = GADGET_ID_SINGLE_ITEMS; + static int last_edit_mode = ED_MODE_DRAWING; + static int last_custom_copy_mode = -1; int id = gi->custom_id; int button = gi->event.button; int step = BUTTON_STEPSIZE(button); @@ -6822,8 +7584,11 @@ static void HandleControlButtons(struct GadgetInfo *gi) if (edit_mode == ED_MODE_DRAWING && drawing_function == GADGET_ID_TEXT) DrawLevelText(0, 0, 0, TEXT_END); - if (id < ED_NUM_CTRL1_BUTTONS && id != GADGET_ID_PROPERTIES && - id != GADGET_ID_PICK_ELEMENT && edit_mode != ED_MODE_DRAWING && + if (id < ED_NUM_CTRL1_BUTTONS && + id != GADGET_ID_SINGLE_ITEMS && + id != GADGET_ID_PROPERTIES && + id != GADGET_ID_PICK_ELEMENT && + edit_mode != ED_MODE_DRAWING && drawing_function != GADGET_ID_PICK_ELEMENT && !(GetKeyModState() & KMOD_Control)) { @@ -6985,14 +7750,28 @@ static void HandleControlButtons(struct GadgetInfo *gi) properties_element = new_element; DrawPropertiesWindow(); edit_mode = ED_MODE_PROPERTIES; + + last_level_drawing_function = drawing_function; + ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS], + MB_LEFTBUTTON); } else { DrawDrawingWindow(); edit_mode = ED_MODE_DRAWING; + + ClickOnGadget(level_editor_gadget[last_level_drawing_function], + MB_LEFTBUTTON); } break; + case GADGET_ID_CUSTOM_COPY_FROM: + case GADGET_ID_CUSTOM_COPY_TO: + case GADGET_ID_CUSTOM_EXCHANGE: + last_custom_copy_mode = id; + last_drawing_function = drawing_function; + break; + case GADGET_ID_UNDO: if (undo_buffer_steps == 0) { @@ -7019,13 +7798,16 @@ static void HandleControlButtons(struct GadgetInfo *gi) case GADGET_ID_INFO: if (edit_mode != ED_MODE_INFO) { - DrawLevelInfoWindow(); + last_edit_mode = edit_mode; edit_mode = ED_MODE_INFO; + + DrawLevelInfoWindow(); } else { - DrawDrawingWindow(); - edit_mode = ED_MODE_DRAWING; + edit_mode = last_edit_mode; + + DrawEditModeWindow(); } break; @@ -7109,6 +7891,19 @@ static void HandleControlButtons(struct GadgetInfo *gi) int element_position = id - GADGET_ID_ELEMENTLIST_FIRST; int new_element = editor_elements[element_position + element_shift]; + if (last_custom_copy_mode != -1) + { + CopyCustomElement(properties_element, new_element, + last_custom_copy_mode); + + ClickOnGadget(level_editor_gadget[last_drawing_function], + MB_LEFTBUTTON); + + last_custom_copy_mode = -1; + + break; + } + PickDrawingElement(button, new_element); if (!stick_element_properties_window && @@ -7444,25 +8239,25 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi) else { if (id == GADGET_ID_AMOEBA_CONTENT) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, + DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "Amoeba content"); else if (id == GADGET_ID_CUSTOM_GRAPHIC) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, + DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "Custom graphic element"); else if (id == GADGET_ID_CUSTOM_CONTENT) DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "Custom element content position: %d, %d", sx, sy); else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, + DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "New element after change"); else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, + DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "New extended elements after change"); else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, + DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "Other element triggering change"); else if (id == GADGET_ID_RANDOM_BACKGROUND) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, + DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "Random placement background"); else if (id >= GADGET_ID_ELEMENT_CONTENT_0 && id <= GADGET_ID_ELEMENT_CONTENT_7) @@ -7479,10 +8274,12 @@ void RequestExitLevelEditor(boolean ask_if_level_has_changed) Request("Level has changed! Exit without saving ?", REQ_ASK | REQ_STAY_OPEN)) { +#if 1 CloseDoor(DOOR_CLOSE_1); - /* + SetDoorState(DOOR_CLOSE_2); +#else CloseDoor(DOOR_CLOSE_ALL); - */ +#endif game_status = GAME_MODE_MAIN; DrawMainMenu(); }