]> granicus.if.org Git - poly2tri-c/commitdiff
Add the ability to undo actions on meshes
authorBarak Itkin <lightningismyname@gmail.com>
Fri, 6 Jul 2012 21:37:59 +0000 (00:37 +0300)
committerBarak Itkin <lightningismyname@gmail.com>
Fri, 6 Jul 2012 21:37:59 +0000 (00:37 +0300)
poly2tri-c/refine/edge.c
poly2tri-c/refine/mesh.c
poly2tri-c/refine/mesh.h
poly2tri-c/refine/triangle.c

index fd91407c8448ed276fb577f77f1ef19319041a96..bfbdbd355a0bd45b1571cd55a89d66e17270528f 100644 (file)
@@ -116,6 +116,12 @@ p2tr_edge_remove (P2trEdge *self)
   if (self->mirror->tri != NULL)
     p2tr_triangle_remove (self->mirror->tri);
 
+  if (mesh != NULL)
+    {
+      p2tr_mesh_on_edge_removed (mesh, self);
+      p2tr_mesh_unref (mesh); /* The get function reffed it */
+    }
+
   _p2tr_point_remove_edge(start, self);
   _p2tr_point_remove_edge(end, self->mirror);
 
@@ -124,13 +130,6 @@ p2tr_edge_remove (P2trEdge *self)
 
   p2tr_point_unref (start);
   p2tr_point_unref (end);
-  
-  if (mesh != NULL)
-  {
-    p2tr_mesh_on_edge_removed (mesh, self);
-    p2tr_mesh_on_edge_removed (mesh, self->mirror);
-    p2tr_mesh_unref (mesh); /* The get function reffed it */
-  }
 }
 
 void
index abd0c69f10f21e8a3cab0224e60eef985a0ac745..166467f35b1c81d033f44c13cb1ea71879b2d570 100644 (file)
@@ -37,6 +37,7 @@
 #include "point.h"
 #include "edge.h"
 #include "triangle.h"
+#include "mesh-action.h"
 
 P2trMesh*
 p2tr_mesh_new (void)
@@ -48,6 +49,9 @@ p2tr_mesh_new (void)
   mesh->points = p2tr_hash_set_new_default ();
   mesh->triangles = p2tr_hash_set_new_default ();
 
+  mesh->record_undo = FALSE;
+  g_queue_init (&mesh->undo);
+
   return mesh;
 }
 
@@ -59,6 +63,10 @@ p2tr_mesh_add_point (P2trMesh  *self,
   point->mesh = self;
   p2tr_mesh_ref (self);
   p2tr_hash_set_insert (self->points, point);
+
+  if (self->record_undo)
+    g_queue_push_tail (&self->undo, p2tr_mesh_action_new_point (point));
+
   return p2tr_point_ref (point);
 }
 
@@ -84,6 +92,10 @@ p2tr_mesh_add_edge (P2trMesh *self,
   g_assert (p2tr_edge_get_mesh (edge) == NULL);
   p2tr_hash_set_insert (self->edges, p2tr_edge_ref (edge->mirror));
   p2tr_hash_set_insert (self->edges, p2tr_edge_ref (edge));
+
+  if (self->record_undo)
+    g_queue_push_tail (&self->undo, p2tr_mesh_action_new_edge (edge));
+
   return edge;
 }
 
@@ -116,6 +128,10 @@ p2tr_mesh_add_triangle (P2trMesh     *self,
 {
   g_assert (p2tr_triangle_get_mesh (tri) == NULL);
   p2tr_hash_set_insert (self->triangles, tri);
+
+  if (self->record_undo)
+    g_queue_push_tail (&self->undo, p2tr_mesh_action_new_triangle (tri));
+
   return p2tr_triangle_ref (tri);
 }
 
@@ -139,6 +155,10 @@ p2tr_mesh_on_point_removed (P2trMesh  *self,
   p2tr_mesh_unref (self);
 
   p2tr_hash_set_remove (self->points, point);
+
+  if (self->record_undo)
+    g_queue_push_tail (&self->undo, p2tr_mesh_action_del_point (point));
+
   p2tr_point_unref (point);
 }
 
@@ -146,7 +166,13 @@ void
 p2tr_mesh_on_edge_removed (P2trMesh *self,
                            P2trEdge *edge)
 {
+  p2tr_hash_set_remove (self->edges, edge->mirror);
+  p2tr_edge_unref (edge->mirror);
   p2tr_hash_set_remove (self->edges, edge);
+
+  if (self->record_undo)
+    g_queue_push_tail (&self->undo, p2tr_mesh_action_del_edge (edge));
+
   p2tr_edge_unref (edge);
 }
 
@@ -155,9 +181,51 @@ p2tr_mesh_on_triangle_removed (P2trMesh     *self,
                                P2trTriangle *triangle)
 {
   p2tr_hash_set_remove (self->triangles, triangle);
+
+  if (self->record_undo)
+    g_queue_push_tail (&self->undo, p2tr_mesh_action_del_triangle (triangle));
+
   p2tr_triangle_unref (triangle);
 }
 
+void
+p2tr_mesh_action_group_begin (P2trMesh *self)
+{
+  g_assert (! self->record_undo);
+  self->record_undo = TRUE;
+}
+
+void
+p2tr_mesh_action_group_commit (P2trMesh *self)
+{
+  GList *iter;
+
+  g_assert (self->record_undo);
+
+  for (iter = self->undo.head; iter != NULL; iter = iter->next)
+    p2tr_mesh_action_unref ((P2trMeshAction*)iter->data);
+  g_queue_clear (&self->undo);
+
+  self->record_undo = FALSE;
+}
+
+void
+p2tr_mesh_action_group_undo (P2trMesh *self)
+{
+  GList *iter;
+
+  g_assert (self->record_undo);
+
+  for (iter = self->undo.tail; iter != NULL; iter = iter->prev)
+    {
+      p2tr_mesh_action_undo ((P2trMeshAction*)iter->data, self);
+      p2tr_mesh_action_unref ((P2trMeshAction*)iter->data);
+    }
+  g_queue_clear (&self->undo);
+
+  self->record_undo = FALSE;
+}
+
 void
 p2tr_mesh_clear (P2trMesh *self)
 {
@@ -195,6 +263,9 @@ p2tr_mesh_clear (P2trMesh *self)
 void
 p2tr_mesh_free (P2trMesh *self)
 {
+  if (self->record_undo)
+    p2tr_mesh_action_group_commit (self);
+
   p2tr_mesh_clear (self);
 
   p2tr_hash_set_free (self->points);
index 8c543c605ae64b66c1b26db76cda5efd10cfb506..feee853b18126d3c2648ec1b32111738806ce646 100644 (file)
@@ -43,6 +43,9 @@ struct P2trMesh_
   P2trHashSet *triangles;
   P2trHashSet *edges;
   P2trHashSet *points;
+
+  gboolean     record_undo;
+  GQueue       undo;
   
   guint        refcount;
 };
@@ -113,6 +116,10 @@ void          p2tr_mesh_on_edge_removed     (P2trMesh *mesh,
 void          p2tr_mesh_on_triangle_removed (P2trMesh     *mesh,
                                              P2trTriangle *triangle);
 
+void          p2tr_mesh_action_group_begin    (P2trMesh *self);
+void          p2tr_mesh_action_group_commit   (P2trMesh *self);
+void          p2tr_mesh_action_group_undo     (P2trMesh *self);
+
 void          p2tr_mesh_clear           (P2trMesh *mesh);
 
 void          p2tr_mesh_destroy         (P2trMesh *mesh);
index 2bf9a7f48295c0d331d41940feb929d14f729826..4625d989bcb623e50f016029a4909bec3d3ea02f 100644 (file)
@@ -157,6 +157,12 @@ p2tr_triangle_remove (P2trTriangle *self)
 
   mesh = p2tr_triangle_get_mesh (self);
   
+  if (mesh != NULL)
+    {
+      p2tr_mesh_on_triangle_removed (mesh, self);
+      p2tr_mesh_unref (mesh); /* The get function reffed it */
+    }
+
   for (i = 0; i < 3; i++)
   {
     self->edges[i]->tri = NULL;
@@ -165,12 +171,6 @@ p2tr_triangle_remove (P2trTriangle *self)
     p2tr_edge_unref (self->edges[i]);
     self->edges[i] = NULL;
   }
-
-  if (mesh != NULL)
-    {
-      p2tr_mesh_on_triangle_removed (mesh, self);
-      p2tr_mesh_unref (mesh); /* The get function reffed it */
-    }
 }
 
 P2trMesh*