forked from bartvdbraak/blender
ToolSystem: support per-tool gizmo group properties
Also add gizmo group example to the tool-template.
This commit is contained in:
parent
f464cac55a
commit
082ddc9379
@ -22,6 +22,7 @@
|
|||||||
# Export Functions
|
# Export Functions
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
|
"_init_properties_from_data", # Shared with gizmo default property initialization.
|
||||||
"keyconfig_export_as_data",
|
"keyconfig_export_as_data",
|
||||||
"keyconfig_import_from_data",
|
"keyconfig_import_from_data",
|
||||||
"keyconfig_init_from_data",
|
"keyconfig_init_from_data",
|
||||||
@ -244,18 +245,22 @@ def keyconfig_export_as_data(wm, kc, filepath, *, all_keymaps=False):
|
|||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Import Functions
|
# Import Functions
|
||||||
|
#
|
||||||
|
# NOTE: unlike export, this runs on startup.
|
||||||
|
# Take care making changes that could impact performance.
|
||||||
|
|
||||||
def _kmi_props_setattr(kmi_props, attr, value):
|
def _init_properties_from_data(base_props, base_value):
|
||||||
|
assert(type(base_value) is list)
|
||||||
|
for attr, value in base_value:
|
||||||
if type(value) is list:
|
if type(value) is list:
|
||||||
kmi_subprop = getattr(kmi_props, attr)
|
base_props.property_unset(attr)
|
||||||
for subattr, subvalue in value:
|
props = getattr(base_props, attr)
|
||||||
_kmi_props_setattr(kmi_subprop, subattr, subvalue)
|
_init_properties_from_data(props, value)
|
||||||
return
|
else:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
setattr(kmi_props, attr, value)
|
setattr(base_props, attr, value)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
print(f"Warning: property '{attr}' not found in keymap item '{kmi_props.__class__.__name__}'")
|
print(f"Warning: property '{attr}' not found in item '{base_props.__class__.__name__}'")
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
print(f"Warning: {ex!r}")
|
print(f"Warning: {ex!r}")
|
||||||
|
|
||||||
@ -271,8 +276,7 @@ def keymap_init_from_data(km, km_items, is_modal=False):
|
|||||||
if kmi_props_data is not None:
|
if kmi_props_data is not None:
|
||||||
kmi_props = kmi.properties
|
kmi_props = kmi.properties
|
||||||
assert type(kmi_props_data) is list
|
assert type(kmi_props_data) is list
|
||||||
for attr, value in kmi_props_data:
|
_init_properties_from_data(kmi_props, kmi_props_data)
|
||||||
_kmi_props_setattr(kmi_props, attr, value)
|
|
||||||
|
|
||||||
|
|
||||||
def keyconfig_init_from_data(kc, keyconfig_data):
|
def keyconfig_init_from_data(kc, keyconfig_data):
|
||||||
|
@ -859,6 +859,7 @@ def register_tool(tool_cls, *, after=None, separator=False, group=False):
|
|||||||
"icon": getattr(tool_cls, "bl_icon", None),
|
"icon": getattr(tool_cls, "bl_icon", None),
|
||||||
"cursor": getattr(tool_cls, "bl_cursor", None),
|
"cursor": getattr(tool_cls, "bl_cursor", None),
|
||||||
"widget": getattr(tool_cls, "bl_widget", None),
|
"widget": getattr(tool_cls, "bl_widget", None),
|
||||||
|
"widget_properties": getattr(tool_cls, "bl_widget_properties", None),
|
||||||
"keymap": getattr(tool_cls, "bl_keymap", None),
|
"keymap": getattr(tool_cls, "bl_keymap", None),
|
||||||
"data_block": getattr(tool_cls, "bl_data_block", None),
|
"data_block": getattr(tool_cls, "bl_data_block", None),
|
||||||
"operator": getattr(tool_cls, "bl_operator", None),
|
"operator": getattr(tool_cls, "bl_operator", None),
|
||||||
|
@ -75,6 +75,8 @@ ToolDef = namedtuple(
|
|||||||
"icon",
|
"icon",
|
||||||
# An optional cursor to use when this tool is active.
|
# An optional cursor to use when this tool is active.
|
||||||
"cursor",
|
"cursor",
|
||||||
|
# The properties to use for the widget.
|
||||||
|
"widget_properties",
|
||||||
# An optional gizmo group to activate when the tool is set or None for no gizmo.
|
# An optional gizmo group to activate when the tool is set or None for no gizmo.
|
||||||
"widget",
|
"widget",
|
||||||
# Optional key-map for tool, possible values are:
|
# Optional key-map for tool, possible values are:
|
||||||
@ -132,6 +134,7 @@ def from_dict(kw_args):
|
|||||||
"icon": None,
|
"icon": None,
|
||||||
"cursor": None,
|
"cursor": None,
|
||||||
"widget": None,
|
"widget": None,
|
||||||
|
"widget_properties": None,
|
||||||
"keymap": None,
|
"keymap": None,
|
||||||
"data_block": None,
|
"data_block": None,
|
||||||
"operator": None,
|
"operator": None,
|
||||||
@ -939,6 +942,21 @@ class WM_MT_toolsystem_submenu(Menu):
|
|||||||
).name = item.idname
|
).name = item.idname
|
||||||
|
|
||||||
|
|
||||||
|
def _kmi_props_setattr(kmi_props, attr, value):
|
||||||
|
if type(value) is list:
|
||||||
|
kmi_subprop = getattr(kmi_props, attr)
|
||||||
|
for subattr, subvalue in value:
|
||||||
|
_kmi_props_setattr(kmi_subprop, subattr, subvalue)
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
setattr(kmi_props, attr, value)
|
||||||
|
except AttributeError:
|
||||||
|
print(f"Warning: property '{attr}' not found in keymap item '{kmi_props.__class__.__name__}'")
|
||||||
|
except Exception as ex:
|
||||||
|
print(f"Warning: {ex!r}")
|
||||||
|
|
||||||
|
|
||||||
def _activate_by_item(context, space_type, item, index, *, as_fallback=False):
|
def _activate_by_item(context, space_type, item, index, *, as_fallback=False):
|
||||||
cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
|
cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
|
||||||
tool = ToolSelectPanelHelper._tool_active_from_context(context, space_type, create=True)
|
tool = ToolSelectPanelHelper._tool_active_from_context(context, space_type, create=True)
|
||||||
@ -983,11 +1001,13 @@ def _activate_by_item(context, space_type, item, index, *, as_fallback=False):
|
|||||||
item_fallback, _index = cls._tool_get_active_by_index(context, select_index)
|
item_fallback, _index = cls._tool_get_active_by_index(context, select_index)
|
||||||
# End calculating fallback.
|
# End calculating fallback.
|
||||||
|
|
||||||
|
gizmo_group = item.widget or ""
|
||||||
|
|
||||||
tool.setup(
|
tool.setup(
|
||||||
idname=item.idname,
|
idname=item.idname,
|
||||||
keymap=item.keymap[0] if item.keymap is not None else "",
|
keymap=item.keymap[0] if item.keymap is not None else "",
|
||||||
cursor=item.cursor or 'DEFAULT',
|
cursor=item.cursor or 'DEFAULT',
|
||||||
gizmo_group=item.widget or "",
|
gizmo_group=gizmo_group,
|
||||||
data_block=item.data_block or "",
|
data_block=item.data_block or "",
|
||||||
operator=item.operator or "",
|
operator=item.operator or "",
|
||||||
index=index,
|
index=index,
|
||||||
@ -995,6 +1015,24 @@ def _activate_by_item(context, space_type, item, index, *, as_fallback=False):
|
|||||||
keymap_fallback=(item_fallback and item_fallback.keymap and item_fallback.keymap[0]) or "",
|
keymap_fallback=(item_fallback and item_fallback.keymap and item_fallback.keymap[0]) or "",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (
|
||||||
|
(gizmo_group != "") and
|
||||||
|
(props := tool.gizmo_group_properties(gizmo_group))
|
||||||
|
):
|
||||||
|
if props is None:
|
||||||
|
print("Error:", gizmo_group, "could not access properties!")
|
||||||
|
else:
|
||||||
|
for key in props.bl_rna.properties.keys():
|
||||||
|
props.property_unset(key)
|
||||||
|
|
||||||
|
gizmo_properties = item.widget_properties
|
||||||
|
if gizmo_properties is not None:
|
||||||
|
if not isinstance(gizmo_properties, list):
|
||||||
|
raise Exception("expected a list, not a %r" % type(gizmo_properties))
|
||||||
|
|
||||||
|
from bl_keymap_utils.io import _init_properties_from_data
|
||||||
|
_init_properties_from_data(props, gizmo_properties)
|
||||||
|
|
||||||
WindowManager = bpy.types.WindowManager
|
WindowManager = bpy.types.WindowManager
|
||||||
|
|
||||||
handle_map = _activate_by_item._cursor_draw_handle
|
handle_map = _activate_by_item._cursor_draw_handle
|
||||||
|
@ -53,14 +53,38 @@ class MyOtherTool(WorkSpaceTool):
|
|||||||
layout.prop(props, "mode")
|
layout.prop(props, "mode")
|
||||||
|
|
||||||
|
|
||||||
|
class MyWidgetTool(WorkSpaceTool):
|
||||||
|
bl_space_type = 'VIEW_3D'
|
||||||
|
bl_context_mode = 'OBJECT'
|
||||||
|
|
||||||
|
bl_idname = "my_template.my_gizmo_translate"
|
||||||
|
bl_label = "My Gizmo Tool"
|
||||||
|
bl_description = "Short description"
|
||||||
|
bl_icon = "ops.transform.translate"
|
||||||
|
bl_widget="VIEW3D_GGT_tool_generic_handle_free"
|
||||||
|
bl_widget_properties=[
|
||||||
|
("radius", 75.0),
|
||||||
|
("backdrop_fill_alpha", 0.0),
|
||||||
|
]
|
||||||
|
bl_keymap = (
|
||||||
|
("transform.translate", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
|
||||||
|
)
|
||||||
|
|
||||||
|
def draw_settings(context, layout, tool):
|
||||||
|
props = tool.operator_properties("transform.translate")
|
||||||
|
layout.prop(props, "mode")
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
bpy.utils.register_tool(MyTool, after={"builtin.scale_cage"}, separator=True, group=True)
|
bpy.utils.register_tool(MyTool, after={"builtin.scale_cage"}, separator=True, group=True)
|
||||||
bpy.utils.register_tool(MyOtherTool, after={MyTool.bl_idname})
|
bpy.utils.register_tool(MyOtherTool, after={MyTool.bl_idname})
|
||||||
|
bpy.utils.register_tool(MyWidgetTool, after={MyTool.bl_idname})
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
bpy.utils.unregister_tool(MyTool)
|
bpy.utils.unregister_tool(MyTool)
|
||||||
bpy.utils.unregister_tool(MyOtherTool)
|
bpy.utils.unregister_tool(MyOtherTool)
|
||||||
|
bpy.utils.unregister_tool(MyWidgetTool)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "WM_toolsystem.h"
|
#include "WM_toolsystem.h"
|
||||||
|
|
||||||
#include "RNA_access.h"
|
#include "RNA_access.h"
|
||||||
|
#include "RNA_define.h"
|
||||||
|
|
||||||
#include "WM_api.h"
|
#include "WM_api.h"
|
||||||
#include "WM_message.h"
|
#include "WM_message.h"
|
||||||
@ -47,6 +48,9 @@
|
|||||||
static const char *handle_normal_id;
|
static const char *handle_normal_id;
|
||||||
static const char *handle_free_id;
|
static const char *handle_free_id;
|
||||||
|
|
||||||
|
static const float handle_normal_radius_default = 100.0f;
|
||||||
|
static const float handle_free_radius_default = 36.0f;
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/** \name Generic Tool
|
/** \name Generic Tool
|
||||||
* \{ */
|
* \{ */
|
||||||
@ -72,6 +76,7 @@ static bool WIDGETGROUP_tool_generic_poll(const bContext *C, wmGizmoGroupType *g
|
|||||||
|
|
||||||
static wmGizmo *tool_generic_create_gizmo(const bContext *C, wmGizmoGroup *gzgroup)
|
static wmGizmo *tool_generic_create_gizmo(const bContext *C, wmGizmoGroup *gzgroup)
|
||||||
{
|
{
|
||||||
|
|
||||||
wmGizmo *gz = WM_gizmo_new("GIZMO_GT_button_2d", gzgroup, NULL);
|
wmGizmo *gz = WM_gizmo_new("GIZMO_GT_button_2d", gzgroup, NULL);
|
||||||
gz->flag |= WM_GIZMO_OPERATOR_TOOL_INIT;
|
gz->flag |= WM_GIZMO_OPERATOR_TOOL_INIT;
|
||||||
|
|
||||||
@ -82,8 +87,17 @@ static wmGizmo *tool_generic_create_gizmo(const bContext *C, wmGizmoGroup *gzgro
|
|||||||
|
|
||||||
RNA_enum_set(gz->ptr, "icon", ICON_NONE);
|
RNA_enum_set(gz->ptr, "icon", ICON_NONE);
|
||||||
|
|
||||||
|
bToolRef *tref = WM_toolsystem_ref_from_context((bContext *)C);
|
||||||
|
PointerRNA gzgt_ptr;
|
||||||
|
const bool gzgt_ptr_is_valid = WM_toolsystem_ref_properties_get_from_gizmo_group(
|
||||||
|
tref, gzgroup->type, &gzgt_ptr);
|
||||||
|
|
||||||
if (gzgroup->type->idname == handle_normal_id) {
|
if (gzgroup->type->idname == handle_normal_id) {
|
||||||
gz->scale_basis = 0.12f;
|
const float radius = (gzgt_ptr_is_valid ? RNA_float_get(&gzgt_ptr, "radius") :
|
||||||
|
handle_normal_radius_default) /
|
||||||
|
12.0f;
|
||||||
|
|
||||||
|
gz->scale_basis = radius / U.gizmo_size;
|
||||||
gz->matrix_offset[3][2] -= 12.0;
|
gz->matrix_offset[3][2] -= 12.0;
|
||||||
RNA_enum_set(gz->ptr,
|
RNA_enum_set(gz->ptr,
|
||||||
"draw_options",
|
"draw_options",
|
||||||
@ -91,16 +105,20 @@ static wmGizmo *tool_generic_create_gizmo(const bContext *C, wmGizmoGroup *gzgro
|
|||||||
ED_GIZMO_BUTTON_SHOW_OUTLINE));
|
ED_GIZMO_BUTTON_SHOW_OUTLINE));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gz->scale_basis = 0.16f * 3;
|
const float radius = gzgt_ptr_is_valid ? RNA_float_get(&gzgt_ptr, "radius") :
|
||||||
|
handle_free_radius_default;
|
||||||
|
|
||||||
|
gz->scale_basis = radius / U.gizmo_size;
|
||||||
|
|
||||||
RNA_enum_set(gz->ptr, "draw_options", ED_GIZMO_BUTTON_SHOW_BACKDROP);
|
RNA_enum_set(gz->ptr, "draw_options", ED_GIZMO_BUTTON_SHOW_BACKDROP);
|
||||||
|
|
||||||
/* Make the center low alpha. */
|
/* Make the center low alpha. */
|
||||||
WM_gizmo_set_line_width(gz, 2.0f);
|
WM_gizmo_set_line_width(gz, 2.0f);
|
||||||
RNA_float_set(gz->ptr, "backdrop_fill_alpha", 0.125f);
|
RNA_float_set(gz->ptr,
|
||||||
|
"backdrop_fill_alpha",
|
||||||
|
gzgt_ptr_is_valid ? RNA_float_get(&gzgt_ptr, "backdrop_fill_alpha") : 0.125f);
|
||||||
}
|
}
|
||||||
|
|
||||||
bToolRef *tref = WM_toolsystem_ref_from_context((bContext *)C);
|
|
||||||
wmWindowManager *wm = CTX_wm_manager(C);
|
wmWindowManager *wm = CTX_wm_manager(C);
|
||||||
struct wmKeyConfig *kc = wm->defaultconf;
|
struct wmKeyConfig *kc = wm->defaultconf;
|
||||||
|
|
||||||
@ -206,6 +224,16 @@ void VIEW3D_GGT_tool_generic_handle_normal(wmGizmoGroupType *gzgt)
|
|||||||
gzgt->setup = WIDGETGROUP_tool_generic_setup;
|
gzgt->setup = WIDGETGROUP_tool_generic_setup;
|
||||||
gzgt->refresh = WIDGETGROUP_tool_generic_refresh;
|
gzgt->refresh = WIDGETGROUP_tool_generic_refresh;
|
||||||
gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
|
gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
|
||||||
|
|
||||||
|
RNA_def_float(gzgt->srna,
|
||||||
|
"radius",
|
||||||
|
handle_normal_radius_default,
|
||||||
|
0.0f,
|
||||||
|
1000.0,
|
||||||
|
"Radius",
|
||||||
|
"Radius in pixels",
|
||||||
|
0.0f,
|
||||||
|
1000.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VIEW3D_GGT_tool_generic_handle_free(wmGizmoGroupType *gzgt)
|
void VIEW3D_GGT_tool_generic_handle_free(wmGizmoGroupType *gzgt)
|
||||||
@ -224,6 +252,18 @@ void VIEW3D_GGT_tool_generic_handle_free(wmGizmoGroupType *gzgt)
|
|||||||
gzgt->setup = WIDGETGROUP_tool_generic_setup;
|
gzgt->setup = WIDGETGROUP_tool_generic_setup;
|
||||||
gzgt->refresh = WIDGETGROUP_tool_generic_refresh;
|
gzgt->refresh = WIDGETGROUP_tool_generic_refresh;
|
||||||
gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
|
gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
|
||||||
|
|
||||||
|
RNA_def_float(gzgt->srna,
|
||||||
|
"radius",
|
||||||
|
handle_free_radius_default,
|
||||||
|
0.0f,
|
||||||
|
1000.0,
|
||||||
|
"Radius",
|
||||||
|
"Radius in pixels",
|
||||||
|
0.0f,
|
||||||
|
1000.0f);
|
||||||
|
RNA_def_float(
|
||||||
|
gzgt->srna, "backdrop_fill_alpha", 0.125, 0.0f, 1.0f, "Backdrop Alpha", "", 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
Loading…
Reference in New Issue
Block a user