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.
16 changed files with 1021 additions and 120 deletions
Showing only changes of commit 4686169584 - Show all commits

View File

@ -1560,7 +1560,7 @@ 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, "drag_select_control")
flow.prop(inputs, "use_mouse_emulate_3_button")
if sys.platform[:3] != "win":
rowsub = flow.row()

View File

@ -889,9 +889,47 @@ class VIEW3D_HT_header(Header):
sub.active = overlay.show_overlays
sub.popover(panel="VIEW3D_PT_overlay", text="")
row = layout.row()
row = layout.row(align=True)
row.active = (object_mode == 'EDIT') or (shading.type in {'WIREFRAME', 'SOLID'})
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
_cls = ToolSelectPanelHelper._tool_class_from_space_type('VIEW_3D')
if tool_settings.workspace_tool_type == 'FALLBACK':
tool = _cls._tool_get_by_id_active(context, _cls.tool_fallback_id)[0].idname
else:
tool = ToolSelectPanelHelper.tool_active_from_context(context).idname
if object_mode in 'EDIT':
mode_match_auto_xray = tool_settings.auto_xray_edit and tool_settings.auto_xray
mode_match_select_through = tool_settings.select_through_edit and tool_settings.select_through
elif object_mode in 'OBJECT':
mode_match_auto_xray = tool_settings.auto_xray_object and tool_settings.auto_xray
mode_match_select_through = tool_settings.select_through_object and tool_settings.select_through
else:
mode_match_auto_xray = False
mode_match_select_through = False
if tool == "builtin.select_box":
depress_auto_xray = mode_match_auto_xray and tool_settings.auto_xray_box
depress_select_through = mode_match_select_through and tool_settings.select_through_box
elif tool == "builtin.select_lasso":
depress_auto_xray = mode_match_auto_xray and tool_settings.auto_xray_lasso
depress_select_through = mode_match_select_through and tool_settings.select_through_lasso
elif tool == "builtin.select_circle":
depress_auto_xray = mode_match_auto_xray and tool_settings.auto_xray_circle
depress_select_through = mode_match_select_through and tool_settings.select_through_circle
else:
depress_auto_xray = False
depress_select_through = False
if object_mode in 'EDIT' or object_mode in 'OBJECT':
if bpy.context.preferences.inputs.drag_select_control == 'USER_DRAG_TOOLSETTING':
if tool_settings.auto_xray_button:
row.operator("view3d.toggle_auto_xray", text="", icon='XRAY', depress=depress_auto_xray)
if tool_settings.select_through_button:
row.operator("view3d.toggle_select_through", text="", icon='XRAY', depress=depress_select_through)
# While exposing `shading.show_xray(_wireframe)` is correct.
# this hides the key shortcut from users: #70433.
if has_pose_mode:
@ -900,12 +938,15 @@ class VIEW3D_HT_header(Header):
draw_depressed = shading.show_xray_wireframe
else:
draw_depressed = shading.show_xray
row.operator(
"view3d.toggle_xray",
text="",
icon='XRAY',
depress=draw_depressed,
)
if bpy.context.preferences.inputs.drag_select_control == 'USER_DRAG_TOOLSETTING':
if tool_settings.xray_button:
row.operator("view3d.toggle_xray", text="", icon='XRAY', depress=draw_depressed)
elif not tool_settings.auto_xray_button and not tool_settings.select_through_button:
row.operator("view3d.toggle_xray", text="", icon='XRAY', depress=draw_depressed)
else:
row.operator("view3d.toggle_xray", text="", icon='XRAY', depress=draw_depressed)
row.popover(panel="VIEW3D_PT_xray", text="")
row = layout.row(align=True)
row.prop(shading, "type", text="", expand=True)
@ -6068,17 +6109,7 @@ class VIEW3D_PT_shading_options(Panel):
row = col.row(align=True)
if shading.type == 'WIREFRAME':
row.prop(shading, "show_xray_wireframe", text="")
sub = row.row()
sub.active = shading.show_xray_wireframe
sub.prop(shading, "xray_alpha_wireframe", text="X-Ray")
elif shading.type == 'SOLID':
row.prop(shading, "show_xray", text="")
sub = row.row()
sub.active = shading.show_xray
sub.prop(shading, "xray_alpha", text="X-Ray")
# X-ray mode is off when alpha is 1.0
if shading.type == 'SOLID':
xray_active = shading.show_xray and shading.xray_alpha != 1
row = col.row(align=True)
@ -6263,6 +6294,83 @@ class VIEW3D_PT_gizmo_display(Panel):
col.prop(view, "show_gizmo_camera_dof_distance", text="Focus Distance")
class VIEW3D_PT_xray(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
bl_label = "X-Ray Settings"
bl_ui_units_x = 14
def draw(self, context):
layout = self.layout
layout.label(text="X-Ray Settings")
shading = VIEW3D_PT_shading.get_shading(context)
col = layout.column()
row = col.row(align=True)
if shading.type == 'WIREFRAME':
row.prop(shading, "show_xray_wireframe", text="")
sub = row.row()
sub.active = shading.show_xray_wireframe
sub.prop(shading, "xray_alpha_wireframe", text="X-Ray Wireframe")
elif shading.type == 'SOLID':
row.prop(shading, "show_xray", text="")
sub = row.row()
sub.active = shading.show_xray
sub.prop(shading, "xray_alpha", text="X-Ray Solid")
if bpy.context.preferences.inputs.drag_select_control == 'USER_DRAG_TOOLSETTING':
tool_settings = context.tool_settings
row = layout.row(align=True)
row = layout.row(align=True)
row = layout.row(align=True)
row = layout.row(heading="Automatic X-Ray")
row.prop(tool_settings, "ui_prop", text="", emboss=False)
row = layout.row(align=True)
row.prop(tool_settings, "auto_xray", text="Enable")
sub = row.row(align=True)
sub.active = tool_settings.auto_xray
sub.prop(tool_settings, "auto_xray_object", text="Object")
sub.prop(tool_settings, "auto_xray_edit", text="Edit")
row = layout.row(align=True)
sub = row.row(align=True)
sub.active = tool_settings.auto_xray
sub.prop(tool_settings, "auto_xray_box", text="Box", toggle=True)
sub.prop(tool_settings, "auto_xray_lasso", text="Lasso", toggle=True)
sub.prop(tool_settings, "auto_xray_circle", text="Circle", toggle=True)
row = layout.row(align=True)
row = layout.row(align=True)
row = layout.row(align=True)
row = layout.row(heading="Select Through")
row.prop(tool_settings, "ui_prop", text="", emboss=False)
row = layout.row(align=True)
row.prop(tool_settings, "select_through", text="Enable")
sub = row.row(align=True)
sub.active = tool_settings.select_through
sub.prop(tool_settings, "select_through_object", text="Object")
sub.prop(tool_settings, "select_through_edit", text="Edit")
row = layout.row(align=True)
sub = row.row(align=True)
sub.active = tool_settings.select_through
sub.prop(tool_settings, "select_through_box", text="Box", toggle=True)
sub.prop(tool_settings, "select_through_lasso", text="Lasso", toggle=True)
sub.prop(tool_settings, "select_through_circle", text="Circle", toggle=True)
row = layout.row(align=True)
row = layout.row(align=True)
row = layout.row(align=True)
row = layout.row(heading="Header Buttons")
row.prop(tool_settings, "ui_prop", text="", emboss=False)
row = layout.row(align=True)
row.prop(tool_settings, "auto_xray_button", text="Auto X-Ray", toggle=True)
row.prop(tool_settings, "select_through_button", text="Select Through", toggle=True)
row.prop(tool_settings, "xray_button", text="X-Ray", toggle=True)
class VIEW3D_PT_overlay(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
@ -8209,6 +8317,7 @@ classes = (
VIEW3D_PT_shading_render_pass,
VIEW3D_PT_shading_compositor,
VIEW3D_PT_gizmo_display,
VIEW3D_PT_xray,
VIEW3D_PT_overlay,
VIEW3D_PT_overlay_guides,
VIEW3D_PT_overlay_object,

View File

@ -154,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 = 14
bl_ui_units_x = 15
@classmethod
def poll(cls, context):
@ -191,7 +191,7 @@ 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':
if bpy.context.preferences.inputs.drag_select_control == 'USER_DRAG_TOOLSETTING':
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
_cls = ToolSelectPanelHelper._tool_class_from_space_type('VIEW_3D')
@ -201,7 +201,7 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
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")
row = layout.row(align=True)
if tool == "builtin.select_box":
row.prop(tool_settings, "box_drag_direction")
row = layout.row(align=True)

View File

@ -399,6 +399,19 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene)
ts->lasso_face_down = 1;
ts->circle_edge = 2;
ts->circle_face = 1;
/* X-Ray. */
ts->xray_button = true;
ts->auto_xray_object = true;
ts->auto_xray_edit = true;
ts->auto_xray_box = true;
ts->auto_xray_lasso = true;
ts->auto_xray_circle = true;
ts->select_through = true;
ts->select_through_object = true;
ts->select_through_box = true;
ts->select_through_lasso = true;
ts->select_through_circle = true;
}
void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)

View File

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

View File

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

View File

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

View File

@ -729,42 +729,225 @@ static void do_lasso_tag_pose(ViewContext *vc,
V3D_PROJ_TEST_CLIP_DEFAULT | V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT);
}
/**
* Compare result of 'GPU_select': 'GPUSelectResult',
* Needed for stable sorting, so cycling through all items near the cursor behaves predictably.
*/
static int gpu_select_buffer_depth_id_cmp(const void *sel_a_p, const void *sel_b_p)
{
GPUSelectResult *a = (GPUSelectResult *)sel_a_p;
GPUSelectResult *b = (GPUSelectResult *)sel_b_p;
if (a->depth < b->depth) {
return -1;
}
if (a->depth > b->depth) {
return 1;
}
/* Depths match, sort by id. */
uint sel_a = a->id;
uint sel_b = b->id;
#ifdef __BIG_ENDIAN__
BLI_endian_switch_uint32(&sel_a);
BLI_endian_switch_uint32(&sel_b);
#endif
if (sel_a < sel_b) {
return -1;
}
if (sel_a > sel_b) {
return 1;
}
return 0;
}
static bool do_lasso_select_objects(ViewContext *vc,
const int mcoords[][2],
const int mcoords_len,
const eSelectOp sel_op)
const eSelectOp sel_op,
wmOperator *op,
int circle_data[3])
{
View3D *v3d = vc->v3d;
int totobj = MAXPICKELEMS; /* XXX solve later */
/* Selection buffer has bones potentially too, so we add #MAXPICKELEMS. */
GPUSelectResult *buffer = static_cast<GPUSelectResult *>(
MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(GPUSelectResult), __func__));
ToolSettings *ts = vc->scene->toolsettings;
bool changed = false;
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
changed |= object_deselect_all_visible(vc->scene, vc->view_layer, vc->v3d);
const int select_through_int = RNA_enum_get(op->ptr, "select_through");
const bool select_through = U.drag_select_control & USER_DRAG_SELECT_KEYMAP ?
select_through_int == 2 || select_through_int == 8 :
circle_data == NULL ?
ts->select_through && ts->select_through_object &&
ts->select_through_lasso :
ts->select_through && ts->select_through_object &&
ts->select_through_circle;
float region_co[2];
float mval_fl[2];
if (circle_data != NULL) {
mval_fl[0] = circle_data[0];
mval_fl[1] = circle_data[1];
}
BKE_view_layer_synced_ensure(vc->scene, vc->view_layer);
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(vc->view_layer)) {
if (BASE_SELECTABLE(v3d, base)) { /* Use this to avoid unnecessary lasso look-ups. */
float region_co[2];
const bool is_select = base->flag & BASE_SELECTED;
const bool is_inside = (ED_view3d_project_base(vc->region, base, region_co) ==
V3D_PROJ_RET_OK) &&
BLI_lasso_is_point_inside(mcoords,
mcoords_len,
int(region_co[0]),
int(region_co[1]),
/* Dummy value. */
INT_MAX);
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
ED_object_base_select(base, sel_op_result ? BA_SELECT : BA_DESELECT);
changed = true;
bool changed = false;
if (select_through && circle_data == NULL) {
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
changed |= object_deselect_all_visible(vc->scene, vc->view_layer, vc->v3d);
}
BKE_view_layer_synced_ensure(vc->scene, vc->view_layer);
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(vc->view_layer)) {
if (BASE_SELECTABLE(v3d, base)) { /* Use this to avoid unnecessary lasso look-ups. */
float region_co[2];
const bool is_select = base->flag & BASE_SELECTED;
const bool is_inside = (ED_view3d_project_base(vc->region, base, region_co) ==
V3D_PROJ_RET_OK) &&
BLI_lasso_is_point_inside(mcoords,
mcoords_len,
int(region_co[0]),
int(region_co[1]),
/* Dummy value. */
INT_MAX);
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
ED_object_base_select(base, sel_op_result ? BA_SELECT : BA_DESELECT);
changed = true;
}
}
}
if (changed) {
DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene);
}
}
if (changed) {
DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene);
else {
int hits = 0;
rcti rect_data;
rcti *rect = &rect_data;
blender::Vector<Base *> bases;
if (circle_data != NULL) {
int point[4][2] = {};
for (int i = 0; i < 4; i++) {
float angle = 6.28f * (i + 1) / 4;
point[i][0] = circle_data[0] + circle_data[2] * cosf(angle);
point[i][1] = circle_data[1] + circle_data[2] * sinf(angle);
}
rect->xmin = rect->xmax = point[0][0];
rect->ymin = rect->ymax = point[0][1];
uint a;
for (a = 1; a < 4; a++) {
if (point[a][0] < rect->xmin) {
rect->xmin = point[a][0];
}
else if (point[a][0] > rect->xmax) {
rect->xmax = point[a][0];
}
if (point[a][1] < rect->ymin) {
rect->ymin = point[a][1];
}
else if (point[a][1] > rect->ymax) {
rect->ymax = point[a][1];
}
}
}
else {
BLI_lasso_boundbox(rect, mcoords, mcoords_len);
}
const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene,
vc->obact);
if (XRAY_FLAG_ENABLED(vc->v3d) || select_through) {
hits = view3d_opengl_select(
vc, buffer, (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
}
else {
hits = view3d_opengl_select(
vc, buffer, (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_PICK_NEAREST, select_filter);
}
BKE_view_layer_synced_ensure(vc->scene, vc->view_layer);
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(vc->view_layer)) {
base->object->id.tag &= ~LIB_TAG_DOIT;
}
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
changed |= object_deselect_all_visible(vc->scene, vc->view_layer, vc->v3d);
}
ListBase *object_bases = BKE_view_layer_object_bases_get(vc->view_layer);
if ((hits == -1) && !SEL_OP_USE_OUTSIDE(sel_op)) {
goto finally;
}
LISTBASE_FOREACH (Base *, base, object_bases) {
if (BASE_SELECTABLE(v3d, base)) {
if ((base->object->runtime.select_id & 0x0000FFFF) != 0) {
bases.append(base);
}
}
}
/* The draw order doesn't always match the order we populate the engine, see: T51695. */
qsort(buffer, hits, sizeof(GPUSelectResult), gpu_select_buffer_depth_id_cmp);
for (const GPUSelectResult *buf_iter = buffer, *buf_end = buf_iter + hits; buf_iter < buf_end;
buf_iter++) {
bPoseChannel *pchan_dummy;
Base *base = ED_armature_base_and_pchan_from_select_buffer(
bases.data(), bases.size(), buf_iter->id, &pchan_dummy);
if (base != nullptr) {
base->object->id.tag |= LIB_TAG_DOIT;
}
}
for (Base *base = static_cast<Base *>(object_bases->first); base && hits; base = base->next) {
if (BASE_SELECTABLE(v3d, base)) {
const bool is_select = base->flag & BASE_SELECTED;
bool is_inside = false;
if (circle_data == NULL) {
is_inside = base->object->id.tag & LIB_TAG_DOIT &&
(ED_view3d_project_base(vc->region, base, region_co) == V3D_PROJ_RET_OK) &&
BLI_lasso_is_point_inside(mcoords,
mcoords_len,
int(region_co[0]),
int(region_co[1]),
/* Dummy value. */
INT_MAX);
}
else {
is_inside = base->object->id.tag & LIB_TAG_DOIT ?
(ED_view3d_project_float_global(vc->region,
base->object->object_to_world[3],
region_co,
V3D_PROJ_TEST_CLIP_DEFAULT) ==
V3D_PROJ_RET_OK) &&
len_squared_v2v2(mval_fl, region_co) <=
circle_data[2] * circle_data[2] :
false;
}
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
ED_object_base_select(base, sel_op_result ? BA_SELECT : BA_DESELECT);
changed = true;
}
}
}
finally:
MEM_freeN(buffer);
if (changed) {
DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(vc->C, NC_SCENE | ND_OB_SELECT, vc->scene);
}
}
return changed;
}
@ -1047,7 +1230,7 @@ static bool do_lasso_select_mesh(ViewContext *vc,
BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
int edge_style, face_style;
if (U.drag_select_mesh_control & USER_DRAG_SELECT_MESH_TOOLSETTING) {
if (U.drag_select_control & USER_DRAG_SELECT_TOOLSETTING) {
if (ts->lasso_drag_direction > 1) {
if (ts->lasso_drag_direction == 2) {
if (ts->lasso_direction_upright) {
@ -1093,7 +1276,12 @@ static bool do_lasso_select_mesh(ViewContext *vc,
GPU_matrix_set(vc->rv3d->viewmat);
const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d);
const int select_through_int = RNA_enum_get(op->ptr, "select_through");
const bool select_through = U.drag_select_control & USER_DRAG_SELECT_KEYMAP ?
select_through_int > 2 :
ts->select_through && ts->select_through_edit &&
ts->select_through_lasso;
const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d) && !select_through;
EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data);
if (use_zbuf) {
@ -1631,7 +1819,7 @@ static bool view3d_lasso_select(bContext *C,
}
}
else {
changed_multi |= do_lasso_select_objects(vc, mcoords, mcoords_len, sel_op);
changed_multi |= do_lasso_select_objects(vc, mcoords, mcoords_len, sel_op, op, NULL);
if (changed_multi) {
ED_outliner_select_sync_from_object_tag(C);
}
@ -2439,40 +2627,6 @@ static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
return hits;
}
/**
* Compare result of 'GPU_select': 'GPUSelectResult',
* Needed for stable sorting, so cycling through all items near the cursor behaves predictably.
*/
static int gpu_select_buffer_depth_id_cmp(const void *sel_a_p, const void *sel_b_p)
{
GPUSelectResult *a = (GPUSelectResult *)sel_a_p;
GPUSelectResult *b = (GPUSelectResult *)sel_b_p;
if (a->depth < b->depth) {
return -1;
}
if (a->depth > b->depth) {
return 1;
}
/* Depths match, sort by id. */
uint sel_a = a->id;
uint sel_b = b->id;
#ifdef __BIG_ENDIAN__
BLI_endian_switch_uint32(&sel_a);
BLI_endian_switch_uint32(&sel_b);
#endif
if (sel_a < sel_b) {
return -1;
}
if (sel_a > sel_b) {
return 1;
}
return 0;
}
/**
* \param has_bones: When true, skip non-bone hits, also allow bases to be used
* that are visible but not select-able,
@ -3919,7 +4073,7 @@ static bool do_mesh_box_select(ViewContext *vc,
ToolSettings *ts = vc->scene->toolsettings;
int edge_style, face_style;
if (U.drag_select_mesh_control & USER_DRAG_SELECT_MESH_TOOLSETTING) {
if (U.drag_select_control & USER_DRAG_SELECT_TOOLSETTING) {
if (ts->box_drag_direction > 1) {
if (ts->box_drag_direction == 2) {
if (ts->box_direction_upright) {
@ -3964,7 +4118,12 @@ static bool do_mesh_box_select(ViewContext *vc,
GPU_matrix_set(vc->rv3d->viewmat);
const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d);
const int select_through_int = RNA_enum_get(op->ptr, "select_through");
const bool select_through = U.drag_select_control & USER_DRAG_SELECT_KEYMAP ?
select_through_int > 2 :
ts->select_through && ts->select_through_edit &&
ts->select_through_box;
const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d) && !select_through;
EditSelectBuf_Cache *esel = static_cast<EditSelectBuf_Cache *>(wm_userdata->data);
if (use_zbuf) {
@ -4199,18 +4358,32 @@ static int opengl_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_
return 0;
}
static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op)
static bool do_object_box_select(
bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op, wmOperator *op)
{
View3D *v3d = vc->v3d;
int totobj = MAXPICKELEMS; /* XXX solve later */
ToolSettings *ts = vc->scene->toolsettings;
/* Selection buffer has bones potentially too, so we add #MAXPICKELEMS. */
GPUSelectResult *buffer = static_cast<GPUSelectResult *>(
MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(GPUSelectResult), __func__));
const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene,
vc->obact);
const int hits = view3d_opengl_select(
vc, buffer, (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
const int select_through_int = RNA_enum_get(op->ptr, "select_through");
const bool select_through = U.drag_select_control & USER_DRAG_SELECT_KEYMAP ?
select_through_int == 2 || select_through_int == 8 :
ts->select_through && ts->select_through_object &&
ts->select_through_box;
int hits = 0;
if (XRAY_FLAG_ENABLED(vc->v3d) || select_through) {
hits = view3d_opengl_select(
vc, buffer, (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
}
else {
hits = view3d_opengl_select(
vc, buffer, (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_PICK_NEAREST, select_filter);
}
BKE_view_layer_synced_ensure(vc->scene, vc->view_layer);
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(vc->view_layer)) {
base->object->id.tag &= ~LIB_TAG_DOIT;
@ -4452,7 +4625,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
}
}
else { /* object mode with none active */
changed_multi = do_object_box_select(C, &vc, &rect, sel_op);
changed_multi = do_object_box_select(C, &vc, &rect, sel_op, op);
if (changed_multi) {
ED_outliner_select_sync_from_object_tag(C);
}
@ -4660,7 +4833,7 @@ static bool mesh_circle_select(ViewContext *vc,
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
int edge_style, face_style;
if (U.drag_select_mesh_control & USER_DRAG_SELECT_MESH_TOOLSETTING) {
if (U.drag_select_control & USER_DRAG_SELECT_TOOLSETTING) {
edge_style = ts->circle_edge;
face_style = ts->circle_face;
}
@ -4671,7 +4844,12 @@ static bool mesh_circle_select(ViewContext *vc,
view3d_userdata_circleselect_init(&data, vc, select, mval, rad, edge_style, face_style);
const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d);
const int select_through_int = RNA_enum_get(op->ptr, "select_through");
const bool select_through = U.drag_select_control & USER_DRAG_SELECT_KEYMAP ?
select_through_int > 2 :
ts->select_through && ts->select_through_edit &&
ts->select_through_circle;
const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d) && !select_through;
if (use_zbuf) {
if (wm_userdata->data == nullptr) {
@ -5399,9 +5577,17 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
const eSelectOp sel_op = ED_select_op_modal(
static_cast<eSelectOp>(RNA_enum_get(op->ptr, "mode")), WM_gesture_is_modal_first(gesture));
ED_view3d_viewcontext_init(C, &vc, depsgraph);
ToolSettings *ts = vc.scene->toolsettings;
const int select_through_int = RNA_enum_get(op->ptr, "select_through");
const bool select_through_object = U.drag_select_control & USER_DRAG_SELECT_KEYMAP ?
select_through_int == 2 || select_through_int == 8 :
ts->select_through && ts->select_through_object &&
ts->select_through_circle;
if (!select_through_object) {
BKE_object_update_select_id(CTX_data_main(C));
}
Object *obact = vc.obact;
Object *obedit = vc.obedit;
@ -5447,11 +5633,17 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
else {
if (object_circle_select(&vc, sel_op, mval, float(radius))) {
DEG_id_tag_update(&vc.scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene);
if (select_through_object) {
if (object_circle_select(&vc, sel_op, mval, float(radius))) {
DEG_id_tag_update(&vc.scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene);
ED_outliner_select_sync_from_object_tag(C);
ED_outliner_select_sync_from_object_tag(C);
}
}
else {
int circle_data[3] = {mval[0], mval[1], radius};
do_lasso_select_objects(&vc, NULL, NULL, sel_op, op, circle_data);
}
}

View File

@ -392,6 +392,19 @@
.lasso_face_down = 1, \
.circle_edge = 2, \
.circle_face = 1, \
\
/* X-Ray */ \
.xray_button = true, \
.auto_xray_object = true, \
.auto_xray_edit = true, \
.auto_xray_box = true, \
.auto_xray_lasso = true, \
.auto_xray_circle = true, \
.select_through = true, \
.select_through_object = true, \
.select_through_box = true, \
.select_through_lasso = true, \
.select_through_circle = true, \
}
/* clang-format off */

View File

@ -1557,7 +1557,28 @@ typedef struct ToolSettings {
char gpencil_v3d_align;
/** General 2D Editor. */
char gpencil_v2d_align;
char _pad0[2];
/* Give the UI an empty prop to expand formatting */
char ui_prop;
/* X-Ray Options */
char xray_button;
char auto_xray;
char auto_xray_button;
char auto_xray_reset;
char auto_xray_object;
char auto_xray_edit;
char auto_xray_box;
char auto_xray_lasso;
char auto_xray_circle;
char select_through;
char select_through_button;
char select_through_object;
char select_through_edit;
char select_through_box;
char select_through_lasso;
char select_through_circle;
char _pad0[1];
/* Annotations. */
/** Stroke placement settings - 3D View. */
@ -2381,6 +2402,22 @@ enum {
MESH_DIRECTION_UP_DOWN = (1 << 2),
};
/** #ToolSettings.auto_xray_mode */
enum {
AUTO_XRAY_DISABLE = (1 << 0),
AUTO_XRAY_OBJECT = (1 << 1),
AUTO_XRAY_EDIT = (1 << 2),
AUTO_XRAY_BOTH = (1 << 3),
};
/** #ToolSettings.select_through_mode */
enum {
SELECT_THROUGH_DISABLE = (1 << 0),
SELECT_THROUGH_OBJECT = (1 << 1),
SELECT_THROUGH_EDIT = (1 << 2),
SELECT_THROUGH_BOTH = (1 << 3),
};
/** #ToolSettings.selectmode */
#define SCE_SELECT_VERTEX (1 << 0) /* for mesh */
#define SCE_SELECT_EDGE (1 << 1)

View File

@ -843,7 +843,7 @@ typedef struct UserDef {
/** Keymap click-drag direction style. */
char click_drag_direction;
/** Box, lasso, and circle select mesh control style. */
char drag_select_mesh_control;
char drag_select_control;
char _pad7[2];
/** Private, defaults to 20 for 72 DPI setting. */
@ -1164,11 +1164,11 @@ typedef enum eUserpref_Click_Drag_Direction {
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.drag_select_control_types */
typedef enum eUserpref_Drag_Select_Control {
USER_DRAG_SELECT_TOOLSETTING = 0,
USER_DRAG_SELECT_KEYMAP = 1,
} eUserpref_Drag_Select_Control;
/** #UserDef.app_flag */
typedef enum eUserpref_APP_Flag {

View File

@ -3130,11 +3130,11 @@ static void rna_def_tool_settings(BlenderRNA *brna)
/* 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");
RNA_def_property_ui_text(prop, "Mesh Drag Direction", "Click-drag direction style for box select");
prop = RNA_def_property(srna, "lasso_drag_direction", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, mesh_drag_direction_items);
RNA_def_property_ui_text(prop, "Lasso Direction", "Click-drag direction style for lasso select");
RNA_def_property_ui_text(prop, "Mesh Drag Direction", "Click-drag direction style for lasso select");
prop = RNA_def_property(srna, "box_direction_upright", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "box_direction_upright", 0);
@ -3904,6 +3904,103 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Normal Vector", "Normal Vector used to copy, add or multiply");
RNA_def_property_ui_range(prop, -10000.0, 10000.0, 1, 3);
/* UI prop helper, so you can use a heading without a real property or operator on the same line */
prop = RNA_def_property(srna, "ui_prop", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "ui_prop", 0);
RNA_def_property_ui_text(prop, "UI Prop", "");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
/* X-Ray header button */
prop = RNA_def_property(srna, "xray_button", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "xray_button", 0);
RNA_def_property_ui_text(
prop, "X-Ray Button", "Show button for X-Ray in viewport header");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
/* Auto X-Ray */
prop = RNA_def_property(srna, "auto_xray", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray", "Transparent scene display during drag select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "auto_xray_button", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray_button", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray Button", "Show button for automatic X-Ray in viewport header");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "auto_xray_reset", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray_reset", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray Reset", "Helper that turns xray off for autoxray");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "auto_xray_object", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray_object", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray Object", "Automatic X-Ray in object mode");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "auto_xray_edit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray_edit", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray Edit", "Automatic X-Ray in edit mode");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "auto_xray_box", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray_box", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray Box", "Transparent scene display during box select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "auto_xray_lasso", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray_lasso", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray Lasso", "Transparent scene display during lasso select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "auto_xray_circle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "auto_xray_circle", 0);
RNA_def_property_ui_text(prop, "Auto X-Ray Circle", "Transparent scene display during circle select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
/* Select Through */
prop = RNA_def_property(srna, "select_through", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_through", 0);
RNA_def_property_ui_text(
prop, "Select Through", "Select occluded objects and mesh elements with drag select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "select_through_button", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_through_button", 0);
RNA_def_property_ui_text(
prop, "Select Through Button", "Show button for select through in viewport header");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "select_through_object", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_through_object", 0);
RNA_def_property_ui_text(prop, "Select Through Object", "Select through in object mode");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "select_through_edit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_through_edit", 0);
RNA_def_property_ui_text(prop, "Select Through Edit", "Select through in edit mode");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "select_through_box", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_through_box", 0);
RNA_def_property_ui_text(
prop, "Select Through Box", "Select occluded objects and mesh elements with box select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "select_through_lasso", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_through_lasso", 0);
RNA_def_property_ui_text(prop,
"Select Through Lasso",
"Select occluded objects and mesh elements with lasso select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "select_through_circle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "select_through_circle", 0);
RNA_def_property_ui_text(prop,
"Select Through Circle",
"Select occluded objects and mesh elements with circle select");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
/* Unified Paint Settings */
prop = RNA_def_property(srna, "unified_paint_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);

View File

@ -5785,17 +5785,17 @@ static void rna_def_userdef_input(BlenderRNA *brna)
{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",
static const EnumPropertyItem drag_select_control_types[] = {
{USER_DRAG_SELECT_TOOLSETTING,
"USER_DRAG_TOOLSETTING",
0,
"Toolsetting",
"Use toolsettings to control mesh selection style for box, lasso, and circle"},
"Use toolsettings to control selection options for box, lasso, and circle select"},
{USER_DRAG_SELECT_KEYMAP,
"USER_DRAG_KEYMAP",
0,
"Keymap",
"Use the keymap to control selection options for box, lasso, and circle selection"},
{0, NULL, 0, NULL, NULL},
};
@ -5910,11 +5910,11 @@ static void rna_def_userdef_input(BlenderRNA *brna)
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);
prop = RNA_def_property(srna, "drag_select_control", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, drag_select_control_types);
RNA_def_property_ui_text(prop,
"Mesh Drag Select Control",
"Use either the keymap or toolsettings to control edge and face selection style "
"Drag Select Control",
"Use either the keymap or toolsettings to control selection options "
"for box, lasso, and circle select");
prop = RNA_def_property(srna, "use_numeric_input_advanced", PROP_BOOLEAN, PROP_NONE);

View File

@ -273,7 +273,7 @@ int WM_event_drag_direction(const wmEvent *event, ToolSettings *ts)
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;
bool drag_select_toolsetting = U.drag_select_control & USER_DRAG_SELECT_TOOLSETTING;
int theta = left_right ?
round_fl_to_int(atan2f(0.0f, (float)delta[0]) / (float)M_PI) :
up_down ?

View File

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

View File

@ -456,12 +456,44 @@ void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bo
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem auto_xray_items[] = {
{AUTO_XRAY_DISABLE, "AUTO_XRAY_DISABLE", 0, "Disable", "Disable Automatic X-Ray"},
{AUTO_XRAY_OBJECT,
"AUTO_XRAY_OBJECT",
0,
"Object",
"Enable X-Ray during box select in object mode"},
{AUTO_XRAY_EDIT, "AUTO_XRAY_EDIT", 0, "Edit", "Enable X-Ray during box select in edit mode"},
{AUTO_XRAY_BOTH,
"AUTO_XRAY_BOTH",
0,
"Both",
"Enable X-Ray during box select in object and edit mode"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem select_through_items[] = {
{SELECT_THROUGH_OBJECT, "SELECT_THROUGH_OBJECT", 0, "Object", "Select occluded objects"},
{SELECT_THROUGH_EDIT, "SELECT_THROUGH_EDIT", 0, "Edit", "Select occluded mesh elements"},
{SELECT_THROUGH_BOTH,
"SELECT_THROUGH_BOTH",
0,
"Both",
"Select occluded objects and mesh elements"},
{SELECT_THROUGH_DISABLE, "SELECT_THROUGH_DISABLE", 0, "Disable", "Disable Select Through"},
{0, NULL, 0, NULL, NULL},
};
WM_operator_properties_border(ot);
prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "auto_xray", auto_xray_items, 0, "Automatic X-Ray", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "select_through", select_through_items, 0, "Select Through", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
if (deselect) {
prop = RNA_def_boolean(
@ -614,10 +646,49 @@ void WM_operator_properties_gesture_lasso(wmOperatorType *ot)
"Select edges that are fully inside the selection area"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem auto_xray_items[] = {
{AUTO_XRAY_DISABLE, "AUTO_XRAY_DISABLE", 0, "Disable", "Disable Automatic X-Ray"},
{AUTO_XRAY_OBJECT,
"AUTO_XRAY_OBJECT",
0,
"Object",
"Enable X-Ray during lasso select in object mode"},
{AUTO_XRAY_EDIT,
"AUTO_XRAY_EDIT",
0,
"Edit",
"Enable X-Ray during lasso select in edit mode"},
{AUTO_XRAY_BOTH,
"AUTO_XRAY_BOTH",
0,
"Both",
"Enable X-Ray during lasso select in object and edit mode"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem select_through_items[] = {
{SELECT_THROUGH_OBJECT, "SELECT_THROUGH_OBJECT", 0, "Object", "Select occluded objects"},
{SELECT_THROUGH_EDIT, "SELECT_THROUGH_EDIT", 0, "Edit", "Select occluded mesh elements"},
{SELECT_THROUGH_BOTH,
"SELECT_THROUGH_BOTH",
0,
"Both",
"Select occluded objects and mesh elements"},
{SELECT_THROUGH_DISABLE, "SELECT_THROUGH_DISABLE", 0, "Disable", "Disable Select Through"},
{0, NULL, 0, NULL, NULL},
};
WM_operator_properties_border(ot);
prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "auto_xray", auto_xray_items, 0, "Automatic X-Ray", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "select_through", select_through_items, 0, "Select Through", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
@ -695,6 +766,42 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot)
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem auto_xray_items[] = {
{AUTO_XRAY_DISABLE, "AUTO_XRAY_DISABLE", 0, "Disable", "Disable Automatic X-Ray"},
{AUTO_XRAY_OBJECT,
"AUTO_XRAY_OBJECT",
0,
"Object",
"Enable X-Ray during circle select in object mode"},
{AUTO_XRAY_EDIT, "AUTO_XRAY_EDIT", 0, "Edit", "Enable X-Ray during circle select in edit mode"},
{AUTO_XRAY_BOTH,
"AUTO_XRAY_BOTH",
0,
"Both",
"Enable X-Ray during circle select in object and edit mode"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem select_through_items[] = {
{SELECT_THROUGH_OBJECT,
"SELECT_THROUGH_OBJECT",
0,
"Object",
"Select occluded objects"},
{SELECT_THROUGH_EDIT,
"SELECT_THROUGH_EDIT",
0,
"Edit",
"Select occluded mesh elements"},
{SELECT_THROUGH_BOTH,
"SELECT_THROUGH_BOTH",
0,
"Both",
"Select occluded objects and mesh elements"},
{SELECT_THROUGH_DISABLE, "SELECT_THROUGH_DISABLE", 0, "Disable", "Disable Select Through"},
{0, NULL, 0, NULL, NULL},
};
prop = RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
@ -708,6 +815,10 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge Select", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "auto_xray", auto_xray_items, 0, "Automatic X-Ray", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "select_through", select_through_items, 0, "Select Through", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
void WM_operator_properties_mouse_select(wmOperatorType *ot)