X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ftools.c;h=10bbe6912a7628454f770afb93d4055f0ac01bf6;hb=6a0abfaaf87f8ae079c0baec627d0a89ae0336cc;hp=3ce90952869b775e0b12b2f7c7dd6136251670e0;hpb=8e3612567b52232c0f1dff593546cb90b396911c;p=rocksndiamonds.git diff --git a/src/tools.c b/src/tools.c index 3ce90952..10bbe691 100644 --- a/src/tools.c +++ b/src/tools.c @@ -334,11 +334,6 @@ void DrawMaskedBorder(int redraw_mask) effectiveGameStatus() == GAME_MODE_TITLE) return; - /* never draw masked screen borders when displaying request outside door */ - if (effectiveGameStatus() == GAME_MODE_PSEUDO_DOOR && - global.use_envelope_request) - return; - if (redraw_mask & REDRAW_ALL) DrawMaskedBorder_ALL(); else @@ -354,9 +349,8 @@ void DrawMaskedBorder(int redraw_mask) } } -static void BlitScreenToBitmap_RND(Bitmap *target_bitmap) +void BlitScreenToBitmap_RND(Bitmap *target_bitmap) { - DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field); int fx = FX, fy = FY; int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0); int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0); @@ -410,23 +404,7 @@ static void BlitScreenToBitmap_RND(Bitmap *target_bitmap) fy = 2 * TILEY_VAR - (EVEN(lev_fieldy) ? TILEY_VAR / 2 : 0); } - if (border.draw_masked[GAME_MODE_PLAYING]) - { - if (buffer != backbuffer) - { - /* copy playfield buffer to backbuffer to add masked border */ - BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY); - DrawMaskedBorder(REDRAW_FIELD); - } - - BlitBitmap(backbuffer, target_bitmap, - REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, - REAL_SX, REAL_SY); - } - else - { - BlitBitmap(buffer, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY); - } + BlitBitmap(drawto_field, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY); } void BlitScreenToBitmap(Bitmap *target_bitmap) @@ -437,106 +415,53 @@ void BlitScreenToBitmap(Bitmap *target_bitmap) BlitScreenToBitmap_SP(target_bitmap); else if (level.game_engine_type == GAME_ENGINE_TYPE_RND) BlitScreenToBitmap_RND(target_bitmap); + + redraw_mask |= REDRAW_FIELD; } -void BackToFront() +void DrawFramesPerSecond() { - DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field); + char text[100]; + int font_nr = FONT_TEXT_2; + int font_width = getFontWidth(font_nr); -#if 0 - /* !!! TEST ONLY !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ - /* (force full redraw) */ - if (game_status == GAME_MODE_PLAYING) - redraw_mask |= REDRAW_FIELD; -#endif + sprintf(text, "%04.1f fps", global.frames_per_second); + + DrawTextExt(backbuffer, WIN_XSIZE - font_width * strlen(text), 0, text, + font_nr, BLIT_OPAQUE); +} +void BackToFront() +{ if (redraw_mask == REDRAW_NONE) return; -#if 0 - printf("::: "); - if (redraw_mask & REDRAW_ALL) - printf("[REDRAW_ALL]"); - if (redraw_mask & REDRAW_FIELD) - printf("[REDRAW_FIELD]"); - if (redraw_mask & REDRAW_DOOR_1) - printf("[REDRAW_DOOR_1]"); - if (redraw_mask & REDRAW_DOOR_2) - printf("[REDRAW_DOOR_2]"); - if (redraw_mask & REDRAW_FROM_BACKBUFFER) - printf("[REDRAW_FROM_BACKBUFFER]"); - printf(" [%d]\n", FrameCounter); -#endif - - if (global.fps_slowdown && game_status == GAME_MODE_PLAYING) - { - static boolean last_frame_skipped = FALSE; - boolean skip_even_when_not_scrolling = TRUE; - boolean just_scrolling = (ScreenMovDir != 0); - boolean verbose = FALSE; - - if (global.fps_slowdown_factor > 1 && - (FrameCounter % global.fps_slowdown_factor) && - (just_scrolling || skip_even_when_not_scrolling)) - { - redraw_mask &= ~REDRAW_MAIN; - - last_frame_skipped = TRUE; - - if (verbose) - printf("FRAME SKIPPED\n"); - } - else - { - if (last_frame_skipped) - redraw_mask |= REDRAW_FIELD; - - last_frame_skipped = FALSE; + // draw masked border to all viewports, if defined + DrawMaskedBorder(redraw_mask); - if (verbose) - printf("frame not skipped\n"); - } - } + // draw frames per second (only if debug mode is enabled) + if (redraw_mask & REDRAW_FPS) + DrawFramesPerSecond(); - /* synchronize X11 graphics at this point; if we would synchronize the - display immediately after the buffer switching (after the XFlush), - this could mean that we have to wait for the graphics to complete, - although we could go on doing calculations for the next frame */ + // redraw complete window if both playfield and (some) doors need redraw + if (redraw_mask & REDRAW_FIELD && redraw_mask & REDRAW_DOORS) + redraw_mask = REDRAW_ALL; - /* SyncDisplay(); */ - - /* never draw masked border to backbuffer when using playfield buffer */ - if (game_status != GAME_MODE_PLAYING || - redraw_mask & REDRAW_FROM_BACKBUFFER || - buffer == backbuffer) - DrawMaskedBorder(redraw_mask); - else - DrawMaskedBorder(redraw_mask & REDRAW_DOORS); + /* although redrawing the whole window would be fine for normal gameplay, + being able to only redraw the playfield is required for deactivating + certain drawing areas (mainly playfield) to work, which is needed for + warp-forward to be fast enough (by skipping redraw of most frames) */ if (redraw_mask & REDRAW_ALL) { BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); - - redraw_mask = REDRAW_NONE; } - - if (redraw_mask & REDRAW_FIELD) + else if (redraw_mask & REDRAW_FIELD) { - if (game_status != GAME_MODE_PLAYING || - redraw_mask & REDRAW_FROM_BACKBUFFER) - { - BlitBitmap(backbuffer, window, - REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY); - } - else - { - BlitScreenToBitmap_RND(window); - } - - redraw_mask &= ~REDRAW_MAIN; + BlitBitmap(backbuffer, window, + REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY); } - - if (redraw_mask & REDRAW_DOORS) + else if (redraw_mask & REDRAW_DOORS) { if (redraw_mask & REDRAW_DOOR_1) BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY); @@ -546,30 +471,6 @@ void BackToFront() if (redraw_mask & REDRAW_DOOR_3) BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY); - - redraw_mask &= ~REDRAW_DOORS; - } - - if (redraw_mask & REDRAW_MICROLEVEL) - { - BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY, - SX, SY + 10 * TILEY); - - redraw_mask &= ~REDRAW_MICROLEVEL; - } - - if (redraw_mask & REDRAW_FPS) /* display frames per second */ - { - char text[100]; - char info1[100]; - - sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor); - if (!global.fps_slowdown) - info1[0] = '\0'; - - sprintf(text, "%04.1f fps%s", global.frames_per_second, info1); - - DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE); } redraw_mask = REDRAW_NONE; @@ -862,7 +763,9 @@ void ClearField() SetDrawtoField(DRAW_FIELDBUFFER); } else + { SetDrawtoField(DRAW_BACKBUFFER); + } } void MarkTileDirty(int x, int y) @@ -2068,7 +1971,7 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action) level.envelope[envelope_nr].autowrap, level.envelope[envelope_nr].centered, FALSE); - redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER; + redraw_mask |= REDRAW_FIELD; BackToFront(); SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame); @@ -2119,13 +2022,57 @@ void ShowEnvelope(int envelope_nr) BackToFront(); } -static void setRequestPosition(int *x, int *y, boolean add_border_size) +static void setRequestBasePosition(int *x, int *y) +{ + int sx_base, sy_base; + + if (request.x != -1) + sx_base = request.x; + else if (request.align == ALIGN_LEFT) + sx_base = SX; + else if (request.align == ALIGN_RIGHT) + sx_base = SX + SXSIZE; + else + sx_base = SX + SXSIZE / 2; + + if (request.y != -1) + sy_base = request.y; + else if (request.valign == VALIGN_TOP) + sy_base = SY; + else if (request.valign == VALIGN_BOTTOM) + sy_base = SY + SYSIZE; + else + sy_base = SY + SYSIZE / 2; + + *x = sx_base; + *y = sy_base; +} + +static void setRequestPositionExt(int *x, int *y, int width, int height, + boolean add_border_size) { int border_size = request.border_size; - int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2); - int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2); - int sx = sx_center - request.width / 2; - int sy = sy_center - request.height / 2; + int sx_base, sy_base; + int sx, sy; + + setRequestBasePosition(&sx_base, &sy_base); + + if (request.align == ALIGN_LEFT) + sx = sx_base; + else if (request.align == ALIGN_RIGHT) + sx = sx_base - width; + else + sx = sx_base - width / 2; + + if (request.valign == VALIGN_TOP) + sy = sy_base; + else if (request.valign == VALIGN_BOTTOM) + sy = sy_base - height; + else + sy = sy_base - height / 2; + + sx = MAX(0, MIN(sx, WIN_XSIZE - width)); + sy = MAX(0, MIN(sy, WIN_YSIZE - height)); if (add_border_size) { @@ -2137,6 +2084,11 @@ static void setRequestPosition(int *x, int *y, boolean add_border_size) *y = sy; } +static void setRequestPosition(int *x, int *y, boolean add_border_size) +{ + setRequestPositionExt(x, y, request.width, request.height, add_border_size); +} + void DrawEnvelopeRequest(char *text) { char *text_final = text; @@ -2225,11 +2177,9 @@ void AnimateEnvelopeRequest(int anim_mode, int action) int anim_delay_value = (no_delay ? 0 : delay_value + 500 * 0) / 2; unsigned int anim_delay = 0; - int width = request.width; - int height = request.height; int tile_size = request.step_offset; - int max_xsize = width / tile_size; - int max_ysize = height / tile_size; + int max_xsize = request.width / tile_size; + int max_ysize = request.height / tile_size; int max_xsize_inner = max_xsize - 2; int max_ysize_inner = max_ysize - 2; @@ -2264,18 +2214,19 @@ void AnimateEnvelopeRequest(int anim_mode, int action) int y = ystart + i * ystep; int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2; int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2; - int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2); - int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2); - int src_x = sx_center - width / 2; - int src_y = sy_center - height / 2; - int dst_x = sx_center - xsize * tile_size / 2; - int dst_y = sy_center - ysize * tile_size / 2; int xsize_size_left = (xsize - 1) * tile_size; int ysize_size_top = (ysize - 1) * tile_size; int max_xsize_pos = (max_xsize - 1) * tile_size; int max_ysize_pos = (max_ysize - 1) * tile_size; + int width = xsize * tile_size; + int height = ysize * tile_size; + int src_x, src_y; + int dst_x, dst_y; int xx, yy; + setRequestPosition(&src_x, &src_y, FALSE); + setRequestPositionExt(&dst_x, &dst_y, width, height, FALSE); + BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); for (yy = 0; yy < 2; yy++) @@ -2298,7 +2249,7 @@ void AnimateEnvelopeRequest(int anim_mode, int action) } } - redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER; + redraw_mask |= REDRAW_FIELD; DoAnimation(); BackToFront(); @@ -2307,14 +2258,15 @@ void AnimateEnvelopeRequest(int anim_mode, int action) } } - void ShowEnvelopeRequest(char *text, unsigned int req_state, int action) { int last_game_status = game_status; /* save current game status */ int graphic = IMG_BACKGROUND_REQUEST; int sound_opening = SND_REQUEST_OPENING; int sound_closing = SND_REQUEST_CLOSING; - int anim_mode = graphic_info[graphic].anim_mode; + int anim_mode_1 = request.anim_mode; /* (higher priority) */ + int anim_mode_2 = graphic_info[graphic].anim_mode; /* (lower priority) */ + int anim_mode = (anim_mode_1 != ANIM_DEFAULT ? anim_mode_1 : anim_mode_2); int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL: anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode); @@ -2491,7 +2443,7 @@ static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y) } } - redraw_mask |= REDRAW_MICROLEVEL; + redraw_mask |= REDRAW_FIELD; } #define MICROLABEL_EMPTY 0 @@ -2560,7 +2512,7 @@ static void DrawPreviewLevelLabelExt(int mode) if (strlen(label_text) > 0) DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align); - redraw_mask |= REDRAW_MICROLEVEL; + redraw_mask |= REDRAW_FIELD; } static void DrawPreviewLevelExt(boolean restart) @@ -3276,9 +3228,15 @@ void WaitForEventToContinue() static int RequestHandleEvents(unsigned int req_state) { + boolean level_solved = (game_status == GAME_MODE_PLAYING && + local_player->LevelSolved_GameEnd); int last_game_status = game_status; /* save current game status */ + int width = request.width; + int height = request.height; + int sx, sy; int result; - int mx, my; + + setRequestPosition(&sx, &sy, FALSE); button_status = MB_RELEASED; @@ -3287,6 +3245,21 @@ static int RequestHandleEvents(unsigned int req_state) while (result < 0) { + if (level_solved) + { + SetDrawtoField(DRAW_FIELDBUFFER); + + HandleGameActions(); + + SetDrawtoField(DRAW_BACKBUFFER); + + if (global.use_envelope_request) + { + /* copy current state of request area to middle of playfield area */ + BlitBitmap(bitmap_db_cross, drawto, sx, sy, width, height, sx, sy); + } + } + if (PendingEvent()) { Event event; @@ -3299,11 +3272,10 @@ static int RequestHandleEvents(unsigned int req_state) case EVENT_BUTTONRELEASE: case EVENT_MOTIONNOTIFY: { + int mx, my; + if (event.type == EVENT_MOTIONNOTIFY) { - if (!PointerInWindow(window)) - continue; /* window and pointer on different screens */ - if (!button_status) continue; @@ -3407,9 +3379,13 @@ static int RequestHandleEvents(unsigned int req_state) result = 0; } - if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd) + if (level_solved) { - HandleGameActions(); + if (global.use_envelope_request) + { + /* copy back current state of pressed buttons inside request area */ + BlitBitmap(drawto, bitmap_db_cross, sx, sy, width, height, sx, sy); + } } else {