Blender V4.3
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
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.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 = static_cast<int *>(MEM_mallocN(4 * 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(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 = static_cast<int *>(MEM_mallocN(4 * 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 = static_cast<int *>(
271 MEM_mallocN(sizeof(*index) * indexar_num, "hook indexar"));
272 *r_indexar_num = indexar_num;
273 nr = 0;
274 zero_v3(r_cent);
275
276 LISTBASE_FOREACH (Nurb *, nu, editnurb) {
277 if (nu->type == CU_BEZIER) {
278 bezt = nu->bezt;
279 a = nu->pntsu;
280 while (a--) {
281 if (bezt->f1 & SELECT) {
282 *index = nr;
283 index++;
284 add_v3_v3(r_cent, bezt->vec[0]);
285 }
286 nr++;
287 if (bezt->f2 & SELECT) {
288 *index = nr;
289 index++;
290 add_v3_v3(r_cent, bezt->vec[1]);
291 }
292 nr++;
293 if (bezt->f3 & SELECT) {
294 *index = nr;
295 index++;
296 add_v3_v3(r_cent, bezt->vec[2]);
297 }
298 nr++;
299 bezt++;
300 }
301 }
302 else {
303 bp = nu->bp;
304 a = nu->pntsu * nu->pntsv;
305 while (a--) {
306 if (bp->f1 & SELECT) {
307 *index = nr;
308 index++;
309 add_v3_v3(r_cent, bp->vec);
310 }
311 nr++;
312 bp++;
313 }
314 }
315 }
316
317 mul_v3_fl(r_cent, 1.0f / float(indexar_num));
318
319 return indexar_num;
320}
321
322static bool object_hook_index_array(Main *bmain,
323 Scene *scene,
324 Object *obedit,
325 int **r_indexar,
326 int *r_indexar_num,
327 char *r_name,
328 float r_cent[3])
329{
330 *r_indexar = nullptr;
331 *r_indexar_num = 0;
332 r_name[0] = 0;
333
334 switch (obedit->type) {
335 case OB_MESH: {
336 Mesh *mesh = static_cast<Mesh *>(obedit->data);
337
338 EDBM_mesh_load(bmain, obedit);
339 EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
340
341 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
342
343 BMEditMesh *em = mesh->runtime->edit_mesh.get();
344
346
347 /* check selected vertices first */
348 if (return_editmesh_indexar(em, r_indexar_num, r_indexar, r_cent) == 0) {
349 return return_editmesh_vgroup(obedit, em, r_name, r_cent);
350 }
351 return true;
352 }
353 case OB_CURVES_LEGACY:
354 case OB_SURF:
355 ED_curve_editnurb_load(bmain, obedit);
357 return return_editcurve_indexar(obedit, r_indexar, r_indexar_num, r_cent);
358 case OB_LATTICE: {
359 Lattice *lt = static_cast<Lattice *>(obedit->data);
360 return return_editlattice_indexar(lt->editlatt->latt, r_indexar, r_indexar_num, r_cent);
361 }
362 default:
363 return false;
364 }
365}
366
368{
369 ListBase *editnurb = object_editcurve_get(obedit);
370 BPoint *bp;
371 BezTriple *bezt;
372 int index = 0, a, nr = 0;
373
374 LISTBASE_FOREACH (Nurb *, nu, editnurb) {
375 if (nu->type == CU_BEZIER) {
376 bezt = nu->bezt;
377 a = nu->pntsu;
378 while (a--) {
379 if (nr == hmd->indexar[index]) {
380 bezt->f1 |= SELECT;
381 if (index < hmd->indexar_num - 1) {
382 index++;
383 }
384 }
385 nr++;
386 if (nr == hmd->indexar[index]) {
387 bezt->f2 |= SELECT;
388 if (index < hmd->indexar_num - 1) {
389 index++;
390 }
391 }
392 nr++;
393 if (nr == hmd->indexar[index]) {
394 bezt->f3 |= SELECT;
395 if (index < hmd->indexar_num - 1) {
396 index++;
397 }
398 }
399 nr++;
400
401 bezt++;
402 }
403 }
404 else {
405 bp = nu->bp;
406 a = nu->pntsu * nu->pntsv;
407 while (a--) {
408 if (nr == hmd->indexar[index]) {
409 bp->f1 |= SELECT;
410 if (index < hmd->indexar_num - 1) {
411 index++;
412 }
413 }
414 nr++;
415 bp++;
416 }
417 }
418 }
419}
420
422 bContext *C, PointerRNA *ptr, const int num, Object **r_ob, HookModifierData **r_hmd)
423{
424 Object *ob;
425 HookModifierData *hmd;
426
427 if (ptr->data) { /* if modifier context is available, use that */
428 ob = (Object *)ptr->owner_id;
429 hmd = static_cast<HookModifierData *>(ptr->data);
430 }
431 else { /* use the provided property */
432 ob = CTX_data_edit_object(C);
433 hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
434 }
435
436 if (ob && hmd && (hmd->modifier.type == eModifierType_Hook)) {
437 *r_ob = ob;
438 *r_hmd = hmd;
439 }
440 else {
441 *r_ob = nullptr;
442 *r_hmd = nullptr;
443 }
444}
445
447{
448 if (hmd->indexar == nullptr) {
449 return;
450 }
451
452 if (ob->type == OB_MESH) {
453 select_editbmesh_hook(ob, hmd);
454 }
455 else if (ob->type == OB_LATTICE) {
457 }
458 else if (ob->type == OB_CURVES_LEGACY) {
459 select_editcurve_hook(ob, hmd);
460 }
461 else if (ob->type == OB_SURF) {
462 select_editcurve_hook(ob, hmd);
463 }
464}
465
466/* special poll operators for hook operators */
467/* TODO: check for properties window modifier context too as alternative? */
469{
470 Object *obedit = CTX_data_edit_object(C);
471
472 if (obedit) {
473 if (ED_operator_editmesh(C)) {
474 return true;
475 }
477 return true;
478 }
480 return true;
481 }
482 // if (ED_operator_editmball(C)) return true;
483 }
484
485 return false;
486}
487
489 Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, Object *obedit)
490{
491 Base *basedit;
492 Object *ob;
493 ob = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, nullptr);
494 BKE_view_layer_synced_ensure(scene, view_layer);
495 Base *basact = BKE_view_layer_active_base_get(view_layer);
496 BLI_assert(basact->object == ob);
497 if (v3d && v3d->localvd) {
498 basact->local_view_bits |= v3d->local_view_uid;
499 }
500
501 /* icky, BKE_object_add sets new base as active.
502 * so set it back to the original edit object */
503 basedit = BKE_view_layer_base_find(view_layer, obedit);
504 view_layer->basact = basedit;
505
506 return ob;
507}
508
509static int add_hook_object(const bContext *C,
510 Main *bmain,
511 Scene *scene,
512 ViewLayer *view_layer,
513 View3D *v3d,
514 Object *obedit,
515 Object *ob,
516 int mode,
517 ReportList *reports)
518{
520 ModifierData *md = nullptr;
521 HookModifierData *hmd = nullptr;
522 float cent[3];
523 float pose_mat[4][4];
524 int indexar_num, ok, *indexar;
525 char name[MAX_NAME];
526
527 ok = object_hook_index_array(bmain, scene, obedit, &indexar, &indexar_num, name, cent);
528
529 if (!ok) {
530 BKE_report(reports, RPT_ERROR, "Requires selected vertices or active vertex group");
531 return false;
532 }
533
534 if (mode == OBJECT_ADDHOOK_NEWOB && !ob) {
535
536 ob = add_hook_object_new(bmain, scene, view_layer, v3d, obedit);
537
538 /* transform cent to global coords for loc */
539 mul_v3_m4v3(ob->loc, obedit->object_to_world().ptr(), cent);
540 }
541
542 md = static_cast<ModifierData *>(obedit->modifiers.first);
544 {
545 md = md->next;
546 }
547
549 BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
550 SNPRINTF(hmd->modifier.name, "Hook-%s", ob->id.name + 2);
553
554 hmd->object = ob;
555 hmd->indexar = indexar;
556 copy_v3_v3(hmd->cent, cent);
557 hmd->indexar_num = indexar_num;
558 STRNCPY(hmd->name, name);
559
560 unit_m4(pose_mat);
561
562 invert_m4_m4(obedit->runtime->world_to_object.ptr(), obedit->object_to_world().ptr());
563 if (mode == OBJECT_ADDHOOK_NEWOB) {
564 /* pass */
565 }
566 else {
567 /* may overwrite with pose-bone location, below */
568 mul_v3_m4v3(cent, obedit->world_to_object().ptr(), ob->object_to_world().location());
569 }
570
571 if (mode == OBJECT_ADDHOOK_SELOB_BONE) {
572 bArmature *arm = static_cast<bArmature *>(ob->data);
574 if (arm->act_bone) {
575 bPoseChannel *pchan_act;
576
577 STRNCPY(hmd->subtarget, arm->act_bone->name);
578
580 if (LIKELY(pchan_act)) {
581 invert_m4_m4(pose_mat, pchan_act->pose_mat);
582 mul_v3_m4v3(cent, ob->object_to_world().ptr(), pchan_act->pose_mat[3]);
583 mul_v3_m4v3(cent, obedit->world_to_object().ptr(), cent);
584 }
585 }
586 else {
587 BKE_report(reports, RPT_WARNING, "Armature has no active object bone");
588 }
589 }
590
591 copy_v3_v3(hmd->cent, cent);
592
593 /* matrix calculus */
594 /* vert x (obmat x hook->world_to_object) x hook->object_to_world().ptr() x ob->world_to_object
595 */
596 /* (parentinv) */
598 Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
599 BKE_object_transform_copy(object_eval, ob);
600 BKE_object_where_is_calc(depsgraph, scene_eval, object_eval);
601
602 invert_m4_m4(object_eval->runtime->world_to_object.ptr(), object_eval->object_to_world().ptr());
603 /* apparently this call goes from right to left... */
605 pose_mat,
606 object_eval->world_to_object().ptr(),
607 obedit->object_to_world().ptr());
608
611
612 return true;
613}
614
616{
617 Main *bmain = CTX_data_main(C);
618 Scene *scene = CTX_data_scene(C);
619 ViewLayer *view_layer = CTX_data_view_layer(C);
620 Object *obedit = CTX_data_edit_object(C);
621 Object *obsel = nullptr;
622 const bool use_bone = RNA_boolean_get(op->ptr, "use_bone");
623 const int mode = use_bone ? OBJECT_ADDHOOK_SELOB_BONE : OBJECT_ADDHOOK_SELOB;
624
625 CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
626 if (ob != obedit) {
627 obsel = ob;
628 break;
629 }
630 }
632
633 if (!obsel) {
634 BKE_report(op->reports, RPT_ERROR, "Cannot add hook with no other selected objects");
635 return OPERATOR_CANCELLED;
636 }
637
638 if (use_bone && obsel->type != OB_ARMATURE) {
639 BKE_report(op->reports, RPT_ERROR, "Cannot add hook bone for a non armature object");
640 return OPERATOR_CANCELLED;
641 }
642
643 if (add_hook_object(C, bmain, scene, view_layer, nullptr, obedit, obsel, mode, op->reports)) {
645 return OPERATOR_FINISHED;
646 }
647 return OPERATOR_CANCELLED;
648}
649
651{
652 /* identifiers */
653 ot->name = "Hook to Selected Object";
654 ot->description = "Hook selected vertices to the first selected object";
655 ot->idname = "OBJECT_OT_hook_add_selob";
656
657 /* api callbacks */
660
661 /* flags */
663
665 "use_bone",
666 false,
667 "Active Bone",
668 "Assign the hook to the hook object's active bone");
669}
670
672{
673 Main *bmain = CTX_data_main(C);
674 Scene *scene = CTX_data_scene(C);
675 ViewLayer *view_layer = CTX_data_view_layer(C);
676 View3D *v3d = CTX_wm_view3d(C);
677 Object *obedit = CTX_data_edit_object(C);
678
679 if (add_hook_object(
680 C, bmain, scene, view_layer, v3d, obedit, nullptr, OBJECT_ADDHOOK_NEWOB, op->reports))
681 {
685 return OPERATOR_FINISHED;
686 }
687 return OPERATOR_CANCELLED;
688}
689
691{
692 /* identifiers */
693 ot->name = "Hook to New Object";
694 ot->description = "Hook selected vertices to a newly created object";
695 ot->idname = "OBJECT_OT_hook_add_newob";
696
697 /* api callbacks */
700
701 /* flags */
703}
704
706{
707 int num = RNA_enum_get(op->ptr, "modifier");
709 HookModifierData *hmd = nullptr;
710
711 hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
712 if (!hmd) {
713 BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
714 return OPERATOR_CANCELLED;
715 }
716
717 /* remove functionality */
718
721
725
726 return OPERATOR_FINISHED;
727}
728
730 PointerRNA * /*ptr*/,
731 PropertyRNA * /*prop*/,
732 bool *r_free)
733{
735 EnumPropertyItem tmp = {0, "", 0, "", ""};
736 EnumPropertyItem *item = nullptr;
737 ModifierData *md = nullptr;
738 int a, totitem = 0;
739
740 if (!ob) {
742 }
743
744 for (a = 0, md = static_cast<ModifierData *>(ob->modifiers.first); md; md = md->next, a++) {
745 if (md->type == eModifierType_Hook) {
746 tmp.value = a;
747 tmp.icon = ICON_HOOK;
748 tmp.identifier = md->name;
749 tmp.name = md->name;
750 RNA_enum_item_add(&item, &totitem, &tmp);
751 }
752 }
753
754 RNA_enum_item_end(&item, &totitem);
755 *r_free = true;
756
757 return item;
758}
759
761{
762 PropertyRNA *prop;
763
764 /* identifiers */
765 ot->name = "Remove Hook";
766 ot->idname = "OBJECT_OT_hook_remove";
767 ot->description = "Remove a hook from the active object";
768
769 /* api callbacks */
773
774 /* flags */
775 /* this operator removes modifier which isn't stored in local undo stack, * so redoing it from
776 * redo panel gives totally weird results. */
777 ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
778
779 /* properties */
780 prop = RNA_def_enum(
781 ot->srna, "modifier", rna_enum_dummy_NULL_items, 0, "Modifier", "Modifier number to remove");
784 ot->prop = prop;
785}
786
788{
789 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
790 int num = RNA_enum_get(op->ptr, "modifier");
791 Object *ob = nullptr;
792 HookModifierData *hmd = nullptr;
793
794 object_hook_from_context(C, &ptr, num, &ob, &hmd);
795 if (hmd == nullptr) {
796 BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
797 return OPERATOR_CANCELLED;
798 }
799
801
804
805 return OPERATOR_FINISHED;
806}
807
809{
810 PropertyRNA *prop;
811
812 /* identifiers */
813 ot->name = "Reset Hook";
814 ot->description = "Recalculate and clear offset transformation";
815 ot->idname = "OBJECT_OT_hook_reset";
816
817 /* callbacks */
820
821 /* flags */
823
824 /* properties */
825 prop = RNA_def_enum(ot->srna,
826 "modifier",
828 0,
829 "Modifier",
830 "Modifier number to assign to");
833}
834
836{
837 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
838 int num = RNA_enum_get(op->ptr, "modifier");
839 Object *ob = nullptr;
840 HookModifierData *hmd = nullptr;
841 Scene *scene = CTX_data_scene(C);
842 float bmat[3][3], imat[3][3];
843
844 object_hook_from_context(C, &ptr, num, &ob, &hmd);
845 if (hmd == nullptr) {
846 BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
847 return OPERATOR_CANCELLED;
848 }
849
850 /* recenter functionality */
851 copy_m3_m4(bmat, ob->object_to_world().ptr());
852 invert_m3_m3(imat, bmat);
853
854 sub_v3_v3v3(hmd->cent, scene->cursor.location, ob->object_to_world().location());
855 mul_m3_v3(imat, hmd->cent);
856
859
860 return OPERATOR_FINISHED;
861}
862
864{
865 PropertyRNA *prop;
866
867 /* identifiers */
868 ot->name = "Recenter Hook";
869 ot->description = "Set hook center to cursor position";
870 ot->idname = "OBJECT_OT_hook_recenter";
871
872 /* callbacks */
875
876 /* flags */
878
879 /* properties */
880 prop = RNA_def_enum(ot->srna,
881 "modifier",
883 0,
884 "Modifier",
885 "Modifier number to assign to");
888}
889
891{
892 Main *bmain = CTX_data_main(C);
893 Scene *scene = CTX_data_scene(C);
894 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
895 int num = RNA_enum_get(op->ptr, "modifier");
896 Object *ob = nullptr;
897 HookModifierData *hmd = nullptr;
898 float cent[3];
899 char name[MAX_NAME];
900 int *indexar, indexar_num;
901
902 object_hook_from_context(C, &ptr, num, &ob, &hmd);
903 if (hmd == nullptr) {
904 BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
905 return OPERATOR_CANCELLED;
906 }
907
908 /* assign functionality */
909
910 if (!object_hook_index_array(bmain, scene, ob, &indexar, &indexar_num, name, cent)) {
911 BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group");
912 return OPERATOR_CANCELLED;
913 }
914 if (hmd->indexar) {
915 MEM_freeN(hmd->indexar);
916 }
917
918 copy_v3_v3(hmd->cent, cent);
919 hmd->indexar = indexar;
920 hmd->indexar_num = indexar_num;
921
924
925 return OPERATOR_FINISHED;
926}
927
929{
930 PropertyRNA *prop;
931
932 /* identifiers */
933 ot->name = "Assign to Hook";
934 ot->description = "Assign the selected vertices to a hook";
935 ot->idname = "OBJECT_OT_hook_assign";
936
937 /* callbacks */
940
941 /* flags */
942 /* this operator changes data stored in modifier which doesn't get pushed to undo stack, * so
943 * redoing it from redo panel gives totally weird results. */
944 ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
945
946 /* properties */
947 prop = RNA_def_enum(ot->srna,
948 "modifier",
950 0,
951 "Modifier",
952 "Modifier number to assign to");
955}
956
958{
959 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
960 int num = RNA_enum_get(op->ptr, "modifier");
961 Object *ob = nullptr;
962 HookModifierData *hmd = nullptr;
963
964 object_hook_from_context(C, &ptr, num, &ob, &hmd);
965 if (hmd == nullptr) {
966 BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
967 return OPERATOR_CANCELLED;
968 }
969
970 /* select functionality */
971 object_hook_select(ob, hmd);
972
973 DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_SELECT);
975
976 return OPERATOR_FINISHED;
977}
978
980{
981 PropertyRNA *prop;
982
983 /* identifiers */
984 ot->name = "Select Hook";
985 ot->description = "Select affected vertices on mesh";
986 ot->idname = "OBJECT_OT_hook_select";
987
988 /* callbacks */
991
992 /* flags */
994
995 /* properties */
996 prop = RNA_def_enum(
997 ot->srna, "modifier", rna_enum_dummy_NULL_items, 0, "Modifier", "Modifier number to remove");
1000}
1001
1002} // 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:601
const ListBase * BKE_object_defgroup_list(const Object *ob)
Definition deform.cc:579
float BKE_defvert_find_weight(const MDeformVert *dvert, int defgroup)
Definition deform.cc:770
void BKE_editmesh_looptris_and_normals_calc(BMEditMesh *em)
Definition editmesh.cc:83
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)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:370
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])
void unit_m4(float m[4][4])
Definition rct.c:1127
#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])
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])
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#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)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
@ ID_RECALC_SELECT
Definition DNA_ID.h:1068
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
@ 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
void EDBM_mesh_make(Object *ob, int select_mode, bool add_key_index)
void EDBM_mesh_load(Main *bmain, Object *ob)
void EDBM_select_flush(BMEditMesh *em)
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:321
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define NC_GEOM
Definition WM_types.hh:360
#define ND_OB_SELECT
Definition WM_types.hh:409
#define NC_SCENE
Definition WM_types.hh:345
#define ND_MODIFIER
Definition WM_types.hh:429
#define ND_SELECT
Definition WM_types.hh:474
#define NC_OBJECT
Definition WM_types.hh:346
@ 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.
#define SELECT
const Depsgraph * depsgraph
void ED_curve_editnurb_make(Object *obedit)
ListBase * object_editcurve_get(Object *ob)
Definition editcurve.cc:88
void ED_curve_editnurb_load(Main *bmain, Object *obedit)
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
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 int object_add_hook_selob_exec(bContext *C, wmOperator *op)
static int object_hook_remove_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 int object_hook_assign_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem * hook_mod_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
void OBJECT_OT_hook_remove(wmOperatorType *ot)
static int object_hook_recenter_exec(bContext *C, wmOperator *op)
static void select_editbmesh_hook(Object *ob, HookModifierData *hmd)
void OBJECT_OT_hook_add_selob(wmOperatorType *ot)
static int object_add_hook_newob_exec(bContext *C, wmOperator *op)
static int return_editlattice_indexar(Lattice *editlatt, int **r_indexar, int *r_indexar_num, float r_cent[3])
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 int object_hook_select_exec(bContext *C, wmOperator *op)
static void object_hook_select(Object *ob, HookModifierData *hmd)
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 void object_hook_from_context(bContext *C, PointerRNA *ptr, const int num, Object **r_ob, HookModifierData **r_hmd)
static int object_hook_reset_exec(bContext *C, wmOperator *op)
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])
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:29
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:506
const char * name
Definition RNA_types.hh:510
struct Object * object
Definition DNA_ID.h:413
char name[66]
Definition DNA_ID.h:425
struct EditLatt * editlatt
struct BPoint * def
void * first
struct ModifierData * next
ModifierTypeType type
ObjectRuntimeHandle * runtime
ListBase modifiers
float loc[3]
ID * owner_id
Definition RNA_types.hh:40
void * data
Definition RNA_types.hh:42
struct View3D * localvd
unsigned short local_view_uid
struct Base * basact
float pose_mat[4][4]
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
PropertyRNA * prop
Definition WM_types.hh:1092
StructRNA * srna
Definition WM_types.hh:1080
struct ReportList * reports
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4126
wmOperatorType * ot
Definition wm_files.cc:4125
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)