GP: Refactor drawing engine to single VBO
[blender.git] / source / blender / gpencil_modifiers / intern / MOD_gpencilmirror.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software  Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2018, Blender Foundation
19  * This is a new part of Blender
20  *
21  * Contributor(s): Antonio Vazquez
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  *
25  */
26
27 /** \file blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
28  *  \ingroup modifiers
29  */
30
31 #include <stdio.h>
32
33 #include "DNA_meshdata_types.h"
34 #include "DNA_scene_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_gpencil_types.h"
37 #include "DNA_gpencil_modifier_types.h"
38
39 #include "BLI_listbase.h"
40 #include "BLI_math.h"
41 #include "BLI_utildefines.h"
42
43 #include "BKE_context.h"
44 #include "BKE_deform.h"
45 #include "BKE_gpencil.h"
46 #include "BKE_gpencil_modifier.h"
47 #include "BKE_modifier.h"
48 #include "BKE_library_query.h"
49 #include "BKE_scene.h"
50 #include "BKE_main.h"
51 #include "BKE_layer.h"
52
53 #include "MEM_guardedalloc.h"
54
55 #include "MOD_gpencil_util.h"
56 #include "MOD_gpencil_modifiertypes.h"
57
58 #include "DEG_depsgraph.h"
59 #include "DEG_depsgraph_build.h"
60 #include "DEG_depsgraph_query.h"
61
62 static void initData(GpencilModifierData *md)
63 {
64         MirrorGpencilModifierData *gpmd = (MirrorGpencilModifierData *)md;
65         gpmd->pass_index = 0;
66         gpmd->layername[0] = '\0';
67         gpmd->object = NULL;
68         gpmd->flag |= GP_MIRROR_AXIS_X;
69 }
70
71 static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
72 {
73         BKE_gpencil_modifier_copyData_generic(md, target);
74 }
75
76 static void update_position(Object *ob, MirrorGpencilModifierData *mmd, bGPDstroke *gps, int axis)
77 {
78         int i;
79         bGPDspoint *pt;
80         float factor[3] = { 1.0f, 1.0f, 1.0f };
81         factor[axis] = -1.0f;
82
83         float clear[3] = { 0.0f, 0.0f, 0.0f };
84         clear[axis] = 1.0f;
85
86         float origin[3];
87         float mirror_origin[3];
88
89         copy_v3_v3(origin, ob->loc);
90         /* only works with current axis */
91         mul_v3_v3(origin, clear);
92         zero_v3(mirror_origin);
93
94         if (mmd->object) {
95                 copy_v3_v3(mirror_origin, mmd->object->loc);
96                 mul_v3_v3(mirror_origin, clear);
97                 sub_v3_v3(origin, mirror_origin);
98         }
99         /* clear other axis */
100         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
101                 add_v3_v3(&pt->x, origin);
102                 mul_v3_v3(&pt->x, factor);
103                 add_v3_v3(&pt->x, mirror_origin);
104         }
105
106 }
107
108 /* Generic "generateStrokes" callback */
109 static void generateStrokes(
110         GpencilModifierData *md, Depsgraph *UNUSED(depsgraph),
111         Object *ob, bGPDlayer *gpl, bGPDframe *gpf)
112 {
113         MirrorGpencilModifierData *mmd = (MirrorGpencilModifierData *)md;
114         bGPDstroke *gps, *gps_new = NULL;
115         int tot_strokes;
116         int i;
117
118         /* check each axis for mirroring */
119         for (int xi = 0; xi < 3; ++xi) {
120                 if (mmd->flag & (GP_MIRROR_AXIS_X << xi)) {
121
122                         /* count strokes to avoid infinite loop after adding new strokes to tail of listbase */
123                         tot_strokes = BLI_listbase_count(&gpf->strokes);
124
125                         for (i = 0, gps = gpf->strokes.first; i < tot_strokes; i++, gps = gps->next) {
126                                 if (is_stroke_affected_by_modifier(
127                                             ob, mmd->layername, mmd->pass_index, mmd->layer_pass,
128                                             1, gpl, gps,
129                                             mmd->flag & GP_MIRROR_INVERT_LAYER,
130                                             mmd->flag & GP_MIRROR_INVERT_PASS,
131                                             mmd->flag & GP_MIRROR_INVERT_LAYERPASS))
132                                 {
133                                         gps_new = BKE_gpencil_stroke_duplicate(gps);
134                                         update_position(ob, mmd, gps_new, xi);
135                                         BLI_addtail(&gpf->strokes, gps_new);
136                                 }
137                         }
138                 }
139         }
140 }
141
142 static void bakeModifier(
143         Main *bmain, Depsgraph *depsgraph,
144         GpencilModifierData *md, Object *ob)
145 {
146         Scene *scene = DEG_get_evaluated_scene(depsgraph);
147         bGPdata *gpd = ob->data;
148         int oldframe = (int)DEG_get_ctime(depsgraph);
149
150         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
151                 for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
152                         /* apply mirror effects on this frame */
153                         CFRA = gpf->framenum;
154                         BKE_scene_graph_update_for_newframe(depsgraph, bmain);
155
156                         /* compute mirror effects on this frame */
157                         generateStrokes(md, depsgraph, ob, gpl, gpf);
158                 }
159         }
160
161         /* return frame state and DB to original state */
162         CFRA = oldframe;
163         BKE_scene_graph_update_for_newframe(depsgraph, bmain);
164 }
165
166 static bool isDisabled(GpencilModifierData *UNUSED(md), int UNUSED(userRenderParams))
167 {
168         //MirrorGpencilModifierData *mmd = (MirrorGpencilModifierData *)md;
169
170         return false;
171 }
172
173 static void updateDepsgraph(GpencilModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
174 {
175         MirrorGpencilModifierData *lmd = (MirrorGpencilModifierData *)md;
176         if (lmd->object != NULL) {
177                 DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_GEOMETRY, "Mirror Modifier");
178                 DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_TRANSFORM, "Mirror Modifier");
179         }
180         DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Mirror Modifier");
181 }
182
183 static void foreachObjectLink(
184         GpencilModifierData *md, Object *ob,
185         ObjectWalkFunc walk, void *userData)
186 {
187         MirrorGpencilModifierData *mmd = (MirrorGpencilModifierData *)md;
188
189         walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
190 }
191
192 static int getDuplicationFactor(GpencilModifierData *md)
193 {
194         MirrorGpencilModifierData *mmd = (MirrorGpencilModifierData *)md;
195         int factor = 1;
196         /* create a duplication for each axis */
197         for (int xi = 0; xi < 3; ++xi) {
198                 if (mmd->flag & (GP_MIRROR_AXIS_X << xi)) {
199                         factor++;
200                 }
201         }
202         CLAMP_MIN(factor, 1);
203
204         return factor;
205 }
206
207 GpencilModifierTypeInfo modifierType_Gpencil_Mirror = {
208         /* name */              "Mirror",
209         /* structName */        "MirrorGpencilModifierData",
210         /* structSize */        sizeof(MirrorGpencilModifierData),
211         /* type */              eGpencilModifierTypeType_Gpencil,
212         /* flags */             eGpencilModifierTypeFlag_SupportsEditmode,
213
214         /* copyData */          copyData,
215
216         /* deformStroke */      NULL,
217         /* generateStrokes */   generateStrokes,
218         /* bakeModifier */      bakeModifier,
219         /* remapTime */         NULL,
220
221         /* initData */          initData,
222         /* freeData */          NULL,
223         /* isDisabled */        isDisabled,
224         /* updateDepsgraph */   updateDepsgraph,
225         /* dependsOnTime */     NULL,
226         /* foreachObjectLink */ foreachObjectLink,
227         /* foreachIDLink */     NULL,
228         /* foreachTexLink */    NULL,
229         /* getDuplicationFactor */ getDuplicationFactor,
230 };