From: Holger Schemel Date: Wed, 19 Apr 2017 14:33:54 +0000 (+0200) Subject: added animation events triggered by clicking other global animations X-Git-Tag: 4.0.1.0~49 X-Git-Url: https://git.artsoft.org/?a=commitdiff_plain;h=5bdc30d016416d04eec826a28321325d4ddc66c2;p=rocksndiamonds.git added animation events triggered by clicking other global animations --- diff --git a/src/anim.c b/src/anim.c index 2ef78725..ef0fb92a 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; @@ -114,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; @@ -328,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; @@ -350,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]; @@ -373,6 +384,8 @@ static void InitToonControls() part->last_anim_status = -1; anim->num_parts++; + anim->num_parts_all++; + part_nr++; } @@ -414,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; @@ -448,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]; @@ -465,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; } @@ -897,12 +922,27 @@ static void StopGlobalAnimSoundAndMusic(struct GlobalAnimPartControlInfo *part) StopGlobalAnimMusic(part); } -static boolean isClickablePart(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; - return (c->init_event & ANIM_EVENT_CLICK || - c->anim_event & ANIM_EVENT_CLICK); + 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, @@ -1043,8 +1083,6 @@ int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state) PlayGlobalAnimSoundAndMusic(part); } - part->clickable = isClickablePart(part); - if (part->clicked && part->init_event_state != ANIM_EVENT_NONE) { @@ -1083,6 +1121,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) || @@ -1366,12 +1407,12 @@ static void InitGlobalAnim_Clickable() struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr]; int anim_nr; - for (anim_nr = 0; anim_nr < NUM_GLOBAL_ANIMS_AND_TOONS; 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 < NUM_GLOBAL_ANIM_PARTS_AND_TOONS; part_nr++) + for (part_nr = 0; part_nr < anim->num_parts_all; part_nr++) { struct GlobalAnimPartControlInfo *part = &anim->part[part_nr]; @@ -1391,19 +1432,71 @@ static boolean InitGlobalAnim_Clicked(int mx, int my, boolean clicked) struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr]; int anim_nr; - for (anim_nr = 0; anim_nr < NUM_GLOBAL_ANIMS_AND_TOONS; 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 < NUM_GLOBAL_ANIM_PARTS_AND_TOONS; part_nr++) + for (part_nr = 0; part_nr < anim->num_parts_all; part_nr++) { struct GlobalAnimPartControlInfo *part = &anim->part[part_nr]; - part->clicked = FALSE; + 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; - if (part->clickable && isClickedPart(part, mx, my, clicked)) - any_part_clicked = part->clicked = TRUE; + 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 + } + } + } } } } diff --git a/src/libgame/misc.c b/src/libgame/misc.c index bb732ffa..4c1f5683 100644 --- a/src/libgame/misc.c +++ b/src/libgame/misc.c @@ -2716,6 +2716,78 @@ static boolean string_has_parameter(char *s, char *s_contained) return string_has_parameter(substring, s_contained); } +static boolean string_has_anim_parameter(char *s, char *s_contained) +{ + char *s_copy = getStringCopy(s); + boolean has_parameter = FALSE; + int len_s_copy = strlen(s_copy); + int i; + + // replace all "anim" and "part" numbers with 'X' + for (i = 0; i < len_s_copy; i++) + if (s_copy[i] >= '1' && s_copy[i] <= '8') + s_copy[i] = 'X'; + + has_parameter = string_has_parameter(s_copy, s_contained); + + checked_free(s_copy); + + return has_parameter; +} + +int get_anim_parameter_value(char *s) +{ + char *pattern_1 = "click:anim_"; + char *pattern_2 = ".part_"; + char *matching_char = NULL; + char *s_ptr = s; + int result = ANIM_EVENT_NONE; + + matching_char = strstr(s_ptr, pattern_1); + if (matching_char == NULL) + return result; + + s_ptr = matching_char + strlen(pattern_1); + if (*s_ptr == '\0') + return result; + + // check for "click:anim_X" + if (*s_ptr >= '1' && *s_ptr <= '8') + { + result |= ANIM_EVENT_CLICK_ANIM_1 << (*s_ptr - '1'); + s_ptr++; + + // check for "click:anim_X.part_X" + if (strPrefix(s_ptr, pattern_2)) + { + s_ptr += strlen(pattern_2); + + if (*s_ptr >= '1' && *s_ptr <= '8') + { + result |= ANIM_EVENT_CLICK_PART_1 << (*s_ptr - '1'); + s_ptr++; + } + } + else + { + // no "part_X" specified -- trigger by click on any part + result |= ANIM_EVENT_CLICK_PART_ALL; + } + } + + /* discard result if next character is neither delimiter nor whitespace */ + if (!(*s_ptr == ',' || *s_ptr == '\0' || + *s_ptr == ' ' || *s_ptr == '\t')) + return get_anim_parameter_value(s_ptr); + + /* check if string contains another parameter string after a comma */ + s_ptr = strchr(s_ptr, ','); + if (s_ptr == NULL) /* string does not contain a comma */ + return result; + + return result | get_anim_parameter_value(s_ptr); +} + int get_parameter_value(char *value_raw, char *suffix, int type) { char *value = getStringToLower(value_raw); @@ -2788,7 +2860,11 @@ int get_parameter_value(char *value_raw, char *suffix, int type) result = ANIM_EVENT_DEFAULT; if (string_has_parameter(value, "click")) - result |= ANIM_EVENT_CLICK; + result |= ANIM_EVENT_CLICK_SELF; + + if (string_has_anim_parameter(value, "click:anim_X") || + string_has_anim_parameter(value, "click:anim_X.part_X")) + result |= get_anim_parameter_value(value); } else if (strEqual(suffix, ".class")) { diff --git a/src/libgame/system.h b/src/libgame/system.h index 9c95802d..406a6f36 100644 --- a/src/libgame/system.h +++ b/src/libgame/system.h @@ -325,7 +325,41 @@ #define STYLE_DEFAULT STYLE_NONE #define ANIM_EVENT_NONE 0 -#define ANIM_EVENT_CLICK (1 << 0) +#define ANIM_EVENT_CLICK_ANIM_1 (1 << 0) +#define ANIM_EVENT_CLICK_ANIM_2 (1 << 1) +#define ANIM_EVENT_CLICK_ANIM_3 (1 << 2) +#define ANIM_EVENT_CLICK_ANIM_4 (1 << 3) +#define ANIM_EVENT_CLICK_ANIM_5 (1 << 4) +#define ANIM_EVENT_CLICK_ANIM_6 (1 << 5) +#define ANIM_EVENT_CLICK_ANIM_7 (1 << 6) +#define ANIM_EVENT_CLICK_ANIM_8 (1 << 7) +#define ANIM_EVENT_CLICK_PART_1 (1 << 8) +#define ANIM_EVENT_CLICK_PART_2 (1 << 9) +#define ANIM_EVENT_CLICK_PART_3 (1 << 10) +#define ANIM_EVENT_CLICK_PART_4 (1 << 11) +#define ANIM_EVENT_CLICK_PART_5 (1 << 12) +#define ANIM_EVENT_CLICK_PART_6 (1 << 13) +#define ANIM_EVENT_CLICK_PART_7 (1 << 14) +#define ANIM_EVENT_CLICK_PART_8 (1 << 15) +#define ANIM_EVENT_CLICK_SELF (1 << 16) + +#define ANIM_EVENT_CLICK_ANIM_ALL (ANIM_EVENT_CLICK_ANIM_1 | \ + ANIM_EVENT_CLICK_ANIM_2 | \ + ANIM_EVENT_CLICK_ANIM_3 | \ + ANIM_EVENT_CLICK_ANIM_4 | \ + ANIM_EVENT_CLICK_ANIM_5 | \ + ANIM_EVENT_CLICK_ANIM_6 | \ + ANIM_EVENT_CLICK_ANIM_7 | \ + ANIM_EVENT_CLICK_ANIM_8) + +#define ANIM_EVENT_CLICK_PART_ALL (ANIM_EVENT_CLICK_PART_1 | \ + ANIM_EVENT_CLICK_PART_2 | \ + ANIM_EVENT_CLICK_PART_3 | \ + ANIM_EVENT_CLICK_PART_4 | \ + ANIM_EVENT_CLICK_PART_5 | \ + ANIM_EVENT_CLICK_PART_6 | \ + ANIM_EVENT_CLICK_PART_7 | \ + ANIM_EVENT_CLICK_PART_8) #define ANIM_EVENT_DEFAULT ANIM_EVENT_NONE