Tool System: per space/mode tool support
authorCampbell Barton <ideasman42@gmail.com>
Wed, 16 May 2018 16:41:11 +0000 (18:41 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 17 May 2018 13:57:33 +0000 (15:57 +0200)
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

29 files changed:
release/scripts/startup/bl_operators/wm.py
release/scripts/startup/bl_ui/space_toolsystem_common.py
release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
source/blender/blenkernel/intern/workspace.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/mesh/editmesh_extrude.c
source/blender/editors/object/object_edit.c
source/blender/editors/physics/particle_edit.c
source/blender/editors/screen/workspace_edit.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/space_topbar/space_topbar.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/editors/space_view3d/view3d_manipulator_ruler.c
source/blender/editors/transform/transform_manipulator_3d.c
source/blender/makesdna/DNA_workspace_types.h
source/blender/makesrna/RNA_enum_types.h
source/blender/makesrna/intern/CMakeLists.txt
source/blender/makesrna/intern/makesrna.c
source/blender/makesrna/intern/rna_internal.h
source/blender/makesrna/intern/rna_space.c
source/blender/makesrna/intern/rna_workspace.c
source/blender/makesrna/intern/rna_workspace_api.c [new file with mode: 0644]
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_operators.c
source/blender/windowmanager/intern/wm_toolsystem.c

index a9d766b29e28e8aedf66909167972e0c9c10751c..970eff34026806beb686d510ec5ad6873dfa192c 100644 (file)
@@ -2335,10 +2335,21 @@ class WM_OT_tool_set_by_name(Operator):
             name="Text",
             description="Display name of the tool",
             )
+    space_type = EnumProperty(
+            name="Type",
+            items=tuple(
+                (e.identifier, e.name, "", e. value)
+                for e in bpy.types.Space.bl_rna.properties["type"].enum_items
+            ),
+            default='EMPTY',
+            )
 
     def execute(self, context):
         from bl_ui.space_toolsystem_common import activate_by_name
-        if activate_by_name(context, context.space_data.type, self.name):
+        space_type = self.space_type
+        if space_type == 'EMPTY':
+            space_type = context.space_data.type
+        if activate_by_name(context, space_type, self.name):
             return {'FINISHED'}
         else:
             self.report({'WARNING'}, f"Tool {self.name!r} not found.")
index b58bff7cf32ab221d1ab11c61585a69918e39105..ad5c970a6d515cd9ea2b12d57bce0b2962750fc0 100644 (file)
@@ -140,7 +140,7 @@ class ToolSelectPanelHelper:
       The text prefix for each key-map for this spaces tools.
     - tools_all():
       Returns (context_mode, tools) tuple pair for all tools defined.
-    - tools_from_context(context):
+    - tools_from_context(context, mode=None):
       Returns tools available in this context.
 
     Each tool is a 'ToolDef' or None for a separator in the toolbar, use ``None``.
@@ -230,23 +230,23 @@ class ToolSelectPanelHelper:
                     yield item, -1
 
     @staticmethod
-    def _tool_get_active(context, with_icon=False):
+    def _tool_get_active(context, space_type, mode, with_icon=False):
         """
         Return the active Python tool definition and icon name.
         """
 
         workspace = context.workspace
-        cls = ToolSelectPanelHelper._tool_class_from_space_type(workspace.tool_space_type)
+        cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
         if cls is not None:
-            tool_def_active, index_active = ToolSelectPanelHelper._tool_vars_from_active_with_index(context)
+            tool_active_text = getattr(
+                ToolSelectPanelHelper._tool_active_from_context(context, space_type, mode),
+                "name", None)
 
-            context_mode = context.mode
-            for item in ToolSelectPanelHelper._tools_flatten(cls.tools_from_context(context)):
+            for item in ToolSelectPanelHelper._tools_flatten(cls.tools_from_context(context, mode)):
                 if item is not None:
-                    tool_def, icon_name = ToolSelectPanelHelper._tool_vars_from_def(item, context_mode)
-                    if (tool_def == tool_def_active):
+                    if item.text == tool_active_text:
                         if with_icon:
-                            icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(icon_name)
+                            icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(item.icon)
                         else:
                             icon_value = 0
                         return (item, icon_value)
@@ -259,7 +259,6 @@ class ToolSelectPanelHelper:
         """
         cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
         if cls is not None:
-            context_mode = context.mode
             for item, index in ToolSelectPanelHelper._tools_flatten_with_tool_index(cls.tools_from_context(context)):
                 if item is not None:
                     if item.text == text:
@@ -267,7 +266,7 @@ class ToolSelectPanelHelper:
         return None, -1
 
     @staticmethod
-    def _tool_vars_from_def(item, context_mode):
+    def _tool_vars_from_def(item):
         # For now be strict about whats in this dict
         # prevent accidental adding unknown keys.
         text = item.text
@@ -282,16 +281,22 @@ class ToolSelectPanelHelper:
         return (km_idname, mp_idname, datablock_idname), icon_name
 
     @staticmethod
-    def _tool_vars_from_active_with_index(context):
-        workspace = context.workspace
-        return (
-            (
-                workspace.tool_keymap or None,
-                workspace.tool_manipulator_group or None,
-                workspace.tool_data_block or None,
-            ),
-            workspace.tool_index,
-        )
+    def _tool_active_from_context(context, space_type, mode=None, create=False):
+        if space_type == 'VIEW_3D':
+            if mode is None:
+                obj = context.active_object
+                mode = obj.mode if obj is not None else 'OBJECT'
+            tool = context.workspace.tools.from_space_view3d_mode(mode, create)
+            if tool is not None:
+                return tool
+        elif space_type == 'IMAGE_EDITOR':
+            space_data = context.space_data
+            if mode is None:
+                mode = space_data.mode
+            tool = context.workspace.tools.from_space_image_mode(mode, create)
+            if tool is not None:
+                return tool
+        return None
 
     @staticmethod
     def _tool_text_from_button(context):
@@ -445,8 +450,11 @@ class ToolSelectPanelHelper:
         # - tool-tips that include multiple key shortcuts.
         # - ability to click and hold to expose sub-tools.
 
-        context_mode = context.mode
-        tool_def_active, index_active = ToolSelectPanelHelper._tool_vars_from_active_with_index(context)
+        space_type = context.space_data.type
+        tool_active_text = getattr(
+            ToolSelectPanelHelper._tool_active_from_context(context, space_type),
+            "name", None,
+        )
 
         ui_gen, show_text = self._layout_generator_detect_from_region(self.layout, context.region)
 
@@ -464,8 +472,7 @@ class ToolSelectPanelHelper:
                 for i, sub_item in enumerate(item):
                     if sub_item is None:
                         continue
-                    tool_def, icon_name = ToolSelectPanelHelper._tool_vars_from_def(sub_item, context_mode)
-                    is_active = (tool_def == tool_def_active)
+                    is_active = (sub_item.text == tool_active_text)
                     if is_active:
                         index = i
                         break
@@ -483,8 +490,8 @@ class ToolSelectPanelHelper:
                 index = -1
                 use_menu = False
 
-            tool_def, icon_name = ToolSelectPanelHelper._tool_vars_from_def(item, context_mode)
-            is_active = (tool_def == tool_def_active)
+            tool_def, icon_name = ToolSelectPanelHelper._tool_vars_from_def(item)
+            is_active = (item.text == tool_active_text)
 
             icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(icon_name)
 
@@ -510,7 +517,11 @@ class ToolSelectPanelHelper:
 
     @staticmethod
     def draw_active_tool_header(context, layout):
-        item, icon_value = ToolSelectPanelHelper._tool_get_active(context, with_icon=True)
+        # BAD DESIGN WARNING: last used tool
+        workspace = context.workspace
+        space_type = workspace.tools_space_type
+        mode = workspace.tools_mode
+        item, icon_value = ToolSelectPanelHelper._tool_get_active(context, space_type, mode, with_icon=True)
         if item is None:
             return
         # Note: we could show 'item.text' here but it makes the layout jitter when switcuing tools.
@@ -527,7 +538,6 @@ class WM_MT_toolsystem_submenu(Menu):
 
     @staticmethod
     def _tool_group_from_button(context):
-        context_mode = context.mode
         # Lookup the tool definitions based on the space-type.
         cls = ToolSelectPanelHelper._tool_class_from_space_type(context.space_data.type)
         if cls is not None:
@@ -540,7 +550,6 @@ class WM_MT_toolsystem_submenu(Menu):
         return None, None
 
     def draw(self, context):
-        context_mode = context.mode
         layout = self.layout
         layout.scale_y = 2.0
 
@@ -554,7 +563,7 @@ class WM_MT_toolsystem_submenu(Menu):
             if item is None:
                 layout.separator()
                 continue
-            tool_def, icon_name = ToolSelectPanelHelper._tool_vars_from_def(item, context_mode)
+            tool_def, icon_name = ToolSelectPanelHelper._tool_vars_from_def(item)
             icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(icon_name)
             layout.operator(
                 "wm.tool_set_by_name",
@@ -566,9 +575,10 @@ class WM_MT_toolsystem_submenu(Menu):
 def activate_by_name(context, space_type, text):
     item, index = ToolSelectPanelHelper._tool_get_by_name(context, space_type, text)
     if item is not None:
-        context_mode = context.mode
-        tool_def, icon_name = ToolSelectPanelHelper._tool_vars_from_def(item, context_mode)
-        bpy.ops.wm.tool_set(
+        tool = ToolSelectPanelHelper._tool_active_from_context(context, space_type, create=True)
+        tool_def, icon_name = ToolSelectPanelHelper._tool_vars_from_def(item)
+        tool.setup(
+            name=text,
             keymap=tool_def[0] or "",
             manipulator_group=tool_def[1] or "",
             data_block=tool_def[2] or "",
index a0360c0900ba2f2a61928716e24084d5cb2af907..4a368bd712de4941fd0811dad08339fd401d8944 100644 (file)
@@ -777,6 +777,108 @@ class _defs_weight_paint:
         )
 
 
+class _defs_uv_select:
+
+    @ToolDef.from_fn
+    def border():
+        return dict(
+            text="Select Border",
+            icon="ops.generic.select_border",
+            widget=None,
+            keymap=(
+                ("uv.select_border",
+                 dict(deselect=False),
+                 dict(type='EVT_TWEAK_A', value='ANY')),
+                # ("uv.select_border",
+                #  dict(deselect=True),
+                #  dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)),
+            ),
+        )
+
+    @ToolDef.from_fn
+    def circle():
+        return dict(
+            text="Select Circle",
+            icon="ops.generic.select_circle",
+            widget=None,
+            keymap=(
+                ("uv.select_circle",
+                 dict(),  # dict(deselect=False),
+                 dict(type='ACTIONMOUSE', value='PRESS')),
+                # ("uv.select_circle",
+                #  dict(deselect=True),
+                #  dict(type='ACTIONMOUSE', value='PRESS', ctrl=True)),
+            ),
+        )
+
+    @ToolDef.from_fn
+    def lasso():
+        return dict(
+            text="Select Lasso",
+            icon="ops.generic.select_lasso",
+            widget=None,
+            keymap=(
+                ("uv.select_lasso",
+                 dict(deselect=False),
+                 dict(type='EVT_TWEAK_A', value='ANY')),
+                # ("uv.select_lasso",
+                #  dict(deselect=True),
+                #  dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)),
+            ),
+        )
+
+
+class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel):
+    bl_space_type = 'IMAGE_EDITOR'
+    bl_region_type = 'TOOLS'
+    bl_category = "Tools"
+    bl_label = "Tools"  # not visible
+    bl_options = {'HIDE_HEADER'}
+
+    # Satisfy the 'ToolSelectPanelHelper' API.
+    keymap_prefix = "Image Editor Tool: "
+
+    @classmethod
+    def tools_from_context(cls, context, mode=None):
+        if mode is None:
+            mode = context.space_data.mode
+        for tools in (cls._tools[None], cls._tools.get(mode, ())):
+            for item in tools:
+                if not (type(item) is ToolDef) and callable(item):
+                    yield from item(context)
+                else:
+                    yield item
+
+    @classmethod
+    def tools_all(cls):
+        yield from cls._tools.items()
+
+    # for reuse
+    _tools_select = (
+        (
+            _defs_uv_select.border,
+            _defs_uv_select.circle,
+            _defs_uv_select.lasso,
+        ),
+    )
+
+    _tools = {
+        None: [
+            # for all modes
+        ],
+        'VIEW': [
+            *_tools_select,
+
+        ],
+        'MASK': [
+            None,
+        ],
+        'PAINT': [
+            _defs_texture_paint.generate_from_brushes,
+        ],
+    }
+
+
 class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
     bl_space_type = 'VIEW_3D'
     bl_region_type = 'TOOLS'
@@ -788,8 +890,10 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
     keymap_prefix = "3D View Tool: "
 
     @classmethod
-    def tools_from_context(cls, context):
-        for tools in (cls._tools[None], cls._tools.get(context.mode, ())):
+    def tools_from_context(cls, context, mode=None):
+        if mode is None:
+            mode = context.mode
+        for tools in (cls._tools[None], cls._tools.get(mode, ())):
             for item in tools:
                 if not (type(item) is ToolDef) and callable(item):
                     yield from item(context)
@@ -934,6 +1038,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
 
 
 classes = (
+    IMAGE_PT_tools_active,
     VIEW3D_PT_tools_active,
 )
 
index 38378f66584fe956f3aff5fc7a20ee6b6b1fb99f..fd316cb9d821a4904e28f82cb09b1c177064b315 100644 (file)
@@ -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);
 }
 
 /**
index 9618ae432f1ec6886204dabc23253468854bdf18..42984cfefaaec79b89c272feb4823c5a58ca11f1 100644 (file)
@@ -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)
index bb136cb937d193345397a9aec5c9fb66e9e522d1..507fe2e082c0914bececf6085e8fa6201725fcd5 100644 (file)
@@ -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. */
index 2e3d0a9c6759898b7061bb61464479fa4bdc66f0..67596ef5c8a4c2b9203e14a8d876d52f346759db 100644 (file)
@@ -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);
index e87a24b3af0a9d196c69939e581a90114d6f6c3f..b9a7da0261184804ac644c6424b05b279ef3eaa8 100644 (file)
@@ -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;
 }
 
index e0427b4797c6ade6297e863391c45c87712f903d..6197457293f4c94db685f80d0ca53c23dcc9a58c 100644 (file)
@@ -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;
 }
 
index bd4381f4099869030eed1f6c67419b9f23b8cb27..fe52e9453999b61f37cf6c104ebba4ccc3ae9f8b 100644 (file)
@@ -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);
index cbf755d26b52e86d7f1ee97f537f452df6f17822..6a32fdecfada0a12093133f7ddac51bf96c72556 100644 (file)
@@ -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;
 }
 
index 196505c9542b16ed186ef9553394d7101c023973..3c3df2067ab98617d5f4bf0218f99e1bd00bd8bf 100644 (file)
@@ -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;
 }
 
index 048555d3fcc56f0b87bcbca062e161116cdd6a97..709d6d4c690e5075a0c580abfa6d5498b9103112 100644 (file)
@@ -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;
 }
 
index 8cf27d86cfe98b48365f4d2b509a9f9c3493c24b..4342fa87f890467105e48aee4f0e509393bae53f 100644 (file)
@@ -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)
index fa147ff1226123fee0619a0c16549059608ec85f..de2ef45247bf025f567e342fcffc46189bb1de14 100644 (file)
@@ -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(
index 9f69a33861d7c6991e70d690d92a27d17da02938..d46673b48171cea9a52919bb36388a81c218abbc 100644 (file)
@@ -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;
index 8257ad595d775beaf5c4dccbcbd7dd4dc0e03700..c24291953c8dc4a6644da585f04c4e9fd409d727 100644 (file)
@@ -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;
        }
index 4cc3929b4eac3b3fea34460f4b0c276dc1503d19..693e4f672d2d61c953aa5bc19d11ca0bc0211c0f 100644 (file)
 /* 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 */
index d5b2493078cadfeeb20918c24136a7f06f1453cf..447dc4ce289909efed34e6623780c6514d6430f3 100644 (file)
@@ -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[];
index 7bd5ad2b9592131b6cb8d3bb8f938184bc37d1b7..c62e8ed4da8ea7ae7fe2abc31c3d668637e43b0c 100644 (file)
@@ -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}")
index 0b2efe2705993651d0c6a4e9be0e1b034d97d750..4daf8b6a965d4e12ea6572a3b766850971212d6f 100644 (file)
@@ -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},
index 11ad39a2dd1bda6718f813ee3bb27f343d886a9e..ce16cb69bbd177eb292b180e284afcfd51e9b43b 100644 (file)
@@ -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);
index 12bb4dd0617274e46d74f42f38cd090c6e05dd61..3ce799dfb88d3a55175fb47d3909ca728787d439 100644 (file)
@@ -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");
 
index b82ca145f5fcec63e32daf0aca98725a340e3a4b..485cb298daede2de77915a1e890748400d7a811b 100644 (file)
@@ -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 (file)
index 0000000..4b0e2b5
--- /dev/null
@@ -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
index 9176385c40d1e6e2408123f9c123bcfafef71b52..5562e7880faffc0d2a2d4885cbf0ae2237077db9 100644 (file)
@@ -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(
index 7963bf16534518ca93b06d8fda06b082b812e6ce..8bbbd1b60dfcce4ba270a12a2a8914795095c9b0 100644 (file)
@@ -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. */
index a154f6b83eaa9041f69b3e2552472b66d6911988..22133ae16025280c1aa55fbec96affc177bcbadb 100644 (file)
@@ -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);
index c351d0fd8492336da94b63697c05648f82744ef2..24b902a6a9201f81af897952125e68e783b76fe2 100644 (file)
 
 #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"
 #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);
 }