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:
@@ -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
|
||||
|
@@ -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(
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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. */
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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 *);
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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 */
|
||||
|
Reference in New Issue
Block a user