X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Feditor.c;h=7312964bdf364ac708a91767c388b8c127549b21;hb=3f3ea56ee7a6b0818aa916a44afd5127d99d4f42;hp=6d4b4ad90ce9e51be91218adf9fd18a96dee2670;hpb=1a58dd6669241cfffa14f4e6585787e3efca82fa;p=rocksndiamonds.git diff --git a/src/editor.c b/src/editor.c index 6d4b4ad9..7312964b 100644 --- a/src/editor.c +++ b/src/editor.c @@ -49,7 +49,12 @@ #define RANDOM_USE_PERCENTAGE 0 #define RANDOM_USE_NUM_OBJECTS 1 +/* values for elements with score */ +#define MIN_SCORE 0 +#define MAX_SCORE 255 + /* values for elements with content */ +#define MIN_ELEMCONT 1 #define MAX_ELEMCONT 8 /* values for the control window */ @@ -83,6 +88,10 @@ #define ED_COUNT_ELEMCONT_XPOS ED_PROPERTIES_XPOS #define ED_COUNT_ELEMCONT_YPOS (17 * MINI_TILEY) +/* standard distances */ +#define ED_BORDER_SIZE 3 +#define ED_GADGET_DISTANCE 2 + /* values for element content drawing areas */ #define ED_AREA_ELEMCONT_XPOS (TILEX) #define ED_AREA_ELEMCONT_YPOS (10 * TILEY) @@ -114,6 +123,8 @@ #define ED_SCROLL_HORIZONTAL_YSIZE ED_SCROLLBUTTON_YSIZE /* control button identifiers */ +#define ED_CTRL_ID_NONE -1 + #define ED_CTRL_ID_SINGLE_ITEMS 0 #define ED_CTRL_ID_CONNECTED_ITEMS 1 #define ED_CTRL_ID_LINE 2 @@ -127,7 +138,7 @@ #define ED_CTRL_ID_UNUSED1 10 #define ED_CTRL_ID_WRAP_RIGHT 11 #define ED_CTRL_ID_RANDOM_PLACEMENT 12 -#define ED_CTRL_ID_BRUSH 13 +#define ED_CTRL_ID_GRAB_BRUSH 13 #define ED_CTRL_ID_WRAP_DOWN 14 #define ED_CTRL_ID_PICK_ELEMENT 15 #define ED_CTRL_ID_UNDO 16 @@ -139,32 +150,40 @@ /* counter button identifiers */ #define ED_CTRL_ID_SCORE_DOWN 22 -#define ED_CTRL_ID_SCORE_UP 23 -#define ED_CTRL_ID_ELEMCONT_DOWN 24 -#define ED_CTRL_ID_ELEMCONT_UP 25 +#define ED_CTRL_ID_SCORE_TEXT 23 +#define ED_CTRL_ID_SCORE_UP 24 +#define ED_CTRL_ID_ELEMCONT_DOWN 25 +#define ED_CTRL_ID_ELEMCONT_TEXT 26 +#define ED_CTRL_ID_ELEMCONT_UP 27 /* drawing area identifiers */ -#define ED_CTRL_ID_DRAWING_LEVEL 26 -#define ED_CTRL_ID_ELEMCONT_0 27 -#define ED_CTRL_ID_ELEMCONT_7 34 -#define ED_CTRL_ID_AMOEBA_CONTENT 35 +#define ED_CTRL_ID_DRAWING_LEVEL 28 +#define ED_CTRL_ID_ELEMCONT_0 29 +#define ED_CTRL_ID_ELEMCONT_1 30 +#define ED_CTRL_ID_ELEMCONT_2 31 +#define ED_CTRL_ID_ELEMCONT_3 32 +#define ED_CTRL_ID_ELEMCONT_4 33 +#define ED_CTRL_ID_ELEMCONT_5 34 +#define ED_CTRL_ID_ELEMCONT_6 35 +#define ED_CTRL_ID_ELEMCONT_7 36 +#define ED_CTRL_ID_AMOEBA_CONTENT 37 /* text input identifiers */ -#define ED_CTRL_ID_LEVEL_NAME 36 +#define ED_CTRL_ID_LEVEL_NAME 38 /* gadgets for scrolling of drawing area */ -#define ED_CTRL_ID_SCROLL_UP 37 -#define ED_CTRL_ID_SCROLL_DOWN 38 -#define ED_CTRL_ID_SCROLL_LEFT 39 -#define ED_CTRL_ID_SCROLL_RIGHT 40 -#define ED_CTRL_ID_SCROLL_VERTICAL 41 -#define ED_CTRL_ID_SCROLL_HORIZONTAL 42 +#define ED_CTRL_ID_SCROLL_UP 39 +#define ED_CTRL_ID_SCROLL_DOWN 40 +#define ED_CTRL_ID_SCROLL_LEFT 41 +#define ED_CTRL_ID_SCROLL_RIGHT 42 +#define ED_CTRL_ID_SCROLL_VERTICAL 43 +#define ED_CTRL_ID_SCROLL_HORIZONTAL 44 -#define ED_NUM_GADGETS 43 +#define ED_NUM_GADGETS 45 /* values for counter gadgets */ -#define ED_COUNTER_SCORE 0 -#define ED_COUNTER_ELEMCONT 1 +#define ED_COUNTER_ID_SCORE 0 +#define ED_COUNTER_ID_ELEMCONT 1 #define ED_NUM_COUNTERBUTTONS 2 #define ED_NUM_SCROLLBUTTONS 4 @@ -174,40 +193,59 @@ #define UNDO_IMMEDIATE 0 #define UNDO_ACCUMULATE 1 -static char *control_infotext[ED_NUM_CTRL_BUTTONS] = -{ - "draw single items", - "draw connected items", - "draw lines", - "enter text elements", - "draw outline rectangles", - "draw filled boxes", - "wrap (rotate) level up", - "properties of drawing element", - "flood fill", - "wrap (rotate) level left", - "", - "wrap (rotate) level right", - "random element placement", - "grab brush", - "wrap (rotate) level down", - "pick drawing element from editing area", - "undo last operation", - "level properties", - "save level", - "clear level", - "test level", - "exit level editor", +static struct +{ + char shortcut; + char *text; +} control_info[ED_NUM_CTRL_BUTTONS] = +{ + { 's', "draw single items" }, + { 'd', "draw connected items" }, + { 'l', "draw lines" }, + { 't', "enter text elements" }, + { 'r', "draw outline rectangles" }, + { 'R', "draw filled rectangles" }, + { '\0', "wrap (rotate) level up" }, + { '?', "properties of drawing element" }, + { 'f', "flood fill" }, + { '\0', "wrap (rotate) level left" }, + { '\0', "" }, + { '\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" } }; +/* pointers to counter values */ +static int *gadget_score_value = NULL; +static int *gadget_areas_value = NULL; + static struct { int x, y; - int gadget_id; + int **counter_value; + int min_value, max_value; + int gadget_id_down, gadget_id_up; + int gadget_id_text; } counterbutton_info[ED_NUM_COUNTERBUTTONS] = { - { ED_COUNT_SCORE_XPOS, ED_COUNT_SCORE_YPOS, ED_CTRL_ID_SCORE_DOWN }, - { ED_COUNT_ELEMCONT_XPOS, ED_COUNT_ELEMCONT_YPOS, ED_CTRL_ID_ELEMCONT_DOWN } + { ED_COUNT_SCORE_XPOS, ED_COUNT_SCORE_YPOS, + &gadget_score_value, + MIN_SCORE, MAX_SCORE, + ED_CTRL_ID_SCORE_DOWN, ED_CTRL_ID_SCORE_UP, + ED_CTRL_ID_SCORE_TEXT }, + { ED_COUNT_ELEMCONT_XPOS, ED_COUNT_ELEMCONT_YPOS, + &gadget_areas_value, + MIN_ELEMCONT, MAX_ELEMCONT, + ED_CTRL_ID_ELEMCONT_DOWN, ED_CTRL_ID_ELEMCONT_UP, + ED_CTRL_ID_ELEMCONT_TEXT } }; static struct @@ -268,7 +306,6 @@ static struct }, }; - /* forward declaration for internal use */ static void DrawDrawingWindow(); static void DrawPropertiesWindow(); @@ -301,10 +338,6 @@ static int random_placement_method = RANDOM_USE_PERCENTAGE; static int random_placement_method = RANDOM_USE_NUM_OBJECTS; #endif -/* pointer to score value */ -static int *gadget_score_value; -static int *gadget_areas_value; - static int level_xpos,level_ypos; static int edit_mode; static boolean name_typing; @@ -743,7 +776,7 @@ static void CreateControlButtons() id == ED_CTRL_ID_RECTANGLE || id == ED_CTRL_ID_FILLED_BOX || id == ED_CTRL_ID_FLOOD_FILL || - id == ED_CTRL_ID_BRUSH || + id == ED_CTRL_ID_GRAB_BRUSH || id == ED_CTRL_ID_PICK_ELEMENT) { button_type = GD_TYPE_RADIO_BUTTON; @@ -793,7 +826,7 @@ static void CreateControlButtons() gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_ALT_GFX_YPOS + gd_yoffset; gi = CreateGadget(GDI_CUSTOM_ID, id, - GDI_DESCRIPTION_TEXT, control_infotext[i], + GDI_DESCRIPTION_TEXT, control_info[i].text, GDI_X, EX + gd_xoffset, GDI_Y, EY + gd_yoffset, GDI_WIDTH, width, @@ -851,17 +884,23 @@ static void CreateControlButtons() static void CreateCounterButtons() { - int i, j; + int i; for (i=0; iwidth + ED_GADGET_DISTANCE; /* xpos of text count button */ + + if (j == 0) + { + id = counterbutton_info[i].gadget_id_text; + event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING; + + gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS; + gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS; + + gi = CreateGadget(GDI_CUSTOM_ID, id, + GDI_X, xpos, + GDI_Y, ypos, + GDI_TYPE, GD_TYPE_TEXTINPUT_NUMERIC, + GDI_NUMBER_VALUE, 0, + GDI_NUMBER_MIN, counterbutton_info[i].min_value, + GDI_NUMBER_MAX, counterbutton_info[i].max_value, + GDI_TEXT_SIZE, 3, + GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y, + GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y, + GDI_DESIGN_BORDER, ED_BORDER_SIZE, + GDI_EVENT_MASK, event_mask, + GDI_CALLBACK_ACTION, HandleCounterButtons, + GDI_END); + + if (gi == NULL) + Error(ERR_EXIT, "cannot create gadget"); + + level_editor_gadget[id] = gi; + xpos += gi->width + ED_GADGET_DISTANCE; /* xpos of up count button */ + } } } } @@ -974,21 +1044,22 @@ static void CreateTextInputGadgets() unsigned long event_mask; int id; + event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING; + gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS; gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS; - event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING; /* text input gadget for the level name */ id = ED_CTRL_ID_LEVEL_NAME; gi = CreateGadget(GDI_CUSTOM_ID, id, GDI_X, SX + ED_COUNT_ELEMCONT_XPOS, GDI_Y, SY + ED_AREA_ELEMCONT_YPOS + 3 * TILEX, - GDI_TYPE, GD_TYPE_TEXTINPUT, + GDI_TYPE, GD_TYPE_TEXTINPUT_ALPHANUMERIC, GDI_TEXT_VALUE, level.name, GDI_TEXT_SIZE, 30, GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y, GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y, - GDI_DESIGN_BORDER, 3, + GDI_DESIGN_BORDER, ED_BORDER_SIZE, GDI_EVENT_MASK, event_mask, GDI_CALLBACK_ACTION, HandleTextInputGadgets, GDI_END); @@ -1045,7 +1116,7 @@ static void CreateScrollbarGadgets() GDI_STATE, GD_BUTTON_UNPRESSED, GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1, GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2, - GDI_DESIGN_BORDER, 3, + GDI_DESIGN_BORDER, ED_BORDER_SIZE, GDI_EVENT_MASK, event_mask, GDI_CALLBACK_ACTION, HandleControlButtons, GDI_END); @@ -1079,12 +1150,11 @@ static void MapControlButtons() MapGadget(level_editor_gadget[i]); } -static void MapCounterButtons(int id) +static void MapCounterButtons(int cnt_id) { - int i; - - for (i=0; i<2; i++) - MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id + i]); + MapGadget(level_editor_gadget[counterbutton_info[cnt_id].gadget_id_down]); + MapGadget(level_editor_gadget[counterbutton_info[cnt_id].gadget_id_text]); + MapGadget(level_editor_gadget[counterbutton_info[cnt_id].gadget_id_up]); } static void MapDrawingArea(int id) @@ -1135,8 +1205,6 @@ void DrawLevelEd() { int i, x, y, graphic; - level_xpos = -1; - level_ypos = -1; edit_mode = ED_MODE_DRAWING; name_typing = FALSE; @@ -1158,6 +1226,8 @@ void DrawLevelEd() } else { + level_xpos = -1; + level_ypos = -1; undo_buffer_position = -1; undo_buffer_steps = -1; CopyLevelToUndoBuffer(UNDO_IMMEDIATE); @@ -1246,6 +1316,8 @@ void DrawLevelEd() if (!level_editor_gadgets_created) CreateLevelEditorGadgets(); + else + strcpy(level_editor_gadget[ED_CTRL_ID_LEVEL_NAME]->text.value, level.name); MapControlButtons(); @@ -1440,18 +1512,19 @@ void AdjustLevelScrollPosition() void AdjustEditorScrollbar(int id) { struct GadgetInfo *gi = level_editor_gadget[id]; - struct GadgetScrollbar *gs = &gi->scrollbar; - int items_max, items_visible, item_position = gs->item_position; + int items_max, items_visible, item_position; if (id == ED_CTRL_ID_SCROLL_HORIZONTAL) { items_max = lev_fieldx + 2; items_visible = ED_FIELDX; + item_position = level_xpos + 1; } else { items_max = lev_fieldy + 2; items_visible = ED_FIELDY; + item_position = level_ypos + 1; } if (item_position > items_max - items_visible) @@ -1460,6 +1533,25 @@ void AdjustEditorScrollbar(int id) AdjustScrollbar(gi, items_max, item_position); } +void ModifyEditorTextInput(int gadget_id, char *new_text) +{ + struct GadgetInfo *gi = level_editor_gadget[gadget_id]; + + ModifyTextInputTextValue(gi, new_text); +} + +void ModifyEditorCounter(int counter_id, int new_value) +{ + int *counter_value = *counterbutton_info[counter_id].counter_value; + int gadget_id = counterbutton_info[counter_id].gadget_id_text; + struct GadgetInfo *gi = level_editor_gadget[gadget_id]; + + ModifyTextInputNumberValue(gi, new_value); + + if (counter_value != NULL) + *counter_value = gi->text.number_value; +} + static void PickDrawingElement(int button, int element) { if (button < 1 || button > 3) @@ -2196,12 +2288,13 @@ static void DrawElementContentAreas() /* display counter to choose number of element content areas */ gadget_areas_value = num_areas; - DrawCounterValueField(ED_COUNTER_ELEMCONT, *gadget_areas_value); - x = counterbutton_info[ED_COUNTER_ELEMCONT].x + DXSIZE; - y = counterbutton_info[ED_COUNTER_ELEMCONT].y; + DrawCounterValueField(ED_COUNTER_ID_ELEMCONT, *gadget_areas_value); + x = counterbutton_info[ED_COUNTER_ID_ELEMCONT].x + DXSIZE; + y = counterbutton_info[ED_COUNTER_ID_ELEMCONT].y; DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET, FC_YELLOW, "number of content areas"); - MapCounterButtons(ED_COUNTER_ELEMCONT); + ModifyEditorCounter(ED_COUNTER_ID_ELEMCONT, *gadget_areas_value); + MapCounterButtons(ED_COUNTER_ID_ELEMCONT); /* delete content areas in case of reducing number of them */ XFillRectangle(display, backbuffer, gc, @@ -2380,14 +2473,19 @@ static void DrawPropertiesWindow() { if (elements_with_counter[i].element == properties_element) { - int x = counterbutton_info[ED_COUNTER_SCORE].x + DXSIZE; - int y = counterbutton_info[ED_COUNTER_SCORE].y; + int x = counterbutton_info[ED_COUNTER_ID_SCORE].x + DXSIZE; + int y = counterbutton_info[ED_COUNTER_ID_SCORE].y; gadget_score_value = elements_with_counter[i].counter_value; - DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value); + + /* + DrawCounterValueField(ED_COUNTER_ID_SCORE, *gadget_score_value); + */ + DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET, FC_YELLOW, elements_with_counter[i].text); - MapCounterButtons(ED_COUNTER_SCORE); + ModifyEditorCounter(ED_COUNTER_ID_SCORE, *gadget_score_value); + MapCounterButtons(ED_COUNTER_ID_SCORE); break; } } @@ -2564,17 +2662,23 @@ static void SelectArea(int from_x, int from_y, int to_x, int to_y, #define CB_BRUSH_TO_LEVEL 2 #define CB_DELETE_OLD_CURSOR 3 -static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, int mode) +static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, + int button, int mode) { static short brush_buffer[ED_FIELDX][ED_FIELDY]; static int brush_width, brush_height; static int last_cursor_x = -1, last_cursor_y = -1; static boolean delete_old_brush; + int new_element; int x, y; if (mode == CB_DELETE_OLD_CURSOR && !delete_old_brush) return; + new_element = (button == 1 ? new_element1 : + button == 2 ? new_element2 : + button == 3 ? new_element3 : 0); + if (mode == CB_AREA_TO_BRUSH) { int from_lx, from_ly; @@ -2592,9 +2696,19 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, int mode) from_ly = from_y + level_ypos; for (y=0; y=0 && sx < ED_FIELDX && sy >=0 && sy < ED_FIELDY) + if (IN_ED_FIELD(sx, sy) && IN_LEV_FIELD(lx, ly)) { if (sx < border_from_x) border_from_x = sx; @@ -2652,8 +2768,10 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, int mode) if (mode != CB_DELETE_OLD_CURSOR) DrawAreaBorder(border_from_x, border_from_y, border_to_x, border_to_y); + /* if (mode == CB_BRUSH_TO_LEVEL) CopyLevelToUndoBuffer(UNDO_IMMEDIATE); + */ last_cursor_x = cursor_x; last_cursor_y = cursor_y; @@ -2661,24 +2779,25 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, int mode) } } -static void CopyAreaToBrush(int from_x, int from_y, int to_x, int to_y) +static void CopyAreaToBrush(int from_x, int from_y, int to_x, int to_y, + int button) { - CopyBrushExt(from_x, from_y, to_x, to_y, CB_AREA_TO_BRUSH); + CopyBrushExt(from_x, from_y, to_x, to_y, button, CB_AREA_TO_BRUSH); } -static void CopyBrushToLevel(int x, int y) +static void CopyBrushToLevel(int x, int y, int button) { - CopyBrushExt(x, y, 0, 0, CB_BRUSH_TO_LEVEL); + CopyBrushExt(x, y, 0, 0, button, CB_BRUSH_TO_LEVEL); } static void CopyBrushToCursor(int x, int y) { - CopyBrushExt(x, y, 0, 0, CB_BRUSH_TO_CURSOR); + CopyBrushExt(x, y, 0, 0, 0, CB_BRUSH_TO_CURSOR); } static void DeleteBrushFromCursor() { - CopyBrushExt(0, 0, 0, 0, CB_DELETE_OLD_CURSOR); + CopyBrushExt(0, 0, 0, 0, 0, CB_DELETE_OLD_CURSOR); } static void FloodFill(int from_x, int from_y, int fill_element) @@ -2946,6 +3065,9 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1; int x, y; + /* handle info callback for each invocation of action callback */ + gi->callback_info(gi); + /* if (edit_mode != ED_MODE_DRAWING) return; @@ -2986,6 +3108,13 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) button == 2 ? new_element2 : button == 3 ? new_element3 : 0); + + + if (button_release_event) + button = 0; + + + if (!draw_level && drawing_function != ED_CTRL_ID_SINGLE_ITEMS) return; @@ -2995,12 +3124,20 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) if (draw_level) { if (button_release_event) + { CopyLevelToUndoBuffer(UNDO_IMMEDIATE); + if (edit_mode == ED_MODE_DRAWING && draw_with_brush && + !inside_drawing_area) + DeleteBrushFromCursor(); + } + if (!button) break; - if (new_element != Feld[lx][ly]) + if (draw_with_brush) + CopyBrushToLevel(sx, sy, button); + else if (new_element != Feld[lx][ly]) { if (new_element == EL_SPIELFIGUR) { @@ -3066,7 +3203,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) case ED_CTRL_ID_LINE: case ED_CTRL_ID_RECTANGLE: case ED_CTRL_ID_FILLED_BOX: - case ED_CTRL_ID_BRUSH: + case ED_CTRL_ID_GRAB_BRUSH: case ED_CTRL_ID_TEXT: { static int last_sx = -1; @@ -3081,7 +3218,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) draw_func = DrawRectangle; else if (drawing_function == ED_CTRL_ID_FILLED_BOX) draw_func = DrawFilledBox; - else if (drawing_function == ED_CTRL_ID_BRUSH) + else if (drawing_function == ED_CTRL_ID_GRAB_BRUSH) draw_func = SelectArea; else /* (drawing_function == ED_CTRL_ID_TEXT) */ draw_func = SetTextCursor; @@ -3098,9 +3235,11 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) else if (button_release_event) { draw_func(start_sx, start_sy, sx, sy, new_element, TRUE); - if (drawing_function == ED_CTRL_ID_BRUSH) + if (drawing_function == ED_CTRL_ID_GRAB_BRUSH) { - CopyAreaToBrush(start_sx, start_sy, sx, sy); + CopyAreaToBrush(start_sx, start_sy, sx, sy, button); + CopyBrushToCursor(sx, sy); + ClickOnGadget(level_editor_gadget[ED_CTRL_ID_SINGLE_ITEMS]); draw_with_brush = TRUE; } else if (drawing_function == ED_CTRL_ID_TEXT) @@ -3167,26 +3306,38 @@ static void HandleCounterButtons(struct GadgetInfo *gi) { case ED_CTRL_ID_SCORE_DOWN: case ED_CTRL_ID_SCORE_UP: - *gadget_score_value += (id == ED_CTRL_ID_SCORE_DOWN ? -step : step); - if (*gadget_score_value < 0) - *gadget_score_value = 0; - else if (*gadget_score_value > 255) - *gadget_score_value = 255; - - DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value); + step *= (id == ED_CTRL_ID_SCORE_DOWN ? -1 : 1); + ModifyEditorCounter(ED_COUNTER_ID_SCORE, *gadget_score_value + step); + break; + case ED_CTRL_ID_SCORE_TEXT: + *gadget_score_value = gi->text.number_value; break; case ED_CTRL_ID_ELEMCONT_DOWN: case ED_CTRL_ID_ELEMCONT_UP: - *gadget_areas_value += (id == ED_CTRL_ID_ELEMCONT_DOWN ? -step : step); - if (*gadget_areas_value < 1) - *gadget_areas_value = 1; - else if (*gadget_areas_value > MAX_ELEMCONT) - *gadget_areas_value = MAX_ELEMCONT; - - DrawCounterValueField(ED_COUNTER_ELEMCONT, *gadget_areas_value); + step *= (id == ED_CTRL_ID_ELEMCONT_DOWN ? -1 : 1); + ModifyEditorCounter(ED_COUNTER_ID_ELEMCONT, *gadget_areas_value + step); DrawElementContentAreas(); break; + case ED_CTRL_ID_ELEMCONT_TEXT: + *gadget_areas_value = gi->text.number_value; + DrawElementContentAreas(); + break; + + default: + break; + } +} + +static void HandleTextInputGadgets(struct GadgetInfo *gi) +{ + int id = gi->custom_id; + + switch (id) + { + case ED_CTRL_ID_LEVEL_NAME: + strcpy(level.name, gi->text.value); + break; default: break; @@ -3340,10 +3491,11 @@ static void HandleControlButtons(struct GadgetInfo *gi) case ED_CTRL_ID_RECTANGLE: case ED_CTRL_ID_FILLED_BOX: case ED_CTRL_ID_FLOOD_FILL: - case ED_CTRL_ID_BRUSH: + case ED_CTRL_ID_GRAB_BRUSH: case ED_CTRL_ID_PICK_ELEMENT: last_drawing_function = drawing_function; drawing_function = id; + draw_with_brush = FALSE; break; case ED_CTRL_ID_RANDOM_PLACEMENT: @@ -3538,31 +3690,52 @@ static void HandleControlButtons(struct GadgetInfo *gi) void HandleLevelEditorKeyInput(KeySym key) { - if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT) + if (edit_mode == ED_MODE_DRAWING) { char letter = getCharFromKeySym(key); - if (letter) - DrawLevelText(0, 0, letter, TEXT_WRITECHAR); - else if (key == XK_Delete || key == XK_BackSpace) - DrawLevelText(0, 0, 0, TEXT_BACKSPACE); - else if (key == XK_Return) - DrawLevelText(0, 0, 0, TEXT_NEWLINE); - } -} + if (drawing_function == ED_CTRL_ID_TEXT) + { + if (letter) + DrawLevelText(0, 0, letter, TEXT_WRITECHAR); + else if (key == XK_Delete || key == XK_BackSpace) + DrawLevelText(0, 0, 0, TEXT_BACKSPACE); + else if (key == XK_Return) + DrawLevelText(0, 0, 0, TEXT_NEWLINE); + } + else if (button_status == MB_RELEASED) + { + int i, id; -static void HandleTextInputGadgets(struct GadgetInfo *gi) -{ - int id = gi->custom_id; + switch (key) + { + case XK_Left: + id = ED_CTRL_ID_SCROLL_LEFT; + break; + case XK_Right: + id = ED_CTRL_ID_SCROLL_RIGHT; + break; + case XK_Up: + id = ED_CTRL_ID_SCROLL_UP; + break; + case XK_Down: + id = ED_CTRL_ID_SCROLL_DOWN; + break; - switch (id) - { - case ED_CTRL_ID_LEVEL_NAME: - strcpy(level.name, gi->text_value); - break; + default: + id = ED_CTRL_ID_NONE; + break; + } - default: - break; + if (id != ED_CTRL_ID_NONE) + ClickOnGadget(level_editor_gadget[id]); + else if (letter == '.') + ClickOnGadget(level_editor_gadget[ED_CTRL_ID_SINGLE_ITEMS]); + else + for (i=0; idescription_text, MAX_INFOTEXT_LEN); infotext[MAX_INFOTEXT_LEN] = '\0'; + if (gi->custom_id < ED_NUM_CTRL_BUTTONS) + { + int key = control_info[gi->custom_id].shortcut; + + if (key) + { + sprintf(shortcut, " ('%s%c')", + (key >= 'A' && key <= 'Z' ? "Shift-" : + gi->custom_id == ED_CTRL_ID_SINGLE_ITEMS ? ".' or '" : ""), + key); + + if (strlen(infotext) + strlen(shortcut) <= MAX_INFOTEXT_LEN) + strcat(infotext, shortcut); + } + } + DrawText(INFOTEXT_XPOS, INFOTEXT_YPOS, infotext, FS_SMALL, FC_YELLOW); } static void HandleDrawingAreaInfo(struct GadgetInfo *gi) { + static int start_lx, start_ly; + char *infotext; int id = gi->custom_id; int sx = gi->event.x; int sy = gi->event.y; @@ -3612,13 +3804,94 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi) if (id == ED_CTRL_ID_DRAWING_LEVEL) { - if (IN_LEV_FIELD(lx, ly)) - DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW, - "Level: %d, %d (Screen: %d, %d)", lx, ly, sx, sy); + if (button_status) + { + int min_sx = 0, min_sy = 0; + int max_sx = gi->drawing.area_xsize - 1; + int max_sy = gi->drawing.area_ysize - 1; + int min_lx = 0, min_ly = 0; + int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1; + + /* make sure to stay inside drawing area boundaries */ + sx = (sx < min_sx ? min_sx : sx > max_sx ? max_sx : sx); + sy = (sy < min_sy ? min_sy : sy > max_sy ? max_sy : sy); + + /* get positions inside level field */ + lx = sx + level_xpos; + ly = sy + level_ypos; + + /* make sure to stay inside level field boundaries */ + lx = (lx < min_lx ? min_lx : lx > max_lx ? max_lx : lx); + ly = (ly < min_ly ? min_ly : ly > max_ly ? max_ly : ly); + + /* correct drawing area positions accordingly */ + sx = lx - level_xpos; + sy = ly - level_ypos; + } + + if (IN_ED_FIELD(sx,sy) && IN_LEV_FIELD(lx, ly)) + { + if (button_status) /* if (gi->state == GD_BUTTON_PRESSED) */ + { + if (gi->event.type == GD_EVENT_PRESSED) + { + start_lx = lx; + start_ly = ly; + } + + switch (drawing_function) + { + case ED_CTRL_ID_SINGLE_ITEMS: + infotext = "Drawing single items"; + break; + case ED_CTRL_ID_CONNECTED_ITEMS: + infotext = "Drawing connected items"; + break; + case ED_CTRL_ID_LINE: + infotext = "Drawing line"; + break; + case ED_CTRL_ID_TEXT: + infotext = "Setting text cursor"; + break; + case ED_CTRL_ID_RECTANGLE: + infotext = "Drawing rectangle"; + break; + case ED_CTRL_ID_FILLED_BOX: + infotext = "Drawing filled box"; + break; + case ED_CTRL_ID_FLOOD_FILL: + infotext = "Flood fill"; + break; + case ED_CTRL_ID_GRAB_BRUSH: + infotext = "Grabbing brush"; + break; + case ED_CTRL_ID_PICK_ELEMENT: + infotext = "Picking element"; + break; + + default: + infotext = "Drawing position"; + break; + } + + DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW, + "%s: %d, %d", infotext, + ABS(lx - start_lx) + 1, + ABS(ly - start_ly) + 1); + } + else + DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW, + "Level position: %d, %d", lx, ly); + } /* misuse this function to draw brush cursor, if needed */ - if (edit_mode == ED_MODE_DRAWING && draw_with_brush) - CopyBrushToCursor(sx, sy); + if (edit_mode == ED_MODE_DRAWING && draw_with_brush && !button_status) + { + if (IN_ED_FIELD(sx,sy) && IN_LEV_FIELD(lx, ly)) + CopyBrushToCursor(sx, sy); + else + DeleteBrushFromCursor(); + } } else if (id == ED_CTRL_ID_AMOEBA_CONTENT) DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,