Blender V4.5
mball.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11
12#include <cctype>
13#include <cfloat>
14#include <cmath>
15#include <cstdlib>
16#include <cstring>
17#include <optional>
18
19#include "MEM_guardedalloc.h"
20
21/* Allow using deprecated functionality for .blend file I/O. */
22#define DNA_DEPRECATED_ALLOW
23
24#include "DNA_defaults.h"
25#include "DNA_material_types.h"
26#include "DNA_mesh_types.h"
27#include "DNA_meta_types.h"
28#include "DNA_object_types.h"
29#include "DNA_scene_types.h"
30
31#include "BLI_listbase.h"
32#include "BLI_math_matrix.h"
33#include "BLI_math_rotation.h"
34#include "BLI_math_vector.h"
35#include "BLI_string_utils.hh"
36#include "BLI_utildefines.h"
37
38#include "BLT_translation.hh"
39
40#include "BKE_main.hh"
41
42#include "BKE_geometry_set.hh"
43#include "BKE_idtype.hh"
44#include "BKE_lattice.hh"
45#include "BKE_layer.hh"
46#include "BKE_lib_id.hh"
47#include "BKE_lib_query.hh"
48#include "BKE_library.hh"
49#include "BKE_mball.hh"
51#include "BKE_object.hh"
52#include "BKE_object_types.hh"
53
54#include "DEG_depsgraph.hh"
55
56#include "BLO_read_write.hh"
57
58using blender::Span;
59
68
69static void metaball_copy_data(Main * /*bmain*/,
70 std::optional<Library *> /*owner_library*/,
71 ID *id_dst,
72 const ID *id_src,
73 const int /*flag*/)
74{
75 MetaBall *metaball_dst = (MetaBall *)id_dst;
76 const MetaBall *metaball_src = (const MetaBall *)id_src;
77
78 BLI_duplicatelist(&metaball_dst->elems, &metaball_src->elems);
79
80 metaball_dst->mat = static_cast<Material **>(MEM_dupallocN(metaball_src->mat));
81
82 metaball_dst->editelems = nullptr;
83 metaball_dst->lastelem = nullptr;
84}
85
86static void metaball_free_data(ID *id)
87{
88 MetaBall *metaball = (MetaBall *)id;
89
91
92 BLI_freelistN(&metaball->elems);
93}
94
96{
97 MetaBall *metaball = reinterpret_cast<MetaBall *>(id);
99
100 for (int i = 0; i < metaball->totcol; i++) {
102 }
103
106 }
107}
108
109static void metaball_blend_write(BlendWriter *writer, ID *id, const void *id_address)
110{
111 MetaBall *mb = (MetaBall *)id;
112
113 /* Clean up, important in undo case to reduce false detection of changed datablocks. */
114 mb->editelems = nullptr;
115 /* Must always be cleared (meta's don't have their own edit-data). */
116 mb->needs_flush_to_id = 0;
117 mb->lastelem = nullptr;
118
119 /* write LibData */
120 BLO_write_id_struct(writer, MetaBall, id_address, &mb->id);
121 BKE_id_blend_write(writer, &mb->id);
122
123 /* direct data */
124 BLO_write_pointer_array(writer, mb->totcol, mb->mat);
125
126 LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
127 BLO_write_struct(writer, MetaElem, ml);
128 }
129}
130
132{
133 MetaBall *mb = (MetaBall *)id;
134
135 BLO_read_pointer_array(reader, mb->totcol, (void **)&mb->mat);
136
137 BLO_read_struct_list(reader, MetaElem, &(mb->elems));
138
139 mb->editelems = nullptr;
140 /* Must always be cleared (meta's don't have their own edit-data). */
141 mb->needs_flush_to_id = 0;
142 // mb->edit_elems.first = mb->edit_elems.last = nullptr;
143 mb->lastelem = nullptr;
144}
145
147 /*id_code*/ MetaBall::id_type,
148 /*id_filter*/ FILTER_ID_MB,
149 /*dependencies_id_types*/ FILTER_ID_MA,
150 /*main_listbase_index*/ INDEX_ID_MB,
151 /*struct_size*/ sizeof(MetaBall),
152 /*name*/ "Metaball",
153 /*name_plural*/ N_("metaballs"),
154 /*translation_context*/ BLT_I18NCONTEXT_ID_METABALL,
156 /*asset_type_info*/ nullptr,
157
158 /*init_data*/ metaball_init_data,
159 /*copy_data*/ metaball_copy_data,
160 /*free_data*/ metaball_free_data,
161 /*make_local*/ nullptr,
162 /*foreach_id*/ metaball_foreach_id,
163 /*foreach_cache*/ nullptr,
164 /*foreach_path*/ nullptr,
165 /*owner_pointer_get*/ nullptr,
166
167 /*blend_write*/ metaball_blend_write,
168 /*blend_read_data*/ metaball_blend_read_data,
169 /*blend_read_after_liblink*/ nullptr,
170
171 /*blend_read_undo_preserve*/ nullptr,
172
173 /*lib_override_apply_post*/ nullptr,
174};
175
176/* Functions */
177
178MetaBall *BKE_mball_add(Main *bmain, const char *name)
179{
180 MetaBall *mb = BKE_id_new<MetaBall>(bmain, name);
181 return mb;
182}
183
185{
186 MetaElem *ml = MEM_callocN<MetaElem>(__func__);
187
188 unit_qt(ml->quat);
189
190 ml->rad = 2.0;
191 ml->s = 2.0;
192 ml->flag = MB_SCALE_RAD;
193
194 switch (type) {
195 case MB_BALL:
196 ml->type = MB_BALL;
197 ml->expx = ml->expy = ml->expz = 1.0;
198
199 break;
200 case MB_TUBE:
201 ml->type = MB_TUBE;
202 ml->expx = ml->expy = ml->expz = 1.0;
203
204 break;
205 case MB_PLANE:
206 ml->type = MB_PLANE;
207 ml->expx = ml->expy = ml->expz = 1.0;
208
209 break;
210 case MB_ELIPSOID:
211 ml->type = MB_ELIPSOID;
212 ml->expx = 1.2f;
213 ml->expy = 0.8f;
214 ml->expz = 1.0;
215
216 break;
217 case MB_CUBE:
218 ml->type = MB_CUBE;
219 ml->expx = ml->expy = ml->expz = 1.0;
220
221 break;
222 default:
223 break;
224 }
225
226 BLI_addtail(&mb->elems, ml);
227
228 return ml;
229}
230
232{
233 blender::float2 radius_stiffness = {
234 /* Display radius. */
235 ml->rad,
236 /* Display stiffness. */
237 ml->rad * atanf(ml->s) * float(2.0 / blender::math::numbers::pi),
238 };
239
240 if (ml->type == MB_CUBE) {
241 /* Without this additional size, the cube can't be selected in solid mode.
242 * Use the minimum size so this doesn't become too large because of one large axis.
243 * See: #136396. */
244 const float offset = min_fff(ml->expx, ml->expy, ml->expz) * M_SQRT2;
245 radius_stiffness[0] += offset;
246 radius_stiffness[1] += offset;
247 }
248 return radius_stiffness;
249}
251{
252 float radius = ml->rad;
253 if (ml->type == MB_CUBE) {
254 const float offset = min_fff(ml->expx, ml->expy, ml->expz) * M_SQRT2;
255 radius += offset;
256 }
257 return radius;
258}
259
261{
262 /* Meta-Ball Basis Notes from Blender-2.5x
263 * =======================================
264 *
265 * NOTE(@ideasman42): This is a can of worms.
266 *
267 * This really needs a rewrite/refactor its totally broken in anything other than basic cases
268 * Multiple Scenes + Set Scenes & mixing meta-ball basis _should_ work but fails to update the
269 * depsgraph on rename and linking into scenes or removal of basis meta-ball.
270 * So take care when changing this code.
271 *
272 * Main idiot thing here is that the system returns #BKE_mball_basis_find()
273 * objects which fail a #BKE_mball_is_basis() test.
274 *
275 * Not only that but the depsgraph and their areas depend on this behavior,
276 * so making small fixes here isn't worth it. */
277
278 /* Just a quick test. */
279 const int len = strlen(ob->id.name);
280 return !isdigit(ob->id.name[len - 1]);
281}
282
283bool BKE_mball_is_same_group(const Object *ob1, const Object *ob2)
284{
285 int basis1nr, basis2nr;
286 char basis1name[MAX_ID_NAME], basis2name[MAX_ID_NAME];
287
288 if (ob1->id.name[2] != ob2->id.name[2]) {
289 /* Quick return in case first char of both ID's names is not the same... */
290 return false;
291 }
292
293 BLI_string_split_name_number(ob1->id.name + 2, '.', basis1name, &basis1nr);
294 BLI_string_split_name_number(ob2->id.name + 2, '.', basis2name, &basis2nr);
295
296 return STREQ(basis1name, basis2name);
297}
298
299bool BKE_mball_is_basis_for(const Object *ob1, const Object *ob2)
300{
301 return BKE_mball_is_same_group(ob1, ob2) && BKE_mball_is_basis(ob1);
302}
303
305{
306 LISTBASE_FOREACH (const MetaElem *, ml, mb->editelems) {
307 if (ml->flag & SELECT) {
308 return true;
309 }
310 }
311 return false;
312}
313
315{
316 for (Base *base : bases) {
317 Object *obedit = base->object;
318 MetaBall *mb = (MetaBall *)obedit->data;
320 return true;
321 }
322 }
323 return false;
324}
325
327{
328 LISTBASE_FOREACH (const MetaElem *, ml, mb->editelems) {
329 if ((ml->flag & SELECT) == 0) {
330 return true;
331 }
332 }
333 return false;
334}
335
336static void mball_data_properties_copy(MetaBall *mb_dst, MetaBall *mb_src)
337{
338 mb_dst->wiresize = mb_src->wiresize;
339 mb_dst->rendersize = mb_src->rendersize;
340 mb_dst->thresh = mb_src->thresh;
341 mb_dst->flag = mb_src->flag;
342 DEG_id_tag_update(&mb_dst->id, 0);
343}
344
345void BKE_mball_properties_copy(Main *bmain, MetaBall *metaball_src)
346{
364 for (Object *ob_src = static_cast<Object *>(bmain->objects.first);
365 ob_src != nullptr && ID_IS_EDITABLE(ob_src);)
366 {
367 if (ob_src->data != metaball_src) {
368 ob_src = static_cast<Object *>(ob_src->id.next);
369 continue;
370 }
371
372 /* In this code we take advantage of two facts:
373 * - MetaBalls of the same family have the same basis name,
374 * - IDs are sorted by name in their Main listbase.
375 * So, all MetaBall objects of the same family are contiguous in bmain list (potentially mixed
376 * with non-meta-ball objects with same basis names).
377 *
378 * Using this, it is possible to process the whole set of meta-balls with a single loop on the
379 * whole list of Objects, though additionally going backward on part of the list in some cases.
380 */
381 Object *ob_iter = nullptr;
382 int obactive_nr, ob_nr;
383 char obactive_name[MAX_ID_NAME], ob_name[MAX_ID_NAME];
384 BLI_string_split_name_number(ob_src->id.name + 2, '.', obactive_name, &obactive_nr);
385
386 for (ob_iter = static_cast<Object *>(ob_src->id.prev); ob_iter != nullptr;
387 ob_iter = static_cast<Object *>(ob_iter->id.prev))
388 {
389 if (ob_iter->id.name[2] != obactive_name[0]) {
390 break;
391 }
392 if (ob_iter->type != OB_MBALL || ob_iter->data == metaball_src) {
393 continue;
394 }
395 BLI_string_split_name_number(ob_iter->id.name + 2, '.', ob_name, &ob_nr);
396 if (!STREQ(obactive_name, ob_name)) {
397 break;
398 }
399
400 mball_data_properties_copy(static_cast<MetaBall *>(ob_iter->data), metaball_src);
401 }
402
403 for (ob_iter = static_cast<Object *>(ob_src->id.next); ob_iter != nullptr;
404 ob_iter = static_cast<Object *>(ob_iter->id.next))
405 {
406 if (ob_iter->id.name[2] != obactive_name[0] || !ID_IS_EDITABLE(ob_iter)) {
407 break;
408 }
409 if (ob_iter->type != OB_MBALL || ob_iter->data == metaball_src) {
410 continue;
411 }
412 BLI_string_split_name_number(ob_iter->id.name + 2, '.', ob_name, &ob_nr);
413 if (!STREQ(obactive_name, ob_name)) {
414 break;
415 }
416
417 mball_data_properties_copy(static_cast<MetaBall *>(ob_iter->data), metaball_src);
418 }
419
420 ob_src = ob_iter;
421 }
422}
423
425{
426 Object *bob = object;
427 int basisnr, obnr;
428 char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
429
430 BLI_string_split_name_number(object->id.name + 2, '.', basisname, &basisnr);
431
432 LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
433 BKE_view_layer_synced_ensure(scene, view_layer);
435 Object *ob = base->object;
436 if ((ob->type == OB_MBALL) && !(base->flag & BASE_FROM_DUPLI)) {
437 if (ob != bob) {
438 BLI_string_split_name_number(ob->id.name + 2, '.', obname, &obnr);
439
440 /* Object ob has to be in same "group" ... it means,
441 * that it has to have same base of its name. */
442 if (STREQ(obname, basisname)) {
443 if (obnr < basisnr) {
444 object = ob;
445 basisnr = obnr;
446 }
447 }
448 }
449 }
450 }
451 }
452
453 return object;
454}
455
457 const MetaBall *mb, float min[3], float max[3], const float obmat[4][4], const short flag)
458{
459 const float scale = obmat ? mat4_to_scale(obmat) : 1.0f;
460 bool changed = false;
461 float centroid[3], vec[3];
462
464
465 LISTBASE_FOREACH (const MetaElem *, ml, &mb->elems) {
466 if ((ml->flag & flag) == flag) {
467 const float scale_mb = (ml->rad * 0.5f) * scale;
468
469 if (obmat) {
470 mul_v3_m4v3(centroid, obmat, &ml->x);
471 }
472 else {
473 copy_v3_v3(centroid, &ml->x);
474 }
475
476 /* TODO(@ideasman42): non circle shapes cubes etc, probably nobody notices. */
477 for (int i = -1; i != 3; i += 2) {
478 copy_v3_v3(vec, centroid);
479 add_v3_fl(vec, scale_mb * i);
480 minmax_v3v3_v3(min, max, vec);
481 }
482 changed = true;
483 }
484 }
485
486 return changed;
487}
488
489bool BKE_mball_minmax(const MetaBall *mb, float min[3], float max[3])
490{
492
493 LISTBASE_FOREACH (const MetaElem *, ml, &mb->elems) {
494 minmax_v3v3_v3(min, max, &ml->x);
495 }
496
497 return (BLI_listbase_is_empty(&mb->elems) == false);
498}
499
500bool BKE_mball_center_median(const MetaBall *mb, float r_cent[3])
501{
502 int total = 0;
503
504 zero_v3(r_cent);
505
506 LISTBASE_FOREACH (const MetaElem *, ml, &mb->elems) {
507 add_v3_v3(r_cent, &ml->x);
508 total++;
509 }
510
511 if (total) {
512 mul_v3_fl(r_cent, 1.0f / float(total));
513 }
514
515 return (total != 0);
516}
517
518bool BKE_mball_center_bounds(const MetaBall *mb, float r_cent[3])
519{
520 float min[3], max[3];
521
522 if (BKE_mball_minmax(mb, min, max)) {
523 mid_v3_v3v3(r_cent, min, max);
524 return true;
525 }
526
527 return false;
528}
529
530void BKE_mball_transform(MetaBall *mb, const float mat[4][4], const bool do_props)
531{
532 float quat[4];
533 const float scale = mat4_to_scale(mat);
534 const float scale_sqrt = sqrtf(scale);
535
536 mat4_to_quat(quat, mat);
537
538 LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
539 mul_m4_v3(mat, &ml->x);
540 mul_qt_qtqt(ml->quat, quat, ml->quat);
541
542 if (do_props) {
543 ml->rad *= scale;
544 /* hrmf, probably elems shouldn't be
545 * treating scale differently - campbell */
546 if (!MB_TYPE_SIZE_SQUARED(ml->type)) {
547 mul_v3_fl(&ml->expx, scale);
548 }
549 else {
550 mul_v3_fl(&ml->expx, scale_sqrt);
551 }
552 }
553 }
554}
555
556void BKE_mball_translate(MetaBall *mb, const float offset[3])
557{
558 LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
559 add_v3_v3(&ml->x, offset);
560 }
561}
562
564{
565 int sel = 0;
566 LISTBASE_FOREACH (const MetaElem *, ml, mb->editelems) {
567 if (ml->flag & SELECT) {
568 sel++;
569 }
570 }
571 return sel;
572}
573
575{
576 int sel = 0;
577 for (Base *base : bases) {
578 Object *obedit = base->object;
579 const MetaBall *mb = (MetaBall *)obedit->data;
580 sel += BKE_mball_select_count(mb);
581 }
582 return sel;
583}
584
586{
587 bool changed = false;
588 LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
589 if ((ml->flag & SELECT) == 0) {
590 ml->flag |= SELECT;
591 changed = true;
592 }
593 }
594 return changed;
595}
596
598{
599 bool changed_multi = false;
600 for (Base *base : bases) {
601 Object *obedit = base->object;
602 MetaBall *mb = static_cast<MetaBall *>(obedit->data);
603 changed_multi |= BKE_mball_select_all(mb);
604 }
605 return changed_multi;
606}
607
609{
610 bool changed = false;
611 LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
612 if ((ml->flag & SELECT) != 0) {
613 ml->flag &= ~SELECT;
614 changed = true;
615 }
616 }
617 return changed;
618}
619
621{
622 bool changed_multi = false;
623 for (Base *base : bases) {
624 Object *obedit = base->object;
625 MetaBall *mb = static_cast<MetaBall *>(obedit->data);
626 changed_multi |= BKE_mball_deselect_all(mb);
628 }
629 return changed_multi;
630}
631
633{
634 bool changed = false;
635 LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
636 ml->flag ^= SELECT;
637 changed = true;
638 }
639 return changed;
640}
641
643{
644 bool changed_multi = false;
645 for (Base *base : bases) {
646 Object *obedit = base->object;
647 MetaBall *mb = (MetaBall *)obedit->data;
648 changed_multi |= BKE_mball_select_swap(mb);
649 }
650 return changed_multi;
651}
652
653/* **** Depsgraph evaluation **** */
654
655void BKE_mball_data_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
656{
657 using namespace blender;
658 using namespace blender::bke;
659 BLI_assert(ob->type == OB_MBALL);
660
662
663 const Object *basis_object = BKE_mball_basis_find(scene, ob);
664 if (ob != basis_object) {
665 return;
666 }
667
669 if (mesh == nullptr) {
670 return;
671 }
672
673 const MetaBall *mball = static_cast<MetaBall *>(ob->data);
674 mesh->mat = static_cast<Material **>(MEM_dupallocN(mball->mat));
675 mesh->totcol = mball->totcol;
676
677 if (ob->parent && ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) {
679 ob->parent,
680 ob,
681 reinterpret_cast<float(*)[3]>(mesh->vert_positions_for_write().data()),
682 mesh->verts_num,
683 0,
684 nullptr,
685 1.0f);
686 mesh->tag_positions_changed();
687 }
688
689 ob->runtime->geometry_set_eval = new GeometrySet(GeometrySet::from_mesh(mesh));
690};
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition BKE_idtype.hh:44
IDTypeInfo IDType_ID_MB
Definition mball.cc:146
void BKE_lattice_deform_coords(const Object *ob_lattice, const Object *ob_target, float(*vert_coords)[3], int vert_coords_len, short flag, const char *defgrp_name, float fac)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
ListBase * BKE_view_layer_object_bases_get(ViewLayer *view_layer)
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1495
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2611
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
@ IDWALK_CB_USER
LibraryForeachIDFlag BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
Definition lib_query.cc:129
@ IDWALK_DO_DEPRECATED_POINTERS
#define BKE_LIB_FOREACHID_PROCESS_ID_NOCHECK(data_, id_, cb_flag_)
Mesh * BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
General operations, lookup, etc. for blender objects.
void BKE_object_free_derived_caches(Object *ob)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void void void void void void BLI_duplicatelist(ListBase *dst, const ListBase *src) ATTR_NONNULL(1
MINLINE float min_fff(float a, float b, float c)
#define M_SQRT2
float mat4_to_scale(const float mat[4][4])
void mul_m4_v3(const float M[4][4], float r[3])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
void unit_qt(float q[4])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
void mat4_to_quat(float q[4], const float mat[4][4])
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
MINLINE void add_v3_fl(float r[3], float f)
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
#define INIT_MINMAX(min, max)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define STREQ(a, b)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
void BLO_write_pointer_array(BlendWriter *writer, int64_t num, const void *data_ptr)
void BLO_read_pointer_array(BlendDataReader *reader, int64_t array_size, void **ptr_p)
Definition readfile.cc:5402
#define BLT_I18NCONTEXT_ID_METABALL
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_SELECT
Definition DNA_ID.h:1009
@ INDEX_ID_MB
Definition DNA_ID.h:1236
#define DNA_struct_default_get(struct_name)
@ BASE_FROM_DUPLI
#define MB_TYPE_SIZE_SQUARED(type)
@ MB_SCALE_RAD
@ MB_PLANE
@ MB_ELIPSOID
@ MB_TUBE
@ MB_CUBE
@ MB_BALL
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OB_MBALL
@ PARSKEL
Read Guarded memory(de)allocation.
blender::StringRef BLI_string_split_name_number(const blender::StringRef name_full, const char delim, int &r_number)
BMesh const char void * data
BPy_StructRNA * depsgraph
#define SELECT
#define atanf(x)
#define sqrtf(x)
#define FILTER_ID_MA
#define MEM_SAFE_FREE(v)
#define FILTER_ID_MB
#define MAX_ID_NAME
#define ID_IS_EDITABLE(_id)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
static void metaball_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition mball.cc:109
void BKE_mball_data_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
Definition mball.cc:655
Object * BKE_mball_basis_find(Scene *scene, Object *object)
Definition mball.cc:424
bool BKE_mball_is_same_group(const Object *ob1, const Object *ob2)
Definition mball.cc:283
int BKE_mball_select_count(const MetaBall *mb)
Definition mball.cc:563
void BKE_mball_properties_copy(Main *bmain, MetaBall *metaball_src)
Definition mball.cc:345
bool BKE_mball_deselect_all(MetaBall *mb)
Definition mball.cc:608
bool BKE_mball_is_any_selected_multi(const Span< Base * > bases)
Definition mball.cc:314
bool BKE_mball_minmax_ex(const MetaBall *mb, float min[3], float max[3], const float obmat[4][4], const short flag)
Definition mball.cc:456
bool BKE_mball_center_bounds(const MetaBall *mb, float r_cent[3])
Definition mball.cc:518
bool BKE_mball_is_any_unselected(const MetaBall *mb)
Definition mball.cc:326
bool BKE_mball_select_swap_multi_ex(const Span< Base * > bases)
Definition mball.cc:642
MetaBall * BKE_mball_add(Main *bmain, const char *name)
Definition mball.cc:178
static void metaball_copy_data(Main *, std::optional< Library * >, ID *id_dst, const ID *id_src, const int)
Definition mball.cc:69
static void metaball_blend_read_data(BlendDataReader *reader, ID *id)
Definition mball.cc:131
void BKE_mball_translate(MetaBall *mb, const float offset[3])
Definition mball.cc:556
bool BKE_mball_minmax(const MetaBall *mb, float min[3], float max[3])
Definition mball.cc:489
static void mball_data_properties_copy(MetaBall *mb_dst, MetaBall *mb_src)
Definition mball.cc:336
bool BKE_mball_center_median(const MetaBall *mb, float r_cent[3])
Definition mball.cc:500
static void metaball_init_data(ID *id)
Definition mball.cc:60
blender::float2 BKE_mball_element_display_radius_calc_with_stiffness(const MetaElem *ml)
Definition mball.cc:231
static void metaball_foreach_id(ID *id, LibraryForeachIDData *data)
Definition mball.cc:95
float BKE_mball_element_display_radius_calc(const MetaElem *ml)
Definition mball.cc:250
bool BKE_mball_is_basis(const Object *ob)
Definition mball.cc:260
static void metaball_free_data(ID *id)
Definition mball.cc:86
bool BKE_mball_select_swap(MetaBall *mb)
Definition mball.cc:632
bool BKE_mball_is_any_selected(const MetaBall *mb)
Definition mball.cc:304
bool BKE_mball_deselect_all_multi_ex(const Span< Base * > bases)
Definition mball.cc:620
void BKE_mball_transform(MetaBall *mb, const float mat[4][4], const bool do_props)
Definition mball.cc:530
bool BKE_mball_select_all(MetaBall *mb)
Definition mball.cc:585
bool BKE_mball_select_all_multi_ex(const Span< Base * > bases)
Definition mball.cc:597
int BKE_mball_select_count_multi(const Span< Base * > bases)
Definition mball.cc:574
MetaElem * BKE_mball_element_add(MetaBall *mb, const int type)
Definition mball.cc:184
bool BKE_mball_is_basis_for(const Object *ob1, const Object *ob2)
Definition mball.cc:299
static float metaball(PROCESS *process, float x, float y, float z)
VecBase< float, 2 > float2
#define min(a, b)
Definition sort.cc:36
static GeometrySet from_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Definition DNA_ID.h:404
void * prev
Definition DNA_ID.h:407
void * next
Definition DNA_ID.h:407
char name[66]
Definition DNA_ID.h:415
void * first
ListBase objects
Definition BKE_main.hh:247
MetaElem * lastelem
ListBase elems
float rendersize
float wiresize
ListBase * editelems
char needs_flush_to_id
struct Material ** mat
float quat[4]
ObjectRuntimeHandle * runtime
struct Object * parent
ListBase view_layers
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
uint len
#define N_(msgid)
uint8_t flag
Definition wm_window.cc:139