Blender V5.0
mball_edit.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
8
9#include <cmath>
10#include <cstring>
11
12#include "MEM_guardedalloc.h"
13
14#include "BLI_kdtree.h"
15#include "BLI_listbase.h"
16#include "BLI_math_matrix.h"
17#include "BLI_math_rotation.h"
18#include "BLI_math_vector.h"
19#include "BLI_rand.h"
20#include "BLI_rect.h"
21#include "BLI_utildefines.h"
22
23#include "DNA_meta_types.h"
24#include "DNA_object_types.h"
25#include "DNA_scene_types.h"
26
27#include "RNA_access.hh"
28#include "RNA_define.hh"
29
30#include "BKE_context.hh"
31#include "BKE_layer.hh"
32#include "BKE_mball.hh"
33#include "BKE_object.hh"
34#include "BKE_object_types.hh"
35
36#include "BLT_translation.hh"
37
38#include "DEG_depsgraph.hh"
39
40#include "GPU_select.hh"
41
42#include "ED_mball.hh"
43#include "ED_object.hh"
44#include "ED_screen.hh"
45#include "ED_select_utils.hh"
46#include "ED_view3d.hh"
47
48#include "WM_api.hh"
49#include "WM_types.hh"
50
51#include "UI_interface_icons.hh"
52
53#include "mball_intern.hh"
54
55using blender::Span;
56using blender::Vector;
57
58/* -------------------------------------------------------------------- */
61
63{
64 MetaBall *mb = (MetaBall *)obedit->data;
65
66 mb->editelems = nullptr;
67 mb->lastelem = nullptr;
68}
69
71{
72 MetaBall *mb = (MetaBall *)obedit->data;
73 MetaElem *ml; /*, *newml;*/
74
75 ml = static_cast<MetaElem *>(mb->elems.first);
76
77 while (ml) {
78 if (ml->flag & SELECT) {
79 mb->lastelem = ml;
80 }
81 ml = ml->next;
82 }
83
84 mb->editelems = &mb->elems;
85}
86
87void ED_mball_editmball_load(Object * /*obedit*/) {}
88
90
91/* -------------------------------------------------------------------- */
94
103
105
106/* -------------------------------------------------------------------- */
109
111 bContext * /*C*/, Object *obedit, bool obedit_is_new, float mat[4][4], float dia, int type)
112{
113 MetaBall *mball = (MetaBall *)obedit->data;
114 MetaElem *ml;
115
116 /* Deselect all existing metaelems */
117 ml = static_cast<MetaElem *>(mball->editelems->first);
118 while (ml) {
119 ml->flag &= ~SELECT;
120 ml = ml->next;
121 }
122
123 ml = BKE_mball_element_add(mball, type);
124 ml->rad *= dia;
125
126 if (obedit_is_new) {
127 mball->wiresize *= dia;
128 mball->rendersize *= dia;
129 }
130 copy_v3_v3(&ml->x, mat[3]);
131 /* MB_ELIPSOID works differently (intentional?). Whatever the case,
132 * on testing this needs to be skipped otherwise it doesn't behave like other types. */
133 if (type != MB_ELIPSOID) {
134 mul_v3_fl(&ml->expx, dia);
135 }
136
137 ml->flag |= SELECT;
138 mball->lastelem = ml;
139 return ml;
140}
141
143
144/* -------------------------------------------------------------------- */
147
148/* Select or deselect all MetaElements */
150{
151 int action = RNA_enum_get(op->ptr, "action");
152
153 const Scene *scene = CTX_data_scene(C);
154 ViewLayer *view_layer = CTX_data_view_layer(C);
156 scene, view_layer, CTX_wm_view3d(C));
157
158 if (action == SEL_TOGGLE) {
160 }
161
162 switch (action) {
163 case SEL_SELECT:
165 break;
166 case SEL_DESELECT:
168 break;
169 case SEL_INVERT:
171 break;
172 }
173
174 for (Base *base : bases) {
175 Object *obedit = base->object;
176 MetaBall *mb = (MetaBall *)obedit->data;
179 }
180
181 return OPERATOR_FINISHED;
182}
183
185{
186 /* identifiers */
187 ot->name = "(De)select All";
188 ot->description = "Change selection of all metaball elements";
189 ot->idname = "MBALL_OT_select_all";
190
191 /* callback functions */
194
195 /* flags */
197
199}
200
202
203/* -------------------------------------------------------------------- */
206
207enum {
212};
213
215 {SIMMBALL_TYPE, "TYPE", 0, "Type", ""},
216 {SIMMBALL_RADIUS, "RADIUS", 0, "Radius", ""},
217 {SIMMBALL_STIFFNESS, "STIFFNESS", 0, "Stiffness", ""},
218 {SIMMBALL_ROTATION, "ROTATION", 0, "Rotation", ""},
219 {0, nullptr, 0, nullptr, nullptr},
220};
221
223 Object *obedit, MetaBall *mb, int type, KDTree_1d *tree_1d, KDTree_3d *tree_3d)
224{
225 float tree_entry[3] = {0.0f, 0.0f, 0.0f};
226 int tree_index = 0;
227 LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
228 if (ml->flag & SELECT) {
229 switch (type) {
230 case SIMMBALL_RADIUS: {
231 float radius = ml->rad;
232 /* Radius in world space. */
233 float smat[3][3];
234 float radius_vec[3] = {radius, radius, radius};
235 BKE_object_scale_to_mat3(obedit, smat);
236 mul_m3_v3(smat, radius_vec);
237 radius = (radius_vec[0] + radius_vec[1] + radius_vec[2]) / 3;
238 tree_entry[0] = radius;
239 break;
240 }
241 case SIMMBALL_STIFFNESS: {
242 tree_entry[0] = ml->s;
243 break;
244 }
245 case SIMMBALL_ROTATION: {
246 float dir[3] = {1.0f, 0.0f, 0.0f};
247 float rmat[3][3];
248 mul_qt_v3(ml->quat, dir);
249 BKE_object_rot_to_mat3(obedit, rmat, true);
250 mul_m3_v3(rmat, dir);
251 copy_v3_v3(tree_entry, dir);
252 break;
253 }
254 }
255 if (tree_1d) {
256 BLI_kdtree_1d_insert(tree_1d, tree_index++, tree_entry);
257 }
258 else {
259 BLI_kdtree_3d_insert(tree_3d, tree_index++, tree_entry);
260 }
261 }
262 }
263}
264
266 MetaBall *mb,
267 int type,
268 const KDTree_1d *tree_1d,
269 const KDTree_3d *tree_3d,
270 const float thresh)
271{
272 bool changed = false;
273 LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
274 bool select = false;
275 switch (type) {
276 case SIMMBALL_RADIUS: {
277 float radius = ml->rad;
278 /* Radius in world space is the average of the
279 * scaled radius in x, y and z directions. */
280 float smat[3][3];
281 float radius_vec[3] = {radius, radius, radius};
282 BKE_object_scale_to_mat3(obedit, smat);
283 mul_m3_v3(smat, radius_vec);
284 radius = (radius_vec[0] + radius_vec[1] + radius_vec[2]) / 3;
285
286 if (ED_select_similar_compare_float_tree(tree_1d, radius, thresh, SIM_CMP_EQ)) {
287 select = true;
288 }
289 break;
290 }
291 case SIMMBALL_STIFFNESS: {
292 float s = ml->s;
293 if (ED_select_similar_compare_float_tree(tree_1d, s, thresh, SIM_CMP_EQ)) {
294 select = true;
295 }
296 break;
297 }
298 case SIMMBALL_ROTATION: {
299 float dir[3] = {1.0f, 0.0f, 0.0f};
300 float rmat[3][3];
301 mul_qt_v3(ml->quat, dir);
302 BKE_object_rot_to_mat3(obedit, rmat, true);
303 mul_m3_v3(rmat, dir);
304
305 float thresh_cos = cosf(thresh * float(M_PI_2));
306
307 KDTreeNearest_3d nearest;
308 if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) {
309 float orient = angle_normalized_v3v3(dir, nearest.co);
310 /* Map to 0-1 to compare orientation. */
311 float delta = thresh_cos - fabsf(cosf(orient));
312 if (ED_select_similar_compare_float(delta, thresh, SIM_CMP_EQ)) {
313 select = true;
314 }
315 }
316 break;
317 }
318 }
319
320 if (select) {
321 changed = true;
322 ml->flag |= SELECT;
323 }
324 }
325 return changed;
326}
327
329{
330 const int type = RNA_enum_get(op->ptr, "type");
331 const float thresh = RNA_float_get(op->ptr, "threshold");
332 int tot_mball_selected_all = 0;
333
334 const Scene *scene = CTX_data_scene(C);
335 ViewLayer *view_layer = CTX_data_view_layer(C);
337 scene, view_layer, CTX_wm_view3d(C));
338
339 tot_mball_selected_all = BKE_mball_select_count_multi(bases);
340
341 short type_ref = 0;
342 KDTree_1d *tree_1d = nullptr;
343 KDTree_3d *tree_3d = nullptr;
344
345 switch (type) {
346 case SIMMBALL_RADIUS:
348 tree_1d = BLI_kdtree_1d_new(tot_mball_selected_all);
349 break;
351 tree_3d = BLI_kdtree_3d_new(tot_mball_selected_all);
352 break;
353 }
354
355 /* Get type of selected MetaBall */
356 for (Base *base : bases) {
357 Object *obedit = base->object;
358 MetaBall *mb = (MetaBall *)obedit->data;
359
360 switch (type) {
361 case SIMMBALL_TYPE: {
362 LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
363 if (ml->flag & SELECT) {
364 short mball_type = 1 << (ml->type + 1);
365 type_ref |= mball_type;
366 }
367 }
368 break;
369 }
370 case SIMMBALL_RADIUS:
373 mball_select_similar_type_get(obedit, mb, type, tree_1d, tree_3d);
374 break;
375 default:
376 BLI_assert(0);
377 break;
378 }
379 }
380
381 if (tree_1d != nullptr) {
382 BLI_kdtree_1d_deduplicate(tree_1d);
383 BLI_kdtree_1d_balance(tree_1d);
384 }
385 if (tree_3d != nullptr) {
386 BLI_kdtree_3d_deduplicate(tree_3d);
387 BLI_kdtree_3d_balance(tree_3d);
388 }
389 /* Select MetaBalls with desired type. */
390 for (Base *base : bases) {
391 Object *obedit = base->object;
392 MetaBall *mb = (MetaBall *)obedit->data;
393 bool changed = false;
394
395 switch (type) {
396 case SIMMBALL_TYPE: {
397 LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
398 short mball_type = 1 << (ml->type + 1);
399 if (mball_type & type_ref) {
400 ml->flag |= SELECT;
401 changed = true;
402 }
403 }
404 break;
405 }
406 case SIMMBALL_RADIUS:
409 changed = mball_select_similar_type(obedit, mb, type, tree_1d, tree_3d, thresh);
410 break;
411 default:
412 BLI_assert(0);
413 break;
414 }
415
416 if (changed) {
419 }
420 }
421
422 if (tree_1d != nullptr) {
423 BLI_kdtree_1d_free(tree_1d);
424 }
425 if (tree_3d != nullptr) {
426 BLI_kdtree_3d_free(tree_3d);
427 }
428 return OPERATOR_FINISHED;
429}
430
432{
433 /* identifiers */
434 ot->name = "Select Similar";
435 ot->idname = "MBALL_OT_select_similar";
436
437 /* callback functions */
438 ot->invoke = WM_menu_invoke;
441 ot->description = "Select similar metaballs by property types";
442
443 /* flags */
445
446 /* properties */
447 ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, 0, "Type", "");
448
449 RNA_def_float(ot->srna, "threshold", 0.1, 0.0, FLT_MAX, "Threshold", "", 0.01, 1.0);
450}
451
453
454/* -------------------------------------------------------------------- */
457
459{
460 const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
461 const float randfac = RNA_float_get(op->ptr, "ratio");
463
464 const Scene *scene = CTX_data_scene(C);
465 ViewLayer *view_layer = CTX_data_view_layer(C);
467 scene, view_layer, CTX_wm_view3d(C));
468 for (const int ob_index : objects.index_range()) {
469 Object *obedit = objects[ob_index];
470 MetaBall *mb = (MetaBall *)obedit->data;
472 continue;
473 }
474 int seed_iter = seed;
475
476 /* This gives a consistent result regardless of object order. */
477 if (ob_index) {
478 seed_iter += BLI_ghashutil_strhash_p(obedit->id.name);
479 }
480
481 RNG *rng = BLI_rng_new_srandom(seed_iter);
482
483 LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
484 if (BLI_rng_get_float(rng) < randfac) {
485 if (select) {
486 ml->flag |= SELECT;
487 }
488 else {
489 ml->flag &= ~SELECT;
490 }
491 }
492 }
493
494 BLI_rng_free(rng);
495
498 }
499 return OPERATOR_FINISHED;
500}
501
503{
504 /* identifiers */
505 ot->name = "Select Random";
506 ot->description = "Randomly select metaball elements";
507 ot->idname = "MBALL_OT_select_random_metaelems";
508
509 /* callback functions */
512
513 /* flags */
515
516 /* properties */
518}
519
521
522/* -------------------------------------------------------------------- */
525
526/* Duplicate selected MetaElements */
528{
529 const Scene *scene = CTX_data_scene(C);
530 ViewLayer *view_layer = CTX_data_view_layer(C);
532 scene, view_layer, CTX_wm_view3d(C));
533 for (Object *obedit : objects) {
534 MetaBall *mb = (MetaBall *)obedit->data;
535 MetaElem *ml, *newml;
536
537 if (!BKE_mball_is_any_selected(mb)) {
538 continue;
539 }
540
541 ml = static_cast<MetaElem *>(mb->editelems->last);
542 if (ml) {
543 while (ml) {
544 if (ml->flag & SELECT) {
545 newml = static_cast<MetaElem *>(MEM_dupallocN(ml));
546 BLI_addtail(mb->editelems, newml);
547 mb->lastelem = newml;
548 ml->flag &= ~SELECT;
549 }
550 ml = ml->prev;
551 }
553 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
554 }
555 }
556 return OPERATOR_FINISHED;
557}
558
560{
561 /* identifiers */
562 ot->name = "Duplicate Metaball Elements";
563 ot->description = "Duplicate selected metaball element(s)";
564 ot->idname = "MBALL_OT_duplicate_metaelems";
565
566 /* callback functions */
569
570 /* flags */
572}
573
575
576/* -------------------------------------------------------------------- */
581
583{
584 const Scene *scene = CTX_data_scene(C);
585 ViewLayer *view_layer = CTX_data_view_layer(C);
587 scene, view_layer, CTX_wm_view3d(C));
588 for (Object *obedit : objects) {
589 MetaBall *mb = (MetaBall *)obedit->data;
590 MetaElem *ml, *next;
591
592 if (!BKE_mball_is_any_selected(mb)) {
593 continue;
594 }
595
596 ml = static_cast<MetaElem *>(mb->editelems->first);
597 if (ml) {
598 while (ml) {
599 next = ml->next;
600 if (ml->flag & SELECT) {
601 if (mb->lastelem == ml) {
602 mb->lastelem = nullptr;
603 }
604 BLI_remlink(mb->editelems, ml);
605 MEM_freeN(ml);
606 }
607 ml = next;
608 }
610 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
611 }
612 }
613 return OPERATOR_FINISHED;
614}
615
617 wmOperator *op,
618 const wmEvent * /*event*/)
619{
620 if (RNA_boolean_get(op->ptr, "confirm")) {
622 op,
623 IFACE_("Delete selected metaball elements?"),
624 nullptr,
625 IFACE_("Delete"),
627 false);
628 }
629 return delete_metaelems_exec(C, op);
630}
631
633{
634 /* identifiers */
635 ot->name = "Delete";
636 ot->description = "Delete selected metaball element(s)";
637 ot->idname = "MBALL_OT_delete_metaelems";
638
639 /* callback functions */
640 ot->invoke = delete_metaelems_invoke;
643
644 /* flags */
647}
648
650
651/* -------------------------------------------------------------------- */
654
656{
657 Object *obedit = CTX_data_edit_object(C);
658 MetaBall *mb = (MetaBall *)obedit->data;
659 MetaElem *ml;
660 const bool invert = RNA_boolean_get(op->ptr, "unselected") ? SELECT : false;
661
662 ml = static_cast<MetaElem *>(mb->editelems->first);
663
664 if (ml) {
665 while (ml) {
666 if ((ml->flag & SELECT) != invert) {
667 ml->flag |= MB_HIDE;
668 }
669 ml = ml->next;
670 }
672 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
673 }
674
675 return OPERATOR_FINISHED;
676}
677
679{
680 /* identifiers */
681 ot->name = "Hide Selected";
682 ot->description = "Hide (un)selected metaball element(s)";
683 ot->idname = "MBALL_OT_hide_metaelems";
684
685 /* callback functions */
686 ot->exec = hide_metaelems_exec;
688
689 /* flags */
691
692 /* props */
694 ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected");
695}
696
698
699/* -------------------------------------------------------------------- */
702
704{
705 Object *obedit = CTX_data_edit_object(C);
706 MetaBall *mb = (MetaBall *)obedit->data;
707 const bool select = RNA_boolean_get(op->ptr, "select");
708 bool changed = false;
709
710 LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
711 if (ml->flag & MB_HIDE) {
712 SET_FLAG_FROM_TEST(ml->flag, select, SELECT);
713 ml->flag &= ~MB_HIDE;
714 changed = true;
715 }
716 }
717 if (changed) {
719 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
720 }
721
722 return OPERATOR_FINISHED;
723}
724
726{
727 /* identifiers */
728 ot->name = "Reveal Hidden";
729 ot->description = "Reveal all hidden metaball elements";
730 ot->idname = "MBALL_OT_reveal_metaelems";
731
732 /* callback functions */
735
736 /* flags */
738
739 /* props */
740 RNA_def_boolean(ot->srna, "select", true, "Select", "");
741}
742
744
745/* -------------------------------------------------------------------- */
748
750 const uint select_id,
751 MetaElem **r_ml)
752{
753 const uint hit_object = select_id & 0xFFFF;
754 Base *base = nullptr;
755 MetaElem *ml = nullptr;
756 /* TODO(@ideasman42): optimize, eg: sort & binary search. */
757 for (Base *base_iter : bases) {
758 if (base_iter->object->runtime->select_id == hit_object) {
759 base = base_iter;
760 break;
761 }
762 }
763 if (base != nullptr) {
764 const uint hit_elem = (select_id & ~MBALLSEL_ANY) >> 16;
765 MetaBall *mb = static_cast<MetaBall *>(base->object->data);
766 ml = static_cast<MetaElem *>(BLI_findlink(mb->editelems, hit_elem));
767 }
768 *r_ml = ml;
769 return base;
770}
771
773 const int mval[2],
774 bool use_cycle,
775 Base **r_base,
776 MetaElem **r_ml,
777 uint *r_selmask)
778{
780 int a, hits;
781 GPUSelectBuffer buffer;
782 rcti rect;
783 bool found = false;
784
786
787 BLI_rcti_init_pt_radius(&rect, mval, 12);
788
789 hits = view3d_gpu_select(&vc,
790 &buffer,
791 &rect,
794
795 if (hits == 0) {
796 return false;
797 }
798
800 vc.scene, vc.view_layer, vc.v3d);
801
802 int hit_cycle_offset = 0;
803 if (use_cycle) {
804 /* When cycling, use the hit directly after the current active meta-element (when set). */
805 const int base_index = vc.obact->runtime->select_id;
806 MetaBall *mb = (MetaBall *)vc.obact->data;
807 MetaElem *ml = mb->lastelem;
808 if (ml && (ml->flag & SELECT)) {
809 const int ml_index = BLI_findindex(mb->editelems, ml);
810 BLI_assert(ml_index != -1);
811
812 /* Count backwards in case the active meta-element has multiple entries,
813 * ensure this steps onto the next meta-element. */
814 a = hits;
815 while (a--) {
816 const int select_id = buffer.storage[a].id;
817 if (select_id == -1) {
818 continue;
819 }
820
821 if (((select_id & 0xFFFF) == base_index) &&
822 ((select_id & ~MBALLSEL_ANY) >> 16 == ml_index))
823 {
824 hit_cycle_offset = a + 1;
825 break;
826 }
827 }
828 }
829 }
830
831 for (a = 0; a < hits; a++) {
832 const int index = (hit_cycle_offset == 0) ? a : ((a + hit_cycle_offset) % hits);
833 const uint select_id = buffer.storage[index].id;
834 if (select_id == -1) {
835 continue;
836 }
837
838 MetaElem *ml;
839 Base *base = ED_mball_base_and_elem_from_select_buffer(bases, select_id, &ml);
840 if (ml == nullptr) {
841 continue;
842 }
843 *r_base = base;
844 *r_ml = ml;
845 *r_selmask = select_id & MBALLSEL_ANY;
846 found = true;
847 break;
848 }
849
850 return found;
851}
852
853bool ED_mball_select_pick(bContext *C, const int mval[2], const SelectPick_Params &params)
854{
855 Base *base = nullptr;
856 MetaElem *ml = nullptr;
857 uint selmask = 0;
858
859 bool changed = false;
860
861 bool found = ed_mball_findnearest_metaelem(C, mval, true, &base, &ml, &selmask);
862
863 if (params.sel_op == SEL_OP_SET) {
864 if ((found && params.select_passthrough) && (ml->flag & SELECT)) {
865 found = false;
866 }
867 else if (found || params.deselect_all) {
868 /* Deselect everything. */
869 changed |= ED_mball_deselect_all_multi(C);
870 }
871 }
872
873 if (found) {
874 if (selmask & MBALLSEL_RADIUS) {
875 ml->flag |= MB_SCALE_RAD;
876 }
877 else if (selmask & MBALLSEL_STIFF) {
878 ml->flag &= ~MB_SCALE_RAD;
879 }
880
881 switch (params.sel_op) {
882 case SEL_OP_ADD: {
883 ml->flag |= SELECT;
884 break;
885 }
886 case SEL_OP_SUB: {
887 ml->flag &= ~SELECT;
888 break;
889 }
890 case SEL_OP_XOR: {
891 if (ml->flag & SELECT) {
892 ml->flag &= ~SELECT;
893 }
894 else {
895 ml->flag |= SELECT;
896 }
897 break;
898 }
899 case SEL_OP_SET: {
900 /* Deselect has already been performed. */
901 ml->flag |= SELECT;
902 break;
903 }
904 case SEL_OP_AND: {
905 BLI_assert_unreachable(); /* Doesn't make sense for picking. */
906 break;
907 }
908 }
909 const Scene *scene = CTX_data_scene(C);
910 ViewLayer *view_layer = CTX_data_view_layer(C);
911 MetaBall *mb = (MetaBall *)base->object->data;
912 mb->lastelem = ml;
913
916
917 BKE_view_layer_synced_ensure(scene, view_layer);
918 if (BKE_view_layer_active_base_get(view_layer) != base) {
920 }
921
922 changed = true;
923 }
924
925 return changed || found;
926}
927
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
blender::Vector< Base * > BKE_view_layer_array_from_bases_in_edit_mode(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
Base * BKE_view_layer_active_base_get(ViewLayer *view_layer)
blender::Vector< Base * > BKE_view_layer_array_from_bases_in_edit_mode_unique_data(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_edit_mode_unique_data(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
bool BKE_mball_select_swap_multi_ex(blender::Span< Base * > bases)
MetaElem * BKE_mball_element_add(MetaBall *mb, int type)
Definition mball.cc:179
bool BKE_mball_is_any_selected_multi(blender::Span< Base * > bases)
int BKE_mball_select_count_multi(blender::Span< Base * > bases)
bool BKE_mball_is_any_unselected(const MetaBall *mb)
Definition mball.cc:321
bool BKE_mball_select_all_multi_ex(blender::Span< Base * > bases)
bool BKE_mball_is_any_selected(const MetaBall *mb)
Definition mball.cc:299
bool BKE_mball_deselect_all_multi_ex(blender::Span< Base * > bases)
General operations, lookup, etc. for blender objects.
void BKE_object_rot_to_mat3(const Object *ob, float r_mat[3][3], bool use_drot)
void BKE_object_scale_to_mat3(const Object *ob, float r_mat[3][3])
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
unsigned int BLI_ghashutil_strhash_p(const void *ptr)
A KD-tree for nearest neighbor search.
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
#define M_PI_2
void mul_m3_v3(const float M[3][3], float r[3])
void mul_qt_v3(const float q[4], float r[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
Random number functions.
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition rand.cc:53
struct RNG * BLI_rng_new_srandom(unsigned int seed)
Definition rand.cc:46
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition rand.cc:88
void BLI_rcti_init_pt_radius(struct rcti *rect, const int xy[2], int size)
Definition rct.cc:466
unsigned int uint
#define SET_FLAG_FROM_TEST(value, test, flag)
#define IFACE_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_SELECT
Definition DNA_ID.h:1101
@ MB_SCALE_RAD
@ MB_HIDE
@ MB_ELIPSOID
Object is a sort of wrapper for general info.
@ OPERATOR_FINISHED
#define MBALLSEL_ANY
Definition ED_mball.hh:64
#define MBALLSEL_STIFF
Definition ED_mball.hh:62
#define MBALLSEL_RADIUS
Definition ED_mball.hh:63
bool ED_operator_editmball(bContext *C)
@ SEL_OP_ADD
@ SEL_OP_SUB
@ SEL_OP_SET
@ SEL_OP_AND
@ SEL_OP_XOR
@ SEL_SELECT
@ SEL_INVERT
@ SEL_DESELECT
@ SEL_TOGGLE
bool ED_select_similar_compare_float(float delta, float thresh, eSimilarCmp compare)
@ SIM_CMP_EQ
bool ED_select_similar_compare_float_tree(const KDTree_1d *tree, float length, float thresh, eSimilarCmp compare)
int view3d_gpu_select(const ViewContext *vc, GPUSelectBuffer *buffer, const rcti *input, eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter)
ViewContext ED_view3d_viewcontext_init(bContext *C, Depsgraph *depsgraph)
@ VIEW3D_SELECT_PICK_ALL
Definition ED_view3d.hh:983
@ VIEW3D_SELECT_PICK_NEAREST
Definition ED_view3d.hh:985
@ VIEW3D_SELECT_FILTER_NOP
Definition ED_view3d.hh:990
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
@ ALERT_ICON_NONE
#define NC_GEOM
Definition WM_types.hh:393
#define ND_DATA
Definition WM_types.hh:509
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define ND_SELECT
Definition WM_types.hh:508
static const EnumPropertyItem prop_similar_types[]
BPy_StructRNA * depsgraph
static unsigned long seed
Definition btSoftBody.h:39
IndexRange index_range() const
#define SELECT
#define select(A, B, C)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
CCL_NAMESPACE_BEGIN ccl_device float invert(const float color, const float factor)
Definition invert.h:11
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static ulong * next
void MBALL_OT_select_all(wmOperatorType *ot)
MetaElem * ED_mball_add_primitive(bContext *, Object *obedit, bool obedit_is_new, float mat[4][4], float dia, int type)
static wmOperatorStatus delete_metaelems_invoke(bContext *C, wmOperator *op, const wmEvent *)
bool ED_mball_select_pick(bContext *C, const int mval[2], const SelectPick_Params &params)
void MBALL_OT_hide_metaelems(wmOperatorType *ot)
bool ED_mball_deselect_all_multi(bContext *C)
Definition mball_edit.cc:95
static void mball_select_similar_type_get(Object *obedit, MetaBall *mb, int type, KDTree_1d *tree_1d, KDTree_3d *tree_3d)
static wmOperatorStatus mball_select_similar_exec(bContext *C, wmOperator *op)
void ED_mball_editmball_free(Object *obedit)
Definition mball_edit.cc:62
void ED_mball_editmball_load(Object *)
Definition mball_edit.cc:87
void MBALL_OT_duplicate_metaelems(wmOperatorType *ot)
static wmOperatorStatus duplicate_metaelems_exec(bContext *C, wmOperator *)
static bool mball_select_similar_type(Object *obedit, MetaBall *mb, int type, const KDTree_1d *tree_1d, const KDTree_3d *tree_3d, const float thresh)
void MBALL_OT_select_random_metaelems(wmOperatorType *ot)
static bool ed_mball_findnearest_metaelem(bContext *C, const int mval[2], bool use_cycle, Base **r_base, MetaElem **r_ml, uint *r_selmask)
void MBALL_OT_select_similar(wmOperatorType *ot)
static wmOperatorStatus select_random_metaelems_exec(bContext *C, wmOperator *op)
void MBALL_OT_delete_metaelems(wmOperatorType *ot)
void MBALL_OT_reveal_metaelems(wmOperatorType *ot)
static wmOperatorStatus reveal_metaelems_exec(bContext *C, wmOperator *op)
static wmOperatorStatus mball_select_all_exec(bContext *C, wmOperator *op)
Base * ED_mball_base_and_elem_from_select_buffer(const Span< Base * > bases, const uint select_id, MetaElem **r_ml)
static wmOperatorStatus hide_metaelems_exec(bContext *C, wmOperator *op)
static wmOperatorStatus delete_metaelems_exec(bContext *C, wmOperator *)
@ SIMMBALL_STIFFNESS
@ SIMMBALL_TYPE
@ SIMMBALL_RADIUS
@ SIMMBALL_ROTATION
void ED_mball_editmball_make(Object *obedit)
Definition mball_edit.cc:70
void base_activate(bContext *C, Base *base)
#define fabsf
#define cosf
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
#define FLT_MAX
Definition stdcycles.h:14
struct Object * object
GPUSelectStorage storage
Definition GPU_select.hh:47
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
void * last
void * first
MetaElem * lastelem
ListBase elems
float rendersize
float wiresize
ListBase * editelems
struct MetaElem * next
struct MetaElem * prev
ObjectRuntimeHandle * runtime
Definition rand.cc:33
Scene * scene
Definition ED_view3d.hh:73
ViewLayer * view_layer
Definition ED_view3d.hh:74
View3D * v3d
Definition ED_view3d.hh:78
Object * obact
Definition ED_view3d.hh:75
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4237
int WM_operator_properties_select_random_seed_increment_get(wmOperator *op)
void WM_operator_properties_confirm_or_exec(wmOperatorType *ot)
void WM_operator_properties_select_random(wmOperatorType *ot)
void WM_operator_properties_select_all(wmOperatorType *ot)
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
wmOperatorStatus WM_operator_confirm_ex(bContext *C, wmOperator *op, const char *title, const char *message, const char *confirm_text, int icon, bool cancel_default)