X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Feditor.c;h=c5eb3e09d49eee142e7fdf9c0cb835f3c98b7b47;hb=f857fec3082c785b0dd271b6ad1b7642a2ed4e65;hp=1951d1f47bce14d94be2a9a2ab83d05267444ec5;hpb=514321a85f7dda02848a3ce78667329f9c891156;p=rocksndiamonds.git diff --git a/src/editor.c b/src/editor.c index 1951d1f4..c5eb3e09 100644 --- a/src/editor.c +++ b/src/editor.c @@ -22,6 +22,13 @@ #include "game.h" #include "tape.h" + +/* + ----------------------------------------------------------------------------- + screen and artwork graphic pixel position definitions + ----------------------------------------------------------------------------- +*/ + /* positions in the level editor */ #define ED_WIN_MB_LEFT_XPOS 6 #define ED_WIN_MB_LEFT_YPOS 258 @@ -30,25 +37,6 @@ #define ED_WIN_MB_RIGHT_XPOS 78 #define ED_WIN_MB_RIGHT_YPOS ED_WIN_MB_LEFT_YPOS -/* other constants for the editor */ -#define ED_SCROLL_NO 0 -#define ED_SCROLL_LEFT 1 -#define ED_SCROLL_RIGHT 2 -#define ED_SCROLL_UP 4 -#define ED_SCROLL_DOWN 8 - -/* screens in the level editor */ -#define ED_MODE_DRAWING 0 -#define ED_MODE_INFO 1 -#define ED_MODE_PROPERTIES 2 - -/* how many steps can be cancelled */ -#define NUM_UNDO_STEPS (10 + 1) - -/* values for elements with score */ -#define MIN_SCORE 0 -#define MAX_SCORE 255 - /* values for the control window */ #define ED_CTRL_BUTTONS_GFX_YPOS 236 #define ED_CTRL_BUTTONS_ALT_GFX_YPOS 142 @@ -102,6 +90,7 @@ /* standard distances */ #define ED_BORDER_SIZE 3 +#define ED_BORDER2_SIZE 5 #define ED_GADGET_DISTANCE 2 /* values for element content drawing areas */ @@ -204,12 +193,31 @@ #define ED_BUTTON_PLUS_YSIZE ED_BUTTON_COUNT_YSIZE #define ED_SELECTBOX_XPOS ED_WIN_COUNT_XPOS -#define ED_SELECTBOX_YPOS (ED_WIN_COUNT_YPOS + 2 + \ - ED_WIN_COUNT_YSIZE) +#define ED_SELECTBOX_YPOS (ED_WIN_COUNT_YPOS + \ + 2 + ED_WIN_COUNT_YSIZE) #define ED_SELECTBOX_XSIZE ED_WIN_COUNT_XSIZE #define ED_SELECTBOX_YSIZE ED_WIN_COUNT_YSIZE -/* editor gadget identifiers */ +#define ED_TEXTBUTTON_XPOS ED_WIN_COUNT_XPOS +#define ED_TEXTBUTTON_YPOS (ED_WIN_COUNT_YPOS + \ + 2 * (2 + ED_WIN_COUNT_YSIZE)) +#define ED_TEXTBUTTON_INACTIVE_YPOS (ED_WIN_COUNT_YPOS + \ + 3 * (2 + ED_WIN_COUNT_YSIZE)) +#define ED_TEXTBUTTON_XSIZE ED_WIN_COUNT_XSIZE +#define ED_TEXTBUTTON_YSIZE ED_WIN_COUNT_YSIZE + +/* values for ClearEditorGadgetInfoText() and HandleGadgetInfoText() */ +#define INFOTEXT_XPOS SX +#define INFOTEXT_YPOS (SY + SYSIZE - MINI_TILEX + 2) +#define INFOTEXT_XSIZE SXSIZE +#define INFOTEXT_YSIZE MINI_TILEX + + +/* + ----------------------------------------------------------------------------- + editor gadget definitions + ----------------------------------------------------------------------------- +*/ /* drawing toolbox buttons */ #define GADGET_ID_NONE -1 @@ -294,10 +302,17 @@ /* selectbox identifiers */ #define GADGET_ID_SELECTBOX_FIRST (GADGET_ID_TEXT_INPUT_FIRST + 2) -#define GADGET_ID_SELECTBOX_TEST (GADGET_ID_SELECTBOX_FIRST + 0) +#define GADGET_ID_CUSTOM_CHANGE_CAUSE (GADGET_ID_SELECTBOX_FIRST + 0) + +/* textbutton identifiers */ +#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 1) + +#define GADGET_ID_PROPERTIES_INFO (GADGET_ID_TEXTBUTTON_FIRST + 0) +#define GADGET_ID_PROPERTIES_CONFIG (GADGET_ID_TEXTBUTTON_FIRST + 1) +#define GADGET_ID_PROPERTIES_ADVANCED (GADGET_ID_TEXTBUTTON_FIRST + 2) /* gadgets for scrolling of drawing area */ -#define GADGET_ID_SCROLLING_FIRST (GADGET_ID_SELECTBOX_FIRST + 1) +#define GADGET_ID_SCROLLING_FIRST (GADGET_ID_TEXTBUTTON_FIRST + 3) #define GADGET_ID_SCROLL_UP (GADGET_ID_SCROLLING_FIRST + 0) #define GADGET_ID_SCROLL_DOWN (GADGET_ID_SCROLLING_FIRST + 1) @@ -390,9 +405,16 @@ #define ED_TEXTINPUT_ID_LEVEL_LAST ED_TEXTINPUT_ID_LEVEL_AUTHOR /* values for selectbox gadgets */ -#define ED_SELECTBOX_ID_TEST 0 +#define ED_SELECTBOX_ID_CUSTOM_CHANGE_CAUSE 0 + +#define ED_NUM_SELECTBOX 1 + +/* values for textbutton gadgets */ +#define ED_TEXTBUTTON_ID_PROPERTIES_INFO 0 +#define ED_TEXTBUTTON_ID_PROPERTIES_CONFIG 1 +#define ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED 2 -#define ED_NUM_SELECTBOX 1 +#define ED_NUM_TEXTBUTTON 3 /* values for checkbutton gadgets */ #define ED_CHECKBUTTON_ID_DOUBLE_SPEED 0 @@ -423,15 +445,55 @@ #define ED_RADIOBUTTON_ID_LEVEL_FIRST ED_RADIOBUTTON_ID_PERCENTAGE #define ED_RADIOBUTTON_ID_LEVEL_LAST ED_RADIOBUTTON_ID_QUANTITY + +/* + ----------------------------------------------------------------------------- + some internally used definitions + ----------------------------------------------------------------------------- +*/ + /* values for CopyLevelToUndoBuffer() */ #define UNDO_IMMEDIATE 0 #define UNDO_ACCUMULATE 1 -/* values for ClearEditorGadgetInfoText() and HandleGadgetInfoText() */ -#define INFOTEXT_XPOS SX -#define INFOTEXT_YPOS (SY + SYSIZE - MINI_TILEX + 2) -#define INFOTEXT_XSIZE SXSIZE -#define INFOTEXT_YSIZE MINI_TILEX +/* values for scrollbars */ +#define ED_SCROLL_NO 0 +#define ED_SCROLL_LEFT 1 +#define ED_SCROLL_RIGHT 2 +#define ED_SCROLL_UP 4 +#define ED_SCROLL_DOWN 8 + +/* screens in the level editor */ +#define ED_MODE_DRAWING 0 +#define ED_MODE_INFO 1 +#define ED_MODE_PROPERTIES 2 + +/* sub-screens in the element properties section */ +#define ED_MODE_PROPERTIES_INFO ED_TEXTBUTTON_ID_PROPERTIES_INFO +#define ED_MODE_PROPERTIES_CONFIG ED_TEXTBUTTON_ID_PROPERTIES_CONFIG +#define ED_MODE_PROPERTIES_ADVANCED ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED + +/* how many steps can be cancelled */ +#define NUM_UNDO_STEPS (10 + 1) + +/* values for elements with score */ +#define MIN_SCORE 0 +#define MAX_SCORE 255 + +/* values for random placement */ +#define RANDOM_USE_PERCENTAGE 0 +#define RANDOM_USE_QUANTITY 1 + +/* maximal size of level editor drawing area */ +#define MAX_ED_FIELDX (2 * SCR_FIELDX) +#define MAX_ED_FIELDY (2 * SCR_FIELDY - 1) + + +/* + ----------------------------------------------------------------------------- + some internally used data structure definitions + ----------------------------------------------------------------------------- +*/ static struct { @@ -463,24 +525,12 @@ static struct { 'E', "exit level editor" } }; -/* values for random placement */ -#define RANDOM_USE_PERCENTAGE 0 -#define RANDOM_USE_QUANTITY 1 - static int random_placement_value = 10; static int random_placement_method = RANDOM_USE_QUANTITY; static int random_placement_background_element = EL_SAND; static boolean random_placement_background_restricted = FALSE; static boolean stick_element_properties_window = FALSE; - -static struct -{ - boolean indestructible; - boolean can_fall; - boolean can_smash; - boolean pushable; - boolean slippery; -} custom_element_properties[NUM_CUSTOM_ELEMENTS]; +static boolean custom_element_properties[NUM_ELEMENT_PROPERTIES]; static struct { @@ -545,7 +595,7 @@ static struct 0, 255, GADGET_ID_LEVEL_TIMESCORE_DOWN, GADGET_ID_LEVEL_TIMESCORE_UP, GADGET_ID_LEVEL_TIMESCORE_TEXT, - &level.score[SC_ZEITBONUS], + &level.score[SC_TIME_BONUS], "score for each 10 seconds left", NULL }, { @@ -591,35 +641,65 @@ static struct } }; -static char *test_values[] = +static struct ValueTextInfo options_change_cause[] = { - "test 1", - "test 2", - "dieser test-text ist viel zu lang fuer die selectbox", - "letzter text", - NULL + { 1, "specified delay" }, + { 2, "impact (active)" }, + { 3, "impact (passive)" }, + { 4, "touched by player" }, + { 5, "pressed by player" }, + { -1, NULL } }; -static int test_index = 0; +static int index_change_cause = 0; static struct { int x, y; int gadget_id; int size; - char **values; + struct ValueTextInfo *options; int *index; char *text, *infotext; } selectbox_info[ED_NUM_SELECTBOX] = { { ED_SETTINGS_XPOS, ED_COUNTER_YPOS(3), - GADGET_ID_SELECTBOX_TEST, - MAX_PLAYER_NAME_LEN, - test_values, &test_index, + GADGET_ID_CUSTOM_CHANGE_CAUSE, + 17, + options_change_cause, &index_change_cause, "test:", "test-selectbox entry" }, }; +static struct +{ + int x, y; + int gadget_id; + int size; + char *value; + char *infotext; +} textbutton_info[ED_NUM_TEXTBUTTON] = +{ + { + ED_SETTINGS_XPOS, ED_COUNTER_YPOS(1), + GADGET_ID_PROPERTIES_INFO, + 11, "Information", + "Show information about element" + }, + { + ED_SETTINGS_XPOS + 166, ED_COUNTER_YPOS(1), + GADGET_ID_PROPERTIES_CONFIG, + 11, "Configure", + "Configure element properties" + }, + { + ED_SETTINGS_XPOS + 332, ED_COUNTER_YPOS(1), + GADGET_ID_PROPERTIES_ADVANCED, + 11, "Advanced", + "Advanced element configuration" + }, +}; + static struct { int xpos, ypos; @@ -769,38 +849,41 @@ static struct { ED_SETTINGS_XPOS, ED_COUNTER_YPOS2(10), GADGET_ID_CUSTOM_INDESTRUCTIBLE, - &custom_element_properties[0].indestructible, + &custom_element_properties[EP_INDESTRUCTIBLE], "indestructible", "element cannot be destroyed" }, { ED_SETTINGS_XPOS, ED_COUNTER_YPOS2(11), GADGET_ID_CUSTOM_CAN_FALL, - &custom_element_properties[0].can_fall, + &custom_element_properties[EP_CAN_FALL], "can fall", "element can fall down" }, { ED_SETTINGS_XPOS, ED_COUNTER_YPOS2(12), GADGET_ID_CUSTOM_CAN_SMASH, - &custom_element_properties[0].can_smash, + &custom_element_properties[EP_CAN_SMASH], "can smash", "element can smash other elements" }, { ED_SETTINGS_XPOS, ED_COUNTER_YPOS2(13), GADGET_ID_CUSTOM_PUSHABLE, - &custom_element_properties[0].pushable, + &custom_element_properties[EP_PUSHABLE], "pushable", "element can be pushed" }, { ED_SETTINGS_XPOS, ED_COUNTER_YPOS2(14), GADGET_ID_CUSTOM_SLIPPERY, - &custom_element_properties[0].slippery, + &custom_element_properties[EP_SLIPPERY], "slippery", "other elements can fall down from it" } }; -/* maximal size of level editor drawing area */ -#define MAX_ED_FIELDX (2 * SCR_FIELDX) -#define MAX_ED_FIELDY (2 * SCR_FIELDY - 1) + +/* + ----------------------------------------------------------------------------- + some internally used variables + ----------------------------------------------------------------------------- +*/ /* actual size of level editor drawing area */ static int ed_fieldx = MAX_ED_FIELDX - 1, ed_fieldy = MAX_ED_FIELDY - 1; @@ -831,6 +914,7 @@ static void HandleDrawingAreas(struct GadgetInfo *); static void HandleCounterButtons(struct GadgetInfo *); static void HandleTextInputGadgets(struct GadgetInfo *); static void HandleSelectboxGadgets(struct GadgetInfo *); +static void HandleTextbuttonGadgets(struct GadgetInfo *); static void HandleRadiobuttons(struct GadgetInfo *); static void HandleCheckbuttons(struct GadgetInfo *); static void HandleControlButtons(struct GadgetInfo *); @@ -850,6 +934,7 @@ static int undo_buffer_position = 0; static int undo_buffer_steps = 0; static int edit_mode; +static int edit_mode_properties; static int element_shift = 0; @@ -1624,6 +1709,13 @@ editor_elements_info[] = NULL } }; + +/* + ----------------------------------------------------------------------------- + functions + ----------------------------------------------------------------------------- +*/ + static void ReinitializeElementList() { int pos = 0; @@ -1684,7 +1776,7 @@ static void ReinitializeElementListButtons() static int getCounterGadgetWidth() { - return (DXSIZE + getFontWidth(FONT_INPUT) - 2 * ED_GADGET_DISTANCE); + return (DXSIZE + getFontWidth(FONT_INPUT_1) - 2 * ED_GADGET_DISTANCE); } static int getMaxInfoTextLength() @@ -2036,7 +2128,8 @@ static void CreateCounterButtons() if (j == 0) { - int font_type = FONT_INPUT; + int font_type = FONT_INPUT_1; + int font_type_active = FONT_INPUT_1_ACTIVE; int gd_width = ED_WIN_COUNT_XSIZE; id = counterbutton_info[i].gadget_id_text; @@ -2045,6 +2138,7 @@ static void CreateCounterButtons() if (i == ED_COUNTER_ID_SELECT_LEVEL) { font_type = FONT_LEVEL_NUMBER; + font_type_active = FONT_LEVEL_NUMBER; xpos += 2 * ED_GADGET_DISTANCE; ypos -= ED_GADGET_DISTANCE; @@ -2070,10 +2164,11 @@ static void CreateCounterButtons() GDI_NUMBER_MAX, counterbutton_info[i].max_value, GDI_TEXT_SIZE, 3, GDI_TEXT_FONT, font_type, + GDI_TEXT_FONT_ACTIVE, font_type_active, GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x, gd_y, GDI_DESIGN_PRESSED, gd_bitmap, gd_x, gd_y, - GDI_BORDER_SIZE, ED_BORDER_SIZE, - GDI_TEXTINPUT_DESIGN_WIDTH, gd_width, + GDI_BORDER_SIZE, ED_BORDER_SIZE, ED_BORDER_SIZE, + GDI_DESIGN_WIDTH, gd_width, GDI_EVENT_MASK, event_mask, GDI_CALLBACK_INFO, HandleEditorGadgetInfoText, GDI_CALLBACK_ACTION, HandleCounterButtons, @@ -2233,11 +2328,12 @@ static void CreateTextInputGadgets() GDI_TYPE, GD_TYPE_TEXTINPUT_ALPHANUMERIC, GDI_TEXT_VALUE, textinput_info[i].value, GDI_TEXT_SIZE, textinput_info[i].size, - GDI_TEXT_FONT, FONT_INPUT, + GDI_TEXT_FONT, FONT_INPUT_1, + GDI_TEXT_FONT_ACTIVE, FONT_INPUT_1_ACTIVE, GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x, gd_y, GDI_DESIGN_PRESSED, gd_bitmap, gd_x, gd_y, - GDI_BORDER_SIZE, ED_BORDER_SIZE, - GDI_TEXTINPUT_DESIGN_WIDTH, ED_WIN_COUNT_XSIZE, + GDI_BORDER_SIZE, ED_BORDER_SIZE, ED_BORDER_SIZE, + GDI_DESIGN_WIDTH, ED_WIN_COUNT_XSIZE, GDI_EVENT_MASK, event_mask, GDI_CALLBACK_INFO, HandleEditorGadgetInfoText, GDI_CALLBACK_ACTION, HandleTextInputGadgets, @@ -2279,15 +2375,16 @@ static void CreateSelectboxGadgets() GDI_X, SX + selectbox_info[i].x, GDI_Y, SY + selectbox_info[i].y, GDI_TYPE, GD_TYPE_SELECTBOX, - GDI_SELECTBOX_VALUES, selectbox_info[i].values, + GDI_SELECTBOX_OPTIONS, selectbox_info[i].options, GDI_SELECTBOX_INDEX, selectbox_info[i].index, GDI_TEXT_SIZE, selectbox_info[i].size, - GDI_TEXT_FONT, FONT_INPUT, + GDI_TEXT_FONT, FONT_INPUT_1, + GDI_TEXT_FONT_ACTIVE, FONT_INPUT_1_ACTIVE, GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x, gd_y, GDI_DESIGN_PRESSED, gd_bitmap, gd_x, gd_y, - GDI_BORDER_SIZE, ED_BORDER_SIZE, - GDI_BORDER_SIZE_SELECTBUTTON, getFontHeight(FONT_INPUT), - GDI_TEXTINPUT_DESIGN_WIDTH, ED_WIN_COUNT_XSIZE, + GDI_BORDER_SIZE, ED_BORDER_SIZE, ED_BORDER_SIZE, + GDI_BORDER_SIZE_SELECTBUTTON, getFontWidth(FONT_INPUT_1), + GDI_DESIGN_WIDTH, ED_WIN_COUNT_XSIZE, GDI_EVENT_MASK, event_mask, GDI_CALLBACK_INFO, HandleEditorGadgetInfoText, GDI_CALLBACK_ACTION, HandleSelectboxGadgets, @@ -2300,6 +2397,58 @@ static void CreateSelectboxGadgets() } } +static void CreateTextbuttonGadgets() +{ + int max_infotext_len = getMaxInfoTextLength(); + int i; + + for (i=0; i= max_lines_per_screen) + return FALSE; - DrawTextF(x, y, FONT_TEXT_1, checkbutton_info[i].text); - ModifyGadget(level_editor_gadget[checkbutton_info[i].gadget_id], - GDI_CHECKED, *checkbutton_info[i].value, GDI_END); - MapCheckbuttonGadget(i); + DrawText(sx, sy + screen_line * font_height, text, font_nr); - /* draw checkbutton gadget */ - i = ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY; - x = checkbutton_info[i].x + xoffset_right2; - y = checkbutton_info[i].y + yoffset_right2; + return TRUE; +} - checkbutton_info[i].value = &custom_element_properties[nr].slippery; +static int PrintElementDescriptionFromFile(char *filename, int screen_line) +{ + int font_nr = FONT_TEXT_2; + int font_width = getFontWidth(font_nr); + int pad_x = ED_SETTINGS_XPOS; + int max_chars_per_line = (SXSIZE - 2 * pad_x) / font_width; + char line[MAX_LINE_LEN]; + char buffer[max_chars_per_line + 1]; + int buffer_len; + int lines_printed = 0; + 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; - DrawTextF(x, y, FONT_TEXT_1, checkbutton_info[i].text); - ModifyGadget(level_editor_gadget[checkbutton_info[i].gadget_id], - GDI_CHECKED, *checkbutton_info[i].value, GDI_END); - MapCheckbuttonGadget(i); + /* read next line of input file */ + if (!fgets(line, MAX_LINE_LEN, file)) + break; - /* draw selectbox gadget */ - i = ED_SELECTBOX_ID_TEST; - x = selectbox_info[i].x + xoffset_right2; - y = selectbox_info[i].y + yoffset_right2; + /* skip comments (lines directly beginning with '#') */ + if (line[0] == '#') + continue; - selectbox_info[i].index = &test_index; + /* 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; + } + } - DrawTextF(x, y, FONT_TEXT_1, selectbox_info[i].text); - ModifyGadget(level_editor_gadget[selectbox_info[i].gadget_id], - GDI_SELECTBOX_INDEX, *selectbox_info[i].index, GDI_END); - MapSelectboxGadget(i); + 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 (!PrintInfoText(buffer, font_nr, screen_line + lines_printed)) + return lines_printed; + + last_line_was_empty = (buffer_len == 0); + lines_printed++; + + buffer[0] = '\0'; + buffer_len = 0; + print_buffer = FALSE; + } + } + } + + fclose(file); + + if (buffer_len > 0) + if (PrintInfoText(buffer, font_nr, screen_line + lines_printed)) + lines_printed++; + + return lines_printed; +} + +static void DrawPropertiesTabulatorGadgets() +{ + struct GadgetInfo *gd_gi = level_editor_gadget[GADGET_ID_PROPERTIES_INFO]; + struct GadgetDesign *gd = &gd_gi->alt_design[GD_BUTTON_UNPRESSED]; + int gd_x = gd->x + gd_gi->border.width / 2; + int gd_y = gd->y + gd_gi->height - 1; + Pixel tab_color = GetPixel(gd->bitmap, gd_x, gd_y); + int id_first = ED_TEXTBUTTON_ID_PROPERTIES_INFO; + int id_last = ED_TEXTBUTTON_ID_PROPERTIES_INFO; + int i; + + /* draw additional "configure" tabulator for configurable elements */ + if (checkPropertiesConfig()) + id_last = ED_TEXTBUTTON_ID_PROPERTIES_CONFIG; + + /* draw additional "advanced" tabulator for custom elements */ + if (IS_CUSTOM_ELEMENT(properties_element)) + id_last = ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED; + + for (i=id_first; i <= id_last; i++) + { + int gadget_id = textbutton_info[i].gadget_id; + struct GadgetInfo *gi = level_editor_gadget[gadget_id]; + boolean active = (i != edit_mode_properties); + + /* draw background line below tabulator button */ + ClearRectangleOnBackground(drawto, gi->x, gi->y + gi->height, gi->width,1); + + /* draw solid line below inactive tabulator buttons */ + if (!active && tab_color != BLACK_PIXEL) /* black => transparent */ + FillRectangle(drawto, gi->x, gi->y + gi->height, gi->width,1, tab_color); + + ModifyGadget(gi, GDI_ACTIVE, active, GDI_END); + MapTextbuttonGadget(i); + } + + /* draw little border line below tabulator buttons */ + if (tab_color != BLACK_PIXEL) /* black => transparent */ + FillRectangle(drawto, gd_gi->x, gd_gi->y + gd_gi->height + 1, + 3 * gd_gi->width + 2 * ED_GADGET_DISTANCE, + ED_GADGET_DISTANCE, tab_color); +} + +static void DrawPropertiesInfo() +{ + static struct + { + int value; + char *text; + } + properties[] = + { + /* configurable properties */ + { EP_INDESTRUCTIBLE, "- undestructible" }, + { EP_DIGGABLE, "- diggable" }, + { EP_COLLECTIBLE, "- collectible" }, + { EP_PUSHABLE, "- pushable" }, + { EP_CAN_FALL, "- can fall" }, + { EP_CAN_SMASH, "- can smash other objects" }, + { EP_CAN_MOVE, "- can move" }, + { EP_SLIPPERY, "- slippery for falling objects" }, + { EP_EM_SLIPPERY_WALL, "- slippery for some gems (EM style)" }, + { EP_WALKABLE_OVER, "- player can walk over it" }, + { EP_WALKABLE_INSIDE, "- player can walk inside it" }, + { EP_WALKABLE_UNDER, "- player can walk under it" }, + { EP_PASSABLE_OVER, "- player can pass over it" }, + { EP_PASSABLE_INSIDE, "- player can pass through it" }, + { EP_PASSABLE_UNDER, "- player can pass under it" }, + + /* pre-defined properties */ + { EP_CAN_PASS_MAGIC_WALL, "- can pass magic walls" }, + { EP_DONT_TOUCH, "- deadly when touched" }, + { EP_ENEMY, "- can kill the player" }, + { EP_DONT_GO_TO, "- deadly when walked to" }, + { EP_CAN_EXPLODE, "- can explode" }, + { EP_HAS_CONTENT, "- can contain other elements" }, + + { -1, NULL } + }; + char *filename = getElementDescriptionFilename(properties_element); + char *percentage_text = "In this level:"; + char *properties_text = "Standard properties:"; + float percentage; + int num_elements_in_level; + int num_standard_properties = 0; + int font1_nr = FONT_TEXT_1; + int font2_nr = FONT_TEXT_2; + int font1_width = getFontWidth(font1_nr); + int font2_height = getFontHeight(font2_nr); + int pad_x = ED_SETTINGS_XPOS; + int pad_y = 5 * TILEY; + int screen_line = 2; + int i, x, y; + + num_elements_in_level = 0; + for (y=0; y 0) + { + DrawTextF(pad_x, pad_y + screen_line * font2_height, font1_nr, + properties_text); + screen_line++; + + for (i=0; properties[i].value != -1; i++) + { + if (!HAS_PROPERTY(properties_element, properties[i].value)) + continue; + + DrawTextF(pad_x, pad_y + screen_line * font2_height, font2_nr, + properties[i].text); + screen_line++; + } + + screen_line++; } +#endif + + PrintInfoText("Description:", FONT_TEXT_1, screen_line); + if (PrintElementDescriptionFromFile(filename, screen_line + 1) == 0) + PrintInfoText("No description available.", FONT_TEXT_1, screen_line); +} + +static void DrawPropertiesAdvanced() +{ + DrawText(SX + ED_SETTINGS_XPOS, SY + 5 * TILEY, + "Under construction! :-)", FONT_TEXT_1); +} + +static void DrawPropertiesWindow() +{ + int xstart = 2; + int ystart = 4; + + /* make sure that previous properties edit mode exists for this element */ + if (edit_mode_properties == ED_MODE_PROPERTIES_ADVANCED && + !IS_CUSTOM_ELEMENT(properties_element)) + edit_mode_properties = ED_MODE_PROPERTIES_CONFIG; + + if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG && + !checkPropertiesConfig()) + edit_mode_properties = ED_MODE_PROPERTIES_INFO; + + UnmapLevelEditorWindowGadgets(); + + SetMainBackgroundImage(IMG_BACKGROUND_EDITOR); + ClearWindow(); + + DrawText(SX + ED_SETTINGS2_XPOS, SY + ED_SETTINGS_YPOS, + "Element Settings", FONT_TITLE_1); + + DrawElementBorder(SX + xstart * MINI_TILEX, + SY + ystart * MINI_TILEY + MINI_TILEY / 2, + TILEX, TILEY); + DrawGraphicAnimationExt(drawto, + SX + xstart * MINI_TILEX, + SY + ystart * MINI_TILEY + MINI_TILEY / 2, + el2img(properties_element), -1, NO_MASKING); + + FrameCounter = 0; /* restart animation frame counter */ + + DrawTextF((xstart + 3) * MINI_TILEX, (ystart + 1) * MINI_TILEY, + FONT_TEXT_1, getElementInfoText(properties_element)); + + DrawPropertiesTabulatorGadgets(); + + if (edit_mode_properties == ED_MODE_PROPERTIES_INFO) + DrawPropertiesInfo(); + else if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG) + DrawPropertiesConfig(); + else /* edit_mode_properties == ED_MODE_PROPERTIES_ADVANCED */ + DrawPropertiesAdvanced(); } static void DrawLineElement(int sx, int sy, int element, boolean change_level) @@ -4322,14 +4731,28 @@ static void HandleTextInputGadgets(struct GadgetInfo *gi) static void HandleSelectboxGadgets(struct GadgetInfo *gi) { - *selectbox_info[gi->custom_type_id].index = gi->selectbox.index; + int type_id = gi->custom_type_id; -#if 1 - printf("Selected text value: '%s'\n", - selectbox_info[gi->custom_type_id].values[gi->selectbox.index]); + *selectbox_info[type_id].index = gi->selectbox.index; + +#if 0 + printf("Selected text value: '%s' [%d]\n", + selectbox_info[type_id].options[gi->selectbox.index].text, + selectbox_info[type_id].options[gi->selectbox.index].value); #endif } +static void HandleTextbuttonGadgets(struct GadgetInfo *gi) +{ + if (gi->custom_type_id >= ED_TEXTBUTTON_ID_PROPERTIES_INFO && + gi->custom_type_id <= ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED) + { + edit_mode_properties = gi->custom_type_id; + + DrawPropertiesWindow(); + } +} + static void HandleRadiobuttons(struct GadgetInfo *gi) { *radiobutton_info[gi->custom_type_id].value = @@ -4344,7 +4767,7 @@ static void HandleCheckbuttons(struct GadgetInfo *gi) if (type_id >= ED_CHECKBUTTON_ID_CUSTOM_FIRST && type_id <= ED_CHECKBUTTON_ID_CUSTOM_LAST) - CopyCustomElementPropertiesToGame(); + CopyCustomElementPropertiesToGame(properties_element); } static void HandleControlButtons(struct GadgetInfo *gi) @@ -4617,7 +5040,7 @@ static void HandleControlButtons(struct GadgetInfo *gi) TapeStartRecording(); level_editor_test_game = TRUE; - game_status = PLAYING; + game_status = GAME_MODE_PLAYING; InitGame(); } @@ -4755,7 +5178,7 @@ void HandleLevelEditorIdle() DrawGraphicAnimationExt(drawto, SX + xpos * TILEX, SY + ypos * TILEY + MINI_TILEY / 2, - el2edimg(properties_element), -1, NO_MASKING); + el2img(properties_element), -1, NO_MASKING); MarkTileDirty(xpos, ypos); MarkTileDirty(xpos, ypos + 1); @@ -4775,7 +5198,7 @@ void HandleEditorGadgetInfoText(void *ptr) char shortcut[MAX_OUTPUT_LINESIZE + 1]; int max_infotext_len = getMaxInfoTextLength(); - if (game_status != LEVELED) + if (game_status != GAME_MODE_EDITOR) return; ClearEditorGadgetInfoText(); @@ -4956,7 +5379,7 @@ void RequestExitLevelEditor(boolean ask_if_level_has_changed) /* CloseDoor(DOOR_CLOSE_ALL); */ - game_status = MAINMENU; + game_status = GAME_MODE_MAIN; DrawMainMenu(); } else