diff options
author | Vasily_Makarov <danilka.pro@gmail.com> | 2011-06-09 18:17:08 +0400 |
---|---|---|
committer | Vasily_Makarov <danilka.pro@gmail.com> | 2011-06-09 18:17:08 +0400 |
commit | fae8a3bcd2f31afb357fcf83beb9a7cd6d4bc400 (patch) | |
tree | cafd334e75b8b369912c7ab89953f12a2b73816a /saedit | |
parent | 9bb81baee05bb38cf80c8ef10d4db94b307f6eea (diff) | |
download | evol-tools-fae8a3bcd2f31afb357fcf83beb9a7cd6d4bc400.tar.gz evol-tools-fae8a3bcd2f31afb357fcf83beb9a7cd6d4bc400.tar.bz2 evol-tools-fae8a3bcd2f31afb357fcf83beb9a7cd6d4bc400.tar.xz evol-tools-fae8a3bcd2f31afb357fcf83beb9a7cd6d4bc400.zip |
Add Sprite Animation Editor in /saedit
Diffstat (limited to 'saedit')
-rw-r--r-- | saedit/Makefile | 8 | ||||
-rw-r--r-- | saedit/main.c | 553 | ||||
-rw-r--r-- | saedit/main.h | 62 |
3 files changed, 623 insertions, 0 deletions
diff --git a/saedit/Makefile b/saedit/Makefile new file mode 100644 index 0000000..772012e --- /dev/null +++ b/saedit/Makefile @@ -0,0 +1,8 @@ +GTK_FLAGS = $(shell pkg-config gtk+-2.0 --cflags --libs) $(shell pkg-config gtksourceview-2.0 --cflags --libs) +IBUS_FLAGS = $(shell pkg-config ibus-1.0 --cflags --libs) +OUTPUT = saedit +all:compile clean +compile: + gcc ${CFLAGS} ${GTK_FLAGS} ${IBUS_FLAGS} ${LDFLAGS} main.c -o '${OUTPUT}' +clean: + rm -rfv *.o~ *.c~ *.h~ diff --git a/saedit/main.c b/saedit/main.c new file mode 100644 index 0000000..a9b77cd --- /dev/null +++ b/saedit/main.c @@ -0,0 +1,553 @@ +/*=======================================*\ +| ____ ____ | +| / \ /\ | | +| \____ / \ |____ | +| \ /____\ | | +| \____/prite / \nimation |____ditor | +| | +| Copyleft Vasily_Makarov 2011 | +| | +\*=======================================*/ +#include <stdlib.h> +#include <gtk/gtk.h> +#include <gtksourceview/gtksourceview.h> +#include <gtksourceview/gtksourcelanguagemanager.h> +#include <ibusxml.h> +#include <cairo.h> +#include <glib/gi18n.h> + +#include "main.h"; + +const int MIN_WIDTH = 600; +const int MIN_HEIGHT = 600; +const int SPRITE_WIDTH_DEFAULT = 64; +const int SPRITE_HEIGHT_DEFAULT = 64; +const int GRID_SIZE = 32; + +int sprite_width = 64, sprite_height = 64; +int spriteset_width, spriteset_height; + +GtkWidget *win = NULL; +GtkWidget *darea = NULL; +GtkWidget *datafoldcbutton = NULL; +GtkWidget *xmlfcbutton = NULL; +GtkWidget *xmlfsbutton = NULL; +GtkWidget *xmlfobutton = NULL; +GtkWidget *imagesetscombobox = NULL; +GtkWidget *actionscombobox = NULL; +GtkWidget *animationscombobox = NULL; + +GdkPixbuf *spriteset = NULL; + +GList *imagesets = NULL; +GList *actions = NULL; +GList *animations = NULL; + +XMLNode *root = NULL; +imageset_info *imageset = NULL; + +sprite_info *current_sprite; +guint running_animation = 0; + +sprite_info *sprite_info_new(int index, int offsetX, int offsetY) { + sprite_info *res = g_new0(sprite_info, 1); + res->index = index; + res->offsetX = offsetX; + res->offsetY = offsetY; +} +gboolean on_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) { + int width = widget->allocation.width, + height = widget->allocation.height; + + cairo_t *cr = gdk_cairo_create(widget->window); + cairo_surface_t *gridsurf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cairo_t *scr = cairo_create(gridsurf); + cairo_set_line_width(scr, 0.1); + cairo_rectangle(scr, width/2 -GRID_SIZE/2, height/2, GRID_SIZE, GRID_SIZE); + cairo_stroke(scr); + cairo_set_source_surface(cr, gridsurf, 0, 0); + cairo_paint(cr); + + GdkPixbuf *pbuf = get_sprite_by_index(current_sprite->index); + if (pbuf == NULL) return FALSE; + gdk_cairo_set_source_pixbuf(cr, pbuf, width/2 - sprite_width/2 + current_sprite->offsetX + imageset->offsetX, height/2 - sprite_height/2 + current_sprite->offsetY + imageset->offsetY); + cairo_paint(cr); + + cairo_destroy(cr); +} + +gchar *markup_bold(gchar *str) { + gchar *buffer[255]; + g_sprintf(buffer, "<b>%s</b>", str); + return buffer; +} + +void format_src_string(gchar *src) { + gchar *str = g_strrstr(src, "|"); + if (str == NULL) return; + strncpy(str, "\0", 1); +} + +void open_xml_file(GtkButton *button, gpointer buffer) { + gchar *buf; + size_t len; + g_file_get_contents(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(xmlfcbutton)), &buf, &len, NULL); + gtk_text_buffer_set_text((GtkTextBuffer *)buffer, buf, len); + gtk_widget_set_sensitive(xmlfsbutton, TRUE); +} + +void free_imagesets() { + imageset = imageset_info_new(); + imagesets = NULL; + gtk_list_store_clear(gtk_combo_box_get_model(imagesetscombobox)); +} + +void free_actions() { + actions = NULL; + gtk_list_store_clear(gtk_combo_box_get_model(actionscombobox)); +} + +void free_animations() { + animations = NULL; + gtk_list_store_clear(gtk_combo_box_get_model(animationscombobox)); + g_source_remove(running_animation); + running_animation = 0; + set_sprite_by_index(0); +} + +void save_to_xml_file(GtkButton *button, gpointer buffer) { + g_file_set_contents(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(xmlfcbutton)), buffer, sizeof(buffer), NULL); +} + +void xml_file_set_handler(GtkFileChooserButton *widget, gpointer data) { + gtk_widget_set_sensitive(xmlfobutton, TRUE); +} + +void data_folder_set_handler(GtkFileChooserButton *widget, gpointer data) { + gtk_file_chooser_set_current_folder(xmlfcbutton, gtk_file_chooser_get_filename(widget)); +} + +void show_wrong_source_buffer_dialog() { + GtkWidget *dialog = gtk_message_dialog_new(win, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + NULL); + gtk_message_dialog_set_markup(dialog, markup_bold(_("Wrong source buffer! Could not parse XML!"))); + g_signal_connect(dialog, "response", gtk_widget_destroy, NULL); + gtk_widget_show_all(dialog); +} + +gchar* xml_node_get_attr_value(const XMLNode *node, const gchar *attr_name) { + gchar **attr = node->attributes; + int i; + for (i = 0; i < g_strv_length(attr); i += 2) + if (g_str_equal(attr[i], attr_name)) + return attr[i + 1]; + return NULL; +} + + +gint xml_node_compare_with_name(gconstpointer a, gconstpointer b) { + return g_strcmp0((gchar *)b, ((XMLNode *)a)->name); +} + +gint xml_node_compare_with_action_node_by_imageset_name_func(gconstpointer a, gconstpointer b) { + return g_strcmp0("action", ((XMLNode *)a)->name) || + g_strcmp0((gchar *)b, xml_node_get_attr_value((XMLNode *)a, "imageset")); +} + +gint xml_node_compare_with_direction_attr(gconstpointer node, gconstpointer direction) { + return g_strcmp0((gchar *)direction, xml_node_get_attr_value((XMLNode *)node, "direction")); +} + +gint xml_node_compare_with_name_attr(gconstpointer node, gconstpointer name) { + return g_strcmp0((gchar *)name, xml_node_get_attr_value((XMLNode *)node, "name")); +} + +GdkPixbuf* get_sprite_by_index(size_t index) { + size_t w = spriteset_width/sprite_width; + size_t h = spriteset_height/sprite_height; + if (spriteset == NULL) return NULL; + return gdk_pixbuf_new_subpixbuf(spriteset, index%w*sprite_width, index/w*sprite_height, sprite_width, sprite_height); +} + +void set_sprite_by_index(size_t index) { + current_sprite->index = index; + gtk_widget_queue_draw(darea); +} + +void set_up_actions_by_imageset_name(gchar *imageset_name) { + free_actions(); + free_animations(); + actions = NULL; + GList *list = root->sub_nodes; + XMLNode *node = NULL; + while (TRUE) { + list = g_list_find_custom(list, imageset_name, xml_node_compare_with_action_node_by_imageset_name_func); + if (list == NULL) + break; + if (actions == NULL) { + actions = g_list_alloc(); + actions->data = list->data; + } else + g_list_append(actions, list->data); + node = list->data; + gtk_combo_box_append_text(actionscombobox, xml_node_get_attr_value(node, "name")); + list = list->next; + } +} + +gboolean set_up_imagesets(const XMLNode *root) { + free_imagesets(); + free_actions(); + free_animations(); + GList *list = root->sub_nodes; + XMLNode *node = NULL; + while (TRUE) { + list = g_list_find_custom(list, "imageset", xml_node_compare_with_name); + if (list == NULL) + break; + if (imagesets == NULL) { + imagesets = g_list_alloc(); + imagesets->data = list->data; + } else + g_list_append(imagesets, list->data); + node = list->data; + gtk_combo_box_append_text(imagesetscombobox, xml_node_get_attr_value(node, "name")); + list = list->next; + } + if (imagesets == NULL) + return FALSE; + gtk_combo_box_set_active(imagesetscombobox, 0); + return TRUE; +} + +gboolean sequence_source_func(sequence *seq) { + gchar *end_attr = xml_node_get_attr_value(seq->node, "end"); + size_t end; + sscanf(end_attr, "%d", &end); + if (current_sprite->index == end) { + running_animation = g_timeout_add(seq->delay, show_animation_by_sub_nodes, seq->next); + return FALSE; + } + set_sprite_by_index(current_sprite->index+1); + return TRUE; +} + +gboolean show_animation_by_sub_nodes(GList *sub_nodes) { + XMLNode *node = sub_nodes->data; + if (node == NULL) + return FALSE; + + GList *next = sub_nodes->next; + if (next == NULL) + next = g_list_first(sub_nodes); + + int ofX = 0, ofY = 0; + gchar *ofX_param, *ofY_param; + ofX_param = xml_node_get_attr_value(node, "offsetX"); + if (ofX_param != NULL) + sscanf(ofX_param, "%d", &ofX); + ofY_param = xml_node_get_attr_value(node, "offsetY"); + if (ofY_param != NULL) + sscanf(ofY_param, "%d", &ofY); + current_sprite->offsetX = ofX; + current_sprite->offsetY = ofY; + + if (g_strcmp0(node->name, "frame") == 0) { + gchar *index_attr = xml_node_get_attr_value(node, "index"); + if (index_attr == NULL) + return FALSE; + size_t index; + sscanf(index_attr, "%d", &index); + set_sprite_by_index(index); + if (g_list_length(g_list_first(sub_nodes)) == 1) + return FALSE; + size_t delay = 0; + gchar *delay_attr = xml_node_get_attr_value(node, "delay"); + if (delay_attr != NULL) + sscanf(delay_attr, "%d", &delay); + g_source_remove(running_animation); + running_animation = g_timeout_add(delay, show_animation_by_sub_nodes, next); + return FALSE; + } + if (g_strcmp0(node->name, "sequence") == 0) { + gchar *start_attr = xml_node_get_attr_value(node, "start"); + if (start_attr == NULL) + return FALSE; + gchar *end_attr = xml_node_get_attr_value(node, "end"); + if (end_attr == NULL) + return FALSE; + gchar *delay_attr = xml_node_get_attr_value(node, "delay"); + if (delay_attr == NULL) + return FALSE; + size_t start; + sscanf(start_attr, "%d", &start); + size_t end; + sscanf(end_attr, "%d", &end); + size_t delay; + sscanf(delay_attr, "%d", &delay); + set_sprite_by_index(start); + sequence *seq = g_new0(sequence, 1); + seq->delay = delay; + seq->next = next; + seq->node = node; + g_source_remove(running_animation); + running_animation = g_timeout_add(delay, sequence_source_func, seq); + } + return FALSE; +} + +gboolean show_general_animation() { + XMLNode *node = animations->data; + if (node == NULL) + return FALSE; + return show_animation_by_sub_nodes(node->sub_nodes); +} + +gboolean set_up_action_by_name(const gchar *name) { + free_animations(); + GList *list = g_list_find_custom(actions, name, xml_node_compare_with_name_attr); + if (list == NULL) return FALSE; + list = ((XMLNode *)list->data)->sub_nodes; + gboolean was_direction = FALSE; + while (TRUE) { + list = g_list_find_custom(list, "animation", xml_node_compare_with_name); + if (list == NULL) + break; + if (animations == NULL) { + animations = g_list_alloc(); + animations->data = list->data; + } else + g_list_append(animations, list->data); + XMLNode *node = list->data; + gchar *direction = xml_node_get_attr_value(node, "direction"); + if (direction != NULL) { + gtk_combo_box_append_text(animationscombobox, direction); + was_direction = TRUE; + } + list = list->next; + } + if (animations == NULL) + return FALSE; + if (!was_direction) + show_general_animation(); + return TRUE; +} + +void actions_combo_box_changed_handler(GtkComboBox *widget, gpointer user_data) { + set_up_action_by_name(gtk_combo_box_get_active_text(widget)); +} + +void animations_combo_box_changed_handler(GtkComboBox *widget, gpointer user_data) { + GList *list = g_list_find_custom(animations, gtk_combo_box_get_active_text(widget), xml_node_compare_with_direction_attr); + if (list == NULL) + return; + XMLNode *node = list->data; + show_animation_by_sub_nodes(node->sub_nodes); +} + +void set_up_imageset_by_node(XMLNode *node) { + free_actions(); + free_animations(); + + imageset->node = node; + imageset->offsetX = 0; + imageset->offsetY = 0; + + gchar *offset_attr = xml_node_get_attr_value(imageset->node, "offsetX"); + if (offset_attr != NULL) + sscanf(offset_attr, "%d", &imageset->offsetX); + + offset_attr = xml_node_get_attr_value(imageset->node, "offsetY"); + if (offset_attr != NULL) + sscanf(offset_attr, "%d", &imageset->offsetY); + + gchar *imageset_name = xml_node_get_attr_value(imageset->node, "name"); + set_up_actions_by_imageset_name(imageset_name); + if (actions == NULL) + return; + + gchar *src = xml_node_get_attr_value(imageset->node, "src"); + format_src_string(src); + gchar *datapath = gtk_file_chooser_get_filename(datafoldcbutton); + gchar path[255]; + g_sprintf(path, "%s/%s", datapath, src); + + spriteset = gdk_pixbuf_new_from_file(path, NULL); + spriteset_width = gdk_pixbuf_get_width(spriteset); + spriteset_height = gdk_pixbuf_get_height(spriteset); + + gchar *width = xml_node_get_attr_value(imageset->node, "width"); + sscanf(width, "%d", &sprite_width); + gchar *height = xml_node_get_attr_value(imageset->node, "height"); + sscanf(height, "%d", &sprite_height); + + set_sprite_by_index(0); +} + +void imagesets_combo_box_changed_handler(GtkComboBox *widget, gpointer user_data) { + GList *list = g_list_find_custom(imagesets, gtk_combo_box_get_active_text(widget), xml_node_compare_with_name_attr); + if (list == NULL) + return; + set_up_imageset_by_node(list->data); +} + +void parse_xml_buffer(GtkWidget *button, gpointer buffer) { + GtkTextIter beg, end; + gtk_text_buffer_get_start_iter((GtkSourceBuffer *)buffer, &beg); + gtk_text_buffer_get_end_iter((GtkSourceBuffer *)buffer, &end); + root = ibus_xml_parse_buffer(gtk_text_iter_get_text(&beg, &end)); + if (root == NULL) { + show_wrong_source_buffer_dialog(); + return; + } + if (!set_up_imagesets(root)) { + show_wrong_source_buffer_dialog(); + return; + } + set_up_imageset_by_node(imagesets->data); +} + +void show_about_dialog() { + gchar *authors[] = {"Dan Sagunov <danilka.pro@gmail.com>", + "Reid Yaro <reidyaro@gmail.com>", + NULL}; + gtk_show_about_dialog(GTK_WINDOW(win), + "authors", authors, + "comments", _("Sprite Animation Editor could be used to edit animations from Evol and The Mana World projects"), + "copyright", "Copyleft Vasily_Makarov 2011", + "program-name", "Sprite Animation Editor", + "version", "0.1 prealpha", + NULL); +} + +void set_up_interface() { + GtkWidget *button = NULL; + GtkWidget *hbox = NULL; + GtkWidget *vbox = NULL; + GtkWidget *vbbox = NULL; + GtkWidget *text = NULL; + GtkWidget *label = NULL; + GtkWidget *menubar = NULL; + GtkWidget *menuitem = NULL; + GtkWidget *menu = NULL; + + GtkSourceLanguageManager *langman = gtk_source_language_manager_get_default(); + GtkSourceBuffer *sbuf = gtk_source_buffer_new_with_language(gtk_source_language_manager_get_language(langman, "xml")); + + win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(win), "Sprite Animation Editor"); + gtk_window_set_position (GTK_WINDOW(win), GTK_WIN_POS_CENTER); + gtk_widget_realize(win); + g_signal_connect(win, "destroy", gtk_main_quit, NULL); + gtk_widget_set_size_request(win, MIN_WIDTH, MIN_HEIGHT); + + vbox = gtk_vbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(win), vbox); + + menubar = gtk_menu_bar_new(); + gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, TRUE, 0); + + menu = gtk_menu_new(); + menuitem = gtk_menu_item_new_with_label(_("About")); + g_signal_connect(menuitem, "activate", show_about_dialog, NULL); + gtk_menu_append(menu, menuitem); + + menuitem = gtk_menu_item_new_with_label(_("Help")); + gtk_menu_item_set_submenu(menuitem, menu); + gtk_menu_bar_append(menubar, menuitem); + + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); + + vbbox = gtk_vbutton_box_new(); + gtk_button_box_set_layout(vbbox, GTK_BUTTONBOX_START); + gtk_button_box_set_child_size(vbbox, 180, 0); + gtk_box_pack_start(GTK_BOX(hbox), vbbox, FALSE, TRUE, 0); + + label = gtk_label_new(""); + gtk_label_set_markup(label, markup_bold(_("Clientdata folder"))); + gtk_box_pack_start(GTK_BOX(vbbox), label, TRUE, TRUE, 0); + + datafoldcbutton = gtk_file_chooser_button_new(_("Clientdata folder"), 0); + gtk_box_pack_start(GTK_BOX(vbbox), datafoldcbutton, TRUE, TRUE, 0); + gtk_file_chooser_set_action(datafoldcbutton, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); + g_signal_connect(datafoldcbutton, "file-set", G_CALLBACK(data_folder_set_handler), NULL); + + label = gtk_label_new(""); + gtk_label_set_markup(label, markup_bold(_("XML source file"))); + gtk_box_pack_start(GTK_BOX(vbbox), label, TRUE, TRUE, 0); + + xmlfcbutton = gtk_file_chooser_button_new(_("XML source file"), 0); + gtk_box_pack_start(GTK_BOX(vbbox), xmlfcbutton, TRUE, TRUE, 0); + + xmlfobutton = gtk_button_new_from_stock(GTK_STOCK_OPEN); + gtk_widget_set_sensitive(xmlfobutton, FALSE); + gtk_box_pack_start(GTK_BOX(vbbox), xmlfobutton, TRUE, TRUE, 0); + g_signal_connect(xmlfobutton, "clicked", G_CALLBACK(open_xml_file), sbuf); + + xmlfsbutton = gtk_button_new_from_stock(GTK_STOCK_SAVE); + gtk_widget_set_sensitive(xmlfsbutton, FALSE); + gtk_box_pack_start(GTK_BOX(vbbox), xmlfsbutton, TRUE, TRUE, 0); + g_signal_connect(xmlfsbutton, "clicked", G_CALLBACK(save_to_xml_file), sbuf); + + g_signal_connect(xmlfcbutton, "file-set", G_CALLBACK(xml_file_set_handler), NULL); + + button = gtk_button_new_with_label("Parse XML buffer"); + gtk_box_pack_start(GTK_BOX(vbbox), button, TRUE, TRUE, 0); + g_signal_connect(button, "clicked", G_CALLBACK(parse_xml_buffer), sbuf); + + label = gtk_label_new(""); + gtk_label_set_markup(label, markup_bold(_("Imagesets"))); + gtk_box_pack_start(GTK_BOX(vbbox), label, TRUE, TRUE, 0); + + imagesetscombobox = gtk_combo_box_new_text(); + g_signal_connect(imagesetscombobox, "changed", imagesets_combo_box_changed_handler, NULL); + gtk_box_pack_start(GTK_BOX(vbbox), imagesetscombobox, TRUE, TRUE, 0); + + label = gtk_label_new(""); + gtk_label_set_markup(label, markup_bold(_("Actions"))); + gtk_box_pack_start(GTK_BOX(vbbox), label, TRUE, TRUE, 0); + + actionscombobox = gtk_combo_box_new_text(); + g_signal_connect(actionscombobox, "changed", actions_combo_box_changed_handler, NULL); + gtk_box_pack_start(GTK_BOX(vbbox), actionscombobox, TRUE, TRUE, 0); + + label = gtk_label_new(""); + gtk_label_set_markup(label, markup_bold(_("Directions"))); + gtk_box_pack_start(GTK_BOX(vbbox), label, TRUE, TRUE, 0); + + animationscombobox = gtk_combo_box_new_text(); + g_signal_connect(animationscombobox, "changed", animations_combo_box_changed_handler, NULL); + gtk_box_pack_start(GTK_BOX(vbbox), animationscombobox, TRUE, TRUE, 0); + + vbox = gtk_vbox_new(TRUE, 0); + gtk_box_pack_end(GTK_BOX(hbox), vbox, TRUE, TRUE, 0); + + darea = gtk_drawing_area_new(); + gtk_box_pack_start(GTK_BOX(vbox), darea, TRUE, TRUE, 0); + g_signal_connect(darea, "expose-event", on_expose_event, NULL); + + text = gtk_source_view_new_with_buffer(sbuf); + gtk_source_view_set_show_line_numbers(text, TRUE); + gtk_box_pack_start(GTK_BOX(vbox), text, TRUE, TRUE, 0); + + gtk_widget_show_all(win); + gtk_widget_show_all(text); +} + +int main (int argc, char *argv[]) { + + gtk_init(&argc, &argv); + + current_sprite = sprite_info_new(-1, 0, 0); + imageset = imageset_info_new(); + + set_up_interface(); + + gtk_main(); + + return 0; +} diff --git a/saedit/main.h b/saedit/main.h new file mode 100644 index 0000000..02f060f --- /dev/null +++ b/saedit/main.h @@ -0,0 +1,62 @@ +/*=======================================*\ +| ____ ____ | +| / \ /\ | | +| \____ / \ |____ | +| \ /____\ | | +| \____/prite / \nimation |____ditor | +| | +| Copyleft Vasily_Makarov 2011 | +| | +\*=======================================*/ +typedef struct { + XMLNode *node; + GList *next; + guint delay; +} sequence; + +typedef struct { + int index; + int offsetX; + int offsetY; +} sprite_info; +static sprite_info *sprite_info_new(int index, int offsetX, int offsetY); + +typedef struct { + XMLNode *node; + int offsetX; + int offsetY; +} imageset_info; +static imageset_info *imageset_info_new() { + return g_new0(imageset_info, 1); +} + +static gboolean show_animation_by_sub_nodes (GList *sub_nodes); +static gchar *markup_bold(gchar *str); +static void format_src_string(gchar *src); +static void open_xml_file(GtkButton *button, gpointer buffer); +static void free_imagesets(); +static void free_actions(); +static void free_animations(); +static void save_to_xml_file(GtkButton *button, gpointer buffer); +static void xml_file_set_handler(GtkFileChooserButton *widget, gpointer data); +static void data_folder_set_handler(GtkFileChooserButton *widget, gpointer data); +static void show_wrong_source_buffer_dialog(); +static gchar* xml_node_get_attr_value(const XMLNode *node, const gchar *attr_name); +static gint xml_node_compare_with_name(gconstpointer a, gconstpointer b); +static gint xml_node_compare_with_action_node_by_imageset_name_func(gconstpointer a, gconstpointer b); +static gint xml_node_compare_with_direction_attr(gconstpointer node, gconstpointer direction); +static gint xml_node_compare_with_name_attr(gconstpointer node, gconstpointer name); +static GdkPixbuf* get_sprite_by_index(size_t index); +static void set_sprite_by_index(size_t index); +static void set_up_actions_by_imageset_name(gchar *imageset_name); +static gboolean set_up_imagesets(const XMLNode *root); +static gboolean sequence_source_func(sequence *seq); +static gboolean show_general_animation(); +static gboolean set_up_action_by_name(const gchar *name); +static void actions_combo_box_changed_handler(GtkComboBox *widget, gpointer user_data); +static void animations_combo_box_changed_handler(GtkComboBox *widget, gpointer user_data); +static void set_up_imageset_by_node(XMLNode *node); +static void imagesets_combo_box_changed_handler(GtkComboBox *widget, gpointer user_data); +static void parse_xml_buffer(GtkWidget *button, gpointer buffer); +static void set_up_interface(); +static void show_about_dialog(); |