X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Feditor.c;h=faeca9b629a4657ce952e6fee2aad7da5fa28154;hb=446c65ff4739d51e02dd3556226b51f1b8fb8f79;hp=b6ae1b0cbb574932467e9e1d73fdb5d8d916d73d;hpb=403fa67c24301d440ae0871c2e31e1e395133a41;p=rocksndiamonds.git diff --git a/src/editor.c b/src/editor.c index b6ae1b0c..faeca9b6 100644 --- a/src/editor.c +++ b/src/editor.c @@ -114,6 +114,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 +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 @@ -174,30 +176,34 @@ #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" } }; static struct @@ -268,7 +274,6 @@ static struct }, }; - /* forward declaration for internal use */ static void DrawDrawingWindow(); static void DrawPropertiesWindow(); @@ -284,6 +289,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]; @@ -742,7 +748,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; @@ -792,7 +798,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, @@ -1245,6 +1251,8 @@ void DrawLevelEd() if (!level_editor_gadgets_created) CreateLevelEditorGadgets(); + else + strcpy(level_editor_gadget[ED_CTRL_ID_LEVEL_NAME]->text.value, level.name); MapControlButtons(); @@ -2557,66 +2565,149 @@ static void SelectArea(int from_x, int from_y, int to_x, int to_y, DrawAreaBorder(from_x, from_y, to_x, to_y); } -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); -} - /* 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 int brush_from_x, brush_from_y; - static int 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; - brush_from_x = from_x; - brush_from_y = from_y; - brush_to_x = to_x; - brush_to_y = to_y; + 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; + + 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) { @@ -2756,6 +2847,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; @@ -2856,7 +2959,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; @@ -2872,6 +2974,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; @@ -2926,7 +3031,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) { @@ -2992,7 +3099,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; @@ -3007,7 +3114,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; @@ -3024,9 +3131,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) @@ -3266,10 +3375,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: @@ -3464,16 +3574,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; + + 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]); + else if (letter == '.') + ClickOnGadget(level_editor_gadget[ED_CTRL_ID_SINGLE_ITEMS]); + else + for (i=0; itext_value); + strcpy(level.name, gi->text.value); break; default: @@ -3510,20 +3656,41 @@ void HandleEditorGadgetInfoText(void *ptr) { struct GadgetInfo *gi = (struct GadgetInfo *)ptr; char infotext[MAX_INFOTEXT_LEN + 1]; + char shortcut[20]; 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'; + 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-" : ""), 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; @@ -3535,8 +3702,63 @@ 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 (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,