Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/hair/hair_undo.c')
-rw-r--r--source/blender/editors/hair/hair_undo.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/source/blender/editors/hair/hair_undo.c b/source/blender/editors/hair/hair_undo.c
new file mode 100644
index 00000000000..a58b9c042f8
--- /dev/null
+++ b/source/blender/editors/hair/hair_undo.c
@@ -0,0 +1,190 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/hair/hair_undo.c
+ * \ingroup edhair
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_context.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_editstrands.h"
+#include "BKE_key.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_sample.h"
+
+#include "ED_physics.h"
+#include "ED_util.h"
+
+#include "bmesh.h"
+
+#include "hair_intern.h"
+
+static void *strands_get_edit(bContext *C)
+{
+ Object *obact = CTX_data_active_object(C);
+ const int mode_flag = OB_MODE_HAIR_EDIT;
+ const bool is_mode_set = ((obact->mode & mode_flag) != 0);
+
+ if (obact && is_mode_set) {
+ BMEditStrands *edit = BKE_editstrands_from_object(obact);
+ return edit;
+ }
+ return NULL;
+}
+
+typedef struct UndoStrands {
+ Mesh me; /* Mesh supports all the customdata we need, easiest way to implement undo storage */
+ int selectmode;
+
+ /** \note
+ * this isn't a prefect solution, if you edit keys and change shapes this works well (fixing [#32442]),
+ * but editing shape keys, going into object mode, removing or changing their order,
+ * then go back into editmode and undo will give issues - where the old index will be out of sync
+ * with the new object index.
+ *
+ * There are a few ways this could be made to work but for now its a known limitation with mixing
+ * object and editmode operations - Campbell */
+ int shapenr;
+} UndoStrands;
+
+/* undo simply makes copies of a bmesh */
+static void *strands_edit_to_undo(void *editv, void *UNUSED(obdata))
+{
+ BMEditStrands *edit = editv;
+// Mesh *obme = obdata;
+
+ UndoStrands *undo = MEM_callocN(sizeof(UndoStrands), "undo Strands");
+
+ /* make sure shape keys work */
+// um->me.key = obme->key ? BKE_key_copy_nolib(obme->key) : NULL;
+
+ /* BM_mesh_validate(em->bm); */ /* for troubleshooting */
+
+ BM_mesh_bm_to_me_ex(edit->bm, &undo->me, CD_MASK_STRANDS, false);
+
+ undo->selectmode = edit->bm->selectmode;
+ undo->shapenr = edit->bm->shapenr;
+
+ return undo;
+}
+
+static void strands_undo_to_edit(void *undov, void *editv, void *UNUSED(obdata))
+{
+ UndoStrands *undo = undov;
+ BMEditStrands *edit = editv, *edit_tmp;
+ Object *ob = edit->ob;
+ DerivedMesh *dm = edit->root_dm;
+ BMesh *bm;
+// Key *key = ((Mesh *) obdata)->key;
+
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(&undo->me);
+
+ edit->bm->shapenr = undo->shapenr;
+
+ bm = BM_mesh_create(&allocsize);
+ BM_mesh_bm_from_me_ex(bm, &undo->me, CD_MASK_STRANDS_BMESH, false, false, undo->shapenr);
+
+ /* note: have to create the new edit before freeing the old one,
+ * because it owns the root_dm and we have to copy it before
+ * it gets released when freeing the old edit.
+ */
+ edit_tmp = BKE_editstrands_create(bm, dm, NULL);
+ BKE_editstrands_free(edit);
+ *edit = *edit_tmp;
+
+ bm->selectmode = undo->selectmode;
+ edit->ob = ob;
+
+#if 0
+ /* T35170: Restore the active key on the RealMesh. Otherwise 'fake' offset propagation happens
+ * if the active is a basis for any other. */
+ if (key && (key->type == KEY_RELATIVE)) {
+ /* Since we can't add, remove or reorder keyblocks in editmode, it's safe to assume
+ * shapenr from restored bmesh and keyblock indices are in sync. */
+ const int kb_act_idx = ob->shapenr - 1;
+
+ /* If it is, let's patch the current mesh key block to its restored value.
+ * Else, the offsets won't be computed and it won't matter. */
+ if (BKE_keyblock_is_basis(key, kb_act_idx)) {
+ KeyBlock *kb_act = BLI_findlink(&key->block, kb_act_idx);
+
+ if (kb_act->totelem != undo->me.totvert) {
+ /* The current mesh has some extra/missing verts compared to the undo, adjust. */
+ MEM_SAFE_FREE(kb_act->data);
+ kb_act->data = MEM_mallocN((size_t)(key->elemsize * bm->totvert), __func__);
+ kb_act->totelem = undo->me.totvert;
+ }
+
+ BKE_keyblock_update_from_mesh(&undo->me, kb_act);
+ }
+ }
+#endif
+
+ ob->shapenr = undo->shapenr;
+
+ MEM_freeN(edit_tmp);
+}
+
+static void strands_free_undo(void *undov)
+{
+ UndoStrands *undo = undov;
+
+ if (undo->me.key) {
+ BKE_key_free(undo->me.key);
+ MEM_freeN(undo->me.key);
+ }
+
+ BKE_mesh_free(&undo->me, false);
+ MEM_freeN(undo);
+}
+
+/* and this is all the undo system needs to know */
+void undo_push_strands(bContext *C, const char *name)
+{
+ /* edit->ob gets out of date and crashes on mesh undo,
+ * this is an easy way to ensure its OK
+ * though we could investigate the matter further. */
+ Object *obact = CTX_data_active_object(C);
+ BMEditStrands *edit = BKE_editstrands_from_object(obact);
+ if (edit) {
+ edit->ob = obact;
+
+ undo_editmode_push(C, name, CTX_data_active_object, strands_get_edit, strands_free_undo, strands_undo_to_edit, strands_edit_to_undo, NULL);
+ }
+}