X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Ftools.c;h=24fecfb31d478829d2f89bf2e59fa93a93a8e812;hp=a16135cc7926f2a03263daa105742adbf6b04fce;hb=70fe541d68f18a22eb3bd134f128c0d56b885701;hpb=99bfb768ebcf81fe1026fff8492824175e4dd903 diff --git a/src/tools.c b/src/tools.c index a16135cc..24fecfb3 100644 --- a/src/tools.c +++ b/src/tools.c @@ -360,30 +360,26 @@ static int getLevelFromScreenY_SP(int sy) static int getLevelFromScreenX_MM(int sx) { -#if 0 int level_xsize = level.native_mm_level->fieldx; int full_xsize = level_xsize * TILESIZE_VAR; sx -= (full_xsize < SXSIZE ? (SXSIZE - full_xsize) / 2 : 0); -#endif int px = sx - SX; - int lx = px / TILESIZE_VAR; + int lx = (px + TILESIZE_VAR) / TILESIZE_VAR - 1; return lx; } static int getLevelFromScreenY_MM(int sy) { -#if 0 int level_ysize = level.native_mm_level->fieldy; int full_ysize = level_ysize * TILESIZE_VAR; sy -= (full_ysize < SYSIZE ? (SYSIZE - full_ysize) / 2 : 0); -#endif int py = sy - SY; - int ly = py / TILESIZE_VAR; + int ly = (py + TILESIZE_VAR) / TILESIZE_VAR - 1; return ly; } @@ -635,6 +631,64 @@ void DrawMaskedBorderToTarget(int draw_target) } } +void DrawTileCursor(int draw_target) +{ + Bitmap *fade_bitmap; + Bitmap *src_bitmap; + int src_x, src_y; + int dst_x, dst_y; + int graphic = IMG_GLOBAL_TILE_CURSOR; + int frame = 0; + int tilesize = TILESIZE_VAR; + int width = tilesize; + int height = tilesize; + + if (game_status != GAME_MODE_PLAYING) + return; + + if (!tile_cursor.enabled || + !tile_cursor.active) + return; + + if (tile_cursor.moving) + { + int step = TILESIZE_VAR / 4; + int dx = tile_cursor.target_x - tile_cursor.x; + int dy = tile_cursor.target_y - tile_cursor.y; + + if (ABS(dx) < step) + tile_cursor.x = tile_cursor.target_x; + else + tile_cursor.x += SIGN(dx) * step; + + if (ABS(dy) < step) + tile_cursor.y = tile_cursor.target_y; + else + tile_cursor.y += SIGN(dy) * step; + + if (tile_cursor.x == tile_cursor.target_x && + tile_cursor.y == tile_cursor.target_y) + tile_cursor.moving = FALSE; + } + + dst_x = tile_cursor.x; + dst_y = tile_cursor.y; + + frame = getGraphicAnimationFrame(graphic, -1); + + getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y); + + fade_bitmap = + (draw_target == DRAW_TO_FADE_SOURCE ? gfx.fade_bitmap_source : + draw_target == DRAW_TO_FADE_TARGET ? gfx.fade_bitmap_target : NULL); + + if (draw_target == DRAW_TO_SCREEN) + BlitToScreenMasked(src_bitmap, src_x, src_y, width, height, dst_x, dst_y); + else + BlitBitmapMasked(src_bitmap, fade_bitmap, src_x, src_y, width, height, + dst_x, dst_y); +} + void BlitScreenToBitmap_RND(Bitmap *target_bitmap) { int fx = getFieldbufferOffsetX_RND(); @@ -1005,6 +1059,7 @@ void FadeOut(int fade_mask) SetScreenStates_BeforeFadingOut(); + SetTileCursorActive(FALSE); SetOverlayActive(FALSE); #if 0 @@ -1210,6 +1265,8 @@ static int dx_last = -1, dy_last = -1; static int dxsize_last = -1, dysize_last = -1; static int vx_last = -1, vy_last = -1; static int vxsize_last = -1, vysize_last = -1; +static int ex_last = -1, ey_last = -1; +static int exsize_last = -1, eysize_last = -1; boolean CheckIfGlobalBorderHasChanged() { @@ -1252,6 +1309,11 @@ boolean CheckIfGlobalBorderRedrawIsNeeded() vxsize_last != VXSIZE || vysize_last != VYSIZE) return TRUE; + // redraw if position or size of editor area has changed + if (ex_last != EX || ey_last != EY || + exsize_last != EXSIZE || eysize_last != EYSIZE) + return TRUE; + return FALSE; } @@ -1272,20 +1334,29 @@ void RedrawGlobalBorder() redraw_mask = REDRAW_ALL; } +#define ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED 0 + static void RedrawGlobalBorderIfNeeded() { +#if ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED if (game_status == game_status_last) return; +#endif // copy current draw buffer to later copy back areas that have not changed if (game_status_last != GAME_MODE_TITLE) BlitBitmap(backbuffer, bitmap_db_store_1, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); +#if ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED if (CheckIfGlobalBorderRedrawIsNeeded()) +#endif { // redraw global screen border (or clear, if defined to be empty) RedrawGlobalBorderFromBitmap(global_border_bitmap); + if (game_status == GAME_MODE_EDITOR) + DrawSpecialEditorDoor(); + // copy previous playfield and door areas, if they are defined on both // previous and current screen and if they still have the same size @@ -1302,11 +1373,22 @@ static void RedrawGlobalBorderIfNeeded() BlitBitmap(bitmap_db_store_1, backbuffer, dx_last, dy_last, DXSIZE, DYSIZE, DX, DY); - if (vx_last != -1 && vy_last != -1 && - VX != -1 && VY != -1 && - vxsize_last == VXSIZE && vysize_last == VYSIZE) - BlitBitmap(bitmap_db_store_1, backbuffer, - vx_last, vy_last, VXSIZE, VYSIZE, VX, VY); + if (game_status != GAME_MODE_EDITOR) + { + if (vx_last != -1 && vy_last != -1 && + VX != -1 && VY != -1 && + vxsize_last == VXSIZE && vysize_last == VYSIZE) + BlitBitmap(bitmap_db_store_1, backbuffer, + vx_last, vy_last, VXSIZE, VYSIZE, VX, VY); + } + else + { + if (ex_last != -1 && ey_last != -1 && + EX != -1 && EY != -1 && + exsize_last == EXSIZE && eysize_last == EYSIZE) + BlitBitmap(bitmap_db_store_1, backbuffer, + ex_last, ey_last, EXSIZE, EYSIZE, EX, EY); + } redraw_mask = REDRAW_ALL; } @@ -1327,6 +1409,10 @@ static void RedrawGlobalBorderIfNeeded() vy_last = VY; vxsize_last = VXSIZE; vysize_last = VYSIZE; + ex_last = EX; + ey_last = EY; + exsize_last = EXSIZE; + eysize_last = EYSIZE; } void ClearField() @@ -1488,6 +1574,10 @@ void getSizedGraphicSourceExt(int graphic, int frame, int tilesize, { struct GraphicInfo *g = &graphic_info[graphic]; + // if no graphics defined at all, use fallback graphics + if (g->bitmaps == NULL) + *g = graphic_info[IMG_CHAR_EXCLAM]; + // if no in-game graphics defined, always use standard graphic size if (g->bitmaps[IMG_BITMAP_GAME] == NULL) tilesize = TILESIZE; @@ -4095,7 +4185,9 @@ static int RequestHandleEvents(unsigned int req_state) break; case KSYM_Return: + case KSYM_y: #if defined(TARGET_SDL2) + case KSYM_Y: case KSYM_Select: case KSYM_Menu: #if defined(KSYM_Rewind) @@ -4106,7 +4198,9 @@ static int RequestHandleEvents(unsigned int req_state) break; case KSYM_Escape: + case KSYM_n: #if defined(TARGET_SDL2) + case KSYM_N: case KSYM_Back: #if defined(KSYM_FastForward) case KSYM_FastForward: /* for Amazon Fire TV remote */ @@ -4770,7 +4864,7 @@ unsigned int MoveDoor(unsigned int door_state) door_state &= ~DOOR_CLOSE_ALL; } - if (game_status == GAME_MODE_EDITOR) + if (game_status == GAME_MODE_EDITOR && !(door_state & DOOR_FORCE_ANIM)) door_state |= DOOR_NO_DELAY; if (door_state & DOOR_ACTION) @@ -5055,6 +5149,20 @@ unsigned int MoveDoor(unsigned int door_state) if (door_part_done_all) break; } + + if (!(door_state & DOOR_NO_DELAY)) + { + /* wait for specified door action post delay */ + if (door_state & DOOR_ACTION_1 && door_state & DOOR_ACTION_2) + door_delay_value = MAX(door_1.post_delay, door_2.post_delay); + else if (door_state & DOOR_ACTION_1) + door_delay_value = door_1.post_delay; + else if (door_state & DOOR_ACTION_2) + door_delay_value = door_2.post_delay; + + while (!DelayReached(&door_delay, door_delay_value)) + BackToFront(); + } } if (door_state & DOOR_ACTION_1) @@ -5196,7 +5304,8 @@ void CreateToolButtons() for (i = 0; i < NUM_TOOL_BUTTONS; i++) { - struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic]; + int graphic = toolbutton_info[i].graphic; + struct GraphicInfo *gfx = &graphic_info[graphic]; struct TextPosInfo *pos = toolbutton_info[i].pos; struct GadgetInfo *gi; Bitmap *deco_bitmap = None; @@ -5208,11 +5317,49 @@ void CreateToolButtons() int gd_y = gfx->src_y; int gd_xp = gfx->src_x + gfx->pressed_xoffset; int gd_yp = gfx->src_y + gfx->pressed_yoffset; + int x = pos->x; + int y = pos->y; int id = i; if (global.use_envelope_request) + { setRequestPosition(&dx, &dy, TRUE); + // check if request buttons are outside of envelope and fix, if needed + if (x < 0 || x + gfx->width > request.width || + y < 0 || y + gfx->height > request.height) + { + // use left padding of "yes" button as default border padding + int padding = toolbutton_info[TOOL_CTRL_ID_YES].pos->x; + + if (id == TOOL_CTRL_ID_YES) + { + x = padding; + y = request.height - 2 * request.border_size - gfx->height - padding; + } + else if (id == TOOL_CTRL_ID_NO) + { + x = request.width - 2 * request.border_size - gfx->width - padding; + y = request.height - 2 * request.border_size - gfx->height - padding; + } + else if (id == TOOL_CTRL_ID_CONFIRM) + { + x = (request.width - 2 * request.border_size - gfx->width) / 2; + y = request.height - 2 * request.border_size - gfx->height - padding; + } + else if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4) + { + int player_nr = id - TOOL_CTRL_ID_PLAYER_1; + + x = (request.width - 2 * request.border_size - gfx->width) / 2; + y = request.height - 2 * request.border_size - gfx->height - padding; + + x += (player_nr % 2 ? +1 : -1) * gfx->width / 2; + y += (player_nr / 2 ? 0 : -1) * gfx->height; + } + } + } + if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4) { int player_nr = id - TOOL_CTRL_ID_PLAYER_1; @@ -5224,9 +5371,10 @@ void CreateToolButtons() } gi = CreateGadget(GDI_CUSTOM_ID, id, + GDI_IMAGE_ID, graphic, GDI_INFO_TEXT, toolbutton_info[i].infotext, - GDI_X, dx + GDI_ACTIVE_POS(pos->x), - GDI_Y, dy + GDI_ACTIVE_POS(pos->y), + GDI_X, dx + x, + GDI_Y, dy + y, GDI_WIDTH, gfx->width, GDI_HEIGHT, gfx->height, GDI_TYPE, GD_TYPE_NORMAL_BUTTON, @@ -8677,6 +8825,23 @@ void CheckSaveEngineSnapshot_SP(boolean murphy_is_waiting, } } +void CheckSaveEngineSnapshot_MM(boolean element_clicked, + boolean button_released) +{ + if (button_released) + { + if (game.snapshot.mode == SNAPSHOT_MODE_EVERY_MOVE) + CheckSaveEngineSnapshotToList(); + } + else if (element_clicked) + { + if (game.snapshot.mode != SNAPSHOT_MODE_EVERY_MOVE) + CheckSaveEngineSnapshotToList(); + + game.snapshot.changed_action = TRUE; + } +} + void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame, boolean any_player_moving, boolean any_player_snapping, @@ -8707,6 +8872,16 @@ void CheckSingleStepMode_SP(boolean murphy_is_waiting, CheckSaveEngineSnapshot_SP(murphy_is_waiting, murphy_is_dropping); } +void CheckSingleStepMode_MM(boolean element_clicked, + boolean button_released) +{ + if (tape.single_step && tape.recording && !tape.pausing) + if (button_released) + TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); + + CheckSaveEngineSnapshot_MM(element_clicked, button_released); +} + void getGraphicSource_SP(struct GraphicInfo_SP *g_sp, int graphic, int sync_frame, int x, int y) { @@ -8962,6 +9137,31 @@ void ResetFontStatus() SetFontStatus(-1); } +boolean CheckIfPlayfieldViewportHasChanged() +{ + // if game status has not changed, playfield viewport has not changed either + if (game_status == game_status_last) + return FALSE; + + // check if playfield viewport has changed with current game status + struct RectWithBorder *vp_playfield = &viewport.playfield[game_status]; + int new_real_sx = vp_playfield->x; + int new_real_sy = vp_playfield->y; + int new_full_sxsize = vp_playfield->width; + int new_full_sysize = vp_playfield->height; + + return (new_real_sx != REAL_SX || + new_real_sy != REAL_SY || + new_full_sxsize != FULL_SXSIZE || + new_full_sysize != FULL_SYSIZE); +} + +boolean CheckIfGlobalBorderOrPlayfieldViewportHasChanged() +{ + return (CheckIfGlobalBorderHasChanged() || + CheckIfPlayfieldViewportHasChanged()); +} + void ChangeViewportPropertiesIfNeeded() { boolean use_mini_tilesize = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?