diff options
Diffstat (limited to 'saedit/animation.c')
-rw-r--r-- | saedit/animation.c | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/saedit/animation.c b/saedit/animation.c new file mode 100644 index 0000000..997b420 --- /dev/null +++ b/saedit/animation.c @@ -0,0 +1,386 @@ +#include "animation.h" +#include <string.h> + +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); +} |