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>2018-05-16 19:41:11 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-05-17 16:57:33 +0300
commitedf6676a77b30290918e60547544bc1a6f7a8838 (patch)
tree26012f315c75686553e6be87b73ad270b98eb01a /source/blender/windowmanager
parent20cc14e2b7551bb043472174b8be79d8aaa4df3d (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.h41
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c11
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c66
-rw-r--r--source/blender/windowmanager/intern/wm_toolsystem.c271
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);
}