Blender V5.0
transform_snap_object_curve.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "DNA_curve_types.h"
10
11#include "BLI_listbase.h"
12
13#include "BKE_curve.hh"
14#include "BKE_object.hh"
15
17
19
20namespace blender::ed::transform {
21
22eSnapMode snapCurve(SnapObjectContext *sctx, const Object *ob_eval, const float4x4 &obmat)
23{
24 bool has_snap = false;
25
26 /* Only vertex snapping mode (eg control points and handles) supported for now). */
27 if ((sctx->runtime.snap_to_flag & SCE_SNAP_TO_POINT) == 0) {
28 return SCE_SNAP_TO_NONE;
29 }
30
31 Curve *cu = static_cast<Curve *>(ob_eval->data);
32
33 SnapData nearest2d(sctx, obmat);
34
35 const bool use_obedit = BKE_object_is_in_editmode(ob_eval);
36
37 if (use_obedit == false) {
38 /* Test BoundBox. */
39 std::optional<Bounds<float3>> bounds = BKE_curve_minmax(cu, true);
40 if (bounds && !nearest2d.snap_boundbox(bounds->min, bounds->max)) {
41 return SCE_SNAP_TO_NONE;
42 }
43 }
44
45 nearest2d.clip_planes_enable(sctx, ob_eval, true);
46
47 bool skip_selected = (sctx->runtime.params.snap_target_select & SCE_SNAP_TARGET_NOT_SELECTED) !=
48 0;
49
50 LISTBASE_FOREACH (Nurb *, nu, (use_obedit ? &cu->editnurb->nurbs : &cu->nurb)) {
51 if (nu->bezt) {
52 for (int u : IndexRange(nu->pntsu)) {
53 if (use_obedit) {
54 if (nu->bezt[u].hide) {
55 /* Skip hidden. */
56 continue;
57 }
58
59 bool is_selected = (nu->bezt[u].f2 & SELECT) != 0;
60 if (is_selected && skip_selected) {
61 continue;
62 }
63
64 /* Don't snap if handle is selected (moving),
65 * or if it is aligning to a moving handle. */
66 bool is_selected_h1 = (nu->bezt[u].f1 & SELECT) != 0;
67 bool is_selected_h2 = (nu->bezt[u].f3 & SELECT) != 0;
68 bool is_autoalign_h1 = (nu->bezt[u].h1 & HD_ALIGN) != 0;
69 bool is_autoalign_h2 = (nu->bezt[u].h2 & HD_ALIGN) != 0;
70 if (!skip_selected || !(is_selected_h1 || (is_autoalign_h1 && is_selected_h2))) {
71 has_snap |= nearest2d.snap_point(nu->bezt[u].vec[0]);
72 }
73
74 if (!skip_selected || !(is_selected_h2 || (is_autoalign_h2 && is_selected_h1))) {
75 has_snap |= nearest2d.snap_point(nu->bezt[u].vec[2]);
76 }
77 }
78 has_snap |= nearest2d.snap_point(nu->bezt[u].vec[1]);
79 }
80 }
81 else if (nu->bp) {
82 for (int u : IndexRange(nu->pntsu * nu->pntsv)) {
83 if (use_obedit) {
84 if (nu->bp[u].hide) {
85 /* Skip hidden. */
86 continue;
87 }
88
89 bool is_selected = (nu->bp[u].f1 & SELECT) != 0;
90 if (is_selected && skip_selected) {
91 continue;
92 }
93 }
94 has_snap |= nearest2d.snap_point(nu->bp[u].vec);
95 }
96 }
97 }
98 if (has_snap) {
99 nearest2d.register_result(sctx, ob_eval, &cu->id);
100 return SCE_SNAP_TO_POINT;
101 }
102 return SCE_SNAP_TO_NONE;
103}
104
105} // namespace blender::ed::transform
std::optional< blender::Bounds< blender::float3 > > BKE_curve_minmax(const Curve *cu, bool use_radius)
Definition curve.cc:5097
General operations, lookup, etc. for blender objects.
bool BKE_object_is_in_editmode(const Object *ob)
#define LISTBASE_FOREACH(type, var, list)
@ HD_ALIGN
@ SCE_SNAP_TARGET_NOT_SELECTED
@ SCE_SNAP_TO_POINT
@ SCE_SNAP_TO_NONE
void clip_planes_enable(SnapObjectContext *sctx, const Object *ob_eval, bool skip_occlusion_plane=false)
bool snap_point(const float3 &co, int index=-1)
static void register_result(SnapObjectContext *sctx, const Object *ob_eval, const ID *id_eval, const float4x4 &obmat, BVHTreeNearest *r_nearest)
bool snap_boundbox(const float3 &min, const float3 &max)
#define SELECT
eSnapMode snapCurve(SnapObjectContext *sctx, const Object *ob_eval, const float4x4 &obmat)
MatBase< float, 4, 4 > float4x4
EditNurb * editnurb
ListBase nurb
ListBase nurbs
struct blender::ed::transform::SnapObjectContext::@170374026073064374202114033260227063176045253050 runtime