diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-11-13 11:43:34 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-12-04 12:42:34 +0300 |
commit | 7a8ac1b09b1cf321f259b8eb9b832424d2c7bf5b (patch) | |
tree | 5f9a861e234799149fc99f25e5df7bd96fb46cae /source/blender/editors | |
parent | 5b6cfa705cb180d042f6f27e45331c12972be7ae (diff) |
WM: message bus replacement for property notifiers
Use dynamically generated message publish/subscribe
so buttons and manipulators update properly.
This resolves common glitches where manipulators weren't updating
as well as the UI when add-ons exposed properties which
hard coded listeners weren't checking for.
Python can also publish/scribe changes via `bpy.msgbus`.
See D2917
Diffstat (limited to 'source/blender/editors')
-rw-r--r-- | source/blender/editors/include/ED_screen.h | 15 | ||||
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 3 | ||||
-rw-r--r-- | source/blender/editors/interface/interface.c | 38 | ||||
-rw-r--r-- | source/blender/editors/screen/area.c | 81 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_edit.c | 4 | ||||
-rw-r--r-- | source/blender/editors/space_buttons/space_buttons.c | 1 | ||||
-rw-r--r-- | source/blender/editors/space_file/space_file.c | 29 | ||||
-rw-r--r-- | source/blender/editors/space_time/space_time.c | 45 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/space_view3d.c | 71 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_draw.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_manipulator_camera.c | 51 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_manipulator.c | 62 |
12 files changed, 402 insertions, 0 deletions
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 23e65011387..89a6828a59d 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -55,6 +55,9 @@ struct ARegion; struct uiBlock; struct rcti; struct Main; +struct wmMsgBus; +struct wmMsgSubscribeKey; +struct wmMsgSubscribeValue; /* regions */ void ED_region_do_listen( @@ -86,6 +89,18 @@ void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy); float ED_region_blend_factor(struct ARegion *ar); void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect); +/* message_bus callbacks */ +void ED_region_do_msg_notify_tag_redraw( + struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val); +void ED_area_do_msg_notify_tag_refresh( + struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val); + +/* message bus */ +void ED_region_message_subscribe( + struct bContext *C, + struct WorkSpace *workspace, struct Scene *scene, + struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar, + struct wmMsgBus *mbus); /* spaces */ void ED_spacetypes_keymap(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index e2a6ca65b51..eba31a21094 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -73,6 +73,7 @@ struct bNodeSocket; struct wmDropBox; struct wmDrag; struct wmEvent; +struct wmMsgBus; typedef struct uiBut uiBut; typedef struct uiBlock uiBlock; @@ -875,6 +876,8 @@ uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int s void UI_block_layout_set_current(uiBlock *block, uiLayout *layout); void UI_block_layout_resolve(uiBlock *block, int *x, int *y); +void UI_region_message_subscribe(struct ARegion *ar, struct wmMsgBus *mbus); + uiBlock *uiLayoutGetBlock(uiLayout *layout); void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index fbdd48d42a7..9e6d9f23442 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -41,6 +41,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_userdef_types.h" +#include "DNA_workspace_types.h" #include "BLI_math.h" #include "BLI_listbase.h" @@ -69,11 +70,14 @@ #include "WM_api.h" #include "WM_types.h" #include "wm_subwindow.h" +#include "WM_message.h" #include "RNA_access.h" #include "BPY_extern.h" +#include "ED_screen.h" + #include "IMB_colormanagement.h" #include "interface_intern.h" @@ -1453,6 +1457,40 @@ void UI_block_draw(const bContext *C, uiBlock *block) ui_draw_links(block); } +static void ui_block_message_subscribe(ARegion *ar, struct wmMsgBus *mbus, uiBlock *block) +{ + uiBut *but_prev = NULL; + /* possibly we should keep the region this block is contained in? */ + for (uiBut *but = block->buttons.first; but; but = but->next) { + if (but->rnapoin.type && but->rnaprop) { + /* quick check to avoid adding buttons representing a vector, multiple times. */ + if ((but_prev && + (but_prev->rnaprop == but->rnaprop) && + (but_prev->rnapoin.type == but->rnapoin.type) && + (but_prev->rnapoin.data == but->rnapoin.data) && + (but_prev->rnapoin.id.data == but->rnapoin.id.data)) == false) + { + /* TODO: could make this into utility function. */ + WM_msg_subscribe_rna( + mbus, &but->rnapoin, but->rnaprop, + &(const wmMsgSubscribeValue){ + .owner = ar, + .user_data = ar, + .notify = ED_region_do_msg_notify_tag_redraw, + }, __func__); + but_prev = but; + } + } + } +} + +void UI_region_message_subscribe(ARegion *ar, struct wmMsgBus *mbus) +{ + for (uiBlock *block = ar->uiblocks.first; block; block = block->next) { + ui_block_message_subscribe(ar, mbus, block); + } +} + /* ************* EVENTS ************* */ /** diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 315b02cde93..08d92dfc9ff 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -51,6 +51,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "WM_message.h" #include "wm_subwindow.h" #include "ED_screen.h" @@ -511,6 +512,33 @@ void ED_region_set(const bContext *C, ARegion *ar) ED_region_pixelspace(ar); } +/* Follow wmMsgNotifyFn spec */ +void ED_region_do_msg_notify_tag_redraw( + bContext *UNUSED(C), wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val) +{ + ARegion *ar = msg_val->owner; + ED_region_tag_redraw(ar); + + /* This avoids _many_ situations where header/properties control display settings. + * the common case is space properties in the header */ + if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_UI)) { + while (ar && ar->prev) { + ar = ar->prev; + } + for (; ar; ar = ar->next) { + if (ELEM(ar->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_CHANNELS)) { + ED_region_tag_redraw(ar); + } + } + } +} +/* Follow wmMsgNotifyFn spec */ +void ED_area_do_msg_notify_tag_refresh( + bContext *UNUSED(C), wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val) +{ + ScrArea *sa = msg_val->user_data; + ED_area_tag_refresh(sa); +} /* only exported for WM */ void ED_region_do_draw(bContext *C, ARegion *ar) @@ -589,6 +617,37 @@ void ED_region_do_draw(bContext *C, ARegion *ar) region_draw_emboss(ar, &ar->winrct); } } + + /* We may want to detach message-subscriptions from drawing. */ + { + WorkSpace *workspace = CTX_wm_workspace(C); + wmWindowManager *wm = CTX_wm_manager(C); + bScreen *screen = WM_window_get_active_screen(win); + Scene *scene = CTX_data_scene(C); + struct wmMsgBus *mbus = wm->message_bus; + WM_msgbus_clear_by_owner(mbus, ar); + + /* Cheat, always subscribe to this space type properties. + * + * This covers most cases and avoids copy-paste similar code for each space type. + */ + if (ELEM(ar->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_CHANNELS, RGN_TYPE_UI, RGN_TYPE_TOOLS)) { + SpaceLink *sl = sa->spacedata.first; + + PointerRNA ptr; + RNA_pointer_create(&screen->id, &RNA_Space, sl, &ptr); + + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { + .owner = ar, + .user_data = ar, + .notify = ED_region_do_msg_notify_tag_redraw, + }; + /* All properties for this space type. */ + WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_region_tag_redraw, __func__); + } + + ED_region_message_subscribe(C, workspace, scene, screen, sa, ar, mbus); + } } /* ********************************** @@ -2595,3 +2654,25 @@ void ED_region_cache_draw_cached_segments(const ARegion *ar, const int num_segme immUnbindProgram(); } } + +/** + * Generate subscriptions for this region. + */ +void ED_region_message_subscribe( + bContext *C, + struct WorkSpace *workspace, struct Scene *scene, + struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar, + struct wmMsgBus *mbus) +{ + if (ar->manipulator_map != NULL) { + WM_manipulatormap_message_subscribe(C, ar->manipulator_map, ar, mbus); + } + + if (BLI_listbase_is_empty(&ar->uiblocks)) { + UI_region_message_subscribe(ar, mbus); + } + + if (ar->type->message_subscribe != NULL) { + ar->type->message_subscribe(C, workspace, scene, screen, sa, ar, mbus); + } +} diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index b702edf8864..d3f99dc8152 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -66,6 +66,8 @@ #include "UI_interface.h" +#include "WM_message.h" + /* XXX actually should be not here... solve later */ #include "wm_subwindow.h" @@ -1004,6 +1006,8 @@ void ED_region_exit(bContext *C, ARegion *ar) ar->regiontimer = NULL; } + WM_msgbus_clear_by_owner(wm->message_bus, ar); + CTX_wm_region_set(C, prevar); } diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 74b20360a53..d2f407bfa8c 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -44,6 +44,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "WM_message.h" #include "RNA_access.h" diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 780c2ec5a47..3f26604c23a 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -49,6 +49,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "WM_message.h" #include "ED_space_api.h" #include "ED_screen.h" @@ -354,6 +355,33 @@ static void file_main_region_listener( } } +static void file_main_region_message_subscribe( + const struct bContext *UNUSED(C), + struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene), + struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar, + struct wmMsgBus *mbus) +{ + SpaceFile *sfile = sa->spacedata.first; + FileSelectParams *params = ED_fileselect_get_params(sfile); + /* This is a bit odd that a region owns the subscriber for an area, + * keep for now since all subscribers for WM are regions. + * May be worth re-visiting later. */ + wmMsgSubscribeValue msg_sub_value_area_tag_refresh = { + .owner = ar, + .user_data = sa, + .notify = ED_area_do_msg_notify_tag_refresh, + }; + + /* FileSelectParams */ + { + PointerRNA ptr; + RNA_pointer_create(&screen->id, &RNA_FileSelectParams, params, &ptr); + + /* All properties for this space type. */ + WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_area_tag_refresh, __func__); + } +} + static void file_main_region_draw(const bContext *C, ARegion *ar) { /* draw entirely, view changes should be handled here */ @@ -731,6 +759,7 @@ void ED_spacetype_file(void) art->init = file_main_region_init; art->draw = file_main_region_draw; art->listener = file_main_region_listener; + art->message_subscribe = file_main_region_message_subscribe; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index 99ac0d9024c..283dbf3b4e2 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -58,6 +58,9 @@ #include "WM_api.h" #include "WM_types.h" +#include "WM_message.h" + +#include "RNA_access.h" #include "BIF_gl.h" @@ -649,6 +652,47 @@ static void time_main_region_listener( } } +static void time_main_region_message_subscribe( + const struct bContext *UNUSED(C), + struct WorkSpace *UNUSED(workspace), struct Scene *scene, + struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar, + struct wmMsgBus *mbus) +{ + PointerRNA ptr; + RNA_pointer_create(&screen->id, &RNA_SpaceTimeline, sa->spacedata.first, &ptr); + + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { + .owner = ar, + .user_data = ar, + .notify = ED_region_do_msg_notify_tag_redraw, + }; + + /* Timeline depends on scene properties. */ + { + bool use_preview = (scene->r.flag & SCER_PRV_RANGE); + extern PropertyRNA rna_Scene_frame_start; + extern PropertyRNA rna_Scene_frame_end; + extern PropertyRNA rna_Scene_frame_preview_start; + extern PropertyRNA rna_Scene_frame_preview_end; + extern PropertyRNA rna_Scene_use_preview_range; + extern PropertyRNA rna_Scene_frame_current; + const PropertyRNA *props[] = { + use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start, + use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end, + &rna_Scene_use_preview_range, + &rna_Scene_frame_current, + }; + + PointerRNA idptr; + RNA_id_pointer_create(&scene->id, &idptr); + + for (int i = 0; i < ARRAY_SIZE(props); i++) { + WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__); + } + } +} + + /* ************************ header time area region *********************** */ /* add handlers, stuff you only do once or on area/region changes */ @@ -797,6 +841,7 @@ void ED_spacetype_time(void) art->init = time_main_region_init; art->draw = time_main_region_draw; art->listener = time_main_region_listener; + art->message_subscribe = time_main_region_message_subscribe; art->keymap = time_keymap; art->lock = 1; /* Due to pointcache, see T4960. */ BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 12d0ed4501b..728547e7a40 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -67,6 +67,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "WM_message.h" #include "RE_engine.h" #include "RE_pipeline.h" @@ -1056,6 +1057,75 @@ static void view3d_main_region_listener( } } +static void view3d_main_region_message_subscribe( + const struct bContext *UNUSED(C), + struct WorkSpace *workspace, struct Scene *scene, + struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar, + struct wmMsgBus *mbus) +{ + /* Developer note: there are many properties that impact 3D view drawing, + * so instead of subscribing to individual properties, just subscribe to types + * accepting some redundant redraws. + * + * For other space types we might try avoid this, keep the 3D view as an exceptional case! */ + ViewRender *view_render = BKE_viewrender_get(scene, workspace); + wmMsgParams_RNA msg_key_params = {0}; + + /* Only subscribe to types. */ + StructRNA *type_array[] = { + /* These object have properties that impact drawing. */ + &RNA_AreaLamp, + &RNA_Camera, + &RNA_Lamp, + &RNA_Speaker, + &RNA_SunLamp, + + /* General types the 3D view depends on. */ + &RNA_Object, + &RNA_UnitSettings, /* grid-floor */ + + &RNA_ViewRenderSettings, + &RNA_World, + }; + + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { + .owner = ar, + .user_data = ar, + .notify = ED_region_do_msg_notify_tag_redraw, + }; + + for (int i = 0; i < ARRAY_SIZE(type_array); i++) { + msg_key_params.ptr.type = type_array[i]; + WM_msg_subscribe_rna_params( + mbus, + &msg_key_params, + &msg_sub_value_region_tag_redraw, + __func__); + } + + /* Subscribe to a handful of other properties. */ + RegionView3D *rv3d = ar->regiondata; + + WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_region_tag_redraw); + WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_region_tag_redraw); + WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_region_tag_redraw); + WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_region_tag_redraw); + if (rv3d->persp == RV3D_CAMOB) { + WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, use_border, &msg_sub_value_region_tag_redraw); + } + + /* Each engine could be responsible for its own engine data types. + * For now this is simplest. */ + if (STREQ(view_render->engine_id, RE_engine_id_BLENDER_EEVEE)) { + extern StructRNA RNA_ViewLayerEngineSettingsEevee; + WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsEevee, &msg_sub_value_region_tag_redraw); + } + else if (STREQ(view_render->engine_id, RE_engine_id_BLENDER_CLAY)) { + extern StructRNA RNA_ViewLayerEngineSettingsClay; + WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsClay, &msg_sub_value_region_tag_redraw); + } +} + /* concept is to retrieve cursor type context-less */ static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar)) { @@ -1418,6 +1488,7 @@ void ED_spacetype_view3d(void) art->free = view3d_main_region_free; art->duplicate = view3d_main_region_duplicate; art->listener = view3d_main_region_listener; + art->message_subscribe = view3d_main_region_message_subscribe; art->cursor = view3d_main_region_cursor; art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */ BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index c341a4cde1c..6ea2ff10af2 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -90,6 +90,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "RNA_access.h" + #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/editors/space_view3d/view3d_manipulator_camera.c b/source/blender/editors/space_view3d/view3d_manipulator_camera.c index a4d408eedc6..d020571930a 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_camera.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_camera.c @@ -45,6 +45,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "WM_message.h" #include "view3d_intern.h" /* own include */ @@ -217,6 +218,55 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmManipulatorGroup *mg } +static void WIDGETGROUP_camera_message_subscribe( + const bContext *C, wmManipulatorGroup *mgroup, struct wmMsgBus *mbus) +{ + ARegion *ar = CTX_wm_region(C); + Object *ob = CTX_data_active_object(C); + Camera *ca = ob->data; + + wmMsgSubscribeValue msg_sub_value_mpr_tag_refresh = { + .owner = ar, + .user_data = mgroup->parent_mmap, + .notify = WM_manipulator_do_msg_notify_tag_refresh, + }; + + { + extern PropertyRNA rna_Camera_dof_distance; + extern PropertyRNA rna_Camera_draw_size; + extern PropertyRNA rna_Camera_ortho_scale; + extern PropertyRNA rna_Camera_sensor_fit; + extern PropertyRNA rna_Camera_sensor_width; + extern PropertyRNA rna_Camera_shift_x; + extern PropertyRNA rna_Camera_shift_y; + extern PropertyRNA rna_Camera_type; + const PropertyRNA *props[] = { + &rna_Camera_dof_distance, + &rna_Camera_draw_size, + &rna_Camera_ortho_scale, + &rna_Camera_sensor_fit, + &rna_Camera_sensor_width, + &rna_Camera_shift_x, + &rna_Camera_shift_y, + &rna_Camera_type, + }; + + PointerRNA idptr; + RNA_id_pointer_create(&ca->id, &idptr); + + for (int i = 0; i < ARRAY_SIZE(props); i++) { + WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__); + } + } + + /* Subscribe to render settings */ + { + WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_mpr_tag_refresh); + WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_mpr_tag_refresh); + WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_mpr_tag_refresh); + WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_mpr_tag_refresh); + } +} void VIEW3D_WGT_camera(wmManipulatorGroupType *wgt) { @@ -230,6 +280,7 @@ void VIEW3D_WGT_camera(wmManipulatorGroupType *wgt) wgt->poll = WIDGETGROUP_camera_poll; wgt->setup = WIDGETGROUP_camera_setup; wgt->refresh = WIDGETGROUP_camera_refresh; + wgt->message_subscribe = WIDGETGROUP_camera_message_subscribe; } /** \} */ diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 3d9ab560bc7..0e0c2f3ae25 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -65,6 +65,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "WM_message.h" #include "ED_armature.h" #include "ED_curve.h" @@ -1115,6 +1116,47 @@ static void manipulator_line_range(const View3D *v3d, const short axis_type, flo *r_len -= *r_start; } +static void manipulator_xform_message_subscribe( + wmManipulatorGroup *mgroup, struct wmMsgBus *mbus, + bScreen *screen, ScrArea *sa, ARegion *ar, const void *type_fn) +{ + /* Subscribe to view properties */ + wmMsgSubscribeValue msg_sub_value_mpr_tag_refresh = { + .owner = ar, + .user_data = mgroup->parent_mmap, + .notify = WM_manipulator_do_msg_notify_tag_refresh, + }; + + PointerRNA space_ptr; + RNA_pointer_create(&screen->id, &RNA_SpaceView3D, sa->spacedata.first, &space_ptr); + + { + extern PropertyRNA rna_SpaceView3D_transform_orientation; + const PropertyRNA *props[] = { + &rna_SpaceView3D_transform_orientation, + }; + for (int i = 0; i < ARRAY_SIZE(props); i++) { + WM_msg_subscribe_rna(mbus, &space_ptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__); + } + } + + if (type_fn == TRANSFORM_WGT_manipulator) { + extern PropertyRNA rna_SpaceView3D_pivot_point; + const PropertyRNA *props[] = { + &rna_SpaceView3D_pivot_point + }; + for (int i = 0; i < ARRAY_SIZE(props); i++) { + WM_msg_subscribe_rna(mbus, &space_ptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__); + } + } + else if (type_fn == VIEW3D_WGT_xform_cage) { + /* pass */ + } + else { + BLI_assert(0); + } +} + /** \} */ @@ -1383,6 +1425,15 @@ static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGrou MAN_ITER_AXES_END; } +static void WIDGETGROUP_manipulator_message_subscribe( + const bContext *C, wmManipulatorGroup *mgroup, struct wmMsgBus *mbus) +{ + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + manipulator_xform_message_subscribe(mgroup, mbus, screen, sa, ar, TRANSFORM_WGT_manipulator); +} + static void WIDGETGROUP_manipulator_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) { ManipulatorGroup *man = mgroup->customdata; @@ -1464,6 +1515,7 @@ void TRANSFORM_WGT_manipulator(wmManipulatorGroupType *wgt) wgt->poll = WIDGETGROUP_manipulator_poll; wgt->setup = WIDGETGROUP_manipulator_setup; wgt->refresh = WIDGETGROUP_manipulator_refresh; + wgt->message_subscribe = WIDGETGROUP_manipulator_message_subscribe; wgt->draw_prepare = WIDGETGROUP_manipulator_draw_prepare; } @@ -1585,6 +1637,15 @@ static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmManipulatorGroup } } +static void WIDGETGROUP_xform_cage_message_subscribe( + const bContext *C, wmManipulatorGroup *mgroup, struct wmMsgBus *mbus) +{ + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + manipulator_xform_message_subscribe(mgroup, mbus, screen, sa, ar, VIEW3D_WGT_xform_cage); +} + static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) { struct XFormCageWidgetGroup *xmgroup = mgroup->customdata; @@ -1613,6 +1674,7 @@ void VIEW3D_WGT_xform_cage(wmManipulatorGroupType *wgt) wgt->poll = WIDGETGROUP_xform_cage_poll; wgt->setup = WIDGETGROUP_xform_cage_setup; wgt->refresh = WIDGETGROUP_xform_cage_refresh; + wgt->message_subscribe = WIDGETGROUP_xform_cage_message_subscribe; wgt->draw_prepare = WIDGETGROUP_xform_cage_draw_prepare; } |