[gimp/wip/animation: 288/373] plug-ins: automatically create animation cycles from layer names.
- From: Jehan Pagès <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/wip/animation: 288/373] plug-ins: automatically create animation cycles from layer names.
- Date: Sat, 7 Oct 2017 02:18:56 +0000 (UTC)
commit 45bf32b055b719f663de6e00aa9de726de3e027a
Author: Jehan <jehan girinstud io>
Date: Sun Dec 4 14:12:53 2016 +0100
plug-ins: automatically create animation cycles from layer names.
.../animation-play/widgets/animation-layer-view.c | 2 +-
plug-ins/animation-play/widgets/animation-xsheet.c | 655 +++++++++++++++++---
2 files changed, 571 insertions(+), 86 deletions(-)
---
diff --git a/plug-ins/animation-play/widgets/animation-layer-view.c
b/plug-ins/animation-play/widgets/animation-layer-view.c
index c7e632c..af116c5 100644
--- a/plug-ins/animation-play/widgets/animation-layer-view.c
+++ b/plug-ins/animation-play/widgets/animation-layer-view.c
@@ -97,7 +97,7 @@ animation_layer_view_class_init (AnimationLayerViewClass *klass)
/**
* AnimationLayerView::layer-selection:
* @layer_view: the widget which received the signal.
- * @layers: the #GList of layer ids which are currently selected.
+ * @layers: the #GList of layer tattoos which are currently selected.
*
* The ::layer-selection signal is emitted each time the selection changes
* in @layer_view.
diff --git a/plug-ins/animation-play/widgets/animation-xsheet.c
b/plug-ins/animation-play/widgets/animation-xsheet.c
index ef243b6..e1b4beb 100755
--- a/plug-ins/animation-play/widgets/animation-xsheet.c
+++ b/plug-ins/animation-play/widgets/animation-xsheet.c
@@ -24,6 +24,7 @@
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
#include "animation-utils.h"
@@ -41,7 +42,9 @@ enum
{
PROP_0,
PROP_ANIMATION,
- PROP_LAYER_VIEW
+ PROP_LAYER_VIEW,
+ PROP_SUITE_CYCLE,
+ PROP_SUITE_FPI
};
struct _AnimationXSheetPrivate
@@ -56,6 +59,13 @@ struct _AnimationXSheetPrivate
GtkWidget *active_pos_button;
GList *position_buttons;
+ GtkWidget *suite_box;
+ GtkWidget *suite_button;
+ gint suite_position;
+ gint suite_level;
+ gint suite_cycle;
+ gint suite_fpi;
+
GList *cels;
gint selected_track;
GQueue *selected_frames;
@@ -118,11 +128,15 @@ static void on_layer_selection (AnimationLayerView *view,
AnimationXSheet *xsheet);
/* UI Signals */
+static void animation_xsheet_suite_do (GtkWidget *button,
+ AnimationXSheet *xsheet);
+static void animation_xsheet_suite_cancelled (GtkWidget *button,
+ AnimationXSheet *xsheet);
static gboolean animation_xsheet_frame_clicked (GtkWidget *button,
GdkEvent *event,
AnimationXSheet *xsheet);
static gboolean animation_xsheet_cel_clicked (GtkWidget *button,
- GdkEvent *event,
+ GdkEventButton *event,
AnimationXSheet *xsheet);
static void animation_xsheet_track_title_updated (GtkEntryBuffer *buffer,
GParamSpec *param_spec,
@@ -177,12 +191,37 @@ animation_xsheet_class_init (AnimationXSheetClass *klass)
ANIMATION_TYPE_CEL_ANIMATION,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
+ /**
+ * AnimationXSheet:layer-view:
+ *
+ * The associated #AnimationLayerView.
+ */
g_object_class_install_property (object_class, PROP_LAYER_VIEW,
g_param_spec_object ("layer-view",
NULL, NULL,
ANIMATION_TYPE_LAYER_VIEW,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
+ /**
+ * AnimationXSheet:suite-cycle:
+ *
+ * The configured cycle repeat. 0 means indefinitely.
+ */
+ g_object_class_install_property (object_class, PROP_SUITE_CYCLE,
+ g_param_spec_int ("suite-cycle", NULL,
+ NULL,
+ 0, 100, 0,
+ GIMP_PARAM_READWRITE));
+ /**
+ * AnimationXSheet:suite-frames-per-image:
+ *
+ * The number of frames each image will be displayed.
+ */
+ g_object_class_install_property (object_class, PROP_SUITE_FPI,
+ g_param_spec_int ("suite-frames-per-image", NULL,
+ NULL,
+ 0, 10, 0,
+ GIMP_PARAM_READWRITE));
g_type_class_add_private (klass, sizeof (AnimationXSheetPrivate));
}
@@ -194,6 +233,8 @@ animation_xsheet_init (AnimationXSheet *xsheet)
ANIMATION_TYPE_XSHEET,
AnimationXSheetPrivate);
xsheet->priv->selected_frames = g_queue_new ();
+ xsheet->priv->suite_fpi = 2;
+ xsheet->priv->suite_cycle = 1;
}
/************ Public Functions ****************/
@@ -269,6 +310,12 @@ animation_xsheet_set_property (GObject *object,
case PROP_LAYER_VIEW:
xsheet->priv->layer_view = g_value_dup_object (value);
break;
+ case PROP_SUITE_CYCLE:
+ xsheet->priv->suite_cycle = g_value_get_int (value);
+ break;
+ case PROP_SUITE_FPI:
+ xsheet->priv->suite_fpi = g_value_get_int (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -292,6 +339,12 @@ animation_xsheet_get_property (GObject *object,
case PROP_LAYER_VIEW:
g_value_set_object (value, xsheet->priv->layer_view);
break;
+ case PROP_SUITE_CYCLE:
+ g_value_set_int (value, xsheet->priv->suite_cycle);
+ break;
+ case PROP_SUITE_FPI:
+ g_value_set_int (value, xsheet->priv->suite_fpi);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -1065,6 +1118,325 @@ on_animation_rendered (AnimationPlayback *playback,
animation_xsheet_jump (xsheet, frame_number);
}
+static gint
+compare_layer_names (gchar *title1,
+ gchar *title2,
+ GRegex *regex)
+{
+ GMatchInfo *match1;
+ GMatchInfo *match2;
+ gint retval = 0;
+
+ if (g_regex_match (regex, title1, 0, &match1) &&
+ g_regex_match (regex, title2, 0, &match2))
+ {
+ gchar **tokens1;
+ gchar **tokens2;
+ gchar *str_num1 = g_match_info_fetch (match1, 1);
+ gchar *str_num2 = g_match_info_fetch (match2, 1);
+ gint i = 0;
+
+ tokens1 = g_strsplit_set (str_num1, "-_", -1);
+ tokens2 = g_strsplit_set (str_num2, "-_", -1);
+
+ while (TRUE)
+ {
+ gchar *token1 = tokens1[i];
+ gchar *token2 = tokens2[i];
+ gint num1;
+ gint num2;
+
+ if (token1 && strlen (token1) &&
+ (! token2 || strlen (token2) == 0))
+ {
+ retval = 1;
+ break;
+ }
+ else if (token2 && strlen (token2) &&
+ (! token1 || strlen (token1) == 0))
+ {
+ retval = -1;
+ break;
+ }
+ else if ((! token1 || strlen (token1) == 0) &&
+ (! token2 || strlen (token2) == 0))
+ {
+ retval = 0;
+ break;
+ }
+
+ num1 = (gint) g_ascii_strtoll (token1, NULL, 10);
+ num2 = (gint) g_ascii_strtoll (token2, NULL, 10);
+
+ if (num1 > num2)
+ {
+ retval = 1;
+ break;
+ }
+ else if (num1 < num2)
+ {
+ retval = -1;
+ break;
+ }
+ /* In case of equal numbers, continue. */
+ i++;
+ }
+ g_free (str_num1);
+ g_free (str_num2);
+ g_strfreev (tokens1);
+ g_strfreev (tokens2);
+ }
+
+ return retval;
+}
+
+static gint
+compare_layer_by_name (gint layer1,
+ gint layer2,
+ GRegex *regex)
+{
+ gchar *title1;
+ gchar *title2;
+ gint retval;
+
+ title1 = gimp_item_get_name (layer1);
+ title2 = gimp_item_get_name (layer2);
+
+ retval = compare_layer_names (title1, title2, regex);
+
+ g_free (title1);
+ g_free (title2);
+
+ return retval;
+}
+
+static GList *
+animation_xsheet_get_layer_suite (AnimationXSheet *xsheet,
+ const gchar *prefix,
+ const gchar *suffix,
+ const gchar *lower_title)
+{
+ GRegex *regex;
+ gchar *esc_prefix;
+ gchar *esc_suffix;
+ gchar *regex_string;
+ GList *compatible_layers = NULL;
+ gint *layers;
+ gint32 image_id;
+ gint num_layers;
+ gint i;
+
+ image_id = animation_get_image_id (ANIMATION (xsheet->priv->animation));
+
+ /* Escape characters used in regular expressions. */
+ esc_prefix = g_regex_escape_string (prefix, -1);
+ esc_suffix = g_regex_escape_string (suffix, -1);
+
+ regex_string = g_strdup_printf ("^%s[ \t_-]*([0-9]*(([-_][0-9]+)*)?)[ \t]*%s[ \t]*$",
+ esc_prefix, esc_suffix);
+ regex = g_regex_new (regex_string, 0, 0, NULL);
+ g_free (esc_prefix);
+ g_free (esc_suffix);
+ g_free (regex_string);
+
+ /* Loop through the image layers. */
+ layers = gimp_image_get_layers (image_id,
+ &num_layers);
+ for (i = 0; i < num_layers; i++)
+ {
+ gchar *layer_title;
+
+ layer_title = gimp_item_get_name (layers[i]);
+ if (g_regex_match (regex, layer_title, 0, NULL) &&
+ (! lower_title || compare_layer_names (layer_title,
+ (gchar *) lower_title,
+ regex) >= 0))
+ {
+ compatible_layers = g_list_insert_sorted_with_data (compatible_layers,
+ GINT_TO_POINTER (layers[i]),
+ (GCompareDataFunc) compare_layer_by_name,
+ regex);
+ }
+
+ g_free (layer_title);
+ }
+ g_regex_unref (regex);
+ g_free (layers);
+
+ return compatible_layers;
+}
+
+static void
+animation_xsheet_suite_do (GtkWidget *button,
+ AnimationXSheet *xsheet)
+{
+ const GList *selection;
+ GList **select_compat;
+ GList *cels;
+ GtkWidget *cel;
+ GRegex *regex;
+ gint32 image_id;
+ gint selected_position;
+ gint position;
+ gint level;
+ gint duration;
+ gint n_selection;
+ gint loop;
+ gint suite_length = 0;
+ gint i;
+
+ image_id = animation_get_image_id (ANIMATION (xsheet->priv->animation));
+ duration = animation_get_duration (ANIMATION (xsheet->priv->animation));
+
+ selected_position = GPOINTER_TO_INT (g_queue_peek_tail (xsheet->priv->selected_frames));
+ position = xsheet->priv->suite_position;
+ level = xsheet->priv->suite_level;
+
+ selection = animation_cel_animation_get_layers (xsheet->priv->animation,
+ level, position);
+ n_selection = selection ? g_list_length ((GList *) selection) : 1;
+ select_compat = g_new0 (GList *, n_selection);
+
+ if (selection)
+ {
+ /* Using current selection as base. */
+ GMatchInfo *match;
+
+ regex = g_regex_new ("^(.*[^0-9_-])[ \t_-]*([0-9]+([-_][0-9]+)*)[ \t]*([^0-9]*)[ \t]*$",
+ 0, 0, NULL);
+ for (i = 0; selection; selection = selection->next, i++)
+ {
+ GList *compatible_layers;
+ gint32 layer;
+ gchar *layer_title;
+ gchar *title_prefix;
+ gchar *title_suffix;
+
+ layer = gimp_image_get_layer_by_tattoo (image_id,
+ GPOINTER_TO_INT (selection->data));
+ layer_title = gimp_item_get_name (layer);
+
+ if (g_regex_match (regex, layer_title, 0, &match))
+ {
+ title_prefix = g_match_info_fetch (match, 1);
+ title_suffix = g_match_info_fetch (match, 4);
+ }
+ else
+ {
+ title_prefix = g_strdup (layer_title);
+ title_suffix = g_strdup ("");
+ }
+ compatible_layers = animation_xsheet_get_layer_suite (xsheet, title_prefix,
+ title_suffix, layer_title);
+ select_compat[i] = compatible_layers;
+ g_free (title_prefix);
+ g_free (title_suffix);
+ }
+ }
+ else
+ {
+ const gchar *track_title;
+ GList *compatible_layers = NULL;
+
+ track_title = animation_cel_animation_get_track_title (xsheet->priv->animation,
+ level);
+ compatible_layers = animation_xsheet_get_layer_suite (xsheet, track_title,
+ "", NULL);
+ select_compat[0] = compatible_layers;
+ }
+
+ for (i = 0; i < n_selection; i++)
+ {
+ GList *layers = select_compat[i];
+
+ suite_length = MAX (suite_length,
+ g_list_length (layers) * xsheet->priv->suite_fpi);
+ }
+
+ for (loop = 0; xsheet->priv->suite_cycle == 0 || loop < xsheet->priv->suite_cycle; loop++)
+ {
+ /* If no current selection, use the track name. */
+ gboolean end_of_animation = FALSE;
+
+ /* Set the layers to successive positions. */
+ for (i = 0; i < suite_length; i++)
+ {
+ GList *new_layers = NULL;
+ gint j;
+
+ for (j = 0; j < n_selection; j++)
+ {
+ GList *layers = select_compat[j];
+ GList *layer;
+
+ layer = g_list_nth (layers, i);
+ if (layer)
+ {
+ gint tattoo;
+
+ tattoo = gimp_item_get_tattoo (GPOINTER_TO_INT (layer->data));
+ new_layers = g_list_prepend (new_layers, GINT_TO_POINTER (tattoo));
+ }
+ }
+
+ for (j = 0; j < xsheet->priv->suite_fpi; j++)
+ {
+ gint pos;
+
+ pos = position + (i * xsheet->priv->suite_fpi) + j + suite_length * loop;
+ if (pos >= duration)
+ {
+ end_of_animation = TRUE;
+ break;
+ }
+
+ animation_cel_animation_set_layers (xsheet->priv->animation,
+ level, pos,
+ new_layers);
+ /* If currently selected position, refresh the layer view. */
+ if (xsheet->priv->selected_track == level &&
+ selected_position == pos)
+ {
+ animation_layer_view_select (ANIMATION_LAYER_VIEW (xsheet->priv->layer_view),
+ new_layers);
+ }
+ }
+
+ g_list_free (new_layers);
+
+ if (end_of_animation)
+ break;
+ }
+
+ if (end_of_animation)
+ break;
+ }
+
+ /* Cleaning. */
+ for (i = 0; i < n_selection; i++)
+ g_list_free (select_compat[i]);
+ g_free (select_compat);
+
+ /* Rename the cels. */
+ cels = g_list_nth_data (xsheet->priv->cels, level);
+ cel = g_list_nth_data (cels, position);
+
+ animation_xsheet_rename_cel (xsheet, cel, TRUE);
+
+ /* Delete the widget. */
+ animation_xsheet_suite_cancelled (NULL, xsheet);
+}
+
+static void
+animation_xsheet_suite_cancelled (GtkWidget *button,
+ AnimationXSheet *xsheet)
+{
+ gtk_widget_destroy (xsheet->priv->suite_box);
+ xsheet->priv->suite_box = NULL;
+ gtk_widget_show (xsheet->priv->suite_button);
+ xsheet->priv->suite_button = NULL;
+}
+
static gboolean
animation_xsheet_frame_clicked (GtkWidget *button,
GdkEvent *event,
@@ -1093,7 +1465,7 @@ animation_xsheet_frame_clicked (GtkWidget *button,
static gboolean
animation_xsheet_cel_clicked (GtkWidget *button,
- GdkEvent *event,
+ GdkEventButton *event,
AnimationXSheet *xsheet)
{
gpointer track_num;
@@ -1106,116 +1478,229 @@ animation_xsheet_cel_clicked (GtkWidget *button,
position = g_object_get_data (G_OBJECT (button), "frame-position");
toggled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
- shift = ((GdkEventButton *) event)->state & GDK_SHIFT_MASK;
- ctrl = ((GdkEventButton *) event)->state & GDK_CONTROL_MASK;
+ shift = event->state & GDK_SHIFT_MASK;
+ ctrl = event->state & GDK_CONTROL_MASK;
- if ((! shift && ! ctrl) ||
- (xsheet->priv->selected_track >= 0 &&
- xsheet->priv->selected_track != GPOINTER_TO_INT (track_num)))
+ /* Left click */
+ if (event->button == 1)
{
- /* Changing track and normal click resets selection. */
- GList *track_iter;
- GList *frame_iter;
- for (track_iter = xsheet->priv->cels; track_iter; track_iter = track_iter->next)
+ if ((! shift && ! ctrl) ||
+ (xsheet->priv->selected_track >= 0 &&
+ xsheet->priv->selected_track != GPOINTER_TO_INT (track_num)))
{
- for (frame_iter = track_iter->data; frame_iter; frame_iter = frame_iter->next)
+ /* Changing track and normal click resets selection. */
+ GList *track_iter;
+ GList *frame_iter;
+
+ for (track_iter = xsheet->priv->cels; track_iter; track_iter = track_iter->next)
{
- gtk_toggle_button_set_active (frame_iter->data, FALSE);
+ for (frame_iter = track_iter->data; frame_iter; frame_iter = frame_iter->next)
+ {
+ gtk_toggle_button_set_active (frame_iter->data, FALSE);
+ }
}
+ g_queue_clear (xsheet->priv->selected_frames);
+ xsheet->priv->selected_track = -1;
}
- g_queue_clear (xsheet->priv->selected_frames);
- xsheet->priv->selected_track = -1;
- }
- if (ctrl)
- {
- /* Ctrl toggle the clicked selection. */
- if (toggled)
+ if (ctrl)
{
- g_queue_remove (xsheet->priv->selected_frames, position);
- if (g_queue_is_empty (xsheet->priv->selected_frames))
+ /* Ctrl toggle the clicked selection. */
+ if (toggled)
+ {
+ g_queue_remove (xsheet->priv->selected_frames, position);
+ if (g_queue_is_empty (xsheet->priv->selected_frames))
+ {
+ xsheet->priv->selected_track = -1;
+ }
+ }
+ else
{
- xsheet->priv->selected_track = -1;
+ g_queue_push_head (xsheet->priv->selected_frames, position);
+ xsheet->priv->selected_track = GPOINTER_TO_INT (track_num);
}
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+ ! toggled);
}
- else
+ else if (shift)
{
- g_queue_push_head (xsheet->priv->selected_frames, position);
+ /* Shift selects all from the first selection, and unselects
+ * anything else. */
+ GList *track_iter;
+ GList *frame_iter;
+ gint from = GPOINTER_TO_INT (position);
+ gint to = from;
+ gint direction;
+ gint min;
+ gint max;
+ gint i;
+
xsheet->priv->selected_track = GPOINTER_TO_INT (track_num);
- }
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
- ! toggled);
- }
- else if (shift)
- {
- /* Shift selects all from the first selection, and unselects
- * anything else. */
- GList *track_iter;
- GList *frame_iter;
- gint from = GPOINTER_TO_INT (position);
- gint to = from;
- gint direction;
- gint min;
- gint max;
- gint i;
-
- xsheet->priv->selected_track = GPOINTER_TO_INT (track_num);
- for (track_iter = xsheet->priv->cels; track_iter; track_iter = track_iter->next)
- {
- for (frame_iter = track_iter->data; frame_iter; frame_iter = frame_iter->next)
+ for (track_iter = xsheet->priv->cels; track_iter; track_iter = track_iter->next)
+ {
+ for (frame_iter = track_iter->data; frame_iter; frame_iter = frame_iter->next)
+ {
+ gtk_toggle_button_set_active (frame_iter->data, FALSE);
+ }
+ }
+ if (! g_queue_is_empty (xsheet->priv->selected_frames))
{
- gtk_toggle_button_set_active (frame_iter->data, FALSE);
+ from = GPOINTER_TO_INT (g_queue_pop_tail (xsheet->priv->selected_frames));
+ g_queue_clear (xsheet->priv->selected_frames);
+ }
+ direction = from > to? -1 : 1;
+ for (i = from; i != to + direction; i = i + direction)
+ {
+ g_queue_push_head (xsheet->priv->selected_frames,
+ GINT_TO_POINTER (i));
+ }
+ min = MIN (to, from);
+ max = MAX (to, from);
+ track_iter = g_list_nth (xsheet->priv->cels, xsheet->priv->selected_track);
+ frame_iter = track_iter->data;
+ for (i = 0; frame_iter && i <= max; frame_iter = frame_iter->next, i++)
+ {
+ if (i >= min)
+ {
+ gtk_toggle_button_set_active (frame_iter->data, TRUE);
+ }
}
}
- if (! g_queue_is_empty (xsheet->priv->selected_frames))
+ else /* ! shift && ! ctrl */
{
- from = GPOINTER_TO_INT (g_queue_pop_tail (xsheet->priv->selected_frames));
- g_queue_clear (xsheet->priv->selected_frames);
+ xsheet->priv->selected_track = GPOINTER_TO_INT (track_num);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+ g_queue_push_head (xsheet->priv->selected_frames, position);
}
- direction = from > to? -1 : 1;
- for (i = from; i != to + direction; i = i + direction)
+
+ /* Finally update the layer view. */
+ if (g_queue_is_empty (xsheet->priv->selected_frames))
{
- g_queue_push_head (xsheet->priv->selected_frames,
- GINT_TO_POINTER (i));
+ animation_layer_view_select (ANIMATION_LAYER_VIEW (xsheet->priv->layer_view),
+ NULL);
}
- min = MIN (to, from);
- max = MAX (to, from);
- track_iter = g_list_nth (xsheet->priv->cels, xsheet->priv->selected_track);
- frame_iter = track_iter->data;
- for (i = 0; frame_iter && i <= max; frame_iter = frame_iter->next, i++)
+ else
{
- if (i >= min)
- {
- gtk_toggle_button_set_active (frame_iter->data, TRUE);
- }
+ const GList *layers;
+
+ /* When several frames are selected, show layers of the first selected. */
+ position = g_queue_peek_tail (xsheet->priv->selected_frames);
+
+ layers = animation_cel_animation_get_layers (xsheet->priv->animation,
+ GPOINTER_TO_INT (track_num),
+ GPOINTER_TO_INT (position));
+ animation_layer_view_select (ANIMATION_LAYER_VIEW (xsheet->priv->layer_view),
+ layers);
}
}
- else /* ! shift && ! ctrl */
+ /* Middle click */
+ else if (event->button == 2)
{
- xsheet->priv->selected_track = GPOINTER_TO_INT (track_num);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
- g_queue_push_head (xsheet->priv->selected_frames, position);
- }
+ GtkWidget *widget;
+ GtkWidget *image;
+ gint level = GPOINTER_TO_INT (track_num);
+ gint pos = GPOINTER_TO_INT (position);
- /* Finally update the layer view. */
- if (g_queue_is_empty (xsheet->priv->selected_frames))
- {
- animation_layer_view_select (ANIMATION_LAYER_VIEW (xsheet->priv->layer_view),
- NULL);
- }
- else
- {
- const GList *layers;
+ if (xsheet->priv->suite_box)
+ {
+ gtk_widget_show (xsheet->priv->suite_button);
+ gtk_widget_destroy (xsheet->priv->suite_box);
+ }
- /* When several frames are selected, show layers of the first selected. */
- position = g_queue_peek_tail (xsheet->priv->selected_frames);
+ xsheet->priv->suite_box = gtk_table_new (2, 3, FALSE);
+ xsheet->priv->suite_position = pos;
+ xsheet->priv->suite_level = level;
+
+ g_object_set_data (G_OBJECT (xsheet->priv->suite_box),
+ "frame-position", position);
+ g_object_set_data (G_OBJECT (xsheet->priv->suite_box),
+ "track-num", track_num);
+
+ /* Frame per image label */
+ widget = gtk_label_new (_("On:"));
+ gimp_help_set_help_data (widget,
+ _("Number of frames per image"),
+ NULL);
+ gtk_table_attach (GTK_TABLE (xsheet->priv->suite_box),
+ widget, 0, 1, 0, 1,
+ GTK_EXPAND, GTK_SHRINK, 2, 0);
+ gtk_widget_show (widget);
+
+ /* Frame per image spin */
+ widget = gimp_prop_spin_button_new (G_OBJECT (xsheet),
+ "suite-frames-per-image",
+ 1.0, 2.0, 0.0);
+ gtk_spin_button_set_range (GTK_SPIN_BUTTON (widget),
+ 1.0, 100.0);
+ gtk_entry_set_width_chars (GTK_ENTRY (widget), 2);
+ gtk_table_attach (GTK_TABLE (xsheet->priv->suite_box),
+ widget, 1, 2, 0, 1,
+ GTK_SHRINK, GTK_SHRINK, 2, 0);
+ gtk_widget_show (widget);
+
+ /* Cycle label */
+ widget = gtk_label_new (_("Cycle:"));
+ gimp_help_set_help_data (widget,
+ _("Number of times the whole cycle repeats"
+ " (0 means indefinitely)"),
+ NULL);
+ gtk_table_attach (GTK_TABLE (xsheet->priv->suite_box),
+ widget, 0, 1, 1, 2,
+ GTK_EXPAND, GTK_SHRINK, 2, 0);
+ gtk_widget_show (widget);
+
+ /* Cycle spin */
+ widget = gimp_prop_spin_button_new (G_OBJECT (xsheet),
+ "suite-cycle",
+ 1.0, 5.0, 0.0);
+ gtk_entry_set_width_chars (GTK_ENTRY (widget), 2);
+ gtk_table_attach (GTK_TABLE (xsheet->priv->suite_box),
+ widget, 1, 2, 1, 2,
+ GTK_SHRINK, GTK_SHRINK, 2, 0);
+ gtk_widget_show (widget);
+
+ /* Ok button */
+ widget = gtk_button_new ();
+
+ image = gtk_image_new_from_icon_name ("gtk-ok",
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_container_add (GTK_CONTAINER (widget),
+ image);
+ gtk_table_attach (GTK_TABLE (xsheet->priv->suite_box),
+ widget, 2, 3, 0, 1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 0);
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (animation_xsheet_suite_do),
+ xsheet);
+ gtk_widget_show (image);
+ gtk_widget_show (widget);
+
+ /* Cancel button */
+ widget = gtk_button_new ();
+
+ image = gtk_image_new_from_icon_name ("gtk-cancel",
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_container_add (GTK_CONTAINER (widget),
+ image);
+ gtk_table_attach (GTK_TABLE (xsheet->priv->suite_box),
+ widget, 2, 3, 1, 2,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 0);
+ g_signal_connect (widget, "clicked",
+ G_CALLBACK (animation_xsheet_suite_cancelled),
+ xsheet);
+ gtk_widget_show (image);
+ gtk_widget_show (widget);
- layers = animation_cel_animation_get_layers (xsheet->priv->animation,
- GPOINTER_TO_INT (track_num),
- GPOINTER_TO_INT (position));
- animation_layer_view_select (ANIMATION_LAYER_VIEW (xsheet->priv->layer_view),
- layers);
+ /* Finalize */
+ gtk_table_attach (GTK_TABLE (xsheet->priv->track_layout),
+ xsheet->priv->suite_box,
+ level * 9 + 1, level * 9 + 10,
+ pos + 2, pos + 3,
+ GTK_FILL, GTK_FILL, 0, 0);
+ gtk_widget_hide (button);
+ xsheet->priv->suite_button = button;
+ gtk_widget_show (xsheet->priv->suite_box);
}
/* All handled here. */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]