Blender V4.5
transform_snap_object_editmesh.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 "BKE_attribute.hh"
10#include "BKE_editmesh.hh"
11#include "BKE_global.hh"
12#include "BKE_lib_id.hh"
13#include "BKE_mesh.hh"
14#include "BKE_object.hh"
15#include "BKE_object_types.hh"
16
18
20
22
23namespace blender::ed::transform {
24
25/* -------------------------------------------------------------------- */
28
29static const Mesh *get_mesh_ref(const Object *ob_eval)
30{
31 if (const Mesh *me = BKE_object_get_editmesh_eval_final(ob_eval)) {
32 return me;
33 }
34
35 if (const Mesh *me = BKE_object_get_editmesh_eval_cage(ob_eval)) {
36 return me;
37 }
38
39 return static_cast<const Mesh *>(ob_eval->data);
40}
41
43 /* Mesh created from the edited mesh. */
45
46 /* Reference to pointers that change when the mesh is changed. It is used to detect updates. */
47 const Mesh *mesh_ref;
50
52 {
53 if (mesh != this->mesh_ref || mesh->runtime != this->runtime_ref ||
54 mesh->runtime->edit_data.get() != this->edit_data_ref)
55 {
56 return true;
57 }
58
59 return false;
60 }
61
62 void clear()
63 {
64 if (this->mesh) {
65 BKE_id_free(nullptr, this->mesh);
66 }
67 }
68
70 {
71 this->clear();
72 }
73
74 MEM_CXX_CLASS_ALLOC_FUNCS("SnapCache_EditMesh")
75};
76
78 const Object *ob_eval,
79 eSnapEditType /*edit_mode_type*/)
80{
82 const BMEditMesh *em = BKE_editmesh_from_object(const_cast<Object *>(DEG_get_original(ob_eval)));
83 BMesh *bm = em->bm;
84 BM_mesh_bm_to_me_compact(*bm, *mesh, nullptr, false);
85
86 bke::MutableAttributeAccessor attrs = mesh->attributes_for_write();
88 ".hide_vert", bke::AttrDomain::Point);
90 ".hide_edge", bke::AttrDomain::Edge);
92 ".hide_poly", bke::AttrDomain::Face);
93
94 /* Loop over all elements in parallel to choose which elements will participate in the snap.
95 * Hidden elements are ignored for snapping. */
96 const bool use_threading = (mesh->faces_num + mesh->edges_num) > 1024;
98 use_threading,
99 [&]() {
100 BMIter iter;
101 BMVert *v;
102 int i;
104 if (sctx->callbacks.edit_mesh.test_vert_fn) {
105 hide_vert.span[i] = !sctx->callbacks.edit_mesh.test_vert_fn(
107 }
108 else {
110 }
111 }
112 },
113 [&]() {
114 BMIter iter;
115 BMEdge *e;
116 int i;
118 if (sctx->callbacks.edit_mesh.test_edge_fn) {
119 hide_edge.span[i] = !sctx->callbacks.edit_mesh.test_edge_fn(
121 }
122 else {
123 hide_edge.span[i] = BM_elem_flag_test_bool(e, BM_ELEM_HIDDEN);
124 }
125 }
126 },
127 [&]() {
128 BMIter iter;
129 BMFace *f;
130 int i;
132 if (sctx->callbacks.edit_mesh.test_face_fn) {
133 hide_poly.span[i] = !sctx->callbacks.edit_mesh.test_face_fn(
134 f, sctx->callbacks.edit_mesh.user_data);
135 }
136 else {
137 hide_poly.span[i] = BM_elem_flag_test_bool(f, BM_ELEM_HIDDEN);
138 }
139 }
140 });
141
142 hide_vert.finish();
143 hide_edge.finish();
144 hide_poly.finish();
145 return mesh;
146}
147
149 const Object *ob_eval,
150 bool create)
151{
152 SnapCache_EditMesh *em_cache = nullptr;
153
154 bool init = false;
155 const Mesh *mesh_ref = (G.moving) ? /* WORKAROUND:
156 * Avoid updating while transforming. Do not check if the
157 * reference mesh has been updated. */
158 nullptr :
159 get_mesh_ref(ob_eval);
160
161 if (std::unique_ptr<SnapObjectContext::SnapCache> *em_cache_p = sctx->editmesh_caches.lookup_ptr(
162 ob_eval->runtime->data_orig))
163 {
164 em_cache = static_cast<SnapCache_EditMesh *>(em_cache_p->get());
165
166 /* Check if the geometry has changed. */
167 if (mesh_ref && em_cache->has_mesh_updated(mesh_ref)) {
168 em_cache->clear();
169 init = true;
170 }
171 }
172 else if (create) {
173 std::unique_ptr<SnapCache_EditMesh> em_cache_ptr = std::make_unique<SnapCache_EditMesh>();
174 em_cache = em_cache_ptr.get();
175 sctx->editmesh_caches.add_new(ob_eval->runtime->data_orig, std::move(em_cache_ptr));
176 init = true;
177 }
178
179 if (init) {
180 em_cache->mesh = create_mesh(sctx, ob_eval, sctx->runtime.params.edit_mode_type);
181 if (mesh_ref) {
182 em_cache->mesh_ref = mesh_ref;
183 em_cache->runtime_ref = mesh_ref->runtime;
184 em_cache->edit_data_ref = mesh_ref->runtime->edit_data.get();
185 }
186 }
187
188 return em_cache;
189}
190
192
193/* -------------------------------------------------------------------- */
196
198{
199 eSnapMode snap_mode_supported = SCE_SNAP_TO_NONE;
200 if (bm->totface) {
203 }
204 else if (bm->totedge) {
205 snap_mode_supported |= SNAP_TO_EDGE_ELEMENTS | SCE_SNAP_TO_POINT;
206 }
207 else if (bm->totvert) {
208 snap_mode_supported |= SCE_SNAP_TO_POINT;
209 }
210 return snap_mode_supported;
211}
212
214 const Object *ob_eval,
215 eSnapMode snap_to_flag)
216{
217 const BMEditMesh *em = BKE_editmesh_from_object(const_cast<Object *>(DEG_get_original(ob_eval)));
218 if (em == nullptr) {
219 return nullptr;
220 }
221
222 SnapCache_EditMesh *em_cache = snap_object_data_editmesh_get(sctx, ob_eval, false);
223 if (em_cache != nullptr) {
224 return em_cache;
225 }
226
227 eSnapMode snap_mode_used = snap_to_flag & editmesh_snap_mode_supported(em->bm);
228 if (snap_mode_used == SCE_SNAP_TO_NONE) {
229 return nullptr;
230 }
231
232 return snap_object_data_editmesh_get(sctx, ob_eval, true);
233}
234
236
238 const Object *ob_eval,
239 const ID * /*id*/,
240 const float4x4 &obmat,
241 eSnapMode snap_to_flag,
242 bool /*use_hide*/)
243{
244 SnapCache_EditMesh *em_cache = editmesh_snapdata_init(sctx, ob_eval, snap_to_flag);
245 if (em_cache && em_cache->mesh) {
246 return snap_object_mesh(sctx, ob_eval, &em_cache->mesh->id, obmat, snap_to_flag, true, true);
247 }
248 return SCE_SNAP_TO_NONE;
249}
250
251} // namespace blender::ed::transform
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:61
void BKE_id_free(Main *bmain, void *idv)
void * BKE_id_new_nomain(short type, const char *name)
Definition lib_id.cc:1500
General operations, lookup, etc. for blender objects.
const Mesh * BKE_object_get_editmesh_eval_cage(const Object *object)
const Mesh * BKE_object_get_editmesh_eval_final(const Object *object)
T * DEG_get_original(T *id)
@ SCE_SNAP_INDIVIDUAL_NEAREST
@ SCE_SNAP_TO_FACE
@ SCE_SNAP_TO_POINT
@ SCE_SNAP_TO_NONE
@ BM_ELEM_HIDDEN
#define BM_elem_flag_test_bool(ele, hflag)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
BMesh * bm
void BM_mesh_bm_to_me_compact(BMesh &bm, Mesh &mesh, const CustomData_MeshMasks *mask, const bool add_mesh_attributes)
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
#define this
#define G(x, y, z)
static const Mesh * get_mesh_ref(const Object *ob_eval)
static SnapCache_EditMesh * snap_object_data_editmesh_get(SnapObjectContext *sctx, const Object *ob_eval, bool create)
eSnapMode snap_object_mesh(SnapObjectContext *sctx, const Object *ob_eval, const ID *id, const float4x4 &obmat, eSnapMode snap_to_flag, bool skip_hidden, bool is_editmesh=false)
eSnapMode snap_object_editmesh(SnapObjectContext *sctx, const Object *ob_eval, const ID *id, const float4x4 &obmat, eSnapMode snap_to_flag, bool use_hide)
static SnapCache_EditMesh * editmesh_snapdata_init(SnapObjectContext *sctx, const Object *ob_eval, eSnapMode snap_to_flag)
static Mesh * create_mesh(SnapObjectContext *sctx, const Object *ob_eval, eSnapEditType)
static eSnapMode editmesh_snap_mode_supported(BMesh *bm)
void parallel_invoke(Functions &&...functions)
Definition BLI_task.hh:221
MatBase< float, 4, 4 > float4x4
static void init(bNodeTree *, bNode *node)
Definition DNA_ID.h:404
MeshRuntimeHandle * runtime
ObjectRuntimeHandle * runtime
struct blender::ed::transform::SnapObjectContext::@050234250074125370117204111326226263104177061171 runtime
bool(* test_edge_fn)(BMEdge *, void *user_data)
bool(* test_face_fn)(BMFace *, void *user_data)
bool(* test_vert_fn)(BMVert *, void *user_data)
struct blender::ed::transform::SnapObjectContext::@177172077214017204166102251345003071342254304273::@230110077146263070013032025175364155315020002303 edit_mesh
struct blender::ed::transform::SnapObjectContext::@177172077214017204166102251345003071342254304273 callbacks
Map< const ID *, std::unique_ptr< SnapCache > > editmesh_caches
i
Definition text_draw.cc:230
#define SNAP_TO_EDGE_ELEMENTS