Blender V4.3
grease_pencil_trace.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BKE_attribute.hh"
6#include "BKE_context.hh"
7#include "BKE_curves.hh"
8#include "BKE_global.hh"
10#include "BKE_image.hh"
11#include "BKE_layer.hh"
12#include "BKE_lib_id.hh"
13#include "BKE_material.h"
14#include "BKE_object.hh"
15#include "BKE_report.hh"
16
17#include "BLI_math_matrix.hh"
18#include "BLI_math_vector.h"
19#include "BLI_math_vector.hh"
20
21#include "BLI_task.hh"
22#include "BLT_translation.hh"
23
24#include "DEG_depsgraph.hh"
26
27#include "DNA_curves_types.h"
29#include "DNA_material_types.h"
30#include "DNA_object_types.h"
31
32#include "IMB_imbuf_types.hh"
33
34#include "ED_grease_pencil.hh"
35#include "ED_numinput.hh"
36#include "ED_object.hh"
37#include "ED_screen.hh"
38
39#include "MEM_guardedalloc.h"
40
41#include "RNA_access.hh"
42#include "RNA_define.hh"
43
45
47
48/* -------------------------------------------------------------------- */
51
53
54/* Target object modes. */
56 New = 0,
58};
59
60enum class TraceMode : int8_t {
61 Single = 0,
63};
64
65#ifdef WITH_POTRACE
66
67struct TraceJob {
68 /* from wmJob */
69 Object *owner;
70 bool *stop, *do_update;
71 float *progress;
72
73 bContext *C;
75 Main *bmain;
76 Scene *scene;
77 View3D *v3d;
78 Base *base_active;
79 Object *ob_active;
80 Image *image;
81 Object *ob_grease_pencil;
83
84 Array<bke::CurvesGeometry> traced_curves;
85
86 bool was_ob_created;
87 bool use_current_frame;
88
89 /* Frame number where the output frame is generated. */
90 int frame_target;
91 float threshold;
92 float radius;
93 TurnPolicy turnpolicy;
94 TraceMode mode;
95 /* Custom source frame, allows overriding the default scene frame. */
96 int frame_number;
97
98 bool success;
99 bool was_canceled;
100
101 void ensure_output_object();
102};
103
104void TraceJob::ensure_output_object()
105{
106 using namespace blender::bke::greasepencil;
107
108 /* Create a new grease pencil object. */
109 if (this->ob_grease_pencil == nullptr) {
110 const ushort local_view_bits = (this->v3d && this->v3d->localvd) ? this->v3d->local_view_uid :
111 0;
112
113 /* Copy transform from the active object. */
114 this->ob_grease_pencil = ed::object::add_type(this->C,
116 nullptr,
117 this->ob_active->loc,
118 this->ob_active->rot,
119 false,
120 local_view_bits);
121 copy_v3_v3(this->ob_grease_pencil->scale, this->ob_active->scale);
122 this->was_ob_created = true;
123 }
124
125 /* Create Layer. */
126 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(this->ob_grease_pencil->data);
127 this->layer = grease_pencil.get_active_layer();
128 if (this->layer == nullptr) {
129 Layer &new_layer = grease_pencil.add_layer(DATA_("Trace"));
130 grease_pencil.set_active_layer(&new_layer);
131 this->layer = &new_layer;
132 }
133}
134
135static float4x4 pixel_to_object_transform(const Object &image_object,
136 const ImBuf &ibuf,
137 const float2 pixel_center = float2(0.5f))
138{
139 const float3 pixel_center_3d = float3(pixel_center.x, pixel_center.y, 0);
140 const float3 pixel_size_3d = math::safe_rcp(float3(ibuf.x, ibuf.y, 0));
141 const float3 image_offset_3d = float3(image_object.ima_ofs[0], image_object.ima_ofs[1], 0);
142 const float max_image_scale = image_object.empty_drawsize;
143 const float3 image_aspect_3d = (ibuf.x > ibuf.y ? float3(1, float(ibuf.y) / float(ibuf.x), 1) :
144 float3(float(ibuf.x) / float(ibuf.y), 1, 1));
145
146 const float4x4 to_object = math::translate(
147 math::from_scale<float4x4>(image_aspect_3d * max_image_scale), image_offset_3d);
148 const float4x4 to_normalized = math::translate(math::scale(to_object, pixel_size_3d),
149 pixel_center_3d);
150 return to_normalized;
151}
152
153static int ensure_foreground_material(Main *bmain, Object *ob, const StringRefNull name)
154{
156 if (index == -1) {
157 Material &ma = *BKE_grease_pencil_object_material_new(bmain, ob, name.c_str(), &index);
158 copy_v4_v4(ma.gp_style->stroke_rgba, float4(0, 0, 0, 1));
161 }
162 return index;
163}
164
165static int ensure_background_material(Main *bmain, Object *ob, const StringRefNull name)
166{
168 if (index == -1) {
169 Material &ma = *BKE_grease_pencil_object_material_new(bmain, ob, name.c_str(), &index);
170 copy_v4_v4(ma.gp_style->stroke_rgba, float4(0, 0, 0, 1));
171 copy_v4_v4(ma.gp_style->fill_rgba, float4(0, 0, 0, 1));
176 }
177 return index;
178}
179
180static bke::CurvesGeometry grease_pencil_trace_image(TraceJob &trace_job, const ImBuf &ibuf)
181{
182 /* Trace the image.
183 * Note: Colors above threshold are interpreted as "background". This works well for images with
184 * black-on-white drawings, but is quite arbitrary. */
185 potrace_bitmap_t *bm = image_trace::image_to_bitmap(ibuf, [&](const ColorGeometry4f &color) {
186 return math::average(float3(color.r, color.g, color.b)) * color.a <= trace_job.threshold;
187 });
188
189 image_trace::TraceParams params;
190 params.size_threshold = 0;
191 params.turn_policy = trace_job.turnpolicy;
192 image_trace::Trace *trace = image_trace::trace_bitmap(params, *bm);
194
195 /* Attribute ID for which curves are "holes" with a negative trace sign. */
196 const StringRef hole_attribute_id = "is_hole";
197
198 /* Transform from bitmap index space to local image object space. */
199 const float4x4 transform = pixel_to_object_transform(*trace_job.ob_active, ibuf);
200 bke::CurvesGeometry trace_curves = image_trace::trace_to_curves(
201 *trace, hole_attribute_id, transform);
203
204 /* Assign different materials to foreground curves and hole curves. */
205 bke::MutableAttributeAccessor attributes = trace_curves.attributes_for_write();
206 const int material_fg = ensure_foreground_material(
207 trace_job.bmain, trace_job.ob_grease_pencil, "Stroke");
208 const int material_bg = ensure_background_material(
209 trace_job.bmain, trace_job.ob_grease_pencil, "Holdout");
210 const VArraySpan<bool> holes = *attributes.lookup<bool>(hole_attribute_id);
211 bke::SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_span<int>(
212 "material_index", bke::AttrDomain::Curve);
213 threading::parallel_for(trace_curves.curves_range(), 4096, [&](const IndexRange range) {
214 for (const int curve_i : range) {
215 const bool is_hole = holes[curve_i];
216 material_indices.span[curve_i] = (is_hole ? material_bg : material_fg);
217 }
218 });
219 material_indices.finish();
220 /* Remove hole attribute */
221 attributes.remove(hole_attribute_id);
222
223 /* Uniform radius for all trace curves. */
224 bke::SpanAttributeWriter<float> radii = attributes.lookup_or_add_for_write_only_span<float>(
225 "radius", bke::AttrDomain::Point);
226 radii.span.fill(trace_job.radius);
227 radii.finish();
228
229 return trace_curves;
230}
231
232static void trace_start_job(void *customdata, wmJobWorkerStatus *worker_status)
233{
234 TraceJob &trace_job = *static_cast<TraceJob *>(customdata);
235
236 trace_job.stop = &worker_status->stop;
237 trace_job.do_update = &worker_status->do_update;
238 trace_job.progress = &worker_status->progress;
239 trace_job.was_canceled = false;
240 const int init_frame = std::max((trace_job.use_current_frame) ? trace_job.frame_target : 0, 0);
241
242 G.is_break = false;
243
244 /* Single Image. */
245 if (trace_job.image->source == IMA_SRC_FILE || trace_job.mode == TraceMode::Single) {
246 ImageUser &iuser = *trace_job.ob_active->iuser;
247 trace_job.traced_curves.reinitialize(1);
248
249 iuser.framenr = ((trace_job.frame_number == 0) || (trace_job.frame_number > iuser.frames)) ?
250 init_frame :
251 trace_job.frame_number;
252 void *lock;
253 ImBuf *ibuf = BKE_image_acquire_ibuf(trace_job.image, &iuser, &lock);
254 if (ibuf) {
255 trace_job.traced_curves.first() = grease_pencil_trace_image(trace_job, *ibuf);
256 BKE_image_release_ibuf(trace_job.image, ibuf, lock);
257 *(trace_job.progress) = 1.0f;
258 }
259 }
260 /* Image sequence. */
261 else if (trace_job.image->type == IMA_TYPE_IMAGE) {
262 ImageUser &iuser = *trace_job.ob_active->iuser;
263 const int num_frames = iuser.frames - init_frame + 1;
264 trace_job.traced_curves.reinitialize(num_frames);
265 for (const int i : IndexRange(num_frames)) {
266 if (G.is_break) {
267 trace_job.was_canceled = true;
268 break;
269 }
270
271 const int frame_number = init_frame + i;
272 *(trace_job.progress) = float(frame_number) / float(iuser.frames);
273 worker_status->do_update = true;
274
275 iuser.framenr = frame_number;
276
277 void *lock;
278 ImBuf *ibuf = BKE_image_acquire_ibuf(trace_job.image, &iuser, &lock);
279 if (ibuf) {
280 trace_job.traced_curves[i] = grease_pencil_trace_image(trace_job, *ibuf);
281 BKE_image_release_ibuf(trace_job.image, ibuf, lock);
282 }
283 }
284 }
285
286 trace_job.success = !trace_job.was_canceled;
287 worker_status->do_update = true;
288 worker_status->stop = false;
289}
290
291static void trace_end_job(void *customdata)
292{
293 TraceJob &trace_job = *static_cast<TraceJob *>(customdata);
294 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(trace_job.ob_grease_pencil->data);
295
296 /* Update all the drawings once the job is done and we're executing in the main thread again.
297 * Changing drawing array or updating the drawing geometry is not thread-safe. */
298 switch (trace_job.mode) {
299 case TraceMode::Single: {
300 BLI_assert(trace_job.traced_curves.size() == 1);
301 bke::greasepencil::Drawing *drawing = grease_pencil.get_drawing_at(*trace_job.layer,
302 trace_job.frame_target);
303 if (drawing == nullptr) {
304 drawing = grease_pencil.insert_frame(*trace_job.layer, trace_job.frame_target);
305 }
306 BLI_assert(drawing != nullptr);
307 drawing->strokes_for_write() = trace_job.traced_curves.first();
308 drawing->tag_topology_changed();
309 break;
310 }
311 case TraceMode::Sequence: {
312 const ImageUser &iuser = *trace_job.ob_active->iuser;
313 const int init_frame = std::max((trace_job.use_current_frame) ? trace_job.frame_target : 0,
314 0);
315 const int num_frames = iuser.frames - init_frame + 1;
316 BLI_assert(trace_job.traced_curves.size() == num_frames);
317 for (const int i : IndexRange(num_frames)) {
318 const int frame_number = init_frame + i;
319 bke::greasepencil::Drawing *drawing = grease_pencil.get_drawing_at(*trace_job.layer,
320 frame_number);
321 if (drawing == nullptr) {
322 drawing = grease_pencil.insert_frame(*trace_job.layer, frame_number);
323 }
324 BLI_assert(drawing != nullptr);
325 drawing->strokes_for_write() = trace_job.traced_curves[i];
326 drawing->tag_topology_changed();
327 }
328 break;
329 }
330 }
331
332 /* If canceled, delete all previously created object and data-block. */
333 if ((trace_job.was_canceled) && (trace_job.was_ob_created) && (trace_job.ob_grease_pencil)) {
334 BKE_id_delete(trace_job.bmain, &trace_job.ob_grease_pencil->id);
335 BKE_id_delete(trace_job.bmain, &grease_pencil.id);
336 }
337
338 if (trace_job.success) {
339 DEG_relations_tag_update(trace_job.bmain);
340
341 DEG_id_tag_update(&trace_job.scene->id, ID_RECALC_SELECT);
343
345 WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, trace_job.scene);
346 }
347}
348
349static void trace_free_job(void *customdata)
350{
351 TraceJob *tj = static_cast<TraceJob *>(customdata);
352 MEM_delete(tj);
353}
354
355/* Trace Image to Grease Pencil. */
356static bool grease_pencil_trace_image_poll(bContext *C)
357{
359 if ((ob == nullptr) || (ob->type != OB_EMPTY) || (ob->data == nullptr)) {
360 CTX_wm_operator_poll_msg_set(C, "No image empty selected");
361 return false;
362 }
363
364 Image *image = static_cast<Image *>(ob->data);
366 CTX_wm_operator_poll_msg_set(C, "No valid image format selected");
367 return false;
368 }
369
370 return true;
371}
372
373static int grease_pencil_trace_image_exec(bContext *C, wmOperator *op)
374{
375 TraceJob *job = MEM_new<TraceJob>("TraceJob");
376 job->C = C;
377 job->owner = CTX_data_active_object(C);
378 job->wm = CTX_wm_manager(C);
379 job->bmain = CTX_data_main(C);
380 Scene *scene = CTX_data_scene(C);
381 job->scene = scene;
382 job->v3d = CTX_wm_view3d(C);
383 job->base_active = CTX_data_active_base(C);
384 job->ob_active = job->base_active->object;
385 job->image = static_cast<Image *>(job->ob_active->data);
386 job->frame_target = scene->r.cfra;
387 job->use_current_frame = RNA_boolean_get(op->ptr, "use_current_frame");
388
389 /* Create a new grease pencil object or reuse selected. */
390 const TargetObjectMode target = TargetObjectMode(RNA_enum_get(op->ptr, "target"));
391 job->ob_grease_pencil = (target == TargetObjectMode::Selected) ?
393 scene, CTX_data_view_layer(C), job->v3d) :
394 nullptr;
395
396 if (job->ob_grease_pencil != nullptr) {
397 if (job->ob_grease_pencil->type != OB_GREASE_PENCIL) {
398 BKE_report(op->reports, RPT_WARNING, "Target object not a grease pencil, ignoring!");
399 job->ob_grease_pencil = nullptr;
400 }
401 else if (BKE_object_obdata_is_libdata(job->ob_grease_pencil)) {
402 BKE_report(op->reports, RPT_WARNING, "Target object library-data, ignoring!");
403 job->ob_grease_pencil = nullptr;
404 }
405 }
406
407 job->was_ob_created = false;
408
409 job->threshold = RNA_float_get(op->ptr, "threshold");
410 job->radius = RNA_float_get(op->ptr, "radius");
411 job->turnpolicy = TurnPolicy(RNA_enum_get(op->ptr, "turnpolicy"));
412 job->mode = TraceMode(RNA_enum_get(op->ptr, "mode"));
413 job->frame_number = RNA_int_get(op->ptr, "frame_number");
414
415 job->ensure_output_object();
416
417 /* Back to active base. */
418 blender::ed::object::base_activate(job->C, job->base_active);
419
420 if ((job->image->source == IMA_SRC_FILE) || (job->frame_number > 0)) {
421 wmJobWorkerStatus worker_status = {};
422 trace_start_job(job, &worker_status);
423 trace_end_job(job);
424 trace_free_job(job);
425 }
426 else {
427 wmJob *wm_job = WM_jobs_get(job->wm,
429 job->scene,
430 "Trace Image",
433
434 WM_jobs_customdata_set(wm_job, job, trace_free_job);
435 WM_jobs_timer(wm_job, 0.1, NC_GEOM | ND_DATA, NC_GEOM | ND_DATA);
436 WM_jobs_callbacks(wm_job, trace_start_job, nullptr, nullptr, trace_end_job);
437
439 }
440
441 return OPERATOR_FINISHED;
442}
443
444static int grease_pencil_trace_image_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
445{
446 /* Show popup dialog to allow editing. */
447 /* FIXME: hard-coded dimensions here are just arbitrary. */
448 return WM_operator_props_dialog_popup(C, op, 250);
449}
450
451static void GREASE_PENCIL_OT_trace_image(wmOperatorType *ot)
452{
453 PropertyRNA *prop;
454
455 static const EnumPropertyItem turnpolicy_type[] = {
456 {int(TurnPolicy::Foreground),
457 "FOREGROUND",
458 0,
459 "Foreground",
460 "Prefers to connect foreground components"},
461 {int(TurnPolicy::Background),
462 "BACKGROUND",
463 0,
464 "Background",
465 "Prefers to connect background components"},
466 {int(TurnPolicy::Left), "LEFT", 0, "Left", "Always take a left turn"},
467 {int(TurnPolicy::Right), "RIGHT", 0, "Right", "Always take a right turn"},
468 {int(TurnPolicy::Minority),
469 "MINORITY",
470 0,
471 "Minority",
472 "Prefers to connect the color that occurs least frequently in the local "
473 "neighborhood of the current position"},
474 {int(TurnPolicy::Majority),
475 "MAJORITY",
476 0,
477 "Majority",
478 "Prefers to connect the color that occurs most frequently in the local "
479 "neighborhood of the current position"},
480 {int(TurnPolicy::Random), "RANDOM", 0, "Random", "Choose pseudo-randomly"},
481 {0, nullptr, 0, nullptr, nullptr},
482 };
483
484 static const EnumPropertyItem trace_modes[] = {
485 {int(TraceMode::Single), "SINGLE", 0, "Single", "Trace the current frame of the image"},
486 {int(TraceMode::Sequence), "SEQUENCE", 0, "Sequence", "Trace full sequence"},
487 {0, nullptr, 0, nullptr, nullptr},
488 };
489
490 static const EnumPropertyItem target_object_modes[] = {
491 {int(TargetObjectMode::New), "NEW", 0, "New Object", ""},
492 {int(TargetObjectMode::Selected), "SELECTED", 0, "Selected Object", ""},
493 {0, nullptr, 0, nullptr, nullptr},
494 };
495
496 /* identifiers */
497 ot->name = "Trace Image to Grease Pencil";
498 ot->idname = "GREASE_PENCIL_OT_trace_image";
499 ot->description = "Extract Grease Pencil strokes from image";
500
501 /* callbacks */
502 ot->invoke = grease_pencil_trace_image_invoke;
503 ot->exec = grease_pencil_trace_image_exec;
504 ot->poll = grease_pencil_trace_image_poll;
505
506 /* flags */
508
509 /* properties */
510 ot->prop = RNA_def_enum(ot->srna,
511 "target",
512 target_object_modes,
513 int(TargetObjectMode::New),
514 "Target Object",
515 "Target grease pencil");
517
518 RNA_def_float(ot->srna, "radius", 0.01f, 0.001f, 1.0f, "Radius", "", 0.001, 1.0f);
519
521 "threshold",
522 0.5f,
523 0.0f,
524 1.0f,
525 "Color Threshold",
526 "Determine the lightness threshold above which strokes are generated",
527 0.0f,
528 1.0f);
529 RNA_def_enum(ot->srna,
530 "turnpolicy",
531 turnpolicy_type,
532 int(TurnPolicy::Minority),
533 "Turn Policy",
534 "Determines how to resolve ambiguities during decomposition of bitmaps into paths");
535 RNA_def_enum(ot->srna,
536 "mode",
537 trace_modes,
538 int(TraceMode::Single),
539 "Mode",
540 "Determines if trace simple image or full sequence");
541 RNA_def_boolean(ot->srna,
542 "use_current_frame",
543 true,
544 "Start At Current Frame",
545 "Trace Image starting in current image frame");
546 prop = RNA_def_int(
547 ot->srna,
548 "frame_number",
549 0,
550 0,
551 9999,
552 "Trace Frame",
553 "Used to trace only one frame of the image sequence, set to zero to trace all",
554 0,
555 9999);
557}
558
559#endif
560
562
563} // namespace blender::ed::sculpt_paint::greasepencil
564
565/* -------------------------------------------------------------------- */
568
570{
572
573#ifdef WITH_POTRACE
574 WM_operatortype_append(GREASE_PENCIL_OT_trace_image);
575#endif
576}
577
void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
wmWindow * CTX_wm_window(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Base * CTX_data_active_base(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
Low-level operations for curves.
Low-level operations for grease pencil.
Material * BKE_grease_pencil_object_material_new(Main *bmain, Object *ob, const char *name, int *r_index)
int BKE_grease_pencil_object_material_index_get_by_name(Object *ob, const char *name)
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
Object * BKE_view_layer_non_active_selected_object(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
void BKE_id_delete(Main *bmain, void *idv) ATTR_NONNULL()
General operations, lookup, etc. for materials.
General operations, lookup, etc. for blender objects.
bool BKE_object_obdata_is_libdata(const Object *ob)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
unsigned short ushort
#define ELEM(...)
#define DATA_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
@ ID_RECALC_SELECT
Definition DNA_ID.h:1068
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1085
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
@ IMA_SRC_FILE
@ IMA_SRC_MOVIE
@ IMA_SRC_SEQUENCE
@ IMA_TYPE_IMAGE
struct Material Material
@ GP_MATERIAL_IS_STROKE_HOLDOUT
@ GP_MATERIAL_STROKE_SHOW
@ GP_MATERIAL_IS_FILL_HOLDOUT
@ GP_MATERIAL_FILL_SHOW
Object is a sort of wrapper for general info.
@ OB_EMPTY
@ OB_GREASE_PENCIL
struct Object Object
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
@ PROP_SKIP_SAVE
Definition RNA_types.hh:245
#define C
Definition RandGen.cpp:29
@ WM_JOB_TYPE_TRACE_IMAGE
Definition WM_api.hh:1605
@ WM_JOB_PROGRESS
Definition WM_api.hh:1566
#define NC_GEOM
Definition WM_types.hh:360
#define ND_OB_ACTIVE
Definition WM_types.hh:407
#define ND_DATA
Definition WM_types.hh:475
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define NC_SCENE
Definition WM_types.hh:345
#define NA_ADDED
Definition WM_types.hh:552
#define NC_OBJECT
Definition WM_types.hh:346
volatile int lock
ATTR_WARN_UNUSED_RESULT BMesh * bm
constexpr const char * c_str() const
GAttributeReader lookup(const StringRef attribute_id) const
IndexRange curves_range() const
MutableAttributeAccessor attributes_for_write()
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
bool remove(const StringRef attribute_id)
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
bke::CurvesGeometry & strokes_for_write()
input_tx image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img") .compute_source("compositor_compute_preview.glsl") .do_static_compilation(true)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void ED_operatortypes_grease_pencil_trace()
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define G(x, y, z)
void free_bitmap(Bitmap *bm)
Bitmap * image_to_bitmap(const ImBuf &ibuf, ThresholdFn fn)
bke::CurvesGeometry trace_to_curves(const Trace &trace, StringRef hole_attribute_id, const float4x4 &transform)
void free_trace(Trace *trace)
Trace * trace_bitmap(const TraceParams &params, Bitmap &bm)
Object * add_type(bContext *C, int type, const char *name, const float loc[3], const float rot[3], bool enter_editmode, unsigned short local_view_bits) ATTR_NONNULL(1) ATTR_RETURNS_NONNULL
void base_activate(bContext *C, Base *base)
T safe_rcp(const T &a)
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
T average(const VecBase< T, Size > &a)
MatT from_scale(const VecBase< typename MatT::base_type, ScaleDim > &scale)
MatBase< T, NumCol, NumRow > translate(const MatBase< T, NumCol, NumRow > &mat, const VectorT &translation)
void index(const bNode &, void *r_value)
void transform(Context &context, Result &input, Result &output, const float3x3 &transformation, RealizationOptions realization_options)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:95
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
VecBase< float, 2 > float2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:337
VecBase< float, 3 > float3
int RNA_int_get(PointerRNA *ptr, const char *name)
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_float_factor(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
signed char int8_t
Definition stdint.h:75
struct MaterialGPencilStyle * gp_style
float empty_drawsize
float ima_ofs[2]
struct RenderData r
struct ReportList * reports
struct PointerRNA * ptr
void WM_main_add_notifier(uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4125
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
Definition wm_jobs.cc:352
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:455
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, const eWM_JobFlag flag, const eWM_JobType job_type)
Definition wm_jobs.cc:189
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
Definition wm_jobs.cc:364
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
Definition wm_jobs.cc:336
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, std::optional< std::string > title, std::optional< std::string > confirm_text, const bool cancel_default)