WIP: Custom build, mostly selection options #105712

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

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
23 changed files with 1596 additions and 177 deletions
Showing only changes of commit d9e10e6ddb - Show all commits

View File

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

View File

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

View File

@ -1559,6 +1559,8 @@ class USERPREF_PT_input_mouse(InputPanel, CenterAlignMixIn, Panel):
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
flow.prop(inputs, "click_drag_direction")
flow.prop(inputs, "drag_select_mesh_control")
flow.prop(inputs, "use_mouse_emulate_3_button")
if sys.platform[:3] != "win":
rowsub = flow.row()

View File

@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
import bpy
from bpy.types import Menu, Panel, UIList, WindowManager
from bl_ui.properties_grease_pencil_common import (
GreasePencilSculptAdvancedPanel,
@ -153,7 +154,7 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
bl_context = ".mesh_edit" # dot on purpose (access from topbar)
bl_label = "Options"
bl_options = {'DEFAULT_CLOSED'}
bl_ui_units_x = 12
bl_ui_units_x = 14
@classmethod
def poll(cls, context):
@ -169,6 +170,7 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
ob = context.active_object
mesh = ob.data
row = layout.row(align=True)
row = layout.row(align=True, heading="Transform")
row.prop(tool_settings, "use_transform_correct_face_attributes")
@ -189,6 +191,61 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
row.active = ob.data.use_mirror_x or ob.data.use_mirror_y or ob.data.use_mirror_z
row.prop(mesh, "use_mirror_topology")
if bpy.context.preferences.inputs.drag_select_mesh_control == 'USER_MESH_TOOLSETTING':
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 tool == "builtin.select_box" or tool == "builtin.select_lasso" or tool == "builtin.select_circle":
row = layout.row(align=True, heading="Drag Select")
if tool == "builtin.select_box":
row.prop(tool_settings, "box_drag_direction")
row = layout.row(align=True)
if tool_settings.box_drag_direction == 'MESH_DIRECTION_ANY':
row.prop(tool_settings, "box_edge")
row = layout.row(align=True)
row.prop(tool_settings, "box_face")
elif tool_settings.box_drag_direction == 'MESH_DIRECTION_LEFT_RIGHT':
row.prop(tool_settings, "box_edge_left", text="Box Edge", icon='TRIA_LEFT')
row.prop(tool_settings, "box_edge_right", text="", icon='TRIA_RIGHT')
row = layout.row(align=True)
row.prop(tool_settings, "box_face_left", text="Box Face", icon='TRIA_LEFT')
row.prop(tool_settings, "box_face_right", text="", icon='TRIA_RIGHT')
else:
row.prop(tool_settings, "box_edge_up", text="Box Edge", icon='TRIA_UP')
row.prop(tool_settings, "box_edge_down", text="", icon='TRIA_DOWN')
row = layout.row(align=True)
row.prop(tool_settings, "box_face_up", text="Box Face", icon='TRIA_UP')
row.prop(tool_settings, "box_face_down", text="", icon='TRIA_DOWN')
elif tool == "builtin.select_lasso":
row.prop(tool_settings, "lasso_drag_direction")
row = layout.row(align=True)
if tool_settings.lasso_drag_direction == 'MESH_DIRECTION_ANY':
row.prop(tool_settings, "lasso_edge")
row = layout.row(align=True)
row.prop(tool_settings, "lasso_face")
elif tool_settings.lasso_drag_direction == 'MESH_DIRECTION_LEFT_RIGHT':
row.prop(tool_settings, "lasso_edge_left", text="Lasso Edge", icon='TRIA_LEFT')
row.prop(tool_settings, "lasso_edge_right", text="", icon='TRIA_RIGHT')
row = layout.row(align=True)
row.prop(tool_settings, "lasso_face_left", text="Lasso Face", icon='TRIA_LEFT')
row.prop(tool_settings, "lasso_face_right", text="", icon='TRIA_RIGHT')
else:
row.prop(tool_settings, "lasso_edge_up", text="Lasso Edge", icon='TRIA_UP')
row.prop(tool_settings, "lasso_edge_down", text="", icon='TRIA_DOWN')
row = layout.row(align=True)
row.prop(tool_settings, "lasso_face_up", text="Lasso Face", icon='TRIA_UP')
row.prop(tool_settings, "lasso_face_down", text="", icon='TRIA_DOWN')
elif tool == "builtin.select_circle":
row = layout.row(align=True)
row.prop(tool_settings, "circle_edge")
row = layout.row(align=True)
row.prop(tool_settings, "circle_face")
class VIEW3D_PT_tools_meshedit_options_automerge(View3DPanel, Panel):
bl_category = "Tool"

View File

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

View File

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

View File

@ -373,6 +373,32 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene)
if (idprop) {
IDP_ClearProperty(idprop);
}
/* Mesh select. */
ts->box_drag_direction = 1;
ts->lasso_drag_direction = 1;
ts->box_edge = 1;
ts->box_edge_left = 1;
ts->box_edge_right = 1;
ts->box_edge_up = 1;
ts->box_edge_down = 1;
ts->box_face = 1;
ts->box_face_left = 1;
ts->box_face_right = 1;
ts->box_face_up = 1;
ts->box_face_down = 1;
ts->lasso_edge = 1;
ts->lasso_edge_left = 1;
ts->lasso_edge_right = 1;
ts->lasso_edge_up = 1;
ts->lasso_edge_down = 1;
ts->lasso_face = 1;
ts->lasso_face_left = 1;
ts->lasso_face_right = 1;
ts->lasso_face_up = 1;
ts->lasso_face_down = 1;
ts->circle_edge = 2;
ts->circle_face = 1;
}
void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)

View File

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

View File

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

View File

@ -752,7 +752,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
mesh_foreachScreenFace(
mesh_foreachScreenFaceCenter(
vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
*r_dist_center = data.dist_px_manhattan;
@ -804,7 +804,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
*dist_px_manhattan_p;
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
mesh_foreachScreenFaceCenter(vc, findnearestface__doClosest, &data, clip_flag);
hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -366,6 +366,32 @@
/* UV painting */ \
.uv_sculpt_settings = 0, \
.uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN, \
\
/* Mesh Select */ \
.box_drag_direction = 1, \
.lasso_drag_direction = 1, \
.box_edge = 1, \
.box_edge_left = 1, \
.box_edge_right = 1, \
.box_edge_up = 1, \
.box_edge_down = 1, \
.box_face = 1, \
.box_face_left = 1, \
.box_face_right = 1, \
.box_face_up = 1, \
.box_face_down = 1, \
.lasso_edge = 1, \
.lasso_edge_left = 1, \
.lasso_edge_right = 1, \
.lasso_edge_up = 1, \
.lasso_edge_down = 1, \
.lasso_face = 1, \
.lasso_face_left = 1, \
.lasso_face_right = 1, \
.lasso_face_up = 1, \
.lasso_face_down = 1, \
.circle_edge = 2, \
.circle_face = 1, \
}
/* clang-format off */

View File

@ -1682,7 +1682,35 @@ typedef struct ToolSettings {
/** Normal Editing. */
float normal_vector[3];
char _pad6[4];
/** Mesh Select Options. */
char box_drag_direction;
char lasso_drag_direction;
char box_direction_upright;
char lasso_direction_upright;
char box_edge;
char box_edge_left;
char box_edge_right;
char box_edge_up;
char box_edge_down;
char box_face;
char box_face_left;
char box_face_right;
char box_face_up;
char box_face_down;
char lasso_edge;
char lasso_edge_left;
char lasso_edge_right;
char lasso_edge_up;
char lasso_edge_down;
char lasso_face;
char lasso_face_left;
char lasso_face_right;
char lasso_face_up;
char lasso_face_down;
char circle_edge;
char circle_face;
char _pad6[2];
/**
* Custom Curve Profile for bevel tool:
@ -2331,6 +2359,28 @@ typedef enum eSnapTransformMode {
SCE_SNAP_TRANSFORM_MODE_SCALE = (1 << 2),
} eSnapTransformMode;
/** #ToolSettings.face_select */
enum {
FACE_AUTO = (1 << 0),
FACE_TOUCH = (1 << 1),
FACE_ENCLOSE = (1 << 2),
FACE_CENTER = (1 << 3),
};
/** #ToolSettings.edge_select */
enum {
EDGE_HYBRID = (1 << 0),
EDGE_TOUCH = (1 << 1),
EDGE_ENCLOSE = (1 << 2),
};
/** #ToolSettings.mesh_drag_direction */
enum {
MESH_DIRECTION_ANY = (1 << 0),
MESH_DIRECTION_LEFT_RIGHT = (1 << 1),
MESH_DIRECTION_UP_DOWN = (1 << 2),
};
/** #ToolSettings.selectmode */
#define SCE_SELECT_VERTEX (1 << 0) /* for mesh */
#define SCE_SELECT_EDGE (1 << 1)

View File

@ -840,7 +840,11 @@ typedef struct UserDef {
/** #eGPUBackendType */
short gpu_backend;
char _pad7[4];
/** Keymap click-drag direction style. */
char click_drag_direction;
/** Box, lasso, and circle select mesh control style. */
char drag_select_mesh_control;
char _pad7[2];
/** Private, defaults to 20 for 72 DPI setting. */
short widget_unit;
@ -1153,6 +1157,19 @@ typedef enum eUserpref_TableAPI {
USER_TABLET_WINTAB = 2,
} eUserpref_TabletAPI;
/** #UserDef.click_drag_direction_types */
typedef enum eUserpref_Click_Drag_Direction {
USER_CLICK_DRAG_DIRECTION_EIGHT_WAY = 0,
USER_CLICK_DRAG_DIRECTION_LEFT_RIGHT = 1,
USER_CLICK_DRAG_DIRECTION_UP_DOWN = 2,
} eUserpref_Click_Drag_Direction;
/** #UserDef.drag_select_mesh_control_types */
typedef enum eUserpref_Drag_Select_Mesh_Control {
USER_DRAG_SELECT_MESH_KEYMAP = 0,
USER_DRAG_SELECT_MESH_TOOLSETTING = 1,
} eUserpref_Drag_Select_Mesh_Control;
/** #UserDef.app_flag */
typedef enum eUserpref_APP_Flag {
USER_APP_LOCK_CORNER_SPLIT = (1 << 0),

View File

@ -3049,10 +3049,189 @@ static void rna_def_tool_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem mesh_drag_direction_items[] = {
{MESH_DIRECTION_ANY, "MESH_DIRECTION_ANY", 0, "Any", "Drag in any direction"},
{MESH_DIRECTION_LEFT_RIGHT,
"MESH_DIRECTION_LEFT_RIGHT",
0,
"Left Right",
"Drag to the left and right"},
{MESH_DIRECTION_UP_DOWN,
"MESH_DIRECTION_UP_DOWN",
0,
"Up Down",
"Drag upwards and downwards"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem edge_select_items[] = {
{EDGE_HYBRID,
"EDGE_HYBRID",
0,
"Hybrid",
"Select edges that are fully inside the selection area. If no edges are fully inside the "
"selection area, select edges that are touched by the selection area"},
{EDGE_TOUCH,
"EDGE_TOUCH",
0,
"Touch",
"Select edges that are touched by the selection area"},
{EDGE_ENCLOSE,
"EDGE_ENCLOSE",
0,
"Enclose",
"Select edges that are fully inside the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem edge_circle_select_items[] = {
{EDGE_TOUCH,
"EDGE_TOUCH",
0,
"Touch",
"Select edges that are touched by the selection area"},
{EDGE_ENCLOSE,
"EDGE_ENCLOSE",
0,
"Enclose",
"Select edges that are fully inside the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem face_select_items[] = {
{FACE_AUTO,
"FACE_AUTO",
0,
"Auto",
"Select faces that are touched by the selection area in near select. Select faces whose "
"center is touched by the selection area in X-Ray select"},
{FACE_TOUCH,
"FACE_TOUCH",
0,
"Touch",
"Select faces that are touched by the selection area"},
{FACE_ENCLOSE,
"FACE_ENCLOSE",
0,
"Enclose",
"Select faces that are fully inside the selection area"},
{FACE_CENTER,
"FACE_CENTER",
0,
"Center",
"Select faces whose center is touched by the selection area"},
{0, NULL, 0, NULL, NULL},
};
srna = RNA_def_struct(brna, "ToolSettings", NULL);
RNA_def_struct_path_func(srna, "rna_ToolSettings_path");
RNA_def_struct_ui_text(srna, "Tool Settings", "");
/* Mesh select settings. */
prop = RNA_def_property(srna, "box_drag_direction", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, mesh_drag_direction_items);
RNA_def_property_ui_text(prop, "Box Direction", "Click-drag direction style for box select");
prop = RNA_def_property(srna, "lasso_drag_direction", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, mesh_drag_direction_items);
RNA_def_property_ui_text(prop, "Lasso Direction", "Click-drag direction style for lasso select");
prop = RNA_def_property(srna, "box_direction_upright", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "box_direction_upright", 0);
RNA_def_property_ui_text(prop, "Box Direction Helper", "");
prop = RNA_def_property(srna, "lasso_direction_upright", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "lasso_direction_upright", 0);
RNA_def_property_ui_text(prop, "Lasso Direction Helper", "");
prop = RNA_def_property(srna, "box_edge", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Box Edge", "Box edge selection style");
prop = RNA_def_property(srna, "box_edge_left", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Box Edge Left", "Box edge selection style when dragging left");
prop = RNA_def_property(srna, "box_edge_right", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Box Edge Right", "Box edge selection style when dragging right");
prop = RNA_def_property(srna, "box_edge_up", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Box Edge Up", "Box edge selection style when dragging up");
prop = RNA_def_property(srna, "box_edge_down", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Box Edge Down", "Box edge selection style when dragging down");
prop = RNA_def_property(srna, "box_face", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Box Face", "Box face selection style");
prop = RNA_def_property(srna, "box_face_left", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Box Face Left", "Box face selection style when dragging left");
prop = RNA_def_property(srna, "box_face_right", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Box Face Right", "Box face selection style when dragging right");
prop = RNA_def_property(srna, "box_face_up", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Box Face Up", "Box face selection style when dragging up");
prop = RNA_def_property(srna, "box_face_down", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Box Face Down", "Box face selection style when dragging down");
prop = RNA_def_property(srna, "lasso_edge", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Lasso Edge", "Lasso edge selection style");
prop = RNA_def_property(srna, "lasso_edge_left", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Lasso Edge Left", "Lasso edge selection style when dragging left");
prop = RNA_def_property(srna, "lasso_edge_right", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Lasso Edge Right", "Lasso edge selection style when dragging right");
prop = RNA_def_property(srna, "lasso_edge_up", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Lasso Edge Up", "Lasso edge selection style when dragging up");
prop = RNA_def_property(srna, "lasso_edge_down", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_select_items);
RNA_def_property_ui_text(prop, "Lasso Edge Down", "Lasso edge selection style when dragging down");
prop = RNA_def_property(srna, "lasso_face", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Lasso Face", "Lasso face selection style");
prop = RNA_def_property(srna, "lasso_face_left", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Lasso Face Left", "Lasso face selection style when dragging left");
prop = RNA_def_property(srna, "lasso_face_right", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Lasso Face Right", "Lasso face selection style when dragging right");
prop = RNA_def_property(srna, "lasso_face_up", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Lasso Face Up", "Lasso face selection style when dragging up");
prop = RNA_def_property(srna, "lasso_face_down", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Lasso Face Down", "Lasso face selection style when dragging down");
prop = RNA_def_property(srna, "circle_edge", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, edge_circle_select_items);
RNA_def_property_ui_text(prop, "Circle Edge", "Circle edge selection style");
prop = RNA_def_property(srna, "circle_face", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, face_select_items);
RNA_def_property_ui_text(prop, "Circle Face", "Circle face selection style");
prop = RNA_def_property(srna, "sculpt", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Sculpt");
RNA_def_property_ui_text(prop, "Sculpt", "");

View File

@ -5774,6 +5774,31 @@ static void rna_def_userdef_input(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem click_drag_direction_types[] = {
{USER_CLICK_DRAG_DIRECTION_EIGHT_WAY,
"EIGHT_WAY",
0,
"Eight",
"Eight directions (N, NE, E, SE, S, SW, W, NW)"},
{USER_CLICK_DRAG_DIRECTION_LEFT_RIGHT, "LEFT_RIGHT", 0, "Left Right", "Left and right"},
{USER_CLICK_DRAG_DIRECTION_UP_DOWN, "UP_DOWN", 0, "Up Down", "Up and down"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem drag_select_mesh_control_types[] = {
{USER_DRAG_SELECT_MESH_KEYMAP,
"USER_MESH_KEYMAP",
0,
"Keymap",
"Use the keymap to control mesh selection style for box, lasso, and circle"},
{USER_DRAG_SELECT_MESH_TOOLSETTING,
"USER_MESH_TOOLSETTING",
0,
"Toolsetting",
"Use toolsettings to control mesh selection style for box, lasso, and circle"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem view_zoom_styles[] = {
{USER_ZOOM_CONTINUE,
"CONTINUE",
@ -5880,6 +5905,18 @@ static void rna_def_userdef_input(BlenderRNA *brna)
"Release Confirms",
"Moving things with a mouse drag confirms when releasing the button");
prop = RNA_def_property(srna, "click_drag_direction", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, click_drag_direction_types);
RNA_def_property_ui_text(
prop, "Keymap Drag Directions", "Style of click-drag direction the keymap will use");
prop = RNA_def_property(srna, "drag_select_mesh_control", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, drag_select_mesh_control_types);
RNA_def_property_ui_text(prop,
"Mesh Drag Select Control",
"Use either the keymap or toolsettings to control edge and face selection style "
"for box, lasso, and circle select");
prop = RNA_def_property(srna, "use_numeric_input_advanced", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_FLAG_NUMINPUT_ADVANCED);
RNA_def_property_ui_text(prop,

View File

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

View File

@ -1611,7 +1611,7 @@ bool WM_event_is_modal_drag_exit(const struct wmEvent *event,
short init_event_val);
bool WM_event_is_mouse_drag(const struct wmEvent *event);
bool WM_event_is_mouse_drag_or_press(const wmEvent *event);
int WM_event_drag_direction(const wmEvent *event);
int WM_event_drag_direction(const wmEvent *event, const struct Scene *scene);
char WM_event_utf8_to_ascii(const struct wmEvent *event) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
/**

View File

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

View File

@ -3432,7 +3432,8 @@ static eHandlerActionFlag wm_handlers_do(bContext *C, wmEvent *event, ListBase *
if ((event->flag & WM_EVENT_FORCE_DRAG_THRESHOLD) ||
WM_event_drag_test(event, event->prev_press_xy)) {
win->event_queue_check_drag_handled = true;
const int direction = WM_event_drag_direction(event);
const Scene *scene = CTX_data_scene(C);
const int direction = WM_event_drag_direction(event, scene);
/* 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

@ -411,8 +411,58 @@ void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bo
{
PropertyRNA *prop;
static const EnumPropertyItem face_select_items[] = {
{FACE_AUTO,
"FACE_AUTO",
0,
"Auto",
"Select faces that are touched by the selection area in near select. Select faces whose "
"center is touched by the selection area in X-Ray select"},
{FACE_TOUCH,
"FACE_TOUCH",
0,
"Touch",
"Select faces that are touched by the selection area"},
{FACE_ENCLOSE,
"FACE_ENCLOSE",
0,
"Enclose",
"Select faces that are fully inside the selection area"},
{FACE_CENTER,
"FACE_CENTER",
0,
"Center",
"Select faces whose center is touched by the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem edge_select_items[] = {
{EDGE_HYBRID,
"EDGE_HYBRID",
0,
"Hybrid",
"Select edges that are fully inside the selection area. If no edges are fully inside the "
"selection area, select edges that are touched by the selection area"},
{EDGE_TOUCH,
"EDGE_TOUCH",
0,
"Touch",
"Select edges that are touched by the selection area"},
{EDGE_ENCLOSE,
"EDGE_ENCLOSE",
0,
"Enclose",
"Select edges that are fully inside the selection area"},
{0, NULL, 0, NULL, NULL},
};
WM_operator_properties_border(ot);
prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
if (deselect) {
prop = RNA_def_boolean(
ot->srna, "deselect", false, "Deselect", "Deselect rather than select items");
@ -440,7 +490,8 @@ void WM_operator_properties_use_cursor_init(wmOperatorType *ot)
void WM_operator_properties_gesture_box_select(wmOperatorType *ot)
{
WM_operator_properties_gesture_box_ex(ot, true, true);
WM_operator_properties_gesture_box_ex(
ot, true, true);
}
void WM_operator_properties_gesture_box(wmOperatorType *ot)
{
@ -519,6 +570,54 @@ void WM_operator_properties_gesture_box_zoom(wmOperatorType *ot)
void WM_operator_properties_gesture_lasso(wmOperatorType *ot)
{
PropertyRNA *prop;
static const EnumPropertyItem face_select_items[] = {
{FACE_AUTO,
"FACE_AUTO",
0,
"Auto",
"Select faces that are touched by the selection area in near select. Select faces whose "
"center is touched by the selection area in X-Ray select"},
{FACE_TOUCH,
"FACE_TOUCH",
0,
"Touch",
"Select faces that are touched by the selection area"},
{FACE_ENCLOSE,
"FACE_ENCLOSE",
0,
"Enclose",
"Select faces that are fully inside the selection area"},
{FACE_CENTER,
"FACE_CENTER",
0,
"Center",
"Select faces whose center is touched by the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem edge_select_items[] = {
{EDGE_HYBRID,
"EDGE_HYBRID",
0,
"Hybrid",
"Select edges that are fully inside the selection area. If no edges are fully inside the "
"selection area, select edges that are touched by the selection area"},
{EDGE_TOUCH,
"EDGE_TOUCH",
0,
"Touch",
"Select edges that are touched by the selection area"},
{EDGE_ENCLOSE,
"EDGE_ENCLOSE",
0,
"Enclose",
"Select edges that are fully inside the selection area"},
{0, NULL, 0, NULL, NULL},
};
prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
@ -557,6 +656,45 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot)
PropertyRNA *prop;
const int radius_default = 25;
static const EnumPropertyItem face_select_items[] = {
{FACE_AUTO,
"FACE_AUTO",
0,
"Auto",
"Select faces that are touched by the selection area in near select. Select faces whose "
"center is touched by the selection area in X-Ray select"},
{FACE_TOUCH,
"FACE_TOUCH",
0,
"Touch",
"Select faces that are touched by the selection area"},
{FACE_ENCLOSE,
"FACE_ENCLOSE",
0,
"Enclose",
"Select faces that are fully inside the selection area"},
{FACE_CENTER,
"FACE_CENTER",
0,
"Center",
"Select faces whose center is touched by the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem edge_select_items[] = {
{EDGE_TOUCH,
"EDGE_TOUCH",
0,
"Touch",
"Select edges that are touched by the selection area"},
{EDGE_ENCLOSE,
"EDGE_ENCLOSE",
0,
"Enclose",
"Select edges that are fully inside the selection area"},
{0, NULL, 0, NULL, NULL},
};
prop = RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
@ -565,6 +703,11 @@ 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, "face_type", face_select_items, 0, "Face Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
void WM_operator_properties_mouse_select(wmOperatorType *ot)