#include "animation.h" #include static void animation_add_element_pause ( Animation *animation, gint delay, gint rand, gint line_no ) { AnimElement *elem = animation_element_new (); elem->delay = delay; elem->rand = rand; elem->type = ELEMENT_PAUSE; elem->line_no = line_no; animation->elements = g_list_append (animation->elements, elem); } static void animation_add_element_end ( Animation *animation, gint rand, gint line_no ) { AnimElement *elem = animation_element_new (); elem->type = ELEMENT_END; elem->rand = rand; elem->line_no = line_no; animation->elements = g_list_append (animation->elements, elem); } static void animation_add_element_frame ( Animation *animation, const Imageset *imageset, gint index, gint offsetX, gint offsetY, gint delay, gint rand, gint line_no ) { gint x, y; AnimElement *elem = animation_element_new (); elem->type = ELEMENT_FRAME; imageset_get_offset (imageset, &x, &y); offsetX += x; offsetY += y; imageset_get_size (imageset, &x, &y); offsetX -= x / 2; offsetY -= y; elem->offsetX = offsetX; elem->offsetY = offsetY; elem->delay = delay; elem->rand = rand; elem->line_no = line_no; elem->sprite = imageset_get_sprite_by_index (imageset, index); if (elem->sprite == NULL) { /* TODO: report this */ g_free (elem); return; } animation->elements = g_list_append (animation->elements, elem); } static void animation_add_element_goto ( Animation *animation, gchar *label, gint rand, gint line_no ) { AnimElement *elem = animation_element_new (); elem->type = ELEMENT_GOTO; elem->str = label; elem->rand = rand; elem->line_no = line_no; animation->elements = g_list_append (animation->elements, elem); } static void animation_add_element_jump ( Animation *animation, gchar *action, gint rand, gint line_no ) { AnimElement *elem = animation_element_new (); elem->type = ELEMENT_JUMP; elem->str = action; elem->rand = rand; elem->line_no = line_no; animation->elements = g_list_append (animation->elements, elem); } static void animation_add_element_label ( Animation *animation, gchar *name, gint line_no ) { AnimElement *elem = animation_element_new (); elem->type = ELEMENT_LABEL; elem->str = name; elem->line_no = line_no; animation->elements = g_list_append (animation->elements, elem); } static void animation_add_sequence ( Animation *animation, const Imageset *imageset, const XMLNode *node, gint offsetX, gint offsetY, gint delay, gint rand, gint line_no ) { gchar *value, **tokens; gint start = xml_node_get_int_attr_value (node, "start", -1); gint end = xml_node_get_int_attr_value (node, "end", -1); gint repeat = xml_node_get_int_attr_value_limited ( node, "repeat", 1, 0, 100 ); g_return_if_fail (g_strcmp0 (node->name, "sequence") == 0); if (repeat < 1) { /* TODO: show error */ return; } value = xml_node_get_attr_value (node, "value"); if (value == NULL) { if (start < 0 || end < 0) { /* TODO: show error */ return; } value = g_strdup_printf ("%d-%d", start, end); } tokens = g_strsplit (value, ",", 0); g_free (value); while (repeat > 0) { gchar **token = tokens; while (*token != NULL) { if (g_strcmp0 (*token, "p") == 0) { animation_add_element_pause ( animation, delay, rand, line_no ); } else { gint start = -1, end = -1, d; gchar *delim = strchr (*token, '-'); if (delim == NULL) { try_strtoint (*token, &start); end = start; } else { *delim = 0; try_strtoint ( *token, &start); try_strtoint (delim + 1, &end); *delim = '-'; } if (start < 0 || end < 0) { /* TODO: show error */ g_strfreev (tokens); return; } d = start <= end ? +1 : -1; end += d; while (start != end) { animation_add_element_frame ( animation, imageset, start, offsetX, offsetY, delay, rand, line_no ); start += d; } } ++token; } --repeat; } g_strfreev (tokens); } static void animation_add_elements_from_node ( Animation *animation, const Imageset *imageset, const XMLNode *node, gint included_from ) { gchar *name = node->name; gint offsetX, offsetY; gint delay, rand; gchar *str; gint line_no; imageset_get_offset (imageset, &offsetX, &offsetY); offsetX += xml_node_get_int_attr_value (node, "offsetX", 0); offsetY += xml_node_get_int_attr_value (node, "offsetY", 0); delay = xml_node_get_int_attr_value_limited ( node, "delay", 0, 0, 100000 ); rand = xml_node_get_int_attr_value_limited ( node, "rand", 100, 0, 100 ); line_no = included_from; if (line_no == -1) line_no = node->line_no; if (g_strcmp0 (name, "frame") == 0) { gint index = xml_node_get_int_attr_value (node, "index", -1); if (index < 0) { /* TODO: report error */ return; } animation_add_element_frame ( animation, imageset, index, offsetX, offsetY, delay, rand, line_no ); } else if (g_strcmp0 (name, "pause") == 0) { animation_add_element_pause ( animation, delay, rand, line_no ); } else if (g_strcmp0 (name, "end") == 0) { animation_add_element_end (animation, rand, line_no); } else if (g_strcmp0 (name, "jump") == 0) { str = xml_node_get_attr_value (node, "action"); animation_add_element_jump ( animation, str, rand, line_no ); } else if (g_strcmp0 (name, "label") == 0) { str = xml_node_get_attr_value (node, "name"); if (str == NULL) { /* TODO: report error */ return; } animation_add_element_label (animation, str, line_no); } else if (g_strcmp0 (name, "goto") == 0) { str = xml_node_get_attr_value (node, "label"); if (str == NULL) { /* TODO: report error */ return; } animation_add_element_goto ( animation, str, rand, line_no ); } else if (g_strcmp0 (name, "sequence") == 0) { animation_add_sequence ( animation, imageset, node, offsetX, offsetY, delay, rand, line_no ); } else { /* TODO: unknown tag */ return; } } Animation * animation_new ( const Imageset *imageset, const XMLNode *node, gint included_from ) { Animation *animation; gchar *dir; GList *sub_node; g_return_val_if_fail (g_strcmp0 (node->name, "animation") == 0, NULL); dir = xml_node_get_attr_value (node, "direction"); if (dir == NULL) dir = ""; animation = (Animation *) g_new0 (Animation, 1); animation->direction = dir; sub_node = node->sub_nodes; while (sub_node != NULL) { animation_add_elements_from_node ( animation, imageset, (XMLNode *) sub_node->data, included_from ); sub_node = g_list_next (sub_node); } return animation; } gint animation_compare_by_direction ( const Animation *first, const Animation *second ) { return g_strcmp0 (first->direction, second->direction); } gboolean animation_direction_equals ( const Animation *animation, const gchar *direction ) { return g_strcmp0 (animation->direction, direction) == 0; } void animation_free (Animation *animation) { g_list_free_full ( animation->elements, (GDestroyNotify) g_free ); g_free (animation->direction); g_free (animation); } AnimElement * animation_element_new () { return (AnimElement *) g_new0 (AnimElement, 1); }