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
path: root/source
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
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')
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c13
-rw-r--r--source/blender/editors/include/ED_gizmo_library.h1
-rw-r--r--source/blender/editors/space_view3d/view3d_placement.c109
3 files changed, 115 insertions, 8 deletions
diff --git a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
index 8755dea51e1..b8ee1722cb3 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
@@ -80,6 +80,9 @@ typedef struct SnapGizmo3D {
#endif
int use_snap_override;
short snap_elem;
+
+ /** Enabled when snap is activated, even if it didn't find anything. */
+ bool is_enabled;
} SnapGizmo3D;
/* Checks if the current event is different from the one captured in the last update. */
@@ -284,6 +287,12 @@ void ED_gizmotypes_snap_3d_toggle_clear(wmGizmo *gz)
snap_gizmo->use_snap_override = -1;
}
+bool ED_gizmotypes_snap_3d_is_enabled(wmGizmo *gz)
+{
+ SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
+ return snap_gizmo->is_enabled;
+}
+
short ED_gizmotypes_snap_3d_update(wmGizmo *gz,
struct Depsgraph *depsgraph,
const ARegion *region,
@@ -294,6 +303,8 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz,
float r_nor[3])
{
SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
+ snap_gizmo->is_enabled = false;
+
if (snap_gizmo->use_snap_override != -1) {
if (snap_gizmo->use_snap_override == false) {
snap_gizmo->snap_elem = 0;
@@ -318,6 +329,8 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz,
}
#endif
+ snap_gizmo->is_enabled = true;
+
float co[3], no[3];
short snap_elem = 0;
int snap_elem_index[3] = {-1, -1, -1};
diff --git a/source/blender/editors/include/ED_gizmo_library.h b/source/blender/editors/include/ED_gizmo_library.h
index 434ab743d18..dfc8cfea5ce 100644
--- a/source/blender/editors/include/ED_gizmo_library.h
+++ b/source/blender/editors/include/ED_gizmo_library.h
@@ -264,6 +264,7 @@ struct SnapObjectContext *ED_gizmotypes_snap_3d_context_ensure(struct Scene *sce
bool ED_gizmotypes_snap_3d_invert_snap_get(struct wmGizmo *gz);
void ED_gizmotypes_snap_3d_toggle_set(struct wmGizmo *gz, bool enable);
void ED_gizmotypes_snap_3d_toggle_clear(struct wmGizmo *gz);
+bool ED_gizmotypes_snap_3d_is_enabled(struct wmGizmo *gz);
short ED_gizmotypes_snap_3d_update(struct wmGizmo *gz,
struct Depsgraph *depsgraph,
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,