1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17 * All rights reserved.
18 * MetaBalls are created from a single Object (with a name without number in it),
19 * here the DispList and BoundBox also is located.
20 * All objects with the same name (but with a number in it) are added to this.
21 *
22 * texture coordinates are patched within the displist
23 */
24
25 /** \file
26 * \ingroup bke
27 */
28
29 #include <ctype.h>
30 #include <float.h>
31 #include <math.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "MEM_guardedalloc.h"
37
38 /* Allow using deprecated functionality for .blend file I/O. */
39 #define DNA_DEPRECATED_ALLOW
40
41 #include "DNA_defaults.h"
42 #include "DNA_material_types.h"
43 #include "DNA_meta_types.h"
44 #include "DNA_object_types.h"
45 #include "DNA_scene_types.h"
46
47 #include "BLI_blenlib.h"
48 #include "BLI_math.h"
49 #include "BLI_string_utils.h"
50 #include "BLI_utildefines.h"
51
52 #include "BLT_translation.h"
53
54 #include "BKE_main.h"
55
56 #include "BKE_anim_data.h"
57 #include "BKE_curve.h"
58 #include "BKE_displist.h"
59 #include "BKE_idtype.h"
60 #include "BKE_lib_id.h"
61 #include "BKE_lib_query.h"
62 #include "BKE_material.h"
63 #include "BKE_mball.h"
64 #include "BKE_object.h"
65 #include "BKE_scene.h"
66
67 #include "DEG_depsgraph.h"
68
69 #include "BLO_read_write.h"
70
metaball_init_data(ID * id)71 static void metaball_init_data(ID *id)
72 {
73 MetaBall *metaball = (MetaBall *)id;
74
75 BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(metaball, id));
76
77 MEMCPY_STRUCT_AFTER(metaball, DNA_struct_default_get(MetaBall), id);
78 }
79
metaball_copy_data(Main * UNUSED (bmain),ID * id_dst,const ID * id_src,const int UNUSED (flag))80 static void metaball_copy_data(Main *UNUSED(bmain),
81 ID *id_dst,
82 const ID *id_src,
83 const int UNUSED(flag))
84 {
85 MetaBall *metaball_dst = (MetaBall *)id_dst;
86 const MetaBall *metaball_src = (const MetaBall *)id_src;
87
88 BLI_duplicatelist(&metaball_dst->elems, &metaball_src->elems);
89
90 metaball_dst->mat = MEM_dupallocN(metaball_src->mat);
91
92 metaball_dst->editelems = NULL;
93 metaball_dst->lastelem = NULL;
94 metaball_dst->batch_cache = NULL;
95 }
96
metaball_free_data(ID * id)97 static void metaball_free_data(ID *id)
98 {
99 MetaBall *metaball = (MetaBall *)id;
100
101 BKE_mball_batch_cache_free(metaball);
102
103 MEM_SAFE_FREE(metaball->mat);
104
105 BLI_freelistN(&metaball->elems);
106 if (metaball->disp.first) {
107 BKE_displist_free(&metaball->disp);
108 }
109 }
110
metaball_foreach_id(ID * id,LibraryForeachIDData * data)111 static void metaball_foreach_id(ID *id, LibraryForeachIDData *data)
112 {
113 MetaBall *metaball = (MetaBall *)id;
114 for (int i = 0; i < metaball->totcol; i++) {
115 BKE_LIB_FOREACHID_PROCESS(data, metaball->mat[i], IDWALK_CB_USER);
116 }
117 }
118
metaball_blend_write(BlendWriter * writer,ID * id,const void * id_address)119 static void metaball_blend_write(BlendWriter *writer, ID *id, const void *id_address)
120 {
121 MetaBall *mb = (MetaBall *)id;
122 if (mb->id.us > 0 || BLO_write_is_undo(writer)) {
123 /* Clean up, important in undo case to reduce false detection of changed datablocks. */
124 BLI_listbase_clear(&mb->disp);
125 mb->editelems = NULL;
126 /* Must always be cleared (meta's don't have their own edit-data). */
127 mb->needs_flush_to_id = 0;
128 mb->lastelem = NULL;
129 mb->batch_cache = NULL;
130
131 /* write LibData */
132 BLO_write_id_struct(writer, MetaBall, id_address, &mb->id);
133 BKE_id_blend_write(writer, &mb->id);
134
135 /* direct data */
136 BLO_write_pointer_array(writer, mb->totcol, mb->mat);
137 if (mb->adt) {
138 BKE_animdata_blend_write(writer, mb->adt);
139 }
140
141 LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
142 BLO_write_struct(writer, MetaElem, ml);
143 }
144 }
145 }
146
metaball_blend_read_data(BlendDataReader * reader,ID * id)147 static void metaball_blend_read_data(BlendDataReader *reader, ID *id)
148 {
149 MetaBall *mb = (MetaBall *)id;
150 BLO_read_data_address(reader, &mb->adt);
151 BKE_animdata_blend_read_data(reader, mb->adt);
152
153 BLO_read_pointer_array(reader, (void **)&mb->mat);
154
155 BLO_read_list(reader, &(mb->elems));
156
157 BLI_listbase_clear(&mb->disp);
158 mb->editelems = NULL;
159 /* Must always be cleared (meta's don't have their own edit-data). */
160 mb->needs_flush_to_id = 0;
161 /* mb->edit_elems.first= mb->edit_elems.last= NULL;*/
162 mb->lastelem = NULL;
163 mb->batch_cache = NULL;
164 }
165
metaball_blend_read_lib(BlendLibReader * reader,ID * id)166 static void metaball_blend_read_lib(BlendLibReader *reader, ID *id)
167 {
168 MetaBall *mb = (MetaBall *)id;
169 for (int a = 0; a < mb->totcol; a++) {
170 BLO_read_id_address(reader, mb->id.lib, &mb->mat[a]);
171 }
172
173 BLO_read_id_address(reader, mb->id.lib, &mb->ipo); // XXX deprecated - old animation system
174 }
175
metaball_blend_read_expand(BlendExpander * expander,ID * id)176 static void metaball_blend_read_expand(BlendExpander *expander, ID *id)
177 {
178 MetaBall *mb = (MetaBall *)id;
179 for (int a = 0; a < mb->totcol; a++) {
180 BLO_expand(expander, mb->mat[a]);
181 }
182 }
183
184 IDTypeInfo IDType_ID_MB = {
185 .id_code = ID_MB,
186 .id_filter = FILTER_ID_MB,
187 .main_listbase_index = INDEX_ID_MB,
188 .struct_size = sizeof(MetaBall),
189 .name = "Metaball",
190 .name_plural = "metaballs",
191 .translation_context = BLT_I18NCONTEXT_ID_METABALL,
192 .flags = 0,
193
194 .init_data = metaball_init_data,
195 .copy_data = metaball_copy_data,
196 .free_data = metaball_free_data,
197 .make_local = NULL,
198 .foreach_id = metaball_foreach_id,
199 .foreach_cache = NULL,
200
201 .blend_write = metaball_blend_write,
202 .blend_read_data = metaball_blend_read_data,
203 .blend_read_lib = metaball_blend_read_lib,
204 .blend_read_expand = metaball_blend_read_expand,
205 };
206
207 /* Functions */
208
BKE_mball_add(Main * bmain,const char * name)209 MetaBall *BKE_mball_add(Main *bmain, const char *name)
210 {
211 MetaBall *mb;
212
213 mb = BKE_id_new(bmain, ID_MB, name);
214
215 return mb;
216 }
217
218 /* most simple meta-element adding function
219 * don't do context manipulation here (rna uses) */
BKE_mball_element_add(MetaBall * mb,const int type)220 MetaElem *BKE_mball_element_add(MetaBall *mb, const int type)
221 {
222 MetaElem *ml = MEM_callocN(sizeof(MetaElem), "metaelem");
223
224 unit_qt(ml->quat);
225
226 ml->rad = 2.0;
227 ml->s = 2.0;
228 ml->flag = MB_SCALE_RAD;
229
230 switch (type) {
231 case MB_BALL:
232 ml->type = MB_BALL;
233 ml->expx = ml->expy = ml->expz = 1.0;
234
235 break;
236 case MB_TUBE:
237 ml->type = MB_TUBE;
238 ml->expx = ml->expy = ml->expz = 1.0;
239
240 break;
241 case MB_PLANE:
242 ml->type = MB_PLANE;
243 ml->expx = ml->expy = ml->expz = 1.0;
244
245 break;
246 case MB_ELIPSOID:
247 ml->type = MB_ELIPSOID;
248 ml->expx = 1.2f;
249 ml->expy = 0.8f;
250 ml->expz = 1.0;
251
252 break;
253 case MB_CUBE:
254 ml->type = MB_CUBE;
255 ml->expx = ml->expy = ml->expz = 1.0;
256
257 break;
258 default:
259 break;
260 }
261
262 BLI_addtail(&mb->elems, ml);
263
264 return ml;
265 }
266 /**
267 * Compute bounding box of all #MetaElem / #MetaBall
268 *
269 * Bounding box is computed from polygonized surface. \a ob is
270 * basic meta-balls (with name `Meta` for example). All other meta-ball objects
271 * (with names `Meta.001`, `Meta.002`, etc) are included in this bounding-box.
272 */
BKE_mball_texspace_calc(Object * ob)273 void BKE_mball_texspace_calc(Object *ob)
274 {
275 DispList *dl;
276 BoundBox *bb;
277 float *data, min[3], max[3] /*, loc[3], size[3] */;
278 int tot;
279 bool do_it = false;
280
281 if (ob->runtime.bb == NULL) {
282 ob->runtime.bb = MEM_callocN(sizeof(BoundBox), "mb boundbox");
283 }
284 bb = ob->runtime.bb;
285
286 /* Weird one, this. */
287 /* INIT_MINMAX(min, max); */
288 (min)[0] = (min)[1] = (min)[2] = 1.0e30f;
289 (max)[0] = (max)[1] = (max)[2] = -1.0e30f;
290
291 dl = ob->runtime.curve_cache->disp.first;
292 while (dl) {
293 tot = dl->nr;
294 if (tot) {
295 do_it = true;
296 }
297 data = dl->verts;
298 while (tot--) {
299 /* Also weird... but longer. From utildefines. */
300 minmax_v3v3_v3(min, max, data);
301 data += 3;
302 }
303 dl = dl->next;
304 }
305
306 if (!do_it) {
307 min[0] = min[1] = min[2] = -1.0f;
308 max[0] = max[1] = max[2] = 1.0f;
309 }
310
311 BKE_boundbox_init_from_minmax(bb, min, max);
312
313 bb->flag &= ~BOUNDBOX_DIRTY;
314 }
315
316 /** Return or compute bbox for given metaball object. */
BKE_mball_boundbox_get(Object * ob)317 BoundBox *BKE_mball_boundbox_get(Object *ob)
318 {
319 BLI_assert(ob->type == OB_MBALL);
320
321 if (ob->runtime.bb != NULL && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
322 return ob->runtime.bb;
323 }
324
325 /* This should always only be called with evaluated objects,
326 * but currently RNA is a problem here... */
327 if (ob->runtime.curve_cache != NULL) {
328 BKE_mball_texspace_calc(ob);
329 }
330
331 return ob->runtime.bb;
332 }
333
BKE_mball_make_orco(Object * ob,ListBase * dispbase)334 float *BKE_mball_make_orco(Object *ob, ListBase *dispbase)
335 {
336 BoundBox *bb;
337 DispList *dl;
338 float *data, *orco, *orcodata;
339 float loc[3], size[3];
340 int a;
341
342 /* restore size and loc */
343 bb = ob->runtime.bb;
344 loc[0] = (bb->vec[0][0] + bb->vec[4][0]) / 2.0f;
345 size[0] = bb->vec[4][0] - loc[0];
346 loc[1] = (bb->vec[0][1] + bb->vec[2][1]) / 2.0f;
347 size[1] = bb->vec[2][1] - loc[1];
348 loc[2] = (bb->vec[0][2] + bb->vec[1][2]) / 2.0f;
349 size[2] = bb->vec[1][2] - loc[2];
350
351 dl = dispbase->first;
352 orcodata = MEM_mallocN(sizeof(float[3]) * dl->nr, "MballOrco");
353
354 data = dl->verts;
355 orco = orcodata;
356 a = dl->nr;
357 while (a--) {
358 orco[0] = (data[0] - loc[0]) / size[0];
359 orco[1] = (data[1] - loc[1]) / size[1];
360 orco[2] = (data[2] - loc[2]) / size[2];
361
362 data += 3;
363 orco += 3;
364 }
365
366 return orcodata;
367 }
368
369 /**
370 * \brief Test, if \a ob is a basis meta-ball.
371 *
372 * It test last character of Object ID name. If last character
373 * is digit it return 0, else it return 1.
374 *
375 *
376 * Meta-Ball Basis Notes from Blender-2.5x
377 * =======================================
378 *
379 * This is a can of worms.
380 *
381 * This really needs a rewrite/refactor its totally broken in anything other than basic cases
382 * Multiple Scenes + Set Scenes & mixing meta-ball basis _should_ work but fails to update the
383 * depsgraph on rename and linking into scenes or removal of basis meta-ball.
384 * So take care when changing this code.
385 *
386 * Main idiot thing here is that the system returns #BKE_mball_basis_find()
387 * objects which fail a #BKE_mball_is_basis() test.
388 *
389 * Not only that but the depsgraph and their areas depend on this behavior,
390 * so making small fixes here isn't worth it.
391 * - Campbell
392 */
BKE_mball_is_basis(Object * ob)393 bool BKE_mball_is_basis(Object *ob)
394 {
395 /* just a quick test */
396 const int len = strlen(ob->id.name);
397 return (!isdigit(ob->id.name[len - 1]));
398 }
399
400 /* return nonzero if ob1 is a basis mball for ob */
BKE_mball_is_basis_for(Object * ob1,Object * ob2)401 bool BKE_mball_is_basis_for(Object *ob1, Object *ob2)
402 {
403 int basis1nr, basis2nr;
404 char basis1name[MAX_ID_NAME], basis2name[MAX_ID_NAME];
405
406 if (ob1->id.name[2] != ob2->id.name[2]) {
407 /* Quick return in case first char of both ID's names is not the same... */
408 return false;
409 }
410
411 BLI_split_name_num(basis1name, &basis1nr, ob1->id.name + 2, '.');
412 BLI_split_name_num(basis2name, &basis2nr, ob2->id.name + 2, '.');
413
414 if (STREQ(basis1name, basis2name)) {
415 return BKE_mball_is_basis(ob1);
416 }
417
418 return false;
419 }
420
BKE_mball_is_any_selected(const MetaBall * mb)421 bool BKE_mball_is_any_selected(const MetaBall *mb)
422 {
423 for (const MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next) {
424 if (ml->flag & SELECT) {
425 return true;
426 }
427 }
428 return false;
429 }
430
BKE_mball_is_any_selected_multi(Base ** bases,int bases_len)431 bool BKE_mball_is_any_selected_multi(Base **bases, int bases_len)
432 {
433 for (uint base_index = 0; base_index < bases_len; base_index++) {
434 Object *obedit = bases[base_index]->object;
435 MetaBall *mb = (MetaBall *)obedit->data;
436 if (BKE_mball_is_any_selected(mb)) {
437 return true;
438 }
439 }
440 return false;
441 }
442
BKE_mball_is_any_unselected(const MetaBall * mb)443 bool BKE_mball_is_any_unselected(const MetaBall *mb)
444 {
445 for (const MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next) {
446 if ((ml->flag & SELECT) == 0) {
447 return true;
448 }
449 }
450 return false;
451 }
452
453 /**
454 * \brief copy some properties from object to other meta-ball object with same base name
455 *
456 * When some properties (wire-size, threshold, update flags) of meta-ball are changed, then this
457 * properties are copied to all meta-balls in same "group" (meta-balls with same base name:
458 * `MBall`, `MBall.001`, `MBall.002`, etc). The most important is to copy properties to the base
459 * meta-ball, because this meta-ball influence polygonization of meta-balls. */
BKE_mball_properties_copy(Scene * scene,Object * active_object)460 void BKE_mball_properties_copy(Scene *scene, Object *active_object)
461 {
462 Scene *sce_iter = scene;
463 Base *base;
464 Object *ob;
465 MetaBall *active_mball = (MetaBall *)active_object->data;
466 int basisnr, obnr;
467 char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
468 SceneBaseIter iter;
469
470 BLI_split_name_num(basisname, &basisnr, active_object->id.name + 2, '.');
471
472 /* Pass depsgraph as NULL, which means we will not expand into
473 * duplis unlike when we generate the meta-ball. Expanding duplis
474 * would not be compatible when editing multiple view layers. */
475 BKE_scene_base_iter_next(NULL, &iter, &sce_iter, 0, NULL, NULL);
476 while (BKE_scene_base_iter_next(NULL, &iter, &sce_iter, 1, &base, &ob)) {
477 if (ob->type == OB_MBALL) {
478 if (ob != active_object) {
479 BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
480
481 /* Object ob has to be in same "group" ... it means, that it has to have
482 * same base of its name */
483 if (STREQ(obname, basisname)) {
484 MetaBall *mb = ob->data;
485
486 /* Copy properties from selected/edited metaball */
487 mb->wiresize = active_mball->wiresize;
488 mb->rendersize = active_mball->rendersize;
489 mb->thresh = active_mball->thresh;
490 mb->flag = active_mball->flag;
491 DEG_id_tag_update(&mb->id, 0);
492 }
493 }
494 }
495 }
496 }
497
498 /** \brief This function finds the basis MetaBall.
499 *
500 * Basis meta-ball doesn't include any number at the end of
501 * its name. All meta-balls with same base of name can be
502 * blended. meta-balls with different basic name can't be blended.
503 *
504 * \warning #BKE_mball_is_basis() can fail on returned object, see function docs for details.
505 */
BKE_mball_basis_find(Scene * scene,Object * object)506 Object *BKE_mball_basis_find(Scene *scene, Object *object)
507 {
508 Object *bob = object;
509 int basisnr, obnr;
510 char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
511
512 BLI_split_name_num(basisname, &basisnr, object->id.name + 2, '.');
513
514 LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
515 LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
516 Object *ob = base->object;
517 if ((ob->type == OB_MBALL) && !(base->flag & BASE_FROM_DUPLI)) {
518 if (ob != bob) {
519 BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
520
521 /* Object ob has to be in same "group" ... it means,
522 * that it has to have same base of its name. */
523 if (STREQ(obname, basisname)) {
524 if (obnr < basisnr) {
525 object = ob;
526 basisnr = obnr;
527 }
528 }
529 }
530 }
531 }
532 }
533
534 return object;
535 }
536
BKE_mball_minmax_ex(const MetaBall * mb,float min[3],float max[3],const float obmat[4][4],const short flag)537 bool BKE_mball_minmax_ex(
538 const MetaBall *mb, float min[3], float max[3], const float obmat[4][4], const short flag)
539 {
540 const float scale = obmat ? mat4_to_scale(obmat) : 1.0f;
541 bool changed = false;
542 float centroid[3], vec[3];
543
544 INIT_MINMAX(min, max);
545
546 LISTBASE_FOREACH (const MetaElem *, ml, &mb->elems) {
547 if ((ml->flag & flag) == flag) {
548 const float scale_mb = (ml->rad * 0.5f) * scale;
549
550 if (obmat) {
551 mul_v3_m4v3(centroid, obmat, &ml->x);
552 }
553 else {
554 copy_v3_v3(centroid, &ml->x);
555 }
556
557 /* TODO, non circle shapes cubes etc, probably nobody notices - campbell */
558 for (int i = -1; i != 3; i += 2) {
559 copy_v3_v3(vec, centroid);
560 add_v3_fl(vec, scale_mb * i);
561 minmax_v3v3_v3(min, max, vec);
562 }
563 changed = true;
564 }
565 }
566
567 return changed;
568 }
569
570 /* basic vertex data functions */
BKE_mball_minmax(const MetaBall * mb,float min[3],float max[3])571 bool BKE_mball_minmax(const MetaBall *mb, float min[3], float max[3])
572 {
573 INIT_MINMAX(min, max);
574
575 LISTBASE_FOREACH (const MetaElem *, ml, &mb->elems) {
576 minmax_v3v3_v3(min, max, &ml->x);
577 }
578
579 return (BLI_listbase_is_empty(&mb->elems) == false);
580 }
581
BKE_mball_center_median(const MetaBall * mb,float r_cent[3])582 bool BKE_mball_center_median(const MetaBall *mb, float r_cent[3])
583 {
584 int total = 0;
585
586 zero_v3(r_cent);
587
588 LISTBASE_FOREACH (const MetaElem *, ml, &mb->elems) {
589 add_v3_v3(r_cent, &ml->x);
590 total++;
591 }
592
593 if (total) {
594 mul_v3_fl(r_cent, 1.0f / (float)total);
595 }
596
597 return (total != 0);
598 }
599
BKE_mball_center_bounds(const MetaBall * mb,float r_cent[3])600 bool BKE_mball_center_bounds(const MetaBall *mb, float r_cent[3])
601 {
602 float min[3], max[3];
603
604 if (BKE_mball_minmax(mb, min, max)) {
605 mid_v3_v3v3(r_cent, min, max);
606 return true;
607 }
608
609 return false;
610 }
611
BKE_mball_transform(MetaBall * mb,const float mat[4][4],const bool do_props)612 void BKE_mball_transform(MetaBall *mb, const float mat[4][4], const bool do_props)
613 {
614 float quat[4];
615 const float scale = mat4_to_scale(mat);
616 const float scale_sqrt = sqrtf(scale);
617
618 mat4_to_quat(quat, mat);
619
620 LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
621 mul_m4_v3(mat, &ml->x);
622 mul_qt_qtqt(ml->quat, quat, ml->quat);
623
624 if (do_props) {
625 ml->rad *= scale;
626 /* hrmf, probably elems shouldn't be
627 * treating scale differently - campbell */
628 if (!MB_TYPE_SIZE_SQUARED(ml->type)) {
629 mul_v3_fl(&ml->expx, scale);
630 }
631 else {
632 mul_v3_fl(&ml->expx, scale_sqrt);
633 }
634 }
635 }
636 }
637
BKE_mball_translate(MetaBall * mb,const float offset[3])638 void BKE_mball_translate(MetaBall *mb, const float offset[3])
639 {
640 LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
641 add_v3_v3(&ml->x, offset);
642 }
643 }
644
645 /* *** select funcs *** */
BKE_mball_select_count(const MetaBall * mb)646 int BKE_mball_select_count(const MetaBall *mb)
647 {
648 int sel = 0;
649 LISTBASE_FOREACH (const MetaElem *, ml, mb->editelems) {
650 if (ml->flag & SELECT) {
651 sel++;
652 }
653 }
654 return sel;
655 }
656
BKE_mball_select_count_multi(Base ** bases,int bases_len)657 int BKE_mball_select_count_multi(Base **bases, int bases_len)
658 {
659 int sel = 0;
660 for (uint ob_index = 0; ob_index < bases_len; ob_index++) {
661 const Object *obedit = bases[ob_index]->object;
662 const MetaBall *mb = (MetaBall *)obedit->data;
663 sel += BKE_mball_select_count(mb);
664 }
665 return sel;
666 }
667
BKE_mball_select_all(MetaBall * mb)668 bool BKE_mball_select_all(MetaBall *mb)
669 {
670 bool changed = false;
671 LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
672 if ((ml->flag & SELECT) == 0) {
673 ml->flag |= SELECT;
674 changed = true;
675 }
676 }
677 return changed;
678 }
679
BKE_mball_select_all_multi_ex(Base ** bases,int bases_len)680 bool BKE_mball_select_all_multi_ex(Base **bases, int bases_len)
681 {
682 bool changed_multi = false;
683 for (uint ob_index = 0; ob_index < bases_len; ob_index++) {
684 Object *obedit = bases[ob_index]->object;
685 MetaBall *mb = obedit->data;
686 changed_multi |= BKE_mball_select_all(mb);
687 }
688 return changed_multi;
689 }
690
BKE_mball_deselect_all(MetaBall * mb)691 bool BKE_mball_deselect_all(MetaBall *mb)
692 {
693 bool changed = false;
694 LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
695 if ((ml->flag & SELECT) != 0) {
696 ml->flag &= ~SELECT;
697 changed = true;
698 }
699 }
700 return changed;
701 }
702
BKE_mball_deselect_all_multi_ex(Base ** bases,int bases_len)703 bool BKE_mball_deselect_all_multi_ex(Base **bases, int bases_len)
704 {
705 bool changed_multi = false;
706 for (uint ob_index = 0; ob_index < bases_len; ob_index++) {
707 Object *obedit = bases[ob_index]->object;
708 MetaBall *mb = obedit->data;
709 changed_multi |= BKE_mball_deselect_all(mb);
710 DEG_id_tag_update(&mb->id, ID_RECALC_SELECT);
711 }
712 return changed_multi;
713 }
714
BKE_mball_select_swap(MetaBall * mb)715 bool BKE_mball_select_swap(MetaBall *mb)
716 {
717 bool changed = false;
718 LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
719 ml->flag ^= SELECT;
720 changed = true;
721 }
722 return changed;
723 }
724
BKE_mball_select_swap_multi_ex(Base ** bases,int bases_len)725 bool BKE_mball_select_swap_multi_ex(Base **bases, int bases_len)
726 {
727 bool changed_multi = false;
728 for (uint ob_index = 0; ob_index < bases_len; ob_index++) {
729 Object *obedit = bases[ob_index]->object;
730 MetaBall *mb = (MetaBall *)obedit->data;
731 changed_multi |= BKE_mball_select_swap(mb);
732 }
733 return changed_multi;
734 }
735
736 /* **** Depsgraph evaluation **** */
737
738 /* Draw Engine */
739
740 void (*BKE_mball_batch_cache_dirty_tag_cb)(MetaBall *mb, int mode) = NULL;
741 void (*BKE_mball_batch_cache_free_cb)(MetaBall *mb) = NULL;
742
BKE_mball_batch_cache_dirty_tag(MetaBall * mb,int mode)743 void BKE_mball_batch_cache_dirty_tag(MetaBall *mb, int mode)
744 {
745 if (mb->batch_cache) {
746 BKE_mball_batch_cache_dirty_tag_cb(mb, mode);
747 }
748 }
BKE_mball_batch_cache_free(MetaBall * mb)749 void BKE_mball_batch_cache_free(MetaBall *mb)
750 {
751 if (mb->batch_cache) {
752 BKE_mball_batch_cache_free_cb(mb);
753 }
754 }
755