+
+static void InitGlobalAnim_Clickable()
+{
+ int mode_nr;
+
+ for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
+ {
+ struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
+ int anim_nr;
+
+ for (anim_nr = 0; anim_nr < ctrl->num_anims; anim_nr++)
+ {
+ struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr];
+ int part_nr;
+
+ for (part_nr = 0; part_nr < anim->num_parts_all; part_nr++)
+ {
+ struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
+
+ part->clickable = FALSE;
+ }
+ }
+ }
+}
+
+static boolean InitGlobalAnim_Clicked(int mx, int my, boolean clicked)
+{
+ boolean anything_clicked = FALSE;
+ boolean any_part_clicked = FALSE;
+ int mode_nr;
+
+ for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
+ {
+ struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
+ int anim_nr;
+
+ // check animations in reverse draw order (to stop when clicked)
+ for (anim_nr = ctrl->num_anims - 1; anim_nr >= 0; anim_nr--)
+ {
+ struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr];
+ int part_nr;
+
+ // check animation parts in reverse draw order (to stop when clicked)
+ for (part_nr = anim->num_parts_all - 1; part_nr >= 0; part_nr--)
+ {
+ struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
+
+ if (!clicked)
+ {
+ part->clicked = FALSE;
+
+ continue;
+ }
+
+ if (!part->clickable)
+ continue;
+
+ // always handle "any" click events (clicking anywhere on screen) ...
+ if (isClickablePart(part, ANIM_EVENT_ANY))
+ anything_clicked = part->clicked = TRUE;
+
+ // ... but only handle the first (topmost) clickable animation
+ if (any_part_clicked)
+ continue;
+
+ if (isClickedPart(part, mx, my, clicked))
+ {
+#if 0
+ printf("::: %d.%d CLICKED\n", anim_nr, part_nr);
+#endif
+
+ any_part_clicked = TRUE;
+
+ if (isClickablePart(part, ANIM_EVENT_SELF))
+ anything_clicked = part->clicked = TRUE;
+
+ // check if this click is defined to trigger other animations
+ int gic_anim_nr = part->old_anim_nr + 1; // X as in "anim_X"
+ int gic_part_nr = part->old_nr + 1; // Y as in "part_Y"
+ int mask = gic_anim_nr << ANIM_EVENT_ANIM_BIT;
+
+ if (!part->is_base)
+ mask |= gic_part_nr << ANIM_EVENT_PART_BIT;
+
+ int anim2_nr;
+
+ for (anim2_nr = 0; anim2_nr < ctrl->num_anims; anim2_nr++)
+ {
+ struct GlobalAnimMainControlInfo *anim2 = &ctrl->anim[anim2_nr];
+ int part2_nr;
+
+ for (part2_nr = 0; part2_nr < anim2->num_parts_all; part2_nr++)
+ {
+ struct GlobalAnimPartControlInfo *part2 = &anim2->part[part2_nr];
+
+ if (isClickablePart(part2, mask))
+ anything_clicked = part2->clicked = TRUE;
+
+#if 0
+ struct GraphicInfo *c = &part2->control_info;
+
+ printf("::: - %d.%d: 0x%08x, 0x%08x [0x%08x]",
+ anim2_nr, part2_nr, c->init_event, c->anim_event, mask);
+
+ if (isClickablePart(part2, mask))
+ printf(" <--- TRIGGERED BY %d.%d",
+ anim_nr, part_nr);
+
+ printf("\n");
+#endif
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return anything_clicked;
+}
+
+static void ResetGlobalAnim_Clickable()
+{
+ InitGlobalAnim_Clickable();
+}
+
+static void ResetGlobalAnim_Clicked()
+{
+ InitGlobalAnim_Clicked(-1, -1, FALSE);
+}
+
+boolean HandleGlobalAnimClicks(int mx, int my, int button)
+{
+ static boolean click_consumed = FALSE;
+ static int last_button = 0;
+ boolean press_event;
+ boolean release_event;
+ boolean click_consumed_current = click_consumed;
+
+ /* 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;
+
+ if (press_event)
+ {
+ click_consumed = InitGlobalAnim_Clicked(mx, my, TRUE);
+ click_consumed_current = click_consumed;
+ }
+
+ if (release_event)
+ click_consumed = FALSE;
+
+ return click_consumed_current;
+}