Blender  V3.3
MOD_gpencilhook.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2017 Blender Foundation. */
3 
8 #include <stdio.h>
9 #include <string.h>
10 
11 #include "BLI_listbase.h"
12 #include "BLI_math_base.h"
13 #include "BLI_math_matrix.h"
14 #include "BLI_math_vector.h"
15 #include "BLI_utildefines.h"
16 
17 #include "BLT_translation.h"
18 
19 #include "DNA_defaults.h"
21 #include "DNA_gpencil_types.h"
22 #include "DNA_meshdata_types.h"
23 #include "DNA_modifier_types.h"
24 #include "DNA_object_types.h"
25 #include "DNA_scene_types.h"
26 #include "DNA_screen_types.h"
27 
28 #include "BKE_action.h"
29 #include "BKE_colortools.h"
30 #include "BKE_context.h"
31 #include "BKE_deform.h"
32 #include "BKE_gpencil_geom.h"
33 #include "BKE_gpencil_modifier.h"
34 #include "BKE_lib_query.h"
35 #include "BKE_main.h"
36 #include "BKE_modifier.h"
37 #include "BKE_scene.h"
38 #include "BKE_screen.h"
39 
40 #include "UI_interface.h"
41 #include "UI_resources.h"
42 
43 #include "RNA_access.h"
44 
46 #include "MOD_gpencil_ui_common.h"
47 #include "MOD_gpencil_util.h"
48 
49 #include "DEG_depsgraph.h"
50 #include "DEG_depsgraph_build.h"
51 #include "DEG_depsgraph_query.h"
52 
53 /* temp struct to hold data */
54 struct GPHookData_cb {
56 
58  float falloff;
59  float falloff_sq;
60  float fac_orig;
61 
64 
65  float cent[3];
66 
67  float mat_uniform[3][3];
68  float mat[4][4];
69 };
70 
71 static void initData(GpencilModifierData *md)
72 {
74 
75  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(gpmd, modifier));
76 
78 
79  gpmd->curfalloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
81 }
82 
83 static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
84 {
87 
88  if (tgmd->curfalloff != NULL) {
90  tgmd->curfalloff = NULL;
91  }
92 
94 
96 }
97 
98 /* Calculate the factor of falloff. */
99 static float gpencil_hook_falloff(const struct GPHookData_cb *tData, const float len_sq)
100 {
101  BLI_assert(tData->falloff_sq);
102  if (len_sq > tData->falloff_sq) {
103  return 0.0f;
104  }
105  if (len_sq > 0.0f) {
106  float fac;
107 
108  if (tData->falloff_type == eGPHook_Falloff_Const) {
109  fac = 1.0f;
110  goto finally;
111  }
112  else if (tData->falloff_type == eGPHook_Falloff_InvSquare) {
113  /* avoid sqrt below */
114  fac = 1.0f - (len_sq / tData->falloff_sq);
115  goto finally;
116  }
117 
118  fac = 1.0f - (sqrtf(len_sq) / tData->falloff);
119 
120  switch (tData->falloff_type) {
122  fac = BKE_curvemapping_evaluateF(tData->curfalloff, 0, fac);
123  break;
125  fac = fac * fac;
126  break;
128  fac = 3.0f * fac * fac - 2.0f * fac * fac * fac;
129  break;
131  fac = sqrtf(fac);
132  break;
134  /* pass */
135  break;
137  fac = sqrtf(2 * fac - fac * fac);
138  break;
139  default:
140  break;
141  }
142 
143  finally:
144  return fac * tData->fac_orig;
145  }
146  else {
147  return tData->fac_orig;
148  }
149 }
150 
151 /* apply point deformation */
152 static void gpencil_hook_co_apply(struct GPHookData_cb *tData, float weight, bGPDspoint *pt)
153 {
154  float fac;
155 
156  if (tData->use_falloff) {
157  float len_sq;
158 
159  if (tData->use_uniform) {
160  float co_uniform[3];
161  mul_v3_m3v3(co_uniform, tData->mat_uniform, &pt->x);
162  len_sq = len_squared_v3v3(tData->cent, co_uniform);
163  }
164  else {
165  len_sq = len_squared_v3v3(tData->cent, &pt->x);
166  }
167 
168  fac = gpencil_hook_falloff(tData, len_sq);
169  }
170  else {
171  fac = tData->fac_orig;
172  }
173 
174  if (fac) {
175  float co_tmp[3];
176  mul_v3_m4v3(co_tmp, tData->mat, &pt->x);
177  interp_v3_v3v3(&pt->x, &pt->x, co_tmp, fac * weight);
178  }
179 }
180 
181 /* deform stroke */
184  Object *ob,
185  bGPDlayer *gpl,
186  bGPDframe *UNUSED(gpf),
187  bGPDstroke *gps)
188 {
190  if (!mmd->object) {
191  return;
192  }
193 
194  const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
195 
197  float dmat[4][4];
198  struct GPHookData_cb tData;
199 
201  mmd->layername,
202  mmd->material,
203  mmd->pass_index,
204  mmd->layer_pass,
205  1,
206  gpl,
207  gps,
208  mmd->flag & GP_HOOK_INVERT_LAYER,
209  mmd->flag & GP_HOOK_INVERT_PASS,
211  mmd->flag & GP_HOOK_INVERT_MATERIAL)) {
212  return;
213  }
214  bGPdata *gpd = ob->data;
215 
216  /* init struct */
217  tData.curfalloff = mmd->curfalloff;
218  tData.falloff_type = mmd->falloff_type;
219  tData.falloff = (mmd->falloff_type == eHook_Falloff_None) ? 0.0f : mmd->falloff;
220  tData.falloff_sq = square_f(tData.falloff);
221  tData.fac_orig = mmd->force;
222  tData.use_falloff = (tData.falloff_sq != 0.0f);
223  tData.use_uniform = (mmd->flag & GP_HOOK_UNIFORM_SPACE) != 0;
224 
225  if (tData.use_uniform) {
226  copy_m3_m4(tData.mat_uniform, mmd->parentinv);
227  mul_v3_m3v3(tData.cent, tData.mat_uniform, mmd->cent);
228  }
229  else {
230  unit_m3(tData.mat_uniform);
231  copy_v3_v3(tData.cent, mmd->cent);
232  }
233 
234  /* get world-space matrix of target, corrected for the space the verts are in */
235  if (mmd->subtarget[0] && pchan) {
236  /* bone target if there's a matching pose-channel */
237  mul_m4_m4m4(dmat, mmd->object->obmat, pchan->pose_mat);
238  }
239  else {
240  /* just object target */
241  copy_m4_m4(dmat, mmd->object->obmat);
242  }
243  invert_m4_m4(ob->imat, ob->obmat);
244  mul_m4_series(tData.mat, ob->imat, dmat, mmd->parentinv);
245 
246  /* loop points and apply deform */
247  for (int i = 0; i < gps->totpoints; i++) {
248  bGPDspoint *pt = &gps->points[i];
249  MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
250 
251  /* verify vertex group */
252  const float weight = get_modifier_point_weight(
253  dvert, (mmd->flag & GP_HOOK_INVERT_VGROUP) != 0, def_nr);
254  if (weight < 0.0f) {
255  continue;
256  }
257  gpencil_hook_co_apply(&tData, weight, pt);
258  }
259  /* Calc geometry data. */
261 }
262 
263 /* FIXME: Ideally we be doing this on a copy of the main depsgraph
264  * (i.e. one where we don't have to worry about restoring state)
265  */
266 static void bakeModifier(Main *UNUSED(bmain),
269  Object *ob)
270 {
272 
273  if (mmd->object == NULL) {
274  return;
275  }
276 
278 }
279 
281 {
283 
284  if (mmd->curfalloff) {
286  }
287 }
288 
289 static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
290 {
292 
293  return !mmd->object;
294 }
295 
298  const int UNUSED(mode))
299 {
301  if (lmd->object != NULL) {
302  DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_GEOMETRY, "Hook Modifier");
303  DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_TRANSFORM, "Hook Modifier");
304  }
305  DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Hook Modifier");
306 }
307 
308 static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
309 {
311 
312  walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER);
313  walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP);
314 }
315 
316 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
317 {
318  uiLayout *sub, *row, *col;
319  uiLayout *layout = panel->layout;
320 
321  PointerRNA ob_ptr;
323 
324  PointerRNA hook_object_ptr = RNA_pointer_get(ptr, "object");
325  bool has_vertex_group = RNA_string_length(ptr, "vertex_group") != 0;
326 
327  uiLayoutSetPropSep(layout, true);
328 
329  col = uiLayoutColumn(layout, false);
330  uiItemR(col, ptr, "object", 0, NULL, ICON_NONE);
331  if (!RNA_pointer_is_null(&hook_object_ptr) &&
332  RNA_enum_get(&hook_object_ptr, "type") == OB_ARMATURE) {
333  PointerRNA hook_object_data_ptr = RNA_pointer_get(&hook_object_ptr, "data");
335  col, ptr, "subtarget", &hook_object_data_ptr, "bones", IFACE_("Bone"), ICON_NONE);
336  }
337 
338  row = uiLayoutRow(layout, true);
339  uiItemPointerR(row, ptr, "vertex_group", &ob_ptr, "vertex_groups", NULL, ICON_NONE);
340  sub = uiLayoutRow(row, true);
341  uiLayoutSetActive(sub, has_vertex_group);
342  uiLayoutSetPropSep(sub, false);
343  uiItemR(sub, ptr, "invert_vertex", 0, "", ICON_ARROW_LEFTRIGHT);
344 
345  uiItemR(layout, ptr, "strength", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
346 
348 }
349 
350 static void falloff_panel_draw(const bContext *UNUSED(C), Panel *panel)
351 {
352  uiLayout *row;
353  uiLayout *layout = panel->layout;
354 
356 
357  bool use_falloff = RNA_enum_get(ptr, "falloff_type") != eWarp_Falloff_None;
358 
359  uiLayoutSetPropSep(layout, true);
360 
361  uiItemR(layout, ptr, "falloff_type", 0, IFACE_("Type"), ICON_NONE);
362 
363  row = uiLayoutRow(layout, false);
365  uiItemR(row, ptr, "falloff_radius", 0, NULL, ICON_NONE);
366 
367  uiItemR(layout, ptr, "use_falloff_uniform", 0, NULL, ICON_NONE);
368 
369  if (RNA_enum_get(ptr, "falloff_type") == eWarp_Falloff_Curve) {
370  uiTemplateCurveMapping(layout, ptr, "falloff_curve", 0, false, false, false, false);
371  }
372 }
373 
374 static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
375 {
376  gpencil_modifier_masking_panel_draw(panel, true, false);
377 }
378 
379 static void panelRegister(ARegionType *region_type)
380 {
382  region_type, eGpencilModifierType_Hook, panel_draw);
384  region_type, "falloff", "Falloff", NULL, falloff_panel_draw, panel_type);
386  region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type);
387 }
388 
390  /* name */ N_("Hook"),
391  /* structName */ "HookGpencilModifierData",
392  /* structSize */ sizeof(HookGpencilModifierData),
395 
396  /* copyData */ copyData,
397 
398  /* deformStroke */ deformStroke,
399  /* generateStrokes */ NULL,
400  /* bakeModifier */ bakeModifier,
401  /* remapTime */ NULL,
402 
403  /* initData */ initData,
404  /* freeData */ freeData,
405  /* isDisabled */ isDisabled,
406  /* updateDepsgraph */ updateDepsgraph,
407  /* dependsOnTime */ NULL,
408  /* foreachIDLink */ foreachIDLink,
409  /* foreachTexLink */ NULL,
410  /* panelRegister */ panelRegister,
411 };
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1235
struct CurveMapping * BKE_curvemapping_copy(const struct CurveMapping *cumap)
float BKE_curvemapping_evaluateF(const struct CurveMapping *cumap, int cur, float value)
void BKE_curvemapping_free(struct CurveMapping *cumap)
Definition: colortools.c:103
struct CurveMapping * BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
Definition: colortools.c:72
support for deformation groups and hooks.
int BKE_object_defgroup_name_index(const struct Object *ob, const char *name)
void BKE_gpencil_stroke_geometry_update(struct bGPdata *gpd, struct bGPDstroke *gps)
void BKE_gpencil_modifier_copydata_generic(const struct GpencilModifierData *md_src, struct GpencilModifierData *md_dst)
@ eGpencilModifierTypeFlag_SupportsEditmode
@ eGpencilModifierTypeType_Gpencil
@ IDWALK_CB_USER
Definition: BKE_lib_query.h:73
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:33
void(* IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag)
Definition: BKE_modifier.h:107
#define BLI_assert(a)
Definition: BLI_assert.h:46
MINLINE float square_f(float a)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void unit_m3(float m[3][3])
Definition: math_matrix.c:40
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
#define mul_m4_series(...)
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:897
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])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define IFACE_(msgid)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_add_object_relation(struct DepsNodeHandle *node_handle, struct Object *object, eDepsObjectComponentType component, const char *description)
@ DEG_OB_COMP_GEOMETRY
@ DEG_OB_COMP_TRANSFORM
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
@ GP_HOOK_INVERT_MATERIAL
@ GP_HOOK_INVERT_LAYERPASS
@ eGPHook_Falloff_InvSquare
@ eGPHook_Falloff_Smooth
@ eGPHook_Falloff_Linear
@ eGPHook_Falloff_Sphere
struct HookGpencilModifierData HookGpencilModifierData
@ eGpencilModifierType_Hook
@ eWarp_Falloff_Curve
@ eWarp_Falloff_None
@ eHook_Falloff_None
Object is a sort of wrapper for general info.
@ OB_ARMATURE
PointerRNA * gpencil_modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void gpencil_modifier_masking_panel_draw(Panel *panel, bool use_material, bool use_vertex)
void gpencil_modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * gpencil_modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
PanelType * gpencil_modifier_panel_register(ARegionType *region_type, GpencilModifierType type, PanelDrawFn draw)
float get_modifier_point_weight(MDeformVert *dvert, bool inverse, int def_nr)
void generic_bake_deform_stroke(Depsgraph *depsgraph, GpencilModifierData *md, Object *ob, const bool retime, gpBakeCb bake_cb)
bool is_stroke_affected_by_modifier(Object *ob, char *mlayername, Material *material, const int mpassindex, const int gpl_passindex, const int minpoints, bGPDlayer *gpl, bGPDstroke *gps, const bool inv1, const bool inv2, const bool inv3, const bool inv4)
static void deformStroke(GpencilModifierData *md, Depsgraph *UNUSED(depsgraph), Object *ob, bGPDlayer *gpl, bGPDframe *UNUSED(gpf), bGPDstroke *gps)
static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
static void falloff_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void freeData(GpencilModifierData *md)
GpencilModifierTypeInfo modifierType_Gpencil_Hook
static void updateDepsgraph(GpencilModifierData *md, const ModifierUpdateDepsgraphContext *ctx, const int UNUSED(mode))
static float gpencil_hook_falloff(const struct GPHookData_cb *tData, const float len_sq)
static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
static void bakeModifier(Main *UNUSED(bmain), Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
static void panelRegister(ARegionType *region_type)
static void initData(GpencilModifierData *md)
static void gpencil_hook_co_apply(struct GPHookData_cb *tData, float weight, bGPDspoint *pt)
#define C
Definition: RandGen.cpp:25
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int type, bool levels, bool brush, bool neg_slope, bool tone)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
@ UI_ITEM_R_SLIDER
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *searchptr, const char *searchpropname, const char *name, int icon)
const Depsgraph * depsgraph
uint col
#define sqrtf(x)
Definition: metal/compat.h:243
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5167
int RNA_string_length(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5144
bool RNA_pointer_is_null(const PointerRNA *ptr)
Definition: rna_access.c:164
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
float mat_uniform[3][3]
float mat[4][4]
struct CurveMapping * curfalloff
Definition: DNA_ID.h:368
Definition: BKE_main.h:121
struct DepsNodeHandle * node
Definition: BKE_modifier.h:134
struct bPose * pose
float imat[4][4]
float obmat[4][4]
void * data
struct uiLayout * layout
bGPDspoint * points
struct MDeformVert * dvert
float pose_mat[4][4]
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480