diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-07-17 07:33:12 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-07-17 07:36:20 +0300 |
commit | 02257ace225fc7cb4673639bd807360fb9e12592 (patch) | |
tree | 6171519c77fcb9e7a845a3be876777b32c5b733b /source/blender/windowmanager | |
parent | d221a999cb18e67e638066c275fc3178e164df84 (diff) |
Fix crash re-registering the same manipulator type
Wasn't unlinking from the group instance.
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r-- | source/blender/windowmanager/manipulators/WM_manipulator_api.h | 4 | ||||
-rw-r--r-- | source/blender/windowmanager/manipulators/intern/wm_manipulator_type.c | 47 |
2 files changed, 46 insertions, 5 deletions
diff --git a/source/blender/windowmanager/manipulators/WM_manipulator_api.h b/source/blender/windowmanager/manipulators/WM_manipulator_api.h index d6774333ba4..43a5af3bbc4 100644 --- a/source/blender/windowmanager/manipulators/WM_manipulator_api.h +++ b/source/blender/windowmanager/manipulators/WM_manipulator_api.h @@ -113,8 +113,8 @@ void WM_manipulator_properties_free(struct PointerRNA *ptr); const struct wmManipulatorType *WM_manipulatortype_find(const char *idname, bool quiet); void WM_manipulatortype_append(void (*wtfunc)(struct wmManipulatorType *)); void WM_manipulatortype_append_ptr(void (*mnpfunc)(struct wmManipulatorType *, void *), void *userdata); -bool WM_manipulatortype_remove(const char *idname); -void WM_manipulatortype_remove_ptr(struct wmManipulatorType *wt); +bool WM_manipulatortype_remove(struct bContext *C, struct Main *bmain, const char *idname); +void WM_manipulatortype_remove_ptr(struct bContext *C, struct Main *bmain, struct wmManipulatorType *wt); void WM_manipulatortype_iter(struct GHashIterator *ghi); /* wm_manipulator_group_type.c */ diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_type.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_type.c index 7dabc70d69d..976ef1ddab2 100644 --- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_type.c +++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_type.c @@ -28,6 +28,11 @@ #include "BLI_string.h" #include "BLI_string_utils.h" +#include "BKE_main.h" + +#include "DNA_screen_types.h" +#include "DNA_space_types.h" + #include "MEM_guardedalloc.h" #include "RNA_access.h" @@ -36,6 +41,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "ED_screen.h" + /* only for own init/exit calls (wm_manipulatortype_init/wm_manipulatortype_free) */ #include "wm.h" @@ -123,16 +130,50 @@ static void manipulatortype_free(wmManipulatorType *wt) MEM_freeN(wt); } -void WM_manipulatortype_remove_ptr(wmManipulatorType *wt) +/** + * \param C: May be NULL. + */ +static void manipulatortype_unlink( + bContext *C, Main *bmain, wmManipulatorType *wt) +{ + /* Free instances. */ + for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) { + for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { + for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { + ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase; + for (ARegion *ar = lb->first; ar; ar = ar->next) { + wmManipulatorMap *mmap = ar->manipulator_map; + if (mmap) { + wmManipulatorGroup *mgroup; + for (mgroup = mmap->groups.first; mgroup; mgroup = mgroup->next) { + for (wmManipulator *mpr = mgroup->manipulators.first, *mpr_next; mpr; mpr = mpr_next) { + mpr_next = mpr->next; + BLI_assert(mgroup->parent_mmap == mmap); + if (mpr->type == wt) { + WM_manipulator_free(&mgroup->manipulators, mgroup->parent_mmap, mpr, C); + ED_region_tag_redraw(ar); + } + } + } + } + } + } + } + } +} + +void WM_manipulatortype_remove_ptr(bContext *C, Main *bmain, wmManipulatorType *wt) { BLI_assert(wt == WM_manipulatortype_find(wt->idname, false)); BLI_ghash_remove(global_manipulatortype_hash, wt->idname, NULL, NULL); + manipulatortype_unlink(C, bmain, wt); + manipulatortype_free(wt); } -bool WM_manipulatortype_remove(const char *idname) +bool WM_manipulatortype_remove(bContext *C, Main *bmain, const char *idname) { wmManipulatorType *wt = BLI_ghash_lookup(global_manipulatortype_hash, idname); @@ -140,7 +181,7 @@ bool WM_manipulatortype_remove(const char *idname) return false; } - WM_manipulatortype_remove_ptr(wt); + WM_manipulatortype_remove_ptr(C, bmain, wt); return true; } |