diff options
Diffstat (limited to 'source/blender/editors/render')
-rw-r--r-- | source/blender/editors/render/CMakeLists.txt | 62 | ||||
-rw-r--r-- | source/blender/editors/render/render_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/render/render_internal.c | 1792 | ||||
-rw-r--r-- | source/blender/editors/render/render_opengl.c | 1879 | ||||
-rw-r--r-- | source/blender/editors/render/render_ops.c | 92 | ||||
-rw-r--r-- | source/blender/editors/render/render_preview.c | 2221 | ||||
-rw-r--r-- | source/blender/editors/render/render_shading.c | 2551 | ||||
-rw-r--r-- | source/blender/editors/render/render_update.c | 387 | ||||
-rw-r--r-- | source/blender/editors/render/render_view.c | 521 |
9 files changed, 4848 insertions, 4659 deletions
diff --git a/source/blender/editors/render/CMakeLists.txt b/source/blender/editors/render/CMakeLists.txt index dee56d7f2fa..5d414c3af0f 100644 --- a/source/blender/editors/render/CMakeLists.txt +++ b/source/blender/editors/render/CMakeLists.txt @@ -16,58 +16,58 @@ # ***** END GPL LICENSE BLOCK ***** set(INC - ../include - ../../blenkernel - ../../blenlib - ../../blenloader - ../../blentranslation - ../../depsgraph - ../../draw - ../../gpu - ../../imbuf - ../../bmesh - ../../makesdna - ../../makesrna - ../../render/extern/include - ../../windowmanager - ../../../../intern/guardedalloc - ../../../../intern/glew-mx + ../include + ../../blenkernel + ../../blenlib + ../../blenloader + ../../blentranslation + ../../depsgraph + ../../draw + ../../gpu + ../../imbuf + ../../bmesh + ../../makesdna + ../../makesrna + ../../render/extern/include + ../../windowmanager + ../../../../intern/guardedalloc + ../../../../intern/glew-mx ) set(INC_SYS - ${GLEW_INCLUDE_PATH} + ${GLEW_INCLUDE_PATH} ) set(SRC - render_internal.c - render_opengl.c - render_ops.c - render_preview.c - render_shading.c - render_update.c - render_view.c + render_internal.c + render_opengl.c + render_ops.c + render_preview.c + render_shading.c + render_update.c + render_view.c - render_intern.h + render_intern.h ) set(LIB ) if(WITH_HEADLESS) - add_definitions(-DWITH_HEADLESS) + add_definitions(-DWITH_HEADLESS) endif() add_definitions(${GL_DEFINITIONS}) if(WITH_FREESTYLE) - list(APPEND INC - ../../freestyle - ) - add_definitions(-DWITH_FREESTYLE) + list(APPEND INC + ../../freestyle + ) + add_definitions(-DWITH_FREESTYLE) endif() if(WITH_INTERNATIONAL) - add_definitions(-DWITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) endif() blender_add_lib(bf_editor_render "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h index 88f6df50420..1e03d986e3e 100644 --- a/source/blender/editors/render/render_intern.h +++ b/source/blender/editors/render/render_intern.h @@ -21,7 +21,6 @@ * \ingroup edrend */ - #ifndef __RENDER_INTERN_H__ #define __RENDER_INTERN_H__ @@ -75,7 +74,6 @@ void SCENE_OT_freestyle_modifier_copy(struct wmOperatorType *ot); void SCENE_OT_freestyle_stroke_material_create(struct wmOperatorType *ot); #endif - void TEXTURE_OT_slot_copy(struct wmOperatorType *ot); void TEXTURE_OT_slot_paste(struct wmOperatorType *ot); void TEXTURE_OT_slot_move(struct wmOperatorType *ot); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index b5546bd7b90..6df1ba5e0aa 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -21,7 +21,6 @@ * \ingroup edrend */ - #include <math.h> #include <string.h> #include <stddef.h> @@ -92,160 +91,175 @@ static int render_break(void *rjv); typedef struct RenderJob { - Main *main; - Scene *scene; - ViewLayer *single_layer; - Scene *current_scene; - /* TODO(sergey): Should not be needed once engine will have own - * depsgraph and copy-on-write will be implemented. - */ - Depsgraph *depsgraph; - Render *re; - struct Object *camera_override; - bool v3d_override; - bool anim, write_still; - Image *image; - ImageUser iuser; - bool image_outdated; - short *stop; - short *do_update; - float *progress; - ReportList *reports; - int orig_layer; - int last_layer; - ScrArea *sa; - ColorManagedViewSettings view_settings; - ColorManagedDisplaySettings display_settings; - bool supports_glsl_draw; - bool interface_locked; + Main *main; + Scene *scene; + ViewLayer *single_layer; + Scene *current_scene; + /* TODO(sergey): Should not be needed once engine will have own + * depsgraph and copy-on-write will be implemented. + */ + Depsgraph *depsgraph; + Render *re; + struct Object *camera_override; + bool v3d_override; + bool anim, write_still; + Image *image; + ImageUser iuser; + bool image_outdated; + short *stop; + short *do_update; + float *progress; + ReportList *reports; + int orig_layer; + int last_layer; + ScrArea *sa; + ColorManagedViewSettings view_settings; + ColorManagedDisplaySettings display_settings; + bool supports_glsl_draw; + bool interface_locked; } RenderJob; /* called inside thread! */ -static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibuf, ImageUser *iuser, volatile rcti *renrect, const char *viewname) +static void image_buffer_rect_update(RenderJob *rj, + RenderResult *rr, + ImBuf *ibuf, + ImageUser *iuser, + volatile rcti *renrect, + const char *viewname) { - Scene *scene = rj->scene; - const float *rectf = NULL; - int ymin, ymax, xmin, xmax; - int rymin, rxmin; - int linear_stride, linear_offset_x, linear_offset_y; - ColorManagedViewSettings *view_settings; - ColorManagedDisplaySettings *display_settings; - - /* Exception for exr tiles -- display buffer conversion happens here, - * NOT in the color management pipeline. - */ - if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID && - rr->do_exr_tile == false) - { - /* The whole image buffer it so be color managed again anyway. */ - return; - } - - /* if renrect argument, we only refresh scanlines */ - if (renrect) { - /* if (ymax == recty), rendering of layer is ready, - * we should not draw, other things happen... */ - if (rr->renlay == NULL || renrect->ymax >= rr->recty) - return; - - /* xmin here is first subrect x coord, xmax defines subrect width */ - xmin = renrect->xmin + rr->crop; - xmax = renrect->xmax - xmin + rr->crop; - if (xmax < 2) - return; - - ymin = renrect->ymin + rr->crop; - ymax = renrect->ymax - ymin + rr->crop; - if (ymax < 2) - return; - renrect->ymin = renrect->ymax; - - } - else { - xmin = ymin = rr->crop; - xmax = rr->rectx - 2 * rr->crop; - ymax = rr->recty - 2 * rr->crop; - } - - /* xmin ymin is in tile coords. transform to ibuf */ - rxmin = rr->tilerect.xmin + xmin; - if (rxmin >= ibuf->x) return; - rymin = rr->tilerect.ymin + ymin; - if (rymin >= ibuf->y) return; - - if (rxmin + xmax > ibuf->x) - xmax = ibuf->x - rxmin; - if (rymin + ymax > ibuf->y) - ymax = ibuf->y - rymin; - - if (xmax < 1 || ymax < 1) return; - - /* The thing here is, the logic below (which was default behavior - * of how rectf is acquiring since forever) gives float buffer for - * composite output only. This buffer can not be used for other - * passes obviously. - * - * We might try finding corresponding for pass buffer in render result - * (which is actually missing when rendering with Cycles, who only - * writes all the passes when the tile is finished) or use float - * buffer from image buffer as reference, which is easier to use and - * contains all the data we need anyway. - * - sergey - - */ - /* TODO(sergey): Need to check has_combined here? */ - if (iuser->pass == 0) { - RenderView *rv; - const int view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname); - rv = RE_RenderViewGetById(rr, view_id); - - /* find current float rect for display, first case is after composite... still weak */ - if (rv->rectf) - rectf = rv->rectf; - else { - if (rv->rect32) { - /* special case, currently only happens with sequencer rendering, - * which updates the whole frame, so we can only mark display buffer - * as invalid here (sergey) - */ - ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; - return; - } - else { - if (rr->renlay == NULL) return; - rectf = RE_RenderLayerGetPass(rr->renlay, RE_PASSNAME_COMBINED, viewname); - } - } - if (rectf == NULL) return; - - rectf += 4 * (rr->rectx * ymin + xmin); - linear_stride = rr->rectx; - linear_offset_x = rxmin; - linear_offset_y = rymin; - } - else { - rectf = ibuf->rect_float; - linear_stride = ibuf->x; - linear_offset_x = 0; - linear_offset_y = 0; - } - - if (rr->do_exr_tile) { - /* We don't support changing color management settings during rendering - * when using Save Buffers option. - */ - view_settings = &rj->view_settings; - display_settings = &rj->display_settings; - } - else { - view_settings = &scene->view_settings; - display_settings = &scene->display_settings; - } - - IMB_partial_display_buffer_update(ibuf, rectf, NULL, - linear_stride, linear_offset_x, linear_offset_y, - view_settings, display_settings, - rxmin, rymin, rxmin + xmax, rymin + ymax, - rr->do_exr_tile); + Scene *scene = rj->scene; + const float *rectf = NULL; + int ymin, ymax, xmin, xmax; + int rymin, rxmin; + int linear_stride, linear_offset_x, linear_offset_y; + ColorManagedViewSettings *view_settings; + ColorManagedDisplaySettings *display_settings; + + /* Exception for exr tiles -- display buffer conversion happens here, + * NOT in the color management pipeline. + */ + if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID && rr->do_exr_tile == false) { + /* The whole image buffer it so be color managed again anyway. */ + return; + } + + /* if renrect argument, we only refresh scanlines */ + if (renrect) { + /* if (ymax == recty), rendering of layer is ready, + * we should not draw, other things happen... */ + if (rr->renlay == NULL || renrect->ymax >= rr->recty) + return; + + /* xmin here is first subrect x coord, xmax defines subrect width */ + xmin = renrect->xmin + rr->crop; + xmax = renrect->xmax - xmin + rr->crop; + if (xmax < 2) + return; + + ymin = renrect->ymin + rr->crop; + ymax = renrect->ymax - ymin + rr->crop; + if (ymax < 2) + return; + renrect->ymin = renrect->ymax; + } + else { + xmin = ymin = rr->crop; + xmax = rr->rectx - 2 * rr->crop; + ymax = rr->recty - 2 * rr->crop; + } + + /* xmin ymin is in tile coords. transform to ibuf */ + rxmin = rr->tilerect.xmin + xmin; + if (rxmin >= ibuf->x) + return; + rymin = rr->tilerect.ymin + ymin; + if (rymin >= ibuf->y) + return; + + if (rxmin + xmax > ibuf->x) + xmax = ibuf->x - rxmin; + if (rymin + ymax > ibuf->y) + ymax = ibuf->y - rymin; + + if (xmax < 1 || ymax < 1) + return; + + /* The thing here is, the logic below (which was default behavior + * of how rectf is acquiring since forever) gives float buffer for + * composite output only. This buffer can not be used for other + * passes obviously. + * + * We might try finding corresponding for pass buffer in render result + * (which is actually missing when rendering with Cycles, who only + * writes all the passes when the tile is finished) or use float + * buffer from image buffer as reference, which is easier to use and + * contains all the data we need anyway. + * - sergey - + */ + /* TODO(sergey): Need to check has_combined here? */ + if (iuser->pass == 0) { + RenderView *rv; + const int view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname); + rv = RE_RenderViewGetById(rr, view_id); + + /* find current float rect for display, first case is after composite... still weak */ + if (rv->rectf) + rectf = rv->rectf; + else { + if (rv->rect32) { + /* special case, currently only happens with sequencer rendering, + * which updates the whole frame, so we can only mark display buffer + * as invalid here (sergey) + */ + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + return; + } + else { + if (rr->renlay == NULL) + return; + rectf = RE_RenderLayerGetPass(rr->renlay, RE_PASSNAME_COMBINED, viewname); + } + } + if (rectf == NULL) + return; + + rectf += 4 * (rr->rectx * ymin + xmin); + linear_stride = rr->rectx; + linear_offset_x = rxmin; + linear_offset_y = rymin; + } + else { + rectf = ibuf->rect_float; + linear_stride = ibuf->x; + linear_offset_x = 0; + linear_offset_y = 0; + } + + if (rr->do_exr_tile) { + /* We don't support changing color management settings during rendering + * when using Save Buffers option. + */ + view_settings = &rj->view_settings; + display_settings = &rj->display_settings; + } + else { + view_settings = &scene->view_settings; + display_settings = &scene->display_settings; + } + + IMB_partial_display_buffer_update(ibuf, + rectf, + NULL, + linear_stride, + linear_offset_x, + linear_offset_y, + view_settings, + display_settings, + rxmin, + rymin, + rxmin + xmax, + rymin + ymax, + rr->do_exr_tile); } /* ****************************** render invoking ***************** */ @@ -253,108 +267,118 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu /* set callbacks, exported to sequence render too. * Only call in foreground (UI) renders. */ -static void screen_render_single_layer_set(wmOperator *op, Main *mainp, ViewLayer *active_layer, Scene **scene, ViewLayer **single_layer) +static void screen_render_single_layer_set( + wmOperator *op, Main *mainp, ViewLayer *active_layer, Scene **scene, ViewLayer **single_layer) { - /* single layer re-render */ - if (RNA_struct_property_is_set(op->ptr, "scene")) { - Scene *scn; - char scene_name[MAX_ID_NAME - 2]; - - RNA_string_get(op->ptr, "scene", scene_name); - scn = (Scene *)BLI_findstring(&mainp->scenes, scene_name, offsetof(ID, name) + 2); - - if (scn) { - /* camera switch wont have updated */ - scn->r.cfra = (*scene)->r.cfra; - BKE_scene_camera_switch_update(scn); - - *scene = scn; - } - } - - if (RNA_struct_property_is_set(op->ptr, "layer")) { - ViewLayer *rl; - char rl_name[RE_MAXNAME]; - - RNA_string_get(op->ptr, "layer", rl_name); - rl = (ViewLayer *)BLI_findstring(&(*scene)->view_layers, rl_name, offsetof(ViewLayer, name)); - - if (rl) - *single_layer = rl; - } - else if (((*scene)->r.scemode & R_SINGLE_LAYER) && active_layer) { - *single_layer = active_layer; - } + /* single layer re-render */ + if (RNA_struct_property_is_set(op->ptr, "scene")) { + Scene *scn; + char scene_name[MAX_ID_NAME - 2]; + + RNA_string_get(op->ptr, "scene", scene_name); + scn = (Scene *)BLI_findstring(&mainp->scenes, scene_name, offsetof(ID, name) + 2); + + if (scn) { + /* camera switch wont have updated */ + scn->r.cfra = (*scene)->r.cfra; + BKE_scene_camera_switch_update(scn); + + *scene = scn; + } + } + + if (RNA_struct_property_is_set(op->ptr, "layer")) { + ViewLayer *rl; + char rl_name[RE_MAXNAME]; + + RNA_string_get(op->ptr, "layer", rl_name); + rl = (ViewLayer *)BLI_findstring(&(*scene)->view_layers, rl_name, offsetof(ViewLayer, name)); + + if (rl) + *single_layer = rl; + } + else if (((*scene)->r.scemode & R_SINGLE_LAYER) && active_layer) { + *single_layer = active_layer; + } } /* executes blocking render */ static int screen_render_exec(bContext *C, wmOperator *op) { - Scene *scene = CTX_data_scene(C); - RenderEngineType *re_type = RE_engines_find(scene->r.engine); - ViewLayer *active_layer = CTX_data_view_layer(C); - ViewLayer *single_layer = NULL; - Render *re; - Image *ima; - View3D *v3d = CTX_wm_view3d(C); - Main *mainp = CTX_data_main(C); - const bool is_animation = RNA_boolean_get(op->ptr, "animation"); - const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); - struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL; - - /* Cannot do render if there is not this function. */ - if (re_type->render == NULL) { - return OPERATOR_CANCELLED; - } - - /* custom scene and single layer re-render */ - screen_render_single_layer_set(op, mainp, active_layer, &scene, &single_layer); - - if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) { - BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected"); - return OPERATOR_CANCELLED; - } - - re = RE_NewSceneRender(scene); - - G.is_break = false; - RE_test_break_cb(re, NULL, render_break); - - ima = BKE_image_verify_viewer(mainp, IMA_TYPE_R_RESULT, "Render Result"); - BKE_image_signal(mainp, ima, NULL, IMA_SIGNAL_FREE); - BKE_image_backup_render(scene, ima, true); - - /* cleanup sequencer caches before starting user triggered render. - * otherwise, invalidated cache entries can make their way into - * the output rendering. We can't put that into RE_BlenderFrame, - * since sequence rendering can call that recursively... (peter) */ - BKE_sequencer_cache_cleanup(); - - RE_SetReports(re, op->reports); - - BLI_threaded_malloc_begin(); - if (is_animation) - RE_BlenderAnim(re, mainp, scene, single_layer, camera_override, scene->r.sfra, scene->r.efra, scene->r.frame_step); - else - RE_BlenderFrame(re, mainp, scene, single_layer, camera_override, scene->r.cfra, is_write_still); - BLI_threaded_malloc_end(); - - RE_SetReports(re, NULL); - - // no redraw needed, we leave state as we entered it - ED_update_for_newframe(mainp, CTX_data_depsgraph(C)); - - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene); - - return OPERATOR_FINISHED; + Scene *scene = CTX_data_scene(C); + RenderEngineType *re_type = RE_engines_find(scene->r.engine); + ViewLayer *active_layer = CTX_data_view_layer(C); + ViewLayer *single_layer = NULL; + Render *re; + Image *ima; + View3D *v3d = CTX_wm_view3d(C); + Main *mainp = CTX_data_main(C); + const bool is_animation = RNA_boolean_get(op->ptr, "animation"); + const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); + struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL; + + /* Cannot do render if there is not this function. */ + if (re_type->render == NULL) { + return OPERATOR_CANCELLED; + } + + /* custom scene and single layer re-render */ + screen_render_single_layer_set(op, mainp, active_layer, &scene, &single_layer); + + if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) { + BKE_report( + op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected"); + return OPERATOR_CANCELLED; + } + + re = RE_NewSceneRender(scene); + + G.is_break = false; + RE_test_break_cb(re, NULL, render_break); + + ima = BKE_image_verify_viewer(mainp, IMA_TYPE_R_RESULT, "Render Result"); + BKE_image_signal(mainp, ima, NULL, IMA_SIGNAL_FREE); + BKE_image_backup_render(scene, ima, true); + + /* cleanup sequencer caches before starting user triggered render. + * otherwise, invalidated cache entries can make their way into + * the output rendering. We can't put that into RE_BlenderFrame, + * since sequence rendering can call that recursively... (peter) */ + BKE_sequencer_cache_cleanup(); + + RE_SetReports(re, op->reports); + + BLI_threaded_malloc_begin(); + if (is_animation) + RE_BlenderAnim(re, + mainp, + scene, + single_layer, + camera_override, + scene->r.sfra, + scene->r.efra, + scene->r.frame_step); + else + RE_BlenderFrame( + re, mainp, scene, single_layer, camera_override, scene->r.cfra, is_write_still); + BLI_threaded_malloc_end(); + + RE_SetReports(re, NULL); + + // no redraw needed, we leave state as we entered it + ED_update_for_newframe(mainp, CTX_data_depsgraph(C)); + + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene); + + return OPERATOR_FINISHED; } static void render_freejob(void *rjv) { - RenderJob *rj = rjv; + RenderJob *rj = rjv; - BKE_color_managed_view_settings_free(&rj->view_settings); - MEM_freeN(rj); + BKE_color_managed_view_settings_free(&rj->view_settings); + MEM_freeN(rj); } /* str is IMA_MAX_RENDER_TEXT in size */ @@ -364,124 +388,130 @@ static void make_renderinfo_string(const RenderStats *rs, const char *error, char *str) { - char info_time_str[32]; // used to be extern to header_info.c - uintptr_t mem_in_use, mmap_in_use, peak_memory; - float megs_used_memory, mmap_used_memory, megs_peak_memory; - char *spos = str; - - mem_in_use = MEM_get_memory_in_use(); - mmap_in_use = MEM_get_mapped_memory_in_use(); - peak_memory = MEM_get_peak_memory(); - - megs_used_memory = (mem_in_use - mmap_in_use) / (1024.0 * 1024.0); - mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0); - megs_peak_memory = (peak_memory) / (1024.0 * 1024.0); - - /* local view */ - if (rs->localview) - spos += sprintf(spos, "%s | ", IFACE_("3D Local View")); - else if (v3d_override) - spos += sprintf(spos, "%s | ", IFACE_("3D View")); - - /* frame number */ - spos += sprintf(spos, IFACE_("Frame:%d "), (scene->r.cfra)); - - /* previous and elapsed time */ - BLI_timecode_string_from_time_simple(info_time_str, sizeof(info_time_str), rs->lastframetime); - - if (rs->infostr && rs->infostr[0]) { - if (rs->lastframetime != 0.0) - spos += sprintf(spos, IFACE_("| Last:%s "), info_time_str); - else - spos += sprintf(spos, "| "); - - BLI_timecode_string_from_time_simple(info_time_str, sizeof(info_time_str), PIL_check_seconds_timer() - rs->starttime); - } - else - spos += sprintf(spos, "| "); - - spos += sprintf(spos, IFACE_("Time:%s "), info_time_str); - - /* statistics */ - if (rs->statstr) { - if (rs->statstr[0]) { - spos += sprintf(spos, "| %s ", rs->statstr); - } - } - else { - if (rs->totvert || rs->totface || rs->tothalo || rs->totstrand || rs->totlamp) - spos += sprintf(spos, "| "); - - if (rs->totvert) spos += sprintf(spos, IFACE_("Ve:%d "), rs->totvert); - if (rs->totface) spos += sprintf(spos, IFACE_("Fa:%d "), rs->totface); - if (rs->tothalo) spos += sprintf(spos, IFACE_("Ha:%d "), rs->tothalo); - if (rs->totstrand) spos += sprintf(spos, IFACE_("St:%d "), rs->totstrand); - if (rs->totlamp) spos += sprintf(spos, IFACE_("Li:%d "), rs->totlamp); - - if (rs->mem_peak == 0.0f) - spos += sprintf(spos, IFACE_("| Mem:%.2fM (%.2fM, Peak %.2fM) "), - megs_used_memory, mmap_used_memory, megs_peak_memory); - else - spos += sprintf(spos, IFACE_("| Mem:%.2fM, Peak: %.2fM "), rs->mem_used, rs->mem_peak); - - if (rs->curfield) - spos += sprintf(spos, IFACE_("Field %d "), rs->curfield); - if (rs->curblur) - spos += sprintf(spos, IFACE_("Blur %d "), rs->curblur); - } - - /* full sample */ - if (rs->curfsa) - spos += sprintf(spos, IFACE_("| Full Sample %d "), rs->curfsa); - - /* extra info */ - if (rs->infostr && rs->infostr[0]) { - spos += sprintf(spos, "| %s ", rs->infostr); - } - else if (error && error[0]) { - spos += sprintf(spos, "| %s ", error); - } - - /* very weak... but 512 characters is quite safe */ - if (spos >= str + IMA_MAX_RENDER_TEXT) - if (G.debug & G_DEBUG) - printf("WARNING! renderwin text beyond limit\n"); - + char info_time_str[32]; // used to be extern to header_info.c + uintptr_t mem_in_use, mmap_in_use, peak_memory; + float megs_used_memory, mmap_used_memory, megs_peak_memory; + char *spos = str; + + mem_in_use = MEM_get_memory_in_use(); + mmap_in_use = MEM_get_mapped_memory_in_use(); + peak_memory = MEM_get_peak_memory(); + + megs_used_memory = (mem_in_use - mmap_in_use) / (1024.0 * 1024.0); + mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0); + megs_peak_memory = (peak_memory) / (1024.0 * 1024.0); + + /* local view */ + if (rs->localview) + spos += sprintf(spos, "%s | ", IFACE_("3D Local View")); + else if (v3d_override) + spos += sprintf(spos, "%s | ", IFACE_("3D View")); + + /* frame number */ + spos += sprintf(spos, IFACE_("Frame:%d "), (scene->r.cfra)); + + /* previous and elapsed time */ + BLI_timecode_string_from_time_simple(info_time_str, sizeof(info_time_str), rs->lastframetime); + + if (rs->infostr && rs->infostr[0]) { + if (rs->lastframetime != 0.0) + spos += sprintf(spos, IFACE_("| Last:%s "), info_time_str); + else + spos += sprintf(spos, "| "); + + BLI_timecode_string_from_time_simple( + info_time_str, sizeof(info_time_str), PIL_check_seconds_timer() - rs->starttime); + } + else + spos += sprintf(spos, "| "); + + spos += sprintf(spos, IFACE_("Time:%s "), info_time_str); + + /* statistics */ + if (rs->statstr) { + if (rs->statstr[0]) { + spos += sprintf(spos, "| %s ", rs->statstr); + } + } + else { + if (rs->totvert || rs->totface || rs->tothalo || rs->totstrand || rs->totlamp) + spos += sprintf(spos, "| "); + + if (rs->totvert) + spos += sprintf(spos, IFACE_("Ve:%d "), rs->totvert); + if (rs->totface) + spos += sprintf(spos, IFACE_("Fa:%d "), rs->totface); + if (rs->tothalo) + spos += sprintf(spos, IFACE_("Ha:%d "), rs->tothalo); + if (rs->totstrand) + spos += sprintf(spos, IFACE_("St:%d "), rs->totstrand); + if (rs->totlamp) + spos += sprintf(spos, IFACE_("Li:%d "), rs->totlamp); + + if (rs->mem_peak == 0.0f) + spos += sprintf(spos, + IFACE_("| Mem:%.2fM (%.2fM, Peak %.2fM) "), + megs_used_memory, + mmap_used_memory, + megs_peak_memory); + else + spos += sprintf(spos, IFACE_("| Mem:%.2fM, Peak: %.2fM "), rs->mem_used, rs->mem_peak); + + if (rs->curfield) + spos += sprintf(spos, IFACE_("Field %d "), rs->curfield); + if (rs->curblur) + spos += sprintf(spos, IFACE_("Blur %d "), rs->curblur); + } + + /* full sample */ + if (rs->curfsa) + spos += sprintf(spos, IFACE_("| Full Sample %d "), rs->curfsa); + + /* extra info */ + if (rs->infostr && rs->infostr[0]) { + spos += sprintf(spos, "| %s ", rs->infostr); + } + else if (error && error[0]) { + spos += sprintf(spos, "| %s ", error); + } + + /* very weak... but 512 characters is quite safe */ + if (spos >= str + IMA_MAX_RENDER_TEXT) + if (G.debug & G_DEBUG) + printf("WARNING! renderwin text beyond limit\n"); } static void image_renderinfo_cb(void *rjv, RenderStats *rs) { - RenderJob *rj = rjv; - RenderResult *rr; - - rr = RE_AcquireResultRead(rj->re); + RenderJob *rj = rjv; + RenderResult *rr; - if (rr) { - /* malloc OK here, stats_draw is not in tile threads */ - if (rr->text == NULL) - rr->text = MEM_callocN(IMA_MAX_RENDER_TEXT, "rendertext"); + rr = RE_AcquireResultRead(rj->re); - make_renderinfo_string(rs, rj->scene, rj->v3d_override, - rr->error, rr->text); - } + if (rr) { + /* malloc OK here, stats_draw is not in tile threads */ + if (rr->text == NULL) + rr->text = MEM_callocN(IMA_MAX_RENDER_TEXT, "rendertext"); - RE_ReleaseResult(rj->re); + make_renderinfo_string(rs, rj->scene, rj->v3d_override, rr->error, rr->text); + } - /* make jobs timer to send notifier */ - *(rj->do_update) = true; + RE_ReleaseResult(rj->re); + /* make jobs timer to send notifier */ + *(rj->do_update) = true; } static void render_progress_update(void *rjv, float progress) { - RenderJob *rj = rjv; + RenderJob *rj = rjv; - if (rj->progress && *rj->progress != progress) { - *rj->progress = progress; + if (rj->progress && *rj->progress != progress) { + *rj->progress = progress; - /* make jobs timer to send notifier */ - *(rj->do_update) = true; - } + /* make jobs timer to send notifier */ + *(rj->do_update) = true; + } } /* Not totally reliable, but works fine in most of cases and @@ -491,615 +521,645 @@ static void render_progress_update(void *rjv, float progress) */ static void render_image_update_pass_and_layer(RenderJob *rj, RenderResult *rr, ImageUser *iuser) { - wmWindowManager *wm; - ScrArea *first_sa = NULL, *matched_sa = NULL; - - /* image window, compo node users */ - for (wm = rj->main->wm.first; wm && matched_sa == NULL; wm = wm->id.next) { /* only 1 wm */ - wmWindow *win; - for (win = wm->windows.first; win && matched_sa == NULL; win = win->next) { - const bScreen *screen = WM_window_get_active_screen(win); - - for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { - if (sa->spacetype == SPACE_IMAGE) { - SpaceImage *sima = sa->spacedata.first; - // sa->spacedata might be empty when toggling fullscreen mode. - if (sima != NULL && sima->image == rj->image) { - if (first_sa == NULL) { - first_sa = sa; - } - if (sa == rj->sa) { - matched_sa = sa; - break; - } - } - } - } - } - } - - if (matched_sa == NULL) { - matched_sa = first_sa; - } - - if (matched_sa) { - SpaceImage *sima = matched_sa->spacedata.first; - RenderResult *main_rr = RE_AcquireResultRead(rj->re); - - /* TODO(sergey): is there faster way to get the layer index? */ - if (rr->renlay) { - int layer = BLI_findstringindex(&main_rr->layers, - (char *)rr->renlay->name, - offsetof(RenderLayer, name)); - sima->iuser.layer = layer; - rj->last_layer = layer; - } - - iuser->pass = sima->iuser.pass; - iuser->layer = sima->iuser.layer; - - RE_ReleaseResult(rj->re); - } + wmWindowManager *wm; + ScrArea *first_sa = NULL, *matched_sa = NULL; + + /* image window, compo node users */ + for (wm = rj->main->wm.first; wm && matched_sa == NULL; wm = wm->id.next) { /* only 1 wm */ + wmWindow *win; + for (win = wm->windows.first; win && matched_sa == NULL; win = win->next) { + const bScreen *screen = WM_window_get_active_screen(win); + + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (sa->spacetype == SPACE_IMAGE) { + SpaceImage *sima = sa->spacedata.first; + // sa->spacedata might be empty when toggling fullscreen mode. + if (sima != NULL && sima->image == rj->image) { + if (first_sa == NULL) { + first_sa = sa; + } + if (sa == rj->sa) { + matched_sa = sa; + break; + } + } + } + } + } + } + + if (matched_sa == NULL) { + matched_sa = first_sa; + } + + if (matched_sa) { + SpaceImage *sima = matched_sa->spacedata.first; + RenderResult *main_rr = RE_AcquireResultRead(rj->re); + + /* TODO(sergey): is there faster way to get the layer index? */ + if (rr->renlay) { + int layer = BLI_findstringindex( + &main_rr->layers, (char *)rr->renlay->name, offsetof(RenderLayer, name)); + sima->iuser.layer = layer; + rj->last_layer = layer; + } + + iuser->pass = sima->iuser.pass; + iuser->layer = sima->iuser.layer; + + RE_ReleaseResult(rj->re); + } } static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect) { - RenderJob *rj = rjv; - Image *ima = rj->image; - ImBuf *ibuf; - void *lock; - const char *viewname = RE_GetActiveRenderView(rj->re); - - /* only update if we are displaying the slot being rendered */ - if (ima->render_slot != ima->last_render_slot) { - rj->image_outdated = true; - return; - } - else if (rj->image_outdated) { - /* update entire render */ - rj->image_outdated = false; - BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_COLORMANAGE); - *(rj->do_update) = true; - return; - } - - if (rr == NULL) - return; - - /* update part of render */ - render_image_update_pass_and_layer(rj, rr, &rj->iuser); - ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock); - if (ibuf) { - /* Don't waste time on CPU side color management if - * image will be displayed using GLSL. - * - * Need to update rect if Save Buffers enabled because in - * this case GLSL doesn't have original float buffer to - * operate with. - */ - if (rr->do_exr_tile || - !rj->supports_glsl_draw || - ibuf->channels == 1 || - U.image_draw_method != IMAGE_DRAW_METHOD_GLSL) - { - image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect, viewname); - } - - /* make jobs timer to send notifier */ - *(rj->do_update) = true; - } - BKE_image_release_ibuf(ima, ibuf, lock); + RenderJob *rj = rjv; + Image *ima = rj->image; + ImBuf *ibuf; + void *lock; + const char *viewname = RE_GetActiveRenderView(rj->re); + + /* only update if we are displaying the slot being rendered */ + if (ima->render_slot != ima->last_render_slot) { + rj->image_outdated = true; + return; + } + else if (rj->image_outdated) { + /* update entire render */ + rj->image_outdated = false; + BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_COLORMANAGE); + *(rj->do_update) = true; + return; + } + + if (rr == NULL) + return; + + /* update part of render */ + render_image_update_pass_and_layer(rj, rr, &rj->iuser); + ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock); + if (ibuf) { + /* Don't waste time on CPU side color management if + * image will be displayed using GLSL. + * + * Need to update rect if Save Buffers enabled because in + * this case GLSL doesn't have original float buffer to + * operate with. + */ + if (rr->do_exr_tile || !rj->supports_glsl_draw || ibuf->channels == 1 || + U.image_draw_method != IMAGE_DRAW_METHOD_GLSL) { + image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect, viewname); + } + + /* make jobs timer to send notifier */ + *(rj->do_update) = true; + } + BKE_image_release_ibuf(ima, ibuf, lock); } static void current_scene_update(void *rjv, Scene *scene) { - RenderJob *rj = rjv; - rj->current_scene = scene; - rj->iuser.scene = scene; + RenderJob *rj = rjv; + rj->current_scene = scene; + rj->iuser.scene = scene; } static void render_startjob(void *rjv, short *stop, short *do_update, float *progress) { - RenderJob *rj = rjv; - - rj->stop = stop; - rj->do_update = do_update; - rj->progress = progress; - - RE_SetReports(rj->re, rj->reports); - - if (rj->anim) - RE_BlenderAnim(rj->re, rj->main, rj->scene, rj->single_layer, rj->camera_override, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->r.frame_step); - else - RE_BlenderFrame(rj->re, rj->main, rj->scene, rj->single_layer, rj->camera_override, rj->scene->r.cfra, rj->write_still); - - RE_SetReports(rj->re, NULL); + RenderJob *rj = rjv; + + rj->stop = stop; + rj->do_update = do_update; + rj->progress = progress; + + RE_SetReports(rj->re, rj->reports); + + if (rj->anim) + RE_BlenderAnim(rj->re, + rj->main, + rj->scene, + rj->single_layer, + rj->camera_override, + rj->scene->r.sfra, + rj->scene->r.efra, + rj->scene->r.frame_step); + else + RE_BlenderFrame(rj->re, + rj->main, + rj->scene, + rj->single_layer, + rj->camera_override, + rj->scene->r.cfra, + rj->write_still); + + RE_SetReports(rj->re, NULL); } static void render_image_restore_layer(RenderJob *rj) { - wmWindowManager *wm; - - /* image window, compo node users */ - for (wm = rj->main->wm.first; wm; wm = wm->id.next) { /* only 1 wm */ - wmWindow *win; - for (win = wm->windows.first; win; win = win->next) { - const bScreen *screen = WM_window_get_active_screen(win); - - for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { - if (sa == rj->sa) { - if (sa->spacetype == SPACE_IMAGE) { - SpaceImage *sima = sa->spacedata.first; - - if (RE_HasSingleLayer(rj->re)) { - /* For single layer renders keep the active layer - * visible, or show the compositing result. */ - RenderResult *rr = RE_AcquireResultRead(rj->re); - if (RE_HasCombinedLayer(rr)) { - sima->iuser.layer = 0; - } - RE_ReleaseResult(rj->re); - } - else { - /* For multiple layer render, set back the layer - * that was set at the start of rendering. */ - sima->iuser.layer = rj->orig_layer; - } - } - return; - } - } - } - } + wmWindowManager *wm; + + /* image window, compo node users */ + for (wm = rj->main->wm.first; wm; wm = wm->id.next) { /* only 1 wm */ + wmWindow *win; + for (win = wm->windows.first; win; win = win->next) { + const bScreen *screen = WM_window_get_active_screen(win); + + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (sa == rj->sa) { + if (sa->spacetype == SPACE_IMAGE) { + SpaceImage *sima = sa->spacedata.first; + + if (RE_HasSingleLayer(rj->re)) { + /* For single layer renders keep the active layer + * visible, or show the compositing result. */ + RenderResult *rr = RE_AcquireResultRead(rj->re); + if (RE_HasCombinedLayer(rr)) { + sima->iuser.layer = 0; + } + RE_ReleaseResult(rj->re); + } + else { + /* For multiple layer render, set back the layer + * that was set at the start of rendering. */ + sima->iuser.layer = rj->orig_layer; + } + } + return; + } + } + } + } } static void render_endjob(void *rjv) { - RenderJob *rj = rjv; - - /* this render may be used again by the sequencer without the active - * 'Render' where the callbacks would be re-assigned. assign dummy callbacks - * to avoid referencing freed renderjobs bug T24508. */ - RE_InitRenderCB(rj->re); - - if (rj->main != G_MAIN) - BKE_main_free(rj->main); - - /* else the frame will not update for the original value */ - if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) { - /* possible this fails of loading new file while rendering */ - if (G_MAIN->wm.first) { - ED_update_for_newframe(G_MAIN, rj->depsgraph); - } - } - - /* XXX above function sets all tags in nodes */ - ntreeCompositClearTags(rj->scene->nodetree); - - /* potentially set by caller */ - rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE; - - if (rj->single_layer) { - nodeUpdateID(rj->scene->nodetree, &rj->scene->id); - WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene); - } - - if (rj->sa) { - render_image_restore_layer(rj); - } - - /* XXX render stability hack */ - G.is_rendering = false; - WM_main_add_notifier(NC_SCENE | ND_RENDER_RESULT, NULL); - - /* Partial render result will always update display buffer - * for first render layer only. This is nice because you'll - * see render progress during rendering, but it ends up in - * wrong display buffer shown after rendering. - * - * The code below will mark display buffer as invalid after - * rendering in case multiple layers were rendered, which - * ensures display buffer matches render layer after - * rendering. - * - * Perhaps proper way would be to toggle active render - * layer in image editor and job, so we always display - * layer being currently rendered. But this is not so much - * trivial at this moment, especially because of external - * engine API, so lets use simple and robust way for now - * - sergey - - */ - if (rj->scene->view_layers.first != rj->scene->view_layers.last || - rj->image_outdated) - { - void *lock; - Image *ima = rj->image; - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock); - - if (ibuf) - ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; - - BKE_image_release_ibuf(ima, ibuf, lock); - } - - /* Finally unlock the user interface (if it was locked). */ - if (rj->interface_locked) { - /* Interface was locked, so window manager couldn't have been changed - * and using one from Global will unlock exactly the same manager as - * was locked before running the job. - */ - WM_set_locked_interface(G_MAIN->wm.first, false); - DEG_on_visible_update(G_MAIN, false); - } + RenderJob *rj = rjv; + + /* this render may be used again by the sequencer without the active + * 'Render' where the callbacks would be re-assigned. assign dummy callbacks + * to avoid referencing freed renderjobs bug T24508. */ + RE_InitRenderCB(rj->re); + + if (rj->main != G_MAIN) + BKE_main_free(rj->main); + + /* else the frame will not update for the original value */ + if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) { + /* possible this fails of loading new file while rendering */ + if (G_MAIN->wm.first) { + ED_update_for_newframe(G_MAIN, rj->depsgraph); + } + } + + /* XXX above function sets all tags in nodes */ + ntreeCompositClearTags(rj->scene->nodetree); + + /* potentially set by caller */ + rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE; + + if (rj->single_layer) { + nodeUpdateID(rj->scene->nodetree, &rj->scene->id); + WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene); + } + + if (rj->sa) { + render_image_restore_layer(rj); + } + + /* XXX render stability hack */ + G.is_rendering = false; + WM_main_add_notifier(NC_SCENE | ND_RENDER_RESULT, NULL); + + /* Partial render result will always update display buffer + * for first render layer only. This is nice because you'll + * see render progress during rendering, but it ends up in + * wrong display buffer shown after rendering. + * + * The code below will mark display buffer as invalid after + * rendering in case multiple layers were rendered, which + * ensures display buffer matches render layer after + * rendering. + * + * Perhaps proper way would be to toggle active render + * layer in image editor and job, so we always display + * layer being currently rendered. But this is not so much + * trivial at this moment, especially because of external + * engine API, so lets use simple and robust way for now + * - sergey - + */ + if (rj->scene->view_layers.first != rj->scene->view_layers.last || rj->image_outdated) { + void *lock; + Image *ima = rj->image; + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock); + + if (ibuf) + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + + BKE_image_release_ibuf(ima, ibuf, lock); + } + + /* Finally unlock the user interface (if it was locked). */ + if (rj->interface_locked) { + /* Interface was locked, so window manager couldn't have been changed + * and using one from Global will unlock exactly the same manager as + * was locked before running the job. + */ + WM_set_locked_interface(G_MAIN->wm.first, false); + DEG_on_visible_update(G_MAIN, false); + } } /* called by render, check job 'stop' value or the global */ static int render_breakjob(void *rjv) { - RenderJob *rj = rjv; + RenderJob *rj = rjv; - if (G.is_break) - return 1; - if (rj->stop && *(rj->stop)) - return 1; - return 0; + if (G.is_break) + return 1; + if (rj->stop && *(rj->stop)) + return 1; + return 0; } /* for exec() when there is no render job * note: this wont check for the escape key being pressed, but doing so isnt threadsafe */ static int render_break(void *UNUSED(rjv)) { - if (G.is_break) - return 1; - return 0; + if (G.is_break) + return 1; + return 0; } /* runs in thread, no cursor setting here works. careful with notifiers too (malloc conflicts) */ /* maybe need a way to get job send notifier? */ static void render_drawlock(void *rjv, int lock) { - RenderJob *rj = rjv; + RenderJob *rj = rjv; - /* If interface is locked, renderer callback shall do nothing. */ - if (!rj->interface_locked) { - BKE_spacedata_draw_locks(lock); - } + /* If interface is locked, renderer callback shall do nothing. */ + if (!rj->interface_locked) { + BKE_spacedata_draw_locks(lock); + } } /* catch esc */ static int screen_render_modal(bContext *C, wmOperator *op, const wmEvent *event) { - Scene *scene = (Scene *) op->customdata; - - /* no running blender, remove handler and pass through */ - if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) { - return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; - } - - /* running render */ - switch (event->type) { - case ESCKEY: - return OPERATOR_RUNNING_MODAL; - } - return OPERATOR_PASS_THROUGH; + Scene *scene = (Scene *)op->customdata; + + /* no running blender, remove handler and pass through */ + if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) { + return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; + } + + /* running render */ + switch (event->type) { + case ESCKEY: + return OPERATOR_RUNNING_MODAL; + } + return OPERATOR_PASS_THROUGH; } static void screen_render_cancel(bContext *C, wmOperator *op) { - wmWindowManager *wm = CTX_wm_manager(C); - Scene *scene = (Scene *) op->customdata; + wmWindowManager *wm = CTX_wm_manager(C); + Scene *scene = (Scene *)op->customdata; - /* kill on cancel, because job is using op->reports */ - WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER); + /* kill on cancel, because job is using op->reports */ + WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER); } static void clean_viewport_memory_base(Base *base) { - if ((base->flag & BASE_VISIBLE) == 0) { - return; - } + if ((base->flag & BASE_VISIBLE) == 0) { + return; + } - Object *object = base->object; + Object *object = base->object; - if (object->id.tag & LIB_TAG_DOIT) { - return; - } + if (object->id.tag & LIB_TAG_DOIT) { + return; + } - object->id.tag &= ~LIB_TAG_DOIT; - if (RE_allow_render_generic_object(object)) { - BKE_object_free_derived_caches(object); - } + object->id.tag &= ~LIB_TAG_DOIT; + if (RE_allow_render_generic_object(object)) { + BKE_object_free_derived_caches(object); + } } static void clean_viewport_memory(Main *bmain, Scene *scene) { - Scene *sce_iter; - Base *base; - - /* Tag all the available objects. */ - BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, true); - - /* Go over all the visible objects. */ - for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { - for (wmWindow *win = wm->windows.first; win; win = win->next) { - ViewLayer *view_layer = WM_window_get_active_view_layer(win); - - for (base = view_layer->object_bases.first; base; base = base->next) { - clean_viewport_memory_base(base); - } - } - } - - for (SETLOOPER_SET_ONLY(scene, sce_iter, base)) { - clean_viewport_memory_base(base); - } + Scene *sce_iter; + Base *base; + + /* Tag all the available objects. */ + BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, true); + + /* Go over all the visible objects. */ + for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { + for (wmWindow *win = wm->windows.first; win; win = win->next) { + ViewLayer *view_layer = WM_window_get_active_view_layer(win); + + for (base = view_layer->object_bases.first; base; base = base->next) { + clean_viewport_memory_base(base); + } + } + } + + for (SETLOOPER_SET_ONLY(scene, sce_iter, base)) { + clean_viewport_memory_base(base); + } } /* using context, starts job */ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - /* new render clears all callbacks */ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *active_layer = CTX_data_view_layer(C); - ViewLayer *single_layer = NULL; - RenderEngineType *re_type = RE_engines_find(scene->r.engine); - Render *re; - wmJob *wm_job; - RenderJob *rj; - Image *ima; - int jobflag; - const bool is_animation = RNA_boolean_get(op->ptr, "animation"); - const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); - const bool use_viewport = RNA_boolean_get(op->ptr, "use_viewport"); - View3D *v3d = use_viewport ? CTX_wm_view3d(C) : NULL; - struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL; - const char *name; - ScrArea *sa; - - /* Cannot do render if there is not this function. */ - if (re_type->render == NULL) { - return OPERATOR_CANCELLED; - } - - /* custom scene and single layer re-render */ - screen_render_single_layer_set(op, bmain, active_layer, &scene, &single_layer); - - /* only one render job at a time */ - if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) - return OPERATOR_CANCELLED; - - if (!RE_is_rendering_allowed(scene, single_layer, camera_override, op->reports)) { - return OPERATOR_CANCELLED; - } - - if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) { - BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected"); - return OPERATOR_CANCELLED; - } - - /* stop all running jobs, except screen one. currently previews frustrate Render */ - WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C)); - - /* cancel animation playback */ - if (ED_screen_animation_playing(CTX_wm_manager(C))) - ED_screen_animation_play(C, 0, 0); - - /* handle UI stuff */ - WM_cursor_wait(1); - - /* flush sculpt and editmode changes */ - ED_editors_flush_edits(bmain, true); - - /* cleanup sequencer caches before starting user triggered render. - * otherwise, invalidated cache entries can make their way into - * the output rendering. We can't put that into RE_BlenderFrame, - * since sequence rendering can call that recursively... (peter) */ - BKE_sequencer_cache_cleanup(); - - // store spare - // get view3d layer, local layer, make this nice api call to render - // store spare - - /* ensure at least 1 area shows result */ - sa = render_view_open(C, event->x, event->y, op->reports); - - jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS; - - if (RNA_struct_property_is_set(op->ptr, "layer")) - jobflag |= WM_JOB_SUSPEND; - - /* job custom data */ - rj = MEM_callocN(sizeof(RenderJob), "render job"); - rj->main = bmain; - rj->scene = scene; - rj->current_scene = rj->scene; - rj->single_layer = single_layer; - /* TODO(sergey): Render engine should be using own depsgraph. */ - rj->depsgraph = CTX_data_depsgraph(C); - rj->camera_override = camera_override; - rj->anim = is_animation; - rj->write_still = is_write_still && !is_animation; - rj->iuser.scene = scene; - rj->iuser.ok = 1; - rj->reports = op->reports; - rj->orig_layer = 0; - rj->last_layer = 0; - rj->sa = sa; - rj->supports_glsl_draw = IMB_colormanagement_support_glsl_draw(&scene->view_settings); - - BKE_color_managed_display_settings_copy(&rj->display_settings, &scene->display_settings); - BKE_color_managed_view_settings_copy(&rj->view_settings, &scene->view_settings); - - if (sa) { - SpaceImage *sima = sa->spacedata.first; - rj->orig_layer = sima->iuser.layer; - } - - if (v3d) { - if (camera_override && camera_override != scene->camera) - rj->v3d_override = true; - } - - /* Lock the user interface depending on render settings. */ - if (scene->r.use_lock_interface) { - WM_set_locked_interface(CTX_wm_manager(C), true); - - /* Set flag interface need to be unlocked. - * - * This is so because we don't have copy of render settings - * accessible from render job and copy is needed in case - * of non-locked rendering, so we wouldn't try to unlock - * anything if option was initially unset but then was - * enabled during rendering. - */ - rj->interface_locked = true; - - /* Clean memory used by viewport? */ - clean_viewport_memory(rj->main, scene); - } - - /* setup job */ - if (RE_seq_render_active(scene, &scene->r)) name = "Sequence Render"; - else name = "Render"; - - wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, name, jobflag, WM_JOB_TYPE_RENDER); - WM_jobs_customdata_set(wm_job, rj, render_freejob); - WM_jobs_timer(wm_job, 0.2, NC_SCENE | ND_RENDER_RESULT, 0); - WM_jobs_callbacks(wm_job, render_startjob, NULL, NULL, render_endjob); - - /* get a render result image, and make sure it is empty */ - ima = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"); - BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_FREE); - BKE_image_backup_render(rj->scene, ima, true); - rj->image = ima; - - /* setup new render */ - re = RE_NewSceneRender(scene); - RE_test_break_cb(re, rj, render_breakjob); - RE_draw_lock_cb(re, rj, render_drawlock); - RE_display_update_cb(re, rj, image_rect_update); - RE_current_scene_update_cb(re, rj, current_scene_update); - RE_stats_draw_cb(re, rj, image_renderinfo_cb); - RE_progress_cb(re, rj, render_progress_update); - RE_gl_context_create(re); - - rj->re = re; - G.is_break = false; - - /* store actual owner of job, so modal operator could check for it, - * the reason of this is that active scene could change when rendering - * several layers from compositor [#31800] - */ - op->customdata = scene; - - WM_jobs_start(CTX_wm_manager(C), wm_job); - - WM_cursor_wait(0); - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene); - - /* we set G.is_rendering here already instead of only in the job, this ensure - * main loop or other scene updates are disabled in time, since they may - * have started before the job thread */ - G.is_rendering = true; - - /* add modal handler for ESC */ - WM_event_add_modal_handler(C, op); - - return OPERATOR_RUNNING_MODAL; + /* new render clears all callbacks */ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *active_layer = CTX_data_view_layer(C); + ViewLayer *single_layer = NULL; + RenderEngineType *re_type = RE_engines_find(scene->r.engine); + Render *re; + wmJob *wm_job; + RenderJob *rj; + Image *ima; + int jobflag; + const bool is_animation = RNA_boolean_get(op->ptr, "animation"); + const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); + const bool use_viewport = RNA_boolean_get(op->ptr, "use_viewport"); + View3D *v3d = use_viewport ? CTX_wm_view3d(C) : NULL; + struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL; + const char *name; + ScrArea *sa; + + /* Cannot do render if there is not this function. */ + if (re_type->render == NULL) { + return OPERATOR_CANCELLED; + } + + /* custom scene and single layer re-render */ + screen_render_single_layer_set(op, bmain, active_layer, &scene, &single_layer); + + /* only one render job at a time */ + if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) + return OPERATOR_CANCELLED; + + if (!RE_is_rendering_allowed(scene, single_layer, camera_override, op->reports)) { + return OPERATOR_CANCELLED; + } + + if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) { + BKE_report( + op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected"); + return OPERATOR_CANCELLED; + } + + /* stop all running jobs, except screen one. currently previews frustrate Render */ + WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C)); + + /* cancel animation playback */ + if (ED_screen_animation_playing(CTX_wm_manager(C))) + ED_screen_animation_play(C, 0, 0); + + /* handle UI stuff */ + WM_cursor_wait(1); + + /* flush sculpt and editmode changes */ + ED_editors_flush_edits(bmain, true); + + /* cleanup sequencer caches before starting user triggered render. + * otherwise, invalidated cache entries can make their way into + * the output rendering. We can't put that into RE_BlenderFrame, + * since sequence rendering can call that recursively... (peter) */ + BKE_sequencer_cache_cleanup(); + + // store spare + // get view3d layer, local layer, make this nice api call to render + // store spare + + /* ensure at least 1 area shows result */ + sa = render_view_open(C, event->x, event->y, op->reports); + + jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS; + + if (RNA_struct_property_is_set(op->ptr, "layer")) + jobflag |= WM_JOB_SUSPEND; + + /* job custom data */ + rj = MEM_callocN(sizeof(RenderJob), "render job"); + rj->main = bmain; + rj->scene = scene; + rj->current_scene = rj->scene; + rj->single_layer = single_layer; + /* TODO(sergey): Render engine should be using own depsgraph. */ + rj->depsgraph = CTX_data_depsgraph(C); + rj->camera_override = camera_override; + rj->anim = is_animation; + rj->write_still = is_write_still && !is_animation; + rj->iuser.scene = scene; + rj->iuser.ok = 1; + rj->reports = op->reports; + rj->orig_layer = 0; + rj->last_layer = 0; + rj->sa = sa; + rj->supports_glsl_draw = IMB_colormanagement_support_glsl_draw(&scene->view_settings); + + BKE_color_managed_display_settings_copy(&rj->display_settings, &scene->display_settings); + BKE_color_managed_view_settings_copy(&rj->view_settings, &scene->view_settings); + + if (sa) { + SpaceImage *sima = sa->spacedata.first; + rj->orig_layer = sima->iuser.layer; + } + + if (v3d) { + if (camera_override && camera_override != scene->camera) + rj->v3d_override = true; + } + + /* Lock the user interface depending on render settings. */ + if (scene->r.use_lock_interface) { + WM_set_locked_interface(CTX_wm_manager(C), true); + + /* Set flag interface need to be unlocked. + * + * This is so because we don't have copy of render settings + * accessible from render job and copy is needed in case + * of non-locked rendering, so we wouldn't try to unlock + * anything if option was initially unset but then was + * enabled during rendering. + */ + rj->interface_locked = true; + + /* Clean memory used by viewport? */ + clean_viewport_memory(rj->main, scene); + } + + /* setup job */ + if (RE_seq_render_active(scene, &scene->r)) + name = "Sequence Render"; + else + name = "Render"; + + wm_job = WM_jobs_get( + CTX_wm_manager(C), CTX_wm_window(C), scene, name, jobflag, WM_JOB_TYPE_RENDER); + WM_jobs_customdata_set(wm_job, rj, render_freejob); + WM_jobs_timer(wm_job, 0.2, NC_SCENE | ND_RENDER_RESULT, 0); + WM_jobs_callbacks(wm_job, render_startjob, NULL, NULL, render_endjob); + + /* get a render result image, and make sure it is empty */ + ima = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"); + BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_FREE); + BKE_image_backup_render(rj->scene, ima, true); + rj->image = ima; + + /* setup new render */ + re = RE_NewSceneRender(scene); + RE_test_break_cb(re, rj, render_breakjob); + RE_draw_lock_cb(re, rj, render_drawlock); + RE_display_update_cb(re, rj, image_rect_update); + RE_current_scene_update_cb(re, rj, current_scene_update); + RE_stats_draw_cb(re, rj, image_renderinfo_cb); + RE_progress_cb(re, rj, render_progress_update); + RE_gl_context_create(re); + + rj->re = re; + G.is_break = false; + + /* store actual owner of job, so modal operator could check for it, + * the reason of this is that active scene could change when rendering + * several layers from compositor [#31800] + */ + op->customdata = scene; + + WM_jobs_start(CTX_wm_manager(C), wm_job); + + WM_cursor_wait(0); + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene); + + /* we set G.is_rendering here already instead of only in the job, this ensure + * main loop or other scene updates are disabled in time, since they may + * have started before the job thread */ + G.is_rendering = true; + + /* add modal handler for ESC */ + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; } /* contextual render, using current scene, view3d? */ void RENDER_OT_render(wmOperatorType *ot) { - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Render"; - ot->description = "Render active scene"; - ot->idname = "RENDER_OT_render"; - - /* api callbacks */ - ot->invoke = screen_render_invoke; - ot->modal = screen_render_modal; - ot->cancel = screen_render_cancel; - ot->exec = screen_render_exec; - - /*ot->poll = ED_operator_screenactive;*/ /* this isn't needed, causes failer in background mode */ - - prop = RNA_def_boolean(ot->srna, "animation", 0, "Animation", "Render files from the animation range of this scene"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - RNA_def_boolean(ot->srna, "write_still", 0, "Write Image", "Save rendered the image to the output path (used only when animation is disabled)"); - prop = RNA_def_boolean(ot->srna, "use_viewport", 0, "Use 3D Viewport", "When inside a 3D viewport, use layers and camera of the viewport"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_string(ot->srna, "layer", NULL, RE_MAXNAME, "Render Layer", "Single render layer to re-render (used only when animation is disabled)"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_string(ot->srna, "scene", NULL, MAX_ID_NAME - 2, "Scene", "Scene to render, current scene if not specified"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Render"; + ot->description = "Render active scene"; + ot->idname = "RENDER_OT_render"; + + /* api callbacks */ + ot->invoke = screen_render_invoke; + ot->modal = screen_render_modal; + ot->cancel = screen_render_cancel; + ot->exec = screen_render_exec; + + /*ot->poll = ED_operator_screenactive;*/ /* this isn't needed, causes failer in background mode */ + + prop = RNA_def_boolean(ot->srna, + "animation", + 0, + "Animation", + "Render files from the animation range of this scene"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_boolean( + ot->srna, + "write_still", + 0, + "Write Image", + "Save rendered the image to the output path (used only when animation is disabled)"); + prop = RNA_def_boolean(ot->srna, + "use_viewport", + 0, + "Use 3D Viewport", + "When inside a 3D viewport, use layers and camera of the viewport"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_string(ot->srna, + "layer", + NULL, + RE_MAXNAME, + "Render Layer", + "Single render layer to re-render (used only when animation is disabled)"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_string(ot->srna, + "scene", + NULL, + MAX_ID_NAME - 2, + "Scene", + "Scene to render, current scene if not specified"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } - Scene *ED_render_job_get_scene(const bContext *C) { - wmWindowManager *wm = CTX_wm_manager(C); - RenderJob *rj = (RenderJob *)WM_jobs_customdata_from_type(wm, WM_JOB_TYPE_RENDER); + wmWindowManager *wm = CTX_wm_manager(C); + RenderJob *rj = (RenderJob *)WM_jobs_customdata_from_type(wm, WM_JOB_TYPE_RENDER); - if (rj) - return rj->scene; + if (rj) + return rj->scene; - return NULL; + return NULL; } Scene *ED_render_job_get_current_scene(const bContext *C) { - wmWindowManager *wm = CTX_wm_manager(C); - RenderJob *rj = (RenderJob *)WM_jobs_customdata_from_type(wm, WM_JOB_TYPE_RENDER); - if (rj) { - return rj->current_scene; - } - return NULL; + wmWindowManager *wm = CTX_wm_manager(C); + RenderJob *rj = (RenderJob *)WM_jobs_customdata_from_type(wm, WM_JOB_TYPE_RENDER); + if (rj) { + return rj->current_scene; + } + return NULL; } - /* Motion blur curve preset */ static int render_shutter_curve_preset_exec(bContext *C, wmOperator *op) { - Scene *scene = CTX_data_scene(C); - CurveMapping *mblur_shutter_curve = &scene->r.mblur_shutter_curve; - CurveMap *cm = mblur_shutter_curve->cm; - int preset = RNA_enum_get(op->ptr, "shape"); - - cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; - mblur_shutter_curve->preset = preset; - curvemap_reset(cm, - &mblur_shutter_curve->clipr, - mblur_shutter_curve->preset, - CURVEMAP_SLOPE_POS_NEG); - curvemapping_changed(mblur_shutter_curve, false); - - return OPERATOR_FINISHED; + Scene *scene = CTX_data_scene(C); + CurveMapping *mblur_shutter_curve = &scene->r.mblur_shutter_curve; + CurveMap *cm = mblur_shutter_curve->cm; + int preset = RNA_enum_get(op->ptr, "shape"); + + cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + mblur_shutter_curve->preset = preset; + curvemap_reset( + cm, &mblur_shutter_curve->clipr, mblur_shutter_curve->preset, CURVEMAP_SLOPE_POS_NEG); + curvemapping_changed(mblur_shutter_curve, false); + + return OPERATOR_FINISHED; } void RENDER_OT_shutter_curve_preset(wmOperatorType *ot) { - PropertyRNA *prop; - static const EnumPropertyItem prop_shape_items[] = { - {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""}, - {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""}, - {CURVE_PRESET_MAX, "MAX", 0, "Max", ""}, - {CURVE_PRESET_LINE, "LINE", 0, "Line", ""}, - {CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""}, - {CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""}, - {0, NULL, 0, NULL, NULL}, - }; - - ot->name = "Shutter Curve Preset"; - ot->description = "Set shutter curve"; - ot->idname = "RENDER_OT_shutter_curve_preset"; - - ot->exec = render_shutter_curve_preset_exec; - - prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", ""); - RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ + PropertyRNA *prop; + static const EnumPropertyItem prop_shape_items[] = { + {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""}, + {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""}, + {CURVE_PRESET_MAX, "MAX", 0, "Max", ""}, + {CURVE_PRESET_LINE, "LINE", 0, "Line", ""}, + {CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""}, + {CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + ot->name = "Shutter Curve Preset"; + ot->description = "Set shutter curve"; + ot->idname = "RENDER_OT_shutter_curve_preset"; + + ot->exec = render_shutter_curve_preset_exec; + + prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", ""); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ } diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 3fdc34bd9c9..6862881de59 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -21,7 +21,6 @@ * \ingroup edrend */ - #include <math.h> #include <string.h> #include <stddef.h> @@ -88,1039 +87,1079 @@ #define MAX_SCHEDULED_FRAMES 8 typedef struct OGLRender { - Main *bmain; - Render *re; - Scene *scene; - WorkSpace *workspace; - ViewLayer *view_layer; - Depsgraph *depsgraph; - - View3D *v3d; - RegionView3D *rv3d; - ARegion *ar; - - ScrArea *prevsa; - ARegion *prevar; - - int views_len; /* multi-view views */ - - bool is_sequencer; - SpaceSeq *sseq; - struct { - ImBuf **ibufs_arr; - } seq_data; - - - Image *ima; - ImageUser iuser; - - GPUOffScreen *ofs; - int ofs_samples; - bool ofs_full_samples; - int sizex, sizey; - int write_still; - - ReportList *reports; - bMovieHandle *mh; - int cfrao, nfra; - - int totvideos; - - /* quick lookup */ - int view_id; - - /* wm vars for timer and progress cursor */ - wmWindowManager *wm; - wmWindow *win; - - wmTimer *timer; /* use to check if running modal or not (invoke'd or exec'd)*/ - void **movie_ctx_arr; - - TaskScheduler *task_scheduler; - TaskPool *task_pool; - bool pool_ok; - bool is_animation; - SpinLock reports_lock; - unsigned int num_scheduled_frames; - ThreadMutex task_mutex; - ThreadCondition task_condition; + Main *bmain; + Render *re; + Scene *scene; + WorkSpace *workspace; + ViewLayer *view_layer; + Depsgraph *depsgraph; + + View3D *v3d; + RegionView3D *rv3d; + ARegion *ar; + + ScrArea *prevsa; + ARegion *prevar; + + int views_len; /* multi-view views */ + + bool is_sequencer; + SpaceSeq *sseq; + struct { + ImBuf **ibufs_arr; + } seq_data; + + Image *ima; + ImageUser iuser; + + GPUOffScreen *ofs; + int ofs_samples; + bool ofs_full_samples; + int sizex, sizey; + int write_still; + + ReportList *reports; + bMovieHandle *mh; + int cfrao, nfra; + + int totvideos; + + /* quick lookup */ + int view_id; + + /* wm vars for timer and progress cursor */ + wmWindowManager *wm; + wmWindow *win; + + wmTimer *timer; /* use to check if running modal or not (invoke'd or exec'd)*/ + void **movie_ctx_arr; + + TaskScheduler *task_scheduler; + TaskPool *task_pool; + bool pool_ok; + bool is_animation; + SpinLock reports_lock; + unsigned int num_scheduled_frames; + ThreadMutex task_mutex; + ThreadCondition task_condition; #ifdef DEBUG_TIME - double time_start; + double time_start; #endif } OGLRender; static bool screen_opengl_is_multiview(OGLRender *oglrender) { - View3D *v3d = oglrender->v3d; - RegionView3D *rv3d = oglrender->rv3d; - RenderData *rd = &oglrender->scene->r; + View3D *v3d = oglrender->v3d; + RegionView3D *rv3d = oglrender->rv3d; + RenderData *rd = &oglrender->scene->r; - if ((rd == NULL) || ((v3d != NULL) && (rv3d == NULL))) - return false; + if ((rd == NULL) || ((v3d != NULL) && (rv3d == NULL))) + return false; - return (rd->scemode & R_MULTIVIEW) && ((v3d == NULL) || (rv3d->persp == RV3D_CAMOB && v3d->camera)); + return (rd->scemode & R_MULTIVIEW) && + ((v3d == NULL) || (rv3d->persp == RV3D_CAMOB && v3d->camera)); } static void screen_opengl_views_setup(OGLRender *oglrender) { - RenderResult *rr; - RenderView *rv; - SceneRenderView *srv; - bool is_multiview; - Object *camera; - View3D *v3d = oglrender->v3d; - - RenderData *rd = &oglrender->scene->r; - - rr = RE_AcquireResultWrite(oglrender->re); - - is_multiview = screen_opengl_is_multiview(oglrender); - - if (!is_multiview) { - /* we only have one view when multiview is off */ - rv = rr->views.first; - - if (rv == NULL) { - rv = MEM_callocN(sizeof(RenderView), "new opengl render view"); - BLI_addtail(&rr->views, rv); - } - - while (rv->next) { - RenderView *rv_del = rv->next; - BLI_remlink(&rr->views, rv_del); - - if (rv_del->rectf) - MEM_freeN(rv_del->rectf); - - if (rv_del->rectz) - MEM_freeN(rv_del->rectz); - - if (rv_del->rect32) - MEM_freeN(rv_del->rect32); - - MEM_freeN(rv_del); - } - } - else { - if (v3d) { - RE_SetOverrideCamera(oglrender->re, V3D_CAMERA_SCENE(oglrender->scene, v3d)); - } - - /* remove all the views that are not needed */ - rv = rr->views.last; - while (rv) { - srv = BLI_findstring(&rd->views, rv->name, offsetof(SceneRenderView, name)); - if (BKE_scene_multiview_is_render_view_active(rd, srv)) { - rv = rv->prev; - } - else { - RenderView *rv_del = rv; - rv = rv_del->prev; - - BLI_remlink(&rr->views, rv_del); - - if (rv_del->rectf) - MEM_freeN(rv_del->rectf); - - if (rv_del->rectz) - MEM_freeN(rv_del->rectz); - - if (rv_del->rect32) - MEM_freeN(rv_del->rect32); - - MEM_freeN(rv_del); - } - } - - /* create all the views that are needed */ - for (srv = rd->views.first; srv; srv = srv->next) { - if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) - continue; - - rv = BLI_findstring(&rr->views, srv->name, offsetof(SceneRenderView, name)); - - if (rv == NULL) { - rv = MEM_callocN(sizeof(RenderView), "new opengl render view"); - BLI_strncpy(rv->name, srv->name, sizeof(rv->name)); - BLI_addtail(&rr->views, rv); - } - } - } - - if (!(is_multiview && BKE_scene_multiview_is_stereo3d(rd))) - oglrender->iuser.flag &= ~IMA_SHOW_STEREO; - - /* will only work for non multiview correctly */ - if (v3d) { - camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, "new opengl render view"); - BKE_render_result_stamp_info(oglrender->scene, camera, rr, false); - } - else { - BKE_render_result_stamp_info(oglrender->scene, oglrender->scene->camera, rr, false); - } - - RE_ReleaseResult(oglrender->re); + RenderResult *rr; + RenderView *rv; + SceneRenderView *srv; + bool is_multiview; + Object *camera; + View3D *v3d = oglrender->v3d; + + RenderData *rd = &oglrender->scene->r; + + rr = RE_AcquireResultWrite(oglrender->re); + + is_multiview = screen_opengl_is_multiview(oglrender); + + if (!is_multiview) { + /* we only have one view when multiview is off */ + rv = rr->views.first; + + if (rv == NULL) { + rv = MEM_callocN(sizeof(RenderView), "new opengl render view"); + BLI_addtail(&rr->views, rv); + } + + while (rv->next) { + RenderView *rv_del = rv->next; + BLI_remlink(&rr->views, rv_del); + + if (rv_del->rectf) + MEM_freeN(rv_del->rectf); + + if (rv_del->rectz) + MEM_freeN(rv_del->rectz); + + if (rv_del->rect32) + MEM_freeN(rv_del->rect32); + + MEM_freeN(rv_del); + } + } + else { + if (v3d) { + RE_SetOverrideCamera(oglrender->re, V3D_CAMERA_SCENE(oglrender->scene, v3d)); + } + + /* remove all the views that are not needed */ + rv = rr->views.last; + while (rv) { + srv = BLI_findstring(&rd->views, rv->name, offsetof(SceneRenderView, name)); + if (BKE_scene_multiview_is_render_view_active(rd, srv)) { + rv = rv->prev; + } + else { + RenderView *rv_del = rv; + rv = rv_del->prev; + + BLI_remlink(&rr->views, rv_del); + + if (rv_del->rectf) + MEM_freeN(rv_del->rectf); + + if (rv_del->rectz) + MEM_freeN(rv_del->rectz); + + if (rv_del->rect32) + MEM_freeN(rv_del->rect32); + + MEM_freeN(rv_del); + } + } + + /* create all the views that are needed */ + for (srv = rd->views.first; srv; srv = srv->next) { + if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) + continue; + + rv = BLI_findstring(&rr->views, srv->name, offsetof(SceneRenderView, name)); + + if (rv == NULL) { + rv = MEM_callocN(sizeof(RenderView), "new opengl render view"); + BLI_strncpy(rv->name, srv->name, sizeof(rv->name)); + BLI_addtail(&rr->views, rv); + } + } + } + + if (!(is_multiview && BKE_scene_multiview_is_stereo3d(rd))) + oglrender->iuser.flag &= ~IMA_SHOW_STEREO; + + /* will only work for non multiview correctly */ + if (v3d) { + camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, "new opengl render view"); + BKE_render_result_stamp_info(oglrender->scene, camera, rr, false); + } + else { + BKE_render_result_stamp_info(oglrender->scene, oglrender->scene->camera, rr, false); + } + + RE_ReleaseResult(oglrender->re); } static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, RenderResult *rr) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene = oglrender->scene; - ARegion *ar = oglrender->ar; - View3D *v3d = oglrender->v3d; - RegionView3D *rv3d = oglrender->rv3d; - Object *camera = NULL; - int sizex = oglrender->sizex; - int sizey = oglrender->sizey; - const short view_context = (v3d != NULL); - bool draw_sky = (scene->r.alphamode == R_ADDSKY); - float *rectf = NULL; - const char *viewname = RE_GetActiveRenderView(oglrender->re); - ImBuf *ibuf_result = NULL; - - if (oglrender->is_sequencer) { - SpaceSeq *sseq = oglrender->sseq; - struct bGPdata *gpd = (sseq && (sseq->flag & SEQ_SHOW_GPENCIL)) ? sseq->gpd : NULL; - - /* use pre-calculated ImBuf (avoids deadlock), see: */ - ImBuf *ibuf = oglrender->seq_data.ibufs_arr[oglrender->view_id]; - - if (ibuf) { - ImBuf *out = IMB_dupImBuf(ibuf); - IMB_freeImBuf(ibuf); - /* OpenGL render is considered to be preview and should be - * as fast as possible. So currently we're making sure sequencer - * result is always byte to simplify color management pipeline. - * - * TODO(sergey): In the case of output to float container (EXR) - * it actually makes sense to keep float buffer instead. - */ - if (out->rect_float != NULL) { - IMB_rect_from_float(out); - imb_freerectfloatImBuf(out); - } - BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y)); - RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id); - IMB_freeImBuf(out); - } - else if (gpd) { - /* If there are no strips, Grease Pencil still needs a buffer to draw on */ - ImBuf *out = IMB_allocImBuf(oglrender->sizex, oglrender->sizey, 32, IB_rect); - RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id); - IMB_freeImBuf(out); - } - - if (gpd) { - int i; - unsigned char *gp_rect; - unsigned char *render_rect = (unsigned char *)RE_RenderViewGetById(rr, oglrender->view_id)->rect32; - - DRW_opengl_context_enable(); - GPU_offscreen_bind(oglrender->ofs, true); - - GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f); - GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT); - - wmOrtho2(0, sizex, 0, sizey); - GPU_matrix_translate_2f(sizex / 2, sizey / 2); - - G.f |= G_FLAG_RENDER_VIEWPORT; - ED_annotation_draw_ex( - scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ); - G.f &= ~G_FLAG_RENDER_VIEWPORT; - - gp_rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect"); - GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, gp_rect); - - for (i = 0; i < sizex * sizey * 4; i += 4) { - blend_color_mix_byte(&render_rect[i], &render_rect[i], &gp_rect[i]); - } - GPU_offscreen_unbind(oglrender->ofs, true); - DRW_opengl_context_disable(); - - MEM_freeN(gp_rect); - } - } - else { - /* shouldnt suddenly give errors mid-render but possible */ - char err_out[256] = "unknown"; - ImBuf *ibuf_view; - const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL; - - unsigned int draw_flags = V3D_OFSDRAW_NONE; - draw_flags |= (oglrender->ofs_full_samples) ? V3D_OFSDRAW_USE_FULL_SAMPLE : 0; - - if (view_context) { - ibuf_view = ED_view3d_draw_offscreen_imbuf( - depsgraph, scene, v3d->shading.type, - v3d, ar, sizex, sizey, - IB_rectfloat, draw_flags, alpha_mode, oglrender->ofs_samples, viewname, - oglrender->ofs, err_out); - - /* for stamp only */ - if (rv3d->persp == RV3D_CAMOB && v3d->camera) { - camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname); - } - } - else { - draw_flags |= V3D_OFSDRAW_USE_GPENCIL; - ibuf_view = ED_view3d_draw_offscreen_imbuf_simple( - depsgraph, scene, OB_SOLID, - scene->camera, oglrender->sizex, oglrender->sizey, - IB_rectfloat, draw_flags, - alpha_mode, oglrender->ofs_samples, viewname, - oglrender->ofs, err_out); - camera = scene->camera; - } - - if (ibuf_view) { - ibuf_result = ibuf_view; - rectf = (float *)ibuf_view->rect_float; - } - else { - fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out); - } - } - - if (ibuf_result != NULL) { - if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) { - BKE_image_stamp_buf(scene, camera, NULL, NULL, rectf, rr->rectx, rr->recty, 4); - } - RE_render_result_rect_from_ibuf(rr, &scene->r, ibuf_result, oglrender->view_id); - IMB_freeImBuf(ibuf_result); - } + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene = oglrender->scene; + ARegion *ar = oglrender->ar; + View3D *v3d = oglrender->v3d; + RegionView3D *rv3d = oglrender->rv3d; + Object *camera = NULL; + int sizex = oglrender->sizex; + int sizey = oglrender->sizey; + const short view_context = (v3d != NULL); + bool draw_sky = (scene->r.alphamode == R_ADDSKY); + float *rectf = NULL; + const char *viewname = RE_GetActiveRenderView(oglrender->re); + ImBuf *ibuf_result = NULL; + + if (oglrender->is_sequencer) { + SpaceSeq *sseq = oglrender->sseq; + struct bGPdata *gpd = (sseq && (sseq->flag & SEQ_SHOW_GPENCIL)) ? sseq->gpd : NULL; + + /* use pre-calculated ImBuf (avoids deadlock), see: */ + ImBuf *ibuf = oglrender->seq_data.ibufs_arr[oglrender->view_id]; + + if (ibuf) { + ImBuf *out = IMB_dupImBuf(ibuf); + IMB_freeImBuf(ibuf); + /* OpenGL render is considered to be preview and should be + * as fast as possible. So currently we're making sure sequencer + * result is always byte to simplify color management pipeline. + * + * TODO(sergey): In the case of output to float container (EXR) + * it actually makes sense to keep float buffer instead. + */ + if (out->rect_float != NULL) { + IMB_rect_from_float(out); + imb_freerectfloatImBuf(out); + } + BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y)); + RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id); + IMB_freeImBuf(out); + } + else if (gpd) { + /* If there are no strips, Grease Pencil still needs a buffer to draw on */ + ImBuf *out = IMB_allocImBuf(oglrender->sizex, oglrender->sizey, 32, IB_rect); + RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id); + IMB_freeImBuf(out); + } + + if (gpd) { + int i; + unsigned char *gp_rect; + unsigned char *render_rect = + (unsigned char *)RE_RenderViewGetById(rr, oglrender->view_id)->rect32; + + DRW_opengl_context_enable(); + GPU_offscreen_bind(oglrender->ofs, true); + + GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f); + GPU_clear(GPU_COLOR_BIT | GPU_DEPTH_BIT); + + wmOrtho2(0, sizex, 0, sizey); + GPU_matrix_translate_2f(sizex / 2, sizey / 2); + + G.f |= G_FLAG_RENDER_VIEWPORT; + ED_annotation_draw_ex(scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ); + G.f &= ~G_FLAG_RENDER_VIEWPORT; + + gp_rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect"); + GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, gp_rect); + + for (i = 0; i < sizex * sizey * 4; i += 4) { + blend_color_mix_byte(&render_rect[i], &render_rect[i], &gp_rect[i]); + } + GPU_offscreen_unbind(oglrender->ofs, true); + DRW_opengl_context_disable(); + + MEM_freeN(gp_rect); + } + } + else { + /* shouldnt suddenly give errors mid-render but possible */ + char err_out[256] = "unknown"; + ImBuf *ibuf_view; + const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL; + + unsigned int draw_flags = V3D_OFSDRAW_NONE; + draw_flags |= (oglrender->ofs_full_samples) ? V3D_OFSDRAW_USE_FULL_SAMPLE : 0; + + if (view_context) { + ibuf_view = ED_view3d_draw_offscreen_imbuf(depsgraph, + scene, + v3d->shading.type, + v3d, + ar, + sizex, + sizey, + IB_rectfloat, + draw_flags, + alpha_mode, + oglrender->ofs_samples, + viewname, + oglrender->ofs, + err_out); + + /* for stamp only */ + if (rv3d->persp == RV3D_CAMOB && v3d->camera) { + camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname); + } + } + else { + draw_flags |= V3D_OFSDRAW_USE_GPENCIL; + ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(depsgraph, + scene, + OB_SOLID, + scene->camera, + oglrender->sizex, + oglrender->sizey, + IB_rectfloat, + draw_flags, + alpha_mode, + oglrender->ofs_samples, + viewname, + oglrender->ofs, + err_out); + camera = scene->camera; + } + + if (ibuf_view) { + ibuf_result = ibuf_view; + rectf = (float *)ibuf_view->rect_float; + } + else { + fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out); + } + } + + if (ibuf_result != NULL) { + if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) { + BKE_image_stamp_buf(scene, camera, NULL, NULL, rectf, rr->rectx, rr->recty, 4); + } + RE_render_result_rect_from_ibuf(rr, &scene->r, ibuf_result, oglrender->view_id); + IMB_freeImBuf(ibuf_result); + } } static void screen_opengl_render_write(OGLRender *oglrender) { - Scene *scene = oglrender->scene; - RenderResult *rr; - bool ok; - char name[FILE_MAX]; - - rr = RE_AcquireResultRead(oglrender->re); - - BKE_image_path_from_imformat( - name, scene->r.pic, BKE_main_blendfile_path(oglrender->bmain), scene->r.cfra, - &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false, NULL); - - /* write images as individual images or stereo */ - BKE_render_result_stamp_info(scene, scene->camera, rr, false); - ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, false, name); - - RE_ReleaseResultImage(oglrender->re); - - if (ok) printf("OpenGL Render written to '%s'\n", name); - else printf("OpenGL Render failed to write '%s'\n", name); + Scene *scene = oglrender->scene; + RenderResult *rr; + bool ok; + char name[FILE_MAX]; + + rr = RE_AcquireResultRead(oglrender->re); + + BKE_image_path_from_imformat(name, + scene->r.pic, + BKE_main_blendfile_path(oglrender->bmain), + scene->r.cfra, + &scene->r.im_format, + (scene->r.scemode & R_EXTENSION) != 0, + false, + NULL); + + /* write images as individual images or stereo */ + BKE_render_result_stamp_info(scene, scene->camera, rr, false); + ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, false, name); + + RE_ReleaseResultImage(oglrender->re); + + if (ok) + printf("OpenGL Render written to '%s'\n", name); + else + printf("OpenGL Render failed to write '%s'\n", name); } static void UNUSED_FUNCTION(addAlphaOverFloat)(float dest[4], const float source[4]) { - /* d = s + (1-alpha_s)d*/ - float mul; - - mul = 1.0f - source[3]; + /* d = s + (1-alpha_s)d*/ + float mul; - dest[0] = (mul * dest[0]) + source[0]; - dest[1] = (mul * dest[1]) + source[1]; - dest[2] = (mul * dest[2]) + source[2]; - dest[3] = (mul * dest[3]) + source[3]; + mul = 1.0f - source[3]; + dest[0] = (mul * dest[0]) + source[0]; + dest[1] = (mul * dest[1]) + source[1]; + dest[2] = (mul * dest[2]) + source[2]; + dest[3] = (mul * dest[3]) + source[3]; } static void screen_opengl_render_apply(const bContext *C, OGLRender *oglrender) { - RenderResult *rr; - RenderView *rv; - int view_id; - ImBuf *ibuf; - void *lock; - - if (oglrender->is_sequencer) { - Scene *scene = oglrender->scene; - - SeqRenderData context; - SpaceSeq *sseq = oglrender->sseq; - int chanshown = sseq ? sseq->chanshown : 0; - - BKE_sequencer_new_render_data( - oglrender->bmain, oglrender->depsgraph, scene, - oglrender->sizex, oglrender->sizey, 100.0f, false, - &context); - - for (view_id = 0; view_id < oglrender->views_len; view_id++) { - context.view_id = view_id; - context.gpu_offscreen = oglrender->ofs; - context.gpu_full_samples = oglrender->ofs_full_samples; - - oglrender->seq_data.ibufs_arr[view_id] = BKE_sequencer_give_ibuf(&context, CFRA, chanshown); - } - } - - rr = RE_AcquireResultRead(oglrender->re); - for (rv = rr->views.first, view_id = 0; rv; rv = rv->next, view_id++) { - BLI_assert(view_id < oglrender->views_len); - RE_SetActiveRenderView(oglrender->re, rv->name); - oglrender->view_id = view_id; - /* render composite */ - screen_opengl_render_doit(C, oglrender, rr); - } - - RE_ReleaseResult(oglrender->re); - - ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); - if (ibuf) { - ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; - } - BKE_image_release_ibuf(oglrender->ima, ibuf, lock); - - if (oglrender->write_still) { - screen_opengl_render_write(oglrender); - } + RenderResult *rr; + RenderView *rv; + int view_id; + ImBuf *ibuf; + void *lock; + + if (oglrender->is_sequencer) { + Scene *scene = oglrender->scene; + + SeqRenderData context; + SpaceSeq *sseq = oglrender->sseq; + int chanshown = sseq ? sseq->chanshown : 0; + + BKE_sequencer_new_render_data(oglrender->bmain, + oglrender->depsgraph, + scene, + oglrender->sizex, + oglrender->sizey, + 100.0f, + false, + &context); + + for (view_id = 0; view_id < oglrender->views_len; view_id++) { + context.view_id = view_id; + context.gpu_offscreen = oglrender->ofs; + context.gpu_full_samples = oglrender->ofs_full_samples; + + oglrender->seq_data.ibufs_arr[view_id] = BKE_sequencer_give_ibuf(&context, CFRA, chanshown); + } + } + + rr = RE_AcquireResultRead(oglrender->re); + for (rv = rr->views.first, view_id = 0; rv; rv = rv->next, view_id++) { + BLI_assert(view_id < oglrender->views_len); + RE_SetActiveRenderView(oglrender->re, rv->name); + oglrender->view_id = view_id; + /* render composite */ + screen_opengl_render_doit(C, oglrender, rr); + } + + RE_ReleaseResult(oglrender->re); + + ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); + if (ibuf) { + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + } + BKE_image_release_ibuf(oglrender->ima, ibuf, lock); + + if (oglrender->write_still) { + screen_opengl_render_write(oglrender); + } } static bool screen_opengl_fullsample_enabled(Scene *scene) { - if (scene->r.scemode & R_FULL_SAMPLE) { - return true; - } - else { - /* XXX TODO: - * Technically if the hardware supports MSAA we could keep using Blender 2.7x approach. - * However anti-aliasing without full_sample is not playing well even in 2.7x. - * - * For example, if you enable depth of field, there is aliasing, even if the viewport is fine. - * For 2.8x this is more complicated because so many things rely on shader. - * So until we fix the gpu_framebuffer anti-aliasing suupport we need to force full sample. - */ - return true; - } + if (scene->r.scemode & R_FULL_SAMPLE) { + return true; + } + else { + /* XXX TODO: + * Technically if the hardware supports MSAA we could keep using Blender 2.7x approach. + * However anti-aliasing without full_sample is not playing well even in 2.7x. + * + * For example, if you enable depth of field, there is aliasing, even if the viewport is fine. + * For 2.8x this is more complicated because so many things rely on shader. + * So until we fix the gpu_framebuffer anti-aliasing suupport we need to force full sample. + */ + return true; + } } static bool screen_opengl_render_init(bContext *C, wmOperator *op) { - /* new render clears all callbacks */ - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); - WorkSpace *workspace = CTX_wm_workspace(C); - - Scene *scene = CTX_data_scene(C); - ScrArea *prevsa = CTX_wm_area(C); - ARegion *prevar = CTX_wm_region(C); - GPUOffScreen *ofs; - OGLRender *oglrender; - int sizex, sizey; - const int samples = (scene->r.mode & R_OSA) ? scene->r.osa : 0; - const bool full_samples = (samples != 0) && screen_opengl_fullsample_enabled(scene); - bool is_view_context = RNA_boolean_get(op->ptr, "view_context"); - const bool is_animation = RNA_boolean_get(op->ptr, "animation"); - const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer"); - const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); - char err_out[256] = "unknown"; - - if (G.background) { - BKE_report(op->reports, RPT_ERROR, "Cannot use OpenGL render in background mode (no opengl context)"); - return false; - } - - /* only one render job at a time */ - if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER)) - return false; - - if (is_sequencer) { - is_view_context = false; - } - else { - /* ensure we have a 3d view */ - if (!ED_view3d_context_activate(C)) { - RNA_boolean_set(op->ptr, "view_context", false); - is_view_context = false; - } - - if (!is_view_context && scene->camera == NULL) { - BKE_report(op->reports, RPT_ERROR, "Scene has no camera"); - return false; - } - } - - if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) { - BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected"); - return false; - } - - /* stop all running jobs, except screen one. currently previews frustrate Render */ - WM_jobs_kill_all_except(wm, CTX_wm_screen(C)); - - /* create offscreen buffer */ - sizex = (scene->r.size * scene->r.xsch) / 100; - sizey = (scene->r.size * scene->r.ysch) / 100; - - /* corrects render size with actual size, not every card supports non-power-of-two dimensions */ - DRW_opengl_context_enable(); /* Offscreen creation needs to be done in DRW context. */ - ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, true, true, err_out); - DRW_opengl_context_disable(); - - if (!ofs) { - BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out); - return false; - } - - /* allocate opengl render */ - oglrender = MEM_callocN(sizeof(OGLRender), "OGLRender"); - op->customdata = oglrender; - - oglrender->ofs = ofs; - oglrender->ofs_samples = samples; - oglrender->ofs_full_samples = full_samples; - oglrender->sizex = sizex; - oglrender->sizey = sizey; - oglrender->bmain = CTX_data_main(C); - oglrender->scene = scene; - oglrender->workspace = workspace; - oglrender->view_layer = CTX_data_view_layer(C); - oglrender->depsgraph = CTX_data_depsgraph(C); - oglrender->cfrao = scene->r.cfra; - - oglrender->write_still = is_write_still && !is_animation; - oglrender->is_animation = is_animation; - - oglrender->views_len = BKE_scene_multiview_num_views_get(&scene->r); - - oglrender->is_sequencer = is_sequencer; - if (is_sequencer) { - oglrender->sseq = CTX_wm_space_seq(C); - ImBuf **ibufs_arr = MEM_callocN(sizeof(*ibufs_arr) * oglrender->views_len, __func__); - oglrender->seq_data.ibufs_arr = ibufs_arr; - } - - oglrender->prevsa = prevsa; - oglrender->prevar = prevar; - - if (is_view_context) { - /* so quad view renders camera */ - ED_view3d_context_user_region(C, &oglrender->v3d, &oglrender->ar); - - oglrender->rv3d = oglrender->ar->regiondata; - - /* MUST be cleared on exit */ - memset(&oglrender->scene->customdata_mask_modal, 0, sizeof(oglrender->scene->customdata_mask_modal)); - ED_view3d_datamask(C, oglrender->scene, oglrender->v3d, &oglrender->scene->customdata_mask_modal); - - /* apply immediately in case we're rendering from a script, - * running notifiers again will overwrite */ - CustomData_MeshMasks_update(&oglrender->scene->customdata_mask, &oglrender->scene->customdata_mask_modal); - } - - /* create render */ - oglrender->re = RE_NewSceneRender(scene); - - /* create image and image user */ - oglrender->ima = BKE_image_verify_viewer(oglrender->bmain, IMA_TYPE_R_RESULT, "Render Result"); - BKE_image_signal(oglrender->bmain, oglrender->ima, NULL, IMA_SIGNAL_FREE); - BKE_image_backup_render(oglrender->scene, oglrender->ima, true); - - oglrender->iuser.scene = scene; - oglrender->iuser.ok = 1; - - /* create render result */ - RE_InitState(oglrender->re, NULL, &scene->r, &scene->view_layers, NULL, sizex, sizey, NULL); - - /* create render views */ - screen_opengl_views_setup(oglrender); - - /* wm vars */ - oglrender->wm = wm; - oglrender->win = win; - - oglrender->totvideos = 0; - oglrender->mh = NULL; - oglrender->movie_ctx_arr = NULL; - - if (is_animation) { - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); - if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { - task_scheduler = BLI_task_scheduler_create(1); - oglrender->task_scheduler = task_scheduler; - oglrender->task_pool = BLI_task_pool_create_background(task_scheduler, - oglrender); - } - else { - oglrender->task_scheduler = NULL; - oglrender->task_pool = BLI_task_pool_create(task_scheduler, - oglrender); - } - oglrender->pool_ok = true; - BLI_spin_init(&oglrender->reports_lock); - } - else { - oglrender->task_scheduler = NULL; - oglrender->task_pool = NULL; - } - oglrender->num_scheduled_frames = 0; - BLI_mutex_init(&oglrender->task_mutex); - BLI_condition_init(&oglrender->task_condition); + /* new render clears all callbacks */ + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); + WorkSpace *workspace = CTX_wm_workspace(C); + + Scene *scene = CTX_data_scene(C); + ScrArea *prevsa = CTX_wm_area(C); + ARegion *prevar = CTX_wm_region(C); + GPUOffScreen *ofs; + OGLRender *oglrender; + int sizex, sizey; + const int samples = (scene->r.mode & R_OSA) ? scene->r.osa : 0; + const bool full_samples = (samples != 0) && screen_opengl_fullsample_enabled(scene); + bool is_view_context = RNA_boolean_get(op->ptr, "view_context"); + const bool is_animation = RNA_boolean_get(op->ptr, "animation"); + const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer"); + const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); + char err_out[256] = "unknown"; + + if (G.background) { + BKE_report( + op->reports, RPT_ERROR, "Cannot use OpenGL render in background mode (no opengl context)"); + return false; + } + + /* only one render job at a time */ + if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER)) + return false; + + if (is_sequencer) { + is_view_context = false; + } + else { + /* ensure we have a 3d view */ + if (!ED_view3d_context_activate(C)) { + RNA_boolean_set(op->ptr, "view_context", false); + is_view_context = false; + } + + if (!is_view_context && scene->camera == NULL) { + BKE_report(op->reports, RPT_ERROR, "Scene has no camera"); + return false; + } + } + + if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) { + BKE_report( + op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected"); + return false; + } + + /* stop all running jobs, except screen one. currently previews frustrate Render */ + WM_jobs_kill_all_except(wm, CTX_wm_screen(C)); + + /* create offscreen buffer */ + sizex = (scene->r.size * scene->r.xsch) / 100; + sizey = (scene->r.size * scene->r.ysch) / 100; + + /* corrects render size with actual size, not every card supports non-power-of-two dimensions */ + DRW_opengl_context_enable(); /* Offscreen creation needs to be done in DRW context. */ + ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, true, true, err_out); + DRW_opengl_context_disable(); + + if (!ofs) { + BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out); + return false; + } + + /* allocate opengl render */ + oglrender = MEM_callocN(sizeof(OGLRender), "OGLRender"); + op->customdata = oglrender; + + oglrender->ofs = ofs; + oglrender->ofs_samples = samples; + oglrender->ofs_full_samples = full_samples; + oglrender->sizex = sizex; + oglrender->sizey = sizey; + oglrender->bmain = CTX_data_main(C); + oglrender->scene = scene; + oglrender->workspace = workspace; + oglrender->view_layer = CTX_data_view_layer(C); + oglrender->depsgraph = CTX_data_depsgraph(C); + oglrender->cfrao = scene->r.cfra; + + oglrender->write_still = is_write_still && !is_animation; + oglrender->is_animation = is_animation; + + oglrender->views_len = BKE_scene_multiview_num_views_get(&scene->r); + + oglrender->is_sequencer = is_sequencer; + if (is_sequencer) { + oglrender->sseq = CTX_wm_space_seq(C); + ImBuf **ibufs_arr = MEM_callocN(sizeof(*ibufs_arr) * oglrender->views_len, __func__); + oglrender->seq_data.ibufs_arr = ibufs_arr; + } + + oglrender->prevsa = prevsa; + oglrender->prevar = prevar; + + if (is_view_context) { + /* so quad view renders camera */ + ED_view3d_context_user_region(C, &oglrender->v3d, &oglrender->ar); + + oglrender->rv3d = oglrender->ar->regiondata; + + /* MUST be cleared on exit */ + memset(&oglrender->scene->customdata_mask_modal, + 0, + sizeof(oglrender->scene->customdata_mask_modal)); + ED_view3d_datamask( + C, oglrender->scene, oglrender->v3d, &oglrender->scene->customdata_mask_modal); + + /* apply immediately in case we're rendering from a script, + * running notifiers again will overwrite */ + CustomData_MeshMasks_update(&oglrender->scene->customdata_mask, + &oglrender->scene->customdata_mask_modal); + } + + /* create render */ + oglrender->re = RE_NewSceneRender(scene); + + /* create image and image user */ + oglrender->ima = BKE_image_verify_viewer(oglrender->bmain, IMA_TYPE_R_RESULT, "Render Result"); + BKE_image_signal(oglrender->bmain, oglrender->ima, NULL, IMA_SIGNAL_FREE); + BKE_image_backup_render(oglrender->scene, oglrender->ima, true); + + oglrender->iuser.scene = scene; + oglrender->iuser.ok = 1; + + /* create render result */ + RE_InitState(oglrender->re, NULL, &scene->r, &scene->view_layers, NULL, sizex, sizey, NULL); + + /* create render views */ + screen_opengl_views_setup(oglrender); + + /* wm vars */ + oglrender->wm = wm; + oglrender->win = win; + + oglrender->totvideos = 0; + oglrender->mh = NULL; + oglrender->movie_ctx_arr = NULL; + + if (is_animation) { + TaskScheduler *task_scheduler = BLI_task_scheduler_get(); + if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { + task_scheduler = BLI_task_scheduler_create(1); + oglrender->task_scheduler = task_scheduler; + oglrender->task_pool = BLI_task_pool_create_background(task_scheduler, oglrender); + } + else { + oglrender->task_scheduler = NULL; + oglrender->task_pool = BLI_task_pool_create(task_scheduler, oglrender); + } + oglrender->pool_ok = true; + BLI_spin_init(&oglrender->reports_lock); + } + else { + oglrender->task_scheduler = NULL; + oglrender->task_pool = NULL; + } + oglrender->num_scheduled_frames = 0; + BLI_mutex_init(&oglrender->task_mutex); + BLI_condition_init(&oglrender->task_condition); #ifdef DEBUG_TIME - oglrender->time_start = PIL_check_seconds_timer(); + oglrender->time_start = PIL_check_seconds_timer(); #endif - return true; + return true; } static void screen_opengl_render_end(bContext *C, OGLRender *oglrender) { - Main *bmain = CTX_data_main(C); - Scene *scene = oglrender->scene; - int i; - - if (oglrender->is_animation) { - /* Trickery part for movie output: - * - * We MUST write frames in an exact order, so we only let background - * thread to work on that, and main thread is simply waits for that - * thread to do all the dirty work. - * - * After this loop is done work_and_wait() will have nothing to do, - * so we don't run into wrong order of frames written to the stream. - */ - if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { - BLI_mutex_lock(&oglrender->task_mutex); - while (oglrender->num_scheduled_frames > 0) { - BLI_condition_wait(&oglrender->task_condition, - &oglrender->task_mutex); - } - BLI_mutex_unlock(&oglrender->task_mutex); - } - BLI_task_pool_work_and_wait(oglrender->task_pool); - BLI_task_pool_free(oglrender->task_pool); - /* Depending on various things we might or might not use global scheduler. */ - if (oglrender->task_scheduler != NULL) { - BLI_task_scheduler_free(oglrender->task_scheduler); - } - BLI_spin_end(&oglrender->reports_lock); - } - BLI_mutex_end(&oglrender->task_mutex); - BLI_condition_end(&oglrender->task_condition); + Main *bmain = CTX_data_main(C); + Scene *scene = oglrender->scene; + int i; + + if (oglrender->is_animation) { + /* Trickery part for movie output: + * + * We MUST write frames in an exact order, so we only let background + * thread to work on that, and main thread is simply waits for that + * thread to do all the dirty work. + * + * After this loop is done work_and_wait() will have nothing to do, + * so we don't run into wrong order of frames written to the stream. + */ + if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { + BLI_mutex_lock(&oglrender->task_mutex); + while (oglrender->num_scheduled_frames > 0) { + BLI_condition_wait(&oglrender->task_condition, &oglrender->task_mutex); + } + BLI_mutex_unlock(&oglrender->task_mutex); + } + BLI_task_pool_work_and_wait(oglrender->task_pool); + BLI_task_pool_free(oglrender->task_pool); + /* Depending on various things we might or might not use global scheduler. */ + if (oglrender->task_scheduler != NULL) { + BLI_task_scheduler_free(oglrender->task_scheduler); + } + BLI_spin_end(&oglrender->reports_lock); + } + BLI_mutex_end(&oglrender->task_mutex); + BLI_condition_end(&oglrender->task_condition); #ifdef DEBUG_TIME - printf("Total render time: %f\n", PIL_check_seconds_timer() - oglrender->time_start); + printf("Total render time: %f\n", PIL_check_seconds_timer() - oglrender->time_start); #endif - if (oglrender->mh) { - if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { - for (i = 0; i < oglrender->totvideos; i++) { - oglrender->mh->end_movie(oglrender->movie_ctx_arr[i]); - oglrender->mh->context_free(oglrender->movie_ctx_arr[i]); - } - } + if (oglrender->mh) { + if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { + for (i = 0; i < oglrender->totvideos; i++) { + oglrender->mh->end_movie(oglrender->movie_ctx_arr[i]); + oglrender->mh->context_free(oglrender->movie_ctx_arr[i]); + } + } - if (oglrender->movie_ctx_arr) { - MEM_freeN(oglrender->movie_ctx_arr); - } - } + if (oglrender->movie_ctx_arr) { + MEM_freeN(oglrender->movie_ctx_arr); + } + } - if (oglrender->timer) { /* exec will not have a timer */ - Depsgraph *depsgraph = oglrender->depsgraph; - scene->r.cfra = oglrender->cfrao; - BKE_scene_graph_update_for_newframe(depsgraph, bmain); + if (oglrender->timer) { /* exec will not have a timer */ + Depsgraph *depsgraph = oglrender->depsgraph; + scene->r.cfra = oglrender->cfrao; + BKE_scene_graph_update_for_newframe(depsgraph, bmain); - WM_event_remove_timer(oglrender->wm, oglrender->win, oglrender->timer); - } + WM_event_remove_timer(oglrender->wm, oglrender->win, oglrender->timer); + } - WM_cursor_modal_restore(oglrender->win); + WM_cursor_modal_restore(oglrender->win); - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene); + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene); - DRW_opengl_context_enable(); - GPU_offscreen_free(oglrender->ofs); - DRW_opengl_context_disable(); + DRW_opengl_context_enable(); + GPU_offscreen_free(oglrender->ofs); + DRW_opengl_context_disable(); - if (oglrender->is_sequencer) { - MEM_freeN(oglrender->seq_data.ibufs_arr); - } + if (oglrender->is_sequencer) { + MEM_freeN(oglrender->seq_data.ibufs_arr); + } - memset(&oglrender->scene->customdata_mask_modal, 0, sizeof(oglrender->scene->customdata_mask_modal)); + memset(&oglrender->scene->customdata_mask_modal, + 0, + sizeof(oglrender->scene->customdata_mask_modal)); - CTX_wm_area_set(C, oglrender->prevsa); - CTX_wm_region_set(C, oglrender->prevar); + CTX_wm_area_set(C, oglrender->prevsa); + CTX_wm_region_set(C, oglrender->prevar); - MEM_freeN(oglrender); + MEM_freeN(oglrender); } static void screen_opengl_render_cancel(bContext *C, wmOperator *op) { - screen_opengl_render_end(C, op->customdata); + screen_opengl_render_end(C, op->customdata); } /* share between invoke and exec */ static bool screen_opengl_render_anim_initialize(bContext *C, wmOperator *op) { - /* initialize animation */ - OGLRender *oglrender; - Scene *scene; - - oglrender = op->customdata; - scene = oglrender->scene; - oglrender->totvideos = BKE_scene_multiview_num_videos_get(&scene->r); - - oglrender->reports = op->reports; - - if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { - size_t width, height; - int i; - - BKE_scene_multiview_videos_dimensions_get(&scene->r, oglrender->sizex, oglrender->sizey, &width, &height); - oglrender->mh = BKE_movie_handle_get(scene->r.im_format.imtype); - - if (oglrender->mh == NULL) { - BKE_report(oglrender->reports, RPT_ERROR, "Movie format unsupported"); - screen_opengl_render_end(C, oglrender); - return false; - } - - oglrender->movie_ctx_arr = MEM_mallocN(sizeof(void *) * oglrender->totvideos, "Movies"); - - for (i = 0; i < oglrender->totvideos; i++) { - const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, i); - - oglrender->movie_ctx_arr[i] = oglrender->mh->context_create(); - if (!oglrender->mh->start_movie(oglrender->movie_ctx_arr[i], scene, &scene->r, oglrender->sizex, - oglrender->sizey, oglrender->reports, PRVRANGEON != 0, suffix)) - { - screen_opengl_render_end(C, oglrender); - return false; - } - } - } - - oglrender->cfrao = scene->r.cfra; - oglrender->nfra = PSFRA; - scene->r.cfra = PSFRA; - - return true; + /* initialize animation */ + OGLRender *oglrender; + Scene *scene; + + oglrender = op->customdata; + scene = oglrender->scene; + oglrender->totvideos = BKE_scene_multiview_num_videos_get(&scene->r); + + oglrender->reports = op->reports; + + if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { + size_t width, height; + int i; + + BKE_scene_multiview_videos_dimensions_get( + &scene->r, oglrender->sizex, oglrender->sizey, &width, &height); + oglrender->mh = BKE_movie_handle_get(scene->r.im_format.imtype); + + if (oglrender->mh == NULL) { + BKE_report(oglrender->reports, RPT_ERROR, "Movie format unsupported"); + screen_opengl_render_end(C, oglrender); + return false; + } + + oglrender->movie_ctx_arr = MEM_mallocN(sizeof(void *) * oglrender->totvideos, "Movies"); + + for (i = 0; i < oglrender->totvideos; i++) { + const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, i); + + oglrender->movie_ctx_arr[i] = oglrender->mh->context_create(); + if (!oglrender->mh->start_movie(oglrender->movie_ctx_arr[i], + scene, + &scene->r, + oglrender->sizex, + oglrender->sizey, + oglrender->reports, + PRVRANGEON != 0, + suffix)) { + screen_opengl_render_end(C, oglrender); + return false; + } + } + } + + oglrender->cfrao = scene->r.cfra; + oglrender->nfra = PSFRA; + scene->r.cfra = PSFRA; + + return true; } typedef struct WriteTaskData { - RenderResult *rr; - Scene tmp_scene; + RenderResult *rr; + Scene tmp_scene; } WriteTaskData; -static void write_result_func(TaskPool * __restrict pool, - void *task_data_v, - int UNUSED(thread_id)) +static void write_result_func(TaskPool *__restrict pool, void *task_data_v, int UNUSED(thread_id)) { - OGLRender *oglrender = (OGLRender *) BLI_task_pool_userdata(pool); - WriteTaskData *task_data = (WriteTaskData *) task_data_v; - Scene *scene = &task_data->tmp_scene; - RenderResult *rr = task_data->rr; - const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype); - const int cfra = scene->r.cfra; - bool ok; - /* Don't attempt to write if we've got an error. */ - if (!oglrender->pool_ok) { - RE_FreeRenderResult(rr); - BLI_mutex_lock(&oglrender->task_mutex); - oglrender->num_scheduled_frames--; - BLI_condition_notify_all(&oglrender->task_condition); - BLI_mutex_unlock(&oglrender->task_mutex); - return; - } - /* Construct local thread0safe copy of reports structure which we can - * safely pass to the underlying functions. - */ - ReportList reports; - BKE_reports_init(&reports, oglrender->reports->flag & ~RPT_PRINT); - /* Do actual save logic here, depending on the file format. - * - * NOTE: We have to construct temporary scene with proper scene->r.cfra. - * This is because underlying calls do not use r.cfra but use scene - * for that. - */ - if (is_movie) { - ok = RE_WriteRenderViewsMovie(&reports, - rr, - scene, - &scene->r, - oglrender->mh, - oglrender->movie_ctx_arr, - oglrender->totvideos, - PRVRANGEON != 0); - } - else { - /* TODO(sergey): We can in theory save some CPU ticks here because we - * calculate file name again here. - */ - char name[FILE_MAX]; - BKE_image_path_from_imformat(name, - scene->r.pic, - BKE_main_blendfile_path(oglrender->bmain), - cfra, - &scene->r.im_format, - (scene->r.scemode & R_EXTENSION) != 0, - true, - NULL); - - BKE_render_result_stamp_info(scene, scene->camera, rr, false); - ok = RE_WriteRenderViewsImage(NULL, rr, scene, true, name); - if (!ok) { - BKE_reportf(&reports, - RPT_ERROR, - "Write error: cannot save %s", - name); - } - } - if (reports.list.first != NULL) { - BLI_spin_lock(&oglrender->reports_lock); - for (Report *report = reports.list.first; - report != NULL; - report = report->next) - { - BKE_report(oglrender->reports, - report->type, - report->message); - } - BLI_spin_unlock(&oglrender->reports_lock); - } - if (!ok) { - oglrender->pool_ok = false; - } - RE_FreeRenderResult(rr); - BLI_mutex_lock(&oglrender->task_mutex); - oglrender->num_scheduled_frames--; - BLI_condition_notify_all(&oglrender->task_condition); - BLI_mutex_unlock(&oglrender->task_mutex); + OGLRender *oglrender = (OGLRender *)BLI_task_pool_userdata(pool); + WriteTaskData *task_data = (WriteTaskData *)task_data_v; + Scene *scene = &task_data->tmp_scene; + RenderResult *rr = task_data->rr; + const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype); + const int cfra = scene->r.cfra; + bool ok; + /* Don't attempt to write if we've got an error. */ + if (!oglrender->pool_ok) { + RE_FreeRenderResult(rr); + BLI_mutex_lock(&oglrender->task_mutex); + oglrender->num_scheduled_frames--; + BLI_condition_notify_all(&oglrender->task_condition); + BLI_mutex_unlock(&oglrender->task_mutex); + return; + } + /* Construct local thread0safe copy of reports structure which we can + * safely pass to the underlying functions. + */ + ReportList reports; + BKE_reports_init(&reports, oglrender->reports->flag & ~RPT_PRINT); + /* Do actual save logic here, depending on the file format. + * + * NOTE: We have to construct temporary scene with proper scene->r.cfra. + * This is because underlying calls do not use r.cfra but use scene + * for that. + */ + if (is_movie) { + ok = RE_WriteRenderViewsMovie(&reports, + rr, + scene, + &scene->r, + oglrender->mh, + oglrender->movie_ctx_arr, + oglrender->totvideos, + PRVRANGEON != 0); + } + else { + /* TODO(sergey): We can in theory save some CPU ticks here because we + * calculate file name again here. + */ + char name[FILE_MAX]; + BKE_image_path_from_imformat(name, + scene->r.pic, + BKE_main_blendfile_path(oglrender->bmain), + cfra, + &scene->r.im_format, + (scene->r.scemode & R_EXTENSION) != 0, + true, + NULL); + + BKE_render_result_stamp_info(scene, scene->camera, rr, false); + ok = RE_WriteRenderViewsImage(NULL, rr, scene, true, name); + if (!ok) { + BKE_reportf(&reports, RPT_ERROR, "Write error: cannot save %s", name); + } + } + if (reports.list.first != NULL) { + BLI_spin_lock(&oglrender->reports_lock); + for (Report *report = reports.list.first; report != NULL; report = report->next) { + BKE_report(oglrender->reports, report->type, report->message); + } + BLI_spin_unlock(&oglrender->reports_lock); + } + if (!ok) { + oglrender->pool_ok = false; + } + RE_FreeRenderResult(rr); + BLI_mutex_lock(&oglrender->task_mutex); + oglrender->num_scheduled_frames--; + BLI_condition_notify_all(&oglrender->task_condition); + BLI_mutex_unlock(&oglrender->task_mutex); } static bool schedule_write_result(OGLRender *oglrender, RenderResult *rr) { - if (!oglrender->pool_ok) { - RE_FreeRenderResult(rr); - return false; - } - Scene *scene = oglrender->scene; - WriteTaskData *task_data = MEM_mallocN(sizeof(WriteTaskData), "write task data"); - task_data->rr = rr; - task_data->tmp_scene = *scene; - BLI_mutex_lock(&oglrender->task_mutex); - oglrender->num_scheduled_frames++; - if (oglrender->num_scheduled_frames > MAX_SCHEDULED_FRAMES) { - BLI_condition_wait(&oglrender->task_condition, - &oglrender->task_mutex); - } - BLI_mutex_unlock(&oglrender->task_mutex); - BLI_task_pool_push(oglrender->task_pool, - write_result_func, - task_data, - true, - TASK_PRIORITY_LOW); - return true; + if (!oglrender->pool_ok) { + RE_FreeRenderResult(rr); + return false; + } + Scene *scene = oglrender->scene; + WriteTaskData *task_data = MEM_mallocN(sizeof(WriteTaskData), "write task data"); + task_data->rr = rr; + task_data->tmp_scene = *scene; + BLI_mutex_lock(&oglrender->task_mutex); + oglrender->num_scheduled_frames++; + if (oglrender->num_scheduled_frames > MAX_SCHEDULED_FRAMES) { + BLI_condition_wait(&oglrender->task_condition, &oglrender->task_mutex); + } + BLI_mutex_unlock(&oglrender->task_mutex); + BLI_task_pool_push(oglrender->task_pool, write_result_func, task_data, true, TASK_PRIORITY_LOW); + return true; } static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - OGLRender *oglrender = op->customdata; - Scene *scene = oglrender->scene; - Depsgraph *depsgraph = oglrender->depsgraph; - char name[FILE_MAX]; - bool ok = false; - const bool view_context = (oglrender->v3d != NULL); - bool is_movie; - RenderResult *rr; - - /* go to next frame */ - if (CFRA < oglrender->nfra) - CFRA++; - while (CFRA < oglrender->nfra) { - BKE_scene_graph_update_for_newframe(depsgraph, bmain); - CFRA++; - } - - is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype); - - if (!is_movie) { - BKE_image_path_from_imformat( - name, scene->r.pic, BKE_main_blendfile_path(oglrender->bmain), scene->r.cfra, - &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL); - - if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) { - BLI_spin_lock(&oglrender->reports_lock); - BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name); - BLI_spin_unlock(&oglrender->reports_lock); - ok = true; - goto finally; - } - } - - WM_cursor_time(oglrender->win, scene->r.cfra); - - BKE_scene_graph_update_for_newframe(depsgraph, bmain); - - if (view_context) { - if (oglrender->rv3d->persp == RV3D_CAMOB && oglrender->v3d->camera && oglrender->v3d->scenelock) { - /* since BKE_scene_graph_update_for_newframe() is used rather - * then ED_update_for_newframe() the camera needs to be set */ - if (BKE_scene_camera_switch_update(scene)) { - oglrender->v3d->camera = scene->camera; - } - } - } - else { - BKE_scene_camera_switch_update(scene); - } - - /* render into offscreen buffer */ - screen_opengl_render_apply(C, oglrender); - - /* save to disk */ - rr = RE_AcquireResultRead(oglrender->re); - RenderResult *new_rr = RE_DuplicateRenderResult(rr); - RE_ReleaseResult(oglrender->re); - - ok = schedule_write_result(oglrender, new_rr); - -finally: /* Step the frame and bail early if needed */ - - /* go to next frame */ - oglrender->nfra += scene->r.frame_step; - - /* stop at the end or on error */ - if (CFRA >= PEFRA || !ok) { - screen_opengl_render_end(C, op->customdata); - return 0; - } - - return 1; + Main *bmain = CTX_data_main(C); + OGLRender *oglrender = op->customdata; + Scene *scene = oglrender->scene; + Depsgraph *depsgraph = oglrender->depsgraph; + char name[FILE_MAX]; + bool ok = false; + const bool view_context = (oglrender->v3d != NULL); + bool is_movie; + RenderResult *rr; + + /* go to next frame */ + if (CFRA < oglrender->nfra) + CFRA++; + while (CFRA < oglrender->nfra) { + BKE_scene_graph_update_for_newframe(depsgraph, bmain); + CFRA++; + } + + is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype); + + if (!is_movie) { + BKE_image_path_from_imformat(name, + scene->r.pic, + BKE_main_blendfile_path(oglrender->bmain), + scene->r.cfra, + &scene->r.im_format, + (scene->r.scemode & R_EXTENSION) != 0, + true, + NULL); + + if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) { + BLI_spin_lock(&oglrender->reports_lock); + BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name); + BLI_spin_unlock(&oglrender->reports_lock); + ok = true; + goto finally; + } + } + + WM_cursor_time(oglrender->win, scene->r.cfra); + + BKE_scene_graph_update_for_newframe(depsgraph, bmain); + + if (view_context) { + if (oglrender->rv3d->persp == RV3D_CAMOB && oglrender->v3d->camera && + oglrender->v3d->scenelock) { + /* since BKE_scene_graph_update_for_newframe() is used rather + * then ED_update_for_newframe() the camera needs to be set */ + if (BKE_scene_camera_switch_update(scene)) { + oglrender->v3d->camera = scene->camera; + } + } + } + else { + BKE_scene_camera_switch_update(scene); + } + + /* render into offscreen buffer */ + screen_opengl_render_apply(C, oglrender); + + /* save to disk */ + rr = RE_AcquireResultRead(oglrender->re); + RenderResult *new_rr = RE_DuplicateRenderResult(rr); + RE_ReleaseResult(oglrender->re); + + ok = schedule_write_result(oglrender, new_rr); + +finally: /* Step the frame and bail early if needed */ + + /* go to next frame */ + oglrender->nfra += scene->r.frame_step; + + /* stop at the end or on error */ + if (CFRA >= PEFRA || !ok) { + screen_opengl_render_end(C, op->customdata); + return 0; + } + + return 1; } - static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent *event) { - OGLRender *oglrender = op->customdata; - const bool anim = RNA_boolean_get(op->ptr, "animation"); - bool ret; - - switch (event->type) { - case ESCKEY: - /* cancel */ - oglrender->pool_ok = false; /* Flag pool for cancel. */ - screen_opengl_render_end(C, op->customdata); - return OPERATOR_FINISHED; - case TIMER: - /* render frame? */ - if (oglrender->timer == event->customdata) - break; - ATTR_FALLTHROUGH; - default: - /* nothing to do */ - return OPERATOR_RUNNING_MODAL; - } - - /* run first because screen_opengl_render_anim_step can free oglrender */ - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene); - - if (anim == 0) { - screen_opengl_render_apply(C, op->customdata); - screen_opengl_render_end(C, op->customdata); - return OPERATOR_FINISHED; - } - else { - ret = screen_opengl_render_anim_step(C, op); - } - - /* stop at the end or on error */ - if (ret == false) { - return OPERATOR_FINISHED; - } - - return OPERATOR_RUNNING_MODAL; + OGLRender *oglrender = op->customdata; + const bool anim = RNA_boolean_get(op->ptr, "animation"); + bool ret; + + switch (event->type) { + case ESCKEY: + /* cancel */ + oglrender->pool_ok = false; /* Flag pool for cancel. */ + screen_opengl_render_end(C, op->customdata); + return OPERATOR_FINISHED; + case TIMER: + /* render frame? */ + if (oglrender->timer == event->customdata) + break; + ATTR_FALLTHROUGH; + default: + /* nothing to do */ + return OPERATOR_RUNNING_MODAL; + } + + /* run first because screen_opengl_render_anim_step can free oglrender */ + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, oglrender->scene); + + if (anim == 0) { + screen_opengl_render_apply(C, op->customdata); + screen_opengl_render_end(C, op->customdata); + return OPERATOR_FINISHED; + } + else { + ret = screen_opengl_render_anim_step(C, op); + } + + /* stop at the end or on error */ + if (ret == false) { + return OPERATOR_FINISHED; + } + + return OPERATOR_RUNNING_MODAL; } static int screen_opengl_render_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - OGLRender *oglrender; - const bool anim = RNA_boolean_get(op->ptr, "animation"); + OGLRender *oglrender; + const bool anim = RNA_boolean_get(op->ptr, "animation"); - if (!screen_opengl_render_init(C, op)) - return OPERATOR_CANCELLED; + if (!screen_opengl_render_init(C, op)) + return OPERATOR_CANCELLED; - if (anim) { - if (!screen_opengl_render_anim_initialize(C, op)) - return OPERATOR_CANCELLED; - } + if (anim) { + if (!screen_opengl_render_anim_initialize(C, op)) + return OPERATOR_CANCELLED; + } - oglrender = op->customdata; - render_view_open(C, event->x, event->y, op->reports); + oglrender = op->customdata; + render_view_open(C, event->x, event->y, op->reports); - /* view may be changed above (R_OUTPUT_WINDOW) */ - oglrender->win = CTX_wm_window(C); + /* view may be changed above (R_OUTPUT_WINDOW) */ + oglrender->win = CTX_wm_window(C); - WM_event_add_modal_handler(C, op); - oglrender->timer = WM_event_add_timer(oglrender->wm, oglrender->win, TIMER, 0.01f); + WM_event_add_modal_handler(C, op); + oglrender->timer = WM_event_add_timer(oglrender->wm, oglrender->win, TIMER, 0.01f); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } /* executes blocking render */ static int screen_opengl_render_exec(bContext *C, wmOperator *op) { - const bool is_animation = RNA_boolean_get(op->ptr, "animation"); + const bool is_animation = RNA_boolean_get(op->ptr, "animation"); - if (!screen_opengl_render_init(C, op)) - return OPERATOR_CANCELLED; + if (!screen_opengl_render_init(C, op)) + return OPERATOR_CANCELLED; - if (!is_animation) { /* same as invoke */ - /* render image */ - screen_opengl_render_apply(C, op->customdata); - screen_opengl_render_end(C, op->customdata); + if (!is_animation) { /* same as invoke */ + /* render image */ + screen_opengl_render_apply(C, op->customdata); + screen_opengl_render_end(C, op->customdata); - return OPERATOR_FINISHED; - } - else { - bool ret = true; + return OPERATOR_FINISHED; + } + else { + bool ret = true; - if (!screen_opengl_render_anim_initialize(C, op)) - return OPERATOR_CANCELLED; + if (!screen_opengl_render_anim_initialize(C, op)) + return OPERATOR_CANCELLED; - while (ret) { - ret = screen_opengl_render_anim_step(C, op); - } - } + while (ret) { + ret = screen_opengl_render_anim_step(C, op); + } + } - /* no redraw needed, we leave state as we entered it */ -// ED_update_for_newframe(C); - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, CTX_data_scene(C)); + /* no redraw needed, we leave state as we entered it */ + // ED_update_for_newframe(C); + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, CTX_data_scene(C)); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void RENDER_OT_opengl(wmOperatorType *ot) { - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Viewport Render"; - ot->description = "Take a snapshot of the active viewport"; - ot->idname = "RENDER_OT_opengl"; - - /* api callbacks */ - ot->invoke = screen_opengl_render_invoke; - ot->exec = screen_opengl_render_exec; /* blocking */ - ot->modal = screen_opengl_render_modal; - ot->cancel = screen_opengl_render_cancel; - - ot->poll = ED_operator_screenactive; - - prop = RNA_def_boolean(ot->srna, "animation", 0, "Animation", "Render files from the animation range of this scene"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "sequencer", 0, "Sequencer", "Render using the sequencer's OpenGL display"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "write_still", 0, "Write Image", "Save rendered the image to the output path (used only when animation is disabled)"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "view_context", 1, "View Context", "Use the current 3D view for rendering, else use scene settings"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Viewport Render"; + ot->description = "Take a snapshot of the active viewport"; + ot->idname = "RENDER_OT_opengl"; + + /* api callbacks */ + ot->invoke = screen_opengl_render_invoke; + ot->exec = screen_opengl_render_exec; /* blocking */ + ot->modal = screen_opengl_render_modal; + ot->cancel = screen_opengl_render_cancel; + + ot->poll = ED_operator_screenactive; + + prop = RNA_def_boolean(ot->srna, + "animation", + 0, + "Animation", + "Render files from the animation range of this scene"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "sequencer", 0, "Sequencer", "Render using the sequencer's OpenGL display"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, + "write_still", + 0, + "Write Image", + "Save rendered the image to the output path (used only when animation is disabled)"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, + "view_context", + 1, + "View Context", + "Use the current 3D view for rendering, else use scene settings"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* function for getting an opengl buffer from a View3D, used by sequencer */ diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c index ad3a5a161ac..b77f5c2bbad 100644 --- a/source/blender/editors/render/render_ops.c +++ b/source/blender/editors/render/render_ops.c @@ -29,66 +29,66 @@ #include "WM_api.h" -#include "render_intern.h" // own include +#include "render_intern.h" // own include /***************************** render ***********************************/ void ED_operatortypes_render(void) { - WM_operatortype_append(OBJECT_OT_material_slot_add); - WM_operatortype_append(OBJECT_OT_material_slot_remove); - WM_operatortype_append(OBJECT_OT_material_slot_assign); - WM_operatortype_append(OBJECT_OT_material_slot_select); - WM_operatortype_append(OBJECT_OT_material_slot_deselect); - WM_operatortype_append(OBJECT_OT_material_slot_copy); - WM_operatortype_append(OBJECT_OT_material_slot_move); + WM_operatortype_append(OBJECT_OT_material_slot_add); + WM_operatortype_append(OBJECT_OT_material_slot_remove); + WM_operatortype_append(OBJECT_OT_material_slot_assign); + WM_operatortype_append(OBJECT_OT_material_slot_select); + WM_operatortype_append(OBJECT_OT_material_slot_deselect); + WM_operatortype_append(OBJECT_OT_material_slot_copy); + WM_operatortype_append(OBJECT_OT_material_slot_move); - WM_operatortype_append(MATERIAL_OT_new); - WM_operatortype_append(TEXTURE_OT_new); - WM_operatortype_append(WORLD_OT_new); + WM_operatortype_append(MATERIAL_OT_new); + WM_operatortype_append(TEXTURE_OT_new); + WM_operatortype_append(WORLD_OT_new); - WM_operatortype_append(MATERIAL_OT_copy); - WM_operatortype_append(MATERIAL_OT_paste); + WM_operatortype_append(MATERIAL_OT_copy); + WM_operatortype_append(MATERIAL_OT_paste); - WM_operatortype_append(SCENE_OT_view_layer_add); - WM_operatortype_append(SCENE_OT_view_layer_remove); + WM_operatortype_append(SCENE_OT_view_layer_add); + WM_operatortype_append(SCENE_OT_view_layer_remove); - WM_operatortype_append(SCENE_OT_render_view_add); - WM_operatortype_append(SCENE_OT_render_view_remove); + WM_operatortype_append(SCENE_OT_render_view_add); + WM_operatortype_append(SCENE_OT_render_view_remove); - WM_operatortype_append(SCENE_OT_light_cache_bake); - WM_operatortype_append(SCENE_OT_light_cache_free); + WM_operatortype_append(SCENE_OT_light_cache_bake); + WM_operatortype_append(SCENE_OT_light_cache_free); #ifdef WITH_FREESTYLE - WM_operatortype_append(SCENE_OT_freestyle_module_add); - WM_operatortype_append(SCENE_OT_freestyle_module_remove); - WM_operatortype_append(SCENE_OT_freestyle_module_move); - WM_operatortype_append(SCENE_OT_freestyle_lineset_add); - WM_operatortype_append(SCENE_OT_freestyle_lineset_copy); - WM_operatortype_append(SCENE_OT_freestyle_lineset_paste); - WM_operatortype_append(SCENE_OT_freestyle_lineset_remove); - WM_operatortype_append(SCENE_OT_freestyle_lineset_move); - WM_operatortype_append(SCENE_OT_freestyle_linestyle_new); - WM_operatortype_append(SCENE_OT_freestyle_color_modifier_add); - WM_operatortype_append(SCENE_OT_freestyle_alpha_modifier_add); - WM_operatortype_append(SCENE_OT_freestyle_thickness_modifier_add); - WM_operatortype_append(SCENE_OT_freestyle_geometry_modifier_add); - WM_operatortype_append(SCENE_OT_freestyle_modifier_remove); - WM_operatortype_append(SCENE_OT_freestyle_modifier_move); - WM_operatortype_append(SCENE_OT_freestyle_modifier_copy); - WM_operatortype_append(SCENE_OT_freestyle_stroke_material_create); + WM_operatortype_append(SCENE_OT_freestyle_module_add); + WM_operatortype_append(SCENE_OT_freestyle_module_remove); + WM_operatortype_append(SCENE_OT_freestyle_module_move); + WM_operatortype_append(SCENE_OT_freestyle_lineset_add); + WM_operatortype_append(SCENE_OT_freestyle_lineset_copy); + WM_operatortype_append(SCENE_OT_freestyle_lineset_paste); + WM_operatortype_append(SCENE_OT_freestyle_lineset_remove); + WM_operatortype_append(SCENE_OT_freestyle_lineset_move); + WM_operatortype_append(SCENE_OT_freestyle_linestyle_new); + WM_operatortype_append(SCENE_OT_freestyle_color_modifier_add); + WM_operatortype_append(SCENE_OT_freestyle_alpha_modifier_add); + WM_operatortype_append(SCENE_OT_freestyle_thickness_modifier_add); + WM_operatortype_append(SCENE_OT_freestyle_geometry_modifier_add); + WM_operatortype_append(SCENE_OT_freestyle_modifier_remove); + WM_operatortype_append(SCENE_OT_freestyle_modifier_move); + WM_operatortype_append(SCENE_OT_freestyle_modifier_copy); + WM_operatortype_append(SCENE_OT_freestyle_stroke_material_create); #endif - WM_operatortype_append(TEXTURE_OT_slot_copy); - WM_operatortype_append(TEXTURE_OT_slot_paste); - WM_operatortype_append(TEXTURE_OT_slot_move); + WM_operatortype_append(TEXTURE_OT_slot_copy); + WM_operatortype_append(TEXTURE_OT_slot_paste); + WM_operatortype_append(TEXTURE_OT_slot_move); - /* render_internal.c */ - WM_operatortype_append(RENDER_OT_view_show); - WM_operatortype_append(RENDER_OT_render); - WM_operatortype_append(RENDER_OT_view_cancel); - WM_operatortype_append(RENDER_OT_shutter_curve_preset); + /* render_internal.c */ + WM_operatortype_append(RENDER_OT_view_show); + WM_operatortype_append(RENDER_OT_render); + WM_operatortype_append(RENDER_OT_view_cancel); + WM_operatortype_append(RENDER_OT_shutter_curve_preset); - /* render_opengl.c */ - WM_operatortype_append(RENDER_OT_opengl); + /* render_opengl.c */ + WM_operatortype_append(RENDER_OT_opengl); } diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 77b24a1b4d9..c62d6530c6b 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -21,7 +21,6 @@ * \ingroup edrend */ - /* global includes */ #include <stdlib.h> @@ -29,9 +28,9 @@ #include <string.h> #ifndef WIN32 -#include <unistd.h> +# include <unistd.h> #else -#include <io.h> +# include <io.h> #endif #include "MEM_guardedalloc.h" @@ -102,89 +101,90 @@ ImBuf *get_brush_icon(Brush *brush) { - static const int flags = IB_rect | IB_multilayer | IB_metadata; + static const int flags = IB_rect | IB_multilayer | IB_metadata; - char path[FILE_MAX]; - const char *folder; + char path[FILE_MAX]; + const char *folder; - if (!(brush->icon_imbuf)) { - if (brush->flag & BRUSH_CUSTOM_ICON) { + if (!(brush->icon_imbuf)) { + if (brush->flag & BRUSH_CUSTOM_ICON) { - if (brush->icon_filepath[0]) { - // first use the path directly to try and load the file + if (brush->icon_filepath[0]) { + // first use the path directly to try and load the file - BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath)); - BLI_path_abs(path, BKE_main_blendfile_path_from_global()); + BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath)); + BLI_path_abs(path, BKE_main_blendfile_path_from_global()); - /* use default colorspaces for brushes */ - brush->icon_imbuf = IMB_loadiffname(path, flags, NULL); + /* use default colorspaces for brushes */ + brush->icon_imbuf = IMB_loadiffname(path, flags, NULL); - // otherwise lets try to find it in other directories - if (!(brush->icon_imbuf)) { - folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons"); + // otherwise lets try to find it in other directories + if (!(brush->icon_imbuf)) { + folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons"); - BLI_make_file_string(BKE_main_blendfile_path_from_global(), path, folder, brush->icon_filepath); + BLI_make_file_string( + BKE_main_blendfile_path_from_global(), path, folder, brush->icon_filepath); - if (path[0]) { - /* use fefault color spaces */ - brush->icon_imbuf = IMB_loadiffname(path, flags, NULL); - } - } + if (path[0]) { + /* use fefault color spaces */ + brush->icon_imbuf = IMB_loadiffname(path, flags, NULL); + } + } - if (brush->icon_imbuf) - BKE_icon_changed(BKE_icon_id_ensure(&brush->id)); - } - } - } + if (brush->icon_imbuf) + BKE_icon_changed(BKE_icon_id_ensure(&brush->id)); + } + } + } - if (!(brush->icon_imbuf)) - brush->id.icon_id = 0; + if (!(brush->icon_imbuf)) + brush->id.icon_id = 0; - return brush->icon_imbuf; + return brush->icon_imbuf; } typedef struct ShaderPreview { - /* from wmJob */ - void *owner; - short *stop, *do_update; - - Scene *scene; - Depsgraph *depsgraph; - ID *id, *id_copy; - ID *parent; - MTex *slot; - - /* datablocks with nodes need full copy during preview render, glsl uses it too */ - Material *matcopy; - Tex *texcopy; - Light *lampcopy; - World *worldcopy; - - /** Copy of the active objects #Object.color */ - float color[4]; - - int sizex, sizey; - unsigned int *pr_rect; - int pr_method; - bool own_id_copy; - - Main *bmain; - Main *pr_main; + /* from wmJob */ + void *owner; + short *stop, *do_update; + + Scene *scene; + Depsgraph *depsgraph; + ID *id, *id_copy; + ID *parent; + MTex *slot; + + /* datablocks with nodes need full copy during preview render, glsl uses it too */ + Material *matcopy; + Tex *texcopy; + Light *lampcopy; + World *worldcopy; + + /** Copy of the active objects #Object.color */ + float color[4]; + + int sizex, sizey; + unsigned int *pr_rect; + int pr_method; + bool own_id_copy; + + Main *bmain; + Main *pr_main; } ShaderPreview; typedef struct IconPreviewSize { - struct IconPreviewSize *next, *prev; - int sizex, sizey; - unsigned int *rect; + struct IconPreviewSize *next, *prev; + int sizex, sizey; + unsigned int *rect; } IconPreviewSize; typedef struct IconPreview { - Main *bmain; - Scene *scene; - Depsgraph *depsgraph; - void *owner; - ID *id, *id_copy; - ListBase sizes; + Main *bmain; + Scene *scene; + Depsgraph *depsgraph; + void *owner; + ID *id, *id_copy; + ListBase sizes; } IconPreview; /* *************************** Preview for buttons *********************** */ @@ -195,1195 +195,1242 @@ static Main *G_pr_main_grease_pencil = NULL; #ifndef WITH_HEADLESS static Main *load_main_from_memory(const void *blend, int blend_size) { - const int fileflags = G.fileflags; - Main *bmain = NULL; - BlendFileData *bfd; + const int fileflags = G.fileflags; + Main *bmain = NULL; + BlendFileData *bfd; - G.fileflags |= G_FILE_NO_UI; - bfd = BLO_read_from_memory(blend, blend_size, BLO_READ_SKIP_NONE, NULL); - if (bfd) { - bmain = bfd->main; + G.fileflags |= G_FILE_NO_UI; + bfd = BLO_read_from_memory(blend, blend_size, BLO_READ_SKIP_NONE, NULL); + if (bfd) { + bmain = bfd->main; - MEM_freeN(bfd); - } - G.fileflags = fileflags; + MEM_freeN(bfd); + } + G.fileflags = fileflags; - return bmain; + return bmain; } #endif void ED_preview_ensure_dbase(void) { #ifndef WITH_HEADLESS - static bool base_initialized = false; - BLI_assert(BLI_thread_is_main()); - if (!base_initialized) { - G_pr_main = load_main_from_memory(datatoc_preview_blend, datatoc_preview_blend_size); - G_pr_main_grease_pencil = load_main_from_memory(datatoc_preview_grease_pencil_blend, datatoc_preview_grease_pencil_blend_size); - base_initialized = true; - } + static bool base_initialized = false; + BLI_assert(BLI_thread_is_main()); + if (!base_initialized) { + G_pr_main = load_main_from_memory(datatoc_preview_blend, datatoc_preview_blend_size); + G_pr_main_grease_pencil = load_main_from_memory(datatoc_preview_grease_pencil_blend, + datatoc_preview_grease_pencil_blend_size); + base_initialized = true; + } #endif } static bool check_engine_supports_preview(Scene *scene) { - RenderEngineType *type = RE_engines_find(scene->r.engine); - return (type->flag & RE_USE_PREVIEW) != 0; + RenderEngineType *type = RE_engines_find(scene->r.engine); + return (type->flag & RE_USE_PREVIEW) != 0; } void ED_preview_free_dbase(void) { - if (G_pr_main) - BKE_main_free(G_pr_main); + if (G_pr_main) + BKE_main_free(G_pr_main); - if (G_pr_main_grease_pencil) - BKE_main_free(G_pr_main_grease_pencil); + if (G_pr_main_grease_pencil) + BKE_main_free(G_pr_main_grease_pencil); } static Scene *preview_get_scene(Main *pr_main) { - if (pr_main == NULL) return NULL; + if (pr_main == NULL) + return NULL; - return pr_main->scenes.first; + return pr_main->scenes.first; } static const char *preview_collection_name(const char pr_type) { - switch (pr_type) { - case MA_FLAT: - return "Flat"; - case MA_SPHERE: - return "Sphere"; - case MA_CUBE: - return "Cube"; - case MA_SHADERBALL: - return "Shader Ball"; - case MA_CLOTH: - return "Cloth"; - case MA_FLUID: - return "Fluid"; - case MA_SPHERE_A: - return "World Shader Ball"; - case MA_LAMP: - return "Lamp"; - case MA_SKY: - return "Sky"; - case MA_HAIR: - return "Hair"; - case MA_ATMOS: - return "Atmosphere"; - default: - BLI_assert(!"Unknown preview type"); - return ""; - } + switch (pr_type) { + case MA_FLAT: + return "Flat"; + case MA_SPHERE: + return "Sphere"; + case MA_CUBE: + return "Cube"; + case MA_SHADERBALL: + return "Shader Ball"; + case MA_CLOTH: + return "Cloth"; + case MA_FLUID: + return "Fluid"; + case MA_SPHERE_A: + return "World Shader Ball"; + case MA_LAMP: + return "Lamp"; + case MA_SKY: + return "Sky"; + case MA_HAIR: + return "Hair"; + case MA_ATMOS: + return "Atmosphere"; + default: + BLI_assert(!"Unknown preview type"); + return ""; + } } -static void set_preview_visibility(Scene *scene, ViewLayer *view_layer, char pr_type, int pr_method) +static void set_preview_visibility(Scene *scene, + ViewLayer *view_layer, + char pr_type, + int pr_method) { - /* Set appropriate layer as visibile. */ - LayerCollection *lc = view_layer->layer_collections.first; - const char *collection_name = preview_collection_name(pr_type); - - for (lc = lc->layer_collections.first; lc; lc = lc->next) { - if (STREQ(lc->collection->id.name + 2, collection_name)) { - lc->collection->flag &= ~COLLECTION_RESTRICT_RENDER; - } - else { - lc->collection->flag |= COLLECTION_RESTRICT_RENDER; - } - } - - /* Hide floor for icon renders. */ - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (STREQ(base->object->id.name + 2, "Floor")) { - if (pr_method == PR_ICON_RENDER) { - base->object->restrictflag |= OB_RESTRICT_RENDER; - } - else { - base->object->restrictflag &= ~OB_RESTRICT_RENDER; - } - } - } - - BKE_layer_collection_sync(scene, view_layer); + /* Set appropriate layer as visibile. */ + LayerCollection *lc = view_layer->layer_collections.first; + const char *collection_name = preview_collection_name(pr_type); + + for (lc = lc->layer_collections.first; lc; lc = lc->next) { + if (STREQ(lc->collection->id.name + 2, collection_name)) { + lc->collection->flag &= ~COLLECTION_RESTRICT_RENDER; + } + else { + lc->collection->flag |= COLLECTION_RESTRICT_RENDER; + } + } + + /* Hide floor for icon renders. */ + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if (STREQ(base->object->id.name + 2, "Floor")) { + if (pr_method == PR_ICON_RENDER) { + base->object->restrictflag |= OB_RESTRICT_RENDER; + } + else { + base->object->restrictflag &= ~OB_RESTRICT_RENDER; + } + } + } + + BKE_layer_collection_sync(scene, view_layer); } static World *preview_get_localized_world(ShaderPreview *sp, World *world) { - if (world == NULL) { - return NULL; - } - if (sp->worldcopy != NULL) { - return sp->worldcopy; - } - sp->worldcopy = BKE_world_localize(world); - BLI_addtail(&sp->pr_main->worlds, sp->worldcopy); - return sp->worldcopy; + if (world == NULL) { + return NULL; + } + if (sp->worldcopy != NULL) { + return sp->worldcopy; + } + sp->worldcopy = BKE_world_localize(world); + BLI_addtail(&sp->pr_main->worlds, sp->worldcopy); + return sp->worldcopy; } static ID *duplicate_ids(ID *id, Depsgraph *depsgraph) { - if (id == NULL) { - /* Non-ID preview render. */ - return NULL; - } - - ID *id_eval = id; - - if (depsgraph) { - id_eval = DEG_get_evaluated_id(depsgraph, id); - } - - switch (GS(id->name)) { - case ID_MA: - return (ID *)BKE_material_localize((Material *)id_eval); - case ID_TE: - return (ID *)BKE_texture_localize((Tex *)id_eval); - case ID_LA: - return (ID *)BKE_light_localize((Light *)id_eval); - case ID_WO: - return (ID *)BKE_world_localize((World *)id_eval); - case ID_IM: - case ID_BR: - case ID_SCR: - return NULL; - default: - BLI_assert(!"ID type preview not supported."); - return NULL; - } + if (id == NULL) { + /* Non-ID preview render. */ + return NULL; + } + + ID *id_eval = id; + + if (depsgraph) { + id_eval = DEG_get_evaluated_id(depsgraph, id); + } + + switch (GS(id->name)) { + case ID_MA: + return (ID *)BKE_material_localize((Material *)id_eval); + case ID_TE: + return (ID *)BKE_texture_localize((Tex *)id_eval); + case ID_LA: + return (ID *)BKE_light_localize((Light *)id_eval); + case ID_WO: + return (ID *)BKE_world_localize((World *)id_eval); + case ID_IM: + case ID_BR: + case ID_SCR: + return NULL; + default: + BLI_assert(!"ID type preview not supported."); + return NULL; + } } /* call this with a pointer to initialize preview scene */ /* call this with NULL to restore assigned ID pointers in preview scene */ -static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp) +static Scene *preview_prepare_scene( + Main *bmain, Scene *scene, ID *id, int id_type, ShaderPreview *sp) { - Scene *sce; - Main *pr_main = sp->pr_main; - - memcpy(pr_main->name, BKE_main_blendfile_path(bmain), sizeof(pr_main->name)); - - sce = preview_get_scene(pr_main); - if (sce) { - ViewLayer *view_layer = sce->view_layers.first; - - /* this flag tells render to not execute depsgraph or ipos etc */ - sce->r.scemode |= R_BUTS_PREVIEW; - /* set world always back, is used now */ - sce->world = pr_main->worlds.first; - /* now: exposure copy */ - if (scene->world) { - sce->world->exp = scene->world->exp; - sce->world->range = scene->world->range; - } - - sce->r.color_mgt_flag = scene->r.color_mgt_flag; - BKE_color_managed_display_settings_copy(&sce->display_settings, &scene->display_settings); - - BKE_color_managed_view_settings_free(&sce->view_settings); - BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings); - - /* prevent overhead for small renders and icons (32) */ - if (id && sp->sizex < 40) { - sce->r.tilex = sce->r.tiley = 64; - } - else { - sce->r.tilex = sce->r.xsch / 4; - sce->r.tiley = sce->r.ysch / 4; - } - - if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO) - sce->r.alphamode = R_ALPHAPREMUL; - else - sce->r.alphamode = R_ADDSKY; - - sce->r.cfra = scene->r.cfra; - - if (id_type == ID_TE) { - /* Texture is not actually rendered with engine, just set dummy value. */ - BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(sce->r.engine)); - } - else { - BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine)); - } - - if (id_type == ID_MA) { - Material *mat = NULL, *origmat = (Material *)id; - - if (origmat) { - /* work on a copy */ - BLI_assert(sp->id_copy != NULL); - mat = sp->matcopy = (Material *)sp->id_copy; - sp->id_copy = NULL; - BLI_addtail(&pr_main->materials, mat); - - /* Use current scene world for lighting. */ - if (mat->pr_flag == MA_PREVIEW_WORLD && sp->pr_method == PR_BUTS_RENDER) { - /* Use current scene world to light sphere. */ - sce->world = preview_get_localized_world(sp, scene->world); - } - else if (sce->world) { - /* Use a default world color. Using the current - * scene world can be slow if it has big textures. */ - sce->world->use_nodes = false; - sce->world->horr = 0.05f; - sce->world->horg = 0.05f; - sce->world->horb = 0.05f; - } - - set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method); - - if (sp->pr_method != PR_ICON_RENDER) { - if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) { - /* two previews, they get copied by wmJob */ - BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true); - /* WATCH: Accessing origmat is not safe! */ - BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, true); - } - } - } - else { - sce->r.mode &= ~(R_OSA); - } - - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (base->object->id.name[2] == 'p') { - /* copy over object color, in case material uses it */ - copy_v4_v4(base->object->color, sp->color); - - if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) { - /* don't use assign_material, it changed mat->id.us, which shows in the UI */ - Material ***matar = give_matarar(base->object); - int actcol = max_ii(base->object->actcol - 1, 0); - - if (matar && actcol < base->object->totcol) - (*matar)[actcol] = mat; - } - else if (base->object->type == OB_LAMP) { - base->flag |= BASE_VISIBLE; - } - } - } - } - else if (id_type == ID_TE) { - Tex *tex = NULL, *origtex = (Tex *)id; - - if (origtex) { - BLI_assert(sp->id_copy != NULL); - tex = sp->texcopy = (Tex *)sp->id_copy; - sp->id_copy = NULL; - BLI_addtail(&pr_main->textures, tex); - } - - if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) { - /* two previews, they get copied by wmJob */ - BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, true); - /* WATCH: Accessing origtex is not safe! */ - BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, true); - } - } - else if (id_type == ID_LA) { - Light *la = NULL, *origla = (Light *)id; - - /* work on a copy */ - if (origla) { - BLI_assert(sp->id_copy != NULL); - la = sp->lampcopy = (Light *)sp->id_copy; - sp->id_copy = NULL; - BLI_addtail(&pr_main->lights, la); - } - - set_preview_visibility(sce, view_layer, MA_LAMP, sp->pr_method); - - if (sce->world) { - /* Only use lighting from the light. */ - sce->world->use_nodes = false; - sce->world->horr = 0.0f; - sce->world->horg = 0.0f; - sce->world->horb = 0.0f; - } - - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (base->object->id.name[2] == 'p') { - if (base->object->type == OB_LAMP) - base->object->data = la; - } - } - - if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) { - /* two previews, they get copied by wmJob */ - BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, true); - /* WATCH: Accessing origla is not safe! */ - BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, true); - } - } - else if (id_type == ID_WO) { - World *wrld = NULL, *origwrld = (World *)id; - - if (origwrld) { - BLI_assert(sp->id_copy != NULL); - wrld = sp->worldcopy = (World *)sp->id_copy; - sp->id_copy = NULL; - BLI_addtail(&pr_main->worlds, wrld); - } - - set_preview_visibility(sce, view_layer, MA_SKY, sp->pr_method); - sce->world = wrld; - - if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) { - /* two previews, they get copied by wmJob */ - BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, true); - /* WATCH: Accessing origwrld is not safe! */ - BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, true); - } - } - - return sce; - } - - return NULL; + Scene *sce; + Main *pr_main = sp->pr_main; + + memcpy(pr_main->name, BKE_main_blendfile_path(bmain), sizeof(pr_main->name)); + + sce = preview_get_scene(pr_main); + if (sce) { + ViewLayer *view_layer = sce->view_layers.first; + + /* this flag tells render to not execute depsgraph or ipos etc */ + sce->r.scemode |= R_BUTS_PREVIEW; + /* set world always back, is used now */ + sce->world = pr_main->worlds.first; + /* now: exposure copy */ + if (scene->world) { + sce->world->exp = scene->world->exp; + sce->world->range = scene->world->range; + } + + sce->r.color_mgt_flag = scene->r.color_mgt_flag; + BKE_color_managed_display_settings_copy(&sce->display_settings, &scene->display_settings); + + BKE_color_managed_view_settings_free(&sce->view_settings); + BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings); + + /* prevent overhead for small renders and icons (32) */ + if (id && sp->sizex < 40) { + sce->r.tilex = sce->r.tiley = 64; + } + else { + sce->r.tilex = sce->r.xsch / 4; + sce->r.tiley = sce->r.ysch / 4; + } + + if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO) + sce->r.alphamode = R_ALPHAPREMUL; + else + sce->r.alphamode = R_ADDSKY; + + sce->r.cfra = scene->r.cfra; + + if (id_type == ID_TE) { + /* Texture is not actually rendered with engine, just set dummy value. */ + BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(sce->r.engine)); + } + else { + BLI_strncpy(sce->r.engine, scene->r.engine, sizeof(sce->r.engine)); + } + + if (id_type == ID_MA) { + Material *mat = NULL, *origmat = (Material *)id; + + if (origmat) { + /* work on a copy */ + BLI_assert(sp->id_copy != NULL); + mat = sp->matcopy = (Material *)sp->id_copy; + sp->id_copy = NULL; + BLI_addtail(&pr_main->materials, mat); + + /* Use current scene world for lighting. */ + if (mat->pr_flag == MA_PREVIEW_WORLD && sp->pr_method == PR_BUTS_RENDER) { + /* Use current scene world to light sphere. */ + sce->world = preview_get_localized_world(sp, scene->world); + } + else if (sce->world) { + /* Use a default world color. Using the current + * scene world can be slow if it has big textures. */ + sce->world->use_nodes = false; + sce->world->horr = 0.05f; + sce->world->horg = 0.05f; + sce->world->horb = 0.05f; + } + + set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method); + + if (sp->pr_method != PR_ICON_RENDER) { + if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) { + /* two previews, they get copied by wmJob */ + BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, true); + /* WATCH: Accessing origmat is not safe! */ + BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, true); + } + } + } + else { + sce->r.mode &= ~(R_OSA); + } + + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if (base->object->id.name[2] == 'p') { + /* copy over object color, in case material uses it */ + copy_v4_v4(base->object->color, sp->color); + + if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) { + /* don't use assign_material, it changed mat->id.us, which shows in the UI */ + Material ***matar = give_matarar(base->object); + int actcol = max_ii(base->object->actcol - 1, 0); + + if (matar && actcol < base->object->totcol) + (*matar)[actcol] = mat; + } + else if (base->object->type == OB_LAMP) { + base->flag |= BASE_VISIBLE; + } + } + } + } + else if (id_type == ID_TE) { + Tex *tex = NULL, *origtex = (Tex *)id; + + if (origtex) { + BLI_assert(sp->id_copy != NULL); + tex = sp->texcopy = (Tex *)sp->id_copy; + sp->id_copy = NULL; + BLI_addtail(&pr_main->textures, tex); + } + + if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) { + /* two previews, they get copied by wmJob */ + BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, true); + /* WATCH: Accessing origtex is not safe! */ + BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, true); + } + } + else if (id_type == ID_LA) { + Light *la = NULL, *origla = (Light *)id; + + /* work on a copy */ + if (origla) { + BLI_assert(sp->id_copy != NULL); + la = sp->lampcopy = (Light *)sp->id_copy; + sp->id_copy = NULL; + BLI_addtail(&pr_main->lights, la); + } + + set_preview_visibility(sce, view_layer, MA_LAMP, sp->pr_method); + + if (sce->world) { + /* Only use lighting from the light. */ + sce->world->use_nodes = false; + sce->world->horr = 0.0f; + sce->world->horg = 0.0f; + sce->world->horb = 0.0f; + } + + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if (base->object->id.name[2] == 'p') { + if (base->object->type == OB_LAMP) + base->object->data = la; + } + } + + if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) { + /* two previews, they get copied by wmJob */ + BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, true); + /* WATCH: Accessing origla is not safe! */ + BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, true); + } + } + else if (id_type == ID_WO) { + World *wrld = NULL, *origwrld = (World *)id; + + if (origwrld) { + BLI_assert(sp->id_copy != NULL); + wrld = sp->worldcopy = (World *)sp->id_copy; + sp->id_copy = NULL; + BLI_addtail(&pr_main->worlds, wrld); + } + + set_preview_visibility(sce, view_layer, MA_SKY, sp->pr_method); + sce->world = wrld; + + if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) { + /* two previews, they get copied by wmJob */ + BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, true); + /* WATCH: Accessing origwrld is not safe! */ + BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, true); + } + } + + return sce; + } + + return NULL; } /* new UI convention: draw is in pixel space already. */ /* uses UI_BTYPE_ROUNDBOX button in block to get the rect */ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, rcti *newrect) { - Render *re; - RenderView *rv; - RenderResult rres; - char name[32]; - int offx = 0; - int newx = BLI_rcti_size_x(rect); - int newy = BLI_rcti_size_y(rect); - bool ok = false; - - if (!split || first) sprintf(name, "Preview %p", (void *)sa); - else sprintf(name, "SecondPreview %p", (void *)sa); - - if (split) { - if (first) { - offx = 0; - newx = newx / 2; - } - else { - offx = newx / 2; - newx = newx - newx / 2; - } - } - - /* test if something rendered ok */ - re = RE_GetRender(name); - - if (re == NULL) - return false; - - RE_AcquireResultImageViews(re, &rres); - - if (!BLI_listbase_is_empty(&rres.views)) { - /* material preview only needs monoscopy (view 0) */ - rv = RE_RenderViewGetById(&rres, 0); - } - else { - /* possible the job clears the views but we're still drawing T45496 */ - rv = NULL; - } - - if (rv && rv->rectf) { - - if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) { - - newrect->xmax = max_ii(newrect->xmax, rect->xmin + rres.rectx + offx); - newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty); - - if (rres.rectx && rres.recty) { - unsigned char *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect"); - float fx = rect->xmin + offx; - float fy = rect->ymin; - - /* material preview only needs monoscopy (view 0) */ - if (re) - RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte, 0); - - IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); - immDrawPixelsTex(&state, fx, fy, rres.rectx, rres.recty, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect_byte, - 1.0f, 1.0f, NULL); - - MEM_freeN(rect_byte); - - ok = 1; - } - } - } - - RE_ReleaseResultImageViews(re, &rres); - - return ok; + Render *re; + RenderView *rv; + RenderResult rres; + char name[32]; + int offx = 0; + int newx = BLI_rcti_size_x(rect); + int newy = BLI_rcti_size_y(rect); + bool ok = false; + + if (!split || first) + sprintf(name, "Preview %p", (void *)sa); + else + sprintf(name, "SecondPreview %p", (void *)sa); + + if (split) { + if (first) { + offx = 0; + newx = newx / 2; + } + else { + offx = newx / 2; + newx = newx - newx / 2; + } + } + + /* test if something rendered ok */ + re = RE_GetRender(name); + + if (re == NULL) + return false; + + RE_AcquireResultImageViews(re, &rres); + + if (!BLI_listbase_is_empty(&rres.views)) { + /* material preview only needs monoscopy (view 0) */ + rv = RE_RenderViewGetById(&rres, 0); + } + else { + /* possible the job clears the views but we're still drawing T45496 */ + rv = NULL; + } + + if (rv && rv->rectf) { + + if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) { + + newrect->xmax = max_ii(newrect->xmax, rect->xmin + rres.rectx + offx); + newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty); + + if (rres.rectx && rres.recty) { + unsigned char *rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), + "ed_preview_draw_rect"); + float fx = rect->xmin + offx; + float fy = rect->ymin; + + /* material preview only needs monoscopy (view 0) */ + if (re) + RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte, 0); + + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, + fx, + fy, + rres.rectx, + rres.recty, + GL_RGBA, + GL_UNSIGNED_BYTE, + GL_NEAREST, + rect_byte, + 1.0f, + 1.0f, + NULL); + + MEM_freeN(rect_byte); + + ok = 1; + } + } + } + + RE_ReleaseResultImageViews(re, &rres); + + return ok; } void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, rcti *rect) { - if (idp) { - wmWindowManager *wm = CTX_wm_manager(C); - ScrArea *sa = CTX_wm_area(C); - ID *id = (ID *)idp; - ID *parent = (ID *)parentp; - MTex *slot = (MTex *)slotp; - SpaceProperties *sbuts = CTX_wm_space_properties(C); - ShaderPreview *sp = WM_jobs_customdata(wm, sa); - rcti newrect; - int ok; - int newx = BLI_rcti_size_x(rect); - int newy = BLI_rcti_size_y(rect); - - newrect.xmin = rect->xmin; - newrect.xmax = rect->xmin; - newrect.ymin = rect->ymin; - newrect.ymax = rect->ymin; - - if (parent) { - ok = ed_preview_draw_rect(sa, 1, 1, rect, &newrect); - ok &= ed_preview_draw_rect(sa, 1, 0, rect, &newrect); - } - else - ok = ed_preview_draw_rect(sa, 0, 0, rect, &newrect); - - if (ok) - *rect = newrect; - - /* start a new preview render job if signaled through sbuts->preview, - * if no render result was found and no preview render job is running, - * or if the job is running and the size of preview changed */ - if ((sbuts != NULL && sbuts->preview) || - (!ok && !WM_jobs_test(wm, sa, WM_JOB_TYPE_RENDER_PREVIEW)) || - (sp && (ABS(sp->sizex - newx) >= 2 || ABS(sp->sizey - newy) > 2))) - { - if (sbuts != NULL) { - sbuts->preview = 0; - } - ED_preview_shader_job(C, sa, id, parent, slot, newx, newy, PR_BUTS_RENDER); - } - } + if (idp) { + wmWindowManager *wm = CTX_wm_manager(C); + ScrArea *sa = CTX_wm_area(C); + ID *id = (ID *)idp; + ID *parent = (ID *)parentp; + MTex *slot = (MTex *)slotp; + SpaceProperties *sbuts = CTX_wm_space_properties(C); + ShaderPreview *sp = WM_jobs_customdata(wm, sa); + rcti newrect; + int ok; + int newx = BLI_rcti_size_x(rect); + int newy = BLI_rcti_size_y(rect); + + newrect.xmin = rect->xmin; + newrect.xmax = rect->xmin; + newrect.ymin = rect->ymin; + newrect.ymax = rect->ymin; + + if (parent) { + ok = ed_preview_draw_rect(sa, 1, 1, rect, &newrect); + ok &= ed_preview_draw_rect(sa, 1, 0, rect, &newrect); + } + else + ok = ed_preview_draw_rect(sa, 0, 0, rect, &newrect); + + if (ok) + *rect = newrect; + + /* start a new preview render job if signaled through sbuts->preview, + * if no render result was found and no preview render job is running, + * or if the job is running and the size of preview changed */ + if ((sbuts != NULL && sbuts->preview) || + (!ok && !WM_jobs_test(wm, sa, WM_JOB_TYPE_RENDER_PREVIEW)) || + (sp && (ABS(sp->sizex - newx) >= 2 || ABS(sp->sizey - newy) > 2))) { + if (sbuts != NULL) { + sbuts->preview = 0; + } + ED_preview_shader_job(C, sa, id, parent, slot, newx, newy, PR_BUTS_RENDER); + } + } } /* **************************** new shader preview system ****************** */ /* inside thread, called by renderer, sets job update value */ -static void shader_preview_update(void *spv, RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect)) +static void shader_preview_update(void *spv, + RenderResult *UNUSED(rr), + volatile struct rcti *UNUSED(rect)) { - ShaderPreview *sp = spv; + ShaderPreview *sp = spv; - *(sp->do_update) = true; + *(sp->do_update) = true; } /* called by renderer, checks job value */ static int shader_preview_break(void *spv) { - ShaderPreview *sp = spv; + ShaderPreview *sp = spv; - return *(sp->stop); + return *(sp->stop); } /* outside thread, called before redraw notifiers, it moves finished preview over */ static void shader_preview_updatejob(void *spv) { - ShaderPreview *sp = spv; - - if (sp->id) { - if (sp->pr_method == PR_NODE_RENDER) { - if (GS(sp->id->name) == ID_MA) { - Material *mat = (Material *)sp->id; - - if (sp->matcopy && mat->nodetree && sp->matcopy->nodetree) - ntreeLocalSync(sp->matcopy->nodetree, mat->nodetree); - } - else if (GS(sp->id->name) == ID_TE) { - Tex *tex = (Tex *)sp->id; - - if (sp->texcopy && tex->nodetree && sp->texcopy->nodetree) - ntreeLocalSync(sp->texcopy->nodetree, tex->nodetree); - } - else if (GS(sp->id->name) == ID_WO) { - World *wrld = (World *)sp->id; - - if (sp->worldcopy && wrld->nodetree && sp->worldcopy->nodetree) - ntreeLocalSync(sp->worldcopy->nodetree, wrld->nodetree); - } - else if (GS(sp->id->name) == ID_LA) { - Light *la = (Light *)sp->id; - - if (sp->lampcopy && la->nodetree && sp->lampcopy->nodetree) - ntreeLocalSync(sp->lampcopy->nodetree, la->nodetree); - } - } - } + ShaderPreview *sp = spv; + + if (sp->id) { + if (sp->pr_method == PR_NODE_RENDER) { + if (GS(sp->id->name) == ID_MA) { + Material *mat = (Material *)sp->id; + + if (sp->matcopy && mat->nodetree && sp->matcopy->nodetree) + ntreeLocalSync(sp->matcopy->nodetree, mat->nodetree); + } + else if (GS(sp->id->name) == ID_TE) { + Tex *tex = (Tex *)sp->id; + + if (sp->texcopy && tex->nodetree && sp->texcopy->nodetree) + ntreeLocalSync(sp->texcopy->nodetree, tex->nodetree); + } + else if (GS(sp->id->name) == ID_WO) { + World *wrld = (World *)sp->id; + + if (sp->worldcopy && wrld->nodetree && sp->worldcopy->nodetree) + ntreeLocalSync(sp->worldcopy->nodetree, wrld->nodetree); + } + else if (GS(sp->id->name) == ID_LA) { + Light *la = (Light *)sp->id; + + if (sp->lampcopy && la->nodetree && sp->lampcopy->nodetree) + ntreeLocalSync(sp->lampcopy->nodetree, la->nodetree); + } + } + } } /* Renders texture directly to render buffer. */ static void shader_preview_texture(ShaderPreview *sp, Tex *tex, Scene *sce, Render *re) { - /* Setup output buffer. */ - int width = sp->sizex; - int height = sp->sizey; - - /* This is needed otherwise no RenderResult is created. */ - sce->r.scemode &= ~R_BUTS_PREVIEW; - RE_InitState(re, NULL, &sce->r, &sce->view_layers, NULL, width, height, NULL); - RE_SetScene(re, sce); - - /* Create buffer in empty RenderView created in the init step. */ - RenderResult *rr = RE_AcquireResultWrite(re); - RenderView *rv = (RenderView *)rr->views.first; - rv->rectf = MEM_callocN(sizeof(float) * 4 * width * height, "texture render result"); - RE_ReleaseResult(re); - - /* Get texture image pool (if any) */ - struct ImagePool *img_pool = BKE_image_pool_new(); - BKE_texture_fetch_images_for_pool(tex, img_pool); - - /* Fill in image buffer. */ - float *rect_float = rv->rectf; - float tex_coord[3] = {0.0f, 0.0f, 0.0f}; - bool color_manage = true; - - for (int y = 0; y < height; y++) { - /* Tex coords between -1.0f and 1.0f. */ - tex_coord[1] = ((float)y / (float)height) * 2.0f - 1.0f; - - for (int x = 0; x < width; x++) { - tex_coord[0] = ((float)x / (float)height) * 2.0f - 1.0f; - - /* Evaluate texture at tex_coord .*/ - TexResult texres = {0}; - BKE_texture_get_value_ex(sce, tex, tex_coord, &texres, img_pool, color_manage); - - rect_float[0] = texres.tr; - rect_float[1] = texres.tg; - rect_float[2] = texres.tb; - rect_float[3] = 1.0f; - - rect_float += 4; - } - - /* Check if we should cancel texture preview. */ - if (shader_preview_break(sp)) { - break; - } - } - - BKE_image_pool_free(img_pool); + /* Setup output buffer. */ + int width = sp->sizex; + int height = sp->sizey; + + /* This is needed otherwise no RenderResult is created. */ + sce->r.scemode &= ~R_BUTS_PREVIEW; + RE_InitState(re, NULL, &sce->r, &sce->view_layers, NULL, width, height, NULL); + RE_SetScene(re, sce); + + /* Create buffer in empty RenderView created in the init step. */ + RenderResult *rr = RE_AcquireResultWrite(re); + RenderView *rv = (RenderView *)rr->views.first; + rv->rectf = MEM_callocN(sizeof(float) * 4 * width * height, "texture render result"); + RE_ReleaseResult(re); + + /* Get texture image pool (if any) */ + struct ImagePool *img_pool = BKE_image_pool_new(); + BKE_texture_fetch_images_for_pool(tex, img_pool); + + /* Fill in image buffer. */ + float *rect_float = rv->rectf; + float tex_coord[3] = {0.0f, 0.0f, 0.0f}; + bool color_manage = true; + + for (int y = 0; y < height; y++) { + /* Tex coords between -1.0f and 1.0f. */ + tex_coord[1] = ((float)y / (float)height) * 2.0f - 1.0f; + + for (int x = 0; x < width; x++) { + tex_coord[0] = ((float)x / (float)height) * 2.0f - 1.0f; + + /* Evaluate texture at tex_coord .*/ + TexResult texres = {0}; + BKE_texture_get_value_ex(sce, tex, tex_coord, &texres, img_pool, color_manage); + + rect_float[0] = texres.tr; + rect_float[1] = texres.tg; + rect_float[2] = texres.tb; + rect_float[3] = 1.0f; + + rect_float += 4; + } + + /* Check if we should cancel texture preview. */ + if (shader_preview_break(sp)) { + break; + } + } + + BKE_image_pool_free(img_pool); } static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int first) { - Render *re; - Scene *sce; - float oldlens; - short idtype = GS(id->name); - char name[32]; - int sizex; - Main *pr_main = sp->pr_main; - ID *id_eval = id; - - if (sp->depsgraph) { - id_eval = DEG_get_evaluated_id(sp->depsgraph, id); - } - - /* in case of split preview, use border render */ - if (split) { - if (first) sizex = sp->sizex / 2; - else sizex = sp->sizex - sp->sizex / 2; - } - else { - sizex = sp->sizex; - } - - /* we have to set preview variables first */ - sce = preview_get_scene(pr_main); - if (sce) { - sce->r.xsch = sizex; - sce->r.ysch = sp->sizey; - sce->r.size = 100; - } - - - /* get the stuff from the builtin preview dbase */ - sce = preview_prepare_scene(sp->bmain, sp->scene, id_eval, idtype, sp); - if (sce == NULL) return; - - if (!split || first) sprintf(name, "Preview %p", sp->owner); - else sprintf(name, "SecondPreview %p", sp->owner); - re = RE_GetRender(name); - - /* full refreshed render from first tile */ - if (re == NULL) - re = RE_NewRender(name); - - /* sce->r gets copied in RE_InitState! */ - sce->r.scemode &= ~(R_MATNODE_PREVIEW | R_TEXNODE_PREVIEW); - sce->r.scemode &= ~R_NO_IMAGE_LOAD; - - if (sp->pr_method == PR_ICON_RENDER) { - sce->r.scemode |= R_NO_IMAGE_LOAD; - sce->r.mode |= R_OSA; - } - else if (sp->pr_method == PR_NODE_RENDER) { - if (idtype == ID_MA) sce->r.scemode |= R_MATNODE_PREVIEW; - else if (idtype == ID_TE) sce->r.scemode |= R_TEXNODE_PREVIEW; - sce->r.mode &= ~R_OSA; - } - else { /* PR_BUTS_RENDER */ - sce->r.mode |= R_OSA; - } - - - /* callbacs are cleared on GetRender() */ - if (ELEM(sp->pr_method, PR_BUTS_RENDER, PR_NODE_RENDER)) { - RE_display_update_cb(re, sp, shader_preview_update); - } - /* set this for all previews, default is react to G.is_break still */ - RE_test_break_cb(re, sp, shader_preview_break); - - /* lens adjust */ - oldlens = ((Camera *)sce->camera->data)->lens; - if (sizex > sp->sizey) - ((Camera *)sce->camera->data)->lens *= (float)sp->sizey / (float)sizex; - - /* entire cycle for render engine */ - if (idtype == ID_TE) { - shader_preview_texture(sp, (Tex *)id, sce, re); - } - else { - /* Render preview scene */ - RE_PreviewRender(re, pr_main, sce); - } - - ((Camera *)sce->camera->data)->lens = oldlens; - - /* handle results */ - if (sp->pr_method == PR_ICON_RENDER) { - // char *rct= (char *)(sp->pr_rect + 32*16 + 16); - - if (sp->pr_rect) - RE_ResultGet32(re, sp->pr_rect); - } - - /* unassign the pointers, reset vars */ - preview_prepare_scene(sp->bmain, sp->scene, NULL, GS(id->name), sp); - - /* XXX bad exception, end-exec is not being called in render, because it uses local main */ -// if (idtype == ID_TE) { -// Tex *tex= (Tex *)id; -// if (tex->use_nodes && tex->nodetree) -// ntreeEndExecTree(tex->nodetree); -// } - + Render *re; + Scene *sce; + float oldlens; + short idtype = GS(id->name); + char name[32]; + int sizex; + Main *pr_main = sp->pr_main; + ID *id_eval = id; + + if (sp->depsgraph) { + id_eval = DEG_get_evaluated_id(sp->depsgraph, id); + } + + /* in case of split preview, use border render */ + if (split) { + if (first) + sizex = sp->sizex / 2; + else + sizex = sp->sizex - sp->sizex / 2; + } + else { + sizex = sp->sizex; + } + + /* we have to set preview variables first */ + sce = preview_get_scene(pr_main); + if (sce) { + sce->r.xsch = sizex; + sce->r.ysch = sp->sizey; + sce->r.size = 100; + } + + /* get the stuff from the builtin preview dbase */ + sce = preview_prepare_scene(sp->bmain, sp->scene, id_eval, idtype, sp); + if (sce == NULL) + return; + + if (!split || first) + sprintf(name, "Preview %p", sp->owner); + else + sprintf(name, "SecondPreview %p", sp->owner); + re = RE_GetRender(name); + + /* full refreshed render from first tile */ + if (re == NULL) + re = RE_NewRender(name); + + /* sce->r gets copied in RE_InitState! */ + sce->r.scemode &= ~(R_MATNODE_PREVIEW | R_TEXNODE_PREVIEW); + sce->r.scemode &= ~R_NO_IMAGE_LOAD; + + if (sp->pr_method == PR_ICON_RENDER) { + sce->r.scemode |= R_NO_IMAGE_LOAD; + sce->r.mode |= R_OSA; + } + else if (sp->pr_method == PR_NODE_RENDER) { + if (idtype == ID_MA) + sce->r.scemode |= R_MATNODE_PREVIEW; + else if (idtype == ID_TE) + sce->r.scemode |= R_TEXNODE_PREVIEW; + sce->r.mode &= ~R_OSA; + } + else { /* PR_BUTS_RENDER */ + sce->r.mode |= R_OSA; + } + + /* callbacs are cleared on GetRender() */ + if (ELEM(sp->pr_method, PR_BUTS_RENDER, PR_NODE_RENDER)) { + RE_display_update_cb(re, sp, shader_preview_update); + } + /* set this for all previews, default is react to G.is_break still */ + RE_test_break_cb(re, sp, shader_preview_break); + + /* lens adjust */ + oldlens = ((Camera *)sce->camera->data)->lens; + if (sizex > sp->sizey) + ((Camera *)sce->camera->data)->lens *= (float)sp->sizey / (float)sizex; + + /* entire cycle for render engine */ + if (idtype == ID_TE) { + shader_preview_texture(sp, (Tex *)id, sce, re); + } + else { + /* Render preview scene */ + RE_PreviewRender(re, pr_main, sce); + } + + ((Camera *)sce->camera->data)->lens = oldlens; + + /* handle results */ + if (sp->pr_method == PR_ICON_RENDER) { + // char *rct= (char *)(sp->pr_rect + 32*16 + 16); + + if (sp->pr_rect) + RE_ResultGet32(re, sp->pr_rect); + } + + /* unassign the pointers, reset vars */ + preview_prepare_scene(sp->bmain, sp->scene, NULL, GS(id->name), sp); + + /* XXX bad exception, end-exec is not being called in render, because it uses local main */ + // if (idtype == ID_TE) { + // Tex *tex= (Tex *)id; + // if (tex->use_nodes && tex->nodetree) + // ntreeEndExecTree(tex->nodetree); + // } } /* runs inside thread for material and icons */ static void shader_preview_startjob(void *customdata, short *stop, short *do_update) { - ShaderPreview *sp = customdata; + ShaderPreview *sp = customdata; - sp->stop = stop; - sp->do_update = do_update; + sp->stop = stop; + sp->do_update = do_update; - if (sp->parent) { - shader_preview_render(sp, sp->id, 1, 1); - shader_preview_render(sp, sp->parent, 1, 0); - } - else - shader_preview_render(sp, sp->id, 0, 0); + if (sp->parent) { + shader_preview_render(sp, sp->id, 1, 1); + shader_preview_render(sp, sp->parent, 1, 0); + } + else + shader_preview_render(sp, sp->id, 0, 0); - *do_update = true; + *do_update = true; } static void shader_preview_free(void *customdata) { - ShaderPreview *sp = customdata; - Main *pr_main = sp->pr_main; - - if (sp->matcopy) { - sp->id_copy = (ID *)sp->matcopy; - BLI_remlink(&pr_main->materials, sp->matcopy); - } - if (sp->texcopy) { - sp->id_copy = (ID *)sp->texcopy; - BLI_remlink(&pr_main->textures, sp->texcopy); - } - if (sp->worldcopy) { - sp->id_copy = (ID *)sp->worldcopy; - BLI_remlink(&pr_main->worlds, sp->worldcopy); - } - if (sp->lampcopy) { - sp->id_copy = (ID *)sp->lampcopy; - BLI_remlink(&pr_main->lights, sp->lampcopy); - } - if (sp->id_copy) { - /* node previews */ - shader_preview_updatejob(sp); - } - if (sp->id_copy && sp->own_id_copy) { - struct IDProperty *properties; - /* get rid of copied ID */ - properties = IDP_GetProperties(sp->id_copy, false); - if (properties) { - IDP_FreeProperty_ex(properties, false); - MEM_freeN(properties); - } - switch (GS(sp->id_copy->name)) { - case ID_MA: - BKE_material_free((Material *)sp->id_copy); - break; - case ID_TE: - BKE_texture_free((Tex *)sp->id_copy); - break; - case ID_LA: - BKE_light_free((Light *)sp->id_copy); - break; - case ID_WO: - BKE_world_free((World *)sp->id_copy); - break; - default: - BLI_assert(!"ID type preview not supported."); - break; - } - MEM_freeN(sp->id_copy); - } - - MEM_freeN(sp); + ShaderPreview *sp = customdata; + Main *pr_main = sp->pr_main; + + if (sp->matcopy) { + sp->id_copy = (ID *)sp->matcopy; + BLI_remlink(&pr_main->materials, sp->matcopy); + } + if (sp->texcopy) { + sp->id_copy = (ID *)sp->texcopy; + BLI_remlink(&pr_main->textures, sp->texcopy); + } + if (sp->worldcopy) { + sp->id_copy = (ID *)sp->worldcopy; + BLI_remlink(&pr_main->worlds, sp->worldcopy); + } + if (sp->lampcopy) { + sp->id_copy = (ID *)sp->lampcopy; + BLI_remlink(&pr_main->lights, sp->lampcopy); + } + if (sp->id_copy) { + /* node previews */ + shader_preview_updatejob(sp); + } + if (sp->id_copy && sp->own_id_copy) { + struct IDProperty *properties; + /* get rid of copied ID */ + properties = IDP_GetProperties(sp->id_copy, false); + if (properties) { + IDP_FreeProperty_ex(properties, false); + MEM_freeN(properties); + } + switch (GS(sp->id_copy->name)) { + case ID_MA: + BKE_material_free((Material *)sp->id_copy); + break; + case ID_TE: + BKE_texture_free((Tex *)sp->id_copy); + break; + case ID_LA: + BKE_light_free((Light *)sp->id_copy); + break; + case ID_WO: + BKE_world_free((World *)sp->id_copy); + break; + default: + BLI_assert(!"ID type preview not supported."); + break; + } + MEM_freeN(sp->id_copy); + } + + MEM_freeN(sp); } /* ************************* icon preview ********************** */ static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned int *rect) { - struct ImBuf *ima; - unsigned int *drect, *srect; - float scaledx, scaledy; - short ex, ey, dx, dy; + struct ImBuf *ima; + unsigned int *drect, *srect; + float scaledx, scaledy; + short ex, ey, dx, dy; - /* paranoia test */ - if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) - return; + /* paranoia test */ + if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) + return; - /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */ - ima = IMB_dupImBuf(ibuf); + /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */ + ima = IMB_dupImBuf(ibuf); - if (!ima) - return; + if (!ima) + return; - if (ima->x > ima->y) { - scaledx = (float)w; - scaledy = ( (float)ima->y / (float)ima->x) * (float)w; - } - else { - scaledx = ( (float)ima->x / (float)ima->y) * (float)h; - scaledy = (float)h; - } + if (ima->x > ima->y) { + scaledx = (float)w; + scaledy = ((float)ima->y / (float)ima->x) * (float)w; + } + else { + scaledx = ((float)ima->x / (float)ima->y) * (float)h; + scaledy = (float)h; + } - ex = (short)scaledx; - ey = (short)scaledy; + ex = (short)scaledx; + ey = (short)scaledy; - dx = (w - ex) / 2; - dy = (h - ey) / 2; + dx = (w - ex) / 2; + dy = (h - ey) / 2; - IMB_scalefastImBuf(ima, ex, ey); + IMB_scalefastImBuf(ima, ex, ey); - /* if needed, convert to 32 bits */ - if (ima->rect == NULL) - IMB_rect_from_float(ima); + /* if needed, convert to 32 bits */ + if (ima->rect == NULL) + IMB_rect_from_float(ima); - srect = ima->rect; - drect = rect; + srect = ima->rect; + drect = rect; - drect += dy * w + dx; - for (; ey > 0; ey--) { - memcpy(drect, srect, ex * sizeof(int)); - drect += w; - srect += ima->x; - } + drect += dy * w + dx; + for (; ey > 0; ey--) { + memcpy(drect, srect, ex * sizeof(int)); + drect += w; + srect += ima->x; + } - IMB_freeImBuf(ima); + IMB_freeImBuf(ima); } static void set_alpha(char *cp, int sizex, int sizey, char alpha) { - int a, size = sizex * sizey; + int a, size = sizex * sizey; - for (a = 0; a < size; a++, cp += 4) - cp[3] = alpha; + for (a = 0; a < size; a++, cp += 4) + cp[3] = alpha; } static void icon_preview_startjob(void *customdata, short *stop, short *do_update) { - ShaderPreview *sp = customdata; - - if (sp->pr_method == PR_ICON_DEFERRED) { - PreviewImage *prv = sp->owner; - ImBuf *thumb; - char *deferred_data = PRV_DEFERRED_DATA(prv); - int source = deferred_data[0]; - char *path = &deferred_data[1]; - -// printf("generating deferred %d×%d preview for %s\n", sp->sizex, sp->sizey, path); - - thumb = IMB_thumb_manage(path, THB_LARGE, source); - - if (thumb) { - /* PreviewImage assumes premultiplied alhpa... */ - IMB_premultiply_alpha(thumb); - - icon_copy_rect(thumb, sp->sizex, sp->sizey, sp->pr_rect); - IMB_freeImBuf(thumb); - } - } - else { - ID *id = sp->id; - short idtype = GS(id->name); - - if (idtype == ID_IM) { - Image *ima = (Image *)id; - ImBuf *ibuf = NULL; - ImageUser iuser = {NULL}; - - /* ima->ok is zero when Image cannot load */ - if (ima == NULL || ima->ok == 0) - return; - - /* setup dummy image user */ - iuser.ok = iuser.framenr = 1; - iuser.scene = sp->scene; - - /* elubie: this needs to be changed: here image is always loaded if not - * already there. Very expensive for large images. Need to find a way to - * only get existing ibuf */ - ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); - if (ibuf == NULL || ibuf->rect == NULL) { - BKE_image_release_ibuf(ima, ibuf, NULL); - return; - } - - icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect); - - *do_update = true; - - BKE_image_release_ibuf(ima, ibuf, NULL); - } - else if (idtype == ID_BR) { - Brush *br = (Brush *)id; - - br->icon_imbuf = get_brush_icon(br); - - memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int)); - - if (!(br->icon_imbuf) || !(br->icon_imbuf->rect)) - return; - - icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect); - - *do_update = true; - } - else if (idtype == ID_SCR) { - bScreen *screen = (bScreen *)id; - - ED_screen_preview_render(screen, sp->sizex, sp->sizey, sp->pr_rect); - *do_update = true; - } - else { - /* re-use shader job */ - shader_preview_startjob(customdata, stop, do_update); - - /* world is rendered with alpha=0, so it wasn't displayed - * this could be render option for sky to, for later */ - if (idtype == ID_WO) { - set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255); - } - } - } + ShaderPreview *sp = customdata; + + if (sp->pr_method == PR_ICON_DEFERRED) { + PreviewImage *prv = sp->owner; + ImBuf *thumb; + char *deferred_data = PRV_DEFERRED_DATA(prv); + int source = deferred_data[0]; + char *path = &deferred_data[1]; + + // printf("generating deferred %d×%d preview for %s\n", sp->sizex, sp->sizey, path); + + thumb = IMB_thumb_manage(path, THB_LARGE, source); + + if (thumb) { + /* PreviewImage assumes premultiplied alhpa... */ + IMB_premultiply_alpha(thumb); + + icon_copy_rect(thumb, sp->sizex, sp->sizey, sp->pr_rect); + IMB_freeImBuf(thumb); + } + } + else { + ID *id = sp->id; + short idtype = GS(id->name); + + if (idtype == ID_IM) { + Image *ima = (Image *)id; + ImBuf *ibuf = NULL; + ImageUser iuser = {NULL}; + + /* ima->ok is zero when Image cannot load */ + if (ima == NULL || ima->ok == 0) + return; + + /* setup dummy image user */ + iuser.ok = iuser.framenr = 1; + iuser.scene = sp->scene; + + /* elubie: this needs to be changed: here image is always loaded if not + * already there. Very expensive for large images. Need to find a way to + * only get existing ibuf */ + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); + if (ibuf == NULL || ibuf->rect == NULL) { + BKE_image_release_ibuf(ima, ibuf, NULL); + return; + } + + icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect); + + *do_update = true; + + BKE_image_release_ibuf(ima, ibuf, NULL); + } + else if (idtype == ID_BR) { + Brush *br = (Brush *)id; + + br->icon_imbuf = get_brush_icon(br); + + memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int)); + + if (!(br->icon_imbuf) || !(br->icon_imbuf->rect)) + return; + + icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect); + + *do_update = true; + } + else if (idtype == ID_SCR) { + bScreen *screen = (bScreen *)id; + + ED_screen_preview_render(screen, sp->sizex, sp->sizey, sp->pr_rect); + *do_update = true; + } + else { + /* re-use shader job */ + shader_preview_startjob(customdata, stop, do_update); + + /* world is rendered with alpha=0, so it wasn't displayed + * this could be render option for sky to, for later */ + if (idtype == ID_WO) { + set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255); + } + } + } } /* use same function for icon & shader, so the job manager * does not run two of them at the same time. */ -static void common_preview_startjob(void *customdata, short *stop, short *do_update, float *UNUSED(progress)) +static void common_preview_startjob(void *customdata, + short *stop, + short *do_update, + float *UNUSED(progress)) { - ShaderPreview *sp = customdata; + ShaderPreview *sp = customdata; - if (ELEM(sp->pr_method, PR_ICON_RENDER, PR_ICON_DEFERRED)) - icon_preview_startjob(customdata, stop, do_update); - else - shader_preview_startjob(customdata, stop, do_update); + if (ELEM(sp->pr_method, PR_ICON_RENDER, PR_ICON_DEFERRED)) + icon_preview_startjob(customdata, stop, do_update); + else + shader_preview_startjob(customdata, stop, do_update); } /* exported functions */ static void icon_preview_add_size(IconPreview *ip, unsigned int *rect, int sizex, int sizey) { - IconPreviewSize *cur_size = ip->sizes.first, *new_size; + IconPreviewSize *cur_size = ip->sizes.first, *new_size; - while (cur_size) { - if (cur_size->sizex == sizex && cur_size->sizey == sizey) { - /* requested size is already in list, no need to add it again */ - return; - } + while (cur_size) { + if (cur_size->sizex == sizex && cur_size->sizey == sizey) { + /* requested size is already in list, no need to add it again */ + return; + } - cur_size = cur_size->next; - } + cur_size = cur_size->next; + } - new_size = MEM_callocN(sizeof(IconPreviewSize), "IconPreviewSize"); - new_size->sizex = sizex; - new_size->sizey = sizey; - new_size->rect = rect; + new_size = MEM_callocN(sizeof(IconPreviewSize), "IconPreviewSize"); + new_size->sizex = sizex; + new_size->sizey = sizey; + new_size->rect = rect; - BLI_addtail(&ip->sizes, new_size); + BLI_addtail(&ip->sizes, new_size); } -static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short *do_update, float *progress) +static void icon_preview_startjob_all_sizes(void *customdata, + short *stop, + short *do_update, + float *progress) { - IconPreview *ip = (IconPreview *)customdata; - IconPreviewSize *cur_size; - - for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) { - PreviewImage *prv = ip->owner; - - if (prv->tag & PRV_TAG_DEFFERED_DELETE) { - /* Non-thread-protected reading is not an issue here. */ - continue; - } - - if (!check_engine_supports_preview(ip->scene)) { - continue; - } - - ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview"); - const bool is_render = !(prv->tag & PRV_TAG_DEFFERED); - - /* construct shader preview from image size and previewcustomdata */ - sp->scene = ip->scene; - sp->depsgraph = ip->depsgraph; - sp->owner = ip->owner; - sp->sizex = cur_size->sizex; - sp->sizey = cur_size->sizey; - sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED; - sp->pr_rect = cur_size->rect; - sp->id = ip->id; - sp->id_copy = ip->id_copy; - sp->bmain = ip->bmain; - sp->own_id_copy = false; - Material *ma = NULL; - - if (is_render) { - BLI_assert(ip->id); - - /* grease pencil use its own preview file */ - if (GS(ip->id->name) == ID_MA) { - ma = (Material *)ip->id; - } - - if ((ma == NULL) || (ma->gp_style == NULL)) { - sp->pr_main = G_pr_main; - } - else { - sp->pr_main = G_pr_main_grease_pencil; - } - } - - common_preview_startjob(sp, stop, do_update, progress); - shader_preview_free(sp); - } + IconPreview *ip = (IconPreview *)customdata; + IconPreviewSize *cur_size; + + for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) { + PreviewImage *prv = ip->owner; + + if (prv->tag & PRV_TAG_DEFFERED_DELETE) { + /* Non-thread-protected reading is not an issue here. */ + continue; + } + + if (!check_engine_supports_preview(ip->scene)) { + continue; + } + + ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview"); + const bool is_render = !(prv->tag & PRV_TAG_DEFFERED); + + /* construct shader preview from image size and previewcustomdata */ + sp->scene = ip->scene; + sp->depsgraph = ip->depsgraph; + sp->owner = ip->owner; + sp->sizex = cur_size->sizex; + sp->sizey = cur_size->sizey; + sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED; + sp->pr_rect = cur_size->rect; + sp->id = ip->id; + sp->id_copy = ip->id_copy; + sp->bmain = ip->bmain; + sp->own_id_copy = false; + Material *ma = NULL; + + if (is_render) { + BLI_assert(ip->id); + + /* grease pencil use its own preview file */ + if (GS(ip->id->name) == ID_MA) { + ma = (Material *)ip->id; + } + + if ((ma == NULL) || (ma->gp_style == NULL)) { + sp->pr_main = G_pr_main; + } + else { + sp->pr_main = G_pr_main_grease_pencil; + } + } + + common_preview_startjob(sp, stop, do_update, progress); + shader_preview_free(sp); + } } static void icon_preview_endjob(void *customdata) { - IconPreview *ip = customdata; + IconPreview *ip = customdata; - if (ip->id) { + if (ip->id) { - if (GS(ip->id->name) == ID_BR) - WM_main_add_notifier(NC_BRUSH | NA_EDITED, ip->id); + if (GS(ip->id->name) == ID_BR) + WM_main_add_notifier(NC_BRUSH | NA_EDITED, ip->id); #if 0 - if (GS(ip->id->name) == ID_MA) { - Material *ma = (Material *)ip->id; - PreviewImage *prv_img = ma->preview; - int i; - - /* signal to gpu texture */ - for (i = 0; i < NUM_ICON_SIZES; ++i) { - if (prv_img->gputexture[i]) { - GPU_texture_free(prv_img->gputexture[i]); - prv_img->gputexture[i] = NULL; - WM_main_add_notifier(NC_MATERIAL|ND_SHADING_DRAW, ip->id); - } - } - } + if (GS(ip->id->name) == ID_MA) { + Material *ma = (Material *)ip->id; + PreviewImage *prv_img = ma->preview; + int i; + + /* signal to gpu texture */ + for (i = 0; i < NUM_ICON_SIZES; ++i) { + if (prv_img->gputexture[i]) { + GPU_texture_free(prv_img->gputexture[i]); + prv_img->gputexture[i] = NULL; + WM_main_add_notifier(NC_MATERIAL|ND_SHADING_DRAW, ip->id); + } + } + } #endif - } - - if (ip->owner) { - PreviewImage *prv_img = ip->owner; - prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING; - if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) { - BLI_assert(prv_img->tag & PRV_TAG_DEFFERED); - BKE_previewimg_cached_release_pointer(prv_img); - } - } + } + + if (ip->owner) { + PreviewImage *prv_img = ip->owner; + prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING; + if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) { + BLI_assert(prv_img->tag & PRV_TAG_DEFFERED); + BKE_previewimg_cached_release_pointer(prv_img); + } + } } static void icon_preview_free(void *customdata) { - IconPreview *ip = (IconPreview *)customdata; - - if (ip->id_copy) { - /* Feels a bit hacky just to reuse shader_preview_free() */ - ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview"); - sp->id_copy = ip->id_copy; - sp->own_id_copy = true; - shader_preview_free(sp); - ip->id_copy = NULL; - } - - BLI_freelistN(&ip->sizes); - MEM_freeN(ip); + IconPreview *ip = (IconPreview *)customdata; + + if (ip->id_copy) { + /* Feels a bit hacky just to reuse shader_preview_free() */ + ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview"); + sp->id_copy = ip->id_copy; + sp->own_id_copy = true; + shader_preview_free(sp); + ip->id_copy = NULL; + } + + BLI_freelistN(&ip->sizes); + MEM_freeN(ip); } -void ED_preview_icon_render(Main *bmain, Scene *scene, ID *id, unsigned int *rect, int sizex, int sizey) +void ED_preview_icon_render( + Main *bmain, Scene *scene, ID *id, unsigned int *rect, int sizex, int sizey) { - IconPreview ip = {NULL}; - short stop = false, update = false; - float progress = 0.0f; + IconPreview ip = {NULL}; + short stop = false, update = false; + float progress = 0.0f; - ED_preview_ensure_dbase(); + ED_preview_ensure_dbase(); - ip.bmain = bmain; - ip.scene = scene; - ip.owner = BKE_previewimg_id_ensure(id); - ip.id = id; - ip.id_copy = duplicate_ids(id, NULL); + ip.bmain = bmain; + ip.scene = scene; + ip.owner = BKE_previewimg_id_ensure(id); + ip.id = id; + ip.id_copy = duplicate_ids(id, NULL); - icon_preview_add_size(&ip, rect, sizex, sizey); + icon_preview_add_size(&ip, rect, sizex, sizey); - icon_preview_startjob_all_sizes(&ip, &stop, &update, &progress); + icon_preview_startjob_all_sizes(&ip, &stop, &update, &progress); - icon_preview_endjob(&ip); + icon_preview_endjob(&ip); - BLI_freelistN(&ip.sizes); + BLI_freelistN(&ip.sizes); } -void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *rect, int sizex, int sizey) +void ED_preview_icon_job( + const bContext *C, void *owner, ID *id, unsigned int *rect, int sizex, int sizey) { - wmJob *wm_job; - IconPreview *ip, *old_ip; - - ED_preview_ensure_dbase(); - - /* suspended start means it starts after 1 timer step, see WM_jobs_timer below */ - wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Icon Preview", - WM_JOB_EXCL_RENDER | WM_JOB_SUSPEND, WM_JOB_TYPE_RENDER_PREVIEW); - - ip = MEM_callocN(sizeof(IconPreview), "icon preview"); - - /* render all resolutions from suspended job too */ - old_ip = WM_jobs_customdata_get(wm_job); - if (old_ip) - BLI_movelisttolist(&ip->sizes, &old_ip->sizes); - - /* customdata for preview thread */ - ip->bmain = CTX_data_main(C); - ip->scene = CTX_data_scene(C); - ip->depsgraph = CTX_data_depsgraph(C); - ip->owner = owner; - ip->id = id; - ip->id_copy = duplicate_ids(id, ip->depsgraph); - - icon_preview_add_size(ip, rect, sizex, sizey); - - /* Special threading hack: warn main code that this preview is being rendered and cannot be freed... */ - { - PreviewImage *prv_img = owner; - if (prv_img->tag & PRV_TAG_DEFFERED) { - prv_img->tag |= PRV_TAG_DEFFERED_RENDERING; - } - } - - /* setup job */ - WM_jobs_customdata_set(wm_job, ip, icon_preview_free); - WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW); - WM_jobs_callbacks(wm_job, icon_preview_startjob_all_sizes, NULL, NULL, icon_preview_endjob); - - WM_jobs_start(CTX_wm_manager(C), wm_job); + wmJob *wm_job; + IconPreview *ip, *old_ip; + + ED_preview_ensure_dbase(); + + /* suspended start means it starts after 1 timer step, see WM_jobs_timer below */ + wm_job = WM_jobs_get(CTX_wm_manager(C), + CTX_wm_window(C), + owner, + "Icon Preview", + WM_JOB_EXCL_RENDER | WM_JOB_SUSPEND, + WM_JOB_TYPE_RENDER_PREVIEW); + + ip = MEM_callocN(sizeof(IconPreview), "icon preview"); + + /* render all resolutions from suspended job too */ + old_ip = WM_jobs_customdata_get(wm_job); + if (old_ip) + BLI_movelisttolist(&ip->sizes, &old_ip->sizes); + + /* customdata for preview thread */ + ip->bmain = CTX_data_main(C); + ip->scene = CTX_data_scene(C); + ip->depsgraph = CTX_data_depsgraph(C); + ip->owner = owner; + ip->id = id; + ip->id_copy = duplicate_ids(id, ip->depsgraph); + + icon_preview_add_size(ip, rect, sizex, sizey); + + /* Special threading hack: warn main code that this preview is being rendered and cannot be freed... */ + { + PreviewImage *prv_img = owner; + if (prv_img->tag & PRV_TAG_DEFFERED) { + prv_img->tag |= PRV_TAG_DEFFERED_RENDERING; + } + } + + /* setup job */ + WM_jobs_customdata_set(wm_job, ip, icon_preview_free); + WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW); + WM_jobs_callbacks(wm_job, icon_preview_startjob_all_sizes, NULL, NULL, icon_preview_endjob); + + WM_jobs_start(CTX_wm_manager(C), wm_job); } -void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, MTex *slot, int sizex, int sizey, int method) +void ED_preview_shader_job(const bContext *C, + void *owner, + ID *id, + ID *parent, + MTex *slot, + int sizex, + int sizey, + int method) { - Object *ob = CTX_data_active_object(C); - wmJob *wm_job; - ShaderPreview *sp; - Scene *scene = CTX_data_scene(C); - short id_type = GS(id->name); - - /* Use workspace render only for buttons Window, since the other previews are related to the datablock. */ - - if (!check_engine_supports_preview(scene)) { - return; - } - - /* Only texture node preview is supported with Cycles. */ - if (method == PR_NODE_RENDER && id_type != ID_TE) { - return; - } - - ED_preview_ensure_dbase(); - - wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), owner, "Shader Preview", - WM_JOB_EXCL_RENDER, WM_JOB_TYPE_RENDER_PREVIEW); - sp = MEM_callocN(sizeof(ShaderPreview), "shader preview"); - - /* customdata for preview thread */ - sp->scene = scene; - sp->depsgraph = CTX_data_depsgraph(C); - sp->owner = owner; - sp->sizex = sizex; - sp->sizey = sizey; - sp->pr_method = method; - sp->id = id; - sp->id_copy = duplicate_ids(id, sp->depsgraph); - sp->own_id_copy = true; - sp->parent = parent; - sp->slot = slot; - sp->bmain = CTX_data_main(C); - Material *ma = NULL; - - /* hardcoded preview .blend for Eevee + Cycles, this should be solved - * once with custom preview .blend path for external engines */ - - /* grease pencil use its own preview file */ - if (GS(id->name) == ID_MA) { - ma = (Material *)id; - } - - if ((ma == NULL) || (ma->gp_style == NULL)) { - sp->pr_main = G_pr_main; - } - else { - sp->pr_main = G_pr_main_grease_pencil; - } - - if (ob && ob->totcol) { - copy_v4_v4(sp->color, ob->color); - } - else { - ARRAY_SET_ITEMS(sp->color, 0.0f, 0.0f, 0.0f, 1.0f); - } - - /* setup job */ - WM_jobs_customdata_set(wm_job, sp, shader_preview_free); - WM_jobs_timer(wm_job, 0.1, NC_MATERIAL, NC_MATERIAL); - WM_jobs_callbacks(wm_job, common_preview_startjob, NULL, shader_preview_updatejob, NULL); - - WM_jobs_start(CTX_wm_manager(C), wm_job); + Object *ob = CTX_data_active_object(C); + wmJob *wm_job; + ShaderPreview *sp; + Scene *scene = CTX_data_scene(C); + short id_type = GS(id->name); + + /* Use workspace render only for buttons Window, since the other previews are related to the datablock. */ + + if (!check_engine_supports_preview(scene)) { + return; + } + + /* Only texture node preview is supported with Cycles. */ + if (method == PR_NODE_RENDER && id_type != ID_TE) { + return; + } + + ED_preview_ensure_dbase(); + + wm_job = WM_jobs_get(CTX_wm_manager(C), + CTX_wm_window(C), + owner, + "Shader Preview", + WM_JOB_EXCL_RENDER, + WM_JOB_TYPE_RENDER_PREVIEW); + sp = MEM_callocN(sizeof(ShaderPreview), "shader preview"); + + /* customdata for preview thread */ + sp->scene = scene; + sp->depsgraph = CTX_data_depsgraph(C); + sp->owner = owner; + sp->sizex = sizex; + sp->sizey = sizey; + sp->pr_method = method; + sp->id = id; + sp->id_copy = duplicate_ids(id, sp->depsgraph); + sp->own_id_copy = true; + sp->parent = parent; + sp->slot = slot; + sp->bmain = CTX_data_main(C); + Material *ma = NULL; + + /* hardcoded preview .blend for Eevee + Cycles, this should be solved + * once with custom preview .blend path for external engines */ + + /* grease pencil use its own preview file */ + if (GS(id->name) == ID_MA) { + ma = (Material *)id; + } + + if ((ma == NULL) || (ma->gp_style == NULL)) { + sp->pr_main = G_pr_main; + } + else { + sp->pr_main = G_pr_main_grease_pencil; + } + + if (ob && ob->totcol) { + copy_v4_v4(sp->color, ob->color); + } + else { + ARRAY_SET_ITEMS(sp->color, 0.0f, 0.0f, 0.0f, 1.0f); + } + + /* setup job */ + WM_jobs_customdata_set(wm_job, sp, shader_preview_free); + WM_jobs_timer(wm_job, 0.1, NC_MATERIAL, NC_MATERIAL); + WM_jobs_callbacks(wm_job, common_preview_startjob, NULL, shader_preview_updatejob, NULL); + + WM_jobs_start(CTX_wm_manager(C), wm_job); } void ED_preview_kill_jobs(wmWindowManager *wm, Main *UNUSED(bmain)) { - if (wm) - WM_jobs_kill(wm, NULL, common_preview_startjob); + if (wm) + WM_jobs_kill(wm, NULL, common_preview_startjob); } diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 9bf9b15cd07..70157abf2ef 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -100,1890 +100,1937 @@ */ static Object **object_array_for_shading(bContext *C, uint *r_objects_len) { - ScrArea *sa = CTX_wm_area(C); - SpaceProperties *sbuts = NULL; - View3D *v3d = NULL; - if (sa->spacetype == SPACE_PROPERTIES) { - sbuts = sa->spacedata.first; - } - else if (sa->spacetype == SPACE_VIEW3D) { - v3d = sa->spacedata.first; - } - - Object **objects; - if (sbuts && sbuts->pinid && GS(sbuts->pinid->name) == ID_OB) { - objects = MEM_mallocN(sizeof(*objects), __func__); - objects[0] = (Object *)sbuts->pinid; - *r_objects_len = 1; - } - else { - ViewLayer *view_layer = CTX_data_view_layer(C); - objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, r_objects_len); - } - return objects; + ScrArea *sa = CTX_wm_area(C); + SpaceProperties *sbuts = NULL; + View3D *v3d = NULL; + if (sa->spacetype == SPACE_PROPERTIES) { + sbuts = sa->spacedata.first; + } + else if (sa->spacetype == SPACE_VIEW3D) { + v3d = sa->spacedata.first; + } + + Object **objects; + if (sbuts && sbuts->pinid && GS(sbuts->pinid->name) == ID_OB) { + objects = MEM_mallocN(sizeof(*objects), __func__); + objects[0] = (Object *)sbuts->pinid; + *r_objects_len = 1; + } + else { + ViewLayer *view_layer = CTX_data_view_layer(C); + objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, v3d, r_objects_len); + } + return objects; } /********************** material slot operators *********************/ static int material_slot_add_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - Object *ob = ED_object_context(C); + Main *bmain = CTX_data_main(C); + Object *ob = ED_object_context(C); - if (!ob) - return OPERATOR_CANCELLED; + if (!ob) + return OPERATOR_CANCELLED; - BKE_object_material_slot_add(bmain, ob); + BKE_object_material_slot_add(bmain, ob); - if (ob->mode & OB_MODE_TEXTURE_PAINT) { - Scene *scene = CTX_data_scene(C); - BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); - WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); - } + if (ob->mode & OB_MODE_TEXTURE_PAINT) { + Scene *scene = CTX_data_scene(C); + BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); + } - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob); - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob); + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void OBJECT_OT_material_slot_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Material Slot"; - ot->idname = "OBJECT_OT_material_slot_add"; - ot->description = "Add a new material slot"; + /* identifiers */ + ot->name = "Add Material Slot"; + ot->idname = "OBJECT_OT_material_slot_add"; + ot->description = "Add a new material slot"; - /* api callbacks */ - ot->exec = material_slot_add_exec; - ot->poll = ED_operator_object_active_editable; + /* api callbacks */ + ot->exec = material_slot_add_exec; + ot->poll = ED_operator_object_active_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static int material_slot_remove_exec(bContext *C, wmOperator *op) { - Object *ob = ED_object_context(C); + Object *ob = ED_object_context(C); - if (!ob) - return OPERATOR_CANCELLED; + if (!ob) + return OPERATOR_CANCELLED; - /* Removing material slots in edit mode screws things up, see bug #21822.*/ - if (ob == CTX_data_edit_object(C)) { - BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode"); - return OPERATOR_CANCELLED; - } + /* Removing material slots in edit mode screws things up, see bug #21822.*/ + if (ob == CTX_data_edit_object(C)) { + BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode"); + return OPERATOR_CANCELLED; + } - BKE_object_material_slot_remove(CTX_data_main(C), ob); + BKE_object_material_slot_remove(CTX_data_main(C), ob); - if (ob->mode & OB_MODE_TEXTURE_PAINT) { - Scene *scene = CTX_data_scene(C); - BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); - WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); - } + if (ob->mode & OB_MODE_TEXTURE_PAINT) { + Scene *scene = CTX_data_scene(C); + BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); + } - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob); - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob); + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void OBJECT_OT_material_slot_remove(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove Material Slot"; - ot->idname = "OBJECT_OT_material_slot_remove"; - ot->description = "Remove the selected material slot"; + /* identifiers */ + ot->name = "Remove Material Slot"; + ot->idname = "OBJECT_OT_material_slot_remove"; + ot->description = "Remove the selected material slot"; - /* api callbacks */ - ot->exec = material_slot_remove_exec; - ot->poll = ED_operator_object_active_editable; + /* api callbacks */ + ot->exec = material_slot_remove_exec; + ot->poll = ED_operator_object_active_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op)) { - View3D *v3d = CTX_wm_view3d(C); - bool changed_multi = false; - - uint objects_len = 0; - Object **objects = object_array_for_shading(C, &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *ob = objects[ob_index]; - if (ob->actcol <= 0) { - continue; - } - bool changed = false; - if (ob->type == OB_MESH) { - BMEditMesh *em = BKE_editmesh_from_object(ob); - BMFace *efa; - BMIter iter; - - if (em) { - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { - changed = true; - efa->mat_nr = ob->actcol - 1; - } - } - } - } - else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { - Nurb *nu; - ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data); - - if (nurbs) { - for (nu = nurbs->first; nu; nu = nu->next) { - if (ED_curve_nurb_select_check(v3d, nu)) { - changed = true; - nu->mat_nr = ob->actcol - 1; - } - } - } - } - else if (ob->type == OB_FONT) { - EditFont *ef = ((Curve *)ob->data)->editfont; - int i, selstart, selend; - - if (ef && BKE_vfont_select_get(ob, &selstart, &selend)) { - for (i = selstart; i <= selend; i++) { - changed = true; - ef->textbufinfo[i].mat_nr = ob->actcol; - } - } - } - - if (changed) { - changed_multi = true; - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); - } - } - MEM_freeN(objects); - - return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + View3D *v3d = CTX_wm_view3d(C); + bool changed_multi = false; + + uint objects_len = 0; + Object **objects = object_array_for_shading(C, &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; + if (ob->actcol <= 0) { + continue; + } + bool changed = false; + if (ob->type == OB_MESH) { + BMEditMesh *em = BKE_editmesh_from_object(ob); + BMFace *efa; + BMIter iter; + + if (em) { + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + changed = true; + efa->mat_nr = ob->actcol - 1; + } + } + } + } + else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + Nurb *nu; + ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data); + + if (nurbs) { + for (nu = nurbs->first; nu; nu = nu->next) { + if (ED_curve_nurb_select_check(v3d, nu)) { + changed = true; + nu->mat_nr = ob->actcol - 1; + } + } + } + } + else if (ob->type == OB_FONT) { + EditFont *ef = ((Curve *)ob->data)->editfont; + int i, selstart, selend; + + if (ef && BKE_vfont_select_get(ob, &selstart, &selend)) { + for (i = selstart; i <= selend; i++) { + changed = true; + ef->textbufinfo[i].mat_nr = ob->actcol; + } + } + } + + if (changed) { + changed_multi = true; + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + } + } + MEM_freeN(objects); + + return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } void OBJECT_OT_material_slot_assign(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Assign Material Slot"; - ot->idname = "OBJECT_OT_material_slot_assign"; - ot->description = "Assign active material slot to selection"; + /* identifiers */ + ot->name = "Assign Material Slot"; + ot->idname = "OBJECT_OT_material_slot_assign"; + ot->description = "Assign active material slot to selection"; - /* api callbacks */ - ot->exec = material_slot_assign_exec; - ot->poll = ED_operator_object_active_editable; + /* api callbacks */ + ot->exec = material_slot_assign_exec; + ot->poll = ED_operator_object_active_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static int material_slot_de_select(bContext *C, bool select) { - bool changed_multi = false; - Object *obact = CTX_data_active_object(C); - const Material *mat_active = obact ? give_current_material(obact, obact->actcol) : NULL; - - uint objects_len = 0; - Object **objects = object_array_for_shading(C, &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *ob = objects[ob_index]; - short mat_nr_active = -1; - - if (ob->totcol == 0) { - continue; - } - if (obact && (mat_active == give_current_material(ob, obact->actcol))) { - /* Avoid searching since there may be multiple slots with the same material. - * For the active object or duplicates: match the material slot index first. */ - mat_nr_active = obact->actcol - 1; - } - else { - /* Find the first matching material. - * Note: there may be multiple but thats not a common use case. */ - for (short i = 0; i < ob->totcol; i++) { - const Material *mat = give_current_material(ob, i + 1); - if (mat_active == mat) { - mat_nr_active = i; - break; - } - } - if (mat_nr_active == -1) { - continue; - } - } - - - bool changed = false; - - if (ob->type == OB_MESH) { - BMEditMesh *em = BKE_editmesh_from_object(ob); - - if (em) { - changed = EDBM_deselect_by_material(em, mat_nr_active, select); - } - } - else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { - ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data); - Nurb *nu; - BPoint *bp; - BezTriple *bezt; - int a; - - if (nurbs) { - for (nu = nurbs->first; nu; nu = nu->next) { - if (nu->mat_nr == mat_nr_active) { - if (nu->bezt) { - a = nu->pntsu; - bezt = nu->bezt; - while (a--) { - if (bezt->hide == 0) { - changed = true; - if (select) { - bezt->f1 |= SELECT; - bezt->f2 |= SELECT; - bezt->f3 |= SELECT; - } - else { - bezt->f1 &= ~SELECT; - bezt->f2 &= ~SELECT; - bezt->f3 &= ~SELECT; - } - } - bezt++; - } - } - else if (nu->bp) { - a = nu->pntsu * nu->pntsv; - bp = nu->bp; - while (a--) { - if (bp->hide == 0) { - changed = true; - if (select) bp->f1 |= SELECT; - else bp->f1 &= ~SELECT; - } - bp++; - } - } - } - } - } - } - - if (changed) { - changed_multi = true; - DEG_id_tag_update(ob->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); - } - } - - MEM_freeN(objects); - - return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + bool changed_multi = false; + Object *obact = CTX_data_active_object(C); + const Material *mat_active = obact ? give_current_material(obact, obact->actcol) : NULL; + + uint objects_len = 0; + Object **objects = object_array_for_shading(C, &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; + short mat_nr_active = -1; + + if (ob->totcol == 0) { + continue; + } + if (obact && (mat_active == give_current_material(ob, obact->actcol))) { + /* Avoid searching since there may be multiple slots with the same material. + * For the active object or duplicates: match the material slot index first. */ + mat_nr_active = obact->actcol - 1; + } + else { + /* Find the first matching material. + * Note: there may be multiple but thats not a common use case. */ + for (short i = 0; i < ob->totcol; i++) { + const Material *mat = give_current_material(ob, i + 1); + if (mat_active == mat) { + mat_nr_active = i; + break; + } + } + if (mat_nr_active == -1) { + continue; + } + } + + bool changed = false; + + if (ob->type == OB_MESH) { + BMEditMesh *em = BKE_editmesh_from_object(ob); + + if (em) { + changed = EDBM_deselect_by_material(em, mat_nr_active, select); + } + } + else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + ListBase *nurbs = BKE_curve_editNurbs_get((Curve *)ob->data); + Nurb *nu; + BPoint *bp; + BezTriple *bezt; + int a; + + if (nurbs) { + for (nu = nurbs->first; nu; nu = nu->next) { + if (nu->mat_nr == mat_nr_active) { + if (nu->bezt) { + a = nu->pntsu; + bezt = nu->bezt; + while (a--) { + if (bezt->hide == 0) { + changed = true; + if (select) { + bezt->f1 |= SELECT; + bezt->f2 |= SELECT; + bezt->f3 |= SELECT; + } + else { + bezt->f1 &= ~SELECT; + bezt->f2 &= ~SELECT; + bezt->f3 &= ~SELECT; + } + } + bezt++; + } + } + else if (nu->bp) { + a = nu->pntsu * nu->pntsv; + bp = nu->bp; + while (a--) { + if (bp->hide == 0) { + changed = true; + if (select) + bp->f1 |= SELECT; + else + bp->f1 &= ~SELECT; + } + bp++; + } + } + } + } + } + } + + if (changed) { + changed_multi = true; + DEG_id_tag_update(ob->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); + } + } + + MEM_freeN(objects); + + return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } static int material_slot_select_exec(bContext *C, wmOperator *UNUSED(op)) { - return material_slot_de_select(C, true); + return material_slot_de_select(C, true); } void OBJECT_OT_material_slot_select(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select Material Slot"; - ot->idname = "OBJECT_OT_material_slot_select"; - ot->description = "Select by active material slot"; + /* identifiers */ + ot->name = "Select Material Slot"; + ot->idname = "OBJECT_OT_material_slot_select"; + ot->description = "Select by active material slot"; - /* api callbacks */ - ot->exec = material_slot_select_exec; + /* api callbacks */ + ot->exec = material_slot_select_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static int material_slot_deselect_exec(bContext *C, wmOperator *UNUSED(op)) { - return material_slot_de_select(C, false); + return material_slot_de_select(C, false); } void OBJECT_OT_material_slot_deselect(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Deselect Material Slot"; - ot->idname = "OBJECT_OT_material_slot_deselect"; - ot->description = "Deselect by active material slot"; + /* identifiers */ + ot->name = "Deselect Material Slot"; + ot->idname = "OBJECT_OT_material_slot_deselect"; + ot->description = "Deselect by active material slot"; - /* api callbacks */ - ot->exec = material_slot_deselect_exec; + /* api callbacks */ + ot->exec = material_slot_deselect_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } - static int material_slot_copy_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - Object *ob = ED_object_context(C); - Material ***matar; + Main *bmain = CTX_data_main(C); + Object *ob = ED_object_context(C); + Material ***matar; - if (!ob || !(matar = give_matarar(ob))) - return OPERATOR_CANCELLED; + if (!ob || !(matar = give_matarar(ob))) + return OPERATOR_CANCELLED; - CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) - { - if (ob != ob_iter && give_matarar(ob_iter)) { - if (ob->data != ob_iter->data) - assign_matarar(bmain, ob_iter, matar, ob->totcol); + CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) { + if (ob != ob_iter && give_matarar(ob_iter)) { + if (ob->data != ob_iter->data) + assign_matarar(bmain, ob_iter, matar, ob->totcol); - if (ob_iter->totcol == ob->totcol) { - ob_iter->actcol = ob->actcol; - DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter); - } - } - } - CTX_DATA_END; + if (ob_iter->totcol == ob->totcol) { + ob_iter->actcol = ob->actcol; + DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter); + } + } + } + CTX_DATA_END; - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } - void OBJECT_OT_material_slot_copy(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Copy Material to Selected"; - ot->idname = "OBJECT_OT_material_slot_copy"; - ot->description = "Copy material to selected objects"; + /* identifiers */ + ot->name = "Copy Material to Selected"; + ot->idname = "OBJECT_OT_material_slot_copy"; + ot->description = "Copy material to selected objects"; - /* api callbacks */ - ot->exec = material_slot_copy_exec; + /* api callbacks */ + ot->exec = material_slot_copy_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static int material_slot_move_exec(bContext *C, wmOperator *op) { - Object *ob = ED_object_context(C); + Object *ob = ED_object_context(C); - unsigned int *slot_remap; - int index_pair[2]; + unsigned int *slot_remap; + int index_pair[2]; - int dir = RNA_enum_get(op->ptr, "direction"); + int dir = RNA_enum_get(op->ptr, "direction"); - if (!ob || ob->totcol < 2) { - return OPERATOR_CANCELLED; - } + if (!ob || ob->totcol < 2) { + return OPERATOR_CANCELLED; + } - /* up */ - if (dir == 1 && ob->actcol > 1) { - index_pair[0] = ob->actcol - 2; - index_pair[1] = ob->actcol - 1; - ob->actcol--; - } - /* down */ - else if (dir == -1 && ob->actcol < ob->totcol) { - index_pair[0] = ob->actcol - 1; - index_pair[1] = ob->actcol - 0; - ob->actcol++; - } - else { - return OPERATOR_CANCELLED; - } + /* up */ + if (dir == 1 && ob->actcol > 1) { + index_pair[0] = ob->actcol - 2; + index_pair[1] = ob->actcol - 1; + ob->actcol--; + } + /* down */ + else if (dir == -1 && ob->actcol < ob->totcol) { + index_pair[0] = ob->actcol - 1; + index_pair[1] = ob->actcol - 0; + ob->actcol++; + } + else { + return OPERATOR_CANCELLED; + } - slot_remap = MEM_mallocN(sizeof(unsigned int) * ob->totcol, __func__); + slot_remap = MEM_mallocN(sizeof(unsigned int) * ob->totcol, __func__); - range_vn_u(slot_remap, ob->totcol, 0); + range_vn_u(slot_remap, ob->totcol, 0); - slot_remap[index_pair[0]] = index_pair[1]; - slot_remap[index_pair[1]] = index_pair[0]; + slot_remap[index_pair[0]] = index_pair[1]; + slot_remap[index_pair[1]] = index_pair[0]; - BKE_material_remap_object(ob, slot_remap); + BKE_material_remap_object(ob, slot_remap); - MEM_freeN(slot_remap); + MEM_freeN(slot_remap); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void OBJECT_OT_material_slot_move(wmOperatorType *ot) { - static const EnumPropertyItem material_slot_move[] = { - {1, "UP", 0, "Up", ""}, - {-1, "DOWN", 0, "Down", ""}, - {0, NULL, 0, NULL, NULL}, - }; + static const EnumPropertyItem material_slot_move[] = { + {1, "UP", 0, "Up", ""}, + {-1, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL}, + }; - /* identifiers */ - ot->name = "Move Material"; - ot->idname = "OBJECT_OT_material_slot_move"; - ot->description = "Move the active material up/down in the list"; + /* identifiers */ + ot->name = "Move Material"; + ot->idname = "OBJECT_OT_material_slot_move"; + ot->description = "Move the active material up/down in the list"; - /* api callbacks */ - ot->exec = material_slot_move_exec; + /* api callbacks */ + ot->exec = material_slot_move_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_enum(ot->srna, "direction", material_slot_move, 0, "Direction", - "Direction to move the active material towards"); + RNA_def_enum(ot->srna, + "direction", + material_slot_move, + 0, + "Direction", + "Direction to move the active material towards"); } /********************** new material operator *********************/ static int new_material_exec(bContext *C, wmOperator *UNUSED(op)) { - Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data; - Main *bmain = CTX_data_main(C); - PointerRNA ptr, idptr; - PropertyRNA *prop; - - /* hook into UI */ - UI_context_active_but_prop_get_templateID(C, &ptr, &prop); - - Object *ob = (prop && RNA_struct_is_a(ptr.type, &RNA_Object)) ? ptr.data : NULL; - - /* add or copy material */ - if (ma) { - Material *new_ma = NULL; - BKE_id_copy_ex(bmain, &ma->id, (ID **)&new_ma, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS); - ma = new_ma; - } - else { - const char *name = DATA_("Material"); - if (!(ob != NULL && ob->type == OB_GPENCIL)) { - ma = BKE_material_add(bmain, name); - } - else { - ma = BKE_material_add_gpencil(bmain, name); - } - ED_node_shader_default(C, &ma->id); - ma->use_nodes = true; - } - - - if (prop) { - if (ob != NULL) { - /* Add slot follows user-preferences for creating new slots, - * RNA pointer assignment doesn't, see: T60014. */ - if (give_current_material_p(ob, ob->actcol) == NULL) { - BKE_object_material_slot_add(bmain, ob); - } - } - - /* when creating new ID blocks, use is already 1, but RNA - * pointer use also increases user, so this compensates it */ - id_us_min(&ma->id); - - RNA_id_pointer_create(&ma->id, &idptr); - RNA_property_pointer_set(&ptr, prop, idptr); - RNA_property_update(C, &ptr, prop); - } - - WM_event_add_notifier(C, NC_MATERIAL | NA_ADDED, ma); - - return OPERATOR_FINISHED; + Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data; + Main *bmain = CTX_data_main(C); + PointerRNA ptr, idptr; + PropertyRNA *prop; + + /* hook into UI */ + UI_context_active_but_prop_get_templateID(C, &ptr, &prop); + + Object *ob = (prop && RNA_struct_is_a(ptr.type, &RNA_Object)) ? ptr.data : NULL; + + /* add or copy material */ + if (ma) { + Material *new_ma = NULL; + BKE_id_copy_ex(bmain, &ma->id, (ID **)&new_ma, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS); + ma = new_ma; + } + else { + const char *name = DATA_("Material"); + if (!(ob != NULL && ob->type == OB_GPENCIL)) { + ma = BKE_material_add(bmain, name); + } + else { + ma = BKE_material_add_gpencil(bmain, name); + } + ED_node_shader_default(C, &ma->id); + ma->use_nodes = true; + } + + if (prop) { + if (ob != NULL) { + /* Add slot follows user-preferences for creating new slots, + * RNA pointer assignment doesn't, see: T60014. */ + if (give_current_material_p(ob, ob->actcol) == NULL) { + BKE_object_material_slot_add(bmain, ob); + } + } + + /* when creating new ID blocks, use is already 1, but RNA + * pointer use also increases user, so this compensates it */ + id_us_min(&ma->id); + + RNA_id_pointer_create(&ma->id, &idptr); + RNA_property_pointer_set(&ptr, prop, idptr); + RNA_property_update(C, &ptr, prop); + } + + WM_event_add_notifier(C, NC_MATERIAL | NA_ADDED, ma); + + return OPERATOR_FINISHED; } void MATERIAL_OT_new(wmOperatorType *ot) { - /* identifiers */ - ot->name = "New Material"; - ot->idname = "MATERIAL_OT_new"; - ot->description = "Add a new material"; + /* identifiers */ + ot->name = "New Material"; + ot->idname = "MATERIAL_OT_new"; + ot->description = "Add a new material"; - /* api callbacks */ - ot->exec = new_material_exec; + /* api callbacks */ + ot->exec = new_material_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } /********************** new texture operator *********************/ static int new_texture_exec(bContext *C, wmOperator *UNUSED(op)) { - Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data; - Main *bmain = CTX_data_main(C); - PointerRNA ptr, idptr; - PropertyRNA *prop; + Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data; + Main *bmain = CTX_data_main(C); + PointerRNA ptr, idptr; + PropertyRNA *prop; - /* add or copy texture */ - if (tex) { - tex = BKE_texture_copy(bmain, tex); - } - else { - tex = BKE_texture_add(bmain, DATA_("Texture")); - } + /* add or copy texture */ + if (tex) { + tex = BKE_texture_copy(bmain, tex); + } + else { + tex = BKE_texture_add(bmain, DATA_("Texture")); + } - /* hook into UI */ - UI_context_active_but_prop_get_templateID(C, &ptr, &prop); + /* hook into UI */ + UI_context_active_but_prop_get_templateID(C, &ptr, &prop); - if (prop) { - /* when creating new ID blocks, use is already 1, but RNA - * pointer use also increases user, so this compensates it */ - id_us_min(&tex->id); + if (prop) { + /* when creating new ID blocks, use is already 1, but RNA + * pointer use also increases user, so this compensates it */ + id_us_min(&tex->id); - RNA_id_pointer_create(&tex->id, &idptr); - RNA_property_pointer_set(&ptr, prop, idptr); - RNA_property_update(C, &ptr, prop); - } + RNA_id_pointer_create(&tex->id, &idptr); + RNA_property_pointer_set(&ptr, prop, idptr); + RNA_property_update(C, &ptr, prop); + } - WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, tex); + WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, tex); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXTURE_OT_new(wmOperatorType *ot) { - /* identifiers */ - ot->name = "New Texture"; - ot->idname = "TEXTURE_OT_new"; - ot->description = "Add a new texture"; + /* identifiers */ + ot->name = "New Texture"; + ot->idname = "TEXTURE_OT_new"; + ot->description = "Add a new texture"; - /* api callbacks */ - ot->exec = new_texture_exec; + /* api callbacks */ + ot->exec = new_texture_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } /********************** new world operator *********************/ static int new_world_exec(bContext *C, wmOperator *UNUSED(op)) { - World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data; - Main *bmain = CTX_data_main(C); - PointerRNA ptr, idptr; - PropertyRNA *prop; + World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data; + Main *bmain = CTX_data_main(C); + PointerRNA ptr, idptr; + PropertyRNA *prop; - /* add or copy world */ - if (wo) { - wo = BKE_world_copy(bmain, wo); - } - else { - wo = BKE_world_add(bmain, DATA_("World")); - ED_node_shader_default(C, &wo->id); - wo->use_nodes = true; - } + /* add or copy world */ + if (wo) { + wo = BKE_world_copy(bmain, wo); + } + else { + wo = BKE_world_add(bmain, DATA_("World")); + ED_node_shader_default(C, &wo->id); + wo->use_nodes = true; + } - /* hook into UI */ - UI_context_active_but_prop_get_templateID(C, &ptr, &prop); + /* hook into UI */ + UI_context_active_but_prop_get_templateID(C, &ptr, &prop); - if (prop) { - /* when creating new ID blocks, use is already 1, but RNA - * pointer use also increases user, so this compensates it */ - id_us_min(&wo->id); + if (prop) { + /* when creating new ID blocks, use is already 1, but RNA + * pointer use also increases user, so this compensates it */ + id_us_min(&wo->id); - RNA_id_pointer_create(&wo->id, &idptr); - RNA_property_pointer_set(&ptr, prop, idptr); - RNA_property_update(C, &ptr, prop); - } + RNA_id_pointer_create(&wo->id, &idptr); + RNA_property_pointer_set(&ptr, prop, idptr); + RNA_property_update(C, &ptr, prop); + } - WM_event_add_notifier(C, NC_WORLD | NA_ADDED, wo); + WM_event_add_notifier(C, NC_WORLD | NA_ADDED, wo); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void WORLD_OT_new(wmOperatorType *ot) { - /* identifiers */ - ot->name = "New World"; - ot->idname = "WORLD_OT_new"; - ot->description = "Create a new world Data-Block"; + /* identifiers */ + ot->name = "New World"; + ot->idname = "WORLD_OT_new"; + ot->description = "Create a new world Data-Block"; - /* api callbacks */ - ot->exec = new_world_exec; + /* api callbacks */ + ot->exec = new_world_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } /********************** render layer operators *********************/ static int view_layer_add_exec(bContext *C, wmOperator *UNUSED(op)) { - wmWindow *win = CTX_wm_window(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = BKE_view_layer_add(scene, NULL); + wmWindow *win = CTX_wm_window(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = BKE_view_layer_add(scene, NULL); - if (win) { - WM_window_set_active_view_layer(win, view_layer); - } + if (win) { + WM_window_set_active_view_layer(win, view_layer); + } - DEG_id_tag_update(&scene->id, 0); - DEG_relations_tag_update(CTX_data_main(C)); - WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + DEG_id_tag_update(&scene->id, 0); + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_view_layer_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add View Layer"; - ot->idname = "SCENE_OT_view_layer_add"; - ot->description = "Add a view layer"; + /* identifiers */ + ot->name = "Add View Layer"; + ot->idname = "SCENE_OT_view_layer_add"; + ot->description = "Add a view layer"; - /* api callbacks */ - ot->exec = view_layer_add_exec; + /* api callbacks */ + ot->exec = view_layer_add_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static bool view_layer_remove_poll(bContext *C) { - Scene *scene = CTX_data_scene(C); - return (scene->view_layers.first != scene->view_layers.last); + Scene *scene = CTX_data_scene(C); + return (scene->view_layers.first != scene->view_layers.last); } static int view_layer_remove_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); - if (!ED_scene_view_layer_delete(bmain, scene, view_layer, NULL)) { - return OPERATOR_CANCELLED; - } + if (!ED_scene_view_layer_delete(bmain, scene, view_layer, NULL)) { + return OPERATOR_CANCELLED; + } - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_view_layer_remove(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove View Layer"; - ot->idname = "SCENE_OT_view_layer_remove"; - ot->description = "Remove the selected view layer"; + /* identifiers */ + ot->name = "Remove View Layer"; + ot->idname = "SCENE_OT_view_layer_remove"; + ot->description = "Remove the selected view layer"; - /* api callbacks */ - ot->exec = view_layer_remove_exec; - ot->poll = view_layer_remove_poll; + /* api callbacks */ + ot->exec = view_layer_remove_exec; + ot->poll = view_layer_remove_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } /********************** light cache operators *********************/ enum { - LIGHTCACHE_SUBSET_ALL = 0, - LIGHTCACHE_SUBSET_DIRTY, - LIGHTCACHE_SUBSET_CUBE, + LIGHTCACHE_SUBSET_ALL = 0, + LIGHTCACHE_SUBSET_DIRTY, + LIGHTCACHE_SUBSET_CUBE, }; static void light_cache_bake_tag_cache(Scene *scene, wmOperator *op) { - if (scene->eevee.light_cache != NULL) { - int subset = RNA_enum_get(op->ptr, "subset"); - switch (subset) { - case LIGHTCACHE_SUBSET_ALL: - scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_GRID | LIGHTCACHE_UPDATE_CUBE; - break; - case LIGHTCACHE_SUBSET_CUBE: - scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_CUBE; - break; - case LIGHTCACHE_SUBSET_DIRTY: - /* Leave tag untouched. */ - break; - } - } + if (scene->eevee.light_cache != NULL) { + int subset = RNA_enum_get(op->ptr, "subset"); + switch (subset) { + case LIGHTCACHE_SUBSET_ALL: + scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_GRID | LIGHTCACHE_UPDATE_CUBE; + break; + case LIGHTCACHE_SUBSET_CUBE: + scene->eevee.light_cache->flag |= LIGHTCACHE_UPDATE_CUBE; + break; + case LIGHTCACHE_SUBSET_DIRTY: + /* Leave tag untouched. */ + break; + } + } } /* catch esc */ static int light_cache_bake_modal(bContext *C, wmOperator *op, const wmEvent *event) { - Scene *scene = (Scene *) op->customdata; + Scene *scene = (Scene *)op->customdata; - /* no running blender, remove handler and pass through */ - if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) { - return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; - } + /* no running blender, remove handler and pass through */ + if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER)) { + return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; + } - /* running render */ - switch (event->type) { - case ESCKEY: - return OPERATOR_RUNNING_MODAL; - } - return OPERATOR_PASS_THROUGH; + /* running render */ + switch (event->type) { + case ESCKEY: + return OPERATOR_RUNNING_MODAL; + } + return OPERATOR_PASS_THROUGH; } static void light_cache_bake_cancel(bContext *C, wmOperator *op) { - wmWindowManager *wm = CTX_wm_manager(C); - Scene *scene = (Scene *) op->customdata; + wmWindowManager *wm = CTX_wm_manager(C); + Scene *scene = (Scene *)op->customdata; - /* kill on cancel, because job is using op->reports */ - WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER); + /* kill on cancel, because job is using op->reports */ + WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER); } /* executes blocking render */ static int light_cache_bake_exec(bContext *C, wmOperator *op) { - ViewLayer *view_layer = CTX_data_view_layer(C); - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); - G.is_break = false; + G.is_break = false; - /* TODO abort if selected engine is not eevee. */ - void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, false, scene->r.cfra); + /* TODO abort if selected engine is not eevee. */ + void *rj = EEVEE_lightbake_job_data_alloc(bmain, view_layer, scene, false, scene->r.cfra); - light_cache_bake_tag_cache(scene, op); + light_cache_bake_tag_cache(scene, op); - short stop = 0, do_update; float progress; /* Not actually used. */ - EEVEE_lightbake_job(rj, &stop, &do_update, &progress); - EEVEE_lightbake_job_data_free(rj); + short stop = 0, do_update; + float progress; /* Not actually used. */ + EEVEE_lightbake_job(rj, &stop, &do_update, &progress); + EEVEE_lightbake_job_data_free(rj); - // no redraw needed, we leave state as we entered it - ED_update_for_newframe(bmain, CTX_data_depsgraph(C)); + // no redraw needed, we leave state as we entered it + ED_update_for_newframe(bmain, CTX_data_depsgraph(C)); - WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene); + WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static int light_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - int delay = RNA_int_get(op->ptr, "delay"); + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + int delay = RNA_int_get(op->ptr, "delay"); - wmJob *wm_job = EEVEE_lightbake_job_create(wm, win, bmain, view_layer, scene, delay, scene->r.cfra); + wmJob *wm_job = EEVEE_lightbake_job_create( + wm, win, bmain, view_layer, scene, delay, scene->r.cfra); - if (!wm_job) { - return OPERATOR_CANCELLED; - } + if (!wm_job) { + return OPERATOR_CANCELLED; + } - /* add modal handler for ESC */ - WM_event_add_modal_handler(C, op); + /* add modal handler for ESC */ + WM_event_add_modal_handler(C, op); - light_cache_bake_tag_cache(scene, op); + light_cache_bake_tag_cache(scene, op); - /* store actual owner of job, so modal operator could check for it, - * the reason of this is that active scene could change when rendering - * several layers from compositor [#31800] - */ - op->customdata = scene; + /* store actual owner of job, so modal operator could check for it, + * the reason of this is that active scene could change when rendering + * several layers from compositor [#31800] + */ + op->customdata = scene; - WM_jobs_start(wm, wm_job); + WM_jobs_start(wm, wm_job); - WM_cursor_wait(0); + WM_cursor_wait(0); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } void SCENE_OT_light_cache_bake(wmOperatorType *ot) { - static const EnumPropertyItem light_cache_subset_items[] = { - {LIGHTCACHE_SUBSET_ALL, "ALL", 0, "All LightProbes", - "Bake both irradiance grids and reflection cubemaps"}, - {LIGHTCACHE_SUBSET_DIRTY, "DIRTY", 0, "Dirty Only", - "Only bake lightprobes that are marked as dirty"}, - {LIGHTCACHE_SUBSET_CUBE, "CUBEMAPS", 0, "Cubemaps Only", - "Try to only bake reflection cubemaps if irradiance grids are up to date"}, - {0, NULL, 0, NULL, NULL}, - }; - - /* identifiers */ - ot->name = "Bake Light Cache"; - ot->idname = "SCENE_OT_light_cache_bake"; - ot->description = "Bake the active view layer lighting"; - - /* api callbacks */ - ot->invoke = light_cache_bake_invoke; - ot->modal = light_cache_bake_modal; - ot->cancel = light_cache_bake_cancel; - ot->exec = light_cache_bake_exec; - - ot->prop = RNA_def_int(ot->srna, "delay", 0, 0, 2000, "Delay", "Delay in millisecond before baking starts", 0, 2000); - RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); - - ot->prop = RNA_def_enum(ot->srna, "subset", light_cache_subset_items, 0, "Subset", "Subset of probes to update"); - RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); + static const EnumPropertyItem light_cache_subset_items[] = { + {LIGHTCACHE_SUBSET_ALL, + "ALL", + 0, + "All LightProbes", + "Bake both irradiance grids and reflection cubemaps"}, + {LIGHTCACHE_SUBSET_DIRTY, + "DIRTY", + 0, + "Dirty Only", + "Only bake lightprobes that are marked as dirty"}, + {LIGHTCACHE_SUBSET_CUBE, + "CUBEMAPS", + 0, + "Cubemaps Only", + "Try to only bake reflection cubemaps if irradiance grids are up to date"}, + {0, NULL, 0, NULL, NULL}, + }; + + /* identifiers */ + ot->name = "Bake Light Cache"; + ot->idname = "SCENE_OT_light_cache_bake"; + ot->description = "Bake the active view layer lighting"; + + /* api callbacks */ + ot->invoke = light_cache_bake_invoke; + ot->modal = light_cache_bake_modal; + ot->cancel = light_cache_bake_cancel; + ot->exec = light_cache_bake_exec; + + ot->prop = RNA_def_int(ot->srna, + "delay", + 0, + 0, + 2000, + "Delay", + "Delay in millisecond before baking starts", + 0, + 2000); + RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); + + ot->prop = RNA_def_enum( + ot->srna, "subset", light_cache_subset_items, 0, "Subset", "Subset of probes to update"); + RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); } static bool light_cache_free_poll(bContext *C) { - Scene *scene = CTX_data_scene(C); + Scene *scene = CTX_data_scene(C); - return scene->eevee.light_cache; + return scene->eevee.light_cache; } static int light_cache_free_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); + Scene *scene = CTX_data_scene(C); - /* kill potential bake job first (see T57011) */ - wmWindowManager *wm = CTX_wm_manager(C); - WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_LIGHT_BAKE); + /* kill potential bake job first (see T57011) */ + wmWindowManager *wm = CTX_wm_manager(C); + WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_LIGHT_BAKE); - if (!scene->eevee.light_cache) { - return OPERATOR_CANCELLED; - } + if (!scene->eevee.light_cache) { + return OPERATOR_CANCELLED; + } - EEVEE_lightcache_free(scene->eevee.light_cache); - scene->eevee.light_cache = NULL; + EEVEE_lightcache_free(scene->eevee.light_cache); + scene->eevee.light_cache = NULL; - EEVEE_lightcache_info_update(&scene->eevee); + EEVEE_lightcache_info_update(&scene->eevee); - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_light_cache_free(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Delete Light Cache"; - ot->idname = "SCENE_OT_light_cache_free"; - ot->description = "Delete cached indirect lighting"; + /* identifiers */ + ot->name = "Delete Light Cache"; + ot->idname = "SCENE_OT_light_cache_free"; + ot->description = "Delete cached indirect lighting"; - /* api callbacks */ - ot->exec = light_cache_free_exec; - ot->poll = light_cache_free_poll; + /* api callbacks */ + ot->exec = light_cache_free_exec; + ot->poll = light_cache_free_poll; } /********************** render view operators *********************/ static bool render_view_remove_poll(bContext *C) { - Scene *scene = CTX_data_scene(C); + Scene *scene = CTX_data_scene(C); - /* don't allow user to remove "left" and "right" views */ - return scene->r.actview > 1; + /* don't allow user to remove "left" and "right" views */ + return scene->r.actview > 1; } static int render_view_add_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); + Scene *scene = CTX_data_scene(C); - BKE_scene_add_render_view(scene, NULL); - scene->r.actview = BLI_listbase_count(&scene->r.views) - 1; + BKE_scene_add_render_view(scene, NULL); + scene->r.actview = BLI_listbase_count(&scene->r.views) - 1; - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_render_view_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Render View"; - ot->idname = "SCENE_OT_render_view_add"; - ot->description = "Add a render view"; + /* identifiers */ + ot->name = "Add Render View"; + ot->idname = "SCENE_OT_render_view_add"; + ot->description = "Add a render view"; - /* api callbacks */ - ot->exec = render_view_add_exec; + /* api callbacks */ + ot->exec = render_view_add_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } static int render_view_remove_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); - SceneRenderView *rv = BLI_findlink(&scene->r.views, scene->r.actview); + Scene *scene = CTX_data_scene(C); + SceneRenderView *rv = BLI_findlink(&scene->r.views, scene->r.actview); - if (!BKE_scene_remove_render_view(scene, rv)) - return OPERATOR_CANCELLED; + if (!BKE_scene_remove_render_view(scene, rv)) + return OPERATOR_CANCELLED; - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_render_view_remove(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove Render View"; - ot->idname = "SCENE_OT_render_view_remove"; - ot->description = "Remove the selected render view"; + /* identifiers */ + ot->name = "Remove Render View"; + ot->idname = "SCENE_OT_render_view_remove"; + ot->description = "Remove the selected render view"; - /* api callbacks */ - ot->exec = render_view_remove_exec; - ot->poll = render_view_remove_poll; + /* api callbacks */ + ot->exec = render_view_remove_exec; + ot->poll = render_view_remove_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } #ifdef WITH_FREESTYLE static bool freestyle_linestyle_check_report(FreestyleLineSet *lineset, ReportList *reports) { - if (!lineset) { - BKE_report(reports, RPT_ERROR, "No active lineset and associated line style to manipulate the modifier"); - return false; - } - if (!lineset->linestyle) { - BKE_report(reports, RPT_ERROR, "The active lineset does not have a line style (indicating data corruption)"); - return false; - } + if (!lineset) { + BKE_report(reports, + RPT_ERROR, + "No active lineset and associated line style to manipulate the modifier"); + return false; + } + if (!lineset->linestyle) { + BKE_report(reports, + RPT_ERROR, + "The active lineset does not have a line style (indicating data corruption)"); + return false; + } - return true; + return true; } static bool freestyle_active_module_poll(bContext *C) { - PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings); - FreestyleModuleConfig *module = ptr.data; + PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings); + FreestyleModuleConfig *module = ptr.data; - return module != NULL; + return module != NULL; } static int freestyle_module_add_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); - BKE_freestyle_module_add(&view_layer->freestyle_config); + BKE_freestyle_module_add(&view_layer->freestyle_config); - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_module_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Freestyle Module"; - ot->idname = "SCENE_OT_freestyle_module_add"; - ot->description = "Add a style module into the list of modules"; + /* identifiers */ + ot->name = "Add Freestyle Module"; + ot->idname = "SCENE_OT_freestyle_module_add"; + ot->description = "Add a style module into the list of modules"; - /* api callbacks */ - ot->exec = freestyle_module_add_exec; + /* api callbacks */ + ot->exec = freestyle_module_add_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static int freestyle_module_remove_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings); - FreestyleModuleConfig *module = ptr.data; + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings); + FreestyleModuleConfig *module = ptr.data; - BKE_freestyle_module_delete(&view_layer->freestyle_config, module); + BKE_freestyle_module_delete(&view_layer->freestyle_config, module); - DEG_id_tag_update(&scene->id, 0); - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + DEG_id_tag_update(&scene->id, 0); + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_module_remove(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove Freestyle Module"; - ot->idname = "SCENE_OT_freestyle_module_remove"; - ot->description = "Remove the style module from the stack"; + /* identifiers */ + ot->name = "Remove Freestyle Module"; + ot->idname = "SCENE_OT_freestyle_module_remove"; + ot->description = "Remove the style module from the stack"; - /* api callbacks */ - ot->poll = freestyle_active_module_poll; - ot->exec = freestyle_module_remove_exec; + /* api callbacks */ + ot->poll = freestyle_active_module_poll; + ot->exec = freestyle_module_remove_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static int freestyle_module_move_exec(bContext *C, wmOperator *op) { - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings); - FreestyleModuleConfig *module = ptr.data; - int dir = RNA_enum_get(op->ptr, "direction"); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings); + FreestyleModuleConfig *module = ptr.data; + int dir = RNA_enum_get(op->ptr, "direction"); - if (BKE_freestyle_module_move(&view_layer->freestyle_config, module, dir)) { - DEG_id_tag_update(&scene->id, 0); - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); - } + if (BKE_freestyle_module_move(&view_layer->freestyle_config, module, dir)) { + DEG_id_tag_update(&scene->id, 0); + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + } - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_module_move(wmOperatorType *ot) { - static const EnumPropertyItem direction_items[] = { - {-1, "UP", 0, "Up", ""}, - {1, "DOWN", 0, "Down", ""}, - {0, NULL, 0, NULL, NULL}, - }; + static const EnumPropertyItem direction_items[] = { + {-1, "UP", 0, "Up", ""}, + {1, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL}, + }; - /* identifiers */ - ot->name = "Move Freestyle Module"; - ot->idname = "SCENE_OT_freestyle_module_move"; - ot->description = "Change the position of the style module within in the list of style modules"; + /* identifiers */ + ot->name = "Move Freestyle Module"; + ot->idname = "SCENE_OT_freestyle_module_move"; + ot->description = "Change the position of the style module within in the list of style modules"; - /* api callbacks */ - ot->poll = freestyle_active_module_poll; - ot->exec = freestyle_module_move_exec; + /* api callbacks */ + ot->poll = freestyle_active_module_poll; + ot->exec = freestyle_module_move_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", - "Direction to move the chosen style module towards"); + /* props */ + RNA_def_enum(ot->srna, + "direction", + direction_items, + 0, + "Direction", + "Direction to move the chosen style module towards"); } static int freestyle_lineset_add_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); - BKE_freestyle_lineset_add(bmain, &view_layer->freestyle_config, NULL); + BKE_freestyle_lineset_add(bmain, &view_layer->freestyle_config, NULL); - DEG_id_tag_update(&scene->id, 0); - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + DEG_id_tag_update(&scene->id, 0); + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_lineset_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Line Set"; - ot->idname = "SCENE_OT_freestyle_lineset_add"; - ot->description = "Add a line set into the list of line sets"; + /* identifiers */ + ot->name = "Add Line Set"; + ot->idname = "SCENE_OT_freestyle_lineset_add"; + ot->description = "Add a line set into the list of line sets"; - /* api callbacks */ - ot->exec = freestyle_lineset_add_exec; + /* api callbacks */ + ot->exec = freestyle_lineset_add_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static bool freestyle_active_lineset_poll(bContext *C) { - ViewLayer *view_layer = CTX_data_view_layer(C); + ViewLayer *view_layer = CTX_data_view_layer(C); - if (!view_layer) { - return false; - } + if (!view_layer) { + return false; + } - return BKE_freestyle_lineset_get_active(&view_layer->freestyle_config) != NULL; + return BKE_freestyle_lineset_get_active(&view_layer->freestyle_config) != NULL; } static int freestyle_lineset_copy_exec(bContext *C, wmOperator *UNUSED(op)) { - ViewLayer *view_layer = CTX_data_view_layer(C); + ViewLayer *view_layer = CTX_data_view_layer(C); - FRS_copy_active_lineset(&view_layer->freestyle_config); + FRS_copy_active_lineset(&view_layer->freestyle_config); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_lineset_copy(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Copy Line Set"; - ot->idname = "SCENE_OT_freestyle_lineset_copy"; - ot->description = "Copy the active line set to a buffer"; + /* identifiers */ + ot->name = "Copy Line Set"; + ot->idname = "SCENE_OT_freestyle_lineset_copy"; + ot->description = "Copy the active line set to a buffer"; - /* api callbacks */ - ot->exec = freestyle_lineset_copy_exec; - ot->poll = freestyle_active_lineset_poll; + /* api callbacks */ + ot->exec = freestyle_lineset_copy_exec; + ot->poll = freestyle_active_lineset_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static int freestyle_lineset_paste_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); - FRS_paste_active_lineset(&view_layer->freestyle_config); + FRS_paste_active_lineset(&view_layer->freestyle_config); - DEG_id_tag_update(&scene->id, 0); - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + DEG_id_tag_update(&scene->id, 0); + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_lineset_paste(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Paste Line Set"; - ot->idname = "SCENE_OT_freestyle_lineset_paste"; - ot->description = "Paste the buffer content to the active line set"; + /* identifiers */ + ot->name = "Paste Line Set"; + ot->idname = "SCENE_OT_freestyle_lineset_paste"; + ot->description = "Paste the buffer content to the active line set"; - /* api callbacks */ - ot->exec = freestyle_lineset_paste_exec; - ot->poll = freestyle_active_lineset_poll; + /* api callbacks */ + ot->exec = freestyle_lineset_paste_exec; + ot->poll = freestyle_active_lineset_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static int freestyle_lineset_remove_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); - FRS_delete_active_lineset(&view_layer->freestyle_config); + FRS_delete_active_lineset(&view_layer->freestyle_config); - DEG_id_tag_update(&scene->id, 0); - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + DEG_id_tag_update(&scene->id, 0); + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_lineset_remove(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove Line Set"; - ot->idname = "SCENE_OT_freestyle_lineset_remove"; - ot->description = "Remove the active line set from the list of line sets"; + /* identifiers */ + ot->name = "Remove Line Set"; + ot->idname = "SCENE_OT_freestyle_lineset_remove"; + ot->description = "Remove the active line set from the list of line sets"; - /* api callbacks */ - ot->exec = freestyle_lineset_remove_exec; - ot->poll = freestyle_active_lineset_poll; + /* api callbacks */ + ot->exec = freestyle_lineset_remove_exec; + ot->poll = freestyle_active_lineset_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static int freestyle_lineset_move_exec(bContext *C, wmOperator *op) { - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - int dir = RNA_enum_get(op->ptr, "direction"); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + int dir = RNA_enum_get(op->ptr, "direction"); - if (FRS_move_active_lineset(&view_layer->freestyle_config, dir)) { - DEG_id_tag_update(&scene->id, 0); - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); - } + if (FRS_move_active_lineset(&view_layer->freestyle_config, dir)) { + DEG_id_tag_update(&scene->id, 0); + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); + } - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_lineset_move(wmOperatorType *ot) { - static const EnumPropertyItem direction_items[] = { - {-1, "UP", 0, "Up", ""}, - {1, "DOWN", 0, "Down", ""}, - {0, NULL, 0, NULL, NULL}, - }; + static const EnumPropertyItem direction_items[] = { + {-1, "UP", 0, "Up", ""}, + {1, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL}, + }; - /* identifiers */ - ot->name = "Move Line Set"; - ot->idname = "SCENE_OT_freestyle_lineset_move"; - ot->description = "Change the position of the active line set within the list of line sets"; + /* identifiers */ + ot->name = "Move Line Set"; + ot->idname = "SCENE_OT_freestyle_lineset_move"; + ot->description = "Change the position of the active line set within the list of line sets"; - /* api callbacks */ - ot->exec = freestyle_lineset_move_exec; - ot->poll = freestyle_active_lineset_poll; + /* api callbacks */ + ot->exec = freestyle_lineset_move_exec; + ot->poll = freestyle_active_lineset_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", - "Direction to move the active line set towards"); + /* props */ + RNA_def_enum(ot->srna, + "direction", + direction_items, + 0, + "Direction", + "Direction to move the active line set towards"); } static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); - if (!lineset) { - BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to"); - return OPERATOR_CANCELLED; - } - if (lineset->linestyle) { - id_us_min(&lineset->linestyle->id); - lineset->linestyle = BKE_linestyle_copy(bmain, lineset->linestyle); - } - else { - lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle"); - } - DEG_id_tag_update(&lineset->linestyle->id, 0); - WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); + if (!lineset) { + BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to"); + return OPERATOR_CANCELLED; + } + if (lineset->linestyle) { + id_us_min(&lineset->linestyle->id); + lineset->linestyle = BKE_linestyle_copy(bmain, lineset->linestyle); + } + else { + lineset->linestyle = BKE_linestyle_new(bmain, "LineStyle"); + } + DEG_id_tag_update(&lineset->linestyle->id, 0); + WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_linestyle_new(wmOperatorType *ot) { - /* identifiers */ - ot->name = "New Line Style"; - ot->idname = "SCENE_OT_freestyle_linestyle_new"; - ot->description = "Create a new line style, reusable by multiple line sets"; + /* identifiers */ + ot->name = "New Line Style"; + ot->idname = "SCENE_OT_freestyle_linestyle_new"; + ot->description = "Create a new line style, reusable by multiple line sets"; - /* api callbacks */ - ot->exec = freestyle_linestyle_new_exec; - ot->poll = freestyle_active_lineset_poll; + /* api callbacks */ + ot->exec = freestyle_linestyle_new_exec; + ot->poll = freestyle_active_lineset_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op) { - ViewLayer *view_layer = CTX_data_view_layer(C); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); - int type = RNA_enum_get(op->ptr, "type"); + ViewLayer *view_layer = CTX_data_view_layer(C); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); + int type = RNA_enum_get(op->ptr, "type"); - if (!freestyle_linestyle_check_report(lineset, op->reports)) { - return OPERATOR_CANCELLED; - } + if (!freestyle_linestyle_check_report(lineset, op->reports)) { + return OPERATOR_CANCELLED; + } - if (BKE_linestyle_color_modifier_add(lineset->linestyle, NULL, type) == NULL) { - BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type"); - return OPERATOR_CANCELLED; - } - DEG_id_tag_update(&lineset->linestyle->id, 0); - WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); + if (BKE_linestyle_color_modifier_add(lineset->linestyle, NULL, type) == NULL) { + BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type"); + return OPERATOR_CANCELLED; + } + DEG_id_tag_update(&lineset->linestyle->id, 0); + WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_color_modifier_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Line Color Modifier"; - ot->idname = "SCENE_OT_freestyle_color_modifier_add"; - ot->description = "Add a line color modifier to the line style associated with the active lineset"; + /* identifiers */ + ot->name = "Add Line Color Modifier"; + ot->idname = "SCENE_OT_freestyle_color_modifier_add"; + ot->description = + "Add a line color modifier to the line style associated with the active lineset"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = freestyle_color_modifier_add_exec; - ot->poll = freestyle_active_lineset_poll; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = freestyle_color_modifier_add_exec; + ot->poll = freestyle_active_lineset_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_color_modifier_type_items, 0, "Type", ""); + /* properties */ + ot->prop = RNA_def_enum( + ot->srna, "type", rna_enum_linestyle_color_modifier_type_items, 0, "Type", ""); } static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op) { - ViewLayer *view_layer = CTX_data_view_layer(C); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); - int type = RNA_enum_get(op->ptr, "type"); + ViewLayer *view_layer = CTX_data_view_layer(C); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); + int type = RNA_enum_get(op->ptr, "type"); - if (!freestyle_linestyle_check_report(lineset, op->reports)) { - return OPERATOR_CANCELLED; - } + if (!freestyle_linestyle_check_report(lineset, op->reports)) { + return OPERATOR_CANCELLED; + } - if (BKE_linestyle_alpha_modifier_add(lineset->linestyle, NULL, type) == NULL) { - BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type"); - return OPERATOR_CANCELLED; - } - DEG_id_tag_update(&lineset->linestyle->id, 0); - WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); + if (BKE_linestyle_alpha_modifier_add(lineset->linestyle, NULL, type) == NULL) { + BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type"); + return OPERATOR_CANCELLED; + } + DEG_id_tag_update(&lineset->linestyle->id, 0); + WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_alpha_modifier_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Alpha Transparency Modifier"; - ot->idname = "SCENE_OT_freestyle_alpha_modifier_add"; - ot->description = "Add an alpha transparency modifier to the line style associated with the active lineset"; + /* identifiers */ + ot->name = "Add Alpha Transparency Modifier"; + ot->idname = "SCENE_OT_freestyle_alpha_modifier_add"; + ot->description = + "Add an alpha transparency modifier to the line style associated with the active lineset"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = freestyle_alpha_modifier_add_exec; - ot->poll = freestyle_active_lineset_poll; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = freestyle_alpha_modifier_add_exec; + ot->poll = freestyle_active_lineset_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_alpha_modifier_type_items, 0, "Type", ""); + /* properties */ + ot->prop = RNA_def_enum( + ot->srna, "type", rna_enum_linestyle_alpha_modifier_type_items, 0, "Type", ""); } static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op) { - ViewLayer *view_layer = CTX_data_view_layer(C); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); - int type = RNA_enum_get(op->ptr, "type"); + ViewLayer *view_layer = CTX_data_view_layer(C); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); + int type = RNA_enum_get(op->ptr, "type"); - if (!freestyle_linestyle_check_report(lineset, op->reports)) { - return OPERATOR_CANCELLED; - } + if (!freestyle_linestyle_check_report(lineset, op->reports)) { + return OPERATOR_CANCELLED; + } - if (BKE_linestyle_thickness_modifier_add(lineset->linestyle, NULL, type) == NULL) { - BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type"); - return OPERATOR_CANCELLED; - } - DEG_id_tag_update(&lineset->linestyle->id, 0); - WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); + if (BKE_linestyle_thickness_modifier_add(lineset->linestyle, NULL, type) == NULL) { + BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type"); + return OPERATOR_CANCELLED; + } + DEG_id_tag_update(&lineset->linestyle->id, 0); + WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_thickness_modifier_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Line Thickness Modifier"; - ot->idname = "SCENE_OT_freestyle_thickness_modifier_add"; - ot->description = "Add a line thickness modifier to the line style associated with the active lineset"; + /* identifiers */ + ot->name = "Add Line Thickness Modifier"; + ot->idname = "SCENE_OT_freestyle_thickness_modifier_add"; + ot->description = + "Add a line thickness modifier to the line style associated with the active lineset"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = freestyle_thickness_modifier_add_exec; - ot->poll = freestyle_active_lineset_poll; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = freestyle_thickness_modifier_add_exec; + ot->poll = freestyle_active_lineset_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_thickness_modifier_type_items, 0, "Type", ""); + /* properties */ + ot->prop = RNA_def_enum( + ot->srna, "type", rna_enum_linestyle_thickness_modifier_type_items, 0, "Type", ""); } static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op) { - ViewLayer *view_layer = CTX_data_view_layer(C); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); - int type = RNA_enum_get(op->ptr, "type"); + ViewLayer *view_layer = CTX_data_view_layer(C); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); + int type = RNA_enum_get(op->ptr, "type"); - if (!freestyle_linestyle_check_report(lineset, op->reports)) { - return OPERATOR_CANCELLED; - } + if (!freestyle_linestyle_check_report(lineset, op->reports)) { + return OPERATOR_CANCELLED; + } - if (BKE_linestyle_geometry_modifier_add(lineset->linestyle, NULL, type) == NULL) { - BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type"); - return OPERATOR_CANCELLED; - } - DEG_id_tag_update(&lineset->linestyle->id, 0); - WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); + if (BKE_linestyle_geometry_modifier_add(lineset->linestyle, NULL, type) == NULL) { + BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type"); + return OPERATOR_CANCELLED; + } + DEG_id_tag_update(&lineset->linestyle->id, 0); + WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_geometry_modifier_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Stroke Geometry Modifier"; - ot->idname = "SCENE_OT_freestyle_geometry_modifier_add"; - ot->description = "Add a stroke geometry modifier to the line style associated with the active lineset"; + /* identifiers */ + ot->name = "Add Stroke Geometry Modifier"; + ot->idname = "SCENE_OT_freestyle_geometry_modifier_add"; + ot->description = + "Add a stroke geometry modifier to the line style associated with the active lineset"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = freestyle_geometry_modifier_add_exec; - ot->poll = freestyle_active_lineset_poll; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = freestyle_geometry_modifier_add_exec; + ot->poll = freestyle_active_lineset_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_linestyle_geometry_modifier_type_items, 0, "Type", ""); + /* properties */ + ot->prop = RNA_def_enum( + ot->srna, "type", rna_enum_linestyle_geometry_modifier_type_items, 0, "Type", ""); } static int freestyle_get_modifier_type(PointerRNA *ptr) { - if (RNA_struct_is_a(ptr->type, &RNA_LineStyleColorModifier)) - return LS_MODIFIER_TYPE_COLOR; - else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleAlphaModifier)) - return LS_MODIFIER_TYPE_ALPHA; - else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleThicknessModifier)) - return LS_MODIFIER_TYPE_THICKNESS; - else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleGeometryModifier)) - return LS_MODIFIER_TYPE_GEOMETRY; - return -1; + if (RNA_struct_is_a(ptr->type, &RNA_LineStyleColorModifier)) + return LS_MODIFIER_TYPE_COLOR; + else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleAlphaModifier)) + return LS_MODIFIER_TYPE_ALPHA; + else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleThicknessModifier)) + return LS_MODIFIER_TYPE_THICKNESS; + else if (RNA_struct_is_a(ptr->type, &RNA_LineStyleGeometryModifier)) + return LS_MODIFIER_TYPE_GEOMETRY; + return -1; } static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op) { - ViewLayer *view_layer = CTX_data_view_layer(C); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); - PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier); - LineStyleModifier *modifier = ptr.data; - - if (!freestyle_linestyle_check_report(lineset, op->reports)) { - return OPERATOR_CANCELLED; - } - - switch (freestyle_get_modifier_type(&ptr)) { - case LS_MODIFIER_TYPE_COLOR: - BKE_linestyle_color_modifier_remove(lineset->linestyle, modifier); - break; - case LS_MODIFIER_TYPE_ALPHA: - BKE_linestyle_alpha_modifier_remove(lineset->linestyle, modifier); - break; - case LS_MODIFIER_TYPE_THICKNESS: - BKE_linestyle_thickness_modifier_remove(lineset->linestyle, modifier); - break; - case LS_MODIFIER_TYPE_GEOMETRY: - BKE_linestyle_geometry_modifier_remove(lineset->linestyle, modifier); - break; - default: - BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier"); - return OPERATOR_CANCELLED; - } - DEG_id_tag_update(&lineset->linestyle->id, 0); - WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); - - return OPERATOR_FINISHED; + ViewLayer *view_layer = CTX_data_view_layer(C); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); + PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier); + LineStyleModifier *modifier = ptr.data; + + if (!freestyle_linestyle_check_report(lineset, op->reports)) { + return OPERATOR_CANCELLED; + } + + switch (freestyle_get_modifier_type(&ptr)) { + case LS_MODIFIER_TYPE_COLOR: + BKE_linestyle_color_modifier_remove(lineset->linestyle, modifier); + break; + case LS_MODIFIER_TYPE_ALPHA: + BKE_linestyle_alpha_modifier_remove(lineset->linestyle, modifier); + break; + case LS_MODIFIER_TYPE_THICKNESS: + BKE_linestyle_thickness_modifier_remove(lineset->linestyle, modifier); + break; + case LS_MODIFIER_TYPE_GEOMETRY: + BKE_linestyle_geometry_modifier_remove(lineset->linestyle, modifier); + break; + default: + BKE_report( + op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier"); + return OPERATOR_CANCELLED; + } + DEG_id_tag_update(&lineset->linestyle->id, 0); + WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); + + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_modifier_remove(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove Modifier"; - ot->idname = "SCENE_OT_freestyle_modifier_remove"; - ot->description = "Remove the modifier from the list of modifiers"; + /* identifiers */ + ot->name = "Remove Modifier"; + ot->idname = "SCENE_OT_freestyle_modifier_remove"; + ot->description = "Remove the modifier from the list of modifiers"; - /* api callbacks */ - ot->exec = freestyle_modifier_remove_exec; - ot->poll = freestyle_active_lineset_poll; + /* api callbacks */ + ot->exec = freestyle_modifier_remove_exec; + ot->poll = freestyle_active_lineset_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op) { - ViewLayer *view_layer = CTX_data_view_layer(C); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); - PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier); - LineStyleModifier *modifier = ptr.data; - - if (!freestyle_linestyle_check_report(lineset, op->reports)) { - return OPERATOR_CANCELLED; - } - - switch (freestyle_get_modifier_type(&ptr)) { - case LS_MODIFIER_TYPE_COLOR: - BKE_linestyle_color_modifier_copy(lineset->linestyle, modifier, 0); - break; - case LS_MODIFIER_TYPE_ALPHA: - BKE_linestyle_alpha_modifier_copy(lineset->linestyle, modifier, 0); - break; - case LS_MODIFIER_TYPE_THICKNESS: - BKE_linestyle_thickness_modifier_copy(lineset->linestyle, modifier, 0); - break; - case LS_MODIFIER_TYPE_GEOMETRY: - BKE_linestyle_geometry_modifier_copy(lineset->linestyle, modifier, 0); - break; - default: - BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier"); - return OPERATOR_CANCELLED; - } - DEG_id_tag_update(&lineset->linestyle->id, 0); - WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); - - return OPERATOR_FINISHED; + ViewLayer *view_layer = CTX_data_view_layer(C); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); + PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier); + LineStyleModifier *modifier = ptr.data; + + if (!freestyle_linestyle_check_report(lineset, op->reports)) { + return OPERATOR_CANCELLED; + } + + switch (freestyle_get_modifier_type(&ptr)) { + case LS_MODIFIER_TYPE_COLOR: + BKE_linestyle_color_modifier_copy(lineset->linestyle, modifier, 0); + break; + case LS_MODIFIER_TYPE_ALPHA: + BKE_linestyle_alpha_modifier_copy(lineset->linestyle, modifier, 0); + break; + case LS_MODIFIER_TYPE_THICKNESS: + BKE_linestyle_thickness_modifier_copy(lineset->linestyle, modifier, 0); + break; + case LS_MODIFIER_TYPE_GEOMETRY: + BKE_linestyle_geometry_modifier_copy(lineset->linestyle, modifier, 0); + break; + default: + BKE_report( + op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier"); + return OPERATOR_CANCELLED; + } + DEG_id_tag_update(&lineset->linestyle->id, 0); + WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); + + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_modifier_copy(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Copy Modifier"; - ot->idname = "SCENE_OT_freestyle_modifier_copy"; - ot->description = "Duplicate the modifier within the list of modifiers"; + /* identifiers */ + ot->name = "Copy Modifier"; + ot->idname = "SCENE_OT_freestyle_modifier_copy"; + ot->description = "Duplicate the modifier within the list of modifiers"; - /* api callbacks */ - ot->exec = freestyle_modifier_copy_exec; - ot->poll = freestyle_active_lineset_poll; + /* api callbacks */ + ot->exec = freestyle_modifier_copy_exec; + ot->poll = freestyle_active_lineset_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } static int freestyle_modifier_move_exec(bContext *C, wmOperator *op) { - ViewLayer *view_layer = CTX_data_view_layer(C); - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); - PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier); - LineStyleModifier *modifier = ptr.data; - int dir = RNA_enum_get(op->ptr, "direction"); - bool changed = false; - - if (!freestyle_linestyle_check_report(lineset, op->reports)) { - return OPERATOR_CANCELLED; - } - - switch (freestyle_get_modifier_type(&ptr)) { - case LS_MODIFIER_TYPE_COLOR: - changed = BKE_linestyle_color_modifier_move(lineset->linestyle, modifier, dir); - break; - case LS_MODIFIER_TYPE_ALPHA: - changed = BKE_linestyle_alpha_modifier_move(lineset->linestyle, modifier, dir); - break; - case LS_MODIFIER_TYPE_THICKNESS: - changed = BKE_linestyle_thickness_modifier_move(lineset->linestyle, modifier, dir); - break; - case LS_MODIFIER_TYPE_GEOMETRY: - changed = BKE_linestyle_geometry_modifier_move(lineset->linestyle, modifier, dir); - break; - default: - BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier"); - return OPERATOR_CANCELLED; - } - - if (changed) { - DEG_id_tag_update(&lineset->linestyle->id, 0); - WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); - } - - return OPERATOR_FINISHED; + ViewLayer *view_layer = CTX_data_view_layer(C); + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&view_layer->freestyle_config); + PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier); + LineStyleModifier *modifier = ptr.data; + int dir = RNA_enum_get(op->ptr, "direction"); + bool changed = false; + + if (!freestyle_linestyle_check_report(lineset, op->reports)) { + return OPERATOR_CANCELLED; + } + + switch (freestyle_get_modifier_type(&ptr)) { + case LS_MODIFIER_TYPE_COLOR: + changed = BKE_linestyle_color_modifier_move(lineset->linestyle, modifier, dir); + break; + case LS_MODIFIER_TYPE_ALPHA: + changed = BKE_linestyle_alpha_modifier_move(lineset->linestyle, modifier, dir); + break; + case LS_MODIFIER_TYPE_THICKNESS: + changed = BKE_linestyle_thickness_modifier_move(lineset->linestyle, modifier, dir); + break; + case LS_MODIFIER_TYPE_GEOMETRY: + changed = BKE_linestyle_geometry_modifier_move(lineset->linestyle, modifier, dir); + break; + default: + BKE_report( + op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier"); + return OPERATOR_CANCELLED; + } + + if (changed) { + DEG_id_tag_update(&lineset->linestyle->id, 0); + WM_event_add_notifier(C, NC_LINESTYLE, lineset->linestyle); + } + + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_modifier_move(wmOperatorType *ot) { - static const EnumPropertyItem direction_items[] = { - {-1, "UP", 0, "Up", ""}, - {1, "DOWN", 0, "Down", ""}, - {0, NULL, 0, NULL, NULL}, - }; + static const EnumPropertyItem direction_items[] = { + {-1, "UP", 0, "Up", ""}, + {1, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL}, + }; - /* identifiers */ - ot->name = "Move Modifier"; - ot->idname = "SCENE_OT_freestyle_modifier_move"; - ot->description = "Move the modifier within the list of modifiers"; + /* identifiers */ + ot->name = "Move Modifier"; + ot->idname = "SCENE_OT_freestyle_modifier_move"; + ot->description = "Move the modifier within the list of modifiers"; - /* api callbacks */ - ot->exec = freestyle_modifier_move_exec; - ot->poll = freestyle_active_lineset_poll; + /* api callbacks */ + ot->exec = freestyle_modifier_move_exec; + ot->poll = freestyle_active_lineset_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", - "Direction to move the chosen modifier towards"); + /* props */ + RNA_def_enum(ot->srna, + "direction", + direction_items, + 0, + "Direction", + "Direction to move the chosen modifier towards"); } static int freestyle_stroke_material_create_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer); + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer); - if (!linestyle) { - BKE_report(op->reports, RPT_ERROR, "No active line style in the current scene"); - return OPERATOR_CANCELLED; - } + if (!linestyle) { + BKE_report(op->reports, RPT_ERROR, "No active line style in the current scene"); + return OPERATOR_CANCELLED; + } - FRS_create_stroke_material(bmain, linestyle); + FRS_create_stroke_material(bmain, linestyle); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void SCENE_OT_freestyle_stroke_material_create(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Create Freestyle Stroke Material"; - ot->idname = "SCENE_OT_freestyle_stroke_material_create"; - ot->description = "Create Freestyle stroke material for testing"; + /* identifiers */ + ot->name = "Create Freestyle Stroke Material"; + ot->idname = "SCENE_OT_freestyle_stroke_material_create"; + ot->description = "Create Freestyle stroke material for testing"; - /* api callbacks */ - ot->exec = freestyle_stroke_material_create_exec; + /* api callbacks */ + ot->exec = freestyle_stroke_material_create_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } #endif /* WITH_FREESTYLE */ static int texture_slot_move_exec(bContext *C, wmOperator *op) { - ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; + ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; - if (id) { - MTex **mtex_ar, *mtexswap; - short act; - int type = RNA_enum_get(op->ptr, "type"); - struct AnimData *adt = BKE_animdata_from_id(id); + if (id) { + MTex **mtex_ar, *mtexswap; + short act; + int type = RNA_enum_get(op->ptr, "type"); + struct AnimData *adt = BKE_animdata_from_id(id); - give_active_mtex(id, &mtex_ar, &act); + give_active_mtex(id, &mtex_ar, &act); - if (type == -1) { /* Up */ - if (act > 0) { - mtexswap = mtex_ar[act]; - mtex_ar[act] = mtex_ar[act - 1]; - mtex_ar[act - 1] = mtexswap; + if (type == -1) { /* Up */ + if (act > 0) { + mtexswap = mtex_ar[act]; + mtex_ar[act] = mtex_ar[act - 1]; + mtex_ar[act - 1] = mtexswap; - BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act - 1, -1, 0); - BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act - 1, 0); - BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0); + BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act - 1, -1, 0); + BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act - 1, 0); + BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0); - set_active_mtex(id, act - 1); - } - } - else { /* Down */ - if (act < MAX_MTEX - 1) { - mtexswap = mtex_ar[act]; - mtex_ar[act] = mtex_ar[act + 1]; - mtex_ar[act + 1] = mtexswap; + set_active_mtex(id, act - 1); + } + } + else { /* Down */ + if (act < MAX_MTEX - 1) { + mtexswap = mtex_ar[act]; + mtex_ar[act] = mtex_ar[act + 1]; + mtex_ar[act + 1] = mtexswap; - BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act + 1, -1, 0); - BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act + 1, 0); - BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0); + BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act + 1, -1, 0); + BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, act, act + 1, 0); + BKE_animdata_fix_paths_rename(id, adt, NULL, "texture_slots", NULL, NULL, -1, act, 0); - set_active_mtex(id, act + 1); - } - } + set_active_mtex(id, act + 1); + } + } - DEG_id_tag_update(id, 0); - WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C)); - } + DEG_id_tag_update(id, 0); + WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C)); + } - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXTURE_OT_slot_move(wmOperatorType *ot) { - static const EnumPropertyItem slot_move[] = { - {-1, "UP", 0, "Up", ""}, - {1, "DOWN", 0, "Down", ""}, - {0, NULL, 0, NULL, NULL}, - }; + static const EnumPropertyItem slot_move[] = { + {-1, "UP", 0, "Up", ""}, + {1, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL}, + }; - /* identifiers */ - ot->name = "Move Texture Slot"; - ot->idname = "TEXTURE_OT_slot_move"; - ot->description = "Move texture slots up and down"; + /* identifiers */ + ot->name = "Move Texture Slot"; + ot->idname = "TEXTURE_OT_slot_move"; + ot->description = "Move texture slots up and down"; - /* api callbacks */ - ot->exec = texture_slot_move_exec; + /* api callbacks */ + ot->exec = texture_slot_move_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", ""); + RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", ""); } - - /********************** material operators *********************/ /* material copy/paste */ static int copy_material_exec(bContext *C, wmOperator *UNUSED(op)) { - Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data; + Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data; - if (ma == NULL) - return OPERATOR_CANCELLED; + if (ma == NULL) + return OPERATOR_CANCELLED; - copy_matcopybuf(CTX_data_main(C), ma); + copy_matcopybuf(CTX_data_main(C), ma); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void MATERIAL_OT_copy(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Copy Material"; - ot->idname = "MATERIAL_OT_copy"; - ot->description = "Copy the material settings and nodes"; + /* identifiers */ + ot->name = "Copy Material"; + ot->idname = "MATERIAL_OT_copy"; + ot->description = "Copy the material settings and nodes"; - /* api callbacks */ - ot->exec = copy_material_exec; + /* api callbacks */ + ot->exec = copy_material_exec; - /* flags */ - /* no undo needed since no changes are made to the material */ - ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL; + /* flags */ + /* no undo needed since no changes are made to the material */ + ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL; } static int paste_material_exec(bContext *C, wmOperator *UNUSED(op)) { - Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data; + Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data; - if (ma == NULL) - return OPERATOR_CANCELLED; + if (ma == NULL) + return OPERATOR_CANCELLED; - paste_matcopybuf(CTX_data_main(C), ma); + paste_matcopybuf(CTX_data_main(C), ma); - DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE); - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma); + DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void MATERIAL_OT_paste(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Paste Material"; - ot->idname = "MATERIAL_OT_paste"; - ot->description = "Paste the material settings and nodes"; + /* identifiers */ + ot->name = "Paste Material"; + ot->idname = "MATERIAL_OT_paste"; + ot->description = "Paste the material settings and nodes"; - /* api callbacks */ - ot->exec = paste_material_exec; + /* api callbacks */ + ot->exec = paste_material_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } - static short mtexcopied = 0; /* must be reset on file load */ static MTex mtexcopybuf; void ED_render_clear_mtex_copybuf(void) -{ /* use for file reload */ - mtexcopied = 0; +{ /* use for file reload */ + mtexcopied = 0; } static void copy_mtex_copybuf(ID *id) { - MTex **mtex = NULL; + MTex **mtex = NULL; - switch (GS(id->name)) { - case ID_PA: - mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]); - break; - case ID_LS: - mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]); - break; - default: - break; - } + switch (GS(id->name)) { + case ID_PA: + mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]); + break; + case ID_LS: + mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]); + break; + default: + break; + } - if (mtex && *mtex) { - memcpy(&mtexcopybuf, *mtex, sizeof(MTex)); - mtexcopied = 1; - } - else { - mtexcopied = 0; - } + if (mtex && *mtex) { + memcpy(&mtexcopybuf, *mtex, sizeof(MTex)); + mtexcopied = 1; + } + else { + mtexcopied = 0; + } } static void paste_mtex_copybuf(ID *id) { - MTex **mtex = NULL; + MTex **mtex = NULL; - if (mtexcopied == 0 || mtexcopybuf.tex == NULL) - return; + if (mtexcopied == 0 || mtexcopybuf.tex == NULL) + return; - switch (GS(id->name)) { - case ID_PA: - mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]); - break; - case ID_LS: - mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]); - break; - default: - BLI_assert(!"invalid id type"); - return; - } + switch (GS(id->name)) { + case ID_PA: + mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]); + break; + case ID_LS: + mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]); + break; + default: + BLI_assert(!"invalid id type"); + return; + } - if (mtex) { - if (*mtex == NULL) { - *mtex = MEM_mallocN(sizeof(MTex), "mtex copy"); - } - else if ((*mtex)->tex) { - id_us_min(&(*mtex)->tex->id); - } + if (mtex) { + if (*mtex == NULL) { + *mtex = MEM_mallocN(sizeof(MTex), "mtex copy"); + } + else if ((*mtex)->tex) { + id_us_min(&(*mtex)->tex->id); + } - memcpy(*mtex, &mtexcopybuf, sizeof(MTex)); + memcpy(*mtex, &mtexcopybuf, sizeof(MTex)); - id_us_plus((ID *)mtexcopybuf.tex); - } + id_us_plus((ID *)mtexcopybuf.tex); + } } - static int copy_mtex_exec(bContext *C, wmOperator *UNUSED(op)) { - ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; + ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; - if (id == NULL) { - /* copying empty slot */ - ED_render_clear_mtex_copybuf(); - return OPERATOR_CANCELLED; - } + if (id == NULL) { + /* copying empty slot */ + ED_render_clear_mtex_copybuf(); + return OPERATOR_CANCELLED; + } - copy_mtex_copybuf(id); + copy_mtex_copybuf(id); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static bool copy_mtex_poll(bContext *C) { - ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; + ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; - return (id != NULL); + return (id != NULL); } void TEXTURE_OT_slot_copy(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Copy Texture Slot Settings"; - ot->idname = "TEXTURE_OT_slot_copy"; - ot->description = "Copy the material texture settings and nodes"; + /* identifiers */ + ot->name = "Copy Texture Slot Settings"; + ot->idname = "TEXTURE_OT_slot_copy"; + ot->description = "Copy the material texture settings and nodes"; - /* api callbacks */ - ot->exec = copy_mtex_exec; - ot->poll = copy_mtex_poll; + /* api callbacks */ + ot->exec = copy_mtex_exec; + ot->poll = copy_mtex_poll; - /* flags */ - /* no undo needed since no changes are made to the mtex */ - ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL; + /* flags */ + /* no undo needed since no changes are made to the mtex */ + ot->flag = OPTYPE_REGISTER | OPTYPE_INTERNAL; } static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op)) { - ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; + ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data; - if (id == NULL) { - Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data; - Light *la = CTX_data_pointer_get_type(C, "light", &RNA_Light).data; - World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data; - ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data; - FreestyleLineStyle *linestyle = CTX_data_pointer_get_type(C, "line_style", &RNA_FreestyleLineStyle).data; + if (id == NULL) { + Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data; + Light *la = CTX_data_pointer_get_type(C, "light", &RNA_Light).data; + World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data; + ParticleSystem *psys = + CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data; + FreestyleLineStyle *linestyle = + CTX_data_pointer_get_type(C, "line_style", &RNA_FreestyleLineStyle).data; - if (ma) - id = &ma->id; - else if (la) - id = &la->id; - else if (wo) - id = &wo->id; - else if (psys) - id = &psys->part->id; - else if (linestyle) - id = &linestyle->id; + if (ma) + id = &ma->id; + else if (la) + id = &la->id; + else if (wo) + id = &wo->id; + else if (psys) + id = &psys->part->id; + else if (linestyle) + id = &linestyle->id; - if (id == NULL) - return OPERATOR_CANCELLED; - } + if (id == NULL) + return OPERATOR_CANCELLED; + } - paste_mtex_copybuf(id); + paste_mtex_copybuf(id); - WM_event_add_notifier(C, NC_TEXTURE | ND_SHADING_LINKS, NULL); + WM_event_add_notifier(C, NC_TEXTURE | ND_SHADING_LINKS, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXTURE_OT_slot_paste(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Paste Texture Slot Settings"; - ot->idname = "TEXTURE_OT_slot_paste"; - ot->description = "Copy the texture settings and nodes"; + /* identifiers */ + ot->name = "Paste Texture Slot Settings"; + ot->idname = "TEXTURE_OT_slot_paste"; + ot->description = "Copy the texture settings and nodes"; - /* api callbacks */ - ot->exec = paste_mtex_exec; + /* api callbacks */ + ot->exec = paste_mtex_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index bbd73b581f4..dfc7610946a 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -69,141 +69,138 @@ void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, int updated) { - /* viewport rendering update on data changes, happens after depsgraph - * updates if there was any change. context is set to the 3d view */ - Main *bmain = update_ctx->bmain; - Scene *scene = update_ctx->scene; - ViewLayer *view_layer = update_ctx->view_layer; - bContext *C; - wmWindowManager *wm; - wmWindow *win; - static bool recursive_check = false; - - /* don't do this render engine update if we're updating the scene from - * other threads doing e.g. rendering or baking jobs */ - if (!BLI_thread_is_main()) - return; - - /* don't call this recursively for frame updates */ - if (recursive_check) - return; - - /* Do not call if no WM available, see T42688. */ - if (BLI_listbase_is_empty(&bmain->wm)) - return; - - recursive_check = true; - - C = CTX_create(); - CTX_data_main_set(C, bmain); - CTX_data_scene_set(C, scene); - - CTX_wm_manager_set(C, bmain->wm.first); - wm = bmain->wm.first; - - for (win = wm->windows.first; win; win = win->next) { - bScreen *sc = WM_window_get_active_screen(win); - ScrArea *sa; - ARegion *ar; - - CTX_wm_window_set(C, win); - - for (sa = sc->areabase.first; sa; sa = sa->next) { - if (sa->spacetype != SPACE_VIEW3D) { - continue; - } - View3D *v3d = sa->spacedata.first; - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype != RGN_TYPE_WINDOW) { - continue; - } - RegionView3D *rv3d = ar->regiondata; - RenderEngine *engine = rv3d->render_engine; - /* call update if the scene changed, or if the render engine - * tagged itself for update (e.g. because it was busy at the - * time of the last update) */ - if (engine && (updated || (engine->flag & RE_ENGINE_DO_UPDATE))) { - - CTX_wm_screen_set(C, sc); - CTX_wm_area_set(C, sa); - CTX_wm_region_set(C, ar); - - engine->flag &= ~RE_ENGINE_DO_UPDATE; - engine->type->view_update(engine, C); - - } - else { - RenderEngineType *engine_type = - ED_view3d_engine_type(scene, v3d->shading.type); - if (updated) { - DRW_notify_view_update( - (&(DRWUpdateContext){ - .bmain = bmain, - .depsgraph = update_ctx->depsgraph, - .scene = scene, - .view_layer = view_layer, - .ar = ar, - .v3d = (View3D *)sa->spacedata.first, - .engine_type = engine_type, - })); - } - } - } - } - } - - CTX_free(C); - - recursive_check = false; + /* viewport rendering update on data changes, happens after depsgraph + * updates if there was any change. context is set to the 3d view */ + Main *bmain = update_ctx->bmain; + Scene *scene = update_ctx->scene; + ViewLayer *view_layer = update_ctx->view_layer; + bContext *C; + wmWindowManager *wm; + wmWindow *win; + static bool recursive_check = false; + + /* don't do this render engine update if we're updating the scene from + * other threads doing e.g. rendering or baking jobs */ + if (!BLI_thread_is_main()) + return; + + /* don't call this recursively for frame updates */ + if (recursive_check) + return; + + /* Do not call if no WM available, see T42688. */ + if (BLI_listbase_is_empty(&bmain->wm)) + return; + + recursive_check = true; + + C = CTX_create(); + CTX_data_main_set(C, bmain); + CTX_data_scene_set(C, scene); + + CTX_wm_manager_set(C, bmain->wm.first); + wm = bmain->wm.first; + + for (win = wm->windows.first; win; win = win->next) { + bScreen *sc = WM_window_get_active_screen(win); + ScrArea *sa; + ARegion *ar; + + CTX_wm_window_set(C, win); + + for (sa = sc->areabase.first; sa; sa = sa->next) { + if (sa->spacetype != SPACE_VIEW3D) { + continue; + } + View3D *v3d = sa->spacedata.first; + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->regiontype != RGN_TYPE_WINDOW) { + continue; + } + RegionView3D *rv3d = ar->regiondata; + RenderEngine *engine = rv3d->render_engine; + /* call update if the scene changed, or if the render engine + * tagged itself for update (e.g. because it was busy at the + * time of the last update) */ + if (engine && (updated || (engine->flag & RE_ENGINE_DO_UPDATE))) { + + CTX_wm_screen_set(C, sc); + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, ar); + + engine->flag &= ~RE_ENGINE_DO_UPDATE; + engine->type->view_update(engine, C); + } + else { + RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); + if (updated) { + DRW_notify_view_update((&(DRWUpdateContext){ + .bmain = bmain, + .depsgraph = update_ctx->depsgraph, + .scene = scene, + .view_layer = view_layer, + .ar = ar, + .v3d = (View3D *)sa->spacedata.first, + .engine_type = engine_type, + })); + } + } + } + } + } + + CTX_free(C); + + recursive_check = false; } void ED_render_engine_area_exit(Main *bmain, ScrArea *sa) { - /* clear all render engines in this area */ - ARegion *ar; - wmWindowManager *wm = bmain->wm.first; - - if (sa->spacetype != SPACE_VIEW3D) - return; - - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype != RGN_TYPE_WINDOW || !(ar->regiondata)) - continue; - ED_view3d_stop_render_preview(wm, ar); - } + /* clear all render engines in this area */ + ARegion *ar; + wmWindowManager *wm = bmain->wm.first; + + if (sa->spacetype != SPACE_VIEW3D) + return; + + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->regiontype != RGN_TYPE_WINDOW || !(ar->regiondata)) + continue; + ED_view3d_stop_render_preview(wm, ar); + } } void ED_render_engine_changed(Main *bmain) { - /* on changing the render engine type, clear all running render engines */ - for (bScreen *sc = bmain->screens.first; sc; sc = sc->id.next) { - for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { - ED_render_engine_area_exit(bmain, sa); - } - } - RE_FreePersistentData(); - /* Inform all render engines and draw managers. */ - DEGEditorUpdateContext update_ctx = {NULL}; - update_ctx.bmain = bmain; - for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { - update_ctx.scene = scene; - LISTBASE_FOREACH(ViewLayer *, view_layer, &scene->view_layers) { - /* TDODO(sergey): Iterate over depsgraphs instead? */ - update_ctx.depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); - update_ctx.view_layer = view_layer; - ED_render_id_flush_update(&update_ctx, &scene->id); - } - if (scene->nodetree) { - ntreeCompositUpdateRLayers(scene->nodetree); - } - } + /* on changing the render engine type, clear all running render engines */ + for (bScreen *sc = bmain->screens.first; sc; sc = sc->id.next) { + for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { + ED_render_engine_area_exit(bmain, sa); + } + } + RE_FreePersistentData(); + /* Inform all render engines and draw managers. */ + DEGEditorUpdateContext update_ctx = {NULL}; + update_ctx.bmain = bmain; + for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { + update_ctx.scene = scene; + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) { + /* TDODO(sergey): Iterate over depsgraphs instead? */ + update_ctx.depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); + update_ctx.view_layer = view_layer; + ED_render_id_flush_update(&update_ctx, &scene->id); + } + if (scene->nodetree) { + ntreeCompositUpdateRLayers(scene->nodetree); + } + } } void ED_render_view_layer_changed(Main *bmain, bScreen *sc) { - for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { - ED_render_engine_area_exit(bmain, sa); - } + for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { + ED_render_engine_area_exit(bmain, sa); + } } /***************************** Updates *********************************** @@ -213,102 +210,102 @@ void ED_render_view_layer_changed(Main *bmain, bScreen *sc) static void material_changed(Main *UNUSED(bmain), Material *ma) { - /* icons */ - BKE_icon_changed(BKE_icon_id_ensure(&ma->id)); + /* icons */ + BKE_icon_changed(BKE_icon_id_ensure(&ma->id)); } static void lamp_changed(Main *UNUSED(bmain), Light *la) { - /* icons */ - BKE_icon_changed(BKE_icon_id_ensure(&la->id)); + /* icons */ + BKE_icon_changed(BKE_icon_id_ensure(&la->id)); } static void texture_changed(Main *bmain, Tex *tex) { - Scene *scene; - ViewLayer *view_layer; - bNode *node; - - /* icons */ - BKE_icon_changed(BKE_icon_id_ensure(&tex->id)); - - for (scene = bmain->scenes.first; scene; scene = scene->id.next) { - /* paint overlays */ - for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { - BKE_paint_invalidate_overlay_tex(scene, view_layer, tex); - } - /* find compositing nodes */ - if (scene->use_nodes && scene->nodetree) { - for (node = scene->nodetree->nodes.first; node; node = node->next) { - if (node->id == &tex->id) - ED_node_tag_update_id(&scene->id); - } - } - } + Scene *scene; + ViewLayer *view_layer; + bNode *node; + + /* icons */ + BKE_icon_changed(BKE_icon_id_ensure(&tex->id)); + + for (scene = bmain->scenes.first; scene; scene = scene->id.next) { + /* paint overlays */ + for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + BKE_paint_invalidate_overlay_tex(scene, view_layer, tex); + } + /* find compositing nodes */ + if (scene->use_nodes && scene->nodetree) { + for (node = scene->nodetree->nodes.first; node; node = node->next) { + if (node->id == &tex->id) + ED_node_tag_update_id(&scene->id); + } + } + } } static void world_changed(Main *UNUSED(bmain), World *wo) { - /* icons */ - BKE_icon_changed(BKE_icon_id_ensure(&wo->id)); + /* icons */ + BKE_icon_changed(BKE_icon_id_ensure(&wo->id)); } static void image_changed(Main *bmain, Image *ima) { - Tex *tex; + Tex *tex; - /* icons */ - BKE_icon_changed(BKE_icon_id_ensure(&ima->id)); + /* icons */ + BKE_icon_changed(BKE_icon_id_ensure(&ima->id)); - /* textures */ - for (tex = bmain->textures.first; tex; tex = tex->id.next) - if (tex->ima == ima) - texture_changed(bmain, tex); + /* textures */ + for (tex = bmain->textures.first; tex; tex = tex->id.next) + if (tex->ima == ima) + texture_changed(bmain, tex); } static void scene_changed(Main *bmain, Scene *scene) { - Object *ob; - - /* glsl */ - for (ob = bmain->objects.first; ob; ob = ob->id.next) { - if (ob->mode & OB_MODE_TEXTURE_PAINT) { - BKE_texpaint_slots_refresh_object(scene, ob); - BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); - } - } + Object *ob; + + /* glsl */ + for (ob = bmain->objects.first; ob; ob = ob->id.next) { + if (ob->mode & OB_MODE_TEXTURE_PAINT) { + BKE_texpaint_slots_refresh_object(scene, ob); + BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + } + } } void ED_render_id_flush_update(const DEGEditorUpdateContext *update_ctx, ID *id) { - /* this can be called from render or baking thread when a python script makes - * changes, in that case we don't want to do any editor updates, and making - * GPU changes is not possible because OpenGL only works in the main thread */ - if (!BLI_thread_is_main()) { - return; - } - Main *bmain = update_ctx->bmain; - /* Internal ID update handlers. */ - switch (GS(id->name)) { - case ID_MA: - material_changed(bmain, (Material *)id); - break; - case ID_TE: - texture_changed(bmain, (Tex *)id); - break; - case ID_WO: - world_changed(bmain, (World *)id); - break; - case ID_LA: - lamp_changed(bmain, (Light *)id); - break; - case ID_IM: - image_changed(bmain, (Image *)id); - break; - case ID_SCE: - scene_changed(bmain, (Scene *)id); - break; - default: - break; - } + /* this can be called from render or baking thread when a python script makes + * changes, in that case we don't want to do any editor updates, and making + * GPU changes is not possible because OpenGL only works in the main thread */ + if (!BLI_thread_is_main()) { + return; + } + Main *bmain = update_ctx->bmain; + /* Internal ID update handlers. */ + switch (GS(id->name)) { + case ID_MA: + material_changed(bmain, (Material *)id); + break; + case ID_TE: + texture_changed(bmain, (Tex *)id); + break; + case ID_WO: + world_changed(bmain, (World *)id); + break; + case ID_LA: + lamp_changed(bmain, (Light *)id); + break; + case ID_IM: + image_changed(bmain, (Image *)id); + break; + case ID_SCE: + scene_changed(bmain, (Scene *)id); + break; + default: + break; + } } diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c index 1d7022c5263..258e98977c7 100644 --- a/source/blender/editors/render/render_view.c +++ b/source/blender/editors/render/render_view.c @@ -49,77 +49,77 @@ /*********************** utilities for finding areas *************************/ /* returns biggest area that is not uv/image editor. Note that it uses buttons */ -/* window as the last possible alternative. */ +/* window as the last possible alternative. */ /* would use BKE_screen_find_big_area(...) but this is too specific */ static ScrArea *biggest_non_image_area(bContext *C) { - bScreen *sc = CTX_wm_screen(C); - ScrArea *sa, *big = NULL; - int size, maxsize = 0, bwmaxsize = 0; - short foundwin = 0; - - for (sa = sc->areabase.first; sa; sa = sa->next) { - if (sa->winx > 30 && sa->winy > 30) { - size = sa->winx * sa->winy; - if (!sa->full && sa->spacetype == SPACE_PROPERTIES) { - if (foundwin == 0 && size > bwmaxsize) { - bwmaxsize = size; - big = sa; - } - } - else if (sa->spacetype != SPACE_IMAGE && size > maxsize) { - maxsize = size; - big = sa; - foundwin = 1; - } - } - } - - return big; + bScreen *sc = CTX_wm_screen(C); + ScrArea *sa, *big = NULL; + int size, maxsize = 0, bwmaxsize = 0; + short foundwin = 0; + + for (sa = sc->areabase.first; sa; sa = sa->next) { + if (sa->winx > 30 && sa->winy > 30) { + size = sa->winx * sa->winy; + if (!sa->full && sa->spacetype == SPACE_PROPERTIES) { + if (foundwin == 0 && size > bwmaxsize) { + bwmaxsize = size; + big = sa; + } + } + else if (sa->spacetype != SPACE_IMAGE && size > maxsize) { + maxsize = size; + big = sa; + foundwin = 1; + } + } + } + + return big; } static ScrArea *find_area_showing_r_result(bContext *C, Scene *scene, wmWindow **win) { - wmWindowManager *wm = CTX_wm_manager(C); - ScrArea *sa = NULL; - SpaceImage *sima; - - /* find an imagewindow showing render result */ - for (*win = wm->windows.first; *win; *win = (*win)->next) { - if (WM_window_get_active_scene(*win) == scene) { - const bScreen *screen = WM_window_get_active_screen(*win); - - for (sa = screen->areabase.first; sa; sa = sa->next) { - if (sa->spacetype == SPACE_IMAGE) { - sima = sa->spacedata.first; - if (sima->image && sima->image->type == IMA_TYPE_R_RESULT) - break; - } - } - if (sa) - break; - } - } - - return sa; + wmWindowManager *wm = CTX_wm_manager(C); + ScrArea *sa = NULL; + SpaceImage *sima; + + /* find an imagewindow showing render result */ + for (*win = wm->windows.first; *win; *win = (*win)->next) { + if (WM_window_get_active_scene(*win) == scene) { + const bScreen *screen = WM_window_get_active_screen(*win); + + for (sa = screen->areabase.first; sa; sa = sa->next) { + if (sa->spacetype == SPACE_IMAGE) { + sima = sa->spacedata.first; + if (sima->image && sima->image->type == IMA_TYPE_R_RESULT) + break; + } + } + if (sa) + break; + } + } + + return sa; } static ScrArea *find_area_image_empty(bContext *C) { - bScreen *sc = CTX_wm_screen(C); - ScrArea *sa; - SpaceImage *sima; - - /* find an imagewindow showing render result */ - for (sa = sc->areabase.first; sa; sa = sa->next) { - if (sa->spacetype == SPACE_IMAGE) { - sima = sa->spacedata.first; - if (!sima->image) - break; - } - } - - return sa; + bScreen *sc = CTX_wm_screen(C); + ScrArea *sa; + SpaceImage *sima; + + /* find an imagewindow showing render result */ + for (sa = sc->areabase.first; sa; sa = sa->next) { + if (sa->spacetype == SPACE_IMAGE) { + sima = sa->spacedata.first; + if (!sima->image) + break; + } + } + + return sa; } /********************** open image editor for render *************************/ @@ -127,224 +127,225 @@ static ScrArea *find_area_image_empty(bContext *C) /* new window uses x,y to set position */ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - wmWindow *win = NULL; - ScrArea *sa = NULL; - SpaceImage *sima; - bool area_was_image = false; - - if (scene->r.displaymode == R_OUTPUT_NONE) - return NULL; - - if (scene->r.displaymode == R_OUTPUT_WINDOW) { - int sizex = 30 * UI_DPI_FAC + (scene->r.xsch * scene->r.size) / 100; - int sizey = 60 * UI_DPI_FAC + (scene->r.ysch * scene->r.size) / 100; - - /* arbitrary... miniature image window views don't make much sense */ - if (sizex < 320) sizex = 320; - if (sizey < 256) sizey = 256; - - /* changes context! */ - if (WM_window_open_temp(C, mx, my, sizex, sizey, WM_WINDOW_RENDER) == NULL) { - BKE_report(reports, RPT_ERROR, "Failed to open window!"); - return NULL; - } - - sa = CTX_wm_area(C); - } - else if (scene->r.displaymode == R_OUTPUT_SCREEN) { - sa = CTX_wm_area(C); - - /* if the active screen is already in fullscreen mode, skip this and - * unset the area, so that the fullscreen area is just changed later */ - if (sa && sa->full) { - sa = NULL; - } - else { - if (sa && sa->spacetype == SPACE_IMAGE) - area_was_image = true; - - /* this function returns with changed context */ - sa = ED_screen_full_newspace(C, sa, SPACE_IMAGE); - } - } - - if (!sa) { - sa = find_area_showing_r_result(C, scene, &win); - if (sa == NULL) - sa = find_area_image_empty(C); - - /* if area found in other window, we make that one show in front */ - if (win && win != CTX_wm_window(C)) - wm_window_raise(win); - - if (sa == NULL) { - /* find largest open non-image area */ - sa = biggest_non_image_area(C); - if (sa) { - ED_area_newspace(C, sa, SPACE_IMAGE, true); - sima = sa->spacedata.first; - - /* makes ESC go back to prev space */ - sima->flag |= SI_PREVSPACE; - - /* we already had a fullscreen here -> mark new space as a stacked fullscreen */ - if (sa->full) { - sa->flag |= (AREA_FLAG_STACKED_FULLSCREEN | AREA_FLAG_TEMP_TYPE); - } - } - else { - /* use any area of decent size */ - sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TYPE_ANY, 0); - if (sa->spacetype != SPACE_IMAGE) { - // XXX newspace(sa, SPACE_IMAGE); - sima = sa->spacedata.first; - - /* makes ESC go back to prev space */ - sima->flag |= SI_PREVSPACE; - } - } - } - } - sima = sa->spacedata.first; - - /* get the correct image, and scale it */ - sima->image = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"); - - - /* if we're rendering to full screen, set appropriate hints on image editor - * so it can restore properly on pressing esc */ - if (sa->full) { - sima->flag |= SI_FULLWINDOW; - - /* Tell the image editor to revert to previous space in space list on close - * _only_ if it wasn't already an image editor when the render was invoked */ - if (area_was_image == 0) - sima->flag |= SI_PREVSPACE; - else { - /* Leave it alone so the image editor will just go back from - * full screen to the original tiled setup */ - } - } - - return sa; + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + wmWindow *win = NULL; + ScrArea *sa = NULL; + SpaceImage *sima; + bool area_was_image = false; + + if (scene->r.displaymode == R_OUTPUT_NONE) + return NULL; + + if (scene->r.displaymode == R_OUTPUT_WINDOW) { + int sizex = 30 * UI_DPI_FAC + (scene->r.xsch * scene->r.size) / 100; + int sizey = 60 * UI_DPI_FAC + (scene->r.ysch * scene->r.size) / 100; + + /* arbitrary... miniature image window views don't make much sense */ + if (sizex < 320) + sizex = 320; + if (sizey < 256) + sizey = 256; + + /* changes context! */ + if (WM_window_open_temp(C, mx, my, sizex, sizey, WM_WINDOW_RENDER) == NULL) { + BKE_report(reports, RPT_ERROR, "Failed to open window!"); + return NULL; + } + + sa = CTX_wm_area(C); + } + else if (scene->r.displaymode == R_OUTPUT_SCREEN) { + sa = CTX_wm_area(C); + + /* if the active screen is already in fullscreen mode, skip this and + * unset the area, so that the fullscreen area is just changed later */ + if (sa && sa->full) { + sa = NULL; + } + else { + if (sa && sa->spacetype == SPACE_IMAGE) + area_was_image = true; + + /* this function returns with changed context */ + sa = ED_screen_full_newspace(C, sa, SPACE_IMAGE); + } + } + + if (!sa) { + sa = find_area_showing_r_result(C, scene, &win); + if (sa == NULL) + sa = find_area_image_empty(C); + + /* if area found in other window, we make that one show in front */ + if (win && win != CTX_wm_window(C)) + wm_window_raise(win); + + if (sa == NULL) { + /* find largest open non-image area */ + sa = biggest_non_image_area(C); + if (sa) { + ED_area_newspace(C, sa, SPACE_IMAGE, true); + sima = sa->spacedata.first; + + /* makes ESC go back to prev space */ + sima->flag |= SI_PREVSPACE; + + /* we already had a fullscreen here -> mark new space as a stacked fullscreen */ + if (sa->full) { + sa->flag |= (AREA_FLAG_STACKED_FULLSCREEN | AREA_FLAG_TEMP_TYPE); + } + } + else { + /* use any area of decent size */ + sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TYPE_ANY, 0); + if (sa->spacetype != SPACE_IMAGE) { + // XXX newspace(sa, SPACE_IMAGE); + sima = sa->spacedata.first; + + /* makes ESC go back to prev space */ + sima->flag |= SI_PREVSPACE; + } + } + } + } + sima = sa->spacedata.first; + + /* get the correct image, and scale it */ + sima->image = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"); + + /* if we're rendering to full screen, set appropriate hints on image editor + * so it can restore properly on pressing esc */ + if (sa->full) { + sima->flag |= SI_FULLWINDOW; + + /* Tell the image editor to revert to previous space in space list on close + * _only_ if it wasn't already an image editor when the render was invoked */ + if (area_was_image == 0) + sima->flag |= SI_PREVSPACE; + else { + /* Leave it alone so the image editor will just go back from + * full screen to the original tiled setup */ + } + } + + return sa; } /*************************** cancel render viewer **********************/ static int render_view_cancel_exec(bContext *C, wmOperator *UNUSED(op)) { - wmWindow *win = CTX_wm_window(C); - ScrArea *sa = CTX_wm_area(C); - SpaceImage *sima = sa->spacedata.first; - - /* ensure image editor fullscreen and area fullscreen states are in sync */ - if ((sima->flag & SI_FULLWINDOW) && !sa->full) { - sima->flag &= ~SI_FULLWINDOW; - } - - /* test if we have a temp screen in front */ - if (WM_window_is_temp_screen(win)) { - wm_window_lower(win); - return OPERATOR_FINISHED; - } - /* determine if render already shows */ - else if (sima->flag & SI_PREVSPACE) { - sima->flag &= ~SI_PREVSPACE; - - if (sima->flag & SI_FULLWINDOW) { - sima->flag &= ~SI_FULLWINDOW; - ED_screen_full_prevspace(C, sa); - } - else { - ED_area_prevspace(C, sa); - } - - return OPERATOR_FINISHED; - } - else if (sima->flag & SI_FULLWINDOW) { - sima->flag &= ~SI_FULLWINDOW; - ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED); - return OPERATOR_FINISHED; - } - - return OPERATOR_PASS_THROUGH; + wmWindow *win = CTX_wm_window(C); + ScrArea *sa = CTX_wm_area(C); + SpaceImage *sima = sa->spacedata.first; + + /* ensure image editor fullscreen and area fullscreen states are in sync */ + if ((sima->flag & SI_FULLWINDOW) && !sa->full) { + sima->flag &= ~SI_FULLWINDOW; + } + + /* test if we have a temp screen in front */ + if (WM_window_is_temp_screen(win)) { + wm_window_lower(win); + return OPERATOR_FINISHED; + } + /* determine if render already shows */ + else if (sima->flag & SI_PREVSPACE) { + sima->flag &= ~SI_PREVSPACE; + + if (sima->flag & SI_FULLWINDOW) { + sima->flag &= ~SI_FULLWINDOW; + ED_screen_full_prevspace(C, sa); + } + else { + ED_area_prevspace(C, sa); + } + + return OPERATOR_FINISHED; + } + else if (sima->flag & SI_FULLWINDOW) { + sima->flag &= ~SI_FULLWINDOW; + ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED); + return OPERATOR_FINISHED; + } + + return OPERATOR_PASS_THROUGH; } void RENDER_OT_view_cancel(struct wmOperatorType *ot) { - /* identifiers */ - ot->name = "Cancel Render View"; - ot->description = "Cancel show render view"; - ot->idname = "RENDER_OT_view_cancel"; - - /* api callbacks */ - ot->exec = render_view_cancel_exec; - ot->poll = ED_operator_image_active; + /* identifiers */ + ot->name = "Cancel Render View"; + ot->description = "Cancel show render view"; + ot->idname = "RENDER_OT_view_cancel"; + + /* api callbacks */ + ot->exec = render_view_cancel_exec; + ot->poll = ED_operator_image_active; } /************************* show render viewer *****************/ static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - wmWindow *wincur = CTX_wm_window(C); - - /* test if we have currently a temp screen active */ - if (WM_window_is_temp_screen(wincur)) { - wm_window_lower(wincur); - } - else { - wmWindow *win, *winshow; - ScrArea *sa = find_area_showing_r_result(C, CTX_data_scene(C), &winshow); - - /* is there another window on current scene showing result? */ - for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) { - const bScreen *sc = WM_window_get_active_screen(win); - - if ((WM_window_is_temp_screen(win) && ((ScrArea *)sc->areabase.first)->spacetype == SPACE_IMAGE) || - (win == winshow && winshow != wincur)) - { - wm_window_raise(win); - return OPERATOR_FINISHED; - } - } - - /* determine if render already shows */ - if (sa) { - /* but don't close it when rendering */ - if (G.is_rendering == false) { - SpaceImage *sima = sa->spacedata.first; - - if (sima->flag & SI_PREVSPACE) { - sima->flag &= ~SI_PREVSPACE; - - if (sima->flag & SI_FULLWINDOW) { - sima->flag &= ~SI_FULLWINDOW; - ED_screen_full_prevspace(C, sa); - } - else { - ED_area_prevspace(C, sa); - } - } - } - } - else { - render_view_open(C, event->x, event->y, op->reports); - } - } - - return OPERATOR_FINISHED; + wmWindow *wincur = CTX_wm_window(C); + + /* test if we have currently a temp screen active */ + if (WM_window_is_temp_screen(wincur)) { + wm_window_lower(wincur); + } + else { + wmWindow *win, *winshow; + ScrArea *sa = find_area_showing_r_result(C, CTX_data_scene(C), &winshow); + + /* is there another window on current scene showing result? */ + for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) { + const bScreen *sc = WM_window_get_active_screen(win); + + if ((WM_window_is_temp_screen(win) && + ((ScrArea *)sc->areabase.first)->spacetype == SPACE_IMAGE) || + (win == winshow && winshow != wincur)) { + wm_window_raise(win); + return OPERATOR_FINISHED; + } + } + + /* determine if render already shows */ + if (sa) { + /* but don't close it when rendering */ + if (G.is_rendering == false) { + SpaceImage *sima = sa->spacedata.first; + + if (sima->flag & SI_PREVSPACE) { + sima->flag &= ~SI_PREVSPACE; + + if (sima->flag & SI_FULLWINDOW) { + sima->flag &= ~SI_FULLWINDOW; + ED_screen_full_prevspace(C, sa); + } + else { + ED_area_prevspace(C, sa); + } + } + } + } + else { + render_view_open(C, event->x, event->y, op->reports); + } + } + + return OPERATOR_FINISHED; } void RENDER_OT_view_show(struct wmOperatorType *ot) { - /* identifiers */ - ot->name = "Show/Hide Render View"; - ot->description = "Toggle show render view"; - ot->idname = "RENDER_OT_view_show"; - - /* api callbacks */ - ot->invoke = render_view_show_invoke; - ot->poll = ED_operator_screenactive; + /* identifiers */ + ot->name = "Show/Hide Render View"; + ot->description = "Toggle show render view"; + ot->idname = "RENDER_OT_view_show"; + + /* api callbacks */ + ot->invoke = render_view_show_invoke; + ot->poll = ED_operator_screenactive; } |