[gimp/wip/animation: 82/197] plug-ins: add a spin button to set duration for cel animations.



commit e04da2b7adabcdbc43a6167385fff6692fa55fdb
Author: Jehan <jehan girinstud io>
Date:   Fri Nov 11 03:13:24 2016 +0100

    plug-ins: add a spin button to set duration for cel animations.
    
    Current GUI is not very pretty, but I just do something which "works"
    for now. I also have some issues with the spin button: clicking an arrow
    sometimes moves of 2 or 3 frames. Using a debugger, there seems to be
    some race condition with GtkSpinButton code which reproduces the event.
    I will have to get a closer look later.

 .../animation-play/core/animation-celanimation.c   |    9 ++-
 plug-ins/animation-play/widgets/animation-dialog.c |   62 +++++++++++++
 plug-ins/animation-play/widgets/animation-xsheet.c |   91 ++++++++++++++------
 3 files changed, 133 insertions(+), 29 deletions(-)
---
diff --git a/plug-ins/animation-play/core/animation-celanimation.c 
b/plug-ins/animation-play/core/animation-celanimation.c
index 49eea13..df1f80f 100644
--- a/plug-ins/animation-play/core/animation-celanimation.c
+++ b/plug-ins/animation-play/core/animation-celanimation.c
@@ -337,9 +337,12 @@ animation_cel_animation_set_duration (AnimationCelAnimation *animation,
         }
     }
 
-  animation->priv->duration = duration;
-  g_signal_emit_by_name (animation, "duration-changed",
-                         duration);
+  if (duration != animation->priv->duration)
+    {
+      animation->priv->duration = duration;
+      g_signal_emit_by_name (animation, "duration-changed",
+                             duration);
+    }
 }
 
 gint
diff --git a/plug-ins/animation-play/widgets/animation-dialog.c 
b/plug-ins/animation-play/widgets/animation-dialog.c
index 948b41a..3be948b 100755
--- a/plug-ins/animation-play/widgets/animation-dialog.c
+++ b/plug-ins/animation-play/widgets/animation-dialog.c
@@ -71,6 +71,8 @@ struct _AnimationDialogPrivate
 
   GtkWidget         *animation_type_combo;
   GtkWidget         *fpscombo;
+  GtkWidget         *duration_box;
+  GtkWidget         *duration_spin;
   GtkWidget         *zoomcombo;
   GtkWidget         *proxycombo;
 
@@ -147,6 +149,9 @@ static void        help_callback             (GtkAction        *action,
 static void        animation_type_changed    (GtkWidget        *combo,
                                               AnimationDialog  *dialog);
 
+static void        on_duration_spin_changed  (GtkAdjustment    *adjustment,
+                                              AnimationDialog  *dialog);
+
 static void        fpscombo_activated        (GtkEntry         *combo,
                                               AnimationDialog  *dialog);
 static void        fpscombo_changed          (GtkWidget        *combo,
@@ -477,6 +482,32 @@ animation_dialog_constructed (GObject *object)
   gtk_container_add (GTK_CONTAINER (widget),
                      priv->proxycombo);
 
+  /* Settings: duration */
+  priv->duration_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_box_pack_end (GTK_BOX (priv->settings_bar), priv->duration_box, FALSE, FALSE, 0);
+
+  widget = gtk_label_new (_("frames"));
+  gtk_box_pack_end (GTK_BOX (priv->duration_box), widget, FALSE, FALSE, 0);
+  gtk_widget_show (widget);
+
+  adjust = GTK_ADJUSTMENT (gtk_adjustment_new (240.0, 1.0, G_MAXDOUBLE, 1.0, 10.0, 0.0));
+  priv->duration_spin = gtk_spin_button_new (adjust, 0.0, 0.0);
+  gtk_entry_set_width_chars (GTK_ENTRY (priv->duration_spin), 5);
+  gimp_help_set_help_data (priv->duration_spin, _("Duration in frames"), NULL);
+  gtk_box_pack_end (GTK_BOX (priv->duration_box), priv->duration_spin, FALSE, FALSE, 0);
+
+  widget = gtk_label_new (_("Duration:"));
+  gtk_box_pack_end (GTK_BOX (priv->duration_box), widget, FALSE, FALSE, 0);
+  gtk_widget_show (widget);
+
+  g_signal_connect (adjust,
+                    "value-changed",
+                    G_CALLBACK (on_duration_spin_changed),
+                    dialog);
+
+  gtk_widget_show (priv->duration_spin);
+  gtk_widget_show (priv->duration_box);
+
   /* Settings: fps */
   priv->fpscombo = gtk_combo_box_text_new_with_entry ();
 
@@ -1242,6 +1273,9 @@ animation_dialog_set_animation (AnimationDialog *dialog,
 
       /* The animation type box. */
       gtk_combo_box_set_active (GTK_COMBO_BOX (priv->animation_type_combo), 0);
+
+      /* The duration box. */
+      gtk_widget_hide (priv->duration_box);
     }
   else
     {
@@ -1256,6 +1290,9 @@ animation_dialog_set_animation (AnimationDialog *dialog,
 
       /* The animation type box. */
       gtk_combo_box_set_active (GTK_COMBO_BOX (priv->animation_type_combo), 1);
+
+      /* The duration box. */
+      gtk_widget_show (priv->duration_box);
     }
 
   /* The bottom panel. */
@@ -1439,6 +1476,21 @@ animation_type_changed (GtkWidget       *combo,
   animation_load (animation);
 }
 
+static void
+on_duration_spin_changed (GtkAdjustment   *adjustment,
+                          AnimationDialog *dialog)
+{
+  AnimationDialogPrivate *priv = GET_PRIVATE (dialog);
+  AnimationCelAnimation  *animation;
+  gdouble                 value = gtk_adjustment_get_value (adjustment);
+
+  g_return_if_fail (priv->animation &&
+                    ANIMATION_IS_CEL_ANIMATION (priv->animation));
+
+  animation = ANIMATION_CEL_ANIMATION (priv->animation);
+  animation_cel_animation_set_duration (animation, (gint) value);
+}
+
 
 /*
  * Callback emitted when the user hits the Enter key of the fps combo.
@@ -1953,6 +2005,7 @@ playback_range_changed (AnimationPlayback *playback,
   AnimationDialogPrivate *priv = GET_PRIVATE (dialog);
   GtkAdjustment *startframe_adjust;
   GtkAdjustment *stopframe_adjust;
+  GtkAdjustment *duration_adjust;
 
   update_progress (dialog);
 
@@ -1974,6 +2027,15 @@ playback_range_changed (AnimationPlayback *playback,
                                      G_CALLBACK (endframe_changed),
                                      dialog);
 
+  /* The duration adjust for cel animation. */
+  duration_adjust  = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->duration_spin));
+  g_signal_handlers_block_by_func (duration_adjust,
+                                   G_CALLBACK (on_duration_spin_changed),
+                                   dialog);
+  gtk_adjustment_set_value (duration_adjust, animation_get_duration (priv->animation));
+  g_signal_handlers_unblock_by_func (duration_adjust,
+                                     G_CALLBACK (on_duration_spin_changed),
+                                     dialog);
   show_playing_progress (dialog);
 }
 
diff --git a/plug-ins/animation-play/widgets/animation-xsheet.c 
b/plug-ins/animation-play/widgets/animation-xsheet.c
index c7aaa9a..5ee9d5c 100755
--- a/plug-ins/animation-play/widgets/animation-xsheet.c
+++ b/plug-ins/animation-play/widgets/animation-xsheet.c
@@ -58,36 +58,41 @@ struct _AnimationXSheetPrivate
   GQueue                *selected_frames;
 
   GList                 *comment_fields;
+
+  guint                  layout_reset_src;
 };
 
-static void animation_xsheet_constructed  (GObject      *object);
-static void animation_xsheet_set_property (GObject      *object,
-                                           guint         property_id,
-                                           const GValue *value,
-                                           GParamSpec   *pspec);
-static void animation_xsheet_get_property (GObject      *object,
-                                           guint         property_id,
-                                           GValue       *value,
-                                           GParamSpec   *pspec);
-static void animation_xsheet_finalize     (GObject      *object);
+static void    animation_xsheet_constructed  (GObject      *object);
+static void    animation_xsheet_set_property (GObject      *object,
+                                              guint         property_id,
+                                              const GValue *value,
+                                              GParamSpec   *pspec);
+static void    animation_xsheet_get_property (GObject      *object,
+                                              guint         property_id,
+                                              GValue       *value,
+                                              GParamSpec   *pspec);
+static void    animation_xsheet_finalize     (GObject      *object);
 
 /* Construction methods */
-static void animation_xsheet_reset_layout (AnimationXSheet *xsheet);
+static gboolean animation_xsheet_reset_layout (AnimationXSheet *xsheet);
 
 /* Callbacks on animation. */
-static void on_animation_loaded           (Animation       *animation,
-                                           AnimationXSheet *xsheet);
-/* Callbacks on callback. */
-static void on_animation_rendered         (AnimationPlayback *animation,
-                                           gint               frame_number,
-                                           GeglBuffer        *buffer,
-                                           gboolean           must_draw_null,
-                                           AnimationXSheet   *xsheet);
+static void     on_animation_loaded           (Animation       *animation,
+                                               AnimationXSheet *xsheet);
+static void     on_animation_duration_changed (Animation         *animation,
+                                               gint               duration,
+                                               AnimationXSheet   *xsheet);
+/* Callbacks on playback. */
+static void     on_animation_rendered         (AnimationPlayback *animation,
+                                              gint               frame_number,
+                                              GeglBuffer        *buffer,
+                                              gboolean           must_draw_null,
+                                              AnimationXSheet   *xsheet);
 
 /* Callbacks on layer view. */
-static void on_layer_selection            (AnimationLayerView *view,
-                                           GList              *layers,
-                                           AnimationXSheet    *xsheet);
+static void     on_layer_selection            (AnimationLayerView *view,
+                                              GList              *layers,
+                                              AnimationXSheet    *xsheet);
 
 /* UI Signals */
 static gboolean animation_xsheet_frame_clicked       (GtkWidget       *button,
@@ -171,8 +176,8 @@ animation_xsheet_new (AnimationCelAnimation *animation,
                          NULL);
   ANIMATION_XSHEET (xsheet)->priv->playback = playback;
   g_signal_connect (ANIMATION_XSHEET (xsheet)->priv->playback,
-                    "render",
-                    G_CALLBACK (on_animation_rendered), xsheet);
+                    "render", G_CALLBACK (on_animation_rendered),
+                    xsheet);
 
   return xsheet;
 }
@@ -204,6 +209,11 @@ animation_xsheet_constructed (GObject *object)
   /* Reload everything when we reload the animation. */
   g_signal_connect_after (xsheet->priv->animation, "loaded",
                           G_CALLBACK (on_animation_loaded), xsheet);
+
+  g_signal_connect_after (xsheet->priv->animation,
+                          "duration-changed",
+                          G_CALLBACK (on_animation_duration_changed),
+                          xsheet);
 }
 
 static void
@@ -272,7 +282,7 @@ animation_xsheet_finalize (GObject *object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-static void
+static gboolean
 animation_xsheet_reset_layout (AnimationXSheet *xsheet)
 {
   GtkWidget *frame;
@@ -288,8 +298,12 @@ animation_xsheet_reset_layout (AnimationXSheet *xsheet)
                          (GtkCallback) gtk_widget_destroy,
                          NULL);
   g_list_free_full (xsheet->priv->cels, (GDestroyNotify) g_list_free);
-  g_list_free (xsheet->priv->comment_fields);
   xsheet->priv->cels = NULL;
+  g_list_free (xsheet->priv->comment_fields);
+  xsheet->priv->comment_fields = NULL;
+  g_list_free (xsheet->priv->position_buttons);
+  xsheet->priv->position_buttons = NULL;
+  xsheet->priv->active_pos_button = NULL;
   xsheet->priv->selected_track = -1;
   g_queue_clear (xsheet->priv->selected_frames);
 
@@ -446,6 +460,11 @@ animation_xsheet_reset_layout (AnimationXSheet *xsheet)
 
   gtk_table_set_row_spacings (GTK_TABLE (xsheet->priv->track_layout), 0);
   gtk_table_set_col_spacings (GTK_TABLE (xsheet->priv->track_layout), 0);
+
+  /* Return a boolean in order to be used as a source function.
+   * FALSE means the source should be removed once processed. */
+  xsheet->priv->layout_reset_src = 0;
+  return FALSE;
 }
 
 static void
@@ -490,6 +509,26 @@ on_animation_loaded (Animation       *animation,
 }
 
 static void
+on_animation_duration_changed (Animation       *animation,
+                               gint             duration,
+                               AnimationXSheet *xsheet)
+{
+  if (! xsheet->priv->layout_reset_src)
+    {
+      gint src;
+
+      /* Directly running animation_xsheet_reset_layout() repeats
+       * indefinitely with a loop timer. There seems to be some kind of
+       * race condition in the spin button code when the action takes
+       * too long. Run this as idle instead.
+       */
+      src = g_idle_add ((GSourceFunc) animation_xsheet_reset_layout,
+                        xsheet);
+      xsheet->priv->layout_reset_src = src;
+    }
+}
+
+static void
 on_animation_rendered (AnimationPlayback *playback,
                        gint               frame_number,
                        GeglBuffer        *buffer,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]