Blender V5.0
object_hook.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 <cstdlib>
10#include <cstring>
11
12#include "MEM_guardedalloc.h"
13
14#include "BLI_listbase.h"
15#include "BLI_math_matrix.h"
16#include "BLI_math_vector.h"
17#include "BLI_string_utf8.h"
18#include "BLI_utildefines.h"
19
20#include "DNA_armature_types.h"
21#include "DNA_curve_types.h"
22#include "DNA_lattice_types.h"
23#include "DNA_mesh_types.h"
24#include "DNA_object_types.h"
25#include "DNA_scene_types.h"
26
27#include "BKE_action.hh"
28#include "BKE_context.hh"
29#include "BKE_deform.hh"
30#include "BKE_editmesh.hh"
31#include "BKE_layer.hh"
32#include "BKE_mesh_types.hh"
33#include "BKE_modifier.hh"
34#include "BKE_object.hh"
35#include "BKE_report.hh"
36
37#include "DEG_depsgraph.hh"
40
41#include "RNA_access.hh"
42#include "RNA_define.hh"
43#include "RNA_enum_types.hh"
44#include "RNA_prototypes.hh"
45
46#include "ED_curve.hh"
47#include "ED_mesh.hh"
48#include "ED_screen.hh"
49
50#include "WM_api.hh"
51#include "WM_types.hh"
52
53#include "UI_resources.hh"
54
55#include "object_intern.hh"
56
57namespace blender::ed::object {
58
60 int *r_indexar_num,
61 int **r_indexar,
62 float r_cent[3])
63{
64 BMVert *eve;
65 BMIter iter;
66 int *index, nr, indexar_num = 0;
67
68 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
70 indexar_num++;
71 }
72 }
73 if (indexar_num == 0) {
74 return 0;
75 }
76
77 *r_indexar = index = MEM_malloc_arrayN<int>(indexar_num, "hook indexar");
78 *r_indexar_num = indexar_num;
79 nr = 0;
80 zero_v3(r_cent);
81
82 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
84 *index = nr;
85 index++;
86 add_v3_v3(r_cent, eve->co);
87 }
88 nr++;
89 }
90
91 mul_v3_fl(r_cent, 1.0f / float(indexar_num));
92
93 return indexar_num;
94}
95
96static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, float r_cent[3])
97{
98 const int active_index = BKE_object_defgroup_active_index_get(obedit);
99 const int cd_dvert_offset = active_index ?
101 -1;
102
103 if (cd_dvert_offset != -1) {
104 const int defgrp_index = active_index - 1;
105 int indexar_num = 0;
106
107 MDeformVert *dvert;
108 BMVert *eve;
109 BMIter iter;
110
111 /* find the vertices */
112 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
113 dvert = static_cast<MDeformVert *>(BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset));
114
115 if (BKE_defvert_find_weight(dvert, defgrp_index) > 0.0f) {
116 add_v3_v3(r_cent, eve->co);
117 indexar_num++;
118 }
119 }
120 if (indexar_num) {
121 const ListBase *defbase = BKE_object_defgroup_list(obedit);
122 bDeformGroup *dg = static_cast<bDeformGroup *>(BLI_findlink(defbase, defgrp_index));
123 BLI_strncpy_utf8(r_name, dg->name, sizeof(dg->name));
124 mul_v3_fl(r_cent, 1.0f / float(indexar_num));
125 return true;
126 }
127 }
128
129 return false;
130}
131
133{
134 Mesh *mesh = static_cast<Mesh *>(ob->data);
135 BMEditMesh *em = mesh->runtime->edit_mesh.get();
136 BMVert *eve;
137 BMIter iter;
138 int index = 0, nr = 0;
139
140 if (hmd->indexar == nullptr) {
141 return;
142 }
143
144 BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
145 if (nr == hmd->indexar[index]) {
146 BM_vert_select_set(em->bm, eve, true);
147 if (index < hmd->indexar_num - 1) {
148 index++;
149 }
150 }
151
152 nr++;
153 }
154
156}
157
159 int **r_indexar,
160 int *r_indexar_num,
161 float r_cent[3])
162{
163 BPoint *bp;
164 int *index, nr, indexar_num = 0, a;
165
166 /* count */
167 a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
168 bp = editlatt->def;
169 while (a--) {
170 if (bp->f1 & SELECT) {
171 if (bp->hide == 0) {
172 indexar_num++;
173 }
174 }
175 bp++;
176 }
177
178 if (indexar_num == 0) {
179 return 0;
180 }
181
182 *r_indexar = index = MEM_malloc_arrayN<int>(indexar_num, "hook indexar");
183 *r_indexar_num = indexar_num;
184 nr = 0;
185 zero_v3(r_cent);
186
187 a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
188 bp = editlatt->def;
189 while (a--) {
190 if (bp->f1 & SELECT) {
191 if (bp->hide == 0) {
192 *index = nr;
193 index++;
194 add_v3_v3(r_cent, bp->vec);
195 }
196 }
197 bp++;
198 nr++;
199 }
200
201 mul_v3_fl(r_cent, 1.0f / float(indexar_num));
202
203 return indexar_num;
204}
205
207{
208 Lattice *lt = static_cast<Lattice *>(obedit->data), *editlt;
209 BPoint *bp;
210 int index = 0, nr = 0, a;
211
212 editlt = lt->editlatt->latt;
213 /* count */
214 a = editlt->pntsu * editlt->pntsv * editlt->pntsw;
215 bp = editlt->def;
216 while (a--) {
217 if (hmd->indexar[index] == nr) {
218 bp->f1 |= SELECT;
219 if (index < hmd->indexar_num - 1) {
220 index++;
221 }
222 }
223 nr++;
224 bp++;
225 }
226}
227
229 int **r_indexar,
230 int *r_indexar_num,
231 float r_cent[3])
232{
233 ListBase *editnurb = object_editcurve_get(obedit);
234 BPoint *bp;
235 BezTriple *bezt;
236 int *index, a, nr, indexar_num = 0;
237
238 LISTBASE_FOREACH (Nurb *, nu, editnurb) {
239 if (nu->type == CU_BEZIER) {
240 bezt = nu->bezt;
241 a = nu->pntsu;
242 while (a--) {
243 if (bezt->f1 & SELECT) {
244 indexar_num++;
245 }
246 if (bezt->f2 & SELECT) {
247 indexar_num++;
248 }
249 if (bezt->f3 & SELECT) {
250 indexar_num++;
251 }
252 bezt++;
253 }
254 }
255 else {
256 bp = nu->bp;
257 a = nu->pntsu * nu->pntsv;
258 while (a--) {
259 if (bp->f1 & SELECT) {
260 indexar_num++;
261 }
262 bp++;
263 }
264 }
265 }
266 if (indexar_num == 0) {
267 return 0;
268 }
269
270 *r_indexar = index = MEM_malloc_arrayN<int>(indexar_num, "hook indexar");
271 *r_indexar_num = indexar_num;
272 nr = 0;
273 zero_v3(r_cent);
274
275 LISTBASE_FOREACH (Nurb *, nu, editnurb) {
276 if (nu->type == CU_BEZIER) {
277 bezt = nu->bezt;
278 a = nu->pntsu;
279 while (a--) {
280 if (bezt->f1 & SELECT) {
281 *index = nr;
282 index++;
283 add_v3_v3(r_cent, bezt->vec[0]);
284 }
285 nr++;
286 if (bezt->f2 & SELECT) {
287 *index = nr;
288 index++;
289 add_v3_v3(r_cent, bezt->vec[1]);
290 }
291 nr++;
292 if (bezt->f3 & SELECT) {
293 *index = nr;
294 index++;
295 add_v3_v3(r_cent, bezt->vec[2]);
296 }
297 nr++;
298 bezt++;
299 }
300 }
301 else {
302 bp = nu->bp;
303 a = nu->pntsu * nu->pntsv;
304 while (a--) {
305 if (bp->f1 & SELECT) {
306 *index = nr;
307 index++;
308 add_v3_v3(r_cent, bp->vec);
309 }
310 nr++;
311 bp++;
312 }
313 }
314 }
315
316 mul_v3_fl(r_cent, 1.0f / float(indexar_num));
317
318 return indexar_num;
319}
320
321static bool object_hook_index_array(Main *bmain,
322 Scene *scene,
323 Object *obedit,
324 int **r_indexar,
325 int *r_indexar_num,
326 char *r_name,
327 float r_cent[3])
328{
329 *r_indexar = nullptr;
330 *r_indexar_num = 0;
331 r_name[0] = 0;
332
333 switch (obedit->type) {
334 case OB_MESH: {
335 Mesh *mesh = static_cast<Mesh *>(obedit->data);
336
337 EDBM_mesh_load(bmain, obedit);
338 EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
339
340 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
341
342 BMEditMesh *em = mesh->runtime->edit_mesh.get();
343
345
346 /* check selected vertices first */
347 if (return_editmesh_indexar(em, r_indexar_num, r_indexar, r_cent) == 0) {
348 return return_editmesh_vgroup(obedit, em, r_name, r_cent);
349 }
350 return true;
351 }
352 case OB_CURVES_LEGACY:
353 case OB_SURF:
354 ED_curve_editnurb_load(bmain, obedit);
356 return return_editcurve_indexar(obedit, r_indexar, r_indexar_num, r_cent);
357 case OB_LATTICE: {
358 Lattice *lt = static_cast<Lattice *>(obedit->data);
359 return return_editlattice_indexar(lt->editlatt->latt, r_indexar, r_indexar_num, r_cent);
360 }
361 default:
362 return false;
363 }
364}
365
367{
368 ListBase *editnurb = object_editcurve_get(obedit);
369 BPoint *bp;
370 BezTriple *bezt;
371 int index = 0, a, nr = 0;
372
373 LISTBASE_FOREACH (Nurb *, nu, editnurb) {
374 if (nu->type == CU_BEZIER) {
375 bezt = nu->bezt;
376 a = nu->pntsu;
377 while (a--) {
378 if (nr == hmd->indexar[index]) {
379 bezt->f1 |= SELECT;
380 if (index < hmd->indexar_num - 1) {
381 index++;
382 }
383 }
384 nr++;
385 if (nr == hmd->indexar[index]) {
386 bezt->f2 |= SELECT;
387 if (index < hmd->indexar_num - 1) {
388 index++;
389 }
390 }
391 nr++;
392 if (nr == hmd->indexar[index]) {
393 bezt->f3 |= SELECT;
394 if (index < hmd->indexar_num - 1) {
395 index++;
396 }
397 }
398 nr++;
399
400 bezt++;
401 }
402 }
403 else {
404 bp = nu->bp;
405 a = nu->pntsu * nu->pntsv;
406 while (a--) {
407 if (nr == hmd->indexar[index]) {
408 bp->f1 |= SELECT;
409 if (index < hmd->indexar_num - 1) {
410 index++;
411 }
412 }
413 nr++;
414 bp++;
415 }
416 }
417 }
418}
419
421 bContext *C, PointerRNA *ptr, const int num, Object **r_ob, HookModifierData **r_hmd)
422{
423 Object *ob;
424 HookModifierData *hmd;
425
426 if (ptr->data) { /* if modifier context is available, use that */
427 ob = (Object *)ptr->owner_id;
428 hmd = static_cast<HookModifierData *>(ptr->data);
429 }
430 else { /* use the provided property */
433 }
434
435 if (ob && hmd && (hmd->modifier.type == eModifierType_Hook)) {
436 *r_ob = ob;
437 *r_hmd = hmd;
438 }
439 else {
440 *r_ob = nullptr;
441 *r_hmd = nullptr;
442 }
443}
444
446{
447 if (hmd->indexar == nullptr) {
448 return;
449 }
450
451 if (ob->type == OB_MESH) {
452 select_editbmesh_hook(ob, hmd);
453 }
454 else if (ob->type == OB_LATTICE) {
456 }
457 else if (ob->type == OB_CURVES_LEGACY) {
458 select_editcurve_hook(ob, hmd);
459 }
460 else if (ob->type == OB_SURF) {
461 select_editcurve_hook(ob, hmd);
462 }
463}
464
465/* special poll operators for hook operators */
466/* TODO: check for properties window modifier context too as alternative? */
468{
469 Object *obedit = CTX_data_edit_object(C);
470
471 if (obedit) {
472 if (ED_operator_editmesh(C)) {
473 return true;
474 }
476 return true;
477 }
479 return true;
480 }
481 // if (ED_operator_editmball(C)) return true;
482 }
483
484 return false;
485}
486
488 Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, Object *obedit)
489{
490 Base *basedit;
491 Object *ob;
492 ob = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, nullptr);
493 BKE_view_layer_synced_ensure(scene, view_layer);
494 Base *basact = BKE_view_layer_active_base_get(view_layer);
495 BLI_assert(basact->object == ob);
496 if (v3d && v3d->localvd) {
497 basact->local_view_bits |= v3d->local_view_uid;
498 }
499
500 /* icky, BKE_object_add sets new base as active.
501 * so set it back to the original edit object */
502 basedit = BKE_view_layer_base_find(view_layer, obedit);
503 view_layer->basact = basedit;
504
505 return ob;
506}
507
508static int add_hook_object(const bContext *C,
509 Main *bmain,
510 Scene *scene,
511 ViewLayer *view_layer,
512 View3D *v3d,
513 Object *obedit,
514 Object *ob,
515 int mode,
516 ReportList *reports)
517{
519 ModifierData *md = nullptr;
520 HookModifierData *hmd = nullptr;
521 float cent[3];
522 float pose_mat[4][4];
523 int indexar_num, ok, *indexar;
524 char name[MAX_NAME];
525
526 ok = object_hook_index_array(bmain, scene, obedit, &indexar, &indexar_num, name, cent);
527
528 if (!ok) {
529 BKE_report(reports, RPT_ERROR, "Requires selected vertices or active vertex group");
530 return false;
531 }
532
533 if (mode == OBJECT_ADDHOOK_NEWOB && !ob) {
534
535 ob = add_hook_object_new(bmain, scene, view_layer, v3d, obedit);
536
537 /* transform cent to global coords for loc */
538 mul_v3_m4v3(ob->loc, obedit->object_to_world().ptr(), cent);
539 }
540
541 md = static_cast<ModifierData *>(obedit->modifiers.first);
543 {
544 md = md->next;
545 }
546
548 BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
549 SNPRINTF_UTF8(hmd->modifier.name, "Hook-%s", ob->id.name + 2);
552
553 hmd->object = ob;
554 hmd->indexar = indexar;
555 copy_v3_v3(hmd->cent, cent);
556 hmd->indexar_num = indexar_num;
557 STRNCPY_UTF8(hmd->name, name);
558
559 unit_m4(pose_mat);
560
561 invert_m4_m4(obedit->runtime->world_to_object.ptr(), obedit->object_to_world().ptr());
562 if (mode == OBJECT_ADDHOOK_NEWOB) {
563 /* pass */
564 }
565 else {
566 /* may overwrite with pose-bone location, below */
567 mul_v3_m4v3(cent, obedit->world_to_object().ptr(), ob->object_to_world().location());
568 }
569
570 if (mode == OBJECT_ADDHOOK_SELOB_BONE) {
571 bArmature *arm = static_cast<bArmature *>(ob->data);
573 if (arm->act_bone) {
574 bPoseChannel *pchan_act;
575
576 STRNCPY_UTF8(hmd->subtarget, arm->act_bone->name);
577
579 if (LIKELY(pchan_act)) {
580 invert_m4_m4(pose_mat, pchan_act->pose_mat);
581 mul_v3_m4v3(cent, ob->object_to_world().ptr(), pchan_act->pose_mat[3]);
582 mul_v3_m4v3(cent, obedit->world_to_object().ptr(), cent);
583 }
584 }
585 else {
586 BKE_report(reports, RPT_WARNING, "Armature has no active object bone");
587 }
588 }
589
590 copy_v3_v3(hmd->cent, cent);
591
592 /* matrix calculus */
593 /* vert x (obmat x hook->world_to_object) x hook->object_to_world().ptr() x ob->world_to_object
594 */
595 /* (parentinv) */
597 Object *object_eval = DEG_get_evaluated(depsgraph, ob);
598 BKE_object_transform_copy(object_eval, ob);
599 BKE_object_where_is_calc(depsgraph, scene_eval, object_eval);
600
601 invert_m4_m4(object_eval->runtime->world_to_object.ptr(), object_eval->object_to_world().ptr());
602 /* apparently this call goes from right to left... */
604 pose_mat,
605 object_eval->world_to_object().ptr(),
606 obedit->object_to_world().ptr());
607
610
611 return true;
612}
613
615{
616 Main *bmain = CTX_data_main(C);
617 Scene *scene = CTX_data_scene(C);
618 ViewLayer *view_layer = CTX_data_view_layer(C);
619 Object *obedit = CTX_data_edit_object(C);
620 Object *obsel = nullptr;
621 const bool use_bone = RNA_boolean_get(op->ptr, "use_bone");
622 const int mode = use_bone ? OBJECT_ADDHOOK_SELOB_BONE : OBJECT_ADDHOOK_SELOB;
623
624 CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
625 if (ob != obedit) {
626 obsel = ob;
627 break;
628 }
629 }
631
632 if (!obsel) {
633 BKE_report(op->reports, RPT_ERROR, "Cannot add hook with no other selected objects");
634 return OPERATOR_CANCELLED;
635 }
636
637 if (use_bone && obsel->type != OB_ARMATURE) {
638 BKE_report(op->reports, RPT_ERROR, "Cannot add hook bone for a non armature object");
639 return OPERATOR_CANCELLED;
640 }
641
642 if (add_hook_object(C, bmain, scene, view_layer, nullptr, obedit, obsel, mode, op->reports)) {
644 return OPERATOR_FINISHED;
645 }
646 return OPERATOR_CANCELLED;
647}
648
650{
651 /* identifiers */
652 ot->name = "Hook to Selected Object";
653 ot->description = "Hook selected vertices to the first selected object";
654 ot->idname = "OBJECT_OT_hook_add_selob";
655
656 /* API callbacks. */
658 ot->poll = hook_op_edit_poll;
659
660 /* flags */
662
663 RNA_def_boolean(ot->srna,
664 "use_bone",
665 false,
666 "Active Bone",
667 "Assign the hook to the hook object's active bone");
668}
669
671{
672 Main *bmain = CTX_data_main(C);
673 Scene *scene = CTX_data_scene(C);
674 ViewLayer *view_layer = CTX_data_view_layer(C);
675 View3D *v3d = CTX_wm_view3d(C);
676 Object *obedit = CTX_data_edit_object(C);
677
678 if (add_hook_object(
679 C, bmain, scene, view_layer, v3d, obedit, nullptr, OBJECT_ADDHOOK_NEWOB, op->reports))
680 {
684 return OPERATOR_FINISHED;
685 }
686 return OPERATOR_CANCELLED;
687}
688
690{
691 /* identifiers */
692 ot->name = "Hook to New Object";
693 ot->description = "Hook selected vertices to a newly created object";
694 ot->idname = "OBJECT_OT_hook_add_newob";
695
696 /* API callbacks. */
698 ot->poll = hook_op_edit_poll;
699
700 /* flags */
702}
703
705{
706 int num = RNA_enum_get(op->ptr, "modifier");
708 HookModifierData *hmd = nullptr;
709
711 if (!hmd) {
712 BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
713 return OPERATOR_CANCELLED;
714 }
715
716 /* remove functionality */
717
720
724
725 return OPERATOR_FINISHED;
726}
727
729 PointerRNA * /*ptr*/,
730 PropertyRNA * /*prop*/,
731 bool *r_free)
732{
734 EnumPropertyItem tmp = {0, "", 0, "", ""};
735 EnumPropertyItem *item = nullptr;
736 ModifierData *md = nullptr;
737 int a, totitem = 0;
738
739 if (!ob) {
741 }
742
743 for (a = 0, md = static_cast<ModifierData *>(ob->modifiers.first); md; md = md->next, a++) {
744 if (md->type == eModifierType_Hook) {
745 tmp.value = a;
746 tmp.icon = ICON_HOOK;
747 tmp.identifier = md->name;
748 tmp.name = md->name;
749 RNA_enum_item_add(&item, &totitem, &tmp);
750 }
751 }
752
753 RNA_enum_item_end(&item, &totitem);
754 *r_free = true;
755
756 return item;
757}
758
760{
761 PropertyRNA *prop;
762
763 /* identifiers */
764 ot->name = "Remove Hook";
765 ot->idname = "OBJECT_OT_hook_remove";
766 ot->description = "Remove a hook from the active object";
767
768 /* API callbacks. */
770 ot->invoke = WM_menu_invoke;
771 ot->poll = hook_op_edit_poll;
772
773 /* flags */
774 /* this operator removes modifier which isn't stored in local undo stack, * so redoing it from
775 * redo panel gives totally weird results. */
776 ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
777
778 /* properties */
779 prop = RNA_def_enum(
780 ot->srna, "modifier", rna_enum_dummy_NULL_items, 0, "Modifier", "Modifier number to remove");
783 ot->prop = prop;
784}
785
787{
788 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
789 int num = RNA_enum_get(op->ptr, "modifier");
790 Object *ob = nullptr;
791 HookModifierData *hmd = nullptr;
792
793 object_hook_from_context(C, &ptr, num, &ob, &hmd);
794 if (hmd == nullptr) {
795 BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
796 return OPERATOR_CANCELLED;
797 }
798
800
803
804 return OPERATOR_FINISHED;
805}
806
808{
809 PropertyRNA *prop;
810
811 /* identifiers */
812 ot->name = "Reset Hook";
813 ot->description = "Recalculate and clear offset transformation";
814 ot->idname = "OBJECT_OT_hook_reset";
815
816 /* callbacks */
818 ot->poll = hook_op_edit_poll;
819
820 /* flags */
822
823 /* properties */
824 prop = RNA_def_enum(ot->srna,
825 "modifier",
827 0,
828 "Modifier",
829 "Modifier number to assign to");
832}
833
835{
836 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
837 int num = RNA_enum_get(op->ptr, "modifier");
838 Object *ob = nullptr;
839 HookModifierData *hmd = nullptr;
840 Scene *scene = CTX_data_scene(C);
841 float bmat[3][3], imat[3][3];
842
843 object_hook_from_context(C, &ptr, num, &ob, &hmd);
844 if (hmd == nullptr) {
845 BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
846 return OPERATOR_CANCELLED;
847 }
848
849 /* recenter functionality */
850 copy_m3_m4(bmat, ob->object_to_world().ptr());
851 invert_m3_m3(imat, bmat);
852
853 sub_v3_v3v3(hmd->cent, scene->cursor.location, ob->object_to_world().location());
854 mul_m3_v3(imat, hmd->cent);
855
858
859 return OPERATOR_FINISHED;
860}
861
863{
864 PropertyRNA *prop;
865
866 /* identifiers */
867 ot->name = "Recenter Hook";
868 ot->description = "Set hook center to cursor position";
869 ot->idname = "OBJECT_OT_hook_recenter";
870
871 /* callbacks */
873 ot->poll = hook_op_edit_poll;
874
875 /* flags */
877
878 /* properties */
879 prop = RNA_def_enum(ot->srna,
880 "modifier",
882 0,
883 "Modifier",
884 "Modifier number to assign to");
887}
888
890{
891 Main *bmain = CTX_data_main(C);
892 Scene *scene = CTX_data_scene(C);
893 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
894 int num = RNA_enum_get(op->ptr, "modifier");
895 Object *ob = nullptr;
896 HookModifierData *hmd = nullptr;
897 float cent[3];
898 char name[MAX_NAME];
899 int *indexar, indexar_num;
900
901 object_hook_from_context(C, &ptr, num, &ob, &hmd);
902 if (hmd == nullptr) {
903 BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
904 return OPERATOR_CANCELLED;
905 }
906
907 /* assign functionality */
908
909 if (!object_hook_index_array(bmain, scene, ob, &indexar, &indexar_num, name, cent)) {
910 BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group");
911 return OPERATOR_CANCELLED;
912 }
913 if (hmd->indexar) {
914 MEM_freeN(hmd->indexar);
915 }
916
917 copy_v3_v3(hmd->cent, cent);
918 hmd->indexar = indexar;
919 hmd->indexar_num = indexar_num;
920
923
924 return OPERATOR_FINISHED;
925}
926
928{
929 PropertyRNA *prop;
930
931 /* identifiers */
932 ot->name = "Assign to Hook";
933 ot->description = "Assign the selected vertices to a hook";
934 ot->idname = "OBJECT_OT_hook_assign";
935
936 /* callbacks */
938 ot->poll = hook_op_edit_poll;
939
940 /* flags */
941 /* this operator changes data stored in modifier which doesn't get pushed to undo stack, * so
942 * redoing it from redo panel gives totally weird results. */
943 ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
944
945 /* properties */
946 prop = RNA_def_enum(ot->srna,
947 "modifier",
949 0,
950 "Modifier",
951 "Modifier number to assign to");
954}
955
957{
958 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
959 int num = RNA_enum_get(op->ptr, "modifier");
960 Object *ob = nullptr;
961 HookModifierData *hmd = nullptr;
962
963 object_hook_from_context(C, &ptr, num, &ob, &hmd);
964 if (hmd == nullptr) {
965 BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
966 return OPERATOR_CANCELLED;
967 }
968
969 /* select functionality */
970 object_hook_select(ob, hmd);
971
972 DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_SELECT);
974
975 return OPERATOR_FINISHED;
976}
977
979{
980 PropertyRNA *prop;
981
982 /* identifiers */
983 ot->name = "Select Hook";
984 ot->description = "Select affected vertices on mesh";
985 ot->idname = "OBJECT_OT_hook_select";
986
987 /* callbacks */
989 ot->poll = hook_op_edit_poll;
990
991 /* flags */
993
994 /* properties */
995 prop = RNA_def_enum(
996 ot->srna, "modifier", rna_enum_dummy_NULL_items, 0, "Modifier", "Modifier number to remove");
999}
1000
1001} // namespace blender::ed::object
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_active_if_bonecoll_visible(Object *ob) ATTR_WARN_UNUSED_RESULT
#define CTX_DATA_BEGIN(C, Type, instance, member)
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
Main * CTX_data_main(const bContext *C)
#define CTX_DATA_END
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
support for deformation groups and hooks.
int BKE_object_defgroup_active_index_get(const Object *ob)
Definition deform.cc:607
const ListBase * BKE_object_defgroup_list(const Object *ob)
Definition deform.cc:585
float BKE_defvert_find_weight(const MDeformVert *dvert, int defgroup)
Definition deform.cc:774
void BKE_editmesh_looptris_and_normals_calc(BMEditMesh *em)
Definition editmesh.cc:95
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Base * BKE_view_layer_active_base_get(ViewLayer *view_layer)
Base * BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
void BKE_modifiers_persistent_uid_init(const Object &object, ModifierData &md)
void BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md)
void BKE_modifier_free(ModifierData *md)
void BKE_modifier_remove_from_list(Object *ob, ModifierData *md)
ModifierData * BKE_modifier_new(int type)
General operations, lookup, etc. for blender objects.
Object * BKE_object_add(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name) ATTR_NONNULL(1
void BKE_object_modifier_hook_reset(Object *ob, HookModifierData *hmd)
void BKE_object_where_is_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
#define BLI_assert(a)
Definition BLI_assert.h:46
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_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:371
void mul_m3_v3(const float M[3][3], float r[3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
#define mul_m4_series(...)
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void unit_m4(float m[4][4])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
ATTR_WARN_UNUSED_RESULT const size_t num
#define SNPRINTF_UTF8(dst, format,...)
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define STRNCPY_UTF8(dst, src)
#define LIKELY(x)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ ID_RECALC_SELECT
Definition DNA_ID.h:1101
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ CU_BEZIER
@ CD_MDEFORMVERT
#define MAX_NAME
Definition DNA_defs.h:50
@ eModifierType_Hook
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OB_EMPTY
@ OB_SURF
@ OB_ARMATURE
@ OB_MESH
@ OB_CURVES_LEGACY
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
void EDBM_select_flush_from_verts(BMEditMesh *em, bool select)
void EDBM_mesh_make(Object *ob, int select_mode, bool add_key_index)
void EDBM_mesh_load(Main *bmain, Object *ob)
bool ED_operator_editsurfcurve(bContext *C)
bool ED_operator_editlattice(bContext *C)
bool ED_operator_editmesh(bContext *C)
Read Guarded memory(de)allocation.
@ PROP_ENUM_NO_TRANSLATE
Definition RNA_types.hh:432
#define C
Definition RandGen.cpp:29
#define NC_GEOM
Definition WM_types.hh:393
#define ND_OB_SELECT
Definition WM_types.hh:442
#define NC_SCENE
Definition WM_types.hh:378
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define ND_MODIFIER
Definition WM_types.hh:462
#define ND_SELECT
Definition WM_types.hh:508
#define NC_OBJECT
Definition WM_types.hh:379
@ BM_ELEM_SELECT
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
#define BM_elem_flag_test(ele, hflag)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_VERTS_OF_MESH
void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select)
Select Vert.
BPy_StructRNA * depsgraph
#define SELECT
void ED_curve_editnurb_make(Object *obedit)
ListBase * object_editcurve_get(Object *ob)
Definition editcurve.cc:92
void ED_curve_editnurb_load(Main *bmain, Object *obedit)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
void OBJECT_OT_hook_select(wmOperatorType *ot)
static int return_editmesh_indexar(BMEditMesh *em, int *r_indexar_num, int **r_indexar, float r_cent[3])
static wmOperatorStatus object_hook_select_exec(bContext *C, wmOperator *op)
static int return_editcurve_indexar(Object *obedit, int **r_indexar, int *r_indexar_num, float r_cent[3])
static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, float r_cent[3])
static Object * add_hook_object_new(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, Object *obedit)
static const EnumPropertyItem * hook_mod_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
void OBJECT_OT_hook_remove(wmOperatorType *ot)
static void select_editbmesh_hook(Object *ob, HookModifierData *hmd)
void OBJECT_OT_hook_add_selob(wmOperatorType *ot)
static int return_editlattice_indexar(Lattice *editlatt, int **r_indexar, int *r_indexar_num, float r_cent[3])
static wmOperatorStatus object_hook_remove_exec(bContext *C, wmOperator *op)
static wmOperatorStatus object_add_hook_selob_exec(bContext *C, wmOperator *op)
static int add_hook_object(const bContext *C, Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, Object *obedit, Object *ob, int mode, ReportList *reports)
void OBJECT_OT_hook_add_newob(wmOperatorType *ot)
static void object_hook_select(Object *ob, HookModifierData *hmd)
static wmOperatorStatus object_hook_assign_exec(bContext *C, wmOperator *op)
static bool hook_op_edit_poll(bContext *C)
static void select_editlattice_hook(Object *obedit, HookModifierData *hmd)
void OBJECT_OT_hook_assign(wmOperatorType *ot)
static wmOperatorStatus object_add_hook_newob_exec(bContext *C, wmOperator *op)
static void object_hook_from_context(bContext *C, PointerRNA *ptr, const int num, Object **r_ob, HookModifierData **r_hmd)
void OBJECT_OT_hook_recenter(wmOperatorType *ot)
void OBJECT_OT_hook_reset(wmOperatorType *ot)
static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
static bool object_hook_index_array(Main *bmain, Scene *scene, Object *obedit, int **r_indexar, int *r_indexar_num, char *r_name, float r_cent[3])
static wmOperatorStatus object_hook_recenter_exec(bContext *C, wmOperator *op)
static wmOperatorStatus object_hook_reset_exec(bContext *C, wmOperator *op)
const char * name
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
const EnumPropertyItem rna_enum_dummy_NULL_items[]
Definition rna_rna.cc:26
float co[3]
CustomData vdata
uint8_t f1
float vec[4]
struct Object * object
unsigned short local_view_bits
float vec[3][3]
char name[64]
struct Lattice * latt
const char * identifier
Definition RNA_types.hh:657
const char * name
Definition RNA_types.hh:661
struct Object * object
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
struct EditLatt * editlatt
struct BPoint * def
void * first
struct ModifierData * next
ModifierTypeType type
ObjectRuntimeHandle * runtime
ListBase modifiers
float loc[3]
struct ToolSettings * toolsettings
View3DCursor cursor
struct View3D * localvd
unsigned short local_view_uid
struct Base * basact
float pose_mat[4][4]
struct ReportList * reports
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)