Blender  V2.93
gpencil_armature.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) 2018, Blender Foundation
17  * This is a new part of Blender
18  */
19 
26 #include <math.h>
27 #include <stddef.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include "MEM_guardedalloc.h"
33 
34 #include "BLI_math.h"
35 #include "BLI_utildefines.h"
36 
37 #include "DNA_armature_types.h"
38 #include "DNA_gpencil_types.h"
39 #include "DNA_meshdata_types.h"
40 #include "DNA_scene_types.h"
41 
42 #include "BKE_action.h"
43 #include "BKE_armature.h"
44 #include "BKE_context.h"
45 #include "BKE_deform.h"
46 #include "BKE_gpencil.h"
47 #include "BKE_gpencil_modifier.h"
48 #include "BKE_main.h"
49 #include "BKE_object_deform.h"
50 #include "BKE_report.h"
51 
52 #include "WM_api.h"
53 #include "WM_types.h"
54 
55 #include "RNA_access.h"
56 #include "RNA_define.h"
57 #include "RNA_enum_types.h"
58 
59 #include "ED_gpencil.h"
60 #include "ED_mesh.h"
61 #include "ED_object.h"
62 
63 #include "DEG_depsgraph.h"
64 #include "DEG_depsgraph_query.h"
65 
66 #include "gpencil_intern.h"
67 
68 enum {
71 };
72 
73 #define DEFAULT_RATIO 0.10f
74 #define DEFAULT_DECAY 0.8f
75 
76 static int gpencil_bone_looper(Object *ob,
77  Bone *bone,
78  void *data,
79  int (*bone_func)(Object *, Bone *, void *))
80 {
81  /* We want to apply the function bone_func to every bone
82  * in an armature -- feed bone_looper the first bone and
83  * a pointer to the bone_func and watch it go!. The int count
84  * can be useful for counting bones with a certain property
85  * (e.g. skinnable)
86  */
87  int count = 0;
88 
89  if (bone) {
90  /* only do bone_func if the bone is non null */
91  count += bone_func(ob, bone, data);
92 
93  /* try to execute bone_func for the first child */
94  count += gpencil_bone_looper(ob, bone->childbase.first, data, bone_func);
95 
96  /* try to execute bone_func for the next bone at this
97  * depth of the recursion.
98  */
99  count += gpencil_bone_looper(ob, bone->next, data, bone_func);
100  }
101 
102  return count;
103 }
104 
105 static int gpencil_bone_skinnable_cb(Object *UNUSED(ob), Bone *bone, void *datap)
106 {
107  /* Bones that are deforming
108  * are regarded to be "skinnable" and are eligible for
109  * auto-skinning.
110  *
111  * This function performs 2 functions:
112  *
113  * a) It returns 1 if the bone is skinnable.
114  * If we loop over all bones with this
115  * function, we can count the number of
116  * skinnable bones.
117  * b) If the pointer data is non null,
118  * it is treated like a handle to a
119  * bone pointer -- the bone pointer
120  * is set to point at this bone, and
121  * the pointer the handle points to
122  * is incremented to point to the
123  * next member of an array of pointers
124  * to bones. This way we can loop using
125  * this function to construct an array of
126  * pointers to bones that point to all
127  * skinnable bones.
128  */
129  Bone ***hbone;
130  int a, segments;
131  struct {
132  Object *armob;
133  void *list;
134  int heat;
135  } *data = datap;
136 
137  if (!(bone->flag & BONE_HIDDEN_P)) {
138  if (!(bone->flag & BONE_NO_DEFORM)) {
139  if (data->heat && data->armob->pose &&
140  BKE_pose_channel_find_name(data->armob->pose, bone->name)) {
141  segments = bone->segments;
142  }
143  else {
144  segments = 1;
145  }
146 
147  if (data->list != NULL) {
148  hbone = (Bone ***)&data->list;
149 
150  for (a = 0; a < segments; a++) {
151  **hbone = bone;
152  (*hbone)++;
153  }
154  }
155  return segments;
156  }
157  }
158  return 0;
159 }
160 
161 static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
162 {
163  /* This group creates a vertex group to ob that has the
164  * same name as bone (provided the bone is skinnable).
165  * If such a vertex group already exist the routine exits.
166  */
167  if (!(bone->flag & BONE_NO_DEFORM)) {
168  if (!BKE_object_defgroup_find_name(ob, bone->name)) {
170  return 1;
171  }
172  }
173  return 0;
174 }
175 
176 static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
177 {
178  /* Bones that are deforming
179  * are regarded to be "skinnable" and are eligible for
180  * auto-skinning.
181  *
182  * This function performs 2 functions:
183  *
184  * a) If the bone is skinnable, it creates
185  * a vertex group for ob that has
186  * the name of the skinnable bone
187  * (if one doesn't exist already).
188  * b) If the pointer data is non null,
189  * it is treated like a handle to a
190  * bDeformGroup pointer -- the
191  * bDeformGroup pointer is set to point
192  * to the deform group with the bone's
193  * name, and the pointer the handle
194  * points to is incremented to point to the
195  * next member of an array of pointers
196  * to bDeformGroups. This way we can loop using
197  * this function to construct an array of
198  * pointers to bDeformGroups, all with names
199  * of skinnable bones.
200  */
201  bDeformGroup ***hgroup, *defgroup = NULL;
202  int a, segments;
203  struct {
204  Object *armob;
205  void *list;
206  int heat;
207  } *data = datap;
208  bArmature *arm = data->armob->data;
209 
210  if (!(bone->flag & BONE_HIDDEN_P)) {
211  if (!(bone->flag & BONE_NO_DEFORM)) {
212  if (data->heat && data->armob->pose &&
213  BKE_pose_channel_find_name(data->armob->pose, bone->name)) {
214  segments = bone->segments;
215  }
216  else {
217  segments = 1;
218  }
219 
220  if (arm->layer & bone->layer) {
221  if (!(defgroup = BKE_object_defgroup_find_name(ob, bone->name))) {
222  defgroup = BKE_object_defgroup_add_name(ob, bone->name);
223  }
224  else if (defgroup->flag & DG_LOCK_WEIGHT) {
225  /* In case vgroup already exists and is locked, do not modify it here. See T43814. */
226  defgroup = NULL;
227  }
228  }
229 
230  if (data->list != NULL) {
231  hgroup = (bDeformGroup ***)&data->list;
232 
233  for (a = 0; a < segments; a++) {
234  **hgroup = defgroup;
235  (*hgroup)++;
236  }
237  }
238  return segments;
239  }
240  }
241  return 0;
242 }
243 
244 /* get weight value depending of distance and decay value */
245 static float get_weight(float dist, float decay_rad, float dif_rad)
246 {
247  float weight = 1.0f;
248  if (dist < decay_rad) {
249  weight = 1.0f;
250  }
251  else {
252  weight = interpf(0.0f, 0.9f, (dist - decay_rad) / dif_rad);
253  }
254 
255  return weight;
256 }
257 
258 /* This functions implements the automatic computation of vertex group weights */
260  const bContext *C, Object *ob, Object *ob_arm, const float ratio, const float decay)
261 {
262  bArmature *arm = ob_arm->data;
263  Bone **bonelist, *bone;
264  bDeformGroup **dgrouplist;
265  bPoseChannel *pchan;
266  bGPdata *gpd = (bGPdata *)ob->data;
267  const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
268 
269  Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = NULL;
270  float(*root)[3], (*tip)[3], (*verts)[3];
271  float *radsqr;
272  int *selected;
273  float weight;
274  int numbones, i, j, segments = 0;
275  struct {
276  Object *armob;
277  void *list;
278  int heat;
279  } looper_data;
280 
281  looper_data.armob = ob_arm;
282  looper_data.heat = true;
283  looper_data.list = NULL;
284 
285  /* count the number of skinnable bones */
286  numbones = gpencil_bone_looper(ob, arm->bonebase.first, &looper_data, gpencil_bone_skinnable_cb);
287 
288  if (numbones == 0) {
289  return;
290  }
291 
292  /* create an array of pointer to bones that are skinnable
293  * and fill it with all of the skinnable bones */
294  bonelist = MEM_callocN(numbones * sizeof(Bone *), "bonelist");
295  looper_data.list = bonelist;
297 
298  /* create an array of pointers to the deform groups that
299  * correspond to the skinnable bones (creating them
300  * as necessary. */
301  dgrouplist = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgrouplist");
302 
303  looper_data.list = dgrouplist;
304  gpencil_bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable_cb);
305 
306  /* create an array of root and tip positions transformed into
307  * global coords */
308  root = MEM_callocN(sizeof(float[3]) * numbones, "root");
309  tip = MEM_callocN(sizeof(float[3]) * numbones, "tip");
310  selected = MEM_callocN(sizeof(int) * numbones, "selected");
311  radsqr = MEM_callocN(sizeof(float) * numbones, "radsqr");
312 
313  for (j = 0; j < numbones; j++) {
314  bone = bonelist[j];
315 
316  /* handle bbone */
317  if (segments == 0) {
318  segments = 1;
319  bbone = NULL;
320 
321  if ((ob_arm->pose) && (pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name))) {
322  if (bone->segments > 1) {
323  segments = bone->segments;
324  BKE_pchan_bbone_spline_setup(pchan, true, false, bbone_array);
325  bbone = bbone_array;
326  }
327  }
328  }
329 
330  segments--;
331 
332  /* compute root and tip */
333  if (bbone) {
334  mul_v3_m4v3(root[j], bone->arm_mat, bbone[segments].mat[3]);
335  if ((segments + 1) < bone->segments) {
336  mul_v3_m4v3(tip[j], bone->arm_mat, bbone[segments + 1].mat[3]);
337  }
338  else {
339  copy_v3_v3(tip[j], bone->arm_tail);
340  }
341  }
342  else {
343  copy_v3_v3(root[j], bone->arm_head);
344  copy_v3_v3(tip[j], bone->arm_tail);
345  }
346 
347  mul_m4_v3(ob_arm->obmat, root[j]);
348  mul_m4_v3(ob_arm->obmat, tip[j]);
349 
350  selected[j] = 1;
351 
352  /* calculate radius squared */
353  radsqr[j] = len_squared_v3v3(root[j], tip[j]) * ratio;
354  }
355 
356  /* loop all strokes */
357  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
358  bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
359  bGPDspoint *pt = NULL;
360 
361  for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
362  if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
363 
364  if (gpf == NULL) {
365  continue;
366  }
367 
368  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
369  /* skip strokes that are invalid for current view */
370  if (ED_gpencil_stroke_can_use(C, gps) == false) {
371  continue;
372  }
373 
375 
376  /* create verts array */
377  verts = MEM_callocN(gps->totpoints * sizeof(*verts), __func__);
378 
379  /* transform stroke points to global space */
380  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
381  copy_v3_v3(verts[i], &pt->x);
382  mul_m4_v3(ob->obmat, verts[i]);
383  }
384 
385  /* loop groups and assign weight */
386  for (j = 0; j < numbones; j++) {
387  int def_nr = BLI_findindex(&ob->defbase, dgrouplist[j]);
388  if (def_nr < 0) {
389  continue;
390  }
391 
392  float decay_rad = radsqr[j] - (radsqr[j] * decay);
393  float dif_rad = radsqr[j] - decay_rad;
394 
395  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
396  MDeformVert *dvert = &gps->dvert[i];
397  float dist = dist_squared_to_line_segment_v3(verts[i], root[j], tip[j]);
398  if (dist > radsqr[j]) {
399  /* if not in cylinder, check if inside extreme spheres */
400  weight = 0.0f;
401  dist = len_squared_v3v3(root[j], verts[i]);
402  if (dist < radsqr[j]) {
403  weight = get_weight(dist, decay_rad, dif_rad);
404  }
405  else {
406  dist = len_squared_v3v3(tip[j], verts[i]);
407  if (dist < radsqr[j]) {
408  weight = get_weight(dist, decay_rad, dif_rad);
409  }
410  }
411  }
412  else {
413  /* inside bone cylinder */
414  weight = get_weight(dist, decay_rad, dif_rad);
415  }
416 
417  /* assign weight */
418  MDeformWeight *dw = BKE_defvert_ensure_index(dvert, def_nr);
419  if (dw) {
420  dw->weight = weight;
421  }
422  }
423  }
425  }
426  }
427 
428  /* if not multiedit, exit loop*/
429  if (!is_multiedit) {
430  break;
431  }
432  }
433  }
434 
435  /* free the memory allocated */
436  MEM_SAFE_FREE(bonelist);
437  MEM_SAFE_FREE(dgrouplist);
438  MEM_SAFE_FREE(root);
439  MEM_SAFE_FREE(tip);
440  MEM_SAFE_FREE(radsqr);
441  MEM_SAFE_FREE(selected);
442 }
443 
445  Object *ob,
446  Object *ob_arm,
447  const int mode,
448  const float ratio,
449  const float decay)
450 {
451  /* Lets try to create some vertex groups
452  * based on the bones of the parent armature.
453  */
454  bArmature *arm = ob_arm->data;
455 
456  /* always create groups */
457  const int defbase_tot = BLI_listbase_count(&ob->defbase);
458  int defbase_add;
459  /* Traverse the bone list, trying to create empty vertex
460  * groups corresponding to the bone.
461  */
463 
464  if (defbase_add) {
465  /* its possible there are DWeight's outside the range of the current
466  * objects deform groups, in this case the new groups wont be empty */
467  ED_vgroup_data_clamp_range(ob->data, defbase_tot);
468  }
469 
470  if (mode == GP_ARMATURE_AUTO) {
471  /* Traverse the bone list, trying to fill vertex groups
472  * with the corresponding vertice weights for which the
473  * bone is closest.
474  */
475  gpencil_add_verts_to_dgroups(C, ob, ob_arm, ratio, decay);
476  }
477 
479 }
480 
481 bool ED_gpencil_add_armature(const bContext *C, ReportList *reports, Object *ob, Object *ob_arm)
482 {
483  Main *bmain = CTX_data_main(C);
485 
486  if (ob == NULL) {
487  return false;
488  }
489 
490  /* if no armature modifier, add a new one */
492  if (md == NULL) {
494  reports, bmain, scene, ob, "Armature", eGpencilModifierType_Armature);
495  if (md == NULL) {
496  BKE_report(reports, RPT_ERROR, "Unable to add a new Armature modifier to object");
497  return false;
498  }
500  }
501 
502  /* verify armature */
504  if (mmd->object == NULL) {
505  mmd->object = ob_arm;
506  }
507  else {
508  if (ob_arm != mmd->object) {
509  BKE_report(reports,
510  RPT_ERROR,
511  "The existing Armature modifier is already using a different Armature object");
512  return false;
513  }
514  }
515  return true;
516 }
517 
519  const bContext *C, ReportList *reports, Object *ob, Object *ob_arm, int mode)
520 {
521  if (ob == NULL) {
522  return false;
523  }
524 
525  bool success = ED_gpencil_add_armature(C, reports, ob, ob_arm);
526 
527  /* add weights */
528  if (success) {
530  }
531 
532  return success;
533 }
534 /* ***************** Generate armature weights ************************** */
536 {
538 
539  if (ob == NULL) {
540  return false;
541  }
542 
543  if (ob->type != OB_GPENCIL) {
544  return false;
545  }
546 
547  ViewLayer *view_layer = CTX_data_view_layer(C);
548  bGPdata *gpd = (bGPdata *)ob->data;
549 
550  if (BLI_listbase_count(&gpd->layers) == 0) {
551  return false;
552  }
553 
554  /* need some armature in the view layer */
555  LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
556  if (base->object->type == OB_ARMATURE) {
557  return true;
558  }
559  }
560 
561  return false;
562 }
563 
565 {
567  ViewLayer *view_layer = CTX_data_view_layer(C);
569  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
570  bGPdata *gpd = (bGPdata *)ob->data;
571  Object *ob_arm = NULL;
572 
573  const int mode = RNA_enum_get(op->ptr, "mode");
574  const float ratio = RNA_float_get(op->ptr, "ratio");
575  const float decay = RNA_float_get(op->ptr, "decay");
576 
577  /* sanity checks */
578  if (ELEM(NULL, ob, gpd)) {
579  return OPERATOR_CANCELLED;
580  }
581 
582  /* get armature */
583  const int arm_idx = RNA_enum_get(op->ptr, "armature");
584  if (arm_idx > 0) {
585  Base *base = BLI_findlink(&view_layer->object_bases, arm_idx - 1);
586  ob_arm = base->object;
587  }
588  else {
589  /* get armature from modifier */
592  if (md == NULL) {
593  BKE_report(op->reports, RPT_ERROR, "The grease pencil object need an Armature modifier");
594  return OPERATOR_CANCELLED;
595  }
596 
598  if (mmd->object == NULL) {
599  BKE_report(op->reports, RPT_ERROR, "Armature modifier is not valid or wrong defined");
600  return OPERATOR_CANCELLED;
601  }
602 
603  ob_arm = mmd->object;
604  }
605 
606  if (ob_arm == NULL) {
607  BKE_report(op->reports, RPT_ERROR, "No Armature object in the view layer");
608  return OPERATOR_CANCELLED;
609  }
610 
611  gpencil_object_vgroup_calc_from_armature(C, ob, ob_arm, mode, ratio, decay);
612 
613  /* notifiers */
616 
617  return OPERATOR_FINISHED;
618 }
619 
620 /* Dynamically populate an enum of Armatures */
623  PropertyRNA *UNUSED(prop),
624  bool *r_free)
625 {
626  ViewLayer *view_layer = CTX_data_view_layer(C);
627  EnumPropertyItem *item = NULL, item_tmp = {0};
628  int totitem = 0;
629  int i = 0;
630 
631  if (C == NULL) {
632  return DummyRNA_DEFAULT_items;
633  }
634 
635  /* add default */
636  item_tmp.identifier = "DEFAULT";
637  item_tmp.name = "Default";
638  item_tmp.value = 0;
639  RNA_enum_item_add(&item, &totitem, &item_tmp);
640  i++;
641 
642  LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
643  Object *ob = base->object;
644  if (ob->type == OB_ARMATURE) {
645  item_tmp.identifier = item_tmp.name = ob->id.name + 2;
646  item_tmp.value = i;
647  RNA_enum_item_add(&item, &totitem, &item_tmp);
648  }
649  i++;
650  }
651 
652  RNA_enum_item_end(&item, &totitem);
653  *r_free = true;
654 
655  return item;
656 }
657 
659 {
660  static const EnumPropertyItem mode_type[] = {
661  {GP_ARMATURE_NAME, "NAME", 0, "Empty Groups", ""},
662  {GP_ARMATURE_AUTO, "AUTO", 0, "Automatic Weights", ""},
663  {0, NULL, 0, NULL, NULL},
664  };
665 
666  PropertyRNA *prop;
667 
668  /* identifiers */
669  ot->name = "Generate Automatic Weights";
670  ot->idname = "GPENCIL_OT_generate_weights";
671  ot->description = "Generate automatic weights for armatures (requires armature modifier)";
672 
674 
675  /* callbacks */
678 
679  ot->prop = RNA_def_enum(ot->srna, "mode", mode_type, 0, "Mode", "");
680 
681  prop = RNA_def_enum(
682  ot->srna, "armature", DummyRNA_DEFAULT_items, 0, "Armature", "Armature to use");
684 
686  "ratio",
688  0.0f,
689  2.0f,
690  "Ratio",
691  "Ratio between bone length and influence radius",
692  0.001f,
693  1.0f);
694 
696  "decay",
698  0.0f,
699  1.0f,
700  "Decay",
701  "Factor to reduce influence depending of distance to bone axis",
702  0.0f,
703  1.0f);
704 }
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
#define MAX_BBONE_SUBDIV
Definition: BKE_armature.h:277
void BKE_pchan_bbone_spline_setup(struct bPoseChannel *pchan, const bool rest, const bool for_deform, Mat4 *result_array)
Definition: armature.c:1134
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
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 Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1279
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
support for deformation groups and hooks.
struct MDeformWeight * BKE_defvert_ensure_index(struct MDeformVert *dv, const int defgroup)
Definition: deform.c:688
struct bDeformGroup * BKE_object_defgroup_find_name(const struct Object *ob, const char *name)
void BKE_gpencil_dvert_ensure(struct bGPDstroke *gps)
Definition: gpencil.c:2067
struct GpencilModifierData * BKE_gpencil_modifiers_findby_type(struct Object *ob, GpencilModifierType type)
Functions for dealing with objects and deform verts, used by painting and tools.
struct bDeformGroup * BKE_object_defgroup_add_name(struct Object *ob, const char *name)
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float interpf(float a, float b, float t)
float dist_squared_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:493
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define UNUSED(x)
#define ELEM(...)
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)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:599
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
@ BONE_HIDDEN_P
@ BONE_NO_DEFORM
@ eGpencilModifierType_Armature
#define GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)
@ GP_FRAME_SELECT
#define DG_LOCK_WEIGHT
@ OB_ARMATURE
@ OB_GPENCIL
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
void ED_vgroup_data_clamp_range(struct ID *id, const int total)
struct GpencilModifierData * ED_object_gpencil_modifier_add(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob, const char *name, int type)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define C
Definition: RandGen.cpp:39
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_DATA
Definition: WM_types.h:408
#define NA_EDITED
Definition: WM_types.h:462
#define NC_GPENCIL
Definition: WM_types.h:300
Scene scene
const Depsgraph * depsgraph
static float verts[][3]
static void gpencil_object_vgroup_calc_from_armature(const bContext *C, Object *ob, Object *ob_arm, const int mode, const float ratio, const float decay)
static int gpencil_bone_looper(Object *ob, Bone *bone, void *data, int(*bone_func)(Object *, Bone *, void *))
static int gpencil_generate_weights_exec(bContext *C, wmOperator *op)
static float get_weight(float dist, float decay_rad, float dif_rad)
#define DEFAULT_RATIO
@ GP_ARMATURE_AUTO
@ GP_ARMATURE_NAME
static void gpencil_add_verts_to_dgroups(const bContext *C, Object *ob, Object *ob_arm, const float ratio, const float decay)
static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
bool ED_gpencil_add_armature_weights(const bContext *C, ReportList *reports, Object *ob, Object *ob_arm, int mode)
void GPENCIL_OT_generate_weights(wmOperatorType *ot)
static const EnumPropertyItem * gpencil_armatures_enum_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
bool ED_gpencil_add_armature(const bContext *C, ReportList *reports, Object *ob, Object *ob_arm)
#define DEFAULT_DECAY
static bool gpencil_generate_weights_poll(bContext *C)
static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
static int gpencil_bone_skinnable_cb(Object *UNUSED(ob), Bone *bone, void *datap)
bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps)
int count
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static unsigned a[3]
Definition: RandGen.cpp:92
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6355
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3825
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_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_DEFAULT_items[]
Definition: rna_rna.c:45
struct Object * object
float arm_head[3]
char name[64]
float arm_tail[3]
short segments
float arm_mat[4][4]
struct Bone * next
ListBase childbase
const char * identifier
Definition: RNA_types.h:446
char name[66]
Definition: DNA_ID.h:283
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
float mat[4][4]
Definition: BKE_armature.h:280
ustring name
Definition: node.h:174
ListBase defbase
struct bPose * pose
float obmat[4][4]
void * data
ListBase object_bases
ListBase bonebase
unsigned int layer
struct bGPDframe * next
ListBase layers
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