X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Feditor.c;h=44ad038d4b79672d2ca5c74049a71bf32e2ad169;hb=ed4b7eed89c292042403561e1ed1449e60888b45;hp=4b3110b13e9b7d750f075b7839453fc278ee958f;hpb=f70652c4a2f2e45d0f4ed7baf62e2311e66d4b13;p=rocksndiamonds.git diff --git a/src/editor.c b/src/editor.c index 4b3110b1..44ad038d 100644 --- a/src/editor.c +++ b/src/editor.c @@ -74,6 +74,7 @@ /* values for properties window */ #define ED_PROPERTIES_XPOS (TILEX - MINI_TILEX/2) + /* values for counter gadgets */ #define ED_COUNT_VALUE_XOFFSET 5 #define ED_COUNT_VALUE_YOFFSET 3 @@ -87,16 +88,34 @@ #define ED_AREA_ELEMCONT_YPOS (10 * TILEY) /* values for scrolling gadgets */ +#define ED_SCROLLBUTTON_XPOS 24 +#define ED_SCROLLBUTTON_YPOS 0 +#define ED_SCROLLBAR_XPOS 24 +#define ED_SCROLLBAR_YPOS 64 + +#define ED_SCROLLBUTTON_XSIZE 16 +#define ED_SCROLLBUTTON_YSIZE 16 + #define ED_SCROLL_UP_XPOS (SXSIZE - ED_SCROLLBUTTON_XSIZE) #define ED_SCROLL_UP_YPOS (0) -#define ED_SCROLL_DOWN_XPOS (SXSIZE - ED_SCROLLBUTTON_XSIZE) -#define ED_SCROLL_DOWN_YPOS (SYSIZE - TILEX - ED_SCROLLBUTTON_YSIZE) +#define ED_SCROLL_DOWN_XPOS ED_SCROLL_UP_XPOS +#define ED_SCROLL_DOWN_YPOS (SYSIZE - 3 * ED_SCROLLBUTTON_YSIZE) #define ED_SCROLL_LEFT_XPOS (0) -#define ED_SCROLL_LEFT_YPOS (SYSIZE - ED_SCROLLBUTTON_YSIZE) -#define ED_SCROLL_RIGHT_XPOS (SXSIZE - TILEX - ED_SCROLLBUTTON_XSIZE) -#define ED_SCROLL_RIGHT_YPOS (SYSIZE - ED_SCROLLBUTTON_YSIZE) +#define ED_SCROLL_LEFT_YPOS (SYSIZE - 2 * ED_SCROLLBUTTON_YSIZE) +#define ED_SCROLL_RIGHT_XPOS (SXSIZE - 2 * ED_SCROLLBUTTON_XSIZE) +#define ED_SCROLL_RIGHT_YPOS ED_SCROLL_LEFT_YPOS +#define ED_SCROLL_VERTICAL_XPOS ED_SCROLL_UP_XPOS +#define ED_SCROLL_VERTICAL_YPOS (ED_SCROLL_UP_YPOS + ED_SCROLLBUTTON_YSIZE) +#define ED_SCROLL_VERTICAL_XSIZE ED_SCROLLBUTTON_XSIZE +#define ED_SCROLL_VERTICAL_YSIZE (SYSIZE - 4 * ED_SCROLLBUTTON_YSIZE) +#define ED_SCROLL_HORIZONTAL_XPOS (ED_SCROLL_LEFT_XPOS + ED_SCROLLBUTTON_XSIZE) +#define ED_SCROLL_HORIZONTAL_YPOS ED_SCROLL_LEFT_YPOS +#define ED_SCROLL_HORIZONTAL_XSIZE (SXSIZE - 3 * ED_SCROLLBUTTON_XSIZE) +#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 @@ -110,7 +129,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 @@ -140,8 +159,10 @@ #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_NUM_GADGETS 41 +#define ED_NUM_GADGETS 43 /* values for counter gadgets */ #define ED_COUNTER_SCORE 0 @@ -149,11 +170,38 @@ #define ED_NUM_COUNTERBUTTONS 2 #define ED_NUM_SCROLLBUTTONS 4 +#define ED_NUM_SCROLLBARS 2 /* values for CopyLevelToUndoBuffer() */ #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 { int x, y; @@ -169,18 +217,58 @@ static struct int xpos, ypos; int x, y; int gadget_id; + char *text; } scrollbutton_info[ED_NUM_SCROLLBUTTONS] = { - { ED_BUTTON_UP_XPOS, ED_BUTTON_UP_YPOS, - ED_SCROLL_UP_XPOS, ED_SCROLL_UP_YPOS, ED_CTRL_ID_SCROLL_UP }, - { ED_BUTTON_DOWN_XPOS, ED_BUTTON_DOWN_YPOS, - ED_SCROLL_DOWN_XPOS, ED_SCROLL_DOWN_YPOS, ED_CTRL_ID_SCROLL_DOWN }, - { ED_BUTTON_LEFT_XPOS, ED_BUTTON_LEFT_YPOS, - ED_SCROLL_LEFT_XPOS, ED_SCROLL_LEFT_YPOS, ED_CTRL_ID_SCROLL_LEFT }, - { ED_BUTTON_RIGHT_XPOS, ED_BUTTON_RIGHT_YPOS, - ED_SCROLL_RIGHT_XPOS, ED_SCROLL_RIGHT_YPOS, ED_CTRL_ID_SCROLL_RIGHT } + { + ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 0 * ED_SCROLLBUTTON_YSIZE, + ED_SCROLL_UP_XPOS, ED_SCROLL_UP_YPOS, ED_CTRL_ID_SCROLL_UP, + "scroll level editing area up" + }, + { + ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 1 * ED_SCROLLBUTTON_YSIZE, + ED_SCROLL_DOWN_XPOS, ED_SCROLL_DOWN_YPOS, ED_CTRL_ID_SCROLL_DOWN, + "scroll level editing area down" + }, + { + ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 2 * ED_SCROLLBUTTON_YSIZE, + ED_SCROLL_LEFT_XPOS, ED_SCROLL_LEFT_YPOS, ED_CTRL_ID_SCROLL_LEFT, + "scroll level editing area left" + }, + { + ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 3 * ED_SCROLLBUTTON_YSIZE, + ED_SCROLL_RIGHT_XPOS, ED_SCROLL_RIGHT_YPOS, ED_CTRL_ID_SCROLL_RIGHT, + "scroll level editing area right" + } }; +static struct +{ + int xpos, ypos; + int x, y; + int width, height; + int type; + int gadget_id; + char *text; +} scrollbar_info[ED_NUM_SCROLLBARS] = +{ + { + ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS, + ED_SCROLL_VERTICAL_XPOS, ED_SCROLL_VERTICAL_YPOS, + ED_SCROLL_VERTICAL_XSIZE, ED_SCROLL_VERTICAL_YSIZE, + GD_TYPE_SCROLLBAR_VERTICAL, + ED_CTRL_ID_SCROLL_VERTICAL, + "scroll level editing area vertically" + }, + { + ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS, + ED_SCROLL_HORIZONTAL_XPOS, ED_SCROLL_HORIZONTAL_YPOS, + ED_SCROLL_HORIZONTAL_XSIZE, ED_SCROLL_HORIZONTAL_YSIZE, + GD_TYPE_SCROLLBAR_HORIZONTAL, + ED_CTRL_ID_SCROLL_HORIZONTAL, + "scroll level editing area horizontally" + }, +}; /* forward declaration for internal use */ static void DrawDrawingWindow(); @@ -189,6 +277,7 @@ static void CopyLevelToUndoBuffer(int); static void HandleControlButtons(struct GadgetInfo *); static void HandleCounterButtons(struct GadgetInfo *); static void HandleDrawingAreas(struct GadgetInfo *); +static void HandleDrawingAreaInfo(struct GadgetInfo *); static void HandleTextInputGadgets(struct GadgetInfo *); static struct GadgetInfo *level_editor_gadget[ED_NUM_GADGETS]; @@ -196,6 +285,7 @@ static boolean level_editor_gadgets_created = FALSE; static int drawing_function = ED_CTRL_ID_SINGLE_ITEMS; static int last_drawing_function = ED_CTRL_ID_SINGLE_ITEMS; +static boolean draw_with_brush = FALSE; static int properties_element = 0; static short ElementContent[MAX_ELEMCONT][3][3]; @@ -654,7 +744,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; @@ -704,6 +794,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_X, EX + gd_xoffset, GDI_Y, EY + gd_yoffset, GDI_WIDTH, width, @@ -717,7 +808,7 @@ static void CreateControlButtons() GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y2, GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2, GDI_EVENT_MASK, event_mask, - GDI_CALLBACK, HandleControlButtons, + GDI_CALLBACK_ACTION, HandleControlButtons, GDI_END); if (gi == NULL) @@ -734,11 +825,12 @@ static void CreateControlButtons() event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED; - gd_x1 = DOOR_GFX_PAGEX6 + scrollbutton_info[i].xpos; - gd_x2 = DOOR_GFX_PAGEX5 + scrollbutton_info[i].xpos; - gd_y = DOOR_GFX_PAGEY2 + scrollbutton_info[i].ypos; + gd_y = DOOR_GFX_PAGEY1 + scrollbutton_info[i].ypos; + gd_x1 = DOOR_GFX_PAGEX8 + scrollbutton_info[i].xpos; + gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE; gi = CreateGadget(GDI_CUSTOM_ID, id, + GDI_DESCRIPTION_TEXT, scrollbutton_info[i].text, GDI_X, SX + scrollbutton_info[i].x, GDI_Y, SY + scrollbutton_info[i].y, GDI_WIDTH, ED_SCROLLBUTTON_XSIZE, @@ -748,7 +840,7 @@ static void CreateControlButtons() GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y, GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y, GDI_EVENT_MASK, event_mask, - GDI_CALLBACK, HandleControlButtons, + GDI_CALLBACK_ACTION, HandleControlButtons, GDI_END); if (gi == NULL) @@ -790,7 +882,7 @@ static void CreateCounterButtons() GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y, GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y, GDI_EVENT_MASK, event_mask, - GDI_CALLBACK, HandleCounterButtons, + GDI_CALLBACK_ACTION, HandleCounterButtons, GDI_END); if (gi == NULL) @@ -817,17 +909,12 @@ static void CreateDrawingAreas() gi = CreateGadget(GDI_CUSTOM_ID, id, GDI_X, SX, GDI_Y, SY, - - /* - GDI_WIDTH, SXSIZE, - GDI_HEIGHT, SYSIZE, - */ - GDI_TYPE, GD_TYPE_DRAWING_AREA, GDI_AREA_SIZE, ED_FIELDX, ED_FIELDY, GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY, GDI_EVENT_MASK, event_mask, - GDI_CALLBACK, HandleDrawingAreas, + GDI_CALLBACK_INFO, HandleDrawingAreaInfo, + GDI_CALLBACK_ACTION, HandleDrawingAreas, GDI_END); if (gi == NULL) @@ -850,7 +937,8 @@ static void CreateDrawingAreas() GDI_TYPE, GD_TYPE_DRAWING_AREA, GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY, GDI_EVENT_MASK, event_mask, - GDI_CALLBACK, HandleDrawingAreas, + GDI_CALLBACK_INFO, HandleDrawingAreaInfo, + GDI_CALLBACK_ACTION, HandleDrawingAreas, GDI_END); if (gi == NULL) @@ -869,7 +957,8 @@ static void CreateDrawingAreas() GDI_TYPE, GD_TYPE_DRAWING_AREA, GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY, GDI_EVENT_MASK, event_mask, - GDI_CALLBACK, HandleDrawingAreas, + GDI_CALLBACK_INFO, HandleDrawingAreaInfo, + GDI_CALLBACK_ACTION, HandleDrawingAreas, GDI_END); if (gi == NULL) @@ -898,11 +987,11 @@ static void CreateTextInputGadgets() GDI_TYPE, GD_TYPE_TEXTINPUT, GDI_TEXT_VALUE, level.name, GDI_TEXT_SIZE, 30, - GDI_TEXT_BORDER, 3, GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y, GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y, + GDI_DESIGN_BORDER, 3, GDI_EVENT_MASK, event_mask, - GDI_CALLBACK, HandleTextInputGadgets, + GDI_CALLBACK_ACTION, HandleTextInputGadgets, GDI_END); if (gi == NULL) @@ -911,6 +1000,64 @@ static void CreateTextInputGadgets() level_editor_gadget[id] = gi; } +static void CreateScrollbarGadgets() +{ + int i; + + for (i=0; itext.value, level.name); MapControlButtons(); @@ -1287,6 +1440,29 @@ void AdjustLevelScrollPosition() level_ypos = -1; } +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; + + if (id == ED_CTRL_ID_SCROLL_HORIZONTAL) + { + items_max = lev_fieldx + 2; + items_visible = ED_FIELDX; + } + else + { + items_max = lev_fieldy + 2; + items_visible = ED_FIELDY; + } + + if (item_position > items_max - items_visible) + item_position = items_max - items_visible; + + AdjustScrollbar(gi, items_max, item_position); +} + static void PickDrawingElement(int button, int element) { if (button < 1 || button > 3) @@ -1997,9 +2173,11 @@ static void DrawDrawingWindow() { ClearWindow(); UnmapLevelEditorWindowGadgets(); - MapMainDrawingArea(); AdjustLevelScrollPosition(); + AdjustEditorScrollbar(ED_CTRL_ID_SCROLL_HORIZONTAL); + AdjustEditorScrollbar(ED_CTRL_ID_SCROLL_VERTICAL); DrawMiniLevel(level_xpos, level_ypos); + MapMainDrawingArea(); } static void DrawElementContentAreas() @@ -2385,52 +2563,147 @@ static void SelectArea(int from_x, int from_y, int to_x, int to_y, /* values for CopyBrushExt() */ #define CB_AREA_TO_BRUSH 0 -#define CB_BRUSH_TO_LEVEL 1 +#define CB_BRUSH_TO_CURSOR 1 +#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[MAX_LEV_FIELDX][MAX_LEV_FIELDY]; - static brush_from_x, brush_from_y; - static brush_to_x, brush_to_y; + 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 (from_x > to_x) - swap_numbers(&from_x, &to_x); + if (mode == CB_DELETE_OLD_CURSOR && !delete_old_brush) + return; - if (from_y > to_y) - swap_numbers(&from_y, &to_y); + new_element = (button == 1 ? new_element1 : + button == 2 ? new_element2 : + button == 3 ? new_element3 : 0); if (mode == CB_AREA_TO_BRUSH) { - for (y=from_y; y<=to_y; y++) - for (x=from_x; x<=to_x; x++) - brush_buffer[x][y] = Feld[x][y]; + int from_lx, from_ly; + + if (from_x > to_x) + swap_numbers(&from_x, &to_x); + + if (from_y > to_y) + swap_numbers(&from_y, &to_y); + + brush_width = to_x - from_x + 1; + brush_height = to_y - from_y + 1; - brush_from_x = from_x; - brush_from_y = from_y; - brush_to_x = to_x; - brush_to_y = to_y; + from_lx = from_x + level_xpos; + from_ly = from_y + level_ypos; + + for (y=0; y=0 && sx < ED_FIELDX && sy >=0 && sy < ED_FIELDY) + { + if (sx < border_from_x) + border_from_x = sx; + else if (sx > border_to_x) + border_to_x = sx; + if (sy < border_from_y) + border_from_y = sy; + else if (sy > border_to_y) + border_to_y = sy; + + DrawLineElement(sx, sy, element, change_level); + } + } + } + + /* + printf("%d, %d - %d, %d in level and screen\n", + border_from_x, border_from_y, border_to_x, border_to_y); + */ + + 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; + delete_old_brush = TRUE; } } -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); } -#if 0 -static void CopyBrushToLevel() +static void CopyBrushToLevel(int x, int y, int button) { - CopyBrushExt(0, 0, 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, 0, CB_BRUSH_TO_CURSOR); +} + +static void DeleteBrushFromCursor() +{ + CopyBrushExt(0, 0, 0, 0, 0, CB_DELETE_OLD_CURSOR); } -#endif static void FloodFill(int from_x, int from_y, int fill_element) { @@ -2480,6 +2753,20 @@ static void DrawLevelText(int sx, int sy, char letter, int mode) int letter_element = EL_CHAR_ASCII0 + letter; int lx, ly; + /* map lower case letters to upper case and convert special characters */ + if (letter >= 'a' && letter <= 'z') + letter_element = EL_CHAR_ASCII0 + letter + (int)('A' - 'a'); + else if (letter == 'ä' || letter == 'Ä') + letter_element = EL_CHAR_AE; + else if (letter == 'ö' || letter == 'Ö') + letter_element = EL_CHAR_OE; + else if (letter == 'ü' || letter == 'Ü') + letter_element = EL_CHAR_UE; + else if (letter == '^') + letter_element = EL_CHAR_COPY; + else + letter_element = EL_CHAR_ASCII0 + letter; + if (mode != TEXT_INIT) { if (!typing) @@ -2556,6 +2843,18 @@ static void DrawLevelText(int sx, int sy, char letter, int mode) } } +static void SetTextCursor(int unused_sx, int unused_sy, int sx, int sy, + int element, boolean change_level) +{ + int lx = sx + level_xpos; + int ly = sy + level_ypos; + + if (element == -1) + DrawMiniElement(sx, sy, Feld[lx][ly]); + else + DrawAreaBorder(sx, sy, sx, sy); +} + static void CopyLevelToUndoBuffer(int mode) { static boolean accumulated_undo = FALSE; @@ -2656,7 +2955,6 @@ void WrapLevel(int dx, int dy) static void HandleDrawingAreas(struct GadgetInfo *gi) { static boolean started_inside_drawing_area = FALSE; - static boolean draw_with_brush = FALSE; int id = gi->custom_id; boolean inside_drawing_area = !gi->event.off_borders; boolean button_press_event; @@ -2672,6 +2970,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; @@ -2726,7 +3027,9 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) 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) { @@ -2792,7 +3095,8 @@ 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; static int last_sy = -1; @@ -2806,23 +3110,32 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) draw_func = DrawRectangle; else if (drawing_function == ED_CTRL_ID_FILLED_BOX) draw_func = DrawFilledBox; - else + else if (drawing_function == ED_CTRL_ID_GRAB_BRUSH) draw_func = SelectArea; + else /* (drawing_function == ED_CTRL_ID_TEXT) */ + draw_func = SetTextCursor; if (button_press_event) { draw_func(sx, sy, sx, sy, new_element, FALSE); start_sx = last_sx = sx; start_sy = last_sy = sy; + + if (drawing_function == ED_CTRL_ID_TEXT) + DrawLevelText(0, 0, 0, TEXT_END); } 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) + DrawLevelText(sx, sy, 0, TEXT_INIT); else CopyLevelToUndoBuffer(UNDO_IMMEDIATE); } @@ -2836,10 +3149,23 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) } break; + + +#if 0 case ED_CTRL_ID_TEXT: + /* + DrawMiniElement(last_sx, last_sy, Feld[lx][ly]); + DrawAreaBorder(sx, sy, sx, sy); + last_sx = sx; + last_sy = sy; + */ + if (button_press_event) DrawLevelText(sx, sy, 0, TEXT_INIT); break; +#endif + + case ED_CTRL_ID_FLOOD_FILL: if (button_press_event && Feld[lx][ly] != new_element) @@ -2927,22 +3253,32 @@ static void HandleControlButtons(struct GadgetInfo *gi) case ED_CTRL_ID_SCROLL_LEFT: if (level_xpos >= 0) { + int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL; + struct GadgetInfo *gi = level_editor_gadget[gadget_id]; + struct GadgetScrollbar *gs = &gi->scrollbar; + if (lev_fieldx < ED_FIELDX - 2) break; level_xpos -= step; - if (level_xpos <- 1) + if (level_xpos < -1) level_xpos = -1; if (button == 1) ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT); else DrawMiniLevel(level_xpos, level_ypos); + + AdjustScrollbar(gi, gs->items_max, level_xpos + 1); } break; case ED_CTRL_ID_SCROLL_RIGHT: if (level_xpos <= lev_fieldx - ED_FIELDX) { + int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL; + struct GadgetInfo *gi = level_editor_gadget[gadget_id]; + struct GadgetScrollbar *gs = &gi->scrollbar; + if (lev_fieldx < ED_FIELDX - 2) break; @@ -2953,12 +3289,18 @@ static void HandleControlButtons(struct GadgetInfo *gi) ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_LEFT); else DrawMiniLevel(level_xpos, level_ypos); + + AdjustScrollbar(gi, gs->items_max, level_xpos + 1); } break; case ED_CTRL_ID_SCROLL_UP: if (level_ypos >= 0) { + int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL; + struct GadgetInfo *gi = level_editor_gadget[gadget_id]; + struct GadgetScrollbar *gs = &gi->scrollbar; + if (lev_fieldy < ED_FIELDY - 2) break; @@ -2969,12 +3311,18 @@ static void HandleControlButtons(struct GadgetInfo *gi) ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_DOWN); else DrawMiniLevel(level_xpos, level_ypos); + + AdjustScrollbar(gi, gs->items_max, level_ypos + 1); } break; case ED_CTRL_ID_SCROLL_DOWN: if (level_ypos <= lev_fieldy - ED_FIELDY) { + int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL; + struct GadgetInfo *gi = level_editor_gadget[gadget_id]; + struct GadgetScrollbar *gs = &gi->scrollbar; + if (lev_fieldy < ED_FIELDY - 2) break; @@ -2985,9 +3333,21 @@ static void HandleControlButtons(struct GadgetInfo *gi) ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_UP); else DrawMiniLevel(level_xpos, level_ypos); + + AdjustScrollbar(gi, gs->items_max, level_ypos + 1); } break; + case ED_CTRL_ID_SCROLL_HORIZONTAL: + level_xpos = gi->event.item_position - 1; + DrawMiniLevel(level_xpos, level_ypos); + break; + + case ED_CTRL_ID_SCROLL_VERTICAL: + level_ypos = gi->event.item_position - 1; + DrawMiniLevel(level_xpos, level_ypos); + break; + case ED_CTRL_ID_WRAP_LEFT: WrapLevel(-step, 0); break; @@ -3011,10 +3371,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: @@ -3209,26 +3570,109 @@ 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); - /* map lower case letters to upper case */ - if (letter >= 'a' && letter <= 'z') - letter += (int)('A' - 'a'); - else if (letter == 'ä') - letter = 'Ä'; - else if (letter == 'ä') - letter = 'Ö'; - else if (letter == 'ä') - letter = 'Ü'; - - 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 id; + + switch (letter) + { + case '.': + case 's': + id = ED_CTRL_ID_SINGLE_ITEMS; + break; + case 'd': + id = ED_CTRL_ID_CONNECTED_ITEMS; + break; + case 'l': + id = ED_CTRL_ID_LINE; + break; + case 't': + id = ED_CTRL_ID_TEXT; + break; + case 'r': + id = ED_CTRL_ID_RECTANGLE; + break; + case 'R': + id = ED_CTRL_ID_FILLED_BOX; + break; + case '?': + id = ED_CTRL_ID_PROPERTIES; + break; + case 'f': + id = ED_CTRL_ID_FLOOD_FILL; + break; + case 'b': + id = ED_CTRL_ID_GRAB_BRUSH; + break; + case ',': + id = ED_CTRL_ID_PICK_ELEMENT; + break; + + case 'U': + id = ED_CTRL_ID_UNDO; + break; + case 'I': + id = ED_CTRL_ID_INFO; + break; + case 'S': + id = ED_CTRL_ID_SAVE; + break; + case 'C': + id = ED_CTRL_ID_CLEAR; + break; + case 'T': + id = ED_CTRL_ID_TEST; + break; + case 'E': + id = ED_CTRL_ID_EXIT; + break; + + default: + id = ED_CTRL_ID_NONE; + break; + } + + if (id != ED_CTRL_ID_NONE) + ClickOnGadget(level_editor_gadget[id]); + else + { + 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; + + default: + id = ED_CTRL_ID_NONE; + break; + } + + if (id != ED_CTRL_ID_NONE) + ClickOnGadget(level_editor_gadget[id]); + } + } } } @@ -3239,10 +3683,126 @@ static void HandleTextInputGadgets(struct GadgetInfo *gi) switch (id) { case ED_CTRL_ID_LEVEL_NAME: - strcpy(level.name, gi->text_value); + strcpy(level.name, gi->text.value); break; default: break; } } + +/* 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 +#define MAX_INFOTEXT_LEN (SXSIZE / FONT2_XSIZE) + +void ClearEditorGadgetInfoText() +{ + XFillRectangle(display, drawto, gc, + INFOTEXT_XPOS, INFOTEXT_YPOS, INFOTEXT_XSIZE, INFOTEXT_YSIZE); + redraw_mask |= REDRAW_FIELD; +} + +void HandleEditorGadgetInfoText(void *ptr) +{ + struct GadgetInfo *gi = (struct GadgetInfo *)ptr; + char infotext[MAX_INFOTEXT_LEN + 1]; + + ClearEditorGadgetInfoText(); + + /* misuse this function to delete brush cursor, if needed */ + if (edit_mode == ED_MODE_DRAWING && draw_with_brush) + DeleteBrushFromCursor(); + + if (gi == NULL || gi->description_text == NULL) + return; + + strncpy(infotext, gi->description_text, MAX_INFOTEXT_LEN); + infotext[MAX_INFOTEXT_LEN] = '\0'; + + 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; + int lx = sx + level_xpos; + int ly = sy + level_ypos; + + ClearEditorGadgetInfoText(); + + if (id == ED_CTRL_ID_DRAWING_LEVEL) + { + if (IN_LEV_FIELD(lx, ly)) + { + 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); + } + else if (id == ED_CTRL_ID_AMOEBA_CONTENT) + DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW, + "Amoeba content"); + else + DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW, + "Cruncher %d content: %d, %d", id - ED_CTRL_ID_ELEMCONT_0 + 1, + sx, sy); +}