Blender  V3.3
paint_vertex_weight_utils.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include "BLI_listbase.h"
10 #include "BLI_math.h"
11 #include "BLI_string_utils.h"
12 
13 #include "DNA_armature_types.h"
14 #include "DNA_mesh_types.h"
15 #include "DNA_object_types.h"
16 
17 #include "BKE_action.h"
18 #include "BKE_context.h"
19 #include "BKE_deform.h"
20 #include "BKE_mesh.h"
21 #include "BKE_modifier.h"
22 #include "BKE_object.h"
23 #include "BKE_object_deform.h"
24 #include "BKE_report.h"
25 
26 #include "DEG_depsgraph_build.h"
27 
28 /* Only for blend modes. */
29 #include "IMB_imbuf.h"
30 
31 #include "WM_api.h"
32 #include "WM_types.h"
33 
34 #include "paint_intern.h" /* own include */
35 
36 /* -------------------------------------------------------------------- */
41  struct ReportList *reports,
42  enum eWPaintFlag flag,
43  struct WPaintVGroupIndex *vgroup_index)
44 {
46  Mesh *me = BKE_mesh_from_object(ob);
47 
48  if (vgroup_index) {
49  vgroup_index->active = -1;
50  vgroup_index->mirror = -1;
51  }
52 
53  if (BKE_object_is_in_editmode(ob)) {
54  return false;
55  }
56 
57  if (me == NULL || me->totpoly == 0) {
58  return false;
59  }
60 
61  /* if nothing was added yet, we make dverts and a vertex deform group */
62  if (!me->dvert) {
65  }
66 
67  const ListBase *defbase = BKE_object_defgroup_list(ob);
68 
69  /* this happens on a Bone select, when no vgroup existed yet */
70  if (me->vertex_group_active_index <= 0) {
71  Object *modob;
72  if ((modob = BKE_modifiers_is_deformed_by_armature(ob))) {
73  Bone *actbone = ((bArmature *)modob->data)->act_bone;
74  if (actbone) {
75  bPoseChannel *pchan = BKE_pose_channel_find_name(modob->pose, actbone->name);
76 
77  if (pchan) {
79  if (dg == NULL) {
80  dg = BKE_object_defgroup_add_name(ob, pchan->name); /* sets actdef */
82  }
83  else {
84 
85  int actdef = 1 + BLI_findindex(defbase, dg);
86  BLI_assert(actdef >= 0);
87  me->vertex_group_active_index = actdef;
88  }
89  }
90  }
91  }
92  }
93  if (BLI_listbase_is_empty(defbase)) {
96  }
97 
98  /* ensure we don't try paint onto an invalid group */
99  if (me->vertex_group_active_index <= 0) {
100  BKE_report(reports, RPT_WARNING, "No active vertex group for painting, aborting");
101  return false;
102  }
103 
104  if (vgroup_index) {
105  vgroup_index->active = me->vertex_group_active_index - 1;
106  }
107 
108  if (flag & WPAINT_ENSURE_MIRROR) {
111  if (vgroup_index) {
112  vgroup_index->mirror = mirror;
113  }
114  }
115  }
116 
117  return true;
118 }
119 
122 int ED_wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
123 {
124  const ListBase *defbase = BKE_object_defgroup_list(ob);
125  bDeformGroup *defgroup = BLI_findlink(defbase, vgroup_active);
126 
127  if (defgroup) {
128  int mirrdef;
129  char name_flip[MAXBONENAME];
130 
131  BLI_string_flip_side_name(name_flip, defgroup->name, false, sizeof(name_flip));
132  mirrdef = BKE_object_defgroup_name_index(ob, name_flip);
133  if (mirrdef == -1) {
134  if (BKE_object_defgroup_new(ob, name_flip)) {
135  mirrdef = BLI_listbase_count(defbase) - 1;
136  }
137  }
138 
139  /* curdef should never be NULL unless this is
140  * a light and BKE_object_defgroup_add_name fails */
141  return mirrdef;
142  }
143 
144  return -1;
145 }
146 
147 /* -------------------------------------------------------------------- */
151 BLI_INLINE float wval_blend(const float weight, const float paintval, const float alpha)
152 {
153  const float talpha = min_ff(alpha, 1.0f); /* blending with values over 1 doesn't make sense */
154  return (paintval * talpha) + (weight * (1.0f - talpha));
155 }
156 BLI_INLINE float wval_add(const float weight, const float paintval, const float alpha)
157 {
158  return weight + (paintval * alpha);
159 }
160 BLI_INLINE float wval_sub(const float weight, const float paintval, const float alpha)
161 {
162  return weight - (paintval * alpha);
163 }
164 BLI_INLINE float wval_mul(const float weight, const float paintval, const float alpha)
165 { /* first mul, then blend the fac */
166  return ((1.0f - alpha) + (alpha * paintval)) * weight;
167 }
168 BLI_INLINE float wval_lighten(const float weight, const float paintval, const float alpha)
169 {
170  return (weight < paintval) ? wval_blend(weight, paintval, alpha) : weight;
171 }
172 BLI_INLINE float wval_darken(const float weight, const float paintval, const float alpha)
173 {
174  return (weight > paintval) ? wval_blend(weight, paintval, alpha) : weight;
175 }
176 
177 /* mainly for color */
178 BLI_INLINE float wval_colordodge(float weight, float paintval, float fac)
179 {
180  float mfac, temp;
181  if (fac == 0.0f) {
182  return weight;
183  }
184  mfac = 1.0f - fac;
185  temp = (paintval == 1.0f) ? 1.0f :
186  min_ff((weight * (225.0f / 255.0f)) / (1.0f - paintval), 1.0f);
187  return mfac * weight + temp * fac;
188 }
189 BLI_INLINE float wval_difference(float weight, float paintval, float fac)
190 {
191  float mfac, temp;
192  if (fac == 0.0f) {
193  return weight;
194  }
195  mfac = 1.0f - fac;
196  temp = fabsf(weight - paintval);
197  return mfac * weight + temp * fac;
198 }
199 BLI_INLINE float wval_screen(float weight, float paintval, float fac)
200 {
201  float mfac, temp;
202  if (fac == 0.0f) {
203  return weight;
204  }
205  mfac = 1.0f - fac;
206  temp = max_ff(1.0f - (((1.0f - weight) * (1.0f - paintval))), 0);
207  return mfac * weight + temp * fac;
208 }
209 BLI_INLINE float wval_hardlight(float weight, float paintval, float fac)
210 {
211  float mfac, temp;
212  if (fac == 0.0f) {
213  return weight;
214  }
215  mfac = 1.0f - fac;
216  if (paintval > 0.5f) {
217  temp = 1.0f - ((1.0f - 2.0f * (paintval - 0.5f)) * (1.0f - weight));
218  }
219  else {
220  temp = (2.0f * paintval * weight);
221  }
222  return mfac * weight + temp * fac;
223 }
224 BLI_INLINE float wval_overlay(float weight, float paintval, float fac)
225 {
226  float mfac, temp;
227  if (fac == 0.0f) {
228  return weight;
229  }
230  mfac = 1.0f - fac;
231  if (weight > 0.5f) {
232  temp = 1.0f - ((1.0f - 2.0f * (weight - 0.5f)) * (1.0f - paintval));
233  }
234  else {
235  temp = (2.0f * paintval * weight);
236  }
237  return mfac * weight + temp * fac;
238 }
239 BLI_INLINE float wval_softlight(float weight, float paintval, float fac)
240 {
241  float mfac, temp;
242  if (fac == 0.0f) {
243  return weight;
244  }
245  mfac = 1.0f - fac;
246  if (weight < 0.5f) {
247  temp = ((2.0f * ((paintval / 2.0f) + 0.25f)) * weight);
248  }
249  else {
250  temp = 1.0f - (2.0f * (1.0f - ((paintval / 2.0f) + 0.25f)) * (1.0f - weight));
251  }
252  return temp * fac + weight * mfac;
253 }
254 BLI_INLINE float wval_exclusion(float weight, float paintval, float fac)
255 {
256  float mfac, temp;
257  if (fac == 0.0f) {
258  return weight;
259  }
260  mfac = 1.0f - fac;
261  temp = 0.5f - ((2.0f * (weight - 0.5f) * (paintval - 0.5f)));
262  return temp * fac + weight * mfac;
263 }
264 
265 float ED_wpaint_blend_tool(const int tool,
266  const float weight,
267  const float paintval,
268  const float alpha)
269 {
270  switch ((IMB_BlendMode)tool) {
271  case IMB_BLEND_MIX:
272  return wval_blend(weight, paintval, alpha);
273  case IMB_BLEND_ADD:
274  return wval_add(weight, paintval, alpha);
275  case IMB_BLEND_SUB:
276  return wval_sub(weight, paintval, alpha);
277  case IMB_BLEND_MUL:
278  return wval_mul(weight, paintval, alpha);
279  case IMB_BLEND_LIGHTEN:
280  return wval_lighten(weight, paintval, alpha);
281  case IMB_BLEND_DARKEN:
282  return wval_darken(weight, paintval, alpha);
283  /* Mostly make sense for color: support anyway. */
285  return wval_colordodge(weight, paintval, alpha);
287  return wval_difference(weight, paintval, alpha);
288  case IMB_BLEND_SCREEN:
289  return wval_screen(weight, paintval, alpha);
290  case IMB_BLEND_HARDLIGHT:
291  return wval_hardlight(weight, paintval, alpha);
292  case IMB_BLEND_OVERLAY:
293  return wval_overlay(weight, paintval, alpha);
294  case IMB_BLEND_SOFTLIGHT:
295  return wval_softlight(weight, paintval, alpha);
296  case IMB_BLEND_EXCLUSION:
297  return wval_exclusion(weight, paintval, alpha);
298  /* Only for color: just use blend. */
299  default:
300  return wval_blend(weight, paintval, alpha);
301  }
302 }
303 
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
support for deformation groups and hooks.
int BKE_object_defgroup_name_index(const struct Object *ob, const char *name)
const struct ListBase * BKE_object_defgroup_list(const struct Object *ob)
struct bDeformGroup * BKE_object_defgroup_new(struct Object *ob, const char *name)
Definition: deform.c:43
struct bDeformGroup * BKE_object_defgroup_find_name(const struct Object *ob, const char *name)
struct Mesh * BKE_mesh_from_object(struct Object *ob)
Definition: mesh.cc:1365
struct Object * BKE_modifiers_is_deformed_by_armature(struct Object *ob)
General operations, lookup, etc. for blender objects.
bool BKE_object_is_in_editmode(const struct Object *ob)
Functions for dealing with objects and deform verts, used by painting and tools.
struct MDeformVert * BKE_object_defgroup_data_create(struct ID *id)
struct bDeformGroup * BKE_object_defgroup_add(struct Object *ob)
struct bDeformGroup * BKE_object_defgroup_add_name(struct Object *ob, const char *name)
Definition: object_deform.c:95
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_INLINE
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
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 max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
size_t BLI_string_flip_side_name(char *r_name, const char *from_name, bool strip_number, size_t name_len)
Definition: string_utils.c:112
void DEG_relations_tag_update(struct Main *bmain)
#define MAXBONENAME
#define ME_USING_MIRROR_X_VERTEX_GROUPS(_me)
Object is a sort of wrapper for general info.
IMB_BlendMode
Definition: IMB_imbuf.h:209
@ IMB_BLEND_EXCLUSION
Definition: IMB_imbuf.h:229
@ IMB_BLEND_DIFFERENCE
Definition: IMB_imbuf.h:228
@ IMB_BLEND_HARDLIGHT
Definition: IMB_imbuf.h:219
@ IMB_BLEND_COLORDODGE
Definition: IMB_imbuf.h:222
@ IMB_BLEND_SCREEN
Definition: IMB_imbuf.h:223
@ IMB_BLEND_MUL
Definition: IMB_imbuf.h:213
@ IMB_BLEND_DARKEN
Definition: IMB_imbuf.h:215
@ IMB_BLEND_OVERLAY
Definition: IMB_imbuf.h:218
@ IMB_BLEND_LIGHTEN
Definition: IMB_imbuf.h:214
@ IMB_BLEND_SOFTLIGHT
Definition: IMB_imbuf.h:224
@ IMB_BLEND_MIX
Definition: IMB_imbuf.h:210
@ IMB_BLEND_ADD
Definition: IMB_imbuf.h:211
@ IMB_BLEND_SUB
Definition: IMB_imbuf.h:212
#define C
Definition: RandGen.cpp:25
#define NC_GEOM
Definition: WM_types.h:343
#define ND_DATA
Definition: WM_types.h:456
#define fabsf(x)
Definition: metal/compat.h:219
eWPaintFlag
Definition: paint_intern.h:157
@ WPAINT_ENSURE_MIRROR
Definition: paint_intern.h:158
BLI_INLINE float wval_screen(float weight, float paintval, float fac)
BLI_INLINE float wval_softlight(float weight, float paintval, float fac)
BLI_INLINE float wval_difference(float weight, float paintval, float fac)
BLI_INLINE float wval_colordodge(float weight, float paintval, float fac)
float ED_wpaint_blend_tool(const int tool, const float weight, const float paintval, const float alpha)
BLI_INLINE float wval_blend(const float weight, const float paintval, const float alpha)
BLI_INLINE float wval_lighten(const float weight, const float paintval, const float alpha)
BLI_INLINE float wval_overlay(float weight, float paintval, float fac)
bool ED_wpaint_ensure_data(bContext *C, struct ReportList *reports, enum eWPaintFlag flag, struct WPaintVGroupIndex *vgroup_index)
BLI_INLINE float wval_mul(const float weight, const float paintval, const float alpha)
BLI_INLINE float wval_darken(const float weight, const float paintval, const float alpha)
BLI_INLINE float wval_add(const float weight, const float paintval, const float alpha)
BLI_INLINE float wval_exclusion(float weight, float paintval, float fac)
BLI_INLINE float wval_hardlight(float weight, float paintval, float fac)
BLI_INLINE float wval_sub(const float weight, const float paintval, const float alpha)
int ED_wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
char name[64]
struct MDeformVert * dvert
int totpoly
int vertex_group_active_index
struct bPose * pose
void * data
void WM_event_add_notifier(const bContext *C, uint type, void *reference)