[Bf-blender-cvs] [18773f3f150] blender2.8: Fix manipulator Python API crash w/ undo
Campbell Barton
noreply at git.blender.org
Sun Jul 30 22:30:40 CEST 2017
Commit: 18773f3f1502d35d2a4b88e5d7579ba015095a96
Author: Campbell Barton
Date: Mon Jul 31 06:41:10 2017 +1000
Branches: blender2.8
https://developer.blender.org/rB18773f3f1502d35d2a4b88e5d7579ba015095a96
Fix manipulator Python API crash w/ undo
Split up manipulator free & unlink, so freeing window data doesn't
run callbacks that might use freed data.
===================================================================
M source/blender/makesrna/intern/rna_wm_manipulator.c
M source/blender/windowmanager/manipulators/WM_manipulator_api.h
M source/blender/windowmanager/manipulators/intern/wm_manipulator.c
M source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
M source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
M source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
M source/blender/windowmanager/manipulators/intern/wm_manipulator_type.c
M source/blenderplayer/bad_level_call_stubs/stubs.c
===================================================================
diff --git a/source/blender/makesrna/intern/rna_wm_manipulator.c b/source/blender/makesrna/intern/rna_wm_manipulator.c
index fc7dcdbe3cb..28821ecb0bd 100644
--- a/source/blender/makesrna/intern/rna_wm_manipulator.c
+++ b/source/blender/makesrna/intern/rna_wm_manipulator.c
@@ -522,14 +522,14 @@ static wmManipulator *rna_ManipulatorGroup_manipulator_new(
static void rna_ManipulatorGroup_manipulator_remove(
wmManipulatorGroup *mgroup, bContext *C, wmManipulator *mpr)
{
- WM_manipulator_free(&mgroup->manipulators, mgroup->parent_mmap, mpr, C);
+ WM_manipulator_unlink(&mgroup->manipulators, mgroup->parent_mmap, mpr, C);
}
static void rna_ManipulatorGroup_manipulator_clear(
wmManipulatorGroup *mgroup, bContext *C)
{
while (mgroup->manipulators.first) {
- WM_manipulator_free(&mgroup->manipulators, mgroup->parent_mmap, mgroup->manipulators.first, C);
+ WM_manipulator_unlink(&mgroup->manipulators, mgroup->parent_mmap, mgroup->manipulators.first, C);
}
}
diff --git a/source/blender/windowmanager/manipulators/WM_manipulator_api.h b/source/blender/windowmanager/manipulators/WM_manipulator_api.h
index 9211c3365c5..a4b4964384c 100644
--- a/source/blender/windowmanager/manipulators/WM_manipulator_api.h
+++ b/source/blender/windowmanager/manipulators/WM_manipulator_api.h
@@ -63,12 +63,14 @@ struct wmManipulator *WM_manipulator_new_ptr(
struct wmManipulator *WM_manipulator_new(
const char *idname, struct wmManipulatorGroup *mgroup,
struct PointerRNA *properties);
-void WM_manipulator_free(
+void WM_manipulator_free(struct wmManipulator *mpr);
+void WM_manipulator_unlink(
ListBase *manipulatorlist, struct wmManipulatorMap *mmap, struct wmManipulator *mpr,
struct bContext *C);
void WM_manipulator_name_set(struct wmManipulatorGroup *mgroup, struct wmManipulator *mpr, const char *name);
+bool WM_manipulator_select_unlink(struct wmManipulatorMap *mmap, struct wmManipulator *mpr);
bool WM_manipulator_select_set(struct wmManipulatorMap *mmap, struct wmManipulator *mpr, bool select);
struct PointerRNA *WM_manipulator_set_operator(
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
index 4936afde0c1..82ce0cf24ba 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
@@ -157,10 +157,11 @@ static void wm_manipulator_register(wmManipulatorGroup *mgroup, wmManipulator *m
}
/**
- * Free \a manipulator and unlink from \a manipulatorlist.
- * \a manipulatorlist is allowed to be NULL.
+ * \warning this doesn't check #wmManipulatorMap (highlight, selection etc).
+ * Typical use is when freeing the windowing data,
+ * where caller can manage clearing selection, highlight... etc.
*/
-void WM_manipulator_free(ListBase *manipulatorlist, wmManipulatorMap *mmap, wmManipulator *mpr, bContext *C)
+void WM_manipulator_free(wmManipulator *mpr)
{
#ifdef WITH_PYTHON
if (mpr->py_instance) {
@@ -170,16 +171,6 @@ void WM_manipulator_free(ListBase *manipulatorlist, wmManipulatorMap *mmap, wmMa
}
#endif
- if (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) {
- wm_manipulatormap_highlight_set(mmap, C, NULL, 0);
- }
- if (mpr->state & WM_MANIPULATOR_STATE_MODAL) {
- wm_manipulatormap_modal_set(mmap, C, NULL, NULL);
- }
- if (mpr->state & WM_MANIPULATOR_STATE_SELECT) {
- WM_manipulator_select_set(mmap, mpr, false);
- }
-
if (mpr->op_data.ptr.data) {
WM_operator_properties_free(&mpr->op_data.ptr);
}
@@ -199,6 +190,26 @@ void WM_manipulator_free(ListBase *manipulatorlist, wmManipulatorMap *mmap, wmMa
}
}
+ MEM_freeN(mpr);
+}
+
+/**
+ * Free \a manipulator and unlink from \a manipulatorlist.
+ * \a manipulatorlist is allowed to be NULL.
+ */
+void WM_manipulator_unlink(ListBase *manipulatorlist, wmManipulatorMap *mmap, wmManipulator *mpr, bContext *C)
+{
+ if (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) {
+ wm_manipulatormap_highlight_set(mmap, C, NULL, 0);
+ }
+ if (mpr->state & WM_MANIPULATOR_STATE_MODAL) {
+ wm_manipulatormap_modal_set(mmap, C, NULL, NULL);
+ }
+ /* Unlink instead of setting so we don't run callbacks. */
+ if (mpr->state & WM_MANIPULATOR_STATE_SELECT) {
+ WM_manipulator_select_unlink(mmap, mpr);
+ }
+
if (manipulatorlist) {
BLI_remlink(manipulatorlist, mpr);
}
@@ -206,7 +217,7 @@ void WM_manipulator_free(ListBase *manipulatorlist, wmManipulatorMap *mmap, wmMa
BLI_assert(mmap->mmap_context.highlight != mpr);
BLI_assert(mmap->mmap_context.modal != mpr);
- MEM_freeN(mpr);
+ WM_manipulator_free(mpr);
}
/* -------------------------------------------------------------------- */
@@ -367,7 +378,9 @@ void WM_manipulator_set_fn_custom_modal(struct wmManipulator *mpr, wmManipulator
*
* \return if the selection has changed.
*/
-bool wm_manipulator_select_set_ex(wmManipulatorMap *mmap, wmManipulator *mpr, bool select, bool use_array)
+bool wm_manipulator_select_set_ex(
+ wmManipulatorMap *mmap, wmManipulator *mpr, bool select,
+ bool use_array, bool use_callback)
{
bool changed = false;
@@ -390,7 +403,9 @@ bool wm_manipulator_select_set_ex(wmManipulatorMap *mmap, wmManipulator *mpr, bo
}
}
- if (changed) {
+ /* In the case of unlinking we only want to remove from the array
+ * and not write to the external state */
+ if (use_callback && changed) {
if (mpr->type->select_refresh) {
mpr->type->select_refresh(mpr);
}
@@ -399,9 +414,15 @@ bool wm_manipulator_select_set_ex(wmManipulatorMap *mmap, wmManipulator *mpr, bo
return changed;
}
+/* Remove from selection array without running callbacks. */
+bool WM_manipulator_select_unlink(wmManipulatorMap *mmap, wmManipulator *mpr)
+{
+ return wm_manipulator_select_set_ex(mmap, mpr, false, true, false);
+}
+
bool WM_manipulator_select_set(wmManipulatorMap *mmap, wmManipulator *mpr, bool select)
{
- return wm_manipulator_select_set_ex(mmap, mpr, select, true);
+ return wm_manipulator_select_set_ex(mmap, mpr, select, true, true);
}
bool wm_manipulator_select_and_highlight(bContext *C, wmManipulatorMap *mmap, wmManipulator *mpr)
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
index 08dc9f2c8f9..f9cce984708 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
@@ -91,11 +91,24 @@ wmManipulatorGroup *wm_manipulatorgroup_new_from_type(
void wm_manipulatorgroup_free(bContext *C, wmManipulatorGroup *mgroup)
{
wmManipulatorMap *mmap = mgroup->parent_mmap;
+
+ /* Similar to WM_manipulator_unlink, but only to keep mmap state correct,
+ * we don't want to run callbacks. */
+ if (mmap->mmap_context.highlight && mmap->mmap_context.highlight->parent_mgroup == mgroup) {
+ wm_manipulatormap_highlight_set(mmap, C, NULL, 0);
+ }
+ if (mmap->mmap_context.modal && mmap->mmap_context.modal->parent_mgroup == mgroup) {
+ wm_manipulatormap_modal_set(mmap, C, NULL, NULL);
+ }
+
for (wmManipulator *mpr = mgroup->manipulators.first, *mpr_next; mpr; mpr = mpr_next) {
mpr_next = mpr->next;
- WM_manipulator_free(&mgroup->manipulators, mmap, mpr, C);
+ if (mmap->mmap_context.select.len) {
+ WM_manipulator_select_unlink(mmap, mpr);
+ }
+ WM_manipulator_free(mpr);
}
- BLI_assert(BLI_listbase_is_empty(&mgroup->manipulators));
+ BLI_listbase_clear(&mgroup->manipulators);
#ifdef WITH_PYTHON
if (mgroup->py_instance) {
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
index f7b82bfc68b..b8be482c3b8 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
@@ -39,7 +39,9 @@ struct GHashIterator;
/* wmManipulator */
-bool wm_manipulator_select_set_ex(struct wmManipulatorMap *mmap, struct wmManipulator *mpr, bool select, bool use_array);
+bool wm_manipulator_select_set_ex(
+ struct wmManipulatorMap *mmap, struct wmManipulator *mpr, bool select,
+ bool use_array, bool use_callback);
bool wm_manipulator_select_and_highlight(bContext *C, struct wmManipulatorMap *mmap, struct wmManipulator *mpr);
void wm_manipulator_calculate_scale(struct wmManipulator *mpr, const bContext *C);
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
index c0da31fdbdd..1a96846e75d 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
@@ -182,6 +182,9 @@ void wm_manipulatormap_remove(wmManipulatorMap *mmap)
if (!mmap)
return;
+ /* Clear first so further calls don't waste time trying to maintain correct array state. */
+ wm_manipulatormap_select_array_clear(mmap);
+
for (wmManipulatorGroup *mgroup = mmap->groups.first, *mgroup_next; mgroup; mgroup = mgroup_next) {
mgroup_next = mgroup->next;
BLI_assert(mgroup->parent_mmap == mmap);
@@ -189,8 +192,6 @@ void wm_manipulatormap_remove(wmManipulatorMap *mmap)
}
BLI_assert(BLI_listbase_is_empty(&mmap->groups));
- wm_manipulatormap_select_array_clear(mmap);
-
MEM_freeN(mmap);
}
@@ -636,7 +637,7 @@ bool wm_manipulatormap_deselect_all(wmManipulatorMap *mmap)
}
for (int i = 0; i < msel->len; i++) {
- wm_manipulator_select_set_ex(mmap, msel->items[i], false, false);
+ wm_manipulator_select_set_ex(mmap, msel->items[i], false, false, true);
}
wm_manipulatormap_select_array_clear(mmap);
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_type.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_type.c
index 976ef1ddab2..18265319024 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_type.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_type.c
@@ -150,7 +150,7 @@ static void manipulatortype_unlink(
mpr_next
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list