WIP: Custom build, mostly selection options #105712

Closed
Lukas Sneyd wants to merge 20 commits from lcas:custom-build-35 into blender-v3.5-release

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
41 changed files with 3653 additions and 341 deletions

View File

@ -235,6 +235,8 @@ typedef enum {
GHOST_kStandardCursorCrosshairA,
GHOST_kStandardCursorCrosshairB,
GHOST_kStandardCursorCrosshairC,
GHOST_kStandardCursorCrosshairD,
GHOST_kStandardCursorCrosshairE,
GHOST_kStandardCursorPencil,
GHOST_kStandardCursorUpArrow,
GHOST_kStandardCursorDownArrow,

View File

@ -772,6 +772,12 @@ HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const
case GHOST_kStandardCursorCrosshairC:
cursor = ::LoadImage(module, "crossC_cursor", IMAGE_CURSOR, cx, cy, flags);
break; /* Minimal Crosshair C */
case GHOST_kStandardCursorCrosshairD:
cursor = ::LoadImage(module, "crossD_cursor", IMAGE_CURSOR, cx, cy, flags);
break; /* Alternate Crosshair D */
case GHOST_kStandardCursorCrosshairE:
cursor = ::LoadImage(module, "crossE_cursor", IMAGE_CURSOR, cx, cy, flags);
break; /* Large Crosshair E */
case GHOST_kStandardCursorBottomSide:
case GHOST_kStandardCursorUpDown:
cursor = ::LoadImage(module, "movens_cursor", IMAGE_CURSOR, cx, cy, flags);

View File

@ -185,6 +185,7 @@ const UserDef U_default = {
.render_display_type = USER_RENDER_DISPLAY_WINDOW,
.filebrowser_display_type = USER_TEMP_SPACE_DISPLAY_WINDOW,
.viewport_aa = 8,
.selection_radius = 75.0f,
.walk_navigation =
{

View File

@ -23,6 +23,8 @@ cross_cursor CURSOR "cursors/cross.cur"
crossA_cursor CURSOR "cursors/crossa.cur"
crossB_cursor CURSOR "cursors/crossb.cur"
crossC_cursor CURSOR "cursors/crossc.cur"
crossD_cursor CURSOR "cursors/crossd.cur"
crossE_cursor CURSOR "cursors/crosse.cur"
eraser_cursor CURSOR "cursors/eraser.cur"
eyedropper_cursor CURSOR "cursors/eyedropper.cur"
handopen_cursor CURSOR "cursors/handopen.cur"

View File

@ -182,7 +182,24 @@ def draw_kmi(display_keymaps, kc, km, kmi, layout, level):
if map_type in {'KEYBOARD', 'MOUSE'} and kmi.value == 'CLICK_DRAG':
subrow = sub.row()
subrow.prop(kmi, "direction")
if bpy.context.preferences.inputs.click_drag_direction == 'LEFT_RIGHT':
if kmi.direction == 'ANY' or kmi.direction == 'EAST' or kmi.direction == 'WEST':
subrow.label(text="Direction:")
else:
subrow.label(text="WARNING - No Direction:")
subrow.operator("preferences.set_direction_any", text="Any", depress= kmi.direction == 'ANY').item_id = kmi.id
subrow.operator("preferences.set_direction_left", text="Left", depress= kmi.direction == 'WEST').item_id = kmi.id
subrow.operator("preferences.set_direction_right", text="Right", depress= kmi.direction == 'EAST').item_id = kmi.id
elif bpy.context.preferences.inputs.click_drag_direction == 'UP_DOWN':
if kmi.direction == 'ANY' or kmi.direction == 'NORTH' or kmi.direction == 'SOUTH':
subrow.label(text="Direction:")
else:
subrow.label(text="WARNING - No Direction:")
subrow.operator("preferences.set_direction_any", text="Any", depress= kmi.direction == 'ANY').item_id = kmi.id
subrow.operator("preferences.set_direction_up", text="Up", depress= kmi.direction == 'NORTH').item_id = kmi.id
subrow.operator("preferences.set_direction_down", text="Down", depress= kmi.direction == 'SOUTH').item_id = kmi.id
else:
subrow.prop(kmi, "direction")
subrow = sub.row()
subrow.scale_x = 0.75

View File

@ -400,6 +400,111 @@ class PREFERENCES_OT_keyitem_remove(Operator):
return {'FINISHED'}
class PREFERENCES_OT_set_direction_any(Operator):
"""Drag in any direction"""
bl_idname = "preferences.set_direction_any"
bl_label = "Set Direction Any"
item_id: IntProperty(
name="Item Identifier",
description="Identifier of the item to remove",
)
@classmethod
def poll(cls, context):
return hasattr(context, "keymap")
def execute(self, context):
km = context.keymap
kmi = km.keymap_items.from_id(self.item_id)
km.keymap_items.set_direction_any(kmi)
return {'FINISHED'}
class PREFERENCES_OT_set_direction_left(Operator):
"""Drag to the left"""
bl_idname = "preferences.set_direction_left"
bl_label = "Set Direction Left"
item_id: IntProperty(
name="Item Identifier",
description="Identifier of the item to remove",
)
@classmethod
def poll(cls, context):
return hasattr(context, "keymap")
def execute(self, context):
km = context.keymap
kmi = km.keymap_items.from_id(self.item_id)
km.keymap_items.set_direction_left(kmi)
return {'FINISHED'}
class PREFERENCES_OT_set_direction_right(Operator):
"""Drag to the right"""
bl_idname = "preferences.set_direction_right"
bl_label = "Set Direction Right"
item_id: IntProperty(
name="Item Identifier",
description="Identifier of the item to remove",
)
@classmethod
def poll(cls, context):
return hasattr(context, "keymap")
def execute(self, context):
km = context.keymap
kmi = km.keymap_items.from_id(self.item_id)
km.keymap_items.set_direction_right(kmi)
return {'FINISHED'}
class PREFERENCES_OT_set_direction_up(Operator):
"""Drag upwards"""
bl_idname = "preferences.set_direction_up"
bl_label = "Set Direction Up"
item_id: IntProperty(
name="Item Identifier",
description="Identifier of the item to remove",
)
@classmethod
def poll(cls, context):
return hasattr(context, "keymap")
def execute(self, context):
km = context.keymap
kmi = km.keymap_items.from_id(self.item_id)
km.keymap_items.set_direction_up(kmi)
return {'FINISHED'}
class PREFERENCES_OT_set_direction_down(Operator):
"""Drag downwards"""
bl_idname = "preferences.set_direction_down"
bl_label = "Set Direction Down"
item_id: IntProperty(
name="Item Identifier",
description="Identifier of the item to remove",
)
@classmethod
def poll(cls, context):
return hasattr(context, "keymap")
def execute(self, context):
km = context.keymap
kmi = km.keymap_items.from_id(self.item_id)
km.keymap_items.set_direction_down(kmi)
return {'FINISHED'}
class PREFERENCES_OT_keyconfig_remove(Operator):
"""Remove key config"""
bl_idname = "preferences.keyconfig_remove"
@ -1156,6 +1261,11 @@ classes = (
PREFERENCES_OT_keyconfig_test,
PREFERENCES_OT_keyitem_add,
PREFERENCES_OT_keyitem_remove,
PREFERENCES_OT_set_direction_any,
PREFERENCES_OT_set_direction_left,
PREFERENCES_OT_set_direction_right,
PREFERENCES_OT_set_direction_up,
PREFERENCES_OT_set_direction_down,
PREFERENCES_OT_keyitem_restore,
PREFERENCES_OT_keymap_restore,
PREFERENCES_OT_theme_install,

View File

@ -386,10 +386,37 @@ class _defs_view3d_select:
@ToolDef.from_fn
def box():
def draw_settings(_context, layout, tool):
tool_settings = _context.tool_settings
props = tool.operator_properties("view3d.select_box")
row = layout.row()
row.use_property_split = False
row.prop(props, "mode", text="", expand=True, icon_only=True)
if _context.mode == 'OBJECT' and bpy.context.preferences.inputs.drag_select_control == 'USER_DRAG_TOOLSETTING':
layout.prop(tool_settings, "select_origin_box")
if _context.mode == 'EDIT_MESH' and bpy.context.preferences.inputs.drag_select_control == 'USER_DRAG_TOOLSETTING':
layout.prop(tool_settings, "show_box_options", toggle=True)
if tool_settings.show_box_options:
row = layout.row(align=True)
row.prop(tool_settings, "box_drag_direction")
row = layout.row(align=True)
if tool_settings.box_drag_direction == 'MESH_DIRECTION_ANY':
row.prop(tool_settings, "box_edge")
row = layout.row(align=True)
row.prop(tool_settings, "box_face")
elif tool_settings.box_drag_direction == 'MESH_DIRECTION_LEFT_RIGHT':
row.prop(tool_settings, "box_edge_left", icon='TRIA_LEFT')
row.prop(tool_settings, "box_edge_right", text="", icon='TRIA_RIGHT')
row = layout.row(align=True)
row.prop(tool_settings, "box_face_left", icon='TRIA_LEFT')
row.prop(tool_settings, "box_face_right", text="", icon='TRIA_RIGHT')
else:
row.prop(tool_settings, "box_edge_up", icon='TRIA_UP')
row.prop(tool_settings, "box_edge_down", text="", icon='TRIA_DOWN')
row = layout.row(align=True)
row.prop(tool_settings, "box_face_up", icon='TRIA_UP')
row.prop(tool_settings, "box_face_down", text="", icon='TRIA_DOWN')
return dict(
idname="builtin.select_box",
label="Select Box",
@ -402,10 +429,33 @@ class _defs_view3d_select:
@ToolDef.from_fn
def lasso():
def draw_settings(_context, layout, tool):
tool_settings = _context.tool_settings
props = tool.operator_properties("view3d.select_lasso")
row = layout.row()
row.use_property_split = False
row.prop(props, "mode", text="", expand=True, icon_only=True)
if _context.mode == 'EDIT_MESH' and bpy.context.preferences.inputs.drag_select_control == 'USER_DRAG_TOOLSETTING':
layout.prop(tool_settings, "show_lasso_options", toggle=True)
if tool_settings.show_lasso_options:
row = layout.row(align=True)
row.prop(tool_settings, "lasso_drag_direction")
row = layout.row(align=True)
if tool_settings.lasso_drag_direction == 'MESH_DIRECTION_ANY':
row.prop(tool_settings, "lasso_edge")
row = layout.row(align=True)
row.prop(tool_settings, "lasso_face")
elif tool_settings.lasso_drag_direction == 'MESH_DIRECTION_LEFT_RIGHT':
row.prop(tool_settings, "lasso_edge_left", icon='TRIA_LEFT')
row.prop(tool_settings, "lasso_edge_right", text="", icon='TRIA_RIGHT')
row = layout.row(align=True)
row.prop(tool_settings, "lasso_face_left", icon='TRIA_LEFT')
row.prop(tool_settings, "lasso_face_right", text="", icon='TRIA_RIGHT')
else:
row.prop(tool_settings, "lasso_edge_up", icon='TRIA_UP')
row.prop(tool_settings, "lasso_edge_down", text="", icon='TRIA_DOWN')
row = layout.row(align=True)
row.prop(tool_settings, "lasso_face_up", icon='TRIA_UP')
row.prop(tool_settings, "lasso_face_down", text="", icon='TRIA_DOWN')
return dict(
idname="builtin.select_lasso",
label="Select Lasso",
@ -418,12 +468,23 @@ class _defs_view3d_select:
@ToolDef.from_fn
def circle():
def draw_settings(_context, layout, tool):
tool_settings = _context.tool_settings
props = tool.operator_properties("view3d.select_circle")
row = layout.row()
row.use_property_split = False
row.prop(props, "mode", text="", expand=True, icon_only=True)
layout.prop(props, "radius")
if _context.mode == 'OBJECT' and bpy.context.preferences.inputs.drag_select_control == 'USER_DRAG_TOOLSETTING':
layout.prop(tool_settings, "select_origin_circle")
if _context.mode == 'EDIT_MESH' and bpy.context.preferences.inputs.drag_select_control == 'USER_DRAG_TOOLSETTING':
layout.prop(tool_settings, "show_circle_options", toggle=True)
if tool_settings.show_circle_options:
row = layout.row(align=True)
row.prop(tool_settings, "circle_edge")
row = layout.row(align=True)
row.prop(tool_settings, "circle_face")
def draw_cursor(_context, tool, xy):
from gpu_extras.presets import draw_circle_2d
props = tool.operator_properties("view3d.select_circle")

View File

@ -496,6 +496,17 @@ class USERPREF_PT_edit_misc(EditingPanel, CenterAlignMixIn, Panel):
col = layout.column()
col.prop(edit, "sculpt_paint_overlay_color", text="Sculpt Overlay Color")
col.prop(edit, "node_margin", text="Node Auto-Offset Margin")
col.prop(edit, "adjustable_click_select")
colsub = col.column(align=True)
colsub.active = edit.adjustable_click_select
colsub.prop(edit, "select_unbiased")
colsub.prop(edit, "selection_radius")
col = layout.column()
col.prop(edit, "alternate_cursor")
colsub = col.column(align=True)
colsub.active = edit.alternate_cursor
colsub.prop(edit, "alternate_cursor_large")
# -----------------------------------------------------------------------------
@ -1559,6 +1570,8 @@ class USERPREF_PT_input_mouse(InputPanel, CenterAlignMixIn, Panel):
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
flow.prop(inputs, "click_drag_direction")
flow.prop(inputs, "drag_select_control")
flow.prop(inputs, "use_mouse_emulate_3_button")
if sys.platform[:3] != "win":
rowsub = flow.row()

View File

@ -889,9 +889,47 @@ class VIEW3D_HT_header(Header):
sub.active = overlay.show_overlays
sub.popover(panel="VIEW3D_PT_overlay", text="")
row = layout.row()
row = layout.row(align=True)
row.active = (object_mode == 'EDIT') or (shading.type in {'WIREFRAME', 'SOLID'})
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
_cls = ToolSelectPanelHelper._tool_class_from_space_type('VIEW_3D')
if tool_settings.workspace_tool_type == 'FALLBACK':
tool = _cls._tool_get_by_id_active(context, _cls.tool_fallback_id)[0].idname
else:
tool = ToolSelectPanelHelper.tool_active_from_context(context).idname
if object_mode in 'EDIT':
mode_match_auto_xray = tool_settings.auto_xray_edit and tool_settings.auto_xray
mode_match_select_through = tool_settings.select_through_edit and tool_settings.select_through
elif object_mode in 'OBJECT':
mode_match_auto_xray = tool_settings.auto_xray_object and tool_settings.auto_xray
mode_match_select_through = tool_settings.select_through_object and tool_settings.select_through
else:
mode_match_auto_xray = False
mode_match_select_through = False
if tool == "builtin.select_box":
depress_auto_xray = mode_match_auto_xray and tool_settings.auto_xray_box
depress_select_through = mode_match_select_through and tool_settings.select_through_box
elif tool == "builtin.select_lasso":
depress_auto_xray = mode_match_auto_xray and tool_settings.auto_xray_lasso
depress_select_through = mode_match_select_through and tool_settings.select_through_lasso
elif tool == "builtin.select_circle":
depress_auto_xray = mode_match_auto_xray and tool_settings.auto_xray_circle
depress_select_through = mode_match_select_through and tool_settings.select_through_circle
else:
depress_auto_xray = False
depress_select_through = False
if object_mode in 'EDIT' or object_mode in 'OBJECT':
if bpy.context.preferences.inputs.drag_select_control == 'USER_DRAG_TOOLSETTING':
if tool_settings.auto_xray_button:
row.operator("view3d.toggle_auto_xray", text="", icon='XRAY', depress=depress_auto_xray)
if tool_settings.select_through_button:
row.operator("view3d.toggle_select_through", text="", icon='XRAY', depress=depress_select_through)
# While exposing `shading.show_xray(_wireframe)` is correct.
# this hides the key shortcut from users: #70433.
if has_pose_mode:
@ -900,15 +938,29 @@ class VIEW3D_HT_header(Header):
draw_depressed = shading.show_xray_wireframe
else:
draw_depressed = shading.show_xray
row.operator(
"view3d.toggle_xray",
text="",
icon='XRAY',
depress=draw_depressed,
)
if bpy.context.preferences.inputs.drag_select_control == 'USER_DRAG_TOOLSETTING':
if tool_settings.xray_button:
row.operator("view3d.toggle_xray", text="", icon='XRAY', depress=draw_depressed)
elif not tool_settings.auto_xray_button and not tool_settings.select_through_button:
row.operator("view3d.toggle_xray", text="", icon='XRAY', depress=draw_depressed)
else:
row.operator("view3d.toggle_xray", text="", icon='XRAY', depress=draw_depressed)
row.popover(panel="VIEW3D_PT_xray", text="")
row = layout.row(align=True)
row.prop(shading, "type", text="", expand=True)
if tool_settings.shrink_shading_header:
if shading.type == 'SOLID':
shadicon = 'SHADING_SOLID'
elif shading.type == 'MATERIAL':
shadicon = 'SHADING_TEXTURE'
elif shading.type == 'RENDERED':
shadicon = 'SHADING_RENDERED'
else:
shadicon = 'SHADING_WIRE'
row.operator("view3d.toggle_xray", text="", icon=shadicon, depress=draw_depressed)
else:
row.prop(shading, "type", text="", expand=True)
sub = row.row(align=True)
# TODO, currently render shading type ignores mesh two-side, until it's supported
# show the shading popover which shows double-sided option.
@ -1025,6 +1077,99 @@ class ShowHideMenu:
layout.operator("%s.hide" % self._operator_name, text="Hide Unselected").unselected = True
# Custom Operators
class VIEW3D_gizmo_tweak(bpy.types.Operator):
"""tweak based on gizmo shown"""
bl_idname = "view3d.gizmo_tweak"
bl_label = "gizmo tweak"
from bpy.props import StringProperty, BoolProperty
tmode: StringProperty(name="Transform Mode")
release: BoolProperty(name="Confirm on Release")
def modal(self, context, event):
if event.type == 'MOUSEMOVE':
bpy.ops.transform.transform(
'INVOKE_DEFAULT',
mode=self.tmode,
release_confirm=self.release)
return {'FINISHED'}
return {'RUNNING_MODAL'}
def invoke(self, context, event):
if context.object:
if context.space_data.show_gizmo_object_translate==True:
self.tmode = 'TRANSLATION'
elif context.space_data.show_gizmo_object_rotate==True:
self.tmode = 'ROTATION'
elif context.space_data.show_gizmo_object_scale==True:
self.tmode = 'RESIZE'
else: self.tmode = 'TRANSLATION'
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
else:
self.report({'WARNING'}, "No active object, could not finish")
return {'CANCELLED'}
class VIEW3D_gizmo_move(bpy.types.Operator):
bl_idname = "view3d.gizmo_move"
bl_label = "gizmo move"
def invoke(self, context, event):
areas = bpy.context.workspace.screens[0].areas
for area in areas:
for space in area.spaces:
if space.type == 'VIEW_3D':
space.show_gizmo_object_translate^= True
space.show_gizmo_object_rotate = False
space.show_gizmo_object_scale = False
return {'FINISHED'}
class VIEW3D_gizmo_scale(bpy.types.Operator):
bl_idname = "view3d.gizmo_scale"
bl_label = "gizmo scale"
def invoke(self, context, event):
areas = bpy.context.workspace.screens[0].areas
for area in areas:
for space in area.spaces:
if space.type == 'VIEW_3D':
space.show_gizmo_object_translate = False
space.show_gizmo_object_rotate = False
space.show_gizmo_object_scale ^= True
return {'FINISHED'}
class VIEW3D_gizmo_rotate(bpy.types.Operator):
bl_idname = "view3d.gizmo_rotate"
bl_label = "gizmo rotate"
def invoke(self, context, event):
areas = bpy.context.workspace.screens[0].areas
for area in areas:
for space in area.spaces:
if space.type == 'VIEW_3D':
space.show_gizmo_object_translate = False
space.show_gizmo_object_rotate ^= True
space.show_gizmo_object_scale = False
return {'FINISHED'}
class VIEW3D_box_lasso(bpy.types.Operator):
bl_idname = "view3d.box_lasso"
bl_label = "box lasso"
def invoke(self, context, event):
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
tool = ToolSelectPanelHelper.tool_active_from_context(context)
if tool.idname == "builtin.select_box":
bpy.ops.wm.tool_set_by_id(name="builtin.select_lasso")
else:
bpy.ops.wm.tool_set_by_id(name="builtin.select_box")
return {'FINISHED'}
# Standard transforms which apply to all cases (mix-in class, not used directly).
class VIEW3D_MT_transform_base:
bl_label = "Transform"
@ -5888,6 +6033,12 @@ class VIEW3D_PT_shading(Panel):
def draw(self, _context):
layout = self.layout
layout.label(text="Viewport Shading")
tool_settings = _context.tool_settings
shading = VIEW3D_PT_shading.get_shading(_context)
layout.prop(tool_settings, "shrink_shading_header")
if tool_settings.shrink_shading_header:
layout.prop(shading, "type", text="", expand=True)
class VIEW3D_PT_shading_lighting(Panel):
@ -6068,17 +6219,7 @@ class VIEW3D_PT_shading_options(Panel):
row = col.row(align=True)
if shading.type == 'WIREFRAME':
row.prop(shading, "show_xray_wireframe", text="")
sub = row.row()
sub.active = shading.show_xray_wireframe
sub.prop(shading, "xray_alpha_wireframe", text="X-Ray")
elif shading.type == 'SOLID':
row.prop(shading, "show_xray", text="")
sub = row.row()
sub.active = shading.show_xray
sub.prop(shading, "xray_alpha", text="X-Ray")
# X-ray mode is off when alpha is 1.0
if shading.type == 'SOLID':
xray_active = shading.show_xray and shading.xray_alpha != 1
row = col.row(align=True)
@ -6263,6 +6404,83 @@ class VIEW3D_PT_gizmo_display(Panel):
col.prop(view, "show_gizmo_camera_dof_distance", text="Focus Distance")
class VIEW3D_PT_xray(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
bl_label = "X-Ray Settings"
bl_ui_units_x = 14
def draw(self, context):
layout = self.layout
layout.label(text="X-Ray Settings")
shading = VIEW3D_PT_shading.get_shading(context)
col = layout.column()
row = col.row(align=True)
if shading.type == 'WIREFRAME':
row.prop(shading, "show_xray_wireframe", text="")
sub = row.row()
sub.active = shading.show_xray_wireframe
sub.prop(shading, "xray_alpha_wireframe", text="X-Ray Wireframe")
elif shading.type == 'SOLID':
row.prop(shading, "show_xray", text="")
sub = row.row()
sub.active = shading.show_xray
sub.prop(shading, "xray_alpha", text="X-Ray Solid")
if bpy.context.preferences.inputs.drag_select_control == 'USER_DRAG_TOOLSETTING':
tool_settings = context.tool_settings
row = layout.row(align=True)
row = layout.row(align=True)
row = layout.row(align=True)
row = layout.row(heading="Automatic X-Ray")
row.prop(tool_settings, "ui_prop", text="", emboss=False)
row = layout.row(align=True)
row.prop(tool_settings, "auto_xray", text="Enable")
sub = row.row(align=True)
sub.active = tool_settings.auto_xray
sub.prop(tool_settings, "auto_xray_object", text="Object")
sub.prop(tool_settings, "auto_xray_edit", text="Edit")
row = layout.row(align=True)
sub = row.row(align=True)
sub.active = tool_settings.auto_xray
sub.prop(tool_settings, "auto_xray_box", text="Box", toggle=True)
sub.prop(tool_settings, "auto_xray_lasso", text="Lasso", toggle=True)
sub.prop(tool_settings, "auto_xray_circle", text="Circle", toggle=True)
row = layout.row(align=True)
row = layout.row(align=True)
row = layout.row(align=True)
row = layout.row(heading="Select Through")
row.prop(tool_settings, "ui_prop", text="", emboss=False)
row = layout.row(align=True)
row.prop(tool_settings, "select_through", text="Enable")
sub = row.row(align=True)
sub.active = tool_settings.select_through
sub.prop(tool_settings, "select_through_object", text="Object")
sub.prop(tool_settings, "select_through_edit", text="Edit")
row = layout.row(align=True)
sub = row.row(align=True)
sub.active = tool_settings.select_through
sub.prop(tool_settings, "select_through_box", text="Box", toggle=True)
sub.prop(tool_settings, "select_through_lasso", text="Lasso", toggle=True)
sub.prop(tool_settings, "select_through_circle", text="Circle", toggle=True)
row = layout.row(align=True)
row = layout.row(align=True)
row = layout.row(align=True)
row = layout.row(heading="Header Buttons")
row.prop(tool_settings, "ui_prop", text="", emboss=False)
row = layout.row(align=True)
row.prop(tool_settings, "auto_xray_button", text="Auto X-Ray", toggle=True)
row.prop(tool_settings, "select_through_button", text="Select Through", toggle=True)
row.prop(tool_settings, "xray_button", text="X-Ray", toggle=True)
class VIEW3D_PT_overlay(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
@ -8185,6 +8403,11 @@ classes = (
VIEW3D_MT_sculpt_gpencil_automasking_pie,
VIEW3D_MT_wpaint_vgroup_lock_pie,
VIEW3D_MT_sculpt_face_sets_edit_pie,
VIEW3D_gizmo_tweak,
VIEW3D_gizmo_move,
VIEW3D_gizmo_scale,
VIEW3D_gizmo_rotate,
VIEW3D_box_lasso,
VIEW3D_MT_sculpt_curves,
VIEW3D_PT_active_tool,
VIEW3D_PT_active_tool_duplicate,
@ -8209,6 +8432,7 @@ classes = (
VIEW3D_PT_shading_render_pass,
VIEW3D_PT_shading_compositor,
VIEW3D_PT_gizmo_display,
VIEW3D_PT_xray,
VIEW3D_PT_overlay,
VIEW3D_PT_overlay_guides,
VIEW3D_PT_overlay_object,

View File

@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
import bpy
from bpy.types import Menu, Panel, UIList, WindowManager
from bl_ui.properties_grease_pencil_common import (
GreasePencilSculptAdvancedPanel,
@ -153,7 +154,7 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
bl_context = ".mesh_edit" # dot on purpose (access from topbar)
bl_label = "Options"
bl_options = {'DEFAULT_CLOSED'}
bl_ui_units_x = 12
bl_ui_units_x = 15
@classmethod
def poll(cls, context):
@ -169,6 +170,7 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
ob = context.active_object
mesh = ob.data
row = layout.row(align=True)
row = layout.row(align=True, heading="Transform")
row.prop(tool_settings, "use_transform_correct_face_attributes")
@ -220,6 +222,39 @@ class VIEW3D_PT_tools_meshedit_options_automerge(View3DPanel, Panel):
col.prop(tool_settings, "double_threshold", text="Threshold")
class VIEW3D_PT_tools_meshedit_options_viewport_facing_select(View3DPanel, Panel):
bl_category = "Tool"
bl_context = ".mesh_edit" # dot on purpose (access from topbar)
bl_label = "Viewport Facing Select"
bl_parent_id = "VIEW3D_PT_tools_meshedit_options"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
return context.active_object
def draw_header(self, context):
tool_settings = context.tool_settings
self.layout.prop(tool_settings, "viewport_facing_select", text="", toggle=False)
def draw(self, context):
layout = self.layout
tool_settings = context.tool_settings
layout.use_property_split = True
layout.use_property_decorate = False
col = layout.column()
col.active = tool_settings.viewport_facing_select
col.prop(tool_settings, "viewport_facing_select_mode")
col.prop(tool_settings, "viewport_facing_select_threshold", text="Threshold")
col.prop(tool_settings, "viewport_facing_select_vert")
col.prop(tool_settings, "viewport_facing_select_edge")
col.prop(tool_settings, "viewport_facing_select_face")
# ********** default tools for editmode_armature ****************
@ -2364,6 +2399,7 @@ classes = (
VIEW3D_PT_tools_object_options_transform,
VIEW3D_PT_tools_meshedit_options,
VIEW3D_PT_tools_meshedit_options_automerge,
VIEW3D_PT_tools_meshedit_options_viewport_facing_select,
VIEW3D_PT_tools_armatureedit_options,
VIEW3D_PT_tools_posemode_options,

View File

@ -25,7 +25,8 @@ bool BLI_lasso_is_edge_inside(const int mcoords[][2],
int y0,
int x1,
int y1,
int error_value);
int error_value,
bool fully_inside);
#ifdef __cplusplus
}

View File

@ -55,7 +55,8 @@ bool BLI_lasso_is_edge_inside(const int mcoords[][2],
int y0,
int x1,
int y1,
const int error_value)
const int error_value,
bool fully_inside)
{
if (x0 == error_value || x1 == error_value || mcoords_len == 0) {
@ -64,23 +65,31 @@ bool BLI_lasso_is_edge_inside(const int mcoords[][2],
const int v1[2] = {x0, y0}, v2[2] = {x1, y1};
/* check points in lasso */
if (BLI_lasso_is_point_inside(mcoords, mcoords_len, v1[0], v1[1], error_value)) {
return true;
}
if (BLI_lasso_is_point_inside(mcoords, mcoords_len, v2[0], v2[1], error_value)) {
/* enclosed faces only checks for both points inside selection area */
if (BLI_lasso_is_point_inside(mcoords, mcoords_len, v1[0], v1[1], error_value) &&
BLI_lasso_is_point_inside(mcoords, mcoords_len, v2[0], v2[1], error_value)) {
return true;
}
/* no points in lasso, so we have to intersect with lasso edge */
if (isect_seg_seg_v2_int(mcoords[0], mcoords[mcoords_len - 1], v1, v2) > 0) {
return true;
}
for (uint a = 0; a < mcoords_len - 1; a++) {
if (isect_seg_seg_v2_int(mcoords[a], mcoords[a + 1], v1, v2) > 0) {
if (!fully_inside) {
/* check points in lasso */
if (BLI_lasso_is_point_inside(mcoords, mcoords_len, v1[0], v1[1], error_value)) {
return true;
}
if (BLI_lasso_is_point_inside(mcoords, mcoords_len, v2[0], v2[1], error_value)) {
return true;
}
/* no points in lasso, so we have to intersect with lasso edge */
if (isect_seg_seg_v2_int(mcoords[0], mcoords[mcoords_len - 1], v1, v2) > 0) {
return true;
}
for (unsigned int a = 0; a < mcoords_len - 1; a++) {
if (isect_seg_seg_v2_int(mcoords[a], mcoords[a + 1], v1, v2) > 0) {
return true;
}
}
}
return false;

View File

@ -373,6 +373,54 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene)
if (idprop) {
IDP_ClearProperty(idprop);
}
/* Mesh select. */
ts->box_drag_direction = 1;
ts->lasso_drag_direction = 1;
ts->box_edge = 1;
ts->box_edge_left = 1;
ts->box_edge_right = 1;
ts->box_edge_up = 1;
ts->box_edge_down = 1;
ts->box_face = 1;
ts->box_face_left = 1;
ts->box_face_right = 1;
ts->box_face_up = 1;
ts->box_face_down = 1;
ts->lasso_edge = 1;
ts->lasso_edge_left = 1;
ts->lasso_edge_right = 1;
ts->lasso_edge_up = 1;
ts->lasso_edge_down = 1;
ts->lasso_face = 1;
ts->lasso_face_left = 1;
ts->lasso_face_right = 1;
ts->lasso_face_up = 1;
ts->lasso_face_down = 1;
ts->circle_edge = 2;
ts->circle_face = 1;
/* X-Ray. */
ts->xray_button = true;
ts->auto_xray_object = true;
ts->auto_xray_edit = true;
ts->auto_xray_box = true;
ts->auto_xray_lasso = true;
ts->auto_xray_circle = true;
ts->select_through = true;
ts->select_through_object = true;
ts->select_through_box = true;
ts->select_through_lasso = true;
ts->select_through_circle = true;
/* Viewport-Facing Select */
ts->viewport_facing_select_mode = 1;
ts->viewport_facing_select_vert = 1;
ts->viewport_facing_select_edge = 1;
ts->viewport_facing_select_face = 1;
/* Object Origin Select */
ts->select_origin_circle = true;
}
void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)

View File

@ -434,9 +434,8 @@ void blo_do_versions_userdef(UserDef *userdef)
if (!USER_VERSION_ATLEAST(278, 6)) {
/* Clear preference flags for re-use. */
userdef->flag &= ~(USER_FLAG_NUMINPUT_ADVANCED | USER_FLAG_UNUSED_2 | USER_FLAG_UNUSED_3 |
USER_FLAG_UNUSED_6 | USER_FLAG_UNUSED_7 | USER_FLAG_UNUSED_9 |
USER_DEVELOPER_UI);
userdef->flag &= ~(USER_FLAG_NUMINPUT_ADVANCED | USER_FLAG_UNUSED_7 |
USER_FLAG_UNUSED_9 | USER_DEVELOPER_UI);
userdef->uiflag &= ~(USER_HEADER_BOTTOM);
userdef->transopts &= ~(USER_TR_UNUSED_2 | USER_TR_UNUSED_3 | USER_TR_UNUSED_4 |
USER_TR_UNUSED_6 | USER_TR_UNUSED_7);
@ -525,8 +524,6 @@ void blo_do_versions_userdef(UserDef *userdef)
copy_v3_fl3(userdef->light_ambient, 0.025000, 0.025000, 0.025000);
userdef->flag &= ~(USER_FLAG_UNUSED_4);
userdef->uiflag &= ~(USER_HEADER_FROM_PREF | USER_UIFLAG_UNUSED_12 | USER_UIFLAG_UNUSED_22);
}

View File

@ -705,7 +705,8 @@ bool select_lasso(const ViewContext &vc,
int(pos1_proj.y),
int(pos2_proj.x),
int(pos2_proj.y),
IS_CLIPPED)) {
IS_CLIPPED,
false)) {
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
changed = true;
break;

View File

@ -100,7 +100,10 @@ void ED_getTransformOrientationMatrix(const struct Scene *scene,
struct Object *ob,
struct Object *obedit,
short around,
float r_orientation_mat[3][3]);
float r_orientation_mat[3][3],
struct BMVert *eve,
struct BMEdge *eed,
struct BMFace *efa);
int BIF_countTransformOrientation(const struct bContext *C);

View File

@ -390,11 +390,20 @@ void mesh_foreachScreenEdge_clip_bb_segment(struct ViewContext *vc,
void *userData,
eV3DProjTest clip_flag);
void mesh_foreachScreenFace(
void mesh_foreachScreenFaceCenter(
struct ViewContext *vc,
void (*func)(void *userData, struct BMFace *efa, const float screen_co[2], int index),
void *userData,
eV3DProjTest clip_flag);
void mesh_foreachScreenFaceVerts(struct ViewContext *vc,
void (*func)(void *userData,
struct BMFace *efa,
const float screen_co[][2],
int total_count,
struct rctf *poly_rect,
bool *face_hit),
void *userData,
const eV3DProjTest clip_flag);
void nurbs_foreachScreenVert(struct ViewContext *vc,
void (*func)(void *userData,
struct Nurb *nu,

View File

@ -233,7 +233,8 @@ static void findnearestvert__doClosest(void *userData,
dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT && U.flag & USER_SELECT_UNBIASED) &&
data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
dist_test_bias += FIND_NEAR_SELECT_BIAS;
}
@ -438,7 +439,8 @@ static void find_nearest_edge__doClosest(
dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
if (data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT && U.flag & USER_SELECT_UNBIASED) &&
data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) {
dist_test_bias += FIND_NEAR_SELECT_BIAS;
}
@ -670,7 +672,8 @@ static void findnearestface__doClosest(void *userData,
dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co);
if (data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT && U.flag & USER_SELECT_UNBIASED) &&
data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
dist_test_bias += FIND_NEAR_SELECT_BIAS;
}
@ -706,27 +709,26 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
uint base_index = 0;
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
float dist_test;
float dist_test = 0.0f;
uint index;
BMFace *efa;
uint dist_px_manhattan_test = 0;
{
uint dist_px_manhattan_test = 0;
if (*dist_px_manhattan_p != 0.0f && (use_zbuf_single_px == false)) {
dist_px_manhattan_test = uint(
ED_view3d_backbuf_sample_size_clamp(vc->region, *dist_px_manhattan_p));
if (U.flag & USER_ADJUSTABLE_CLICK_SELECT ||
*dist_px_manhattan_p != 0.0f && (use_zbuf_single_px == false)) {
dist_px_manhattan_test = (uint)ED_view3d_backbuf_sample_size_clamp(vc->region,
*dist_px_manhattan_p);
}
DRW_select_buffer_context_create(bases, bases_len, SCE_SELECT_FACE);
if (dist_px_manhattan_test == 0) {
if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT) && dist_px_manhattan_test == 0) {
index = DRW_select_buffer_sample_point(vc->depsgraph, vc->region, vc->v3d, vc->mval);
dist_test = 0.0f;
}
else {
index = DRW_select_buffer_find_nearest_to_point(
vc->depsgraph, vc->region, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px_manhattan_test);
dist_test = dist_px_manhattan_test;
}
if (index) {
@ -752,7 +754,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
mesh_foreachScreenFace(
mesh_foreachScreenFaceCenter(
vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
*r_dist_center = data.dist_px_manhattan;
@ -760,7 +762,14 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
/* end exception */
if (efa) {
if (dist_test < *dist_px_manhattan_p) {
if (U.flag & USER_ADJUSTABLE_CLICK_SELECT && dist_px_manhattan_test < *dist_px_manhattan_p) {
if (r_base_index) {
*r_base_index = base_index;
}
*dist_px_manhattan_p = dist_px_manhattan_test;
return efa;
}
else if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT) && dist_test < *dist_px_manhattan_p) {
if (r_base_index) {
*r_base_index = base_index;
}
@ -804,7 +813,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
*dist_px_manhattan_p;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
mesh_foreachScreenFaceCenter(vc, findnearestface__doClosest, &data, clip_flag);
hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;

View File

@ -3847,6 +3847,61 @@ static void SCREEN_OT_repeat_history(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Repeat Tool Operator
* \{ */
static int repeat_tool_exec(bContext *C, wmOperator *UNUSED(op))
{
wmWindowManager *wm = CTX_wm_manager(C);
wmOperator *lastop = wm->operators.last;
/* Seek last registered operator */
while (lastop) {
if (lastop->type->flag & OPTYPE_REGISTER) {
if (STREQ(lastop->idname, "MESH_OT_delete") || STREQ(lastop->idname, "MESH_OT_select_all") ||
STREQ(lastop->idname, "MESH_OT_select_mode") ||
STREQ(lastop->idname, "OBJECT_OT_editmode_toggle") ||
STREQ(lastop->idname, "OBJECT_OT_select_all") ||
STREQ(lastop->idname, "TRANSFORM_OT_resize") ||
STREQ(lastop->idname, "TRANSFORM_OT_rotate") ||
STREQ(lastop->idname, "TRANSFORM_OT_trackball") ||
STREQ(lastop->idname, "TRANSFORM_OT_translate")) {
lastop = lastop->prev;
}
else {
printf(lastop->idname, "\n");
break;
}
}
else {
lastop = lastop->prev;
}
}
if (lastop) {
WM_operator_free_all_after(wm, lastop);
WM_operator_repeat_tool(C, lastop);
}
return OPERATOR_CANCELLED;
}
static void SCREEN_OT_repeat_tool(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Repeat Tool";
ot->description = "Repeat last tool";
ot->idname = "SCREEN_OT_repeat_tool";
/* api callbacks */
ot->exec = repeat_tool_exec;
ot->poll = ED_operator_screenactive;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Redo Operator
* \{ */
@ -5679,6 +5734,7 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(SCREEN_OT_actionzone);
WM_operatortype_append(SCREEN_OT_repeat_last);
WM_operatortype_append(SCREEN_OT_repeat_history);
WM_operatortype_append(SCREEN_OT_repeat_tool);
WM_operatortype_append(SCREEN_OT_redo_last);
/* Screen tools. */

View File

@ -1235,3 +1235,211 @@ void VIEW3D_OT_toggle_xray(wmOperatorType *ot)
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Toggle Automatic XRay
* \{ */
static int toggle_auto_xray_exec(bContext *C, wmOperator *op)
{
ScrArea *area = CTX_wm_area(C);
ToolSettings *ts = CTX_data_tool_settings(C);
Object *obedit = CTX_data_edit_object(C);
bToolRef *tref = area->runtime.tool;
const bool mode_match = obedit ? ts->auto_xray_edit : ts->auto_xray_object;
if (STREQ(tref->idname, "builtin.select_box") ||
STREQ(tref->idname_fallback, "builtin.select_box")) {
if (mode_match && ts->auto_xray && ts->auto_xray_box) {
ts->auto_xray ^= true;
}
else {
if (!mode_match) {
if (obedit) {
ts->auto_xray_edit ^= true;
}
else {
ts->auto_xray_object ^= true;
}
}
if (!ts->auto_xray) {
ts->auto_xray ^= true;
}
if (!ts->auto_xray_box) {
ts->auto_xray_box ^= true;
}
}
}
else if (STREQ(tref->idname, "builtin.select_lasso") ||
STREQ(tref->idname_fallback, "builtin.select_lasso")) {
if (mode_match && ts->auto_xray && ts->auto_xray_lasso) {
ts->auto_xray ^= true;
}
else {
if (!mode_match) {
if (obedit) {
ts->auto_xray_edit ^= true;
}
else {
ts->auto_xray_object ^= true;
}
}
if (!ts->auto_xray) {
ts->auto_xray ^= true;
}
if (!ts->auto_xray_lasso) {
ts->auto_xray_lasso ^= true;
}
}
}
else if (STREQ(tref->idname, "builtin.select_circle") ||
STREQ(tref->idname_fallback, "builtin.select_circle")) {
if (mode_match && ts->auto_xray && ts->auto_xray_circle) {
ts->auto_xray ^= true;
}
else {
if (!mode_match) {
if (obedit) {
ts->auto_xray_edit ^= true;
}
else {
ts->auto_xray_object ^= true;
}
}
if (!ts->auto_xray) {
ts->auto_xray ^= true;
}
if (!ts->auto_xray_circle) {
ts->auto_xray_circle ^= true;
}
}
}
ED_area_tag_redraw(area);
return OPERATOR_FINISHED;
}
void VIEW3D_OT_toggle_auto_xray(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Toggle Automatic X-Ray";
ot->idname = "VIEW3D_OT_toggle_auto_xray";
ot->description = "Transparent scene display during box, lasso, and circle select";
/* api callbacks */
ot->exec = toggle_auto_xray_exec;
ot->poll = ED_operator_view3d_active;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Toggle Select Through
* \{ */
static int toggle_select_through_exec(bContext *C, wmOperator *op)
{
ScrArea *area = CTX_wm_area(C);
ToolSettings *ts = CTX_data_tool_settings(C);
Object *obedit = CTX_data_edit_object(C);
bToolRef *tref = area->runtime.tool;
const bool mode_match = obedit ? ts->select_through_edit : ts->select_through_object;
if (STREQ(tref->idname, "builtin.select_box") ||
STREQ(tref->idname_fallback, "builtin.select_box")) {
if (mode_match && ts->select_through && ts->select_through_box) {
ts->select_through ^= true;
}
else {
if (!mode_match) {
if (obedit) {
ts->select_through_edit ^= true;
}
else {
ts->select_through_object ^= true;
}
}
if (!ts->select_through) {
ts->select_through ^= true;
}
if (!ts->select_through_box) {
ts->select_through_box ^= true;
}
}
}
else if (STREQ(tref->idname, "builtin.select_lasso") ||
STREQ(tref->idname_fallback, "builtin.select_lasso")) {
if (mode_match && ts->select_through && ts->select_through_lasso) {
ts->select_through ^= true;
}
else {
if (!mode_match) {
if (obedit) {
ts->select_through_edit ^= true;
}
else {
ts->select_through_object ^= true;
}
}
if (!ts->select_through) {
ts->select_through ^= true;
}
if (!ts->select_through_lasso) {
ts->select_through_lasso ^= true;
}
}
}
else if (STREQ(tref->idname, "builtin.select_circle") ||
STREQ(tref->idname_fallback, "builtin.select_circle")) {
if (mode_match && ts->select_through && ts->select_through_circle) {
ts->select_through ^= true;
}
else {
if (!mode_match) {
if (obedit) {
ts->select_through_edit ^= true;
}
else {
ts->select_through_object ^= true;
}
}
if (!ts->select_through) {
ts->select_through ^= true;
}
if (!ts->select_through_circle) {
ts->select_through_circle ^= true;
}
}
}
ED_area_tag_redraw(area);
return OPERATOR_FINISHED;
}
void VIEW3D_OT_toggle_select_through(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Toggle Select Through";
ot->idname = "VIEW3D_OT_toggle_select_through";
ot->description = "Select occluded objects and mesh elements with box, lasso, and circle select";
/* api callbacks */
ot->exec = toggle_select_through_exec;
ot->poll = ED_operator_view3d_active;
}
/** \} */

View File

@ -55,6 +55,8 @@ void VIEW3D_OT_render_border(struct wmOperatorType *ot);
void VIEW3D_OT_clear_render_border(struct wmOperatorType *ot);
void VIEW3D_OT_toggle_shading(struct wmOperatorType *ot);
void VIEW3D_OT_toggle_xray(struct wmOperatorType *ot);
void VIEW3D_OT_toggle_auto_xray(struct wmOperatorType *ot);
void VIEW3D_OT_toggle_select_through(struct wmOperatorType *ot);
/* view3d_draw.c */

View File

@ -13,6 +13,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_bitmap.h"
#include "BLI_math_geom.h"
#include "BLI_rect.h"
#include "BLI_utildefines.h"
@ -38,6 +39,8 @@
#include "ED_screen.h"
#include "ED_view3d.h"
#include "MEM_guardedalloc.h"
/* -------------------------------------------------------------------- */
/** \name Internal Clipping Utilities
* \{ */
@ -238,7 +241,7 @@ struct foreachScreenEdge_userData {
int content_planes_len;
};
struct foreachScreenFace_userData {
struct foreachScreenFaceCenter_userData {
void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index);
void *userData;
ViewContext vc;
@ -536,12 +539,12 @@ void mesh_foreachScreenEdge_clip_bb_segment(ViewContext *vc,
/** \name Edit-Mesh: For Each Screen Face Center
* \{ */
static void mesh_foreachScreenFace__mapFunc(void *userData,
static void mesh_foreachScreenFaceCenter__mapFunc(void *userData,
int index,
const float cent[3],
const float /*no*/[3])
{
foreachScreenFace_userData *data = static_cast<foreachScreenFace_userData *>(userData);
foreachScreenFaceCenter_userData *data = static_cast<foreachScreenFaceCenter_userData *>(userData);
BMFace *efa = BM_face_at_index(data->vc.em->bm, index);
if (UNLIKELY(BM_elem_flag_test(efa, BM_ELEM_HIDDEN))) {
return;
@ -556,14 +559,14 @@ static void mesh_foreachScreenFace__mapFunc(void *userData,
data->func(data->userData, efa, screen_co, index);
}
void mesh_foreachScreenFace(
void mesh_foreachScreenFaceCenter(
ViewContext *vc,
void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index),
void *userData,
const eV3DProjTest clip_flag)
{
BLI_assert((clip_flag & V3D_PROJ_TEST_CLIP_CONTENT) == 0);
foreachScreenFace_userData data;
foreachScreenFaceCenter_userData data;
Mesh *me = editbmesh_get_eval_cage_from_orig(
vc->depsgraph, vc->scene, vc->obedit, &CD_MASK_BAREMESH);
@ -580,16 +583,150 @@ void mesh_foreachScreenFace(
const int face_dot_tags_num = me->runtime->subsurf_face_dot_tags.size();
if (face_dot_tags_num && (face_dot_tags_num != me->totvert)) {
BKE_mesh_foreach_mapped_subdiv_face_center(
me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
me, mesh_foreachScreenFaceCenter__mapFunc, &data, MESH_FOREACH_NOP);
}
else {
BKE_mesh_foreach_mapped_face_center(
me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
me, mesh_foreachScreenFaceCenter__mapFunc, &data, MESH_FOREACH_NOP);
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Edit-Mesh: For Each Screen Face Verts
* \{ */
void mesh_foreachScreenFaceVerts(ViewContext *vc,
void (*func)(void *userData,
struct BMFace *efa,
const float screen_co[][2],
int total_count,
rctf *screen_rect,
bool *face_hit),
void *userData,
const eV3DProjTest clip_flag)
{
ED_view3d_check_mats_rv3d(vc->rv3d);
BM_mesh_elem_table_ensure(vc->em->bm, BM_FACE);
BMFace *efa;
const BMesh *bm = vc->em->bm;
float temp_screen_co[2];
int total_length = 0;
float(*screen_coords)[2] = static_cast<float(*)[2]>(
MEM_mallocN(sizeof(float) * 2 * bm->totvert, __func__));
int face_screen_verts_size = 4;
float(*face_screen_verts)[2] = static_cast<float(*)[2]>(
MEM_mallocN(sizeof(int) * 2 * face_screen_verts_size, __func__));
/* This makes only sense on subdivided meshes.*/
BLI_bitmap *faces_visited;
int cage_index = BKE_modifiers_get_cage_index(vc->scene, vc->obedit, NULL, 1);
const bool cage_display = cage_index != -1;
if (cage_display) {
faces_visited = BLI_BITMAP_NEW((size_t)bm->totface, __func__);
}
/* Transform and store all visible verts into screen coords. */
for (int i = 0; i < bm->totvert; i++) {
BMVert *bmvert = BM_vert_at_index(vc->em->bm, i);
if (BM_elem_flag_test_bool(bmvert, BM_ELEM_HIDDEN)) {
continue;
}
if (ED_view3d_project_float_object(vc->region, bmvert->co, temp_screen_co, clip_flag) ==
V3D_PROJ_RET_OK) {
screen_coords[i][0] = temp_screen_co[0];
screen_coords[i][1] = temp_screen_co[1];
}
else {
screen_coords[i][0] = 0.0f;
screen_coords[i][1] = 0.0f;
}
}
const int *poly_index = static_cast<const int *>(CustomData_get_layer(&bm->pdata, CD_ORIGINDEX));
const bool use_original_index = poly_index != 0;
rctf poly_rect_data;
rctf *poly_rect = &poly_rect_data;
bool face_hit = false;
/* Collect polygon verts and send off per poly callback. */
for (int i = 0; i < bm->totface; i++) {
int original_index = i;
if (use_original_index) {
original_index = *poly_index++;
if (original_index == ORIGINDEX_NONE) {
continue;
}
}
if (cage_display && BLI_BITMAP_TEST(faces_visited, original_index)) {
continue;
}
efa = BM_face_at_index(vc->em->bm, original_index);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
if (bm->totvert > face_screen_verts_size) {
face_screen_verts_size = bm->totvert;
MEM_freeN(face_screen_verts);
face_screen_verts = static_cast<float(*)[2]>(
MEM_mallocN(sizeof(float) * 2 * face_screen_verts_size, __func__));
}
total_length = 0;
BLI_rctf_init_minmax(poly_rect);
bool skip = false;
BMLoop *l_first, *l_iter;
int j = 0;
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
do {
const int k = BM_elem_index_get(l_iter->v);
face_screen_verts[j][0] = screen_coords[k][0];
face_screen_verts[j][1] = screen_coords[k][1];
/* Ignore polygons with invalid screen coords.*/
if (face_screen_verts[j][0] == 0.0f && face_screen_verts[j][1] == 0.0f) {
skip = true;
break;
}
total_length++, j++;
BLI_rctf_do_minmax_v(poly_rect, screen_coords[k]);
} while ((l_iter = l_iter->next) != l_first);
if (skip) {
continue;
}
face_hit = false;
func(
userData, efa, (const float(*)[2])face_screen_verts, total_length, poly_rect, &face_hit);
if (cage_display && face_hit) {
BLI_BITMAP_ENABLE(faces_visited, original_index);
}
}
}
if (cage_display) {
MEM_freeN(faces_visited);
}
MEM_freeN(screen_coords);
MEM_freeN(face_screen_verts);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Edit-Nurbs: For Each Screen Vertex
* \{ */

View File

@ -99,6 +99,26 @@ void view3d_operator_properties_common(wmOperatorType *ot, const enum eV3D_OpPro
if (flag & V3D_OP_PROP_USE_MOUSE_INIT) {
WM_operator_properties_use_cursor_init(ot);
}
if (flag & V3D_OP_PROP_FRAME_SELECTED_DISTANCE) {
PropertyRNA *prop;
prop = RNA_def_int(ot->srna,
"frame_selected_distance",
0,
0,
1000,
"Camera Offset",
"Distance to put camera from selected",
0,
1000);
}
if (flag & V3D_OP_PROP_ZOOM_SPEED) {
PropertyRNA *prop;
prop = RNA_def_float(
ot->srna, "zoom_speed", 1.2f, 1.001, 10, "Zoom Speed", "Speed to zoom camera", 1.001f, 10);
}
}
/** \} */
@ -652,7 +672,8 @@ static void view3d_from_minmax(bContext *C,
const float min[3],
const float max[3],
bool ok_dist,
const int smooth_viewtx)
const int smooth_viewtx,
const int view_dist)
{
RegionView3D *rv3d = region->regiondata;
float afm[3];
@ -695,7 +716,7 @@ static void view3d_from_minmax(bContext *C,
v3d, region, depsgraph, persp, true, (size / 2) * VIEW3D_MARGIN);
if (rv3d->is_persp) {
/* don't zoom closer than the near clipping plane */
new_dist = max_ff(new_dist, v3d->clip_start * 1.5f);
new_dist = max_ff(new_dist, v3d->clip_start * 1.5f + view_dist);
}
}
}
@ -741,7 +762,8 @@ static void view3d_from_minmax_multi(bContext *C,
const float min[3],
const float max[3],
const bool ok_dist,
const int smooth_viewtx)
const int smooth_viewtx,
const int view_dist)
{
ScrArea *area = CTX_wm_area(C);
ARegion *region;
@ -751,7 +773,7 @@ static void view3d_from_minmax_multi(bContext *C,
/* when using all regions, don't jump out of camera view,
* but _do_ allow locked cameras to be moved */
if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
view3d_from_minmax(C, v3d, region, min, max, ok_dist, smooth_viewtx);
view3d_from_minmax(C, v3d, region, min, max, ok_dist, smooth_viewtx, view_dist);
}
}
}
@ -831,10 +853,10 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
ED_view3d_smooth_view_undo_begin(C, area);
if (use_all_regions) {
view3d_from_minmax_multi(C, v3d, min, max, true, smooth_viewtx);
view3d_from_minmax_multi(C, v3d, min, max, true, smooth_viewtx, 0);
}
else {
view3d_from_minmax(C, v3d, region, min, max, true, smooth_viewtx);
view3d_from_minmax(C, v3d, region, min, max, true, smooth_viewtx, 0);
}
ED_view3d_smooth_view_undo_end(C, area, op->type->name, false);
@ -893,6 +915,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
/* any one of the regions may be locked */
(use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA));
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
const int view_dist = RNA_int_get(op->ptr, "frame_selected_distance");
INIT_MINMAX(min, max);
if (is_face_map) {
@ -1007,10 +1030,10 @@ static int viewselected_exec(bContext *C, wmOperator *op)
ED_view3d_smooth_view_undo_begin(C, area);
if (use_all_regions) {
view3d_from_minmax_multi(C, v3d, min, max, ok_dist, smooth_viewtx);
view3d_from_minmax_multi(C, v3d, min, max, ok_dist, smooth_viewtx, view_dist);
}
else {
view3d_from_minmax(C, v3d, region, min, max, ok_dist, smooth_viewtx);
view3d_from_minmax(C, v3d, region, min, max, ok_dist, smooth_viewtx, view_dist);
}
ED_view3d_smooth_view_undo_end(C, area, op->type->name, false);
@ -1033,7 +1056,8 @@ void VIEW3D_OT_view_selected(wmOperatorType *ot)
ot->flag = 0;
/* properties */
view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS);
view3d_operator_properties_common(
ot, V3D_OP_PROP_USE_ALL_REGIONS | V3D_OP_PROP_FRAME_SELECTED_DISTANCE);
}
/** \} */
@ -1192,7 +1216,7 @@ static int view_axis_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
/* same as transform gizmo when normal is set */
ED_getTransformOrientationMatrix(
scene, view_layer, v3d, obact, obedit, V3D_AROUND_ACTIVE, twmat);
scene, view_layer, v3d, obact, obedit, V3D_AROUND_ACTIVE, twmat, NULL, NULL, NULL);
align_quat = align_quat_buf;
mat3_to_quat(align_quat, twmat);
invert_qt_normalized(align_quat);

View File

@ -34,6 +34,8 @@ enum eV3D_OpPropFlag {
V3D_OP_PROP_DELTA = (1 << 1),
V3D_OP_PROP_USE_ALL_REGIONS = (1 << 2),
V3D_OP_PROP_USE_MOUSE_INIT = (1 << 3),
V3D_OP_PROP_FRAME_SELECTED_DISTANCE = (1 << 4),
V3D_OP_PROP_ZOOM_SPEED = (1 << 5),
};
enum {

View File

@ -506,9 +506,10 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
}
ED_view3d_dist_range_get(v3d, dist_range);
const float zoom_speed = RNA_float_get(op->ptr, "zoom_speed");
if (delta < 0) {
const float step = 1.2f;
const float step = zoom_speed;
if (use_cam_zoom) {
view_zoom_to_window_xy_camera(scene, depsgraph, v3d, region, step, zoom_xy);
}
@ -519,7 +520,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
}
}
else {
const float step = 1.0f / 1.2f;
const float step = 1.0f / zoom_speed;
if (use_cam_zoom) {
view_zoom_to_window_xy_camera(scene, depsgraph, v3d, region, step, zoom_xy);
}
@ -631,8 +632,9 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY;
/* properties */
view3d_operator_properties_common(
ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT);
view3d_operator_properties_common(ot,
V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO |
V3D_OP_PROP_USE_MOUSE_INIT | V3D_OP_PROP_ZOOM_SPEED);
}
/** \} */

View File

@ -200,6 +200,8 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_toggle_shading);
WM_operatortype_append(VIEW3D_OT_toggle_xray);
WM_operatortype_append(VIEW3D_OT_toggle_matcap_flip);
WM_operatortype_append(VIEW3D_OT_toggle_auto_xray);
WM_operatortype_append(VIEW3D_OT_toggle_select_through);
WM_operatortype_append(VIEW3D_OT_ruler_add);
WM_operatortype_append(VIEW3D_OT_ruler_remove);

File diff suppressed because it is too large Load Diff

View File

@ -516,7 +516,8 @@ short ED_transform_calc_orientation_from_type_ex(const Scene *scene,
}
case V3D_ORIENT_NORMAL: {
if (obedit || (ob && ob->mode & OB_MODE_POSE)) {
ED_getTransformOrientationMatrix(scene, view_layer, v3d, ob, obedit, pivot_point, r_mat);
ED_getTransformOrientationMatrix(
scene, view_layer, v3d, ob, obedit, pivot_point, r_mat, NULL, NULL, NULL);
break;
}
/* No break we define 'normal' as 'local' in Object mode. */
@ -529,7 +530,8 @@ short ED_transform_calc_orientation_from_type_ex(const Scene *scene,
* use the active pones axis for display #33575, this works as expected on a single
* bone and users who select many bones will understand what's going on and what local
* means when they start transforming. */
ED_getTransformOrientationMatrix(scene, view_layer, v3d, ob, obedit, pivot_point, r_mat);
ED_getTransformOrientationMatrix(
scene, view_layer, v3d, ob, obedit, pivot_point, r_mat, NULL, NULL, NULL);
}
else {
transform_orientations_create_from_axis(r_mat, UNPACK3(ob->object_to_world));
@ -752,13 +754,18 @@ int getTransformOrientation_ex(const Scene *scene,
struct Object *obedit,
float normal[3],
float plane[3],
const short around)
const short around,
struct BMVert *eve,
struct BMEdge *eed,
struct BMFace *efa)
{
int result = ORIENTATION_NONE;
const bool activeOnly = (around == V3D_AROUND_ACTIVE);
zero_v3(normal);
zero_v3(plane);
if (efa == NULL && eed == NULL) {
zero_v3(normal);
zero_v3(plane);
}
if (obedit) {
float imat[3][3], mat[3][3];
@ -777,20 +784,72 @@ int getTransformOrientation_ex(const Scene *scene,
float vec[3] = {0, 0, 0};
/* USE LAST SELECTED WITH ACTIVE */
if (activeOnly && BM_select_history_active_get(em->bm, &ese)) {
BM_editselection_normal(&ese, normal);
BM_editselection_plane(&ese, plane);
if (efa != NULL || eed != NULL || eve != NULL ||
activeOnly && BM_select_history_active_get(em->bm, &ese)) {
if (efa != NULL) {
copy_v3_v3(normal, efa->no);
BM_face_calc_tangent_auto(efa, plane);
result = ORIENTATION_FACE;
}
else if (eed != NULL) {
float eed_plane[3];
float vec[3];
add_v3_v3v3(normal, eed->v1->no, eed->v2->no);
sub_v3_v3v3(eed_plane, eed->v2->co, eed->v1->co);
cross_v3_v3v3(vec, normal, eed_plane);
cross_v3_v3v3(normal, eed_plane, vec);
normalize_v3(normal);
switch (ese.htype) {
case BM_VERT:
result = ORIENTATION_VERT;
break;
case BM_EDGE:
result = ORIENTATION_EDGE;
break;
case BM_FACE:
result = ORIENTATION_FACE;
break;
if (BM_edge_is_boundary(eed)) {
sub_v3_v3v3(plane, eed->l->v->co, eed->l->next->v->co);
}
else {
if (eed->v2->co[1] > eed->v1->co[1]) {
sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
}
else {
sub_v3_v3v3(plane, eed->v1->co, eed->v2->co);
}
}
normalize_v3(plane);
result = ORIENTATION_EDGE;
}
else if (eve != NULL) {
copy_v3_v3(normal, eve->no);
if (eve->e) {
float vert1v3[3] = {eve->e->v1->co[0], eve->e->v1->co[1], eve->e->v1->co[2]};
float vert2v3[3] = {eve->e->v2->co[0], eve->e->v2->co[1], eve->e->v2->co[2]};
sub_v3_v3v3(plane, vert2v3, vert1v3);
}
else {
if (eve->no[0] < 0.5f) {
vec[0] = 1.0f;
}
else if (eve->no[1] < 0.5f) {
vec[1] = 1.0f;
}
else {
vec[2] = 1.0f;
}
cross_v3_v3v3(plane, eve->no, vec);
}
normalize_v3(plane);
result = ORIENTATION_VERT;
}
else {
BM_editselection_normal(&ese, normal);
BM_editselection_plane(&ese, plane);
switch (ese.htype) {
case BM_VERT:
result = ORIENTATION_VERT;
break;
case BM_EDGE:
result = ORIENTATION_EDGE;
break;
case BM_FACE:
result = ORIENTATION_FACE;
break;
}
}
}
else {
@ -1289,7 +1348,8 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3])
ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = CTX_wm_view3d(C);
return getTransformOrientation_ex(scene, view_layer, v3d, obact, obedit, normal, plane, around);
return getTransformOrientation_ex(
scene, view_layer, v3d, obact, obedit, normal, plane, around, NULL, NULL, NULL);
}
void ED_getTransformOrientationMatrix(const Scene *scene,
@ -1298,14 +1358,32 @@ void ED_getTransformOrientationMatrix(const Scene *scene,
Object *ob,
Object *obedit,
const short around,
float r_orientation_mat[3][3])
float r_orientation_mat[3][3],
struct BMVert *eve,
struct BMEdge *eed,
struct BMFace *efa)
{
float normal[3] = {0.0, 0.0, 0.0};
float plane[3] = {0.0, 0.0, 0.0};
int type;
type = getTransformOrientation_ex(scene, view_layer, v3d, ob, obedit, normal, plane, around);
if (efa != NULL) {
type = getTransformOrientation_ex(
scene, view_layer, v3d, ob, obedit, normal, plane, around, NULL, NULL, efa);
}
else if (eed != NULL) {
type = getTransformOrientation_ex(
scene, view_layer, v3d, ob, obedit, normal, plane, around, NULL, eed, NULL);
}
else if (eve != NULL) {
type = getTransformOrientation_ex(
scene, view_layer, v3d, ob, obedit, normal, plane, around, eve, NULL, NULL);
}
else {
type = getTransformOrientation_ex(
scene, view_layer, v3d, ob, obedit, normal, plane, around, NULL, NULL, NULL);
}
/* Fallback, when the plane can't be calculated. */
if (ORIENTATION_USE_PLANE(type) && is_zero_v3(plane)) {

View File

@ -3947,8 +3947,12 @@ static bool do_lasso_select_mesh_uv_is_edge_inside(const ARegion *region,
if (UI_view2d_view_to_region_segment_clip(
&region->v2d, co_test_a, co_test_b, co_screen_a, co_screen_b) &&
BLI_rcti_isect_segment(clip_rect, co_screen_a, co_screen_b) &&
BLI_lasso_is_edge_inside(
mcoords, mcoords_len, UNPACK2(co_screen_a), UNPACK2(co_screen_b), V2D_IS_CLIPPED)) {
BLI_lasso_is_edge_inside(mcoords,
mcoords_len,
UNPACK2(co_screen_a),
UNPACK2(co_screen_b),
V2D_IS_CLIPPED,
false)) {
return true;
}
return false;

View File

@ -366,6 +366,54 @@
/* UV painting */ \
.uv_sculpt_settings = 0, \
.uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN, \
\
/* Mesh Select */ \
.box_drag_direction = 1, \
.lasso_drag_direction = 1, \
.box_edge = 1, \
.box_edge_left = 1, \
.box_edge_right = 1, \
.box_edge_up = 1, \
.box_edge_down = 1, \
.box_face = 1, \
.box_face_left = 1, \
.box_face_right = 1, \
.box_face_up = 1, \
.box_face_down = 1, \
.lasso_edge = 1, \
.lasso_edge_left = 1, \
.lasso_edge_right = 1, \
.lasso_edge_up = 1, \
.lasso_edge_down = 1, \
.lasso_face = 1, \
.lasso_face_left = 1, \
.lasso_face_right = 1, \
.lasso_face_up = 1, \
.lasso_face_down = 1, \
.circle_edge = 2, \
.circle_face = 1, \
\
/* X-Ray */ \
.xray_button = true, \
.auto_xray_object = true, \
.auto_xray_edit = true, \
.auto_xray_box = true, \
.auto_xray_lasso = true, \
.auto_xray_circle = true, \
.select_through = true, \
.select_through_object = true, \
.select_through_box = true, \
.select_through_lasso = true, \
.select_through_circle = true, \
\
/* Viewport-Facing Select */ \
.viewport_facing_select_mode = 1, \
.viewport_facing_select_vert = 1, \
.viewport_facing_select_edge = 1, \
.viewport_facing_select_face = 1, \
\
/* Object Origin Select */ \
.select_origin_circle = true, \
}
/* clang-format off */

View File

@ -1557,7 +1557,40 @@ typedef struct ToolSettings {
char gpencil_v3d_align;
/** General 2D Editor. */
char gpencil_v2d_align;
char _pad0[2];
/* Give the UI an empty prop to expand formatting */
char ui_prop;
/* X-Ray Options */
char xray_button;
char auto_xray;
char auto_xray_button;
char auto_xray_reset;
char auto_xray_object;
char auto_xray_edit;
char auto_xray_box;
char auto_xray_lasso;
char auto_xray_circle;
char select_through;
char select_through_button;
char select_through_object;
char select_through_edit;
char select_through_box;
char select_through_lasso;
char select_through_circle;
/* Mesh Normal Direction Select */
char viewport_facing_select;
char viewport_facing_select_mode;
float viewport_facing_select_threshold;
char viewport_facing_select_vert;
char viewport_facing_select_edge;
char viewport_facing_select_face;
/* object origin select */
char select_origin_box;
char select_origin_circle;
char _pad0[6];
/* Annotations. */
/** Stroke placement settings - 3D View. */
@ -1682,7 +1715,41 @@ typedef struct ToolSettings {
/** Normal Editing. */
float normal_vector[3];
char _pad6[4];
/** Mesh Select Options. */
char box_drag_direction;
char lasso_drag_direction;
char box_direction_upright;
char lasso_direction_upright;
char box_edge;
char box_edge_left;
char box_edge_right;
char box_edge_up;
char box_edge_down;
char box_face;
char box_face_left;
char box_face_right;
char box_face_up;
char box_face_down;
char lasso_edge;
char lasso_edge_left;
char lasso_edge_right;
char lasso_edge_up;
char lasso_edge_down;
char lasso_face;
char lasso_face_left;
char lasso_face_right;
char lasso_face_up;
char lasso_face_down;
char circle_edge;
char circle_face;
char show_box_options;
char show_lasso_options;
char show_circle_options;
/* Combine shading and xray header buttons */
char shrink_shading_header;
char _pad6[6];
/**
* Custom Curve Profile for bevel tool:
@ -2331,6 +2398,78 @@ typedef enum eSnapTransformMode {
SCE_SNAP_TRANSFORM_MODE_SCALE = (1 << 2),
} eSnapTransformMode;
/** #ToolSettings.viewport_facing_mode */
enum {
VIEWPORT_FACING_SELECT_BOTH = (1 << 0),
VIEWPORT_FACING_SELECT_NEAR = (1 << 1),
VIEWPORT_FACING_SELECT_XRAY = (1 << 2),
};
/** #ToolSettings.viewport_facing_select_vert */
enum {
VIEWPORT_FACING_SELECT_FRONT_VERTS = (1 << 0),
VIEWPORT_FACING_SELECT_FRONT_VERTS_FACE = (1 << 1),
VIEWPORT_FACING_SELECT_REAR_VERTS = (1 << 2),
VIEWPORT_FACING_SELECT_REAR_VERTS_FACE = (1 << 3),
VIEWPORT_FACING_SELECT_ALL_VERTS = (1 << 4),
};
/** #ToolSettings.viewport_facing_select_edge */
enum {
VIEWPORT_FACING_SELECT_FRONT_EDGES = (1 << 0),
VIEWPORT_FACING_SELECT_FRONT_EDGES_FACE = (1 << 1),
VIEWPORT_FACING_SELECT_REAR_EDGES = (1 << 2),
VIEWPORT_FACING_SELECT_REAR_EDGES_FACE = (1 << 3),
VIEWPORT_FACING_SELECT_ALL_EDGES = (1 << 4),
};
/** #ToolSettings.viewport_facing_select_face */
enum {
VIEWPORT_FACING_SELECT_FRONT_FACES = (1 << 0),
VIEWPORT_FACING_SELECT_FRONT_FACES_VERT = (1 << 1),
VIEWPORT_FACING_SELECT_REAR_FACES = (1 << 2),
VIEWPORT_FACING_SELECT_REAR_FACES_VERT = (1 << 3),
VIEWPORT_FACING_SELECT_ALL_FACES = (1 << 4),
};
/** #ToolSettings.face_select */
enum {
FACE_AUTO = (1 << 0),
FACE_TOUCH = (1 << 1),
FACE_ENCLOSE = (1 << 2),
FACE_CENTER = (1 << 3),
};
/** #ToolSettings.edge_select */
enum {
EDGE_HYBRID = (1 << 0),
EDGE_TOUCH = (1 << 1),
EDGE_ENCLOSE = (1 << 2),
};
/** #ToolSettings.mesh_drag_direction */
enum {
MESH_DIRECTION_ANY = (1 << 0),
MESH_DIRECTION_LEFT_RIGHT = (1 << 1),
MESH_DIRECTION_UP_DOWN = (1 << 2),
};
/** #ToolSettings.auto_xray_mode */
enum {
AUTO_XRAY_DISABLE = (1 << 0),
AUTO_XRAY_OBJECT = (1 << 1),
AUTO_XRAY_EDIT = (1 << 2),
AUTO_XRAY_BOTH = (1 << 3),
};
/** #ToolSettings.select_through_mode */
enum {
SELECT_THROUGH_DISABLE = (1 << 0),
SELECT_THROUGH_OBJECT = (1 << 1),
SELECT_THROUGH_EDIT = (1 << 2),
SELECT_THROUGH_BOTH = (1 << 3),
};
/** #ToolSettings.selectmode */
#define SCE_SELECT_VERTEX (1 << 0) /* for mesh */
#define SCE_SELECT_EDGE (1 << 1)

View File

@ -840,7 +840,11 @@ typedef struct UserDef {
/** #eGPUBackendType */
short gpu_backend;
char _pad7[4];
/** Keymap click-drag direction style. */
char click_drag_direction;
/** Box, lasso, and circle select mesh control style. */
char drag_select_control;
char _pad7[2];
/** Private, defaults to 20 for 72 DPI setting. */
short widget_unit;
@ -900,6 +904,12 @@ typedef struct UserDef {
char drag_threshold;
char move_threshold;
/** Adjustable selection radius */
float selection_radius;
char adjustable_click_select;
char select_unbiased;
char _pad9[2];
char font_path_ui[1024];
char font_path_ui_mono[1024];
@ -1002,11 +1012,11 @@ typedef enum eUserPref_SpaceData_Flag {
typedef enum eUserPref_Flag {
USER_AUTOSAVE = (1 << 0),
USER_FLAG_NUMINPUT_ADVANCED = (1 << 1),
USER_FLAG_UNUSED_2 = (1 << 2), /* cleared */
USER_FLAG_UNUSED_3 = (1 << 3), /* cleared */
USER_FLAG_UNUSED_4 = (1 << 4), /* cleared */
USER_ADJUSTABLE_CLICK_SELECT = (1 << 2),
USER_SELECT_UNBIASED = (1 << 3),
USER_ALTERNATE_CURSOR = (1 << 4),
USER_TRACKBALL = (1 << 5),
USER_FLAG_UNUSED_6 = (1 << 6), /* cleared */
USER_ALTERNATE_CURSOR_LARGE = (1 << 6),
USER_FLAG_UNUSED_7 = (1 << 7), /* cleared */
USER_MAT_ON_OB = (1 << 8),
USER_FLAG_UNUSED_9 = (1 << 9), /* cleared */
@ -1153,6 +1163,19 @@ typedef enum eUserpref_TableAPI {
USER_TABLET_WINTAB = 2,
} eUserpref_TabletAPI;
/** #UserDef.click_drag_direction_types */
typedef enum eUserpref_Click_Drag_Direction {
USER_CLICK_DRAG_DIRECTION_EIGHT_WAY = 0,
USER_CLICK_DRAG_DIRECTION_LEFT_RIGHT = 1,
USER_CLICK_DRAG_DIRECTION_UP_DOWN = 2,
} eUserpref_Click_Drag_Direction;
/** #UserDef.drag_select_control_types */
typedef enum eUserpref_Drag_Select_Control {
USER_DRAG_SELECT_TOOLSETTING = 0,
USER_DRAG_SELECT_KEYMAP = 1,
} eUserpref_Drag_Select_Control;
/** #UserDef.app_flag */
typedef enum eUserpref_APP_Flag {
USER_APP_LOCK_CORNER_SPLIT = (1 << 0),

View File

@ -3049,10 +3049,347 @@ static void rna_def_tool_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem mesh_drag_direction_items[] = {
{MESH_DIRECTION_ANY, "MESH_DIRECTION_ANY", 0, "Any", "Drag in any direction"},
{MESH_DIRECTION_LEFT_RIGHT,
"MESH_DIRECTION_LEFT_RIGHT",
0,
"Left Right",
"Drag to the left and right"},
{MESH_DIRECTION_UP_DOWN,
"MESH_DIRECTION_UP_DOWN",
0,
"Up Down",
"Drag upwards and downwards"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem edge_select_items[] = {
{EDGE_HYBRID,
"EDGE_HYBRID",
0,
"Hybrid",
"Select edges that are fully inside the selection area. If no edges are fully inside the "
"selection area, select edges that are touched by the selection area"},
{EDGE_TOUCH,
"EDGE_TOUCH",
0,
"Touch",
"Select edges that are touched by the selection area"},
{EDGE_ENCLOSE,
"EDGE_ENCLOSE",
0,
"Enclose",
"Select edges that are fully inside the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem edge_circle_select_items[] = {
{EDGE_TOUCH,
"EDGE_TOUCH",
0,
"Touch",
"Select edges that are touched by the selection area"},
{EDGE_ENCLOSE,
"EDGE_ENCLOSE",
0,
"Enclose",
"Select edges that are fully inside the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem face_select_items[] = {
{FACE_AUTO,
"FACE_AUTO",
0,
"Auto",
"Select faces that are touched by the selection area in near select. Select faces whose "
"center is touched by the selection area in X-Ray select"},
{FACE_TOUCH,
"FACE_TOUCH",
0,
"Touch",
"Select faces that are touched by the selection area"},
{FACE_ENCLOSE,
"FACE_ENCLOSE",
0,
"Enclose",
"Select faces that are fully inside the selection area"},
{FACE_CENTER,
"FACE_CENTER",
0,
"Center",
"Select faces whose center is touched by the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem viewport_facing_select_mode_items[] = {
{VIEWPORT_FACING_SELECT_BOTH,
"BOTH",
0,
"Near and X-Ray",
"Use viewport-facing selection in near select and X-Ray"},
{VIEWPORT_FACING_SELECT_NEAR,
"NEAR",
0,
"Near",
"Use viewport-facing selection in near select"},
{VIEWPORT_FACING_SELECT_XRAY,
"XRAY",
0,
"X-Ray",
"Use viewport-facing selection in X-Ray"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem viewport_facing_select_vert_items[] = {
{VIEWPORT_FACING_SELECT_FRONT_VERTS,
"FRONT_VERTS",
0,
"Front Verts",
"Select vertices with viewport-facing normals"},
{VIEWPORT_FACING_SELECT_FRONT_VERTS_FACE,
"FRONT_VERTS_FACE",
0,
"Verts of Front Face",
"Select vertices if they are part of a face that has a viewport-facing normal"},
{VIEWPORT_FACING_SELECT_REAR_VERTS,
"REAR_VERTS",
0,
"Rear Verts",
"Select vertices without viewport-facing normals"},
{VIEWPORT_FACING_SELECT_REAR_VERTS_FACE,
"REAR_VERTS_FACE",
0,
"Verts of Rear Face",
"Select vertices if they are part of a face that does not have a viewport-facing normal"},
{VIEWPORT_FACING_SELECT_ALL_VERTS,
"ALL_VERTS",
0,
"All Verts",
"Select vertices regarless of their normal direction"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem viewport_facing_select_edge_items[] = {
{VIEWPORT_FACING_SELECT_FRONT_EDGES,
"FRONT_EDGES",
0,
"Front Edges",
"Select edges with viewport-facing normals"},
{VIEWPORT_FACING_SELECT_FRONT_EDGES_FACE,
"FRONT_EDGES_FACE",
0,
"Edges of Front Face",
"Select edges if they are part of a face that has a viewport-facing normal"},
{VIEWPORT_FACING_SELECT_REAR_EDGES,
"REAR_EDGES",
0,
"Rear Edges",
"Select edges without viewport-facing normals"},
{VIEWPORT_FACING_SELECT_REAR_EDGES_FACE,
"REAR_EDGES_FACE",
0,
"Edges of Rear Face",
"Select edges if they are part of a face that does not have a viewport-facing normal"},
{VIEWPORT_FACING_SELECT_ALL_EDGES,
"ALL_EDGES",
0,
"All Edges",
"Select edges regarless of their normal direction"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem viewport_facing_select_face_items[] = {
{VIEWPORT_FACING_SELECT_FRONT_FACES,
"FRONT_FACES",
0,
"Front Faces",
"Select faces with viewport-facing normals"},
{VIEWPORT_FACING_SELECT_FRONT_FACES_VERT,
"FRONT_FACES_VERT",
0,
"Faces of Front Vert",
"Select faces if they have a vertex with a viewport-facing normal"},
{VIEWPORT_FACING_SELECT_REAR_FACES,
"REAR_FACES",
0,
"Rear Faces",
"Select faces without viewport-facing normals"},
{VIEWPORT_FACING_SELECT_REAR_FACES_VERT,
"REAR_FACES_VERT",
0,
"Faces of Rear Vert",
"Select faces if they have a vertex without a viewport-facing normal"},
{VIEWPORT_FACING_SELECT_ALL_FACES,
"ALL_FACES",
0,
"All Faces",
"Select faces regarless of their normal direction"},
{0, NULL, 0, NULL, NULL},
};
srna = RNA_def_struct(brna, "ToolSettings", NULL);
RNA_def_struct_path_func(srna, "rna_ToolSettings_path");
RNA_def_struct_ui_text(srna, "Tool Settings", "");
/* Viewport-Facing Select */
prop = RNA_def_property(srna, "viewport_facing_select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "viewport_facing_select", 0);
RNA_def_property_ui_text(
prop,
"Viewport Facing Select",
"Filter box, lasso, and circle selection of mesh elements based on the direction of their "
"normals compared to the viewport");
prop = RNA_def_property(srna, "viewport_facing_select_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "viewport_facing_select_mode");
RNA_def_property_enum_items(prop, viewport_facing_select_mode_items);
RNA_def_property_ui_text(prop, "Mode", "Which selection modes to use viewport-facing selection");
prop = RNA_def_property(srna, "viewport_facing_select_vert", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "viewport_facing_select_vert");
RNA_def_property_enum_items(prop, viewport_facing_select_vert_items);
RNA_def_property_ui_text(prop, "Vert", "Direction and mode for vertices");
prop = RNA_def_property(srna, "viewport_facing_select_edge", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "viewport_facing_select_edge");
RNA_def_property_enum_items(prop, viewport_facing_select_edge_items);
RNA_def_property_ui_text(prop, "Edge", "Direction and mode for edges");
prop = RNA_def_property(srna, "viewport_facing_select_face", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "viewport_facing_select_face");
RNA_def_property_enum_items(prop, viewport_facing_select_face_items);
RNA_def_property_ui_text(prop, "Face", "Direction and mode for faces");
prop = RNA_def_property(srna, "viewport_facing_select_threshold", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1.0f, 2);
RNA_def_property_ui_text(
prop,
"Threshold",
"How close the angles of the viewport and mesh element need to be for selection to occur");
/* Mesh select settings. */
prop = RNA_def_property(srna, "box_drag_direction", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, mesh_drag_direction_items);
RNA_def_property_ui_text(prop, "Drag Direction", "Click-drag direction style for box select");
prop = RNA_def_property(srna, "lasso_drag_direction", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, mesh_drag_direction_items);
RNA_def_property_ui_text(prop, "Drag Direction", "Click-drag direction style for lasso select");
prop = RNA_def_property(srna, "box_direction_upright", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "box_direction_upright", 0);
RNA_def_property_ui_text(prop, "Box Direction Helper", "");
prop = RNA_def_property(srna, "lasso_direction_upright", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "lasso_direction_upright", 0);
RNA_def_property_ui_text(prop, "Lasso Direction Helper", "");
prop = RNA_def_property(srna, "show_box_options", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "show_box_options", 0);
RNA_def_property_ui_text(
prop, "Mesh Options", "Additional options for box selection of mesh elements");
prop = RNA_def_property(srna, "show_lasso_options", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "show_lasso_options", 0);
RNA_def_property_ui_text(
prop, "Mesh Options", "Additional options for lasso selection of mesh elements");
prop = RNA_def_property(srna, "show_circle_options", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "show_circle_options", 0);
RNA_def_property_ui_text(
prop, "Mesh Options", "Additional options for circle selection of mesh elements");
prop = RNA_def_property(srna, "box_edge", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Edge", "Box edge selection style");
prop = RNA_def_property(srna, "box_edge_left", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Edge", "Box edge selection style when dragging left");
prop = RNA_def_property(srna, "box_edge_right", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Edge", "Box edge selection style when dragging right");
prop = RNA_def_property(srna, "box_edge_up", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Edge", "Box edge selection style when dragging up");
prop = RNA_def_property(srna, "box_edge_down", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Edge", "Box edge selection style when dragging down");
prop = RNA_def_property(srna, "box_face", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Face", "Box face selection style");
prop = RNA_def_property(srna, "box_face_left", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Face", "Box face selection style when dragging left");
prop = RNA_def_property(srna, "box_face_right", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Face", "Box face selection style when dragging right");
prop = RNA_def_property(srna, "box_face_up", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Face", "Box face selection style when dragging up");
prop = RNA_def_property(srna, "box_face_down", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Face", "Box face selection style when dragging down");
prop = RNA_def_property(srna, "lasso_edge", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Edge", "Lasso edge selection style");
prop = RNA_def_property(srna, "lasso_edge_left", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Edge", "Lasso edge selection style when dragging left");
prop = RNA_def_property(srna, "lasso_edge_right", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Edge", "Lasso edge selection style when dragging right");
prop = RNA_def_property(srna, "lasso_edge_up", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Edge", "Lasso edge selection style when dragging up");
prop = RNA_def_property(srna, "lasso_edge_down", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Edge", "Lasso edge selection style when dragging down");
prop = RNA_def_property(srna, "lasso_face", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Face", "Lasso face selection style");
prop = RNA_def_property(srna, "lasso_face_left", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Face", "Lasso face selection style when dragging left");
prop = RNA_def_property(srna, "lasso_face_right", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Face", "Lasso face selection style when dragging right");
prop = RNA_def_property(srna, "lasso_face_up", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Face", "Lasso face selection style when dragging up");
prop = RNA_def_property(srna, "lasso_face_down", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Face", "Lasso face selection style when dragging down");
prop = RNA_def_property(srna, "circle_edge", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_circle_select_items);
RNA_def_property_ui_text(prop, "Edge", "Circle edge selection style");
prop = RNA_def_property(srna, "circle_face", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Face", "Circle face selection style");
prop = RNA_def_property(srna, "sculpt", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Sculpt");
RNA_def_property_ui_text(prop, "Sculpt", "");
@ -3725,6 +4062,122 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Normal Vector", "Normal Vector used to copy, add or multiply");
RNA_def_property_ui_range(prop, -10000.0, 10000.0, 1, 3);
/* UI prop helper, might help with formatting and using headings on a blank line, unused for now */
prop = RNA_def_property(srna, "ui_prop", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "ui_prop", 0);
RNA_def_property_ui_text(prop, "UI Prop", "");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
/* Shrink Shading Header */
prop = RNA_def_property(srna, "shrink_shading_header", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "shrink_shading_header", 0);
RNA_def_property_ui_text(
prop, "Shrink Header", "Combine the four Shading Header buttons into one button that also toggles X-Ray");
/* X-Ray header button */
prop = RNA_def_property(srna, "xray_button", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "xray_button", 0);
RNA_def_property_ui_text(
prop, "X-Ray Button", "Show button for X-Ray in viewport header");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
/* Auto X-Ray */
prop = RNA_def_property(srna, "auto_xray", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray", "Transparent scene display during drag select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "auto_xray_button", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray_button", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray Button", "Show button for automatic X-Ray in viewport header");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "auto_xray_reset", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray_reset", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray Reset", "Helper that turns xray off for autoxray");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "auto_xray_object", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray_object", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray Object", "Automatic X-Ray in object mode");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "auto_xray_edit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray_edit", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray Edit", "Automatic X-Ray in edit mode");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "auto_xray_box", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray_box", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray Box", "Transparent scene display during box select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "auto_xray_lasso", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray_lasso", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray Lasso", "Transparent scene display during lasso select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "auto_xray_circle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray_circle", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray Circle", "Transparent scene display during circle select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
/* Select Through */
prop = RNA_def_property(srna, "select_through", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_through", 0);
RNA_def_property_ui_text(
prop, "Select Through", "Select occluded objects and mesh elements with drag select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "select_through_button", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_through_button", 0);
RNA_def_property_ui_text(
prop, "Select Through Button", "Show button for select through in viewport header");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "select_through_object", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_through_object", 0);
RNA_def_property_ui_text(prop, "Select Through Object", "Select through in object mode");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "select_through_edit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_through_edit", 0);
RNA_def_property_ui_text(prop, "Select Through Edit", "Select through in edit mode");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "select_through_box", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_through_box", 0);
RNA_def_property_ui_text(
prop, "Select Through Box", "Select occluded objects and mesh elements with box select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "select_through_lasso", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_through_lasso", 0);
RNA_def_property_ui_text(prop,
"Select Through Lasso",
"Select occluded objects and mesh elements with lasso select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "select_through_circle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_through_circle", 0);
RNA_def_property_ui_text(prop,
"Select Through Circle",
"Select occluded objects and mesh elements with circle select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
/* Object Origin Select */
prop = RNA_def_property(srna, "select_origin_box", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_origin_box", 0);
RNA_def_property_ui_text(
prop, "Select Origin", "Select objects by their origin with box select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "select_origin_circle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_origin_circle", 0);
RNA_def_property_ui_text(
prop, "Select Origin", "Select objects by their origin with circle select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
/* Unified Paint Settings */
prop = RNA_def_property(srna, "unified_paint_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);

View File

@ -5310,6 +5310,21 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
prop, "Auto-offset Margin", "Minimum distance between nodes for Auto-offsetting nodes");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "adjustable_click_select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_ADJUSTABLE_CLICK_SELECT);
RNA_def_property_ui_text(
prop, "Adjustable Click-Select", "Use additional options for single-click select");
prop = RNA_def_property(srna, "select_unbiased", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_SELECT_UNBIASED);
RNA_def_property_ui_text(
prop, "Select Unbiased", "Click-select will not favor unselected mesh elements");
prop = RNA_def_property(srna, "selection_radius", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.1f, 150.0f);
RNA_def_property_ui_range(prop, 0.1f, 150.0f, 0.01f, 2);
RNA_def_property_ui_text(prop, "Radius", "Size of single-click selection radius");
/* cursor */
prop = RNA_def_property(srna, "use_cursor_lock_adjust", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_LOCK_CURSOR_ADJUST);
@ -5322,6 +5337,14 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_DEPTH_CURSOR);
RNA_def_property_ui_text(
prop, "Cursor Surface Project", "Use the surface depth for cursor placement");
prop = RNA_def_property(srna, "alternate_cursor", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_ALTERNATE_CURSOR);
RNA_def_property_ui_text(prop, "Alternate Cursor", "Alternate edit mode crosshair");
prop = RNA_def_property(srna, "alternate_cursor_large", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_ALTERNATE_CURSOR_LARGE);
RNA_def_property_ui_text(prop, "Large Cursor", "Supersize the alternate edit mode crosshair");
}
static void rna_def_userdef_system(BlenderRNA *brna)
@ -5774,6 +5797,31 @@ static void rna_def_userdef_input(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem click_drag_direction_types[] = {
{USER_CLICK_DRAG_DIRECTION_EIGHT_WAY,
"EIGHT_WAY",
0,
"Eight",
"Eight directions (N, NE, E, SE, S, SW, W, NW)"},
{USER_CLICK_DRAG_DIRECTION_LEFT_RIGHT, "LEFT_RIGHT", 0, "Left Right", "Left and right"},
{USER_CLICK_DRAG_DIRECTION_UP_DOWN, "UP_DOWN", 0, "Up Down", "Up and down"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem drag_select_control_types[] = {
{USER_DRAG_SELECT_TOOLSETTING,
"USER_DRAG_TOOLSETTING",
0,
"Toolsetting",
"Use toolsettings to control selection options for box, lasso, and circle select"},
{USER_DRAG_SELECT_KEYMAP,
"USER_DRAG_KEYMAP",
0,
"Keymap",
"Use the keymap to control selection options for box, lasso, and circle selection"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem view_zoom_styles[] = {
{USER_ZOOM_CONTINUE,
"CONTINUE",
@ -5880,6 +5928,18 @@ static void rna_def_userdef_input(BlenderRNA *brna)
"Release Confirms",
"Moving things with a mouse drag confirms when releasing the button");
prop = RNA_def_property(srna, "click_drag_direction", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, click_drag_direction_types);
RNA_def_property_ui_text(
prop, "Keymap Drag Directions", "Style of click-drag direction the keymap will use");
prop = RNA_def_property(srna, "drag_select_control", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, drag_select_control_types);
RNA_def_property_ui_text(prop,
"Drag Select Control",
"Use either the keymap or toolsettings to control selection options "
"for box, lasso, and circle select");
prop = RNA_def_property(srna, "use_numeric_input_advanced", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_FLAG_NUMINPUT_ADVANCED);
RNA_def_property_ui_text(prop,

View File

@ -389,6 +389,41 @@ static void rna_KeyMap_item_remove(wmKeyMap *km, ReportList *reports, PointerRNA
RNA_POINTER_INVALIDATE(kmi_ptr);
}
static void rna_keymap_set_direction_any(wmKeyMap *km, PointerRNA *kmi_ptr)
{
wmKeyMapItem *kmi = kmi_ptr->data;
kmi->direction = -1;
WM_keyconfig_update_tag(km, kmi);
}
static void rna_keymap_set_direction_left(wmKeyMap *km, PointerRNA *kmi_ptr)
{
wmKeyMapItem *kmi = kmi_ptr->data;
kmi->direction = 7;
WM_keyconfig_update_tag(km, kmi);
}
static void rna_keymap_set_direction_right(wmKeyMap *km, PointerRNA *kmi_ptr)
{
wmKeyMapItem *kmi = kmi_ptr->data;
kmi->direction = 3;
WM_keyconfig_update_tag(km, kmi);
}
static void rna_keymap_set_direction_up(wmKeyMap *km, PointerRNA *kmi_ptr)
{
wmKeyMapItem *kmi = kmi_ptr->data;
kmi->direction = 1;
WM_keyconfig_update_tag(km, kmi);
}
static void rna_keymap_set_direction_down(wmKeyMap *km, PointerRNA *kmi_ptr)
{
wmKeyMapItem *kmi = kmi_ptr->data;
kmi->direction = 5;
WM_keyconfig_update_tag(km, kmi);
}
static PointerRNA rna_KeyMap_item_find_from_operator(ID *id,
wmKeyMap *km,
const char *idname,
@ -1197,6 +1232,31 @@ void RNA_api_keymapitems(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", "");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
func = RNA_def_function(srna, "set_direction_any", "rna_keymap_set_direction_any");
parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", "");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
func = RNA_def_function(srna, "set_direction_left", "rna_keymap_set_direction_left");
parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", "");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
func = RNA_def_function(srna, "set_direction_right", "rna_keymap_set_direction_right");
parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", "");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
func = RNA_def_function(srna, "set_direction_up", "rna_keymap_set_direction_up");
parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", "");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
func = RNA_def_function(srna, "set_direction_down", "rna_keymap_set_direction_down");
parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", "");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
func = RNA_def_function(srna, "from_id", "WM_keymap_item_find_id");

View File

@ -688,6 +688,7 @@ int WM_operator_call_notest(struct bContext *C, struct wmOperator *op);
* Execute this operator again, put here so it can share above code
*/
int WM_operator_repeat(struct bContext *C, struct wmOperator *op);
int WM_operator_repeat_tool(struct bContext *C, struct wmOperator *op);
int WM_operator_repeat_last(struct bContext *C, struct wmOperator *op);
/**
* \return true if #WM_operator_repeat can run.
@ -1611,7 +1612,7 @@ bool WM_event_is_modal_drag_exit(const struct wmEvent *event,
short init_event_val);
bool WM_event_is_mouse_drag(const struct wmEvent *event);
bool WM_event_is_mouse_drag_or_press(const wmEvent *event);
int WM_event_drag_direction(const wmEvent *event);
int WM_event_drag_direction(const wmEvent *event, struct ToolSettings *ts);
char WM_event_utf8_to_ascii(const struct wmEvent *event) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
/**

View File

@ -50,7 +50,15 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs)
return GHOST_kStandardCursorWait;
case WM_CURSOR_EDIT:
case WM_CURSOR_CROSS:
return GHOST_kStandardCursorCrosshair;
if (U.flag & USER_ALTERNATE_CURSOR && !(U.flag & USER_ALTERNATE_CURSOR_LARGE)) {
return GHOST_kStandardCursorCrosshairD;
}
else if (U.flag & USER_ALTERNATE_CURSOR && U.flag & USER_ALTERNATE_CURSOR_LARGE) {
return GHOST_kStandardCursorCrosshairE;
}
else {
return GHOST_kStandardCursorCrosshair;
}
case WM_CURSOR_X_MOVE:
return GHOST_kStandardCursorLeftRight;
case WM_CURSOR_Y_MOVE:

View File

@ -264,36 +264,71 @@ bool WM_event_is_mouse_drag_or_press(const wmEvent *event)
(ISMOUSE_BUTTON(event->type) && (event->val == KM_PRESS));
}
int WM_event_drag_direction(const wmEvent *event)
int WM_event_drag_direction(const wmEvent *event, ToolSettings *ts)
{
const int delta[2] = {
event->xy[0] - event->prev_press_xy[0],
event->xy[1] - event->prev_press_xy[1],
};
int theta = round_fl_to_int(4.0f * atan2f((float)delta[1], (float)delta[0]) / (float)M_PI);
int val = KM_DIRECTION_W;
bool left_right = U.click_drag_direction & USER_CLICK_DRAG_DIRECTION_LEFT_RIGHT;
bool up_down = U.click_drag_direction & USER_CLICK_DRAG_DIRECTION_UP_DOWN;
int theta = left_right ?
round_fl_to_int(atan2f(0.0f, (float)delta[0]) / (float)M_PI) :
up_down ?
round_fl_to_int(atan2f(0.0f, (float)delta[1]) / (float)M_PI) :
round_fl_to_int(4.0f * atan2f((float)delta[1], (float)delta[0]) / (float)M_PI);
int val = up_down ? KM_DIRECTION_S : KM_DIRECTION_W;
if (theta == 0) {
val = KM_DIRECTION_E;
if (left_right || up_down) {
if (theta == 0) {
val = up_down ? KM_DIRECTION_N : KM_DIRECTION_E;
}
}
else if (theta == 1) {
val = KM_DIRECTION_NE;
else {
if (theta == 0) {
val = KM_DIRECTION_E;
}
else if (theta == 1) {
val = KM_DIRECTION_NE;
}
else if (theta == 2) {
val = KM_DIRECTION_N;
}
else if (theta == 3) {
val = KM_DIRECTION_NW;
}
else if (theta == -1) {
val = KM_DIRECTION_SE;
}
else if (theta == -2) {
val = KM_DIRECTION_S;
}
else if (theta == -3) {
val = KM_DIRECTION_SW;
}
}
else if (theta == 2) {
val = KM_DIRECTION_N;
}
else if (theta == 3) {
val = KM_DIRECTION_NW;
}
else if (theta == -1) {
val = KM_DIRECTION_SE;
}
else if (theta == -2) {
val = KM_DIRECTION_S;
}
else if (theta == -3) {
val = KM_DIRECTION_SW;
if (U.drag_select_control < 1) {
int box = ts->box_drag_direction;
int lasso = ts->lasso_drag_direction;
if (box > 1) {
ts->box_direction_upright = false;
theta = box == 2 ? round_fl_to_int(atan2f(0.0f, (float)delta[0]) / (float)M_PI) :
round_fl_to_int(atan2f(0.0f, (float)delta[1]) / (float)M_PI);
if (theta == 0) {
ts->box_direction_upright = true;
}
}
if (lasso > 1) {
ts->lasso_direction_upright = false;
theta = lasso == 2 ? round_fl_to_int(atan2f(0.0f, (float)delta[0]) / (float)M_PI) :
round_fl_to_int(atan2f(0.0f, (float)delta[1]) / (float)M_PI);
if (theta == 0) {
ts->lasso_direction_upright = true;
}
}
}
#if 0

View File

@ -1292,6 +1292,11 @@ int WM_operator_repeat(bContext *C, wmOperator *op)
op->flag &= ~op_flag;
return ret;
}
int WM_operator_repeat_tool(bContext *C, wmOperator *op)
{
const int ret = WM_operator_name_call_ptr(C, op->type, WM_OP_INVOKE_DEFAULT, NULL, NULL);
return ret;
}
int WM_operator_repeat_last(bContext *C, wmOperator *op)
{
const int op_flag = OP_IS_REPEAT_LAST;
@ -3432,7 +3437,8 @@ static eHandlerActionFlag wm_handlers_do(bContext *C, wmEvent *event, ListBase *
if ((event->flag & WM_EVENT_FORCE_DRAG_THRESHOLD) ||
WM_event_drag_test(event, event->prev_press_xy)) {
win->event_queue_check_drag_handled = true;
const int direction = WM_event_drag_direction(event);
ToolSettings *ts = CTX_data_tool_settings(C);
const int direction = WM_event_drag_direction(event, ts);
/* Intentionally leave `event->xy` as-is, event users are expected to use
* `event->prev_press_xy` if they need to access the drag start location. */

View File

@ -29,6 +29,7 @@
#include "ED_screen.h"
#include "ED_select_utils.h"
#include "ED_view3d.h"
#include "UI_interface.h"
@ -85,6 +86,18 @@ static void gesture_modal_state_to_operator(wmOperator *op, int modal_state)
}
}
static void gesture_toggle_xray(bContext *C)
{
wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_toggle_xray", true);
ToolSettings *ts = CTX_data_tool_settings(C);
BLI_assert(ot);
PointerRNA ptr;
WM_operator_properties_create_ptr(&ptr, ot);
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, NULL);
WM_operator_properties_free(&ptr);
ts->auto_xray_reset ^= true;
}
static int UNUSED_FUNCTION(gesture_modal_state_from_operator)(wmOperator *op)
{
PropertyRNA *prop;
@ -163,9 +176,33 @@ static bool gesture_box_apply(bContext *C, wmOperator *op)
int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C);
Object *obedit = CTX_data_edit_object(C);
ToolSettings *ts = CTX_data_tool_settings(C);
const ARegion *region = CTX_wm_region(C);
const bool wait_for_input = !WM_event_is_mouse_drag_or_press(event) &&
RNA_boolean_get(op->ptr, "wait_for_input");
bool auto_xray = false;
if (U.drag_select_control & USER_DRAG_SELECT_KEYMAP) {
const int auto_xray_int = RNA_enum_get(op->ptr, "auto_xray");
auto_xray = obedit ? auto_xray_int > 2 : auto_xray_int == 2 || auto_xray_int == 8;
}
else {
auto_xray = ts->auto_xray && ts->auto_xray_box ?
obedit ? ts->auto_xray_edit : ts->auto_xray_object :
false;
}
if (ts->auto_xray_reset) {
ts->auto_xray_reset ^= true;
}
if (v3d && auto_xray) {
if (!XRAY_FLAG_ENABLED(v3d)) {
gesture_toggle_xray(C);
}
}
if (wait_for_input) {
op->customdata = WM_gesture_new(win, region, event, WM_GESTURE_CROSS_RECT);
@ -190,8 +227,11 @@ int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C);
wmGesture *gesture = op->customdata;
rcti *rect = gesture->customdata;
Object *obedit = CTX_data_edit_object(C);
ToolSettings *ts = CTX_data_tool_settings(C);
if (event->type == EVT_MODAL_MAP) {
switch (event->val) {
@ -214,13 +254,22 @@ int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event)
gesture->modal_state = event->val;
}
if (gesture_box_apply(C, op)) {
if (ts->auto_xray_reset) {
gesture_toggle_xray(C);
}
gesture_modal_end(C, op);
return OPERATOR_FINISHED;
}
if (ts->auto_xray_reset) {
gesture_toggle_xray(C);
}
gesture_modal_end(C, op);
return OPERATOR_CANCELLED;
}
case GESTURE_MODAL_CANCEL: {
if (ts->auto_xray_reset) {
gesture_toggle_xray(C);
}
gesture_modal_end(C, op);
return OPERATOR_CANCELLED;
}
@ -286,8 +335,31 @@ static void gesture_circle_apply(bContext *C, wmOperator *op);
int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C);
const bool wait_for_input = !WM_event_is_mouse_drag_or_press(event) &&
RNA_boolean_get(op->ptr, "wait_for_input");
Object *obedit = CTX_data_edit_object(C);
ToolSettings *ts = win->scene->toolsettings;
bool auto_xray = false;
if (U.drag_select_control & USER_DRAG_SELECT_KEYMAP) {
const int auto_xray_int = RNA_enum_get(op->ptr, "auto_xray");
auto_xray = obedit ? auto_xray_int > 2 : auto_xray_int == 2 || auto_xray_int == 8;
}
else {
auto_xray = ts->auto_xray && ts->auto_xray_circle ?
obedit ? ts->auto_xray_edit : ts->auto_xray_object :
false;
}
if (ts->auto_xray_reset) {
ts->auto_xray_reset ^= true;
}
if (v3d && auto_xray) {
if (!XRAY_FLAG_ENABLED(v3d)) {
gesture_toggle_xray(C);
}
}
op->customdata = WM_gesture_new(win, CTX_wm_region(C), event, WM_GESTURE_CIRCLE);
wmGesture *gesture = op->customdata;
@ -345,11 +417,14 @@ static void gesture_circle_apply(bContext *C, wmOperator *op)
int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C);
wmGesture *gesture = op->customdata;
rcti *rect = gesture->customdata;
if (event->type == MOUSEMOVE) {
Object *obedit = CTX_data_edit_object(C);
ToolSettings *ts = win->scene->toolsettings;
if (event->type == MOUSEMOVE) {
rect->xmin = event->xy[0] - gesture->winrct.xmin;
rect->ymin = event->xy[1] - gesture->winrct.ymin;
@ -415,6 +490,9 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (is_finished) {
if (ts->auto_xray_reset) {
gesture_toggle_xray(C);
}
gesture_modal_end(C, op);
return OPERATOR_FINISHED; /* use finish or we don't get an undo */
}
@ -477,7 +555,31 @@ void WM_OT_circle_gesture(wmOperatorType *ot)
int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C);
PropertyRNA *prop;
Object *obedit = CTX_data_edit_object(C);
ToolSettings *ts = win->scene->toolsettings;
bool auto_xray = false;
if (U.drag_select_control & USER_DRAG_SELECT_KEYMAP) {
const int auto_xray_int = RNA_enum_get(op->ptr, "auto_xray");
auto_xray = obedit ? auto_xray_int > 2 : auto_xray_int == 2 || auto_xray_int == 8;
}
else {
auto_xray = ts->auto_xray && ts->auto_xray_lasso ?
obedit ? ts->auto_xray_edit : ts->auto_xray_object :
false;
}
if (ts->auto_xray_reset) {
ts->auto_xray_reset ^= true;
}
if (v3d && auto_xray) {
if (!XRAY_FLAG_ENABLED(v3d)) {
gesture_toggle_xray(C);
}
}
op->customdata = WM_gesture_new(win, CTX_wm_region(C), event, WM_GESTURE_LASSO);
@ -517,6 +619,10 @@ static int gesture_lasso_apply(bContext *C, wmOperator *op)
int retval = OPERATOR_FINISHED;
wmGesture *gesture = op->customdata;
PointerRNA itemptr;
View3D *v3d = CTX_wm_view3d(C);
Object *obedit = CTX_data_edit_object(C);
wmWindow *win = CTX_wm_window(C);
ToolSettings *ts = win->scene->toolsettings;
float loc[2];
int i;
const short *lasso = gesture->customdata;
@ -538,12 +644,20 @@ static int gesture_lasso_apply(bContext *C, wmOperator *op)
OPERATOR_RETVAL_CHECK(retval);
}
if (ts->auto_xray_reset) {
gesture_toggle_xray(C);
}
return retval;
}
int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
View3D *v3d = CTX_wm_view3d(C);
Object *obedit = CTX_data_edit_object(C);
wmWindow *win = CTX_wm_window(C);
ToolSettings *ts = win->scene->toolsettings;
if (event->type == EVT_MODAL_MAP) {
switch (event->val) {
@ -597,6 +711,9 @@ int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
case EVT_ESCKEY: {
if (ts->auto_xray_reset) {
gesture_toggle_xray(C);
}
gesture_modal_end(C, op);
return OPERATOR_CANCELLED;
}

View File

@ -411,8 +411,93 @@ void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bo
{
PropertyRNA *prop;
static const EnumPropertyItem face_select_items[] = {
{FACE_AUTO,
"FACE_AUTO",
0,
"Auto",
"Select faces that are touched by the selection area in near select. Select faces whose "
"center is touched by the selection area in X-Ray select"},
{FACE_TOUCH,
"FACE_TOUCH",
0,
"Touch",
"Select faces that are touched by the selection area"},
{FACE_ENCLOSE,
"FACE_ENCLOSE",
0,
"Enclose",
"Select faces that are fully inside the selection area"},
{FACE_CENTER,
"FACE_CENTER",
0,
"Center",
"Select faces whose center is touched by the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem edge_select_items[] = {
{EDGE_HYBRID,
"EDGE_HYBRID",
0,
"Hybrid",
"Select edges that are fully inside the selection area. If no edges are fully inside the "
"selection area, select edges that are touched by the selection area"},
{EDGE_TOUCH,
"EDGE_TOUCH",
0,
"Touch",
"Select edges that are touched by the selection area"},
{EDGE_ENCLOSE,
"EDGE_ENCLOSE",
0,
"Enclose",
"Select edges that are fully inside the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem auto_xray_items[] = {
{AUTO_XRAY_DISABLE, "AUTO_XRAY_DISABLE", 0, "Disable", "Disable Automatic X-Ray"},
{AUTO_XRAY_OBJECT,
"AUTO_XRAY_OBJECT",
0,
"Object",
"Enable X-Ray during box select in object mode"},
{AUTO_XRAY_EDIT, "AUTO_XRAY_EDIT", 0, "Edit", "Enable X-Ray during box select in edit mode"},
{AUTO_XRAY_BOTH,
"AUTO_XRAY_BOTH",
0,
"Both",
"Enable X-Ray during box select in object and edit mode"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem select_through_items[] = {
{SELECT_THROUGH_OBJECT, "SELECT_THROUGH_OBJECT", 0, "Object", "Select occluded objects"},
{SELECT_THROUGH_EDIT, "SELECT_THROUGH_EDIT", 0, "Edit", "Select occluded mesh elements"},
{SELECT_THROUGH_BOTH,
"SELECT_THROUGH_BOTH",
0,
"Both",
"Select occluded objects and mesh elements"},
{SELECT_THROUGH_DISABLE, "SELECT_THROUGH_DISABLE", 0, "Disable", "Disable Select Through"},
{0, NULL, 0, NULL, NULL},
};
WM_operator_properties_border(ot);
prop = RNA_def_boolean(ot->srna, "select_origin_box", false, "Select Object Origin", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "auto_xray", auto_xray_items, 0, "Automatic X-Ray", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "select_through", select_through_items, 0, "Select Through", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
if (deselect) {
prop = RNA_def_boolean(
ot->srna, "deselect", false, "Deselect", "Deselect rather than select items");
@ -440,7 +525,8 @@ void WM_operator_properties_use_cursor_init(wmOperatorType *ot)
void WM_operator_properties_gesture_box_select(wmOperatorType *ot)
{
WM_operator_properties_gesture_box_ex(ot, true, true);
WM_operator_properties_gesture_box_ex(
ot, true, true);
}
void WM_operator_properties_gesture_box(wmOperatorType *ot)
{
@ -519,6 +605,93 @@ void WM_operator_properties_gesture_box_zoom(wmOperatorType *ot)
void WM_operator_properties_gesture_lasso(wmOperatorType *ot)
{
PropertyRNA *prop;
static const EnumPropertyItem face_select_items[] = {
{FACE_AUTO,
"FACE_AUTO",
0,
"Auto",
"Select faces that are touched by the selection area in near select. Select faces whose "
"center is touched by the selection area in X-Ray select"},
{FACE_TOUCH,
"FACE_TOUCH",
0,
"Touch",
"Select faces that are touched by the selection area"},
{FACE_ENCLOSE,
"FACE_ENCLOSE",
0,
"Enclose",
"Select faces that are fully inside the selection area"},
{FACE_CENTER,
"FACE_CENTER",
0,
"Center",
"Select faces whose center is touched by the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem edge_select_items[] = {
{EDGE_HYBRID,
"EDGE_HYBRID",
0,
"Hybrid",
"Select edges that are fully inside the selection area. If no edges are fully inside the "
"selection area, select edges that are touched by the selection area"},
{EDGE_TOUCH,
"EDGE_TOUCH",
0,
"Touch",
"Select edges that are touched by the selection area"},
{EDGE_ENCLOSE,
"EDGE_ENCLOSE",
0,
"Enclose",
"Select edges that are fully inside the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem auto_xray_items[] = {
{AUTO_XRAY_DISABLE, "AUTO_XRAY_DISABLE", 0, "Disable", "Disable Automatic X-Ray"},
{AUTO_XRAY_OBJECT,
"AUTO_XRAY_OBJECT",
0,
"Object",
"Enable X-Ray during lasso select in object mode"},
{AUTO_XRAY_EDIT,
"AUTO_XRAY_EDIT",
0,
"Edit",
"Enable X-Ray during lasso select in edit mode"},
{AUTO_XRAY_BOTH,
"AUTO_XRAY_BOTH",
0,
"Both",
"Enable X-Ray during lasso select in object and edit mode"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem select_through_items[] = {
{SELECT_THROUGH_OBJECT, "SELECT_THROUGH_OBJECT", 0, "Object", "Select occluded objects"},
{SELECT_THROUGH_EDIT, "SELECT_THROUGH_EDIT", 0, "Edit", "Select occluded mesh elements"},
{SELECT_THROUGH_BOTH,
"SELECT_THROUGH_BOTH",
0,
"Both",
"Select occluded objects and mesh elements"},
{SELECT_THROUGH_DISABLE, "SELECT_THROUGH_DISABLE", 0, "Disable", "Disable Select Through"},
{0, NULL, 0, NULL, NULL},
};
WM_operator_properties_border(ot);
prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "auto_xray", auto_xray_items, 0, "Automatic X-Ray", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "select_through", select_through_items, 0, "Select Through", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
@ -557,6 +730,81 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot)
PropertyRNA *prop;
const int radius_default = 25;
static const EnumPropertyItem face_select_items[] = {
{FACE_AUTO,
"FACE_AUTO",
0,
"Auto",
"Select faces that are touched by the selection area in near select. Select faces whose "
"center is touched by the selection area in X-Ray select"},
{FACE_TOUCH,
"FACE_TOUCH",
0,
"Touch",
"Select faces that are touched by the selection area"},
{FACE_ENCLOSE,
"FACE_ENCLOSE",
0,
"Enclose",
"Select faces that are fully inside the selection area"},
{FACE_CENTER,
"FACE_CENTER",
0,
"Center",
"Select faces whose center is touched by the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem edge_select_items[] = {
{EDGE_TOUCH,
"EDGE_TOUCH",
0,
"Touch",
"Select edges that are touched by the selection area"},
{EDGE_ENCLOSE,
"EDGE_ENCLOSE",
0,
"Enclose",
"Select edges that are fully inside the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem auto_xray_items[] = {
{AUTO_XRAY_DISABLE, "AUTO_XRAY_DISABLE", 0, "Disable", "Disable Automatic X-Ray"},
{AUTO_XRAY_OBJECT,
"AUTO_XRAY_OBJECT",
0,
"Object",
"Enable X-Ray during circle select in object mode"},
{AUTO_XRAY_EDIT, "AUTO_XRAY_EDIT", 0, "Edit", "Enable X-Ray during circle select in edit mode"},
{AUTO_XRAY_BOTH,
"AUTO_XRAY_BOTH",
0,
"Both",
"Enable X-Ray during circle select in object and edit mode"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem select_through_items[] = {
{SELECT_THROUGH_OBJECT,
"SELECT_THROUGH_OBJECT",
0,
"Object",
"Select occluded objects"},
{SELECT_THROUGH_EDIT,
"SELECT_THROUGH_EDIT",
0,
"Edit",
"Select occluded mesh elements"},
{SELECT_THROUGH_BOTH,
"SELECT_THROUGH_BOTH",
0,
"Both",
"Select occluded objects and mesh elements"},
{SELECT_THROUGH_DISABLE, "SELECT_THROUGH_DISABLE", 0, "Disable", "Disable Select Through"},
{0, NULL, 0, NULL, NULL},
};
prop = RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
@ -565,6 +813,18 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot)
prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna, "select_origin_circle", true, "Select Object Origin", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "auto_xray", auto_xray_items, 0, "Automatic X-Ray", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "select_through", select_through_items, 0, "Select Through", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
void WM_operator_properties_mouse_select(wmOperatorType *ot)