// anim.c
// ============================================================================
+#include "libgame/libgame.h"
+
#include "anim.h"
#include "main.h"
#include "tools.h"
int anim_delay_counter;
int post_delay_counter;
+ boolean init_event_state;
+ boolean anim_event_state;
+
int drawing_stage;
int state;
static int anim_status_last = GAME_MODE_DEFAULT;
static int anim_classes_last = ANIM_CLASS_NONE;
+static boolean drawing_to_fading_buffer = FALSE;
+
+static boolean anim_click_event = FALSE;
+static int anim_click_mx = 0;
+static int anim_click_my = 0;
+
/* ========================================================================= */
/* generic animation frame calculation */
void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage)
{
+ 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 game_mode_anim_action[NUM_GAME_MODES];
int mode_nr;
if (!setup.toons)
return;
- if (drawing_stage == DRAW_GLOBAL_ANIM_STAGE_1)
+ if (drawing_stage == DRAW_GLOBAL_ANIM_STAGE_1 &&
+ drawing_target == DRAW_TO_SCREEN)
DoAnimationExt();
// always start with reliable default values (no animation actions)
int anim_classes_next = game_mode_anim_classes[global.anim_status_next];
int i;
+ if (drawing_target == DRAW_TO_FADE_TARGET)
+ after_fading = TRUE;
+
// ---------- part 1 ------------------------------------------------------
// start or stop global animations by change of game mode
// (special handling of animations for "current screen" and "all screens")
game_mode_anim_action[anim_class_game_mode] = ANIM_START;
}
- if (after_fading)
- anim_classes_last = anim_classes_next;
+ if (drawing_target == DRAW_TO_SCREEN)
+ {
+ if (after_fading)
+ anim_classes_last = anim_classes_next;
- anim_status_last = global.anim_status;
+ anim_status_last = global.anim_status;
- // start or stop animations determined to be started or stopped above
- for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
- if (game_mode_anim_action[mode_nr] != ANIM_NO_ACTION)
- HandleGlobalAnim(game_mode_anim_action[mode_nr], mode_nr);
+ // start or stop animations determined to be started or stopped above
+ for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
+ if (game_mode_anim_action[mode_nr] != ANIM_NO_ACTION)
+ HandleGlobalAnim(game_mode_anim_action[mode_nr], mode_nr);
+ }
+ else if (drawing_target == DRAW_TO_FADE_TARGET)
+ {
+ drawing_to_fading_buffer = TRUE;
+
+ // start animations determined to be (temporary) started above
+ for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
+ if (game_mode_anim_action[mode_nr] == ANIM_START)
+ HandleGlobalAnim(ANIM_START, mode_nr);
+ }
}
if (global.anim_status == GAME_MODE_LOADING)
struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
int anim_nr;
+ // when preparing source fading buffer, only draw animations to be stopped
+ if (drawing_target == DRAW_TO_FADE_SOURCE &&
+ game_mode_anim_action[mode_nr] != ANIM_STOP)
+ continue;
+
+ // when preparing target fading buffer, only draw animations to be started
+ if (drawing_target == DRAW_TO_FADE_TARGET &&
+ game_mode_anim_action[mode_nr] != ANIM_START)
+ continue;
+
#if 0
if (mode_nr != GFX_SPECIAL_ARG_DEFAULT &&
mode_nr != game_status)
src_x += cut_x;
src_y += cut_y;
- BlitToScreenMasked(src_bitmap, src_x, src_y, width, height,
+ if (drawing_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);
}
}
}
+
+ if (drawing_target == DRAW_TO_FADE_TARGET)
+ {
+ // stop animations determined to be (temporary) started above
+ for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
+ if (game_mode_anim_action[mode_nr] == ANIM_START)
+ HandleGlobalAnim(ANIM_STOP, mode_nr);
+
+ drawing_to_fading_buffer = FALSE;
+ }
}
void DrawGlobalAnimations(int drawing_target, int drawing_stage)
static void PlayGlobalAnimSoundAndMusic(struct GlobalAnimPartControlInfo *part)
{
+ // when drawing animations to fading buffer, do not play sounds or music
+ if (drawing_to_fading_buffer)
+ return;
+
PlayGlobalAnimSound(part);
PlayGlobalAnimMusic(part);
}
StopGlobalAnimMusic(part);
}
+static boolean getPartClickEvent(struct GlobalAnimPartControlInfo *part)
+{
+ struct GraphicInfo *g = &part->graphic_info;
+ int part_x = part->viewport_x + part->x;
+ int part_y = part->viewport_y + part->y;
+ int part_width = g->width;
+ int part_height = g->height;
+ int mx = anim_click_mx;
+ int my = anim_click_my;
+
+ // check if mouse click event was detected at all
+ if (!anim_click_event)
+ return FALSE;
+
+ // check if mouse click is inside the animation part's viewport
+ if (mx < part->viewport_x ||
+ mx >= part->viewport_x + part->viewport_width ||
+ my < part->viewport_y ||
+ my >= part->viewport_y + part->viewport_height)
+ return FALSE;
+
+ // check if mouse click is inside the animation part's graphic
+ if (mx < part_x ||
+ mx >= part_x + part_width ||
+ my < part_y ||
+ my >= part_y + part_height)
+ return FALSE;
+
+ return TRUE;
+}
+
int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state)
{
struct GraphicInfo *g = &part->graphic_info;
struct GraphicInfo *c = &part->control_info;
boolean viewport_changed = SetGlobalAnimPart_Viewport(part);
+ boolean part_click_event = getPartClickEvent(part);
if (viewport_changed)
state |= ANIM_STATE_RESTART;
if (state & ANIM_STATE_RESTART)
{
+ // when drawing animations to fading buffer, only start fixed animations
+ if (drawing_to_fading_buffer && (c->x == ARG_UNDEFINED_VALUE ||
+ c->y == ARG_UNDEFINED_VALUE))
+ return ANIM_STATE_INACTIVE;
+
ResetDelayCounterExt(&part->step_delay, anim_sync_frame);
part->init_delay_counter =
part->anim_delay_counter =
(c->anim_delay_fixed + GetSimpleRandom(c->anim_delay_random));
+ part->init_event_state = c->init_event;
+ part->anim_event_state = c->anim_event;
+
part->initial_anim_sync_frame =
(g->anim_global_sync ? 0 : anim_sync_frame + part->init_delay_counter);
if (c->step_yoffset != ARG_UNDEFINED_VALUE)
part->step_yoffset = c->step_yoffset;
- if (part->init_delay_counter == 0)
+ if (part->init_delay_counter == 0 &&
+ part->init_event_state == ANIM_EVENT_NONE)
PlayGlobalAnimSoundAndMusic(part);
}
+ if (part_click_event &&
+ part->init_event_state != ANIM_EVENT_NONE)
+ {
+ if (part->initial_anim_sync_frame > 0)
+ part->initial_anim_sync_frame -= part->init_delay_counter - 1;
+
+ part->init_delay_counter = 1;
+ part->init_event_state = ANIM_EVENT_NONE;
+
+ anim_click_event = FALSE;
+ }
+
+ if (part_click_event &&
+ part->anim_event_state != ANIM_EVENT_NONE)
+ {
+ part->anim_delay_counter = 1;
+ part->anim_event_state = ANIM_EVENT_NONE;
+
+ anim_click_event = FALSE;
+ }
+
if (part->init_delay_counter > 0)
{
part->init_delay_counter--;
if (part->init_delay_counter == 0)
+ {
+ part->init_event_state = ANIM_EVENT_NONE;
+
PlayGlobalAnimSoundAndMusic(part);
+ }
return ANIM_STATE_WAITING;
}
+ if (part->init_event_state != ANIM_EVENT_NONE)
+ return ANIM_STATE_WAITING;
+
// check if moving animation has left the visible screen area
if ((part->x <= -g->width && part->step_xoffset <= 0) ||
(part->x >= part->viewport_width && part->step_xoffset >= 0) ||
(part->y <= -g->height && part->step_yoffset <= 0) ||
(part->y >= part->viewport_height && part->step_yoffset >= 0))
{
+ // do not wait for "anim" events for off-screen animations
+ part->anim_event_state = ANIM_EVENT_NONE;
+
// do not stop animation before "anim" or "post" counter are finished
if (part->anim_delay_counter == 0 &&
part->post_delay_counter == 0)
if (part->anim_delay_counter == 0)
{
+ part->anim_event_state = ANIM_EVENT_NONE;
+
StopGlobalAnimSoundAndMusic(part);
part->post_delay_counter =
for (i = 0; i < NUM_GAME_MODES; i++)
HandleGlobalAnim(ANIM_CONTINUE, i);
-#if 1
+#if 0
// force screen redraw in next frame to continue drawing global animations
redraw_mask = REDRAW_ALL;
#endif
}
+
+void HandleGlobalAnimClicks(int mx, int my, int button)
+{
+ static int last_button = 0;
+ boolean press_event;
+ boolean release_event;
+
+ /* check if button state has changed since last invocation */
+ press_event = (button != 0 && last_button == 0);
+ release_event = (button == 0 && last_button != 0);
+ last_button = button;
+
+ anim_click_mx = mx;
+ anim_click_my = my;
+ anim_click_event = (press_event ? TRUE :
+ release_event ? FALSE : anim_click_event);
+}