[gimp/wip/animation: 260/373] plug-ins: don't rebuild whole xsheet when changing animation duration.



commit 97a233a60fb4876e417ece52359b0a5627636b68
Author: Jehan <jehan girinstud io>
Date:   Sat Nov 12 03:10:25 2016 +0100

    plug-ins: don't rebuild whole xsheet when changing animation duration.

 plug-ins/animation-play/widgets/animation-xsheet.c |  231 ++++++++++++++++++--
 1 files changed, 211 insertions(+), 20 deletions(-)
---
diff --git a/plug-ins/animation-play/widgets/animation-xsheet.c 
b/plug-ins/animation-play/widgets/animation-xsheet.c
index 5ee9d5c..e834dc2 100755
--- a/plug-ins/animation-play/widgets/animation-xsheet.c
+++ b/plug-ins/animation-play/widgets/animation-xsheet.c
@@ -59,7 +59,8 @@ struct _AnimationXSheetPrivate
 
   GList                 *comment_fields;
 
-  guint                  layout_reset_src;
+  guint                  layout_update_src;
+  gint                   duration;
 };
 
 static void    animation_xsheet_constructed  (GObject      *object);
@@ -74,25 +75,26 @@ static void    animation_xsheet_get_property (GObject      *object,
 static void    animation_xsheet_finalize     (GObject      *object);
 
 /* Construction methods */
-static gboolean animation_xsheet_reset_layout (AnimationXSheet *xsheet);
+static void     animation_xsheet_reset_layout  (AnimationXSheet *xsheet);
+static gboolean animation_xsheet_update_layout (AnimationXSheet *xsheet);
 
 /* Callbacks on animation. */
-static void     on_animation_loaded           (Animation       *animation,
-                                               AnimationXSheet *xsheet);
-static void     on_animation_duration_changed (Animation         *animation,
-                                               gint               duration,
-                                               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);
+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,
@@ -282,7 +284,7 @@ animation_xsheet_finalize (GObject *object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-static gboolean
+static void
 animation_xsheet_reset_layout (AnimationXSheet *xsheet)
 {
   GtkWidget *frame;
@@ -317,6 +319,7 @@ animation_xsheet_reset_layout (AnimationXSheet *xsheet)
 
   n_tracks = animation_cel_animation_get_levels (xsheet->priv->animation);
   n_frames = animation_get_duration (ANIMATION (xsheet->priv->animation));
+  xsheet->priv->duration = n_frames;
 
   /* The cels structure is a matrix of every cel widget. */
   for (j = 0; j < n_tracks; j++)
@@ -460,10 +463,198 @@ 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);
+}
+
+static gboolean
+animation_xsheet_update_layout (AnimationXSheet *xsheet)
+{
+  GList *iter;
+  GList *item;
+  gint   prev_duration;
+  gint   duration;
+  gint   n_tracks;
+  gint   i;
+
+  prev_duration = xsheet->priv->duration;
+  duration = animation_get_duration (ANIMATION (xsheet->priv->animation));
+  xsheet->priv->duration = duration;
+
+  n_tracks = animation_cel_animation_get_levels (xsheet->priv->animation);
+
+  /* Only consider duration change in this first version, i.e. removing
+   * or adding frames at the end of the animation.
+   * Further updates could allow removing a given frame, adding a frame
+   * in the middle of the animation, and adding, removing or moving
+   * tracks.
+   */
+  if (prev_duration < duration)
+    {
+      GtkWidget *frame;
+      gint       j = 0;
+
+      for (iter = xsheet->priv->cels; iter; iter = iter->next, j++)
+        {
+          /* Show the hidden cels. */
+          item = g_list_nth (iter->data, prev_duration);
+          for (i = prev_duration; item && i < duration; item = item->next, i++)
+            {
+              gtk_widget_show (gtk_widget_get_parent (item->data));
+            }
+          /* Create new cels. */
+          for (; i < duration; i++)
+            {
+              GtkWidget *cel;
+
+              frame = gtk_frame_new (NULL);
+              gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+              gtk_table_attach (GTK_TABLE (xsheet->priv->track_layout),
+                                frame, j + 1, j + 2, i + 1, i + 2,
+                                GTK_FILL, GTK_FILL, 0, 0);
+
+              cel = gtk_toggle_button_new ();
+              iter->data = g_list_append (iter->data, cel);
+              g_object_set_data (G_OBJECT (cel), "track-num",
+                                 GINT_TO_POINTER (j));
+              g_object_set_data (G_OBJECT (cel), "frame-position",
+                                 GINT_TO_POINTER (i));
+              animation_xsheet_rename_cel (xsheet, cel, FALSE);
+              g_signal_connect (cel, "button-release-event",
+                                G_CALLBACK (animation_xsheet_cel_clicked),
+                                xsheet);
+              gtk_button_set_relief (GTK_BUTTON (cel), GTK_RELIEF_NONE);
+              gtk_button_set_focus_on_click (GTK_BUTTON (cel), FALSE);
+              gtk_container_add (GTK_CONTAINER (frame), cel);
+              gtk_widget_show (cel);
+              gtk_widget_show (frame);
+            }
+        }
+
+      /* Show hidden position buttons. */
+      item = g_list_nth (xsheet->priv->position_buttons,
+                         prev_duration);
+      for (i = prev_duration ; item && i < duration; item = item->next, i++)
+        {
+          gtk_widget_show (gtk_widget_get_parent (item->data));
+        }
+
+      /* Create new position buttons. */
+      for (; i < duration; i++)
+        {
+          GtkWidget *label;
+          gchar     *num_str;
+
+          frame = gtk_frame_new (NULL);
+          gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT);
+          gtk_table_attach (GTK_TABLE (xsheet->priv->track_layout),
+                            frame, 0, 1, i + 1, i + 2,
+                            GTK_FILL, GTK_FILL, 0, 0);
+
+          num_str = g_strdup_printf ("%d", i + 1);
+          label = gtk_toggle_button_new ();
+          xsheet->priv->position_buttons = g_list_append (xsheet->priv->position_buttons,
+                                                          label);
+          gtk_button_set_label (GTK_BUTTON (label), num_str);
+          g_free (num_str);
+          g_object_set_data (G_OBJECT (label), "frame-position",
+                             GINT_TO_POINTER (i));
+          gtk_button_set_relief (GTK_BUTTON (label), GTK_RELIEF_NONE);
+          gtk_button_set_focus_on_click (GTK_BUTTON (label), FALSE);
+          g_signal_connect (label, "button-press-event",
+                            G_CALLBACK (animation_xsheet_frame_clicked),
+                            xsheet);
+          gtk_container_add (GTK_CONTAINER (frame), label);
+
+          gtk_widget_show (label);
+          gtk_widget_show (frame);
+        }
+
+      /* Show hidden comment fields. */
+      item = g_list_nth (xsheet->priv->comment_fields,
+                         prev_duration);
+      for (i = prev_duration; item && i < duration; item = item->next, i++)
+        {
+          gtk_widget_show (gtk_widget_get_parent (item->data));
+        }
+
+      /* Create new comment fields. */
+      for (; i < duration; i++)
+        {
+          GtkWidget     *comment_field;
+          const gchar   *comment;
+          GtkTextBuffer *text_buffer;
+
+          frame = gtk_frame_new (NULL);
+          gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+          gtk_table_attach (GTK_TABLE (xsheet->priv->track_layout),
+                            frame, n_tracks + 1, n_tracks + 6, i + 1, i + 2,
+                            GTK_FILL, GTK_FILL, 0, 0);
+          comment_field = gtk_text_view_new ();
+          xsheet->priv->comment_fields = g_list_append (xsheet->priv->comment_fields,
+                                                        comment_field);
+          text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (comment_field));
+          comment = animation_cel_animation_get_comment (xsheet->priv->animation,
+                                                         i);
+          if (comment != NULL)
+            gtk_text_buffer_insert_at_cursor (text_buffer, comment, -1);
+
+          g_object_set_data (G_OBJECT (comment_field), "frame-position",
+                             GINT_TO_POINTER (i));
+          g_object_set_data (G_OBJECT (text_buffer), "frame-position",
+                             GINT_TO_POINTER (i));
+          g_signal_connect (comment_field, "key-press-event",
+                            G_CALLBACK (animation_xsheet_comment_keypress),
+                            xsheet);
+          g_signal_connect (text_buffer, "changed",
+                            (GCallback) animation_xsheet_comment_changed,
+                            xsheet);
+          gtk_container_add (GTK_CONTAINER (frame), comment_field);
+          gtk_widget_show (comment_field);
+          gtk_widget_show (frame);
+        }
+    }
+  else if (duration < prev_duration)
+    {
+      /* Removing frames at the end. */
+      for (iter = xsheet->priv->cels; iter; iter = iter->next)
+        {
+          GList *track_cels;
+
+          /* Remove the "cels" buttons. */
+          track_cels = iter->data;
+          item = g_list_nth (track_cels, duration);
+
+          for (i = duration; i < prev_duration; i++)
+            {
+              /* Make sure this is not a selected frame. */
+              g_queue_remove (xsheet->priv->selected_frames,
+                              GINT_TO_POINTER (i));
+            }
+          /* Hide the parent frame but keep it around. */
+          for (; item; item = item->next)
+            {
+              gtk_widget_hide (gtk_widget_get_parent (item->data));
+            }
+        }
+      /* Remove the position button. */
+      item = g_list_nth (xsheet->priv->position_buttons,
+                         duration);
+      for (; item; item = item->next)
+        {
+          gtk_widget_hide (gtk_widget_get_parent (item->data));
+        }
+
+      /* Remove the comments field. */
+      item = g_list_nth (xsheet->priv->comment_fields,
+                         duration);
+      for (; item; item = item->next)
+        {
+          gtk_widget_hide (gtk_widget_get_parent (item->data));
+        }
+    }
 
   /* 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;
+  xsheet->priv->layout_update_src = 0;
   return FALSE;
 }
 
@@ -513,7 +704,7 @@ on_animation_duration_changed (Animation       *animation,
                                gint             duration,
                                AnimationXSheet *xsheet)
 {
-  if (! xsheet->priv->layout_reset_src)
+  if (! xsheet->priv->layout_update_src)
     {
       gint src;
 
@@ -522,9 +713,9 @@ on_animation_duration_changed (Animation       *animation,
        * 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,
+      src = g_idle_add ((GSourceFunc) animation_xsheet_update_layout,
                         xsheet);
-      xsheet->priv->layout_reset_src = src;
+      xsheet->priv->layout_update_src = src;
     }
 }
 


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