added support for fading in and fading out global animations
authorHolger Schemel <info@artsoft.org>
Sun, 19 Nov 2023 13:23:27 +0000 (14:23 +0100)
committerHolger Schemel <info@artsoft.org>
Sun, 19 Nov 2023 13:43:57 +0000 (14:43 +0100)
To fade global animations in or out, use the attribute ".fade_mode"
with value "fade_in" or "fade_out" and the attribute ".fade_delay"
with the number of video frames to use for fading in or out. (Note
that this attribute expects frames when used with global animations,
while it expects milliseconds when used with screens and menus.)

src/anim.c
src/files.c

index 5967bb735525e288e93621c3379ff248c2af75d1..6d761f43b296ce0783c5889aa24472d1844d81e6 100644 (file)
@@ -137,6 +137,9 @@ struct GlobalAnimPartControlInfo
   int anim_delay_counter;
   int post_delay_counter;
 
+  int fade_delay_counter;
+  int fade_alpha;
+
   boolean init_event_state;
   boolean anim_event_state;
 
@@ -735,6 +738,7 @@ static void BlitGlobalAnimation(struct GlobalAnimPartControlInfo *part,
   Bitmap *fade_bitmap =
     (drawing_target == DRAW_TO_FADE_SOURCE ? gfx.fade_bitmap_source :
      drawing_target == DRAW_TO_FADE_TARGET ? gfx.fade_bitmap_target : NULL);
+  int alpha = (c->fade_mode & FADE_MODE_FADE ? part->fade_alpha : g->alpha);
   int x, y;
 
   for (y = 0; y < c->stacked_yfactor; y++)
@@ -781,7 +785,7 @@ static void BlitGlobalAnimation(struct GlobalAnimPartControlInfo *part,
       dst_x += part->viewport_x;
       dst_y += part->viewport_y;
 
-      SetBitmapAlphaNextBlit(src_bitmap, g->alpha);
+      SetBitmapAlphaNextBlit(src_bitmap, alpha);
 
       if (drawing_target == DRAW_TO_SCREEN)
        blit_screen(src_bitmap, src_x, src_y, width, height,
@@ -1537,6 +1541,7 @@ static int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part,
   struct GraphicInfo *g = &part->graphic_info;
   struct GraphicInfo *c = &part->control_info;
   boolean viewport_changed = SetGlobalAnimPart_Viewport(part);
+  int alpha = (g->alpha != -1 ? g->alpha : SDL_ALPHA_OPAQUE);
 
   // if game is paused, also pause playfield and door animations
   if (isPausedOnPlayfieldOrDoor(part))
@@ -1573,6 +1578,18 @@ static int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part,
     if (part->anim_random_frame == -1)
       part->anim_random_frame = GetSimpleRandom(g->anim_frames);
 
+    if (c->fade_mode & FADE_MODE_FADE)
+    {
+      // when fading in screen, first frame is 100 % transparent or opaque
+      part->fade_delay_counter = c->fade_delay + 1;
+      part->fade_alpha = (c->fade_mode == FADE_MODE_FADE_IN ? 0 : alpha);
+    }
+    else
+    {
+      part->fade_delay_counter = 0;
+      part->fade_alpha = -1;
+    }
+
     if (c->direction & MV_HORIZONTAL)
     {
       int pos_bottom = part->viewport_height - g->height;
@@ -1786,6 +1803,14 @@ static int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part,
     return ANIM_STATE_WAITING;
   }
 
+  if (part->fade_delay_counter > 0)
+  {
+    part->fade_delay_counter--;
+    part->fade_alpha = alpha * (c->fade_mode == FADE_MODE_FADE_IN ?
+                               c->fade_delay - part->fade_delay_counter :
+                               part->fade_delay_counter) / c->fade_delay;
+  }
+
   // special case to prevent expiring loop sounds when playing
   PlayGlobalAnimSoundIfLoop(part);
 
index 1514d4e6d864ddc0dc0761257561b8f1f77baa45..c4881f64fff85756c90754a210f51a4dbf834b5b 100644 (file)
@@ -11925,6 +11925,8 @@ int get_parameter_value(char *value_raw, char *suffix, int type)
   {
     result = (string_has_parameter(value, "none")      ? FADE_MODE_NONE :
              string_has_parameter(value, "fade")       ? FADE_MODE_FADE :
+             string_has_parameter(value, "fade_in")    ? FADE_MODE_FADE_IN :
+             string_has_parameter(value, "fade_out")   ? FADE_MODE_FADE_OUT :
              string_has_parameter(value, "crossfade")  ? FADE_MODE_CROSSFADE :
              string_has_parameter(value, "melt")       ? FADE_MODE_MELT :
              string_has_parameter(value, "curtain")    ? FADE_MODE_CURTAIN :