Blender  V3.3
object_hook.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "BLI_listbase.h"
14 #include "BLI_math.h"
15 #include "BLI_string.h"
16 #include "BLI_utildefines.h"
17 
18 #include "DNA_armature_types.h"
19 #include "DNA_curve_types.h"
20 #include "DNA_lattice_types.h"
21 #include "DNA_mesh_types.h"
22 #include "DNA_meshdata_types.h"
23 #include "DNA_object_types.h"
24 #include "DNA_scene_types.h"
25 
26 #include "BKE_action.h"
27 #include "BKE_context.h"
28 #include "BKE_deform.h"
29 #include "BKE_editmesh.h"
30 #include "BKE_layer.h"
31 #include "BKE_main.h"
32 #include "BKE_modifier.h"
33 #include "BKE_object.h"
34 #include "BKE_report.h"
35 #include "BKE_scene.h"
36 
37 #include "DEG_depsgraph.h"
38 #include "DEG_depsgraph_build.h"
39 #include "DEG_depsgraph_query.h"
40 
41 #include "RNA_access.h"
42 #include "RNA_define.h"
43 #include "RNA_enum_types.h"
44 #include "RNA_prototypes.h"
45 
46 #include "ED_curve.h"
47 #include "ED_mesh.h"
48 #include "ED_screen.h"
49 
50 #include "WM_api.h"
51 #include "WM_types.h"
52 
53 #include "UI_resources.h"
54 
55 #include "object_intern.h"
56 
58  int *r_indexar_num,
59  int **r_indexar,
60  float r_cent[3])
61 {
62  BMVert *eve;
63  BMIter iter;
64  int *index, nr, indexar_num = 0;
65 
66  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
68  indexar_num++;
69  }
70  }
71  if (indexar_num == 0) {
72  return 0;
73  }
74 
75  *r_indexar = index = MEM_mallocN(4 * indexar_num, "hook indexar");
76  *r_indexar_num = indexar_num;
77  nr = 0;
78  zero_v3(r_cent);
79 
80  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
82  *index = nr;
83  index++;
84  add_v3_v3(r_cent, eve->co);
85  }
86  nr++;
87  }
88 
89  mul_v3_fl(r_cent, 1.0f / (float)indexar_num);
90 
91  return indexar_num;
92 }
93 
94 static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, float r_cent[3])
95 {
96  const int active_index = BKE_object_defgroup_active_index_get(obedit);
97  const int cd_dvert_offset = active_index ?
99  -1;
100 
101  if (cd_dvert_offset != -1) {
102  const int defgrp_index = active_index - 1;
103  int indexar_num = 0;
104 
105  MDeformVert *dvert;
106  BMVert *eve;
107  BMIter iter;
108 
109  /* find the vertices */
110  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
111  dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
112 
113  if (BKE_defvert_find_weight(dvert, defgrp_index) > 0.0f) {
114  add_v3_v3(r_cent, eve->co);
115  indexar_num++;
116  }
117  }
118  if (indexar_num) {
119  const ListBase *defbase = BKE_object_defgroup_list(obedit);
120  bDeformGroup *dg = BLI_findlink(defbase, defgrp_index);
121  BLI_strncpy(r_name, dg->name, sizeof(dg->name));
122  mul_v3_fl(r_cent, 1.0f / (float)indexar_num);
123  return true;
124  }
125  }
126 
127  return false;
128 }
129 
131 {
132  Mesh *me = ob->data;
133  BMEditMesh *em = me->edit_mesh;
134  BMVert *eve;
135  BMIter iter;
136  int index = 0, nr = 0;
137 
138  if (hmd->indexar == NULL) {
139  return;
140  }
141 
142  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
143  if (nr == hmd->indexar[index]) {
144  BM_vert_select_set(em->bm, eve, true);
145  if (index < hmd->indexar_num - 1) {
146  index++;
147  }
148  }
149 
150  nr++;
151  }
152 
153  EDBM_select_flush(em);
154 }
155 
156 static int return_editlattice_indexar(Lattice *editlatt,
157  int **r_indexar,
158  int *r_indexar_num,
159  float r_cent[3])
160 {
161  BPoint *bp;
162  int *index, nr, indexar_num = 0, a;
163 
164  /* count */
165  a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
166  bp = editlatt->def;
167  while (a--) {
168  if (bp->f1 & SELECT) {
169  if (bp->hide == 0) {
170  indexar_num++;
171  }
172  }
173  bp++;
174  }
175 
176  if (indexar_num == 0) {
177  return 0;
178  }
179 
180  *r_indexar = index = MEM_mallocN(4 * indexar_num, "hook indexar");
181  *r_indexar_num = indexar_num;
182  nr = 0;
183  zero_v3(r_cent);
184 
185  a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
186  bp = editlatt->def;
187  while (a--) {
188  if (bp->f1 & SELECT) {
189  if (bp->hide == 0) {
190  *index = nr;
191  index++;
192  add_v3_v3(r_cent, bp->vec);
193  }
194  }
195  bp++;
196  nr++;
197  }
198 
199  mul_v3_fl(r_cent, 1.0f / (float)indexar_num);
200 
201  return indexar_num;
202 }
203 
205 {
206  Lattice *lt = obedit->data, *editlt;
207  BPoint *bp;
208  int index = 0, nr = 0, a;
209 
210  editlt = lt->editlatt->latt;
211  /* count */
212  a = editlt->pntsu * editlt->pntsv * editlt->pntsw;
213  bp = editlt->def;
214  while (a--) {
215  if (hmd->indexar[index] == nr) {
216  bp->f1 |= SELECT;
217  if (index < hmd->indexar_num - 1) {
218  index++;
219  }
220  }
221  nr++;
222  bp++;
223  }
224 }
225 
226 static int return_editcurve_indexar(Object *obedit,
227  int **r_indexar,
228  int *r_indexar_num,
229  float r_cent[3])
230 {
231  ListBase *editnurb = object_editcurve_get(obedit);
232  BPoint *bp;
233  BezTriple *bezt;
234  int *index, a, nr, indexar_num = 0;
235 
236  LISTBASE_FOREACH (Nurb *, nu, editnurb) {
237  if (nu->type == CU_BEZIER) {
238  bezt = nu->bezt;
239  a = nu->pntsu;
240  while (a--) {
241  if (bezt->f1 & SELECT) {
242  indexar_num++;
243  }
244  if (bezt->f2 & SELECT) {
245  indexar_num++;
246  }
247  if (bezt->f3 & SELECT) {
248  indexar_num++;
249  }
250  bezt++;
251  }
252  }
253  else {
254  bp = nu->bp;
255  a = nu->pntsu * nu->pntsv;
256  while (a--) {
257  if (bp->f1 & SELECT) {
258  indexar_num++;
259  }
260  bp++;
261  }
262  }
263  }
264  if (indexar_num == 0) {
265  return 0;
266  }
267 
268  *r_indexar = index = MEM_mallocN(sizeof(*index) * indexar_num, "hook indexar");
269  *r_indexar_num = indexar_num;
270  nr = 0;
271  zero_v3(r_cent);
272 
273  LISTBASE_FOREACH (Nurb *, nu, editnurb) {
274  if (nu->type == CU_BEZIER) {
275  bezt = nu->bezt;
276  a = nu->pntsu;
277  while (a--) {
278  if (bezt->f1 & SELECT) {
279  *index = nr;
280  index++;
281  add_v3_v3(r_cent, bezt->vec[0]);
282  }
283  nr++;
284  if (bezt->f2 & SELECT) {
285  *index = nr;
286  index++;
287  add_v3_v3(r_cent, bezt->vec[1]);
288  }
289  nr++;
290  if (bezt->f3 & SELECT) {
291  *index = nr;
292  index++;
293  add_v3_v3(r_cent, bezt->vec[2]);
294  }
295  nr++;
296  bezt++;
297  }
298  }
299  else {
300  bp = nu->bp;
301  a = nu->pntsu * nu->pntsv;
302  while (a--) {
303  if (bp->f1 & SELECT) {
304  *index = nr;
305  index++;
306  add_v3_v3(r_cent, bp->vec);
307  }
308  nr++;
309  bp++;
310  }
311  }
312  }
313 
314  mul_v3_fl(r_cent, 1.0f / (float)indexar_num);
315 
316  return indexar_num;
317 }
318 
319 static bool object_hook_index_array(Main *bmain,
320  Scene *scene,
321  Object *obedit,
322  int **r_indexar,
323  int *r_indexar_num,
324  char *r_name,
325  float r_cent[3])
326 {
327  *r_indexar = NULL;
328  *r_indexar_num = 0;
329  r_name[0] = 0;
330 
331  switch (obedit->type) {
332  case OB_MESH: {
333  Mesh *me = obedit->data;
334 
335  BMEditMesh *em;
336 
337  EDBM_mesh_load(bmain, obedit);
338  EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
339 
340  DEG_id_tag_update(obedit->data, 0);
341 
342  em = me->edit_mesh;
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);
355  ED_curve_editnurb_make(obedit);
356  return return_editcurve_indexar(obedit, r_indexar, r_indexar_num, r_cent);
357  case OB_LATTICE: {
358  Lattice *lt = 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 = ptr->data;
429  }
430  else { /* use the provided property */
431  ob = CTX_data_edit_object(C);
432  hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
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 = NULL;
441  *r_hmd = NULL;
442  }
443 }
444 
446 {
447  if (hmd->indexar == NULL) {
448  return;
449  }
450 
451  if (ob->type == OB_MESH) {
452  select_editbmesh_hook(ob, hmd);
453  }
454  else if (ob->type == OB_LATTICE) {
455  select_editlattice_hook(ob, hmd);
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  }
478  if (ED_operator_editlattice(C)) {
479  return true;
480  }
481  // if (ED_operator_editmball(C)) return true;
482  }
483 
484  return false;
485 }
486 
487 static Object *add_hook_object_new(Main *bmain, ViewLayer *view_layer, View3D *v3d, Object *obedit)
488 {
489  Base *basedit;
490  Object *ob;
491 
492  ob = BKE_object_add(bmain, view_layer, OB_EMPTY, NULL);
493 
494  basedit = BKE_view_layer_base_find(view_layer, obedit);
495  BLI_assert(view_layer->basact->object == ob);
496 
497  if (v3d && v3d->localvd) {
498  view_layer->basact->local_view_bits |= v3d->local_view_uuid;
499  }
500 
501  /* icky, BKE_object_add sets new base as active.
502  * so set it back to the original edit object */
503  view_layer->basact = basedit;
504 
505  return ob;
506 }
507 
508 static 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 = NULL;
520  HookModifierData *hmd = NULL;
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, view_layer, v3d, obedit);
536 
537  /* transform cent to global coords for loc */
538  mul_v3_m4v3(ob->loc, obedit->obmat, cent);
539  }
540 
541  md = obedit->modifiers.first;
543  md = md->next;
544  }
545 
547  BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
548  BLI_snprintf(hmd->modifier.name, sizeof(hmd->modifier.name), "Hook-%s", ob->id.name + 2);
550 
551  hmd->object = ob;
552  hmd->indexar = indexar;
553  copy_v3_v3(hmd->cent, cent);
554  hmd->indexar_num = indexar_num;
555  BLI_strncpy(hmd->name, name, sizeof(hmd->name));
556 
557  unit_m4(pose_mat);
558 
559  invert_m4_m4(obedit->imat, obedit->obmat);
560  if (mode == OBJECT_ADDHOOK_NEWOB) {
561  /* pass */
562  }
563  else {
564  /* may overwrite with pose-bone location, below */
565  mul_v3_m4v3(cent, obedit->imat, ob->obmat[3]);
566  }
567 
568  if (mode == OBJECT_ADDHOOK_SELOB_BONE) {
569  bArmature *arm = ob->data;
570  BLI_assert(ob->type == OB_ARMATURE);
571  if (arm->act_bone) {
572  bPoseChannel *pchan_act;
573 
574  BLI_strncpy(hmd->subtarget, arm->act_bone->name, sizeof(hmd->subtarget));
575 
577  if (LIKELY(pchan_act)) {
578  invert_m4_m4(pose_mat, pchan_act->pose_mat);
579  mul_v3_m4v3(cent, ob->obmat, pchan_act->pose_mat[3]);
580  mul_v3_m4v3(cent, obedit->imat, cent);
581  }
582  }
583  else {
584  BKE_report(reports, RPT_WARNING, "Armature has no active object bone");
585  }
586  }
587 
588  copy_v3_v3(hmd->cent, cent);
589 
590  /* matrix calculus */
591  /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
592  /* (parentinv ) */
593  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
594  Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
595  BKE_object_transform_copy(object_eval, ob);
596  BKE_object_where_is_calc(depsgraph, scene_eval, object_eval);
597 
598  invert_m4_m4(object_eval->imat, object_eval->obmat);
599  /* apparently this call goes from right to left... */
600  mul_m4_series(hmd->parentinv, pose_mat, object_eval->imat, obedit->obmat);
601 
603 
604  return true;
605 }
606 
608 {
609  Main *bmain = CTX_data_main(C);
611  ViewLayer *view_layer = CTX_data_view_layer(C);
612  Object *obedit = CTX_data_edit_object(C);
613  Object *obsel = NULL;
614  const bool use_bone = RNA_boolean_get(op->ptr, "use_bone");
615  const int mode = use_bone ? OBJECT_ADDHOOK_SELOB_BONE : OBJECT_ADDHOOK_SELOB;
616 
617  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
618  if (ob != obedit) {
619  obsel = ob;
620  break;
621  }
622  }
623  CTX_DATA_END;
624 
625  if (!obsel) {
626  BKE_report(op->reports, RPT_ERROR, "Cannot add hook with no other selected objects");
627  return OPERATOR_CANCELLED;
628  }
629 
630  if (use_bone && obsel->type != OB_ARMATURE) {
631  BKE_report(op->reports, RPT_ERROR, "Cannot add hook bone for a non armature object");
632  return OPERATOR_CANCELLED;
633  }
634 
635  if (add_hook_object(C, bmain, scene, view_layer, NULL, obedit, obsel, mode, op->reports)) {
637  return OPERATOR_FINISHED;
638  }
639  return OPERATOR_CANCELLED;
640 }
641 
643 {
644  /* identifiers */
645  ot->name = "Hook to Selected Object";
646  ot->description = "Hook selected vertices to the first selected object";
647  ot->idname = "OBJECT_OT_hook_add_selob";
648 
649  /* api callbacks */
652 
653  /* flags */
655 
657  "use_bone",
658  false,
659  "Active Bone",
660  "Assign the hook to the hook objects active bone");
661 }
662 
664 {
665  Main *bmain = CTX_data_main(C);
667  ViewLayer *view_layer = CTX_data_view_layer(C);
668  View3D *v3d = CTX_wm_view3d(C);
669  Object *obedit = CTX_data_edit_object(C);
670 
671  if (add_hook_object(
672  C, bmain, scene, view_layer, v3d, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) {
676  return OPERATOR_FINISHED;
677  }
678  return OPERATOR_CANCELLED;
679 }
680 
682 {
683  /* identifiers */
684  ot->name = "Hook to New Object";
685  ot->description = "Hook selected vertices to a newly created object";
686  ot->idname = "OBJECT_OT_hook_add_newob";
687 
688  /* api callbacks */
691 
692  /* flags */
694 }
695 
697 {
698  int num = RNA_enum_get(op->ptr, "modifier");
700  HookModifierData *hmd = NULL;
701 
702  hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
703  if (!hmd) {
704  BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
705  return OPERATOR_CANCELLED;
706  }
707 
708  /* remove functionality */
709 
712 
715 
716  return OPERATOR_FINISHED;
717 }
718 
721  PropertyRNA *UNUSED(prop),
722  bool *r_free)
723 {
725  EnumPropertyItem tmp = {0, "", 0, "", ""};
726  EnumPropertyItem *item = NULL;
727  ModifierData *md = NULL;
728  int a, totitem = 0;
729 
730  if (!ob) {
731  return DummyRNA_NULL_items;
732  }
733 
734  for (a = 0, md = ob->modifiers.first; md; md = md->next, a++) {
735  if (md->type == eModifierType_Hook) {
736  tmp.value = a;
737  tmp.icon = ICON_HOOK;
738  tmp.identifier = md->name;
739  tmp.name = md->name;
740  RNA_enum_item_add(&item, &totitem, &tmp);
741  }
742  }
743 
744  RNA_enum_item_end(&item, &totitem);
745  *r_free = true;
746 
747  return item;
748 }
749 
751 {
752  PropertyRNA *prop;
753 
754  /* identifiers */
755  ot->name = "Remove Hook";
756  ot->idname = "OBJECT_OT_hook_remove";
757  ot->description = "Remove a hook from the active object";
758 
759  /* api callbacks */
763 
764  /* flags */
765  /* this operator removes modifier which isn't stored in local undo stack,
766  * so redoing it from redo panel gives totally weird results. */
767  ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
768 
769  /* properties */
770  prop = RNA_def_enum(
771  ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to remove");
774  ot->prop = prop;
775 }
776 
778 {
779  PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
780  int num = RNA_enum_get(op->ptr, "modifier");
781  Object *ob = NULL;
782  HookModifierData *hmd = NULL;
783 
784  object_hook_from_context(C, &ptr, num, &ob, &hmd);
785  if (hmd == NULL) {
786  BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
787  return OPERATOR_CANCELLED;
788  }
789 
791 
794 
795  return OPERATOR_FINISHED;
796 }
797 
799 {
800  PropertyRNA *prop;
801 
802  /* identifiers */
803  ot->name = "Reset Hook";
804  ot->description = "Recalculate and clear offset transformation";
805  ot->idname = "OBJECT_OT_hook_reset";
806 
807  /* callbacks */
810 
811  /* flags */
813 
814  /* properties */
815  prop = RNA_def_enum(
816  ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
819 }
820 
822 {
823  PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
824  int num = RNA_enum_get(op->ptr, "modifier");
825  Object *ob = NULL;
826  HookModifierData *hmd = NULL;
828  float bmat[3][3], imat[3][3];
829 
830  object_hook_from_context(C, &ptr, num, &ob, &hmd);
831  if (hmd == NULL) {
832  BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
833  return OPERATOR_CANCELLED;
834  }
835 
836  /* recenter functionality */
837  copy_m3_m4(bmat, ob->obmat);
838  invert_m3_m3(imat, bmat);
839 
840  sub_v3_v3v3(hmd->cent, scene->cursor.location, ob->obmat[3]);
841  mul_m3_v3(imat, hmd->cent);
842 
845 
846  return OPERATOR_FINISHED;
847 }
848 
850 {
851  PropertyRNA *prop;
852 
853  /* identifiers */
854  ot->name = "Recenter Hook";
855  ot->description = "Set hook center to cursor position";
856  ot->idname = "OBJECT_OT_hook_recenter";
857 
858  /* callbacks */
861 
862  /* flags */
864 
865  /* properties */
866  prop = RNA_def_enum(
867  ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
870 }
871 
873 {
874  Main *bmain = CTX_data_main(C);
876  PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
877  int num = RNA_enum_get(op->ptr, "modifier");
878  Object *ob = NULL;
879  HookModifierData *hmd = NULL;
880  float cent[3];
881  char name[MAX_NAME];
882  int *indexar, indexar_num;
883 
884  object_hook_from_context(C, &ptr, num, &ob, &hmd);
885  if (hmd == NULL) {
886  BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
887  return OPERATOR_CANCELLED;
888  }
889 
890  /* assign functionality */
891 
892  if (!object_hook_index_array(bmain, scene, ob, &indexar, &indexar_num, name, cent)) {
893  BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group");
894  return OPERATOR_CANCELLED;
895  }
896  if (hmd->indexar) {
897  MEM_freeN(hmd->indexar);
898  }
899 
900  copy_v3_v3(hmd->cent, cent);
901  hmd->indexar = indexar;
902  hmd->indexar_num = indexar_num;
903 
906 
907  return OPERATOR_FINISHED;
908 }
909 
911 {
912  PropertyRNA *prop;
913 
914  /* identifiers */
915  ot->name = "Assign to Hook";
916  ot->description = "Assign the selected vertices to a hook";
917  ot->idname = "OBJECT_OT_hook_assign";
918 
919  /* callbacks */
922 
923  /* flags */
924  /* this operator changes data stored in modifier which doesn't get pushed to undo stack,
925  * so redoing it from redo panel gives totally weird results. */
926  ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
927 
928  /* properties */
929  prop = RNA_def_enum(
930  ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
933 }
934 
936 {
937  PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
938  int num = RNA_enum_get(op->ptr, "modifier");
939  Object *ob = NULL;
940  HookModifierData *hmd = NULL;
941 
942  object_hook_from_context(C, &ptr, num, &ob, &hmd);
943  if (hmd == NULL) {
944  BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
945  return OPERATOR_CANCELLED;
946  }
947 
948  /* select functionality */
949  object_hook_select(ob, hmd);
950 
953 
954  return OPERATOR_FINISHED;
955 }
956 
958 {
959  PropertyRNA *prop;
960 
961  /* identifiers */
962  ot->name = "Select Hook";
963  ot->description = "Select affected vertices on mesh";
964  ot->idname = "OBJECT_OT_hook_select";
965 
966  /* callbacks */
969 
970  /* flags */
972 
973  /* properties */
974  prop = RNA_def_enum(
975  ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to remove");
978 }
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_active_if_layer_visible(struct Object *ob)
Definition: action.c:720
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1370
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:269
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
Definition: context.c:473
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
#define CTX_DATA_END
Definition: BKE_context.h:278
int CustomData_get_offset(const struct CustomData *data, int type)
support for deformation groups and hooks.
int BKE_object_defgroup_active_index_get(const struct Object *ob)
const struct ListBase * BKE_object_defgroup_list(const struct Object *ob)
float BKE_defvert_find_weight(const struct MDeformVert *dvert, int defgroup)
Definition: deform.c:704
void BKE_editmesh_looptri_and_normals_calc(BMEditMesh *em)
Definition: editmesh.c:135
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
Definition: layer.c:379
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
void BKE_modifier_free(struct ModifierData *md)
void BKE_modifier_remove_from_list(struct Object *ob, struct ModifierData *md)
struct ModifierData * BKE_modifier_new(int type)
@ eModifierTypeType_OnlyDeform
Definition: BKE_modifier.h:44
bool BKE_modifier_unique_name(struct ListBase *modifiers, struct ModifierData *md)
General operations, lookup, etc. for blender objects.
void BKE_object_where_is_calc(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
Definition: object.cc:3495
void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *hmd)
Definition: object.cc:1320
struct Object * BKE_object_add(struct Main *bmain, struct ViewLayer *view_layer, int type, const char *name) ATTR_NONNULL(1
void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:340
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void unit_m4(float m[4][4])
Definition: rct.c:1090
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
#define mul_m4_series(...)
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1180
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
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])
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
#define UNUSED(x)
#define LIKELY(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
@ ID_RECALC_SELECT
Definition: DNA_ID.h:818
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ CU_BEZIER
@ CD_MDEFORMVERT
#define MAX_NAME
Definition: DNA_defs.h:48
@ 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_mesh_load(struct Main *bmain, struct Object *ob)
void EDBM_select_flush(struct BMEditMesh *em)
void EDBM_mesh_make(struct Object *ob, int select_mode, bool add_key_index)
bool ED_operator_editsurfcurve(struct bContext *C)
Definition: screen_ops.c:587
bool ED_operator_editlattice(struct bContext *C)
Definition: screen_ops.c:644
bool ED_operator_editmesh(struct bContext *C)
Definition: screen_ops.c:433
Read Guarded memory(de)allocation.
@ PROP_ENUM_NO_TRANSLATE
Definition: RNA_types.h:294
#define C
Definition: RandGen.cpp:25
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_GEOM
Definition: WM_types.h:343
#define ND_OB_SELECT
Definition: WM_types.h:390
#define NC_SCENE
Definition: WM_types.h:328
#define ND_MODIFIER
Definition: WM_types.h:411
#define ND_SELECT
Definition: WM_types.h:455
#define NC_OBJECT
Definition: WM_types.h:329
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:541
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
#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
Scene scene
const Depsgraph * depsgraph
ListBase * object_editcurve_get(Object *ob)
Definition: editcurve.c:74
void ED_curve_editnurb_make(Object *obedit)
Definition: editcurve.c:1271
void ED_curve_editnurb_load(Main *bmain, Object *obedit)
Definition: editcurve.c:1234
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static unsigned a[3]
Definition: RandGen.cpp:78
void OBJECT_OT_hook_add_newob(wmOperatorType *ot)
Definition: object_hook.c:681
static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
Definition: object_hook.c:366
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)
Definition: object_hook.c:508
void OBJECT_OT_hook_recenter(wmOperatorType *ot)
Definition: object_hook.c:849
static void select_editlattice_hook(Object *obedit, HookModifierData *hmd)
Definition: object_hook.c:204
static void select_editbmesh_hook(Object *ob, HookModifierData *hmd)
Definition: object_hook.c:130
void OBJECT_OT_hook_assign(wmOperatorType *ot)
Definition: object_hook.c:910
static int object_add_hook_newob_exec(bContext *C, wmOperator *op)
Definition: object_hook.c:663
static int object_hook_select_exec(bContext *C, wmOperator *op)
Definition: object_hook.c:935
static Object * add_hook_object_new(Main *bmain, ViewLayer *view_layer, View3D *v3d, Object *obedit)
Definition: object_hook.c:487
void OBJECT_OT_hook_select(wmOperatorType *ot)
Definition: object_hook.c:957
static int return_editlattice_indexar(Lattice *editlatt, int **r_indexar, int *r_indexar_num, float r_cent[3])
Definition: object_hook.c:156
static void object_hook_from_context(bContext *C, PointerRNA *ptr, const int num, Object **r_ob, HookModifierData **r_hmd)
Definition: object_hook.c:420
static int object_hook_reset_exec(bContext *C, wmOperator *op)
Definition: object_hook.c:777
void OBJECT_OT_hook_reset(wmOperatorType *ot)
Definition: object_hook.c:798
static int object_hook_assign_exec(bContext *C, wmOperator *op)
Definition: object_hook.c:872
static const EnumPropertyItem * hook_mod_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
Definition: object_hook.c:719
static int return_editmesh_indexar(BMEditMesh *em, int *r_indexar_num, int **r_indexar, float r_cent[3])
Definition: object_hook.c:57
static int object_add_hook_selob_exec(bContext *C, wmOperator *op)
Definition: object_hook.c:607
void OBJECT_OT_hook_add_selob(wmOperatorType *ot)
Definition: object_hook.c:642
static void object_hook_select(Object *ob, HookModifierData *hmd)
Definition: object_hook.c:445
static int return_editcurve_indexar(Object *obedit, int **r_indexar, int *r_indexar_num, float r_cent[3])
Definition: object_hook.c:226
void OBJECT_OT_hook_remove(wmOperatorType *ot)
Definition: object_hook.c:750
static bool hook_op_edit_poll(bContext *C)
Definition: object_hook.c:467
static int object_hook_remove_exec(bContext *C, wmOperator *op)
Definition: object_hook.c:696
static int object_hook_recenter_exec(bContext *C, wmOperator *op)
Definition: object_hook.c:821
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])
Definition: object_hook.c:319
static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, float r_cent[3])
Definition: object_hook.c:94
@ OBJECT_ADDHOOK_NEWOB
Definition: object_intern.h:24
@ OBJECT_ADDHOOK_SELOB_BONE
Definition: object_intern.h:26
@ OBJECT_ADDHOOK_SELOB
Definition: object_intern.h:25
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
Definition: rna_define.c:4487
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
Definition: rna_define.c:4436
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3830
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3783
const EnumPropertyItem DummyRNA_NULL_items[]
Definition: rna_rna.c:26
struct BMesh * bm
Definition: BKE_editmesh.h:40
float co[3]
Definition: bmesh_class.h:87
CustomData vdata
Definition: bmesh_class.h:337
short hide
uint8_t f1
float vec[4]
struct Object * object
unsigned short local_view_bits
uint8_t f3
float vec[3][3]
uint8_t f1
uint8_t f2
char name[64]
struct Lattice * latt
const char * identifier
Definition: RNA_types.h:461
const char * name
Definition: RNA_types.h:465
struct Object * object
char name[66]
Definition: DNA_ID.h:378
struct EditLatt * editlatt
struct BPoint * def
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
struct BMEditMesh * edit_mesh
struct ModifierData * next
ModifierTypeType type
Definition: BKE_modifier.h:160
ListBase modifiers
float loc[3]
float imat[4][4]
float obmat[4][4]
void * data
void * data
Definition: RNA_types.h:38
struct ID * owner_id
Definition: RNA_types.h:36
struct ToolSettings * toolsettings
View3DCursor cursor
unsigned short local_view_uuid
struct View3D * localvd
struct Base * basact
float pose_mat[4][4]
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct ReportList * reports
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))