Blender  V2.93
lineart_ops.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  * The Original Code is Copyright (C) 2019 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <stdlib.h>
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "BLI_linklist.h"
29 #include "BLI_math.h"
30 #include "BLI_utildefines.h"
31 
32 #include "BKE_context.h"
33 #include "BKE_global.h"
34 #include "BKE_gpencil.h"
35 #include "BKE_gpencil_modifier.h"
36 #include "BKE_report.h"
37 #include "BKE_scene.h"
38 
39 #include "DEG_depsgraph_query.h"
40 
41 #include "WM_api.h"
42 #include "WM_types.h"
43 
45 #include "DNA_gpencil_types.h"
46 #include "DNA_scene_types.h"
47 
48 #include "MOD_gpencil_lineart.h"
49 #include "MOD_lineart.h"
50 
52 {
54 
56 
58 
59  /* Toggle on and off the baked flag as we are only interested in if something else is disabling
60  * it. We can assume that the guard function has already toggled this on for all modifiers that
61  * are sent here. */
62  lmd->flags &= (~LRT_GPENCIL_IS_BAKED);
63  bool disabled = info->isDisabled(md, 0);
65 
66  return disabled;
67 }
68 
69 static void clear_strokes(Object *ob, GpencilModifierData *md, int frame)
70 {
72  return;
73  }
75  bGPdata *gpd = ob->data;
76 
78  if (!gpl) {
79  return;
80  }
81  bGPDframe *gpf = BKE_gpencil_layer_frame_find(gpl, frame);
82 
83  if (!gpf) {
84  /* No greasepencil frame found. */
85  return;
86  }
87 
89 }
90 
91 static bool bake_strokes(Object *ob, Depsgraph *dg, GpencilModifierData *md, int frame)
92 {
93  /* Modifier data sanity check. */
94  if (lineart_mod_is_disabled(md)) {
95  return false;
96  }
97 
99  bGPdata *gpd = ob->data;
100 
102  if (!gpl) {
103  return false;
104  }
105  bool only_use_existing_gp_frames = false;
106  bGPDframe *gpf = (only_use_existing_gp_frames ?
107  BKE_gpencil_layer_frame_find(gpl, frame) :
109 
110  if (!gpf) {
111  /* No greasepencil frame created or found. */
112  return false;
113  }
114 
116 
118  lmd->render_buffer,
119  dg,
120  ob,
121  gpl,
122  gpf,
123  lmd->source_type,
124  lmd->source_type == LRT_SOURCE_OBJECT ? (void *)lmd->source_object :
125  (void *)lmd->source_collection,
126  lmd->level_start,
127  lmd->use_multiple_levels ? lmd->level_end : lmd->level_start,
129  lmd->edge_types,
130  lmd->transparency_flags,
131  lmd->transparency_mask,
132  lmd->thickness,
133  lmd->opacity,
134  lmd->source_vertex_group,
135  lmd->vgname,
136  lmd->flags);
137 
139 
140  return true;
141 }
142 
143 typedef struct LineartBakeJob {
145  void *owner;
146  short *stop, *do_update;
147  float *progress;
148 
149  /* C or ob must have one != NULL. */
154  int frame;
161 
163 {
164  bool touched = false;
165  if (ob->type != OB_GPENCIL || G.is_break) {
166  return false;
167  }
168 
169  if (bj->overwrite_frames) {
171  if (md->type == eGpencilModifierType_Lineart) {
172  clear_strokes(ob, md, frame);
173  }
174  }
175  }
176 
178  if (md->type != eGpencilModifierType_Lineart) {
179  continue;
180  }
181  if (bake_strokes(ob, bj->dg, md, frame)) {
182  touched = true;
183  }
184  }
185 
186  return touched;
187 }
188 
190 {
191  for (LinkNode *l = bj->objects; l; l = l->next) {
192  Object *ob = l->link;
194  if (md->type == eGpencilModifierType_Lineart) {
196  lmd->flags |= LRT_GPENCIL_IS_BAKED;
197  }
198  }
199  }
200 }
201 
202 static void lineart_gpencil_bake_startjob(void *customdata,
203  short *stop,
204  short *do_update,
205  float *progress)
206 {
207  LineartBakeJob *bj = (LineartBakeJob *)customdata;
208  bj->stop = stop;
209  bj->do_update = do_update;
210  bj->progress = progress;
211 
213 
214  for (int frame = bj->frame_begin; frame <= bj->frame_end; frame += bj->frame_increment) {
215 
216  if (G.is_break) {
217  G.is_break = false;
218  break;
219  }
220 
221  BKE_scene_frame_set(bj->scene, frame);
223 
224  for (LinkNode *l = bj->objects; l; l = l->next) {
225  Object *ob = l->link;
226  if (lineart_gpencil_bake_single_target(bj, ob, frame)) {
229  }
230  }
231 
232  /* Update and refresh the progress bar. */
233  *bj->progress = (float)(frame - bj->frame_begin) / (bj->frame_end - bj->frame_begin);
234  *bj->do_update = true;
235  }
236 
237  /* This need to be reset manually. */
238  G.is_break = false;
239 
240  /* Restore original frame. */
243 }
244 
245 static void lineart_gpencil_bake_endjob(void *customdata)
246 {
247  LineartBakeJob *bj = customdata;
248 
250 
252 
253  for (LinkNode *l = bj->objects; l; l = l->next) {
255  }
256 
258 }
259 
261  wmOperator *op,
262  bool bake_all_targets,
263  bool do_background)
264 {
265  LineartBakeJob *bj = MEM_callocN(sizeof(LineartBakeJob), "LineartBakeJob");
266 
267  if (!bake_all_targets) {
269  if (!ob || ob->type != OB_GPENCIL) {
270  WM_report(RPT_ERROR, "No active object or active object isn't a GPencil object.");
271  return OPERATOR_FINISHED;
272  }
273  BLI_linklist_prepend(&bj->objects, ob);
274  }
275  else {
276  /* #CTX_DATA_BEGIN is not available for iterating in objects while using the job system. */
277  CTX_DATA_BEGIN (C, Object *, ob, visible_objects) {
278  if (ob->type == OB_GPENCIL) {
279  LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
280  if (md->type == eGpencilModifierType_Lineart) {
281  BLI_linklist_prepend(&bj->objects, ob);
282  break;
283  }
284  }
285  }
286  }
287  CTX_DATA_END;
288  }
289  bj->C = C;
291  bj->scene = scene;
293  bj->frame_begin = scene->r.sfra;
294  bj->frame_end = scene->r.efra;
295  bj->frame_orig = scene->r.cfra;
297  bj->overwrite_frames = true;
298 
299  if (do_background) {
300  wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
301  CTX_wm_window(C),
302  scene,
303  "Line Art",
306 
307  WM_jobs_customdata_set(wm_job, bj, MEM_freeN);
311 
313 
314  WM_jobs_start(CTX_wm_manager(C), wm_job);
315 
317 
318  return OPERATOR_RUNNING_MODAL;
319  }
320 
321  float pseduo_progress;
322  short pseduo_do_update;
323  lineart_gpencil_bake_startjob(bj, NULL, &pseduo_do_update, &pseduo_progress);
324 
326  MEM_freeN(bj);
327 
328  return OPERATOR_FINISHED;
329 }
330 
332  wmOperator *op,
333  const wmEvent *UNUSED(event))
334 {
335  return lineart_gpencil_bake_common(C, op, true, true);
336 }
338 {
339  return lineart_gpencil_bake_common(C, op, true, false);
340 }
342  wmOperator *op,
343  const wmEvent *UNUSED(event))
344 {
345  return lineart_gpencil_bake_common(C, op, false, true);
346 }
348 {
349  return lineart_gpencil_bake_common(C, op, false, false);
350 }
352  wmOperator *op,
353  const wmEvent *UNUSED(event))
354 {
355  Scene *scene = (Scene *)op->customdata;
356 
357  /* no running blender, remove handler and pass through. */
360  }
361 
362  return OPERATOR_PASS_THROUGH;
363 }
364 
366 {
367  /* TODO: move these checks to an operator poll function. */
368  if ((ob == NULL) || ob->type != OB_GPENCIL) {
369  return;
370  }
372  if (md->type != eGpencilModifierType_Lineart) {
373  continue;
374  }
376  bGPdata *gpd = ob->data;
377 
379  if (!gpl) {
380  continue;
381  }
383  BKE_gpencil_frame_addnew(gpl, 0);
384 
386 
387  lmd->flags &= (~LRT_GPENCIL_IS_BAKED);
388  }
390 }
391 
393 {
395 
397 
399 
400  return OPERATOR_FINISHED;
401 }
403 {
404  CTX_DATA_BEGIN (C, Object *, ob, visible_objects) {
407  }
408  CTX_DATA_END;
409 
410  BKE_report(op->reports, RPT_INFO, "All line art objects are now cleared");
411 
412  return OPERATOR_FINISHED;
413 }
414 
415 /* Bake all line art modifiers on the current object. */
417 {
418  ot->name = "Bake Line Art";
419  ot->description = "Bake Line Art for current GPencil object";
420  ot->idname = "OBJECT_OT_lineart_bake_strokes";
421 
425 }
426 
427 /* Bake all lineart objects in the scene. */
429 {
430  ot->name = "Bake Line Art (All)";
431  ot->description = "Bake all Grease Pencil objects that have a line art modifier";
432  ot->idname = "OBJECT_OT_lineart_bake_strokes_all";
433 
437 }
438 
439 /* clear all line art modifiers on the current object. */
441 {
442  ot->name = "Clear Baked Line Art";
443  ot->description = "Clear all strokes in current GPencil object";
444  ot->idname = "OBJECT_OT_lineart_clear";
445 
447 }
448 
449 /* clear all lineart objects in the scene. */
451 {
452  ot->name = "Clear Baked Line Art (All)";
453  ot->description = "Clear all strokes in all Grease Pencil objects that have a line art modifier";
454  ot->idname = "OBJECT_OT_lineart_clear_all";
455 
457 }
458 
460 {
465 }
typedef float(TangentPoint)[2]
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:689
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:252
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1279
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1401
#define CTX_DATA_END
Definition: BKE_context.h:260
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
struct bGPDframe * BKE_gpencil_frame_addnew(struct bGPDlayer *gpl, int cframe)
Definition: gpencil.c:539
void BKE_gpencil_free_frames(struct bGPDlayer *gpl)
Definition: gpencil.c:439
bool BKE_gpencil_layer_frame_delete(struct bGPDlayer *gpl, struct bGPDframe *gpf)
Definition: gpencil.c:1467
int BKE_gpencil_object_material_index_get(struct Object *ob, struct Material *ma)
Definition: gpencil.c:2437
struct bGPDframe * BKE_gpencil_layer_frame_find(struct bGPDlayer *gpl, int cframe)
Definition: gpencil.c:1281
struct bGPDlayer * BKE_gpencil_layer_get_by_name(struct bGPdata *gpd, char *name, int first_if_not_found)
Definition: gpencil.c:1668
struct bGPDframe * BKE_gpencil_layer_frame_get(struct bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
Definition: gpencil.c:1307
@ GP_GETFRAME_ADD_NEW
Definition: BKE_gpencil.h:190
const GpencilModifierTypeInfo * BKE_gpencil_modifier_get_info(GpencilModifierType type)
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
void BKE_scene_frame_set(struct Scene *scene, double cfra)
Definition: scene.c:2475
void BKE_scene_graph_update_for_newframe(struct Depsgraph *depsgraph)
Definition: scene.c:2794
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
#define UNUSED(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
@ eGpencilModifierMode_Render
@ eGpencilModifierMode_Realtime
@ eGpencilModifierType_Lineart
@ OB_GPENCIL
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:39
@ WM_JOB_TYPE_LINEART
Definition: WM_api.h:758
@ WM_JOB_PROGRESS
Definition: WM_api.h:726
#define ND_DATA
Definition: WM_types.h:408
#define NC_SCENE
Definition: WM_types.h:279
#define NA_EDITED
Definition: WM_types.h:462
#define ND_FRAME
Definition: WM_types.h:334
#define NC_GPENCIL
Definition: WM_types.h:300
ATTR_WARN_UNUSED_RESULT const BMLoop * l
Scene scene
void MOD_lineart_destroy_render_data(LineartGpencilModifierData *lmd)
Definition: lineart_cpu.c:2629
bool MOD_lineart_compute_feature_lines(Depsgraph *depsgraph, LineartGpencilModifierData *lmd)
Definition: lineart_cpu.c:3651
void MOD_lineart_gpencil_generate(LineartRenderBuffer *rb, Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, bGPDframe *gpf, char source_type, void *source_reference, int level_start, int level_end, int mat_nr, short edge_types, uchar transparency_flags, uchar transparency_mask, short thickness, float opacity, const char *source_vgname, const char *vgname, int modifier_flags)
Definition: lineart_cpu.c:3932
static bool lineart_mod_is_disabled(GpencilModifierData *md)
Definition: lineart_ops.c:51
void OBJECT_OT_lineart_bake_strokes_all(wmOperatorType *ot)
Definition: lineart_ops.c:428
static int lineart_gpencil_bake_strokes_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: lineart_ops.c:331
static int lineart_gpencil_clear_strokes_exec(bContext *C, wmOperator *UNUSED(op))
Definition: lineart_ops.c:392
static void lineart_gpencil_bake_endjob(void *customdata)
Definition: lineart_ops.c:245
void OBJECT_OT_lineart_bake_strokes(wmOperatorType *ot)
Definition: lineart_ops.c:416
static void lineart_gpencil_guard_modifiers(LineartBakeJob *bj)
Definition: lineart_ops.c:189
static int lineart_gpencil_bake_strokes_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: lineart_ops.c:341
void OBJECT_OT_lineart_clear_all(wmOperatorType *ot)
Definition: lineart_ops.c:450
void OBJECT_OT_lineart_clear(wmOperatorType *ot)
Definition: lineart_ops.c:440
static int lineart_gpencil_clear_strokes_all_exec(bContext *C, wmOperator *op)
Definition: lineart_ops.c:402
static int lineart_gpencil_bake_strokes_exec(bContext *C, wmOperator *op)
Definition: lineart_ops.c:347
static bool lineart_gpencil_bake_single_target(LineartBakeJob *bj, Object *ob, int frame)
Definition: lineart_ops.c:162
static void lineart_gpencil_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
Definition: lineart_ops.c:202
static int lineart_gpencil_bake_common(bContext *C, wmOperator *op, bool bake_all_targets, bool do_background)
Definition: lineart_ops.c:260
void WM_operatortypes_lineart(void)
Definition: lineart_ops.c:459
static int lineart_gpencil_bake_strokes_all_exec(bContext *C, wmOperator *op)
Definition: lineart_ops.c:337
static int lineart_gpencil_bake_strokes_commom_modal(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: lineart_ops.c:351
static void lineart_gpencil_clear_strokes_exec_common(Object *ob)
Definition: lineart_ops.c:365
struct LineartBakeJob LineartBakeJob
static bool bake_strokes(Object *ob, Depsgraph *dg, GpencilModifierData *md, int frame)
Definition: lineart_ops.c:91
static void clear_strokes(Object *ob, GpencilModifierData *md, int frame)
Definition: lineart_ops.c:69
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
struct BMLoop * next
Definition: bmesh_class.h:245
bool(* isDisabled)(struct GpencilModifierData *md, int userRenderParams)
Definition: DNA_ID.h:273
LinkNode * objects
Definition: lineart_ops.c:151
Depsgraph * dg
Definition: lineart_ops.c:153
float * progress
Definition: lineart_ops.c:147
bool overwrite_frames
Definition: lineart_ops.c:159
wmWindowManager * wm
Definition: lineart_ops.c:144
bContext * C
Definition: lineart_ops.c:150
short * do_update
Definition: lineart_ops.c:146
ListBase greasepencil_modifiers
void * data
struct RenderData r
Definition: wm_jobs.c:73
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
struct ReportList * reports
#define G(x, y, z)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_report(ReportType type, const char *message)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
void WM_set_locked_interface(wmWindowManager *wm, bool lock)
wmOperatorType * ot
Definition: wm_files.c:3156
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition: wm_jobs.c:450
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, const char *name, int flag, int job_type)
Definition: wm_jobs.c:196
bool WM_jobs_test(wmWindowManager *wm, void *owner, int job_type)
Definition: wm_jobs.c:223
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
Definition: wm_jobs.c:372
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *))
Definition: wm_jobs.c:344
void WM_jobs_timer(wmJob *wm_job, double timestep, unsigned int note, unsigned int endnote)
Definition: wm_jobs.c:360
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))