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