Blender V4.5
view3d_buttons.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cfloat>
10#include <cstring>
11
12#include "DNA_armature_types.h"
13#include "DNA_curve_types.h"
14#include "DNA_lattice_types.h"
15#include "DNA_mesh_types.h"
16#include "DNA_meshdata_types.h"
17#include "DNA_meta_types.h"
18#include "DNA_object_types.h"
19#include "DNA_scene_types.h"
20
21#include "MEM_guardedalloc.h"
22
23#include "BLT_translation.hh"
24
25#include "BLI_array_utils.h"
26#include "BLI_bit_vector.hh"
27#include "BLI_listbase.h"
28#include "BLI_math_matrix.h"
29#include "BLI_math_rotation.h"
30#include "BLI_math_vector.h"
31#include "BLI_string.h"
32#include "BLI_utildefines.h"
33#include "BLI_vector.hh"
34
35#include "BKE_action.hh"
36#include "BKE_armature.hh"
37#include "BKE_context.hh"
38#include "BKE_curve.hh"
39#include "BKE_curves.hh"
40#include "BKE_customdata.hh"
41#include "BKE_deform.hh"
42#include "BKE_editmesh.hh"
43#include "BKE_layer.hh"
44#include "BKE_library.hh"
45#include "BKE_mesh_types.hh"
46#include "BKE_object.hh"
47#include "BKE_object_deform.h"
48#include "BKE_object_types.hh"
49#include "BKE_report.hh"
50#include "BKE_screen.hh"
51
52#include "DEG_depsgraph.hh"
53
54#include "WM_api.hh"
55#include "WM_types.hh"
56
57#include "RNA_access.hh"
58#include "RNA_prototypes.hh"
59
60#include "ED_curves.hh"
61#include "ED_grease_pencil.hh"
62#include "ED_mesh.hh"
63#include "ED_object.hh"
64#include "ED_object_vgroup.hh"
65#include "ED_screen.hh"
66
68
69#include "UI_interface.hh"
70#include "UI_resources.hh"
71
72#include "view3d_intern.hh" /* own include */
73
74/* ******************* view3d space & buttons ************** */
75enum {
76 B_REDR = 2,
79};
80
81/* All must start w/ location */
82
84 float location[3];
85};
86
90
94
98
102
104 float location[3];
105};
106
115
116/* temporary struct for storing transform properties */
117
119 float ob_obmat_orig[4][4];
120 float ob_dims_orig[3];
122 float ob_dims[3];
124 /* Floats only (treated as an array). */
127};
128
129#define TRANSFORM_MEDIAN_ARRAY_LEN (sizeof(TransformMedian) / sizeof(float))
130
132
133/* -------------------------------------------------------------------- */
136
139 void *arg1)
140{
141 const int retval_test = B_TRANSFORM_PANEL_MEDIAN;
143 params->unique_retval_ids, params->unique_retval_ids_len, &retval_test) == -1)
144 {
145 return nullptr;
146 }
147
148 BMEditMesh *em = static_cast<BMEditMesh *>(arg1);
149
150 int verts_mask_count = 0;
151 BMIter iter;
152 BMVert *eve;
153 int i;
154
155 blender::BitVector<> verts_mask(em->bm->totvert);
156 BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
158 continue;
159 }
160 verts_mask[i].set();
161 verts_mask_count += 1;
162 }
163
164 BMPartialUpdate_Params update_params{};
165 update_params.do_tessellate = true;
166 update_params.do_normals = true;
168 *em->bm, update_params, verts_mask, verts_mask_count);
169
170 return bmpinfo;
171}
172
174 const uiBlockInteraction_Params * /*params*/,
175 void * /*arg1*/,
176 void *user_data)
177{
178 BMPartialUpdate *bmpinfo = static_cast<BMPartialUpdate *>(user_data);
179 if (bmpinfo == nullptr) {
180 return;
181 }
183}
184
186 const uiBlockInteraction_Params * /*params*/,
187 void *arg1,
188 void *user_data)
189{
190 BMPartialUpdate *bmpinfo = static_cast<BMPartialUpdate *>(user_data);
191 if (bmpinfo == nullptr) {
192 return;
193 }
194
195 View3D *v3d = CTX_wm_view3d(C);
197 if (tfp->tag_for_update == false) {
198 return;
199 }
200 tfp->tag_for_update = false;
201
202 BMEditMesh *em = static_cast<BMEditMesh *>(arg1);
203
205}
206
208
209/* Helper function to compute a median changed value,
210 * when the value should be clamped in [0.0, 1.0].
211 * Returns either 0.0, 1.0 (both can be applied directly), a positive scale factor
212 * for scale down, or a negative one for scale up.
213 */
214static float compute_scale_factor(const float ve_median, const float median)
215{
216 if (ve_median <= 0.0f) {
217 return 0.0f;
218 }
219 if (ve_median >= 1.0f) {
220 return 1.0f;
221 }
222
223 /* Scale value to target median. */
224 float median_new = ve_median;
225 float median_orig = ve_median - median; /* Previous median value. */
226
227 /* In case of floating point error. */
228 CLAMP(median_orig, 0.0f, 1.0f);
229 CLAMP(median_new, 0.0f, 1.0f);
230
231 if (median_new <= median_orig) {
232 /* Scale down. */
233 return median_new / median_orig;
234 }
235
236 /* Scale up, negative to indicate it... */
237 return -(1.0f - median_new) / (1.0f - median_orig);
238}
239
246static void apply_raw_diff(float *val, const int tot, const float ve_median, const float median)
247{
248 *val = (tot == 1) ? ve_median : (*val + median);
249}
250
251static void apply_raw_diff_v3(float val[3],
252 const int tot,
253 const float ve_median[3],
254 const float median[3])
255{
256 if (tot == 1) {
257 copy_v3_v3(val, ve_median);
258 }
259 else {
260 add_v3_v3(val, median);
261 }
262}
263
265 float *val, const int tot, const float ve_median, const float median, const float sca)
266{
267 if (tot == 1 || ve_median == median) {
268 *val = ve_median;
269 }
270 else {
271 *val *= sca;
272 }
273}
274
275static void apply_scale_factor_clamp(float *val,
276 const int tot,
277 const float ve_median,
278 const float sca)
279{
280 if (tot == 1) {
281 *val = ve_median;
282 CLAMP(*val, 0.0f, 1.0f);
283 }
284 else if (ELEM(sca, 0.0f, 1.0f)) {
285 *val = sca;
286 }
287 else {
288 *val = (sca > 0.0f) ? (*val * sca) : (1.0f + ((1.0f - *val) * sca));
289 CLAMP(*val, 0.0f, 1.0f);
290 }
291}
292
294{
295 if (v3d->runtime.properties_storage == nullptr) {
296 TransformProperties *tfp = MEM_new<TransformProperties>("TransformProperties");
297 /* Construct C++ structures in otherwise zero initialized struct. */
298 new (tfp) TransformProperties();
299
300 v3d->runtime.properties_storage = tfp;
301 v3d->runtime.properties_storage_free = [](void *properties_storage) {
302 MEM_delete(static_cast<TransformProperties *>(properties_storage));
303 };
304 }
305 return static_cast<TransformProperties *>(v3d->runtime.properties_storage);
306}
307
308/* is used for both read and write... */
310 const bContext *C, uiLayout *layout, View3D *v3d, Object *ob, float lim)
311{
312 using namespace blender;
313 uiBlock *block = (layout) ? layout->absolute_block() : nullptr;
315 TransformMedian median_basis, ve_median_basis;
316 int tot, totedgedata, totcurvedata, totlattdata, totcurvebweight;
317 bool has_meshdata = false;
318 bool has_skinradius = false;
319 PointerRNA data_ptr;
320
321 copy_vn_fl((float *)&median_basis, TRANSFORM_MEDIAN_ARRAY_LEN, 0.0f);
322 tot = totedgedata = totcurvedata = totlattdata = totcurvebweight = 0;
323
324 if (ob->type == OB_MESH) {
325 TransformMedian_Mesh *median = &median_basis.mesh;
326 Mesh *mesh = static_cast<Mesh *>(ob->data);
327 BMEditMesh *em = mesh->runtime->edit_mesh.get();
328 BMesh *bm = em->bm;
329 BMVert *eve;
330 BMEdge *eed;
331 BMIter iter;
332
333 const int cd_vert_bweight_offset = CustomData_get_offset_named(
334 &bm->vdata, CD_PROP_FLOAT, "bevel_weight_vert");
335 const int cd_vert_crease_offset = CustomData_get_offset_named(
336 &bm->vdata, CD_PROP_FLOAT, "crease_vert");
337 const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
338 const int cd_edge_bweight_offset = CustomData_get_offset_named(
339 &bm->edata, CD_PROP_FLOAT, "bevel_weight_edge");
340 const int cd_edge_crease_offset = CustomData_get_offset_named(
341 &bm->edata, CD_PROP_FLOAT, "crease_edge");
342
343 has_skinradius = (cd_vert_skin_offset != -1);
344
345 if (bm->totvertsel) {
346 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
348 tot++;
349 add_v3_v3(median->location, eve->co);
350
351 if (cd_vert_bweight_offset != -1) {
352 median->bv_weight += BM_ELEM_CD_GET_FLOAT(eve, cd_vert_bweight_offset);
353 }
354
355 if (cd_vert_crease_offset != -1) {
356 median->v_crease += BM_ELEM_CD_GET_FLOAT(eve, cd_vert_crease_offset);
357 }
358
359 if (has_skinradius) {
360 MVertSkin *vs = static_cast<MVertSkin *>(
361 BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset));
362 add_v2_v2(median->skin, vs->radius); /* Third val not used currently. */
363 }
364 }
365 }
366 }
367
368 if ((cd_edge_bweight_offset != -1) || (cd_edge_crease_offset != -1)) {
369 if (bm->totedgesel) {
370 BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
372 if (cd_edge_bweight_offset != -1) {
373 median->be_weight += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_bweight_offset);
374 }
375
376 if (cd_edge_crease_offset != -1) {
377 median->e_crease += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_crease_offset);
378 }
379
380 totedgedata++;
381 }
382 }
383 }
384 }
385 else {
386 totedgedata = bm->totedgesel;
387 }
388
389 has_meshdata = (tot || totedgedata);
390 }
391 else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
392 TransformMedian_Curve *median = &median_basis.curve;
393 Curve *cu = static_cast<Curve *>(ob->data);
394 BPoint *bp;
395 BezTriple *bezt;
396 int a;
398 StructRNA *seltype = nullptr;
399 void *selp = nullptr;
400
401 LISTBASE_FOREACH (Nurb *, nu, nurbs) {
402 if (nu->type == CU_BEZIER) {
403 bezt = nu->bezt;
404 a = nu->pntsu;
405 while (a--) {
406 if (bezt->f2 & SELECT) {
407 add_v3_v3(median->location, bezt->vec[1]);
408 tot++;
409 median->weight += bezt->weight;
410 median->radius += bezt->radius;
411 median->tilt += bezt->tilt;
412 if (!totcurvedata) { /* I.e. first time... */
413 selp = bezt;
414 seltype = &RNA_BezierSplinePoint;
415 }
416 totcurvedata++;
417 }
418 else {
419 if (bezt->f1 & SELECT) {
420 add_v3_v3(median->location, bezt->vec[0]);
421 tot++;
422 }
423 if (bezt->f3 & SELECT) {
424 add_v3_v3(median->location, bezt->vec[2]);
425 tot++;
426 }
427 }
428 bezt++;
429 }
430 }
431 else {
432 bp = nu->bp;
433 a = nu->pntsu * nu->pntsv;
434 while (a--) {
435 if (bp->f1 & SELECT) {
436 add_v3_v3(median->location, bp->vec);
437 median->b_weight += bp->vec[3];
438 totcurvebweight++;
439 tot++;
440 median->weight += bp->weight;
441 median->radius += bp->radius;
442 median->tilt += bp->tilt;
443 if (!totcurvedata) { /* I.e. first time... */
444 selp = bp;
445 seltype = &RNA_SplinePoint;
446 }
447 totcurvedata++;
448 }
449 bp++;
450 }
451 }
452 }
453
454 if (totcurvedata == 1) {
455 data_ptr = RNA_pointer_create_discrete(&cu->id, seltype, selp);
456 }
457 }
458 else if (ob->type == OB_LATTICE) {
459 Lattice *lt = static_cast<Lattice *>(ob->data);
460 TransformMedian_Lattice *median = &median_basis.lattice;
461 BPoint *bp;
462 int a;
463 StructRNA *seltype = nullptr;
464 void *selp = nullptr;
465
466 a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
467 bp = lt->editlatt->latt->def;
468 while (a--) {
469 if (bp->f1 & SELECT) {
470 add_v3_v3(median->location, bp->vec);
471 tot++;
472 median->weight += bp->weight;
473 if (!totlattdata) { /* I.e. first time... */
474 selp = bp;
475 seltype = &RNA_LatticePoint;
476 }
477 totlattdata++;
478 }
479 bp++;
480 }
481
482 if (totlattdata == 1) {
483 data_ptr = RNA_pointer_create_discrete(&lt->id, seltype, selp);
484 }
485 }
486 else if (ob->type == OB_GREASE_PENCIL) {
487 using namespace blender::ed::greasepencil;
488 using namespace ed::curves;
489 Scene &scene = *CTX_data_scene(C);
490 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
492 grease_pencil);
493
494 threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) {
496 if (curves.is_empty()) {
497 return;
498 }
499
500 const Span<StringRef> selection_names = get_curves_selection_attribute_names(curves);
501 Vector<Span<float3>> positions = get_curves_positions(curves);
502 TransformMedian_Curves &median = median_basis.curves;
503 for (int attribute_i : selection_names.index_range()) {
504 IndexMaskMemory memory;
505 const IndexMask selection = retrieve_selected_points(
506 curves, selection_names[attribute_i], memory);
507 if (selection.is_empty()) {
508 continue;
509 }
510
511 tot += selection.size();
512 selection.foreach_index(
513 [&](const int point) { add_v3_v3(median.location, positions[attribute_i][point]); });
514 }
515 });
516 }
517 else if (ob->type == OB_CURVES) {
518 using namespace ed::curves;
519 const Curves &curves_id = *static_cast<Curves *>(ob->data);
520 const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
521 if (curves.is_empty()) {
522 return;
523 }
524
525 const Span<StringRef> selection_names = get_curves_selection_attribute_names(curves);
526 const Vector<Span<float3>> positions = get_curves_positions(curves);
527 TransformMedian_Curves &median = median_basis.curves;
528 for (int attribute_i : selection_names.index_range()) {
529 IndexMaskMemory memory;
530 const IndexMask selection = retrieve_selected_points(
531 curves, selection_names[attribute_i], memory);
532 if (selection.is_empty()) {
533 continue;
534 }
535
536 tot += selection.size();
537 selection.foreach_index(
538 [&](const int point) { add_v3_v3(median.location, positions[attribute_i][point]); });
539 }
540 }
541
542 if (tot == 0) {
543 uiDefBut(
544 block, UI_BTYPE_LABEL, 0, IFACE_("Nothing selected"), 0, 130, 200, 20, nullptr, 0, 0, "");
545 return;
546 }
547
548 /* Location, X/Y/Z */
549 mul_v3_fl(median_basis.generic.location, 1.0f / float(tot));
550 if (v3d->flag & V3D_GLOBAL_STATS) {
551 mul_m4_v3(ob->object_to_world().ptr(), median_basis.generic.location);
552 }
553
554 if (has_meshdata) {
555 TransformMedian_Mesh *median = &median_basis.mesh;
556 if (totedgedata) {
557 median->e_crease /= float(totedgedata);
558 median->be_weight /= float(totedgedata);
559 }
560 if (tot) {
561 median->bv_weight /= float(tot);
562 median->v_crease /= float(tot);
563 if (has_skinradius) {
564 median->skin[0] /= float(tot);
565 median->skin[1] /= float(tot);
566 }
567 }
568 }
569 else if (totcurvedata) {
570 TransformMedian_Curve *median = &median_basis.curve;
571 if (totcurvebweight) {
572 median->b_weight /= float(totcurvebweight);
573 }
574 median->weight /= float(totcurvedata);
575 median->radius /= float(totcurvedata);
576 median->tilt /= float(totcurvedata);
577 }
578 else if (totlattdata) {
579 TransformMedian_Lattice *median = &median_basis.lattice;
580 median->weight /= float(totlattdata);
581 }
582
583 if (block) { /* buttons */
584 uiBut *but;
585 int yi = 200;
586 const float tilt_limit = DEG2RADF(21600.0f);
587 const int butw = 200;
588 const int buth = 20 * UI_SCALE_FAC;
589 const int but_margin = 2;
590 const char *c;
591
592 memcpy(&tfp->ve_median, &median_basis, sizeof(tfp->ve_median));
593
595 if (tot == 1) {
596 if (totcurvedata) {
597 /* Curve */
598 c = IFACE_("Control Point:");
599 }
600 else if (ELEM(ob->type, OB_CURVES, OB_GREASE_PENCIL)) {
601 c = IFACE_("Point:");
602 }
603 else {
604 /* Mesh or lattice */
605 c = IFACE_("Vertex:");
606 }
607 }
608 else {
609 c = IFACE_("Median:");
610 }
611 uiDefBut(block, UI_BTYPE_LABEL, 0, c, 0, yi -= buth, butw, buth, nullptr, 0, 0, "");
612
614
615 /* Should be no need to translate these. */
616 but = uiDefButF(block,
619 IFACE_("X:"),
620 0,
621 yi -= buth,
622 butw,
623 buth,
624 &tfp->ve_median.generic.location[0],
625 -lim,
626 lim,
627 "");
631 but = uiDefButF(block,
634 IFACE_("Y:"),
635 0,
636 yi -= buth,
637 butw,
638 buth,
639 &tfp->ve_median.generic.location[1],
640 -lim,
641 lim,
642 "");
646 but = uiDefButF(block,
649 IFACE_("Z:"),
650 0,
651 yi -= buth,
652 butw,
653 buth,
654 &tfp->ve_median.generic.location[2],
655 -lim,
656 lim,
657 "");
661
662 if (totcurvebweight == tot) {
663 but = uiDefButF(block,
666 IFACE_("W:"),
667 0,
668 yi -= buth,
669 butw,
670 buth,
671 &(tfp->ve_median.curve.b_weight),
672 0.01,
673 100.0,
674 "");
677 }
678
680 uiDefButBitS(block,
683 B_REDR,
684 IFACE_("Global"),
685 0,
686 yi -= buth + but_margin,
687 100,
688 buth,
689 &v3d->flag,
690 0,
691 0,
692 TIP_("Displays global values"));
693 uiDefButBitS(block,
696 B_REDR,
697 IFACE_("Local"),
698 100,
699 yi,
700 100,
701 buth,
702 &v3d->flag,
703 0,
704 0,
705 TIP_("Displays local values"));
706 UI_block_align_end(block);
707
708 /* Meshes... */
709 if (has_meshdata) {
710 TransformMedian_Mesh *ve_median = &tfp->ve_median.mesh;
711 if (tot) {
712 uiDefBut(block,
714 0,
715 tot == 1 ? IFACE_("Vertex Data:") : IFACE_("Vertices Data:"),
716 0,
717 yi -= buth + but_margin,
718 butw,
719 buth,
720 nullptr,
721 0.0,
722 0.0,
723 "");
724 /* customdata layer added on demand */
725 but = uiDefButF(block,
728 tot == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"),
729 0,
730 yi -= buth + but_margin,
731 butw,
732 buth,
733 &ve_median->bv_weight,
734 0.0,
735 1.0,
736 TIP_("Vertex weight used by Bevel modifier"));
739 /* customdata layer added on demand */
740 but = uiDefButF(block,
743 tot == 1 ? IFACE_("Vertex Crease:") : IFACE_("Mean Vertex Crease:"),
744 0,
745 yi -= buth + but_margin,
746 butw,
747 buth,
748 &ve_median->v_crease,
749 0.0,
750 1.0,
751 TIP_("Weight used by the Subdivision Surface modifier"));
754 }
755 if (has_skinradius) {
757 but = uiDefButF(block,
760 tot == 1 ? IFACE_("Radius X:") : IFACE_("Mean Radius X:"),
761 0,
762 yi -= buth + but_margin,
763 butw,
764 buth,
765 &ve_median->skin[0],
766 0.0,
767 100.0,
768 TIP_("X radius used by Skin modifier"));
771 but = uiDefButF(block,
774 tot == 1 ? IFACE_("Radius Y:") : IFACE_("Mean Radius Y:"),
775 0,
776 yi -= buth + but_margin,
777 butw,
778 buth,
779 &ve_median->skin[1],
780 0.0,
781 100.0,
782 TIP_("Y radius used by Skin modifier"));
785 UI_block_align_end(block);
786 }
787 if (totedgedata) {
788 uiDefBut(block,
790 0,
791 totedgedata == 1 ? IFACE_("Edge Data:") : IFACE_("Edges Data:"),
792 0,
793 yi -= buth + but_margin,
794 butw,
795 buth,
796 nullptr,
797 0.0,
798 0.0,
799 "");
800 /* customdata layer added on demand */
801 but = uiDefButF(block,
804 totedgedata == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"),
805 0,
806 yi -= buth + but_margin,
807 butw,
808 buth,
809 &ve_median->be_weight,
810 0.0,
811 1.0,
812 TIP_("Edge weight used by Bevel modifier"));
815 /* customdata layer added on demand */
816 but = uiDefButF(block,
819 totedgedata == 1 ? IFACE_("Crease:") : IFACE_("Mean Crease:"),
820 0,
821 yi -= buth + but_margin,
822 butw,
823 buth,
824 &ve_median->e_crease,
825 0.0,
826 1.0,
827 TIP_("Weight used by the Subdivision Surface modifier"));
830 }
831 }
832 /* Curve... */
833 else if (totcurvedata) {
834 TransformMedian_Curve *ve_median = &tfp->ve_median.curve;
835 if (totcurvedata == 1) {
836 but = uiDefButR(block,
838 0,
839 IFACE_("Weight:"),
840 0,
841 yi -= buth + but_margin,
842 butw,
843 buth,
844 &data_ptr,
845 "weight_softbody",
846 0,
847 0.0,
848 1.0,
849 std::nullopt);
852 but = uiDefButR(block,
854 0,
855 IFACE_("Radius:"),
856 0,
857 yi -= buth + but_margin,
858 butw,
859 buth,
860 &data_ptr,
861 "radius",
862 0,
863 0.0,
864 100.0,
865 std::nullopt);
868 but = uiDefButR(block,
870 0,
871 IFACE_("Tilt:"),
872 0,
873 yi -= buth + but_margin,
874 butw,
875 buth,
876 &data_ptr,
877 "tilt",
878 0,
879 -tilt_limit,
881 std::nullopt);
884 }
885 else if (totcurvedata > 1) {
886 but = uiDefButF(block,
889 IFACE_("Mean Weight:"),
890 0,
891 yi -= buth + but_margin,
892 butw,
893 buth,
894 &ve_median->weight,
895 0.0,
896 1.0,
897 TIP_("Weight used for Soft Body Goal"));
900 but = uiDefButF(block,
903 IFACE_("Mean Radius:"),
904 0,
905 yi -= buth + but_margin,
906 butw,
907 buth,
908 &ve_median->radius,
909 0.0,
910 100.0,
911 TIP_("Radius of curve control points"));
914 but = uiDefButF(block,
917 IFACE_("Mean Tilt:"),
918 0,
919 yi -= buth + but_margin,
920 butw,
921 buth,
922 &ve_median->tilt,
923 -tilt_limit,
925 TIP_("Tilt of curve control points"));
929 }
930 }
931 /* Lattice... */
932 else if (totlattdata) {
933 TransformMedian_Lattice *ve_median = &tfp->ve_median.lattice;
934 if (totlattdata == 1) {
935 but = uiDefButR(block,
937 0,
938 IFACE_("Weight:"),
939 0,
940 yi -= buth + but_margin,
941 butw,
942 buth,
943 &data_ptr,
944 "weight_softbody",
945 0,
946 0.0,
947 1.0,
948 std::nullopt);
951 }
952 else if (totlattdata > 1) {
953 but = uiDefButF(block,
956 IFACE_("Mean Weight:"),
957 0,
958 yi -= buth + but_margin,
959 butw,
960 buth,
961 &ve_median->weight,
962 0.0,
963 1.0,
964 TIP_("Weight used for Soft Body Goal"));
967 }
968 }
969
970 UI_block_align_end(block);
971
972 if (ob->type == OB_MESH) {
973 Mesh *mesh = static_cast<Mesh *>(ob->data);
974 if (BMEditMesh *em = mesh->runtime->edit_mesh.get()) {
975 uiBlockInteraction_CallbackData callback_data{};
979 callback_data.arg1 = em;
980 UI_block_interaction_set(block, &callback_data);
981 }
982 }
983 }
984 else { /* apply */
985 memcpy(&ve_median_basis, &tfp->ve_median, sizeof(tfp->ve_median));
986
987 if (v3d->flag & V3D_GLOBAL_STATS) {
988 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
989 mul_m4_v3(ob->world_to_object().ptr(), median_basis.generic.location);
990 mul_m4_v3(ob->world_to_object().ptr(), ve_median_basis.generic.location);
991 }
992 sub_vn_vnvn((float *)&median_basis,
993 (float *)&ve_median_basis,
994 (float *)&median_basis,
996
997 /* Note with a single element selected, we always do. */
998 const bool apply_vcos = (tot == 1) || (len_squared_v3(median_basis.generic.location) != 0.0f);
999
1000 if ((ob->type == OB_MESH) &&
1001 (apply_vcos || median_basis.mesh.bv_weight || median_basis.mesh.v_crease ||
1002 median_basis.mesh.skin[0] || median_basis.mesh.skin[1] || median_basis.mesh.be_weight ||
1003 median_basis.mesh.e_crease))
1004 {
1005 const TransformMedian_Mesh *median = &median_basis.mesh, *ve_median = &ve_median_basis.mesh;
1006 Mesh *mesh = static_cast<Mesh *>(ob->data);
1007 BMEditMesh *em = mesh->runtime->edit_mesh.get();
1008 BMesh *bm = em->bm;
1009 BMIter iter;
1010 BMVert *eve;
1011 BMEdge *eed;
1012
1013 int cd_vert_bweight_offset = -1;
1014 int cd_vert_crease_offset = -1;
1015 int cd_vert_skin_offset = -1;
1016 int cd_edge_bweight_offset = -1;
1017 int cd_edge_crease_offset = -1;
1018
1019 float scale_bv_weight = 1.0f;
1020 float scale_v_crease = 1.0f;
1021 float scale_skin[2] = {1.0f, 1.0f};
1022 float scale_be_weight = 1.0f;
1023 float scale_e_crease = 1.0f;
1024
1025 /* Vertices */
1026
1027 if (apply_vcos || median->bv_weight || median->v_crease || median->skin[0] ||
1028 median->skin[1])
1029 {
1030 if (median->bv_weight) {
1031 if (!CustomData_has_layer_named(&bm->vdata, CD_PROP_FLOAT, "bevel_weight_vert")) {
1032 BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_FLOAT, "bevel_weight_vert");
1033 }
1034 cd_vert_bweight_offset = CustomData_get_offset_named(
1035 &bm->vdata, CD_PROP_FLOAT, "bevel_weight_vert");
1036 BLI_assert(cd_vert_bweight_offset != -1);
1037
1038 scale_bv_weight = compute_scale_factor(ve_median->bv_weight, median->bv_weight);
1039 }
1040
1041 if (median->v_crease) {
1042 if (!CustomData_has_layer_named(&bm->vdata, CD_PROP_FLOAT, "crease_vert")) {
1043 BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_FLOAT, "crease_vert");
1044 }
1045 cd_vert_crease_offset = CustomData_get_offset_named(
1046 &bm->vdata, CD_PROP_FLOAT, "crease_vert");
1047 BLI_assert(cd_vert_crease_offset != -1);
1048
1049 scale_v_crease = compute_scale_factor(ve_median->v_crease, median->v_crease);
1050 }
1051
1052 for (int i = 0; i < 2; i++) {
1053 if (median->skin[i]) {
1054 cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
1055 BLI_assert(cd_vert_skin_offset != -1);
1056
1057 if (ve_median->skin[i] != median->skin[i]) {
1058 scale_skin[i] = ve_median->skin[i] / (ve_median->skin[i] - median->skin[i]);
1059 }
1060 }
1061 }
1062
1063 BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
1065 if (apply_vcos) {
1066 apply_raw_diff_v3(eve->co, tot, ve_median->location, median->location);
1067 }
1068
1069 if (cd_vert_bweight_offset != -1) {
1070 float *b_weight = static_cast<float *>(
1071 BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset));
1072 apply_scale_factor_clamp(b_weight, tot, ve_median->bv_weight, scale_bv_weight);
1073 }
1074
1075 if (cd_vert_crease_offset != -1) {
1076 float *crease = static_cast<float *>(
1077 BM_ELEM_CD_GET_VOID_P(eve, cd_vert_crease_offset));
1078 apply_scale_factor_clamp(crease, tot, ve_median->v_crease, scale_v_crease);
1079 }
1080
1081 if (cd_vert_skin_offset != -1) {
1082 MVertSkin *vs = static_cast<MVertSkin *>(
1083 BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset));
1084
1085 /* That one is not clamped to [0.0, 1.0]. */
1086 for (int i = 0; i < 2; i++) {
1087 if (median->skin[i] != 0.0f) {
1089 &vs->radius[i], tot, ve_median->skin[i], median->skin[i], scale_skin[i]);
1090 }
1091 }
1092 }
1093 }
1094 }
1095 }
1096
1097 if (apply_vcos) {
1098 /* Tell the update callback to run. */
1099 tfp->tag_for_update = true;
1100 }
1101
1102 /* Edges */
1103
1104 if (median->be_weight || median->e_crease) {
1105 if (median->be_weight) {
1106 if (!CustomData_has_layer_named(&bm->edata, CD_PROP_FLOAT, "bevel_weight_edge")) {
1107 BM_data_layer_add_named(bm, &bm->edata, CD_PROP_FLOAT, "bevel_weight_edge");
1108 }
1109 cd_edge_bweight_offset = CustomData_get_offset_named(
1110 &bm->edata, CD_PROP_FLOAT, "bevel_weight_edge");
1111 BLI_assert(cd_edge_bweight_offset != -1);
1112
1113 scale_be_weight = compute_scale_factor(ve_median->be_weight, median->be_weight);
1114 }
1115
1116 if (median->e_crease) {
1117 if (!CustomData_has_layer_named(&bm->edata, CD_PROP_FLOAT, "crease_edge")) {
1118 BM_data_layer_add_named(bm, &bm->edata, CD_PROP_FLOAT, "crease_edge");
1119 }
1120 cd_edge_crease_offset = CustomData_get_offset_named(
1121 &bm->edata, CD_PROP_FLOAT, "crease_edge");
1122 BLI_assert(cd_edge_crease_offset != -1);
1123
1124 scale_e_crease = compute_scale_factor(ve_median->e_crease, median->e_crease);
1125 }
1126
1127 BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
1129 if (median->be_weight != 0.0f) {
1130 float *b_weight = static_cast<float *>(
1131 BM_ELEM_CD_GET_VOID_P(eed, cd_edge_bweight_offset));
1132 apply_scale_factor_clamp(b_weight, tot, ve_median->be_weight, scale_be_weight);
1133 }
1134
1135 if (median->e_crease != 0.0f) {
1136 float *crease = static_cast<float *>(
1137 BM_ELEM_CD_GET_VOID_P(eed, cd_edge_crease_offset));
1138 apply_scale_factor_clamp(crease, tot, ve_median->e_crease, scale_e_crease);
1139 }
1140 }
1141 }
1142 }
1143 }
1144 else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF) &&
1145 (apply_vcos || median_basis.curve.b_weight || median_basis.curve.weight ||
1146 median_basis.curve.radius || median_basis.curve.tilt))
1147 {
1148 const TransformMedian_Curve *median = &median_basis.curve,
1149 *ve_median = &ve_median_basis.curve;
1150 Curve *cu = static_cast<Curve *>(ob->data);
1151 BPoint *bp;
1152 BezTriple *bezt;
1153 int a;
1154 ListBase *nurbs = BKE_curve_editNurbs_get(cu);
1155 const float scale_w = compute_scale_factor(ve_median->weight, median->weight);
1156
1157 LISTBASE_FOREACH (Nurb *, nu, nurbs) {
1158 if (nu->type == CU_BEZIER) {
1159 for (a = nu->pntsu, bezt = nu->bezt; a--; bezt++) {
1160 if (bezt->f2 & SELECT) {
1161 if (apply_vcos) {
1162 /* Here we always have to use the diff... :/
1163 * Cannot avoid some glitches when going e.g. from 3 to 0.0001 (see #37327),
1164 * unless we use doubles.
1165 */
1166 add_v3_v3(bezt->vec[0], median->location);
1167 add_v3_v3(bezt->vec[1], median->location);
1168 add_v3_v3(bezt->vec[2], median->location);
1169 }
1170 if (median->weight) {
1171 apply_scale_factor_clamp(&bezt->weight, tot, ve_median->weight, scale_w);
1172 }
1173 if (median->radius) {
1174 apply_raw_diff(&bezt->radius, tot, ve_median->radius, median->radius);
1175 }
1176 if (median->tilt) {
1177 apply_raw_diff(&bezt->tilt, tot, ve_median->tilt, median->tilt);
1178 }
1179 }
1180 else if (apply_vcos) {
1181 /* Handles can only have their coordinates changed here. */
1182 if (bezt->f1 & SELECT) {
1183 apply_raw_diff_v3(bezt->vec[0], tot, ve_median->location, median->location);
1184 }
1185 if (bezt->f3 & SELECT) {
1186 apply_raw_diff_v3(bezt->vec[2], tot, ve_median->location, median->location);
1187 }
1188 }
1189 }
1190 }
1191 else {
1192 for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a--; bp++) {
1193 if (bp->f1 & SELECT) {
1194 if (apply_vcos) {
1195 apply_raw_diff_v3(bp->vec, tot, ve_median->location, median->location);
1196 }
1197 if (median->b_weight) {
1198 apply_raw_diff(&bp->vec[3], tot, ve_median->b_weight, median->b_weight);
1199 }
1200 if (median->weight) {
1201 apply_scale_factor_clamp(&bp->weight, tot, ve_median->weight, scale_w);
1202 }
1203 if (median->radius) {
1204 apply_raw_diff(&bp->radius, tot, ve_median->radius, median->radius);
1205 }
1206 if (median->tilt) {
1207 apply_raw_diff(&bp->tilt, tot, ve_median->tilt, median->tilt);
1208 }
1209 }
1210 }
1211 }
1212 if (CU_IS_2D(cu)) {
1214 }
1215 /* In the case of weight, tilt or radius (these don't change positions),
1216 * don't change handle types. */
1217 if ((nu->type == CU_BEZIER) && apply_vcos) {
1218 BKE_nurb_handles_test(nu, NURB_HANDLE_TEST_EACH, false); /* test for bezier too */
1219 }
1220 }
1221 }
1222 else if ((ob->type == OB_LATTICE) && (apply_vcos || median_basis.lattice.weight)) {
1223 const TransformMedian_Lattice *median = &median_basis.lattice,
1224 *ve_median = &ve_median_basis.lattice;
1225 Lattice *lt = static_cast<Lattice *>(ob->data);
1226 BPoint *bp;
1227 int a;
1228 const float scale_w = compute_scale_factor(ve_median->weight, median->weight);
1229
1230 a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
1231 bp = lt->editlatt->latt->def;
1232 while (a--) {
1233 if (bp->f1 & SELECT) {
1234 if (apply_vcos) {
1235 apply_raw_diff_v3(bp->vec, tot, ve_median->location, median->location);
1236 }
1237 if (median->weight) {
1238 apply_scale_factor_clamp(&bp->weight, tot, ve_median->weight, scale_w);
1239 }
1240 }
1241 bp++;
1242 }
1243 }
1244 else if (ob->type == OB_GREASE_PENCIL && apply_vcos) {
1245 using namespace blender::ed::greasepencil;
1246 using namespace ed::curves;
1247 Scene &scene = *CTX_data_scene(C);
1248 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
1250 grease_pencil);
1251
1252 threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) {
1254 if (curves.is_empty()) {
1255 return;
1256 }
1257
1258 TransformMedian_GreasePencil &median = median_basis.grease_pencil;
1259 TransformMedian_GreasePencil &ve_median = ve_median_basis.grease_pencil;
1260 IndexMaskMemory memory;
1261 const Span<StringRef> selection_names = get_curves_selection_attribute_names(curves);
1262 const Vector<MutableSpan<float3>> positions = get_curves_positions_for_write(curves);
1263 for (int attribute_i : selection_names.index_range()) {
1264 const IndexMask selection = retrieve_selected_points(
1265 curves, selection_names[attribute_i], memory);
1266 if (selection.is_empty()) {
1267 continue;
1268 }
1269
1270 selection.foreach_index([&](const int point) {
1272 positions[attribute_i][point], tot, ve_median.location, median.location);
1273 });
1275 }
1276 });
1277 }
1278 else if (ob->type == OB_CURVES && apply_vcos) {
1279 using namespace ed::curves;
1280 Curves &curves_id = *static_cast<Curves *>(ob->data);
1281 bke::CurvesGeometry &curves = curves_id.geometry.wrap();
1282 if (curves.is_empty()) {
1283 return;
1284 }
1285
1286 TransformMedian_Curves &median = median_basis.curves;
1287 TransformMedian_Curves &ve_median = ve_median_basis.curves;
1288 IndexMaskMemory memory;
1289 const Span<StringRef> selection_names = get_curves_selection_attribute_names(curves);
1290 Vector<MutableSpan<float3>> positions = get_curves_positions_for_write(curves);
1291 for (int attribute_i : selection_names.index_range()) {
1292 const IndexMask selection = retrieve_selected_points(
1293 curves, selection_names[attribute_i], memory);
1294 if (selection.is_empty()) {
1295 continue;
1296 }
1297
1298 selection.foreach_index([&](const int point) {
1300 positions[attribute_i][point], tot, ve_median.location, median.location);
1301 });
1302 }
1303 curves.tag_positions_changed();
1304 }
1305 }
1306
1307 // ED_undo_push(C, "Transform properties");
1308}
1309
1310#undef TRANSFORM_MEDIAN_ARRAY_LEN
1311
1313{
1314 uiBlock *block = (layout) ? layout->absolute_block() : nullptr;
1316 const bool is_editable = ID_IS_EDITABLE(&ob->id);
1317
1318 if (block) {
1319 BLI_assert(C == nullptr);
1320 int yi = 200;
1321 const int butw = 200;
1322 const int buth = 20 * UI_SCALE_FAC;
1323
1325 copy_v3_v3(tfp->ob_dims_orig, tfp->ob_dims);
1326 copy_v3_v3(tfp->ob_scale_orig, ob->scale);
1327 copy_m4_m4(tfp->ob_obmat_orig, ob->object_to_world().ptr());
1328
1329 uiDefBut(block,
1331 0,
1332 IFACE_("Dimensions:"),
1333 0,
1334 yi -= buth,
1335 butw,
1336 buth,
1337 nullptr,
1338 0,
1339 0,
1340 "");
1341 UI_block_align_begin(block);
1342 const float lim = FLT_MAX;
1343 for (int i = 0; i < 3; i++) {
1344 uiBut *but;
1345 const char text[3] = {char('X' + i), ':', '\0'};
1346 but = uiDefButF(block,
1349 text,
1350 0,
1351 yi -= buth,
1352 butw,
1353 buth,
1354 &(tfp->ob_dims[i]),
1355 0.0f,
1356 lim,
1357 "");
1361 if (!is_editable) {
1362 UI_but_disable(but, "Can't edit this property from a linked data-block");
1363 }
1364 }
1365 UI_block_align_end(block);
1366 }
1367 else { /* apply */
1368 int axis_mask = 0;
1369 for (int i = 0; i < 3; i++) {
1370 if (tfp->ob_dims[i] == tfp->ob_dims_orig[i]) {
1371 axis_mask |= (1 << i);
1372 }
1373 }
1375 ob, tfp->ob_dims, axis_mask, tfp->ob_scale_orig, tfp->ob_obmat_orig);
1376
1377 PointerRNA obptr = RNA_id_pointer_create(&ob->id);
1378 PropertyRNA *prop = RNA_struct_find_property(&obptr, "scale");
1379 RNA_property_update(C, &obptr, prop);
1380 }
1381}
1382
1383#define B_VGRP_PNL_EDIT_SINGLE 8 /* or greater */
1384
1385static void do_view3d_vgroup_buttons(bContext *C, void * /*arg*/, int event)
1386{
1387 if (event < B_VGRP_PNL_EDIT_SINGLE) {
1388 /* not for me */
1389 return;
1390 }
1391
1392 const Scene *scene = CTX_data_scene(C);
1393 ViewLayer *view_layer = CTX_data_view_layer(C);
1394 BKE_view_layer_synced_ensure(scene, view_layer);
1395 Object *ob = BKE_view_layer_active_object_get(view_layer);
1397 DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_GEOMETRY);
1399}
1400
1401static bool view3d_panel_vgroup_poll(const bContext *C, PanelType * /*pt*/)
1402{
1403 const Scene *scene = CTX_data_scene(C);
1404 ViewLayer *view_layer = CTX_data_view_layer(C);
1405 BKE_view_layer_synced_ensure(scene, view_layer);
1406 Object *ob = BKE_view_layer_active_object_get(view_layer);
1409 if (dvert_act) {
1410 return (dvert_act->totweight != 0);
1411 }
1412 }
1413
1414 return false;
1415}
1416
1417static void update_active_vertex_weight(bContext *C, void *arg1, void * /*arg2*/)
1418{
1419 View3D *v3d = CTX_wm_view3d(C);
1421 ViewLayer *view_layer = CTX_data_view_layer(C);
1422 Object *ob = BKE_view_layer_active_object_get(view_layer);
1424 const int vertex_group_index = POINTER_AS_INT(arg1);
1425 MDeformWeight *dw = BKE_defvert_find_index(dv, vertex_group_index);
1426 dw->weight = tfp->vertex_weights[vertex_group_index];
1427}
1428
1429static void view3d_panel_vgroup(const bContext *C, Panel *panel)
1430{
1431 uiBlock *block = panel->layout->absolute_block();
1432 Scene *scene = CTX_data_scene(C);
1433 ViewLayer *view_layer = CTX_data_view_layer(C);
1434 BKE_view_layer_synced_ensure(scene, view_layer);
1435 Object *ob = BKE_view_layer_active_object_get(view_layer);
1436 View3D *v3d = CTX_wm_view3d(C);
1438
1439 MDeformVert *dv;
1440
1442
1443 if (dv && dv->totweight) {
1444 ToolSettings *ts = scene->toolsettings;
1445
1447 PointerRNA op_ptr;
1448 PointerRNA *but_ptr;
1449
1450 uiLayout *col, *bcol;
1451 uiLayout *row;
1452 uiBut *but;
1453 bDeformGroup *dg;
1454 uint i;
1455 int subset_count, vgroup_tot;
1456 const bool *vgroup_validmap;
1457 eVGroupSelect subset_type = eVGroupSelect(ts->vgroupsubset);
1458 int yco = 0;
1459 int lock_count = 0;
1460
1462
1463 bcol = &panel->layout->column(true);
1464 row = &bcol->row(true); /* The filter button row */
1465
1466 PointerRNA tools_ptr = RNA_pointer_create_discrete(nullptr, &RNA_ToolSettings, ts);
1467 row->prop(&tools_ptr, "vertex_group_subset", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
1468
1469 col = &bcol->column(true);
1470
1472 ob, subset_type, &vgroup_tot, &subset_count);
1473 const ListBase *defbase = BKE_object_defgroup_list(ob);
1474 const int vgroup_num = BLI_listbase_count(defbase);
1475 tfp->vertex_weights.resize(vgroup_num);
1476
1477 for (i = 0, dg = static_cast<bDeformGroup *>(defbase->first); dg; i++, dg = dg->next) {
1478 bool locked = (dg->flag & DG_LOCK_WEIGHT) != 0;
1479 if (vgroup_validmap[i]) {
1481 if (dw) {
1482 int x, xco = 0;
1483 int icon;
1484 uiLayout *split = &col->split(0.45, true);
1485 row = &split->row(true);
1486
1487 /* The Weight Group Name */
1488
1489 ot = WM_operatortype_find("OBJECT_OT_vertex_weight_set_active", true);
1490 but = uiDefButO_ptr(block,
1492 ot,
1494 dg->name,
1495 xco,
1496 yco,
1497 (x = UI_UNIT_X * 5),
1498 UI_UNIT_Y,
1499 "");
1500 but_ptr = UI_but_operator_ptr_ensure(but);
1501 RNA_int_set(but_ptr, "weight_group", i);
1503 if (BKE_object_defgroup_active_index_get(ob) != i + 1) {
1505 }
1506 xco += x;
1507
1508 row = &split->row(true);
1509 uiLayoutSetEnabled(row, !locked);
1510
1511 /* The weight group value */
1512 /* To be reworked still */
1513 float &vertex_weight = tfp->vertex_weights[i];
1514 vertex_weight = dw->weight;
1515 but = uiDefButF(block,
1518 "",
1519 xco,
1520 yco,
1521 (x = UI_UNIT_X * 4),
1522 UI_UNIT_Y,
1523 &vertex_weight,
1524 0.0,
1525 1.0,
1526 "");
1531 if (locked) {
1532 lock_count++;
1533 }
1534 xco += x;
1535
1536 /* The weight group paste function */
1537 icon = (locked) ? ICON_BLANK1 : ICON_PASTEDOWN;
1538 op_ptr = row->op(
1539 "OBJECT_OT_vertex_weight_paste", "", icon, WM_OP_INVOKE_DEFAULT, UI_ITEM_NONE);
1540 RNA_int_set(&op_ptr, "weight_group", i);
1541
1542 /* The weight entry delete function */
1543 icon = (locked) ? ICON_LOCKED : ICON_X;
1544 op_ptr = row->op(
1545 "OBJECT_OT_vertex_weight_delete", "", icon, WM_OP_INVOKE_DEFAULT, UI_ITEM_NONE);
1546 RNA_int_set(&op_ptr, "weight_group", i);
1547
1548 yco -= UI_UNIT_Y;
1549 }
1550 }
1551 }
1552 MEM_freeN(vgroup_validmap);
1553
1554 yco -= 2;
1555
1556 col = &panel->layout->column(true);
1557 row = &col->row(true);
1558
1559 ot = WM_operatortype_find("OBJECT_OT_vertex_weight_normalize_active_vertex", true);
1560 but = uiDefButO_ptr(
1561 block,
1563 ot,
1565 IFACE_("Normalize"),
1566 0,
1567 yco,
1568 UI_UNIT_X * 5,
1569 UI_UNIT_Y,
1570 TIP_("Normalize weights of active vertex (if affected groups are unlocked)"));
1571
1572 ot = WM_operatortype_find("OBJECT_OT_vertex_weight_copy", true);
1573 but = uiDefButO_ptr(
1574 block,
1576 ot,
1578 IFACE_("Copy"),
1579 UI_UNIT_X * 5,
1580 yco,
1581 UI_UNIT_X * 5,
1582 UI_UNIT_Y,
1583 TIP_("Copy active vertex to other selected vertices (if affected groups are unlocked)"));
1584 if (lock_count) {
1586 }
1587 }
1588}
1589
1591{
1592 uiLayout *split, *colsub;
1593
1594 split = &layout->split(0.8f, false);
1595
1596 if (ptr->type == &RNA_PoseBone) {
1597 PointerRNA boneptr;
1598 Bone *bone;
1599
1600 boneptr = RNA_pointer_get(ptr, "bone");
1601 bone = static_cast<Bone *>(boneptr.data);
1602 uiLayoutSetActive(split, !(bone->parent && bone->flag & BONE_CONNECTED));
1603 }
1604 colsub = &split->column(true);
1605 colsub->prop(ptr, "location", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1606 colsub = &split->column(true);
1608 colsub->label("", ICON_NONE);
1609 colsub->prop(
1610 ptr, "lock_location", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED);
1611
1612 split = &layout->split(0.8f, false);
1613
1614 switch (RNA_enum_get(ptr, "rotation_mode")) {
1615 case ROT_MODE_QUAT: /* quaternion */
1616 colsub = &split->column(true);
1617 colsub->prop(ptr, "rotation_quaternion", UI_ITEM_NONE, IFACE_("Rotation"), ICON_NONE);
1618 colsub = &split->column(true);
1620 colsub->prop(ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, IFACE_("4L"), ICON_NONE);
1621 if (RNA_boolean_get(ptr, "lock_rotations_4d")) {
1622 colsub->prop(ptr,
1623 "lock_rotation_w",
1625 "",
1626 ICON_DECORATE_UNLOCKED);
1627 }
1628 else {
1629 colsub->label("", ICON_NONE);
1630 }
1631 colsub->prop(ptr,
1632 "lock_rotation",
1634 "",
1635 ICON_DECORATE_UNLOCKED);
1636 break;
1637 case ROT_MODE_AXISANGLE: /* axis angle */
1638 colsub = &split->column(true);
1639 colsub->prop(ptr, "rotation_axis_angle", UI_ITEM_NONE, IFACE_("Rotation"), ICON_NONE);
1640 colsub = &split->column(true);
1642 colsub->prop(ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, IFACE_("4L"), ICON_NONE);
1643 if (RNA_boolean_get(ptr, "lock_rotations_4d")) {
1644 colsub->prop(ptr,
1645 "lock_rotation_w",
1647 "",
1648 ICON_DECORATE_UNLOCKED);
1649 }
1650 else {
1651 colsub->label("", ICON_NONE);
1652 }
1653 colsub->prop(ptr,
1654 "lock_rotation",
1656 "",
1657 ICON_DECORATE_UNLOCKED);
1658 break;
1659 default: /* euler rotations */
1660 colsub = &split->column(true);
1661 colsub->prop(ptr, "rotation_euler", UI_ITEM_NONE, IFACE_("Rotation"), ICON_NONE);
1662 colsub = &split->column(true);
1664 colsub->label("", ICON_NONE);
1665 colsub->prop(ptr,
1666 "lock_rotation",
1668 "",
1669 ICON_DECORATE_UNLOCKED);
1670 break;
1671 }
1672 layout->prop(ptr, "rotation_mode", UI_ITEM_NONE, "", ICON_NONE);
1673
1674 split = &layout->split(0.8f, false);
1675 colsub = &split->column(true);
1676 colsub->prop(ptr, "scale", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1677 colsub = &split->column(true);
1679 colsub->label("", ICON_NONE);
1680 colsub->prop(
1681 ptr, "lock_scale", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED);
1682}
1683
1684static void v3d_posearmature_buts(uiLayout *layout, Object *ob)
1685{
1686 bPoseChannel *pchan;
1687 uiLayout *col;
1688
1690
1691 if (!pchan) {
1692 layout->label(IFACE_("No Bone Active"), ICON_NONE);
1693 return;
1694 }
1695
1696 PointerRNA pchanptr = RNA_pointer_create_discrete(&ob->id, &RNA_PoseBone, pchan);
1697
1698 col = &layout->column(false);
1699
1700 /* XXX: RNA buts show data in native types (i.e. quaternion, 4-component axis/angle, etc.)
1701 * but old-school UI shows in eulers always. Do we want to be able to still display in Eulers?
1702 * Maybe needs RNA/UI options to display rotations as different types. */
1703 v3d_transform_butsR(col, &pchanptr);
1704}
1705
1706static void v3d_editarmature_buts(uiLayout *layout, Object *ob)
1707{
1708 bArmature *arm = static_cast<bArmature *>(ob->data);
1709 EditBone *ebone;
1710 uiLayout *col;
1711
1712 ebone = arm->act_edbone;
1713
1714 if (!ebone || !ANIM_bonecoll_is_visible_editbone(arm, ebone)) {
1715 layout->label(IFACE_("Nothing selected"), ICON_NONE);
1716 return;
1717 }
1718
1719 PointerRNA eboneptr = RNA_pointer_create_discrete(&arm->id, &RNA_EditBone, ebone);
1720
1721 col = &layout->column(false);
1722 col->prop(&eboneptr, "head", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1723 if (ebone->parent && ebone->flag & BONE_CONNECTED) {
1724 PointerRNA parptr = RNA_pointer_get(&eboneptr, "parent");
1725 col->prop(&parptr, "tail_radius", UI_ITEM_NONE, IFACE_("Radius (Parent)"), ICON_NONE);
1726 }
1727 else {
1728 col->prop(&eboneptr, "head_radius", UI_ITEM_NONE, IFACE_("Radius"), ICON_NONE);
1729 }
1730
1731 col->prop(&eboneptr, "tail", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1732 col->prop(&eboneptr, "tail_radius", UI_ITEM_NONE, IFACE_("Radius"), ICON_NONE);
1733
1734 col->prop(&eboneptr, "roll", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1735 col->prop(&eboneptr, "length", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1736 col->prop(&eboneptr, "envelope_distance", UI_ITEM_NONE, IFACE_("Envelope"), ICON_NONE);
1737}
1738
1739static void v3d_editmetaball_buts(uiLayout *layout, Object *ob)
1740{
1741 MetaBall *mball = static_cast<MetaBall *>(ob->data);
1742 uiLayout *col;
1743
1744 if (!mball || !(mball->lastelem)) {
1745 layout->label(IFACE_("Nothing selected"), ICON_NONE);
1746 return;
1747 }
1748
1749 PointerRNA ptr = RNA_pointer_create_discrete(&mball->id, &RNA_MetaElement, mball->lastelem);
1750
1751 col = &layout->column(false);
1752 col->prop(&ptr, "co", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1753
1754 col->prop(&ptr, "radius", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1755 col->prop(&ptr, "stiffness", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1756
1757 col->prop(&ptr, "type", UI_ITEM_NONE, std::nullopt, ICON_NONE);
1758
1759 col = &layout->column(true);
1760 switch (RNA_enum_get(&ptr, "type")) {
1761 case MB_BALL:
1762 break;
1763 case MB_CUBE:
1764 col->label(IFACE_("Size:"), ICON_NONE);
1765 col->prop(&ptr, "size_x", UI_ITEM_NONE, "X", ICON_NONE);
1766 col->prop(&ptr, "size_y", UI_ITEM_NONE, "Y", ICON_NONE);
1767 col->prop(&ptr, "size_z", UI_ITEM_NONE, "Z", ICON_NONE);
1768 break;
1769 case MB_TUBE:
1770 col->label(IFACE_("Size:"), ICON_NONE);
1771 col->prop(&ptr, "size_x", UI_ITEM_NONE, "X", ICON_NONE);
1772 break;
1773 case MB_PLANE:
1774 col->label(IFACE_("Size:"), ICON_NONE);
1775 col->prop(&ptr, "size_x", UI_ITEM_NONE, "X", ICON_NONE);
1776 col->prop(&ptr, "size_y", UI_ITEM_NONE, "Y", ICON_NONE);
1777 break;
1778 case MB_ELIPSOID:
1779 col->label(IFACE_("Size:"), ICON_NONE);
1780 col->prop(&ptr, "size_x", UI_ITEM_NONE, "X", ICON_NONE);
1781 col->prop(&ptr, "size_y", UI_ITEM_NONE, "Y", ICON_NONE);
1782 col->prop(&ptr, "size_z", UI_ITEM_NONE, "Z", ICON_NONE);
1783 break;
1784 }
1785}
1786
1787static void do_view3d_region_buttons(bContext *C, void * /*index*/, int event)
1788{
1789 Scene *scene = CTX_data_scene(C);
1790 ViewLayer *view_layer = CTX_data_view_layer(C);
1791 View3D *v3d = CTX_wm_view3d(C);
1792 BKE_view_layer_synced_ensure(scene, view_layer);
1793 Object *ob = BKE_view_layer_active_object_get(view_layer);
1794
1795 switch (event) {
1796
1797 case B_REDR:
1799 return; /* no notifier! */
1800
1802 if (ob) {
1803 v3d_editvertex_buts(C, nullptr, v3d, ob, 1.0);
1804 DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_GEOMETRY);
1805 }
1806 break;
1808 if (ob) {
1809 v3d_object_dimension_buts(C, nullptr, v3d, ob);
1810 }
1811 break;
1812 }
1813
1814 /* default for now */
1816}
1817
1819{
1820 const Scene *scene = CTX_data_scene(C);
1821 ViewLayer *view_layer = CTX_data_view_layer(C);
1822 BKE_view_layer_synced_ensure(scene, view_layer);
1823 return (BKE_view_layer_active_base_get(view_layer) != nullptr);
1824}
1825
1826static void view3d_panel_transform(const bContext *C, Panel *panel)
1827{
1828 uiBlock *block;
1829 const Scene *scene = CTX_data_scene(C);
1830 ViewLayer *view_layer = CTX_data_view_layer(C);
1831 BKE_view_layer_synced_ensure(scene, view_layer);
1832 Object *ob = BKE_view_layer_active_object_get(view_layer);
1833 Object *obedit = OBEDIT_FROM_OBACT(ob);
1834 uiLayout *col;
1835
1836 block = uiLayoutGetBlock(panel->layout);
1838
1839 col = &panel->layout->column(false);
1840
1841 if (ob == obedit) {
1842 if (ob->type == OB_ARMATURE) {
1844 }
1845 else if (ob->type == OB_MBALL) {
1847 }
1848 else {
1849 View3D *v3d = CTX_wm_view3d(C);
1850 v3d_editvertex_buts(C, col, v3d, ob, FLT_MAX);
1851 }
1852 }
1853 else if (ob->mode & OB_MODE_POSE) {
1855 }
1856 else {
1857 PointerRNA obptr = RNA_id_pointer_create(&ob->id);
1858 v3d_transform_butsR(col, &obptr);
1859
1860 /* Dimensions and editmode are mostly the same check. */
1862 {
1863 View3D *v3d = CTX_wm_view3d(C);
1864 v3d_object_dimension_buts(nullptr, col, v3d, ob);
1865 }
1866 }
1867}
1868
1873
1875{
1876 PanelType *pt;
1877
1878 pt = MEM_callocN<PanelType>("spacetype view3d panel object");
1879 STRNCPY(pt->idname, "VIEW3D_PT_transform");
1880 STRNCPY(pt->label, N_("Transform")); /* XXX C panels unavailable through RNA bpy.types! */
1881 STRNCPY(pt->category, "Item");
1885 BLI_addtail(&art->paneltypes, pt);
1886
1887 pt = MEM_callocN<PanelType>("spacetype view3d panel vgroup");
1888 STRNCPY(pt->idname, "VIEW3D_PT_vgroup");
1889 STRNCPY(pt->label, N_("Vertex Weights")); /* XXX C panels unavailable through RNA bpy.types! */
1890 STRNCPY(pt->category, "Item");
1894 BLI_addtail(&art->paneltypes, pt);
1895
1896 MenuType *mt;
1897
1898 mt = MEM_callocN<MenuType>("spacetype view3d menu collections");
1899 STRNCPY(mt->idname, "VIEW3D_MT_collection");
1900 STRNCPY(mt->label, N_("Collection"));
1903 WM_menutype_add(mt);
1904}
1905
1907{
1909 if (ob == nullptr) {
1910 BKE_report(op->reports, RPT_WARNING, "No active object found");
1911 return OPERATOR_CANCELLED;
1912 }
1913 if (((ob->mode & OB_MODE_EDIT) == 0) && ELEM(ob->type, OB_ARMATURE)) {
1915 return OPERATOR_CANCELLED;
1916 }
1917
1918 UI_pie_menu_invoke(C, "VIEW3D_MT_object_mode_pie", CTX_wm_window(C)->eventstate);
1919 return OPERATOR_CANCELLED;
1920}
1921
1923{
1924 ot->name = "Object Mode Menu";
1925 ot->idname = "VIEW3D_OT_object_mode_pie_or_toggle";
1926
1929
1930 /* flags */
1931 ot->flag = 0;
1932}
C++ functions to deal with Armature collections (i.e. the successor of bone layers).
bool ANIM_bonecoll_is_visible_editbone(const bArmature *armature, const EditBone *ebone)
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_active_if_bonecoll_visible(Object *ob) ATTR_WARN_UNUSED_RESULT
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
@ NURB_HANDLE_TEST_EACH
Definition BKE_curve.hh:61
void BKE_nurb_project_2d(Nurb *nu)
Definition curve.cc:688
#define CU_IS_2D(cu)
Definition BKE_curve.hh:89
void BKE_nurb_handles_test(Nurb *nu, eNurbHandleTest_Mode handle_mode, bool use_around_local)
Definition curve.cc:4088
ListBase * BKE_curve_editNurbs_get(Curve *cu)
Definition curve.cc:423
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
bool CustomData_has_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
support for deformation groups and hooks.
int BKE_object_defgroup_active_index_get(const Object *ob)
Definition deform.cc:596
const ListBase * BKE_object_defgroup_list(const Object *ob)
Definition deform.cc:574
MDeformWeight * BKE_defvert_find_index(const MDeformVert *dv, int defgroup)
Definition deform.cc:795
void BKE_editmesh_looptris_and_normals_calc_with_partial(BMEditMesh *em, BMPartialUpdate *bmpinfo)
Definition editmesh.cc:122
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Base * BKE_view_layer_active_base_get(ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
General operations, lookup, etc. for blender objects.
void BKE_object_dimensions_eval_cached_get(const Object *ob, float r_vec[3])
void BKE_object_dimensions_set_ex(Object *ob, const float value[3], int axis_mask, const float ob_scale_orig[3], const float ob_obmat_orig[4][4])
bool BKE_object_is_in_wpaint_select_vert(const Object *ob)
bool BKE_object_is_in_editmode_vgroup(const Object *ob)
Functions for dealing with objects and deform verts, used by painting and tools.
bool * BKE_object_defgroup_subset_from_select_type(struct Object *ob, enum eVGroupSelect subset_type, int *r_defgroup_tot, int *r_subset_count)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
Generic array manipulation API.
#define BLI_array_findindex(arr, arr_len, p)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
#define DEG2RADF(_deg)
void mul_m4_v3(const float M[4][4], float r[3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void mul_v3_fl(float r[3], float f)
void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, int size)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void copy_vn_fl(float *array_tar, int size, float val)
MINLINE void add_v2_v2(float r[2], const float a[2])
MINLINE void add_v3_v3(float r[3], const float a[3])
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
unsigned int uint
#define CLAMP(a, b, c)
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
#define ELEM(...)
#define TIP_(msgid)
#define IFACE_(msgid)
#define BLT_I18NCONTEXT_DEFAULT_BPYRNA
float[3] Vector
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:982
@ ROT_MODE_QUAT
@ ROT_MODE_AXISANGLE
@ BONE_CONNECTED
@ CU_BEZIER
@ CD_MVERT_SKIN
@ CD_PROP_FLOAT
@ MB_PLANE
@ MB_ELIPSOID
@ MB_TUBE
@ MB_CUBE
@ MB_BALL
@ OB_MODE_EDIT
@ OB_MODE_POSE
@ OB_MODE_OBJECT
Object is a sort of wrapper for general info.
@ DG_LOCK_WEIGHT
@ OB_LATTICE
@ OB_MBALL
@ OB_SURF
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_CURVES
#define OB_TYPE_SUPPORT_EDITMODE(_type)
eVGroupSelect
#define OBEDIT_FROM_OBACT(ob)
#define UI_SCALE_FAC
@ V3D_GLOBAL_STATS
@ OPERATOR_CANCELLED
MDeformVert * ED_mesh_active_dvert_get_only(Object *ob)
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:714
bool ED_operator_view3d_active(bContext *C)
static void split(const char *text, const char *seps, char ***str, int *count)
Read Guarded memory(de)allocation.
@ PROP_UNIT_ROTATION
Definition RNA_types.hh:166
@ PROP_UNIT_LENGTH
Definition RNA_types.hh:162
#define RNA_TRANSLATION_PREC_DEFAULT
Definition RNA_types.hh:212
#define C
Definition RandGen.cpp:29
void UI_but_func_set(uiBut *but, std::function< void(bContext &)> func)
void UI_but_disable(uiBut *but, const char *disabled_hint)
#define UI_UNIT_Y
void UI_block_interaction_set(uiBlock *block, uiBlockInteraction_CallbackData *callbacks)
wmOperatorStatus UI_pie_menu_invoke(bContext *C, const char *idname, const wmEvent *event)
uiBut * uiDefBut(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, std::optional< blender::StringRef > tip)
void UI_but_drawflag_enable(uiBut *but, int flag)
void UI_but_number_step_size_set(uiBut *but, float step_size)
void UI_block_func_handle_set(uiBlock *block, uiBlockHandleFunc func, void *arg)
PointerRNA * UI_but_operator_ptr_ensure(uiBut *but)
void UI_block_align_begin(uiBlock *block)
@ UI_BUT_TEXT_RIGHT
@ UI_BUT_TEXT_LEFT
uiBut * uiDefButBitS(uiBlock *block, int type, int bit, int retval, blender::StringRef str, int x, int y, short width, short height, short *poin, float min, float max, std::optional< blender::StringRef > tip)
void UI_but_number_precision_set(uiBut *but, float precision)
uiBut * uiDefButO_ptr(uiBlock *block, int type, wmOperatorType *ot, wmOperatorCallContext opcontext, blender::StringRef str, int x, int y, short width, short height, std::optional< blender::StringRef > tip)
#define UI_UNIT_X
@ UI_BTYPE_BUT
@ UI_BTYPE_TOGGLE
@ UI_BTYPE_TOGGLE_N
@ UI_BTYPE_LABEL
@ UI_BTYPE_NUM
@ UI_BUT_DISABLED
@ UI_BUT_INACTIVE
uiBut * uiDefButR(uiBlock *block, int type, int retval, std::optional< blender::StringRef > str, int x, int y, short width, short height, PointerRNA *ptr, blender::StringRefNull propname, int index, float min, float max, std::optional< blender::StringRef > tip)
uiBut * uiDefButF(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, float *poin, float min, float max, std::optional< blender::StringRef > tip)
void UI_but_unit_type_set(uiBut *but, int unit_type)
void UI_but_flag_enable(uiBut *but, int flag)
void UI_block_align_end(uiBlock *block)
@ UI_ITEM_R_TOGGLE
@ UI_ITEM_R_EXPAND
@ UI_ITEM_R_ICON_ONLY
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiLayoutSetEnabled(uiLayout *layout, bool enabled)
uiBlock * uiLayoutGetBlock(uiLayout *layout)
#define UI_ITEM_NONE
void uiLayoutSetEmboss(uiLayout *layout, blender::ui::EmbossType emboss)
#define NC_GEOM
Definition WM_types.hh:390
#define ND_DATA
Definition WM_types.hh:506
@ WM_OP_INVOKE_DEFAULT
Definition WM_types.hh:238
@ WM_OP_EXEC_DEFAULT
Definition WM_types.hh:245
#define ND_SPACE_VIEW3D
Definition WM_types.hh:525
#define NC_SPACE
Definition WM_types.hh:389
#define BM_ELEM_CD_GET_FLOAT(ele, offset)
@ BM_ELEM_SELECT
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
#define BM_elem_flag_test(ele, hflag)
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const StringRef name)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
BMesh * bm
BMPartialUpdate * BM_mesh_partial_create_from_verts_group_single(BMesh &bm, const BMPartialUpdate_Params &params, const BitSpan verts_mask, const int verts_mask_count)
void BM_mesh_partial_destroy(BMPartialUpdate *bmpinfo)
int64_t size() const
bool is_empty() const
void foreach_index(Fn &&fn) const
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
void resize(const int64_t new_size)
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
#define SELECT
#define B_REDR
uint col
#define ID_IS_EDITABLE(_id)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
Vector< MutableDrawingInfo > retrieve_editable_drawings(const Scene &scene, GreasePencil &grease_pencil)
void collection_hide_menu_draw(const bContext *C, uiLayout *layout)
bool mode_set(bContext *C, eObjectMode mode)
void vgroup_vert_active_mirror(Object *ob, int def_nr)
void parallel_for_each(Range &&range, const Function &function)
Definition BLI_task.hh:56
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_id_pointer_create(ID *id)
static const float tilt_limit
Definition rna_curve.cc:882
#define FLT_MAX
Definition stdcycles.h:14
ListBase paneltypes
float co[3]
int totvert
uint8_t f1
float vec[4]
float vec[3][3]
struct Bone * parent
CurvesGeometry geometry
EditBone * parent
struct Lattice * latt
Definition DNA_ID.h:404
struct EditLatt * editlatt
struct BPoint * def
void * first
char label[BKE_ST_MAXNAME]
char idname[BKE_ST_MAXNAME]
void(* draw)(const bContext *C, Menu *menu)
char translation_context[BKE_ST_MAXNAME]
uiLayout * layout
MeshRuntimeHandle * runtime
MetaElem * lastelem
ObjectRuntimeHandle * runtime
float scale[3]
void(* draw)(const bContext *C, Panel *panel)
char idname[BKE_ST_MAXNAME]
bool(* poll)(const bContext *C, PanelType *pt)
char translation_context[BKE_ST_MAXNAME]
char category[BKE_ST_MAXNAME]
char label[BKE_ST_MAXNAME]
struct uiLayout * layout
void * data
Definition RNA_types.hh:53
struct ToolSettings * toolsettings
TransformMedian ve_median
blender::Vector< float > vertex_weights
TransformMedian median
void(* properties_storage_free)(void *properties_storage)
View3D_Runtime runtime
struct EditBone * act_edbone
struct bDeformGroup * next
uiBlockInteractionBeginFn begin_fn
uiBlockInteractionEndFn end_fn
uiBlockInteractionUpdateFn update_fn
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, wmOperatorCallContext context, eUI_Item_Flag flag)
uiBlock * absolute_block()
void label(blender::StringRef name, int icon)
uiLayout & column(bool align)
uiLayout & row(bool align)
uiLayout & split(float percentage, bool align)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
struct ReportList * reports
i
Definition text_draw.cc:230
TransformMedian_Mesh mesh
TransformMedian_Lattice lattice
TransformMedian_GreasePencil grease_pencil
TransformMedian_Curves curves
TransformMedian_Generic generic
TransformMedian_Curve curve
#define N_(msgid)
static void apply_raw_diff_v3(float val[3], const int tot, const float ve_median[3], const float median[3])
static void do_view3d_vgroup_buttons(bContext *C, void *, int event)
static void v3d_editarmature_buts(uiLayout *layout, Object *ob)
static void apply_raw_diff(float *val, const int tot, const float ve_median, const float median)
#define TRANSFORM_MEDIAN_ARRAY_LEN
static void v3d_transform_butsR(uiLayout *layout, PointerRNA *ptr)
static void view3d_panel_transform(const bContext *C, Panel *panel)
static void v3d_object_dimension_buts(bContext *C, uiLayout *layout, View3D *v3d, Object *ob)
static void do_view3d_region_buttons(bContext *C, void *, int event)
static void editmesh_partial_update_update_fn(bContext *C, const uiBlockInteraction_Params *, void *arg1, void *user_data)
static void * editmesh_partial_update_begin_fn(bContext *, const uiBlockInteraction_Params *params, void *arg1)
@ B_TRANSFORM_PANEL_DIMS
@ B_TRANSFORM_PANEL_MEDIAN
static void apply_scale_factor_clamp(float *val, const int tot, const float ve_median, const float sca)
void view3d_buttons_register(ARegionType *art)
static float compute_scale_factor(const float ve_median, const float median)
static wmOperatorStatus view3d_object_mode_menu_exec(bContext *C, wmOperator *op)
static void editmesh_partial_update_end_fn(bContext *, const uiBlockInteraction_Params *, void *, void *user_data)
static void update_active_vertex_weight(bContext *C, void *arg1, void *)
static void hide_collections_menu_draw(const bContext *C, Menu *menu)
void VIEW3D_OT_object_mode_pie_or_toggle(wmOperatorType *ot)
#define B_VGRP_PNL_EDIT_SINGLE
static bool view3d_panel_transform_poll(const bContext *C, PanelType *)
static void v3d_editmetaball_buts(uiLayout *layout, Object *ob)
static void v3d_posearmature_buts(uiLayout *layout, Object *ob)
static void view3d_panel_vgroup(const bContext *C, Panel *panel)
static bool view3d_panel_vgroup_poll(const bContext *C, PanelType *)
static TransformProperties * v3d_transform_props_ensure(View3D *v3d)
static void apply_scale_factor(float *val, const int tot, const float ve_median, const float median, const float sca)
static void v3d_editvertex_buts(const bContext *C, uiLayout *layout, View3D *v3d, Object *ob, float lim)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4227
wmOperatorType * ot
Definition wm_files.cc:4226
bool WM_menutype_add(MenuType *mt)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)