Blender V4.3
object_bake.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2004 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstring>
10
11#include "MEM_guardedalloc.h"
12
13#include "DNA_mesh_types.h"
14#include "DNA_object_types.h"
15#include "DNA_scene_types.h"
16#include "DNA_screen_types.h"
17#include "DNA_space_types.h"
18
19#include "BLI_utildefines.h"
20
21#include "BKE_attribute.hh"
22#include "BKE_context.hh"
23#include "BKE_customdata.hh"
24#include "BKE_global.hh"
25#include "BKE_image.hh"
27#include "BKE_modifier.hh"
28#include "BKE_multires.hh"
29#include "BKE_report.hh"
30#include "BKE_scene.hh"
31
32#include "RE_multires_bake.h"
33#include "RE_pipeline.h"
34
35#include "IMB_imbuf.hh"
36#include "IMB_imbuf_types.hh"
37
38#include "WM_api.hh"
39#include "WM_types.hh"
40
41#include "ED_screen.hh"
42#include "ED_uvedit.hh"
43
44#include "object_intern.hh"
45
46namespace blender::ed::object {
47
48static Image *bake_object_image_get(Object *ob, int mat_nr)
49{
50 Image *image = nullptr;
51 ED_object_get_active_image(ob, mat_nr + 1, &image, nullptr, nullptr, nullptr);
52 return image;
53}
54
56{
57 Image **image_array = static_cast<Image **>(
58 MEM_mallocN(sizeof(Material *) * ob->totcol, __func__));
59 for (int i = 0; i < ob->totcol; i++) {
60 image_array[i] = bake_object_image_get(ob, i);
61 }
62 return image_array;
63}
64
65/* ****************** multires BAKING ********************** */
66
67/* holder of per-object data needed for bake job
68 * needed to make job totally thread-safe */
71 /* material aligned image array (for per-face bake image) */
72 struct {
74 int len;
79};
80
81/* data passing to multires-baker job */
104
106{
107 Scene *scene = CTX_data_scene(C);
108 Object *ob;
109 Mesh *mesh;
111 bool ok = true;
112 int a;
113
114 CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
115 ob = base->object;
116
117 if (ob->type != OB_MESH) {
119 op->reports, RPT_ERROR, "Baking of multires data only works with an active mesh object");
120
121 ok = false;
122 break;
123 }
124
125 mesh = (Mesh *)ob->data;
126 mmd = get_multires_modifier(scene, ob, false);
127
128 /* Multi-resolution should be and be last in the stack */
129 if (ok && mmd) {
130 ModifierData *md;
131
132 ok = mmd->totlvl > 0;
133
134 for (md = (ModifierData *)mmd->modifier.next; md && ok; md = md->next) {
136 ok = false;
137 }
138 }
139 }
140 else {
141 ok = false;
142 }
143
144 if (!ok) {
145 BKE_report(op->reports, RPT_ERROR, "Multires data baking requires multi-resolution object");
146
147 break;
148 }
149
150 if (!CustomData_has_layer(&mesh->corner_data, CD_PROP_FLOAT2)) {
151 BKE_report(op->reports, RPT_ERROR, "Mesh should be unwrapped before multires data baking");
152
153 ok = false;
154 }
155 else {
156 const bke::AttributeAccessor attributes = mesh->attributes();
157 const VArraySpan material_indices = *attributes.lookup<int>("material_index",
159 a = mesh->faces_num;
160 while (ok && a--) {
162 material_indices.is_empty() ? 0 : material_indices[a]);
163
164 if (!ima) {
166 op->reports, RPT_ERROR, "You should have active texture to use multires baker");
167
168 ok = false;
169 }
170 else {
172 ImageUser iuser;
173 BKE_imageuser_default(&iuser);
174 iuser.tile = tile->tile_number;
175
176 ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, nullptr);
177
178 if (!ibuf) {
180 op->reports, RPT_ERROR, "Baking should happen to image with image buffer");
181
182 ok = false;
183 }
184 else {
185 if (ibuf->byte_buffer.data == nullptr && ibuf->float_buffer.data == nullptr) {
186 ok = false;
187 }
188
189 if (ibuf->float_buffer.data && !ELEM(ibuf->channels, 0, 4)) {
190 ok = false;
191 }
192
193 if (!ok) {
194 BKE_report(op->reports, RPT_ERROR, "Baking to unsupported image type");
195 }
196 }
197
198 BKE_image_release_ibuf(ima, ibuf, nullptr);
199 }
200 }
201 }
202 }
203
204 if (!ok) {
205 break;
206 }
207 }
209
210 return ok;
211}
212
214{
215 DerivedMesh *dm;
216 MultiresModifierData *mmd = get_multires_modifier(scene, ob, false);
217 Mesh *mesh = (Mesh *)ob->data;
218 MultiresModifierData tmp_mmd = dna::shallow_copy(*mmd);
219
220 *lvl = mmd->lvl;
221
222 if (mmd->lvl == 0) {
223 DerivedMesh *cddm = CDDM_from_mesh(mesh);
225 return cddm;
226 }
227
228 DerivedMesh *cddm = CDDM_from_mesh(mesh);
230 tmp_mmd.lvl = mmd->lvl;
231 tmp_mmd.sculptlvl = mmd->lvl;
232 dm = multires_make_derived_from_derived(cddm, &tmp_mmd, scene, ob, MULTIRES_IGNORE_SIMPLIFY);
233
234 cddm->release(cddm);
235
236 return dm;
237}
238
240{
241 Mesh *mesh = (Mesh *)ob->data;
242 MultiresModifierData *mmd = get_multires_modifier(scene, ob, false);
243 MultiresModifierData tmp_mmd = dna::shallow_copy(*mmd);
244 DerivedMesh *cddm = CDDM_from_mesh(mesh);
245 DerivedMesh *dm;
246
248
249 /* TODO: DM_set_only_copy wouldn't set mask for loop and poly data,
250 * but we really need BAREMESH only to save lots of memory
251 */
254
255 *lvl = mmd->totlvl;
256
257 tmp_mmd.lvl = mmd->totlvl;
258 tmp_mmd.sculptlvl = mmd->totlvl;
259 dm = multires_make_derived_from_derived(cddm, &tmp_mmd, scene, ob, MULTIRES_IGNORE_SIMPLIFY);
260 cddm->release(cddm);
261
262 return dm;
263}
264
269
271{
272 const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f};
273 const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f};
274 const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f};
275 const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f};
276 const float disp_alpha[4] = {0.5f, 0.5f, 0.5f, 0.0f};
277 const float disp_solid[4] = {0.5f, 0.5f, 0.5f, 1.0f};
278
279 if ((image->id.tag & ID_TAG_DOIT) == 0) {
280 LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
281 ImageUser iuser;
282 BKE_imageuser_default(&iuser);
283 iuser.tile = tile->tile_number;
284
285 ImBuf *ibuf = BKE_image_acquire_ibuf(image, &iuser, nullptr);
286
287 if (flag == CLEAR_TANGENT_NORMAL) {
288 IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
289 }
290 else if (flag == CLEAR_DISPLACEMENT) {
291 IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid);
292 }
293 else {
294 IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
295 }
296
297 image->id.tag |= ID_TAG_DOIT;
298
299 BKE_image_release_ibuf(image, ibuf, nullptr);
300 }
301 }
302}
303
304static void clear_images_poly(Image **ob_image_array, int ob_image_array_len, ClearFlag flag)
305{
306 for (int i = 0; i < ob_image_array_len; i++) {
307 Image *image = ob_image_array[i];
308 if (image) {
309 image->id.tag &= ~ID_TAG_DOIT;
310 }
311 }
312
313 for (int i = 0; i < ob_image_array_len; i++) {
314 Image *image = ob_image_array[i];
315 if (image) {
316 clear_single_image(image, flag);
317 }
318 }
319
320 for (int i = 0; i < ob_image_array_len; i++) {
321 Image *image = ob_image_array[i];
322 if (image) {
323 image->id.tag &= ~ID_TAG_DOIT;
324 }
325 }
326}
327
329{
330 Object *ob;
331 Scene *scene = CTX_data_scene(C);
332 int objects_baked = 0;
333
334 if (!multiresbake_check(C, op)) {
335 return OPERATOR_CANCELLED;
336 }
337
338 if (scene->r.bake_flag & R_BAKE_CLEAR) { /* clear images */
339 CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
340 ClearFlag clear_flag = ClearFlag(0);
341
342 ob = base->object;
343 // mesh = (Mesh *)ob->data;
344
345 if (scene->r.bake_mode == RE_BAKE_NORMALS) {
346 clear_flag = CLEAR_TANGENT_NORMAL;
347 }
348 else if (scene->r.bake_mode == RE_BAKE_DISPLACEMENT) {
349 clear_flag = CLEAR_DISPLACEMENT;
350 }
351
352 {
353 Image **ob_image_array = bake_object_image_get_array(ob);
354 clear_images_poly(ob_image_array, ob->totcol, clear_flag);
355 MEM_freeN(ob_image_array);
356 }
357 }
359 }
360
361 CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
362 MultiresBakeRender bkr = {nullptr};
363
364 ob = base->object;
365
367
368 /* copy data stored in job descriptor */
369 bkr.scene = scene;
370 bkr.bake_margin = scene->r.bake_margin;
371 if (scene->r.bake_mode == RE_BAKE_NORMALS) {
373 }
374 else {
375 bkr.bake_margin_type = scene->r.bake_margin_type;
376 }
377 bkr.mode = scene->r.bake_mode;
378 bkr.use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH;
379 bkr.bias = scene->r.bake_biasdist;
380 bkr.number_of_rays = scene->r.bake_samples;
381 bkr.threads = BKE_scene_num_threads(scene);
382 bkr.user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f;
383 // bkr.reports= op->reports;
384
385 /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
387 bkr.ob_image.len = ob->totcol;
388
389 bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl);
390 bkr.lores_dm = multiresbake_create_loresdm(scene, ob, &bkr.lvl);
391
393
395
396 BLI_freelistN(&bkr.image);
397
398 bkr.lores_dm->release(bkr.lores_dm);
399 bkr.hires_dm->release(bkr.hires_dm);
400
401 objects_baked++;
402 }
404
405 if (!objects_baked) {
406 BKE_report(op->reports, RPT_ERROR, "No objects found to bake from");
407 }
408
409 return OPERATOR_FINISHED;
410}
411
416{
417 Scene *scene = CTX_data_scene(C);
418 Object *ob;
419
420 /* backup scene settings, so their changing in UI would take no effect on baker */
421 bkj->scene = scene;
422 bkj->bake_margin = scene->r.bake_margin;
423 if (scene->r.bake_mode == RE_BAKE_NORMALS) {
425 }
426 else {
427 bkj->bake_margin_type = scene->r.bake_margin_type;
428 }
429 bkj->mode = scene->r.bake_mode;
430 bkj->use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH;
431 bkj->bake_clear = scene->r.bake_flag & R_BAKE_CLEAR;
432 bkj->bias = scene->r.bake_biasdist;
433 bkj->number_of_rays = scene->r.bake_samples;
434 bkj->threads = BKE_scene_num_threads(scene);
435 bkj->user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f;
436 // bkj->reports = op->reports;
437
438 CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
439 int lvl;
440
441 ob = base->object;
442
444
445 MultiresBakerJobData *data = MEM_cnew<MultiresBakerJobData>(__func__);
446
447 data->ob_image.array = bake_object_image_get_array(ob);
448 data->ob_image.len = ob->totcol;
449
450 /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
451 data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl);
452 data->lores_dm = multiresbake_create_loresdm(scene, ob, &lvl);
453 data->lvl = lvl;
454
455 BLI_addtail(&bkj->data, data);
456 }
458}
459
460static void multiresbake_startjob(void *bkv, wmJobWorkerStatus *worker_status)
461{
462 MultiresBakeJob *bkj = static_cast<MultiresBakeJob *>(bkv);
463 int baked_objects = 0, tot_obj;
464
465 tot_obj = BLI_listbase_count(&bkj->data);
466
467 if (bkj->bake_clear) { /* clear images */
469 ClearFlag clear_flag = ClearFlag(0);
470
471 if (bkj->mode == RE_BAKE_NORMALS) {
472 clear_flag = CLEAR_TANGENT_NORMAL;
473 }
474 else if (bkj->mode == RE_BAKE_DISPLACEMENT) {
475 clear_flag = CLEAR_DISPLACEMENT;
476 }
477
478 clear_images_poly(data->ob_image.array, data->ob_image.len, clear_flag);
479 }
480 }
481
483 MultiresBakeRender bkr = {nullptr};
484
485 /* copy data stored in job descriptor */
486 bkr.scene = bkj->scene;
487 bkr.bake_margin = bkj->bake_margin;
489 bkr.mode = bkj->mode;
491 bkr.user_scale = bkj->user_scale;
492 // bkr.reports = bkj->reports;
493 bkr.ob_image.array = data->ob_image.array;
494 bkr.ob_image.len = data->ob_image.len;
495
496 /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
497 bkr.lores_dm = data->lores_dm;
498 bkr.hires_dm = data->hires_dm;
499 bkr.tot_lvl = data->tot_lvl;
500 bkr.lvl = data->lvl;
501
502 /* needed for proper progress bar */
503 bkr.tot_obj = tot_obj;
504 bkr.baked_objects = baked_objects;
505
506 bkr.stop = &worker_status->stop;
507 bkr.do_update = &worker_status->do_update;
508 bkr.progress = &worker_status->progress;
509
510 bkr.bias = bkj->bias;
512 bkr.threads = bkj->threads;
513
515
516 data->images = bkr.image;
517
518 baked_objects++;
519 }
520}
521
522static void multiresbake_freejob(void *bkv)
523{
524 MultiresBakeJob *bkj = static_cast<MultiresBakeJob *>(bkv);
526
527 data = static_cast<MultiresBakerJobData *>(bkj->data.first);
528 while (data) {
529 next = data->next;
530 data->lores_dm->release(data->lores_dm);
531 data->hires_dm->release(data->hires_dm);
532
533 /* delete here, since this delete will be called from main thread */
534 LISTBASE_FOREACH (LinkData *, link, &data->images) {
535 Image *ima = (Image *)link->data;
537 }
538
539 MEM_freeN(data->ob_image.array);
540
541 BLI_freelistN(&data->images);
542
543 MEM_freeN(data);
544 data = next;
545 }
546
547 MEM_freeN(bkj);
548}
549
551{
552 Scene *scene = CTX_data_scene(C);
553
554 if (!multiresbake_check(C, op)) {
555 return OPERATOR_CANCELLED;
556 }
557
558 MultiresBakeJob *bkr = MEM_cnew<MultiresBakeJob>(__func__);
559 init_multiresbake_job(C, bkr);
560
561 if (!bkr->data.first) {
562 BKE_report(op->reports, RPT_ERROR, "No objects found to bake from");
563 MEM_freeN(bkr);
564 return OPERATOR_CANCELLED;
565 }
566
567 /* setup job */
568 wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
569 CTX_wm_window(C),
570 scene,
571 "Multires Bake",
575 WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO: only draw bake image, can we enforce this. */
576 WM_jobs_callbacks(wm_job, multiresbake_startjob, nullptr, nullptr, nullptr);
577
578 G.is_break = false;
579
580 WM_jobs_start(CTX_wm_manager(C), wm_job);
581 WM_cursor_wait(false);
582
583 /* add modal handler for ESC */
585
587}
588
589/* ****************** render BAKING ********************** */
590
592static int objects_bake_render_modal(bContext *C, wmOperator * /*op*/, const wmEvent *event)
593{
594 /* no running blender, remove handler and pass through */
597 }
598
599 /* running render */
600 switch (event->type) {
601 case EVT_ESCKEY:
603 }
605}
606
607static bool is_multires_bake(Scene *scene)
608{
609 if (ELEM(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_AO)) {
610 return scene->r.bake_flag & R_BAKE_MULTIRES;
611 }
612
613 return false;
614}
615
616static int objects_bake_render_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
617{
618 Scene *scene = CTX_data_scene(C);
619 int result = OPERATOR_CANCELLED;
620
621 result = multiresbake_image_exec(C, op);
622
624
625 return result;
626}
627
629{
630 Scene *scene = CTX_data_scene(C);
631 int result = OPERATOR_CANCELLED;
632
633 if (!is_multires_bake(scene)) {
634 BLI_assert(0);
635 return result;
636 }
637
638 result = multiresbake_image_exec_locked(C, op);
639
641
642 return result;
643}
644
646{
647 /* identifiers */
648 ot->name = "Bake";
649 ot->description = "Bake image textures of selected objects";
650 ot->idname = "OBJECT_OT_bake_image";
651
652 /* api callbacks */
657}
658
659} // namespace blender::ed::object
#define CTX_DATA_BEGIN(C, Type, instance, member)
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
#define CTX_DATA_END
CustomData interface, see also DNA_customdata_types.h.
void CustomData_set_only_copy(const CustomData *data, eCustomDataMask mask)
const CustomData_MeshMasks CD_MASK_BAREMESH
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
void BKE_imageuser_default(ImageUser *iuser)
void BKE_image_partial_update_mark_full_update(Image *image)
Mark the whole image to be updated.
DerivedMesh * CDDM_from_mesh(Mesh *mesh)
void DM_set_only_copy(DerivedMesh *dm, const CustomData_MeshMasks *mask)
bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode)
MultiresModifierData * get_multires_modifier(Scene *scene, Object *ob, bool use_first)
Definition multires.cc:304
void multires_flush_sculpt_updates(Object *object)
Definition multires.cc:394
@ MULTIRES_IGNORE_SIMPLIFY
DerivedMesh * multires_make_derived_from_derived(DerivedMesh *dm, MultiresModifierData *mmd, Scene *scene, Object *ob, MultiresFlags flags)
Definition multires.cc:1215
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
int BKE_scene_num_threads(const Scene *scene)
Definition scene.cc:2872
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define ELEM(...)
@ ID_TAG_DOIT
Definition DNA_ID.h:1003
@ CD_PROP_FLOAT2
@ eModifierMode_Realtime
Object is a sort of wrapper for general info.
@ OB_MESH
@ R_BAKE_EXTEND
@ R_BAKE_LORES_MESH
@ R_BAKE_USERSCALE
@ R_BAKE_CLEAR
@ R_BAKE_MULTIRES
@ R_IMF_PLANES_RGBA
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
bool ED_operator_object_active(bContext *C)
bool ED_object_get_active_image(Object *ob, int mat_nr, Image **r_ima, ImageUser **r_iuser, const bNode **r_node, const bNodeTree **r_ntree)
void IMB_rectfill(ImBuf *drect, const float col[4])
Definition rectop.cc:1051
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
#define RE_BAKE_AO
#define RE_BAKE_NORMALS
#define RE_BAKE_DISPLACEMENT
@ WM_JOB_TYPE_OBJECT_BAKE_TEXTURE
Definition WM_api.hh:1584
@ WM_JOB_EXCL_RENDER
Definition WM_api.hh:1565
@ WM_JOB_PROGRESS
Definition WM_api.hh:1566
@ WM_JOB_PRIORITY
Definition WM_api.hh:1560
#define ND_RENDER_RESULT
Definition WM_types.hh:413
#define NC_SCENE
Definition WM_types.hh:345
#define NC_IMAGE
Definition WM_types.hh:351
constexpr bool is_empty() const
Definition BLI_span.hh:261
input_tx image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img") .compute_source("compositor_compute_preview.glsl") .do_static_compilation(true)
ccl_global const KernelWorkTile * tile
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
static ulong * next
#define G(x, y, z)
void RE_multires_bake_images(MultiresBakeRender *bkr)
static void clear_images_poly(Image **ob_image_array, int ob_image_array_len, ClearFlag flag)
static DerivedMesh * multiresbake_create_loresdm(Scene *scene, Object *ob, int *lvl)
static DerivedMesh * multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl)
void OBJECT_OT_bake_image(wmOperatorType *ot)
static int objects_bake_render_modal(bContext *C, wmOperator *, const wmEvent *event)
static void multiresbake_startjob(void *bkv, wmJobWorkerStatus *worker_status)
static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj)
static bool is_multires_bake(Scene *scene)
static void multiresbake_freejob(void *bkv)
static Image * bake_object_image_get(Object *ob, int mat_nr)
static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
static void clear_single_image(Image *image, ClearFlag flag)
static int bake_image_exec(bContext *C, wmOperator *op)
static int objects_bake_render_invoke(bContext *C, wmOperator *op, const wmEvent *)
static bool multiresbake_check(bContext *C, wmOperator *op)
static Image ** bake_object_image_get_array(Object *ob)
static int multiresbake_image_exec(bContext *C, wmOperator *op)
void(* release)(DerivedMesh *dm)
int tag
Definition DNA_ID.h:434
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
unsigned char planes
ListBase tiles
void * first
struct ModifierData * next
DerivedMesh * hires_dm
DerivedMesh * lores_dm
struct MultiresBakeRender::@1362 ob_image
struct blender::ed::object::MultiresBakerJobData::@448 ob_image
short type
Definition WM_types.hh:722
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(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1036
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
struct ReportList * reports
void WM_cursor_wait(bool val)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ EVT_ESCKEY
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
bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
Definition wm_jobs.cc:223
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *customdata))
Definition wm_jobs.cc:336
uint8_t flag
Definition wm_window.cc:138