Blender  V2.93
object_hook.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "MEM_guardedalloc.h"
28 
29 #include "BLI_listbase.h"
30 #include "BLI_math.h"
31 #include "BLI_string.h"
32 #include "BLI_utildefines.h"
33 
34 #include "DNA_armature_types.h"
35 #include "DNA_curve_types.h"
36 #include "DNA_lattice_types.h"
37 #include "DNA_mesh_types.h"
38 #include "DNA_meshdata_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_scene_types.h"
41 
42 #include "BKE_action.h"
43 #include "BKE_context.h"
44 #include "BKE_deform.h"
45 #include "BKE_editmesh.h"
46 #include "BKE_layer.h"
47 #include "BKE_main.h"
48 #include "BKE_modifier.h"
49 #include "BKE_object.h"
50 #include "BKE_report.h"
51 #include "BKE_scene.h"
52 
53 #include "DEG_depsgraph.h"
54 #include "DEG_depsgraph_build.h"
55 #include "DEG_depsgraph_query.h"
56 
57 #include "RNA_access.h"
58 #include "RNA_define.h"
59 #include "RNA_enum_types.h"
60 
61 #include "ED_curve.h"
62 #include "ED_mesh.h"
63 #include "ED_screen.h"
64 
65 #include "WM_api.h"
66 #include "WM_types.h"
67 
68 #include "UI_resources.h"
69 
70 #include "object_intern.h"
71 
72 static int return_editmesh_indexar(BMEditMesh *em, int *r_tot, int **r_indexar, float r_cent[3])
73 {
74  BMVert *eve;
75  BMIter iter;
76  int *index, nr, totvert = 0;
77 
78  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
80  totvert++;
81  }
82  }
83  if (totvert == 0) {
84  return 0;
85  }
86 
87  *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar");
88  *r_tot = totvert;
89  nr = 0;
90  zero_v3(r_cent);
91 
92  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
94  *index = nr;
95  index++;
96  add_v3_v3(r_cent, eve->co);
97  }
98  nr++;
99  }
100 
101  mul_v3_fl(r_cent, 1.0f / (float)totvert);
102 
103  return totvert;
104 }
105 
106 static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, float r_cent[3])
107 {
108  const int cd_dvert_offset = obedit->actdef ?
110  -1;
111 
112  zero_v3(r_cent);
113 
114  if (cd_dvert_offset != -1) {
115  const int defgrp_index = obedit->actdef - 1;
116  int totvert = 0;
117 
118  MDeformVert *dvert;
119  BMVert *eve;
120  BMIter iter;
121 
122  /* find the vertices */
123  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
124  dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
125 
126  if (BKE_defvert_find_weight(dvert, defgrp_index) > 0.0f) {
127  add_v3_v3(r_cent, eve->co);
128  totvert++;
129  }
130  }
131  if (totvert) {
132  bDeformGroup *dg = BLI_findlink(&obedit->defbase, defgrp_index);
133  BLI_strncpy(r_name, dg->name, sizeof(dg->name));
134  mul_v3_fl(r_cent, 1.0f / (float)totvert);
135  return true;
136  }
137  }
138 
139  return false;
140 }
141 
143 {
144  Mesh *me = ob->data;
145  BMEditMesh *em = me->edit_mesh;
146  BMVert *eve;
147  BMIter iter;
148  int index = 0, nr = 0;
149 
150  if (hmd->indexar == NULL) {
151  return;
152  }
153 
154  BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
155  if (nr == hmd->indexar[index]) {
156  BM_vert_select_set(em->bm, eve, true);
157  if (index < hmd->totindex - 1) {
158  index++;
159  }
160  }
161 
162  nr++;
163  }
164 
165  EDBM_select_flush(em);
166 }
167 
168 static int return_editlattice_indexar(Lattice *editlatt,
169  int *r_tot,
170  int **r_indexar,
171  float r_cent[3])
172 {
173  BPoint *bp;
174  int *index, nr, totvert = 0, a;
175 
176  /* count */
177  a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
178  bp = editlatt->def;
179  while (a--) {
180  if (bp->f1 & SELECT) {
181  if (bp->hide == 0) {
182  totvert++;
183  }
184  }
185  bp++;
186  }
187 
188  if (totvert == 0) {
189  return 0;
190  }
191 
192  *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar");
193  *r_tot = totvert;
194  nr = 0;
195  zero_v3(r_cent);
196 
197  a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
198  bp = editlatt->def;
199  while (a--) {
200  if (bp->f1 & SELECT) {
201  if (bp->hide == 0) {
202  *index = nr;
203  index++;
204  add_v3_v3(r_cent, bp->vec);
205  }
206  }
207  bp++;
208  nr++;
209  }
210 
211  mul_v3_fl(r_cent, 1.0f / (float)totvert);
212 
213  return totvert;
214 }
215 
217 {
218  Lattice *lt = obedit->data, *editlt;
219  BPoint *bp;
220  int index = 0, nr = 0, a;
221 
222  editlt = lt->editlatt->latt;
223  /* count */
224  a = editlt->pntsu * editlt->pntsv * editlt->pntsw;
225  bp = editlt->def;
226  while (a--) {
227  if (hmd->indexar[index] == nr) {
228  bp->f1 |= SELECT;
229  if (index < hmd->totindex - 1) {
230  index++;
231  }
232  }
233  nr++;
234  bp++;
235  }
236 }
237 
238 static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, float r_cent[3])
239 {
240  ListBase *editnurb = object_editcurve_get(obedit);
241  BPoint *bp;
242  BezTriple *bezt;
243  int *index, a, nr, totvert = 0;
244 
245  LISTBASE_FOREACH (Nurb *, nu, editnurb) {
246  if (nu->type == CU_BEZIER) {
247  bezt = nu->bezt;
248  a = nu->pntsu;
249  while (a--) {
250  if (bezt->f1 & SELECT) {
251  totvert++;
252  }
253  if (bezt->f2 & SELECT) {
254  totvert++;
255  }
256  if (bezt->f3 & SELECT) {
257  totvert++;
258  }
259  bezt++;
260  }
261  }
262  else {
263  bp = nu->bp;
264  a = nu->pntsu * nu->pntsv;
265  while (a--) {
266  if (bp->f1 & SELECT) {
267  totvert++;
268  }
269  bp++;
270  }
271  }
272  }
273  if (totvert == 0) {
274  return 0;
275  }
276 
277  *r_indexar = index = MEM_mallocN(sizeof(*index) * totvert, "hook indexar");
278  *r_tot = totvert;
279  nr = 0;
280  zero_v3(r_cent);
281 
282  LISTBASE_FOREACH (Nurb *, nu, editnurb) {
283  if (nu->type == CU_BEZIER) {
284  bezt = nu->bezt;
285  a = nu->pntsu;
286  while (a--) {
287  if (bezt->f1 & SELECT) {
288  *index = nr;
289  index++;
290  add_v3_v3(r_cent, bezt->vec[0]);
291  }
292  nr++;
293  if (bezt->f2 & SELECT) {
294  *index = nr;
295  index++;
296  add_v3_v3(r_cent, bezt->vec[1]);
297  }
298  nr++;
299  if (bezt->f3 & SELECT) {
300  *index = nr;
301  index++;
302  add_v3_v3(r_cent, bezt->vec[2]);
303  }
304  nr++;
305  bezt++;
306  }
307  }
308  else {
309  bp = nu->bp;
310  a = nu->pntsu * nu->pntsv;
311  while (a--) {
312  if (bp->f1 & SELECT) {
313  *index = nr;
314  index++;
315  add_v3_v3(r_cent, bp->vec);
316  }
317  nr++;
318  bp++;
319  }
320  }
321  }
322 
323  mul_v3_fl(r_cent, 1.0f / (float)totvert);
324 
325  return totvert;
326 }
327 
328 static bool object_hook_index_array(Main *bmain,
329  Scene *scene,
330  Object *obedit,
331  int *r_tot,
332  int **r_indexar,
333  char *r_name,
334  float r_cent[3])
335 {
336  *r_indexar = NULL;
337  *r_tot = 0;
338  r_name[0] = 0;
339 
340  switch (obedit->type) {
341  case OB_MESH: {
342  Mesh *me = obedit->data;
343 
344  BMEditMesh *em;
345 
346  EDBM_mesh_load(bmain, obedit);
347  EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
348 
349  DEG_id_tag_update(obedit->data, 0);
350 
351  em = me->edit_mesh;
352 
355 
356  /* check selected vertices first */
357  if (return_editmesh_indexar(em, r_tot, r_indexar, r_cent) == 0) {
358  return return_editmesh_vgroup(obedit, em, r_name, r_cent);
359  }
360  return true;
361  }
362  case OB_CURVE:
363  case OB_SURF:
364  ED_curve_editnurb_load(bmain, obedit);
365  ED_curve_editnurb_make(obedit);
366  return return_editcurve_indexar(obedit, r_tot, r_indexar, r_cent);
367  case OB_LATTICE: {
368  Lattice *lt = obedit->data;
369  return return_editlattice_indexar(lt->editlatt->latt, r_tot, r_indexar, r_cent);
370  }
371  default:
372  return false;
373  }
374 }
375 
377 {
378  ListBase *editnurb = object_editcurve_get(obedit);
379  BPoint *bp;
380  BezTriple *bezt;
381  int index = 0, a, nr = 0;
382 
383  LISTBASE_FOREACH (Nurb *, nu, editnurb) {
384  if (nu->type == CU_BEZIER) {
385  bezt = nu->bezt;
386  a = nu->pntsu;
387  while (a--) {
388  if (nr == hmd->indexar[index]) {
389  bezt->f1 |= SELECT;
390  if (index < hmd->totindex - 1) {
391  index++;
392  }
393  }
394  nr++;
395  if (nr == hmd->indexar[index]) {
396  bezt->f2 |= SELECT;
397  if (index < hmd->totindex - 1) {
398  index++;
399  }
400  }
401  nr++;
402  if (nr == hmd->indexar[index]) {
403  bezt->f3 |= SELECT;
404  if (index < hmd->totindex - 1) {
405  index++;
406  }
407  }
408  nr++;
409 
410  bezt++;
411  }
412  }
413  else {
414  bp = nu->bp;
415  a = nu->pntsu * nu->pntsv;
416  while (a--) {
417  if (nr == hmd->indexar[index]) {
418  bp->f1 |= SELECT;
419  if (index < hmd->totindex - 1) {
420  index++;
421  }
422  }
423  nr++;
424  bp++;
425  }
426  }
427  }
428 }
429 
431  bContext *C, PointerRNA *ptr, const int num, Object **r_ob, HookModifierData **r_hmd)
432 {
433  Object *ob;
434  HookModifierData *hmd;
435 
436  if (ptr->data) { /* if modifier context is available, use that */
437  ob = (Object *)ptr->owner_id;
438  hmd = ptr->data;
439  }
440  else { /* use the provided property */
441  ob = CTX_data_edit_object(C);
442  hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
443  }
444 
445  if (ob && hmd && (hmd->modifier.type == eModifierType_Hook)) {
446  *r_ob = ob;
447  *r_hmd = hmd;
448  }
449  else {
450  *r_ob = NULL;
451  *r_hmd = NULL;
452  }
453 }
454 
456 {
457  if (hmd->indexar == NULL) {
458  return;
459  }
460 
461  if (ob->type == OB_MESH) {
462  select_editbmesh_hook(ob, hmd);
463  }
464  else if (ob->type == OB_LATTICE) {
465  select_editlattice_hook(ob, hmd);
466  }
467  else if (ob->type == OB_CURVE) {
468  select_editcurve_hook(ob, hmd);
469  }
470  else if (ob->type == OB_SURF) {
471  select_editcurve_hook(ob, hmd);
472  }
473 }
474 
475 /* special poll operators for hook operators */
476 /* TODO: check for properties window modifier context too as alternative? */
478 {
479  Object *obedit = CTX_data_edit_object(C);
480 
481  if (obedit) {
482  if (ED_operator_editmesh(C)) {
483  return true;
484  }
486  return true;
487  }
488  if (ED_operator_editlattice(C)) {
489  return true;
490  }
491  // if (ED_operator_editmball(C)) return true;
492  }
493 
494  return false;
495 }
496 
497 static Object *add_hook_object_new(Main *bmain, ViewLayer *view_layer, View3D *v3d, Object *obedit)
498 {
499  Base *basedit;
500  Object *ob;
501 
502  ob = BKE_object_add(bmain, view_layer, OB_EMPTY, NULL);
503 
504  basedit = BKE_view_layer_base_find(view_layer, obedit);
505  BLI_assert(view_layer->basact->object == ob);
506 
507  if (v3d && v3d->localvd) {
508  view_layer->basact->local_view_bits |= v3d->local_view_uuid;
509  }
510 
511  /* icky, BKE_object_add sets new base as active.
512  * so set it back to the original edit object */
513  view_layer->basact = basedit;
514 
515  return ob;
516 }
517 
518 static int add_hook_object(const bContext *C,
519  Main *bmain,
520  Scene *scene,
521  ViewLayer *view_layer,
522  View3D *v3d,
523  Object *obedit,
524  Object *ob,
525  int mode,
526  ReportList *reports)
527 {
529  ModifierData *md = NULL;
530  HookModifierData *hmd = NULL;
531  float cent[3];
532  float pose_mat[4][4];
533  int tot, ok, *indexar;
534  char name[MAX_NAME];
535 
536  ok = object_hook_index_array(bmain, scene, obedit, &tot, &indexar, name, cent);
537 
538  if (!ok) {
539  BKE_report(reports, RPT_ERROR, "Requires selected vertices or active vertex group");
540  return false;
541  }
542 
543  if (mode == OBJECT_ADDHOOK_NEWOB && !ob) {
544 
545  ob = add_hook_object_new(bmain, view_layer, v3d, obedit);
546 
547  /* transform cent to global coords for loc */
548  mul_v3_m4v3(ob->loc, obedit->obmat, cent);
549  }
550 
551  md = obedit->modifiers.first;
553  md = md->next;
554  }
555 
557  BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
558  BLI_snprintf(hmd->modifier.name, sizeof(hmd->modifier.name), "Hook-%s", ob->id.name + 2);
560 
561  hmd->object = ob;
562  hmd->indexar = indexar;
563  copy_v3_v3(hmd->cent, cent);
564  hmd->totindex = tot;
565  BLI_strncpy(hmd->name, name, sizeof(hmd->name));
566 
567  unit_m4(pose_mat);
568 
569  invert_m4_m4(obedit->imat, obedit->obmat);
570  if (mode == OBJECT_ADDHOOK_NEWOB) {
571  /* pass */
572  }
573  else {
574  /* may overwrite with pose-bone location, below */
575  mul_v3_m4v3(cent, obedit->imat, ob->obmat[3]);
576  }
577 
578  if (mode == OBJECT_ADDHOOK_SELOB_BONE) {
579  bArmature *arm = ob->data;
580  BLI_assert(ob->type == OB_ARMATURE);
581  if (arm->act_bone) {
582  bPoseChannel *pchan_act;
583 
584  BLI_strncpy(hmd->subtarget, arm->act_bone->name, sizeof(hmd->subtarget));
585 
586  pchan_act = BKE_pose_channel_active(ob);
587  if (LIKELY(pchan_act)) {
588  invert_m4_m4(pose_mat, pchan_act->pose_mat);
589  mul_v3_m4v3(cent, ob->obmat, pchan_act->pose_mat[3]);
590  mul_v3_m4v3(cent, obedit->imat, cent);
591  }
592  }
593  else {
594  BKE_report(reports, RPT_WARNING, "Armature has no active object bone");
595  }
596  }
597 
598  copy_v3_v3(hmd->cent, cent);
599 
600  /* matrix calculus */
601  /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
602  /* (parentinv ) */
603  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
604  Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
605  BKE_object_transform_copy(object_eval, ob);
606  BKE_object_where_is_calc(depsgraph, scene_eval, object_eval);
607 
608  invert_m4_m4(object_eval->imat, object_eval->obmat);
609  /* apparently this call goes from right to left... */
610  mul_m4_series(hmd->parentinv, pose_mat, object_eval->imat, obedit->obmat);
611 
613 
614  return true;
615 }
616 
618 {
619  Main *bmain = CTX_data_main(C);
621  ViewLayer *view_layer = CTX_data_view_layer(C);
622  Object *obedit = CTX_data_edit_object(C);
623  Object *obsel = NULL;
624  const bool use_bone = RNA_boolean_get(op->ptr, "use_bone");
625  const int mode = use_bone ? OBJECT_ADDHOOK_SELOB_BONE : OBJECT_ADDHOOK_SELOB;
626 
627  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
628  if (ob != obedit) {
629  obsel = ob;
630  break;
631  }
632  }
633  CTX_DATA_END;
634 
635  if (!obsel) {
636  BKE_report(op->reports, RPT_ERROR, "Cannot add hook with no other selected objects");
637  return OPERATOR_CANCELLED;
638  }
639 
640  if (use_bone && obsel->type != OB_ARMATURE) {
641  BKE_report(op->reports, RPT_ERROR, "Cannot add hook bone for a non armature object");
642  return OPERATOR_CANCELLED;
643  }
644 
645  if (add_hook_object(C, bmain, scene, view_layer, NULL, obedit, obsel, mode, op->reports)) {
647  return OPERATOR_FINISHED;
648  }
649  return OPERATOR_CANCELLED;
650 }
651 
653 {
654  /* identifiers */
655  ot->name = "Hook to Selected Object";
656  ot->description = "Hook selected vertices to the first selected object";
657  ot->idname = "OBJECT_OT_hook_add_selob";
658 
659  /* api callbacks */
662 
663  /* flags */
665 
667  "use_bone",
668  false,
669  "Active Bone",
670  "Assign the hook to the hook objects active bone");
671 }
672 
674 {
675  Main *bmain = CTX_data_main(C);
677  ViewLayer *view_layer = CTX_data_view_layer(C);
678  View3D *v3d = CTX_wm_view3d(C);
679  Object *obedit = CTX_data_edit_object(C);
680 
681  if (add_hook_object(
682  C, bmain, scene, view_layer, v3d, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) {
686  return OPERATOR_FINISHED;
687  }
688  return OPERATOR_CANCELLED;
689 }
690 
692 {
693  /* identifiers */
694  ot->name = "Hook to New Object";
695  ot->description = "Hook selected vertices to a newly created object";
696  ot->idname = "OBJECT_OT_hook_add_newob";
697 
698  /* api callbacks */
701 
702  /* flags */
704 }
705 
707 {
708  int num = RNA_enum_get(op->ptr, "modifier");
710  HookModifierData *hmd = NULL;
711 
712  hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
713  if (!hmd) {
714  BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
715  return OPERATOR_CANCELLED;
716  }
717 
718  /* remove functionality */
719 
722 
725 
726  return OPERATOR_FINISHED;
727 }
728 
731  PropertyRNA *UNUSED(prop),
732  bool *r_free)
733 {
735  EnumPropertyItem tmp = {0, "", 0, "", ""};
736  EnumPropertyItem *item = NULL;
737  ModifierData *md = NULL;
738  int a, totitem = 0;
739 
740  if (!ob) {
741  return DummyRNA_NULL_items;
742  }
743 
744  for (a = 0, md = 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,
776  * so redoing it from 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", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to remove");
784  ot->prop = prop;
785 }
786 
788 {
790  int num = RNA_enum_get(op->ptr, "modifier");
791  Object *ob = NULL;
792  HookModifierData *hmd = NULL;
793 
794  object_hook_from_context(C, &ptr, num, &ob, &hmd);
795  if (hmd == NULL) {
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(
826  ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
829 }
830 
832 {
834  int num = RNA_enum_get(op->ptr, "modifier");
835  Object *ob = NULL;
836  HookModifierData *hmd = NULL;
838  float bmat[3][3], imat[3][3];
839 
840  object_hook_from_context(C, &ptr, num, &ob, &hmd);
841  if (hmd == NULL) {
842  BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
843  return OPERATOR_CANCELLED;
844  }
845 
846  /* recenter functionality */
847  copy_m3_m4(bmat, ob->obmat);
848  invert_m3_m3(imat, bmat);
849 
850  sub_v3_v3v3(hmd->cent, scene->cursor.location, ob->obmat[3]);
851  mul_m3_v3(imat, hmd->cent);
852 
855 
856  return OPERATOR_FINISHED;
857 }
858 
860 {
861  PropertyRNA *prop;
862 
863  /* identifiers */
864  ot->name = "Recenter Hook";
865  ot->description = "Set hook center to cursor position";
866  ot->idname = "OBJECT_OT_hook_recenter";
867 
868  /* callbacks */
871 
872  /* flags */
874 
875  /* properties */
876  prop = RNA_def_enum(
877  ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
880 }
881 
883 {
884  Main *bmain = CTX_data_main(C);
887  int num = RNA_enum_get(op->ptr, "modifier");
888  Object *ob = NULL;
889  HookModifierData *hmd = NULL;
890  float cent[3];
891  char name[MAX_NAME];
892  int *indexar, tot;
893 
894  object_hook_from_context(C, &ptr, num, &ob, &hmd);
895  if (hmd == NULL) {
896  BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
897  return OPERATOR_CANCELLED;
898  }
899 
900  /* assign functionality */
901 
902  if (!object_hook_index_array(bmain, scene, ob, &tot, &indexar, name, cent)) {
903  BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group");
904  return OPERATOR_CANCELLED;
905  }
906  if (hmd->indexar) {
907  MEM_freeN(hmd->indexar);
908  }
909 
910  copy_v3_v3(hmd->cent, cent);
911  hmd->indexar = indexar;
912  hmd->totindex = tot;
913 
916 
917  return OPERATOR_FINISHED;
918 }
919 
921 {
922  PropertyRNA *prop;
923 
924  /* identifiers */
925  ot->name = "Assign to Hook";
926  ot->description = "Assign the selected vertices to a hook";
927  ot->idname = "OBJECT_OT_hook_assign";
928 
929  /* callbacks */
932 
933  /* flags */
934  /* this operator changes data stored in modifier which doesn't get pushed to undo stack,
935  * so redoing it from redo panel gives totally weird results */
936  ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
937 
938  /* properties */
939  prop = RNA_def_enum(
940  ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
943 }
944 
946 {
948  int num = RNA_enum_get(op->ptr, "modifier");
949  Object *ob = NULL;
950  HookModifierData *hmd = NULL;
951 
952  object_hook_from_context(C, &ptr, num, &ob, &hmd);
953  if (hmd == NULL) {
954  BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
955  return OPERATOR_CANCELLED;
956  }
957 
958  /* select functionality */
959  object_hook_select(ob, hmd);
960 
963 
964  return OPERATOR_FINISHED;
965 }
966 
968 {
969  PropertyRNA *prop;
970 
971  /* identifiers */
972  ot->name = "Select Hook";
973  ot->description = "Select affected vertices on mesh";
974  ot->idname = "OBJECT_OT_hook_select";
975 
976  /* callbacks */
979 
980  /* flags */
982 
983  /* properties */
984  prop = RNA_def_enum(
985  ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to remove");
988 }
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_active(struct Object *ob)
Definition: action.c:708
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1296
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:252
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
Definition: context.c:456
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:760
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
#define CTX_DATA_END
Definition: BKE_context.h:260
int CustomData_get_offset(const struct CustomData *data, int type)
support for deformation groups and hooks.
float BKE_defvert_find_weight(const struct MDeformVert *dvert, const int defgroup)
Definition: deform.c:632
void BKE_editmesh_looptri_calc(BMEditMesh *em)
Definition: editmesh.c:135
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
Definition: layer.c:394
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:58
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.c:3653
void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *hmd)
Definition: object.c:1231
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, ReportType type, const char *message)
Definition: report.c:104
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:395
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:930
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:105
void unit_m4(float m[4][4])
Definition: rct.c:1140
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
#define mul_m4_series(...)
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1161
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
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])
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
#define UNUSED(x)
#define LIKELY(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
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:638
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
@ CU_BEZIER
@ CD_MDEFORMVERT
#define MAX_NAME
Definition: DNA_defs.h:62
@ eModifierType_Hook
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OB_EMPTY
@ OB_SURF
@ OB_ARMATURE
@ OB_MESH
@ OB_CURVE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
void EDBM_mesh_load(struct Main *bmain, struct Object *ob)
void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool add_key_index)
void EDBM_select_flush(struct BMEditMesh *em)
void EDBM_mesh_normals_update(struct BMEditMesh *em)
bool ED_operator_editsurfcurve(struct bContext *C)
Definition: screen_ops.c:541
bool ED_operator_editlattice(struct bContext *C)
Definition: screen_ops.c:598
bool ED_operator_editmesh(struct bContext *C)
Definition: screen_ops.c:404
Read Guarded memory(de)allocation.
StructRNA RNA_HookModifier
@ PROP_ENUM_NO_TRANSLATE
Definition: RNA_types.h:279
#define C
Definition: RandGen.cpp:39
#define NC_GEOM
Definition: WM_types.h:294
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_OB_SELECT
Definition: WM_types.h:342
#define NC_SCENE
Definition: WM_types.h:279
#define ND_MODIFIER
Definition: WM_types.h:363
#define ND_SELECT
Definition: WM_types.h:407
#define NC_OBJECT
Definition: WM_types.h:280
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:530
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
#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:89
void ED_curve_editnurb_make(Object *obedit)
Definition: editcurve.c:1289
void ED_curve_editnurb_load(Main *bmain, Object *obedit)
Definition: editcurve.c:1251
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static unsigned a[3]
Definition: RandGen.cpp:92
void OBJECT_OT_hook_add_newob(wmOperatorType *ot)
Definition: object_hook.c:691
static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
Definition: object_hook.c:376
static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, float r_cent[3])
Definition: object_hook.c:238
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:518
void OBJECT_OT_hook_recenter(wmOperatorType *ot)
Definition: object_hook.c:859
static int return_editlattice_indexar(Lattice *editlatt, int *r_tot, int **r_indexar, float r_cent[3])
Definition: object_hook.c:168
static void select_editlattice_hook(Object *obedit, HookModifierData *hmd)
Definition: object_hook.c:216
static void select_editbmesh_hook(Object *ob, HookModifierData *hmd)
Definition: object_hook.c:142
void OBJECT_OT_hook_assign(wmOperatorType *ot)
Definition: object_hook.c:920
static int object_add_hook_newob_exec(bContext *C, wmOperator *op)
Definition: object_hook.c:673
static int object_hook_select_exec(bContext *C, wmOperator *op)
Definition: object_hook.c:945
static Object * add_hook_object_new(Main *bmain, ViewLayer *view_layer, View3D *v3d, Object *obedit)
Definition: object_hook.c:497
void OBJECT_OT_hook_select(wmOperatorType *ot)
Definition: object_hook.c:967
static void object_hook_from_context(bContext *C, PointerRNA *ptr, const int num, Object **r_ob, HookModifierData **r_hmd)
Definition: object_hook.c:430
static int object_hook_reset_exec(bContext *C, wmOperator *op)
Definition: object_hook.c:787
void OBJECT_OT_hook_reset(wmOperatorType *ot)
Definition: object_hook.c:808
static int object_hook_assign_exec(bContext *C, wmOperator *op)
Definition: object_hook.c:882
static const EnumPropertyItem * hook_mod_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
Definition: object_hook.c:729
static int object_add_hook_selob_exec(bContext *C, wmOperator *op)
Definition: object_hook.c:617
void OBJECT_OT_hook_add_selob(wmOperatorType *ot)
Definition: object_hook.c:652
static bool object_hook_index_array(Main *bmain, Scene *scene, Object *obedit, int *r_tot, int **r_indexar, char *r_name, float r_cent[3])
Definition: object_hook.c:328
static void object_hook_select(Object *ob, HookModifierData *hmd)
Definition: object_hook.c:455
void OBJECT_OT_hook_remove(wmOperatorType *ot)
Definition: object_hook.c:760
static int return_editmesh_indexar(BMEditMesh *em, int *r_tot, int **r_indexar, float r_cent[3])
Definition: object_hook.c:72
static bool hook_op_edit_poll(bContext *C)
Definition: object_hook.c:477
static int object_hook_remove_exec(bContext *C, wmOperator *op)
Definition: object_hook.c:706
static int object_hook_recenter_exec(bContext *C, wmOperator *op)
Definition: object_hook.c:831
static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, float r_cent[3])
Definition: object_hook.c:106
@ OBJECT_ADDHOOK_NEWOB
Definition: object_intern.h:40
@ OBJECT_ADDHOOK_SELOB_BONE
Definition: object_intern.h:42
@ OBJECT_ADDHOOK_SELOB
Definition: object_intern.h:41
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
Definition: rna_define.c:4470
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
Definition: rna_define.c:4416
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3819
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:3771
const EnumPropertyItem DummyRNA_NULL_items[]
Definition: rna_rna.c:40
struct BMesh * bm
Definition: BKE_editmesh.h:52
float co[3]
Definition: bmesh_class.h:99
CustomData vdata
Definition: bmesh_class.h:337
short hide
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.h:446
const char * name
Definition: RNA_types.h:450
struct Object * object
char name[66]
Definition: DNA_ID.h:283
struct EditLatt * editlatt
struct BPoint * def
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
struct BMEditMesh * edit_mesh
struct ModifierData * next
ModifierTypeType type
Definition: BKE_modifier.h:173
ListBase defbase
ListBase modifiers
float loc[3]
float imat[4][4]
unsigned short actdef
float obmat[4][4]
void * data
void * data
Definition: RNA_types.h:52
struct ID * owner_id
Definition: RNA_types.h:50
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:752
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct ReportList * reports
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: wm_operators.c:982