[gimp] app: maintain warp tool graph structure during undo/redo



commit 9c7cae6220ead9061e6368a8a3ca07a4a9db38f1
Author: Ell <ell_se yahoo com>
Date:   Tue May 16 19:34:22 2017 -0400

    app: maintain warp tool graph structure during undo/redo
    
    When undoing a warp stroke, don't disconnect the current warp node
    from its predecessor; rather, keep the graph as-is, and only
    reconnect the render_node to the previous node.  This avoids
    invalidating the undone node, so that redoing it (which, likewise,
    only involves reconnecting the render_node) doesn't require
    reprocessing, making it much faster.

 app/tools/gimpwarptool.c |   37 +++++++++++++++++++++++++++++--------
 1 files changed, 29 insertions(+), 8 deletions(-)
---
diff --git a/app/tools/gimpwarptool.c b/app/tools/gimpwarptool.c
index 1359a71..b34deaa 100644
--- a/app/tools/gimpwarptool.c
+++ b/app/tools/gimpwarptool.c
@@ -121,6 +121,7 @@ static void       gimp_warp_tool_add_op             (GimpWarpTool          *wt,
                                                      GeglNode              *op);
 static void       gimp_warp_tool_remove_op          (GimpWarpTool          *wt,
                                                      GeglNode              *op);
+static void       gimp_warp_tool_free_op            (GeglNode              *op);
 
 static void       gimp_warp_tool_animate            (GimpWarpTool          *wt);
 
@@ -304,7 +305,7 @@ gimp_warp_tool_button_release (GimpTool              *tool,
       gimp_warp_tool_undo (tool, display);
 
       /*  the just undone stroke has no business on the redo stack  */
-      g_object_unref (wt->redo_stack->data);
+      gimp_warp_tool_free_op (wt->redo_stack->data);
       wt->redo_stack = g_list_remove_link (wt->redo_stack, wt->redo_stack);
     }
   else
@@ -312,7 +313,8 @@ gimp_warp_tool_button_release (GimpTool              *tool,
       if (wt->redo_stack)
         {
           /*  the redo stack becomes invalid by actually doing a stroke  */
-          g_list_free_full (wt->redo_stack, (GDestroyNotify) g_object_unref);
+          g_list_free_full (wt->redo_stack,
+                            (GDestroyNotify) gimp_warp_tool_free_op);
           wt->redo_stack = NULL;
         }
 
@@ -483,6 +485,7 @@ gimp_warp_tool_undo (GimpTool    *tool,
 {
   GimpWarpTool *wt = GIMP_WARP_TOOL (tool);
   GeglNode     *to_delete;
+  GeglNode     *prev_node;
   const gchar  *type;
 
   if (! wt->render_node)
@@ -494,11 +497,17 @@ gimp_warp_tool_undo (GimpTool    *tool,
   if (strcmp (type, "gegl:warp"))
     return FALSE;
 
-  wt->redo_stack = g_list_prepend (wt->redo_stack, g_object_ref (to_delete));
+  wt->redo_stack = g_list_prepend (wt->redo_stack, to_delete);
 
-  gimp_warp_tool_remove_op (wt, to_delete);
+  /* we connect render_node to the previous node, but keep the current node
+   * in the graph, connected to the previous node as well, so that it doesn't
+   * get invalidated and maintains its cache.  this way, redoing it doesn't
+   * require reprocessing.
+   */
+  prev_node = gegl_node_get_producer (to_delete, "input", NULL);
 
-  gegl_node_remove_child (wt->graph, to_delete);
+  gegl_node_connect_to (prev_node,       "output",
+                        wt->render_node, "aux");
 
   gimp_warp_tool_update_stroke (wt, to_delete);
 
@@ -517,8 +526,8 @@ gimp_warp_tool_redo (GimpTool    *tool,
 
   to_add = wt->redo_stack->data;
 
-  gimp_warp_tool_add_op (wt, to_add);
-  g_object_unref (to_add);
+  gegl_node_connect_to (to_add,          "output",
+                        wt->render_node, "aux");
 
   wt->redo_stack = g_list_remove_link (wt->redo_stack, wt->redo_stack);
 
@@ -651,7 +660,7 @@ gimp_warp_tool_halt (GimpWarpTool *wt)
 
   if (wt->redo_stack)
     {
-      g_list_free_full (wt->redo_stack, (GDestroyNotify) g_object_unref);
+      g_list_free (wt->redo_stack);
       wt->redo_stack = NULL;
     }
 
@@ -871,6 +880,18 @@ gimp_warp_tool_remove_op (GimpWarpTool *wt,
 }
 
 static void
+gimp_warp_tool_free_op (GeglNode *op)
+{
+  GeglNode *parent;
+
+  parent = gegl_node_get_parent (op);
+
+  g_assert (parent != NULL);
+
+  gegl_node_remove_child (parent, op);
+}
+
+static void
 gimp_warp_tool_animate (GimpWarpTool *wt)
 {
   GimpTool        *tool    = GIMP_TOOL (wt);


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