#include "screens.h"
+#define DEBUG_ANIM_DELAY 0
#define DEBUG_ANIM_EVENTS 0
};
// forward declaration for internal use
+static void DoGlobalAnim_DelayAction(struct GlobalAnimPartControlInfo *, int);
static boolean DoGlobalAnim_EventAction(struct GlobalAnimPartControlInfo *);
static void HandleGlobalAnim(int, int);
static void DoAnimationExt(void);
void DrawGlobalAnimations(int drawing_target, int drawing_stage)
{
+ int last_cursor_mode_override = gfx.cursor_mode_override;
+
if (drawing_stage == DRAW_GLOBAL_ANIM_STAGE_1)
+ {
ResetGlobalAnim_Clickable();
+ gfx.cursor_mode_override = CURSOR_UNDEFINED;
+ }
+
DrawGlobalAnimationsExt(drawing_target, drawing_stage);
if (drawing_stage == DRAW_GLOBAL_ANIM_STAGE_2)
+ {
ResetGlobalAnim_Clicked();
+ }
+
+ if (gfx.cursor_mode_override != last_cursor_mode_override)
+ SetMouseCursor(gfx.cursor_mode);
}
static boolean SetGlobalAnimPart_Viewport(struct GlobalAnimPartControlInfo *part)
int viewport_height;
boolean changed = FALSE;
- if (part->last_anim_status == global.anim_status)
+ if (part->last_anim_status == global.anim_status &&
+ part->control_info.class != get_hash_from_key("pointer"))
return FALSE;
part->last_anim_status = global.anim_status;
part->drawing_stage = DRAW_GLOBAL_ANIM_STAGE_2;
}
+ else if (part->control_info.class == get_hash_from_key("pointer"))
+ {
+ viewport_x = gfx.mouse_x + part->control_info.x;
+ viewport_y = gfx.mouse_y + part->control_info.y;
+ viewport_width = part->graphic_info.width;
+ viewport_height = part->graphic_info.height;
+
+ part->drawing_stage = DRAW_GLOBAL_ANIM_STAGE_2;
+
+ gfx.cursor_mode_override = CURSOR_NONE;
+ }
else if (part->control_info.class == get_hash_from_key("door_1"))
{
viewport_x = DX;
}
else if (part->control_info.class == get_hash_from_key("door_2"))
{
- viewport_x = VX;
- viewport_y = VY;
- viewport_width = VXSIZE;
- viewport_height = VYSIZE;
+ if (part->mode_nr == GAME_MODE_EDITOR)
+ {
+ viewport_x = EX;
+ viewport_y = EY;
+ viewport_width = EXSIZE;
+ viewport_height = EYSIZE;
+ }
+ else
+ {
+ viewport_x = VX;
+ viewport_y = VY;
+ viewport_width = VXSIZE;
+ viewport_height = VYSIZE;
+ }
}
else // default: "playfield"
{
return (anim_event & ANIM_EVENT_ANY);
else if (mask & ANIM_EVENT_SELF)
return (anim_event & ANIM_EVENT_SELF);
+ else if (mask & ANIM_EVENT_UNCLICK_ANY)
+ return (anim_event & ANIM_EVENT_UNCLICK_ANY);
else
return (anim_event == mask ||
anim_event == mask_anim_only);
}
}
+static void HandleGlobalAnimDelay(struct GlobalAnimPartControlInfo *part,
+ int delay_type, char *info_text)
+{
+#if DEBUG_ANIM_DELAY
+ printf("::: %d.%d %s\n", part->old_anim_nr + 1, part->old_nr + 1, info_text);
+#endif
+
+ DoGlobalAnim_DelayAction(part, delay_type);
+}
+
static void HandleGlobalAnimEvent(struct GlobalAnimPartControlInfo *part,
int event_value, char *info_text)
{
part->anim_delay_counter =
(c->anim_delay_fixed + GetSimpleRandom(c->anim_delay_random));
+ part->post_delay_counter = 0;
+
part->init_event_state = (c->init_event != ANIM_EVENT_UNDEFINED);
part->anim_event_state = (c->anim_event != ANIM_EVENT_UNDEFINED);
part->step_yoffset = 0;
}
- if (c->x != ARG_UNDEFINED_VALUE)
- part->x = c->x;
- if (c->y != ARG_UNDEFINED_VALUE)
- part->y = c->y;
+ if (part->control_info.class != get_hash_from_key("pointer"))
+ {
+ if (c->x != ARG_UNDEFINED_VALUE)
+ part->x = c->x;
+ if (c->y != ARG_UNDEFINED_VALUE)
+ part->y = c->y;
+ }
if (c->position == POS_LAST &&
anim->last_x > -g->width && anim->last_x < part->viewport_width &&
{
PlayGlobalAnimSoundAndMusic(part);
+ HandleGlobalAnimDelay(part, ANIM_DELAY_INIT, "START [INIT_DELAY]");
HandleGlobalAnimEvent(part, ANIM_EVENT_START, "START [ANIM]");
}
else
PlayGlobalAnimSoundAndMusic(part);
+ HandleGlobalAnimDelay(part, ANIM_DELAY_INIT, "START [INIT_DELAY]");
HandleGlobalAnimEvent(part, ANIM_EVENT_START, "START [ANIM]");
}
StopGlobalAnimSoundAndMusic(part);
- HandleGlobalAnimEvent(part, ANIM_EVENT_END, "END [ANIM_DELAY/EVENT]");
+ HandleGlobalAnimDelay(part, ANIM_DELAY_ANIM, "END [ANIM_DELAY]");
+ HandleGlobalAnimEvent(part, ANIM_EVENT_END, "END [ANIM_DELAY/EVENT]");
part->post_delay_counter =
(c->post_delay_fixed + GetSimpleRandom(c->post_delay_random));
if (part->post_delay_counter == 0)
{
+ HandleGlobalAnimDelay(part, ANIM_DELAY_POST, "END [POST_DELAY]");
HandleGlobalAnimEvent(part, ANIM_EVENT_POST, "END [POST_DELAY]");
return ANIM_STATE_RESTART;
#endif
}
+static void DoGlobalAnim_DelayAction(struct GlobalAnimPartControlInfo *part,
+ int delay_type)
+{
+ int delay_action =
+ (delay_type == ANIM_DELAY_INIT ? part->control_info.init_delay_action :
+ delay_type == ANIM_DELAY_ANIM ? part->control_info.anim_delay_action :
+ delay_type == ANIM_DELAY_POST ? part->control_info.post_delay_action :
+ ANIM_DELAY_ACTION_NONE);
+
+ if (delay_action == ANIM_DELAY_ACTION_NONE)
+ return;
+
+ PushUserEvent(USEREVENT_ANIM_DELAY_ACTION, delay_action, 0);
+}
+
static boolean DoGlobalAnim_EventAction(struct GlobalAnimPartControlInfo *part)
{
- int anim_event_action = part->control_info.anim_event_action;
+ int event_action = (part->init_event_state ?
+ part->control_info.init_event_action :
+ part->control_info.anim_event_action);
- if (anim_event_action == -1)
+ if (event_action == ANIM_EVENT_ACTION_NONE)
return FALSE;
- boolean action_executed = (DoGadgetAction(anim_event_action) ||
- DoScreenAction(anim_event_action) ||
- DoKeysymAction(anim_event_action));
+ PushUserEvent(USEREVENT_ANIM_EVENT_ACTION, event_action, 0);
// check if further actions are allowed to be executed
if (part->control_info.style & STYLE_MULTIPLE_ACTIONS)
return FALSE;
- return action_executed;
+ return TRUE;
}
static void InitGlobalAnim_Clickable(void)
}
}
-static boolean InitGlobalAnim_Clicked(int mx, int my, boolean clicked)
+#define ANIM_CLICKED_RESET 0
+#define ANIM_CLICKED_PRESSED 1
+#define ANIM_CLICKED_RELEASED 2
+
+static boolean InitGlobalAnim_Clicked(int mx, int my, int clicked_event)
{
boolean anything_clicked = FALSE;
boolean any_part_clicked = FALSE;
{
struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
- if (!clicked)
+ if (clicked_event == ANIM_CLICKED_RESET)
{
part->clicked = FALSE;
continue;
// always handle "any" click events (clicking anywhere on screen) ...
- if (isClickablePart(part, ANIM_EVENT_ANY))
+ if (clicked_event == ANIM_CLICKED_PRESSED &&
+ isClickablePart(part, ANIM_EVENT_ANY))
{
#if DEBUG_ANIM_EVENTS
printf("::: => %d.%d TRIGGERED BY ANY\n",
anything_clicked = clickConsumed(part);
}
+ // always handle "unclick:any" events (releasing anywhere on screen) ...
+ if (clicked_event == ANIM_CLICKED_RELEASED &&
+ isClickablePart(part, ANIM_EVENT_UNCLICK_ANY))
+ {
+#if DEBUG_ANIM_EVENTS
+ printf("::: => %d.%d TRIGGERED BY UNCLICK:ANY\n",
+ part->old_anim_nr + 1, part->old_nr + 1);
+#endif
+
+ part->clicked = TRUE;
+ anything_clicked = clickConsumed(part);
+ }
+
// ... but only handle the first (topmost) clickable animation
if (any_part_clicked)
continue;
- if (isClickedPart(part, mx, my, clicked))
+ if (clicked_event == ANIM_CLICKED_PRESSED &&
+ isClickedPart(part, mx, my, TRUE))
{
#if 0
printf("::: %d.%d CLICKED [%d]\n", anim_nr, part_nr,
static void ResetGlobalAnim_Clicked(void)
{
- InitGlobalAnim_Clicked(-1, -1, FALSE);
+ InitGlobalAnim_Clicked(-1, -1, ANIM_CLICKED_RESET);
}
-boolean HandleGlobalAnimClicks(int mx, int my, int button)
+boolean HandleGlobalAnimClicks(int mx, int my, int button, boolean force_click)
{
static boolean click_consumed = FALSE;
static int last_button = 0;
boolean release_event;
boolean click_consumed_current = click_consumed;
+ if (button != 0 && force_click)
+ last_button = 0;
+
// check if button state has changed since last invocation
press_event = (button != 0 && last_button == 0);
release_event = (button == 0 && last_button != 0);
if (press_event)
{
- click_consumed = InitGlobalAnim_Clicked(mx, my, TRUE);
+ click_consumed = InitGlobalAnim_Clicked(mx, my, ANIM_CLICKED_PRESSED);
click_consumed_current = click_consumed;
}
if (release_event)
+ {
+ InitGlobalAnim_Clicked(mx, my, ANIM_CLICKED_RELEASED);
click_consumed = FALSE;
+ }
return click_consumed_current;
}