Blender  V2.93
paint_vertex_weight_utils.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 
23 #include "BLI_listbase.h"
24 #include "BLI_math.h"
25 #include "BLI_string_utils.h"
26 
27 #include "DNA_armature_types.h"
28 #include "DNA_mesh_types.h"
29 #include "DNA_object_types.h"
30 
31 #include "BKE_action.h"
32 #include "BKE_context.h"
33 #include "BKE_deform.h"
34 #include "BKE_mesh.h"
35 #include "BKE_modifier.h"
36 #include "BKE_object.h"
37 #include "BKE_object_deform.h"
38 #include "BKE_report.h"
39 
40 #include "DEG_depsgraph_build.h"
41 
42 /* Only for blend modes. */
43 #include "IMB_imbuf.h"
44 
45 #include "WM_api.h"
46 #include "WM_types.h"
47 
48 #include "paint_intern.h" /* own include */
49 
50 /* -------------------------------------------------------------------- */
54 /* ensure we have data on wpaint start, add if needed */
56  struct ReportList *reports,
57  enum eWPaintFlag flag,
58  struct WPaintVGroupIndex *vgroup_index)
59 {
61  Mesh *me = BKE_mesh_from_object(ob);
62 
63  if (vgroup_index) {
64  vgroup_index->active = -1;
65  vgroup_index->mirror = -1;
66  }
67 
68  if (BKE_object_is_in_editmode(ob)) {
69  return false;
70  }
71 
72  if (me == NULL || me->totpoly == 0) {
73  return false;
74  }
75 
76  /* if nothing was added yet, we make dverts and a vertex deform group */
77  if (!me->dvert) {
80  }
81 
82  /* this happens on a Bone select, when no vgroup existed yet */
83  if (ob->actdef <= 0) {
84  Object *modob;
85  if ((modob = BKE_modifiers_is_deformed_by_armature(ob))) {
86  Bone *actbone = ((bArmature *)modob->data)->act_bone;
87  if (actbone) {
88  bPoseChannel *pchan = BKE_pose_channel_find_name(modob->pose, actbone->name);
89 
90  if (pchan) {
92  if (dg == NULL) {
93  dg = BKE_object_defgroup_add_name(ob, pchan->name); /* sets actdef */
95  }
96  else {
97  int actdef = 1 + BLI_findindex(&ob->defbase, dg);
98  BLI_assert(actdef >= 0);
99  ob->actdef = actdef;
100  }
101  }
102  }
103  }
104  }
105  if (BLI_listbase_is_empty(&ob->defbase)) {
108  }
109 
110  /* ensure we don't try paint onto an invalid group */
111  if (ob->actdef <= 0) {
112  BKE_report(reports, RPT_WARNING, "No active vertex group for painting, aborting");
113  return false;
114  }
115 
116  if (vgroup_index) {
117  vgroup_index->active = ob->actdef - 1;
118  }
119 
120  if (flag & WPAINT_ENSURE_MIRROR) {
122  int mirror = ED_wpaint_mirror_vgroup_ensure(ob, ob->actdef - 1);
123  if (vgroup_index) {
124  vgroup_index->mirror = mirror;
125  }
126  }
127  }
128 
129  return true;
130 }
133 /* mirror_vgroup is set to -1 when invalid */
134 int ED_wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
135 {
136  bDeformGroup *defgroup = BLI_findlink(&ob->defbase, vgroup_active);
137 
138  if (defgroup) {
139  int mirrdef;
140  char name_flip[MAXBONENAME];
141 
142  BLI_string_flip_side_name(name_flip, defgroup->name, false, sizeof(name_flip));
143  mirrdef = BKE_object_defgroup_name_index(ob, name_flip);
144  if (mirrdef == -1) {
145  if (BKE_object_defgroup_new(ob, name_flip)) {
146  mirrdef = BLI_listbase_count(&ob->defbase) - 1;
147  }
148  }
149 
150  /* curdef should never be NULL unless this is
151  * a light and BKE_object_defgroup_add_name fails */
152  return mirrdef;
153  }
154 
155  return -1;
156 }
157 
158 /* -------------------------------------------------------------------- */
162 BLI_INLINE float wval_blend(const float weight, const float paintval, const float alpha)
163 {
164  const float talpha = min_ff(alpha, 1.0f); /* blending with values over 1 doesn't make sense */
165  return (paintval * talpha) + (weight * (1.0f - talpha));
166 }
167 BLI_INLINE float wval_add(const float weight, const float paintval, const float alpha)
168 {
169  return weight + (paintval * alpha);
170 }
171 BLI_INLINE float wval_sub(const float weight, const float paintval, const float alpha)
172 {
173  return weight - (paintval * alpha);
174 }
175 BLI_INLINE float wval_mul(const float weight, const float paintval, const float alpha)
176 { /* first mul, then blend the fac */
177  return ((1.0f - alpha) + (alpha * paintval)) * weight;
178 }
179 BLI_INLINE float wval_lighten(const float weight, const float paintval, const float alpha)
180 {
181  return (weight < paintval) ? wval_blend(weight, paintval, alpha) : weight;
182 }
183 BLI_INLINE float wval_darken(const float weight, const float paintval, const float alpha)
184 {
185  return (weight > paintval) ? wval_blend(weight, paintval, alpha) : weight;
186 }
187 
188 /* mainly for color */
189 BLI_INLINE float wval_colordodge(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 = (paintval == 1.0f) ? 1.0f :
197  min_ff((weight * (225.0f / 255.0f)) / (1.0f - paintval), 1.0f);
198  return mfac * weight + temp * fac;
199 }
200 BLI_INLINE float wval_difference(float weight, float paintval, float fac)
201 {
202  float mfac, temp;
203  if (fac == 0.0f) {
204  return weight;
205  }
206  mfac = 1.0f - fac;
207  temp = fabsf(weight - paintval);
208  return mfac * weight + temp * fac;
209 }
210 BLI_INLINE float wval_screen(float weight, float paintval, float fac)
211 {
212  float mfac, temp;
213  if (fac == 0.0f) {
214  return weight;
215  }
216  mfac = 1.0f - fac;
217  temp = max_ff(1.0f - (((1.0f - weight) * (1.0f - paintval))), 0);
218  return mfac * weight + temp * fac;
219 }
220 BLI_INLINE float wval_hardlight(float weight, float paintval, float fac)
221 {
222  float mfac, temp;
223  if (fac == 0.0f) {
224  return weight;
225  }
226  mfac = 1.0f - fac;
227  if (paintval > 0.5f) {
228  temp = 1.0f - ((1.0f - 2.0f * (paintval - 0.5f)) * (1.0f - weight));
229  }
230  else {
231  temp = (2.0f * paintval * weight);
232  }
233  return mfac * weight + temp * fac;
234 }
235 BLI_INLINE float wval_overlay(float weight, float paintval, float fac)
236 {
237  float mfac, temp;
238  if (fac == 0.0f) {
239  return weight;
240  }
241  mfac = 1.0f - fac;
242  if (weight > 0.5f) {
243  temp = 1.0f - ((1.0f - 2.0f * (weight - 0.5f)) * (1.0f - paintval));
244  }
245  else {
246  temp = (2.0f * paintval * weight);
247  }
248  return mfac * weight + temp * fac;
249 }
250 BLI_INLINE float wval_softlight(float weight, float paintval, float fac)
251 {
252  float mfac, temp;
253  if (fac == 0.0f) {
254  return weight;
255  }
256  mfac = 1.0f - fac;
257  if (weight < 0.5f) {
258  temp = ((2.0f * ((paintval / 2.0f) + 0.25f)) * weight);
259  }
260  else {
261  temp = 1.0f - (2.0f * (1.0f - ((paintval / 2.0f) + 0.25f)) * (1.0f - weight));
262  }
263  return temp * fac + weight * mfac;
264 }
265 BLI_INLINE float wval_exclusion(float weight, float paintval, float fac)
266 {
267  float mfac, temp;
268  if (fac == 0.0f) {
269  return weight;
270  }
271  mfac = 1.0f - fac;
272  temp = 0.5f - ((2.0f * (weight - 0.5f) * (paintval - 0.5f)));
273  return temp * fac + weight * mfac;
274 }
275 
284 float ED_wpaint_blend_tool(const int tool,
285  const float weight,
286  const float paintval,
287  const float alpha)
288 {
289  switch ((IMB_BlendMode)tool) {
290  case IMB_BLEND_MIX:
291  return wval_blend(weight, paintval, alpha);
292  case IMB_BLEND_ADD:
293  return wval_add(weight, paintval, alpha);
294  case IMB_BLEND_SUB:
295  return wval_sub(weight, paintval, alpha);
296  case IMB_BLEND_MUL:
297  return wval_mul(weight, paintval, alpha);
298  case IMB_BLEND_LIGHTEN:
299  return wval_lighten(weight, paintval, alpha);
300  case IMB_BLEND_DARKEN:
301  return wval_darken(weight, paintval, alpha);
302  /* Mostly make sense for color: support anyway. */
304  return wval_colordodge(weight, paintval, alpha);
306  return wval_difference(weight, paintval, alpha);
307  case IMB_BLEND_SCREEN:
308  return wval_screen(weight, paintval, alpha);
309  case IMB_BLEND_HARDLIGHT:
310  return wval_hardlight(weight, paintval, alpha);
311  case IMB_BLEND_OVERLAY:
312  return wval_overlay(weight, paintval, alpha);
313  case IMB_BLEND_SOFTLIGHT:
314  return wval_softlight(weight, paintval, alpha);
315  case IMB_BLEND_EXCLUSION:
316  return wval_exclusion(weight, paintval, alpha);
317  /* Only for color: just use blend. */
318  default:
319  return wval_blend(weight, paintval, alpha);
320  }
321 }
322 
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:1279
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
support for deformation groups and hooks.
int BKE_object_defgroup_name_index(const struct Object *ob, const char *name)
struct bDeformGroup * BKE_object_defgroup_new(struct Object *ob, const char *name)
Definition: deform.c:57
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.c:1271
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)
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_INLINE
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
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)
void BLI_string_flip_side_name(char *r_name, const char *from_name, const bool strip_number, const size_t name_len)
Definition: string_utils.c:159
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:197
@ IMB_BLEND_EXCLUSION
Definition: IMB_imbuf.h:217
@ IMB_BLEND_DIFFERENCE
Definition: IMB_imbuf.h:216
@ IMB_BLEND_HARDLIGHT
Definition: IMB_imbuf.h:207
@ IMB_BLEND_COLORDODGE
Definition: IMB_imbuf.h:210
@ IMB_BLEND_SCREEN
Definition: IMB_imbuf.h:211
@ IMB_BLEND_MUL
Definition: IMB_imbuf.h:201
@ IMB_BLEND_DARKEN
Definition: IMB_imbuf.h:203
@ IMB_BLEND_OVERLAY
Definition: IMB_imbuf.h:206
@ IMB_BLEND_LIGHTEN
Definition: IMB_imbuf.h:202
@ IMB_BLEND_SOFTLIGHT
Definition: IMB_imbuf.h:212
@ IMB_BLEND_MIX
Definition: IMB_imbuf.h:198
@ IMB_BLEND_ADD
Definition: IMB_imbuf.h:199
@ IMB_BLEND_SUB
Definition: IMB_imbuf.h:200
#define C
Definition: RandGen.cpp:39
#define NC_GEOM
Definition: WM_types.h:294
#define ND_DATA
Definition: WM_types.h:408
static CCL_NAMESPACE_BEGIN const double alpha
#define fabsf(x)
eWPaintFlag
Definition: paint_intern.h:136
@ WPAINT_ENSURE_MIRROR
Definition: paint_intern.h:137
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
ListBase defbase
struct bPose * pose
unsigned short actdef
void * data
void WM_event_add_notifier(const bContext *C, uint type, void *reference)