Blender V4.3
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
9#include <cmath>
10#include <cstring>
11
12#include "MEM_guardedalloc.h"
13
14#include "BLI_blenlib.h"
15#include "BLI_kdtree.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_utildefines.h"
21
22#include "DNA_defs.h"
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/* -------------------------------------------------------------------- */
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
91/* -------------------------------------------------------------------- */
103
106/* -------------------------------------------------------------------- */
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
144/* -------------------------------------------------------------------- */
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
203/* -------------------------------------------------------------------- */
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 */
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
454/* -------------------------------------------------------------------- */
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
522/* -------------------------------------------------------------------- */
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
576/* -------------------------------------------------------------------- */
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
616static int delete_metaelems_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
617{
618 if (RNA_boolean_get(op->ptr, "confirm")) {
619 return WM_operator_confirm_ex(C,
620 op,
621 IFACE_("Delete selected metaball elements?"),
622 nullptr,
623 IFACE_("Delete"),
625 false);
626 }
627 return delete_metaelems_exec(C, op);
628}
629
631{
632 /* identifiers */
633 ot->name = "Delete";
634 ot->description = "Delete selected metaball element(s)";
635 ot->idname = "MBALL_OT_delete_metaelems";
636
637 /* callback functions */
641
642 /* flags */
645}
646
649/* -------------------------------------------------------------------- */
654{
655 Object *obedit = CTX_data_edit_object(C);
656 MetaBall *mb = (MetaBall *)obedit->data;
657 MetaElem *ml;
658 const bool invert = RNA_boolean_get(op->ptr, "unselected") ? SELECT : false;
659
660 ml = static_cast<MetaElem *>(mb->editelems->first);
661
662 if (ml) {
663 while (ml) {
664 if ((ml->flag & SELECT) != invert) {
665 ml->flag |= MB_HIDE;
666 }
667 ml = ml->next;
668 }
670 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
671 }
672
673 return OPERATOR_FINISHED;
674}
675
677{
678 /* identifiers */
679 ot->name = "Hide Selected";
680 ot->description = "Hide (un)selected metaball element(s)";
681 ot->idname = "MBALL_OT_hide_metaelems";
682
683 /* callback functions */
686
687 /* flags */
689
690 /* props */
692 ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected");
693}
694
697/* -------------------------------------------------------------------- */
702{
703 Object *obedit = CTX_data_edit_object(C);
704 MetaBall *mb = (MetaBall *)obedit->data;
705 const bool select = RNA_boolean_get(op->ptr, "select");
706 bool changed = false;
707
708 LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
709 if (ml->flag & MB_HIDE) {
710 SET_FLAG_FROM_TEST(ml->flag, select, SELECT);
711 ml->flag &= ~MB_HIDE;
712 changed = true;
713 }
714 }
715 if (changed) {
717 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
718 }
719
720 return OPERATOR_FINISHED;
721}
722
724{
725 /* identifiers */
726 ot->name = "Reveal Hidden";
727 ot->description = "Reveal all hidden metaball elements";
728 ot->idname = "MBALL_OT_reveal_metaelems";
729
730 /* callback functions */
733
734 /* flags */
736
737 /* props */
738 RNA_def_boolean(ot->srna, "select", true, "Select", "");
739}
740
743/* -------------------------------------------------------------------- */
748 const uint select_id,
749 MetaElem **r_ml)
750{
751 const uint hit_object = select_id & 0xFFFF;
752 Base *base = nullptr;
753 MetaElem *ml = nullptr;
754 /* TODO(@ideasman42): optimize, eg: sort & binary search. */
755 for (Base *base_iter : bases) {
756 if (base_iter->object->runtime->select_id == hit_object) {
757 base = base_iter;
758 break;
759 }
760 }
761 if (base != nullptr) {
762 const uint hit_elem = (select_id & ~MBALLSEL_ANY) >> 16;
763 MetaBall *mb = static_cast<MetaBall *>(base->object->data);
764 ml = static_cast<MetaElem *>(BLI_findlink(mb->editelems, hit_elem));
765 }
766 *r_ml = ml;
767 return base;
768}
769
771 const int mval[2],
772 bool use_cycle,
773 Base **r_base,
774 MetaElem **r_ml,
775 uint *r_selmask)
776{
778 int a, hits;
779 GPUSelectBuffer buffer;
780 rcti rect;
781 bool found = false;
782
784
785 BLI_rcti_init_pt_radius(&rect, mval, 12);
786
787 hits = view3d_opengl_select(&vc,
788 &buffer,
789 &rect,
792
793 if (hits == 0) {
794 return false;
795 }
796
798 vc.scene, vc.view_layer, vc.v3d);
799
800 int hit_cycle_offset = 0;
801 if (use_cycle) {
802 /* When cycling, use the hit directly after the current active meta-element (when set). */
803 const int base_index = vc.obact->runtime->select_id;
804 MetaBall *mb = (MetaBall *)vc.obact->data;
805 MetaElem *ml = mb->lastelem;
806 if (ml && (ml->flag & SELECT)) {
807 const int ml_index = BLI_findindex(mb->editelems, ml);
808 BLI_assert(ml_index != -1);
809
810 /* Count backwards in case the active meta-element has multiple entries,
811 * ensure this steps onto the next meta-element. */
812 a = hits;
813 while (a--) {
814 const int select_id = buffer.storage[a].id;
815 if (select_id == -1) {
816 continue;
817 }
818
819 if (((select_id & 0xFFFF) == base_index) &&
820 ((select_id & ~MBALLSEL_ANY) >> 16 == ml_index))
821 {
822 hit_cycle_offset = a + 1;
823 break;
824 }
825 }
826 }
827 }
828
829 for (a = 0; a < hits; a++) {
830 const int index = (hit_cycle_offset == 0) ? a : ((a + hit_cycle_offset) % hits);
831 const uint select_id = buffer.storage[index].id;
832 if (select_id == -1) {
833 continue;
834 }
835
836 MetaElem *ml;
837 Base *base = ED_mball_base_and_elem_from_select_buffer(bases, select_id, &ml);
838 if (ml == nullptr) {
839 continue;
840 }
841 *r_base = base;
842 *r_ml = ml;
843 *r_selmask = select_id & MBALLSEL_ANY;
844 found = true;
845 break;
846 }
847
848 return found;
849}
850
851bool ED_mball_select_pick(bContext *C, const int mval[2], const SelectPick_Params *params)
852{
853 Base *base = nullptr;
854 MetaElem *ml = nullptr;
855 uint selmask = 0;
856
857 bool changed = false;
858
859 bool found = ed_mball_findnearest_metaelem(C, mval, true, &base, &ml, &selmask);
860
861 if (params->sel_op == SEL_OP_SET) {
862 if ((found && params->select_passthrough) && (ml->flag & SELECT)) {
863 found = false;
864 }
865 else if (found || params->deselect_all) {
866 /* Deselect everything. */
867 changed |= ED_mball_deselect_all_multi(C);
868 }
869 }
870
871 if (found) {
872 if (selmask & MBALLSEL_RADIUS) {
873 ml->flag |= MB_SCALE_RAD;
874 }
875 else if (selmask & MBALLSEL_STIFF) {
876 ml->flag &= ~MB_SCALE_RAD;
877 }
878
879 switch (params->sel_op) {
880 case SEL_OP_ADD: {
881 ml->flag |= SELECT;
882 break;
883 }
884 case SEL_OP_SUB: {
885 ml->flag &= ~SELECT;
886 break;
887 }
888 case SEL_OP_XOR: {
889 if (ml->flag & SELECT) {
890 ml->flag &= ~SELECT;
891 }
892 else {
893 ml->flag |= SELECT;
894 }
895 break;
896 }
897 case SEL_OP_SET: {
898 /* Deselect has already been performed. */
899 ml->flag |= SELECT;
900 break;
901 }
902 case SEL_OP_AND: {
903 BLI_assert_unreachable(); /* Doesn't make sense for picking. */
904 break;
905 }
906 }
907 const Scene *scene = CTX_data_scene(C);
908 ViewLayer *view_layer = CTX_data_view_layer(C);
909 MetaBall *mb = (MetaBall *)base->object->data;
910 mb->lastelem = ml;
911
914
915 BKE_view_layer_synced_ensure(scene, view_layer);
916 if (BKE_view_layer_active_base_get(view_layer) != base) {
918 }
919
920 changed = true;
921 }
922
923 return changed || found;
924}
925
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:183
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:296
bool BKE_mball_select_all_multi_ex(blender::Span< Base * > bases)
bool BKE_mball_is_any_selected(const MetaBall *mb)
Definition mball.cc:274
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:97
#define BLI_assert(a)
Definition BLI_assert.h:50
unsigned int BLI_ghashutil_strhash_p(const void *ptr)
A KD-tree for nearest neighbor search.
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#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:58
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:93
void BLI_rcti_init_pt_radius(struct rcti *rect, const int xy[2], int size)
Definition rct.c:470
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:1068
@ MB_SCALE_RAD
@ MB_HIDE
@ MB_ELIPSOID
Object is a sort of wrapper for general info.
#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_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)
@ SEL_OP_ADD
@ SEL_OP_SUB
@ SEL_OP_SET
@ SEL_OP_AND
@ SEL_OP_XOR
ViewContext ED_view3d_viewcontext_init(bContext *C, Depsgraph *depsgraph)
int view3d_opengl_select(const ViewContext *vc, GPUSelectBuffer *buffer, const rcti *input, eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter)
@ VIEW3D_SELECT_PICK_ALL
Definition ED_view3d.hh:918
@ VIEW3D_SELECT_PICK_NEAREST
Definition ED_view3d.hh:920
@ VIEW3D_SELECT_FILTER_NOP
Definition ED_view3d.hh:925
Read Guarded memory(de)allocation.
@ ALERT_ICON_NONE
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define NC_GEOM
Definition WM_types.hh:360
#define ND_DATA
Definition WM_types.hh:475
#define ND_SELECT
Definition WM_types.hh:474
static unsigned long seed
Definition btSoftBody.h:39
#define SELECT
const Depsgraph * depsgraph
#define cosf(x)
#define fabsf(x)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
CCL_NAMESPACE_BEGIN ccl_device float invert(float color, float factor)
Definition invert.h:9
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
ccl_device_inline float4 select(const int4 mask, const float4 a, const float4 b)
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)
void MBALL_OT_hide_metaelems(wmOperatorType *ot)
bool ED_mball_select_pick(bContext *C, const int mval[2], const SelectPick_Params *params)
static int delete_metaelems_invoke(bContext *C, wmOperator *op, const wmEvent *)
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)
void ED_mball_editmball_free(Object *obedit)
Definition mball_edit.cc:62
void ED_mball_editmball_load(Object *)
Definition mball_edit.cc:87
static const EnumPropertyItem prop_similar_types[]
static int select_random_metaelems_exec(bContext *C, wmOperator *op)
void MBALL_OT_duplicate_metaelems(wmOperatorType *ot)
static int duplicate_metaelems_exec(bContext *C, wmOperator *)
@ SIMMBALL_STIFFNESS
@ SIMMBALL_TYPE
@ SIMMBALL_RADIUS
@ SIMMBALL_ROTATION
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)
static int mball_select_all_exec(bContext *C, wmOperator *op)
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)
void MBALL_OT_delete_metaelems(wmOperatorType *ot)
void MBALL_OT_reveal_metaelems(wmOperatorType *ot)
static int reveal_metaelems_exec(bContext *C, wmOperator *op)
static int hide_metaelems_exec(bContext *C, wmOperator *op)
static int delete_metaelems_exec(bContext *C, wmOperator *)
Base * ED_mball_base_and_elem_from_select_buffer(const Span< Base * > bases, const uint select_id, MetaElem **r_ml)
static int mball_select_similar_exec(bContext *C, wmOperator *op)
void ED_mball_editmball_make(Object *obedit)
Definition mball_edit.cc:70
void base_activate(bContext *C, Base *base)
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:46
Definition DNA_ID.h:413
char name[66]
Definition DNA_ID.h:425
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:69
ViewLayer * view_layer
Definition ED_view3d.hh:70
View3D * v3d
Definition ED_view3d.hh:74
Object * obact
Definition ED_view3d.hh:71
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
PropertyRNA * prop
Definition WM_types.hh:1092
StructRNA * srna
Definition WM_types.hh:1080
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4125
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)
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
int WM_operator_confirm_ex(bContext *C, wmOperator *op, const char *title, const char *message, const char *confirm_text, int icon, bool cancel_default)