fixed compiler warnings (after adding "-Wmissing-prototypes")
[rocksndiamonds.git] / src / anim.c
index d1ae06a105391ab6b4deda15d2199ce6ec1279fa..cdde423668a441c691c59bc273a558dc090e2047 100644 (file)
@@ -14,6 +14,8 @@
 #include "anim.h"
 #include "main.h"
 #include "tools.h"
+#include "events.h"
+#include "screens.h"
 
 
 /* values for global toon animation definition */
@@ -196,8 +198,8 @@ struct AnimClassGameMode
 /* forward declaration for internal use */
 static void HandleGlobalAnim(int, int);
 static void DoAnimationExt(void);
-static void ResetGlobalAnim_Clickable();
-static void ResetGlobalAnim_Clicked();
+static void ResetGlobalAnim_Clickable(void);
+static void ResetGlobalAnim_Clicked(void);
 
 static struct GlobalAnimControlInfo global_anim_ctrl[NUM_GAME_MODES];
 
@@ -323,7 +325,7 @@ static int compareGlobalAnimMainControlInfo(const void *obj1, const void *obj2)
   return compare_result;
 }
 
-static void InitToonControls()
+static void InitToonControls(void)
 {
   int mode_nr_toons = GAME_MODE_PSEUDO_TOONS;
   struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr_toons];
@@ -405,7 +407,7 @@ static void InitToonControls()
   ctrl->num_anims++;
 }
 
-void InitGlobalAnimControls()
+static void InitGlobalAnimControls(void)
 {
   int i, m, a, p;
   int mode_nr, anim_nr, part_nr;
@@ -566,12 +568,12 @@ void InitGlobalAnimControls()
   anim_classes_last = ANIM_CLASS_NONE;
 }
 
-void InitGlobalAnimations()
+void InitGlobalAnimations(void)
 {
   InitGlobalAnimControls();
 }
 
-void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage)
+static void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage)
 {
   Bitmap *fade_bitmap =
     (drawing_target == DRAW_TO_FADE_SOURCE ? gfx.fade_bitmap_source :
@@ -804,7 +806,7 @@ void DrawGlobalAnimations(int drawing_target, int drawing_stage)
     ResetGlobalAnim_Clicked();
 }
 
-boolean SetGlobalAnimPart_Viewport(struct GlobalAnimPartControlInfo *part)
+static boolean SetGlobalAnimPart_Viewport(struct GlobalAnimPartControlInfo *part)
 {
   int viewport_x;
   int viewport_y;
@@ -915,7 +917,10 @@ static void PlayGlobalAnimMusic(struct GlobalAnimPartControlInfo *part)
   if (!setup.sound_music)
     return;
 
-  PlayMusic(music);
+  if (IS_LOOP_MUSIC(music))
+    PlayMusicLoop(music);
+  else
+    PlayMusic(music);
 
 #if 0
   printf("::: PLAY MUSIC %d.%d.%d: %d\n",
@@ -954,6 +959,28 @@ static void StopGlobalAnimSoundAndMusic(struct GlobalAnimPartControlInfo *part)
   StopGlobalAnimMusic(part);
 }
 
+static void PlayGlobalAnimSoundIfLoop(struct GlobalAnimPartControlInfo *part)
+{
+  // when drawing animations to fading buffer, do not play sounds
+  if (drawing_to_fading_buffer)
+    return;
+
+  // loop sounds only expire when playing
+  if (game_status != GAME_MODE_PLAYING)
+    return;
+
+  // check if any sound is defined for this animation part
+  if (part->sound == SND_UNDEFINED)
+    return;
+
+  // normal (non-loop) sounds do not expire when playing
+  if (!IS_LOOP_SOUND(part->sound))
+    return;
+
+  // prevent expiring loop sounds when playing
+  PlayGlobalAnimSound(part);
+}
+
 static boolean isClickablePart(struct GlobalAnimPartControlInfo *part, int mask)
 {
   struct GraphicInfo *c = &part->control_info;
@@ -1003,7 +1030,13 @@ static boolean isClickedPart(struct GlobalAnimPartControlInfo *part,
   return TRUE;
 }
 
-int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state)
+static boolean clickConsumed(struct GlobalAnimPartControlInfo *part)
+{
+  return (part->control_info.style & STYLE_PASSTHROUGH ? FALSE : TRUE);
+}
+
+static int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part,
+                                int state)
 {
   struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[part->mode_nr];
   struct GlobalAnimMainControlInfo *anim = &ctrl->anim[part->anim_nr];
@@ -1219,6 +1252,9 @@ int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state)
     return ANIM_STATE_WAITING;
   }
 
+  // special case to prevent expiring loop sounds when playing
+  PlayGlobalAnimSoundIfLoop(part);
+
   if (!DelayReachedExt(&part->step_delay, part->step_delay_value,
                       anim_sync_frame))
     return ANIM_STATE_RUNNING;
@@ -1244,7 +1280,8 @@ int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state)
   return ANIM_STATE_RUNNING;
 }
 
-void HandleGlobalAnim_Main(struct GlobalAnimMainControlInfo *anim, int action)
+static void HandleGlobalAnim_Main(struct GlobalAnimMainControlInfo *anim,
+                                 int action)
 {
   struct GlobalAnimPartControlInfo *part;
   struct GraphicInfo *c = &anim->control_info;
@@ -1396,7 +1433,7 @@ void HandleGlobalAnim_Main(struct GlobalAnimMainControlInfo *anim, int action)
   anim->last_active_part_nr = active_part_nr;
 }
 
-void HandleGlobalAnim_Mode(struct GlobalAnimControlInfo *ctrl, int action)
+static void HandleGlobalAnim_Mode(struct GlobalAnimControlInfo *ctrl, int action)
 {
   int i;
 
@@ -1418,7 +1455,7 @@ static void HandleGlobalAnim(int action, int game_mode)
   HandleGlobalAnim_Mode(&global_anim_ctrl[game_mode], action);
 }
 
-static void DoAnimationExt()
+static void DoAnimationExt(void)
 {
   int i;
 
@@ -1445,10 +1482,18 @@ static boolean DoGlobalAnim_EventAction(struct GlobalAnimPartControlInfo *part)
   if (anim_event_action == -1)
     return FALSE;
 
-  return DoGadgetAction(anim_event_action);
+  boolean action_executed = (DoGadgetAction(anim_event_action) ||
+                            DoScreenAction(anim_event_action) ||
+                            DoKeysymAction(anim_event_action));
+
+  // check if further actions are allowed to be executed
+  if (part->control_info.style & STYLE_MULTIPLE_ACTIONS)
+    return FALSE;
+
+  return action_executed;
 }
 
-static void InitGlobalAnim_Clickable()
+static void InitGlobalAnim_Clickable(void)
 {
   int mode_nr;
 
@@ -1476,6 +1521,7 @@ static boolean InitGlobalAnim_Clicked(int mx, int my, boolean clicked)
 {
   boolean anything_clicked = FALSE;
   boolean any_part_clicked = FALSE;
+  boolean any_event_action = FALSE;
   int mode_nr;
 
   // check game modes in reverse draw order (to stop when clicked)
@@ -1510,7 +1556,10 @@ static boolean InitGlobalAnim_Clicked(int mx, int my, boolean clicked)
 
        // always handle "any" click events (clicking anywhere on screen) ...
        if (isClickablePart(part, ANIM_EVENT_ANY))
-         anything_clicked = part->clicked = TRUE;
+       {
+         part->clicked = TRUE;
+         anything_clicked = clickConsumed(part);
+       }
 
        // ... but only handle the first (topmost) clickable animation
        if (any_part_clicked)
@@ -1523,14 +1572,18 @@ static boolean InitGlobalAnim_Clicked(int mx, int my, boolean clicked)
                 part->control_info.anim_event_action);
 #endif
 
-         // after executing event action, force click to be ignored
-         if (DoGlobalAnim_EventAction(part))
-           return TRUE;
+         // after executing event action, ignore any further actions
+         if (!any_event_action && DoGlobalAnim_EventAction(part))
+           any_event_action = TRUE;
 
-         any_part_clicked = TRUE;
+         // determine if mouse clicks should be blocked from other animations
+         any_part_clicked = clickConsumed(part);
 
          if (isClickablePart(part, ANIM_EVENT_SELF))
-           anything_clicked = part->clicked = TRUE;
+         {
+           part->clicked = TRUE;
+           anything_clicked = clickConsumed(part);
+         }
 
          // check if this click is defined to trigger other animations
          int gic_anim_nr = part->old_anim_nr + 1;      // X as in "anim_X"
@@ -1556,16 +1609,17 @@ static boolean InitGlobalAnim_Clicked(int mx, int my, boolean clicked)
 
              if (isClickablePart(part2, mask))
              {
-               anything_clicked = part2->clicked = TRUE;
+               part2->clicked = TRUE;
+               anything_clicked = clickConsumed(part); // click was on "part"!
 
 #if 0
                printf("::: %d.%d TRIGGER CLICKED [%d]\n", anim2_nr, part2_nr,
                       part2->control_info.anim_event_action);
 #endif
 
-               // after executing event action, force click to be ignored
-               if (DoGlobalAnim_EventAction(part2))
-                 return TRUE;
+               // after executing event action, ignore any further actions
+               if (!any_event_action && DoGlobalAnim_EventAction(part2))
+                 any_event_action = TRUE;
              }
 
 #if 0
@@ -1587,15 +1641,15 @@ static boolean InitGlobalAnim_Clicked(int mx, int my, boolean clicked)
     }
   }
 
-  return anything_clicked;
+  return (anything_clicked || any_event_action);
 }
 
-static void ResetGlobalAnim_Clickable()
+static void ResetGlobalAnim_Clickable(void)
 {
   InitGlobalAnim_Clickable();
 }
 
-static void ResetGlobalAnim_Clicked()
+static void ResetGlobalAnim_Clicked(void)
 {
   InitGlobalAnim_Clicked(-1, -1, FALSE);
 }