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
path: root/source
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
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')
-rw-r--r--source/blender/blenkernel/intern/workspace.c8
-rw-r--r--source/blender/blenloader/intern/readfile.c5
-rw-r--r--source/blender/blenloader/intern/writefile.c1
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c5
-rw-r--r--source/blender/editors/object/object_edit.c4
-rw-r--r--source/blender/editors/physics/particle_edit.c2
-rw-r--r--source/blender/editors/screen/workspace_edit.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c2
-rw-r--r--source/blender/editors/space_topbar/space_topbar.c3
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_ruler.c11
-rw-r--r--source/blender/editors/transform/transform_manipulator_3d.c18
-rw-r--r--source/blender/makesdna/DNA_workspace_types.h46
-rw-r--r--source/blender/makesrna/RNA_enum_types.h1
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt1
-rw-r--r--source/blender/makesrna/intern/makesrna.c6
-rw-r--r--source/blender/makesrna/intern/rna_internal.h2
-rw-r--r--source/blender/makesrna/intern/rna_space.c18
-rw-r--r--source/blender/makesrna/intern/rna_workspace.c132
-rw-r--r--source/blender/makesrna/intern/rna_workspace_api.c90
-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
26 files changed, 599 insertions, 165 deletions
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index 38378f66584..fd316cb9d82 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -171,6 +171,14 @@ void BKE_workspace_free(WorkSpace *workspace)
BLI_freelistN(&workspace->owner_ids);
BLI_freelistN(&workspace->layouts);
+
+ for (bToolRef *tref = workspace->tools.first, *tref_next; tref; tref = tref_next) {
+ tref_next = tref->next;
+ if (tref->runtime) {
+ MEM_freeN(tref->runtime);
+ }
+ }
+ BLI_freelistN(&workspace->tools);
}
/**
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 9618ae432f1..42984cfefaa 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2911,6 +2911,7 @@ static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main
link_list(fd, &workspace->hook_layout_relations);
link_list(fd, &workspace->scene_viewlayer_relations);
link_list(fd, &workspace->owner_ids);
+ link_list(fd, &workspace->tools);
for (WorkSpaceDataRelation *relation = workspace->hook_layout_relations.first;
relation;
@@ -2936,6 +2937,10 @@ static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main
}
}
}
+
+ for (bToolRef *tref = workspace->tools.first; tref; tref = tref->next) {
+ tref->runtime = NULL;
+ }
}
static void lib_link_workspace_instance_hook(FileData *fd, WorkSpaceInstanceHook *hook, ID *id)
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index bb136cb937d..507fe2e082c 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -3598,6 +3598,7 @@ static void write_workspace(WriteData *wd, WorkSpace *workspace)
writelist(wd, DATA, WorkSpaceDataRelation, &workspace->hook_layout_relations);
writelist(wd, DATA, WorkSpaceDataRelation, &workspace->scene_viewlayer_relations);
writelist(wd, DATA, wmOwnerID, &workspace->owner_ids);
+ writelist(wd, DATA, bToolRef, &workspace->tools);
}
/* Keep it last of write_foodata functions. */
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index 2e3d0a9c675..67596ef5c8a 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -420,7 +420,10 @@ static void manipulator_mesh_extrude_orientation_matrix_set(
static bool manipulator_mesh_extrude_poll(const bContext *C, wmManipulatorGroupType *wgt)
{
WorkSpace *workspace = CTX_wm_workspace(C);
- if (!STREQ(workspace->tool.manipulator_group, "MESH_WGT_extrude") ||
+ const bToolKey tkey = { .space_type = SPACE_VIEW3D, .mode = OB_MODE_EDIT};
+ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_find(workspace, &tkey);
+ if ((tref_rt == NULL) ||
+ !STREQ(wgt->idname, tref_rt->manipulator_group) ||
!ED_operator_editmesh_view3d((bContext *)C))
{
WM_manipulator_group_type_unlink_delayed_ptr(wgt);
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index e87a24b3af0..b9a7da02611 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -481,6 +481,8 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op)
WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
+ WM_toolsystem_update_from_context_view3d(C);
+
return OPERATOR_FINISHED;
}
@@ -579,6 +581,8 @@ static int posemode_exec(bContext *C, wmOperator *op)
WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
+ WM_toolsystem_update_from_context_view3d(C);
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index e0427b4797c..6197457293f 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -4527,6 +4527,8 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+ WM_toolsystem_update_from_context_view3d(C);
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index bd4381f4099..fe52e945399 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -201,8 +201,8 @@ bool ED_workspace_change(
BLI_assert(BKE_workspace_view_layer_get(workspace_new, CTX_data_scene(C)) != NULL);
BLI_assert(CTX_wm_workspace(C) == workspace_new);
- WM_toolsystem_unlink(C, workspace_old);
- WM_toolsystem_link(C, workspace_new);
+ WM_toolsystem_unlink_all(C, workspace_old);
+ WM_toolsystem_link_all(C, workspace_new);
return true;
}
@@ -224,7 +224,7 @@ WorkSpace *ED_workspace_duplicate(
bmain, workspace_old->id.name + 2, scene,
BKE_workspace_view_layer_get(workspace_old, scene));
- workspace_new->tool = workspace_old->tool;
+ /* TODO(campbell): tools */
for (WorkSpaceLayout *layout_old = layouts_old->first; layout_old; layout_old = layout_old->next) {
WorkSpaceLayout *layout_new = ED_workspace_layout_duplicate(workspace_new, layout_old, win);
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index cbf755d26b5..6a32fdecfad 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -1136,6 +1136,8 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+ WM_toolsystem_update_from_context_view3d(C);
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 196505c9542..3c3df2067ab 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1252,6 +1252,8 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+ WM_toolsystem_update_from_context_view3d(C);
+
return OPERATOR_FINISHED;
}
@@ -2386,6 +2388,8 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+ WM_toolsystem_update_from_context_view3d(C);
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 048555d3fcc..709d6d4c690 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -5820,6 +5820,8 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+ WM_toolsystem_update_from_context_view3d(C);
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c
index 8cf27d86cfe..4342fa87f89 100644
--- a/source/blender/editors/space_topbar/space_topbar.c
+++ b/source/blender/editors/space_topbar/space_topbar.c
@@ -201,9 +201,10 @@ static void topbar_header_region_message_subscribe(
.user_data = ar,
.notify = ED_region_do_msg_notify_tag_redraw,
};
+
WM_msg_subscribe_rna_prop(
mbus, &workspace->id, workspace,
- WorkSpace, tool_keymap, &msg_sub_value_region_tag_redraw);
+ WorkSpace, tools, &msg_sub_value_region_tag_redraw);
}
static void recent_files_menu_draw(const bContext *UNUSED(C), Menu *menu)
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index fa147ff1226..de2ef45247b 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1017,8 +1017,8 @@ static void view3d_main_region_listener(
static void view3d_main_region_message_subscribe(
const struct bContext *C,
- struct WorkSpace *workspace, struct Scene *UNUSED(scene),
- struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
+ struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
+ struct bScreen *UNUSED(screen), struct ScrArea *sa, struct ARegion *ar,
struct wmMsgBus *mbus)
{
/* Developer note: there are many properties that impact 3D view drawing,
@@ -1091,10 +1091,10 @@ static void view3d_main_region_message_subscribe(
}
}
- if (workspace->tool.spacetype == SPACE_VIEW3D) {
+ {
wmMsgSubscribeValue msg_sub_value_region_tag_refresh = {
.owner = ar,
- .user_data = ar,
+ .user_data = sa,
.notify = WM_toolsystem_do_msg_notify_tag_refresh,
};
WM_msg_subscribe_rna_anon_prop(
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
index 9f69a33861d..d46673b4817 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
@@ -982,8 +982,10 @@ void VIEW3D_WT_ruler_item(wmManipulatorType *wt)
static bool WIDGETGROUP_ruler_poll(const bContext *C, wmManipulatorGroupType *wgt)
{
- WorkSpace *workspace = CTX_wm_workspace(C);
- if (!STREQ(wgt->idname, workspace->tool.manipulator_group)) {
+ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
+ if ((tref_rt == NULL) ||
+ !STREQ(wgt->idname, tref_rt->manipulator_group))
+ {
WM_manipulator_group_type_unlink_delayed_ptr(wgt);
return false;
}
@@ -1030,8 +1032,9 @@ void VIEW3D_WGT_ruler(wmManipulatorGroupType *wgt)
static int view3d_ruler_poll(bContext *C)
{
- WorkSpace *workspace = CTX_wm_workspace(C);
- if (!STREQ(view3d_wgt_ruler_id, workspace->tool.manipulator_group) ||
+ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
+ if ((tref_rt == NULL) ||
+ !STREQ(view3d_wgt_ruler_id, tref_rt->manipulator_group) ||
CTX_wm_region_view3d(C) == NULL)
{
return false;
diff --git a/source/blender/editors/transform/transform_manipulator_3d.c b/source/blender/editors/transform/transform_manipulator_3d.c
index 8257ad595d7..c24291953c8 100644
--- a/source/blender/editors/transform/transform_manipulator_3d.c
+++ b/source/blender/editors/transform/transform_manipulator_3d.c
@@ -1283,8 +1283,14 @@ static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup
/* TODO: support mixing modes again? - it's supported but tool system makes it unobvious. */
man->twtype = 0;
WorkSpace *workspace = CTX_wm_workspace(C);
+ Scene *scene = CTX_data_scene(C);
ScrArea *sa = CTX_wm_area(C);
- wmKeyMap *km = WM_keymap_find_all(C, workspace->tool.keymap, sa->spacetype, RGN_TYPE_WINDOW);
+ const bToolKey tkey = {
+ .space_type = sa->spacetype,
+ .mode = WM_toolsystem_mode_from_spacetype(workspace, scene, NULL, sa->spacetype),
+ };
+ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_find(workspace, &tkey);
+ wmKeyMap *km = WM_keymap_find_all(C, tref_rt->keymap, sa->spacetype, RGN_TYPE_WINDOW);
/* Weak, check first event */
wmKeyMapItem *kmi = km ? km->items.first : NULL;
@@ -1552,8 +1558,10 @@ static bool WIDGETGROUP_manipulator_poll(const struct bContext *C, struct wmMani
return false;
}
- WorkSpace *workspace = CTX_wm_workspace(C);
- if (!STREQ(workspace->tool.manipulator_group, "TRANSFORM_WGT_manipulator")) {
+ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
+ if ((tref_rt == NULL) ||
+ !STREQ(wgt->idname, tref_rt->manipulator_group))
+ {
WM_manipulator_group_type_unlink_delayed_ptr(wgt);
return false;
}
@@ -1596,8 +1604,8 @@ static bool WIDGETGROUP_xform_cage_poll(const bContext *C, wmManipulatorGroupTyp
return false;
}
- WorkSpace *workspace = CTX_wm_workspace(C);
- if (!STREQ(wgt->idname, workspace->tool.manipulator_group)) {
+ bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C);
+ if (!STREQ(wgt->idname, tref_rt->manipulator_group)) {
WM_manipulator_group_type_unlink_delayed_ptr(wgt);
return false;
}
diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h
index 4cc3929b4ea..693e4f672d2 100644
--- a/source/blender/makesdna/DNA_workspace_types.h
+++ b/source/blender/makesdna/DNA_workspace_types.h
@@ -53,16 +53,35 @@
/* Currently testing, allow to disable. */
#define USE_WORKSPACE_TOOL
-typedef struct bToolDef {
+#
+#
+typedef struct bToolRef_Runtime {
/* One of these must be defined. */
char keymap[64];
char manipulator_group[64];
char data_block[64];
-
- int spacetype;
/* index when a tool is a member of a group */
- int index;
-} bToolDef;
+ int index;
+} bToolRef_Runtime;
+
+
+/* Stored per mode. */
+typedef struct bToolRef {
+ struct bToolRef *next, *prev;
+ char idname[64];
+
+ /** bToolKey (spacetype, mode), used in 'WM_api.h' */
+ int space_type;
+ /**
+ * Value depends ont the 'space_type', object mode for 3D view, image editor has own mode too.
+ * RNA needs to handle using item function.
+ */
+ int mode;
+
+ /** Variables needed to operate the tool. */
+ bToolRef_Runtime *runtime;
+} bToolRef;
+
/**
* \brief Wrapper for bScreen.
@@ -97,13 +116,22 @@ typedef struct WorkSpace {
/* Feature tagging (use for addons) */
ListBase owner_ids DNA_PRIVATE_WORKSPACE_READ_WRITE; /* wmOwnerID */
- int pad;
- int flags DNA_PRIVATE_WORKSPACE; /* enum eWorkSpaceFlags */
+ struct ViewLayer *view_layer DNA_DEPRECATED;
/* should be: '#ifdef USE_WORKSPACE_TOOL'. */
- bToolDef tool;
- struct ViewLayer *view_layer DNA_DEPRECATED;
+ /** List of #bToolRef */
+ ListBase tools;
+
+ /**
+ * BAD DESIGN WARNING:
+ * This is a workaround for the topbar not knowing which tools spac */
+ char tools_space_type;
+ /** Type is different for each space-type. */
+ char tools_mode;
+
+ char _pad[2];
+ int flags DNA_PRIVATE_WORKSPACE; /* enum eWorkSpaceFlags */
} WorkSpace;
/* internal struct, but exported for read/write */
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index d5b2493078c..447dc4ce289 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -56,6 +56,7 @@ extern const EnumPropertyItem rna_enum_curve_fit_method_items[];
extern const EnumPropertyItem rna_enum_mesh_select_mode_items[];
extern const EnumPropertyItem rna_enum_mesh_delimit_mode_items[];
extern const EnumPropertyItem rna_enum_space_type_items[];
+extern const EnumPropertyItem rna_enum_space_image_mode_items[];
extern const EnumPropertyItem rna_enum_region_type_items[];
extern const EnumPropertyItem rna_enum_object_modifier_type_items[];
extern const EnumPropertyItem rna_enum_constraint_type_items[];
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 7bd5ad2b959..c62e8ed4da8 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -122,6 +122,7 @@ set(APISRC
rna_vfont_api.c
rna_wm_api.c
rna_wm_manipulator_api.c
+ rna_workspace_api.c
)
string(REGEX REPLACE "rna_([a-zA-Z0-9_-]*).c" "${CMAKE_CURRENT_BINARY_DIR}/rna_\\1_gen.c" GENSRC "${DEFSRC}")
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 0b2efe27059..4daf8b6a965 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -2831,6 +2831,10 @@ static void rna_generate_struct_prototypes(FILE *f)
if (dp->prop->type == PROP_POINTER) {
int a, found = 0;
const char *struct_name = rna_parameter_type_name(dp->prop);
+ if (struct_name == NULL) {
+ printf("No struct found for property '%s'\n", dp->prop->identifier);
+ exit(1);
+ }
for (a = 0; a < all_structures; a++) {
if (STREQ(struct_name, structures[a])) {
@@ -3404,7 +3408,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_vfont.c", "rna_vfont_api.c", RNA_def_vfont},
{"rna_wm.c", "rna_wm_api.c", RNA_def_wm},
{"rna_wm_manipulator.c", "rna_wm_manipulator_api.c", RNA_def_wm_manipulator},
- {"rna_workspace.c", NULL, RNA_def_workspace},
+ {"rna_workspace.c", "rna_workspace_api.c", RNA_def_workspace},
{"rna_world.c", NULL, RNA_def_world},
{"rna_movieclip.c", NULL, RNA_def_movieclip},
{"rna_tracking.c", NULL, RNA_def_tracking},
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 11ad39a2dd1..ce16cb69bbd 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -342,6 +342,8 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_api_sequence_elements(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_api_sound(struct StructRNA *srna);
void RNA_api_vfont(struct StructRNA *srna);
+void RNA_api_workspace(struct StructRNA *srna);
+void RNA_api_workspace_tool(struct StructRNA *srna);
/* main collection functions */
void RNA_def_main_cameras(BlenderRNA *brna, PropertyRNA *cprop);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 12bb4dd0617..3ce799dfb88 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -103,6 +103,15 @@ const EnumPropertyItem rna_enum_space_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
+
+const EnumPropertyItem rna_enum_space_image_mode_items[] = {
+ {SI_MODE_VIEW, "VIEW", ICON_FILE_IMAGE, "View", "View the image and UV edit in mesh editmode"},
+ {SI_MODE_PAINT, "PAINT", ICON_TPAINT_HLT, "Paint", "2D image painting mode"},
+ {SI_MODE_MASK, "MASK", ICON_MOD_MASK, "Mask", "Mask editing"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+
#define V3D_S3D_CAMERA_LEFT {STEREO_LEFT_ID, "LEFT", ICON_RESTRICT_RENDER_OFF, "Left", ""},
#define V3D_S3D_CAMERA_RIGHT {STEREO_RIGHT_ID, "RIGHT", ICON_RESTRICT_RENDER_OFF, "Right", ""},
#define V3D_S3D_CAMERA_S3D {STEREO_3D_ID, "S3D", ICON_CAMERA_STEREO, "3D", ""},
@@ -2950,13 +2959,6 @@ static void rna_def_space_buttons(BlenderRNA *brna)
static void rna_def_space_image(BlenderRNA *brna)
{
- static const EnumPropertyItem image_space_mode_items[] = {
- {SI_MODE_VIEW, "VIEW", ICON_FILE_IMAGE, "View", "View the image and UV edit in mesh editmode"},
- {SI_MODE_PAINT, "PAINT", ICON_TPAINT_HLT, "Paint", "2D image painting mode"},
- {SI_MODE_MASK, "MASK", ICON_MOD_MASK, "Mask", "Mask editing"},
- {0, NULL, 0, NULL, NULL}
- };
-
StructRNA *srna;
PropertyRNA *prop;
@@ -3037,7 +3039,7 @@ static void rna_def_space_image(BlenderRNA *brna)
/* mode */
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mode");
- RNA_def_property_enum_items(prop, image_space_mode_items);
+ RNA_def_property_enum_items(prop, rna_enum_space_image_mode_items);
RNA_def_property_ui_text(prop, "Mode", "Editing context being displayed");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, "rna_SpaceImageEditor_mode_update");
diff --git a/source/blender/makesrna/intern/rna_workspace.c b/source/blender/makesrna/intern/rna_workspace.c
index b82ca145f5f..485cb298dae 100644
--- a/source/blender/makesrna/intern/rna_workspace.c
+++ b/source/blender/makesrna/intern/rna_workspace.c
@@ -49,6 +49,7 @@
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "RNA_access.h"
@@ -107,6 +108,42 @@ static void rna_WorkSpace_owner_ids_clear(
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NA_REMOVED, workspace);
}
+static bToolRef *rna_WorkSpace_tools_from_tkey(WorkSpace *workspace, const bToolKey *tkey, bool create)
+{
+ if (create) {
+ bToolRef *tref;
+ WM_toolsystem_ref_ensure(workspace, tkey, &tref);
+ return tref;
+ }
+ return WM_toolsystem_ref_find(workspace, tkey);
+}
+
+static bToolRef *rna_WorkSpace_tools_from_space_view3d_mode(
+ WorkSpace *workspace, int mode, int create)
+{
+ return rna_WorkSpace_tools_from_tkey(workspace, &(bToolKey){ .space_type = SPACE_VIEW3D, .mode = mode}, create);
+}
+
+static bToolRef *rna_WorkSpace_tools_from_space_image_mode(
+ WorkSpace *workspace, int mode, int create)
+{
+ return rna_WorkSpace_tools_from_tkey(workspace, &(bToolKey){ .space_type = SPACE_IMAGE, .mode = mode}, create);
+}
+
+const EnumPropertyItem *rna_WorkSpace_tools_mode_itemf(
+ bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
+{
+ WorkSpace *workspace = ptr->id.data;
+
+ switch (workspace->tools_space_type) {
+ case SPACE_VIEW3D:
+ return rna_enum_object_mode_items;
+ case SPACE_IMAGE:
+ return rna_enum_space_image_mode_items;
+ }
+ return DummyRNA_NULL_items;
+}
+
#else /* RNA_RUNTIME */
static void rna_def_workspace_owner(BlenderRNA *brna)
@@ -159,6 +196,56 @@ static void rna_def_workspace_owner_ids(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Remove all tags");
}
+static void rna_def_workspace_tool(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "WorkspaceTool", NULL);
+ RNA_def_struct_sdna(srna, "bToolRef");
+ RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
+ RNA_def_struct_ui_text(srna, "Work Space Tool", "");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "idname");
+ RNA_def_property_ui_text(prop, "Name", "");
+ RNA_def_struct_name_property(srna, prop);
+
+ RNA_api_workspace_tool(srna);
+}
+
+static void rna_def_workspace_tools(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "wmTools");
+ srna = RNA_def_struct(brna, "wmTools", NULL);
+ RNA_def_struct_sdna(srna, "WorkSpace");
+ RNA_def_struct_ui_text(srna, "WorkSpace UI Tags", "");
+
+ /* add owner_id */
+ func = RNA_def_function(srna, "from_space_view3d_mode", "rna_WorkSpace_tools_from_space_view3d_mode");
+ RNA_def_function_ui_description(func, "");
+ parm = RNA_def_enum(func, "mode", rna_enum_object_mode_items, 0, "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_boolean(func, "create", false, "Create", "");
+ /* return type */
+ parm = RNA_def_pointer(func, "result", "WorkspaceTool", "", "");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "from_space_image_mode", "rna_WorkSpace_tools_from_space_image_mode");
+ RNA_def_function_ui_description(func, "");
+ parm = RNA_def_enum(func, "mode", rna_enum_space_image_mode_items, 0, "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_boolean(func, "create", false, "Create", "");
+ /* return type */
+ parm = RNA_def_pointer(func, "result", "WorkspaceTool", "", "");
+ RNA_def_function_return(func, parm);
+}
+
static void rna_def_workspace(BlenderRNA *brna)
{
StructRNA *srna;
@@ -177,36 +264,29 @@ static void rna_def_workspace(BlenderRNA *brna)
"rna_workspace_screens_item_get", NULL, NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Screens", "Screen layouts of a workspace");
- prop = RNA_def_property(srna, "tool_keymap", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "tool.keymap");
- RNA_def_property_ui_text(prop, "Active Tool", "Currently active tool keymap");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
- prop = RNA_def_property(srna, "tool_manipulator_group", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "tool.manipulator_group");
- RNA_def_property_ui_text(prop, "Active Tool", "Currently active tool manipulator");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
- prop = RNA_def_property(srna, "tool_data_block", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "tool.data_block");
- RNA_def_property_ui_text(prop, "Active Tool", "Currently active data-block");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ prop = RNA_def_property(srna, "owner_ids", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "wmOwnerID");
+ RNA_def_property_ui_text(prop, "UI Tags", "");
+ rna_def_workspace_owner_ids(brna, prop);
- prop = RNA_def_property(srna, "tool_index", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "tool.index");
- RNA_def_property_ui_text(prop, "Active Tool Index", "Tool group index");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ prop = RNA_def_property(srna, "tools", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "tools", NULL);
+ RNA_def_property_struct_type(prop, "WorkspaceTool");
+ RNA_def_property_ui_text(prop, "Tools", "");
+ rna_def_workspace_tools(brna, prop);
- prop = RNA_def_property(srna, "tool_space_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "tool.spacetype");
+ prop = RNA_def_property(srna, "tools_space_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "tools_space_type");
RNA_def_property_enum_items(prop, rna_enum_space_type_items);
RNA_def_property_ui_text(prop, "Active Tool Space", "Tool space type");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- prop = RNA_def_property(srna, "owner_ids", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "wmOwnerID");
- RNA_def_property_ui_text(prop, "UI Tags", "");
- rna_def_workspace_owner_ids(brna, prop);
+ prop = RNA_def_property(srna, "tools_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "tools_mode");
+ RNA_def_property_enum_items(prop, rna_enum_object_mode_items); /* value is placeholder, itemf is used. */
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_WorkSpace_tools_mode_itemf");
+ RNA_def_property_ui_text(prop, "Active Tool Space", "Tool mode");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
#if 0
prop = RNA_def_property(srna, "object_mode", PROP_ENUM, PROP_NONE);
@@ -221,11 +301,15 @@ static void rna_def_workspace(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use UI Tags",
"Filter the UI by tags");
RNA_def_property_update(prop, 0, "rna_window_update_all");
+
+ RNA_api_workspace(srna);
}
void RNA_def_workspace(BlenderRNA *brna)
{
rna_def_workspace_owner(brna);
+ rna_def_workspace_tool(brna);
+
rna_def_workspace(brna);
}
diff --git a/source/blender/makesrna/intern/rna_workspace_api.c b/source/blender/makesrna/intern/rna_workspace_api.c
new file mode 100644
index 00000000000..4b0e2b5918e
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_workspace_api.c
@@ -0,0 +1,90 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/makesrna/intern/rna_workspace_api.c
+ * \ingroup RNA
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "BLI_utildefines.h"
+
+#include "RNA_define.h"
+
+#include "DNA_object_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "rna_internal.h" /* own include */
+
+#ifdef RNA_RUNTIME
+
+static void rna_WorkspaceTool_setup(
+ ID *id,
+ bToolRef *tref,
+ bContext *C,
+ const char *name,
+ /* Args for: 'bToolRef_Runtime'. */
+ const char *keymap,
+ const char *manipulator_group,
+ const char *data_block,
+ int index)
+{
+ bToolRef_Runtime tref_rt = {0};
+
+ STRNCPY(tref_rt.keymap, keymap);
+ STRNCPY(tref_rt.manipulator_group, manipulator_group);
+ STRNCPY(tref_rt.data_block, data_block);
+ tref_rt.index = index;
+
+ WM_toolsystem_ref_set_from_runtime(C, (WorkSpace *)id, tref, &tref_rt, name);
+}
+
+#else
+
+void RNA_api_workspace(StructRNA *UNUSED(srna))
+{
+ /* FunctionRNA *func; */
+ /* PropertyRNA *parm; */
+}
+
+void RNA_api_workspace_tool(StructRNA *srna)
+{
+ PropertyRNA *parm;
+ FunctionRNA *func;
+
+ func = RNA_def_function(srna, "setup", "rna_WorkspaceTool_setup");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_CONTEXT);
+ RNA_def_function_ui_description(func, "Set the tool settings");
+
+ parm = RNA_def_string(func, "name", NULL, KMAP_MAX_NAME, "Name", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ /* 'bToolRef_Runtime' */
+ RNA_def_string(func, "keymap", NULL, KMAP_MAX_NAME, "Key Map", "");
+ RNA_def_string(func, "manipulator_group", NULL, MAX_NAME, "Manipulator Group", "");
+ RNA_def_string(func, "data_block", NULL, MAX_NAME, "Data Block", "");
+ RNA_def_int(func, "index", 0, INT_MIN, INT_MAX, "Index", "", INT_MIN, INT_MAX);
+}
+
+#endif
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);
}