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/* -------------------------------------------------------------------- */
53
54/* Target object modes. */
56 New = 0,
57 Selected = 1,
58};
59
60enum class TraceMode : int8_t {
61 Single = 0,
62 Sequence = 1,
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{
155 int index = BKE_grease_pencil_object_material_index_get_by_name(ob, name.c_str());
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{
167 int index = BKE_grease_pencil_object_material_index_get_by_name(ob, name.c_str());
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 potrace_bitmap_t *bm = image_trace::image_to_bitmap(ibuf, [&](const ColorGeometry4f &color) {
184 return math::average(float3(color.r, color.g, color.b)) * color.a > trace_job.threshold;
185 });
186
187 image_trace::TraceParams params;
188 params.size_threshold = 0;
189 params.turn_policy = trace_job.turnpolicy;
190 image_trace::Trace *trace = image_trace::trace_bitmap(params, *bm);
192
193 /* Attribute ID for which curves are "holes" with a negative trace sign. */
194 const StringRef hole_attribute_id = "is_hole";
195
196 /* Transform from bitmap index space to local image object space. */
197 const float4x4 transform = pixel_to_object_transform(*trace_job.ob_active, ibuf);
199 *trace, hole_attribute_id, transform);
201
202 /* Assign different materials to foreground curves and hole curves. */
203 bke::MutableAttributeAccessor attributes = trace_curves.attributes_for_write();
204 const int material_fg = ensure_foreground_material(
205 trace_job.bmain, trace_job.ob_grease_pencil, "Stroke");
206 const int material_bg = ensure_background_material(
207 trace_job.bmain, trace_job.ob_grease_pencil, "Holdout");
208 const VArraySpan<bool> holes = *attributes.lookup<bool>(hole_attribute_id);
209 bke::SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_span<int>(
210 "material_index", bke::AttrDomain::Curve);
211 threading::parallel_for(trace_curves.curves_range(), 4096, [&](const IndexRange range) {
212 for (const int curve_i : range) {
213 const bool is_hole = holes[curve_i];
214 material_indices.span[curve_i] = (is_hole ? material_bg : material_fg);
215 }
216 });
217 material_indices.finish();
218 /* Remove hole attribute */
219 attributes.remove(hole_attribute_id);
220
221 /* Uniform radius for all trace curves. */
222 bke::SpanAttributeWriter<float> radii = attributes.lookup_or_add_for_write_only_span<float>(
223 "radius", bke::AttrDomain::Point);
224 radii.span.fill(trace_job.radius);
225 radii.finish();
226
227 return trace_curves;
228}
229
230static void trace_start_job(void *customdata, wmJobWorkerStatus *worker_status)
231{
232 TraceJob &trace_job = *static_cast<TraceJob *>(customdata);
233
234 trace_job.stop = &worker_status->stop;
235 trace_job.do_update = &worker_status->do_update;
236 trace_job.progress = &worker_status->progress;
237 trace_job.was_canceled = false;
238 const int init_frame = std::max((trace_job.use_current_frame) ? trace_job.frame_target : 0, 0);
239
240 G.is_break = false;
241
242 /* Single Image. */
243 if (trace_job.image->source == IMA_SRC_FILE || trace_job.mode == TraceMode::Single) {
244 ImageUser &iuser = *trace_job.ob_active->iuser;
245 trace_job.traced_curves.reinitialize(1);
246
247 iuser.framenr = ((trace_job.frame_number == 0) || (trace_job.frame_number > iuser.frames)) ?
248 init_frame :
249 trace_job.frame_number;
250 void *lock;
251 ImBuf *ibuf = BKE_image_acquire_ibuf(trace_job.image, &iuser, &lock);
252 if (ibuf) {
253 trace_job.traced_curves.first() = grease_pencil_trace_image(trace_job, *ibuf);
254 BKE_image_release_ibuf(trace_job.image, ibuf, lock);
255 *(trace_job.progress) = 1.0f;
256 }
257 }
258 /* Image sequence. */
259 else if (trace_job.image->type == IMA_TYPE_IMAGE) {
260 ImageUser &iuser = *trace_job.ob_active->iuser;
261 const int num_frames = iuser.frames - init_frame + 1;
262 trace_job.traced_curves.reinitialize(num_frames);
263 for (const int i : IndexRange(num_frames)) {
264 if (G.is_break) {
265 trace_job.was_canceled = true;
266 break;
267 }
268
269 const int frame_number = init_frame + i;
270 *(trace_job.progress) = float(frame_number) / float(iuser.frames);
271 worker_status->do_update = true;
272
273 iuser.framenr = frame_number;
274
275 void *lock;
276 ImBuf *ibuf = BKE_image_acquire_ibuf(trace_job.image, &iuser, &lock);
277 if (ibuf) {
278 trace_job.traced_curves[i] = grease_pencil_trace_image(trace_job, *ibuf);
279 BKE_image_release_ibuf(trace_job.image, ibuf, lock);
280 }
281 }
282 }
283
284 trace_job.success = !trace_job.was_canceled;
285 worker_status->do_update = true;
286 worker_status->stop = false;
287}
288
289static void trace_end_job(void *customdata)
290{
291 TraceJob &trace_job = *static_cast<TraceJob *>(customdata);
292 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(trace_job.ob_grease_pencil->data);
293
294 /* Update all the drawings once the job is done and we're executing in the main thread again.
295 * Changing drawing array or updating the drawing geometry is not thread-safe. */
296 switch (trace_job.mode) {
297 case TraceMode::Single: {
298 BLI_assert(trace_job.traced_curves.size() == 1);
299 bke::greasepencil::Drawing *drawing = grease_pencil.get_drawing_at(*trace_job.layer,
300 trace_job.frame_target);
301 if (drawing == nullptr) {
302 drawing = grease_pencil.insert_frame(*trace_job.layer, trace_job.frame_target);
303 }
304 BLI_assert(drawing != nullptr);
305 drawing->strokes_for_write() = trace_job.traced_curves.first();
306 drawing->tag_topology_changed();
307 break;
308 }
309 case TraceMode::Sequence: {
310 const ImageUser &iuser = *trace_job.ob_active->iuser;
311 const int init_frame = std::max((trace_job.use_current_frame) ? trace_job.frame_target : 0,
312 0);
313 const int num_frames = iuser.frames - init_frame + 1;
314 BLI_assert(trace_job.traced_curves.size() == num_frames);
315 for (const int i : IndexRange(num_frames)) {
316 const int frame_number = init_frame + i;
317 bke::greasepencil::Drawing *drawing = grease_pencil.get_drawing_at(*trace_job.layer,
318 frame_number);
319 if (drawing == nullptr) {
320 drawing = grease_pencil.insert_frame(*trace_job.layer, frame_number);
321 }
322 BLI_assert(drawing != nullptr);
323 drawing->strokes_for_write() = trace_job.traced_curves[i];
324 drawing->tag_topology_changed();
325 }
326 break;
327 }
328 }
329
330 /* If canceled, delete all previously created object and data-block. */
331 if ((trace_job.was_canceled) && (trace_job.was_ob_created) && (trace_job.ob_grease_pencil)) {
332 BKE_id_delete(trace_job.bmain, &trace_job.ob_grease_pencil->id);
333 BKE_id_delete(trace_job.bmain, &grease_pencil.id);
334 }
335
336 if (trace_job.success) {
337 DEG_relations_tag_update(trace_job.bmain);
338
339 DEG_id_tag_update(&trace_job.scene->id, ID_RECALC_SELECT);
341
343 WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, trace_job.scene);
344 }
345}
346
347static void trace_free_job(void *customdata)
348{
349 TraceJob *tj = static_cast<TraceJob *>(customdata);
350 MEM_delete(tj);
351}
352
353/* Trace Image to Grease Pencil. */
354static bool grease_pencil_trace_image_poll(bContext *C)
355{
357 if ((ob == nullptr) || (ob->type != OB_EMPTY) || (ob->data == nullptr)) {
358 CTX_wm_operator_poll_msg_set(C, "No image empty selected");
359 return false;
360 }
361
362 Image *image = static_cast<Image *>(ob->data);
363 if (!ELEM(image->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
364 CTX_wm_operator_poll_msg_set(C, "No valid image format selected");
365 return false;
366 }
367
368 return true;
369}
370
371static int grease_pencil_trace_image_exec(bContext *C, wmOperator *op)
372{
373 TraceJob *job = MEM_new<TraceJob>("TraceJob");
374 job->C = C;
375 job->owner = CTX_data_active_object(C);
376 job->wm = CTX_wm_manager(C);
377 job->bmain = CTX_data_main(C);
378 Scene *scene = CTX_data_scene(C);
379 job->scene = scene;
380 job->v3d = CTX_wm_view3d(C);
381 job->base_active = CTX_data_active_base(C);
382 job->ob_active = job->base_active->object;
383 job->image = static_cast<Image *>(job->ob_active->data);
384 job->frame_target = scene->r.cfra;
385 job->use_current_frame = RNA_boolean_get(op->ptr, "use_current_frame");
386
387 /* Create a new grease pencil object or reuse selected. */
388 const TargetObjectMode target = TargetObjectMode(RNA_enum_get(op->ptr, "target"));
389 job->ob_grease_pencil = (target == TargetObjectMode::Selected) ?
391 scene, CTX_data_view_layer(C), job->v3d) :
392 nullptr;
393
394 if (job->ob_grease_pencil != nullptr) {
395 if (job->ob_grease_pencil->type != OB_GREASE_PENCIL) {
396 BKE_report(op->reports, RPT_WARNING, "Target object not a grease pencil, ignoring!");
397 job->ob_grease_pencil = nullptr;
398 }
399 else if (BKE_object_obdata_is_libdata(job->ob_grease_pencil)) {
400 BKE_report(op->reports, RPT_WARNING, "Target object library-data, ignoring!");
401 job->ob_grease_pencil = nullptr;
402 }
403 }
404
405 job->was_ob_created = false;
406
407 job->threshold = RNA_float_get(op->ptr, "threshold");
408 job->radius = RNA_float_get(op->ptr, "radius");
409 job->turnpolicy = TurnPolicy(RNA_enum_get(op->ptr, "turnpolicy"));
410 job->mode = TraceMode(RNA_enum_get(op->ptr, "mode"));
411 job->frame_number = RNA_int_get(op->ptr, "frame_number");
412
413 job->ensure_output_object();
414
415 /* Back to active base. */
416 blender::ed::object::base_activate(job->C, job->base_active);
417
418 if ((job->image->source == IMA_SRC_FILE) || (job->frame_number > 0)) {
419 wmJobWorkerStatus worker_status = {};
420 trace_start_job(job, &worker_status);
421 trace_end_job(job);
422 trace_free_job(job);
423 }
424 else {
425 wmJob *wm_job = WM_jobs_get(job->wm,
426 CTX_wm_window(C),
427 job->scene,
428 "Trace Image",
431
432 WM_jobs_customdata_set(wm_job, job, trace_free_job);
433 WM_jobs_timer(wm_job, 0.1, NC_GEOM | ND_DATA, NC_GEOM | ND_DATA);
434 WM_jobs_callbacks(wm_job, trace_start_job, nullptr, nullptr, trace_end_job);
435
436 WM_jobs_start(CTX_wm_manager(C), wm_job);
437 }
438
439 return OPERATOR_FINISHED;
440}
441
442static int grease_pencil_trace_image_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
443{
444 /* Show popup dialog to allow editing. */
445 /* FIXME: hard-coded dimensions here are just arbitrary. */
446 return WM_operator_props_dialog_popup(C, op, 250);
447}
448
449static void GREASE_PENCIL_OT_trace_image(wmOperatorType *ot)
450{
451 PropertyRNA *prop;
452
453 static const EnumPropertyItem turnpolicy_type[] = {
454 {int(TurnPolicy::Foreground),
455 "FOREGROUND",
456 0,
457 "Foreground",
458 "Prefers to connect foreground components"},
459 {int(TurnPolicy::Background),
460 "BACKGROUND",
461 0,
462 "Background",
463 "Prefers to connect background components"},
464 {int(TurnPolicy::Left), "LEFT", 0, "Left", "Always take a left turn"},
465 {int(TurnPolicy::Right), "RIGHT", 0, "Right", "Always take a right turn"},
466 {int(TurnPolicy::Minority),
467 "MINORITY",
468 0,
469 "Minority",
470 "Prefers to connect the color that occurs least frequently in the local "
471 "neighborhood of the current position"},
472 {int(TurnPolicy::Majority),
473 "MAJORITY",
474 0,
475 "Majority",
476 "Prefers to connect the color that occurs most frequently in the local "
477 "neighborhood of the current position"},
478 {int(TurnPolicy::Random), "RANDOM", 0, "Random", "Choose pseudo-randomly"},
479 {0, nullptr, 0, nullptr, nullptr},
480 };
481
482 static const EnumPropertyItem trace_modes[] = {
483 {int(TraceMode::Single), "SINGLE", 0, "Single", "Trace the current frame of the image"},
484 {int(TraceMode::Sequence), "SEQUENCE", 0, "Sequence", "Trace full sequence"},
485 {0, nullptr, 0, nullptr, nullptr},
486 };
487
488 static const EnumPropertyItem target_object_modes[] = {
489 {int(TargetObjectMode::New), "NEW", 0, "New Object", ""},
490 {int(TargetObjectMode::Selected), "SELECTED", 0, "Selected Object", ""},
491 {0, nullptr, 0, nullptr, nullptr},
492 };
493
494 /* identifiers */
495 ot->name = "Trace Image to Grease Pencil";
496 ot->idname = "GREASE_PENCIL_OT_trace_image";
497 ot->description = "Extract Grease Pencil strokes from image";
498
499 /* callbacks */
500 ot->invoke = grease_pencil_trace_image_invoke;
501 ot->exec = grease_pencil_trace_image_exec;
502 ot->poll = grease_pencil_trace_image_poll;
503
504 /* flags */
506
507 /* properties */
509 "target",
510 target_object_modes,
511 int(TargetObjectMode::New),
512 "Target Object",
513 "Target grease pencil");
515
516 RNA_def_float(ot->srna, "radius", 0.01f, 0.001f, 1.0f, "Radius", "", 0.001, 1.0f);
517
519 "threshold",
520 0.5f,
521 0.0f,
522 1.0f,
523 "Color Threshold",
524 "Determine the lightness threshold above which strokes are generated",
525 0.0f,
526 1.0f);
528 "turnpolicy",
529 turnpolicy_type,
530 int(TurnPolicy::Minority),
531 "Turn Policy",
532 "Determines how to resolve ambiguities during decomposition of bitmaps into paths");
534 "mode",
535 trace_modes,
536 int(TraceMode::Single),
537 "Mode",
538 "Determines if trace simple image or full sequence");
540 "use_current_frame",
541 true,
542 "Start At Current Frame",
543 "Trace Image starting in current image frame");
544 prop = RNA_def_int(
545 ot->srna,
546 "frame_number",
547 0,
548 0,
549 9999,
550 "Trace Frame",
551 "Used to trace only one frame of the image sequence, set to zero to trace all",
552 0,
553 9999);
555}
556
557#endif
558
561} // namespace blender::ed::sculpt_paint::greasepencil
562
563/* -------------------------------------------------------------------- */
568{
570
571#ifdef WITH_POTRACE
572 WM_operatortype_append(GREASE_PENCIL_OT_trace_image);
573#endif
574}
575
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
@ 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
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
@ 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
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#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
#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
IndexRange curves_range() const
MutableAttributeAccessor attributes_for_write()
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 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
VecBase< float, 2 > float2
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]
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
PropertyRNA * prop
Definition WM_types.hh:1092
StructRNA * srna
Definition WM_types.hh:1080
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)