X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fanim.c;h=b566bddcbc27132d458a1dbf28519f4b3aba6d78;hp=3018fc137fce3d3a9260a76abf41f3df42599f1d;hb=e14d20831f1abdbcfccd5c8afcaf715e3849f468;hpb=f1dae0af49fa331f6fedc6cbdf59eed0909ae391 diff --git a/src/anim.c b/src/anim.c index 3018fc13..b566bddc 100644 --- a/src/anim.c +++ b/src/anim.c @@ -66,10 +66,15 @@ struct GlobalAnimPartControlInfo { + int old_nr; // position before mapping animation parts linearly + int old_anim_nr; // position before mapping animations linearly + int nr; int anim_nr; int mode_nr; + boolean is_base; // animation part is base/main/default animation part + int sound; int music; int graphic; @@ -95,6 +100,9 @@ struct GlobalAnimPartControlInfo boolean init_event_state; boolean anim_event_state; + boolean clickable; + boolean clicked; + int drawing_stage; int state; @@ -111,11 +119,12 @@ struct GlobalAnimMainControlInfo struct GraphicInfo control_info; - int num_parts; + int num_parts; // number of animation parts, but without base part + int num_parts_all; // number of animation parts, including base part int part_counter; int active_part_nr; - boolean has_base; + boolean has_base; // animation has base/main/default animation part int init_delay_counter; @@ -178,6 +187,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 struct GlobalAnimControlInfo global_anim_ctrl[NUM_GAME_MODES]; @@ -191,10 +202,6 @@ 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 */ @@ -327,6 +334,7 @@ static void InitToonControls() anim->control_info = graphic_info[control]; anim->num_parts = 0; + anim->num_parts_all = 0; anim->part_counter = 0; anim->active_part_nr = 0; @@ -349,9 +357,13 @@ static void InitToonControls() part->nr = part_nr; part->anim_nr = anim_nr; part->mode_nr = mode_nr; + + part->is_base = FALSE; + part->sound = sound; part->music = music; part->graphic = graphic; + part->graphic_info = graphic_info[graphic]; part->control_info = graphic_info[control]; @@ -372,6 +384,8 @@ static void InitToonControls() part->last_anim_status = -1; anim->num_parts++; + anim->num_parts_all++; + part_nr++; } @@ -413,6 +427,7 @@ void InitGlobalAnimControls() anim->control_info = graphic_info[control]; anim->num_parts = 0; + anim->num_parts_all = 0; anim->part_counter = 0; anim->active_part_nr = 0; @@ -447,12 +462,17 @@ void InitGlobalAnimControls() m, a, p, mode_nr, anim_nr, part_nr, sound); #endif + part->old_nr = p; + part->old_anim_nr = a; + part->nr = part_nr; part->anim_nr = anim_nr; part->mode_nr = mode_nr; + part->sound = sound; part->music = music; part->graphic = graphic; + part->graphic_info = graphic_info[graphic]; part->control_info = graphic_info[control]; @@ -464,13 +484,19 @@ void InitGlobalAnimControls() part->state = ANIM_STATE_INACTIVE; part->last_anim_status = -1; + anim->num_parts_all++; + if (p < GLOBAL_ANIM_ID_PART_BASE) { + part->is_base = FALSE; + anim->num_parts++; part_nr++; } else { + part->is_base = TRUE; + anim->base = *part; anim->has_base = TRUE; } @@ -672,6 +698,10 @@ void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage) int cut_y = 0; int sync_frame; int frame; + void (*blit_bitmap)(Bitmap *, Bitmap *, int, int, int, int, int, int) = + (g->draw_masked ? BlitBitmapMasked : BlitBitmap); + void (*blit_screen)(Bitmap *, int, int, int, int, int, int) = + (g->draw_masked ? BlitToScreenMasked : BlitToScreen); if (!(part->state & ANIM_STATE_RUNNING)) continue; @@ -715,11 +745,11 @@ void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage) src_y += cut_y; if (drawing_target == DRAW_TO_SCREEN) - BlitToScreenMasked(src_bitmap, src_x, src_y, width, height, - dst_x, dst_y); + blit_screen(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); + blit_bitmap(src_bitmap, fade_bitmap, src_x, src_y, width, height, + dst_x, dst_y); } } } @@ -737,7 +767,13 @@ void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage) void DrawGlobalAnimations(int drawing_target, int drawing_stage) { + if (drawing_stage == DRAW_GLOBAL_ANIM_STAGE_1) + ResetGlobalAnim_Clickable(); + DrawGlobalAnimationsExt(drawing_target, drawing_stage); + + if (drawing_stage == DRAW_GLOBAL_ANIM_STAGE_2) + ResetGlobalAnim_Clicked(); } boolean SetGlobalAnimPart_Viewport(struct GlobalAnimPartControlInfo *part) @@ -890,18 +926,40 @@ static void StopGlobalAnimSoundAndMusic(struct GlobalAnimPartControlInfo *part) StopGlobalAnimMusic(part); } -static boolean getPartClickEvent(struct GlobalAnimPartControlInfo *part) +static boolean matchesAnimEventMask(int bits, int mask) +{ + return (bits & (mask & ANIM_EVENT_CLICK_ANIM_ALL) && + bits & (mask & ANIM_EVENT_CLICK_PART_ALL)); +} + +static boolean isClickablePart(struct GlobalAnimPartControlInfo *part, int mask) +{ + struct GraphicInfo *c = &part->control_info; + + boolean clickable_self = FALSE; + boolean clickable_triggered = FALSE; + + if (mask & ANIM_EVENT_CLICK_SELF) + clickable_self = (c->init_event & ANIM_EVENT_CLICK_SELF || + c->anim_event & ANIM_EVENT_CLICK_SELF); + + clickable_triggered = (matchesAnimEventMask(c->init_event, mask) || + matchesAnimEventMask(c->anim_event, mask)); + + return (clickable_self || clickable_triggered); +} + +static boolean isClickedPart(struct GlobalAnimPartControlInfo *part, + int mx, int my, boolean clicked) { 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) + // check if mouse click was detected at all + if (!clicked) return FALSE; // check if mouse click is inside the animation part's viewport @@ -926,7 +984,6 @@ 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; @@ -1030,7 +1087,7 @@ int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state) PlayGlobalAnimSoundAndMusic(part); } - if (part_click_event && + if (part->clicked && part->init_event_state != ANIM_EVENT_NONE) { if (part->initial_anim_sync_frame > 0) @@ -1039,16 +1096,16 @@ int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state) part->init_delay_counter = 1; part->init_event_state = ANIM_EVENT_NONE; - anim_click_event = FALSE; + part->clicked = FALSE; } - if (part_click_event && + if (part->clicked && part->anim_event_state != ANIM_EVENT_NONE) { part->anim_delay_counter = 1; part->anim_event_state = ANIM_EVENT_NONE; - anim_click_event = FALSE; + part->clicked = FALSE; } if (part->init_delay_counter > 0) @@ -1068,6 +1125,9 @@ int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state) if (part->init_event_state != ANIM_EVENT_NONE) return ANIM_STATE_WAITING; + // animation part is now running/visible and therefore clickable + part->clickable = TRUE; + // 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) || @@ -1342,19 +1402,143 @@ static void DoAnimationExt() #endif } -void HandleGlobalAnimClicks(int mx, int my, int button) +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 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; + + 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]; + + if (!clicked) + { + part->clicked = FALSE; + + continue; + } + + if (part->clickable && + isClickedPart(part, mx, my, clicked)) + { +#if 0 + printf("::: %d.%d CLICKED\n", anim_nr, part_nr); +#endif + + if (isClickablePart(part, ANIM_EVENT_CLICK_SELF)) + any_part_clicked = part->clicked = TRUE; + + // check if this click is defined to trigger other animations + int old_anim_nr = part->old_anim_nr; + int old_part_nr = part->old_nr; + int mask = ANIM_EVENT_CLICK_ANIM_1 << old_anim_nr; + + if (part->is_base) + mask |= ANIM_EVENT_CLICK_PART_ALL; + else + mask |= ANIM_EVENT_CLICK_PART_1 << old_part_nr; + + 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)) + any_part_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 any_part_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; - anim_click_mx = mx; - anim_click_my = my; - anim_click_event = (press_event ? TRUE : - release_event ? FALSE : anim_click_event); + 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; }