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:
authorCampbell Barton <ideasman42@gmail.com>2019-06-28 11:10:43 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-06-28 11:22:53 +0300
commit9bcab8050f44e5bd36a0715811ee0355e4b221b6 (patch)
tree31d3d4abe5027df7759ae8dd8174fccd02fcb45b /source/blender
parenteac11046a151dd1dfc175f2c3faf00a3baa99956 (diff)
Fix T63694: Crash using tool gizmos with multiple windows
Gizmo group types now store a user count so they aren't unlinked while other tools are using them. The tool system now works with multiple windows.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/editors/util/gizmo_utils.c7
-rw-r--r--source/blender/windowmanager/gizmo/WM_gizmo_api.h9
-rw-r--r--source/blender/windowmanager/gizmo/WM_gizmo_types.h8
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c32
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h3
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c38
6 files changed, 96 insertions, 1 deletions
diff --git a/source/blender/editors/util/gizmo_utils.c b/source/blender/editors/util/gizmo_utils.c
index d330019c816..b856c831424 100644
--- a/source/blender/editors/util/gizmo_utils.c
+++ b/source/blender/editors/util/gizmo_utils.c
@@ -59,7 +59,12 @@ bool ED_gizmo_poll_or_unlink_delayed_from_tool_ex(const bContext *C,
{
bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
if ((tref_rt == NULL) || !STREQ(gzgt_idname, tref_rt->gizmo_group)) {
- WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
+ ScrArea *sa = CTX_wm_area(C);
+ wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(&gzgt->gzmap_params);
+ WM_gizmo_group_unlink_delayed_ptr_from_space(gzgt, gzmap_type, sa);
+ if (gzgt->users == 0) {
+ WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
+ }
return false;
}
return true;
diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_api.h b/source/blender/windowmanager/gizmo/WM_gizmo_api.h
index 293b0cd91dc..5896424d5fe 100644
--- a/source/blender/windowmanager/gizmo/WM_gizmo_api.h
+++ b/source/blender/windowmanager/gizmo/WM_gizmo_api.h
@@ -34,6 +34,7 @@ struct GHashIterator;
struct IDProperty;
struct Main;
struct PropertyRNA;
+struct ScrArea;
struct bToolRef;
struct wmGizmo;
struct wmGizmoGroup;
@@ -166,6 +167,8 @@ void WM_gizmoconfig_update_tag_group_type_remove(struct wmGizmoMapType *gzmap_ty
struct wmGizmoGroupType *gzgt);
void WM_gizmoconfig_update(struct Main *bmain);
+void WM_gizmoconfig_update_tag_group_remove(struct wmGizmoMap *gzmap);
+
/* wm_maniulator_target_props.c */
struct wmGizmoProperty *WM_gizmo_target_property_array(struct wmGizmo *gz);
struct wmGizmoProperty *WM_gizmo_target_property_at_index(struct wmGizmo *gz, int index);
@@ -354,6 +357,10 @@ void WM_gizmo_group_type_unlink_delayed_ptr_ex(struct wmGizmoGroupType *gzgt,
void WM_gizmo_group_type_unlink_delayed_ptr(struct wmGizmoGroupType *gzgt);
void WM_gizmo_group_type_unlink_delayed(const char *idname);
+void WM_gizmo_group_unlink_delayed_ptr_from_space(struct wmGizmoGroupType *gzgt,
+ struct wmGizmoMapType *gzmap_type,
+ struct ScrArea *sa);
+
/* Has the result of unlinking and linking (re-initializes gizmo's). */
void WM_gizmo_group_type_reinit_ptr_ex(struct Main *bmain,
struct wmGizmoGroupType *gzgt,
@@ -370,4 +377,6 @@ void WM_gizmo_group_remove_by_tool(struct bContext *C,
const struct wmGizmoGroupType *gzgt,
const struct bToolRef *tref);
+void WM_gizmo_group_tag_remove(struct wmGizmoGroup *gzgroup);
+
#endif /* __WM_GIZMO_API_H__ */
diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
index 7afd2908b8e..68ecdeea936 100644
--- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h
+++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
@@ -417,6 +417,12 @@ typedef struct wmGizmoGroupType {
/** Same as gizmo-maps, so registering/unregistering goes to the correct region. */
struct wmGizmoMapType_Params gzmap_params;
+ /**
+ * Number of #wmGizmoGroup instances.
+ * Decremented when 'tag_remove' is set, or when removed.
+ */
+ int users;
+
} wmGizmoGroupType;
typedef struct wmGizmoGroup {
@@ -432,6 +438,8 @@ typedef struct wmGizmoGroup {
/** Errors and warnings storage. */
struct ReportList *reports;
+ bool tag_remove;
+
void *customdata;
/** For freeing customdata from above. */
void (*customdata_free)(void *);
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
index f996d938dd7..40d99ce8ba6 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
@@ -70,7 +70,9 @@
wmGizmoGroup *wm_gizmogroup_new_from_type(wmGizmoMap *gzmap, wmGizmoGroupType *gzgt)
{
wmGizmoGroup *gzgroup = MEM_callocN(sizeof(*gzgroup), "gizmo-group");
+
gzgroup->type = gzgt;
+ gzgroup->type->users += 1;
/* keep back-link */
gzgroup->parent_gzmap = gzmap;
@@ -130,9 +132,23 @@ void wm_gizmogroup_free(bContext *C, wmGizmoGroup *gzgroup)
BLI_remlink(&gzmap->groups, gzgroup);
+ if (gzgroup->tag_remove == false) {
+ gzgroup->type->users -= 1;
+ }
+
MEM_freeN(gzgroup);
}
+void WM_gizmo_group_tag_remove(wmGizmoGroup *gzgroup)
+{
+ if (gzgroup->tag_remove == false) {
+ gzgroup->tag_remove = true;
+ gzgroup->type->users -= 1;
+ BLI_assert(gzgroup->type->users >= 0);
+ WM_gizmoconfig_update_tag_group_remove(gzgroup->parent_gzmap);
+ }
+}
+
/**
* Add \a gizmo to \a gzgroup and make sure its name is unique within the group.
*/
@@ -1099,4 +1115,20 @@ void WM_gizmo_group_type_unlink_delayed(const char *idname)
WM_gizmo_group_type_unlink_delayed_ptr(gzgt);
}
+void WM_gizmo_group_unlink_delayed_ptr_from_space(wmGizmoGroupType *gzgt,
+ wmGizmoMapType *gzmap_type,
+ ScrArea *sa)
+{
+ for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
+ wmGizmoMap *gzmap = ar->gizmo_map;
+ if (gzmap && gzmap->type == gzmap_type) {
+ for (wmGizmoGroup *gzgroup = gzmap->groups.first; gzgroup; gzgroup = gzgroup->next) {
+ if (gzgroup->type == gzgt) {
+ WM_gizmo_group_tag_remove(gzgroup);
+ }
+ }
+ }
+ }
+}
+
/** \} */
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h b/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
index 98c3ad8295c..f0771437518 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
@@ -99,6 +99,9 @@ struct wmGizmoMap {
/** Private, true when not yet used. */
bool is_init;
+ /** When set, one of of the items in 'groups' has #wmGizmoGroup.tag_remove set. */
+ bool tag_remove_group;
+
/**
* \brief Gizmo map runtime context
*
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
index edf376b1259..be123bee5df 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
@@ -69,8 +69,13 @@ static ListBase gizmomaptypes = {NULL, NULL};
*/
/* so operator removal can trigger update */
typedef enum eWM_GizmoFlagGroupTypeGlobalFlag {
+ /** Initialize by #wmGroupType.type_update_flag. */
WM_GIZMOMAPTYPE_GLOBAL_UPDATE_INIT = (1 << 0),
+ /** Remove by #wmGroupType.type_update_flag. */
WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE = (1 << 1),
+
+ /** Remove by #wmGroup.tag_remove. */
+ WM_GIZMOTYPE_GLOBAL_UPDATE_REMOVE = (1 << 2),
} eWM_GizmoFlagGroupTypeGlobalFlag;
static eWM_GizmoFlagGroupTypeGlobalFlag wm_gzmap_type_update_flag = 0;
@@ -1257,6 +1262,13 @@ void WM_gizmoconfig_update_tag_group_type_remove(wmGizmoMapType *gzmap_type,
wm_gzmap_type_update_flag |= WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE;
}
+void WM_gizmoconfig_update_tag_group_remove(wmGizmoMap *gzmap)
+{
+ gzmap->tag_remove_group = true;
+
+ wm_gzmap_type_update_flag |= WM_GIZMOTYPE_GLOBAL_UPDATE_REMOVE;
+}
+
/**
* Run in case new types have been added (runs often, early exit where possible).
* Follows #WM_keyconfig_update conventions.
@@ -1271,6 +1283,32 @@ void WM_gizmoconfig_update(struct Main *bmain)
return;
}
+ if (wm_gzmap_type_update_flag & WM_GIZMOTYPE_GLOBAL_UPDATE_REMOVE) {
+ for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ for (ARegion *ar = regionbase->first; ar; ar = ar->next) {
+ wmGizmoMap *gzmap = ar->gizmo_map;
+ if (gzmap != NULL && gzmap->tag_remove_group) {
+ gzmap->tag_remove_group = false;
+
+ for (wmGizmoGroup *gzgroup = gzmap->groups.first, *gzgroup_next; gzgroup;
+ gzgroup = gzgroup_next) {
+ gzgroup_next = gzgroup->next;
+ if (gzgroup->tag_remove) {
+ wm_gizmogroup_free(NULL, gzgroup);
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ wm_gzmap_type_update_flag &= ~WM_GIZMOTYPE_GLOBAL_UPDATE_REMOVE;
+ }
+
if (wm_gzmap_type_update_flag & WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE) {
for (wmGizmoMapType *gzmap_type = gizmomaptypes.first; gzmap_type;
gzmap_type = gzmap_type->next) {