Blender V5.0
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.hh"
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
46#ifdef WITH_POTRACE
47# include "potracelib.h"
48#endif
49
51
52/* -------------------------------------------------------------------- */
55
57
58/* Target object modes. */
59enum class TargetObjectMode : int8_t {
60 New = 0,
62};
63
64enum class TraceMode : int8_t {
65 Single = 0,
67};
68
69#ifdef WITH_POTRACE
70
71struct TraceJob {
72 /* from wmJob */
73 Object *owner;
74 bool *stop, *do_update;
75 float *progress;
76
77 bContext *C;
79 Main *bmain;
80 Scene *scene;
81 View3D *v3d;
82 Base *base_active;
83 Object *ob_active;
84 Image *image;
85 Object *ob_grease_pencil;
87
88 Array<bke::CurvesGeometry> traced_curves;
89
90 bool was_ob_created;
91 bool use_current_frame;
92
93 /* Frame number where the output frame is generated. */
94 int frame_target;
95 float threshold;
96 float radius;
97 TurnPolicy turnpolicy;
98 TraceMode mode;
99 /* Custom source frame, allows overriding the default scene frame. */
100 int frame_number;
101 int foreground_material_index;
102 int background_material_index;
103
104 bool success;
105 bool was_canceled;
106
107 void ensure_output_object();
108};
109
110void TraceJob::ensure_output_object()
111{
112 using namespace blender::bke::greasepencil;
113
114 /* Create a new grease pencil object. */
115 if (this->ob_grease_pencil == nullptr) {
116 const ushort local_view_bits = (this->v3d && this->v3d->localvd) ? this->v3d->local_view_uid :
117 0;
118
119 /* Copy transform from the active object. */
120 this->ob_grease_pencil = ed::object::add_type(this->C,
122 nullptr,
123 this->ob_active->loc,
124 this->ob_active->rot,
125 false,
126 local_view_bits);
127 copy_v3_v3(this->ob_grease_pencil->scale, this->ob_active->scale);
128 this->was_ob_created = true;
129 }
130
131 /* Create Layer. */
132 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(this->ob_grease_pencil->data);
133 this->layer = grease_pencil.get_active_layer();
134 if (this->layer == nullptr) {
135 Layer &new_layer = grease_pencil.add_layer(DATA_("Trace"));
136 grease_pencil.set_active_layer(&new_layer);
137 this->layer = &new_layer;
138 }
139}
140
141static float4x4 pixel_to_object_transform(const Object &image_object,
142 const ImBuf &ibuf,
143 const float2 pixel_center = float2(0.5f))
144{
145 const float3 pixel_center_3d = float3(pixel_center.x, pixel_center.y, 0);
146 const float3 pixel_size_3d = math::safe_rcp(float3(ibuf.x, ibuf.y, 0));
147 const float3 image_offset_3d = float3(image_object.ima_ofs[0], image_object.ima_ofs[1], 0);
148 const float max_image_scale = image_object.empty_drawsize;
149 const float3 image_aspect_3d = (ibuf.x > ibuf.y ? float3(1, float(ibuf.y) / float(ibuf.x), 1) :
150 float3(float(ibuf.x) / float(ibuf.y), 1, 1));
151
152 const float4x4 to_object = math::translate(
153 math::from_scale<float4x4>(image_aspect_3d * max_image_scale), image_offset_3d);
154 const float4x4 to_normalized = math::translate(math::scale(to_object, pixel_size_3d),
155 pixel_center_3d);
156 return to_normalized;
157}
158
159static int ensure_foreground_material(Main *bmain, Object *ob, const StringRefNull name)
160{
162 if (index == -1) {
163 Material &ma = *BKE_grease_pencil_object_material_new(bmain, ob, name.c_str(), &index);
164 copy_v4_v4(ma.gp_style->stroke_rgba, float4(0, 0, 0, 1));
167 }
168 return index;
169}
170
171static int ensure_background_material(Main *bmain, Object *ob, const StringRefNull name)
172{
174 if (index == -1) {
175 Material &ma = *BKE_grease_pencil_object_material_new(bmain, ob, name.c_str(), &index);
176 copy_v4_v4(ma.gp_style->stroke_rgba, float4(0, 0, 0, 1));
177 copy_v4_v4(ma.gp_style->fill_rgba, float4(0, 0, 0, 1));
182 }
183 return index;
184}
185
186static bke::CurvesGeometry grease_pencil_trace_image(TraceJob &trace_job, const ImBuf &ibuf)
187{
188 /* Trace the image.
189 * Note: Colors above threshold are interpreted as "background". This works well for images with
190 * black-on-white drawings, but is quite arbitrary. */
191 potrace_bitmap_t *bm = image_trace::image_to_bitmap(ibuf, [&](const ColorGeometry4f &color) {
192 return math::average(float3(color.r, color.g, color.b)) * color.a <= trace_job.threshold;
193 });
194
195 image_trace::TraceParams params;
196 params.size_threshold = 0;
197 params.turn_policy = trace_job.turnpolicy;
198 image_trace::Trace *trace = image_trace::trace_bitmap(params, *bm);
200
201 /* Attribute ID for which curves are "holes" with a negative trace sign. */
202 const StringRef hole_attribute_id = "is_hole";
203
204 /* Transform from bitmap index space to local image object space. */
205 const float4x4 transform = pixel_to_object_transform(*trace_job.ob_active, ibuf);
206 bke::CurvesGeometry trace_curves = image_trace::trace_to_curves(
207 *trace, hole_attribute_id, transform);
209
210 /* Assign different materials to foreground curves and hole curves. */
211 bke::MutableAttributeAccessor attributes = trace_curves.attributes_for_write();
212 BLI_assert_msg(trace_job.foreground_material_index >= 0,
213 "ensure_foreground_material must be called on the main thread");
214 BLI_assert_msg(trace_job.background_material_index >= 0,
215 "ensure_background_material must be called on the main thread");
216 const VArraySpan<bool> holes = *attributes.lookup<bool>(hole_attribute_id);
217 bke::SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_span<int>(
218 "material_index", bke::AttrDomain::Curve);
219 threading::parallel_for(trace_curves.curves_range(), 4096, [&](const IndexRange range) {
220 for (const int curve_i : range) {
221 const bool is_hole = holes[curve_i];
222 material_indices.span[curve_i] = (is_hole ? trace_job.background_material_index :
223 trace_job.foreground_material_index);
224 }
225 });
226 material_indices.finish();
227 /* Remove hole attribute */
228 attributes.remove(hole_attribute_id);
229
230 /* Uniform radius for all trace curves. */
231 bke::SpanAttributeWriter<float> radii = attributes.lookup_or_add_for_write_only_span<float>(
232 "radius", bke::AttrDomain::Point);
233 radii.span.fill(trace_job.radius);
234 radii.finish();
235
236 return trace_curves;
237}
238
239static void trace_start_job(void *customdata, wmJobWorkerStatus *worker_status)
240{
241 TraceJob &trace_job = *static_cast<TraceJob *>(customdata);
242
243 trace_job.stop = &worker_status->stop;
244 trace_job.do_update = &worker_status->do_update;
245 trace_job.progress = &worker_status->progress;
246 trace_job.was_canceled = false;
247 const int init_frame = std::max((trace_job.use_current_frame) ? trace_job.frame_target : 0, 0);
248
249 G.is_break = false;
250
251 /* Single Image. */
252 if (trace_job.image->source == IMA_SRC_FILE || trace_job.mode == TraceMode::Single) {
253 ImageUser &iuser = *trace_job.ob_active->iuser;
254 trace_job.traced_curves.reinitialize(1);
255
256 iuser.framenr = ((trace_job.frame_number == 0) || (trace_job.frame_number > iuser.frames)) ?
257 init_frame :
258 trace_job.frame_number;
259 void *lock;
260 ImBuf *ibuf = BKE_image_acquire_ibuf(trace_job.image, &iuser, &lock);
261 if (ibuf) {
262 trace_job.traced_curves.first() = grease_pencil_trace_image(trace_job, *ibuf);
263 BKE_image_release_ibuf(trace_job.image, ibuf, lock);
264 *(trace_job.progress) = 1.0f;
265 }
266 /* If source type is not sequence, override `trace_job.mode` to single because we need the
267 * correct mode for finalization. */
268 trace_job.mode = TraceMode::Single;
269 }
270 /* Image sequence. */
271 else if (trace_job.image->type == IMA_TYPE_IMAGE) {
272 ImageUser &iuser = *trace_job.ob_active->iuser;
273 const int num_frames = iuser.frames - init_frame + 1;
274 trace_job.traced_curves.reinitialize(num_frames);
275 for (const int i : IndexRange(num_frames)) {
276 if (G.is_break) {
277 trace_job.was_canceled = true;
278 break;
279 }
280
281 const int frame_number = init_frame + i;
282 *(trace_job.progress) = float(frame_number) / float(iuser.frames);
283 worker_status->do_update = true;
284
285 iuser.framenr = frame_number;
286
287 void *lock;
288 ImBuf *ibuf = BKE_image_acquire_ibuf(trace_job.image, &iuser, &lock);
289 if (ibuf) {
290 trace_job.traced_curves[i] = grease_pencil_trace_image(trace_job, *ibuf);
291 BKE_image_release_ibuf(trace_job.image, ibuf, lock);
292 }
293 }
294 }
295
296 trace_job.success = !trace_job.was_canceled;
297 worker_status->do_update = true;
298 worker_status->stop = false;
299}
300
301static void trace_end_job(void *customdata)
302{
303 TraceJob &trace_job = *static_cast<TraceJob *>(customdata);
304 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(trace_job.ob_grease_pencil->data);
305
306 auto ensure_drawing_at_frame = [&](const int frame_number) {
307 const std::optional<int> start_frame = trace_job.layer->start_frame_at(frame_number);
308 if (start_frame && *start_frame == frame_number) {
309 return grease_pencil.get_editable_drawing_at(*trace_job.layer, frame_number);
310 }
311 return grease_pencil.insert_frame(*trace_job.layer, frame_number);
312 };
313
314 /* Update all the drawings once the job is done and we're executing in the main thread again.
315 * Changing drawing array or updating the drawing geometry is not thread-safe. */
316 switch (trace_job.mode) {
317 case TraceMode::Single: {
318 BLI_assert(trace_job.traced_curves.size() == 1);
319 bke::greasepencil::Drawing *drawing = ensure_drawing_at_frame(trace_job.frame_target);
320 BLI_assert(drawing != nullptr);
321 drawing->strokes_for_write() = trace_job.traced_curves.first();
322 drawing->tag_topology_changed();
323 break;
324 }
325 case TraceMode::Sequence: {
326 const ImageUser &iuser = *trace_job.ob_active->iuser;
327 const int init_frame = std::max((trace_job.use_current_frame) ? trace_job.frame_target : 0,
328 0);
329 const int num_frames = iuser.frames - init_frame + 1;
330 BLI_assert(trace_job.traced_curves.size() == num_frames);
331 for (const int i : IndexRange(num_frames)) {
332 const int frame_number = init_frame + i;
333 bke::greasepencil::Drawing *drawing = ensure_drawing_at_frame(frame_number);
334 BLI_assert(drawing != nullptr);
335 drawing->strokes_for_write() = trace_job.traced_curves[i];
336 drawing->tag_topology_changed();
337 }
338 break;
339 }
340 }
341
342 /* If canceled, delete all previously created object and data-block. */
343 if ((trace_job.was_canceled) && (trace_job.was_ob_created) && (trace_job.ob_grease_pencil)) {
344 BKE_id_delete(trace_job.bmain, &trace_job.ob_grease_pencil->id);
345 BKE_id_delete(trace_job.bmain, &grease_pencil.id);
346 }
347
348 if (trace_job.success) {
349 DEG_relations_tag_update(trace_job.bmain);
350
351 DEG_id_tag_update(&trace_job.scene->id, ID_RECALC_SELECT);
353
355 WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, trace_job.scene);
356 }
357}
358
359static void trace_free_job(void *customdata)
360{
361 TraceJob *tj = static_cast<TraceJob *>(customdata);
362 MEM_delete(tj);
363}
364
365/* Trace Image to Grease Pencil. */
366static bool grease_pencil_trace_image_poll(bContext *C)
367{
369 if ((ob == nullptr) || (ob->type != OB_EMPTY) || (ob->data == nullptr)) {
370 CTX_wm_operator_poll_msg_set(C, "No image empty selected");
371 return false;
372 }
373
374 Image *image = static_cast<Image *>(ob->data);
376 CTX_wm_operator_poll_msg_set(C, "No valid image format selected");
377 return false;
378 }
379
380 return true;
381}
382
383static wmOperatorStatus grease_pencil_trace_image_exec(bContext *C, wmOperator *op)
384{
385 TraceJob *job = MEM_new<TraceJob>("TraceJob");
386 job->C = C;
387 job->owner = CTX_data_active_object(C);
388 job->wm = CTX_wm_manager(C);
389 job->bmain = CTX_data_main(C);
390 Scene *scene = CTX_data_scene(C);
391 job->scene = scene;
392 job->v3d = CTX_wm_view3d(C);
393 job->base_active = CTX_data_active_base(C);
394 job->ob_active = job->base_active->object;
395 job->image = static_cast<Image *>(job->ob_active->data);
396 job->frame_target = scene->r.cfra;
397 job->use_current_frame = RNA_boolean_get(op->ptr, "use_current_frame");
398
399 /* Create a new grease pencil object or reuse selected. */
400 const TargetObjectMode target = TargetObjectMode(RNA_enum_get(op->ptr, "target"));
401 job->ob_grease_pencil = (target == TargetObjectMode::Selected) ?
403 scene, CTX_data_view_layer(C), job->v3d) :
404 nullptr;
405
406 if (job->ob_grease_pencil != nullptr) {
407 if (job->ob_grease_pencil->type != OB_GREASE_PENCIL) {
408 BKE_report(op->reports, RPT_WARNING, "Target object not a Grease Pencil, ignoring!");
409 job->ob_grease_pencil = nullptr;
410 }
411 else if (BKE_object_obdata_is_libdata(job->ob_grease_pencil)) {
412 BKE_report(op->reports, RPT_WARNING, "Target object library-data, ignoring!");
413 job->ob_grease_pencil = nullptr;
414 }
415 }
416
417 job->was_ob_created = false;
418
419 job->threshold = RNA_float_get(op->ptr, "threshold");
420 job->radius = RNA_float_get(op->ptr, "radius");
421 job->turnpolicy = TurnPolicy(RNA_enum_get(op->ptr, "turnpolicy"));
422 job->mode = TraceMode(RNA_enum_get(op->ptr, "mode"));
423 job->frame_number = RNA_int_get(op->ptr, "frame_number");
424
425 job->ensure_output_object();
426
427 /* Back to active base. */
428 blender::ed::object::base_activate(job->C, job->base_active);
429
430 /* Create materials on the main thread before starting the job. */
431 job->foreground_material_index = ensure_foreground_material(
432 job->bmain, job->ob_grease_pencil, "Stroke");
433 job->background_material_index = ensure_background_material(
434 job->bmain, job->ob_grease_pencil, "Holdout");
435
436 if ((job->image->source == IMA_SRC_FILE) || (job->frame_number > 0)) {
437 wmJobWorkerStatus worker_status = {};
438 trace_start_job(job, &worker_status);
439 trace_end_job(job);
440 trace_free_job(job);
441 }
442 else {
443 wmJob *wm_job = WM_jobs_get(job->wm,
445 job->scene,
446 "Tracing image...",
449
450 WM_jobs_customdata_set(wm_job, job, trace_free_job);
451 WM_jobs_timer(wm_job, 0.1, NC_GEOM | ND_DATA, NC_GEOM | ND_DATA);
452 WM_jobs_callbacks(wm_job, trace_start_job, nullptr, nullptr, trace_end_job);
453
455 }
456
457 return OPERATOR_FINISHED;
458}
459
460static wmOperatorStatus grease_pencil_trace_image_invoke(bContext *C,
461 wmOperator *op,
462 const wmEvent * /*event*/)
463{
464 /* Show popup dialog to allow editing. */
465 /* FIXME: hard-coded dimensions here are just arbitrary. */
466 return WM_operator_props_dialog_popup(C, op, 250);
467}
468
469static void GREASE_PENCIL_OT_trace_image(wmOperatorType *ot)
470{
471 PropertyRNA *prop;
472
473 static const EnumPropertyItem turnpolicy_type[] = {
474 {int(TurnPolicy::Foreground),
475 "FOREGROUND",
476 0,
477 "Foreground",
478 "Prefers to connect foreground components"},
479 {int(TurnPolicy::Background),
480 "BACKGROUND",
481 0,
482 "Background",
483 "Prefers to connect background components"},
484 {int(TurnPolicy::Left), "LEFT", 0, "Left", "Always take a left turn"},
485 {int(TurnPolicy::Right), "RIGHT", 0, "Right", "Always take a right turn"},
486 {int(TurnPolicy::Minority),
487 "MINORITY",
488 0,
489 "Minority",
490 "Prefers to connect the color that occurs least frequently in the local "
491 "neighborhood of the current position"},
492 {int(TurnPolicy::Majority),
493 "MAJORITY",
494 0,
495 "Majority",
496 "Prefers to connect the color that occurs most frequently in the local "
497 "neighborhood of the current position"},
498 {int(TurnPolicy::Random), "RANDOM", 0, "Random", "Choose pseudo-randomly"},
499 {0, nullptr, 0, nullptr, nullptr},
500 };
501
502 static const EnumPropertyItem trace_modes[] = {
503 {int(TraceMode::Single), "SINGLE", 0, "Single", "Trace the current frame of the image"},
504 {int(TraceMode::Sequence), "SEQUENCE", 0, "Sequence", "Trace full sequence"},
505 {0, nullptr, 0, nullptr, nullptr},
506 };
507
508 static const EnumPropertyItem target_object_modes[] = {
509 {int(TargetObjectMode::New), "NEW", 0, "New Object", ""},
510 {int(TargetObjectMode::Selected), "SELECTED", 0, "Selected Object", ""},
511 {0, nullptr, 0, nullptr, nullptr},
512 };
513
514 /* identifiers */
515 ot->name = "Trace Image to Grease Pencil";
516 ot->idname = "GREASE_PENCIL_OT_trace_image";
517 ot->description = "Extract Grease Pencil strokes from image";
518
519 /* callbacks */
520 ot->invoke = grease_pencil_trace_image_invoke;
521 ot->exec = grease_pencil_trace_image_exec;
522 ot->poll = grease_pencil_trace_image_poll;
523
524 /* flags */
526
527 /* properties */
528 ot->prop = RNA_def_enum(ot->srna,
529 "target",
530 target_object_modes,
531 int(TargetObjectMode::New),
532 "Target Object",
533 "Target Grease Pencil");
535
536 RNA_def_float(ot->srna, "radius", 0.01f, 0.001f, 1.0f, "Radius", "", 0.001, 1.0f);
537
539 "threshold",
540 0.5f,
541 0.0f,
542 1.0f,
543 "Color Threshold",
544 "Determine the lightness threshold above which strokes are generated",
545 0.0f,
546 1.0f);
547 RNA_def_enum(ot->srna,
548 "turnpolicy",
549 turnpolicy_type,
550 int(TurnPolicy::Minority),
551 "Turn Policy",
552 "Determines how to resolve ambiguities during decomposition of bitmaps into paths");
553 RNA_def_enum(ot->srna,
554 "mode",
555 trace_modes,
556 int(TraceMode::Single),
557 "Mode",
558 "Determines if trace simple image or full sequence");
559 RNA_def_boolean(ot->srna,
560 "use_current_frame",
561 true,
562 "Start At Current Frame",
563 "Trace Image starting in current image frame");
564 prop = RNA_def_int(
565 ot->srna,
566 "frame_number",
567 0,
568 0,
569 9999,
570 "Trace Frame",
571 "Used to trace only one frame of the image sequence, set to zero to trace all",
572 0,
573 9999);
575}
576
577#endif
578
580
581} // namespace blender::ed::sculpt_paint::greasepencil
582
583/* -------------------------------------------------------------------- */
586
588{
590
591#ifdef WITH_POTRACE
592 WM_operatortype_append(GREASE_PENCIL_OT_trace_image);
593#endif
594}
595
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)
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
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:1101
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ 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
@ OPERATOR_FINISHED
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
#define C
Definition RandGen.cpp:29
@ WM_JOB_TYPE_TRACE_IMAGE
Definition WM_api.hh:1805
@ WM_JOB_PROGRESS
Definition WM_api.hh:1766
#define NC_GEOM
Definition WM_types.hh:393
#define ND_OB_ACTIVE
Definition WM_types.hh:440
#define ND_DATA
Definition WM_types.hh:509
#define NC_SCENE
Definition WM_types.hh:378
#define NA_ADDED
Definition WM_types.hh:586
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define NC_OBJECT
Definition WM_types.hh:379
volatile int lock
BMesh * bm
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
ChannelStorageType r
ChannelStorageType g
ChannelStorageType b
ChannelStorageType a
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, AttrType 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, AttrType data_type)
bke::CurvesGeometry & strokes_for_write()
nullptr float
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:93
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
VecBase< float, 2 > float2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
VecBase< float, 3 > float3
const char * name
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)
struct MaterialGPencilStyle * gp_style
float empty_drawsize
float ima_ofs[2]
struct RenderData r
struct ReportList * reports
struct PointerRNA * ptr
i
Definition text_draw.cc:230
void WM_main_add_notifier(uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4237
void WM_jobs_timer(wmJob *wm_job, double time_step, uint note, uint endnote)
Definition wm_jobs.cc:376
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition wm_jobs.cc:479
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:211
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:388
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
Definition wm_jobs.cc:360
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
wmOperatorStatus 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, std::optional< std::string > message)