Fix assert in some cases when using DataTransfer modifier for custom normals.
[blender.git] / source / blender / gpencil_modifiers / intern / MOD_gpencilopacity.c
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) 2017, Blender Foundation
17  * This is a new part of Blender
18  */
19
20 /** \file
21  * \ingroup modifiers
22  */
23
24 #include <stdio.h>
25
26 #include "BLI_utildefines.h"
27
28 #include "BLI_blenlib.h"
29 #include "BLI_ghash.h"
30 #include "BLI_math_vector.h"
31
32 #include "DNA_meshdata_types.h"
33 #include "DNA_scene_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_gpencil_types.h"
36 #include "DNA_gpencil_modifier_types.h"
37
38 #include "BKE_deform.h"
39 #include "BKE_material.h"
40 #include "BKE_gpencil.h"
41 #include "BKE_gpencil_modifier.h"
42 #include "BKE_main.h"
43
44 #include "DEG_depsgraph.h"
45
46 #include "MOD_gpencil_util.h"
47 #include "MOD_gpencil_modifiertypes.h"
48
49 static void initData(GpencilModifierData *md)
50 {
51   OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md;
52   gpmd->pass_index = 0;
53   gpmd->factor = 1.0f;
54   gpmd->layername[0] = '\0';
55   gpmd->vgname[0] = '\0';
56   gpmd->flag |= GP_OPACITY_CREATE_COLORS;
57   gpmd->modify_color = GP_MODIFY_COLOR_BOTH;
58 }
59
60 static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
61 {
62   BKE_gpencil_modifier_copyData_generic(md, target);
63 }
64
65 /* opacity strokes */
66 static void deformStroke(GpencilModifierData *md,
67                          Depsgraph *UNUSED(depsgraph),
68                          Object *ob,
69                          bGPDlayer *gpl,
70                          bGPDstroke *gps)
71 {
72   OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
73   const int def_nr = defgroup_name_index(ob, mmd->vgname);
74
75   if (!is_stroke_affected_by_modifier(ob,
76                                       mmd->layername,
77                                       mmd->pass_index,
78                                       mmd->layer_pass,
79                                       1,
80                                       gpl,
81                                       gps,
82                                       mmd->flag & GP_OPACITY_INVERT_LAYER,
83                                       mmd->flag & GP_OPACITY_INVERT_PASS,
84                                       mmd->flag & GP_OPACITY_INVERT_LAYERPASS)) {
85     return;
86   }
87
88   if (mmd->modify_color != GP_MODIFY_COLOR_FILL) {
89     gps->runtime.tmp_stroke_rgba[3] *= mmd->factor;
90     /* if factor is > 1, then force opacity */
91     if (mmd->factor > 1.0f) {
92       gps->runtime.tmp_stroke_rgba[3] += mmd->factor - 1.0f;
93     }
94     CLAMP(gps->runtime.tmp_stroke_rgba[3], 0.0f, 1.0f);
95   }
96
97   if (mmd->modify_color != GP_MODIFY_COLOR_STROKE) {
98     gps->runtime.tmp_fill_rgba[3] *= mmd->factor;
99     /* if factor is > 1, then force opacity */
100     if (mmd->factor > 1.0f && gps->runtime.tmp_fill_rgba[3] > 1e-5) {
101       gps->runtime.tmp_fill_rgba[3] += mmd->factor - 1.0f;
102     }
103     CLAMP(gps->runtime.tmp_fill_rgba[3], 0.0f, 1.0f);
104   }
105
106   /* if opacity > 1.0, affect the strength of the stroke */
107   if (mmd->factor > 1.0f) {
108     for (int i = 0; i < gps->totpoints; i++) {
109       bGPDspoint *pt = &gps->points[i];
110       MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
111
112       /* verify vertex group */
113       const float weight = get_modifier_point_weight(
114           dvert, (mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0, def_nr);
115       if (weight < 0.0f) {
116         pt->strength += mmd->factor - 1.0f;
117       }
118       else {
119         pt->strength += (mmd->factor - 1.0f) * weight;
120       }
121       CLAMP(pt->strength, 0.0f, 1.0f);
122     }
123   }
124 }
125
126 static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob)
127 {
128   OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md;
129   bGPdata *gpd = ob->data;
130
131   GHash *gh_color = BLI_ghash_str_new("GP_Opacity modifier");
132   for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
133     for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
134       for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
135
136         Material *mat = give_current_material(ob, gps->mat_nr + 1);
137         if (mat == NULL) {
138           continue;
139         }
140         MaterialGPencilStyle *gp_style = mat->gp_style;
141         /* skip stroke if it doesn't have color info */
142         if (ELEM(NULL, gp_style)) {
143           continue;
144         }
145
146         copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
147         copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
148
149         deformStroke(md, depsgraph, ob, gpl, gps);
150
151         gpencil_apply_modifier_material(
152             bmain, ob, mat, gh_color, gps, (bool)(mmd->flag & GP_OPACITY_CREATE_COLORS));
153       }
154     }
155   }
156   /* free hash buffers */
157   if (gh_color) {
158     BLI_ghash_free(gh_color, NULL, NULL);
159     gh_color = NULL;
160   }
161 }
162
163 GpencilModifierTypeInfo modifierType_Gpencil_Opacity = {
164     /* name */ "Opacity",
165     /* structName */ "OpacityGpencilModifierData",
166     /* structSize */ sizeof(OpacityGpencilModifierData),
167     /* type */ eGpencilModifierTypeType_Gpencil,
168     /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
169
170     /* copyData */ copyData,
171
172     /* deformStroke */ deformStroke,
173     /* generateStrokes */ NULL,
174     /* bakeModifier */ bakeModifier,
175     /* remapTime */ NULL,
176
177     /* initData */ initData,
178     /* freeData */ NULL,
179     /* isDisabled */ NULL,
180     /* updateDepsgraph */ NULL,
181     /* dependsOnTime */ NULL,
182     /* foreachObjectLink */ NULL,
183     /* foreachIDLink */ NULL,
184     /* foreachTexLink */ NULL,
185     /* getDuplicationFactor */ NULL,
186 };