Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2021-01-16 03:29:57 +0300
committerCampbell Barton <ideasman42@gmail.com>2021-01-16 03:36:55 +0300
commitcdfa3feb911164118fcc5b574b3e1a35c8f99c72 (patch)
tree779a402ab25b3d4c95f8e96983f164545511057b /source/blender/editors/space_view3d/view3d_placement.c
parentc4bbe44e472b97911127ce354954ff7e9e290a3d (diff)
Add Object Tool: support incremental snapping
This adds a "Snap to" option that allows using all the scenes snap settings which includes incremental & absolute grid snapping options. This is optional because always following scene snapping would not snap to geometry by default (which seems to be the most useful default).
Diffstat (limited to 'source/blender/editors/space_view3d/view3d_placement.c')
-rw-r--r--source/blender/editors/space_view3d/view3d_placement.c109
1 files changed, 101 insertions, 8 deletions
diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c
index 5bd1b3458e2..2bbe512222c 100644
--- a/source/blender/editors/space_view3d/view3d_placement.c
+++ b/source/blender/editors/space_view3d/view3d_placement.c
@@ -102,6 +102,11 @@ enum ePlace_Orient {
PLACE_ORIENT_DEFAULT = 2,
};
+enum ePlace_SnapTo {
+ PLACE_SNAP_TO_GEOMETRY = 1,
+ PLACE_SNAP_TO_DEFAULT = 2,
+};
+
struct InteractivePlaceData {
/* Window manager variables (set these even when waiting for input). */
Scene *scene;
@@ -184,6 +189,8 @@ struct InteractivePlaceData {
/** Optional snap gizmo, needed for snapping. */
wmGizmo *snap_gizmo;
+
+ enum ePlace_SnapTo snap_to;
};
/** \} */
@@ -359,6 +366,56 @@ static wmGizmoGroup *idp_gizmogroup_from_region(ARegion *region)
return gzmap ? WM_gizmomap_group_find(gzmap, view3d_gzgt_placement_id) : NULL;
}
+/**
+ * Calculate 3D view incremental (grid) snapping.
+ *
+ * \note This could be moved to a public function.
+ */
+static bool idp_snap_calc_incremental(
+ Scene *scene, View3D *v3d, ARegion *region, const float co_relative[3], float co[3])
+{
+ if ((scene->toolsettings->snap_mode & SCE_SNAP_MODE_INCREMENT) == 0) {
+ return false;
+ }
+
+ const float grid_size = ED_view3d_grid_view_scale(scene, v3d, region, NULL);
+ if (UNLIKELY(grid_size == 0.0f)) {
+ return false;
+ }
+
+ if (scene->toolsettings->snap_flag & SCE_SNAP_ABS_GRID) {
+ co_relative = NULL;
+ }
+
+ if (co_relative != NULL) {
+ sub_v3_v3(co, co_relative);
+ }
+ mul_v3_fl(co, 1.0f / grid_size);
+ co[0] = roundf(co[0]);
+ co[1] = roundf(co[1]);
+ co[2] = roundf(co[2]);
+ mul_v3_fl(co, grid_size);
+ if (co_relative != NULL) {
+ add_v3_v3(co, co_relative);
+ }
+
+ return true;
+}
+
+static void idp_snap_gizmo_update_snap_elements(Scene *scene,
+ enum ePlace_SnapTo snap_to,
+ wmGizmo *gizmo)
+{
+ const int snap_mode =
+ (snap_to == PLACE_SNAP_TO_GEOMETRY) ?
+ (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
+ /* SCE_SNAP_MODE_VOLUME | SCE_SNAP_MODE_GRID | SCE_SNAP_MODE_INCREMENT | */
+ SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT) :
+ scene->toolsettings->snap_mode;
+
+ RNA_enum_set(gizmo->ptr, "snap_elements_force", snap_mode);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -784,8 +841,9 @@ static void view3d_interactive_add_calc_plane(bContext *C,
Scene *scene,
View3D *v3d,
ARegion *region,
- wmGizmo *snap_gizmo,
const float mval_fl[2],
+ wmGizmo *snap_gizmo,
+ const enum ePlace_SnapTo snap_to,
const enum ePlace_Depth plane_depth,
const enum ePlace_Orient plane_orient,
const int plane_axis,
@@ -914,6 +972,12 @@ static void view3d_interactive_add_calc_plane(bContext *C,
}
}
+ if (!is_snap_found && ((snap_gizmo != NULL) && ED_gizmotypes_snap_3d_is_enabled(snap_gizmo))) {
+ if (snap_to == PLACE_SNAP_TO_DEFAULT) {
+ idp_snap_calc_incremental(scene, v3d, region, NULL, r_co_src);
+ }
+ }
+
if (snap_context_free) {
ED_transform_snap_object_context_destroy(snap_context);
}
@@ -929,6 +993,7 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv
{
const int plane_axis = RNA_enum_get(op->ptr, "plane_axis");
+ const enum ePlace_SnapTo snap_to = RNA_enum_get(op->ptr, "snap_target");
const enum ePlace_Depth plane_depth = RNA_enum_get(op->ptr, "plane_depth");
const enum ePlace_Origin plane_origin = RNA_enum_get(op->ptr, "plane_origin");
const enum ePlace_Orient plane_orient = RNA_enum_get(op->ptr, "plane_orientation");
@@ -976,8 +1041,9 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv
ipd->scene,
ipd->v3d,
ipd->region,
- ipd->snap_gizmo,
mval_fl,
+ ipd->snap_gizmo,
+ snap_to,
plane_depth,
plane_orient,
plane_axis,
@@ -989,6 +1055,7 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv
ipd->step[0].is_centered = ipd->is_centered_init;
ipd->step[1].is_centered = ipd->is_centered_init;
ipd->step_index = STEP_BASE;
+ ipd->snap_to = snap_to;
plane_from_point_normal_v3(ipd->step[0].plane, ipd->co_src, ipd->matrix_orient[plane_axis]);
@@ -1415,6 +1482,12 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve
ipd->step[STEP_BASE].co_dst)) {
/* pass */
}
+
+ if (ipd->use_snap && (ipd->snap_to == PLACE_SNAP_TO_DEFAULT)) {
+ if (idp_snap_calc_incremental(
+ ipd->scene, ipd->v3d, ipd->region, ipd->co_src, ipd->step[STEP_BASE].co_dst)) {
+ }
+ }
}
}
else if (ipd->step_index == STEP_DEPTH) {
@@ -1431,6 +1504,12 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve
ipd->step[STEP_DEPTH].co_dst)) {
/* pass */
}
+
+ if (ipd->use_snap && (ipd->snap_to == PLACE_SNAP_TO_DEFAULT)) {
+ if (idp_snap_calc_incremental(
+ ipd->scene, ipd->v3d, ipd->region, ipd->co_src, ipd->step[STEP_DEPTH].co_dst)) {
+ }
+ }
}
/* Correct the point so it's aligned with the 'ipd->step[0].co_dst'. */
@@ -1550,6 +1629,17 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
RNA_def_property_enum_items(prop, plane_orientation_items);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ static const EnumPropertyItem snap_to_items[] = {
+ {PLACE_SNAP_TO_GEOMETRY, "GEOMETRY", 0, "Geometry", "Snap to all geometry"},
+ {PLACE_SNAP_TO_DEFAULT, "DEFAULT", 0, "Default", "Use the current snap settings"},
+ {0, NULL, 0, NULL, NULL},
+ };
+ prop = RNA_def_property(ot->srna, "snap_target", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Snap to", "The target to use while snapping");
+ RNA_def_property_enum_default(prop, PLACE_SNAP_TO_GEOMETRY);
+ RNA_def_property_enum_items(prop, snap_to_items);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
/* When not accessed via a tool. */
prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
@@ -1573,11 +1663,6 @@ static void WIDGETGROUP_placement_setup(const bContext *UNUSED(C), wmGizmoGroup
const wmGizmoType *gzt_snap;
gzt_snap = WM_gizmotype_find("GIZMO_GT_snap_3d", true);
gizmo = WM_gizmo_new_ptr(gzt_snap, gzgroup, NULL);
- RNA_enum_set(gizmo->ptr,
- "snap_elements_force",
- (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
- /* SCE_SNAP_MODE_VOLUME | SCE_SNAP_MODE_GRID | SCE_SNAP_MODE_INCREMENT | */
- SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT));
WM_gizmo_set_color(gizmo, (float[4]){1.0f, 1.0f, 1.0f, 1.0f});
@@ -1630,6 +1715,7 @@ static void gizmo_plane_update_cursor(const bContext *C,
bToolRef *tref = area->runtime.tool;
WM_toolsystem_ref_properties_ensure_from_operator(tref, ot, &ptr);
+ const enum ePlace_SnapTo snap_to = RNA_enum_get(&ptr, "snap_target");
const int plane_axis = RNA_enum_get(&ptr, "plane_axis");
const enum ePlace_Depth plane_depth = RNA_enum_get(&ptr, "plane_depth");
const enum ePlace_Orient plane_orient = RNA_enum_get(&ptr, "plane_orientation");
@@ -1648,12 +1734,19 @@ static void gizmo_plane_update_cursor(const bContext *C,
}
}
+ /* This ensures the snap gizmo has settings from this tool.
+ * This function call could be moved a more appropriate place,
+ * responding to the setting being changed for example,
+ * however setting the value isn't expensive, so do it here. */
+ idp_snap_gizmo_update_snap_elements(scene, snap_to, snap_gizmo);
+
view3d_interactive_add_calc_plane((bContext *)C,
scene,
v3d,
region,
- snap_gizmo,
mval_fl,
+ snap_gizmo,
+ snap_to,
plane_depth,
plane_orient,
plane_axis,