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
This commit is contained in:
parent
c07fdad03d
commit
d650162ecd
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue