X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Feditor.c;h=490be2699d6b2374aa3e6d64b898d728d94b9cf2;hb=82d9e85c18ff733092fa5a86187b38564617b7de;hp=68dcf25612655fa089dd52c0aebc40bc72df89b0;hpb=01732be3e0e75dbeebc5272b96a2d8dac127c4db;p=rocksndiamonds.git diff --git a/src/editor.c b/src/editor.c index 68dcf256..490be269 100644 --- a/src/editor.c +++ b/src/editor.c @@ -5721,6 +5721,11 @@ static void DrawEditorElement(int x, int y, int element) DrawSizedElement(x, y, element, ed_tilesize); } +static void DrawEditorElementThruMask(int x, int y, int element) +{ + DrawSizedElementThruMask(x, y, element, ed_tilesize); +} + static void DrawEditorElementOrWall(int x, int y, int scroll_x, int scroll_y) { DrawSizedElementOrWall(x, y, scroll_x, scroll_y, ed_tilesize); @@ -6207,7 +6212,7 @@ static void CreateDrawingAreas() event_mask = GD_EVENT_PRESSED | GD_EVENT_RELEASED | GD_EVENT_MOVING | - GD_EVENT_OFF_BORDERS; + GD_EVENT_OFF_BORDERS | GD_EVENT_PIXEL_PRECISE; /* determine horizontal position to the right of specified gadget */ if (drawingarea_info[i].gadget_id_align != GADGET_ID_NONE) @@ -8431,6 +8436,9 @@ static void PickDrawingElement(int button, int element) if (button < 1 || button > 3) return; + if (IS_MM_WALL(element)) + element = map_mm_wall_element(element); + de = drawing_elements[button - 1]; *de.new_element = element; // update global drawing element variable @@ -10136,10 +10144,32 @@ static int getClosedChip(int x, int y) return getChipFromOpenDirectionNotEmpty(direction_new, element_old); } -static void SetElementSimple(int x, int y, int element, boolean change_level) +static void SetElementSimpleExt(int x, int y, int dx, int dy, int element, + boolean change_level) { int sx = x - level_xpos; int sy = y - level_ypos; + int old_element = Feld[x][y]; + unsigned int new_bitmask = (dx + 1) << (dy * 2); + boolean draw_masked = FALSE; + + if (IS_MM_WALL_EDITOR(element)) + { + element = map_mm_wall_element_editor(element) | new_bitmask; + + if (IS_MM_WALL(old_element)) + element |= MM_WALL_BITS(old_element); + + if (!change_level) + draw_masked = TRUE; + } + else if (IS_MM_WALL(old_element) && element == EL_EMPTY) + { + int element_changed = old_element & ~new_bitmask; + + if (MM_WALL_BITS(element_changed) != 0) + element = element_changed; + } IntelliDrawBuffer[x][y] = element; @@ -10147,7 +10177,17 @@ static void SetElementSimple(int x, int y, int element, boolean change_level) Feld[x][y] = element; if (IN_ED_FIELD(sx, sy)) - DrawEditorElement(sx, sy, element); + { + if (draw_masked) + DrawEditorElementThruMask(sx, sy, element); + else + DrawEditorElement(sx, sy, element); + } +} + +static void SetElementSimple(int x, int y, int element, boolean change_level) +{ + SetElementSimpleExt(x, y, 0, 0, element, change_level); } static void MergeAndCloseNeighbourElements(int x1, int y1, int *element1, @@ -10667,33 +10707,71 @@ static void ResetIntelliDraw() SetElementIntelliDraw(-1, -1, EL_UNDEFINED, FALSE, -1); } -static void SetElementExt(int x, int y, int element, boolean change_level, - int button) +static void SetElementExt(int x, int y, int dx, int dy, int element, + boolean change_level, int button) { if (element < 0) SetElementSimple(x, y, Feld[x][y], change_level); - else if (GetKeyModState() & KMOD_Shift) + else if (GetKeyModState() & KMOD_Shift && !IS_MM_WALL_EDITOR(element)) SetElementIntelliDraw(x, y, element, change_level, button); else - SetElementSimple(x, y, element, change_level); + SetElementSimpleExt(x, y, dx, dy, element, change_level); } static void SetElement(int x, int y, int element) { - SetElementExt(x, y, element, TRUE, -1); + SetElementExt(x, y, 0, 0, element, TRUE, -1); } -static void SetElementButton(int x, int y, int element, int button) +static void SetElementButton(int x, int y, int dx, int dy, int element, + int button) { - SetElementExt(x, y, element, TRUE, button); + SetElementExt(x, y, dx, dy, element, TRUE, button); } -static void DrawLineElement(int sx, int sy, int element, boolean change_level) +static void SetElementHiRes(int sx2, int sy2, int element, boolean change_level) { - int lx = sx + level_xpos; - int ly = sy + level_ypos; + int lx = sx2 / 2 + level_xpos; + int ly = sy2 / 2 + level_ypos; + int dx = sx2 % 2; + int dy = sy2 % 2; + + SetElementExt(lx, ly, dx, dy, element, change_level, -1); +} + +static void SetLevelElementHiRes(int lx2, int ly2, int element) +{ + int lx = lx2 / 2; + int ly = ly2 / 2; + int dx = lx2 % 2; + int dy = ly2 % 2; + + SetElementExt(lx, ly, dx, dy, element, TRUE, -1); +} + +static int getLevelElementHiRes(int lx2, int ly2) +{ + int lx = lx2 / 2; + int ly = ly2 / 2; + int dx = lx2 % 2; + int dy = ly2 % 2; + int element = Feld[lx][ly]; + unsigned int bitmask = (dx + 1) << (dy * 2); - SetElementExt(lx, ly, element, change_level, -1); + if (IS_MM_WALL(element)) + { + if (element & bitmask) + return map_mm_wall_element(element); + else + return EL_EMPTY; + } + + return element; +} + +static void DrawLineElement(int sx2, int sy2, int element, boolean change_level) +{ + SetElementHiRes(sx2, sy2, element, change_level); } static void DrawLine(int from_x, int from_y, int to_x, int to_y, @@ -10781,32 +10859,32 @@ static void DrawArcExt(int from_x, int from_y, int to_x2, int to_y2, for (x = 0; x <= radius; x++) { - int sx, sy, lx, ly; + int sx2, sy2, lx, ly; y = (int)(sqrt((float)(radius * radius - x * x)) + 0.5); - sx = from_x + x * (from_x < to_x2 ? +1 : -1); - sy = from_y + y * (from_y < to_y2 ? +1 : -1); - lx = sx + level_xpos; - ly = sy + level_ypos; + sx2 = from_x + x * (from_x < to_x2 ? +1 : -1); + sy2 = from_y + y * (from_y < to_y2 ? +1 : -1); + lx = sx2 / 2 + level_xpos; + ly = sy2 / 2 + level_ypos; - if (IN_ED_FIELD(sx, sy) && IN_LEV_FIELD(lx, ly)) - DrawLineElement(sx, sy, element, change_level); + if (IN_ED_FIELD(sx2 / 2, sy2 / 2) && IN_LEV_FIELD(lx, ly)) + DrawLineElement(sx2, sy2, element, change_level); } for (y = 0; y <= radius; y++) { - int sx, sy, lx, ly; + int sx2, sy2, lx, ly; x = (int)(sqrt((float)(radius * radius - y * y)) + 0.5); - sx = from_x + x * (from_x < to_x2 ? +1 : -1); - sy = from_y + y * (from_y < to_y2 ? +1 : -1); - lx = sx + level_xpos; - ly = sy + level_ypos; + sx2 = from_x + x * (from_x < to_x2 ? +1 : -1); + sy2 = from_y + y * (from_y < to_y2 ? +1 : -1); + lx = sx2 / 2 + level_xpos; + ly = sy2 / 2 + level_ypos; - if (IN_ED_FIELD(sx, sy) && IN_LEV_FIELD(lx, ly)) - DrawLineElement(sx, sy, element, change_level); + if (IN_ED_FIELD(sx2 / 2, sy2 / 2) && IN_LEV_FIELD(lx, ly)) + DrawLineElement(sx2, sy2, element, change_level); } } @@ -10864,11 +10942,17 @@ static void DrawAreaBorder(int from_x, int from_y, int to_x, int to_y) redraw_mask |= REDRAW_FIELD; } +static void DrawAreaBox(int from_x, int from_y, int to_x, int to_y, + int element, boolean change_level) +{ + DrawBox(from_x * 2, from_y * 2, to_x * 2, to_y * 2, element, change_level); +} + static void SelectArea(int from_x, int from_y, int to_x, int to_y, int element, boolean change_level) { if (element == -1 || change_level) - DrawBox(from_x, from_y, to_x, to_y, -1, FALSE); + DrawAreaBox(from_x, from_y, to_x, to_y, -1, FALSE); else DrawAreaBorder(from_x, from_y, to_x, to_y); } @@ -10881,6 +10965,11 @@ static void SelectArea(int from_x, int from_y, int to_x, int to_y, #define CB_DUMP_BRUSH 4 #define CB_DUMP_BRUSH_SMALL 5 +static void DrawBrushElement(int sx, int sy, int element, boolean change_level) +{ + DrawLineElement(sx * 2, sy * 2, element, change_level); +} + static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, int button, int mode) { @@ -10953,7 +11042,7 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, brush_buffer[x][y] = Feld[from_lx + x][from_ly + y]; if (button != 1) - DrawLineElement(from_x + x, from_y + y, new_element, TRUE); + DrawBrushElement(from_x + x, from_y + y, new_element, TRUE); } } @@ -11006,7 +11095,7 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, else if (sy > border_to_y) border_to_y = sy; - DrawLineElement(sx, sy, element, change_level); + DrawBrushElement(sx, sy, element, change_level); } } } @@ -11056,6 +11145,28 @@ static void FloodFill(int from_x, int from_y, int fill_element) FloodFillLevel(from_x, from_y, fill_element, Feld, lev_fieldx, lev_fieldy); } +static void FloodFillWall_MM(int from_sx2, int from_sy2, int fill_element) +{ + int from_x = from_sx2 + 2 * level_xpos; + int from_y = from_sy2 + 2 * level_ypos; + int max_fillx = lev_fieldx * 2; + int max_filly = lev_fieldy * 2; + short FillFeld[max_fillx][max_filly]; + int x, y; + + for (x = 0; x < max_fillx; x++) + for (y = 0; y < max_filly; y++) + FillFeld[x][y] = getLevelElementHiRes(x, y); + + FloodFillLevelExt(from_x, from_y, fill_element, max_fillx, max_filly, + FillFeld, max_fillx, max_filly); + + for (x = 0; x < max_fillx; x++) + for (y = 0; y < max_filly; y++) + if (FillFeld[x][y] == fill_element) + SetLevelElementHiRes(x, y, FillFeld[x][y]); +} + /* values for DrawLevelText() modes */ #define TEXT_INIT 0 #define TEXT_SETCURSOR 1 @@ -11322,6 +11433,8 @@ void WrapLevel(int dx, int dy) static void HandleDrawingAreas(struct GadgetInfo *gi) { static boolean started_inside_drawing_area = FALSE; + static int last_sx = -1, last_sy = -1; + static int last_sx2 = -1, last_sy2 = -1; int id = gi->custom_id; int type_id = gi->custom_type_id; boolean button_press_event; @@ -11335,14 +11448,16 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) int min_sx = 0, min_sy = 0; int max_sx = gi->drawing.area_xsize - 1, max_sy = gi->drawing.area_ysize - 1; int item_xsize = gi->drawing.item_xsize, item_ysize = gi->drawing.item_ysize; + int mini_item_xsize = item_xsize / 2, mini_item_ysize = item_ysize / 2; + int sx2 = gi->event.mx / mini_item_xsize; + int sy2 = gi->event.my / mini_item_ysize; + int dx = sx2 % 2; + int dy = sy2 % 2; int lx = 0, ly = 0; int min_lx = 0, min_ly = 0; 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); - button_press_event = (gi->event.type == GD_EVENT_PRESSED); button_release_event = (gi->event.type == GD_EVENT_RELEASED); @@ -11368,6 +11483,39 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) sy = ly - level_ypos; } + /* also correct MM wall-sized (double) drawing area positions accordingly */ + if (sx2 / 2 < sx || sx2 / 2 > sx) + { + sx2 = sx * 2; + dx = (sx2 / 2 < sx ? 0 : 1); + } + if (sy2 / 2 < sy || sy2 / 2 > sy) + { + sy2 = sy * 2; + dy = (sy2 / 2 < sy ? 0 : 1); + } + + if (button_release_event) + { + last_sx = -1; + last_sy = -1; + last_sx2 = -1; + last_sy2 = -1; + } + else if (!button_press_event) + { + /* prevent handling events for every pixel position when moving mouse */ + if ((sx == last_sx && sy == last_sy && + !IS_MM_WALL_EDITOR(new_element) && new_element != EL_EMPTY) || + (sx2 == last_sx2 && sy2 == last_sy2)) + return; + } + + last_sx = sx; + last_sy = sy; + last_sx2 = sx2; + last_sy2 = sy2; + if (button_press_event) started_inside_drawing_area = inside_drawing_area; @@ -11380,6 +11528,9 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) if (!button && !button_release_event) return; + /* handle info callback for each invocation of action callback */ + gi->callback_info(gi); + /* automatically switch to 'single item' drawing mode, if needed */ actual_drawing_function = (draw_level || drawing_function == GADGET_ID_PICK_ELEMENT ? @@ -11430,7 +11581,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) SetElement(x, y, EL_EMPTY); } - SetElementButton(lx, ly, new_element, button); + SetElementButton(lx, ly, dx, dy, new_element, button); } } else if (!button_release_event) @@ -11474,6 +11625,9 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) if (button) { + sx = sx2; + sy = sy2; + if (!button_press_event) DrawLine(last_sx, last_sy, sx, sy, new_element, TRUE); @@ -11487,6 +11641,9 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) case GADGET_ID_ARC: case GADGET_ID_RECTANGLE: case GADGET_ID_FILLED_BOX: + sx = sx2; + sy = sy2; + /* FALLTHROUGH */ case GADGET_ID_GRAB_BRUSH: case GADGET_ID_TEXT: { @@ -11537,6 +11694,8 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) else if (last_sx != sx || last_sy != sy) { draw_func(start_sx, start_sy, last_sx, last_sy, -1, FALSE); + if (IS_MM_WALL_EDITOR(new_element)) /* clear wall background */ + draw_func(start_sx, start_sy, sx, sy, EL_EMPTY, FALSE); draw_func(start_sx, start_sy, sx, sy, new_element, FALSE); last_sx = sx; last_sy = sy; @@ -11547,7 +11706,11 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) case GADGET_ID_FLOOD_FILL: if (button_press_event && Feld[lx][ly] != new_element) { - FloodFill(lx, ly, new_element); + if (IS_MM_WALL_EDITOR(new_element)) + FloodFillWall_MM(sx2, sy2, new_element); + else + FloodFill(lx, ly, new_element); + DrawEditorLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos); CopyLevelToUndoBuffer(UNDO_IMMEDIATE); } @@ -12254,8 +12417,13 @@ static void HandleControlButtons(struct GadgetInfo *gi) InitZoomLevelSettings(); if (edit_mode == ED_MODE_DRAWING) + { DrawDrawingWindow(); + /* redraw zoom gadget info text */ + PrintEditorGadgetInfoText(level_editor_gadget[id]); + } + break; case GADGET_ID_CUSTOM_COPY_FROM: @@ -12741,7 +12909,7 @@ void PrintEditorGadgetInfoText(struct GadgetInfo *gi) else if (gi->custom_id == GADGET_ID_UNDO) sprintf(shortcut, " ('%c/Shift-U')", key); else if (gi->custom_id == GADGET_ID_ZOOM) - sprintf(shortcut, " ('%c', '0', '+')", key); + sprintf(shortcut, " ('%c', '0', '-')", key); else sprintf(shortcut, " ('%s%c')", (key >= 'A' && key <= 'Z' ? "Shift-" : ""), key);