WIP: Luke's Custom Build 4.1 #119952

Draft
Lukas Sneyd wants to merge 6 commits from lcas/blender:410 into blender-v4.1-release

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
75 changed files with 9453 additions and 468 deletions

View File

@ -329,12 +329,18 @@ typedef enum {
GHOST_kStandardCursorCrosshairA,
GHOST_kStandardCursorCrosshairB,
GHOST_kStandardCursorCrosshairC,
GHOST_kStandardCursorCrosshairD,
GHOST_kStandardCursorBlank,
GHOST_kStandardCursorBox,
GHOST_kStandardCursorBoxDot,
GHOST_kStandardCursorBoxPointer,
GHOST_kStandardCursorPencil,
GHOST_kStandardCursorUpArrow,
GHOST_kStandardCursorDownArrow,
GHOST_kStandardCursorVerticalSplit,
GHOST_kStandardCursorHorizontalSplit,
GHOST_kStandardCursorEraser,
GHOST_kStandardCursorPointer,
GHOST_kStandardCursorKnife,
GHOST_kStandardCursorEyedropper,
GHOST_kStandardCursorZoomIn,

View File

@ -728,6 +728,9 @@ HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const
case GHOST_kStandardCursorHorizontalSplit:
cursor = ::LoadImage(module, "splith_cursor", IMAGE_CURSOR, cx, cy, flags);
break;
case GHOST_kStandardCursorPointer:
cursor = ::LoadImage(module, "pointer_cursor", IMAGE_CURSOR, cx, cy, flags);
break;
case GHOST_kStandardCursorKnife:
cursor = ::LoadImage(module, "knife_cursor", IMAGE_CURSOR, cx, cy, flags);
break;
@ -773,6 +776,21 @@ 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; /* Open Crosshair D */
case GHOST_kStandardCursorBlank:
cursor = ::LoadImage(module, "blank_cursor", IMAGE_CURSOR, cx, cy, flags);
break; /* Blank */
case GHOST_kStandardCursorBox:
cursor = ::LoadImage(module, "box_cursor", IMAGE_CURSOR, cx, cy, flags);
break; /* Box */
case GHOST_kStandardCursorBoxDot:
cursor = ::LoadImage(module, "boxdot_cursor", IMAGE_CURSOR, cx, cy, flags);
break; /* Box Dot */
case GHOST_kStandardCursorBoxPointer:
cursor = ::LoadImage(module, "boxpointer_cursor", IMAGE_CURSOR, cx, cy, flags);
break; /* Box Pointer */
case GHOST_kStandardCursorBottomSide:
case GHOST_kStandardCursorUpDown:
cursor = ::LoadImage(module, "movens_cursor", IMAGE_CURSOR, cx, cy, flags);

Binary file not shown.

Binary file not shown.

View File

@ -196,6 +196,8 @@ 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,
.header_highlight = 5,
.walk_navigation =
{

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -12,7 +12,6 @@
APPICON ICON DISCARDABLE "winblender.ico"
BLENDERFILE ICON DISCARDABLE "winblenderfile.ico"
pointer_cursor CURSOR "cursors/pointer.cur"
moveew_cursor CURSOR "cursors/moveew.cur"
movens_cursor CURSOR "cursors/movens.cur"
arrowdown_cursor CURSOR "cursors/arrowdown.cur"
@ -23,6 +22,12 @@ 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"
blank_cursor CURSOR "cursors/blank.cur"
box_cursor CURSOR "cursors/box.cur"
boxdot_cursor CURSOR "cursors/boxdot.cur"
boxpointer_cursor CURSOR "cursors/boxpointer.cur"
pointer_cursor CURSOR "cursors/pointera.cur"
eraser_cursor CURSOR "cursors/eraser.cur"
eyedropper_cursor CURSOR "cursors/eyedropper.cur"
handopen_cursor CURSOR "cursors/handopen.cur"

View File

@ -182,6 +182,23 @@ def draw_kmi(display_keymaps, kc, km, kmi, layout, level):
if map_type in {'KEYBOARD', 'MOUSE'} and kmi.value == 'CLICK_DRAG':
subrow = sub.row()
if bpy.context.preferences.inputs.keymap_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.keymap_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()

View File

@ -405,6 +405,336 @@ class PREFERENCES_OT_keyitem_remove(Operator):
return {'FINISHED'}
class PREFERENCES_OT_quick_assign(Operator):
"""Assign values to the new drag select settings"""
bl_idname = "preferences.quick_assign"
bl_label = "Quick Assign"
def execute(self, context):
inputs = context.preferences.inputs
if inputs.quick_assign_mode == 'BETTER':
inputs.drag_control_mode = 'USERPREF'
inputs.userpref_mode = 'EASY'
inputs.object_select_box = 'OBJECT_TOUCH'
inputs.face_select_box = 'FACE_TOUCH'
inputs.edge_select_box = 'EDGE_TOUCH'
inputs.backface_box = 'NEAR'
inputs.auto_xray_box = 'AUTO_XRAY_DISABLE'
inputs.select_through_box = 'SELECT_THROUGH_OBJECT'
inputs.object_header = True
inputs.face_header = True
inputs.edge_header = True
inputs.backface_header = True
inputs.auto_xray_header = False
inputs.select_through_header = True
inputs.wireless_touch_object = True
inputs.object_cycle_touch = True
inputs.object_cycle_enclose = True
inputs.object_cycle_origin = False
inputs.face_cycle_default = False
inputs.face_cycle_touch = True
inputs.face_cycle_enclose = True
inputs.face_cycle_center = False
inputs.edge_cycle_default = False
inputs.edge_cycle_touch = True
inputs.edge_cycle_enclose = True
inputs.backface_toggle = 'NEAR'
inputs.select_through_toggle = 'CURRENT'
inputs.object_pie = 'SHOW'
inputs.face_pie = 'SHOW'
inputs.edge_pie = 'SHOW'
inputs.backface_pie = 'SHOW'
inputs.auto_xray_pie = 'HIDE'
inputs.select_through_pie = 'SHOW'
inputs.box_pie = 'CONTEXT'
inputs.circle_pie = 'CONTEXT'
inputs.lasso_pie = 'CONTEXT'
elif inputs.quick_assign_mode == 'AUTO_XRAY':
inputs.drag_control_mode = 'USERPREF'
inputs.userpref_mode = 'EASY'
inputs.object_select_box = 'OBJECT_TOUCH'
inputs.face_select_box = 'FACE_TOUCH'
inputs.edge_select_box = 'EDGE_TOUCH'
inputs.backface_box = 'DEFAULT'
inputs.auto_xray_box = 'AUTO_XRAY_BOTH'
inputs.select_through_box = 'SELECT_THROUGH_OBJECT'
inputs.object_header = True
inputs.face_header = True
inputs.edge_header = True
inputs.backface_header = True
inputs.auto_xray_header = True
inputs.select_through_header = False
inputs.object_cycle_touch = True
inputs.object_cycle_enclose = True
inputs.object_cycle_origin = False
inputs.face_cycle_default = False
inputs.face_cycle_touch = True
inputs.face_cycle_enclose = True
inputs.face_cycle_center = False
inputs.edge_cycle_default = False
inputs.edge_cycle_touch = True
inputs.edge_cycle_enclose = True
inputs.auto_xray_toggle = 'BOTH'
inputs.backface_toggle = 'NONE'
inputs.object_pie = 'SHOW'
inputs.face_pie = 'SHOW'
inputs.edge_pie = 'SHOW'
inputs.backface_pie = 'SHOW'
inputs.auto_xray_pie = 'SHOW'
inputs.select_through_pie = 'HIDE'
inputs.box_pie = 'SHOW'
inputs.circle_pie = 'SHOW'
inputs.lasso_pie = 'SHOW'
elif inputs.quick_assign_mode == 'DIRECTIONAL':
inputs.drag_control_mode = 'USERPREF'
inputs.userpref_mode = 'SPLIT'
inputs.drag_direction_box = 'LEFT_RIGHT'
inputs.drag_direction_lasso = 'ANY'
inputs.drag_direction_mode = 'SELECTIVE'
inputs.direction_object = True
inputs.direction_face = True
inputs.direction_edge = True
inputs.direction_backface = False
inputs.direction_auto_xray = False
inputs.direction_select_through = False
inputs.object_select_box = 'OBJECT_TOUCH'
inputs.object_select_downright_box = 'OBJECT_ENCLOSE'
inputs.face_select_box = 'FACE_TOUCH'
inputs.face_select_downright_box = 'FACE_ENCLOSE'
inputs.edge_select_box = 'EDGE_TOUCH'
inputs.edge_select_downright_box = 'EDGE_ENCLOSE'
inputs.backface_box = 'DEFAULT'
inputs.auto_xray_box = 'AUTO_XRAY_DISABLE'
inputs.select_through_box = 'SELECT_THROUGH_OBJECT'
inputs.object_select_circle = 'OBJECT_TOUCH'
inputs.face_select_circle = 'FACE_TOUCH'
inputs.edge_select_circle = 'EDGE_TOUCH'
inputs.backface_circle = 'DEFAULT'
inputs.auto_xray_circle = 'AUTO_XRAY_DISABLE'
inputs.select_through_circle = 'SELECT_THROUGH_OBJECT'
inputs.object_select_lasso = 'OBJECT_TOUCH'
inputs.face_select_lasso = 'FACE_TOUCH'
inputs.edge_select_lasso = 'EDGE_TOUCH'
inputs.backface_lasso = 'DEFAULT'
inputs.auto_xray_lasso = 'AUTO_XRAY_DISABLE'
inputs.select_through_lasso = 'SELECT_THROUGH_OBJECT'
inputs.object_header = False
inputs.face_header = False
inputs.edge_header = False
inputs.backface_header = False
inputs.auto_xray_header = False
inputs.select_through_header = False
inputs.object_pie = 'HIDE'
inputs.face_pie = 'HIDE'
inputs.edge_pie = 'HIDE'
else:
inputs.drag_control_mode = 'USERPREF'
inputs.userpref_mode = 'SPLIT'
inputs.drag_direction_box = 'ANY'
inputs.drag_direction_lasso = 'ANY'
inputs.object_select_box = 'OBJECT_TOUCH'
inputs.face_select_box = 'FACE_DEFAULT'
inputs.edge_select_box = 'EDGE_DEFAULT'
inputs.backface_box = 'DEFAULT'
inputs.auto_xray_box = 'AUTO_XRAY_DISABLE'
inputs.select_through_box = 'SELECT_THROUGH_OBJECT'
inputs.object_select_circle = 'OBJECT_ORIGIN'
inputs.face_select_circle = 'FACE_DEFAULT'
inputs.edge_select_circle = 'EDGE_TOUCH'
inputs.backface_circle = 'DEFAULT'
inputs.auto_xray_circle = 'AUTO_XRAY_DISABLE'
inputs.select_through_circle = 'SELECT_THROUGH_OBJECT'
inputs.object_select_lasso = 'OBJECT_ORIGIN'
inputs.face_select_lasso = 'FACE_DEFAULT'
inputs.edge_select_lasso = 'EDGE_DEFAULT'
inputs.backface_lasso = 'DEFAULT'
inputs.auto_xray_lasso = 'AUTO_XRAY_DISABLE'
inputs.select_through_lasso = 'SELECT_THROUGH_OBJECT'
inputs.sync_box = False
inputs.sync_circle = False
inputs.sync_lasso = False
inputs.object_header = False
inputs.face_header = False
inputs.edge_header = False
inputs.backface_header = False
inputs.auto_xray_header = False
inputs.select_through_header = False
inputs.object_cycle_touch = True
inputs.object_cycle_enclose = True
inputs.object_cycle_origin = True
inputs.object_cycle_touch_circle = True
inputs.object_cycle_enclose_circle = True
inputs.object_cycle_origin_circle = True
inputs.object_cycle_touch_lasso = True
inputs.object_cycle_enclose_lasso = True
inputs.object_cycle_origin_lasso = True
inputs.face_cycle_default = True
inputs.face_cycle_touch = True
inputs.face_cycle_enclose = True
inputs.face_cycle_center = True
inputs.face_cycle_default_circle = True
inputs.face_cycle_touch_circle = True
inputs.face_cycle_enclose_circle = True
inputs.face_cycle_center_circle = True
inputs.face_cycle_default_lasso = True
inputs.face_cycle_touch_lasso = True
inputs.face_cycle_enclose_lasso = True
inputs.face_cycle_center_lasso = True
inputs.edge_cycle_default = True
inputs.edge_cycle_touch = True
inputs.edge_cycle_enclose = True
inputs.edge_cycle_touch_circle = True
inputs.edge_cycle_enclose_circle = True
inputs.edge_cycle_default_lasso = True
inputs.edge_cycle_touch_lasso = True
inputs.edge_cycle_enclose_lasso = True
inputs.backface_toggle = 'NONE'
inputs.backface_toggle_circle = 'NONE'
inputs.backface_toggle_lasso = 'NONE'
inputs.select_through_toggle = 'BOTH'
inputs.select_through_toggle_circle = 'BOTH'
inputs.select_through_toggle_lasso = 'BOTH'
inputs.auto_xray_toggle = 'BOTH'
inputs.auto_xray_toggle_circle = 'BOTH'
inputs.auto_xray_toggle_lasso = 'BOTH'
inputs.object_pie = 'SHOW'
inputs.face_pie = 'SHOW'
inputs.edge_pie = 'SHOW'
inputs.backface_pie = 'SHOW'
inputs.auto_xray_pie = 'SHOW'
inputs.select_through_pie = 'SHOW'
inputs.box_pie = 'SHOW'
inputs.circle_pie = 'SHOW'
inputs.lasso_pie = 'SHOW'
inputs.wireless_touch_object = False
inputs.square_select = False
return {'FINISHED'}
class PREFERENCES_OT_reset_cursors(Operator):
"""Reset mouse cursors"""
bl_idname = "preferences.reset_cursors"
bl_label = "Reset Cursors"
def execute(self, context):
inputs = context.preferences.inputs
inputs.system_cursor = 'SYSTEM'
inputs.edit_cursor = 'CROSS'
inputs.paint_cursor = 'CROSS_DOT'
inputs.dot_cursor = 'DOT'
inputs.knife_cursor = 'KNIFE'
inputs.eyedropper_cursor = 'EYEDROPPER'
inputs.eraser_cursor = 'ERASER'
inputs.pencil_cursor = 'PENCIL'
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 set direction for",
)
@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 set direction for",
)
@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 set direction for",
)
@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 set direction for",
)
@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 set direction for",
)
@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"
@ -1226,6 +1556,13 @@ classes = (
PREFERENCES_OT_keyconfig_test,
PREFERENCES_OT_keyitem_add,
PREFERENCES_OT_keyitem_remove,
PREFERENCES_OT_quick_assign,
PREFERENCES_OT_reset_cursors,
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

@ -2312,6 +2312,13 @@ class WM_OT_tool_set_by_id(Operator):
space_type = context.space_data.type
fn = activate_by_id_or_cycle if self.cycle else activate_by_id
for area in context.window.screen.areas:
if area.type == 'VIEW_3D':
for region in area.regions:
if region.type == 'HEADER':
region.tag_redraw()
if fn(context, space_type, self.name, as_fallback=self.as_fallback):
if self.as_fallback:
tool_settings = context.tool_settings

View File

@ -426,6 +426,9 @@ class _defs_view3d_select:
row = layout.row()
row.use_property_split = False
row.prop(props, "mode", text="", expand=True, icon_only=True)
if _context.mode == 'OBJECT':
inputs = _context.preferences.inputs
layout.prop(inputs, "wireless_touch_object")
return dict(
idname="builtin.select_box",
label="Select Box",
@ -442,6 +445,9 @@ class _defs_view3d_select:
row = layout.row()
row.use_property_split = False
row.prop(props, "mode", text="", expand=True, icon_only=True)
if _context.mode == 'OBJECT':
inputs = _context.preferences.inputs
layout.prop(inputs, "wireless_touch_object")
return dict(
idname="builtin.select_lasso",
label="Select Lasso",
@ -459,6 +465,10 @@ class _defs_view3d_select:
row.use_property_split = False
row.prop(props, "mode", text="", expand=True, icon_only=True)
layout.prop(props, "radius")
inputs = _context.preferences.inputs
if _context.mode == 'OBJECT':
layout.prop(inputs, "wireless_touch_object")
layout.prop(inputs, "square_select")
def draw_cursor(_context, tool, xy):
from gpu_extras.presets import draw_circle_2d
@ -2274,6 +2284,8 @@ class _defs_gpencil_edit:
layout.prop(props, "radius")
if _defs_gpencil_edit.is_segment(context):
layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
inputs = context.preferences.inputs
layout.prop(inputs, "square_select")
def draw_cursor(_context, tool, xy):
from gpu_extras.presets import draw_circle_2d

View File

@ -189,6 +189,587 @@ class CenterAlignMixIn:
row.label() # Needed so col above is centered.
# -----------------------------------------------------------------------------
# Custom Panels
class CustomPanel:
bl_space_type = 'PREFERENCES'
bl_region_type = 'WINDOW'
bl_context = "custom"
class USERPREF_PT_custom_drag_select(CustomPanel, CenterAlignMixIn, Panel):
bl_label = "Drag Select"
def draw_centered(self, context, layout):
inputs = context.preferences.inputs
row = layout.row(align=True)
row.prop(inputs, "keymap_direction", expand=True)
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "drag_control_mode", expand=True)
if inputs.drag_control_mode == 'USERPREF':
tool_settings = context.tool_settings
row = layout.row(align=True)
row.prop(inputs, "userpref_mode", expand=True)
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "quick_assign", text="Quick Assign", emboss=False)
if inputs.quick_assign:
sub = row.row(align=True)
sub.prop(inputs, "quick_assign", icon='DOWNARROW_HLT', emboss=False)
sub = layout.row(align=True)
sub.prop(inputs, "quick_assign_mode")
sub.operator("preferences.quick_assign")
else:
row.prop(inputs, "quick_assign", icon='RIGHTARROW', emboss=False)
if inputs.userpref_mode == 'SPLIT':
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "direction_controls", text="Drag Direction", emboss=False)
if inputs.direction_controls:
row.prop(inputs, "direction_controls", icon='DOWNARROW_HLT', emboss=False)
row = layout.row(align=True)
row.prop(inputs, "drag_direction_box", expand=True)
row = layout.row(align=True)
row.prop(inputs, "drag_direction_lasso", expand=True)
row = layout.row(align=True)
sub = row.row(align=True)
sub.enabled = inputs.drag_direction_box !='ANY' or inputs.drag_direction_lasso !='ANY'
sub.prop(inputs, "drag_direction_mode", expand=True)
row = layout.row(align=True)
sub = row.row(align=True)
sub.enabled = inputs.drag_direction_mode == 'SELECTIVE' and (inputs.drag_direction_box !='ANY' or inputs.drag_direction_lasso !='ANY')
sub.prop(inputs, "direction_object", toggle=True)
sub.prop(inputs, "direction_backface", toggle=True)
row = layout.row(align=True)
sub = row.row(align=True)
sub.enabled = inputs.drag_direction_mode == 'SELECTIVE' and (inputs.drag_direction_box !='ANY' or inputs.drag_direction_lasso !='ANY')
sub.prop(inputs, "direction_face", toggle=True)
sub.prop(inputs, "direction_auto_xray", toggle=True)
row = layout.row(align=True)
sub = row.row(align=True)
sub.enabled = inputs.drag_direction_mode == 'SELECTIVE' and (inputs.drag_direction_box !='ANY' or inputs.drag_direction_lasso !='ANY')
sub.prop(inputs, "direction_edge", toggle=True)
sub.prop(inputs, "direction_select_through", toggle=True)
else:
row.prop(inputs, "direction_controls", icon='RIGHTARROW', emboss=False)
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "box_controls", text="Box", emboss=False)
if inputs.box_controls:
row.prop(inputs, "box_controls", icon='RIGHTARROW', emboss=False)
else:
row.prop(inputs, "box_controls", icon='DOWNARROW_HLT', emboss=False)
row = layout.row(align=True)
if inputs.drag_direction_box == 'LEFT_RIGHT':
row.prop(inputs, "blank_text", text="Left", emboss=False)
row.prop(inputs, "blank_text", text="Right", emboss=False)
elif inputs.drag_direction_box == 'UP_DOWN':
row.prop(inputs, "blank_text", text="Up", emboss=False)
row.prop(inputs, "blank_text", text="Down", emboss=False)
row = layout.row(align=True)
row.prop(inputs, "object_select_box")
if inputs.drag_direction_box != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_object):
row.prop(inputs, "object_select_downright_box", text="")
row = layout.row(align=True)
row.prop(inputs, "face_select_box")
if inputs.drag_direction_box != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_face):
row.prop(inputs, "face_select_downright_box", text="")
row = layout.row(align=True)
row.prop(inputs, "edge_select_box")
if inputs.drag_direction_box != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_edge):
row.prop(inputs, "edge_select_downright_box", text="")
row = layout.row(align=True)
row.prop(inputs, "backface_box")
if inputs.drag_direction_box != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_backface):
row.prop(inputs, "backface_downright_box", text="")
row = layout.row(align=True)
row.prop(inputs, "auto_xray_box")
if inputs.drag_direction_box != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray):
row.prop(inputs, "auto_xray_downright_box", text="")
row = layout.row(align=True)
row.prop(inputs, "select_through_box")
if inputs.drag_direction_box != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through):
row.prop(inputs, "select_through_downright_box", text="")
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "circle_controls", text="Circle", emboss=False)
if inputs.circle_controls:
row.prop(inputs, "circle_controls", icon='RIGHTARROW', emboss=False)
else:
row.prop(inputs, "circle_controls", icon='DOWNARROW_HLT', emboss=False)
row = layout.row(align=True)
row.prop(inputs, "object_select_circle")
row = layout.row(align=True)
row.prop(inputs, "face_select_circle")
row = layout.row(align=True)
row.prop(inputs, "edge_select_circle")
row = layout.row(align=True)
row.prop(inputs, "backface_circle")
row = layout.row(align=True)
row.prop(inputs, "auto_xray_circle")
row = layout.row(align=True)
row.prop(inputs, "select_through_circle")
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "lasso_controls", text="Lasso", emboss=False)
if inputs.lasso_controls:
row.prop(inputs, "lasso_controls", icon='RIGHTARROW', emboss=False)
else:
row.prop(inputs, "lasso_controls", icon='DOWNARROW_HLT', emboss=False)
row = layout.row(align=True)
if inputs.drag_direction_lasso == 'LEFT_RIGHT':
row.prop(inputs, "blank_text", text="Left", emboss=False)
row.prop(inputs, "blank_text", text="Right", emboss=False)
elif inputs.drag_direction_lasso == 'UP_DOWN':
row.prop(inputs, "blank_text", text="Up", emboss=False)
row.prop(inputs, "blank_text", text="Down", emboss=False)
row = layout.row(align=True)
row.prop(inputs, "object_select_lasso")
if inputs.drag_direction_lasso != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_object):
row.prop(inputs, "object_select_downright_lasso", text="")
row = layout.row(align=True)
row.prop(inputs, "face_select_lasso")
if inputs.drag_direction_lasso != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_face):
row.prop(inputs, "face_select_downright_lasso", text="")
row = layout.row(align=True)
row.prop(inputs, "edge_select_lasso")
if inputs.drag_direction_lasso != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_edge):
row.prop(inputs, "edge_select_downright_lasso", text="")
row = layout.row(align=True)
row.prop(inputs, "backface_lasso")
if inputs.drag_direction_lasso != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_backface):
row.prop(inputs, "backface_downright_lasso", text="")
row = layout.row(align=True)
row.prop(inputs, "auto_xray_lasso")
if inputs.drag_direction_lasso != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray):
row.prop(inputs, "auto_xray_downright_lasso", text="")
row = layout.row(align=True)
row.prop(inputs, "select_through_lasso")
if inputs.drag_direction_lasso != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through):
row.prop(inputs, "select_through_downright_lasso", text="")
else:
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "object_select_box")
row = layout.row(align=True)
row.prop(inputs, "face_select_box")
row = layout.row(align=True)
row.prop(inputs, "edge_select_box")
row = layout.row(align=True)
row.prop(inputs, "backface_box")
row = layout.row(align=True)
row.prop(inputs, "auto_xray_box")
row = layout.row(align=True)
row.prop(inputs, "select_through_box")
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "operator_controls", text="Operator Controls", emboss=False)
if inputs.operator_controls:
row.prop(inputs, "operator_controls", icon='DOWNARROW_HLT', emboss=False)
if inputs.userpref_mode == 'SPLIT':
row = layout.row(align=True, heading="Synchronize")
row.prop(inputs, "sync_box", toggle=True)
row.prop(inputs, "sync_circle", toggle=True)
row.prop(inputs, "sync_lasso", toggle=True)
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "object_operator", text="Object Operator", emboss=False)
if inputs.object_operator:
row.prop(inputs, "object_operator", icon='RIGHTARROW', emboss=False)
else:
row.prop(inputs, "object_operator", icon='DOWNARROW_HLT', emboss=False)
row = layout.row(align=True)
row.prop(inputs, "object_header", toggle=True)
box_op = inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_object)
lasso_op = inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_object)
box_circle_lasso = inputs.sync_box and box_op and inputs.sync_circle and inputs.sync_lasso and lasso_op
box_circle = inputs.sync_box and box_op and inputs.sync_circle
box_lasso = inputs.sync_box and box_op and inputs.sync_lasso and lasso_op
circle_lasso = inputs.sync_circle and inputs.sync_lasso and lasso_op
if inputs.userpref_mode == 'EASY' or box_circle_lasso:
row = layout.row(align=True, heading="Cycle")
elif box_circle:
row = layout.row(align=True, heading="Cycle Box & Circle")
elif box_lasso:
row = layout.row(align=True, heading="Cycle Box & Lasso")
else:
row = layout.row(align=True, heading="Cycle Box")
row.enabled = box_op
row.prop(inputs, "object_cycle_touch", toggle=True)
row.prop(inputs, "object_cycle_enclose", toggle=True)
row.prop(inputs, "object_cycle_origin", toggle=True)
if inputs.userpref_mode == 'SPLIT' and not box_circle_lasso:
if not box_circle and not circle_lasso:
row = layout.row(align=True, heading="Cycle Circle")
row.prop(inputs, "object_cycle_touch_circle", toggle=True)
row.prop(inputs, "object_cycle_enclose_circle", toggle=True)
row.prop(inputs, "object_cycle_origin_circle", toggle=True)
if not box_lasso:
if circle_lasso:
row = layout.row(align=True, heading="Cycle Lasso & Circle")
else:
row = layout.row(align=True, heading="Cycle Lasso")
row.enabled = lasso_op
row.prop(inputs, "object_cycle_touch_lasso", toggle=True)
row.prop(inputs, "object_cycle_enclose_lasso", toggle=True)
row.prop(inputs, "object_cycle_origin_lasso", toggle=True)
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "face_operator", text="Face Operator", emboss=False)
if inputs.face_operator:
row.prop(inputs, "face_operator", icon='RIGHTARROW', emboss=False)
else:
row.prop(inputs, "face_operator", icon='DOWNARROW_HLT', emboss=False)
row = layout.row(align=True)
row.prop(inputs, "face_header", toggle=True)
box_op = inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_face)
lasso_op = inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_face)
box_circle_lasso = inputs.sync_box and box_op and inputs.sync_circle and inputs.sync_lasso and lasso_op
box_circle = inputs.sync_box and box_op and inputs.sync_circle
box_lasso = inputs.sync_box and box_op and inputs.sync_lasso and lasso_op
circle_lasso = inputs.sync_circle and inputs.sync_lasso and lasso_op
if inputs.userpref_mode == 'EASY' or box_circle_lasso:
row = layout.row(align=True, heading="Cycle")
elif box_circle:
row = layout.row(align=True, heading="Cycle Box & Circle")
elif box_lasso:
row = layout.row(align=True, heading="Cycle Box & Lasso")
else:
row = layout.row(align=True, heading="Cycle Box")
row.enabled = box_op
row.prop(inputs, "face_cycle_default", toggle=True)
row.prop(inputs, "face_cycle_touch", toggle=True)
row.prop(inputs, "face_cycle_enclose", toggle=True)
row.prop(inputs, "face_cycle_center", toggle=True)
if inputs.userpref_mode == 'SPLIT' and not box_circle_lasso:
if not box_circle and not circle_lasso:
row = layout.row(align=True, heading="Cycle Circle")
row.prop(inputs, "face_cycle_default_circle", toggle=True)
row.prop(inputs, "face_cycle_touch_circle", toggle=True)
row.prop(inputs, "face_cycle_enclose_circle", toggle=True)
row.prop(inputs, "face_cycle_center_circle", toggle=True)
if not box_lasso:
if circle_lasso:
row = layout.row(align=True, heading="Cycle Lasso & Circle")
else:
row = layout.row(align=True, heading="Cycle Lasso")
row.enabled = lasso_op
row.prop(inputs, "face_cycle_default_lasso", toggle=True)
row.prop(inputs, "face_cycle_touch_lasso", toggle=True)
row.prop(inputs, "face_cycle_enclose_lasso", toggle=True)
row.prop(inputs, "face_cycle_center_lasso", toggle=True)
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "edge_operator", text="Edge Operator", emboss=False)
if inputs.edge_operator:
row.prop(inputs, "edge_operator", icon='RIGHTARROW', emboss=False)
else:
row.prop(inputs, "edge_operator", icon='DOWNARROW_HLT', emboss=False)
row = layout.row(align=True)
row.prop(inputs, "edge_header", toggle=True)
box_op = inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_edge)
lasso_op = inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_edge)
box_circle_lasso = inputs.sync_box and box_op and inputs.sync_circle and inputs.sync_lasso and lasso_op
box_circle = inputs.sync_box and box_op and inputs.sync_circle
box_lasso = inputs.sync_box and box_op and inputs.sync_lasso and lasso_op
circle_lasso = inputs.sync_circle and inputs.sync_lasso and lasso_op
if inputs.userpref_mode == 'EASY' or box_circle_lasso:
row = layout.row(align=True, heading="Cycle")
elif box_circle:
row = layout.row(align=True, heading="Cycle Box & Circle")
elif box_lasso:
row = layout.row(align=True, heading="Cycle Box & Lasso")
else:
row = layout.row(align=True, heading="Cycle Box")
row.enabled = box_op
row.prop(inputs, "edge_cycle_default", toggle=True)
row.prop(inputs, "edge_cycle_touch", toggle=True)
row.prop(inputs, "edge_cycle_enclose", toggle=True)
if inputs.userpref_mode == 'SPLIT' and not box_circle_lasso:
if not box_circle and not circle_lasso:
row = layout.row(align=True, heading="Cycle Circle")
row.prop(inputs, "edge_cycle_touch_circle", toggle=True)
row.prop(inputs, "edge_cycle_enclose_circle", toggle=True)
if not box_lasso:
if circle_lasso:
row = layout.row(align=True, heading="Cycle Lasso & Circle")
else:
row = layout.row(align=True, heading="Cycle Lasso")
row.enabled = lasso_op
row.prop(inputs, "edge_cycle_default_lasso", toggle=True)
row.prop(inputs, "edge_cycle_touch_lasso", toggle=True)
row.prop(inputs, "edge_cycle_enclose_lasso", toggle=True)
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "backface_operator", text="Backface Operator", emboss=False)
if inputs.backface_operator:
row.prop(inputs, "backface_operator", icon='RIGHTARROW', emboss=False)
else:
row.prop(inputs, "backface_operator", icon='DOWNARROW_HLT', emboss=False)
row = layout.row(align=True)
row.prop(inputs, "backface_header", toggle=True)
row = layout.row(align=True)
box_op = inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_backface)
lasso_op = inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_backface)
box_circle_lasso = inputs.sync_box and box_op and inputs.sync_circle and inputs.sync_lasso and lasso_op
box_circle = inputs.sync_box and box_op and inputs.sync_circle
box_lasso = inputs.sync_box and box_op and inputs.sync_lasso and lasso_op
circle_lasso = inputs.sync_circle and inputs.sync_lasso and lasso_op
row = layout.row(align=True)
if inputs.userpref_mode == 'EASY' or box_circle_lasso:
proptext="Toggle"
elif box_circle:
proptext="Toggle Box & Circle"
elif box_lasso:
proptext="Toggle Box & Lasso"
else:
proptext="Toggle Box"
row.enabled = box_op
row.prop(inputs, "backface_toggle", text=proptext)
if inputs.userpref_mode == 'SPLIT' and not box_circle_lasso:
if not box_circle and not circle_lasso:
row = layout.row(align=True)
row.prop(inputs, "backface_toggle_circle", text="Toggle Circle")
if not box_lasso:
if circle_lasso:
row = layout.row(align=True)
proptext="Toggle Lasso & Circle"
else:
row = layout.row(align=True)
proptext="Toggle Lasso"
row.enabled = lasso_op
row.prop(inputs, "backface_toggle_lasso", text=proptext)
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "auto_xray_operator", text="Auto X-Ray Operator", emboss=False)
if inputs.auto_xray_operator:
row.prop(inputs, "auto_xray_operator", icon='RIGHTARROW', emboss=False)
else:
row.prop(inputs, "auto_xray_operator", icon='DOWNARROW_HLT', emboss=False)
row = layout.row(align=True)
row.prop(inputs, "auto_xray_header", toggle=True)
row = layout.row(align=True)
box_op = inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_auto_xray)
lasso_op = inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_auto_xray)
box_circle_lasso = inputs.sync_box and box_op and inputs.sync_circle and inputs.sync_lasso and lasso_op
box_circle = inputs.sync_box and box_op and inputs.sync_circle
box_lasso = inputs.sync_box and box_op and inputs.sync_lasso and lasso_op
circle_lasso = inputs.sync_circle and inputs.sync_lasso and lasso_op
row = layout.row(align=True)
if inputs.userpref_mode == 'EASY' or box_circle_lasso:
proptext="Toggle"
elif box_circle:
proptext="Toggle Box & Circle"
elif box_lasso:
proptext="Toggle Box & Lasso"
else:
proptext="Toggle Box"
row.enabled = box_op
row.prop(inputs, "auto_xray_toggle", text=proptext)
if inputs.userpref_mode == 'SPLIT' and not box_circle_lasso:
if not box_circle and not circle_lasso:
row = layout.row(align=True)
row.prop(inputs, "auto_xray_toggle_circle", text="Toggle Circle")
if not box_lasso:
if circle_lasso:
row = layout.row(align=True)
proptext="Toggle Lasso & Circle"
else:
row = layout.row(align=True)
proptext="Toggle Lasso"
row.enabled = lasso_op
row.prop(inputs, "auto_xray_toggle_lasso", text=proptext)
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "select_through_operator", text="Select Through Operator", emboss=False)
if inputs.select_through_operator:
row.prop(inputs, "select_through_operator", icon='RIGHTARROW', emboss=False)
else:
row.prop(inputs, "select_through_operator", icon='DOWNARROW_HLT', emboss=False)
row = layout.row(align=True)
row.prop(inputs, "select_through_header", toggle=True)
row = layout.row(align=True)
box_op = inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_select_through)
lasso_op = inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_select_through)
box_circle_lasso = inputs.sync_box and box_op and inputs.sync_circle and inputs.sync_lasso and lasso_op
box_circle = inputs.sync_box and box_op and inputs.sync_circle
box_lasso = inputs.sync_box and box_op and inputs.sync_lasso and lasso_op
circle_lasso = inputs.sync_circle and inputs.sync_lasso and lasso_op
row = layout.row(align=True)
if inputs.userpref_mode == 'EASY' or box_circle_lasso:
proptext="Toggle"
elif box_circle:
proptext="Toggle Box & Circle"
elif box_lasso:
proptext="Toggle Box & Lasso"
else:
proptext="Toggle Box"
row.enabled = box_op
row.prop(inputs, "select_through_toggle", text=proptext)
if inputs.userpref_mode == 'SPLIT' and not box_circle_lasso:
if not box_circle and not circle_lasso:
row = layout.row(align=True)
row.prop(inputs, "select_through_toggle_circle", text="Toggle Circle")
if not box_lasso:
if circle_lasso:
row = layout.row(align=True)
proptext="Toggle Lasso & Circle"
else:
row = layout.row(align=True)
proptext="Toggle Lasso"
row.enabled = lasso_op
row.prop(inputs, "select_through_toggle_lasso", text=proptext)
else:
row.prop(inputs, "operator_controls", icon='RIGHTARROW', emboss=False)
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "pie_menu_controls", text="Pie Menu Controls", emboss=False)
if inputs.pie_menu_controls:
row.prop(inputs, "pie_menu_controls", icon='DOWNARROW_HLT', emboss=False)
row = layout.row(align=True)
row.prop(inputs, "object_pie", expand=True)
row = layout.row(align=True)
row.prop(inputs, "face_pie", expand=True)
row = layout.row(align=True)
row.prop(inputs, "edge_pie", expand=True)
row = layout.row(align=True)
row.prop(inputs, "backface_pie", expand=True)
row = layout.row(align=True)
row.prop(inputs, "auto_xray_pie", expand=True)
row = layout.row(align=True)
row.prop(inputs, "select_through_pie", expand=True)
row = layout.row(align=True)
row.prop(inputs, "box_pie", expand=True)
row = layout.row(align=True)
row.prop(inputs, "circle_pie", expand=True)
row = layout.row(align=True)
row.prop(inputs, "lasso_pie", expand=True)
else:
row.prop(inputs, "pie_menu_controls", icon='RIGHTARROW', emboss=False)
class USERPREF_PT_custom_mouse(CustomPanel, CenterAlignMixIn, Panel):
bl_label = "Mouse"
def draw_centered(self, context, layout):
inputs = context.preferences.inputs
row = layout.row(align=True)
row.prop(inputs, "adjustable_click_select")
if inputs.adjustable_click_select == 'CUSTOM':
row.prop(inputs, "selection_radius")
row = layout.row(align=True)
row.prop(inputs, "select_unbiased", toggle=True)
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "custom_cursor")
if inputs.custom_cursor == 'CUSTOM':
row.operator("preferences.reset_cursors")
row = layout.row(align=True)
row.prop(inputs, "system_cursor")
row = layout.row(align=True)
row.prop(inputs, "edit_cursor")
row = layout.row(align=True)
row.prop(inputs, "paint_cursor")
row = layout.row(align=True)
row.prop(inputs, "dot_cursor")
row = layout.row(align=True)
row.prop(inputs, "knife_cursor")
row = layout.row(align=True)
row.prop(inputs, "pencil_cursor")
row = layout.row(align=True)
row.prop(inputs, "eraser_cursor")
row = layout.row(align=True)
row.prop(inputs, "eyedropper_cursor")
class USERPREF_PT_custom_visual(CustomPanel, CenterAlignMixIn, Panel):
bl_label = "Visual"
def draw_centered(self, context, layout):
inputs = context.preferences.inputs
row = layout.row(align=True)
row.prop(inputs, "facedot_mode", expand=True)
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "shading_button_mode")
if inputs.shading_button_mode == 'CYCLE':
row.prop(inputs, "shading_cycle_wire", icon='SHADING_WIRE', toggle=True)
row.prop(inputs, "shading_cycle_solid", icon='SHADING_SOLID', toggle=True)
row.prop(inputs, "shading_cycle_material", icon='SHADING_TEXTURE', toggle=True)
row.prop(inputs, "shading_cycle_render", icon='SHADING_RENDERED', toggle=True)
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.enabled = inputs.shading_button_mode != 'XRAY_COMBINE'
row.prop(inputs, "xray_button", expand=True)
row = layout.row(align=True)
row.separator(factor=1.5)
row = layout.row(align=True)
row.prop(inputs, "custom_highlight")
if inputs.custom_highlight == 'CUSTOM':
row.prop(inputs, "header_highlight")
# -----------------------------------------------------------------------------
# Interface Panels
@ -2728,6 +3309,10 @@ classes = (
USERPREF_MT_view,
USERPREF_MT_save_load,
USERPREF_PT_custom_drag_select,
USERPREF_PT_custom_mouse,
USERPREF_PT_custom_visual,
USERPREF_PT_interface_display,
USERPREF_PT_interface_editors,
USERPREF_PT_interface_temporary_windows,

View File

@ -751,6 +751,7 @@ class VIEW3D_HT_header(Header):
layout = self.layout
tool_settings = context.tool_settings
inputs = context.preferences.inputs
view = context.space_data
shading = view.shading
@ -783,7 +784,220 @@ class VIEW3D_HT_header(Header):
)
del act_mode_item
layout.template_header_3D_mode()
row = layout.row(align=True)
row.template_header_3D_mode()
if inputs.drag_control_mode == 'USERPREF':
if (object_mode == 'OBJECT' and (inputs.object_header or inputs.auto_xray_header or inputs.select_through_header)) or (object_mode == 'EDIT' and (inputs.face_header or inputs.edge_header or inputs.backface_header or inputs.select_through_header or inputs.auto_xray_header)):
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
enable_auto_xray_button = inputs.auto_xray_header
depress_auto_xray = False
enable_select_through_button = inputs.select_through_header
depress_select_through = False
enable_object_button = inputs.object_header
objicon = 'OBJECT_TOUCH'
enable_face_button = inputs.face_header
facicon = 'FACE_DEFAULT'
enable_edge_button = inputs.edge_header
edgicon = 'EDGE_DEFAULT'
enable_backface_button = inputs.backface_header
depress_bface = False
if inputs.userpref_mode == 'SPLIT' and tool == "builtin.select_circle":
if object_mode == 'OBJECT':
if enable_object_button:
if inputs.object_select_circle == 'OBJECT_ENCLOSE':
objicon = 'OBJECT_ENCLOSE'
elif inputs.object_select_circle == 'OBJECT_ORIGIN':
objicon = 'LIGHTPROBE_SPHERE'
if enable_auto_xray_button:
depress_auto_xray = inputs.auto_xray_circle == 'AUTO_XRAY_OBJECT' or inputs.auto_xray_circle == 'AUTO_XRAY_BOTH'
if enable_select_through_button:
depress_select_through = inputs.select_through_circle == 'SELECT_THROUGH_OBJECT' or inputs.select_through_circle == 'SELECT_THROUGH_BOTH'
else:
if enable_face_button:
if inputs.face_select_circle == 'FACE_TOUCH':
facicon = 'FACE_TOUCH'
elif inputs.face_select_circle == 'FACE_ENCLOSE':
facicon = 'FACE_ENCLOSE'
elif inputs.face_select_circle == 'FACE_CENTER':
facicon = 'LIGHTPROBE_PLANE'
if enable_edge_button:
if inputs.edge_select_circle == 'EDGE_ENCLOSE':
edgicon = 'EDGE_ENCLOSE'
else:
edgicon = 'EDGE_TOUCH'
if enable_auto_xray_button:
depress_auto_xray = inputs.auto_xray_circle == 'AUTO_XRAY_EDIT' or inputs.auto_xray_circle == 'AUTO_XRAY_BOTH'
if enable_select_through_button:
depress_select_through = inputs.select_through_circle == 'SELECT_THROUGH_EDIT' or inputs.select_through_circle == 'SELECT_THROUGH_BOTH'
if enable_backface_button:
depress_bface = inputs.backface_circle != 'DEFAULT'
elif inputs.userpref_mode == 'SPLIT' and tool == "builtin.select_lasso":
if object_mode == 'OBJECT':
if enable_object_button:
if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_object == False:
if inputs.object_select_lasso == 'OBJECT_ENCLOSE':
objicon = 'OBJECT_ENCLOSE'
elif inputs.object_select_lasso == 'OBJECT_ORIGIN':
objicon = 'LIGHTPROBE_SPHERE'
else:
enable_object_button = False
if enable_auto_xray_button:
if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False):
depress_auto_xray = inputs.auto_xray_lasso == 'AUTO_XRAY_OBJECT' or inputs.auto_xray_lasso == 'AUTO_XRAY_BOTH'
else:
enable_auto_xray_button = False
if enable_select_through_button:
if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False):
depress_select_through = inputs.select_through_lasso == 'SELECT_THROUGH_OBJECT' or inputs.select_through_lasso == 'SELECT_THROUGH_BOTH'
else:
enable_select_through_button = False
else:
if enable_face_button:
if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_face == False:
if inputs.face_select_lasso == 'FACE_TOUCH':
facicon = 'FACE_TOUCH'
elif inputs.face_select_lasso == 'FACE_ENCLOSE':
facicon = 'FACE_ENCLOSE'
elif inputs.face_select_lasso == 'FACE_CENTER':
facicon = 'LIGHTPROBE_PLANE'
else:
enable_face_button = False
if enable_edge_button:
if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_edge == False:
if inputs.edge_select_lasso == 'EDGE_TOUCH':
edgicon = 'EDGE_TOUCH'
elif inputs.edge_select_lasso == 'EDGE_ENCLOSE':
edgicon = 'EDGE_ENCLOSE'
else:
enable_edge_button = False
if enable_backface_button:
if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_backface == False:
depress_bface = inputs.backface_lasso != 'DEFAULT'
else:
enable_backface_button = False
if enable_auto_xray_button:
if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False):
depress_auto_xray = inputs.auto_xray_lasso == 'AUTO_XRAY_EDIT' or inputs.auto_xray_lasso == 'AUTO_XRAY_BOTH'
else:
enable_auto_xray_button = False
if enable_select_through_button:
if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False):
depress_select_through = inputs.select_through_lasso == 'SELECT_THROUGH_EDIT' or inputs.select_through_lasso == 'SELECT_THROUGH_BOTH'
else:
enable_select_through_button = False
elif (inputs.userpref_mode == 'SPLIT' and tool == "builtin.select_box") or (inputs.userpref_mode == 'EASY' and (tool == "builtin.select_box" or tool == "builtin.select_lasso" or tool == "builtin.select_circle")):
if object_mode == 'OBJECT':
if enable_object_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_object == False):
if inputs.object_select_box == 'OBJECT_ENCLOSE':
objicon = 'OBJECT_ENCLOSE'
elif inputs.object_select_box == 'OBJECT_ORIGIN':
objicon = 'LIGHTPROBE_SPHERE'
else:
enable_object_button = False
if enable_auto_xray_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False):
depress_auto_xray = inputs.auto_xray_box == 'AUTO_XRAY_OBJECT' or inputs.auto_xray_box == 'AUTO_XRAY_BOTH'
else:
enable_auto_xray_button = False
if enable_select_through_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False):
depress_select_through = inputs.select_through_box == 'SELECT_THROUGH_OBJECT' or inputs.select_through_box == 'SELECT_THROUGH_BOTH'
else:
enable_select_through_button = False
else:
if enable_face_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_face == False):
if inputs.face_select_box == 'FACE_TOUCH':
facicon = 'FACE_TOUCH'
elif inputs.face_select_box == 'FACE_ENCLOSE':
facicon = 'FACE_ENCLOSE'
elif inputs.face_select_box == 'FACE_CENTER':
facicon = 'LIGHTPROBE_PLANE'
else:
enable_face_button = False
if enable_edge_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_edge == False):
if inputs.edge_select_box == 'EDGE_TOUCH':
edgicon = 'EDGE_TOUCH'
elif inputs.edge_select_box == 'EDGE_ENCLOSE':
edgicon = 'EDGE_ENCLOSE'
else:
enable_edge_button = False
if enable_backface_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_backface == False):
depress_bface = inputs.backface_box != 'DEFAULT'
else:
enable_backface_button = False
if enable_auto_xray_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False):
depress_auto_xray = inputs.auto_xray_box == 'AUTO_XRAY_EDIT' or inputs.auto_xray_box == 'AUTO_XRAY_BOTH'
else:
enable_auto_xray_button = False
if enable_select_through_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False):
depress_select_through = inputs.select_through_box == 'SELECT_THROUGH_EDIT' or inputs.select_through_box == 'SELECT_THROUGH_BOTH'
else:
enable_select_through_button = False
else:
enable_auto_xray_button = False
enable_select_through_button = False
enable_object_button = False
enable_face_button = False
enable_edge_button = False
enable_backface_button = False
if object_mode == 'OBJECT':
if inputs.object_header:
sub = row.row(align=True)
sub.enabled = enable_object_button
sub.operator("view3d.cycle_object", text="", icon=objicon)
else:
if inputs.face_header:
sub = row.row(align=True)
sub.enabled = enable_face_button
sub.operator("view3d.cycle_face", text="", icon=facicon)
if inputs.edge_header:
sub = row.row(align=True)
sub.enabled = enable_edge_button
sub.operator("view3d.cycle_edge", text="", icon=edgicon)
if inputs.backface_header:
sub = row.row(align=True)
sub.enabled = enable_backface_button
sub.operator("view3d.toggle_backface", text="", icon='NORMALS_FACE', depress=depress_bface)
del tool, enable_object_button, objicon, enable_face_button, facicon, enable_edge_button, edgicon, enable_backface_button, depress_bface
# Contains buttons like Mode, Pivot, Layer, Mesh Select Mode...
if obj:
@ -1057,8 +1271,20 @@ class VIEW3D_HT_header(Header):
):
sub.popover(panel="VIEW3D_PT_overlay_bones", text="", icon='POSE_HLT')
row = layout.row()
row.active = (object_mode == 'EDIT') or (shading.type in {'WIREFRAME', 'SOLID'})
row = layout.row(align=True)
if (object_mode == 'EDIT' or object_mode == 'OBJECT') and inputs.drag_control_mode == 'USERPREF' and (inputs.auto_xray_header or inputs.select_through_header):
if inputs.auto_xray_header:
sub = row.row(align=True)
sub.enabled = enable_auto_xray_button
sub.operator("view3d.toggle_auto_xray", text="", icon='AUTO_XRAY', depress=depress_auto_xray)
if inputs.select_through_header:
sub = row.row(align=True)
sub.enabled = enable_select_through_button
sub.operator("view3d.toggle_select_through", text="", icon='SELECT_THROUGH', depress=depress_select_through)
del enable_auto_xray_button, depress_auto_xray, enable_select_through_button, depress_select_through
# While exposing `shading.show_xray(_wireframe)` is correct.
# this hides the key shortcut from users: #70433.
@ -1068,14 +1294,27 @@ 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 inputs.xray_button != 'HIDE' and inputs.shading_button_mode != 'XRAY_COMBINE':
row.active = (object_mode == 'EDIT') or (shading.type in {'WIREFRAME', 'SOLID'})
row.operator("view3d.toggle_xray", text="", icon='XRAY', depress=draw_depressed)
if not ((inputs.shading_button_mode == 'XRAY_COMBINE' or inputs.xray_button == 'HIDE') and not inputs.select_through_header and not inputs.auto_xray_header):
row = layout.row(align=True)
if inputs.shading_button_mode != 'DEFAULT':
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'
if inputs.shading_button_mode == 'XRAY_COMBINE':
row.operator("view3d.toggle_xray", text="", icon=shadicon, depress=draw_depressed)
else:
row.operator("view3d.cycle_shading", text="", icon=shadicon)
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
@ -1233,6 +1472,322 @@ class ShowHideMenu:
layout.operator("%s.hide" % self._operator_name, text="Hide Unselected").unselected = True
# Custom Operators
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)
tool_settings = context.tool_settings
inputs = context.preferences.inputs
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 tool.idname == "builtin.select_box":
for i in range(2):
bpy.ops.wm.tool_set_by_id(name="builtin.select_lasso")
else:
for i in range(2):
bpy.ops.wm.tool_set_by_id(name="builtin.select_box")
return {'FINISHED'}
class VIEW3D_box_select(bpy.types.Operator):
bl_idname = "view3d.box_select"
bl_label = "Box"
bl_description = "Use Box Select"
def invoke(self, context, event):
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
tool = ToolSelectPanelHelper.tool_active_from_context(context)
tool_settings = context.tool_settings
for i in range(2):
if tool.idname == "builtin.select_circle" or tool.idname == "builtin.select_lasso" or tool.idname == "builtin.select":
bpy.ops.wm.tool_set_by_id(name="builtin.select_box", space_type='VIEW_3D')
elif tool_settings.workspace_tool_type == 'FALLBACK':
bpy.ops.wm.tool_set_by_id(name="builtin.select_box", as_fallback=True, space_type='VIEW_3D')
else:
bpy.ops.wm.tool_set_by_id(name="builtin.select_box", space_type='VIEW_3D')
return {'FINISHED'}
class VIEW3D_circle_select(bpy.types.Operator):
bl_idname = "view3d.circle_select"
bl_label = "Circle"
bl_description = "Use Circle Select"
def invoke(self, context, event):
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
tool = ToolSelectPanelHelper.tool_active_from_context(context)
tool_settings = context.tool_settings
for i in range(2):
if tool.idname == "builtin.select_box" or tool.idname == "builtin.select_lasso" or tool.idname == "builtin.select":
bpy.ops.wm.tool_set_by_id(name="builtin.select_circle", space_type='VIEW_3D')
elif tool_settings.workspace_tool_type == 'FALLBACK':
bpy.ops.wm.tool_set_by_id(name="builtin.select_circle", as_fallback=True, space_type='VIEW_3D')
else:
bpy.ops.wm.tool_set_by_id(name="builtin.select_circle", space_type='VIEW_3D')
return {'FINISHED'}
class VIEW3D_lasso_select(bpy.types.Operator):
bl_idname = "view3d.lasso_select"
bl_label = "Lasso"
bl_description = "Use Lasso Select"
def invoke(self, context, event):
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
tool = ToolSelectPanelHelper.tool_active_from_context(context)
tool_settings = context.tool_settings
for i in range(2):
if tool.idname == "builtin.select_circle" or tool.idname == "builtin.select_box" or tool.idname == "builtin.select":
bpy.ops.wm.tool_set_by_id(name="builtin.select_lasso")
elif tool_settings.workspace_tool_type == 'FALLBACK':
bpy.ops.wm.tool_set_by_id(name="builtin.select_lasso", as_fallback=True)
else:
bpy.ops.wm.tool_set_by_id(name="builtin.select_lasso")
return {'FINISHED'}
class VIEW3D_MT_PIE_Drag_Select(Menu):
bl_label = "Drag Select"
def draw(self, context):
layout = self.layout
tool_settings = context.tool_settings
inputs = context.preferences.inputs
obj = context.active_object
object_mode = 'OBJECT' if obj is None else obj.mode
if inputs.drag_control_mode == 'USERPREF' and (object_mode == 'OBJECT' or object_mode == 'EDIT'):
enable_auto_xray_button = inputs.auto_xray_pie == 'SHOW'
depress_auto_xray = False
enable_select_through_button = inputs.select_through_pie == 'SHOW'
depress_select_through = False
enable_backface_button = inputs.backface_pie == 'SHOW'
depress_bface = False
enable_object_button = inputs.object_pie == 'SHOW'
objicon = 'OBJECT_TOUCH'
enable_face_button = inputs.face_pie == 'SHOW'
facicon = 'FACE_DEFAULT'
enable_edge_button = inputs.edge_pie == 'SHOW'
edgicon = 'EDGE_DEFAULT'
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 inputs.userpref_mode == 'SPLIT' and tool == "builtin.select_circle":
if object_mode == 'OBJECT':
if enable_object_button:
if inputs.object_select_circle == 'OBJECT_ENCLOSE':
objicon = 'OBJECT_ENCLOSE'
elif inputs.object_select_circle == 'OBJECT_ORIGIN':
objicon = 'LIGHTPROBE_SPHERE'
if enable_auto_xray_button:
depress_auto_xray = inputs.auto_xray_circle == 'AUTO_XRAY_OBJECT' or inputs.auto_xray_circle == 'AUTO_XRAY_BOTH'
if enable_select_through_button:
depress_select_through = inputs.select_through_circle == 'SELECT_THROUGH_OBJECT' or inputs.select_through_circle == 'SELECT_THROUGH_BOTH'
else:
if enable_face_button:
if inputs.face_select_circle == 'FACE_TOUCH':
facicon = 'FACE_TOUCH'
elif inputs.face_select_circle == 'FACE_ENCLOSE':
facicon = 'FACE_ENCLOSE'
elif inputs.face_select_circle == 'FACE_CENTER':
facicon = 'LIGHTPROBE_PLANE'
if enable_edge_button:
if inputs.edge_select_circle == 'EDGE_ENCLOSE':
edgicon = 'EDGE_ENCLOSE'
else:
edgicon = 'EDGE_TOUCH'
if enable_backface_button:
depress_bface = inputs.backface_circle != 'DEFAULT'
if enable_auto_xray_button:
depress_auto_xray = inputs.auto_xray_circle == 'AUTO_XRAY_EDIT' or inputs.auto_xray_circle == 'AUTO_XRAY_BOTH'
if enable_select_through_button:
depress_select_through = inputs.select_through_circle == 'SELECT_THROUGH_EDIT' or inputs.select_through_circle == 'SELECT_THROUGH_BOTH'
elif inputs.userpref_mode == 'SPLIT' and tool == "builtin.select_lasso":
if object_mode == 'OBJECT':
if enable_object_button:
if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_object == False:
if inputs.object_select_lasso == 'OBJECT_ENCLOSE':
objicon = 'OBJECT_ENCLOSE'
elif inputs.object_select_lasso == 'OBJECT_ORIGIN':
objicon = 'LIGHTPROBE_SPHERE'
else:
enable_object_button = False
if enable_auto_xray_button:
if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False):
depress_auto_xray = inputs.auto_xray_lasso == 'AUTO_XRAY_OBJECT' or inputs.auto_xray_lasso == 'AUTO_XRAY_BOTH'
else:
enable_auto_xray_button = False
if enable_select_through_button:
if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False):
depress_select_through = inputs.select_through_lasso == 'SELECT_THROUGH_OBJECT' or inputs.select_through_lasso == 'SELECT_THROUGH_BOTH'
else:
enable_select_through_button = False
else:
if enable_face_button:
if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_face == False:
if inputs.face_select_lasso == 'FACE_TOUCH':
facicon = 'FACE_TOUCH'
elif inputs.face_select_lasso == 'FACE_ENCLOSE':
facicon = 'FACE_ENCLOSE'
elif inputs.face_select_lasso == 'FACE_CENTER':
facicon = 'LIGHTPROBE_PLANE'
else:
enable_face_button = False
if enable_edge_button:
if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_edge == False:
if inputs.edge_select_lasso == 'EDGE_TOUCH':
edgicon = 'EDGE_TOUCH'
elif inputs.edge_select_lasso == 'EDGE_ENCLOSE':
edgicon = 'EDGE_ENCLOSE'
else:
enable_edge_button = False
if enable_backface_button:
if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_backface == False:
depress_bface = inputs.backface_lasso != 'DEFAULT'
else:
enable_backface_button = False
if enable_auto_xray_button:
if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False):
depress_auto_xray = inputs.auto_xray_lasso == 'AUTO_XRAY_EDIT' or inputs.auto_xray_lasso == 'AUTO_XRAY_BOTH'
else:
enable_auto_xray_button = False
if enable_select_through_button:
if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False):
depress_select_through = inputs.select_through_lasso == 'SELECT_THROUGH_EDIT' or inputs.select_through_lasso == 'SELECT_THROUGH_BOTH'
else:
enable_select_through_button = False
elif (inputs.userpref_mode == 'SPLIT' and tool == "builtin.select_box") or (inputs.userpref_mode == 'EASY' and (tool == "builtin.select_box" or tool == "builtin.select_lasso" or tool == "builtin.select_circle")):
if object_mode == 'OBJECT':
if enable_object_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_object == False):
if inputs.object_select_box == 'OBJECT_ENCLOSE':
objicon = 'OBJECT_ENCLOSE'
elif inputs.object_select_box == 'OBJECT_ORIGIN':
objicon = 'LIGHTPROBE_SPHERE'
else:
enable_object_button = False
if enable_auto_xray_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False):
depress_auto_xray = inputs.auto_xray_box == 'AUTO_XRAY_OBJECT' or inputs.auto_xray_box == 'AUTO_XRAY_BOTH'
else:
enable_auto_xray_button = False
if enable_select_through_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False):
depress_select_through = inputs.select_through_box == 'SELECT_THROUGH_OBJECT' or inputs.select_through_box == 'SELECT_THROUGH_BOTH'
else:
enable_select_through_button = False
else:
if enable_face_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_face == False):
if inputs.face_select_box == 'FACE_TOUCH':
facicon = 'FACE_TOUCH'
elif inputs.face_select_box == 'FACE_ENCLOSE':
facicon = 'FACE_ENCLOSE'
elif inputs.face_select_box == 'FACE_CENTER':
facicon = 'LIGHTPROBE_PLANE'
else:
enable_face_button = False
if enable_edge_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_edge == False):
if inputs.edge_select_box == 'EDGE_TOUCH':
edgicon = 'EDGE_TOUCH'
elif inputs.edge_select_box == 'EDGE_ENCLOSE':
edgicon = 'EDGE_ENCLOSE'
else:
enable_edge_button = False
if enable_backface_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_backface == False):
depress_bface = inputs.backface_box != 'DEFAULT'
else:
enable_backface_button = False
if enable_auto_xray_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False):
depress_auto_xray = inputs.auto_xray_box == 'AUTO_XRAY_EDIT' or inputs.auto_xray_box == 'AUTO_XRAY_BOTH'
else:
enable_auto_xray_button = False
if enable_select_through_button:
if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False):
depress_select_through = inputs.select_through_box == 'SELECT_THROUGH_EDIT' or inputs.select_through_box == 'SELECT_THROUGH_BOTH'
else:
enable_select_through_button = False
else:
enable_auto_xray_button = False
enable_select_through_button = False
enable_object_button = False
enable_face_button = False
enable_edge_button = False
enable_backface_button = False
pie = layout.menu_pie()
if enable_auto_xray_button:
pie.operator("view3d.toggle_auto_xray", icon='AUTO_XRAY', depress=depress_auto_xray)
if enable_select_through_button:
pie.operator("view3d.toggle_select_through", icon='SELECT_THROUGH', depress=depress_select_through)
if inputs.box_pie == 'SHOW' or tool != "builtin.select_box" and inputs.box_pie == 'CONTEXT':
pie.operator("view3d.box_select", icon='SELECT_SET')
if inputs.circle_pie == 'SHOW' or tool != "builtin.select_circle" and inputs.circle_pie == 'CONTEXT':
pie.operator("view3d.circle_select", icon='MESH_CIRCLE')
if inputs.lasso_pie == 'SHOW' or tool != "builtin.select_lasso" and inputs.lasso_pie == 'CONTEXT':
pie.operator("view3d.lasso_select", icon='MOD_DASH')
if object_mode == 'OBJECT':
if enable_object_button:
pie.operator("view3d.cycle_object", text="Object", icon=objicon)
else:
if enable_backface_button:
pie.operator("view3d.toggle_backface", text="Backface", icon='NORMALS_FACE', depress=depress_bface)
if enable_face_button:
pie.operator("view3d.cycle_face", text="Face", icon=facicon)
if enable_edge_button:
pie.operator("view3d.cycle_edge", text="Edge", icon=edgicon)
class VIEW3D_pie_drag_select(bpy.types.Operator):
bl_idname = "view3d.pie_drag_select"
bl_label = "Drag Select"
def invoke(self, context, event):
bpy.ops.wm.call_menu_pie(name="VIEW3D_MT_PIE_Drag_Select")
return {'FINISHED'}
# Standard transforms which apply to all cases (mix-in class, not used directly).
class VIEW3D_MT_transform_base:
bl_label = "Transform"
@ -6738,6 +7293,61 @@ class VIEW3D_PT_shading_options(Panel):
row = col.row()
row.active = not xray_active
row.prop(shading, "use_dof", text="Depth of Field")
else:
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
xray_active = shading.show_xray and shading.xray_alpha != 1
row = col.row(align=True)
row.prop(shading, "show_shadows", text="")
row.active = not xray_active
sub = row.row(align=True)
sub.active = shading.show_shadows
sub.prop(shading, "shadow_intensity", text="Shadow")
sub.popover(
panel="VIEW3D_PT_shading_options_shadow",
icon='PREFERENCES',
text="",
)
col = layout.column()
row = col.row()
row.active = not xray_active
row.prop(shading, "show_cavity")
if shading.show_cavity and not xray_active:
row.prop(shading, "cavity_type", text="Type")
if shading.cavity_type in {'WORLD', 'BOTH'}:
col.label(text="World Space")
sub = col.row(align=True)
sub.prop(shading, "cavity_ridge_factor", text="Ridge")
sub.prop(shading, "cavity_valley_factor", text="Valley")
sub.popover(
panel="VIEW3D_PT_shading_options_ssao",
icon='PREFERENCES',
text="",
)
if shading.cavity_type in {'SCREEN', 'BOTH'}:
col.label(text="Screen Space")
sub = col.row(align=True)
sub.prop(shading, "curvature_ridge_factor", text="Ridge")
sub.prop(shading, "curvature_valley_factor", text="Valley")
row = col.row()
row.active = not xray_active
row.prop(shading, "use_dof", text="Depth of Field")
if shading.type in {'WIREFRAME', 'SOLID'}:
row = layout.split()
@ -7131,6 +7741,21 @@ class VIEW3D_PT_overlay_edit_mesh(Panel):
is_any_solid_shading = not (shading.show_xray or (shading.type == 'WIREFRAME'))
if shading.type == 'WIREFRAME':
xray = shading.show_xray_wireframe and shading.xray_alpha_wireframe < 1.0
elif shading.type == 'SOLID':
xray = shading.show_xray and shading.xray_alpha < 1.0
else:
xray = False
if xray:
fdot_draw_depressed = overlay.show_face_center_xray
else:
fdot_draw_depressed = overlay.show_face_center
col = layout.column()
col.active = display_all
col = layout.column()
col.active = display_all
@ -7139,8 +7764,7 @@ class VIEW3D_PT_overlay_edit_mesh(Panel):
sub = split.column()
sub.prop(overlay, "show_faces", text="Faces")
sub = split.column()
sub.active = is_any_solid_shading
sub.prop(overlay, "show_face_center", text="Center")
sub.operator("view3d.toggle_facedots", text="Facedots", depress = fdot_draw_depressed)
row = col.row(align=True)
row.prop(overlay, "show_edge_crease", text="Creases", toggle=True)
@ -9018,6 +9642,12 @@ classes = (
VIEW3D_MT_sculpt_gpencil_automasking_pie,
VIEW3D_MT_wpaint_vgroup_lock_pie,
VIEW3D_MT_sculpt_face_sets_edit_pie,
VIEW3D_box_lasso,
VIEW3D_box_select,
VIEW3D_circle_select,
VIEW3D_lasso_select,
VIEW3D_MT_PIE_Drag_Select,
VIEW3D_pie_drag_select,
VIEW3D_MT_sculpt_curves,
VIEW3D_PT_active_tool,
VIEW3D_PT_active_tool_duplicate,

View File

@ -161,7 +161,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 = 13
def draw(self, _context):
# layout = self.layout

View File

@ -26,7 +26,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

@ -57,7 +57,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) {
@ -66,6 +67,14 @@ bool BLI_lasso_is_edge_inside(const int mcoords[][2],
const int v1[2] = {x0, y0}, v2[2] = {x1, y1};
/* 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;
}
if (!fully_inside) {
/* check points in lasso */
if (BLI_lasso_is_point_inside(mcoords, mcoords_len, v1[0], v1[1], error_value)) {
return true;
@ -79,11 +88,12 @@ bool BLI_lasso_is_edge_inside(const int mcoords[][2],
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++) {
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

@ -203,6 +203,8 @@ static void blo_update_defaults_screen(bScreen *screen,
/* Disable Curve Normals. */
v3d->overlay.edit_flag &= ~V3D_OVERLAY_EDIT_CU_NORMALS;
v3d->overlay.normals_constant_screen_size = 7.0f;
/* Show xray facedots */
v3d->overlay.edit_flag |= V3D_OVERLAY_EDIT_FACE_DOT_XRAY;
}
else if (area->spacetype == SPACE_CLIP) {
SpaceClip *sclip = static_cast<SpaceClip *>(area->spacedata.first);

View File

@ -921,6 +921,9 @@ void blo_do_versions_userdef(UserDef *userdef)
STRNCPY(km->idname, "NLA Tracks");
}
}
userdef->header_highlight = 5;
userdef->selection_radius = 75.0f;
}
/**

View File

@ -61,8 +61,10 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
bool select_face = pd->edit_mesh.select_face = (tsettings->selectmode & SCE_SELECT_FACE) != 0;
bool select_edge = pd->edit_mesh.select_edge = (tsettings->selectmode & SCE_SELECT_EDGE) != 0;
bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0 ||
pd->edit_mesh.do_zbufclip;
bool show_face_dots = !XRAY_FLAG_ENABLED(draw_ctx->v3d) &&
v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT ||
XRAY_FLAG_ENABLED(draw_ctx->v3d) &&
v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT_XRAY;
bool show_retopology = RETOPOLOGY_ENABLED(v3d);
float retopology_offset = RETOPOLOGY_OFFSET(v3d);

View File

@ -59,8 +59,10 @@ static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, eDrawTyp
{
if (select_mode & SCE_SELECT_FACE) {
if ((dt < OB_SOLID) || XRAY_FLAG_ENABLED(v3d)) {
if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT_XRAY) {
return true;
}
}
if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) {
return true;
}

View File

@ -832,7 +832,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;

View File

@ -1490,7 +1490,8 @@ static bool gpencil_stroke_do_circle_sel(bGPdata *gpd,
const float diff_mat[4][4],
const int selectmode,
const float scale,
const bool is_curve_edit)
const bool is_curve_edit,
const bool square)
{
bGPDspoint *pt = nullptr;
int x0 = 0, y0 = 0;
@ -1510,7 +1511,9 @@ static bool gpencil_stroke_do_circle_sel(bGPdata *gpd,
/* do boundbox check first */
if (!ELEM(V2D_IS_CLIPPED, x0, y0) && BLI_rcti_isect_pt(rect, x0, y0)) {
/* only check if point is inside */
if (((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)) <= radius * radius) {
if (square ? BLI_rcti_isect_pt(rect, x0, y0) :
((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)) <= radius * radius)
{
hit = true;
/* change selection */
@ -1581,7 +1584,8 @@ static bool gpencil_do_curve_circle_sel(bContext *C,
const bool select,
rcti *rect,
const float diff_mat[4][4],
const int selectmode)
const int selectmode,
const bool square)
{
ARegion *region = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
@ -1629,7 +1633,7 @@ static bool gpencil_do_curve_circle_sel(bContext *C,
int dist_x = screen_co[0] - mx;
int dist_y = screen_co[1] - my;
int dist = dist_x * dist_x + dist_y * dist_y;
if (dist <= radius * radius) {
if (square ? BLI_rcti_isect_pt(rect, screen_co[0], screen_co[1]) : dist <= radius * radius) {
hit = true;
/* change selection */
if (select) {
@ -1674,6 +1678,7 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
ToolSettings *ts = CTX_data_tool_settings(C);
Object *ob = CTX_data_active_object(C);
const bool is_curve_edit = bool(GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd));
const bool square = U.square_select;
int selectmode;
if (ob && ob->mode == OB_MODE_SCULPT_GPENCIL_LEGACY) {
@ -1729,7 +1734,7 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc)
{
changed |= gpencil_do_curve_circle_sel(
C, gps, gpc, mx, my, radius, select, &rect, gps_iter.diff_mat, selectmode);
C, gps, gpc, mx, my, radius, select, &rect, gps_iter.diff_mat, selectmode, square);
}
GP_EDITABLE_CURVES_END(gps_iter);
}
@ -1758,7 +1763,8 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
gpstroke_iter.diff_mat,
selectmode,
scale,
is_curve_edit);
is_curve_edit,
square);
}
GP_EVALUATED_STROKES_END(gpstroke_iter);
}

View File

@ -430,8 +430,8 @@ DEF_ICON(IMAGE_REFERENCE)
/* EMPTY */
DEF_ICON_BLANK(445)
DEF_ICON_BLANK(446)
DEF_ICON_BLANK(447)
DEF_ICON(OBJECT_ENCLOSE)
DEF_ICON(FACE_TOUCH)
DEF_ICON(NODE_INSERT_ON)
DEF_ICON(NODE_INSERT_OFF)
DEF_ICON(NODE_TOP)
@ -442,14 +442,14 @@ DEF_ICON(ANCHOR_BOTTOM)
DEF_ICON(ANCHOR_LEFT)
DEF_ICON(ANCHOR_RIGHT)
DEF_ICON(ANCHOR_CENTER)
DEF_ICON_BLANK(703)
DEF_ICON_BLANK(704)
DEF_ICON_BLANK(705)
DEF_ICON_BLANK(706)
DEF_ICON_BLANK(707)
DEF_ICON_BLANK(708)
DEF_ICON_BLANK(709)
DEF_ICON_BLANK(710)
DEF_ICON(EDGE_DEFAULT)
DEF_ICON(EDGE_ENCLOSE)
DEF_ICON(EDGE_TOUCH)
DEF_ICON(FACE_DEFAULT)
DEF_ICON(FACE_ENCLOSE)
DEF_ICON(OBJECT_TOUCH)
DEF_ICON(AUTO_XRAY)
DEF_ICON(SELECT_THROUGH)
DEF_ICON(SELECT_SET)
DEF_ICON(SELECT_EXTEND)
DEF_ICON(SELECT_SUBTRACT)

View File

@ -248,7 +248,7 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_HEADER_ACTIVE: {
cp = ts->header;
const int factor = 5;
const int factor = U.custom_highlight ? U.header_highlight : 5;
/* Lighten the header color when editor is active. */
header_active[0] = cp[0] > 245 ? cp[0] - factor : cp[0] + factor;
header_active[1] = cp[1] > 245 ? cp[1] - factor : cp[1] + factor;

View File

@ -246,7 +246,9 @@ static void findnearestvert__doClosest(void *user_data,
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.adjustable_click_select && U.select_unbiased) && data->use_select_bias &&
BM_elem_flag_test(eve, BM_ELEM_SELECT))
{
dist_test_bias += FIND_NEAR_SELECT_BIAS;
}
@ -455,7 +457,9 @@ static void find_nearest_edge__doClosest(void *user_data,
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.adjustable_click_select && U.select_unbiased) && data->use_select_bias &&
BM_elem_flag_test(eed, BM_ELEM_SELECT))
{
dist_test_bias += FIND_NEAR_SELECT_BIAS;
}
@ -688,7 +692,9 @@ static void findnearestface__doClosest(void *user_data,
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.adjustable_click_select && U.select_unbiased) && data->use_select_bias &&
BM_elem_flag_test(efa, BM_ELEM_SELECT))
{
dist_test_bias += FIND_NEAR_SELECT_BIAS;
}
@ -724,27 +730,27 @@ 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.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(vc->depsgraph, bases, SCE_SELECT_FACE);
if (dist_px_manhattan_test == 0) {
if (!(U.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) {
@ -778,7 +784,14 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
/* end exception */
if (efa) {
if (dist_test < *dist_px_manhattan_p) {
if (U.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.adjustable_click_select && dist_test < *dist_px_manhattan_p) {
if (r_base_index) {
*r_base_index = base_index;
}

View File

@ -3982,6 +3982,62 @@ static void SCREEN_OT_repeat_history(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Invoke Last Operator
* \{ */
static int invoke_last_exec(bContext *C, wmOperator * /*op*/)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmOperator *lastop = static_cast<wmOperator *>(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_invoke_last(C, lastop);
}
return OPERATOR_CANCELLED;
}
static void SCREEN_OT_invoke_last(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Invoke Last";
ot->description = "Invoke last operation";
ot->idname = "SCREEN_OT_invoke_last";
/* api callbacks */
ot->exec = invoke_last_exec;
ot->poll = ED_operator_screenactive;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Redo Operator
* \{ */
@ -5863,6 +5919,7 @@ void ED_operatortypes_screen()
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_invoke_last);
WM_operatortype_append(SCREEN_OT_redo_last);
/* Screen tools. */

View File

@ -875,9 +875,11 @@ static int node_circleselect_exec(bContext *C, wmOperator *op)
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *region = CTX_wm_region(C);
bNodeTree &node_tree = *snode->edittree;
const bool square = U.square_select;
int x, y, radius;
float2 offset;
rctf rectf;
float zoom = float(BLI_rcti_size_x(&region->winrct)) / float(BLI_rctf_size_x(&region->v2d.cur));
@ -896,6 +898,11 @@ static int node_circleselect_exec(bContext *C, wmOperator *op)
UI_view2d_region_to_view(&region->v2d, x, y, &offset.x, &offset.y);
if (square) {
BLI_rctf_init(&rectf, x - radius, x + radius, y - radius, y + radius);
UI_view2d_region_to_view_rctf(&region->v2d, &rectf, &rectf);
}
for (bNode *node : node_tree.all_nodes()) {
switch (node->type) {
case NODE_FRAME: {
@ -904,17 +911,33 @@ static int node_circleselect_exec(bContext *C, wmOperator *op)
rctf frame_inside = node_frame_rect_inside(*snode, *node);
const float radius_adjusted = float(radius) / zoom;
BLI_rctf_pad(&frame_inside, -2.0f * radius_adjusted, -2.0f * radius_adjusted);
if (square) {
if (BLI_rctf_isect(&rectf, &node->runtime->totr, nullptr) &&
!BLI_rctf_inside_rctf(&frame_inside, &rectf))
{
nodeSetSelected(node, select);
}
}
else {
if (BLI_rctf_isect_circle(&node->runtime->totr, offset, radius_adjusted) &&
!BLI_rctf_isect_circle(&frame_inside, offset, radius_adjusted))
{
nodeSetSelected(node, select);
}
}
break;
}
default: {
if (square) {
if (BLI_rctf_isect(&rectf, &node->runtime->totr, nullptr)) {
nodeSetSelected(node, select);
}
}
else {
if (BLI_rctf_isect_circle(&node->runtime->totr, offset, radius / zoom)) {
nodeSetSelected(node, select);
}
}
break;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,14 @@ 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);
void VIEW3D_OT_toggle_backface(struct wmOperatorType *ot);
void VIEW3D_OT_toggle_facedots(struct wmOperatorType *ot);
void VIEW3D_OT_cycle_shading(struct wmOperatorType *ot);
void VIEW3D_OT_cycle_object(struct wmOperatorType *ot);
void VIEW3D_OT_cycle_face(struct wmOperatorType *ot);
void VIEW3D_OT_cycle_edge(struct wmOperatorType *ot);
/* `view3d_draw.cc` */

View File

@ -663,6 +663,25 @@ 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);
}
}
/** \} */

View File

@ -41,6 +41,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_OPERATORS(eV3D_OpPropFlag, V3D_OP_PROP_USE_MOUSE_INIT);

View File

@ -91,7 +91,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 = static_cast<RegionView3D *>(region->regiondata);
float afm[3];
@ -134,7 +135,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);
}
}
}
@ -166,7 +167,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);
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
@ -175,7 +177,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);
}
}
}
@ -263,10 +265,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);
@ -328,6 +330,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) {
@ -454,10 +457,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);
@ -481,6 +484,7 @@ void VIEW3D_OT_view_selected(wmOperatorType *ot)
/* properties */
view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS);
view3d_operator_properties_common(ot, V3D_OP_PROP_FRAME_SELECTED_DISTANCE);
}
/** \} */

View File

@ -389,7 +389,8 @@ static void view_zoom_apply_step(bContext *C,
ScrArea *area,
ARegion *region,
const int delta,
const int zoom_xy[2])
const int zoom_xy[2],
const float zoom_speed)
{
View3D *v3d = static_cast<View3D *>(area->spacedata.first);
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
@ -402,7 +403,8 @@ static void view_zoom_apply_step(bContext *C,
ED_view3d_dist_range_get(v3d, dist_range);
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);
}
@ -413,7 +415,7 @@ static void view_zoom_apply_step(bContext *C,
}
}
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);
}
@ -446,6 +448,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
const int delta = RNA_int_get(op->ptr, "delta");
const float zoom_speed = RNA_float_get(op->ptr, "zoom_speed");
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
int zoom_xy_buf[2];
@ -459,7 +462,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
zoom_xy = zoom_xy_buf;
}
view_zoom_apply_step(C, depsgraph, scene, area, region, delta, zoom_xy);
view_zoom_apply_step(C, depsgraph, scene, area, region, delta, zoom_xy, zoom_speed);
ED_view3d_camera_lock_undo_grouped_push(op->type->name, v3d, rv3d, C);
return OPERATOR_FINISHED;
@ -481,6 +484,7 @@ static int viewzoom_invoke_impl(bContext *C,
prop = RNA_struct_find_property(ptr, "delta");
const int delta = RNA_property_is_set(ptr, prop) ? RNA_property_int_get(ptr, prop) : 0;
const float zoom_speed = RNA_float_get(ptr, "zoom_speed");
if (delta) {
const bool do_zoom_to_mouse_pos = (vod->viewops_flag & VIEWOPS_FLAG_ZOOM_TO_MOUSE) != 0;
@ -490,7 +494,8 @@ static int viewzoom_invoke_impl(bContext *C,
vod->area,
vod->region,
delta,
do_zoom_to_mouse_pos ? xy : nullptr);
do_zoom_to_mouse_pos ? xy : nullptr,
zoom_speed);
return OPERATOR_FINISHED;
}
@ -545,8 +550,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

@ -223,6 +223,14 @@ void view3d_operatortypes()
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_toggle_backface);
WM_operatortype_append(VIEW3D_OT_toggle_facedots);
WM_operatortype_append(VIEW3D_OT_cycle_shading);
WM_operatortype_append(VIEW3D_OT_cycle_object);
WM_operatortype_append(VIEW3D_OT_cycle_face);
WM_operatortype_append(VIEW3D_OT_cycle_edge);
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

@ -315,6 +315,13 @@ void ED_transverts_create_from_obedit(TransVertStore *tvs, const Object *obedit,
editmesh_eval_cage, set_mapped_co, userdata, MESH_FOREACH_NOP);
}
}
/* Fix vert indices for backfacing mesh filter */
int index = 0;
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
BM_elem_index_set(eve, index);
index++;
}
}
else if (obedit->type == OB_ARMATURE) {
bArmature *arm = static_cast<bArmature *>(obedit->data);

View File

@ -3724,6 +3724,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
int x, y, radius, width, height;
float zoomx, zoomy;
float offset[2], ellipse[2];
rctf rectf;
const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ?
(ts->selectmode == SCE_SELECT_FACE) :
@ -3733,6 +3734,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
(ts->uv_selectmode == UV_SELECT_EDGE));
const bool use_select_linked = !(ts->uv_flag & UV_SYNC_SELECTION) &&
(ts->uv_selectmode == UV_SELECT_ISLAND);
const bool square = U.square_select;
/* get operator properties */
x = RNA_int_get(op->ptr, "x");
@ -3749,6 +3751,11 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
UI_view2d_region_to_view(&region->v2d, x, y, &offset[0], &offset[1]);
if (square) {
BLI_rctf_init(&rectf, x - radius, x + radius, y - radius, y + radius);
UI_view2d_region_to_view_rctf(&region->v2d, &rectf, &rectf);
}
bool changed_multi = false;
Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
@ -3782,7 +3789,9 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
if (select != uvedit_face_select_test(scene, efa, offsets)) {
float cent[2];
BM_face_uv_calc_center_median(efa, offsets.uv, cent);
if (uv_circle_select_is_point_inside(cent, offset, ellipse)) {
if (square ? BLI_rctf_isect_pt_v(&rectf, cent) :
uv_circle_select_is_point_inside(cent, offset, ellipse))
{
BM_elem_flag_enable(efa, BM_ELEM_TAG);
changed = true;
}
@ -3805,7 +3814,9 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
if (uv_circle_select_is_edge_inside(luv, luv_prev, offset, ellipse)) {
if (square ? BLI_rctf_isect_pt_v(&rectf, luv) && BLI_rctf_isect_pt_v(&rectf, luv_prev) :
uv_circle_select_is_edge_inside(luv, luv_prev, offset, ellipse))
{
uvedit_edge_select_set_with_sticky(scene, em, l_prev, select, false, offsets);
changed = true;
}
@ -3825,7 +3836,9 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (select != uvedit_uv_select_test(scene, l, offsets)) {
luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
if (uv_circle_select_is_point_inside(luv, offset, ellipse)) {
if (square ? BLI_rctf_isect_pt_v(&rectf, luv) :
uv_circle_select_is_point_inside(luv, offset, ellipse))
{
changed = true;
uvedit_uv_select_set(scene, em->bm, l, select, false, offsets);
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
@ -3919,7 +3932,7 @@ static bool do_lasso_select_mesh_uv_is_edge_inside(const ARegion *region,
&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))
mcoords, mcoords_len, UNPACK2(co_screen_a), UNPACK2(co_screen_b), V2D_IS_CLIPPED, false))
{
return true;
}

View File

@ -2451,6 +2451,14 @@ typedef enum eSnapTransformMode {
SCE_SNAP_TRANSFORM_MODE_SCALE = (1 << 2),
} eSnapTransformMode;
/** #Auto X-Ray mode */
enum {
OPERATOR_MODE_A = (1 << 0),
OPERATOR_MODE_B = (1 << 1),
OPERATOR_MODE_C = (1 << 2),
OPERATOR_MODE_D = (1 << 3),
};
/** #ToolSettings::selectmode */
enum {
SCE_SELECT_VERTEX = 1 << 0, /* for mesh */

View File

@ -967,6 +967,7 @@ typedef struct UserDef {
/** Flags for which channels to insert keys at. */
short key_insert_channels; // eKeyInsertChannels
char _pad15[6];
/** Flags for animation. */
short animation_flag;
@ -1035,11 +1036,152 @@ typedef struct UserDef {
float collection_instance_empty_size;
char text_flag;
char _pad10[1];
char file_preview_type; /* eUserpref_File_Preview_Type */
char statusbar_flag; /* eUserpref_StatusBar_Flag */
/** Luke's Custom Build Options */
char keymap_direction;
char custom_highlight;
char header_highlight;
char xray_button;
char direction_downright_box;
char direction_downright_lasso;
char auto_xray_reset;
char custom_cursor;
char system_cursor;
char edit_cursor;
char paint_cursor;
char dot_cursor;
char knife_cursor;
char pencil_cursor;
char eraser_cursor;
char eyedropper_cursor;
char adjustable_click_select;
char selection_radius;
char select_unbiased;
char blank_text;
char drag_control_mode;
char userpref_mode;
char drag_direction_box;
char drag_direction_lasso;
char auto_xray_box;
char auto_xray_downright_box;
char select_through_box;
char select_through_downright_box;
char object_select_box;
char object_select_downright_box;
char face_select_box;
char face_select_downright_box;
char edge_select_box;
char edge_select_downright_box;
char backface_box;
char backface_downright_box;
char auto_xray_lasso;
char auto_xray_downright_lasso;
char select_through_lasso;
char select_through_downright_lasso;
char object_select_lasso;
char object_select_downright_lasso;
char face_select_lasso;
char face_select_downright_lasso;
char edge_select_lasso;
char edge_select_downright_lasso;
char backface_lasso;
char backface_downright_lasso;
char auto_xray_circle;
char select_through_circle;
char object_select_circle;
char face_select_circle;
char edge_select_circle;
char backface_circle;
char object_header;
char object_cycle_touch;
char object_cycle_enclose;
char object_cycle_origin;
char face_header;
char face_cycle_default;
char face_cycle_touch;
char face_cycle_enclose;
char face_cycle_center;
char edge_header;
char edge_cycle_default;
char edge_cycle_touch;
char edge_cycle_enclose;
char backface_header;
char auto_xray_header;
char select_through_header;
char object_cycle_touch_circle;
char object_cycle_enclose_circle;
char object_cycle_origin_circle;
char face_cycle_default_circle;
char face_cycle_touch_circle;
char face_cycle_enclose_circle;
char face_cycle_center_circle;
char edge_cycle_touch_circle;
char edge_cycle_enclose_circle;
char backface_toggle_circle;
char auto_xray_toggle_circle;
char select_through_toggle_circle;
char object_cycle_touch_lasso;
char object_cycle_enclose_lasso;
char object_cycle_origin_lasso;
char face_cycle_default_lasso;
char face_cycle_touch_lasso;
char face_cycle_enclose_lasso;
char face_cycle_center_lasso;
char edge_cycle_default_lasso;
char edge_cycle_touch_lasso;
char edge_cycle_enclose_lasso;
char backface_toggle_lasso;
char auto_xray_toggle_lasso;
char select_through_toggle_lasso;
char quick_assign;
char quick_assign_mode;
char operator_controls;
char box_controls;
char circle_controls;
char lasso_controls;
char backface_toggle;
char auto_xray_toggle;
char select_through_toggle;
char direction_controls;
char drag_direction_mode;
char direction_object;
char direction_face;
char direction_edge;
char direction_backface;
char direction_auto_xray;
char direction_select_through;
char object_pie;
char face_pie;
char edge_pie;
char backface_pie;
char auto_xray_pie;
char select_through_pie;
char box_pie;
char circle_pie;
char lasso_pie;
char pie_menu_controls;
char object_operator;
char face_operator;
char edge_operator;
char backface_operator;
char auto_xray_operator;
char select_through_operator;
char wireless_touch_object;
char square_select;
char sync_box;
char sync_circle;
char sync_lasso;
char facedot_mode;
char shading_button_mode;
char shading_cycle_wire;
char shading_cycle_solid;
char shading_cycle_material;
char shading_cycle_render;
char _pad9[6];
struct WalkNavigation walk_navigation;
/** The UI for the user preferences. */
@ -1082,6 +1224,7 @@ typedef enum eUserPref_Section {
USER_SECTION_FILE_PATHS = 15,
USER_SECTION_EXPERIMENTAL = 16,
USER_SECTION_EXTENSIONS = 17,
USER_SECTION_CUSTOM = 18,
} eUserPref_Section;
/** #UserDef_SpaceData.flag (State of the user preferences UI). */
@ -1247,6 +1390,33 @@ typedef enum eUserpref_TableAPI {
USER_TABLET_WINTAB = 2,
} eUserpref_TabletAPI;
/** #UserDef.mode */
typedef enum eUserpref_Mode {
USER_MODE_A = 0,
USER_MODE_B = 1,
USER_MODE_C = 2,
USER_MODE_D = 3,
} eUserpref_Mode;
/** #UserDef.cursor_types */
typedef enum eUserpref_Cursor_Types {
USER_CURSOR_SYSTEM = 0,
USER_CURSOR_CROSS = 1,
USER_CURSOR_POINTER = 2,
USER_CURSOR_CROSS_OPEN = 3,
USER_CURSOR_CROSS_DOT = 4,
USER_CURSOR_CROSS_MIN = 5,
USER_CURSOR_BOX = 6,
USER_CURSOR_BOX_DOT = 7,
USER_CURSOR_BOX_POINTER = 8,
USER_CURSOR_DOT = 9,
USER_CURSOR_BLANK = 10,
USER_CURSOR_KNIFE = 11,
USER_CURSOR_PENCIL = 12,
USER_CURSOR_ERASER = 13,
USER_CURSOR_EYEDROPPER = 14,
} eUserpref_Cursor_Types;
/** #UserDef.app_flag */
typedef enum eUserpref_APP_Flag {
USER_APP_LOCK_CORNER_SPLIT = (1 << 0),

View File

@ -610,6 +610,7 @@ enum {
V3D_OVERLAY_EDIT_CU_NORMALS = (1 << 21),
V3D_OVERLAY_EDIT_CONSTANT_SCREEN_SIZE_NORMALS = (1 << 22),
V3D_OVERLAY_EDIT_FACE_DOT_XRAY = (1 << 23),
};
/** #View3DOverlay.paint_flag */

View File

@ -4661,6 +4661,16 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
"Display face center when face selection is enabled in solid shading modes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, nullptr);
prop = RNA_def_property(srna, "show_face_center_xray", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, nullptr, "overlay.edit_flag", V3D_OVERLAY_EDIT_FACE_DOT_XRAY);
RNA_def_property_boolean_default(prop, true);
RNA_def_property_ui_text(
prop,
"Display Face Center X-Ray",
"Display face center when face selection is enabled in X-Ray shading modes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, nullptr);
prop = RNA_def_property(srna, "show_edge_crease", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "overlay.edit_flag", V3D_OVERLAY_EDIT_CREASES);
RNA_def_property_ui_text(

File diff suppressed because it is too large Load Diff

View File

@ -421,6 +421,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 = static_cast<wmKeyMapItem *>(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 = static_cast<wmKeyMapItem *>(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 = static_cast<wmKeyMapItem *>(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 = static_cast<wmKeyMapItem *>(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 = static_cast<wmKeyMapItem *>(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,
@ -1278,6 +1313,31 @@ void RNA_api_keymapitems(StructRNA *srna)
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(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, ParameterFlag(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, ParameterFlag(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, ParameterFlag(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, ParameterFlag(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, ParameterFlag(0));
func = RNA_def_function(srna, "from_id", "WM_keymap_item_find_id");
parm = RNA_def_property(func, "id", PROP_INT, PROP_NONE);
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);

View File

@ -1356,14 +1356,14 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
if (enum_item != rna_enum_dummy_NULL_items) {
const char *ptr_name = RNA_struct_name_get_alloc(ptr, nullptr, 0, nullptr);
/* Prefer not to fail silently in case of API errors, maybe disable it later. */
/* Prefer not to fail silently in case of API errors, maybe disable it later.
CLOG_WARN(BPY_LOG_RNA,
"current value '%d' "
"matches no enum in '%s', '%s', '%s'",
val,
RNA_struct_identifier(ptr->type),
ptr_name,
RNA_property_identifier(prop));
RNA_property_identifier(prop));*/
#if 0 /* Gives Python decoding errors while generating docs :( */
char error_str[256];

View File

@ -791,6 +791,7 @@ int WM_operator_call_notest(bContext *C, wmOperator *op);
* Execute this operator again, put here so it can share above code
*/
int WM_operator_repeat(bContext *C, wmOperator *op);
int WM_operator_invoke_last(bContext *C, wmOperator *op);
int WM_operator_repeat_last(bContext *C, wmOperator *op);
/**
* \return true if #WM_operator_repeat can run.
@ -1745,7 +1746,7 @@ bool WM_event_is_modal_drag_exit(const wmEvent *event,
short init_event_val);
bool WM_event_is_mouse_drag(const 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(bContext *C, const wmEvent *event);
char WM_event_utf8_to_ascii(const wmEvent *event) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
/**

View File

@ -559,6 +559,7 @@ struct wmNotifier {
#define WM_GESTURE_LASSO 4
#define WM_GESTURE_CIRCLE 5
#define WM_GESTURE_STRAIGHTLINE 6
#define WM_GESTURE_SQUARE 7
/**
* wmGesture is registered to #wmWindow.gesture, handled by operator callbacks.

View File

@ -41,17 +41,79 @@ struct BCursor {
static BCursor *BlenderCursor[WM_CURSOR_NUM] = {nullptr};
static GHOST_TStandardCursor window_get_custom_cursor(const int cursor)
{
if (cursor == 1) {
return GHOST_kStandardCursorCrosshair;
}
else if (cursor == 2) {
return GHOST_kStandardCursorPointer;
}
else if (cursor == 3) {
return GHOST_kStandardCursorCrosshairD;
}
else if (cursor == 4) {
return GHOST_kStandardCursorCrosshairA;
}
else if (cursor == 5) {
return GHOST_kStandardCursorCrosshairC;
}
else if (cursor == 6) {
return GHOST_kStandardCursorBox;
}
else if (cursor == 7) {
return GHOST_kStandardCursorBoxDot;
}
else if (cursor == 8) {
return GHOST_kStandardCursorBoxPointer;
}
else if (cursor == 9) {
return GHOST_kStandardCursorCrosshairB;
}
else if (cursor == 10) {
return GHOST_kStandardCursorBlank;
}
else if (cursor == 11) {
return GHOST_kStandardCursorKnife;
}
else if (cursor == 12) {
return GHOST_kStandardCursorPencil;
}
else if (cursor == 13) {
return GHOST_kStandardCursorEraser;
}
else if (cursor == 14) {
return GHOST_kStandardCursorEyedropper;
}
else {
return GHOST_kStandardCursorDefault;
}
}
/* Blender cursor to GHOST standard cursor conversion. */
static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs)
{
GHOST_TStandardCursor cursor = GHOST_kStandardCursorDefault;
switch (curs) {
case WM_CURSOR_DEFAULT:
if (U.custom_cursor) {
cursor = window_get_custom_cursor(U.system_cursor);
return cursor;
}
else {
return GHOST_kStandardCursorDefault;
}
case WM_CURSOR_WAIT:
return GHOST_kStandardCursorWait;
case WM_CURSOR_EDIT:
case WM_CURSOR_CROSS:
if (U.custom_cursor) {
cursor = window_get_custom_cursor(U.edit_cursor);
return cursor;
}
else {
return GHOST_kStandardCursorCrosshair;
}
case WM_CURSOR_X_MOVE:
return GHOST_kStandardCursorLeftRight;
case WM_CURSOR_Y_MOVE:
@ -67,7 +129,13 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs)
case WM_CURSOR_STOP:
return GHOST_kStandardCursorStop;
case WM_CURSOR_KNIFE:
if (U.custom_cursor) {
cursor = window_get_custom_cursor(U.knife_cursor);
return cursor;
}
else {
return GHOST_kStandardCursorKnife;
}
case WM_CURSOR_NSEW_SCROLL:
return GHOST_kStandardCursorNSEWScroll;
case WM_CURSOR_NS_SCROLL:
@ -75,19 +143,43 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs)
case WM_CURSOR_EW_SCROLL:
return GHOST_kStandardCursorEWScroll;
case WM_CURSOR_EYEDROPPER:
if (U.custom_cursor) {
cursor = window_get_custom_cursor(U.eyedropper_cursor);
return cursor;
}
else {
return GHOST_kStandardCursorEyedropper;
}
case WM_CURSOR_N_ARROW:
return GHOST_kStandardCursorUpArrow;
case WM_CURSOR_S_ARROW:
return GHOST_kStandardCursorDownArrow;
case WM_CURSOR_PAINT:
if (U.custom_cursor) {
cursor = window_get_custom_cursor(U.paint_cursor);
return cursor;
}
else {
return GHOST_kStandardCursorCrosshairA;
}
case WM_CURSOR_DOT:
if (U.custom_cursor) {
cursor = window_get_custom_cursor(U.dot_cursor);
return cursor;
}
else {
return GHOST_kStandardCursorCrosshairB;
}
case WM_CURSOR_CROSSC:
return GHOST_kStandardCursorCrosshairC;
case WM_CURSOR_ERASER:
if (U.custom_cursor) {
cursor = window_get_custom_cursor(U.eraser_cursor);
return cursor;
}
else {
return GHOST_kStandardCursorEraser;
}
case WM_CURSOR_ZOOM_IN:
return GHOST_kStandardCursorZoomIn;
case WM_CURSOR_ZOOM_OUT:
@ -95,7 +187,13 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs)
case WM_CURSOR_TEXT_EDIT:
return GHOST_kStandardCursorText;
case WM_CURSOR_PAINT_BRUSH:
if (U.custom_cursor) {
cursor = window_get_custom_cursor(U.pencil_cursor);
return cursor;
}
else {
return GHOST_kStandardCursorPencil;
}
case WM_CURSOR_E_ARROW:
return GHOST_kStandardCursorRightArrow;
case WM_CURSOR_W_ARROW:

View File

@ -267,16 +267,65 @@ 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(bContext *C, const wmEvent *event)
{
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;
const bool box_left_right = U.drag_direction_box == 1 && U.drag_control_mode == 1;
const bool box_up_down = U.drag_direction_box == 2 && U.drag_control_mode == 1;
const bool lasso_left_right = U.drag_direction_lasso == 1 && U.drag_control_mode == 1;
const bool lasso_up_down = U.drag_direction_lasso == 2 && U.drag_control_mode == 1;
const bool left_right = U.keymap_direction == 1;
const bool up_down = U.keymap_direction == 2;
int val = up_down ? KM_DIRECTION_N : KM_DIRECTION_W;
if (left_right || up_down || box_left_right || box_up_down || lasso_left_right || lasso_up_down)
{
const float thetaf = 4.0f * atan2f((float)delta[1], (float)delta[0]) / (float)M_PI;
if (U.direction_downright_box) {
U.direction_downright_box ^= true;
}
if (U.direction_downright_lasso) {
U.direction_downright_lasso ^= true;
}
if (thetaf > -2.0f && thetaf < 2.0f) {
if (left_right) {
val = KM_DIRECTION_E;
}
if (box_left_right) {
U.direction_downright_box ^= true;
}
if (lasso_left_right) {
U.direction_downright_lasso ^= true;
}
}
if (thetaf < 0.0f) {
if (up_down) {
val = KM_DIRECTION_S;
}
if (box_up_down) {
U.direction_downright_box ^= true;
}
if (lasso_up_down) {
U.direction_downright_lasso ^= true;
}
}
}
if (!left_right && !up_down) {
const int theta = round_fl_to_int(4.0f * atan2f((float)delta[1], (float)delta[0]) /
(float)M_PI);
if (theta == 0) {
val = KM_DIRECTION_E;
}
@ -298,6 +347,7 @@ int WM_event_drag_direction(const wmEvent *event)
else if (theta == -3) {
val = KM_DIRECTION_SW;
}
}
#if 0
/* debug */

View File

@ -1323,6 +1323,11 @@ int WM_operator_repeat(bContext *C, wmOperator *op)
op->flag &= ~op_flag;
return ret;
}
int WM_operator_invoke_last(bContext *C, wmOperator *op)
{
const int ret = WM_operator_name_call_ptr(C, op->type, WM_OP_INVOKE_DEFAULT, nullptr, nullptr);
return ret;
}
int WM_operator_repeat_last(bContext *C, wmOperator *op)
{
const int op_flag = OP_IS_REPEAT_LAST;
@ -3470,7 +3475,7 @@ static eHandlerActionFlag wm_handlers_do(bContext *C, wmEvent *event, ListBase *
WM_event_drag_test(event, event->prev_press_xy))
{
win->event_queue_check_drag_handled = true;
const int direction = WM_event_drag_direction(event);
const int direction = WM_event_drag_direction(C, event);
/* 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

@ -56,6 +56,7 @@ wmGesture *WM_gesture_new(wmWindow *window, const ARegion *region, const wmEvent
WM_GESTURE_RECT,
WM_GESTURE_CROSS_RECT,
WM_GESTURE_CIRCLE,
WM_GESTURE_SQUARE,
WM_GESTURE_STRAIGHTLINE))
{
rcti *rect = static_cast<rcti *>(MEM_callocN(sizeof(rcti), "gesture rect new"));
@ -63,7 +64,7 @@ wmGesture *WM_gesture_new(wmWindow *window, const ARegion *region, const wmEvent
gesture->customdata = rect;
rect->xmin = xy[0] - gesture->winrct.xmin;
rect->ymin = xy[1] - gesture->winrct.ymin;
if (type == WM_GESTURE_CIRCLE) {
if (type == WM_GESTURE_CIRCLE || type == WM_GESTURE_SQUARE) {
/* caller is responsible for initializing 'xmax' to radius. */
}
else {
@ -275,6 +276,51 @@ static void wm_gesture_draw_circle(wmGesture *gt)
immUnbindProgram();
}
static void wm_gesture_draw_square(wmGesture *gt)
{
rcti *rect = (rcti *)gt->customdata;
uint shdr_pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
GPU_blend(GPU_BLEND_ALPHA);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.05f);
immRecti(shdr_pos,
rect->xmin - rect->xmax,
rect->ymin - rect->xmax,
rect->xmin + rect->xmax,
rect->ymin + rect->xmax);
immUnbindProgram();
GPU_blend(GPU_BLEND_NONE);
shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
immUniform1i("colors_len", 2); /* "advanced" mode */
immUniform4f("color", 0.4f, 0.4f, 0.4f, 1.0f);
immUniform4f("color2", 1.0f, 1.0f, 1.0f, 1.0f);
immUniform1f("dash_width", 8.0f);
immUniform1f("udash_factor", 0.5f);
imm_draw_box_wire_2d(shdr_pos,
float(rect->xmin - rect->xmax),
float(rect->ymin - rect->xmax),
float(rect->xmin + rect->xmax),
float(rect->ymin + rect->xmax));
immUnbindProgram();
}
struct LassoFillData {
uchar *px;
int width;
@ -447,6 +493,9 @@ void wm_gesture_draw(wmWindow *win)
else if (gt->type == WM_GESTURE_CIRCLE) {
wm_gesture_draw_circle(gt);
}
else if (gt->type == WM_GESTURE_SQUARE) {
wm_gesture_draw_square(gt);
}
else if (gt->type == WM_GESTURE_CROSS_RECT) {
if (gt->is_active) {
wm_gesture_draw_rect(gt);

View File

@ -31,6 +31,7 @@
#include "ED_screen.hh"
#include "ED_select_utils.hh"
#include "ED_view3d.hh"
#include "UI_interface.hh"
@ -87,6 +88,92 @@ 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);
BLI_assert(ot);
PointerRNA ptr;
WM_operator_properties_create_ptr(&ptr, ot);
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr);
WM_operator_properties_free(&ptr);
U.auto_xray_reset ^= true;
}
static void gesture_auto_xray(bContext *C, wmOperator *op, const bool lasso, const bool circle)
{
View3D *v3d = CTX_wm_view3d(C);
if (!v3d || XRAY_FLAG_ENABLED(v3d)) {
return;
}
Object *mesh = CTX_data_edit_object(C);
bool auto_xray = false;
if (U.drag_control_mode == 1) {
if (U.userpref_mode == 1 && circle) {
if (mesh) {
auto_xray = U.auto_xray_circle == 2 || U.auto_xray_circle == 3;
}
else {
auto_xray = U.auto_xray_circle == 1 || U.auto_xray_circle == 3;
}
}
else if (U.userpref_mode == 1 && lasso) {
if (mesh) {
if (U.direction_downright_lasso && (U.drag_direction_mode == 0 || U.direction_auto_xray)) {
auto_xray = U.auto_xray_downright_lasso == 2 || U.auto_xray_downright_lasso == 3;
}
else {
auto_xray = U.auto_xray_lasso == 2 || U.auto_xray_lasso == 3;
}
}
else {
if (U.direction_downright_lasso && (U.drag_direction_mode == 0 || U.direction_auto_xray)) {
auto_xray = U.auto_xray_downright_lasso == 1 || U.auto_xray_downright_lasso == 3;
}
else {
auto_xray = U.auto_xray_lasso == 1 || U.auto_xray_lasso == 3;
}
}
}
else {
if (mesh) {
if (U.userpref_mode == 1 && U.direction_downright_box &&
(U.drag_direction_mode == 0 || U.direction_auto_xray))
{
auto_xray = U.auto_xray_downright_box == 2 || U.auto_xray_downright_box == 3;
}
else {
auto_xray = U.auto_xray_box == 2 || U.auto_xray_box == 3;
}
}
else {
if (U.userpref_mode == 1 && U.direction_downright_box &&
(U.drag_direction_mode == 0 || U.direction_auto_xray))
{
auto_xray = U.auto_xray_downright_box == 1 || U.auto_xray_downright_box == 3;
}
else {
auto_xray = U.auto_xray_box == 1 || U.auto_xray_box == 3;
}
}
}
}
else {
const int mode = RNA_enum_get(op->ptr, "auto_xray");
auto_xray = mesh ? mode == 4 || mode == 8 : mode == 2 || mode == 8;
}
if (U.auto_xray_reset) {
U.auto_xray_reset ^= true;
}
if (auto_xray) {
gesture_toggle_xray(C);
}
}
static int UNUSED_FUNCTION(gesture_modal_state_from_operator)(wmOperator *op)
{
PropertyRNA *prop;
@ -169,6 +256,8 @@ int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const bool wait_for_input = !WM_event_is_mouse_drag_or_press(event) &&
RNA_boolean_get(op->ptr, "wait_for_input");
gesture_auto_xray(C, op, false, false);
if (wait_for_input) {
op->customdata = WM_gesture_new(win, region, event, WM_GESTURE_CROSS_RECT);
}
@ -216,13 +305,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 (U.auto_xray_reset) {
gesture_toggle_xray(C);
}
gesture_modal_end(C, op);
return OPERATOR_FINISHED;
}
if (U.auto_xray_reset) {
gesture_toggle_xray(C);
}
gesture_modal_end(C, op);
return OPERATOR_CANCELLED;
}
case GESTURE_MODAL_CANCEL: {
if (U.auto_xray_reset) {
gesture_toggle_xray(C);
}
gesture_modal_end(C, op);
return OPERATOR_CANCELLED;
}
@ -290,8 +388,15 @@ int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wmWindow *win = CTX_wm_window(C);
const bool wait_for_input = !WM_event_is_mouse_drag_or_press(event) &&
RNA_boolean_get(op->ptr, "wait_for_input");
gesture_auto_xray(C, op, false, true);
if (U.square_select) {
op->customdata = WM_gesture_new(win, CTX_wm_region(C), event, WM_GESTURE_SQUARE);
}
else {
op->customdata = WM_gesture_new(win, CTX_wm_region(C), event, WM_GESTURE_CIRCLE);
}
wmGesture *gesture = static_cast<wmGesture *>(op->customdata);
rcti *rect = static_cast<rcti *>(gesture->customdata);
@ -417,6 +522,9 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (is_finished) {
if (U.auto_xray_reset) {
gesture_toggle_xray(C);
}
gesture_modal_end(C, op);
return OPERATOR_FINISHED; /* use finish or we don't get an undo */
}
@ -481,6 +589,8 @@ int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wmWindow *win = CTX_wm_window(C);
PropertyRNA *prop;
gesture_auto_xray(C, op, true, false);
op->customdata = WM_gesture_new(win, CTX_wm_region(C), event, WM_GESTURE_LASSO);
/* add modal handler */
@ -540,6 +650,10 @@ static int gesture_lasso_apply(bContext *C, wmOperator *op)
OPERATOR_RETVAL_CHECK(retval);
}
if (U.auto_xray_reset) {
gesture_toggle_xray(C);
}
return retval;
}
@ -599,6 +713,9 @@ int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
case EVT_ESCKEY: {
if (U.auto_xray_reset) {
gesture_toggle_xray(C);
}
gesture_modal_end(C, op);
return OPERATOR_CANCELLED;
}

View File

@ -416,8 +416,116 @@ void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bo
{
PropertyRNA *prop;
static const EnumPropertyItem auto_xray_items[] = {
{OPERATOR_MODE_A, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"},
{OPERATOR_MODE_B, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"},
{OPERATOR_MODE_C, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"},
{OPERATOR_MODE_D, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem select_through_items[] = {
{OPERATOR_MODE_B, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"},
{OPERATOR_MODE_C, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"},
{OPERATOR_MODE_D, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"},
{OPERATOR_MODE_A, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem object_select_items[] = {
{OPERATOR_MODE_A, "OBJECT_TOUCH", 0, "Touch", "Select objects that are touched by the box"},
{OPERATOR_MODE_B,
"OBJECT_ENCLOSE",
0,
"Enclose",
"Select objects that are fully inside the box"},
{OPERATOR_MODE_C,
"OBJECT_ORIGIN",
0,
"Origin",
"Select objects if their origin is touched by the box"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem face_select_items[] = {
{OPERATOR_MODE_A,
"FACE_DEFAULT",
0,
"Default",
"Select faces that are touched by the box in Near Select. Select faces if their center is "
"touched by the box in X-Ray and Select Through"},
{OPERATOR_MODE_B, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the box"},
{OPERATOR_MODE_C,
"FACE_ENCLOSE",
0,
"Enclose",
"Select faces that are fully inside the box"},
{OPERATOR_MODE_D,
"FACE_CENTER",
0,
"Center",
"Select faces if their center is touched by the box"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem edge_select_items[] = {
{OPERATOR_MODE_A,
"EDGE_DEFAULT",
0,
"Default",
"Select edges that are fully inside the box. If no edges are fully inside the box, select "
"edges that are touched by the box"},
{OPERATOR_MODE_B, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the box"},
{OPERATOR_MODE_C,
"EDGE_ENCLOSE",
0,
"Enclose",
"Select edges that are fully inside the box"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem backface_filter_items[] = {
{OPERATOR_MODE_A, "BACKFACE_DEFAULT", 0, "Default", "Select backfacing mesh"},
{OPERATOR_MODE_B, "NONE", 0, "No Backface", "Don't select backfacing mesh"},
{OPERATOR_MODE_C,
"NEAR",
0,
"Edge & Face Near",
"Ignore backfacing edges and faces when not using X-Ray or Select Through"},
{0, nullptr, 0, nullptr, nullptr},
};
WM_operator_properties_border(ot);
prop = RNA_def_enum(ot->srna,
"auto_xray",
auto_xray_items,
0,
"Auto X-Ray",
"Transparent scene display during selection");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna,
"select_through",
select_through_items,
0,
"Select Through",
"Select occluded objects and mesh");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(
ot->srna, "object_type", object_select_items, 0, "Object", "Object selection style");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", "Face selection style");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", "Edge selection style");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna,
"backface_filter",
backface_filter_items,
0,
"Backface",
"Select mesh based on the direction of their normals");
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");
@ -521,9 +629,122 @@ void WM_operator_properties_gesture_box_zoom(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
static const EnumPropertyItem auto_xray_items[] = {
{OPERATOR_MODE_A, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"},
{OPERATOR_MODE_B, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"},
{OPERATOR_MODE_C, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"},
{OPERATOR_MODE_D, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem select_through_items[] = {
{OPERATOR_MODE_B, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"},
{OPERATOR_MODE_C, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"},
{OPERATOR_MODE_D, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"},
{OPERATOR_MODE_A, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"},
{0, nullptr, 0, nullptr, nullptr},
};
void WM_operator_properties_gesture_lasso(wmOperatorType *ot)
{
PropertyRNA *prop;
static const EnumPropertyItem object_select_items[] = {
{OPERATOR_MODE_C,
"OBJECT_ORIGIN",
0,
"Origin",
"Select objects if their origin is touched by the lasso"},
{OPERATOR_MODE_A,
"OBJECT_TOUCH",
0,
"Touch",
"Select objects that are touched by the lasso"},
{OPERATOR_MODE_B,
"OBJECT_ENCLOSE",
0,
"Enclose",
"Select objects that are fully inside the lasso"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem face_select_items[] = {
{OPERATOR_MODE_A,
"FACE_DEFAULT",
0,
"Default",
"Select faces that are touched by the lasso in Near Select. Select faces if their center "
"is touched by the lasso in X-Ray and Select Through"},
{OPERATOR_MODE_B, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the lasso"},
{OPERATOR_MODE_C,
"FACE_ENCLOSE",
0,
"Enclose",
"Select faces that are fully inside the lasso"},
{OPERATOR_MODE_D,
"FACE_CENTER",
0,
"Center",
"Select faces if their center is touched by the lasso"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem edge_select_items[] = {
{OPERATOR_MODE_A,
"EDGE_DEFAULT",
0,
"Default",
"Select edges that are fully inside the lasso. If no edges are fully inside the lasso, "
"select edges that are touched by the lasso"},
{OPERATOR_MODE_B, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the lasso"},
{OPERATOR_MODE_C,
"EDGE_ENCLOSE",
0,
"Enclose",
"Select edges that are fully inside the lasso"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem backface_filter_items[] = {
{OPERATOR_MODE_A, "BACKFACE_DEFAULT", 0, "Default", "Select backfacing mesh"},
{OPERATOR_MODE_B, "NONE", 0, "No Backface", "Don't select backfacing mesh"},
{OPERATOR_MODE_C,
"NEAR",
0,
"Edge & Face Near",
"Ignore backfacing edges and faces when not using X-Ray or Select Through"},
{0, nullptr, 0, nullptr, nullptr},
};
WM_operator_properties_border(ot);
prop = RNA_def_enum(ot->srna,
"auto_xray",
auto_xray_items,
0,
"Auto X-Ray",
"Transparent scene display during selection");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna,
"select_through",
select_through_items,
0,
"Select Through",
"Select occluded objects and mesh");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(
ot->srna, "object_type", object_select_items, 0, "Object", "Object selection style");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", "Face selection style");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", "Edge selection style");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna,
"backface_filter",
backface_filter_items,
0,
"Backface",
"Select mesh based on the direction of their normals");
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);
}
@ -562,6 +783,83 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot)
PropertyRNA *prop;
const int radius_default = 25;
static const EnumPropertyItem auto_xray_items[] = {
{OPERATOR_MODE_A, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"},
{OPERATOR_MODE_B, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"},
{OPERATOR_MODE_C, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"},
{OPERATOR_MODE_D, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem select_through_items[] = {
{OPERATOR_MODE_B, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"},
{OPERATOR_MODE_C, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"},
{OPERATOR_MODE_D, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"},
{OPERATOR_MODE_A, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem object_select_items[] = {
{OPERATOR_MODE_C,
"OBJECT_ORIGIN",
0,
"Origin",
"Select objects if their origin is touched by the circle"},
{OPERATOR_MODE_A,
"OBJECT_TOUCH",
0,
"Touch",
"Select objects that are touched by the circle"},
{OPERATOR_MODE_B,
"OBJECT_ENCLOSE",
0,
"Enclose",
"Select objects that are fully inside the circle"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem face_select_items[] = {
{OPERATOR_MODE_A,
"FACE_DEFAULT",
0,
"Default",
"Select faces that are touched by the circle in Near Select. Select faces if their center "
"is touched by the circle in X-Ray and Select Through"},
{OPERATOR_MODE_B, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the circle"},
{OPERATOR_MODE_C,
"FACE_ENCLOSE",
0,
"Enclose",
"Select faces that are fully inside the circle"},
{OPERATOR_MODE_D,
"FACE_CENTER",
0,
"Center",
"Select faces if their center is touched by the circle"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem edge_select_items[] = {
{OPERATOR_MODE_B, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the circle"},
{OPERATOR_MODE_C,
"EDGE_ENCLOSE",
0,
"Enclose",
"Select edges that are fully inside the circle"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem backface_filter_items[] = {
{OPERATOR_MODE_A, "BACKFACE_DEFAULT", 0, "Default", "Select backfacing mesh"},
{OPERATOR_MODE_B, "NONE", 0, "No Backface", "Don't select backfacing mesh"},
{OPERATOR_MODE_C,
"NEAR",
0,
"Edge & Face Near",
"Ignore backfacing edges and faces when not using X-Ray or Select Through"},
{0, nullptr, 0, nullptr, nullptr},
};
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);
@ -570,6 +868,35 @@ 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_enum(ot->srna,
"auto_xray",
auto_xray_items,
0,
"Auto X-Ray",
"Transparent scene display during selection");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna,
"select_through",
select_through_items,
0,
"Select Through",
"Select occluded objects and mesh");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(
ot->srna, "object_type", object_select_items, 0, "Object", "Object selection style");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", "Face selection style");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", "Edge selection style");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna,
"backface_filter",
backface_filter_items,
0,
"Backface",
"Select mesh based on the direction of their normals");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
void WM_operator_properties_mouse_select(wmOperatorType *ot)