Tool System: store operator properties in the tool

This replaces last-used property use which wasn't reliable since
properties were not considered 'set' - causing them to be ignored.
This commit is contained in:
2018-05-22 14:00:44 +02:00
parent 298f8042ef
commit 96a7ed8a15
11 changed files with 140 additions and 31 deletions

View File

@@ -237,14 +237,11 @@ class ToolSelectPanelHelper:
"""
Return the active Python tool definition and icon name.
"""
workspace = context.workspace
cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
if cls is not None:
tool_active_text = getattr(
ToolSelectPanelHelper._tool_active_from_context(context, space_type, mode),
"name", None)
tool_active = ToolSelectPanelHelper._tool_active_from_context(context, space_type, mode)
tool_active_text = getattr(tool_active, "name", None)
for item in ToolSelectPanelHelper._tools_flatten(cls.tools_from_context(context, mode)):
if item is not None:
if item.text == tool_active_text:
@@ -252,8 +249,8 @@ class ToolSelectPanelHelper:
icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(item.icon)
else:
icon_value = 0
return (item, icon_value)
return None, 0
return (item, tool_active, icon_value)
return None, None, 0
@staticmethod
def _tool_get_by_name(context, space_type, text):
@@ -517,14 +514,14 @@ class ToolSelectPanelHelper:
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)
item, tool, 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.
layout.label(" ", icon_value=icon_value)
draw_settings = item.draw_settings
if draw_settings is not None:
draw_settings(context, layout)
draw_settings(context, layout, tool)
# The purpose of this menu is to be a generic popup to select between tools

View File

@@ -293,9 +293,9 @@ class _defs_edit_mesh:
@ToolDef.from_fn
def rip_region():
def draw_settings(context, layout):
def draw_settings(context, layout, tool):
wm = context.window_manager
props = wm.operator_properties_last("mesh.rip_move")
props = tool.operator_properties("mesh.rip_move")
props_macro = props.MESH_OT_rip
layout.prop(props_macro, "use_fill")
@@ -393,9 +393,9 @@ class _defs_edit_mesh:
@ToolDef.from_fn
def inset():
def draw_settings(context, layout):
def draw_settings(context, layout, tool):
wm = context.window_manager
props = wm.operator_properties_last("mesh.inset")
props = tool.operator_properties("mesh.inset")
layout.prop(props, "use_outset")
layout.prop(props, "use_individual")
layout.prop(props, "use_even_offset")
@@ -507,9 +507,9 @@ class _defs_edit_mesh:
@ToolDef.from_fn
def shrink_fatten():
def draw_settings(context, layout):
def draw_settings(context, layout, tool):
wm = context.window_manager
props = wm.operator_properties_last("transform.shrink_fatten")
props = tool.operator_properties("transform.shrink_fatten")
layout.prop(props, "use_even_offset")
return dict(
@@ -537,9 +537,9 @@ class _defs_edit_mesh:
@ToolDef.from_fn
def knife():
def draw_settings(context, layout):
def draw_settings(context, layout, tool):
wm = context.window_manager
props = wm.operator_properties_last("mesh.knife_tool")
props = tool.operator_properties("mesh.knife_tool")
layout.prop(props, "use_occlude_geometry")
layout.prop(props, "only_selected")
@@ -573,7 +573,7 @@ class _defs_edit_curve:
@ToolDef.from_fn
def draw():
def draw_settings(context, layout):
def draw_settings(context, layout, tool):
# Tool settings initialize operator options.
tool_settings = context.tool_settings
cps = tool_settings.curve_paint_settings
@@ -765,9 +765,9 @@ class _defs_weight_paint:
@ToolDef.from_fn
def gradient():
def draw_settings(context, layout):
def draw_settings(context, layout, tool):
wm = context.window_manager
props = wm.operator_properties_last("paint.weight_gradient")
props = tool.operator_properties("paint.weight_gradient")
layout.prop(props, "type")
return dict(

View File

@@ -34,6 +34,7 @@
#include "BLI_listbase.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_scene.h"
@@ -176,6 +177,10 @@ void BKE_workspace_free(WorkSpace *workspace)
tref_next = tref->next;
if (tref->runtime) {
MEM_freeN(tref->runtime);
if (tref->properties) {
IDP_FreeProperty(tref->properties);
MEM_freeN(tref->properties);
}
}
}
BLI_freelistN(&workspace->tools);

View File

@@ -2941,6 +2941,7 @@ static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main
for (bToolRef *tref = workspace->tools.first; tref; tref = tref->next) {
tref->runtime = NULL;
tref->properties = newdataadr(fd, tref->properties);
}
}

View File

@@ -3602,6 +3602,11 @@ static void write_workspace(WriteData *wd, WorkSpace *workspace)
writelist(wd, DATA, WorkSpaceDataRelation, &workspace->scene_viewlayer_relations);
writelist(wd, DATA, wmOwnerID, &workspace->owner_ids);
writelist(wd, DATA, bToolRef, &workspace->tools);
for (bToolRef *tref = workspace->tools.first; tref; tref = tref->next) {
if (tref->properties) {
IDP_WriteProperty(tref->properties, wd);
}
}
}
/* Keep it last of write_foodata functions. */

View File

@@ -56,11 +56,13 @@
#
#
typedef struct bToolRef_Runtime {
/* One of these must be defined. */
int cursor;
/* One of these 3 must be defined. */
char keymap[64];
char manipulator_group[64];
char data_block[64];
/* index when a tool is a member of a group */
int index;
} bToolRef_Runtime;
@@ -82,6 +84,15 @@ typedef struct bToolRef {
*/
int mode;
/**
* Use for tool options, each group's name must match a tool name:
*
* {"Tool Name": {"SOME_OT_operator": {...}, ..}, ..}
*
* This is done since different tools may call the same operators with their own options.
*/
IDProperty *properties;
/** Variables needed to operate the tool. */
bToolRef_Runtime *runtime;
} bToolRef;

View File

@@ -64,6 +64,20 @@ static void rna_WorkspaceTool_setup(
WM_toolsystem_ref_set_from_runtime(C, (WorkSpace *)id, tref, &tref_rt, name);
}
static PointerRNA rna_WorkspaceTool_operator_properties(
bToolRef *tref,
const char *idname)
{
wmOperatorType *ot = WM_operatortype_find(idname, true);
if (ot != NULL) {
PointerRNA ptr;
WM_toolsystem_ref_properties_ensure(tref, ot, &ptr);
return ptr;
}
return PointerRNA_NULL;
}
#else
void RNA_api_workspace(StructRNA *UNUSED(srna))
@@ -91,6 +105,16 @@ void RNA_api_workspace_tool(StructRNA *srna)
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);
/* Access tool operator options (optionally create). */
func = RNA_def_function(srna, "operator_properties", "rna_WorkspaceTool_operator_properties");
parm = RNA_def_string(func, "operator", NULL, 0, "", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
/* return */
parm = RNA_def_pointer(func, "result", "OperatorProperties", "", "");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_RNAPTR);
RNA_def_function_return(func, parm);
}
#endif

View File

@@ -646,6 +646,12 @@ bool WM_toolsystem_active_tool_is_brush(const struct bContext *C);
void WM_toolsystem_do_msg_notify_tag_refresh(
struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val);
struct IDProperty *WM_toolsystem_ref_properties_ensure_idprops(struct bToolRef *tref);
void WM_toolsystem_ref_properties_ensure(struct bToolRef *tref, struct wmOperatorType *ot, struct PointerRNA *ptr);
void WM_toolsystem_ref_properties_init_for_keymap(
struct bToolRef *tref, struct PointerRNA *dst_ptr, struct PointerRNA *src_ptr, struct wmOperatorType *ot);
/* wm_tooltip.c */
typedef struct ARegion *(*wmTooltipInitFn)(struct bContext *, struct ARegion *, bool *);

View File

@@ -1235,7 +1235,8 @@ bool WM_operator_last_properties_store(wmOperator *UNUSED(op))
*/
static int wm_operator_invoke(
bContext *C, wmOperatorType *ot, wmEvent *event,
PointerRNA *properties, ReportList *reports, const bool poll_only)
PointerRNA *properties, ReportList *reports,
const bool poll_only, bool use_last_properties)
{
int retval = OPERATOR_PASS_THROUGH;
@@ -1253,7 +1254,7 @@ static int wm_operator_invoke(
}
/* initialize setting from previous run */
if (!is_nested_call) { /* not called by py script */
if (!is_nested_call && use_last_properties) { /* not called by py script */
WM_operator_last_properties_init(op);
}
@@ -1301,7 +1302,7 @@ static int wm_operator_invoke(
/* do nothing, wm_operator_exec() has been called somewhere */
}
else if (retval & OPERATOR_FINISHED) {
const bool store = !is_nested_call;
const bool store = !is_nested_call && use_last_properties;
wm_operator_finished(C, op, false, store);
}
else if (retval & OPERATOR_RUNNING_MODAL) {
@@ -1464,7 +1465,7 @@ static int wm_operator_call_internal(
CTX_wm_region_set(C, ar1);
}
retval = wm_operator_invoke(C, ot, event, properties, reports, poll_only);
retval = wm_operator_invoke(C, ot, event, properties, reports, poll_only, true);
/* set region back */
CTX_wm_region_set(C, ar);
@@ -1478,7 +1479,7 @@ static int wm_operator_call_internal(
ARegion *ar = CTX_wm_region(C);
CTX_wm_region_set(C, NULL);
retval = wm_operator_invoke(C, ot, event, properties, reports, poll_only);
retval = wm_operator_invoke(C, ot, event, properties, reports, poll_only, true);
CTX_wm_region_set(C, ar);
return retval;
@@ -1492,7 +1493,7 @@ static int wm_operator_call_internal(
CTX_wm_region_set(C, NULL);
CTX_wm_area_set(C, NULL);
retval = wm_operator_invoke(C, ot, event, properties, reports, poll_only);
retval = wm_operator_invoke(C, ot, event, properties, reports, poll_only, true);
CTX_wm_area_set(C, area);
CTX_wm_region_set(C, ar);
@@ -1500,7 +1501,7 @@ static int wm_operator_call_internal(
}
case WM_OP_EXEC_DEFAULT:
case WM_OP_INVOKE_DEFAULT:
return wm_operator_invoke(C, ot, event, properties, reports, poll_only);
return wm_operator_invoke(C, ot, event, properties, reports, poll_only, true);
}
}
@@ -1975,9 +1976,19 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
else {
wmOperatorType *ot = WM_operatortype_find(event->keymap_idname, 0);
if (ot) {
if (wm_operator_check_locked_interface(C, ot)) {
retval = wm_operator_invoke(C, ot, event, properties, NULL, false);
if (ot && wm_operator_check_locked_interface(C, ot)) {
bool use_last_properties = true;
PointerRNA tool_properties = {0};
if (handler->keymap_tool) {
WM_toolsystem_ref_properties_init_for_keymap(handler->keymap_tool, &tool_properties, properties, ot);
properties = &tool_properties;
use_last_properties = false;
}
retval = wm_operator_invoke(C, ot, event, properties, NULL, false, use_last_properties);
if (handler->keymap_tool) {
WM_operator_properties_free(&tool_properties);
}
}
}
@@ -2887,6 +2898,8 @@ void wm_event_do_handlers(bContext *C)
C, tref_rt->keymap, sa->spacetype, RGN_TYPE_WINDOW);
if (km != NULL) {
sneaky_handler.keymap = km;
sneaky_handler.keymap_tool = sa->runtime.tool;
/* Handle widgets first. */
wmEventHandler *handler_last = ar->handlers.last;
while (handler_last && handler_last->manipulator_map == NULL) {

View File

@@ -45,6 +45,7 @@
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_paint.h"
#include "BKE_idprop.h"
#include "BKE_workspace.h"
#include "RNA_access.h"
@@ -527,3 +528,48 @@ void WM_toolsystem_do_msg_notify_tag_refresh(
};
WM_toolsystem_refresh(C, workspace, &tkey);
}
IDProperty *WM_toolsystem_ref_properties_ensure_idprops(bToolRef *tref)
{
if (tref->properties == NULL) {
IDPropertyTemplate val = {0};
tref->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
}
return tref->properties;
}
void WM_toolsystem_ref_properties_ensure(bToolRef *tref, wmOperatorType *ot, PointerRNA *ptr)
{
IDProperty *group = WM_toolsystem_ref_properties_ensure_idprops(tref);
IDProperty *prop = IDP_GetPropertyFromGroup(group, ot->idname);
if (prop == NULL) {
IDPropertyTemplate val = {0};
prop = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
STRNCPY(prop->name, ot->idname);
IDP_ReplaceInGroup_ex(group, prop, NULL);
}
else {
BLI_assert(prop->type == IDP_GROUP);
}
RNA_pointer_create(NULL, ot->srna, prop, ptr);
}
void WM_toolsystem_ref_properties_init_for_keymap(
bToolRef *tref, PointerRNA *dst_ptr, PointerRNA *src_ptr, wmOperatorType *ot)
{
*dst_ptr = *src_ptr;
if (dst_ptr->data) {
dst_ptr->data = IDP_CopyProperty(dst_ptr->data);
}
else {
IDPropertyTemplate val = {0};
dst_ptr->data = IDP_New(IDP_GROUP, &val, "wmOpItemProp");
}
if (tref->properties != NULL) {
IDProperty *prop = IDP_GetPropertyFromGroup(tref->properties, ot->idname);
if (prop) {
IDP_MergeGroup(dst_ptr->data, prop, true);
}
}
}

View File

@@ -54,6 +54,7 @@ typedef struct wmEventHandler {
/* Run after the keymap item runs. */
void (*keymap_callback)(wmKeyMap *keymap, wmKeyMapItem *kmi, void *user_data);
void *keymap_callback_user_data;
struct bToolRef *keymap_tool;
/* modal operator handler */
wmOperator *op; /* for derived/modal handlers */