diff options
author | Campbell Barton <ideasman42@gmail.com> | 2018-05-16 19:41:11 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2018-05-17 16:57:33 +0300 |
commit | edf6676a77b30290918e60547544bc1a6f7a8838 (patch) | |
tree | 26012f315c75686553e6be87b73ad270b98eb01a /source/blender/windowmanager | |
parent | 20cc14e2b7551bb043472174b8be79d8aaa4df3d (diff) |
Tool System: per space/mode tool support
This patch adds support for:
- Per space-type tools (3D view and edit).
- Per mode tools (object, edit, weight-paint .. etc).
The top-bar shows the last activated tools options, this is a design
issue with using a global topbar to show per-space settings.
See D3395
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 41 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 11 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 66 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_toolsystem.c | 271 |
4 files changed, 284 insertions, 105 deletions
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 9176385c40d..5562e7880fa 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -47,6 +47,7 @@ extern "C" { #endif struct bContext; +struct bToolRef_Runtime; struct GHashIterator; struct IDProperty; struct wmEvent; @@ -595,13 +596,45 @@ bool WM_event_is_ime_switch(const struct wmEvent *event); #endif /* wm_toolsystem.c */ -void WM_toolsystem_unlink(struct bContext *C, struct WorkSpace *workspace); -void WM_toolsystem_link(struct bContext *C, struct WorkSpace *workspace); -void WM_toolsystem_refresh(struct bContext *C, struct WorkSpace *workspace); -void WM_toolsystem_set(struct bContext *C, const struct bToolDef *tool); +/* Values that define a categoey of active tool. */ +typedef struct bToolKey { int space_type; int mode; } bToolKey; + +struct bToolRef *WM_toolsystem_ref_from_context(struct bContext *C); +struct bToolRef *WM_toolsystem_ref_find(struct WorkSpace *workspace, const bToolKey *tkey); +bool WM_toolsystem_ref_ensure( + struct WorkSpace *workspace, const bToolKey *tkey, + struct bToolRef **r_tref); + +struct bToolRef_Runtime *WM_toolsystem_runtime_from_context(struct bContext *C); +struct bToolRef_Runtime *WM_toolsystem_runtime_find(struct WorkSpace *workspace, const bToolKey *tkey); + +void WM_toolsystem_unlink(struct bContext *C, struct WorkSpace *workspace, const bToolKey *tkey); +void WM_toolsystem_link(struct bContext *C, struct WorkSpace *workspace, const bToolKey *tkey); +void WM_toolsystem_refresh(struct bContext *C, struct WorkSpace *workspace, const bToolKey *tkey); + +void WM_toolsystem_unlink_all(struct bContext *C, struct WorkSpace *workspace); +void WM_toolsystem_link_all(struct bContext *C, struct WorkSpace *workspace); +void WM_toolsystem_refresh_all(struct bContext *C, struct WorkSpace *workspace); + +void WM_toolsystem_ref_set_from_runtime( + struct bContext *C, struct WorkSpace *workspace, struct bToolRef *tref, + const struct bToolRef_Runtime *tool, const char *idname); + void WM_toolsystem_init(struct bContext *C); +int WM_toolsystem_mode_from_spacetype( + struct WorkSpace *workspace, struct Scene *scene, struct ScrArea *sa, + int space_type); +bool WM_toolsystem_key_from_context( + struct WorkSpace *workspace, struct Scene *scene, struct ScrArea *sa, + bToolKey *tkey); +void WM_toolsystem_update_from_context( + struct bContext *C, + struct WorkSpace *workspace, struct Scene *scene, struct ScrArea *sa); + +void WM_toolsystem_update_from_context_view3d(struct bContext *C); + bool WM_toolsystem_active_tool_is_brush(const struct bContext *C); void WM_toolsystem_do_msg_notify_tag_refresh( diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 7963bf16534..8bbbd1b60df 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2875,11 +2875,14 @@ void wm_event_do_handlers(bContext *C) wmEventHandler sneaky_handler = {NULL}; if (ar->regiontype == RGN_TYPE_WINDOW) { WorkSpace *workspace = WM_window_get_active_workspace(win); - if (workspace->tool.keymap[0] && - workspace->tool.spacetype == sa->spacetype) - { + const bToolKey tkey = { + .space_type = sa->spacetype, + .mode = WM_toolsystem_mode_from_spacetype(workspace, win->scene, sa, sa->spacetype), + }; + bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_find(workspace, &tkey); + if (tref_rt && tref_rt->keymap[0]) { wmKeyMap *km = WM_keymap_find_all( - C, workspace->tool.keymap, sa->spacetype, RGN_TYPE_WINDOW); + C, tref_rt->keymap, sa->spacetype, RGN_TYPE_WINDOW); if (km != NULL) { sneaky_handler.keymap = km; /* Handle widgets first. */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index a154f6b83ea..22133ae1602 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1826,69 +1826,6 @@ static void WM_OT_operator_defaults(wmOperatorType *ot) ot->flag = OPTYPE_INTERNAL; } -#ifdef USE_WORKSPACE_TOOL -/* ***************** Set Active Tool ************************* */ - -/* Developers note: in it's current form this doesn't need to be an operator, - * keep this as-is for now since it may end up setting an active key-map. - */ - -static int wm_operator_tool_set_exec(bContext *C, wmOperator *op) -{ - ScrArea *sa = CTX_wm_area(C); - - bToolDef tool_def = {{0}}; - - { - PropertyRNA *prop = RNA_struct_find_property(op->ptr, "space_type"); - if (RNA_property_is_set(op->ptr, prop)) { - tool_def.spacetype = RNA_property_enum_get(op->ptr, prop); - } - else { - if (sa == NULL) { - BKE_report(op->reports, RPT_ERROR, "Space type not set"); - return OPERATOR_CANCELLED; - } - tool_def.spacetype = sa->spacetype; - } - } - - tool_def.index = RNA_int_get(op->ptr, "index"); - RNA_string_get(op->ptr, "keymap", tool_def.keymap); - RNA_string_get(op->ptr, "manipulator_group", tool_def.manipulator_group); - RNA_string_get(op->ptr, "data_block", tool_def.data_block); - - WM_toolsystem_set(C, &tool_def); - - /* For some reason redraw fails with menus (even though 'ar' isn't the menu's region). */ - if (sa) { - ED_area_tag_redraw(sa); - } - else { - WM_event_add_notifier(C, NC_WINDOW, NULL); - } - - return OPERATOR_FINISHED; -} - -static void WM_OT_tool_set(wmOperatorType *ot) -{ - ot->name = "Set Active Tool"; - ot->idname = "WM_OT_tool_set"; - ot->description = "Set the active tool"; - - ot->exec = wm_operator_tool_set_exec; - - ot->flag = OPTYPE_INTERNAL; - - RNA_def_enum(ot->srna, "space_type", rna_enum_space_type_items + 1, SPACE_EMPTY, "Space Type", ""); - RNA_def_string(ot->srna, "keymap", NULL, KMAP_MAX_NAME, "Key Map", ""); - RNA_def_string(ot->srna, "manipulator_group", NULL, MAX_NAME, "Manipulator Group", ""); - RNA_def_string(ot->srna, "data_block", NULL, MAX_NAME, "Data Block", ""); - RNA_def_int(ot->srna, "index", 0, INT_MIN, INT_MAX, "Index", "", INT_MIN, INT_MAX); -} -#endif /* USE_WORKSPACE_TOOL */ - /* ***************** Splash Screen ************************* */ static void wm_block_splash_close(bContext *C, void *arg_block, void *UNUSED(arg)) @@ -3765,9 +3702,6 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_memory_statistics); WM_operatortype_append(WM_OT_debug_menu); WM_operatortype_append(WM_OT_operator_defaults); -#ifdef USE_WORKSPACE_TOOL - WM_operatortype_append(WM_OT_tool_set); -#endif WM_operatortype_append(WM_OT_splash); WM_operatortype_append(WM_OT_search_menu); WM_operatortype_append(WM_OT_call_menu); diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c index c351d0fd849..24b902a6a92 100644 --- a/source/blender/windowmanager/intern/wm_toolsystem.c +++ b/source/blender/windowmanager/intern/wm_toolsystem.c @@ -28,13 +28,18 @@ #include "CLG_log.h" +#include "MEM_guardedalloc.h" + #include "BLI_utildefines.h" #include "BLI_string.h" +#include "BLI_listbase.h" #include "DNA_ID.h" #include "DNA_scene_types.h" +#include "DNA_space_types.h" #include "DNA_windowmanager_types.h" #include "DNA_workspace_types.h" +#include "DNA_object_types.h" #include "BKE_context.h" #include "BKE_library.h" @@ -48,16 +53,80 @@ #include "WM_types.h" #include "WM_message.h" -void WM_toolsystem_unlink(bContext *C, WorkSpace *workspace) + +/* -------------------------------------------------------------------- */ +/** \name Tool Reference API + * \{ */ + +struct bToolRef *WM_toolsystem_ref_from_context(struct bContext *C) { - Main *bmain = CTX_data_main(C); - wmWindowManager *wm = bmain->wm.first; + WorkSpace *workspace = CTX_wm_workspace(C); + Scene *scene = CTX_data_scene(C); + ScrArea *sa = CTX_wm_area(C); + const bToolKey tkey = { + .space_type = sa->spacetype, + .mode = WM_toolsystem_mode_from_spacetype(workspace, scene, sa, sa->spacetype), + }; + return WM_toolsystem_ref_find(workspace, &tkey); +} + +struct bToolRef_Runtime *WM_toolsystem_runtime_from_context(struct bContext *C) +{ + bToolRef *tref = WM_toolsystem_ref_from_context(C); + return tref ? tref->runtime : NULL; +} + +bToolRef *WM_toolsystem_ref_find(WorkSpace *workspace, const bToolKey *tkey) +{ + LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { + if ((tref->space_type == tkey->space_type) && + (tref->mode == tkey->mode)) + { + return tref; + } + } + return NULL; +} + +bToolRef_Runtime *WM_toolsystem_runtime_find(WorkSpace *workspace, const bToolKey *tkey) +{ + bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); + return tref ? tref->runtime : NULL; +} + +bool WM_toolsystem_ref_ensure( + struct WorkSpace *workspace, const bToolKey *tkey, + bToolRef **r_tref) +{ + bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); + if (tref) { + *r_tref = tref; + return false; + } + tref = MEM_callocN(sizeof(*tref), __func__); + BLI_addhead(&workspace->tools, tref); + tref->space_type = tkey->space_type; + tref->mode = tkey->mode; + *r_tref = tref; + return true; +} + +/** \} */ + + +static void toolsystem_unlink_ref(bContext *C, WorkSpace *workspace, bToolRef *tref) +{ + bToolRef_Runtime *tref_rt = tref->runtime; - if (workspace->tool.manipulator_group[0]) { - wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_find(workspace->tool.manipulator_group, false); + if (tref_rt->manipulator_group[0]) { + wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_find(tref_rt->manipulator_group, false); if (wgt != NULL) { bool found = false; + /* TODO(campbell) */ + Main *bmain = CTX_data_main(C); +#if 0 + wmWindowManager *wm = bmain->wm.first; /* Check another workspace isn't using this tool. */ for (wmWindow *win = wm->windows.first; win; win = win->next) { const WorkSpace *workspace_iter = WM_window_get_active_workspace(win); @@ -68,7 +137,9 @@ void WM_toolsystem_unlink(bContext *C, WorkSpace *workspace) } } } - +#else + UNUSED_VARS(workspace); +#endif if (!found) { wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure(&wgt->mmap_params); WM_manipulatormaptype_group_unlink(C, bmain, mmap_type, wgt); @@ -76,11 +147,19 @@ void WM_toolsystem_unlink(bContext *C, WorkSpace *workspace) } } } +void WM_toolsystem_unlink(bContext *C, WorkSpace *workspace, const bToolKey *tkey) +{ + bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); + if (tref && tref->runtime) { + toolsystem_unlink_ref(C, workspace, tref); + } +} -void WM_toolsystem_link(bContext *C, WorkSpace *workspace) +static void toolsystem_ref_link(bContext *C, WorkSpace *workspace, bToolRef *tref) { - if (workspace->tool.manipulator_group[0]) { - const char *idname = workspace->tool.manipulator_group; + bToolRef_Runtime *tref_rt = tref->runtime; + if (tref_rt->manipulator_group[0]) { + const char *idname = tref_rt->manipulator_group; wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_find(idname, false); if (wgt != NULL) { WM_manipulator_group_type_ensure_ptr(wgt); @@ -90,11 +169,11 @@ void WM_toolsystem_link(bContext *C, WorkSpace *workspace) } } - if (workspace->tool.data_block[0]) { + if (tref_rt->data_block[0]) { Main *bmain = CTX_data_main(C); /* Currently only brush data-blocks supported. */ - struct Brush *brush = (struct Brush *)BKE_libblock_find_name(ID_BR, workspace->tool.data_block); + struct Brush *brush = (struct Brush *)BKE_libblock_find_name(ID_BR, tref_rt->data_block); if (brush) { wmWindowManager *wm = bmain->wm.first; @@ -113,34 +192,82 @@ void WM_toolsystem_link(bContext *C, WorkSpace *workspace) } } } +void WM_toolsystem_link(bContext *C, WorkSpace *workspace, const bToolKey *tkey) +{ + bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); + if (tref) { + toolsystem_ref_link(C, workspace, tref); + } +} -void WM_toolsystem_refresh(bContext *C, WorkSpace *workspace) +static void toolsystem_refresh_ref(bContext *C, WorkSpace *workspace, bToolRef *tref) +{ + /* currently same operation. */ + toolsystem_ref_link(C, workspace, tref); +} +void WM_toolsystem_refresh(bContext *C, WorkSpace *workspace, const bToolKey *tkey) { - WM_toolsystem_link(C, workspace); + bToolRef *tref = WM_toolsystem_ref_find(workspace, tkey); + if (tref) { + toolsystem_refresh_ref(C, workspace, tref); + } } -void WM_toolsystem_set(bContext *C, const bToolDef *tool) +/* Operate on all active tools. */ +void WM_toolsystem_unlink_all(struct bContext *C, struct WorkSpace *workspace) { - WorkSpace *workspace = CTX_wm_workspace(C); + LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { + if (tref->runtime) { + toolsystem_unlink_ref(C, workspace, tref); + } + } +} +void WM_toolsystem_link_all(struct bContext *C, struct WorkSpace *workspace) +{ + LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { + if (tref->runtime) { + toolsystem_ref_link(C, workspace, tref); + } + } +} +void WM_toolsystem_refresh_all(struct bContext *C, struct WorkSpace *workspace) +{ + LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { + if (tref->runtime) { + toolsystem_refresh_ref(C, workspace, tref); + } + } +} + +void WM_toolsystem_ref_set_from_runtime( + struct bContext *C, struct WorkSpace *workspace, bToolRef *tref, + const bToolRef_Runtime *tref_rt, const char *idname) +{ + if (tref->runtime) { + toolsystem_unlink_ref(C, workspace, tref); + } - WM_toolsystem_unlink(C, workspace); + STRNCPY(tref->idname, idname); - workspace->tool.index = tool->index; - workspace->tool.spacetype = tool->spacetype; + /* BAD DESIGN WARNING: used for topbar. */ + workspace->tools_space_type = tref->space_type; + workspace->tools_mode = tref->mode; - if (&workspace->tool != tool) { - STRNCPY(workspace->tool.keymap, tool->keymap); - STRNCPY(workspace->tool.manipulator_group, tool->manipulator_group); - STRNCPY(workspace->tool.data_block, tool->data_block); - workspace->tool.spacetype = tool->spacetype; + if (tref->runtime == NULL) { + tref->runtime = MEM_callocN(sizeof(*tref->runtime), __func__); } - WM_toolsystem_link(C, workspace); + if (tref_rt != tref->runtime) { + *tref->runtime = *tref_rt; + } + toolsystem_ref_link(C, workspace, tref); + + /* TODO(campbell): fix message. */ { struct wmMsgBus *mbus = CTX_wm_message_bus(C); WM_msg_publish_rna_prop( - mbus, &workspace->id, workspace, WorkSpace, tool_keymap); + mbus, &workspace->id, workspace, WorkSpace, tools); } } @@ -151,8 +278,84 @@ void WM_toolsystem_init(bContext *C) for (wmWindow *win = wm->windows.first; win; win = win->next) { WorkSpace *workspace = WM_window_get_active_workspace(win); - WM_toolsystem_link(C, workspace); + WM_toolsystem_link_all(C, workspace); + } +} + +int WM_toolsystem_mode_from_spacetype( + WorkSpace *workspace, Scene *scene, ScrArea *sa, + int spacetype) +{ + int mode = -1; + switch (spacetype) { + case SPACE_VIEW3D: + { + /* 'sa' may be NULL in this case. */ + ViewLayer *view_layer = BKE_workspace_view_layer_get(workspace, scene); + Object *obact = OBACT(view_layer); + mode = obact ? obact->mode : OB_MODE_OBJECT; + break; + } + case SPACE_IMAGE: + { + SpaceImage *sima = sa->spacedata.first; + mode = sima->mode; + break; + } } + return mode; +} + +bool WM_toolsystem_key_from_context( + WorkSpace *workspace, Scene *scene, ScrArea *sa, + bToolKey *tkey) +{ + int space_type = SPACE_EMPTY; + int mode = -1; + + if (sa != NULL) { + space_type = sa->spacetype; + mode = WM_toolsystem_mode_from_spacetype(workspace, scene, sa, space_type); + } + + if (mode != -1) { + tkey->space_type = space_type; + tkey->mode = mode; + return true; + } + return false; +} + +/** + * Run after changing modes. + */ +static void toolsystem_update_with_toolref( + bContext *C, WorkSpace *workspace, const bToolKey *tkey, const char *default_tool) +{ + bToolRef *tref; + if (WM_toolsystem_ref_ensure(workspace, tkey, &tref)) { + STRNCPY(tref->idname, default_tool); + } + + wmOperatorType *ot = WM_operatortype_find("WM_OT_tool_set_by_name", false); + PointerRNA op_props; + WM_operator_properties_create_ptr(&op_props, ot); + RNA_string_set(&op_props, "name", tref->idname); + RNA_enum_set(&op_props, "space_type", tkey->space_type); + WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props); + WM_operator_properties_free(&op_props); +} + +void WM_toolsystem_update_from_context_view3d(bContext *C) +{ + WorkSpace *workspace = CTX_wm_workspace(C); + Scene *scene = CTX_data_scene(C); + int space_type = SPACE_VIEW3D; + const bToolKey tkey = { + .space_type = space_type, + .mode = WM_toolsystem_mode_from_spacetype(workspace, scene, NULL, space_type), + }; + toolsystem_update_with_toolref(C, workspace, &tkey, "Cursor"); } /** @@ -160,15 +363,21 @@ void WM_toolsystem_init(bContext *C) */ bool WM_toolsystem_active_tool_is_brush(const bContext *C) { - WorkSpace *workspace = CTX_wm_workspace(C); - /* Will need to become more comprehensive, for now check tool data-block. */ - return workspace->tool.data_block[0] != '\0'; + bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C); + return tref_rt->data_block[0] != '\0'; } /* Follow wmMsgNotifyFn spec */ void WM_toolsystem_do_msg_notify_tag_refresh( - bContext *C, wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *UNUSED(msg_val)) + bContext *C, wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val) { WorkSpace *workspace = CTX_wm_workspace(C); - WM_toolsystem_refresh(C, workspace); + Scene *scene = CTX_data_scene(C); + ScrArea *sa = msg_val->user_data; + int space_type = sa->spacetype; + const bToolKey tkey = { + .space_type = space_type, + .mode = WM_toolsystem_mode_from_spacetype(workspace, scene, sa, sa->spacetype), + }; + WM_toolsystem_refresh(C, workspace, &tkey); } |