WIP: Custom build, mostly selection options #105712
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
@ -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(
|
||||
®ion->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;
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
@ -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", "");
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user