X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Ftools.c;h=3cf3b9609618d50b46346dba54d7bed7c7f32937;hp=61b4c4cb420347554d384de6c1687b92ea40162d;hb=7ecbe0a730dc19d8a46ffe6bbcb052f20d0c4152;hpb=fb2947925e0e990825ded896d29b20296c950ab1 diff --git a/src/tools.c b/src/tools.c index 61b4c4cb..3cf3b960 100644 --- a/src/tools.c +++ b/src/tools.c @@ -227,7 +227,7 @@ void DumpTile(int x, int y) printf(" CustomValue: %d\n", CustomValue[x][y]); printf(" GfxElement: %d\n", GfxElement[x][y]); printf(" GfxAction: %d\n", GfxAction[x][y]); - printf(" GfxFrame: %d\n", GfxFrame[x][y]); + printf(" GfxFrame: %d [%d]\n", GfxFrame[x][y], FrameCounter); printf("\n"); } @@ -286,7 +286,7 @@ void RedrawPlayfield() void DrawMaskedBorder_Rect(int x, int y, int width, int height) { - Bitmap *bitmap = graphic_info[IMG_GLOBAL_BORDER].bitmap; + Bitmap *bitmap = getGlobalBorderBitmapFromGameStatus(); BlitBitmapMasked(bitmap, backbuffer, x, y, width, height, x, y); } @@ -330,13 +330,8 @@ void DrawMaskedBorder_ALL() void DrawMaskedBorder(int redraw_mask) { /* never draw masked screen borders on borderless screens */ - if (effectiveGameStatus() == GAME_MODE_LOADING || - 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) + if (game_status == GAME_MODE_LOADING || + game_status == GAME_MODE_TITLE) return; if (redraw_mask & REDRAW_ALL) @@ -356,7 +351,6 @@ void DrawMaskedBorder(int redraw_mask) 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,7 +404,7 @@ void BlitScreenToBitmap_RND(Bitmap *target_bitmap) fy = 2 * TILEY_VAR - (EVEN(lev_fieldy) ? TILEY_VAR / 2 : 0); } - 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) @@ -421,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_OLD() +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; - - if (verbose) - printf("frame not skipped\n"); - } - } + // draw masked border to all viewports, if defined + DrawMaskedBorder(redraw_mask); - /* 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 */ + // draw frames per second (only if debug mode is enabled) + if (redraw_mask & REDRAW_FPS) + DrawFramesPerSecond(); - /* SyncDisplay(); */ + // redraw complete window if both playfield and (some) doors need redraw + if (redraw_mask & REDRAW_FIELD && redraw_mask & REDRAW_DOORS) + redraw_mask = REDRAW_ALL; - /* 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); @@ -530,52 +471,24 @@ void BackToFront_OLD() 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; } -void BackToFront() +static void FadeCrossSaveBackbuffer() { - if (redraw_mask == REDRAW_NONE) - return; - - // draw masked border to all viewports, if defined - DrawMaskedBorder(redraw_mask); - - // blit backbuffer to visible screen - BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); - - redraw_mask = REDRAW_NONE; + BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); } -static void FadeCrossSaveBackbuffer() +static void FadeCrossRestoreBackbuffer() { - BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + int redraw_mask_last = redraw_mask; + + BlitBitmap(bitmap_db_cross, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + + // do not change redraw mask when restoring backbuffer after cross-fading + redraw_mask = redraw_mask_last; } static void FadeExt(int fade_mask, int fade_mode, int fade_type) @@ -597,9 +510,15 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type) return; } +#if 1 + FadeCrossSaveBackbuffer(); +#endif + if (fading.fade_mode & FADE_TYPE_TRANSFORM) { +#if 0 FadeCrossSaveBackbuffer(); +#endif return; } @@ -633,10 +552,10 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type) if (fade_mask == REDRAW_FIELD) { - x = REAL_SX; - y = REAL_SY; - width = FULL_SXSIZE; - height = FULL_SYSIZE; + x = FADE_SX; + y = FADE_SY; + width = FADE_SXSIZE; + height = FADE_SYSIZE; if (border.draw_masked_when_fading) draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */ @@ -668,6 +587,9 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type) FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay, draw_border_function); + if (fade_type == FADE_TYPE_FADE_OUT) + FadeCrossRestoreBackbuffer(); + redraw_mask &= ~fade_mask; } @@ -677,6 +599,11 @@ void FadeIn(int fade_mask) FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN); else FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN); + + FADE_SX = REAL_SX; + FADE_SY = REAL_SY; + FADE_SXSIZE = FULL_SXSIZE; + FADE_SYSIZE = FULL_SYSIZE; } void FadeOut(int fade_mask) @@ -760,6 +687,39 @@ void FadeSkipNextFadeOut() FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP); } +Bitmap *getBitmapFromGraphicOrDefault(int graphic, int default_graphic) +{ + boolean redefined = getImageListEntryFromImageID(graphic)->redefined; + + return (graphic == IMG_UNDEFINED ? NULL : + graphic_info[graphic].bitmap != NULL || redefined ? + graphic_info[graphic].bitmap : + graphic_info[default_graphic].bitmap); +} + +Bitmap *getBackgroundBitmap(int graphic) +{ + return getBitmapFromGraphicOrDefault(graphic, IMG_BACKGROUND); +} + +Bitmap *getGlobalBorderBitmap(int graphic) +{ + return getBitmapFromGraphicOrDefault(graphic, IMG_GLOBAL_BORDER); +} + +Bitmap *getGlobalBorderBitmapFromGameStatus() +{ + int graphic = + (game_status == GAME_MODE_MAIN || + game_status == GAME_MODE_PSEUDO_TYPENAME ? IMG_GLOBAL_BORDER_MAIN : + game_status == GAME_MODE_SCORES ? IMG_GLOBAL_BORDER_SCORES : + game_status == GAME_MODE_EDITOR ? IMG_GLOBAL_BORDER_EDITOR : + game_status == GAME_MODE_PLAYING ? IMG_GLOBAL_BORDER_PLAYING : + IMG_GLOBAL_BORDER); + + return getGlobalBorderBitmap(graphic); +} + void SetWindowBackgroundImageIfDefined(int graphic) { if (graphic_info[graphic].bitmap) @@ -780,26 +740,17 @@ void SetDoorBackgroundImageIfDefined(int graphic) void SetWindowBackgroundImage(int graphic) { - SetWindowBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL : - graphic_info[graphic].bitmap ? - graphic_info[graphic].bitmap : - graphic_info[IMG_BACKGROUND].bitmap); + SetWindowBackgroundBitmap(getBackgroundBitmap(graphic)); } void SetMainBackgroundImage(int graphic) { - SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL : - graphic_info[graphic].bitmap ? - graphic_info[graphic].bitmap : - graphic_info[IMG_BACKGROUND].bitmap); + SetMainBackgroundBitmap(getBackgroundBitmap(graphic)); } void SetDoorBackgroundImage(int graphic) { - SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL : - graphic_info[graphic].bitmap ? - graphic_info[graphic].bitmap : - graphic_info[IMG_BACKGROUND].bitmap); + SetDoorBackgroundBitmap(getBackgroundBitmap(graphic)); } void SetPanelBackground() @@ -847,8 +798,137 @@ void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic) DrawBackground(x, y, width, height); } +static int game_status_last = -1; +static Bitmap *global_border_bitmap_last = NULL; +static Bitmap *global_border_bitmap = NULL; +static int real_sx_last = -1, real_sy_last = -1; +static int full_sxsize_last = -1, full_sysize_last = -1; +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; + +boolean CheckIfGlobalBorderHasChanged() +{ + // if game status has not changed, global border has not changed either + if (game_status == game_status_last) + return FALSE; + + // determine and store new global border bitmap for current game status + global_border_bitmap = getGlobalBorderBitmapFromGameStatus(); + + return (global_border_bitmap_last != global_border_bitmap); +} + +boolean CheckIfGlobalBorderRedrawIsNeeded() +{ + // if game status has not changed, nothing has to be redrawn + if (game_status == game_status_last) + return FALSE; + + // redraw if last screen was title screen + if (game_status_last == GAME_MODE_TITLE) + return TRUE; + + // redraw if global screen border has changed + if (CheckIfGlobalBorderHasChanged()) + return TRUE; + + // redraw if position or size of playfield area has changed + if (real_sx_last != REAL_SX || real_sy_last != REAL_SY || + full_sxsize_last != FULL_SXSIZE || full_sysize_last != FULL_SYSIZE) + return TRUE; + + // redraw if position or size of door area has changed + if (dx_last != DX || dy_last != DY || + dxsize_last != DXSIZE || dysize_last != DYSIZE) + return TRUE; + + // redraw if position or size of tape area has changed + if (vx_last != VX || vy_last != VY || + vxsize_last != VXSIZE || vysize_last != VYSIZE) + return TRUE; + + return FALSE; +} + +void RedrawGlobalBorderFromBitmap(Bitmap *bitmap) +{ + if (bitmap) + BlitBitmap(bitmap, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + else + ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE); +} + +void RedrawGlobalBorder() +{ + Bitmap *bitmap = getGlobalBorderBitmapFromGameStatus(); + + RedrawGlobalBorderFromBitmap(bitmap); + + redraw_mask = REDRAW_ALL; +} + +static void RedrawGlobalBorderIfNeeded() +{ + if (game_status == game_status_last) + return; + + // copy current draw buffer to later copy back areas that have not changed + BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + + if (CheckIfGlobalBorderRedrawIsNeeded()) + { + // redraw global screen border (or clear, if defined to be empty) + RedrawGlobalBorderFromBitmap(global_border_bitmap); + + // copy previous playfield and door areas, if they are defined on both + // previous and current screen and if they still have the same size + + if (real_sx_last != -1 && real_sy_last != -1 && + REAL_SX != -1 && REAL_SY != -1 && + full_sxsize_last == FULL_SXSIZE && full_sysize_last == FULL_SYSIZE) + BlitBitmap(bitmap_db_store, backbuffer, + real_sx_last, real_sy_last, FULL_SXSIZE, FULL_SYSIZE, + REAL_SX, REAL_SY); + + if (dx_last != -1 && dy_last != -1 && + DX != -1 && DY != -1 && + dxsize_last == DXSIZE && dysize_last == DYSIZE) + BlitBitmap(bitmap_db_store, 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, backbuffer, + vx_last, vy_last, VXSIZE, VYSIZE, VX, VY); + + redraw_mask = REDRAW_ALL; + } + + game_status_last = game_status; + + global_border_bitmap_last = global_border_bitmap; + + real_sx_last = REAL_SX; + real_sy_last = REAL_SY; + full_sxsize_last = FULL_SXSIZE; + full_sysize_last = FULL_SYSIZE; + dx_last = DX; + dy_last = DY; + dxsize_last = DXSIZE; + dysize_last = DYSIZE; + vx_last = VX; + vy_last = VY; + vxsize_last = VXSIZE; + vysize_last = VYSIZE; +} + void ClearField() { + RedrawGlobalBorderIfNeeded(); + /* !!! "drawto" might still point to playfield buffer here (see above) !!! */ /* (when entering hall of fame after playing) */ DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE); @@ -860,7 +940,9 @@ void ClearField() SetDrawtoField(DRAW_FIELDBUFFER); } else + { SetDrawtoField(DRAW_BACKBUFFER); + } } void MarkTileDirty(int x, int y) @@ -925,7 +1007,7 @@ void SetRandomAnimationValue(int x, int y) gfx.anim_random_frame = GfxRandom[x][y]; } -inline int getGraphicAnimationFrame(int graphic, int sync_frame) +int getGraphicAnimationFrame(int graphic, int sync_frame) { /* animation synchronized with global frame counter, not move position */ if (graphic_info[graphic].anim_global_sync || sync_frame < 0) @@ -1010,8 +1092,8 @@ void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y) getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y); } -inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap, - int *x, int *y, boolean get_backside) +inline static void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap, + int *x, int *y, boolean get_backside) { struct GraphicInfo *g = &graphic_info[graphic]; int src_x = g->src_x + (get_backside ? g->offset2_x : 0); @@ -2066,7 +2148,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); @@ -2117,25 +2199,57 @@ void ShowEnvelope(int envelope_nr) BackToFront(); } -static void setRequestCenterPosition(int *x, int *y) +static void setRequestBasePosition(int *x, int *y) { - int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2); - int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2); + int sx_base, sy_base; - *x = sx_center; - *y = sy_center; + 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 setRequestPosition(int *x, int *y, boolean add_border_size) +static void setRequestPositionExt(int *x, int *y, int width, int height, + boolean add_border_size) { int border_size = request.border_size; - int sx_center, sy_center; + int sx_base, sy_base; int sx, sy; - setRequestCenterPosition(&sx_center, &sy_center); + 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 = sx_center - request.width / 2; - sy = sy_center - request.height / 2; + sx = MAX(0, MIN(sx, WIN_XSIZE - width)); + sy = MAX(0, MIN(sy, WIN_YSIZE - height)); if (add_border_size) { @@ -2147,8 +2261,14 @@ 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) { + int last_game_status = game_status; /* save current game status */ char *text_final = text; char *text_door_style = NULL; int graphic = IMG_BACKGROUND_REQUEST; @@ -2160,19 +2280,25 @@ void DrawEnvelopeRequest(char *text) int border_size = request.border_size; int line_spacing = request.line_spacing; int line_height = font_height + line_spacing; - int text_width = request.width - 2 * border_size; - int text_height = request.height - 2 * border_size; - int line_length = text_width / font_width; - int max_lines = text_height / line_height; + int max_text_width = request.width - 2 * border_size; + int max_text_height = request.height - 2 * border_size; + int line_length = max_text_width / font_width; + int max_lines = max_text_height / line_height; + int text_width = line_length * font_width; int width = request.width; int height = request.height; - int tile_size = request.step_offset; + int tile_size = MAX(request.step_offset, 1); int x_steps = width / tile_size; int y_steps = height / tile_size; + int sx_offset = border_size; + int sy_offset = border_size; int sx, sy; int i, x, y; - if (request.wrap_single_words) + if (request.centered) + sx_offset = (request.width - text_width) / 2; + + if (request.wrap_single_words && !request.autowrap) { char *src_text_ptr, *dst_text_ptr; @@ -2209,10 +2335,15 @@ void DrawEnvelopeRequest(char *text) x, y, x_steps, y_steps, tile_size, tile_size); - DrawTextBuffer(sx + border_size, sy + border_size, text_final, font_nr, + /* force DOOR font inside door area */ + game_status = GAME_MODE_PSEUDO_DOOR; + + DrawTextBuffer(sx + sx_offset, sy + sy_offset, text_final, font_nr, line_length, -1, max_lines, line_spacing, mask_mode, request.autowrap, request.centered, FALSE); + game_status = last_game_status; /* restore current game status */ + for (i = 0; i < NUM_TOOL_BUTTONS; i++) RedrawGadget(tool_gadget[i]); @@ -2235,11 +2366,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 tile_size = MAX(request.step_offset, 1); + 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; @@ -2278,17 +2407,14 @@ void AnimateEnvelopeRequest(int anim_mode, int action) 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 sx_center, sy_center; + int width = xsize * tile_size; + int height = ysize * tile_size; int src_x, src_y; int dst_x, dst_y; int xx, yy; - setRequestCenterPosition(&sx_center, &sy_center); - - src_x = sx_center - width / 2; - src_y = sy_center - height / 2; - dst_x = sx_center - xsize * tile_size / 2; - dst_y = sy_center - ysize * tile_size / 2; + 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); @@ -2312,7 +2438,7 @@ void AnimateEnvelopeRequest(int anim_mode, int action) } } - redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER; + redraw_mask |= REDRAW_FIELD; DoAnimation(); BackToFront(); @@ -2321,14 +2447,14 @@ 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); @@ -2366,9 +2492,6 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action) InitAnimation(); } - /* force DOOR font inside door area */ - game_status = GAME_MODE_PSEUDO_DOOR; - game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */ if (action == ACTION_OPENING) @@ -2393,8 +2516,6 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action) game.envelope_active = FALSE; - game_status = last_game_status; /* restore current game status */ - if (action == ACTION_CLOSING) { if (game_status != GAME_MODE_MAIN) @@ -2505,7 +2626,7 @@ static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y) } } - redraw_mask |= REDRAW_MICROLEVEL; + redraw_mask |= REDRAW_FIELD; } #define MICROLABEL_EMPTY 0 @@ -2574,7 +2695,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) @@ -2748,8 +2869,9 @@ void DrawPreviewLevelAnimation() DrawPreviewLevelExt(FALSE); } -inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y, - int graphic, int sync_frame, int mask_mode) +inline static void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y, + int graphic, int sync_frame, + int mask_mode) { int frame = getGraphicAnimationFrame(graphic, sync_frame); @@ -2759,9 +2881,8 @@ inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y, DrawGraphicExt(dst_bitmap, x, y, graphic, frame); } -inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y, - int graphic, int sync_frame, - int mask_mode) +void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y, + int graphic, int sync_frame, int mask_mode) { int frame = getGraphicAnimationFrame(graphic, sync_frame); @@ -2771,7 +2892,7 @@ inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y, DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame); } -inline void DrawGraphicAnimation(int x, int y, int graphic) +inline static void DrawGraphicAnimation(int x, int y, int graphic) { int lx = LEVELX(x), ly = LEVELY(y); @@ -2784,7 +2905,7 @@ inline void DrawGraphicAnimation(int x, int y, int graphic) MarkTileDirty(x, y); } -inline void DrawFixedGraphicAnimation(int x, int y, int graphic) +void DrawFixedGraphicAnimation(int x, int y, int graphic) { int lx = LEVELX(x), ly = LEVELY(y); @@ -2808,7 +2929,7 @@ void DrawLevelElementAnimation(int x, int y, int element) DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic); } -inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic) +void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic) { int sx = SCREENX(x), sy = SCREENY(y); @@ -3292,7 +3413,6 @@ 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; @@ -3457,11 +3577,7 @@ static int RequestHandleEvents(unsigned int req_state) Delay(10); } - game_status = GAME_MODE_PSEUDO_DOOR; - BackToFront(); - - game_status = last_game_status; /* restore current game status */ } return result; @@ -4239,6 +4355,9 @@ unsigned int MoveDoor(unsigned int door_state) width = g->width - src_xx; + if (width > door_rect->width) + width = door_rect->width; + // printf("::: k == %d [%d] \n", k, start_step); } @@ -4325,6 +4444,29 @@ unsigned int MoveDoor(unsigned int door_state) return (door1 | door2); } +static boolean useSpecialEditorDoor() +{ + int graphic = IMG_GLOBAL_BORDER_EDITOR; + boolean redefined = getImageListEntryFromImageID(graphic)->redefined; + + // do not draw special editor door if editor border defined or redefined + if (graphic_info[graphic].bitmap != NULL || redefined) + return FALSE; + + // do not draw special editor door if global border defined to be empty + if (graphic_info[IMG_GLOBAL_BORDER].bitmap == NULL) + return FALSE; + + // do not draw special editor door if viewport definitions do not match + if (EX != VX || + EY >= VY || + EXSIZE != VXSIZE || + EY + EYSIZE != VY + VYSIZE) + return FALSE; + + return TRUE; +} + void DrawSpecialEditorDoor() { struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION]; @@ -4336,6 +4478,9 @@ void DrawSpecialEditorDoor() int vy = VY - outer_border; int exsize = EXSIZE + 2 * outer_border; + if (!useSpecialEditorDoor()) + return; + /* draw bigger level editor toolbox window */ BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y, top_border_width, top_border_height, ex, ey - top_border_height); @@ -4357,6 +4502,9 @@ void UndrawSpecialEditorDoor() int exsize = EXSIZE + 2 * outer_border; int eysize = EYSIZE + 2 * outer_border; + if (!useSpecialEditorDoor()) + return; + /* draw normal tape recorder window */ if (graphic_info[IMG_GLOBAL_BORDER].bitmap) { @@ -7976,15 +8124,31 @@ void ToggleFullscreenOrChangeWindowScalingIfNeeded() } } +void JoinRectangles(int *x, int *y, int *width, int *height, + int x2, int y2, int width2, int height2) +{ + // do not join with "off-screen" rectangle + if (x2 == -1 || y2 == -1) + return; + + *x = MIN(*x, x2); + *y = MIN(*y, y2); + *width = MAX(*width, width2); + *height = MAX(*height, height2); +} + void ChangeViewportPropertiesIfNeeded() { int gfx_game_mode = game_status; int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT : game_status); + struct RectWithBorder *vp_window = &viewport.window[gfx_game_mode]; struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode]; - struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode]; - struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode2]; - struct RectWithBorder *vp_door_3 = &viewport.door_2[GAME_MODE_EDITOR]; + struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode]; + struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode2]; + struct RectWithBorder *vp_door_3 = &viewport.door_2[GAME_MODE_EDITOR]; + int new_win_xsize = vp_window->width; + int new_win_ysize = vp_window->height; int border_size = vp_playfield->border_size; int new_sx = vp_playfield->x + border_size; int new_sy = vp_playfield->y + border_size; @@ -8019,13 +8183,12 @@ void ChangeViewportPropertiesIfNeeded() boolean init_video_buffer = FALSE; boolean init_gadgets_and_toons = FALSE; boolean init_em_graphics = FALSE; - boolean drawing_area_changed = FALSE; - if (viewport.window.width != WIN_XSIZE || - viewport.window.height != WIN_YSIZE) + if (new_win_xsize != WIN_XSIZE || + new_win_ysize != WIN_YSIZE) { - WIN_XSIZE = viewport.window.width; - WIN_YSIZE = viewport.window.height; + WIN_XSIZE = new_win_xsize; + WIN_YSIZE = new_win_ysize; init_video_buffer = TRUE; init_gfx_buffers = TRUE; @@ -8067,6 +8230,48 @@ void ChangeViewportPropertiesIfNeeded() new_tilesize_var != TILESIZE_VAR ) { + // ------------------------------------------------------------------------ + // determine next fading area for changed viewport definitions + // ------------------------------------------------------------------------ + + // start with current playfield area (default fading area) + FADE_SX = REAL_SX; + FADE_SY = REAL_SY; + FADE_SXSIZE = FULL_SXSIZE; + FADE_SYSIZE = FULL_SYSIZE; + + // add new playfield area if position or size has changed + if (new_real_sx != REAL_SX || new_real_sy != REAL_SY || + new_full_sxsize != FULL_SXSIZE || new_full_sysize != FULL_SYSIZE) + { + JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE, + new_real_sx, new_real_sy, new_full_sxsize,new_full_sysize); + } + + // add current and new door 1 area if position or size has changed + if (new_dx != DX || new_dy != DY || + new_dxsize != DXSIZE || new_dysize != DYSIZE) + { + JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE, + DX, DY, DXSIZE, DYSIZE); + JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE, + new_dx, new_dy, new_dxsize, new_dysize); + } + + // add current and new door 2 area if position or size has changed + if (new_dx != VX || new_dy != VY || + new_dxsize != VXSIZE || new_dysize != VYSIZE) + { + JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE, + VX, VY, VXSIZE, VYSIZE); + JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE, + new_vx, new_vy, new_vxsize, new_vysize); + } + + // ------------------------------------------------------------------------ + // handle changed tile size + // ------------------------------------------------------------------------ + if (new_tilesize_var != TILESIZE_VAR) { // printf("::: new_tilesize_var != TILESIZE_VAR\n"); @@ -8078,19 +8283,6 @@ void ChangeViewportPropertiesIfNeeded() init_em_graphics = TRUE; } - if (new_sx != SX || - new_sy != SY || - new_sxsize != SXSIZE || - new_sysize != SYSIZE || - new_real_sx != REAL_SX || - new_real_sy != REAL_SY || - new_full_sxsize != FULL_SXSIZE || - new_full_sysize != FULL_SYSIZE) - { - if (!init_video_buffer) - drawing_area_changed = TRUE; - } - SX = new_sx; SY = new_sy; DX = new_dx; @@ -8132,8 +8324,6 @@ void ChangeViewportPropertiesIfNeeded() SCR_FIELDX = new_scr_fieldx; SCR_FIELDY = new_scr_fieldy; - gfx.drawing_area_changed = drawing_area_changed; - SetDrawDeactivationMask(REDRAW_NONE); SetDrawBackgroundMask(REDRAW_FIELD); }