Compare commits
47 Commits
refactor-m
...
retopo_tra
Author | SHA1 | Date | |
---|---|---|---|
6485941d7a | |||
eee25a175a | |||
4f33dcff78 | |||
fd39da1df6 | |||
dbdab681cf | |||
66c6cf0d71 | |||
8ab91edd91 | |||
3ac5a52d6e | |||
60a8ade18a | |||
d57ce54e30 | |||
a735b2c335 | |||
73aa6b8185 | |||
698efac59e | |||
afe11eff8a | |||
4ebe1c3e69 | |||
887713d08d | |||
cc761cdae6 | |||
a2938c86ca | |||
a66e20f984 | |||
db317f070e | |||
7502bc583c | |||
089870ab3a | |||
298711d158 | |||
8d284d4854 | |||
9e88cfbe0c | |||
405bbb06f2 | |||
ed8f2bbf5c | |||
ddce8e9ea3 | |||
1b9e31f004 | |||
8791762af0 | |||
8d813f2eed | |||
af29d103c6 | |||
ca336c600b | |||
491ada0a38 | |||
62f813754d | |||
cbeb70bdae | |||
139a651434 | |||
add307d429 | |||
59e6dc8a93 | |||
6410fe0492 | |||
b818008ddf | |||
af9c969768 | |||
0b25d923e5 | |||
a863ba191d | |||
f606393522 | |||
f8b389b121 | |||
![]() |
59adee83e7 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -619,7 +619,11 @@ class VIEW3D_HT_header(Header):
|
|||||||
if show_snap:
|
if show_snap:
|
||||||
snap_items = bpy.types.ToolSettings.bl_rna.properties["snap_elements"].enum_items
|
snap_items = bpy.types.ToolSettings.bl_rna.properties["snap_elements"].enum_items
|
||||||
snap_elements = tool_settings.snap_elements
|
snap_elements = tool_settings.snap_elements
|
||||||
if len(snap_elements) == 1:
|
active_tool = context.workspace.tools.from_space_view3d_mode(context.mode, create=False)
|
||||||
|
if active_tool.idname.startswith('retopology'):
|
||||||
|
text = "Tool"
|
||||||
|
icon = 'NONE'
|
||||||
|
elif len(snap_elements) == 1:
|
||||||
text = ""
|
text = ""
|
||||||
for elem in snap_elements:
|
for elem in snap_elements:
|
||||||
icon = snap_items[elem].icon
|
icon = snap_items[elem].icon
|
||||||
@@ -632,6 +636,14 @@ class VIEW3D_HT_header(Header):
|
|||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
row.prop(tool_settings, "use_snap", text="")
|
row.prop(tool_settings, "use_snap", text="")
|
||||||
|
|
||||||
|
if object_mode == 'EDIT' and obj.type == 'MESH':
|
||||||
|
row.prop(
|
||||||
|
tool_settings,
|
||||||
|
"use_snap_retopology_mode",
|
||||||
|
text="",
|
||||||
|
icon='MOD_MESHDEFORM',
|
||||||
|
)
|
||||||
|
|
||||||
sub = row.row(align=True)
|
sub = row.row(align=True)
|
||||||
sub.popover(
|
sub.popover(
|
||||||
panel="VIEW3D_PT_snapping",
|
panel="VIEW3D_PT_snapping",
|
||||||
@@ -6808,73 +6820,106 @@ class VIEW3D_PT_snapping(Panel):
|
|||||||
tool_settings = context.tool_settings
|
tool_settings = context.tool_settings
|
||||||
snap_elements = tool_settings.snap_elements
|
snap_elements = tool_settings.snap_elements
|
||||||
obj = context.active_object
|
obj = context.active_object
|
||||||
object_mode = 'OBJECT' if obj is None else obj.mode
|
object_mode = obj.mode if obj else 'OBJECT'
|
||||||
|
show_target_options = object_mode == 'EDIT' and obj.type not in {'LATTICE', 'META', 'FONT'}
|
||||||
|
multiple_objects = len(context.objects_in_mode) > 1
|
||||||
|
retopo_mode = object_mode == 'EDIT' and tool_settings.use_snap_retopology_mode
|
||||||
|
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
col = layout.column()
|
col = layout.column()
|
||||||
col.label(text="Snap To")
|
|
||||||
col.prop(tool_settings, "snap_elements", expand=True)
|
|
||||||
|
|
||||||
col.separator()
|
if show_target_options:
|
||||||
if 'INCREMENT' in snap_elements:
|
col.prop(
|
||||||
col.prop(tool_settings, "use_snap_grid_absolute")
|
tool_settings,
|
||||||
|
"use_snap_retopology_mode",
|
||||||
|
text="Retopology Mode",
|
||||||
|
# icon='MOD_MESHDEFORM',
|
||||||
|
)
|
||||||
|
|
||||||
|
if not retopo_mode:
|
||||||
|
col_snapto = col.column(align=True, heading="Snap To")
|
||||||
|
col_snapto.prop(tool_settings, "snap_elements", expand=True)
|
||||||
|
else:
|
||||||
|
col_snapto_edited = col.column(align=True, heading="Snap To Edited")
|
||||||
|
col_snapto_edited.prop_enum(tool_settings, "snap_elements", 'VERTEX')
|
||||||
|
col_snapto_edited.prop_enum(tool_settings, "snap_elements", 'EDGE')
|
||||||
|
col_snapto_edited.prop_enum(tool_settings, "snap_elements", 'EDGE_MIDPOINT')
|
||||||
|
col_snapto_edited.prop_enum(tool_settings, "snap_elements", 'EDGE_PERPENDICULAR')
|
||||||
|
|
||||||
|
col_snapto_nonedited = col.column(align=True, heading="Snap To Non-Edited")
|
||||||
|
col_snapto_nonedited.prop_enum(tool_settings, "snap_elements", 'FACE')
|
||||||
|
col_snapto_nonedited.prop_enum(tool_settings, "snap_elements", 'FACE_NEAREST')
|
||||||
|
# row = col_snapto_nonedited.row(align=True)
|
||||||
|
# row.enabled = False
|
||||||
|
# row.prop_enum(tool_settings, "snap_elements", 'FACE_NEAREST')
|
||||||
|
|
||||||
|
if not retopo_mode and snap_elements - {'INCREMENT', 'FACE_NEAREST'}:
|
||||||
|
col_snapwith = col.column(align=True)
|
||||||
|
col_snapwith.label(text='Snap With')
|
||||||
|
col_snapwith.row().prop(tool_settings, "snap_target", expand=True)
|
||||||
|
|
||||||
if snap_elements != {'INCREMENT'}:
|
if snap_elements != {'INCREMENT'}:
|
||||||
if snap_elements != {'FACE_NEAREST'}:
|
col_targetsel = col.column(align=True, heading="Target Selection")
|
||||||
col.label(text="Snap With")
|
if not retopo_mode and show_target_options:
|
||||||
row = col.row(align=True)
|
if not multiple_objects:
|
||||||
row.prop(tool_settings, "snap_target", expand=True)
|
col_targetsel.prop(
|
||||||
|
tool_settings,
|
||||||
if obj:
|
'use_snap_self',
|
||||||
col.label(text="Target Selection")
|
text="Include Edited",
|
||||||
col_targetsel = col.column(align=True)
|
# description='Snap onto edited objects (Edit Mode Only)',
|
||||||
if object_mode == 'EDIT' and obj.type not in {'LATTICE', 'META', 'FONT'}:
|
icon='EDITMODE_HLT',
|
||||||
|
)
|
||||||
|
else:
|
||||||
col_targetsel.prop(
|
col_targetsel.prop(
|
||||||
tool_settings,
|
tool_settings,
|
||||||
"use_snap_self",
|
"use_snap_self",
|
||||||
text="Include Active",
|
text="Include Active Edited",
|
||||||
|
# description='Snap onto active edited object (Edit Mode Only)',
|
||||||
icon='EDITMODE_HLT',
|
icon='EDITMODE_HLT',
|
||||||
)
|
)
|
||||||
col_targetsel.prop(
|
col_targetsel.prop(
|
||||||
tool_settings,
|
tool_settings,
|
||||||
"use_snap_edit",
|
"use_snap_edit",
|
||||||
text="Include Edited",
|
text="Include Other Edited",
|
||||||
|
# description='Snap onto non-active edited object(s) (Edit Mode Only)',
|
||||||
icon='OUTLINER_DATA_MESH',
|
icon='OUTLINER_DATA_MESH',
|
||||||
)
|
)
|
||||||
col_targetsel.prop(
|
|
||||||
tool_settings,
|
|
||||||
"use_snap_nonedit",
|
|
||||||
text="Include Non-Edited",
|
|
||||||
icon='OUTLINER_OB_MESH',
|
|
||||||
)
|
|
||||||
col_targetsel.prop(
|
col_targetsel.prop(
|
||||||
tool_settings,
|
tool_settings,
|
||||||
"use_snap_selectable",
|
"use_snap_nonedit",
|
||||||
text="Exclude Non-Selectable",
|
text="Include Non-Edited",
|
||||||
icon='RESTRICT_SELECT_OFF',
|
icon='OUTLINER_OB_MESH',
|
||||||
)
|
)
|
||||||
|
col_targetsel.prop(
|
||||||
|
tool_settings,
|
||||||
|
"use_snap_selectable_only",
|
||||||
|
text="Exclude Non-Selectable",
|
||||||
|
icon='RESTRICT_SELECT_OFF',
|
||||||
|
)
|
||||||
|
|
||||||
if object_mode in {'OBJECT', 'POSE', 'EDIT', 'WEIGHT_PAINT'}:
|
col_options = col.column(heading="Options")
|
||||||
col.prop(tool_settings, "use_snap_align_rotation")
|
if 'INCREMENT' in snap_elements:
|
||||||
|
col_options.prop(tool_settings, "use_snap_grid_absolute")
|
||||||
col.prop(tool_settings, "use_snap_backface_culling")
|
if snap_elements != {'INCREMENT'}:
|
||||||
|
# TODO(@gfxcoder): Does WEIGHT_PAINT have any snapping?
|
||||||
if 'FACE' in snap_elements:
|
if object_mode in {'OBJECT', 'POSE', 'EDIT', 'WEIGHT_PAINT'}:
|
||||||
col.prop(tool_settings, "use_snap_project")
|
col_options.prop(tool_settings, "use_snap_align_rotation")
|
||||||
|
if snap_elements != {'FACE_NEAREST'}:
|
||||||
|
col_options.prop(tool_settings, "use_snap_backface_culling")
|
||||||
|
if 'FACE' in snap_elements and not retopo_mode:
|
||||||
|
col_options.prop(tool_settings, "use_snap_project")
|
||||||
if 'FACE_NEAREST' in snap_elements:
|
if 'FACE_NEAREST' in snap_elements:
|
||||||
col.prop(tool_settings, 'use_snap_to_same_target')
|
col_options.prop(tool_settings, 'use_snap_to_same_target')
|
||||||
if object_mode == 'EDIT':
|
if object_mode == 'EDIT':
|
||||||
col.prop(tool_settings, 'snap_face_nearest_steps')
|
col_options.prop(tool_settings, 'snap_face_nearest_steps')
|
||||||
|
|
||||||
if 'VOLUME' in snap_elements:
|
if 'VOLUME' in snap_elements:
|
||||||
col.prop(tool_settings, "use_snap_peel_object")
|
col_options.prop(tool_settings, "use_snap_peel_object")
|
||||||
|
|
||||||
col.label(text="Affect")
|
if not retopo_mode:
|
||||||
row = col.row(align=True)
|
row = col.row(align=True, heading="Affect")
|
||||||
row.prop(tool_settings, "use_snap_translate", text="Move", toggle=True)
|
row.prop(tool_settings, "use_snap_translate", text="Move", toggle=True)
|
||||||
row.prop(tool_settings, "use_snap_rotate", text="Rotate", toggle=True)
|
row.prop(tool_settings, "use_snap_rotate", text="Rotate", toggle=True)
|
||||||
row.prop(tool_settings, "use_snap_scale", text="Scale", toggle=True)
|
row.prop(tool_settings, "use_snap_scale", text="Scale", toggle=True)
|
||||||
|
|
||||||
|
|
||||||
class VIEW3D_PT_proportional_edit(Panel):
|
class VIEW3D_PT_proportional_edit(Panel):
|
||||||
|
@@ -26,7 +26,6 @@ struct View3D;
|
|||||||
/* transform_snap_object.cc */
|
/* transform_snap_object.cc */
|
||||||
|
|
||||||
/* ED_transform_snap_object_*** API */
|
/* ED_transform_snap_object_*** API */
|
||||||
|
|
||||||
typedef enum eSnapEditType {
|
typedef enum eSnapEditType {
|
||||||
SNAP_GEOM_FINAL = 0,
|
SNAP_GEOM_FINAL = 0,
|
||||||
SNAP_GEOM_CAGE = 1,
|
SNAP_GEOM_CAGE = 1,
|
||||||
|
@@ -655,6 +655,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flags & P_SNAP) {
|
if (flags & P_SNAP) {
|
||||||
|
// TODO: rename `snap` to `use_snap`?
|
||||||
prop = RNA_def_boolean(ot->srna, "snap", false, "Use Snapping Options", "");
|
prop = RNA_def_boolean(ot->srna, "snap", false, "Use Snapping Options", "");
|
||||||
RNA_def_property_flag(prop, PROP_HIDDEN);
|
RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||||
|
|
||||||
@@ -686,6 +687,12 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
|
|||||||
prop = RNA_def_boolean(
|
prop = RNA_def_boolean(
|
||||||
ot->srna, "use_snap_selectable_only", false, "Target: Exclude Non-Selectable", "");
|
ot->srna, "use_snap_selectable_only", false, "Target: Exclude Non-Selectable", "");
|
||||||
RNA_def_property_flag(prop, PROP_HIDDEN);
|
RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||||
|
prop = RNA_def_boolean(ot->srna,
|
||||||
|
"use_snap_retopology_mode",
|
||||||
|
true,
|
||||||
|
"Target: Retopology Mode",
|
||||||
|
"Optimize snapping options for retopology work");
|
||||||
|
RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||||
|
|
||||||
/* Face Nearest options */
|
/* Face Nearest options */
|
||||||
prop = RNA_def_boolean(
|
prop = RNA_def_boolean(
|
||||||
|
@@ -128,11 +128,11 @@ bool activeSnap(const TransInfo *t)
|
|||||||
|
|
||||||
bool activeSnap_SnappingIndividual(const TransInfo *t)
|
bool activeSnap_SnappingIndividual(const TransInfo *t)
|
||||||
{
|
{
|
||||||
if (activeSnap(t) && t->tsnap.mode & SCE_SNAP_MODE_FACE_NEAREST) {
|
if (activeSnap(t) && (t->tsnap.mode & SCE_SNAP_MODE_FACE_NEAREST)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!t->tsnap.project) {
|
if ((t->tsnap.mode & SCE_SNAP_MODE_FACE_RAYCAST) && !t->tsnap.project) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,9 +168,22 @@ bool activeSnap_SnappingAsGroup(const TransInfo *t)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool useSnapRetopoMode(const TransInfo *t)
|
||||||
|
{
|
||||||
|
if (t->spacetype != SPACE_VIEW3D || t->obedit_type != OB_MESH) {
|
||||||
|
/* Not the correct context for retopology mode. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return t->settings->snap_flag & SCE_SNAP_RETOPOLOGY_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
bool transformModeUseSnap(const TransInfo *t)
|
bool transformModeUseSnap(const TransInfo *t)
|
||||||
{
|
{
|
||||||
ToolSettings *ts = t->settings;
|
ToolSettings *ts = t->settings;
|
||||||
|
if (useSnapRetopoMode(t)) {
|
||||||
|
/* Always use snap when retopology mode is enabled. */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (t->mode == TFM_TRANSLATION) {
|
if (t->mode == TFM_TRANSLATION) {
|
||||||
return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_TRANSLATE) != 0;
|
return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_TRANSLATE) != 0;
|
||||||
}
|
}
|
||||||
@@ -509,9 +522,13 @@ void applySnappingIndividual(TransInfo *t)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If both face ray-cast and face nearest methods are enabled, start with face ray-cast and
|
/* If both face raycast and face nearest methods are enabled, start with face raycast and
|
||||||
* fallback to face nearest ray-cast does not hit. */
|
* fallback to face nearest raycast does not hit. */
|
||||||
bool hit = applyFaceProject(t, tc, td);
|
bool hit = false;
|
||||||
|
if (t->tsnap.flag & SCE_SNAP_PROJECT) {
|
||||||
|
/* Only raycast in this function if projecting individual elements. */
|
||||||
|
hit = applyFaceProject(t, tc, td);
|
||||||
|
}
|
||||||
if (!hit) {
|
if (!hit) {
|
||||||
applyFaceNearest(t, tc, td);
|
applyFaceNearest(t, tc, td);
|
||||||
}
|
}
|
||||||
@@ -738,6 +755,7 @@ static eSnapTargetSelect snap_target_select_from_spacetype(TransInfo *t)
|
|||||||
bool use_snap_edit = (t->tsnap.target_select & SCE_SNAP_TARGET_NOT_EDITED) == 0;
|
bool use_snap_edit = (t->tsnap.target_select & SCE_SNAP_TARGET_NOT_EDITED) == 0;
|
||||||
bool use_snap_nonedit = (t->tsnap.target_select & SCE_SNAP_TARGET_NOT_NONEDITED) == 0;
|
bool use_snap_nonedit = (t->tsnap.target_select & SCE_SNAP_TARGET_NOT_NONEDITED) == 0;
|
||||||
bool use_snap_selectable_only = (t->tsnap.target_select & SCE_SNAP_TARGET_ONLY_SELECTABLE) != 0;
|
bool use_snap_selectable_only = (t->tsnap.target_select & SCE_SNAP_TARGET_ONLY_SELECTABLE) != 0;
|
||||||
|
// bool use_retopology_mode = (t->tsnap.target_select & SCE_SNAP_TARGET_RETOPOLOGY_MODE) != 0;
|
||||||
|
|
||||||
if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && !(t->options & CTX_CAMERA)) {
|
if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && !(t->options & CTX_CAMERA)) {
|
||||||
if (base_act && (base_act->object->mode & OB_MODE_PARTICLE_EDIT)) {
|
if (base_act && (base_act->object->mode & OB_MODE_PARTICLE_EDIT)) {
|
||||||
@@ -840,6 +858,25 @@ static void initSnappingMode(TransInfo *t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void initSnappingRetopoMode(TransInfo *t)
|
||||||
|
{
|
||||||
|
if (!useSnapRetopoMode(t)) {
|
||||||
|
/* Not using retopology mode. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable all possible targets. The targets will be filtered based on snap method. */
|
||||||
|
t->tsnap.source_select = SCE_SNAP_SOURCE_ACTIVE;
|
||||||
|
t->tsnap.targetSnap = TargetSnapActive;
|
||||||
|
t->tsnap.target_select &= ~(SCE_SNAP_TARGET_NOT_ACTIVE | SCE_SNAP_TARGET_NOT_EDITED |
|
||||||
|
SCE_SNAP_TARGET_NOT_NONEDITED);
|
||||||
|
t->tsnap.flag |= (SCE_SNAP_TO_INCLUDE_EDITED | SCE_SNAP_TO_INCLUDE_NONEDITED);
|
||||||
|
t->tsnap.flag &= ~(SCE_SNAP_NOT_TO_ACTIVE);
|
||||||
|
t->tsnap.mode &= ~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID | SCE_SNAP_MODE_VOLUME);
|
||||||
|
t->tsnap.project = true;
|
||||||
|
t->tsnap.flag |= SCE_SNAP_PROJECT;
|
||||||
|
}
|
||||||
|
|
||||||
void initSnapping(TransInfo *t, wmOperator *op)
|
void initSnapping(TransInfo *t, wmOperator *op)
|
||||||
{
|
{
|
||||||
ToolSettings *ts = t->settings;
|
ToolSettings *ts = t->settings;
|
||||||
@@ -912,12 +949,19 @@ void initSnapping(TransInfo *t, wmOperator *op)
|
|||||||
SCE_SNAP_TARGET_NOT_NONEDITED);
|
SCE_SNAP_TARGET_NOT_NONEDITED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((prop = RNA_struct_find_property(op->ptr, "use_snap_selectable")) &&
|
if ((prop = RNA_struct_find_property(op->ptr, "use_snap_selectable_only")) &&
|
||||||
RNA_property_is_set(op->ptr, prop)) {
|
RNA_property_is_set(op->ptr, prop)) {
|
||||||
SET_FLAG_FROM_TEST(t->tsnap.target_select,
|
SET_FLAG_FROM_TEST(t->tsnap.target_select,
|
||||||
RNA_property_boolean_get(op->ptr, prop),
|
RNA_property_boolean_get(op->ptr, prop),
|
||||||
SCE_SNAP_TARGET_ONLY_SELECTABLE);
|
SCE_SNAP_TARGET_ONLY_SELECTABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((prop = RNA_struct_find_property(op->ptr, "use_snap_retopology_mode")) &&
|
||||||
|
RNA_property_is_set(op->ptr, prop)) {
|
||||||
|
SET_FLAG_FROM_TEST(t->tsnap.target_select,
|
||||||
|
RNA_property_boolean_get(op->ptr, prop),
|
||||||
|
SCE_SNAP_TARGET_RETOPOLOGY_MODE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* use scene defaults only when transform is modal */
|
/* use scene defaults only when transform is modal */
|
||||||
@@ -926,9 +970,10 @@ void initSnapping(TransInfo *t, wmOperator *op)
|
|||||||
t->modifiers |= MOD_SNAP;
|
t->modifiers |= MOD_SNAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t->tsnap.target_select = SCE_SNAP_TARGET_ALL;
|
||||||
t->tsnap.align = ((t->tsnap.flag & SCE_SNAP_ROTATE) != 0);
|
t->tsnap.align = ((t->tsnap.flag & SCE_SNAP_ROTATE) != 0);
|
||||||
t->tsnap.project = ((t->tsnap.flag & SCE_SNAP_PROJECT) != 0);
|
t->tsnap.project = ((t->tsnap.flag & SCE_SNAP_PROJECT) != 0);
|
||||||
t->tsnap.peel = ((t->tsnap.flag & SCE_SNAP_PROJECT) != 0);
|
t->tsnap.peel = ((t->tsnap.flag & SCE_SNAP_PEEL_OBJECT) != 0);
|
||||||
SET_FLAG_FROM_TEST(t->tsnap.target_select,
|
SET_FLAG_FROM_TEST(t->tsnap.target_select,
|
||||||
(ts->snap_flag & SCE_SNAP_NOT_TO_ACTIVE),
|
(ts->snap_flag & SCE_SNAP_NOT_TO_ACTIVE),
|
||||||
SCE_SNAP_TARGET_NOT_ACTIVE);
|
SCE_SNAP_TARGET_NOT_ACTIVE);
|
||||||
@@ -941,11 +986,15 @@ void initSnapping(TransInfo *t, wmOperator *op)
|
|||||||
SET_FLAG_FROM_TEST(t->tsnap.target_select,
|
SET_FLAG_FROM_TEST(t->tsnap.target_select,
|
||||||
(ts->snap_flag & SCE_SNAP_TO_ONLY_SELECTABLE),
|
(ts->snap_flag & SCE_SNAP_TO_ONLY_SELECTABLE),
|
||||||
SCE_SNAP_TARGET_ONLY_SELECTABLE);
|
SCE_SNAP_TARGET_ONLY_SELECTABLE);
|
||||||
|
SET_FLAG_FROM_TEST(t->tsnap.target_select,
|
||||||
|
(t->settings->snap_flag & SCE_SNAP_RETOPOLOGY_MODE),
|
||||||
|
SCE_SNAP_TARGET_RETOPOLOGY_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
t->tsnap.source_select = snap_source;
|
t->tsnap.source_select = snap_source;
|
||||||
|
|
||||||
initSnappingMode(t);
|
initSnappingMode(t);
|
||||||
|
initSnappingRetopoMode(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeSnapping(TransInfo *t)
|
void freeSnapping(TransInfo *t)
|
||||||
@@ -1446,16 +1495,28 @@ eSnapMode snapObjectsTransform(
|
|||||||
TransInfo *t, const float mval[2], float *dist_px, float r_loc[3], float r_no[3])
|
TransInfo *t, const float mval[2], float *dist_px, float r_loc[3], float r_no[3])
|
||||||
{
|
{
|
||||||
float *target = (t->tsnap.status & TARGET_INIT) ? t->tsnap.snapTarget : t->center_global;
|
float *target = (t->tsnap.status & TARGET_INIT) ? t->tsnap.snapTarget : t->center_global;
|
||||||
|
|
||||||
|
// filter mode to group snapping modes
|
||||||
|
eSnapMode mode = t->tsnap.mode;
|
||||||
|
mode &= ~(SCE_SNAP_MODE_FACE_NEAREST);
|
||||||
|
if (t->tsnap.flag & SCE_SNAP_PROJECT) {
|
||||||
|
mode &= ~(SCE_SNAP_MODE_FACE_RAYCAST);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool use_retopo_mode = (t->tsnap.target_select & SCE_SNAP_TARGET_RETOPOLOGY_MODE);
|
||||||
|
const bool face_raycast_only = t->settings->snap_mode == SCE_SNAP_MODE_FACE_RAYCAST;
|
||||||
|
const bool use_occlusion_test = use_retopo_mode || !face_raycast_only;
|
||||||
|
|
||||||
return ED_transform_snap_object_project_view3d(
|
return ED_transform_snap_object_project_view3d(
|
||||||
t->tsnap.object_context,
|
t->tsnap.object_context,
|
||||||
t->depsgraph,
|
t->depsgraph,
|
||||||
t->region,
|
t->region,
|
||||||
t->view,
|
t->view,
|
||||||
t->tsnap.mode,
|
mode,
|
||||||
&(const struct SnapObjectParams){
|
&(const struct SnapObjectParams){
|
||||||
.snap_target_select = t->tsnap.target_select,
|
.snap_target_select = t->tsnap.target_select,
|
||||||
.edit_mode_type = (t->flag & T_EDIT) != 0 ? SNAP_GEOM_EDIT : SNAP_GEOM_FINAL,
|
.edit_mode_type = (t->flag & T_EDIT) != 0 ? SNAP_GEOM_EDIT : SNAP_GEOM_FINAL,
|
||||||
.use_occlusion_test = t->settings->snap_mode != SCE_SNAP_MODE_FACE_RAYCAST,
|
.use_occlusion_test = use_occlusion_test,
|
||||||
.use_backface_culling = t->tsnap.use_backface_culling,
|
.use_backface_culling = t->tsnap.use_backface_culling,
|
||||||
},
|
},
|
||||||
NULL,
|
NULL,
|
||||||
|
@@ -1025,6 +1025,12 @@ static void raycast_obj_fn(SnapObjectContext *sctx,
|
|||||||
/* read/write args */
|
/* read/write args */
|
||||||
float *ray_depth = dt->ray_depth;
|
float *ray_depth = dt->ray_depth;
|
||||||
|
|
||||||
|
const bool use_retopo_mode = params->snap_target_select & SCE_SNAP_TARGET_RETOPOLOGY_MODE;
|
||||||
|
const bool is_object_edited = BKE_object_is_in_editmode(ob_eval);
|
||||||
|
if (use_retopo_mode && is_object_edited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
if (use_occlusion_test) {
|
if (use_occlusion_test) {
|
||||||
if (ELEM(ob_eval->dt, OB_BOUNDBOX, OB_WIRE)) {
|
if (ELEM(ob_eval->dt, OB_BOUNDBOX, OB_WIRE)) {
|
||||||
@@ -1261,7 +1267,7 @@ static bool nearest_world_tree(SnapObjectContext *UNUSED(sctx),
|
|||||||
|
|
||||||
/* compute offset between init co and prev co in local space */
|
/* compute offset between init co and prev co in local space */
|
||||||
float init_co_local[3], curr_co_local[3];
|
float init_co_local[3], curr_co_local[3];
|
||||||
float delta_local[3];
|
float delta_local[3], delta_step[3];
|
||||||
mul_v3_m4v3(init_co_local, imat, init_co);
|
mul_v3_m4v3(init_co_local, imat, init_co);
|
||||||
mul_v3_m4v3(curr_co_local, imat, curr_co);
|
mul_v3_m4v3(curr_co_local, imat, curr_co);
|
||||||
sub_v3_v3v3(delta_local, curr_co_local, init_co_local);
|
sub_v3_v3v3(delta_local, curr_co_local, init_co_local);
|
||||||
@@ -1273,8 +1279,8 @@ static bool nearest_world_tree(SnapObjectContext *UNUSED(sctx),
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* NOTE: when `params->face_nearest_steps == 1`, the return variables of function below contain
|
/* NOTE: when `params->face_nearest_steps == 1`, the return variables of function below contain
|
||||||
* the answer. We could return immediately after updating r_loc, r_no, r_index, but that would
|
* the answer. We could return immediately after updating 'r_loc', 'r_no', 'r_index', but that
|
||||||
* also complicate the code. Foregoing slight optimization for code clarity. */
|
* would also complicate the code. Foregoing slight optimization for code clarity. */
|
||||||
nearest_world_tree_co(
|
nearest_world_tree_co(
|
||||||
tree, nearest_cb, treedata, curr_co_local, nullptr, nullptr, nullptr, &dist_sq);
|
tree, nearest_cb, treedata, curr_co_local, nullptr, nullptr, nullptr, &dist_sq);
|
||||||
}
|
}
|
||||||
@@ -1284,8 +1290,9 @@ static bool nearest_world_tree(SnapObjectContext *UNUSED(sctx),
|
|||||||
*r_dist_sq = dist_sq;
|
*r_dist_sq = dist_sq;
|
||||||
|
|
||||||
/* scale to make `snap_face_nearest_steps` steps */
|
/* scale to make `snap_face_nearest_steps` steps */
|
||||||
float step_scale_factor = 1.0f / max_ff(1.0f, (float)params->face_nearest_steps);
|
int steps = max_ii(1, params->face_nearest_steps);
|
||||||
mul_v3_fl(delta_local, step_scale_factor);
|
float factor = 1.0f / (float)steps;
|
||||||
|
mul_v3_v3fl(delta_step, delta_local, factor);
|
||||||
|
|
||||||
float co_local[3];
|
float co_local[3];
|
||||||
float no_local[3];
|
float no_local[3];
|
||||||
@@ -1293,8 +1300,8 @@ static bool nearest_world_tree(SnapObjectContext *UNUSED(sctx),
|
|||||||
|
|
||||||
copy_v3_v3(co_local, init_co_local);
|
copy_v3_v3(co_local, init_co_local);
|
||||||
|
|
||||||
for (int i = 0; i < params->face_nearest_steps; i++) {
|
for (int i = 0; i < steps; i++) {
|
||||||
add_v3_v3(co_local, delta_local);
|
add_v3_v3(co_local, delta_step);
|
||||||
nearest_world_tree_co(
|
nearest_world_tree_co(
|
||||||
tree, nearest_cb, treedata, co_local, co_local, no_local, &index, nullptr);
|
tree, nearest_cb, treedata, co_local, co_local, no_local, &index, nullptr);
|
||||||
}
|
}
|
||||||
@@ -1384,6 +1391,12 @@ static void nearest_world_object_fn(SnapObjectContext *sctx,
|
|||||||
{
|
{
|
||||||
struct NearestWorldObjUserData *dt = static_cast<NearestWorldObjUserData *>(data);
|
struct NearestWorldObjUserData *dt = static_cast<NearestWorldObjUserData *>(data);
|
||||||
|
|
||||||
|
const bool use_retopo_mode = params->snap_target_select & SCE_SNAP_TARGET_RETOPOLOGY_MODE;
|
||||||
|
const bool is_object_edited = BKE_object_is_in_editmode(ob_eval);
|
||||||
|
if (use_retopo_mode && is_object_edited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
switch (ob_eval->type) {
|
switch (ob_eval->type) {
|
||||||
case OB_MESH: {
|
case OB_MESH: {
|
||||||
@@ -3055,6 +3068,12 @@ static void snap_obj_fn(SnapObjectContext *sctx,
|
|||||||
SnapObjUserData *dt = static_cast<SnapObjUserData *>(data);
|
SnapObjUserData *dt = static_cast<SnapObjUserData *>(data);
|
||||||
eSnapMode retval = SCE_SNAP_MODE_NONE;
|
eSnapMode retval = SCE_SNAP_MODE_NONE;
|
||||||
|
|
||||||
|
const bool use_retopo_mode = (params->snap_target_select & SCE_SNAP_TARGET_RETOPOLOGY_MODE);
|
||||||
|
const bool is_object_edited = BKE_object_is_in_editmode(ob_eval);
|
||||||
|
if (use_retopo_mode && !is_object_edited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (ob_eval->type) {
|
switch (ob_eval->type) {
|
||||||
case OB_MESH: {
|
case OB_MESH: {
|
||||||
const eSnapEditType edit_mode_type = params->edit_mode_type;
|
const eSnapEditType edit_mode_type = params->edit_mode_type;
|
||||||
@@ -3384,47 +3403,29 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont
|
|||||||
sctx->runtime.region = region;
|
sctx->runtime.region = region;
|
||||||
sctx->runtime.v3d = v3d;
|
sctx->runtime.v3d = v3d;
|
||||||
|
|
||||||
BLI_assert((snap_to_flag & SCE_SNAP_MODE_GEOM) != 0);
|
if ((snap_to_flag & SCE_SNAP_MODE_GEOM) == 0) {
|
||||||
|
return SCE_SNAP_MODE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BLI_assert((snap_to_flag & SCE_SNAP_MODE_GEOM) != 0);
|
||||||
|
|
||||||
eSnapMode retval = SCE_SNAP_MODE_NONE;
|
eSnapMode retval = SCE_SNAP_MODE_NONE;
|
||||||
|
|
||||||
bool has_hit = false;
|
bool has_hit = false;
|
||||||
Object *ob_eval = nullptr;
|
Object *ob_eval = nullptr;
|
||||||
|
Object *ob_ray = nullptr;
|
||||||
float loc[3];
|
float loc[3];
|
||||||
/* Not all snapping callbacks set the normal,
|
/* Not all snapping callbacks set the normal,
|
||||||
* initialize this since any hit copies both the `loc` and `no`. */
|
* initialize this since any hit copies both the `loc` and `no`. */
|
||||||
float no[3] = {0.0f, 0.0f, 0.0f};
|
float no[3] = {0.0f, 0.0f, 0.0f};
|
||||||
float obmat[4][4];
|
float obmat[4][4];
|
||||||
|
float obmat_ray[4][4];
|
||||||
int index = -1;
|
int index = -1;
|
||||||
|
|
||||||
const RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
|
const RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||||
|
|
||||||
bool use_occlusion_test = params->use_occlusion_test && !XRAY_ENABLED(v3d);
|
const bool use_retopo_mode = params->snap_target_select & SCE_SNAP_TARGET_RETOPOLOGY_MODE;
|
||||||
|
const bool use_occlusion_test = params->use_occlusion_test && !XRAY_ENABLED(v3d);
|
||||||
/* Note: if both face raycast and face nearest are enabled, first find result of nearest, then
|
|
||||||
* override with raycast. */
|
|
||||||
if ((snap_to_flag & SCE_SNAP_MODE_FACE_NEAREST) && !has_hit) {
|
|
||||||
has_hit = nearestWorldObjects(
|
|
||||||
sctx, params, init_co, prev_co, loc, no, &index, &ob_eval, obmat);
|
|
||||||
|
|
||||||
if (has_hit) {
|
|
||||||
retval = SCE_SNAP_MODE_FACE_NEAREST;
|
|
||||||
|
|
||||||
copy_v3_v3(r_loc, loc);
|
|
||||||
if (r_no) {
|
|
||||||
copy_v3_v3(r_no, no);
|
|
||||||
}
|
|
||||||
if (r_ob) {
|
|
||||||
*r_ob = ob_eval;
|
|
||||||
}
|
|
||||||
if (r_obmat) {
|
|
||||||
copy_m4_m4(r_obmat, obmat);
|
|
||||||
}
|
|
||||||
if (r_index) {
|
|
||||||
*r_index = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (snap_to_flag & SCE_SNAP_MODE_FACE_RAYCAST || use_occlusion_test) {
|
if (snap_to_flag & SCE_SNAP_MODE_FACE_RAYCAST || use_occlusion_test) {
|
||||||
float ray_start[3], ray_normal[3];
|
float ray_start[3], ray_normal[3];
|
||||||
@@ -3443,8 +3444,8 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont
|
|||||||
loc,
|
loc,
|
||||||
no,
|
no,
|
||||||
&index,
|
&index,
|
||||||
&ob_eval,
|
&ob_ray, // &ob_eval,
|
||||||
obmat,
|
obmat_ray, // obmat,
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
if (has_hit) {
|
if (has_hit) {
|
||||||
@@ -3453,6 +3454,7 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((snap_to_flag & SCE_SNAP_MODE_FACE_RAYCAST)) {
|
if ((snap_to_flag & SCE_SNAP_MODE_FACE_RAYCAST)) {
|
||||||
|
/* Record snap results only if face raycast snapping mode is enabled. */
|
||||||
retval = SCE_SNAP_MODE_FACE_RAYCAST;
|
retval = SCE_SNAP_MODE_FACE_RAYCAST;
|
||||||
|
|
||||||
copy_v3_v3(r_loc, loc);
|
copy_v3_v3(r_loc, loc);
|
||||||
@@ -3460,15 +3462,19 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont
|
|||||||
copy_v3_v3(r_no, no);
|
copy_v3_v3(r_no, no);
|
||||||
}
|
}
|
||||||
if (r_ob) {
|
if (r_ob) {
|
||||||
*r_ob = ob_eval;
|
*r_ob = ob_ray; // ob_eval;
|
||||||
}
|
}
|
||||||
if (r_obmat) {
|
if (r_obmat) {
|
||||||
copy_m4_m4(r_obmat, obmat);
|
copy_m4_m4(r_obmat, obmat_ray); // obmat
|
||||||
}
|
}
|
||||||
if (r_index) {
|
if (r_index) {
|
||||||
*r_index = index;
|
*r_index = index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (use_occlusion_test && !use_retopo_mode) {
|
||||||
|
ob_eval = ob_ray;
|
||||||
|
copy_m4_m4(obmat, obmat_ray);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3503,7 +3509,7 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont
|
|||||||
sctx->runtime.has_occlusion_plane = false;
|
sctx->runtime.has_occlusion_plane = false;
|
||||||
|
|
||||||
/* By convention we only snap to the original elements of a curve. */
|
/* By convention we only snap to the original elements of a curve. */
|
||||||
if (has_hit && ob_eval->type != OB_CURVES_LEGACY) {
|
if (has_hit && ob_ray->type != OB_CURVES_LEGACY) {
|
||||||
/* Compute the new clip_pane but do not add it yet. */
|
/* Compute the new clip_pane but do not add it yet. */
|
||||||
float new_clipplane[4];
|
float new_clipplane[4];
|
||||||
BLI_ASSERT_UNIT_V3(no);
|
BLI_ASSERT_UNIT_V3(no);
|
||||||
@@ -3517,8 +3523,9 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont
|
|||||||
new_clipplane[3] += 0.01f;
|
new_clipplane[3] += 0.01f;
|
||||||
|
|
||||||
/* Try to snap only to the polygon. */
|
/* Try to snap only to the polygon. */
|
||||||
elem_test = snap_mesh_polygon(sctx, params, ob_eval, obmat, &dist_px_tmp, loc, no, &index);
|
elem_test = snap_mesh_polygon(
|
||||||
if (elem_test) {
|
sctx, params, ob_ray, obmat_ray, &dist_px_tmp, loc, no, &index);
|
||||||
|
if (elem_test && !use_retopo_mode) {
|
||||||
elem = elem_test;
|
elem = elem_test;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3565,6 +3572,31 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Note: if both face raycast and face nearest are enabled, first find result of nearest, then
|
||||||
|
* override with raycast. */
|
||||||
|
if ((snap_to_flag & SCE_SNAP_MODE_FACE_NEAREST) && !has_hit) {
|
||||||
|
has_hit = nearestWorldObjects(
|
||||||
|
sctx, params, init_co, prev_co, loc, no, &index, &ob_eval, obmat);
|
||||||
|
|
||||||
|
if (has_hit) {
|
||||||
|
retval = SCE_SNAP_MODE_FACE_NEAREST;
|
||||||
|
|
||||||
|
copy_v3_v3(r_loc, loc);
|
||||||
|
if (r_no) {
|
||||||
|
copy_v3_v3(r_no, no);
|
||||||
|
}
|
||||||
|
if (r_ob) {
|
||||||
|
*r_ob = ob_eval;
|
||||||
|
}
|
||||||
|
if (r_obmat) {
|
||||||
|
copy_m4_m4(r_obmat, obmat);
|
||||||
|
}
|
||||||
|
if (r_index) {
|
||||||
|
*r_index = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2095,6 +2095,7 @@ typedef enum eSnapFlag {
|
|||||||
SCE_SNAP_TO_INCLUDE_EDITED = (1 << 8),
|
SCE_SNAP_TO_INCLUDE_EDITED = (1 << 8),
|
||||||
SCE_SNAP_TO_INCLUDE_NONEDITED = (1 << 9),
|
SCE_SNAP_TO_INCLUDE_NONEDITED = (1 << 9),
|
||||||
SCE_SNAP_TO_ONLY_SELECTABLE = (1 << 10),
|
SCE_SNAP_TO_ONLY_SELECTABLE = (1 << 10),
|
||||||
|
SCE_SNAP_RETOPOLOGY_MODE = (1 << 11),
|
||||||
} eSnapFlag;
|
} eSnapFlag;
|
||||||
/* Due to dependency conflicts with Cycles, header cannot directly include `BLI_utildefines.h`. */
|
/* Due to dependency conflicts with Cycles, header cannot directly include `BLI_utildefines.h`. */
|
||||||
/* TODO: move this macro to a more general place. */
|
/* TODO: move this macro to a more general place. */
|
||||||
@@ -2119,6 +2120,7 @@ typedef enum eSnapTargetSelect {
|
|||||||
SCE_SNAP_TARGET_NOT_EDITED = (1 << 2),
|
SCE_SNAP_TARGET_NOT_EDITED = (1 << 2),
|
||||||
SCE_SNAP_TARGET_ONLY_SELECTABLE = (1 << 3),
|
SCE_SNAP_TARGET_ONLY_SELECTABLE = (1 << 3),
|
||||||
SCE_SNAP_TARGET_NOT_NONEDITED = (1 << 4),
|
SCE_SNAP_TARGET_NOT_NONEDITED = (1 << 4),
|
||||||
|
SCE_SNAP_TARGET_RETOPOLOGY_MODE = (1 << 5),
|
||||||
} eSnapTargetSelect;
|
} eSnapTargetSelect;
|
||||||
|
|
||||||
/** #ToolSettings.snap_mode */
|
/** #ToolSettings.snap_mode */
|
||||||
|
@@ -151,6 +151,16 @@ const EnumPropertyItem rna_enum_snap_element_items[] = {
|
|||||||
"Snap to increments of grid"},
|
"Snap to increments of grid"},
|
||||||
{SCE_SNAP_MODE_VERTEX, "VERTEX", ICON_SNAP_VERTEX, "Vertex", "Snap to vertices"},
|
{SCE_SNAP_MODE_VERTEX, "VERTEX", ICON_SNAP_VERTEX, "Vertex", "Snap to vertices"},
|
||||||
{SCE_SNAP_MODE_EDGE, "EDGE", ICON_SNAP_EDGE, "Edge", "Snap to edges"},
|
{SCE_SNAP_MODE_EDGE, "EDGE", ICON_SNAP_EDGE, "Edge", "Snap to edges"},
|
||||||
|
{SCE_SNAP_MODE_EDGE_MIDPOINT,
|
||||||
|
"EDGE_MIDPOINT",
|
||||||
|
ICON_SNAP_MIDPOINT,
|
||||||
|
"Edge Center",
|
||||||
|
"Snap to the middle of edges"},
|
||||||
|
{SCE_SNAP_MODE_EDGE_PERPENDICULAR,
|
||||||
|
"EDGE_PERPENDICULAR",
|
||||||
|
ICON_SNAP_PERPENDICULAR,
|
||||||
|
"Edge Perpendicular",
|
||||||
|
"Snap to the nearest point on an edge"},
|
||||||
{SCE_SNAP_MODE_FACE_RAYCAST,
|
{SCE_SNAP_MODE_FACE_RAYCAST,
|
||||||
"FACE", /* TODO(@gfxcoder): replace with "FACE_RAYCAST" as "FACE" is not descriptive. */
|
"FACE", /* TODO(@gfxcoder): replace with "FACE_RAYCAST" as "FACE" is not descriptive. */
|
||||||
ICON_SNAP_FACE,
|
ICON_SNAP_FACE,
|
||||||
@@ -162,16 +172,6 @@ const EnumPropertyItem rna_enum_snap_element_items[] = {
|
|||||||
"Face Nearest",
|
"Face Nearest",
|
||||||
"Snap to nearest point on faces"},
|
"Snap to nearest point on faces"},
|
||||||
{SCE_SNAP_MODE_VOLUME, "VOLUME", ICON_SNAP_VOLUME, "Volume", "Snap to volume"},
|
{SCE_SNAP_MODE_VOLUME, "VOLUME", ICON_SNAP_VOLUME, "Volume", "Snap to volume"},
|
||||||
{SCE_SNAP_MODE_EDGE_MIDPOINT,
|
|
||||||
"EDGE_MIDPOINT",
|
|
||||||
ICON_SNAP_MIDPOINT,
|
|
||||||
"Edge Center",
|
|
||||||
"Snap to the middle of edges"},
|
|
||||||
{SCE_SNAP_MODE_EDGE_PERPENDICULAR,
|
|
||||||
"EDGE_PERPENDICULAR",
|
|
||||||
ICON_SNAP_PERPENDICULAR,
|
|
||||||
"Edge Perpendicular",
|
|
||||||
"Snap to the nearest point on an edge"},
|
|
||||||
{0, NULL, 0, NULL, NULL},
|
{0, NULL, 0, NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3313,10 +3313,10 @@ static void rna_def_tool_settings(BlenderRNA *brna)
|
|||||||
prop = RNA_def_property(srna, "snap_face_nearest_steps", PROP_INT, PROP_FACTOR);
|
prop = RNA_def_property(srna, "snap_face_nearest_steps", PROP_INT, PROP_FACTOR);
|
||||||
RNA_def_property_int_sdna(prop, NULL, "snap_face_nearest_steps");
|
RNA_def_property_int_sdna(prop, NULL, "snap_face_nearest_steps");
|
||||||
RNA_def_property_range(prop, 1, 100);
|
RNA_def_property_range(prop, 1, 100);
|
||||||
RNA_def_property_ui_text(
|
RNA_def_property_ui_text(prop,
|
||||||
prop,
|
"Face Nearest Steps",
|
||||||
"Face Nearest Steps",
|
"Increase precision and smooth large changes by dividing "
|
||||||
"Number of steps to break transformation into for face nearest snapping");
|
"transformation into smaller steps (Face Nearest Only)");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "use_snap_to_same_target", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "use_snap_to_same_target", PROP_BOOLEAN, PROP_NONE);
|
||||||
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_KEEP_ON_SAME_OBJECT);
|
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_KEEP_ON_SAME_OBJECT);
|
||||||
@@ -3379,13 +3379,13 @@ static void rna_def_tool_settings(BlenderRNA *brna)
|
|||||||
prop = RNA_def_property(srna, "use_snap_self", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "use_snap_self", PROP_BOOLEAN, PROP_NONE);
|
||||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "snap_flag", SCE_SNAP_NOT_TO_ACTIVE);
|
RNA_def_property_boolean_negative_sdna(prop, NULL, "snap_flag", SCE_SNAP_NOT_TO_ACTIVE);
|
||||||
RNA_def_property_ui_text(
|
RNA_def_property_ui_text(
|
||||||
prop, "Snap onto Active", "Snap onto itself only if enabled (Edit Mode Only)");
|
prop, "Snap onto Active", "Snap onto active edited object (Edit Mode Only)");
|
||||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "use_snap_edit", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "use_snap_edit", PROP_BOOLEAN, PROP_NONE);
|
||||||
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_TO_INCLUDE_EDITED);
|
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_TO_INCLUDE_EDITED);
|
||||||
RNA_def_property_ui_text(
|
RNA_def_property_ui_text(
|
||||||
prop, "Snap onto Edited", "Snap onto non-active objects in Edit Mode (Edit Mode Only)");
|
prop, "Snap onto Edited", "Snap onto non-active edited objects (Edit Mode Only)");
|
||||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "use_snap_nonedit", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "use_snap_nonedit", PROP_BOOLEAN, PROP_NONE);
|
||||||
@@ -3394,12 +3394,18 @@ static void rna_def_tool_settings(BlenderRNA *brna)
|
|||||||
prop, "Snap onto Non-edited", "Snap onto objects not in Edit Mode (Edit Mode Only)");
|
prop, "Snap onto Non-edited", "Snap onto objects not in Edit Mode (Edit Mode Only)");
|
||||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "use_snap_selectable", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "use_snap_selectable_only", PROP_BOOLEAN, PROP_NONE);
|
||||||
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_TO_ONLY_SELECTABLE);
|
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_TO_ONLY_SELECTABLE);
|
||||||
RNA_def_property_ui_text(
|
RNA_def_property_ui_text(
|
||||||
prop, "Snap onto Selectable Only", "Snap only onto objects that are selectable");
|
prop, "Snap onto Selectable Only", "Snap only onto objects that are selectable");
|
||||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "use_snap_retopology_mode", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_RETOPOLOGY_MODE);
|
||||||
|
RNA_def_property_ui_text(
|
||||||
|
prop, "Retopology Snapping Mode", "Optimize snapping options for retopology work");
|
||||||
|
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "use_snap_translate", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "use_snap_translate", PROP_BOOLEAN, PROP_NONE);
|
||||||
RNA_def_property_boolean_sdna(
|
RNA_def_property_boolean_sdna(
|
||||||
prop, NULL, "snap_transform_mode_flag", SCE_SNAP_TRANSFORM_MODE_TRANSLATE);
|
prop, NULL, "snap_transform_mode_flag", SCE_SNAP_TRANSFORM_MODE_TRANSLATE);
|
||||||
|
@@ -714,6 +714,11 @@ void RNA_api_window(StructRNA *srna)
|
|||||||
FunctionRNA *func;
|
FunctionRNA *func;
|
||||||
PropertyRNA *parm;
|
PropertyRNA *parm;
|
||||||
|
|
||||||
|
func = RNA_def_function(srna, "is_operator_modal", "WM_active_modal_operator_test");
|
||||||
|
RNA_def_function_ui_description(func, "Test if an operator is actively running modal.");
|
||||||
|
parm = RNA_def_boolean(func, "result", 0, "", "Operator running modal");
|
||||||
|
RNA_def_function_return(func, parm);
|
||||||
|
|
||||||
func = RNA_def_function(srna, "cursor_warp", "WM_cursor_warp");
|
func = RNA_def_function(srna, "cursor_warp", "WM_cursor_warp");
|
||||||
parm = RNA_def_int(func, "x", 0, INT_MIN, INT_MAX, "", "", INT_MIN, INT_MAX);
|
parm = RNA_def_int(func, "x", 0, INT_MIN, INT_MAX, "", "", INT_MIN, INT_MAX);
|
||||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||||
@@ -721,6 +726,13 @@ void RNA_api_window(StructRNA *srna)
|
|||||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||||
RNA_def_function_ui_description(func, "Set the cursor position");
|
RNA_def_function_ui_description(func, "Set the cursor position");
|
||||||
|
|
||||||
|
func = RNA_def_function(srna, "cursor_warp_relative", "WM_cursor_warp_relative");
|
||||||
|
parm = RNA_def_int(func, "x", 0, INT_MIN, INT_MAX, "", "Offset of x", INT_MIN, INT_MAX);
|
||||||
|
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||||
|
parm = RNA_def_int(func, "y", 0, INT_MIN, INT_MAX, "", "Offset of y", INT_MIN, INT_MAX);
|
||||||
|
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||||
|
RNA_def_function_ui_description(func, "Offset the cursor position");
|
||||||
|
|
||||||
func = RNA_def_function(srna, "cursor_set", "WM_cursor_set");
|
func = RNA_def_function(srna, "cursor_set", "WM_cursor_set");
|
||||||
parm = RNA_def_property(func, "cursor", PROP_ENUM, PROP_NONE);
|
parm = RNA_def_property(func, "cursor", PROP_ENUM, PROP_NONE);
|
||||||
RNA_def_property_enum_items(parm, rna_enum_window_cursor_items);
|
RNA_def_property_enum_items(parm, rna_enum_window_cursor_items);
|
||||||
|
@@ -310,10 +310,20 @@ void WM_paint_cursor_remove_by_type(struct wmWindowManager *wm,
|
|||||||
void (*free)(void *));
|
void (*free)(void *));
|
||||||
void WM_paint_cursor_tag_redraw(struct wmWindow *win, struct ARegion *region);
|
void WM_paint_cursor_tag_redraw(struct wmWindow *win, struct ARegion *region);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether an operator is actively running modal.
|
||||||
|
*/
|
||||||
|
bool WM_active_modal_operator_test(struct wmWindow *win);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function requires access to the GHOST_SystemHandle (g_system).
|
* This function requires access to the GHOST_SystemHandle (g_system).
|
||||||
*/
|
*/
|
||||||
void WM_cursor_warp(struct wmWindow *win, int x, int y);
|
void WM_cursor_warp(struct wmWindow *win, int x, int y);
|
||||||
|
void WM_cursor_warp_relative(struct wmWindow *win, int x, int y);
|
||||||
|
/**
|
||||||
|
* Set x, y to values we can actually position the cursor to.
|
||||||
|
*/
|
||||||
|
void WM_cursor_compatible_xy(wmWindow *win, int *x, int *y);
|
||||||
|
|
||||||
/* Handlers. */
|
/* Handlers. */
|
||||||
|
|
||||||
|
@@ -278,14 +278,6 @@ void WM_cursor_grab_disable(wmWindow *win, const int mouse_ungrab_xy[2])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wm_cursor_warp_relative(wmWindow *win, int x, int y)
|
|
||||||
{
|
|
||||||
/* NOTE: don't use wmEvent coords because of continuous grab T36409. */
|
|
||||||
int cx, cy;
|
|
||||||
wm_cursor_position_get(win, &cx, &cy);
|
|
||||||
WM_cursor_warp(win, cx + x, cy + y);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wm_cursor_arrow_move(wmWindow *win, const wmEvent *event)
|
bool wm_cursor_arrow_move(wmWindow *win, const wmEvent *event)
|
||||||
{
|
{
|
||||||
/* TODO: give it a modal keymap? Hard coded for now */
|
/* TODO: give it a modal keymap? Hard coded for now */
|
||||||
@@ -295,19 +287,19 @@ bool wm_cursor_arrow_move(wmWindow *win, const wmEvent *event)
|
|||||||
float fac = GHOST_GetNativePixelSize(win->ghostwin);
|
float fac = GHOST_GetNativePixelSize(win->ghostwin);
|
||||||
|
|
||||||
if (event->type == EVT_UPARROWKEY) {
|
if (event->type == EVT_UPARROWKEY) {
|
||||||
wm_cursor_warp_relative(win, 0, fac);
|
WM_cursor_warp_relative(win, 0, fac);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (event->type == EVT_DOWNARROWKEY) {
|
if (event->type == EVT_DOWNARROWKEY) {
|
||||||
wm_cursor_warp_relative(win, 0, -fac);
|
WM_cursor_warp_relative(win, 0, -fac);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (event->type == EVT_LEFTARROWKEY) {
|
if (event->type == EVT_LEFTARROWKEY) {
|
||||||
wm_cursor_warp_relative(win, -fac, 0);
|
WM_cursor_warp_relative(win, -fac, 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (event->type == EVT_RIGHTARROWKEY) {
|
if (event->type == EVT_RIGHTARROWKEY) {
|
||||||
wm_cursor_warp_relative(win, fac, 0);
|
WM_cursor_warp_relative(win, fac, 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2000,6 +2000,22 @@ void WM_init_native_pixels(bool do_it)
|
|||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Operator API
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
bool WM_active_modal_operator_test(struct wmWindow *win)
|
||||||
|
{
|
||||||
|
LISTBASE_FOREACH (wmEventHandler *, handler_base, &win->modalhandlers) {
|
||||||
|
if (handler_base->type == WM_HANDLER_TYPE_OP) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/** \name Cursor API
|
/** \name Cursor API
|
||||||
* \{ */
|
* \{ */
|
||||||
@@ -2038,6 +2054,25 @@ void WM_cursor_warp(wmWindow *win, int x, int y)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WM_cursor_warp_relative(wmWindow *win, int x, int y)
|
||||||
|
{
|
||||||
|
if (win && win->ghostwin) {
|
||||||
|
/* NOTE: don't use wmEvent coords because of continuous grab T36409. */
|
||||||
|
int cx, cy;
|
||||||
|
wm_cursor_position_get(win, &cx, &cy);
|
||||||
|
WM_cursor_warp(win, cx + x, cy + y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WM_cursor_compatible_xy(wmWindow *win, int *x, int *y)
|
||||||
|
{
|
||||||
|
float f = GHOST_GetNativePixelSize(win->ghostwin);
|
||||||
|
if (f != 1.0f) {
|
||||||
|
*x = (int)(*x / f) * f;
|
||||||
|
*y = (int)(*y / f) * f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
Reference in New Issue
Block a user