[Bf-blender-cvs] [d650162ecd4] master: Curves: Add initial undo system

Falk David noreply at git.blender.org
Fri Jan 20 16:32:41 CET 2023


Commit: d650162ecd47d6c12e1d66ffbd413e4f3acb120d
Author: Falk David
Date:   Fri Jan 20 16:32:25 2023 +0100
Branches: master
https://developer.blender.org/rBd650162ecd47d6c12e1d66ffbd413e4f3acb120d

Curves: Add initial undo system

This adds an `UndoType` for the `Curves` object, for edit mode.
For now, this will only store the `CurvesGeometry` at every step.
Other properties such as the `selection_domain` or the `surface` object
will have to be dealt with in subsequent commits.

Differential Revision: https://developer.blender.org/D16979

===================================================================

M	source/blender/editors/curves/CMakeLists.txt
M	source/blender/editors/curves/intern/curves_ops.cc
A	source/blender/editors/curves/intern/curves_undo.cc
M	source/blender/editors/include/ED_curves.h
M	source/blender/editors/undo/CMakeLists.txt
M	source/blender/editors/undo/undo_system_types.c

===================================================================

diff --git a/source/blender/editors/curves/CMakeLists.txt b/source/blender/editors/curves/CMakeLists.txt
index bba85f9c77a..873df89b40c 100644
--- a/source/blender/editors/curves/CMakeLists.txt
+++ b/source/blender/editors/curves/CMakeLists.txt
@@ -12,6 +12,7 @@ set(INC
   ../../makesdna
   ../../makesrna
   ../../windowmanager
+  ../../../../intern/clog
   ../../../../intern/guardedalloc
   ../../bmesh
 
@@ -24,6 +25,7 @@ set(SRC
   intern/curves_data.cc
   intern/curves_ops.cc
   intern/curves_selection.cc
+  intern/curves_undo.cc
 )
 
 set(LIB
diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc
index d084317014d..24aa362b973 100644
--- a/source/blender/editors/curves/intern/curves_ops.cc
+++ b/source/blender/editors/curves/intern/curves_ops.cc
@@ -60,7 +60,7 @@
 
 namespace blender::ed::curves {
 
-static bool object_has_editable_curves(const Main &bmain, const Object &object)
+bool object_has_editable_curves(const Main &bmain, const Object &object)
 {
   if (object.type != OB_CURVES) {
     return false;
@@ -95,7 +95,10 @@ VectorSet<Curves *> get_unique_editable_curves(const bContext &C)
   return unique_curves;
 }
 
-static bool curves_poll_impl(bContext *C, const bool check_editable, const bool check_surface)
+static bool curves_poll_impl(bContext *C,
+                             const bool check_editable,
+                             const bool check_surface,
+                             const bool check_edit_mode)
 {
   Object *object = CTX_data_active_object(C);
   if (object == nullptr || object->type != OB_CURVES) {
@@ -113,27 +116,37 @@ static bool curves_poll_impl(bContext *C, const bool check_editable, const bool
       return false;
     }
   }
+  if (check_edit_mode) {
+    if ((object->mode & OB_MODE_EDIT) == 0) {
+      return false;
+    }
+  }
   return true;
 }
 
+bool editable_curves_in_edit_mode_poll(bContext *C)
+{
+  return curves_poll_impl(C, true, false, true);
+}
+
 bool editable_curves_with_surface_poll(bContext *C)
 {
-  return curves_poll_impl(C, true, true);
+  return curves_poll_impl(C, true, true, false);
 }
 
 bool curves_with_surface_poll(bContext *C)
 {
-  return curves_poll_impl(C, false, true);
+  return curves_poll_impl(C, false, true, false);
 }
 
 bool editable_curves_poll(bContext *C)
 {
-  return curves_poll_impl(C, false, false);
+  return curves_poll_impl(C, false, false, false);
 }
 
 bool curves_poll(bContext *C)
 {
-  return curves_poll_impl(C, false, false);
+  return curves_poll_impl(C, false, false, false);
 }
 
 using bke::CurvesGeometry;
diff --git a/source/blender/editors/curves/intern/curves_undo.cc b/source/blender/editors/curves/intern/curves_undo.cc
new file mode 100644
index 00000000000..551fbadfefc
--- /dev/null
+++ b/source/blender/editors/curves/intern/curves_undo.cc
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/** \file
+ * \ingroup edcurves
+ */
+
+#include "BKE_context.h"
+#include "BKE_curves.hh"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_undo_system.h"
+
+#include "CLG_log.h"
+
+#include "DEG_depsgraph.h"
+
+#include "ED_curves.h"
+#include "ED_undo.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+static CLG_LogRef LOG = {"ed.undo.curves"};
+
+namespace blender::ed::curves::undo {
+
+/* -------------------------------------------------------------------- */
+/** \name Implements ED Undo System
+ *
+ * \note This is similar for all edit-mode types.
+ * \{ */
+
+struct StepObject {
+  UndoRefID_Object obedit_ref = {};
+  bke::CurvesGeometry geometry = {};
+};
+
+struct CurvesUndoStep {
+  UndoStep step;
+  Array<StepObject> objects;
+};
+
+static bool step_encode(bContext *C, Main *bmain, UndoStep *us_p)
+{
+  CurvesUndoStep *us = reinterpret_cast<CurvesUndoStep *>(us_p);
+
+  const Scene *scene = CTX_data_scene(C);
+  ViewLayer *view_layer = CTX_data_view_layer(C);
+  uint objects_num = 0;
+  Object **objects = ED_undo_editmode_objects_from_view_layer(scene, view_layer, &objects_num);
+
+  new (&us->objects) Array<StepObject>(objects_num);
+
+  threading::parallel_for(us->objects.index_range(), 8, [&](const IndexRange range) {
+    for (const int i : range) {
+      Object *ob = objects[i];
+      const Curves &curves_id = *static_cast<Curves *>(ob->data);
+      StepObject &object = us->objects[i];
+
+      object.obedit_ref.ptr = ob;
+      object.geometry = bke::CurvesGeometry::wrap(curves_id.geometry);
+    }
+  });
+  MEM_SAFE_FREE(objects);
+
+  bmain->is_memfile_undo_flush_needed = true;
+
+  return true;
+}
+
+static void step_decode(
+    bContext *C, Main *bmain, UndoStep *us_p, const eUndoStepDir /*dir*/, bool /*is_final*/)
+{
+  CurvesUndoStep *us = reinterpret_cast<CurvesUndoStep *>(us_p);
+
+  ED_undo_object_editmode_restore_helper(C,
+                                         &us->objects.first().obedit_ref.ptr,
+                                         us->objects.size(),
+                                         sizeof(decltype(us->objects)::value_type));
+
+  BLI_assert(BKE_object_is_in_editmode(us->objects.first().obedit_ref.ptr));
+
+  for (const StepObject &object : us->objects) {
+    Curves &curves_id = *static_cast<Curves *>(object.obedit_ref.ptr->data);
+
+    /* Overwrite the curves geometry. */
+    bke::CurvesGeometry::wrap(curves_id.geometry) = object.geometry;
+
+    DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY);
+  }
+
+  ED_undo_object_set_active_or_warn(CTX_data_scene(C),
+                                    CTX_data_view_layer(C),
+                                    us->objects.first().obedit_ref.ptr,
+                                    us_p->name,
+                                    &LOG);
+
+  bmain->is_memfile_undo_flush_needed = true;
+
+  WM_event_add_notifier(C, NC_GEOM | ND_DATA, nullptr);
+}
+
+static void step_free(UndoStep *us_p)
+{
+  CurvesUndoStep *us = reinterpret_cast<CurvesUndoStep *>(us_p);
+  us->objects.~Array();
+}
+
+static void foreach_ID_ref(UndoStep *us_p,
+                           UndoTypeForEachIDRefFn foreach_ID_ref_fn,
+                           void *user_data)
+{
+  CurvesUndoStep *us = reinterpret_cast<CurvesUndoStep *>(us_p);
+
+  for (const StepObject &object : us->objects) {
+    foreach_ID_ref_fn(user_data, ((UndoRefID *)&object.obedit_ref));
+  }
+}
+
+/** \} */
+
+}  // namespace blender::ed::curves::undo
+
+void ED_curves_undosys_type(UndoType *ut)
+{
+  using namespace blender::ed;
+
+  ut->name = "Edit Curves";
+  ut->poll = curves::editable_curves_in_edit_mode_poll;
+  ut->step_encode = curves::undo::step_encode;
+  ut->step_decode = curves::undo::step_decode;
+  ut->step_free = curves::undo::step_free;
+
+  ut->step_foreach_ID_ref = curves::undo::foreach_ID_ref;
+
+  ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
+
+  ut->step_size = sizeof(curves::undo::CurvesUndoStep);
+}
diff --git a/source/blender/editors/include/ED_curves.h b/source/blender/editors/include/ED_curves.h
index bf6b78676b9..74eb290e98a 100644
--- a/source/blender/editors/include/ED_curves.h
+++ b/source/blender/editors/include/ED_curves.h
@@ -18,6 +18,7 @@ extern "C" {
  * \{ */
 
 void ED_operatortypes_curves(void);
+void ED_curves_undosys_type(struct UndoType *ut);
 
 /**
  * Return an owning pointer to an array of point normals the same size as the number of control
@@ -43,6 +44,7 @@ float (*ED_curves_point_normals_array_create(const struct Curves *curves_id))[3]
 
 namespace blender::ed::curves {
 
+bool object_has_editable_curves(const Main &bmain, const Object &object);
 bke::CurvesGeometry primitive_random_sphere(int curves_size, int points_per_curve);
 VectorSet<Curves *> get_unique_editable_curves(const bContext &C);
 void ensure_surface_deformation_node_exists(bContext &C, Object &curves_ob);
@@ -52,6 +54,7 @@ void ensure_surface_deformation_node_exists(bContext &C, Object &curves_ob);
  * \{ */
 
 bool editable_curves_with_surface_poll(bContext *C);
+bool editable_curves_in_edit_mode_poll(bContext *C);
 bool curves_with_surface_poll(bContext *C);
 bool editable_curves_poll(bContext *C);
 bool curves_poll(bContext *C);
diff --git a/source/blender/editors/undo/CMakeLists.txt b/source/blender/editors/undo/CMakeLists.txt
index 11101bb6b25..cfebb2cab1c 100644
--- a/source/blender/editors/undo/CMakeLists.txt
+++ b/source/blender/editors/undo/CMakeLists.txt
@@ -29,6 +29,7 @@ set(LIB
   bf_blenkernel
   bf_blenlib
   bf_editor_curve
+  bf_editor_curves
   bf_editor_lattice
   bf_editor_mesh
   bf_editor_metaball
diff --git a/source/blender/editors/undo/undo_system_types.c b/source/blender/editors/undo/undo_system_types.c
index a4d6df9b5c2..af74a7f3c04 100644
--- a/source/blender/editors/undo/undo_system_types.c
+++ b/source/blender/editors/undo/undo_system_types.c
@@ -10,6 +10,7 @@
 
 #include "ED_armature.h"
 #include "ED_curve.h"
+#include "ED_curves.h"
 #include "ED_lattice.h"
 #include "ED_mball.h"
 #include "ED_mesh.h"
@@ -32,6 +33,7 @@ void ED_undosys_type_init(void)
   BKE_undosys_type_append(ED_lattice_undosys_type);
   BKE_undosys_type_append(ED_mball_undosys_type);
   BKE_undosys_type_append(ED_mesh_undosys_type);
+  BKE_undosys_type_append(ED_curves_undosys_type);
 
   /* Paint Modes */
   BKE_UNDOSYS_TYPE_IMAGE = BKE_undosys_type_append(ED_image_undosys_type);



More information about the Bf-blender-cvs mailing list