// 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 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 */
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;
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 =
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);
+}
void InitGlobalAnimations(void);
void DrawGlobalAnimations(int, int);
+void HandleGlobalAnimClicks(int, int, int);
+
#endif
{ ".anim_delay_random", ARG_UNDEFINED, TYPE_INTEGER },
{ ".post_delay_fixed", ARG_UNDEFINED, TYPE_INTEGER },
{ ".post_delay_random", ARG_UNDEFINED, TYPE_INTEGER },
+ { ".init_event", ARG_UNDEFINED, TYPE_STRING },
+ { ".anim_event", ARG_UNDEFINED, TYPE_STRING },
{ ".name", ARG_UNDEFINED, TYPE_STRING },
{ ".scale_up_factor", ARG_UNDEFINED, TYPE_INTEGER },
{ ".tile_size", ARG_UNDEFINED, TYPE_INTEGER },
}
#endif
+ HandleGlobalAnimClicks(mx, my, button);
+
if (button_hold && game_status == GAME_MODE_PLAYING && tape.pausing)
return;
g->anim_delay_random = 0;
g->post_delay_fixed = 0;
g->post_delay_random = 0;
+ g->init_event = ANIM_EVENT_DEFAULT;
+ g->anim_event = ANIM_EVENT_DEFAULT;
g->draw_order = 0;
g->fade_mode = FADE_MODE_DEFAULT;
g->fade_delay = -1;
if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
g->post_delay_random = parameter[GFX_ARG_POST_DELAY_RANDOM];
+ /* used for global animations */
+ if (parameter[GFX_ARG_INIT_EVENT] != ARG_UNDEFINED_VALUE)
+ g->init_event = parameter[GFX_ARG_INIT_EVENT];
+ if (parameter[GFX_ARG_ANIM_EVENT] != ARG_UNDEFINED_VALUE)
+ g->anim_event = parameter[GFX_ARG_ANIM_EVENT];
+
/* used for toon animations and global animations */
g->step_offset = parameter[GFX_ARG_STEP_OFFSET];
g->step_xoffset = parameter[GFX_ARG_STEP_XOFFSET];
if (string_has_parameter(value, "static_panel"))
result |= ANIM_STATIC_PANEL;
}
+ else if (strEqual(suffix, ".init_event") ||
+ strEqual(suffix, ".anim_event"))
+ {
+ result = ANIM_EVENT_DEFAULT;
+
+ if (string_has_parameter(value, "click"))
+ result |= ANIM_EVENT_CLICK;
+ }
else if (strEqual(suffix, ".class"))
{
result = (strEqual(value, ARG_UNDEFINED) ? ARG_UNDEFINED_VALUE :
#define STYLE_DEFAULT STYLE_NONE
+#define ANIM_EVENT_NONE 0
+#define ANIM_EVENT_CLICK (1 << 0)
+
+#define ANIM_EVENT_DEFAULT ANIM_EVENT_NONE
+
/* values for fade mode */
#define FADE_TYPE_NONE 0
#define FADE_TYPE_FADE_IN (1 << 0)
#define GFX_ARG_ANIM_DELAY_RANDOM 38
#define GFX_ARG_POST_DELAY_FIXED 39
#define GFX_ARG_POST_DELAY_RANDOM 40
-#define GFX_ARG_NAME 41
-#define GFX_ARG_SCALE_UP_FACTOR 42
-#define GFX_ARG_TILE_SIZE 43
-#define GFX_ARG_CLONE_FROM 44
-#define GFX_ARG_FADE_MODE 45
-#define GFX_ARG_FADE_DELAY 46
-#define GFX_ARG_POST_DELAY 47
-#define GFX_ARG_AUTO_DELAY 48
-#define GFX_ARG_ALIGN 49
-#define GFX_ARG_VALIGN 50
-#define GFX_ARG_SORT_PRIORITY 51
-#define GFX_ARG_CLASS 52
-#define GFX_ARG_STYLE 53
-#define GFX_ARG_ACTIVE_XOFFSET 54
-#define GFX_ARG_ACTIVE_YOFFSET 55
-#define GFX_ARG_PRESSED_XOFFSET 56
-#define GFX_ARG_PRESSED_YOFFSET 57
-
-#define NUM_GFX_ARGS 58
+#define GFX_ARG_INIT_EVENT 41
+#define GFX_ARG_ANIM_EVENT 42
+#define GFX_ARG_NAME 43
+#define GFX_ARG_SCALE_UP_FACTOR 44
+#define GFX_ARG_TILE_SIZE 45
+#define GFX_ARG_CLONE_FROM 46
+#define GFX_ARG_FADE_MODE 47
+#define GFX_ARG_FADE_DELAY 48
+#define GFX_ARG_POST_DELAY 49
+#define GFX_ARG_AUTO_DELAY 50
+#define GFX_ARG_ALIGN 51
+#define GFX_ARG_VALIGN 52
+#define GFX_ARG_SORT_PRIORITY 53
+#define GFX_ARG_CLASS 54
+#define GFX_ARG_STYLE 55
+#define GFX_ARG_ACTIVE_XOFFSET 56
+#define GFX_ARG_ACTIVE_YOFFSET 57
+#define GFX_ARG_PRESSED_XOFFSET 58
+#define GFX_ARG_PRESSED_YOFFSET 59
+
+#define NUM_GFX_ARGS 60
/* values for sound configuration suffixes */
int post_delay_fixed; /* optional delay values after bored/global */
int post_delay_random; /* animations (pause before next animation) */
+ int init_event; /* optional event triggering animation start */
+ int anim_event; /* optional event triggering animation end */
+
int step_offset; /* optional step offset of toon animations */
int step_xoffset; /* optional step offset of toon animations */
int step_yoffset; /* optional step offset of toon animations */