From 17b63db4e2721f5cf8389c3354460771d8348c50 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 13 Nov 2019 14:00:03 +0100 Subject: EEVEE: Renderlayer artifacts When rendering the Subsurface scattering lighting render layer with high sample count render artifacts can appear. This patch will remove these render artifacts by using a more precise texture format when samples will be larger than 128. As with the new eevee-shadows it is more common to use higher number of samples. The reason why it was visible in the subsurface scattering is that every sample could change the color. Adding different values will reduce precision over the number of samples. The subsurface color render layer also has this issue, but it is not noticeable as the colors tend to be close to each other so the colors would most of the time just shift the precision and hold up better. Reviewed By: fclem Differential Revision: https://developer.blender.org/D6245 --- source/blender/draw/engines/eevee/eevee_occlusion.c | 6 ++++-- source/blender/draw/engines/eevee/eevee_private.h | 8 ++++++-- source/blender/draw/engines/eevee/eevee_render.c | 20 ++++++++++---------- source/blender/draw/engines/eevee/eevee_subsurface.c | 10 +++++++--- 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index 48e9b5bcc13..0a7d1db1061 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -131,7 +131,7 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) return 0; } -void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples) { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; @@ -143,11 +143,13 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) { + const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_R32F : GPU_R16F; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; /* Should be enough precision for many samples. */ - DRW_texture_ensure_fullscreen_2d(&txl->ao_accum, GPU_R32F, 0); + DRW_texture_ensure_fullscreen_2d(&txl->ao_accum, texture_format, 0); GPU_framebuffer_ensure_config(&fbl->ao_accum_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->ao_accum)}); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 7d02aacfac7..41e38fd8437 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -988,7 +988,9 @@ void EEVEE_bloom_free(void); /* eevee_occlusion.c */ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); -void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint tot_samples); void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_occlusion_compute(EEVEE_ViewLayerData *sldata, @@ -1009,7 +1011,9 @@ void EEVEE_screen_raytrace_free(void); void EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); -void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint tot_samples); void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint sss_id, diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 75e837f140b..ee1dc8a0208 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -517,9 +517,17 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl GPU_framebuffer_bind(fbl->main_fb); DRW_hair_update(); + uint tot_sample = scene_eval->eevee.taa_render_samples; + uint render_samples = 0; + + /* SSR needs one iteration to start properly. */ + if (stl->effects->enabled_effects & EFFECT_SSR) { + tot_sample += 1; + } + if ((view_layer->passflag & (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT | SCE_PASS_SUBSURFACE_INDIRECT)) != 0) { - EEVEE_subsurface_output_init(sldata, vedata); + EEVEE_subsurface_output_init(sldata, vedata, tot_sample); } if ((view_layer->passflag & SCE_PASS_MIST) != 0) { @@ -527,21 +535,13 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl } if ((view_layer->passflag & SCE_PASS_AO) != 0) { - EEVEE_occlusion_output_init(sldata, vedata); + EEVEE_occlusion_output_init(sldata, vedata, tot_sample); } - uint tot_sample = scene_eval->eevee.taa_render_samples; - uint render_samples = 0; - if (RE_engine_test_break(engine)) { return; } - /* SSR needs one iteration to start properly. */ - if (stl->effects->enabled_effects & EFFECT_SSR) { - tot_sample += 1; - } - while (render_samples < tot_sample && !RE_engine_test_break(engine)) { float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; float clear_depth = 1.0f; diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index 8376b8c67b8..a7c28347c15 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -156,7 +156,9 @@ static void set_shgrp_stencil(void *UNUSED(userData), DRWShadingGroup *shgrp) DRW_shgroup_stencil_mask(shgrp, 255); } -void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), + EEVEE_Data *vedata, + uint tot_samples) { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; @@ -164,8 +166,10 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat EEVEE_EffectsInfo *effects = stl->effects; if (effects->enabled_effects & EFFECT_SSS) { - DRW_texture_ensure_fullscreen_2d(&txl->sss_dir_accum, GPU_RGBA16F, 0); - DRW_texture_ensure_fullscreen_2d(&txl->sss_col_accum, GPU_RGBA16F, 0); + const eGPUTextureFormat texture_format_light = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F; + const eGPUTextureFormat texture_format_color = (tot_samples > 512) ? GPU_RGBA32F : GPU_RGBA16F; + DRW_texture_ensure_fullscreen_2d(&txl->sss_dir_accum, texture_format_light, 0); + DRW_texture_ensure_fullscreen_2d(&txl->sss_col_accum, texture_format_color, 0); GPUTexture *stencil_tex = effects->sss_stencil; -- cgit v1.2.3 From 9d7f65630b206385c03d997aa308dbe36c60298f Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Thu, 7 Nov 2019 13:14:15 +0100 Subject: EEVEE: GLSL Renderpasses Most of the renderpasses in EEVEE used post-processing on the CPU. For final image rendering this is sufficient, but when we want to display the data to the user we don't want to transfer to the CPU to do post processing to then upload it back to the GPU to display the result. This patch moves the renderpass postprocessing to a GLSL shader. This is the first step to do, before we will enable the renderpasses in the viewport. Reviewed By: fclem Differential Revision: https://developer.blender.org/D6206 --- source/blender/draw/CMakeLists.txt | 2 + source/blender/draw/engines/eevee/eevee_engine.c | 1 + source/blender/draw/engines/eevee/eevee_private.h | 18 ++ source/blender/draw/engines/eevee/eevee_render.c | 253 +++++---------------- .../draw/engines/eevee/eevee_renderpasses.c | 190 ++++++++++++++++ .../eevee/shaders/renderpass_postprocess_frag.glsl | 63 +++++ 6 files changed, 335 insertions(+), 192 deletions(-) create mode 100644 source/blender/draw/engines/eevee/eevee_renderpasses.c create mode 100644 source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 950adf3ddc5..dc5508340de 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -102,6 +102,7 @@ set(SRC engines/eevee/eevee_motion_blur.c engines/eevee/eevee_occlusion.c engines/eevee/eevee_render.c + engines/eevee/eevee_renderpasses.c engines/eevee/eevee_sampling.c engines/eevee/eevee_screen_raytrace.c engines/eevee/eevee_shaders.c @@ -221,6 +222,7 @@ data_to_c_simple(engines/eevee/shaders/irradiance_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/octahedron_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/bsdf_sampling_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/raytrace_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/renderpass_postprocess_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/ltc_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/ssr_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/update_noise_frag.glsl SRC) diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index a1096390bce..173b7ff57a1 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -483,6 +483,7 @@ static void eevee_engine_free(void) EEVEE_screen_raytrace_free(); EEVEE_subsurface_free(); EEVEE_volumes_free(); + EEVEE_renderpasses_free(); } static const DrawEngineDataSize eevee_data_size = DRW_VIEWPORT_DATA_SIZE(EEVEE_Data); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 41e38fd8437..b49328d90ab 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -271,6 +271,7 @@ typedef struct EEVEE_PassList { struct DRWPass *update_noise_pass; struct DRWPass *lookdev_glossy_pass; struct DRWPass *lookdev_diffuse_pass; + struct DRWPass *renderpass_pass; } EEVEE_PassList; typedef struct EEVEE_FramebufferList { @@ -295,6 +296,7 @@ typedef struct EEVEE_FramebufferList { struct GPUFrameBuffer *screen_tracing_fb; struct GPUFrameBuffer *refract_fb; struct GPUFrameBuffer *mist_accum_fb; + struct GPUFrameBuffer *renderpass_fb; struct GPUFrameBuffer *ao_accum_fb; struct GPUFrameBuffer *velocity_resolve_fb; @@ -341,6 +343,8 @@ typedef struct EEVEE_TextureList { struct GPUTexture *maxzbuffer; + struct GPUTexture *renderpass; + struct GPUTexture *color; /* R16_G16_B16 */ struct GPUTexture *color_double_buffer; struct GPUTexture *depth_double_buffer; @@ -799,6 +803,10 @@ typedef struct EEVEE_PrivateData { float studiolight_glossy_clamp; float studiolight_filter_quality; + /* Renderpasses */ + /* Bitmask containing the active render_passes */ + eScenePassType render_passes; + /** For rendering shadows. */ struct DRWView *cube_views[6]; /** For rendering probes. */ @@ -1039,6 +1047,16 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_mist_free(void); +/* eevee_renderpasses.c */ +void EEVEE_renderpasses_init(EEVEE_Data *vedata); +void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint tot_samples); +void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + eScenePassType renderpass_type); +void EEVEE_renderpasses_free(void); + /* eevee_temporal_sampling.c */ void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata); int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index ee1dc8a0208..9a7d170c9ea 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -130,7 +130,9 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * DRW_view_default_set(view); DRW_view_set_active(view); - /* EEVEE_effects_init needs to go first for TAA */ + /* `EEVEE_renderpasses_init` will set the active render passes used by `EEVEE_effects_init`. + * `EEVEE_effects_init` needs to go second for TAA. */ + EEVEE_renderpasses_init(vedata); EEVEE_effects_init(sldata, vedata, ob_camera_eval, false); EEVEE_materials_init(sldata, stl, fbl); EEVEE_shadows_init(sldata); @@ -202,79 +204,60 @@ void EEVEE_render_cache(void *vedata, } } -static void eevee_render_result_combined(RenderLayer *rl, - const char *viewname, - const rcti *rect, - EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata)) +static void eevee_render_color_result(RenderLayer *rl, + const char *viewname, + const rcti *rect, + const char *render_pass_name, + int num_channels, + GPUFrameBuffer *framebuffer, + EEVEE_Data *vedata) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname); - - GPU_framebuffer_bind(vedata->stl->effects->final_fb); - GPU_framebuffer_read_color(vedata->stl->effects->final_fb, + RenderPass *rp = RE_pass_find_by_name(rl, render_pass_name, viewname); + GPU_framebuffer_bind(framebuffer); + GPU_framebuffer_read_color(framebuffer, vedata->stl->g_data->overscan_pixels + rect->xmin, vedata->stl->g_data->overscan_pixels + rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), - 4, + num_channels, 0, rp->rect); } +static void eevee_render_result_combined(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *UNUSED(sldata)) +{ + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_COMBINED, 4, vedata->stl->effects->final_fb, vedata); +} + static void eevee_render_result_subsurface(RenderLayer *rl, const char *viewname, const rcti *rect, EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata), - int render_samples) + EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - if (vedata->fbl->sss_accum_fb == NULL) { /* SSS is not enabled. */ return; } - if ((view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_SUBSURFACE_COLOR, viewname); - - GPU_framebuffer_bind(vedata->fbl->sss_accum_fb); - GPU_framebuffer_read_color(vedata->fbl->sss_accum_fb, - vedata->stl->g_data->overscan_pixels + rect->xmin, - vedata->stl->g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 3, - 1, - rp->rect); - - /* This is the accumulated color. Divide by the number of samples. */ - for (int i = 0; i < rp->rectx * rp->recty * 3; i++) { - rp->rect[i] /= (float)render_samples; - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_SUBSURFACE_COLOR) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_SUBSURFACE_COLOR); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_SUBSURFACE_COLOR, 3, vedata->fbl->renderpass_fb, vedata); } - if ((view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_SUBSURFACE_DIRECT, viewname); - - GPU_framebuffer_bind(vedata->fbl->sss_accum_fb); - GPU_framebuffer_read_color(vedata->fbl->sss_accum_fb, - vedata->stl->g_data->overscan_pixels + rect->xmin, - vedata->stl->g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 3, - 0, - rp->rect); - - /* This is the accumulated color. Divide by the number of samples. */ - for (int i = 0; i < rp->rectx * rp->recty * 3; i++) { - rp->rect[i] /= (float)render_samples; - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_SUBSURFACE_DIRECT) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_SUBSURFACE_DIRECT); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_SUBSURFACE_DIRECT, 3, vedata->fbl->renderpass_fb, vedata); } - if ((view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT) != 0) { + if ((vedata->stl->g_data->render_passes & SCE_PASS_SUBSURFACE_INDIRECT) != 0) { /* Do nothing as all the lighting is in the direct pass. * TODO : Separate Direct from indirect lighting. */ } @@ -284,54 +267,19 @@ static void eevee_render_result_normal(RenderLayer *rl, const char *viewname, const rcti *rect, EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata)) + EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - EEVEE_StorageList *stl = vedata->stl; - EEVEE_PrivateData *g_data = stl->g_data; + const int current_sample = vedata->stl->effects->taa_current_sample; /* Only read the center texel. */ - if (stl->effects->taa_current_sample > 1) { + if (current_sample > 1) { return; } - if ((view_layer->passflag & SCE_PASS_NORMAL) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_NORMAL, viewname); - - GPU_framebuffer_bind(vedata->fbl->main_fb); - GPU_framebuffer_read_color(vedata->fbl->main_fb, - g_data->overscan_pixels + rect->xmin, - g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 3, - 1, - rp->rect); - - float viewinv[4][4]; - DRW_view_viewmat_get(NULL, viewinv, true); - - /* Convert Eevee encoded normals to Blender normals. */ - for (int i = 0; i < rp->rectx * rp->recty * 3; i += 3) { - if (rp->rect[i] == 0.0f && rp->rect[i + 1] == 0.0f) { - /* If normal is not correct then do not produce NANs. */ - continue; - } - - float fenc[2]; - fenc[0] = rp->rect[i + 0] * 4.0f - 2.0f; - fenc[1] = rp->rect[i + 1] * 4.0f - 2.0f; - - float f = dot_v2v2(fenc, fenc); - float g = sqrtf(1.0f - f / 4.0f); - - rp->rect[i + 0] = fenc[0] * g; - rp->rect[i + 1] = fenc[1] * g; - rp->rect[i + 2] = 1.0f - f / 2.0f; - - mul_mat3_m4_v3(viewinv, &rp->rect[i]); - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_NORMAL) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_NORMAL); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_NORMAL, 3, vedata->fbl->renderpass_fb, vedata); } } @@ -341,49 +289,17 @@ static void eevee_render_result_z(RenderLayer *rl, EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; - EEVEE_StorageList *stl = vedata->stl; - EEVEE_PrivateData *g_data = stl->g_data; + const int current_sample = vedata->stl->effects->taa_current_sample; /* Only read the center texel. */ - if (stl->effects->taa_current_sample > 1) { + if (current_sample > 1) { return; } - if ((view_layer->passflag & SCE_PASS_Z) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname); - - GPU_framebuffer_bind(vedata->fbl->main_fb); - GPU_framebuffer_read_depth(vedata->fbl->main_fb, - g_data->overscan_pixels + rect->xmin, - g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - rp->rect); - - bool is_persp = DRW_view_is_persp_get(NULL); - - float winmat[4][4]; - DRW_view_winmat_get(NULL, winmat, false); - - /* Convert ogl depth [0..1] to view Z [near..far] */ - for (int i = 0; i < rp->rectx * rp->recty; i++) { - if (rp->rect[i] == 1.0f) { - rp->rect[i] = 1e10f; /* Background */ - } - else { - if (is_persp) { - rp->rect[i] = rp->rect[i] * 2.0f - 1.0f; - rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]); - } - else { - rp->rect[i] = -common_data->view_vecs[0][2] + - rp->rect[i] * -common_data->view_vecs[1][2]; - } - } - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_Z) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_Z); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_Z, 1, vedata->fbl->renderpass_fb, vedata); } } @@ -391,29 +307,12 @@ static void eevee_render_result_mist(RenderLayer *rl, const char *viewname, const rcti *rect, EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata), - int render_samples) + EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - - if ((view_layer->passflag & SCE_PASS_MIST) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_MIST, viewname); - - GPU_framebuffer_bind(vedata->fbl->mist_accum_fb); - GPU_framebuffer_read_color(vedata->fbl->mist_accum_fb, - vedata->stl->g_data->overscan_pixels + rect->xmin, - vedata->stl->g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 1, - 0, - rp->rect); - - /* This is the accumulated color. Divide by the number of samples. */ - for (int i = 0; i < rp->rectx * rp->recty; i++) { - rp->rect[i] /= (float)render_samples; - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_MIST) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_MIST); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_MIST, 1, vedata->fbl->renderpass_fb, vedata); } } @@ -421,35 +320,17 @@ static void eevee_render_result_occlusion(RenderLayer *rl, const char *viewname, const rcti *rect, EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata), - int render_samples) + EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - if (vedata->fbl->ao_accum_fb == NULL) { /* AO is not enabled. */ return; } - if ((view_layer->passflag & SCE_PASS_AO) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_AO, viewname); - - GPU_framebuffer_bind(vedata->fbl->ao_accum_fb); - GPU_framebuffer_read_color(vedata->fbl->ao_accum_fb, - vedata->stl->g_data->overscan_pixels + rect->xmin, - vedata->stl->g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 3, - 0, - rp->rect); - - /* This is the accumulated color. Divide by the number of samples. */ - for (int i = 0; i < rp->rectx * rp->recty * 3; i += 3) { - rp->rect[i] = rp->rect[i + 1] = rp->rect[i + 2] = min_ff( - 1.0f, rp->rect[i] / (float)render_samples); - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_AO) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_AO); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_AO, 3, vedata->fbl->renderpass_fb, vedata); } } @@ -488,7 +369,6 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl { const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - ViewLayer *view_layer = draw_ctx->view_layer; const char *viewname = RE_GetActiveRenderView(engine->re); EEVEE_PassList *psl = vedata->psl; EEVEE_StorageList *stl = vedata->stl; @@ -525,18 +405,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl tot_sample += 1; } - if ((view_layer->passflag & (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT | - SCE_PASS_SUBSURFACE_INDIRECT)) != 0) { - EEVEE_subsurface_output_init(sldata, vedata, tot_sample); - } - - if ((view_layer->passflag & SCE_PASS_MIST) != 0) { - EEVEE_mist_output_init(sldata, vedata); - } - - if ((view_layer->passflag & SCE_PASS_AO) != 0) { - EEVEE_occlusion_output_init(sldata, vedata, tot_sample); - } + EEVEE_renderpasses_output_init(sldata, vedata, tot_sample); if (RE_engine_test_break(engine)) { return; @@ -644,9 +513,9 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl } eevee_render_result_combined(rl, viewname, rect, vedata, sldata); - eevee_render_result_subsurface(rl, viewname, rect, vedata, sldata, render_samples); - eevee_render_result_mist(rl, viewname, rect, vedata, sldata, render_samples); - eevee_render_result_occlusion(rl, viewname, rect, vedata, sldata, render_samples); + eevee_render_result_subsurface(rl, viewname, rect, vedata, sldata); + eevee_render_result_mist(rl, viewname, rect, vedata, sldata); + eevee_render_result_occlusion(rl, viewname, rect, vedata, sldata); /* Restore original viewport size. */ DRW_render_viewport_size_set((int[2]){g_data->size_orig[0], g_data->size_orig[1]}); diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c new file mode 100644 index 00000000000..17f1f8c96d6 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -0,0 +1,190 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2019, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "BLI_string_utils.h" + +#include "eevee_private.h" + +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_renderpass_postprocess_frag_glsl[]; + +static struct { + struct GPUShader *postprocess_sh; +} e_data = {NULL}; /* Engine data */ + +/* bitmask containing all renderpasses that need post-processing */ +#define EEVEE_RENDERPASSES_WITH_POST_PROCESSING \ + (SCE_PASS_Z | SCE_PASS_MIST | SCE_PASS_NORMAL | SCE_PASS_AO | SCE_PASS_SUBSURFACE_COLOR | \ + SCE_PASS_SUBSURFACE_DIRECT) + +#define EEVEE_RENDERPASSES_SUBSURFACE \ + (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT | SCE_PASS_SUBSURFACE_INDIRECT) + +#define EEVEE_RENDERPASSES_ALL (EEVEE_RENDERPASSES_WITH_POST_PROCESSING | SCE_PASS_COMBINED) + +void EEVEE_renderpasses_init(EEVEE_Data *vedata) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + ViewLayer *view_layer = draw_ctx->view_layer; + + g_data->render_passes = (view_layer->passflag & EEVEE_RENDERPASSES_ALL) | SCE_PASS_COMBINED; +} + +void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint tot_samples) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + + const bool needs_post_processing = (g_data->render_passes & + EEVEE_RENDERPASSES_WITH_POST_PROCESSING) > 0; + if (needs_post_processing) { + if (e_data.postprocess_sh == NULL) { + char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_renderpass_postprocess_frag_glsl); + e_data.postprocess_sh = DRW_shader_create_fullscreen(frag_str, NULL); + MEM_freeN(frag_str); + } + + /* Create FrameBuffer. */ + + /* Should be enough to store the data needs for a single pass. + * Some passes will use less, but it is only relevant for final renderings and + * when renderpasses other than `SCE_PASS_COMBINED` are requested */ + DRW_texture_ensure_fullscreen_2d(&txl->renderpass, GPU_RGBA16F, 0); + GPU_framebuffer_ensure_config(&fbl->renderpass_fb, + {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->renderpass)}); + + if ((g_data->render_passes & EEVEE_RENDERPASSES_SUBSURFACE) != 0) { + EEVEE_subsurface_output_init(sldata, vedata, tot_samples); + } + + if ((g_data->render_passes & SCE_PASS_MIST) != 0) { + EEVEE_mist_output_init(sldata, vedata); + } + + if ((g_data->render_passes & SCE_PASS_AO) != 0) { + EEVEE_occlusion_output_init(sldata, vedata, tot_samples); + } + + /* Create Pass. */ + DRW_PASS_CREATE(psl->renderpass_pass, DRW_STATE_WRITE_COLOR); + } + else { + /* Free unneeded memory */ + DRW_TEXTURE_FREE_SAFE(txl->renderpass); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->renderpass_fb); + psl->renderpass_pass = NULL; + } +} + +/* Postprocess data to construct a specific renderpass + * + * This method will create a shading group to perform the post-processing for the given + * `renderpass_type`. The post-processing will be done and the result will be stored in the + * `vedata->txl->renderpass` texture. + * + * Only invoke this function for passes that need post-processing. + * + * After invoking this function the active framebuffer is set to `vedata->fbl->renderpass_fb`. */ +void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + eScenePassType renderpass_type) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_EffectsInfo *effects = stl->effects; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + const int current_sample = effects->taa_current_sample; + + DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.postprocess_sh, psl->renderpass_pass); + DRW_shgroup_uniform_int_copy(shgrp, "renderpassType", renderpass_type); + + switch (renderpass_type) { + case SCE_PASS_Z: { + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_texture_ref(shgrp, "depthBuffer", &dtxl->depth); + break; + } + + case SCE_PASS_AO: { + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &txl->ao_accum); + DRW_shgroup_uniform_int_copy(shgrp, "currentSample", current_sample); + break; + } + + case SCE_PASS_NORMAL: { + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &effects->ssr_normal_input); + break; + } + + case SCE_PASS_MIST: { + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &txl->mist_accum); + DRW_shgroup_uniform_int_copy(shgrp, "currentSample", current_sample); + break; + } + + case SCE_PASS_SUBSURFACE_DIRECT: { + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &txl->sss_dir_accum); + DRW_shgroup_uniform_int_copy(shgrp, "currentSample", current_sample); + break; + } + + case SCE_PASS_SUBSURFACE_COLOR: { + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &txl->sss_col_accum); + DRW_shgroup_uniform_int_copy(shgrp, "currentSample", current_sample); + break; + } + + default: { + break; + } + } + + DRW_shgroup_call(shgrp, DRW_cache_fullscreen_quad_get(), NULL); + + /* only draw the shading group that has been added. This function can be called multiple times + * and the pass still hold the previous shading groups.*/ + GPU_framebuffer_bind(fbl->renderpass_fb); + DRW_draw_pass_subset(psl->renderpass_pass, shgrp, shgrp); +} + +void EEVEE_renderpasses_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.postprocess_sh); +} diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl new file mode 100644 index 00000000000..8a543f13fbc --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl @@ -0,0 +1,63 @@ +#define SCE_PASS_Z (1 << 1) +#define SCE_PASS_AO (1 << 6) +#define SCE_PASS_NORMAL (1 << 8) +#define SCE_PASS_MIST (1 << 14) +#define SCE_PASS_SUBSURFACE_DIRECT (1 << 28) +#define SCE_PASS_SUBSURFACE_COLOR (1 << 30) + +#define ACCUMULATED_COLOR_PASSES (SCE_PASS_SUBSURFACE_DIRECT | SCE_PASS_SUBSURFACE_COLOR) +#define ACCUMULATED_VALUE_PASSES (SCE_PASS_MIST) +uniform int renderpassType; +uniform int currentSample; +uniform sampler2D inputBuffer; + +out vec4 fragColor; + +void main() +{ + ivec2 texel = ivec2(gl_FragCoord.xy); + + if (renderpassType == SCE_PASS_Z) { + float depth = texelFetch(depthBuffer, texel, 0).r; + if (depth == 1.0f) { + depth = 1e10; + } + else { + depth = -get_view_z_from_depth(depth); + } + fragColor.r = depth; + } + + else if (renderpassType == SCE_PASS_AO) { + float ao_accum = texelFetch(inputBuffer, texel, 0).r; + fragColor = vec4(vec3(min(1.0, ao_accum / currentSample)), 1.0); + } + + else if (renderpassType == SCE_PASS_NORMAL) { + vec2 encoded_normal = texelFetch(inputBuffer, texel, 0).rg; + /* decode the normals only when they are valid. otherwise the result buffer will be filled with + * NaN's */ + if (any(notEqual(encoded_normal, vec2(0.0)))) { + vec3 decoded_normal = normal_decode(texelFetch(inputBuffer, texel, 0).rg, vec3(0.0)); + vec3 world_normal = mat3(ViewMatrixInverse) * decoded_normal; + fragColor = vec4(world_normal, 0.0); + } + else { + fragColor = vec4(0.0); + } + } + + else if ((renderpassType & ACCUMULATED_VALUE_PASSES) != 0) { + float accumulated_value = texelFetch(inputBuffer, texel, 0).r; + fragColor.r = accumulated_value / currentSample; + } + + else if ((renderpassType & ACCUMULATED_COLOR_PASSES) != 0) { + vec3 accumulated_color = texelFetch(inputBuffer, texel, 0).rgb; + fragColor.rgb = accumulated_color / currentSample; + } + + else { + fragColor = vec4(1.0, 0.0, 1.0, 1.0); + } +} \ No newline at end of file -- cgit v1.2.3 From 7959dcd4f6316ade726209f2452323406f3672ea Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 5 Nov 2019 16:55:51 +0100 Subject: RenderViewport: Texture Format When doing viewport rendering the color management happens on the CPU. This has overhead in downloading a float texture from the gpu and performing color management on the CPU. Based on the scene fileformat bit depth the result will be rendered to a byte texture where the colormanagement happens on the GPU or a float texture where the colormanagement happens on the CPU. This is only done during `Viewport Render Animation` in other cases a float texture is being used. Baseline (HD render of wanderer.blend workbench engine no samples) 15.688038 s After changes: 9.412880s Reviewed By: fclem Differential Revision: https://developer.blender.org/D6195 --- source/blender/editors/render/render_opengl.c | 14 ++++++++++---- source/blender/makesdna/DNA_scene_types.h | 24 +++++++++++++++++------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index f419d30a17e..0d0e183e480 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -18,7 +18,7 @@ */ /** \file - * \ingroup edrend + * \ingroup render */ #include @@ -77,7 +77,7 @@ #include "render_intern.h" /* Define this to get timing information. */ -// #undef DEBUG_TIME +// #define DEBUG_TIME #ifdef DEBUG_TIME # include "PIL_time.h" @@ -138,6 +138,8 @@ typedef struct OGLRender { TaskPool *task_pool; bool pool_ok; bool is_animation; + + eImageFormatDepth color_depth; SpinLock reports_lock; unsigned int num_scheduled_frames; ThreadMutex task_mutex; @@ -356,6 +358,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R char err_out[256] = "unknown"; ImBuf *ibuf_view; const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL; + int output_flags = oglrender->color_depth <= R_IMF_CHAN_DEPTH_8 ? IB_rect : IB_rectfloat; if (view_context) { ibuf_view = ED_view3d_draw_offscreen_imbuf(depsgraph, @@ -365,7 +368,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R ar, sizex, sizey, - IB_rectfloat, + output_flags, alpha_mode, oglrender->ofs_samples, viewname, @@ -385,7 +388,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R scene->camera, oglrender->sizex, oglrender->sizey, - IB_rectfloat, + output_flags, V3D_OFSDRAW_SHOW_ANNOTATION, alpha_mode, oglrender->ofs_samples, @@ -528,6 +531,8 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) 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"); + const eImageFormatDepth color_depth = (is_animation) ? scene->r.im_format.depth : + R_IMF_CHAN_DEPTH_32; const int samples = U.ogl_multisamples; char err_out[256] = "unknown"; @@ -600,6 +605,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) oglrender->write_still = is_write_still && !is_animation; oglrender->is_animation = is_animation; + oglrender->color_depth = color_depth; oglrender->views_len = BKE_scene_multiview_num_views_get(&scene->r); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 0de43c1632f..ce0c7319ce5 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -483,13 +483,23 @@ typedef struct ImageFormatData { #define R_IMF_FLAG_PREVIEW_JPG (1 << 1) /* was R_PREVIEW_JPG */ /* return values from BKE_imtype_valid_depths, note this is depts per channel */ -#define R_IMF_CHAN_DEPTH_1 (1 << 0) /* 1bits (unused) */ -#define R_IMF_CHAN_DEPTH_8 (1 << 1) /* 8bits (default) */ -#define R_IMF_CHAN_DEPTH_10 (1 << 2) /* 10bits (uncommon, Cineon/DPX support) */ -#define R_IMF_CHAN_DEPTH_12 (1 << 3) /* 12bits (uncommon, jp2/DPX support) */ -#define R_IMF_CHAN_DEPTH_16 (1 << 4) /* 16bits (tiff, halff float exr) */ -#define R_IMF_CHAN_DEPTH_24 (1 << 5) /* 24bits (unused) */ -#define R_IMF_CHAN_DEPTH_32 (1 << 6) /* 32bits (full float exr) */ +/* ImageFormatData.depth */ +typedef enum eImageFormatDepth { + /* 1bits (unused) */ + R_IMF_CHAN_DEPTH_1 = (1 << 0), + /* 8bits (default) */ + R_IMF_CHAN_DEPTH_8 = (1 << 1), + /* 10bits (uncommon, Cineon/DPX support) */ + R_IMF_CHAN_DEPTH_10 = (1 << 2), + /* 12bits (uncommon, jp2/DPX support) */ + R_IMF_CHAN_DEPTH_12 = (1 << 3), + /* 16bits (tiff, half float exr) */ + R_IMF_CHAN_DEPTH_16 = (1 << 4), + /* 24bits (unused) */ + R_IMF_CHAN_DEPTH_24 = (1 << 5), + /* 32bits (full float exr) */ + R_IMF_CHAN_DEPTH_32 = (1 << 6), +} eImageFormatDepth; /* ImageFormatData.planes */ #define R_IMF_PLANES_RGB 24 -- cgit v1.2.3 From 6992fc0b3bf85e985169157b2e7ced1e1ed7fcdf Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Wed, 27 Nov 2019 15:02:41 +0100 Subject: Add 'EDBM_selectmode_disable_multi' and use in knifeproject As a followup to rB6f4e595e9ba9 and as per @campbellbarton suggestion, this adds EDBM_selectmode_disable_multi, similar to EDBM_mesh_deselect_all_multi & EDBM_mesh_deselect_all, so other similar uses don't need to be done in a loop. Also, selected_objects isn't a reliable way to handle this case - since objects can be in edit-mode & not selected, use BKE_view_layer_array_from_bases_in_edit_mode_unique_data instead Differential Revision: https://developer.blender.org/D6317 --- source/blender/editors/include/ED_mesh.h | 8 +++++ .../blender/editors/mesh/editmesh_knife_project.c | 17 +---------- source/blender/editors/mesh/editmesh_select.c | 35 ++++++++++++++++++++++ 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index fc7b0d8be8f..835e1b4e26f 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -236,6 +236,14 @@ void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); /* rename bool EDBM_mesh_deselect_all_multi_ex(struct Base **bases, const uint bases_len); bool EDBM_mesh_deselect_all_multi(struct bContext *C); +bool EDBM_selectmode_disable_multi_ex(struct Scene *scene, + struct Base **bases, + const uint bases_len, + const short selectmode_disable, + const short selectmode_fallback); +bool EDBM_selectmode_disable_multi(struct bContext *C, + const short selectmode_disable, + const short selectmode_fallback); /* editmesh_preselect_edgering.c */ struct EditMesh_PreSelEdgeRing; diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index a709bd010aa..ebd1e62e596 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -22,7 +22,6 @@ */ #include "DNA_curve_types.h" -#include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "BLI_math.h" @@ -143,21 +142,7 @@ static int knifeproject_exec(bContext *C, wmOperator *op) /* select only tagged faces */ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); - CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { - if (ob->type == OB_MESH) { - Mesh *me = (Mesh *)ob->data; - BMEditMesh *embm = me->edit_mesh; - if (embm) { - /* not essential, but switch out of vertex mode since the - * selected regions wont be nicely isolated after flushing. - * note: call after de-select to avoid selection flushing. - * note: do this on all participating meshes so this is in sync - * e.g. for later selection picking, see T68852.*/ - EDBM_selectmode_disable(scene, embm, SCE_SELECT_VERTEX, SCE_SELECT_EDGE); - } - } - } - CTX_DATA_END; + EDBM_selectmode_disable_multi(C, SCE_SELECT_VERTEX, SCE_SELECT_EDGE); BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 7955ccc0977..40d57af97aa 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2653,6 +2653,41 @@ bool EDBM_mesh_deselect_all_multi(struct bContext *C) return changed_multi; } +bool EDBM_selectmode_disable_multi_ex(Scene *scene, + struct Base **bases, + const uint bases_len, + const short selectmode_disable, + const short selectmode_fallback) +{ + bool changed_multi = false; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Base *base_iter = bases[base_index]; + Object *ob_iter = base_iter->object; + BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter); + + EDBM_selectmode_disable(scene, em_iter, selectmode_disable, selectmode_fallback); + changed_multi = true; + } + return changed_multi; +} + +bool EDBM_selectmode_disable_multi(struct bContext *C, + const short selectmode_disable, + const short selectmode_fallback) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = CTX_data_scene(C); + ViewContext vc; + ED_view3d_viewcontext_init(C, &vc, depsgraph); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( + vc.view_layer, NULL, &bases_len); + bool changed_multi = EDBM_selectmode_disable_multi_ex( + scene, bases, bases_len, selectmode_disable, selectmode_fallback); + MEM_freeN(bases); + return changed_multi; +} + /** \} */ /* -------------------------------------------------------------------- */ -- cgit v1.2.3 From 2e6159a4948cd0f4e0b636734bfe506796bd87f2 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 1 Nov 2019 12:09:55 +0100 Subject: Curve: CurveMapping Extend Option Extend options are currently stored per curve. This was not clearly communicated to the user and they expected this to be a setting per CurveMapping. This change will move the option from `Curve` to `CurveMapping`. In order to support this the API had to be changed. BPY: CurveMap.evaluate is also moved to CurveMapping.evaluate what breaks Python API. Cycles has been updated but other add-ons have not. After release of 2.81 we can merge this to master and adapt the add-ons. Reviewed By: campbellbarton Differential Revision: https://developer.blender.org/D6169 --- intern/cycles/blender/blender_util.h | 11 +- .../opencolorio/gpu_shader_display_transform.glsl | 10 +- intern/opencolorio/ocio_capi.h | 6 +- intern/opencolorio/ocio_impl_glsl.cc | 4 +- source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenkernel/BKE_colortools.h | 4 +- source/blender/blenkernel/intern/brush.c | 15 +- source/blender/blenkernel/intern/colortools.c | 68 +++--- source/blender/blenkernel/intern/paint.c | 16 +- source/blender/blenkernel/intern/texture.c | 2 +- source/blender/blenloader/intern/versioning_280.c | 256 ++++++++++++++++++++- source/blender/editors/interface/interface_draw.c | 4 +- .../editors/interface/interface_templates.c | 4 +- source/blender/editors/render/render_internal.c | 2 +- .../freestyle/intern/python/BPy_Freestyle.cpp | 4 +- source/blender/imbuf/intern/colormanagement.c | 11 +- source/blender/makesdna/DNA_color_types.h | 23 +- source/blender/makesrna/intern/rna_color.c | 99 ++++---- .../nodes/shader/nodes/node_shader_curves.c | 2 +- 19 files changed, 405 insertions(+), 138 deletions(-) diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 3625dd45ae2..cbe61e367fa 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -159,7 +159,7 @@ static inline void curvemapping_to_array(BL::CurveMapping &cumap, array & data.resize(size); for (int i = 0; i < size; i++) { float t = (float)i / (float)(size - 1); - data[i] = curve.evaluate(t); + data[i] = cumap.evaluate(curve, t); } } @@ -197,15 +197,16 @@ static inline void curvemapping_color_to_array(BL::CurveMapping &cumap, BL::CurveMap mapI = cumap.curves[3]; for (int i = 0; i < size; i++) { const float t = min_x + (float)i / (float)(size - 1) * range_x; - data[i] = make_float3(mapR.evaluate(mapI.evaluate(t)), - mapG.evaluate(mapI.evaluate(t)), - mapB.evaluate(mapI.evaluate(t))); + data[i] = make_float3(cumap.evaluate(mapR, cumap.evaluate(mapI, t)), + cumap.evaluate(mapG, cumap.evaluate(mapI, t)), + cumap.evaluate(mapB, cumap.evaluate(mapI, t))); } } else { for (int i = 0; i < size; i++) { float t = min_x + (float)i / (float)(size - 1) * range_x; - data[i] = make_float3(mapR.evaluate(t), mapG.evaluate(t), mapB.evaluate(t)); + data[i] = make_float3( + cumap.evaluate(mapR, t), cumap.evaluate(mapG, t), cumap.evaluate(mapB, t)); } } } diff --git a/intern/opencolorio/gpu_shader_display_transform.glsl b/intern/opencolorio/gpu_shader_display_transform.glsl index 04e96e8ed3c..9787398e2ae 100644 --- a/intern/opencolorio/gpu_shader_display_transform.glsl +++ b/intern/opencolorio/gpu_shader_display_transform.glsl @@ -16,7 +16,7 @@ out vec4 fragColor; */ uniform sampler1D curve_mapping_texture; uniform int curve_mapping_lut_size; -uniform ivec4 use_curve_mapping_extend_extrapolate; +uniform int use_curve_mapping_extend_extrapolate; uniform vec4 curve_mapping_mintable; uniform vec4 curve_mapping_range; uniform vec4 curve_mapping_ext_in_x; @@ -42,8 +42,8 @@ float read_curve_mapping(int table, int index) float curvemap_calc_extend(int table, float x, vec2 first, vec2 last) { if (x <= first[0]) { - if (use_curve_mapping_extend_extrapolate[table] == 0) { - /* no extrapolate */ + if (use_curve_mapping_extend_extrapolate == 0) { + /* horizontal extrapolation */ return first[1]; } else { @@ -55,8 +55,8 @@ float curvemap_calc_extend(int table, float x, vec2 first, vec2 last) } } else if (x >= last[0]) { - if (use_curve_mapping_extend_extrapolate[table] == 0) { - /* no extrapolate */ + if (use_curve_mapping_extend_extrapolate == 0) { + /* horizontal extrapolation */ return last[1]; } else { diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 9ba2d8fb8f9..5670b37f892 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -73,10 +73,10 @@ typedef struct OCIO_CurveMappingSettings { int lut_size; /* Extend extrapolation flags for all the tables. - * if use_extend_extrapolate[T] != 0 means extrapolation for - * table T is needed. + * if use_extend_extrapolate != 0 means extrapolation for + * curve. */ - int use_extend_extrapolate[4]; + int use_extend_extrapolate; /* Minimal X value of the curve mapping tables. */ float mintable[4]; diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc index 99d59c8d989..a80e29a2dec 100644 --- a/intern/opencolorio/ocio_impl_glsl.cc +++ b/intern/opencolorio/ocio_impl_glsl.cc @@ -499,8 +499,8 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, if (use_curve_mapping) { immUniform1i("curve_mapping_texture", 2); immUniform1i("curve_mapping_lut_size", curve_mapping_settings->lut_size); - immUniform4iv("use_curve_mapping_extend_extrapolate", - curve_mapping_settings->use_extend_extrapolate); + immUniform1i("use_curve_mapping_extend_extrapolate", + curve_mapping_settings->use_extend_extrapolate); immUniform4fv("curve_mapping_mintable", curve_mapping_settings->mintable); immUniform4fv("curve_mapping_range", curve_mapping_settings->range); immUniform4fv("curve_mapping_ext_in_x", curve_mapping_settings->ext_in_x); diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index dd1fff9ce47..c38e6e14d70 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ * \note Use #STRINGIFY() rather than defining with quotes. */ #define BLENDER_VERSION 282 -#define BLENDER_SUBVERSION 1 +#define BLENDER_SUBVERSION 2 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index 643073b3470..e4ea1dad086 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -68,7 +68,9 @@ void BKE_curvemapping_initialize(struct CurveMapping *cumap); /* keep these (const CurveMap) - to help with thread safety */ /* single curve, no table check */ -float BKE_curvemap_evaluateF(const struct CurveMap *cuma, float value); +float BKE_curvemap_evaluateF(const struct CurveMapping *cumap, + const struct CurveMap *cuma, + float value); /* single curve, with table check */ float BKE_curvemapping_evaluateF(const struct CurveMapping *cumap, int cur, float value); void BKE_curvemapping_evaluate3F(const struct CurveMapping *cumap, diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 4d496fe758b..27c3df5ce6e 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -1069,18 +1069,19 @@ void BKE_brush_sculpt_reset(Brush *br) */ void BKE_brush_curve_preset(Brush *b, eCurveMappingPreset preset) { - CurveMap *cm = NULL; + CurveMapping *cumap = NULL; + CurveMap *cuma = NULL; if (!b->curve) { b->curve = BKE_curvemapping_add(1, 0, 0, 1, 1); } + cumap = b->curve; + cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + cumap->preset = preset; - cm = b->curve->cm; - cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; - - b->curve->preset = preset; - BKE_curvemap_reset(cm, &b->curve->clipr, b->curve->preset, CURVEMAP_SLOPE_NEGATIVE); - BKE_curvemapping_changed(b->curve, false); + cuma = b->curve->cm; + BKE_curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_NEGATIVE); + BKE_curvemapping_changed(cumap, false); } /* Generic texture sampler for 3D painting systems. point has to be either in diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 8166bbea962..2ec04ee2747 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -54,7 +54,7 @@ void BKE_curvemapping_set_defaults( int a; float clipminx, clipminy, clipmaxx, clipmaxy; - cumap->flag = CUMA_DO_CLIP; + cumap->flag = CUMA_DO_CLIP | CUMA_EXTEND_EXTRAPOLATE; if (tot == 4) { cumap->cur = 3; /* rhms, hack for 'col' curve? */ } @@ -71,7 +71,6 @@ void BKE_curvemapping_set_defaults( cumap->bwmul[0] = cumap->bwmul[1] = cumap->bwmul[2] = 1.0f; for (a = 0; a < tot; a++) { - cumap->cm[a].flag = CUMA_EXTEND_EXTRAPOLATE; cumap->cm[a].totpoint = 2; cumap->cm[a].curve = MEM_callocN(2 * sizeof(CurveMapPoint), "curve points"); @@ -591,14 +590,15 @@ static void calchandle_curvemap(BezTriple *bezt, const BezTriple *prev, const Be /* in X, out Y. * X is presumed to be outside first or last */ -static float curvemap_calc_extend(const CurveMap *cuma, +static float curvemap_calc_extend(const CurveMapping *cumap, + const CurveMap *cuma, float x, const float first[2], const float last[2]) { if (x <= first[0]) { - if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { - /* no extrapolate */ + if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { + /* extrapolate horizontally */ return first[1]; } else { @@ -611,8 +611,8 @@ static float curvemap_calc_extend(const CurveMap *cuma, } } else if (x >= last[0]) { - if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { - /* no extrapolate */ + if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { + /* extrapolate horizontally */ return last[1]; } else { @@ -628,8 +628,9 @@ static float curvemap_calc_extend(const CurveMap *cuma, } /* only creates a table for a single channel in CurveMapping */ -static void curvemap_make_table(CurveMap *cuma, const rctf *clipr) +static void curvemap_make_table(const CurveMapping *cumap, CurveMap *cuma) { + const rctf *clipr = &cumap->clipr; CurveMapPoint *cmp = cuma->curve; BezTriple *bezt; @@ -782,7 +783,7 @@ static void curvemap_make_table(CurveMap *cuma, const rctf *clipr) } else { /* Extrapolate values that lie outside the start and end point. */ - cmp[a].y = curvemap_calc_extend(cuma, cur_x, firstpoint, lastpoint); + cmp[a].y = curvemap_calc_extend(cumap, cuma, cur_x, firstpoint, lastpoint); } } else { @@ -829,7 +830,7 @@ void BKE_curvemapping_premultiply(CurveMapping *cumap, int restore) /* verify and copy */ for (a = 0; a < 3; a++) { if (cumap->cm[a].table == NULL) { - curvemap_make_table(cumap->cm + a, &cumap->clipr); + curvemap_make_table(cumap, cumap->cm + a); } cumap->cm[a].premultable = cumap->cm[a].table; cumap->cm[a].table = MEM_mallocN((CM_TABLE + 1) * sizeof(CurveMapPoint), "premul table"); @@ -838,14 +839,15 @@ void BKE_curvemapping_premultiply(CurveMapping *cumap, int restore) } if (cumap->cm[3].table == NULL) { - curvemap_make_table(cumap->cm + 3, &cumap->clipr); + curvemap_make_table(cumap, cumap->cm + 3); } /* premul */ for (a = 0; a < 3; a++) { int b; for (b = 0; b <= CM_TABLE; b++) { - cumap->cm[a].table[b].y = BKE_curvemap_evaluateF(cumap->cm + 3, cumap->cm[a].table[b].y); + cumap->cm[a].table[b].y = BKE_curvemap_evaluateF( + cumap, cumap->cm + 3, cumap->cm[a].table[b].y); } copy_v2_v2(cumap->cm[a].premul_ext_in, cumap->cm[a].ext_in); @@ -949,7 +951,7 @@ void BKE_curvemapping_changed(CurveMapping *cumap, const bool rem_doubles) BKE_curvemap_remove(cuma, 2); } } - curvemap_make_table(cuma, clipr); + curvemap_make_table(cumap, cuma); } void BKE_curvemapping_changed_all(CurveMapping *cumap) @@ -967,7 +969,7 @@ void BKE_curvemapping_changed_all(CurveMapping *cumap) } /* table should be verified */ -float BKE_curvemap_evaluateF(const CurveMap *cuma, float value) +float BKE_curvemap_evaluateF(const CurveMapping *cumap, const CurveMap *cuma, float value) { float fi; int i; @@ -978,7 +980,7 @@ float BKE_curvemap_evaluateF(const CurveMap *cuma, float value) /* fi is table float index and should check against table range i.e. [0.0 CM_TABLE] */ if (fi < 0.0f || fi > CM_TABLE) { - return curvemap_calc_extend(cuma, value, &cuma->table[0].x, &cuma->table[CM_TABLE].x); + return curvemap_calc_extend(cumap, cuma, value, &cuma->table[0].x, &cuma->table[CM_TABLE].x); } else { if (i < 0) { @@ -997,7 +999,7 @@ float BKE_curvemap_evaluateF(const CurveMap *cuma, float value) float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value) { const CurveMap *cuma = cumap->cm + cur; - float val = BKE_curvemap_evaluateF(cuma, value); + float val = BKE_curvemap_evaluateF(cumap, cuma, value); /* account for clipping */ if (cumap->flag & CUMA_DO_CLIP) { @@ -1015,9 +1017,9 @@ float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value /* vector case */ void BKE_curvemapping_evaluate3F(const CurveMapping *cumap, float vecout[3], const float vecin[3]) { - vecout[0] = BKE_curvemap_evaluateF(&cumap->cm[0], vecin[0]); - vecout[1] = BKE_curvemap_evaluateF(&cumap->cm[1], vecin[1]); - vecout[2] = BKE_curvemap_evaluateF(&cumap->cm[2], vecin[2]); + vecout[0] = BKE_curvemap_evaluateF(cumap, &cumap->cm[0], vecin[0]); + vecout[1] = BKE_curvemap_evaluateF(cumap, &cumap->cm[1], vecin[1]); + vecout[2] = BKE_curvemap_evaluateF(cumap, &cumap->cm[2], vecin[2]); } /* RGB case, no black/white points, no premult */ @@ -1025,12 +1027,12 @@ void BKE_curvemapping_evaluateRGBF(const CurveMapping *cumap, float vecout[3], const float vecin[3]) { - vecout[0] = BKE_curvemap_evaluateF(&cumap->cm[0], - BKE_curvemap_evaluateF(&cumap->cm[3], vecin[0])); - vecout[1] = BKE_curvemap_evaluateF(&cumap->cm[1], - BKE_curvemap_evaluateF(&cumap->cm[3], vecin[1])); - vecout[2] = BKE_curvemap_evaluateF(&cumap->cm[2], - BKE_curvemap_evaluateF(&cumap->cm[3], vecin[2])); + vecout[0] = BKE_curvemap_evaluateF( + cumap, &cumap->cm[0], BKE_curvemap_evaluateF(cumap, &cumap->cm[3], vecin[0])); + vecout[1] = BKE_curvemap_evaluateF( + cumap, &cumap->cm[1], BKE_curvemap_evaluateF(cumap, &cumap->cm[3], vecin[1])); + vecout[2] = BKE_curvemap_evaluateF( + cumap, &cumap->cm[2], BKE_curvemap_evaluateF(cumap, &cumap->cm[3], vecin[2])); } static void curvemapping_evaluateRGBF_filmlike(const CurveMapping *cumap, @@ -1042,8 +1044,8 @@ static void curvemapping_evaluateRGBF_filmlike(const CurveMapping *cumap, const float v1in = vecin[channel_offset[1]]; const float v2in = vecin[channel_offset[2]]; - const float v0 = BKE_curvemap_evaluateF(&cumap->cm[channel_offset[0]], v0in); - const float v2 = BKE_curvemap_evaluateF(&cumap->cm[channel_offset[2]], v2in); + const float v0 = BKE_curvemap_evaluateF(cumap, &cumap->cm[channel_offset[0]], v0in); + const float v2 = BKE_curvemap_evaluateF(cumap, &cumap->cm[channel_offset[2]], v2in); const float v1 = v2 + ((v0 - v2) * (v1in - v2in) / (v0in - v2in)); vecout[channel_offset[0]] = v0; @@ -1074,9 +1076,9 @@ void BKE_curvemapping_evaluate_premulRGBF_ex(const CurveMapping *cumap, switch (cumap->tone) { default: case CURVE_TONE_STANDARD: { - vecout[0] = BKE_curvemap_evaluateF(&cumap->cm[0], r); - vecout[1] = BKE_curvemap_evaluateF(&cumap->cm[1], g); - vecout[2] = BKE_curvemap_evaluateF(&cumap->cm[2], b); + vecout[0] = BKE_curvemap_evaluateF(cumap, &cumap->cm[0], r); + vecout[1] = BKE_curvemap_evaluateF(cumap, &cumap->cm[1], g); + vecout[2] = BKE_curvemap_evaluateF(cumap, &cumap->cm[2], b); break; } case CURVE_TONE_FILMLIKE: { @@ -1099,8 +1101,8 @@ void BKE_curvemapping_evaluate_premulRGBF_ex(const CurveMapping *cumap, else { /* Case 4: r >= g == b */ copy_v2_fl2(vecout, - BKE_curvemap_evaluateF(&cumap->cm[0], r), - BKE_curvemap_evaluateF(&cumap->cm[1], g)); + BKE_curvemap_evaluateF(cumap, &cumap->cm[0], r), + BKE_curvemap_evaluateF(cumap, &cumap->cm[1], g)); vecout[2] = vecout[1]; } } @@ -1208,7 +1210,7 @@ void BKE_curvemapping_initialize(CurveMapping *cumap) for (a = 0; a < CM_TOT; a++) { if (cumap->cm[a].table == NULL) { - curvemap_make_table(cumap->cm + a, &cumap->clipr); + curvemap_make_table(cumap, cumap->cm + a); } } } diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 46ef24be5e9..e7c20ca4fb2 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -655,19 +655,19 @@ bool BKE_paint_select_elem_test(Object *ob) void BKE_paint_cavity_curve_preset(Paint *p, int preset) { - CurveMap *cm = NULL; + CurveMapping *cumap = NULL; + CurveMap *cuma = NULL; if (!p->cavity_curve) { p->cavity_curve = BKE_curvemapping_add(1, 0, 0, 1, 1); } + cumap = p->cavity_curve; + cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + cumap->preset = preset; - cm = p->cavity_curve->cm; - cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; - - p->cavity_curve->preset = preset; - BKE_curvemap_reset( - cm, &p->cavity_curve->clipr, p->cavity_curve->preset, CURVEMAP_SLOPE_POSITIVE); - BKE_curvemapping_changed(p->cavity_curve, false); + cuma = cumap->cm; + BKE_curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE); + BKE_curvemapping_changed(cumap, false); } eObjectMode BKE_paint_object_mode_from_paintmode(ePaintMode mode) diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index f4e89160487..b1ae71c609f 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -558,7 +558,7 @@ void BKE_texture_pointdensity_init_data(PointDensity *pd) pd->falloff_curve = BKE_curvemapping_add(1, 0, 0, 1, 1); pd->falloff_curve->preset = CURVE_PRESET_LINE; - pd->falloff_curve->cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + pd->falloff_curve->flag &= ~CUMA_EXTEND_EXTRAPOLATE; BKE_curvemap_reset(pd->falloff_curve->cm, &pd->falloff_curve->clipr, pd->falloff_curve->preset, diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 0cb68cfd7fe..0b7ec8cf225 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -37,10 +37,14 @@ #include "DNA_collection_types.h" #include "DNA_constraint_types.h" #include "DNA_curveprofile_types.h" +#include "DNA_freestyle_types.h" #include "DNA_gpu_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_gpencil_modifier_types.h" #include "DNA_light_types.h" #include "DNA_layer_types.h" #include "DNA_lightprobe_types.h" +#include "DNA_linestyle_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" @@ -50,12 +54,12 @@ #include "DNA_screen_types.h" #include "DNA_view3d_types.h" #include "DNA_genfile.h" -#include "DNA_gpencil_types.h" #include "DNA_workspace_types.h" #include "DNA_key_types.h" #include "DNA_curve_types.h" #include "DNA_armature_types.h" #include "DNA_text_types.h" +#include "DNA_texture_types.h" #include "DNA_world_types.h" #include "BKE_animsys.h" @@ -861,6 +865,232 @@ static void do_versions_local_collection_bits_set(LayerCollection *layer_collect } } +static void do_version_curvemapping_flag_extend_extrapolate(CurveMapping *cumap) +{ +#define CUMA_EXTEND_EXTRAPOLATE_OLD 1 + for (int curve_map_index = 0; curve_map_index < 4; curve_map_index++) { + CurveMap *cuma = &cumap->cm[curve_map_index]; + if (cuma->flag & CUMA_EXTEND_EXTRAPOLATE_OLD) { + cumap->flag |= CUMA_EXTEND_EXTRAPOLATE; + return; + } + } +#undef CUMA_EXTEND_EXTRAPOLATE_OLD +} + +/* Util version to walk over all CurveMappings in the given `bmain` */ +static void do_version_curvemapping_walker(Main *bmain, void (*callback)(CurveMapping *cumap)) +{ + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + callback(&scene->r.mblur_shutter_curve); + + if (scene->view_settings.curve_mapping) { + callback(scene->view_settings.curve_mapping); + } + + if (scene->ed != NULL) { + LISTBASE_FOREACH (Sequence *, seq, &scene->ed->seqbase) { + LISTBASE_FOREACH (SequenceModifierData *, smd, &seq->modifiers) { + const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + + if (smti) { + if (smd->type == seqModifierType_Curves) { + CurvesModifierData *cmd = (CurvesModifierData *)smd; + callback(&cmd->curve_mapping); + } + else if (smd->type == seqModifierType_HueCorrect) { + HueCorrectModifierData *hcmd = (HueCorrectModifierData *)smd; + callback(&hcmd->curve_mapping); + } + } + } + } + } + + // toolsettings + ToolSettings *ts = scene->toolsettings; + if (ts->vpaint) { + callback(ts->vpaint->paint.cavity_curve); + } + if (ts->wpaint) { + callback(ts->wpaint->paint.cavity_curve); + } + if (ts->sculpt) { + callback(ts->sculpt->paint.cavity_curve); + } + if (ts->uvsculpt) { + callback(ts->uvsculpt->paint.cavity_curve); + } + if (ts->gp_paint) { + callback(ts->gp_paint->paint.cavity_curve); + } + if (ts->gp_interpolate.custom_ipo) { + callback(ts->gp_interpolate.custom_ipo); + } + if (ts->gp_sculpt.cur_falloff) { + callback(ts->gp_sculpt.cur_falloff); + } + if (ts->gp_sculpt.cur_primitive) { + callback(ts->gp_sculpt.cur_primitive); + } + callback(ts->imapaint.paint.cavity_curve); + } + + FOREACH_NODETREE_BEGIN (bmain, node_tree, id) { + LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) { + if (ELEM(node->type, + SH_NODE_CURVE_VEC, + SH_NODE_CURVE_RGB, + CMP_NODE_CURVE_VEC, + CMP_NODE_CURVE_RGB, + CMP_NODE_TIME, + CMP_NODE_HUECORRECT, + TEX_NODE_CURVE_RGB, + TEX_NODE_CURVE_TIME)) { + callback((CurveMapping *)node->storage); + } + } + } + FOREACH_NODETREE_END; + + LISTBASE_FOREACH (Light *, light, &bmain->lights) { + if (light->curfalloff) { + callback(light->curfalloff); + } + } + + LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { + if (brush->curve) { + callback(brush->curve); + } + if (brush->gpencil_settings) { + if (brush->gpencil_settings->curve_sensitivity) { + callback(brush->gpencil_settings->curve_sensitivity); + } + if (brush->gpencil_settings->curve_strength) { + callback(brush->gpencil_settings->curve_strength); + } + if (brush->gpencil_settings->curve_jitter) { + callback(brush->gpencil_settings->curve_jitter); + } + } + } + + LISTBASE_FOREACH (ParticleSettings *, part, &bmain->particles) { + if (part->clumpcurve) { + callback(part->clumpcurve); + } + if (part->roughcurve) { + callback(part->roughcurve); + } + if (part->twistcurve) { + callback(part->twistcurve); + } + } + + /* Object */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + /* Object modifiers */ + LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { + if (md->type == eModifierType_Hook) { + HookModifierData *hmd = (HookModifierData *)md; + + if (hmd->curfalloff) { + callback(hmd->curfalloff); + } + } + else if (md->type == eModifierType_Warp) { + WarpModifierData *tmd = (WarpModifierData *)md; + if (tmd->curfalloff) { + callback(tmd->curfalloff); + } + } + else if (md->type == eModifierType_WeightVGEdit) { + WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; + + if (wmd->cmap_curve) { + callback(wmd->cmap_curve); + } + } + } + /* Grease pencil modifiers */ + LISTBASE_FOREACH (ModifierData *, md, &ob->greasepencil_modifiers) { + if (md->type == eGpencilModifierType_Thick) { + ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md; + + if (gpmd->curve_thickness) { + callback(gpmd->curve_thickness); + } + } + else if (md->type == eGpencilModifierType_Hook) { + HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md; + + if (gpmd->curfalloff) { + callback(gpmd->curfalloff); + } + } + } + } + + /* Free Style */ + LISTBASE_FOREACH (struct FreestyleLineStyle *, linestyle, &bmain->linestyles) { + LISTBASE_FOREACH (LineStyleModifier *, m, &linestyle->thickness_modifiers) { + switch (m->type) { + case LS_MODIFIER_ALONG_STROKE: + callback(((LineStyleAlphaModifier_AlongStroke *)m)->curve); + break; + case LS_MODIFIER_DISTANCE_FROM_CAMERA: + callback(((LineStyleAlphaModifier_DistanceFromCamera *)m)->curve); + break; + case LS_MODIFIER_DISTANCE_FROM_OBJECT: + callback(((LineStyleAlphaModifier_DistanceFromObject *)m)->curve); + break; + case LS_MODIFIER_MATERIAL: + callback(((LineStyleAlphaModifier_Material *)m)->curve); + break; + case LS_MODIFIER_TANGENT: + callback(((LineStyleAlphaModifier_Tangent *)m)->curve); + break; + case LS_MODIFIER_NOISE: + callback(((LineStyleAlphaModifier_Noise *)m)->curve); + break; + case LS_MODIFIER_CREASE_ANGLE: + callback(((LineStyleAlphaModifier_CreaseAngle *)m)->curve); + break; + case LS_MODIFIER_CURVATURE_3D: + callback(((LineStyleAlphaModifier_Curvature_3D *)m)->curve); + break; + } + } + + LISTBASE_FOREACH (LineStyleModifier *, m, &linestyle->thickness_modifiers) { + switch (m->type) { + case LS_MODIFIER_ALONG_STROKE: + callback(((LineStyleThicknessModifier_AlongStroke *)m)->curve); + break; + case LS_MODIFIER_DISTANCE_FROM_CAMERA: + callback(((LineStyleThicknessModifier_DistanceFromCamera *)m)->curve); + break; + case LS_MODIFIER_DISTANCE_FROM_OBJECT: + callback(((LineStyleThicknessModifier_DistanceFromObject *)m)->curve); + break; + case LS_MODIFIER_MATERIAL: + callback(((LineStyleThicknessModifier_Material *)m)->curve); + break; + case LS_MODIFIER_TANGENT: + callback(((LineStyleThicknessModifier_Tangent *)m)->curve); + break; + case LS_MODIFIER_CREASE_ANGLE: + callback(((LineStyleThicknessModifier_CreaseAngle *)m)->curve); + break; + case LS_MODIFIER_CURVATURE_3D: + callback(((LineStyleThicknessModifier_Curvature_3D *)m)->curve); + break; + } + } + } +} + void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) { bool use_collection_compat_28 = true; @@ -910,11 +1140,10 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) } } - /* We need to assign lib pointer to generated hidden collections *after* all have been created, - * otherwise we'll end up with several data-blocks sharing same name/library, - * which is FORBIDDEN! - * Note: we need this to be recursive, - * since a child collection may be sorted before its parent in bmain. */ + /* We need to assign lib pointer to generated hidden collections *after* all have been + * created, otherwise we'll end up with several data-blocks sharing same name/library, + * which is FORBIDDEN! Note: we need this to be recursive, since a child collection may be + * sorted before its parent in bmain. */ for (Collection *collection = bmain->collections.first; collection != NULL; collection = collection->id.next) { do_version_collection_propagate_lib_to_children(collection); @@ -1218,7 +1447,8 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) } if (!MAIN_VERSION_ATLEAST(bmain, 280, 38)) { - /* Ensure we get valid rigidbody object/constraint data in relevant collections' objects. */ + /* Ensure we get valid rigidbody object/constraint data in relevant collections' objects. + */ for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { RigidBodyWorld *rbw = scene->rigidbody_world; @@ -1431,7 +1661,8 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) if (error & NTREE_DOVERSION_NEED_OUTPUT) { BKE_report(fd->reports, RPT_ERROR, "Eevee material conversion problem. Error in console"); printf( - "You need to connect Principled and Eevee Specular shader nodes to new material output " + "You need to connect Principled and Eevee Specular shader nodes to new material " + "output " "nodes.\n"); } @@ -3931,8 +4162,9 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - { - /* Versioning code until next subversion bump goes here. */ + if (!MAIN_VERSION_ATLEAST(bmain, 282, 2)) { + do_version_curvemapping_walker(bmain, do_version_curvemapping_flag_extend_extrapolate); + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { sa->flag &= ~AREA_FLAG_UNUSED_6; @@ -3988,4 +4220,8 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + { + /* Versioning code until next subversion bump goes here. */ + } } diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 499842a570b..31cbd2a3831 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -2019,7 +2019,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, const uiWidgetColors *wcol, cons rctf line_range; /* First curve point. */ - if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { + if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { line_range.xmin = rect->xmin; line_range.ymin = rect->ymin + zoomy * (cmp[0].y - offsy); } @@ -2028,7 +2028,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, const uiWidgetColors *wcol, cons line_range.ymin = rect->ymin + zoomy * (cmp[0].y - offsy + cuma->ext_in[1]); } /* Last curve point. */ - if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { + if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { line_range.xmax = rect->xmax; line_range.ymax = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy); } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 956fd4514af..17247736d3b 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -3992,11 +3992,11 @@ static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event) BKE_curvemapping_changed(cumap, false); break; case UICURVE_FUNC_EXTEND_HOZ: /* extend horiz */ - cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE; BKE_curvemapping_changed(cumap, false); break; case UICURVE_FUNC_EXTEND_EXP: /* extend extrapolate */ - cuma->flag |= CUMA_EXTEND_EXTRAPOLATE; + cumap->flag |= CUMA_EXTEND_EXTRAPOLATE; BKE_curvemapping_changed(cumap, false); break; } diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 7106af25a82..5740dacd05f 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -1173,7 +1173,7 @@ static int render_shutter_curve_preset_exec(bContext *C, wmOperator *op) CurveMap *cm = mblur_shutter_curve->cm; int preset = RNA_enum_get(op->ptr, "shape"); - cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + mblur_shutter_curve->flag &= ~CUMA_EXTEND_EXTRAPOLATE; mblur_shutter_curve->preset = preset; BKE_curvemap_reset( cm, &mblur_shutter_curve->clipr, mblur_shutter_curve->preset, CURVEMAP_SLOPE_POS_NEG); diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp index 367ad556d02..a6512a64776 100644 --- a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp +++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp @@ -266,8 +266,8 @@ static PyObject *Freestyle_evaluateCurveMappingF(PyObject * /*self*/, PyObject * cumap = (CurveMapping *)py_srna->ptr.data; BKE_curvemapping_initialize(cumap); /* disable extrapolation if enabled */ - if ((cumap->cm[cur].flag & CUMA_EXTEND_EXTRAPOLATE)) { - cumap->cm[cur].flag &= ~(CUMA_EXTEND_EXTRAPOLATE); + if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE)) { + cumap->flag &= ~(CUMA_EXTEND_EXTRAPOLATE); BKE_curvemapping_changed(cumap, 0); } return PyFloat_FromDouble(BKE_curvemapping_evaluateF(cumap, cur, value)); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 1b911226c6f..71e9da70c35 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1029,11 +1029,11 @@ void IMB_colormanagement_init_default_view_settings( static void curve_mapping_apply_pixel(CurveMapping *curve_mapping, float *pixel, int channels) { if (channels == 1) { - pixel[0] = BKE_curvemap_evaluateF(curve_mapping->cm, pixel[0]); + pixel[0] = BKE_curvemap_evaluateF(curve_mapping, curve_mapping->cm, pixel[0]); } else if (channels == 2) { - pixel[0] = BKE_curvemap_evaluateF(curve_mapping->cm, pixel[0]); - pixel[1] = BKE_curvemap_evaluateF(curve_mapping->cm, pixel[1]); + pixel[0] = BKE_curvemap_evaluateF(curve_mapping, curve_mapping->cm, pixel[0]); + pixel[1] = BKE_curvemap_evaluateF(curve_mapping, curve_mapping->cm, pixel[1]); } else { BKE_curvemapping_evaluate_premulRGBF(curve_mapping, pixel, pixel); @@ -3904,10 +3904,11 @@ static void curve_mapping_to_ocio_settings(CurveMapping *curve_mapping, BKE_curvemapping_table_RGBA( curve_mapping, &curve_mapping_settings->lut, &curve_mapping_settings->lut_size); + curve_mapping_settings->use_extend_extrapolate = (curve_mapping->flag & + CUMA_EXTEND_EXTRAPOLATE) != 0; + for (i = 0; i < 4; i++) { CurveMap *cuma = curve_mapping->cm + i; - curve_mapping_settings->use_extend_extrapolate[i] = (cuma->flag & CUMA_EXTEND_EXTRAPOLATE) != - 0; curve_mapping_settings->range[i] = cuma->range; curve_mapping_settings->mintable[i] = cuma->mintable; curve_mapping_settings->ext_in_x[i] = cuma->ext_in[0]; diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index 219fc96554a..66adc547cf2 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -24,6 +24,7 @@ #ifndef __DNA_COLOR_TYPES_H__ #define __DNA_COLOR_TYPES_H__ +#include "DNA_defs.h" #include "DNA_vec_types.h" /* general defines for kernel functions */ @@ -47,7 +48,8 @@ enum { }; typedef struct CurveMap { - short totpoint, flag; + short totpoint; + short flag DNA_DEPRECATED; /** Quick multiply value for reading table. */ float range; @@ -67,9 +69,6 @@ typedef struct CurveMap { float premul_ext_out[2]; } CurveMap; -/* cuma->flag */ -#define CUMA_EXTEND_EXTRAPOLATE 1 - typedef struct CurveMapping { /** Cur; for buttons, to show active curve. */ int flag, cur; @@ -93,11 +92,17 @@ typedef struct CurveMapping { char _pad[6]; } CurveMapping; -/* cumapping->flag */ -#define CUMA_DO_CLIP (1 << 0) -#define CUMA_PREMULLED (1 << 1) -#define CUMA_DRAW_CFRA (1 << 2) -#define CUMA_DRAW_SAMPLE (1 << 3) +/* CurveMapping.flag */ +typedef enum eCurveMappingFlags { + CUMA_DO_CLIP = (1 << 0), + CUMA_PREMULLED = (1 << 1), + CUMA_DRAW_CFRA = (1 << 2), + CUMA_DRAW_SAMPLE = (1 << 3), + + /* The curve is extended by extrapolation. When not set the curve is extended + * Horizontally */ + CUMA_EXTEND_EXTRAPOLATE = (1 << 4), +} eCurveMappingFlags; /* cumapping->preset */ typedef enum eCurveMappingPreset { diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 011e373cc61..679ccc9725b 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -123,6 +123,14 @@ static void rna_CurveMapping_tone_update(Main *UNUSED(bmain), WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); } +static void rna_CurveMapping_extend_update(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *UNUSED(ptr)) +{ + WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); + WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); +} + static void rna_CurveMapping_clipminx_range( PointerRNA *ptr, float *min, float *max, float *UNUSED(softmin), float *UNUSED(softmax)) { @@ -670,8 +678,17 @@ static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene) } /* this function only exists because #BKE_curvemap_evaluateF uses a 'const' qualifier */ -static float rna_CurveMap_evaluateF(struct CurveMap *cuma, ReportList *reports, float value) +static float rna_CurveMapping_evaluateF(struct CurveMapping *cumap, + ReportList *reports, + struct CurveMap *cuma, + float value) { + if (&cumap->cm[0] != cuma && &cumap->cm[1] != cuma && &cumap->cm[2] != cuma && + &cumap->cm[3] != cuma) { + BKE_report(reports, RPT_ERROR, "CurveMapping does not own CurveMap"); + return 0.0f; + } + if (!cuma->table) { BKE_report( reports, @@ -679,7 +696,7 @@ static float rna_CurveMap_evaluateF(struct CurveMap *cuma, ReportList *reports, "CurveMap table not initialized, call initialize() on CurveMapping owner of the CurveMap"); return 0.0f; } - return BKE_curvemap_evaluateF(cuma, value); + return BKE_curvemap_evaluateF(cumap, cuma, value); } static void rna_CurveMap_initialize(struct CurveMapping *cumap) @@ -758,58 +775,22 @@ static void rna_def_curvemap_points_api(BlenderRNA *brna, PropertyRNA *cprop) static void rna_def_curvemap(BlenderRNA *brna) { StructRNA *srna; - PropertyRNA *prop, *parm; - FunctionRNA *func; - - static const EnumPropertyItem prop_extend_items[] = { - {0, "HORIZONTAL", 0, "Horizontal", ""}, - {CUMA_EXTEND_EXTRAPOLATE, "EXTRAPOLATED", 0, "Extrapolated", ""}, - {0, NULL, 0, NULL, NULL}, - }; + PropertyRNA *prop; srna = RNA_def_struct(brna, "CurveMap", NULL); RNA_def_struct_ui_text(srna, "CurveMap", "Curve in a curve mapping"); - prop = RNA_def_property(srna, "extend", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); - RNA_def_property_enum_items(prop, prop_extend_items); - RNA_def_property_ui_text(prop, "Extend", "Extrapolate the curve or extend it horizontally"); - prop = RNA_def_property(srna, "points", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "curve", "totpoint"); RNA_def_property_struct_type(prop, "CurveMapPoint"); RNA_def_property_ui_text(prop, "Points", ""); rna_def_curvemap_points_api(brna, prop); - - func = RNA_def_function(srna, "evaluate", "rna_CurveMap_evaluateF"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); - RNA_def_function_ui_description(func, "Evaluate curve at given location"); - parm = RNA_def_float(func, - "position", - 0.0f, - -FLT_MAX, - FLT_MAX, - "Position", - "Position to evaluate curve at", - -FLT_MAX, - FLT_MAX); - RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - parm = RNA_def_float(func, - "value", - 0.0f, - -FLT_MAX, - FLT_MAX, - "Value", - "Value of curve at given location", - -FLT_MAX, - FLT_MAX); - RNA_def_function_return(func, parm); } static void rna_def_curvemapping(BlenderRNA *brna) { StructRNA *srna; - PropertyRNA *prop; + PropertyRNA *prop, *parm; FunctionRNA *func; static const EnumPropertyItem tone_items[] = { @@ -818,6 +799,12 @@ static void rna_def_curvemapping(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem prop_extend_items[] = { + {0, "HORIZONTAL", 0, "Horizontal", ""}, + {CUMA_EXTEND_EXTRAPOLATE, "EXTRAPOLATED", 0, "Extrapolated", ""}, + {0, NULL, 0, NULL, NULL}, + }; + srna = RNA_def_struct(brna, "CurveMapping", NULL); RNA_def_struct_ui_text( srna, @@ -860,6 +847,12 @@ static void rna_def_curvemapping(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Clip Max Y", ""); RNA_def_property_float_funcs(prop, NULL, NULL, "rna_CurveMapping_clipmaxy_range"); + prop = RNA_def_property(srna, "extend", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, prop_extend_items); + RNA_def_property_ui_text(prop, "Extend", "Extrapolate the curve or extend it horizontally"); + RNA_def_property_update(prop, 0, "rna_CurveMapping_extend_update"); + prop = RNA_def_property(srna, "curves", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_funcs(prop, "rna_CurveMapping_curves_begin", @@ -894,6 +887,32 @@ static void rna_def_curvemapping(BlenderRNA *brna) func = RNA_def_function(srna, "initialize", "rna_CurveMap_initialize"); RNA_def_function_ui_description(func, "Initialize curve"); + + func = RNA_def_function(srna, "evaluate", "rna_CurveMapping_evaluateF"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Evaluate curve at given location"); + parm = RNA_def_pointer(func, "curve", "CurveMap", "curve", "Curve to evaluate"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_float(func, + "position", + 0.0f, + -FLT_MAX, + FLT_MAX, + "Position", + "Position to evaluate curve at", + -FLT_MAX, + FLT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_float(func, + "value", + 0.0f, + -FLT_MAX, + FLT_MAX, + "Value", + "Value of curve at given location", + -FLT_MAX, + FLT_MAX); + RNA_def_function_return(func, parm); } static void rna_def_color_ramp_element(BlenderRNA *brna) diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.c b/source/blender/nodes/shader/nodes/node_shader_curves.c index f5c89e6ba41..6292d7b5062 100644 --- a/source/blender/nodes/shader/nodes/node_shader_curves.c +++ b/source/blender/nodes/shader/nodes/node_shader_curves.c @@ -147,7 +147,7 @@ static int gpu_shader_curve_rgb(GPUMaterial *mat, ext_rgba[a][2] = cm->maxtable; range_rgba[a] = 1.0f / max_ff(1e-8f, cm->maxtable - cm->mintable); /* Compute extrapolation gradients. */ - if ((cm->flag & CUMA_EXTEND_EXTRAPOLATE) != 0) { + if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) != 0) { ext_rgba[a][1] = (cm->ext_in[0] != 0.0f) ? (cm->ext_in[1] / (cm->ext_in[0] * range_rgba[a])) : 1e8f; -- cgit v1.2.3 From 83d3a7c12d80d360268f36878e8ffc2832544b3c Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Thu, 17 Oct 2019 15:27:53 +0200 Subject: Workbench: Performance Small performance improvements by caching the world_ubo in the World. It was detected that NVIDIA driver created threads to update the world_ubo (304 bytes). This patch will reuse the previous created ubo when not changed. Reviewed By: fclem Differential Revision: https://developer.blender.org/D6087 --- .../draw/engines/workbench/workbench_data.c | 94 +++++++++++++++++++--- .../draw/engines/workbench/workbench_deferred.c | 2 +- .../draw/engines/workbench/workbench_forward.c | 2 - .../draw/engines/workbench/workbench_private.h | 14 +++- 4 files changed, 95 insertions(+), 17 deletions(-) diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index 3e63f05ca64..42375f29d4d 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -30,6 +30,77 @@ #include "GPU_batch.h" +/* -------------------------------------------------------------------- */ +/** \name World Data + * \{ */ + +static void workbench_world_data_free(DrawData *dd) +{ + WORKBENCH_WorldData *data = (WORKBENCH_WorldData *)dd; + DRW_UBO_FREE_SAFE(data->world_ubo); +} + +/* Ensure the availability of the world_ubo in the given WORKBENCH_PrivateData + * + * See T70167: Some platforms create threads to upload ubo's. + * + * Reuses the last previous created `world_ubo`. Due to limitations of + * DrawData it will only be reused when there is a world attached to the Scene. + * Future development: The best location would be to store it in the View3D. + * + * We don't cache the data itself as there was no indication that that lead to + * an improvement. + * + * This functions also sets the `WORKBENCH_PrivateData.is_world_ubo_owner` that must + * be respected. + */ +static void workbench_world_data_ubo_ensure(const Scene *scene, WORKBENCH_PrivateData *wpd) +{ + World *world = scene->world; + if (world) { + WORKBENCH_WorldData *engine_world_data = (WORKBENCH_WorldData *)DRW_drawdata_ensure( + &world->id, + &draw_engine_workbench_solid, + sizeof(WORKBENCH_WorldData), + NULL, + &workbench_world_data_free); + + if (engine_world_data->world_ubo == NULL) { + engine_world_data->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), + &wpd->world_data); + } + else { + DRW_uniformbuffer_update(engine_world_data->world_ubo, &wpd->world_data); + } + + /* Borrow world data ubo */ + wpd->is_world_ubo_owner = false; + wpd->world_ubo = engine_world_data->world_ubo; + } + else { + /* there is no world so we cannot cache the UBO. */ + BLI_assert(!wpd->world_ubo || wpd->is_world_ubo_owner); + if (!wpd->world_ubo) { + wpd->is_world_ubo_owner = true; + wpd->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), &wpd->world_data); + } + } +} + +static void workbench_world_data_update_shadow_direction_vs(WORKBENCH_PrivateData *wpd) +{ + WORKBENCH_UBO_World *wd = &wpd->world_data; + float light_direction[3]; + float view_matrix[4][4]; + DRW_view_viewmat_get(NULL, view_matrix, false); + + workbench_private_data_get_light_direction(light_direction); + + /* Shadow direction. */ + mul_v3_mat3_m4v3(wd->shadow_direction_vs, view_matrix, light_direction); +} +/* \} */ + void workbench_effect_info_init(WORKBENCH_EffectInfo *effect_info) { effect_info->jitter_index = 0; @@ -139,7 +210,8 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) } } - wpd->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), &wpd->world_data); + workbench_world_data_update_shadow_direction_vs(wpd); + workbench_world_data_ubo_ensure(scene, wpd); /* Cavity settings */ { @@ -203,31 +275,29 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) BLI_listbase_clear(&wpd->smoke_domains); } -void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, - float r_light_direction[3]) +void workbench_private_data_get_light_direction(float r_light_direction[3]) { const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; - WORKBENCH_UBO_World *wd = &wpd->world_data; - float view_matrix[4][4]; - DRW_view_viewmat_get(NULL, view_matrix, false); copy_v3_v3(r_light_direction, scene->display.light_direction); SWAP(float, r_light_direction[2], r_light_direction[1]); r_light_direction[2] = -r_light_direction[2]; r_light_direction[0] = -r_light_direction[0]; - - /* Shadow direction. */ - mul_v3_mat3_m4v3(wd->shadow_direction_vs, view_matrix, r_light_direction); - - DRW_uniformbuffer_update(wpd->world_ubo, wd); } void workbench_private_data_free(WORKBENCH_PrivateData *wpd) { BLI_ghash_free(wpd->material_hash, NULL, MEM_freeN); BLI_ghash_free(wpd->material_transp_hash, NULL, MEM_freeN); - DRW_UBO_FREE_SAFE(wpd->world_ubo); + + if (wpd->is_world_ubo_owner) { + DRW_UBO_FREE_SAFE(wpd->world_ubo); + } + else { + wpd->world_ubo = NULL; + } + DRW_UBO_FREE_SAFE(wpd->dof_ubo); GPU_BATCH_DISCARD_SAFE(wpd->world_clip_planes_batch); } diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 2e8b952f234..f84bd34545c 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -746,7 +746,7 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata) /* Deferred Mix Pass */ { - workbench_private_data_get_light_direction(wpd, e_data.display.light_direction); + workbench_private_data_get_light_direction(e_data.display.light_direction); studiolight_update_light(wpd, e_data.display.light_direction); if (SHADOW_ENABLED(wpd)) { diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index d731b167c06..7a027bf9c86 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -337,8 +337,6 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) } WORKBENCH_PrivateData *wpd = stl->g_data; workbench_private_data_init(wpd); - float light_direction[3]; - workbench_private_data_get_light_direction(wpd, light_direction); if (!e_data.checker_depth_sh) { e_data.checker_depth_sh = DRW_shader_create_fullscreen( diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 595b92d19d0..9fcd9651f94 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -217,6 +217,11 @@ typedef struct WORKBENCH_PrivateData { View3DShading shading; StudioLight *studio_light; const UserDef *preferences; + /* Does this instance owns the `world_ubo` field. + * Normally the field is borrowed from `WORKBENCH_WorldData`. In case that + * there is no World attached to the scene the UBO cannot be cached and should + * be freed after using. */ + bool is_world_ubo_owner; struct GPUUniformBuffer *world_ubo; struct DRWShadingGroup *shadow_shgrp; struct DRWShadingGroup *depth_shgrp; @@ -307,6 +312,12 @@ typedef struct WORKBENCH_ObjectData { bool shadow_bbox_dirty; } WORKBENCH_ObjectData; +typedef struct WORKBENCH_WorldData { + DrawData dd; + /* The cached `GPUUniformBuffer`, that is reused between draw calls. */ + struct GPUUniformBuffer *world_ubo; +} WORKBENCH_WorldData; + /* inline helper functions */ BLI_INLINE bool workbench_is_specular_highlight_enabled(WORKBENCH_PrivateData *wpd) { @@ -526,8 +537,7 @@ bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, void workbench_effect_info_init(WORKBENCH_EffectInfo *effect_info); void workbench_private_data_init(WORKBENCH_PrivateData *wpd); void workbench_private_data_free(WORKBENCH_PrivateData *wpd); -void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, - float r_light_direction[3]); +void workbench_private_data_get_light_direction(float r_light_direction[3]); /* workbench_volume.c */ void workbench_volume_engine_init(void); -- cgit v1.2.3 From 73fa066e8b3ca4e3ff4a34a328a12b575dfc5823 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 20 Sep 2019 12:44:29 +0200 Subject: Cleanup: Remove BIF_gl.h BIF_gl.h included hacks like redefining glew functions and a constant. The named constant `GLA_PIXEL_OFS` has been moved to `GPU_viewport.h` Reviewed By: brecht Differential Revision: https://developer.blender.org/D5860 --- .../draw/engines/workbench/workbench_forward.c | 2 - .../draw/engines/workbench/workbench_materials.c | 2 - source/blender/draw/modes/paint_texture_mode.c | 2 - source/blender/editors/include/BIF_gl.h | 44 ---------------------- .../editors/interface/interface_eyedropper_color.c | 2 +- source/blender/editors/mesh/editface.c | 2 - source/blender/editors/render/render_preview.c | 2 +- source/blender/editors/util/CMakeLists.txt | 1 - source/blender/gpu/GPU_viewport.h | 1 + source/blender/gpu/intern/gpu_viewport.c | 2 - source/blender/makesrna/intern/rna_image_api.c | 4 +- source/blender/windowmanager/intern/wm_dragdrop.c | 3 +- source/blender/windowmanager/intern/wm_draw.c | 2 - source/blender/windowmanager/intern/wm_stereo.c | 3 +- source/blender/windowmanager/intern/wm_subwindow.c | 4 +- 15 files changed, 10 insertions(+), 66 deletions(-) delete mode 100644 source/blender/editors/include/BIF_gl.h diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 7a027bf9c86..80b274e9b76 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -22,8 +22,6 @@ #include "workbench_private.h" -#include "BIF_gl.h" - #include "BLI_alloca.h" #include "BLI_dynstr.h" #include "BLI_string_utils.h" diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 0f9551a8cc9..45d49448490 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -22,8 +22,6 @@ #include "workbench_private.h" -#include "BIF_gl.h" - #include "BKE_image.h" #include "BKE_node.h" diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c index 7c164a74f2f..969dc54ab7d 100644 --- a/source/blender/draw/modes/paint_texture_mode.c +++ b/source/blender/draw/modes/paint_texture_mode.c @@ -23,8 +23,6 @@ #include "DRW_engine.h" #include "DRW_render.h" -#include "BIF_gl.h" - #include "BKE_node.h" #include "BLI_string_utils.h" diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h deleted file mode 100644 index 84820c3c564..00000000000 --- a/source/blender/editors/include/BIF_gl.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * os dependent include locations of gl.h - */ - -/** \file - * \ingroup editorui - */ - -#ifndef __BIF_GL_H__ -#define __BIF_GL_H__ - -#include "GPU_glew.h" -#include "BLI_utildefines.h" - -/* hacking pointsize and linewidth */ -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) -# define glPointSize(f) \ - glPointSize(U.pixelsize *_Generic((f), double : (float)(f), default : (f))) -# define glLineWidth(f) \ - glLineWidth(U.pixelsize *_Generic((f), double : (float)(f), default : (f))) -#else -# define glPointSize(f) glPointSize(U.pixelsize *(f)) -# define glLineWidth(f) glLineWidth(U.pixelsize *(f)) -#endif /* C11 */ - -#define GLA_PIXEL_OFS 0.375f - -#endif /* #ifdef __BIF_GL_H__ */ diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c index 0cf357c508b..2b5cf2ed6b9 100644 --- a/source/blender/editors/interface/interface_eyedropper_color.c +++ b/source/blender/editors/interface/interface_eyedropper_color.c @@ -39,7 +39,7 @@ #include "RNA_access.h" -#include "BIF_gl.h" +#include "GPU_glew.h" #include "UI_interface.h" diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index b7f506a8a41..5c9fb866df7 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -36,8 +36,6 @@ #include "BKE_global.h" #include "BKE_mesh.h" -#include "BIF_gl.h" - #include "ED_mesh.h" #include "ED_screen.h" #include "ED_select_utils.h" diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 6dc3a1ec1ac..1fe299e58a9 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -80,10 +80,10 @@ #include "IMB_imbuf_types.h" #include "IMB_thumbs.h" -#include "BIF_gl.h" #include "BIF_glutil.h" #include "GPU_shader.h" +#include "GPU_glew.h" #include "RE_pipeline.h" #include "RE_engine.h" diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index 0c52dd15092..987327eefc1 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -44,7 +44,6 @@ set(SRC select_utils.c # general includes - ../include/BIF_gl.h ../include/BIF_glutil.h ../include/ED_anim_api.h ../include/ED_armature.h diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index 4bbcb6a4335..e692262358b 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -32,6 +32,7 @@ #include "GPU_texture.h" #define GPU_INFO_SIZE 512 /* IMA_MAX_RENDER_TEXT */ +#define GLA_PIXEL_OFS 0.375f typedef struct GPUViewport GPUViewport; diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 615af57c1bd..519cd918b53 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -29,8 +29,6 @@ #include "BLI_rect.h" #include "BLI_memblock.h" -#include "BIF_gl.h" - #include "DNA_vec_types.h" #include "DNA_userdef_types.h" diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index d167c650683..997a5f5ca45 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -31,8 +31,6 @@ #include "BLI_utildefines.h" #include "BLI_path_util.h" -#include "BIF_gl.h" - #include "RNA_define.h" #include "RNA_enum_types.h" @@ -52,6 +50,8 @@ # include "DNA_image_types.h" # include "DNA_scene_types.h" +# include "GPU_glew.h" + # include "MEM_guardedalloc.h" static void rna_ImagePackedFile_save(ImagePackedFile *imapf, Main *bmain, ReportList *reports) diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index 901594850dd..e2462bb59b1 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -34,14 +34,15 @@ #include "BLI_blenlib.h" -#include "BIF_gl.h" #include "BIF_glutil.h" #include "BKE_context.h" #include "BKE_idcode.h" +#include "GPU_glew.h" #include "GPU_shader.h" #include "GPU_state.h" +#include "GPU_viewport.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 2f538a19ba2..09b7d89fc2b 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -39,8 +39,6 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "BIF_gl.h" - #include "BKE_context.h" #include "BKE_image.h" #include "BKE_main.h" diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 9b62e532132..54953c097eb 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -32,8 +32,6 @@ #include "BLI_utildefines.h" -#include "BIF_gl.h" - #include "BKE_context.h" #include "BKE_global.h" #include "BKE_report.h" @@ -44,6 +42,7 @@ #include "GPU_immediate.h" #include "GPU_texture.h" +#include "GPU_viewport.h" #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c index 2f40947b395..6a5de84ac31 100644 --- a/source/blender/windowmanager/intern/wm_subwindow.c +++ b/source/blender/windowmanager/intern/wm_subwindow.c @@ -29,9 +29,9 @@ #include "DNA_screen_types.h" #include "DNA_windowmanager_types.h" -#include "BIF_gl.h" - +#include "GPU_glew.h" #include "GPU_matrix.h" +#include "GPU_viewport.h" #include "WM_api.h" -- cgit v1.2.3 From 2ea8c81ac35724c57c42638896dfb58215b3ee52 Mon Sep 17 00:00:00 2001 From: Damien Picard Date: Thu, 28 Nov 2019 02:26:08 +1100 Subject: Text Object: change spacing now operates on selection Without this, it's not practical to change spacing on large blocks of text. --- source/blender/editors/curve/editfont.c | 34 ++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 92957c51c08..c9206e8df4a 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -1320,20 +1320,36 @@ static int change_spacing_exec(bContext *C, wmOperator *op) Curve *cu = obedit->data; EditFont *ef = cu->editfont; int kern, delta = RNA_int_get(op->ptr, "delta"); + int selstart, selend; + bool changed = false; - kern = ef->textbufinfo[ef->pos - 1].kern; - kern += delta; - CLAMP(kern, -20, 20); - - if (ef->textbufinfo[ef->pos - 1].kern == kern) { - return OPERATOR_CANCELLED; + const bool has_select = BKE_vfont_select_get(obedit, &selstart, &selend); + if (has_select) { + selstart -= 1; + } + else { + selstart = selend = ef->pos - 1; } + selstart = max_ii(0, selstart); - ef->textbufinfo[ef->pos - 1].kern = kern; + for (int i = selstart; i <= selend; i++) { + kern = ef->textbufinfo[i].kern + delta; + CLAMP(kern, -20, 20); - text_update_edited(C, obedit, FO_EDIT); + if (ef->textbufinfo[i].kern != kern) { + ef->textbufinfo[i].kern = kern; + changed = true; + } + } - return OPERATOR_FINISHED; + if (changed) { + text_update_edited(C, obedit, FO_EDIT); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void FONT_OT_change_spacing(wmOperatorType *ot) -- cgit v1.2.3 From c9e7d8030f55907e759650f75412d5e58cfce9c7 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Wed, 27 Nov 2019 16:53:43 +0100 Subject: Fix typo in versiong code --- source/blender/blenloader/intern/versioning_280.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 0b7ec8cf225..4af589bb29f 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -4204,7 +4204,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } /* Pose brush smooth iterations */ - if (!DNA_struct_elem_find(fd->filesdna, "Brush", "float", "pose_smooth_itereations")) { + if (!DNA_struct_elem_find(fd->filesdna, "Brush", "float", "pose_smooth_iterations")) { for (Brush *br = bmain->brushes.first; br; br = br->id.next) { br->pose_smooth_iterations = 4; } -- cgit v1.2.3 From e85ab2cdc2a6905f4d2eb4a2acdc6db8e20fbeec Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Sun, 24 Nov 2019 21:15:48 +0100 Subject: Fix T71868: Clay Strips brush collapsed geometry We are now modifying the relation between pressure and radius using custom functions to improve the brushes, but dyntopo was not prepared for this. This fix sends the unmodified radius to dyntopo so it modifies the geometry correctly. Reviewed By: jbakker Maniphest Tasks: T71868 Differential Revision: https://developer.blender.org/D6299 --- source/blender/editors/sculpt_paint/sculpt.c | 7 +++++-- source/blender/editors/sculpt_paint/sculpt_intern.h | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 2e98d463945..5e1a36e8873 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -6989,9 +6989,11 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT)) { cache->radius = sculpt_brush_dynamic_size_get(brush, cache, cache->initial_radius); + cache->dyntopo_radius = cache->initial_radius * cache->pressure; } else { cache->radius = cache->initial_radius; + cache->dyntopo_radius = cache->initial_radius; } cache->radius_squared = cache->radius * cache->radius; @@ -7603,11 +7605,12 @@ static void sculpt_stroke_update_step(bContext *C, BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail); } else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) { - BKE_pbvh_bmesh_detail_size_set(ss->pbvh, ss->cache->radius * sd->detail_percent / 100.0f); + BKE_pbvh_bmesh_detail_size_set(ss->pbvh, + ss->cache->dyntopo_radius * sd->detail_percent / 100.0f); } else { BKE_pbvh_bmesh_detail_size_set(ss->pbvh, - (ss->cache->radius / (float)ups->pixel_radius) * + (ss->cache->dyntopo_radius / (float)ups->pixel_radius) * (float)(sd->detail_size * U.pixelsize) / 0.4f); } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 0b25ab31ce0..324ca250c86 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -318,6 +318,10 @@ typedef struct StrokeCache { float true_last_location[3]; float location[3]; float last_location[3]; + + /* This radius variable is not affected by pressure curves */ + float dyntopo_radius; + bool is_last_valid; bool pen_flip; -- cgit v1.2.3 From b6d436ae28311a8e2e7ea0079b1fa1fb046909ab Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Tue, 19 Nov 2019 18:44:13 +0100 Subject: Fix T71667: Use the Sculpt Mesh API in the Multires Smooth brush This removes all multires code from the smooth brush and replaces it with a new implementation that uses the sculpt mesh API. This makes the code much easier to understand and maintain. We could unify all the smooth brushes into a single implementation, but mesh smoothing has code to deal with open boundaries that I don't want to remove yet. Most bugs and artifacts related to access neighbor grids should be fixed (like T71667). This also fixes performance bugs such as T70689, that were related to grid stitching after applying the brush. Reviewed By: jbakker Maniphest Tasks: T71667 Differential Revision: https://developer.blender.org/D6277 --- source/blender/editors/sculpt_paint/sculpt.c | 174 ++++----------------------- 1 file changed, 25 insertions(+), 149 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 5e1a36e8873..2964d53bc48 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2631,152 +2631,48 @@ static void do_smooth_brush_multires_task_cb_ex(void *__restrict userdata, const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; - SculptDoBrushSmoothGridDataChunk *data_chunk = tls->userdata_chunk; SculptSession *ss = data->ob->sculpt; Sculpt *sd = data->sd; const Brush *brush = data->brush; const bool smooth_mask = data->smooth_mask; float bstrength = data->strength; - CCGElem **griddata, *gddata; - - float(*tmpgrid_co)[3] = NULL; - float tmprow_co[2][3]; - float *tmpgrid_mask = NULL; - float tmprow_mask[2]; + PBVHVertexIter vd; - BLI_bitmap *const *grid_hidden; - int *grid_indices, totgrid, gridsize; - int i, x, y; + CLAMP(bstrength, 0.0f, 1.0f); SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); - CLAMP(bstrength, 0.0f, 1.0f); - - BKE_pbvh_node_get_grids( - ss->pbvh, data->nodes[n], &grid_indices, &totgrid, NULL, &gridsize, &griddata); - CCGKey key = *BKE_pbvh_get_grid_key(ss->pbvh); - - grid_hidden = BKE_pbvh_grid_hidden(ss->pbvh); - - if (smooth_mask) { - tmpgrid_mask = (void *)(data_chunk + 1); - } - else { - tmpgrid_co = (void *)(data_chunk + 1); - } - - for (i = 0; i < totgrid; i++) { - int gi = grid_indices[i]; - const BLI_bitmap *gh = grid_hidden[gi]; - gddata = griddata[gi]; - - if (smooth_mask) { - memset(tmpgrid_mask, 0, data_chunk->tmpgrid_size); - } - else { - memset(tmpgrid_co, 0, data_chunk->tmpgrid_size); - } - - for (y = 0; y < gridsize - 1; y++) { - const int v = y * gridsize; + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + if (sculpt_brush_test_sq_fn(&test, vd.co)) { + const float fade = bstrength * tex_strength(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f), + vd.index, + tls->thread_id); if (smooth_mask) { - tmprow_mask[0] = (*CCG_elem_offset_mask(&key, gddata, v) + - *CCG_elem_offset_mask(&key, gddata, v + gridsize)); + float val = grids_neighbor_average_mask(ss, vd.index) - *vd.mask; + val *= fade * bstrength; + *vd.mask += val; + CLAMP(*vd.mask, 0.0f, 1.0f); } else { - add_v3_v3v3(tmprow_co[0], - CCG_elem_offset_co(&key, gddata, v), - CCG_elem_offset_co(&key, gddata, v + gridsize)); - } - - for (x = 0; x < gridsize - 1; x++) { - const int v1 = x + y * gridsize; - const int v2 = v1 + 1; - const int v3 = v1 + gridsize; - const int v4 = v3 + 1; - - if (smooth_mask) { - float tmp; - - tmprow_mask[(x + 1) % 2] = (*CCG_elem_offset_mask(&key, gddata, v2) + - *CCG_elem_offset_mask(&key, gddata, v4)); - tmp = tmprow_mask[(x + 1) % 2] + tmprow_mask[x % 2]; - - tmpgrid_mask[v1] += tmp; - tmpgrid_mask[v2] += tmp; - tmpgrid_mask[v3] += tmp; - tmpgrid_mask[v4] += tmp; - } - else { - float tmp[3]; - - add_v3_v3v3(tmprow_co[(x + 1) % 2], - CCG_elem_offset_co(&key, gddata, v2), - CCG_elem_offset_co(&key, gddata, v4)); - add_v3_v3v3(tmp, tmprow_co[(x + 1) % 2], tmprow_co[x % 2]); - - add_v3_v3(tmpgrid_co[v1], tmp); - add_v3_v3(tmpgrid_co[v2], tmp); - add_v3_v3(tmpgrid_co[v3], tmp); - add_v3_v3(tmpgrid_co[v4], tmp); - } - } - } - - /* blend with existing coordinates */ - for (y = 0; y < gridsize; y++) { - for (x = 0; x < gridsize; x++) { - float *co; - const float *fno; - float *mask; - const int index = y * gridsize + x; - - if (gh) { - if (BLI_BITMAP_TEST(gh, index)) { - continue; - } - } - - co = CCG_elem_offset_co(&key, gddata, index); - fno = CCG_elem_offset_no(&key, gddata, index); - mask = CCG_elem_offset_mask(&key, gddata, index); - - if (sculpt_brush_test_sq_fn(&test, co)) { - const float strength_mask = (smooth_mask ? 0.0f : *mask); - const float fade = - bstrength * - tex_strength( - ss, brush, co, sqrtf(test.dist), NULL, fno, strength_mask, 0, tls->thread_id); - float f = 1.0f / 16.0f; - - if (x == 0 || x == gridsize - 1) { - f *= 2.0f; - } - - if (y == 0 || y == gridsize - 1) { - f *= 2.0f; - } - - if (smooth_mask) { - *mask += ((tmpgrid_mask[index] * f) - *mask) * fade; - } - else { - float *avg = tmpgrid_co[index]; - float val[3]; - - mul_v3_fl(avg, f); - sub_v3_v3v3(val, avg, co); - madd_v3_v3v3fl(val, co, val, fade); - - sculpt_clip(sd, ss, co, val); - } - } + float avg[3], val[3]; + grids_neighbor_average(ss, avg, vd.index); + sub_v3_v3v3(val, avg, vd.co); + madd_v3_v3v3fl(val, vd.co, val, fade); + sculpt_clip(sd, ss, vd.co, val); } } } + BKE_pbvh_vertex_iter_end; } static void smooth(Sculpt *sd, @@ -2821,25 +2717,9 @@ static void smooth(Sculpt *sd, BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); switch (type) { - case PBVH_GRIDS: { - int gridsize; - size_t size; - SculptDoBrushSmoothGridDataChunk *data_chunk; - - BKE_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL, &gridsize, NULL); - size = (size_t)gridsize; - size = sizeof(float) * size * size * (smooth_mask ? 1 : 3); - data_chunk = MEM_mallocN(sizeof(*data_chunk) + size, __func__); - data_chunk->tmpgrid_size = size; - size += sizeof(*data_chunk); - - settings.userdata_chunk = data_chunk; - settings.userdata_chunk_size = size; + case PBVH_GRIDS: BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings); - - MEM_freeN(data_chunk); break; - } case PBVH_FACES: BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_mesh_task_cb_ex, &settings); break; @@ -2847,10 +2727,6 @@ static void smooth(Sculpt *sd, BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_bmesh_task_cb_ex, &settings); break; } - - if (ss->multires) { - multires_stitch_grids(ob); - } } } -- cgit v1.2.3 From 0e4014ef9215ffe38108b7596a29bd3c5c41bbd1 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Tue, 26 Nov 2019 18:43:44 +0100 Subject: Sculpt/Paint: Move Elastic Deform Kelvinlets to BKE After this commit it should be possible to share the same deformation formulas that are used in the Elastic Deform brush with other areas of Blender such as Grease Pencil or proportional editing. This also removes a lot of code from sculpt.c that is not direclty related to sculpting. Reviewed By: jbakker Differential Revision: https://developer.blender.org/D6281 --- source/blender/blenkernel/BKE_kelvinlet.h | 77 ++++++++ source/blender/blenkernel/CMakeLists.txt | 2 + source/blender/blenkernel/intern/kelvinlet.c | 215 +++++++++++++++++++++++ source/blender/blenlib/intern/math_base_inline.c | 4 + source/blender/editors/sculpt_paint/sculpt.c | 179 ++----------------- 5 files changed, 316 insertions(+), 161 deletions(-) create mode 100644 source/blender/blenkernel/BKE_kelvinlet.h create mode 100644 source/blender/blenkernel/intern/kelvinlet.c diff --git a/source/blender/blenkernel/BKE_kelvinlet.h b/source/blender/blenkernel/BKE_kelvinlet.h new file mode 100644 index 00000000000..fbf7d3ede1f --- /dev/null +++ b/source/blender/blenkernel/BKE_kelvinlet.h @@ -0,0 +1,77 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) Blender Foundation. + * All rights reserved. + */ +#ifndef __BKE_KELVINLET_H__ +#define __BKE_KELVINLET_H__ + +/** \file + * \ingroup bke + */ + +#include "BLI_math.h" + +/* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity + * Pixar Technical Memo #17-03 */ + +#define KELVINLET_MAX_ITERATIONS 3 + +typedef struct KelvinletParams { + float a; + float b; + float c; + + float f; + + float radius_scaled[KELVINLET_MAX_ITERATIONS]; +} KelvinletParams; + +/* Initialize KelvinletParams to store the parameters that will affect the deformation produced by + * a Kelvinlet */ +void BKE_kelvinlet_init_params( + KelvinletParams *params, float radius, float force, float shear_modulus, float poisson_ratio); + +/* Regularized Kelvinlets */ +/* All these functions output the displacement that should be applied to each element. */ +/* The initial coordinates of that element should not be modified during the transformation */ +void BKE_kelvinlet_grab(float r_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float brush_delta[3]); +void BKE_kelvinlet_grab_biscale(float r_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float brush_delta[3]); +void BKE_kelvinlet_grab_triscale(float r_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float brush_delta[3]); +void BKE_kelvinlet_scale(float r_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float surface_normal[3]); +void BKE_kelvinlet_twist(float r_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float surface_normal[3]); + +#endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 883518b7a9d..88a3629ea3f 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -129,6 +129,7 @@ set(SRC intern/image_gen.c intern/image_save.c intern/ipo.c + intern/kelvinlet.c intern/key.c intern/keyconfig.c intern/lattice.c @@ -292,6 +293,7 @@ set(SRC BKE_image.h BKE_image_save.h BKE_ipo.h + BKE_kelvinlet.h BKE_key.h BKE_keyconfig.h BKE_lattice.h diff --git a/source/blender/blenkernel/intern/kelvinlet.c b/source/blender/blenkernel/intern/kelvinlet.c new file mode 100644 index 00000000000..a7b48107873 --- /dev/null +++ b/source/blender/blenkernel/intern/kelvinlet.c @@ -0,0 +1,215 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +#include "BKE_kelvinlet.h" + +/* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity + * Pixar Technical Memo #17-03 */ + +void BKE_kelvinlet_init_params( + KelvinletParams *params, float radius, float force, float shear_modulus, float poisson_ratio) +{ + params->a = 1.0f / (4.0f * (float)M_PI * shear_modulus); + params->b = params->a / (4.0f * (1.0f - poisson_ratio)); + params->c = 2 * (3.0f * params->a - 2.0f * params->b); + + /* Used in scale and twist. */ + params->f = force; + + /* This can be exposed if needed */ + const float radius_e[KELVINLET_MAX_ITERATIONS] = {1.0f, 2.0f, 2.0f}; + params->radius_scaled[0] = radius * radius_e[0]; + params->radius_scaled[1] = params->radius_scaled[0] * radius_e[1]; + params->radius_scaled[2] = params->radius_scaled[1] * radius_e[2]; +} + +static void init_kelvinlet_grab(float radius_e[3], + float kelvinlet[3], + const float radius, + const KelvinletParams *params, + const int num_iterations) +{ + const float a = params->a; + const float b = params->b; + const float *radius_scaled = params->radius_scaled; + + for (int i = 0; i < num_iterations; i++) { + radius_e[i] = sqrtf(pow2f(radius) + pow2f(params->radius_scaled[i])); + } + + /* Regularized Kelvinlets: Formula (6) */ + for (int i = 0; i < num_iterations; i++) { + kelvinlet[i] = ((a - b) / radius_e[i]) + ((b * pow2f(radius)) / pow3f(radius_e[i])) + + ((a * pow2f(radius_scaled[i])) / (2.0f * pow3f(radius_e[i]))); + } +} + +void BKE_kelvinlet_grab(float radius_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float brush_delta[3]) +{ + float radius_e[3], kelvinlet[3]; + const float c = params->c; + const float radius = len_v3v3(brush_location, elem_orig_co); + + init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 1); + + const float fade = kelvinlet[0] * c; + + mul_v3_v3fl(radius_elem_disp, brush_delta, fade); +} + +void BKE_kelvinlet_grab_biscale(float radius_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float brush_delta[3]) +{ + float radius_e[3], kelvinlet[3]; + const float c = params->c; + const float *radius_scaled = params->radius_scaled; + float radius = len_v3v3(brush_location, elem_orig_co); + + init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 2); + + const float u = kelvinlet[0] - kelvinlet[1]; + const float fade = u * c / ((1.0f / radius_scaled[0]) - (1.0f / radius_scaled[1])); + + mul_v3_v3fl(radius_elem_disp, brush_delta, fade); +} + +void BKE_kelvinlet_grab_triscale(float radius_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float brush_delta[3]) +{ + float radius_e[3], kelvinlet[3], weights[3]; + const float c = params->c; + const float *radius_scaled = params->radius_scaled; + const float radius = len_v3v3(brush_location, elem_orig_co); + + init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 3); + + weights[0] = 1.0f; + weights[1] = -((pow2f(radius_scaled[2]) - pow2f(radius_scaled[0])) / + (pow2f(radius_scaled[2]) - pow2f(radius_scaled[1]))); + weights[2] = ((pow2f(radius_scaled[1]) - pow2f(radius_scaled[0])) / + (pow2f(radius_scaled[2]) - pow2f(radius_scaled[1]))); + + const float u = weights[0] * kelvinlet[0] + weights[1] * kelvinlet[1] + + weights[2] * kelvinlet[2]; + const float fade = u * c / + (weights[0] / radius_scaled[0] + weights[1] / radius_scaled[1] + + weights[2] / radius_scaled[2]); + + mul_v3_v3fl(radius_elem_disp, brush_delta, fade); +} + +typedef void (*kelvinlet_fn)( + float[3], const float *, const float *, const float *, const KelvinletParams *); + +static void sculpt_kelvinet_integrate(kelvinlet_fn kelvinlet, + float r_disp[3], + const float vertex_co[3], + const float location[3], + const float normal[3], + const KelvinletParams *p) +{ + float k[4][3], k_it[4][3]; + kelvinlet(k[0], vertex_co, location, normal, p); + copy_v3_v3(k_it[0], k[0]); + mul_v3_fl(k_it[0], 0.5f); + add_v3_v3v3(k_it[0], vertex_co, k_it[0]); + kelvinlet(k[1], k_it[0], location, normal, p); + copy_v3_v3(k_it[1], k[1]); + mul_v3_fl(k_it[1], 0.5f); + add_v3_v3v3(k_it[1], vertex_co, k_it[1]); + kelvinlet(k[2], k_it[1], location, normal, p); + copy_v3_v3(k_it[2], k[2]); + add_v3_v3v3(k_it[2], vertex_co, k_it[2]); + sub_v3_v3v3(k_it[2], k_it[2], location); + kelvinlet(k[3], k_it[2], location, normal, p); + copy_v3_v3(r_disp, k[0]); + madd_v3_v3fl(r_disp, k[1], 2.0f); + madd_v3_v3fl(r_disp, k[2], 2.0f); + add_v3_v3(r_disp, k[3]); + mul_v3_fl(r_disp, 1.0f / 6.0f); +} + +/* Regularized Kelvinlets: Formula (16) */ +static void kelvinlet_scale(float disp[3], + const float vertex_co[3], + const float location[3], + const float UNUSED(normal[3]), + const KelvinletParams *p) +{ + float radius_vertex[3]; + sub_v3_v3v3(radius_vertex, vertex_co, location); + const float radius = len_v3(radius_vertex); + const float radius_e = sqrtf(pow2f(radius) + pow2f(p->radius_scaled[0])); + const float u = (2.0f * p->b - p->a) * ((1.0f / pow3f(radius_e))) + + ((3.0f * pow2f(p->radius_scaled[0])) / (2.0f * pow5f(radius_e))); + const float fade = u * p->c; + mul_v3_v3fl(disp, radius_vertex, fade * p->f); +} + +void BKE_kelvinlet_scale(float radius_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float surface_normal[3]) +{ + sculpt_kelvinet_integrate( + kelvinlet_scale, radius_elem_disp, elem_orig_co, brush_location, surface_normal, params); +} + +/* Regularized Kelvinlets: Formula (15) */ +static void kelvinlet_twist(float disp[3], + const float vertex_co[3], + const float location[3], + const float normal[3], + const KelvinletParams *p) +{ + float radius_vertex[3], q_r[3]; + sub_v3_v3v3(radius_vertex, vertex_co, location); + const float radius = len_v3(radius_vertex); + const float radius_e = sqrtf(pow2f(radius) + pow2f(p->radius_scaled[0])); + const float u = -p->a * ((1.0f / pow3f(radius_e))) + + ((3.0f * pow2f(p->radius_scaled[0])) / (2.0f * pow5f(radius_e))); + const float fade = u * p->c; + cross_v3_v3v3(q_r, normal, radius_vertex); + mul_v3_v3fl(disp, q_r, fade * p->f); +} + +void BKE_kelvinlet_twist(float radius_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float surface_normal[3]) +{ + sculpt_kelvinet_integrate( + kelvinlet_twist, radius_elem_disp, elem_orig_co, brush_location, surface_normal, params); +} diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index 4c86b9d3396..85c6425bb2f 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -58,6 +58,10 @@ MINLINE float pow4f(float x) { return pow2f(pow2f(x)); } +MINLINE float pow5f(float x) +{ + return pow4f(x) * x; +} MINLINE float pow7f(float x) { return pow2f(pow3f(x)) * x; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 2964d53bc48..9d0048ff847 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -48,6 +48,7 @@ #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_image.h" +#include "BKE_kelvinlet.h" #include "BKE_key.h" #include "BKE_library.h" #include "BKE_main.h" @@ -3404,98 +3405,6 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) BKE_pbvh_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings); } -/* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity - * Pixar Technical Memo #17-03 */ - -typedef struct KelvinletParams { - float f; - float a; - float b; - float c; - float radius_scaled; -} KelvinletParams; - -static int sculpt_kelvinlet_get_scale_iteration_count(eBrushElasticDeformType type) -{ - if (type == BRUSH_ELASTIC_DEFORM_GRAB) { - return 1; - } - if (type == BRUSH_ELASTIC_DEFORM_GRAB_BISCALE) { - return 2; - } - if (type == BRUSH_ELASTIC_DEFORM_GRAB_TRISCALE) { - return 3; - } - return 0; -} - -static void sculpt_kelvinet_integrate(void (*kelvinlet)(float disp[3], - const float vertex_co[3], - const float location[3], - float normal[3], - KelvinletParams *p), - float r_disp[3], - const float vertex_co[3], - const float location[3], - float normal[3], - KelvinletParams *p) -{ - float k[4][3], k_it[4][3]; - kelvinlet(k[0], vertex_co, location, normal, p); - copy_v3_v3(k_it[0], k[0]); - mul_v3_fl(k_it[0], 0.5f); - add_v3_v3v3(k_it[0], vertex_co, k_it[0]); - kelvinlet(k[1], k_it[0], location, normal, p); - copy_v3_v3(k_it[1], k[1]); - mul_v3_fl(k_it[1], 0.5f); - add_v3_v3v3(k_it[1], vertex_co, k_it[1]); - kelvinlet(k[2], k_it[1], location, normal, p); - copy_v3_v3(k_it[2], k[2]); - add_v3_v3v3(k_it[2], vertex_co, k_it[2]); - sub_v3_v3v3(k_it[2], k_it[2], location); - kelvinlet(k[3], k_it[2], location, normal, p); - copy_v3_v3(r_disp, k[0]); - madd_v3_v3fl(r_disp, k[1], 2); - madd_v3_v3fl(r_disp, k[2], 2); - add_v3_v3(r_disp, k[3]); - mul_v3_fl(r_disp, 1.0f / 6.0f); -} - -/* Regularized Kelvinlets: Formula (16) */ -static void sculpt_kelvinlet_scale(float disp[3], - const float vertex_co[3], - const float location[3], - float UNUSED(normal[3]), - KelvinletParams *p) -{ - float r_v[3]; - sub_v3_v3v3(r_v, vertex_co, location); - float r = len_v3(r_v); - float r_e = sqrtf(r * r + p->radius_scaled * p->radius_scaled); - float u = (2.0f * p->b - p->a) * ((1.0f / (r_e * r_e * r_e))) + - ((3.0f * p->radius_scaled * p->radius_scaled) / (2.0f * r_e * r_e * r_e * r_e * r_e)); - float fade = u * p->c; - mul_v3_v3fl(disp, r_v, fade * p->f); -} - -/* Regularized Kelvinlets: Formula (15) */ -static void sculpt_kelvinlet_twist(float disp[3], - const float vertex_co[3], - const float location[3], - float normal[3], - KelvinletParams *p) -{ - float r_v[3], q_r[3]; - sub_v3_v3v3(r_v, vertex_co, location); - float r = len_v3(r_v); - float r_e = sqrtf(r * r + p->radius_scaled * p->radius_scaled); - float u = -p->a * ((1.0f / (r_e * r_e * r_e))) + - ((3.0f * p->radius_scaled * p->radius_scaled) / (2.0f * r_e * r_e * r_e * r_e * r_e)); - float fade = u * p->c; - cross_v3_v3v3(q_r, normal, r_v); - mul_v3_v3fl(disp, q_r, fade * p->f); -} - static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls)) @@ -3516,23 +3425,6 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata, proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; - /* Maybe this can be exposed to the user */ - float radius_e[3] = {1.0f, 2.0f, 2.0f}; - float r_e[3]; - float kvl[3]; - float radius_scaled[3]; - - radius_scaled[0] = ss->cache->radius * radius_e[0]; - radius_scaled[1] = radius_scaled[0] * radius_e[1]; - radius_scaled[2] = radius_scaled[1] * radius_e[2]; - - float shear_modulus = 1.0f; - float poisson_ratio = brush->elastic_deform_volume_preservation; - - float a = 1.0f / (4.0f * (float)M_PI * shear_modulus); - float b = a / (4.0f * (1.0f - poisson_ratio)); - float c = 2 * (3.0f * a - 2.0f * b); - float dir; if (ss->cache->mouse[0] > ss->cache->initial_mouse[0]) { dir = 1.0f; @@ -3547,73 +3439,38 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata, dir = -dir; } } + + KelvinletParams params; + float force = len_v3(grab_delta) * dir * bstrength; + BKE_kelvinlet_init_params( + ¶ms, ss->cache->radius, force, 1.0f, brush->elastic_deform_volume_preservation); + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { sculpt_orig_vert_data_update(&orig_data, &vd); - float fade, final_disp[3], weights[3]; - float r = len_v3v3(location, orig_data.co); - KelvinletParams params; - params.a = a; - params.b = b; - params.c = c; - params.radius_scaled = radius_scaled[0]; - - int multi_scale_it = sculpt_kelvinlet_get_scale_iteration_count(brush->elastic_deform_type); - for (int it = 0; it < max_ii(1, multi_scale_it); it++) { - r_e[it] = sqrtf(r * r + radius_scaled[it] * radius_scaled[it]); - } - - /* Regularized Kelvinlets: Formula (6) */ - for (int s_it = 0; s_it < multi_scale_it; s_it++) { - kvl[s_it] = ((a - b) / r_e[s_it]) + ((b * r * r) / (r_e[s_it] * r_e[s_it] * r_e[s_it])) + - ((a * radius_scaled[s_it] * radius_scaled[s_it]) / - (2.0f * r_e[s_it] * r_e[s_it] * r_e[s_it])); - } - + float final_disp[3]; switch (brush->elastic_deform_type) { - /* Regularized Kelvinlets: Multi-scale extrapolation. Formula (11) */ case BRUSH_ELASTIC_DEFORM_GRAB: - fade = kvl[0] * c; - mul_v3_v3fl(final_disp, grab_delta, fade * bstrength * 20.f); + BKE_kelvinlet_grab(final_disp, ¶ms, orig_data.co, location, grab_delta); + mul_v3_fl(final_disp, bstrength * 20.0f); break; case BRUSH_ELASTIC_DEFORM_GRAB_BISCALE: { - const float u = kvl[0] - kvl[1]; - fade = u * c / ((1.0f / radius_scaled[0]) - (1.0f / radius_scaled[1])); - mul_v3_v3fl(final_disp, grab_delta, fade * bstrength * 20.0f); + BKE_kelvinlet_grab_biscale(final_disp, ¶ms, orig_data.co, location, grab_delta); + mul_v3_fl(final_disp, bstrength * 20.0f); break; } case BRUSH_ELASTIC_DEFORM_GRAB_TRISCALE: { - weights[0] = 1.0f; - weights[1] = -( - (radius_scaled[2] * radius_scaled[2] - radius_scaled[0] * radius_scaled[0]) / - (radius_scaled[2] * radius_scaled[2] - radius_scaled[1] * radius_scaled[1])); - weights[2] = ((radius_scaled[1] * radius_scaled[1] - radius_scaled[0] * radius_scaled[0]) / - (radius_scaled[2] * radius_scaled[2] - radius_scaled[1] * radius_scaled[1])); - - const float u = weights[0] * kvl[0] + weights[1] * kvl[1] + weights[2] * kvl[2]; - fade = u * c / - (weights[0] / radius_scaled[0] + weights[1] / radius_scaled[1] + - weights[2] / radius_scaled[2]); - mul_v3_v3fl(final_disp, grab_delta, fade * bstrength * 20.0f); + BKE_kelvinlet_grab_triscale(final_disp, ¶ms, orig_data.co, location, grab_delta); + mul_v3_fl(final_disp, bstrength * 20.0f); break; } case BRUSH_ELASTIC_DEFORM_SCALE: - params.f = len_v3(grab_delta) * dir * bstrength; - sculpt_kelvinet_integrate(sculpt_kelvinlet_scale, - final_disp, - orig_data.co, - location, - ss->cache->sculpt_normal_symm, - ¶ms); + BKE_kelvinlet_scale( + final_disp, ¶ms, orig_data.co, location, ss->cache->sculpt_normal_symm); break; case BRUSH_ELASTIC_DEFORM_TWIST: - params.f = len_v3(grab_delta) * dir * bstrength; - sculpt_kelvinet_integrate(sculpt_kelvinlet_twist, - final_disp, - orig_data.co, - location, - ss->cache->sculpt_normal_symm, - ¶ms); + BKE_kelvinlet_twist( + final_disp, ¶ms, orig_data.co, location, ss->cache->sculpt_normal_symm); break; } -- cgit v1.2.3 From 9251b077203c763f1be83505ed0a4d1e19dab947 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Wed, 27 Nov 2019 02:02:18 +0100 Subject: Sculpt/Paint: Remove Unified SIZE_PRESSURE and ALPHA_PRESSURE The relation between the pressure/size and the pressure/alpha is a fundamental property that defines the behavior of a brush, so it does not make sense to have it unified across all brushes. This applies both for sculpting and painting. Some of the new 2.82 brushes need pressure/size or pressure/alpha to be enabled to work propely, while others don't. Users should not be switching on and off this property manually when changing brushes if they want to use unified size. This is also causing that some users are using the brushes with an incorrect configuration. Reviewed By: jbakker Differential Revision: https://developer.blender.org/D6291 --- release/scripts/startup/bl_ui/properties_paint_common.py | 16 ++++++++-------- source/blender/blenkernel/BKE_brush.h | 4 ++-- source/blender/blenkernel/intern/brush.c | 14 ++++---------- source/blender/blenloader/intern/versioning_280.c | 8 ++++++++ source/blender/editors/sculpt_paint/paint_cursor.c | 11 +++++------ source/blender/editors/sculpt_paint/paint_image.c | 2 +- source/blender/editors/sculpt_paint/paint_stroke.c | 12 ++++++------ source/blender/editors/sculpt_paint/paint_vertex.c | 8 +++----- source/blender/editors/sculpt_paint/sculpt.c | 7 +++---- source/blender/makesdna/DNA_scene_types.h | 9 +++------ source/blender/makesrna/intern/rna_scene.c | 11 ----------- 11 files changed, 43 insertions(+), 59 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 98e812cf02d..7c28095259e 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -296,11 +296,11 @@ def brush_basic_wpaint_settings(layout, context, brush, *, compact=False): row = layout.row(align=True) UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True) - UnifiedPaintPanel.prop_unified_size(row, context, brush, "use_pressure_size", text="") + row.prop(brush, "use_pressure_size", text="") row = layout.row(align=True) UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength") - UnifiedPaintPanel.prop_unified_strength(row, context, brush, "use_pressure_strength", text="") + row.prop(brush, "use_pressure_strength", text="") layout.prop(brush, "blend", text="" if compact else "Blend") @@ -310,11 +310,11 @@ def brush_basic_vpaint_settings(layout, context, brush, *, compact=False): row = layout.row(align=True) UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True) - UnifiedPaintPanel.prop_unified_size(row, context, brush, "use_pressure_size", text="") + row.prop(brush, "use_pressure_size", text="") row = layout.row(align=True) UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength") - UnifiedPaintPanel.prop_unified_strength(row, context, brush, "use_pressure_strength", text="") + row.prop(brush, "use_pressure_strength", text="") if capabilities.has_color: layout.prop(brush, "blend", text="" if compact else "Blend") @@ -326,12 +326,12 @@ def brush_basic_texpaint_settings(layout, context, brush, *, compact=False): if capabilities.has_radius: row = layout.row(align=True) UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True) - UnifiedPaintPanel.prop_unified_size(row, context, brush, "use_pressure_size", text="") + row.prop(brush, "use_pressure_size", text="") row = layout.row(align=True) UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength") - UnifiedPaintPanel.prop_unified_strength(row, context, brush, "use_pressure_strength", text="") + row.prop(brush, "use_pressure_strength", text="") if capabilities.has_color: layout.prop(brush, "blend", text="" if compact else "Blend") @@ -352,7 +352,7 @@ def brush_basic_sculpt_settings(layout, context, brush, *, compact=False): else: UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True) - UnifiedPaintPanel.prop_unified_size(row, context, brush, "use_pressure_size", text="") + row.prop(brush, "use_pressure_size", text="") # strength, use_strength_pressure, and use_strength_attenuation row = layout.row(align=True) @@ -360,7 +360,7 @@ def brush_basic_sculpt_settings(layout, context, brush, *, compact=False): UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength") if capabilities.has_strength_pressure: - UnifiedPaintPanel.prop_unified_strength(row, context, brush, "use_pressure_strength", text="") + row.prop(brush, "use_pressure_strength", text="") # direction if not capabilities.has_direction: diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 70741831727..c7f6c09b886 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -111,8 +111,8 @@ float BKE_brush_weight_get(const struct Scene *scene, const struct Brush *brush) void BKE_brush_weight_set(const struct Scene *scene, struct Brush *brush, float value); bool BKE_brush_use_locked_size(const struct Scene *scene, const struct Brush *brush); -bool BKE_brush_use_alpha_pressure(const struct Scene *scene, const struct Brush *brush); -bool BKE_brush_use_size_pressure(const struct Scene *scene, const struct Brush *brush); +bool BKE_brush_use_alpha_pressure(const struct Brush *brush); +bool BKE_brush_use_size_pressure(const struct Brush *brush); bool BKE_brush_sculpt_has_secondary_color(const struct Brush *brush); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 27c3df5ce6e..a64da8f6606 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -1399,20 +1399,14 @@ bool BKE_brush_use_locked_size(const Scene *scene, const Brush *brush) (brush->flag & BRUSH_LOCK_SIZE); } -bool BKE_brush_use_size_pressure(const Scene *scene, const Brush *brush) +bool BKE_brush_use_size_pressure(const Brush *brush) { - const short us_flag = scene->toolsettings->unified_paint_settings.flag; - - return (us_flag & UNIFIED_PAINT_SIZE) ? (us_flag & UNIFIED_PAINT_BRUSH_SIZE_PRESSURE) : - (brush->flag & BRUSH_SIZE_PRESSURE); + return brush->flag & BRUSH_SIZE_PRESSURE; } -bool BKE_brush_use_alpha_pressure(const Scene *scene, const Brush *brush) +bool BKE_brush_use_alpha_pressure(const Brush *brush) { - const short us_flag = scene->toolsettings->unified_paint_settings.flag; - - return (us_flag & UNIFIED_PAINT_ALPHA) ? (us_flag & UNIFIED_PAINT_BRUSH_ALPHA_PRESSURE) : - (brush->flag & BRUSH_ALPHA_PRESSURE); + return brush->flag & BRUSH_ALPHA_PRESSURE; } bool BKE_brush_sculpt_has_secondary_color(const Brush *brush) diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 4af589bb29f..7c33e853ed1 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -4209,6 +4209,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) br->pose_smooth_iterations = 4; } } + /* Cloth pressure */ for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) { for (ModifierData *md = ob->modifiers.first; md; md = md->next) { @@ -4223,5 +4224,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) { /* Versioning code until next subversion bump goes here. */ + + /* Remove Unified pressure/size and pressure/alpha */ + for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { + ToolSettings *ts = scene->toolsettings; + UnifiedPaintSettings *ups = &ts->unified_paint_settings; + ups->flag &= ~(UNIFIED_PAINT_FLAG_UNUSED_0 | UNIFIED_PAINT_FLAG_UNUSED_1); + } } } diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 78c9980134f..856072ec47a 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -648,7 +648,7 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups, GPU_matrix_translate_2f(-x, -y); /* scale based on tablet pressure */ - if (primary && ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) { + if (primary && ups->stroke_active && BKE_brush_use_size_pressure(brush)) { const float scale = ups->size_pressure_value; GPU_matrix_translate_2f(x, y); GPU_matrix_scale_2f(scale, scale); @@ -778,7 +778,7 @@ static bool paint_draw_cursor_overlay( } /* scale based on tablet pressure */ - if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) { + if (ups->stroke_active && BKE_brush_use_size_pressure(brush)) { do_pop = true; GPU_matrix_push(); GPU_matrix_translate_2fv(center); @@ -1075,7 +1075,7 @@ static void paint_cursor_on_hit(UnifiedPaintSettings *ups, unprojected_radius = paint_calc_object_space_radius(vc, location, projected_radius); /* scale 3D brush radius by pressure */ - if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) { + if (ups->stroke_active && BKE_brush_use_size_pressure(brush)) { unprojected_radius *= ups->size_pressure_value; } @@ -1362,7 +1362,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) immUniformColor3fvAlpha(outline_col, outline_alpha); /* draw brush outline */ - if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) { + if (ups->stroke_active && BKE_brush_use_size_pressure(brush)) { imm_draw_circle_wire_2d( pos, translation[0], translation[1], final_radius * ups->size_pressure_value, 40); /* outer at half alpha */ @@ -1407,8 +1407,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) immUniformColor3fvAlpha(outline_col, outline_alpha); - if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush) && - mode != PAINT_MODE_SCULPT) { + if (ups->stroke_active && BKE_brush_use_size_pressure(brush) && mode != PAINT_MODE_SCULPT) { imm_draw_circle_wire_3d( pos, translation[0], translation[1], final_radius * ups->size_pressure_value, 40); /* outer at half alpha */ diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 9acc189ae95..0b770f17314 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -548,7 +548,7 @@ static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, Po return; } - if (BKE_brush_use_alpha_pressure(scene, brush)) { + if (BKE_brush_use_alpha_pressure(brush)) { BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure * alphafac)); } else { diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index ee359def68c..fc0c6d748cb 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -336,7 +336,7 @@ static bool paint_brush_update(bContext *C, ups->pixel_radius = BKE_brush_size_get(scene, brush); - if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, mode)) { + if (BKE_brush_use_size_pressure(brush) && paint_supports_dynamic_size(brush, mode)) { ups->pixel_radius *= stroke->cached_size_pressure; } @@ -527,8 +527,8 @@ static void paint_brush_stroke_add_step(bContext *C, * windows for some tablets, then we just skip first touch .. */ if (tablet && (pressure >= 0.99f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || - BKE_brush_use_alpha_pressure(scene, pop->s.brush) || - BKE_brush_use_size_pressure(scene, pop->s.brush))) { + BKE_brush_use_alpha_pressure(pop->s.brush) || + BKE_brush_use_size_pressure(pop->s.brush))) { return; } @@ -540,8 +540,8 @@ static void paint_brush_stroke_add_step(bContext *C, * which is the sensitivity of the most sensitive pen tablet available */ if (tablet && (pressure < 0.0002f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || - BKE_brush_use_alpha_pressure(scene, pop->s.brush) || - BKE_brush_use_size_pressure(scene, pop->s.brush))) { + BKE_brush_use_alpha_pressure(pop->s.brush) || + BKE_brush_use_size_pressure(pop->s.brush))) { return; } #endif @@ -756,7 +756,7 @@ static float paint_space_stroke_spacing_variable(bContext *C, float dpressure, float length) { - if (BKE_brush_use_size_pressure(scene, stroke->brush)) { + if (BKE_brush_use_size_pressure(stroke->brush)) { /* use pressure to modify size. set spacing so that at 100%, the circles * are aligned nicely with no overlap. for this the spacing needs to be * the average of the previous and next size. */ diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index ac7cf310099..536d93cac29 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -1522,7 +1522,7 @@ static void vwpaint_update_cache_variants(bContext *C, VPaint *vp, Object *ob, P } } - if (BKE_brush_use_size_pressure(scene, brush) && + if (BKE_brush_use_size_pressure(brush) && paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT)) { cache->radius = cache->initial_radius * cache->pressure; } @@ -1684,11 +1684,9 @@ static void get_brush_alpha_data(const Scene *scene, float *r_brush_alpha_pressure) { *r_brush_size_pressure = BKE_brush_size_get(scene, brush) * - (BKE_brush_use_size_pressure(scene, brush) ? ss->cache->pressure : - 1.0f); + (BKE_brush_use_size_pressure(brush) ? ss->cache->pressure : 1.0f); *r_brush_alpha_value = BKE_brush_alpha_get(scene, brush); - *r_brush_alpha_pressure = (BKE_brush_use_alpha_pressure(scene, brush) ? ss->cache->pressure : - 1.0f); + *r_brush_alpha_pressure = (BKE_brush_use_alpha_pressure(brush) ? ss->cache->pressure : 1.0f); } static float wpaint_get_active_weight(const MDeformVert *dv, const WeightPaintInfo *wpi) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 9d0048ff847..38e4d119aa5 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1724,7 +1724,7 @@ static float brush_strength(const Sculpt *sd, const float root_alpha = BKE_brush_alpha_get(scene, brush); float alpha = root_alpha * root_alpha; float dir = (brush->flag & BRUSH_DIR_IN) ? -1 : 1; - float pressure = BKE_brush_use_alpha_pressure(scene, brush) ? cache->pressure : 1; + float pressure = BKE_brush_use_alpha_pressure(brush) ? cache->pressure : 1; float pen_flip = cache->pen_flip ? -1 : 1; float invert = cache->invert ? -1 : 1; float overlap = ups->overlap_factor; @@ -6719,7 +6719,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po } } - if (BKE_brush_use_size_pressure(scene, brush) && + if (BKE_brush_use_size_pressure(brush) && paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT)) { cache->radius = sculpt_brush_dynamic_size_get(brush, cache, cache->initial_radius); cache->dyntopo_radius = cache->initial_radius * cache->pressure; @@ -7137,14 +7137,13 @@ static void sculpt_brush_stroke_init(bContext *C, wmOperator *op) static void sculpt_restore_mesh(Sculpt *sd, Object *ob) { - SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); /* Restore the mesh before continuing with anchored stroke */ if ((brush->flag & BRUSH_ANCHORED) || ((brush->sculpt_tool == SCULPT_TOOL_GRAB || brush->sculpt_tool == SCULPT_TOOL_ELASTIC_DEFORM) && - BKE_brush_use_size_pressure(ss->cache->vc->scene, brush)) || + BKE_brush_use_size_pressure(brush)) || (brush->flag & BRUSH_DRAG_DOT)) { paint_mesh_restore_co(sd, ob); } diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index ce0c7319ce5..54ae38f608c 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1298,14 +1298,11 @@ typedef enum { UNIFIED_PAINT_WEIGHT = (1 << 5), UNIFIED_PAINT_COLOR = (1 << 6), - /* only used if unified size is enabled, mirrors the brush flags - * BRUSH_LOCK_SIZE and BRUSH_SIZE_PRESSURE */ + /* only used if unified size is enabled, mirrors the brush flag BRUSH_LOCK_SIZE */ UNIFIED_PAINT_BRUSH_LOCK_SIZE = (1 << 2), - UNIFIED_PAINT_BRUSH_SIZE_PRESSURE = (1 << 3), + UNIFIED_PAINT_FLAG_UNUSED_0 = (1 << 3), - /* only used if unified alpha is enabled, mirrors the brush flag - * BRUSH_ALPHA_PRESSURE */ - UNIFIED_PAINT_BRUSH_ALPHA_PRESSURE = (1 << 4), + UNIFIED_PAINT_FLAG_UNUSED_1 = (1 << 4), } eUnifiedPaintSettingsFlags; typedef struct CurvePaintSettings { diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 2b47b1664d7..cca82abc9da 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -3411,17 +3411,6 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Secondary Color", ""); RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update"); - prop = RNA_def_property(srna, "use_pressure_size", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", UNIFIED_PAINT_BRUSH_SIZE_PRESSURE); - RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); - RNA_def_property_ui_text(prop, "Size Pressure", "Enable tablet pressure sensitivity for size"); - - prop = RNA_def_property(srna, "use_pressure_strength", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", UNIFIED_PAINT_BRUSH_ALPHA_PRESSURE); - RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); - RNA_def_property_ui_text( - prop, "Strength Pressure", "Enable tablet pressure sensitivity for strength"); - prop = RNA_def_property(srna, "use_locked_size", PROP_ENUM, PROP_NONE); /* as an enum */ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, brush_size_unit_items); -- cgit v1.2.3 From 47645a8db6223ba31b8128db7502f27876a2586b Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Tue, 26 Nov 2019 18:53:38 +0100 Subject: Sculpt: Sample Voxel Size This adds support to the current sculpt sample detail operator to sample a voxel size for the voxel remesher when sculpting on regular meshes. It provides an approximation of a voxel size that is going to preserve the sampled sculpt details after remeshing. It is not going to be 100% accurate in all cases as it relies on having consistent edge length in the whole sculpt, but it saves a lot of time and avoids guessing the voxel size by trying different values. Reviewed By: jbakker Differential Revision: https://developer.blender.org/D6251 --- .../scripts/startup/bl_ui/space_view3d_toolbar.py | 8 +- source/blender/editors/sculpt_paint/sculpt.c | 107 ++++++++++++++++----- 2 files changed, 91 insertions(+), 24 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 724264fe494..718365ec99d 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -1193,7 +1193,8 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel): if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}: row = sub.row(align=True) row.prop(sculpt, "constant_detail_resolution") - row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER') + props = row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER') + props.mode = 'DYNTOPO' elif (sculpt.detail_type_method == 'BRUSH'): sub.prop(sculpt, "detail_percent") else: @@ -1252,7 +1253,10 @@ class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel): col = layout.column() mesh = context.active_object.data - col.prop(mesh, "remesh_voxel_size") + row = col.row(align=True) + row.prop(mesh, "remesh_voxel_size") + props = row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER') + props.mode = 'VOXEL' col.prop(mesh, "remesh_voxel_adaptivity") col.prop(mesh, "use_remesh_fix_poles") col.prop(mesh, "use_remesh_smooth_normals") diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 38e4d119aa5..63b9949e0ef 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -8445,36 +8445,60 @@ static void SCULPT_OT_detail_flood_fill(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static void sample_detail(bContext *C, int mx, int my) +typedef enum eSculptSampleDetailModeTypes { + SAMPLE_DETAIL_DYNTOPO = 0, + SAMPLE_DETAIL_VOXEL = 1, +} eSculptSampleDetailModeTypes; + +static EnumPropertyItem prop_sculpt_sample_detail_mode_types[] = { + {SAMPLE_DETAIL_DYNTOPO, "DYNTOPO", 0, "Dyntopo", "Sample dyntopo detail"}, + {SAMPLE_DETAIL_VOXEL, "VOXEL", 0, "Voxel", "Sample mesh voxel size"}, + {0, NULL, 0, NULL, NULL}, +}; + +static void sample_detail_voxel(bContext *C, ViewContext *vc, int mx, int my) { - /* Find 3D view to pick from. */ - bScreen *screen = CTX_wm_screen(C); - ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_VIEW3D, mx, my); - ARegion *ar = (sa) ? BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my) : NULL; - if (ar == NULL) { - return; - } + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + Object *ob = vc->obact; + Mesh *mesh = ob->data; - /* Set context to 3D view. */ - ScrArea *prev_sa = CTX_wm_area(C); - ARegion *prev_ar = CTX_wm_region(C); - CTX_wm_area_set(C, sa); - CTX_wm_region_set(C, ar); + SculptSession *ss = ob->sculpt; + SculptCursorGeometryInfo sgi; + sculpt_vertex_random_access_init(ss); - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - ViewContext vc; - ED_view3d_viewcontext_init(C, &vc, depsgraph); + /* Update the active vertex */ + float mouse[2] = {mx, my}; + sculpt_cursor_geometry_info_update(C, &sgi, mouse, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false); - /* Pick sample detail. */ + /* Average the edge length of the connected edges to the active vertex */ + int active_vertex = sculpt_active_vertex_get(ss); + const float *active_vertex_co = sculpt_active_vertex_co_get(ss); + float edge_length = 0.0f; + int tot = 0; + SculptVertexNeighborIter ni; + sculpt_vertex_neighbors_iter_begin(ss, active_vertex, ni) + { + edge_length += len_v3v3(active_vertex_co, sculpt_vertex_co_get(ss, ni.index)); + tot += 1; + } + sculpt_vertex_neighbors_iter_end(ni); + if (tot > 0) { + mesh->remesh_voxel_size = edge_length / (float)tot; + } +} + +static void sample_detail_dyntopo(bContext *C, ViewContext *vc, ARegion *ar, int mx, int my) +{ Sculpt *sd = CTX_data_tool_settings(C)->sculpt; - Object *ob = vc.obact; + Object *ob = vc->obact; Brush *brush = BKE_paint_brush(&sd->paint); sculpt_stroke_modifiers_check(C, ob, brush); float mouse[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; float ray_start[3], ray_end[3], ray_normal[3]; - float depth = sculpt_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, false); + float depth = sculpt_raycast_init(vc, mouse, ray_start, ray_end, ray_normal, false); SculptDetailRaycastData srd; srd.hit = 0; @@ -8489,6 +8513,37 @@ static void sample_detail(bContext *C, int mx, int my) /* Convert edge length to world space detail resolution. */ sd->constant_detail = 1 / (srd.edge_length * mat4_to_scale(ob->obmat)); } +} + +static void sample_detail(bContext *C, int mx, int my, int mode) +{ + /* Find 3D view to pick from. */ + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_VIEW3D, mx, my); + ARegion *ar = (sa) ? BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my) : NULL; + if (ar == NULL) { + return; + } + + /* Set context to 3D view. */ + ScrArea *prev_sa = CTX_wm_area(C); + ARegion *prev_ar = CTX_wm_region(C); + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, ar); + + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + ViewContext vc; + ED_view3d_viewcontext_init(C, &vc, depsgraph); + + /* Pick sample detail. */ + switch (mode) { + case SAMPLE_DETAIL_DYNTOPO: + sample_detail_dyntopo(C, &vc, ar, mx, my); + break; + case SAMPLE_DETAIL_VOXEL: + sample_detail_voxel(C, &vc, mx, my); + break; + } /* Restore context. */ CTX_wm_area_set(C, prev_sa); @@ -8499,7 +8554,8 @@ static int sculpt_sample_detail_size_exec(bContext *C, wmOperator *op) { int ss_co[2]; RNA_int_get_array(op->ptr, "location", ss_co); - sample_detail(C, ss_co[0], ss_co[1]); + int mode = RNA_enum_get(op->ptr, "mode"); + sample_detail(C, ss_co[0], ss_co[1], mode); return OPERATOR_FINISHED; } @@ -8518,7 +8574,8 @@ static int sculpt_sample_detail_size_modal(bContext *C, wmOperator *op, const wm if (event->val == KM_PRESS) { int ss_co[2] = {event->x, event->y}; - sample_detail(C, ss_co[0], ss_co[1]); + int mode = RNA_enum_get(op->ptr, "mode"); + sample_detail(C, ss_co[0], ss_co[1], mode); RNA_int_set_array(op->ptr, "location", ss_co); WM_cursor_modal_restore(CTX_wm_window(C)); @@ -8551,7 +8608,7 @@ static void SCULPT_OT_sample_detail_size(wmOperatorType *ot) ot->invoke = sculpt_sample_detail_size_invoke; ot->exec = sculpt_sample_detail_size_exec; ot->modal = sculpt_sample_detail_size_modal; - ot->poll = sculpt_and_constant_or_manual_detail_poll; + ot->poll = sculpt_mode_poll; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -8565,6 +8622,12 @@ static void SCULPT_OT_sample_detail_size(wmOperatorType *ot) "Screen Coordinates of sampling", 0, SHRT_MAX); + RNA_def_enum(ot->srna, + "mode", + prop_sculpt_sample_detail_mode_types, + SAMPLE_DETAIL_DYNTOPO, + "Detail Mode", + "Target sculpting workflow that is going to use the sampled size"); } /* Dynamic-topology detail size -- cgit v1.2.3 From 9e3006e5079cc3dd65ab755301feda4f603804b4 Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Sun, 24 Nov 2019 21:20:27 +0100 Subject: Clay Brush: Input curves and update defaults Updated defaults and pressure/size curves for the Clay brush. Reviewed By: jbakker Differential Revision: https://developer.blender.org/D6298 --- source/blender/blenkernel/intern/brush.c | 4 +++- source/blender/editors/sculpt_paint/sculpt.c | 11 +++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index a64da8f6606..8b90eafdddf 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -931,7 +931,9 @@ void BKE_brush_sculpt_reset(Brush *br) br->alpha = 1.0f; break; case SCULPT_TOOL_CLAY: - br->spacing = 6; + br->flag |= BRUSH_SIZE_PRESSURE; + br->spacing = 3; + br->autosmooth_factor = 0.25f; br->normal_radius_factor = 0.75f; break; case SCULPT_TOOL_CLAY_STRIPS: diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 63b9949e0ef..9eb32a9f731 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1741,8 +1741,9 @@ static float brush_strength(const Sculpt *sd, switch (brush->sculpt_tool) { case SCULPT_TOOL_CLAY: + final_pressure = pow4f(pressure); overlap = (1.0f + overlap) / 2.0f; - return 0.25f * alpha * flip * pressure * overlap * feather; + return 0.25f * alpha * flip * final_pressure * overlap * feather; case SCULPT_TOOL_DRAW: case SCULPT_TOOL_DRAW_SHARP: case SCULPT_TOOL_LAYER: @@ -4659,7 +4660,6 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata, if (sculpt_brush_test_sq_fn(&test, vd.co)) { float intr[3]; float val[3]; - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); sub_v3_v3v3(val, intr, vd.co); @@ -4695,6 +4695,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) Brush *brush = BKE_paint_brush(&sd->paint); const float radius = fabsf(ss->cache->radius); + const float initial_radius = fabsf(ss->cache->initial_radius); bool flip = ss->cache->bstrength < 0.0f; float offset = get_offset(sd, ss); @@ -4730,7 +4731,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) d_offset = min_ff(radius, d_offset); d_offset = d_offset / radius; d_offset = 1.0f - d_offset; - displace = fabsf(radius * (0.25f + offset + (d_offset * 0.15f))); + displace = fabsf(initial_radius * (0.25f + offset + (d_offset * 0.15f))); if (flip) { displace = -displace; } @@ -6514,8 +6515,10 @@ static void sculpt_update_cache_invariants( static float sculpt_brush_dynamic_size_get(Brush *brush, StrokeCache *cache, float initial_size) { switch (brush->sculpt_tool) { + case SCULPT_TOOL_CLAY: + return max_ff(initial_size * 0.20f, initial_size * pow3f(cache->pressure)); case SCULPT_TOOL_CLAY_STRIPS: - return max_ff(initial_size * 0.35f, initial_size * cache->pressure * cache->pressure); + return max_ff(initial_size * 0.35f, initial_size * pow2f(cache->pressure)); default: return initial_size * cache->pressure; } -- cgit v1.2.3 From 34902f200890d812edfd96e838e03241f5b3eedc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 28 Nov 2019 04:16:38 +1100 Subject: Fix crash exiting edit-mode with an active basis shape key Exposed by T71865, while the bug remains this resolves the crash. --- source/blender/bmesh/intern/bmesh_mesh_conv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 9bab959f0a2..5f0c673b379 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -879,7 +879,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { const int keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset); - if (keyi != ORIGINDEX_NONE) { + if (keyi != ORIGINDEX_NONE && keyi < actkey->totelem) { sub_v3_v3v3(ofs[i], mvert->co, fp[keyi]); } else { -- cgit v1.2.3 From 9c4cec2de9582e9f817af7320f77ee136db29adb Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Wed, 27 Nov 2019 15:06:41 -0300 Subject: Fix T71000: Statistics don't take collections hidden state into account Simple fix, to mimic what we had pre-local collections. So this is not fully representative of the current load of the scene. I started a more complex route where we literally just count objects that are visible (taking object type restriction, local collections, local view, ...). But in the end it is a bit overkill considering that we have plans to change the statistics. --- source/blender/editors/space_info/info_stats.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index b51aec90e4f..225ca72a7d0 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -123,6 +123,10 @@ static bool stats_mesheval(Mesh *me_eval, bool is_selected, SceneStats *stats) static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset) { + if ((ob->base_flag & BASE_VISIBLE_VIEWLAYER) == 0) { + return; + } + const bool is_selected = (ob->base_flag & BASE_SELECTED) != 0; stats->totobj++; -- cgit v1.2.3 From e7502ee0aa8e27247689ef8debccaaa3b8b056bf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 28 Nov 2019 06:12:00 +1100 Subject: Cleanup: bmesh conversion comments --- source/blender/bmesh/intern/bmesh_mesh_conv.c | 158 +++++++++++++------------- 1 file changed, 81 insertions(+), 77 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 5f0c673b379..9bcc9b9e84b 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -91,7 +91,7 @@ #include "BKE_key.h" #include "bmesh.h" -#include "intern/bmesh_private.h" /* for element checking */ +#include "intern/bmesh_private.h" /* For element checking. */ void BM_mesh_cd_flag_ensure(BMesh *bm, Mesh *mesh, const char cd_flag) { @@ -202,7 +202,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar CustomData_MeshMasks_update(&mask, ¶ms->cd_mask_extra); if (!me || !me->totvert) { - if (me && is_new) { /*no verts? still copy customdata layout*/ + if (me && is_new) { /* No verts? still copy custom-data layout. */ CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_ASSIGN, 0); CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_ASSIGN, 0); CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_ASSIGN, 0); @@ -213,7 +213,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP); CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE); } - return; /* sanity check */ + return; /* Sanity check. */ } if (is_new) { @@ -254,9 +254,8 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar if (tot_shape_keys) { if (is_new) { - /* check if we need to generate unique ids for the shapekeys. - * this also exists in the file reading code, but is here for - * a sanity check */ + /* Check if we need to generate unique ids for the shape-keys. + * This also exists in the file reading code, but is here for a sanity check. */ if (!me->key->uidgen) { fprintf(stderr, "%s had to generate shape key uid's in a situation we shouldn't need to! " @@ -310,10 +309,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar v = vtable[i] = BM_vert_create(bm, keyco ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD); BM_elem_index_set(v, i); /* set_ok */ - /* transfer flag */ + /* Transfer flag. */ v->head.hflag = BM_vert_flag_from_mflag(mvert->flag & ~SELECT); - /* this is necessary for selection counts to work properly */ + /* This is necessary for selection counts to work properly. */ if (mvert->flag & SELECT) { BM_vert_select_set(bm, v, true); } @@ -327,12 +326,12 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mvert->bweight / 255.0f); } - /* set shape key original index */ + /* Set shape key original index. */ if (cd_shape_keyindex_offset != -1) { BM_ELEM_CD_SET_INT(v, cd_shape_keyindex_offset, i); } - /* set shapekey data */ + /* Set shape-key data. */ if (tot_shape_keys) { float(*co_dst)[3] = BM_ELEM_CD_GET_VOID_P(v, cd_shape_key_offset); for (int j = 0; j < tot_shape_keys; j++, co_dst++) { @@ -341,7 +340,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar } } if (is_new) { - bm->elem_index_dirty &= ~BM_VERT; /* added in order, clear dirty flag */ + bm->elem_index_dirty &= ~BM_VERT; /* Added in order, clear dirty flag. */ } etable = MEM_mallocN(sizeof(BMEdge **) * me->totedge, __func__); @@ -352,10 +351,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar bm, vtable[medge->v1], vtable[medge->v2], NULL, BM_CREATE_SKIP_CD); BM_elem_index_set(e, i); /* set_ok */ - /* transfer flags */ + /* Transfer flags. */ e->head.hflag = BM_edge_flag_from_mflag(medge->flag & ~SELECT); - /* this is necessary for selection counts to work properly */ + /* This is necessary for selection counts to work properly. */ if (medge->flag & SELECT) { BM_edge_select_set(bm, e, true); } @@ -371,10 +370,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar } } if (is_new) { - bm->elem_index_dirty &= ~BM_EDGE; /* added in order, clear dirty flag */ + bm->elem_index_dirty &= ~BM_EDGE; /* Added in order, clear dirty flag. */ } - /* only needed for selection. */ + /* Only needed for selection. */ if (me->mselect && me->totselect != 0) { ftable = MEM_mallocN(sizeof(BMFace **) * me->totpoly, __func__); } @@ -400,13 +399,13 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar continue; } - /* don't use 'i' since we may have skipped the face */ + /* Don't use 'i' since we may have skipped the face. */ BM_elem_index_set(f, bm->totface - 1); /* set_ok */ - /* transfer flag */ + /* Transfer flag. */ f->head.hflag = BM_face_flag_from_mflag(mp->flag & ~ME_FACE_SEL); - /* this is necessary for selection counts to work properly */ + /* This is necessary for selection counts to work properly. */ if (mp->flag & ME_FACE_SEL) { BM_face_select_set(bm, f, true); } @@ -419,7 +418,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar int j = mp->loopstart; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - /* don't use 'j' since we may have skipped some faces, hence some loops. */ + /* Don't use 'j' since we may have skipped some faces, hence some loops. */ BM_elem_index_set(l_iter, totloops++); /* set_ok */ /* Save index of corresponding #MLoop. */ @@ -434,7 +433,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar } } if (is_new) { - bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* added in order, clear dirty flag */ + bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* Added in order, clear dirty flag. */ } /* -------------------------------------------------------------------- */ @@ -489,7 +488,7 @@ static BMVert **bm_to_mesh_vertex_map(BMesh *bm, int ototvert) int i = 0; BMIter iter; - /* caller needs to ensure this */ + /* Caller needs to ensure this. */ BLI_assert(ototvert > 0); vertMap = MEM_callocN(sizeof(*vertMap) * ototvert, "vertMap"); @@ -497,7 +496,7 @@ static BMVert **bm_to_mesh_vertex_map(BMesh *bm, int ototvert) BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { const int keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset); if ((keyi != ORIGINDEX_NONE) && (keyi < ototvert) && - /* not fool-proof, but chances are if we have many verts with the same index, + /* Not fool-proof, but chances are if we have many verts with the same index, * we will want to use the first one, * since the second is more likely to be a duplicate. */ (vertMap[keyi] == NULL)) { @@ -520,8 +519,9 @@ static BMVert **bm_to_mesh_vertex_map(BMesh *bm, int ototvert) } /** - * returns customdata shapekey index from a keyblock or -1 - * \note could split this out into a more generic function */ + * Returns custom-data shapekey index from a keyblock or -1 + * \note could split this out into a more generic function. + */ static int bm_to_mesh_shape_layer_index_from_kb(BMesh *bm, KeyBlock *currkey) { int i; @@ -540,12 +540,12 @@ static int bm_to_mesh_shape_layer_index_from_kb(BMesh *bm, KeyBlock *currkey) BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e) { - /* this is a cheap way to set the edge draw, its not precise and will + /* This is a cheap way to set the edge draw, its not precise and will * pick the first 2 faces an edge uses. * The dot comparison is a little arbitrary, but set so that a 5 subd - * IcoSphere won't vanish but subd 6 will (as with pre-bmesh blender) */ + * IcoSphere won't vanish but subd 6 will (as with pre-bmesh Blender). */ - if (/* (med->flag & ME_EDGEDRAW) && */ /* assume to be true */ + if (/* (med->flag & ME_EDGEDRAW) && */ /* Assume to be true. */ (e->l && (e->l != e->l->radial_next)) && (dot_v3v3(e->l->f->no, e->l->radial_next->f->no) > 0.9995f)) { med->flag &= ~ME_EDGEDRAW; @@ -577,7 +577,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh ototvert = me->totvert; - /* new vertex block */ + /* New vertex block. */ if (bm->totvert == 0) { mvert = NULL; } @@ -585,7 +585,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh mvert = MEM_callocN(bm->totvert * sizeof(MVert), "loadeditbMesh vert"); } - /* new edge block */ + /* New edge block. */ if (bm->totedge == 0) { medge = NULL; } @@ -593,7 +593,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh medge = MEM_callocN(bm->totedge * sizeof(MEdge), "loadeditbMesh edge"); } - /* new ngon face block */ + /* New ngon face block. */ if (bm->totface == 0) { mpoly = NULL; } @@ -601,7 +601,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh mpoly = MEM_callocN(bm->totface * sizeof(MPoly), "loadeditbMesh poly"); } - /* new loop block */ + /* New loop block. */ if (bm->totloop == 0) { mloop = NULL; } @@ -609,25 +609,24 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh mloop = MEM_callocN(bm->totloop * sizeof(MLoop), "loadeditbMesh loop"); } - /* lets save the old verts just in case we are actually working on - * a key ... we now do processing of the keys at the end */ + /* Lets save the old verts just in case we are actually working on + * a key ... we now do processing of the keys at the end. */ oldverts = MEM_dupallocN(me->mvert); - /* free custom data */ + /* Free custom data. */ CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); CustomData_free(&me->ldata, me->totloop); CustomData_free(&me->pdata, me->totpoly); - /* add new custom data */ + /* Add new custom data. */ me->totvert = bm->totvert; me->totedge = bm->totedge; me->totloop = bm->totloop; me->totpoly = bm->totface; - /* will be overwritten with a valid value if 'dotess' is set, otherwise we - * end up with 'me->totface' and me->mface == NULL which can crash [#28625] - */ + /* Will be overwritten with a valid value if 'dotess' is set, otherwise we + * end up with 'me->totface' and me->mface == NULL which can crash T28625. */ me->totface = 0; me->act_face = -1; @@ -647,7 +646,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm); - /* this is called again, 'dotess' arg is used there */ + /* This is called again, 'dotess' arg is used there. */ BKE_mesh_update_customdata_pointers(me, 0); i = 0; @@ -659,7 +658,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh BM_elem_index_set(v, i); /* set_inline */ - /* copy over customdat */ + /* Copy over custom-data. */ CustomData_from_bmesh_block(&bm->vdata, &me->vdata, v->head.data, i); if (cd_vert_bweight_offset != -1) { @@ -683,7 +682,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh BM_elem_index_set(e, i); /* set_inline */ - /* copy over customdata */ + /* Copy over custom-data. */ CustomData_from_bmesh_block(&bm->edata, &me->edata, e->head.data, i); bmesh_quick_edgedraw_flag(med, e); @@ -715,7 +714,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh mloop->e = BM_elem_index_get(l_iter->e); mloop->v = BM_elem_index_get(l_iter->v); - /* copy over customdata */ + /* Copy over custom-data. */ CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l_iter->head.data, j); j++; @@ -729,7 +728,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh me->act_face = i; } - /* copy over customdata */ + /* Copy over custom-data. */ CustomData_from_bmesh_block(&bm->pdata, &me->pdata, f->head.data, i); i++; @@ -737,7 +736,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh BM_CHECK_ELEMENT(f); } - /* patch hook indices and vertex parents */ + /* Patch hook indices and vertex parents. */ if (params->calc_object_remap && (ototvert > 0)) { BLI_assert(bmain != NULL); Object *ob; @@ -829,7 +828,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh } } - /* see comment below, this logic is in twice */ + /* See comment below, this logic is in twice. */ if (me->key) { const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX); @@ -839,9 +838,8 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh float(*ofs)[3] = NULL; - /* go through and find any shapekey customdata layers - * that might not have corresponding KeyBlocks, and add them if - * necessary */ + /* Go through and find any shape-key custom-data layers + * that might not have corresponding KeyBlocks, and add them if necessary. */ j = 0; for (i = 0; i < bm->vdata.totlayer; i++) { if (bm->vdata.layers[i].type != CD_SHAPEKEY) { @@ -862,30 +860,36 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh j++; } - /* editing the base key should update others */ - if ((me->key->type == KEY_RELATIVE) && /* only need offsets for relative shape keys */ - (actkey != NULL) && /* unlikely, but the active key may not be valid if the - * bmesh and the mesh are out of sync */ - (oldverts != NULL)) /* not used here, but 'oldverts' is used later for applying 'ofs' */ - { + /* Editing the base key should update others. */ + if (/* Only need offsets for relative shape keys. */ + (me->key->type == KEY_RELATIVE) && + + /* Unlikely, but the active key may not be valid if the + * BMesh and the mesh are out of sync. */ + (actkey != NULL) && + + /* Not used here, but 'oldverts' is used later for applying 'ofs'. */ + (oldverts != NULL)) { + const bool act_is_basis = BKE_keyblock_is_basis(me->key, bm->shapenr - 1); - /* active key is a base */ + /* Active key is a base. */ if (act_is_basis && (cd_shape_keyindex_offset != -1)) { - float(*fp)[3] = actkey->data; + const float(*fp)[3] = actkey->data; ofs = MEM_callocN(sizeof(float) * 3 * bm->totvert, "currkey->data"); mvert = me->mvert; BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { const int keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset); + /* Could use 'eve->co' or 'mvert->co', they're the same at this point. */ if (keyi != ORIGINDEX_NONE && keyi < actkey->totelem) { sub_v3_v3v3(ofs[i], mvert->co, fp[keyi]); } else { - /* if there are new vertices in the mesh, we can't propagate the offset + /* If there are new vertices in the mesh, we can't propagate the offset * because it will only work for the existing vertices and not the new - * ones, creating a mess when doing e.g. subdivide + translate */ + * ones, creating a mess when doing e.g. subdivide + translate. */ MEM_freeN(ofs); ofs = NULL; break; @@ -901,7 +905,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh (bm->shapenr - 1 == currkey->relative)); int cd_shape_offset; int keyi; - float(*ofs_pt)[3] = ofs; + const float(*ofs_pt)[3] = ofs; float *newkey, (*oldkey)[3], *fp; j = bm_to_mesh_shape_layer_index_from_kb(bm, currkey); @@ -916,11 +920,11 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh if (currkey == actkey) { copy_v3_v3(fp, eve->co); - if (actkey != me->key->refkey) { /* important see bug [#30771] */ + if (actkey != me->key->refkey) { /* Important see bug T30771. */ if (cd_shape_keyindex_offset != -1) { if (oldverts) { keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset); - if (keyi != ORIGINDEX_NONE && keyi < currkey->totelem) { /* valid old vertex */ + if (keyi != ORIGINDEX_NONE && keyi < currkey->totelem) { /* Valid old vertex. */ copy_v3_v3(mvert->co, oldverts[keyi].co); } } @@ -928,29 +932,29 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh } } else if (j != -1) { - /* in most cases this runs */ + /* In most cases this runs. */ copy_v3_v3(fp, BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset)); } else if ((oldkey != NULL) && (cd_shape_keyindex_offset != -1) && ((keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset)) != ORIGINDEX_NONE) && (keyi < currkey->totelem)) { - /* old method of reconstructing keys via vertice's original key indices, - * currently used if the new method above fails (which is theoretically - * possible in certain cases of undo) */ + /* Old method of reconstructing keys via vertice's original key indices, + * currently used if the new method above fails + * (which is theoretically possible in certain cases of undo). */ copy_v3_v3(fp, oldkey[keyi]); } else { - /* fail! fill in with dummy value */ + /* Fail! fill in with dummy value. */ copy_v3_v3(fp, mvert->co); } - /* propagate edited basis offsets to other shapes */ + /* Propagate edited basis offsets to other shapes. */ if (apply_offset) { add_v3_v3(fp, *ofs_pt++); - /* Apply back new coordinates of offsetted shapekeys into BMesh. + /* Apply back new coordinates of offsetted shape-keys into BMesh. * Otherwise, in case we call again BM_mesh_bm_to_me on same BMesh, * we'll apply diff from previous call to BM_mesh_bm_to_me, - * to shapekey values from *original creation of the BMesh*. See T50524. */ + * to shape-key values from *original creation of the BMesh*. See T50524. */ copy_v3_v3(BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset), fp); } @@ -974,10 +978,10 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh MEM_freeN(oldverts); } - /* topology could be changed, ensure mdisps are ok */ + /* Topology could be changed, ensure mdisps are ok. */ multires_topology_changed(me); - /* to be removed as soon as COW is enabled by default. */ + /* To be removed as soon as COW is enabled by default.. */ BKE_mesh_runtime_clear_geometry(me); } @@ -1000,7 +1004,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh */ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *cd_mask_extra) { - /* must be an empty mesh. */ + /* Must be an empty mesh. */ BLI_assert(me->totvert == 0); BLI_assert(cd_mask_extra == NULL || (cd_mask_extra->vmask & CD_MASK_SHAPEKEY) == 0); @@ -1019,8 +1023,8 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, bm->totloop); CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, bm->totface); - /* don't process shapekeys, we only feed them through the modifier stack as needed, - * e.g. for applying modifiers or the like*/ + /* Don't process shape-keys, we only feed them through the modifier stack as needed, + * e.g. for applying modifiers or the like. */ CustomData_MeshMasks mask = CD_MASK_DERIVEDMESH; if (cd_mask_extra != NULL) { CustomData_MeshMasks_update(&mask, cd_mask_extra); @@ -1050,7 +1054,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * me->runtime.deformed_only = true; - /* don't add origindex layer if one already exists */ + /* Don't add origindex layer if one already exists. */ add_orig = !CustomData_has_layer(&bm->pdata, CD_ORIGINDEX); index = CustomData_get_layer(&me->vdata, CD_ORIGINDEX); @@ -1089,8 +1093,8 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * med->flag = BM_edge_flag_to_mflag(eed); - /* handle this differently to editmode switching, - * only enable draw for single user edges rather then calculating angle */ + /* Handle this differently to editmode switching, + * only enable draw for single user edges rather then calculating angle. */ if ((med->flag & ME_EDGEDRAW) == 0) { if (eed->l && eed->l == eed->l->radial_next) { med->flag |= ME_EDGEDRAW; -- cgit v1.2.3 From 7711231838e726055c6690757f3799dff90bfd96 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 28 Nov 2019 06:12:17 +1100 Subject: Fix T71865: Separating mesh parts breaks shape keys This was an old bug which could be caused by saving after separating. Changes from 79b703bb635e made this fail reliably. Update shape key indices when they may be used again later. --- source/blender/blenkernel/intern/scene.c | 1 + source/blender/bmesh/intern/bmesh_mesh_conv.c | 10 ++++++++++ source/blender/bmesh/intern/bmesh_mesh_conv.h | 10 ++++++++++ source/blender/editors/include/ED_mesh.h | 1 + source/blender/editors/mesh/editmesh_tools.c | 7 ++++++- source/blender/editors/mesh/editmesh_undo.c | 1 + source/blender/editors/mesh/editmesh_utils.c | 8 +++++++- source/blender/editors/object/object_edit.c | 2 +- source/blender/python/bmesh/bmesh_py_types.c | 4 +++- 9 files changed, 40 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 9dcebbba56e..ab72b7d3b0d 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1284,6 +1284,7 @@ static void prepare_mesh_for_viewport_render(Main *bmain, const ViewLayer *view_ mesh, (&(struct BMeshToMeshParams){ .calc_object_remap = true, + .update_shapekey_indices = true, })); DEG_id_tag_update(&mesh->id, 0); } diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 9bcc9b9e84b..4e65ac40dd4 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -972,6 +972,16 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh if (ofs) { MEM_freeN(ofs); } + + if (params->update_shapekey_indices) { + /* We have written a new shape key, if this mesh is _not_ going to be freed, + * update the shape key indices to match the newly updated. */ + if (cd_shape_keyindex_offset != -1) { + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { + BM_ELEM_CD_SET_INT(eve, cd_shape_keyindex_offset, i); + } + } + } } if (oldverts != NULL) { diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h index f0302764a5f..65d5c6d5494 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.h +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h @@ -48,6 +48,16 @@ void BM_mesh_bm_from_me(BMesh *bm, const struct Mesh *me, const struct BMeshFrom struct BMeshToMeshParams { /** Update object hook indices & vertex parents. */ uint calc_object_remap : 1; + /** + * This re-assigns shape-key indices. Only do if the BMesh will have continued use + * to update the mesh & shape key in the future. + * In the case the BMesh is freed immediately, this can be left false. + * + * This is needed when flushing changes from edit-mode into object mode, + * so a second flush or edit-mode exit doesn't run with indices + * that have become invalid from updating the shape-key, see T71865. + */ + uint update_shapekey_indices : 1; struct CustomData_MeshMasks cd_mask_extra; }; void BM_mesh_bm_to_me(struct Main *bmain, diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 835e1b4e26f..4bf43a2034a 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -83,6 +83,7 @@ void EDBM_mesh_clear(struct BMEditMesh *em); void EDBM_selectmode_to_scene(struct bContext *C); void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool add_key_index); void EDBM_mesh_free(struct BMEditMesh *em); +void EDBM_mesh_load_ex(struct Main *bmain, struct Object *ob, bool free_data); void EDBM_mesh_load(struct Main *bmain, struct Object *ob); /* flushes based on the current select mode. if in vertex select mode, diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 8df392fb04b..59090acf433 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -4197,7 +4197,12 @@ static bool mesh_separate_loose( BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); if (clear_object_data) { - BM_mesh_bm_to_me(NULL, bm_old, me_old, (&(struct BMeshToMeshParams){0})); + BM_mesh_bm_to_me(NULL, + bm_old, + me_old, + (&(struct BMeshToMeshParams){ + .update_shapekey_indices = true, + })); } finally: diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 44984251243..d07ba05de20 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -521,6 +521,7 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key) (&(struct BMeshToMeshParams){ /* Undo code should not be manipulating 'G_MAIN->object' hooks/vertex-parent. */ .calc_object_remap = false, + .update_shapekey_indices = false, .cd_mask_extra = {.vmask = CD_MASK_SHAPE_KEYINDEX}, })); diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 522c2f32d27..42404554ed8 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -325,7 +325,7 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index) * \warning This can invalidate the #Mesh runtime cache of other objects (for linked duplicates). * Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913 */ -void EDBM_mesh_load(Main *bmain, Object *ob) +void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data) { Mesh *me = ob->data; BMesh *bm = me->edit_mesh->bm; @@ -341,6 +341,7 @@ void EDBM_mesh_load(Main *bmain, Object *ob) me, (&(struct BMeshToMeshParams){ .calc_object_remap = true, + .update_shapekey_indices = !free_data, })); /* Free derived mesh. usually this would happen through depsgraph but there @@ -380,6 +381,11 @@ void EDBM_mesh_clear(BMEditMesh *em) } } +void EDBM_mesh_load(Main *bmain, Object *ob) +{ + EDBM_mesh_load_ex(bmain, ob, true); +} + /** * Should only be called on the active editmesh, otherwise call #BKE_editmesh_free */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index be815fb0d10..b7c9579e277 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -445,7 +445,7 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f return false; } - EDBM_mesh_load(bmain, obedit); + EDBM_mesh_load_ex(bmain, obedit, freedata); if (freedata) { EDBM_mesh_free(me->edit_mesh); diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index af595de2ee4..b601a35f7f2 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -1091,7 +1091,9 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args) bm = self->bm; struct Main *bmain = NULL; - struct BMeshToMeshParams params = {0}; + struct BMeshToMeshParams params = { + .update_shapekey_indices = true, + }; if (me->id.tag & LIB_TAG_NO_MAIN) { /* Mesh might be coming from a self-contained source like object.to_mesh(). No need to remap * anything in this case. */ -- cgit v1.2.3 From 4659fa547166b589cc8e3aef4b8dc699d95547df Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Wed, 27 Nov 2019 21:22:55 +0100 Subject: Cycles: Scale denoising albedo contribution of Principled BSDFs according to average fresnel The Principled BSDF uses Microfacet closures that include a fresnel term, which are a special case since their weight tends to be near white even if their average contribution is fairly low. The sample weight is scaled by the average fresnel weight to account for this, but the denoising albedo still used the unscaled weight. This was fine for the original denoiser, but apparently OIDN can't handle the resulting albedo pass well. Therefore, this commit adds the described scaling to the albedo pass contribution as well. This problem was described in T69770. Reviewed By: brecht Differential Revision: https://developer.blender.org/D6289 --- intern/cycles/kernel/closure/bsdf_microfacet.h | 35 ++++++++++++++-------- .../cycles/kernel/closure/bsdf_microfacet_multi.h | 12 ++------ intern/cycles/kernel/kernel_passes.h | 12 +++++++- intern/cycles/kernel/svm/svm_types.h | 6 ++++ 4 files changed, 43 insertions(+), 22 deletions(-) diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index 2f73434706c..2884ea62a18 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -37,6 +37,7 @@ CCL_NAMESPACE_BEGIN typedef ccl_addr_space struct MicrofacetExtra { float3 color, cspec0; + float3 fresnel_color; float clearcoat; } MicrofacetExtra; @@ -276,6 +277,22 @@ ccl_device_forceinline float D_GTR1(float NdotH, float alpha) return (alpha2 - 1.0f) / (M_PI_F * logf(alpha2) * t); } +ccl_device_forceinline void bsdf_microfacet_fresnel_color(const ShaderData *sd, + MicrofacetBsdf *bsdf) +{ + kernel_assert(CLOSURE_IS_BSDF_MICROFACET_FRESNEL(bsdf->type)); + + float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); + bsdf->extra->fresnel_color = interpolate_fresnel_color( + sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0); + + if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { + bsdf->extra->fresnel_color *= 0.25f * bsdf->extra->clearcoat; + } + + bsdf->sample_weight *= average(bsdf->extra->fresnel_color); +} + /* GGX microfacet with Smith shadow-masking from: * * Microfacet Models for Refraction through Rough Surfaces @@ -305,15 +322,13 @@ ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const Sha { bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0); - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; - bsdf->alpha_x = saturate(bsdf->alpha_x); bsdf->alpha_y = bsdf->alpha_x; bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID; + bsdf_microfacet_fresnel_color(sd, bsdf); + return SD_BSDF | SD_BSDF_HAS_EVAL; } @@ -321,15 +336,13 @@ ccl_device int bsdf_microfacet_ggx_clearcoat_setup(MicrofacetBsdf *bsdf, const S { bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0); - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= 0.25f * bsdf->extra->clearcoat * F; - bsdf->alpha_x = saturate(bsdf->alpha_x); bsdf->alpha_y = bsdf->alpha_x; bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID; + bsdf_microfacet_fresnel_color(sd, bsdf); + return SD_BSDF | SD_BSDF_HAS_EVAL; } @@ -364,15 +377,13 @@ ccl_device int bsdf_microfacet_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, con { bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0); - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; - bsdf->alpha_x = saturate(bsdf->alpha_x); bsdf->alpha_y = saturate(bsdf->alpha_y); bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID; + bsdf_microfacet_fresnel_color(sd, bsdf); + return SD_BSDF | SD_BSDF_HAS_EVAL; } diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h index 9780dd87415..a5fe989bcd1 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h @@ -402,9 +402,7 @@ ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsd bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID; - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; + bsdf_microfacet_fresnel_color(sd, bsdf); return bsdf_microfacet_multi_ggx_common_setup(bsdf); } @@ -424,9 +422,7 @@ ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf, con bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID; - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; + bsdf_microfacet_fresnel_color(sd, bsdf); return bsdf_microfacet_multi_ggx_common_setup(bsdf); } @@ -582,9 +578,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsd bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID; - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; + bsdf_microfacet_fresnel_color(sd, bsdf); return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG; } diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index c1d74dddc2a..3e423e42573 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -145,7 +145,17 @@ ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg, normal += sc->N * sc->sample_weight; sum_weight += sc->sample_weight; if (bsdf_get_specular_roughness_squared(sc) > sqr(0.075f)) { - albedo += sc->weight; + float3 closure_albedo = sc->weight; + /* Closures that include a Fresnel term typically have weights close to 1 even though their + * actual contribution is significantly lower. + * To account for this, we scale their weight by the average fresnel factor (the same is also + * done for the sample weight in the BSDF setup, so we don't need to scale that here). */ + if (CLOSURE_IS_BSDF_MICROFACET_FRESNEL(sc->type)) { + MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc; + closure_albedo *= bsdf->extra->fresnel_color; + } + + albedo += closure_albedo; sum_nonspecular_weight += sc->sample_weight; } } diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 01710f713ac..aa4dfdca2d1 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -552,6 +552,12 @@ typedef enum ClosureType { (type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && \ type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) || \ (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID)) +#define CLOSURE_IS_BSDF_MICROFACET_FRESNEL(type) \ + (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID || \ + type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID || \ + type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID || \ + type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID || \ + type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID) #define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID) #define CLOSURE_IS_BSSRDF(type) \ (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID) -- cgit v1.2.3 From 6288dbffb6c1f98a04f7c25ed96caa963e5c8819 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 28 Nov 2019 15:06:04 +1100 Subject: NDOF: support panning when orbiting Also make orbit the default rotation mode. Based on feedback from T67579, this seems one of the main pain points users are experiencing. --- release/datafiles/userdef/userdef_default.c | 3 ++- source/blender/editors/space_view3d/view3d_edit.c | 11 +++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/release/datafiles/userdef/userdef_default.c b/release/datafiles/userdef/userdef_default.c index d8b87480f29..93ddc43cf15 100644 --- a/release/datafiles/userdef/userdef_default.c +++ b/release/datafiles/userdef/userdef_default.c @@ -153,7 +153,8 @@ const UserDef U_default = { .ndof_sensitivity = 1.0, .ndof_orbit_sensitivity = 1.0, .ndof_deadzone = 0.1, - .ndof_flag = (NDOF_LOCK_HORIZON | NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM | NDOF_SHOULD_ROTATE), + .ndof_flag = (NDOF_MODE_ORBIT | NDOF_LOCK_HORIZON | NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM | + NDOF_SHOULD_ROTATE), .ogl_multisamples = 0, .image_draw_method = IMAGE_DRAW_METHOD_AUTO, .glalphaclip = 0.004, diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 3ad194a5d2b..67f23012d10 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1432,11 +1432,18 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev } } else if ((U.ndof_flag & NDOF_MODE_ORBIT) || ED_view3d_offset_lock_check(v3d, rv3d)) { + /* Note: based on feedback from T67579, users want to have pan and orbit enabled at once. + * It's arguable that orbit shouldn't pan (since we have a pan only operator), + * so if there are users who like to separate orbit/pan operations - it can be a preference. + * + * Also, the 'orbit' and 'free' blocks of code are now very similar. + * these could be merged, keep separate until design issues are sorted out - Campbell. */ const bool has_rotation = NDOF_HAS_ROTATE; + const bool has_translate = !is_zero_v2(ndof->tvec) && NDOF_HAS_TRANSLATE; const bool has_zoom = (ndof->tvec[2] != 0.0f); - if (has_zoom) { - view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, false, has_zoom); + if (has_translate || has_zoom) { + view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, has_zoom); xform_flag |= HAS_TRANSLATE; } -- cgit v1.2.3 From 716c08903219ad57dcb4a2d970065a7b84c5aef7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 28 Nov 2019 17:33:53 +1100 Subject: Fix separating mesh parts breaking vertex parents & hooks Follow up on T71865 which only reported the issue for shape keys. --- source/blender/bmesh/intern/bmesh_mesh_conv.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 4e65ac40dd4..3942cdd27fb 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -574,6 +574,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); + const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX); ototvert = me->totvert; @@ -831,8 +832,6 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh /* See comment below, this logic is in twice. */ if (me->key) { - const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX); - KeyBlock *currkey; KeyBlock *actkey = BLI_findlink(&me->key->block, bm->shapenr - 1); @@ -972,14 +971,15 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh if (ofs) { MEM_freeN(ofs); } + } - if (params->update_shapekey_indices) { - /* We have written a new shape key, if this mesh is _not_ going to be freed, - * update the shape key indices to match the newly updated. */ - if (cd_shape_keyindex_offset != -1) { - BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - BM_ELEM_CD_SET_INT(eve, cd_shape_keyindex_offset, i); - } + /* Run this even when shape keys aren't used since it may be used for hooks or vertex parents. */ + if (params->update_shapekey_indices) { + /* We have written a new shape key, if this mesh is _not_ going to be freed, + * update the shape key indices to match the newly updated. */ + if (cd_shape_keyindex_offset != -1) { + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { + BM_ELEM_CD_SET_INT(eve, cd_shape_keyindex_offset, i); } } } -- cgit v1.2.3 From ffcf39e3b5dbe7f12d04a350c629055ad21d40ce Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 28 Nov 2019 18:14:08 +1100 Subject: BMesh: reduce memory usage existing edit-mode - Don't duplicate the original vertices. - Free old geometry before allocating the new geometry. --- source/blender/bmesh/intern/bmesh_mesh_conv.c | 66 ++++++++++----------------- 1 file changed, 25 insertions(+), 41 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 3942cdd27fb..1ecbfccab74 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -561,58 +561,34 @@ BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e) */ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params) { - MLoop *mloop; - MPoly *mpoly; - MVert *mvert, *oldverts; - MEdge *med, *medge; + MEdge *med; BMVert *v, *eve; BMEdge *e; BMFace *f; BMIter iter; - int i, j, ototvert; + int i, j; const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX); - ototvert = me->totvert; - - /* New vertex block. */ - if (bm->totvert == 0) { - mvert = NULL; - } - else { - mvert = MEM_callocN(bm->totvert * sizeof(MVert), "loadeditbMesh vert"); - } + MVert *oldverts = NULL; + const int ototvert = me->totvert; - /* New edge block. */ - if (bm->totedge == 0) { - medge = NULL; - } - else { - medge = MEM_callocN(bm->totedge * sizeof(MEdge), "loadeditbMesh edge"); - } + if (me->key && (cd_shape_keyindex_offset != -1)) { + /* Keep the old verts in case we are working on* a key, which is done at the end. */ - /* New ngon face block. */ - if (bm->totface == 0) { - mpoly = NULL; - } - else { - mpoly = MEM_callocN(bm->totface * sizeof(MPoly), "loadeditbMesh poly"); - } - - /* New loop block. */ - if (bm->totloop == 0) { - mloop = NULL; - } - else { - mloop = MEM_callocN(bm->totloop * sizeof(MLoop), "loadeditbMesh loop"); - } - - /* Lets save the old verts just in case we are actually working on - * a key ... we now do processing of the keys at the end. */ + /* Use the array in-place instead of duplicating the array. */ +#if 0 oldverts = MEM_dupallocN(me->mvert); +#else + oldverts = me->mvert; + me->mvert = NULL; + CustomData_update_typemap(&me->vdata); + CustomData_set_layer(&me->vdata, CD_MVERT, NULL); +#endif + } /* Free custom data. */ CustomData_free(&me->vdata, me->totvert); @@ -640,6 +616,11 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly); } + MVert *mvert = bm->totvert ? MEM_callocN(sizeof(MVert) * bm->totvert, "bm_to_me.vert") : NULL; + MEdge *medge = bm->totedge ? MEM_callocN(sizeof(MEdge) * bm->totedge, "bm_to_me.edge") : NULL; + MLoop *mloop = bm->totloop ? MEM_callocN(sizeof(MLoop) * bm->totloop, "bm_to_me.loop") : NULL; + MPoly *mpoly = bm->totface ? MEM_callocN(sizeof(MPoly) * bm->totface, "bm_to_me.poly") : NULL; + CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert); CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge); CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop); @@ -868,12 +849,15 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh (actkey != NULL) && /* Not used here, but 'oldverts' is used later for applying 'ofs'. */ - (oldverts != NULL)) { + (oldverts != NULL) && + + /* Needed for referencing oldverts. */ + (cd_shape_keyindex_offset != -1)) { const bool act_is_basis = BKE_keyblock_is_basis(me->key, bm->shapenr - 1); /* Active key is a base. */ - if (act_is_basis && (cd_shape_keyindex_offset != -1)) { + if (act_is_basis) { const float(*fp)[3] = actkey->data; ofs = MEM_callocN(sizeof(float) * 3 * bm->totvert, "currkey->data"); -- cgit v1.2.3 From 320d8ab1556f1bc76cd9f654476250aebdec101e Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 8 Nov 2019 16:47:33 +0100 Subject: EEVEE: Viewport Renderpasses This patch will allow the user to select the EEVEE renderpass to be shown in the viewport by default the combined pass will be shown. Limitations: * Viewport rendering stores the result in a `RenderResult`. RenderResult is not aware of the type of data it holds. In many places where RenderResult is used it is assumed that it stores a combined pass and the display+view transform are applied. I will propose to fix this in a future patch. But that is still being designed and discussed. Reviewed By: fclem Differential Revision: https://developer.blender.org/D6319 --- release/scripts/startup/bl_ui/space_view3d.py | 21 +++++ source/blender/blenloader/intern/versioning_280.c | 18 +++++ source/blender/draw/engines/eevee/eevee_effects.c | 4 +- source/blender/draw/engines/eevee/eevee_engine.c | 35 +++++++-- source/blender/draw/engines/eevee/eevee_mist.c | 7 +- .../blender/draw/engines/eevee/eevee_occlusion.c | 6 +- source/blender/draw/engines/eevee/eevee_private.h | 11 +++ source/blender/draw/engines/eevee/eevee_render.c | 8 +- .../draw/engines/eevee/eevee_renderpasses.c | 90 +++++++++++++++++++++- .../blender/draw/engines/eevee/eevee_subsurface.c | 11 ++- .../draw/engines/eevee/eevee_temporal_sampling.c | 4 +- .../eevee/shaders/renderpass_postprocess_frag.glsl | 11 +-- source/blender/editors/space_view3d/view3d_draw.c | 2 + source/blender/makesdna/DNA_view3d_defaults.h | 1 + source/blender/makesdna/DNA_view3d_types.h | 4 + source/blender/makesrna/intern/rna_space.c | 18 +++++ 16 files changed, 220 insertions(+), 31 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 113274ce166..9f04dc4627a 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -5466,6 +5466,26 @@ class VIEW3D_PT_shading_options_ssao(Panel): col.prop(scene.display, "matcap_ssao_attenuation") +class VIEW3D_PT_shading_render_pass(Panel): + bl_space_type = 'VIEW_3D' + bl_region_type = 'HEADER' + bl_label = "Render Pass" + bl_parent_id = 'VIEW3D_PT_shading' + COMPAT_ENGINES = {'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + return (context.space_data.shading.type == 'MATERIAL' + or (context.engine in cls.COMPAT_ENGINES + and context.space_data.shading.type == 'RENDERED')) + + def draw(self, context): + shading = context.space_data.shading + + layout = self.layout + layout.prop(shading, "render_pass", text="") + + class VIEW3D_PT_gizmo_display(Panel): bl_space_type = 'VIEW_3D' bl_region_type = 'HEADER' @@ -6909,6 +6929,7 @@ classes = ( VIEW3D_PT_shading_options, VIEW3D_PT_shading_options_shadow, VIEW3D_PT_shading_options_ssao, + VIEW3D_PT_shading_render_pass, VIEW3D_PT_gizmo_display, VIEW3D_PT_overlay, VIEW3D_PT_overlay_guides, diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 7c33e853ed1..47e55a55ea1 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -4231,5 +4231,23 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) UnifiedPaintSettings *ups = &ts->unified_paint_settings; ups->flag &= ~(UNIFIED_PAINT_FLAG_UNUSED_0 | UNIFIED_PAINT_FLAG_UNUSED_1); } + + /* Set the default render pass in the viewport to Combined. */ + if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "int", "render_pass")) { + for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { + scene->display.shading.render_pass = SCE_PASS_COMBINED; + } + + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + v3d->shading.render_pass = SCE_PASS_COMBINED; + } + } + } + } + } } } diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index d59d1f56e92..824ea69ea73 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -136,8 +136,6 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_TextureList *txl = vedata->txl; EEVEE_EffectsInfo *effects; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; const float *viewport_size = DRW_viewport_size_get(); int size_fs[2] = {(int)viewport_size[0], (int)viewport_size[1]}; @@ -172,7 +170,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_subsurface_init(sldata, vedata); /* Force normal buffer creation. */ - if (DRW_state_is_image_render() && !minimal && (view_layer->passflag & SCE_PASS_NORMAL) != 0) { + if (!minimal && (stl->g_data->render_passes & SCE_PASS_NORMAL) != 0) { effects->enabled_effects |= EFFECT_NORMAL_BUFFER; } diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 173b7ff57a1..603a4787dba 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -27,6 +27,8 @@ #include "BKE_object.h" #include "BKE_global.h" /* for G.debug_value */ +#include "DEG_depsgraph_query.h" + #include "DNA_world_types.h" #include "eevee_private.h" @@ -81,7 +83,9 @@ static void eevee_engine_init(void *ved) &sldata->common_data); } - /* EEVEE_effects_init needs to go first for TAA */ + /* `EEVEE_renderpasses_init` will set the active render passes used by `EEVEE_effects_init`. + * `EEVEE_effects_init` needs to go second for TAA. */ + EEVEE_renderpasses_init(vedata); EEVEE_effects_init(sldata, vedata, camera, false); EEVEE_materials_init(sldata, stl, fbl); EEVEE_shadows_init(sldata); @@ -147,6 +151,8 @@ static void eevee_cache_finish(void *vedata) { EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); EEVEE_PrivateData *g_data = ((EEVEE_Data *)vedata)->stl->g_data; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); EEVEE_volumes_cache_finish(sldata, vedata); EEVEE_materials_cache_finish(sldata, vedata); @@ -156,6 +162,14 @@ static void eevee_cache_finish(void *vedata) EEVEE_effects_draw_init(sldata, vedata); EEVEE_volumes_draw_init(sldata, vedata); + uint tot_samples = scene_eval->eevee.taa_render_samples; + if (tot_samples == 0) { + /* use a high number of samples so the outputs accum buffers + * will have the highest possible precision */ + tot_samples = 1024; + } + EEVEE_renderpasses_output_init(sldata, vedata, tot_samples); + /* Restart taa if a shader has finish compiling. */ /* HACK We should use notification of some sort from the compilation job instead. */ if (g_data->queued_shaders_count != g_data->queued_shaders_count_prev) { @@ -306,6 +320,8 @@ static void eevee_draw_background(void *vedata) EEVEE_draw_effects(sldata, vedata); DRW_stats_group_end(); + EEVEE_renderpasses_output_accumulate(sldata, vedata); + DRW_view_set_active(NULL); if (DRW_state_is_image_render() && (stl->effects->enabled_effects & EFFECT_SSR) && @@ -319,14 +335,19 @@ static void eevee_draw_background(void *vedata) } } - /* Tonemapping and transfer result to default framebuffer. */ - bool use_render_settings = stl->g_data->use_color_render_settings; + if ((stl->g_data->render_passes & SCE_PASS_COMBINED) > 0) { + /* Tonemapping and transfer result to default framebuffer. */ + bool use_render_settings = stl->g_data->use_color_render_settings; - GPU_framebuffer_bind(dfbl->default_fb); - DRW_transform_to_display(stl->effects->final_tx, true, use_render_settings); + GPU_framebuffer_bind(dfbl->default_fb); + DRW_transform_to_display(stl->effects->final_tx, true, use_render_settings); - /* Draw checkerboard with alpha under. */ - EEVEE_draw_alpha_checker(vedata); + /* Draw checkerboard with alpha under. */ + EEVEE_draw_alpha_checker(vedata); + } + else { + EEVEE_renderpasses_draw(sldata, vedata); + } /* Debug : Output buffer to view. */ switch (G.debug_value) { diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c index 7209651a1d4..c9b56a6d551 100644 --- a/source/blender/draw/engines/eevee/eevee_mist.c +++ b/source/blender/draw/engines/eevee/eevee_mist.c @@ -49,6 +49,7 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) EEVEE_TextureList *txl = vedata->txl; EEVEE_StorageList *stl = vedata->stl; EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = stl->effects; EEVEE_PrivateData *g_data = stl->g_data; Scene *scene = draw_ctx->scene; @@ -74,8 +75,10 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->mist_accum)}); /* Clear texture. */ - GPU_framebuffer_bind(fbl->mist_accum_fb); - GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear); + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + GPU_framebuffer_bind(fbl->mist_accum_fb); + GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear); + } /* Mist settings. */ if (scene && scene->world) { diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index 0a7d1db1061..6ba518b3a28 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -155,8 +155,10 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->ao_accum)}); /* Clear texture. */ - GPU_framebuffer_bind(fbl->ao_accum_fb); - GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear); + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + GPU_framebuffer_bind(fbl->ao_accum_fb); + GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear); + } /* Accumulation pass */ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD; diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index b49328d90ab..bbe68aec190 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -63,6 +63,14 @@ extern struct DrawEngineType draw_engine_eevee_type; # define SHADER_IRRADIANCE "#define IRRADIANCE_HL2\n" #endif +#define EEVEE_RENDERPASSES_SUPPORTED \ + (SCE_PASS_COMBINED | SCE_PASS_Z | SCE_PASS_MIST | SCE_PASS_NORMAL | SCE_PASS_AO | \ + SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT) + +#define EEVEE_RENDERPASSES_WITH_POST_PROCESSING \ + (SCE_PASS_Z | SCE_PASS_MIST | SCE_PASS_NORMAL | SCE_PASS_AO | SCE_PASS_SUBSURFACE_COLOR | \ + SCE_PASS_SUBSURFACE_DIRECT) + /* Macro causes over indentation. */ /* clang-format off */ #define SHADER_DEFINES \ @@ -1052,10 +1060,13 @@ void EEVEE_renderpasses_init(EEVEE_Data *vedata); void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples); +void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, eScenePassType renderpass_type); +void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_renderpasses_free(void); +bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata); /* eevee_temporal_sampling.c */ void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 9a7d170c9ea..ba5704f14e5 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -485,16 +485,12 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl DRW_draw_pass(psl->refract_depth_pass); DRW_draw_pass(psl->refract_depth_pass_cull); DRW_draw_pass(psl->refract_pass); - /* Subsurface output */ - EEVEE_subsurface_output_accumulate(sldata, vedata); - /* Occlusion output */ - EEVEE_occlusion_output_accumulate(sldata, vedata); /* Result NORMAL */ eevee_render_result_normal(rl, viewname, rect, vedata, sldata); /* Volumetrics Resolve Opaque */ EEVEE_volumes_resolve(sldata, vedata); - /* Mist output */ - EEVEE_mist_output_accumulate(sldata, vedata); + /* Subsurface output, Occlusion output, Mist output */ + EEVEE_renderpasses_output_accumulate(sldata, vedata); /* Transparent */ GPU_framebuffer_texture_attach(fbl->main_color_fb, dtxl->depth, 0, 0); GPU_framebuffer_bind(fbl->main_color_fb); diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index 17f1f8c96d6..b83216ee6d0 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -25,6 +25,8 @@ #include "BLI_string_utils.h" +#include "DEG_depsgraph_query.h" + #include "eevee_private.h" extern char datatoc_common_view_lib_glsl[]; @@ -46,14 +48,31 @@ static struct { #define EEVEE_RENDERPASSES_ALL (EEVEE_RENDERPASSES_WITH_POST_PROCESSING | SCE_PASS_COMBINED) +#define EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE (SCE_PASS_Z | SCE_PASS_NORMAL) + +#define EEVEE_RENDERPASSES_COLOR_PASS (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT) + +bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + return (g_data->render_passes & ~EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE) == 0; +} + void EEVEE_renderpasses_init(EEVEE_Data *vedata) { const DRWContextState *draw_ctx = DRW_context_state_get(); EEVEE_StorageList *stl = vedata->stl; EEVEE_PrivateData *g_data = stl->g_data; ViewLayer *view_layer = draw_ctx->view_layer; + View3D *v3d = draw_ctx->v3d; - g_data->render_passes = (view_layer->passflag & EEVEE_RENDERPASSES_ALL) | SCE_PASS_COMBINED; + if (v3d) { + g_data->render_passes = v3d->shading.render_pass; + } + else { + g_data->render_passes = (view_layer->passflag & EEVEE_RENDERPASSES_ALL) | SCE_PASS_COMBINED; + } } void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, @@ -143,17 +162,21 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, } case SCE_PASS_AO: { + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &txl->ao_accum); DRW_shgroup_uniform_int_copy(shgrp, "currentSample", current_sample); break; } case SCE_PASS_NORMAL: { + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &effects->ssr_normal_input); + DRW_shgroup_uniform_texture_ref(shgrp, "depthBuffer", &dtxl->depth); break; } case SCE_PASS_MIST: { + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &txl->mist_accum); DRW_shgroup_uniform_int_copy(shgrp, "currentSample", current_sample); break; @@ -184,6 +207,71 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, DRW_draw_pass_subset(psl->renderpass_pass, shgrp, shgrp); } +void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + eScenePassType render_pass = stl->g_data->render_passes; + + if ((render_pass & SCE_PASS_MIST) != 0) { + EEVEE_mist_output_accumulate(sldata, vedata); + } + if ((effects->enabled_effects & EFFECT_SSS) && + (render_pass & EEVEE_RENDERPASSES_SUBSURFACE) != 0) { + EEVEE_subsurface_output_accumulate(sldata, vedata); + } + if ((render_pass & SCE_PASS_AO) != 0) { + EEVEE_occlusion_output_accumulate(sldata, vedata); + } +} + +void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + eScenePassType render_pass = stl->g_data->render_passes; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + bool is_valid = true; + bool needs_color_transfer = (render_pass & EEVEE_RENDERPASSES_COLOR_PASS) > 0 && + DRW_state_is_opengl_render(); + + /* When SSS isn't available, but the pass is requested, we mark it as invalid */ + if ((render_pass & EEVEE_RENDERPASSES_SUBSURFACE) != 0 && + (effects->enabled_effects & EFFECT_SSS) == 0) { + is_valid = false; + } + + /* When SSS isn't available, but the pass is requested, we mark it as invalid */ + if ((render_pass & SCE_PASS_AO) != 0 && (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) == 0) { + is_valid = false; + } + + const int current_sample = stl->effects->taa_current_sample; + const int total_samples = stl->effects->taa_total_sample; + if ((render_pass & EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE) && + (current_sample > 1 && total_samples != 1)) { + return; + } + + if (is_valid) { + EEVEE_renderpasses_postprocess(sldata, vedata, render_pass); + GPU_framebuffer_bind(dfbl->default_fb); + DRW_transform_to_display(txl->renderpass, needs_color_transfer, false); + } + else { + /* Draw state is not valid for this pass, clear the buffer */ + static float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_bind(dfbl->default_fb); + GPU_framebuffer_clear_color(dfbl->default_fb, clear_color); + } + GPU_framebuffer_bind(fbl->main_fb); +} + void EEVEE_renderpasses_free(void) { DRW_SHADER_FREE_SAFE(e_data.postprocess_sh); diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index a7c28347c15..e94fc903694 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -187,9 +187,11 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), GPU_ATTACHMENT_TEXTURE(txl->sss_col_accum)}); /* Clear texture. */ - float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - GPU_framebuffer_bind(fbl->sss_accum_fb); - GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear); + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_bind(fbl->sss_accum_fb); + GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear); + } /* Make the opaque refraction pass mask the sss. */ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | @@ -257,7 +259,8 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, DRW_shgroup_stencil_mask(grp, sss_id); DRW_shgroup_call(grp, quad, NULL); - if (DRW_state_is_image_render()) { + if ((stl->g_data->render_passes & (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT)) != + 0) { grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_accum_ps); DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src); diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index e5f89aab4d1..0f0b4a3e0a9 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -234,7 +234,9 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data view_is_valid = view_is_valid && (ED_screen_animation_no_scrub(wm) == NULL); } - effects->taa_total_sample = scene_eval->eevee.taa_samples; + effects->taa_total_sample = EEVEE_renderpasses_only_first_sample_pass_active(vedata) ? + 1 : + scene_eval->eevee.taa_samples; MAX2(effects->taa_total_sample, 0); DRW_view_persmat_get(NULL, persmat, false); diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl index 8a543f13fbc..5a738d0f130 100644 --- a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl @@ -34,27 +34,28 @@ void main() } else if (renderpassType == SCE_PASS_NORMAL) { + float depth = texelFetch(depthBuffer, texel, 0).r; vec2 encoded_normal = texelFetch(inputBuffer, texel, 0).rg; /* decode the normals only when they are valid. otherwise the result buffer will be filled with * NaN's */ - if (any(notEqual(encoded_normal, vec2(0.0)))) { + if (depth != 1.0 && any(notEqual(encoded_normal, vec2(0.0)))) { vec3 decoded_normal = normal_decode(texelFetch(inputBuffer, texel, 0).rg, vec3(0.0)); vec3 world_normal = mat3(ViewMatrixInverse) * decoded_normal; - fragColor = vec4(world_normal, 0.0); + fragColor = vec4(world_normal, 1.0); } else { - fragColor = vec4(0.0); + fragColor = vec4(0.0, 0.0, 0.0, 1.0); } } else if ((renderpassType & ACCUMULATED_VALUE_PASSES) != 0) { float accumulated_value = texelFetch(inputBuffer, texel, 0).r; - fragColor.r = accumulated_value / currentSample; + fragColor = vec4(vec3(accumulated_value / currentSample), 1.0); } else if ((renderpassType & ACCUMULATED_COLOR_PASSES) != 0) { vec3 accumulated_color = texelFetch(inputBuffer, texel, 0).rgb; - fragColor.rgb = accumulated_color / currentSample; + fragColor = vec4(accumulated_color / currentSample, 1.0); } else { diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 3ee9755cb06..831f8d77285 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1866,9 +1866,11 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph, if (drawtype == OB_MATERIAL) { v3d.shading.flag = V3D_SHADING_SCENE_WORLD | V3D_SHADING_SCENE_LIGHTS; + v3d.shading.render_pass = SCE_PASS_COMBINED; } else if (drawtype == OB_RENDER) { v3d.shading.flag = V3D_SHADING_SCENE_WORLD_RENDER | V3D_SHADING_SCENE_LIGHTS_RENDER; + v3d.shading.render_pass = SCE_PASS_COMBINED; } v3d.flag2 = V3D_HIDE_OVERLAYS; diff --git a/source/blender/makesdna/DNA_view3d_defaults.h b/source/blender/makesdna/DNA_view3d_defaults.h index 365b1993d80..f6c8c0b1f6d 100644 --- a/source/blender/makesdna/DNA_view3d_defaults.h +++ b/source/blender/makesdna/DNA_view3d_defaults.h @@ -46,6 +46,7 @@ .single_color = {0.8f, 0.8f, 0.8f}, \ .background_color = {0.05f, 0.05f, 0.05f}, \ .studiolight_intensity = 1.0f, \ + .render_pass = SCE_PASS_COMBINED, \ } #define _DNA_DEFAULT_View3DOverlay \ diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 7b832f1b646..a9a20980677 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -179,6 +179,10 @@ typedef struct View3DShading { float curvature_ridge_factor; float curvature_valley_factor; + /* Render pass displayed in the viewport. Is an `eScenePassType` where one bit is set */ + int render_pass; + char _pad2[4]; + struct IDProperty *prop; } View3DShading; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index e14fff0220e..9d43514f6d4 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -374,6 +374,18 @@ static const EnumPropertyItem rna_enum_studio_light_items[] = { {0, NULL, 0, NULL, NULL}, }; +const EnumPropertyItem rna_enum_view3dshading_render_pass_type_items[] = { + {SCE_PASS_COMBINED, "COMBINED", 0, "Combined", ""}, + /* {SCE_PASS_Z, "Z", 0, "Z", ""},*/ + {SCE_PASS_AO, "AO", 0, "Ambient Occlusion", ""}, + {SCE_PASS_NORMAL, "NORMAL", 0, "Normal", ""}, + {SCE_PASS_MIST, "MIST", 0, "Mist", ""}, + {SCE_PASS_SUBSURFACE_DIRECT, "SUBSURFACE_DIRECT", 0, "Subsurface Direct", ""}, + /* {SCE_PASS_SUBSURFACE_INDIRECT, "SUBSURFACE_INDIRECT", 0, "Subsurface Indirect", ""}, */ + {SCE_PASS_SUBSURFACE_COLOR, "SUBSURFACE_COLOR", 0, "Subsurface Color", ""}, + {0, NULL, 0, NULL, NULL}, +}; + const EnumPropertyItem rna_enum_clip_editor_mode_items[] = { {SC_MODE_TRACKING, "TRACKING", ICON_ANIM_DATA, "Tracking", "Show tracking and solving tools"}, {SC_MODE_MASKEDIT, "MASK", ICON_MOD_MASK, "Mask", "Show mask editing tools"}, @@ -3280,6 +3292,12 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.00f, 1.0f, 1, 3); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "render_pass", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "render_pass"); + RNA_def_property_enum_items(prop, rna_enum_view3dshading_render_pass_type_items); + RNA_def_property_ui_text(prop, "Render Pass", "Render Pass to show in the viewport"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); } static void rna_def_space_view3d_overlay(BlenderRNA *brna) -- cgit v1.2.3 From d4835b88b23bce6c28d8514e35d771408d5ef18b Mon Sep 17 00:00:00 2001 From: Jens Date: Thu, 28 Nov 2019 11:40:59 +0100 Subject: Buildbot: Migrate package archive format for Linux from tar.bz2 to tar.xz xz compresses 25% better than bz2, reducing download times and server load. The numbers: blender-2.80-linux-glibc217-x86_64.tar.bz2 (release): 134 886 174 bytes with xz: 96 181 604 bytes (-28.7%) with xz -9: 93 871 548 bytes (-30.4%) blender-2.81-7c1fbe24ca33-linux-glibc217-x86_64.tar.bz2 (beta): 173 600 363 bytes with xz: 133 100 664 bytes (-23.3%) with xz -9: 129 534 124 bytes (-25.4%) xz also decompresses more than twice as fast as bz2, however compression needs four times as long (on my 7-year-old laptop 3-4 minutes instead of <1). Also xz has become more common than bz2, e.g. Debian/Ubuntu deb packages have been xz-compressed for years, so the dpkg package manager as well as systemd and grub all depend on liblzma being present, whereas bz2 is becoming more and more optional. Current Linux archives also include the UID/GID of whatever user account happens to be used for building by the blender.org infrastructure. If someone then installs these archives as root e.g. to /usr/local/... and doesn't pay full attention the files remain owned by a regular user, which is a serious security issue. This patch fixes that by setting the UID/GID to 0. Differential Revision: https://developer.blender.org/D6138 --- build_files/buildbot/slave_pack.py | 25 ++++++++++++++++++------- build_files/cmake/packaging.cmake | 2 +- build_files/package_spec/build_archive.py | 5 +++-- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/build_files/buildbot/slave_pack.py b/build_files/buildbot/slave_pack.py index 19dac236762..bbacedca0ce 100644 --- a/build_files/buildbot/slave_pack.py +++ b/build_files/buildbot/slave_pack.py @@ -64,7 +64,7 @@ def create_buildbot_upload_zip(builder, package_files): sys.stderr.write('Create buildbot_upload.zip failed: ' + str(ex) + '\n') sys.exit(1) -def create_tar_bz2(src, dest, package_name): +def create_tar_xz(src, dest, package_name): # One extra to remove leading os.sep when cleaning root for package_root ln = len(src) + 1 flist = list() @@ -75,9 +75,20 @@ def create_tar_bz2(src, dest, package_name): flist.extend([(os.path.join(root, file), os.path.join(package_root, file)) for file in files]) import tarfile - package = tarfile.open(dest, 'w:bz2') + + # Set UID/GID of archived files to 0, otherwise they'd be owned by whatever + # user compiled the package. If root then unpacks it to /usr/local/ you get + # a security issue. + def _fakeroot(tarinfo): + tarinfo.gid = 0 + tarinfo.gname = "root" + tarinfo.uid = 0 + tarinfo.uname = "root" + return tarinfo + + package = tarfile.open(dest, 'w:xz', preset=9) for entry in flist: - package.add(entry[0], entry[1], recursive=False) + package.add(entry[0], entry[1], recursive=False, filter=_fakeroot) package.close() def cleanup_files(dirpath, extension): @@ -163,11 +174,11 @@ def pack_linux(builder): # Construct package name platform_name = 'linux-' + blender_glibc + '-' + blender_arch package_name = get_package_name(builder, platform_name) - package_filename = package_name + ".tar.bz2" + package_filename = package_name + ".tar.xz" - print("Creating .tar.bz2 archive") - package_filepath = builder.install_dir + '.tar.bz2' - create_tar_bz2(builder.install_dir, package_filepath, package_name) + print("Creating .tar.xz archive") + package_filepath = builder.install_dir + '.tar.xz' + create_tar_xz(builder.install_dir, package_filepath, package_name) # Create buildbot_upload.zip create_buildbot_upload_zip(builder, [(package_filepath, package_filename)]) diff --git a/build_files/cmake/packaging.cmake b/build_files/cmake/packaging.cmake index 5ace42646c5..0e530463659 100644 --- a/build_files/cmake/packaging.cmake +++ b/build_files/cmake/packaging.cmake @@ -135,7 +135,7 @@ elseif(UNIX) add_package_archive( "${PROJECT_NAME}-${BLENDER_VERSION}-${BUILD_REV}-${PACKAGE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" - "tar.bz2") + "tar.xz") endif() unset(MAJOR_VERSION) diff --git a/build_files/package_spec/build_archive.py b/build_files/package_spec/build_archive.py index 5ca2f319d87..58a970bca31 100755 --- a/build_files/package_spec/build_archive.py +++ b/build_files/package_spec/build_archive.py @@ -51,8 +51,9 @@ try: if extension == 'zip': archive_cmd = ['zip', '-9', '-r', package_archive, package_dir] - elif extension == 'tar.bz2': - archive_cmd = ['tar', 'cjf', package_archive, package_dir] + elif extension == 'tar.xz': + archive_cmd = ['tar', '-cf', package_archive, '--owner=0', '--group=0', + '--use-compress-program=xz -9', package_dir] else: sys.stderr.write('Unknown archive extension: ' + extension) sys.exit(-1) -- cgit v1.2.3 From 70a32adfeb41f9b3fc376a933fbdc2d11bb73c15 Mon Sep 17 00:00:00 2001 From: Patrick Mours Date: Thu, 28 Nov 2019 13:57:02 +0100 Subject: Fix assert in Cycles memory statistics when using OptiX on multiple GPUs The acceleration structure built by OptiX may be different between GPUs, so cannot assume the memory size is the same for all. This fixes that by moving the memory management for all OptiX acceleration structures into the responsibility of each device (was already the case for BLAS previously, now for TLAS too). --- intern/cycles/bvh/bvh_optix.cpp | 2 +- intern/cycles/device/device.h | 2 +- intern/cycles/device/device_multi.cpp | 12 ++---------- intern/cycles/device/device_optix.cpp | 32 ++++++++++++++++++-------------- 4 files changed, 22 insertions(+), 26 deletions(-) diff --git a/intern/cycles/bvh/bvh_optix.cpp b/intern/cycles/bvh/bvh_optix.cpp index b3a9aab3266..86d755ab06a 100644 --- a/intern/cycles/bvh/bvh_optix.cpp +++ b/intern/cycles/bvh/bvh_optix.cpp @@ -49,7 +49,7 @@ void BVHOptiX::copy_to_device(Progress &progress, DeviceScene *dscene) progress.set_status("Updating Scene BVH", "Building OptiX acceleration structure"); Device *const device = dscene->bvh_nodes.device; - if (!device->build_optix_bvh(this, dscene->bvh_nodes)) + if (!device->build_optix_bvh(this)) progress.set_error("Failed to build OptiX acceleration structure"); } diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 672d93c2581..66fcac921d3 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -407,7 +407,7 @@ class Device { const DeviceDrawParams &draw_params); /* acceleration structure building */ - virtual bool build_optix_bvh(BVH *, device_memory &) + virtual bool build_optix_bvh(BVH *) { return false; } diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index ac71be9dbea..b8587eb0a62 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -153,21 +153,13 @@ class MultiDevice : public Device { return result; } - bool build_optix_bvh(BVH *bvh, device_memory &mem) + bool build_optix_bvh(BVH *bvh) { - device_ptr key = unique_key++; - // Broadcast acceleration structure build to all devices foreach (SubDevice &sub, devices) { - mem.device = sub.device; - if (!sub.device->build_optix_bvh(bvh, mem)) + if (!sub.device->build_optix_bvh(bvh)) return false; - sub.ptr_map[key] = mem.device_pointer; } - - mem.device = this; - mem.device_pointer = key; - stats.mem_alloc(mem.device_size); return true; } diff --git a/intern/cycles/device/device_optix.cpp b/intern/cycles/device/device_optix.cpp index e10bab5a0d8..3ef954ab27f 100644 --- a/intern/cycles/device/device_optix.cpp +++ b/intern/cycles/device/device_optix.cpp @@ -174,7 +174,7 @@ class OptiXDevice : public Device { device_vector sbt_data; device_vector texture_info; device_only_memory launch_params; - vector> blas; + vector> as_mem; OptixTraversableHandle tlas_handle = 0; // TODO(pmours): This is copied from device_cuda.cpp, so move to common code eventually @@ -268,8 +268,8 @@ class OptiXDevice : public Device { // Stop processing any more tasks task_pool.stop(); - // Clean up all memory before destroying context - blas.clear(); + // Free all acceleration structures + as_mem.clear(); sbt_data.free(); texture_info.free(); @@ -881,15 +881,16 @@ class OptiXDevice : public Device { return true; } - bool build_optix_bvh(BVH *bvh, device_memory &out_data) override + bool build_optix_bvh(BVH *bvh) override { assert(bvh->params.top_level); unsigned int num_instances = 0; unordered_map> meshes; + meshes.reserve(bvh->meshes.size()); - // Clear all previous AS - blas.clear(); + // Free all previous acceleration structure + as_mem.clear(); // Build bottom level acceleration structures (BLAS) // Note: Always keep this logic in sync with bvh_optix.cpp! @@ -900,6 +901,7 @@ class OptiXDevice : public Device { Mesh *const mesh = ob->mesh; vector handles; + handles.reserve(2); // Build BLAS for curve primitives if (bvh->params.primitive_mask & PRIMITIVE_ALL_CURVE && mesh->num_curves() > 0) { @@ -966,9 +968,9 @@ class OptiXDevice : public Device { build_input.aabbArray.primitiveIndexOffset = mesh->prim_offset; // Allocate memory for new BLAS and build it - blas.emplace_back(this, "blas"); + as_mem.emplace_back(this, "blas"); handles.emplace_back(); - if (!build_optix_bvh(build_input, num_motion_steps, blas.back(), handles.back())) + if (!build_optix_bvh(build_input, num_motion_steps, as_mem.back(), handles.back())) return false; } @@ -1032,9 +1034,9 @@ class OptiXDevice : public Device { build_input.triangleArray.primitiveIndexOffset = mesh->prim_offset + mesh->num_segments(); // Allocate memory for new BLAS and build it - blas.emplace_back(this, "blas"); + as_mem.emplace_back(this, "blas"); handles.emplace_back(); - if (!build_optix_bvh(build_input, num_motion_steps, blas.back(), handles.back())) + if (!build_optix_bvh(build_input, num_motion_steps, as_mem.back(), handles.back())) return false; } @@ -1051,6 +1053,7 @@ class OptiXDevice : public Device { // Skip non-traceable objects if (!ob->is_traceable()) continue; + // Create separate instance for triangle/curve meshes of an object for (OptixTraversableHandle handle : meshes[ob->mesh]) { OptixAabb &aabb = aabbs[num_instances]; @@ -1078,8 +1081,8 @@ class OptiXDevice : public Device { // Insert motion traversable if object has motion if (motion_blur && ob->use_motion()) { - blas.emplace_back(this, "motion_transform"); - device_only_memory &motion_transform_gpu = blas.back(); + as_mem.emplace_back(this, "motion_transform"); + device_only_memory &motion_transform_gpu = as_mem.back(); motion_transform_gpu.alloc_to_device(sizeof(OptixSRTMotionTransform) + (max(ob->motion.size(), 2) - 2) * sizeof(OptixSRTData)); @@ -1157,7 +1160,7 @@ class OptiXDevice : public Device { instances.resize(num_instances); instances.copy_to_device(); - // Build top-level acceleration structure + // Build top-level acceleration structure (TLAS) OptixBuildInput build_input = {}; build_input.type = OPTIX_BUILD_INPUT_TYPE_INSTANCES; build_input.instanceArray.instances = instances.device_pointer; @@ -1165,7 +1168,8 @@ class OptiXDevice : public Device { build_input.instanceArray.aabbs = aabbs.device_pointer; build_input.instanceArray.numAabbs = num_instances; - return build_optix_bvh(build_input, 0 /* TLAS has no motion itself */, out_data, tlas_handle); + as_mem.emplace_back(this, "tlas"); + return build_optix_bvh(build_input, 0, as_mem.back(), tlas_handle); } void update_texture_info() -- cgit v1.2.3 From 47bb3c5d5d0d8f1a2eb27211eba863d065516e0a Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Thu, 28 Nov 2019 15:34:23 +0100 Subject: EEVEE: RenderLayers Small change do not draw an unsupported renderpass in the viewport --- source/blender/draw/engines/eevee/eevee_renderpasses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index b83216ee6d0..9b7bd34c9fa 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -236,7 +236,7 @@ void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - bool is_valid = true; + bool is_valid = (render_pass & EEVEE_RENDERPASSES_SUPPORTED) > 0; bool needs_color_transfer = (render_pass & EEVEE_RENDERPASSES_COLOR_PASS) > 0 && DRW_state_is_opengl_render(); -- cgit v1.2.3 From 66328c0f4fe7d1a2e0f524e3b45fb947f8266f81 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 29 Nov 2019 01:40:09 +1100 Subject: Console: remove shortcuts from console splash Menu items can be used to find shortcuts instead of keeping keymap items here. --- release/scripts/modules/console_python.py | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/release/scripts/modules/console_python.py b/release/scripts/modules/console_python.py index f264de5b140..5106010b555 100644 --- a/release/scripts/modules/console_python.py +++ b/release/scripts/modules/console_python.py @@ -341,23 +341,20 @@ def banner(context): sc = context.space_data version_string = sys.version.strip().replace('\n', ' ') - add_scrollback("PYTHON INTERACTIVE CONSOLE %s" % version_string, 'OUTPUT') - add_scrollback("", 'OUTPUT') - add_scrollback("Command History: Up/Down Arrow", 'OUTPUT') - add_scrollback("Cursor: Left/Right Home/End", 'OUTPUT') - add_scrollback("Remove: Backspace/Delete", 'OUTPUT') - add_scrollback("Execute: Enter", 'OUTPUT') - add_scrollback("Autocomplete: Ctrl-Space", 'OUTPUT') - add_scrollback("Zoom: Ctrl +/-, Ctrl-Wheel", 'OUTPUT') - add_scrollback("Builtin Modules: bpy, bpy.data, bpy.ops, " - "bpy.props, bpy.types, bpy.context, bpy.utils, " - "bgl, blf, mathutils", - 'OUTPUT') - add_scrollback("Convenience Imports: from mathutils import *; " - "from math import *", 'OUTPUT') - add_scrollback("Convenience Variables: C = bpy.context, D = bpy.data", - 'OUTPUT') - add_scrollback("", 'OUTPUT') + message = ( + "PYTHON INTERACTIVE CONSOLE %s" % version_string, + "", + "Builtin Modules: " + "bpy, bpy.data, bpy.ops, bpy.props, bpy.types, bpy.context, bpy.utils, bgl, blf, mathutils", + + "Convenience Imports: from mathutils import *; from math import *", + "Convenience Variables: C = bpy.context, D = bpy.data", + "", + ) + + for line in message: + add_scrollback(line, 'OUTPUT') + sc.prompt = PROMPT return {'FINISHED'} -- cgit v1.2.3 From 627a34463511647e9a697ebd62a03478ec75a7d1 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 28 Nov 2019 15:50:31 +0100 Subject: Fix (unreported) broken python resgistrable classes checks logic. Logic for registering and checking properties of registrable classes was broken, allowing to ignore some errors. Recent fix rBeb798de101a `broke` the result of the pyapi_idprop_datablock test, because previously that test would fail (i.e. suceed, as it is an 'expected to break test') for a reason it was not designed to check. This is the problem with that kind of tests - you cannot really check that they are failing on the expected reason(s)... --- source/blender/python/intern/bpy_rna.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 6fb2b2fd7ee..d49e782c317 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -7818,7 +7818,7 @@ static int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict) } } - { + if (ret == 0) { /* This block can be removed once 2.8x is released and annotations are in use. */ bool has_warning = false; while (PyDict_Next(class_dict, &pos, &key, &item)) { -- cgit v1.2.3 From 8caeae9f40abe942030a5b4c269a3e4b1a601021 Mon Sep 17 00:00:00 2001 From: Patrick Mours Date: Thu, 28 Nov 2019 17:06:56 +0100 Subject: Fix crash if OptiX context creation fails in Cycles When encountering an error during context creation, the "OptiXDevice" constructor aborts early. This means the "cuda_stream" vector is never resized and the destructor iterated over non-existent data. --- intern/cycles/device/device_optix.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/device/device_optix.cpp b/intern/cycles/device/device_optix.cpp index 3ef954ab27f..ae3ab7e1fc2 100644 --- a/intern/cycles/device/device_optix.cpp +++ b/intern/cycles/device/device_optix.cpp @@ -290,8 +290,8 @@ class OptiXDevice : public Device { optixPipelineDestroy(pipelines[i]); // Destroy launch streams - for (int i = 0; i < info.cpu_threads; ++i) - cuStreamDestroy(cuda_stream[i]); + for (CUstream stream : cuda_stream) + cuStreamDestroy(stream); // Destroy OptiX and CUDA context optixDeviceContextDestroy(context); -- cgit v1.2.3 From a8d29ad6e0628e315a1cb741b6136ad8823422dd Mon Sep 17 00:00:00 2001 From: mano-wii Date: Thu, 28 Nov 2019 13:40:44 -0300 Subject: Fix T71558: Hair particles: Brush effect not occluded by emitter geometry --- source/blender/draw/intern/draw_manager.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 9e28627ba3d..e3464ae7320 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -2668,6 +2668,9 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object) RegionView3D *rv3d = ar->regiondata; DRW_opengl_context_enable(); + GPU_matrix_projection_set(rv3d->winmat); + GPU_matrix_set(rv3d->viewmat); + GPU_matrix_mul(object->obmat); /* Setup framebuffer */ DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport); @@ -2675,7 +2678,6 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object) GPU_framebuffer_bind(fbl->depth_only_fb); GPU_framebuffer_clear_depth(fbl->depth_only_fb, 1.0f); GPU_depth_test(true); - GPU_matrix_mul(object->obmat); const float(*world_clip_planes)[4] = NULL; if (rv3d->rflag & RV3D_CLIPPING) { -- cgit v1.2.3 From f445f72ecadf21857a36b52b187620df158ef698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Thu, 28 Nov 2019 17:37:27 +0100 Subject: Tests: Blendfile-loading test class This new test class minimally sets up Blender so that it can load blend files and construct a depsgraph without crashing. Note that it hasn't been tested on very complex blend files, so it may still crash when the loaded blend file references/requires uninitialised data structures. The test will certainly crash with Blend files created with Blender older than 2.80, as the versioning code requires space types to be registered. This is normally done by initialising the window manager, which is not done in this test. The WM requires Python to run, which in turn requires that Blender finds the release directory in the same directory that contains the running executable, which is not the case for GTest tests (they are written to `bin/tests/executablename`. Reviewed By: sergey, mont29 Differential Revision: https://developer.blender.org/D6246 --- build_files/cmake/Modules/GTestTesting.cmake | 36 +++-- tests/gtests/CMakeLists.txt | 1 + tests/gtests/blenloader/CMakeLists.txt | 90 +++++++++++ tests/gtests/blenloader/blendfile_load_test.cc | 31 ++++ .../blenloader/blendfile_loading_base_test.cc | 172 +++++++++++++++++++++ .../blenloader/blendfile_loading_base_test.h | 64 ++++++++ 6 files changed, 385 insertions(+), 9 deletions(-) create mode 100644 tests/gtests/blenloader/CMakeLists.txt create mode 100644 tests/gtests/blenloader/blendfile_load_test.cc create mode 100644 tests/gtests/blenloader/blendfile_loading_base_test.cc create mode 100644 tests/gtests/blenloader/blendfile_loading_base_test.h diff --git a/build_files/cmake/Modules/GTestTesting.cmake b/build_files/cmake/Modules/GTestTesting.cmake index a93e829e6b0..2a05b92ba3f 100644 --- a/build_files/cmake/Modules/GTestTesting.cmake +++ b/build_files/cmake/Modules/GTestTesting.cmake @@ -12,9 +12,14 @@ # #============================================================================= -macro(BLENDER_SRC_GTEST_EX NAME SRC EXTRA_LIBS DO_ADD_TEST) +macro(BLENDER_SRC_GTEST_EX) if(WITH_GTESTS) - set(TARGET_NAME ${NAME}_test) + set(options SKIP_ADD_TEST) + set(oneValueArgs NAME) + set(multiValueArgs SRC EXTRA_LIBS COMMAND_ARGS) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + + set(TARGET_NAME ${ARG_NAME}_test) get_property(_current_include_directories DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) @@ -30,11 +35,11 @@ macro(BLENDER_SRC_GTEST_EX NAME SRC EXTRA_LIBS DO_ADD_TEST) ) unset(_current_include_directories) - add_executable(${TARGET_NAME} ${SRC}) + add_executable(${TARGET_NAME} ${ARG_SRC}) target_include_directories(${TARGET_NAME} PUBLIC "${TEST_INC}") target_include_directories(${TARGET_NAME} SYSTEM PUBLIC "${TEST_INC_SYS}") target_link_libraries(${TARGET_NAME} - ${EXTRA_LIBS} + ${ARG_EXTRA_LIBS} ${PLATFORM_LINKLIBS} bf_testing_main bf_intern_eigen @@ -60,8 +65,11 @@ macro(BLENDER_SRC_GTEST_EX NAME SRC EXTRA_LIBS DO_ADD_TEST) RUNTIME_OUTPUT_DIRECTORY "${TESTS_OUTPUT_DIR}" RUNTIME_OUTPUT_DIRECTORY_RELEASE "${TESTS_OUTPUT_DIR}" RUNTIME_OUTPUT_DIRECTORY_DEBUG "${TESTS_OUTPUT_DIR}") - if(${DO_ADD_TEST}) - add_test(NAME ${TARGET_NAME} COMMAND ${TESTS_OUTPUT_DIR}/${TARGET_NAME} WORKING_DIRECTORY ${TEST_INSTALL_DIR}) + if(NOT ARG_SKIP_ADD_TEST) + add_test( + NAME ${TARGET_NAME} + COMMAND ${TESTS_OUTPUT_DIR}/${TARGET_NAME} ${ARG_COMMAND_ARGS} + WORKING_DIRECTORY ${TEST_INSTALL_DIR}) # Don't fail tests on leaks since these often happen in external libraries # that we can't fix. @@ -74,13 +82,23 @@ macro(BLENDER_SRC_GTEST_EX NAME SRC EXTRA_LIBS DO_ADD_TEST) endmacro() macro(BLENDER_SRC_GTEST NAME SRC EXTRA_LIBS) - BLENDER_SRC_GTEST_EX("${NAME}" "${SRC}" "${EXTRA_LIBS}" "TRUE") + BLENDER_SRC_GTEST_EX( + NAME "${NAME}" + SRC "${SRC}" + EXTRA_LIBS "${EXTRA_LIBS}") endmacro() macro(BLENDER_TEST NAME EXTRA_LIBS) - BLENDER_SRC_GTEST_EX("${NAME}" "${NAME}_test.cc" "${EXTRA_LIBS}" "TRUE") + BLENDER_SRC_GTEST_EX( + NAME "${NAME}" + SRC "${NAME}_test.cc" + EXTRA_LIBS "${EXTRA_LIBS}") endmacro() macro(BLENDER_TEST_PERFORMANCE NAME EXTRA_LIBS) - BLENDER_SRC_GTEST_EX("${NAME}" "${NAME}_test.cc" "${EXTRA_LIBS}" "FALSE") + BLENDER_SRC_GTEST_EX( + NAME "${NAME}" + SRC "${NAME}_test.cc" + EXTRA_LIBS "${EXTRA_LIBS}" + SKIP_ADD_TEST) endmacro() diff --git a/tests/gtests/CMakeLists.txt b/tests/gtests/CMakeLists.txt index 285b414e997..54a1ee41198 100644 --- a/tests/gtests/CMakeLists.txt +++ b/tests/gtests/CMakeLists.txt @@ -13,6 +13,7 @@ if(WITH_GTESTS) add_subdirectory(testing) add_subdirectory(blenlib) + add_subdirectory(blenloader) add_subdirectory(guardedalloc) add_subdirectory(bmesh) if(WITH_ALEMBIC) diff --git a/tests/gtests/blenloader/CMakeLists.txt b/tests/gtests/blenloader/CMakeLists.txt new file mode 100644 index 00000000000..f8457e0164b --- /dev/null +++ b/tests/gtests/blenloader/CMakeLists.txt @@ -0,0 +1,90 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2019 by Blender Foundation. +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . + .. + ../../../source/blender/blenkernel + ../../../source/blender/blenlib + ../../../source/blender/blenloader + ../../../source/blender/depsgraph + ../../../source/blender/imbuf + ../../../source/blender/makesdna + ../../../source/blender/makesrna + ../../../source/blender/windowmanager + ../../../intern/guardedalloc + ${GLOG_INCLUDE_DIRS} + ${GFLAGS_INCLUDE_DIRS} + ../../../extern/gtest/include +) + +set(SRC + blendfile_loading_base_test.cc + blendfile_loading_base_test.h +) + +set(LIB +) + +blender_add_lib(bf_blenloader_test "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") + + +set(INC + . + .. + ../../../source/blender/blenlib + ../../../source/blender/blenloader + ../../../source/blender/blenkernel + ../../../source/blender/makesdna + ../../../source/blender/makesrna + ../../../source/blender/depsgraph + ../../../intern/guardedalloc +) + +set(LIB + bf_blenloader_test + bf_blenloader + + # Should not be needed but gives windows linker errors if the ocio libs are linked before this: + bf_intern_opencolorio + bf_gpu +) + +include_directories(${INC}) + +setup_libdirs() +get_property(BLENDER_SORTED_LIBS GLOBAL PROPERTY BLENDER_SORTED_LIBS_PROP) + + +set(SRC + blendfile_load_test.cc +) +if(WITH_BUILDINFO) + list(APPEND SRC "$") +endif() + +BLENDER_SRC_GTEST_EX( + NAME blenloader + SRC "${SRC}" + EXTRA_LIBS "${LIB}" + COMMAND_ARGS --test-assets-dir "${CMAKE_SOURCE_DIR}/../lib/tests") + +unset(_buildinfo_src) + +setup_liblinks(blenloader_test) diff --git a/tests/gtests/blenloader/blendfile_load_test.cc b/tests/gtests/blenloader/blendfile_load_test.cc new file mode 100644 index 00000000000..2ba3e3fcd88 --- /dev/null +++ b/tests/gtests/blenloader/blendfile_load_test.cc @@ -0,0 +1,31 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 by Blender Foundation. + */ +#include "blendfile_loading_base_test.h" + +class BlendfileLoadingTest : public BlendfileLoadingBaseTest { +}; + +TEST_F(BlendfileLoadingTest, CanaryTest) +{ + /* Load the smallest blend file we have in the SVN lib/tests directory. */ + if (!blendfile_load("modifier_stack/array_test.blend")) { + return; + } + depsgraph_create(DAG_EVAL_RENDER); + EXPECT_NE(nullptr, this->depsgraph); +} diff --git a/tests/gtests/blenloader/blendfile_loading_base_test.cc b/tests/gtests/blenloader/blendfile_loading_base_test.cc new file mode 100644 index 00000000000..5a1a7f9aae5 --- /dev/null +++ b/tests/gtests/blenloader/blendfile_loading_base_test.cc @@ -0,0 +1,172 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 by Blender Foundation. + */ +#include "blendfile_loading_base_test.h" + +extern "C" { +#include "BKE_appdir.h" +#include "BKE_blender.h" +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_main.h" +#include "BKE_modifier.h" +#include "BKE_node.h" +#include "BKE_scene.h" + +#include "BLI_threads.h" +#include "BLI_path_util.h" + +#include "BLO_readfile.h" + +#include "DEG_depsgraph_build.h" +#include "DEG_depsgraph.h" + +#include "DNA_genfile.h" /* for DNA_sdna_current_init() */ +#include "DNA_windowmanager_types.h" + +#include "IMB_imbuf.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_define.h" + +#include "WM_api.h" +#include "wm.h" +} + +DEFINE_string(test_assets_dir, "", "lib/tests directory from SVN containing the test assets."); + +BlendfileLoadingBaseTest::~BlendfileLoadingBaseTest() +{ +} + +void BlendfileLoadingBaseTest::SetUpTestCase() +{ + testing::Test::SetUpTestCase(); + + /* Minimal code to make loading a blendfile and constructing a depsgraph not crash, copied from + * main() in creator.c. */ + BLI_threadapi_init(); + + DNA_sdna_current_init(); + BKE_blender_globals_init(); + IMB_init(); + BKE_images_init(); + BKE_modifier_init(); + DEG_register_node_types(); + RNA_init(); + init_nodesystem(); + + G.background = true; + G.factory_startup = true; + + /* Allocate a dummy window manager. The real window manager will try and load Python scripts from + * the release directory, which it won't be able to find. */ + ASSERT_EQ(G.main->wm.first, nullptr); + G.main->wm.first = MEM_callocN(sizeof(wmWindowManager), __func__); +} + +void BlendfileLoadingBaseTest::TearDownTestCase() +{ + if (G.main->wm.first != nullptr) { + MEM_freeN(G.main->wm.first); + G.main->wm.first = nullptr; + } + + /* Copied from WM_exit_ex() in wm_init_exit.c, and cherry-picked those lines that match the + * allocation/initialisation done in SetUpTestCase(). */ + BKE_blender_free(); + RNA_exit(); + + DEG_free_node_types(); + DNA_sdna_current_free(); + BLI_threadapi_exit(); + + BKE_blender_atexit(); + + if (MEM_get_memory_blocks_in_use() != 0) { + size_t mem_in_use = MEM_get_memory_in_use() + MEM_get_memory_in_use(); + printf("Error: Not freed memory blocks: %u, total unfreed memory %f MB\n", + MEM_get_memory_blocks_in_use(), + (double)mem_in_use / 1024 / 1024); + MEM_printmemlist(); + } + + BKE_tempdir_session_purge(); + + testing::Test::TearDownTestCase(); +} + +void BlendfileLoadingBaseTest::TearDown() +{ + depsgraph_free(); + blendfile_free(); + + testing::Test::TearDown(); +} + +bool BlendfileLoadingBaseTest::blendfile_load(const char *filepath) +{ + if (FLAGS_test_assets_dir.empty()) { + ADD_FAILURE() + << "Pass the flag --test-assets-dir and point to the lib/tests directory from SVN."; + return false; + } + + char abspath[FILENAME_MAX]; + BLI_path_join(abspath, sizeof(abspath), FLAGS_test_assets_dir.c_str(), filepath, NULL); + + bfile = BLO_read_from_file(abspath, BLO_READ_SKIP_NONE, NULL /* reports */); + if (bfile == nullptr) { + ADD_FAILURE() << "Unable to load file '" << filepath << "' from test assets dir '" + << FLAGS_test_assets_dir << "'"; + return false; + } + return true; +} + +void BlendfileLoadingBaseTest::blendfile_free() +{ + if (bfile == nullptr) { + return; + } + + wmWindowManager *wm = static_cast(bfile->main->wm.first); + if (wm != nullptr) { + wm_close_and_free(NULL, wm); + } + BLO_blendfiledata_free(bfile); + bfile = nullptr; +} + +void BlendfileLoadingBaseTest::depsgraph_create(eEvaluationMode depsgraph_evaluation_mode) +{ + depsgraph = DEG_graph_new( + bfile->main, bfile->curscene, bfile->cur_view_layer, depsgraph_evaluation_mode); + DEG_graph_build_from_view_layer(depsgraph, bfile->main, bfile->curscene, bfile->cur_view_layer); + BKE_scene_graph_update_tagged(depsgraph, bfile->main); +} + +void BlendfileLoadingBaseTest::depsgraph_free() +{ + if (depsgraph == nullptr) { + return; + } + DEG_graph_free(depsgraph); + depsgraph = nullptr; +} diff --git a/tests/gtests/blenloader/blendfile_loading_base_test.h b/tests/gtests/blenloader/blendfile_loading_base_test.h new file mode 100644 index 00000000000..466bbcd2392 --- /dev/null +++ b/tests/gtests/blenloader/blendfile_loading_base_test.h @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 by Blender Foundation. + */ +#ifndef __BLENDFILE_LOADING_BASE_TEST_H__ +#define __BLENDFILE_LOADING_BASE_TEST_H__ + +#include "testing/testing.h" +#include "DEG_depsgraph.h" + +struct BlendFileData; +struct Depsgraph; + +class BlendfileLoadingBaseTest : public testing::Test { + protected: + struct BlendFileData *bfile = nullptr; + struct Depsgraph *depsgraph = nullptr; + + public: + virtual ~BlendfileLoadingBaseTest(); + + /* Sets up Blender just enough to not crash on loading + * a blendfile and constructing a depsgraph. */ + static void SetUpTestCase(); + static void TearDownTestCase(); + + protected: + /* Frees the depsgraph & blendfile. */ + virtual void TearDown(); + + /* Loads a blend file from the lib/tests directory from SVN. + * Returns 'ok' flag (true=good, false=bad) and sets this->bfile. + * Fails the test if the file cannot be loaded (still returns though). + * Requires the CLI argument --test-asset-dir to point to ../../lib/tests. + * + * WARNING: only files saved with Blender 2.80+ can be loaded. Since Blender + * is only partially initialised (most importantly, without window manager), + * the space types are not registered, so any versioning code that handles + * those will SEGFAULT. + */ + bool blendfile_load(const char *filepath); + /* Free bfile if it is not nullptr. */ + void blendfile_free(); + + /* Create a depsgraph. Assumes a blend file has been loaded to this->bfile. */ + void depsgraph_create(eEvaluationMode depsgraph_evaluation_mode); + /* Free the depsgraph if it's not nullptr. */ + void depsgraph_free(); +}; + +#endif /* __BLENDFILE_LOADING_BASE_TEST_H__ */ -- cgit v1.2.3 From 4e42a98edd8ca259c9b13c5548a62b46f0261d60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Thu, 28 Nov 2019 18:39:08 +0100 Subject: Fix T71147 Eevee stops rendering after selection attempt This is caused by the fallback path used by OSX, which is reconfiguring the same default VAO. But it seems to be an issue on certain drivers. --- source/blender/gpu/intern/gpu_batch.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c index 168d741f92a..23692cb20ec 100644 --- a/source/blender/gpu/intern/gpu_batch.c +++ b/source/blender/gpu/intern/gpu_batch.c @@ -655,11 +655,24 @@ void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_fi // BLI_assert(v_first + v_count <= // (batch->elem ? batch->elem->index_len : batch->verts[0]->vertex_len)); +#ifdef __APPLE__ + GLuint vao = 0; +#endif + if (!GPU_arb_base_instance_is_supported()) { if (i_first > 0) { +#ifdef __APPLE__ + /** + * There seems to be a nasty bug when drawing using the same VAO reconfiguring. (see T71147) + * We just use a throwaway VAO for that. Note that this is likely to degrade performance. + **/ + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); +#else /* If using offset drawing with instancing, we must * use the default VAO and redo bindings. */ glBindVertexArray(GPU_vao_default()); +#endif batch_update_program_bindings(batch, i_first); } else { @@ -698,6 +711,12 @@ void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_fi glEnable(GL_PRIMITIVE_RESTART); #endif } + +#ifdef __APPLE__ + if (vao != 0) { + glDeleteVertexArrays(1, &vao); + } +#endif } /* just draw some vertices and let shader place them where we want. */ -- cgit v1.2.3 From 9325e5d593ecdfc69ef6d4e129f2fbcae633af43 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 29 Nov 2019 05:05:22 +1100 Subject: Fix T71990: Apply bone transform results differ in edit/object mode When negative scaled matrices were used, the roll calculation didn't match, when calling Armature.transform(). --- source/blender/blenkernel/intern/armature.c | 36 ++++++++++++++++++----------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 58b0c9b41ea..7d10bce60ef 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -281,22 +281,16 @@ static void armature_transform_recurse(ListBase *bonebase, { for (Bone *bone = bonebase->first; bone; bone = bone->next) { - /* Transform the bone's roll. */ - if (bone_parent == NULL) { - - float roll_mat[3][3]; - { - float delta[3]; - sub_v3_v3v3(delta, bone->tail, bone->head); - vec_roll_to_mat3(delta, bone->roll, roll_mat); + float roll_mat3_pre[3][3]; + { + float delta[3]; + sub_v3_v3v3(delta, bone->tail, bone->head); + vec_roll_to_mat3(delta, bone->roll, roll_mat3_pre); + if (bone->parent == NULL) { + mul_m3_m3m3(roll_mat3_pre, mat3, roll_mat3_pre); } - - /* Transform the roll matrix. */ - mul_m3_m3m3(roll_mat, mat3, roll_mat); - - /* Apply the transformed roll back. */ - mat3_to_vec_roll(roll_mat, NULL, &bone->roll); } + bone->roll = 0.0f; mul_m4_v3(mat, bone->arm_head); mul_m4_v3(mat, bone->arm_tail); @@ -314,6 +308,20 @@ static void armature_transform_recurse(ListBase *bonebase, copy_v3_v3(bone->tail, bone->arm_tail); } + { + float roll_mat3_post[3][3]; + float delta_mat3[3][3]; + float delta[3]; + sub_v3_v3v3(delta, bone->tail, bone->head); + vec_roll_to_mat3(delta, bone->roll, roll_mat3_post); + normalize_v3(delta); + + invert_m3(roll_mat3_post); + mul_m3_m3m3(delta_mat3, roll_mat3_post, roll_mat3_pre); + + bone->roll = atan2f(delta_mat3[2][0], delta_mat3[2][2]); + } + BKE_armature_where_is_bone(bone, bone_parent, false); { -- cgit v1.2.3 From bbd5f30ad62cbd9d308fb6861ca782ac7f2f72bc Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 25 Nov 2019 17:41:25 +0100 Subject: Build: change CMake option defaults to match "make full" Previously some important features like OpenSubdiv were disabled by default, which caused confusion. The purpose of disabling some of these features was to avoid potentiall build errors on Linux. But with precompiled libraries, install_deps.sh and better library availability checking this is hopefully not much of a problem anymore. This makes "make full" obsolete, but it's kept to not break docs or shell scripts that people may have, and the .cmake config file remains useful to modify an existing build folder. This also changes some option to only be available on platforms where they are actually supported (WITH_JACK, WITH_TBB_MALLOC_PROXY and X11 options). Fixes T69742 Differential Revision: https://developer.blender.org/D6306 --- CMakeLists.txt | 121 ++++++------------------- build_files/cmake/config/blender_full.cmake | 16 ++-- build_files/cmake/config/blender_lite.cmake | 9 +- build_files/cmake/config/blender_release.cmake | 16 ++-- 4 files changed, 45 insertions(+), 117 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e6e0abe1ab8..0af6d200c6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,76 +130,6 @@ endif() get_blender_version() -#----------------------------------------------------------------------------- -# Platform Specific Defaults - -# list of var-names -set(_init_vars) - -# initialize to ON -macro(option_defaults_init) - foreach(_var ${ARGV}) - set(${_var} ON) - list(APPEND _init_vars "${_var}") - endforeach() - unset(_var) -endmacro() - -# remove from namespace -macro(option_defaults_clear) - foreach(_var ${_init_vars}) - unset(${_var}) - endforeach() - unset(_var) - unset(_init_vars) -endmacro() - - -# values to initialize WITH_**** -option_defaults_init( - _init_BUILDINFO - _init_CODEC_FFMPEG - _init_CYCLES_OSL - _init_IMAGE_OPENEXR - _init_INPUT_NDOF - _init_JACK - _init_OPENCOLLADA - _init_OPENCOLORIO - _init_SDL - _init_FFTW3 - _init_OPENSUBDIV -) - -# TBB malloc is only supported on for windows currently -if(WIN32) - set(_init_TBB_MALLOC_PROXY ON) -else() - set(_init_TBB_MALLOC_PROXY OFF) -endif() - - -# customize... -if(UNIX AND NOT APPLE) - # some of these libraries are problematic on Linux - # disable less important dependencies by default - set(_init_CODEC_FFMPEG OFF) - set(_init_CYCLES_OSL OFF) - set(_init_IMAGE_OPENEXR OFF) - set(_init_JACK OFF) - set(_init_OPENCOLLADA OFF) - set(_init_OPENCOLORIO OFF) - set(_init_SDL OFF) - set(_init_FFTW3 OFF) - set(_init_OPENSUBDIV OFF) - set(_init_OPENVDB OFF) - set(_init_OPENIMAGEDENOISE OFF) -elseif(WIN32) - set(_init_JACK OFF) -elseif(APPLE) - set(_init_JACK OFF) -endif() - - #----------------------------------------------------------------------------- # Options @@ -226,7 +156,7 @@ if(APPLE) option(WITH_PYTHON_FRAMEWORK "Enable building using the Python available in the framework (OSX only)" OFF) endif() -option(WITH_BUILDINFO "Include extra build details (only disable for development & faster builds)" ${_init_BUILDINFO}) +option(WITH_BUILDINFO "Include extra build details (only disable for development & faster builds)" ON) if(${CMAKE_VERSION} VERSION_LESS 2.8.8) # add_library OBJECT arg unsupported set(WITH_BUILDINFO OFF) @@ -240,20 +170,20 @@ mark_as_advanced(BUILDINFO_OVERRIDE_TIME) option(WITH_IK_ITASC "Enable ITASC IK solver (only disable for development & for incompatible C++ compilers)" ON) option(WITH_IK_SOLVER "Enable Legacy IK solver (only disable for development)" ON) -option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke, ocean sim, and audio effects)" ${_init_FFTW3}) +option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke, ocean sim, and audio effects)" ON) option(WITH_BULLET "Enable Bullet (Physics Engine)" ON) option(WITH_SYSTEM_BULLET "Use the systems bullet library (currently unsupported due to missing features in upstream!)" ) mark_as_advanced(WITH_SYSTEM_BULLET) -option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ${_init_OPENCOLORIO}) +option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ON) # Compositor option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON) -option(WITH_OPENIMAGEDENOISE "Enable the OpenImageDenoise compositing node" ${_init_OPENIMAGEDENOISE}) +option(WITH_OPENIMAGEDENOISE "Enable the OpenImageDenoise compositing node" ON) -option(WITH_OPENSUBDIV "Enable OpenSubdiv for surface subdivision" ${_init_OPENSUBDIV}) +option(WITH_OPENSUBDIV "Enable OpenSubdiv for surface subdivision" ON) -option(WITH_OPENVDB "Enable features relying on OpenVDB" ${_init_OPENVDB}) -option(WITH_OPENVDB_BLOSC "Enable blosc compression for OpenVDB, only enable if OpenVDB was built with blosc support" ${_init_OPENVDB}) +option(WITH_OPENVDB "Enable features relying on OpenVDB" ON) +option(WITH_OPENVDB_BLOSC "Enable blosc compression for OpenVDB, only enable if OpenVDB was built with blosc support" ON) option(WITH_OPENVDB_3_ABI_COMPATIBLE "Assume OpenVDB library has been compiled with version 3 ABI compatibility" OFF) mark_as_advanced(WITH_OPENVDB_3_ABI_COMPATIBLE) @@ -315,11 +245,11 @@ endif() option(WITH_MOD_FLUID "Enable Elbeem Modifier (Fluid Simulation)" ON) option(WITH_MOD_SMOKE "Enable Smoke Modifier (Smoke Simulation)" ON) option(WITH_MOD_REMESH "Enable Remesh Modifier" ON) -option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" OFF) +option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" ON) # Image format support option(WITH_OPENIMAGEIO "Enable OpenImageIO Support (http://www.openimageio.org)" ON) -option(WITH_IMAGE_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ${_init_IMAGE_OPENEXR}) +option(WITH_IMAGE_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ON) option(WITH_IMAGE_OPENJPEG "Enable OpenJpeg Support (http://www.openjpeg.org)" ON) option(WITH_IMAGE_TIFF "Enable LibTIFF Support" ON) option(WITH_IMAGE_DDS "Enable DDS Image Support" ON) @@ -328,23 +258,25 @@ option(WITH_IMAGE_HDR "Enable HDR Image Support" ON) # Audio/Video format support option(WITH_CODEC_AVI "Enable Blenders own AVI file support (raw/jpeg)" ON) -option(WITH_CODEC_FFMPEG "Enable FFMPeg Support (http://ffmpeg.org)" ${_init_CODEC_FFMPEG}) -option(WITH_CODEC_SNDFILE "Enable libsndfile Support (http://www.mega-nerd.com/libsndfile)" OFF) +option(WITH_CODEC_FFMPEG "Enable FFMPeg Support (http://ffmpeg.org)" ON) +option(WITH_CODEC_SNDFILE "Enable libsndfile Support (http://www.mega-nerd.com/libsndfile)" ON) # Alembic support -option(WITH_ALEMBIC "Enable Alembic Support" OFF) +option(WITH_ALEMBIC "Enable Alembic Support" ON) option(WITH_ALEMBIC_HDF5 "Enable Legacy Alembic Support (not officially supported)" OFF) # 3D format support # Disable opencollada when we don't have precompiled libs -option(WITH_OPENCOLLADA "Enable OpenCollada Support (http://www.opencollada.org)" ${_init_OPENCOLLADA}) +option(WITH_OPENCOLLADA "Enable OpenCollada Support (http://www.opencollada.org)" ON) # Sound output -option(WITH_SDL "Enable SDL for sound and joystick support" ${_init_SDL}) +option(WITH_SDL "Enable SDL for sound and joystick support" ON) option(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON) -option(WITH_JACK "Enable JACK Support (http://www.jackaudio.org)" ${_init_JACK}) -if(UNIX AND NOT APPLE) - option(WITH_JACK_DYNLOAD "Enable runtime dynamic JACK libraries loading" OFF) +if(NOT WIN32) + option(WITH_JACK "Enable JACK Support (http://www.jackaudio.org)" ON) + if(UNIX AND NOT APPLE) + option(WITH_JACK_DYNLOAD "Enable runtime dynamic JACK libraries loading" OFF) + endif() endif() if(UNIX AND NOT APPLE) option(WITH_SDL_DYNLOAD "Enable runtime dynamic SDL libraries loading" OFF) @@ -360,7 +292,7 @@ option(WITH_DRACO "Enable Draco mesh compression Python module (used for # Camera/motion tracking option(WITH_LIBMV "Enable Libmv structure from motion library" ON) -option(WITH_LIBMV_SCHUR_SPECIALIZATIONS "Enable fixed-size schur specializations." OFF) +option(WITH_LIBMV_SCHUR_SPECIALIZATIONS "Enable fixed-size schur specializations." ON) mark_as_advanced(WITH_LIBMV_SCHUR_SPECIALIZATIONS) # Logging/unbit test libraries. @@ -376,7 +308,7 @@ option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON) if(WIN32) option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON) endif() -option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ${_init_INPUT_NDOF}) +option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON) if(UNIX AND NOT APPLE) option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON) option(WITH_STATIC_LIBS "Try to link with static libraries, as much as possible, to make blender more portable across distributions" OFF) @@ -412,7 +344,7 @@ mark_as_advanced(WITH_CPU_SSE) option(WITH_CYCLES "Enable Cycles Render Engine" ON) option(WITH_CYCLES_STANDALONE "Build Cycles standalone application" OFF) option(WITH_CYCLES_STANDALONE_GUI "Build Cycles standalone with GUI" OFF) -option(WITH_CYCLES_OSL "Build Cycles with OSL support" ${_init_CYCLES_OSL}) +option(WITH_CYCLES_OSL "Build Cycles with OSL support" ON) option(WITH_CYCLES_EMBREE "Build Cycles with Embree support" OFF) option(WITH_CYCLES_CUDA_BINARIES "Build Cycles CUDA binaries" OFF) option(WITH_CYCLES_CUBIN_COMPILER "Build cubins with nvrtc based compiler instead of nvcc" OFF) @@ -468,7 +400,11 @@ mark_as_advanced(WITH_ASSERT_ABORT) option(WITH_BOOST "Enable features depending on boost" ON) option(WITH_TBB "Enable features depending on TBB (OpenVDB, OpenImageDenoise, sculpt multithreading)" ON) -option(WITH_TBB_MALLOC_PROXY "Enable the TBB malloc replacement" ${_init_TBB_MALLOC_PROXY}) + +# TBB malloc is only supported on for windows currently +if(WIN32) + option(WITH_TBB_MALLOC_PROXY "Enable the TBB malloc replacement" ON) +endif() # Unit testsing option(WITH_GTESTS "Enable GTest unit testing" OFF) @@ -591,9 +527,6 @@ endif() option(POSTINSTALL_SCRIPT "Run given CMake script after installation process" OFF) mark_as_advanced(POSTINSTALL_SCRIPT) -# avoid using again -option_defaults_clear() - # end option(...) diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake index 56b970c349d..2511ee02e39 100644 --- a/build_files/cmake/config/blender_full.cmake +++ b/build_files/cmake/config/blender_full.cmake @@ -18,7 +18,6 @@ set(WITH_LIBMV ON CACHE BOOL "" FORCE) set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE) set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE) set(WITH_FREESTYLE ON CACHE BOOL "" FORCE) -set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE) set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE) set(WITH_IK_ITASC ON CACHE BOOL "" FORCE) set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE) @@ -49,20 +48,17 @@ set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE) set(WITH_QUADRIFLOW ON CACHE BOOL "" FORCE) set(WITH_SDL ON CACHE BOOL "" FORCE) set(WITH_TBB ON CACHE BOOL "" FORCE) -set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE) -set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE) set(WITH_MEM_JEMALLOC ON CACHE BOOL "" FORCE) # platform dependent options -if(UNIX AND NOT APPLE) +if(NOT WIN32) set(WITH_JACK ON CACHE BOOL "" FORCE) +endif() +if(UNIX AND NOT APPLE) set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE) -elseif(WIN32) - set(WITH_JACK OFF CACHE BOOL "" FORCE) -elseif(APPLE) - set(WITH_JACK ON CACHE BOOL "" FORCE) - -# include("${CMAKE_CURRENT_SOURCE_DIR}/../platform/platform_apple_xcode.cmake") + set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE) + set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE) + set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE) endif() diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake index 2a1f4a59c15..3a67836d253 100644 --- a/build_files/cmake/config/blender_lite.cmake +++ b/build_files/cmake/config/blender_lite.cmake @@ -24,7 +24,6 @@ set(WITH_LIBMV OFF CACHE BOOL "" FORCE) set(WITH_LLVM OFF CACHE BOOL "" FORCE) set(WITH_COMPOSITOR OFF CACHE BOOL "" FORCE) set(WITH_FREESTYLE OFF CACHE BOOL "" FORCE) -set(WITH_GHOST_XDND OFF CACHE BOOL "" FORCE) set(WITH_IK_SOLVER OFF CACHE BOOL "" FORCE) set(WITH_IK_ITASC OFF CACHE BOOL "" FORCE) set(WITH_IMAGE_CINEON OFF CACHE BOOL "" FORCE) @@ -54,5 +53,9 @@ set(WITH_OPENVDB OFF CACHE BOOL "" FORCE) set(WITH_QUADRIFLOW OFF CACHE BOOL "" FORCE) set(WITH_SDL OFF CACHE BOOL "" FORCE) set(WITH_TBB OFF CACHE BOOL "" FORCE) -set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE) -set(WITH_X11_XF86VMODE OFF CACHE BOOL "" FORCE) + +if(UNIX AND NOT APPLE) + set(WITH_GHOST_XDND OFF CACHE BOOL "" FORCE) + set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE) + set(WITH_X11_XF86VMODE OFF CACHE BOOL "" FORCE) +endif() diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake index af089834295..813dfc493b5 100644 --- a/build_files/cmake/config/blender_release.cmake +++ b/build_files/cmake/config/blender_release.cmake @@ -19,7 +19,6 @@ set(WITH_LIBMV ON CACHE BOOL "" FORCE) set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE) set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE) set(WITH_FREESTYLE ON CACHE BOOL "" FORCE) -set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE) set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE) set(WITH_IK_ITASC ON CACHE BOOL "" FORCE) set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE) @@ -50,8 +49,6 @@ set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE) set(WITH_QUADRIFLOW ON CACHE BOOL "" FORCE) set(WITH_SDL ON CACHE BOOL "" FORCE) set(WITH_TBB ON CACHE BOOL "" FORCE) -set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE) -set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE) set(WITH_MEM_JEMALLOC ON CACHE BOOL "" FORCE) set(WITH_CYCLES_CUDA_BINARIES ON CACHE BOOL "" FORCE) @@ -60,13 +57,12 @@ set(CYCLES_CUDA_BINARIES_ARCH sm_30;sm_35;sm_37;sm_50;sm_52;sm_60;sm_61;sm_70;sm set(WITH_CYCLES_DEVICE_OPTIX ON CACHE BOOL "" FORCE) # platform dependent options -if(UNIX AND NOT APPLE) +if(NOT WIN32) set(WITH_JACK ON CACHE BOOL "" FORCE) +endif() +if(UNIX AND NOT APPLE) set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE) -elseif(WIN32) - set(WITH_JACK OFF CACHE BOOL "" FORCE) -elseif(APPLE) - set(WITH_JACK ON CACHE BOOL "" FORCE) - -# include("${CMAKE_CURRENT_SOURCE_DIR}/../platform/platform_apple_xcode.cmake") + set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE) + set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE) + set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE) endif() -- cgit v1.2.3 From 7e9a827c58944737cd4d5505182317755d98d0fd Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 28 Nov 2019 15:00:30 -0700 Subject: CMake: Remove stray WITH_JACK in full configuration --- build_files/cmake/config/blender_full.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake index 2511ee02e39..fae15ea979b 100644 --- a/build_files/cmake/config/blender_full.cmake +++ b/build_files/cmake/config/blender_full.cmake @@ -28,7 +28,6 @@ set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE) set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE) set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE) set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE) -set(WITH_JACK ON CACHE BOOL "" FORCE) set(WITH_LZMA ON CACHE BOOL "" FORCE) set(WITH_LZO ON CACHE BOOL "" FORCE) set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE) -- cgit v1.2.3 From 77c7440540626828b080444165a28887c255594e Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 28 Nov 2019 15:02:54 -0700 Subject: CMake: Remove stray WITH_JACK in blender_release.cmake Missed one in the previous commit. --- build_files/cmake/config/blender_release.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake index 813dfc493b5..07d95a84112 100644 --- a/build_files/cmake/config/blender_release.cmake +++ b/build_files/cmake/config/blender_release.cmake @@ -29,7 +29,6 @@ set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE) set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE) set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE) set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE) -set(WITH_JACK ON CACHE BOOL "" FORCE) set(WITH_LZMA ON CACHE BOOL "" FORCE) set(WITH_LZO ON CACHE BOOL "" FORCE) set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE) -- cgit v1.2.3 From ac15f5e9b09182340a008cb8c7605777d6736b2b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 29 Nov 2019 14:57:07 +1100 Subject: Cleanup: comments, redundant normalize --- source/blender/blenkernel/intern/armature.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 7d10bce60ef..a694a335069 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -281,6 +281,11 @@ static void armature_transform_recurse(ListBase *bonebase, { for (Bone *bone = bonebase->first; bone; bone = bone->next) { + /* Store the initial bone roll in a matrix, this is needed even for child bones + * so any change in head/tail doesn't cause the roll to change. + * + * Logic here is different to edit-mode because + * this is calculated in relative to the parent. */ float roll_mat3_pre[3][3]; { float delta[3]; @@ -290,6 +295,7 @@ static void armature_transform_recurse(ListBase *bonebase, mul_m3_m3m3(roll_mat3_pre, mat3, roll_mat3_pre); } } + /* Optional, use this for predictable results since the roll is re-calculated below anyway. */ bone->roll = 0.0f; mul_m4_v3(mat, bone->arm_head); @@ -308,17 +314,14 @@ static void armature_transform_recurse(ListBase *bonebase, copy_v3_v3(bone->tail, bone->arm_tail); } + /* Now the head/tail have been updated, set the roll back, matching 'roll_mat3_pre'. */ { - float roll_mat3_post[3][3]; - float delta_mat3[3][3]; + float roll_mat3_post[3][3], delta_mat3[3][3]; float delta[3]; sub_v3_v3v3(delta, bone->tail, bone->head); - vec_roll_to_mat3(delta, bone->roll, roll_mat3_post); - normalize_v3(delta); - + vec_roll_to_mat3(delta, 0.0f, roll_mat3_post); invert_m3(roll_mat3_post); mul_m3_m3m3(delta_mat3, roll_mat3_post, roll_mat3_pre); - bone->roll = atan2f(delta_mat3[2][0], delta_mat3[2][2]); } -- cgit v1.2.3 From 0a3339456bd3e87f7e640b569a32a624003a615a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 29 Nov 2019 18:32:20 +1100 Subject: 3D View: fix NDOF rotation around object locking pan --- source/blender/editors/space_view3d/view3d_edit.c | 41 +++++++---------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 67f23012d10..25d37c36bcc 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1431,48 +1431,33 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev xform_flag |= HAS_TRANSLATE; } } - else if ((U.ndof_flag & NDOF_MODE_ORBIT) || ED_view3d_offset_lock_check(v3d, rv3d)) { + else { /* Note: based on feedback from T67579, users want to have pan and orbit enabled at once. * It's arguable that orbit shouldn't pan (since we have a pan only operator), - * so if there are users who like to separate orbit/pan operations - it can be a preference. - * - * Also, the 'orbit' and 'free' blocks of code are now very similar. - * these could be merged, keep separate until design issues are sorted out - Campbell. */ + * so if there are users who like to separate orbit/pan operations - it can be a preference. */ + const bool is_orbit_around_pivot = (U.ndof_flag & NDOF_MODE_ORBIT) || + ED_view3d_offset_lock_check(v3d, rv3d); const bool has_rotation = NDOF_HAS_ROTATE; const bool has_translate = !is_zero_v2(ndof->tvec) && NDOF_HAS_TRANSLATE; const bool has_zoom = (ndof->tvec[2] != 0.0f); - if (has_translate || has_zoom) { - view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, has_zoom); - xform_flag |= HAS_TRANSLATE; - } - + /* Rotation first because dynamic offset resets offset otherwise (and disasbles panning). */ if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true); + const float dist_backup = rv3d->dist; + if (!is_orbit_around_pivot) { + ED_view3d_distance_set(rv3d, 0.0f); + } + view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, is_orbit_around_pivot); xform_flag |= HAS_ROTATE; + if (!is_orbit_around_pivot) { + ED_view3d_distance_set(rv3d, dist_backup); + } } - } - else { /* free/explore (like fly mode) */ - const bool has_rotation = NDOF_HAS_ROTATE; - const bool has_translate = NDOF_HAS_TRANSLATE; - const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp; - - float dist_backup; if (has_translate || has_zoom) { view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, has_zoom); xform_flag |= HAS_TRANSLATE; } - - dist_backup = rv3d->dist; - ED_view3d_distance_set(rv3d, 0.0f); - - if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, false); - xform_flag |= HAS_ROTATE; - } - - ED_view3d_distance_set(rv3d, dist_backup); } ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); -- cgit v1.2.3 From 780342caaa4b5689b28ffbdc2dc7714adf0ca944 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 29 Nov 2019 18:41:07 +1100 Subject: Preferences: increase NDOF sensitivity This was too slow taking around 8 seconds for a full revolution. --- release/datafiles/userdef/userdef_default.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release/datafiles/userdef/userdef_default.c b/release/datafiles/userdef/userdef_default.c index 93ddc43cf15..35caf9dd6cd 100644 --- a/release/datafiles/userdef/userdef_default.c +++ b/release/datafiles/userdef/userdef_default.c @@ -150,8 +150,8 @@ const UserDef U_default = { .tablet_api = USER_TABLET_AUTOMATIC, .pressure_threshold_max = 1.0, .pressure_softness = 0.0, - .ndof_sensitivity = 1.0, - .ndof_orbit_sensitivity = 1.0, + .ndof_sensitivity = 4.0, + .ndof_orbit_sensitivity = 4.0, .ndof_deadzone = 0.1, .ndof_flag = (NDOF_MODE_ORBIT | NDOF_LOCK_HORIZON | NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM | NDOF_SHOULD_ROTATE), -- cgit v1.2.3 From caca7e5162c8837d9c0912ce3413488d7427d63a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 29 Nov 2019 18:46:46 +1100 Subject: Cleanup: replace macros with functions --- source/blender/editors/space_view3d/view3d_edit.c | 30 +++++++++++++++-------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 25d37c36bcc..d40f79cea3f 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -992,8 +992,17 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) * \{ */ #ifdef WITH_INPUT_NDOF -# define NDOF_HAS_TRANSLATE ((!ED_view3d_offset_lock_check(v3d, rv3d)) && !is_zero_v3(ndof->tvec)) -# define NDOF_HAS_ROTATE (((rv3d->viewlock & RV3D_LOCKED) == 0) && !is_zero_v3(ndof->rvec)) +static bool ndof_has_translate(const wmNDOFMotionData *ndof, + const View3D *v3d, + const RegionView3D *rv3d) +{ + return !is_zero_v3(ndof->tvec) && (!ED_view3d_offset_lock_check(v3d, rv3d)); +} + +static bool ndof_has_rotate(const wmNDOFMotionData *ndof, const RegionView3D *rv3d) +{ + return !is_zero_v3(ndof->rvec) && ((rv3d->viewlock & RV3D_LOCKED) == 0); +} /** * \param depth_pt: A point to calculate the depth (in perspective mode) @@ -1189,8 +1198,8 @@ void view3d_ndof_fly(const wmNDOFMotionData *ndof, bool *r_has_translate, bool *r_has_rotate) { - bool has_translate = NDOF_HAS_TRANSLATE; - bool has_rotate = NDOF_HAS_ROTATE; + bool has_translate = ndof_has_translate(ndof, v3d, rv3d); + bool has_rotate = ndof_has_rotate(ndof, rv3d); float view_inv[4]; invert_qt_qt_normalized(view_inv, rv3d->viewquat); @@ -1338,9 +1347,10 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event) ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false); if (ndof->progress != P_FINISHING) { - const bool has_rotation = NDOF_HAS_ROTATE; + const bool has_rotation = ndof_has_rotate(ndof, rv3d); /* if we can't rotate, fallback to translate (locked axis views) */ - const bool has_translate = NDOF_HAS_TRANSLATE && (rv3d->viewlock & RV3D_LOCKED); + const bool has_translate = ndof_has_translate(ndof, v3d, rv3d) && + (rv3d->viewlock & RV3D_LOCKED); const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp; if (has_translate || has_zoom) { @@ -1423,7 +1433,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev } else if ((rv3d->persp == RV3D_ORTHO) && RV3D_VIEW_IS_AXIS(rv3d->view)) { /* if we can't rotate, fallback to translate (locked axis views) */ - const bool has_translate = NDOF_HAS_TRANSLATE; + const bool has_translate = ndof_has_translate(ndof, v3d, rv3d); const bool has_zoom = (ndof->tvec[2] != 0.0f) && ED_view3d_offset_lock_check(v3d, rv3d); if (has_translate || has_zoom) { @@ -1437,8 +1447,8 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev * so if there are users who like to separate orbit/pan operations - it can be a preference. */ const bool is_orbit_around_pivot = (U.ndof_flag & NDOF_MODE_ORBIT) || ED_view3d_offset_lock_check(v3d, rv3d); - const bool has_rotation = NDOF_HAS_ROTATE; - const bool has_translate = !is_zero_v2(ndof->tvec) && NDOF_HAS_TRANSLATE; + const bool has_rotation = ndof_has_rotate(ndof, rv3d); + const bool has_translate = !is_zero_v2(ndof->tvec) && ndof_has_translate(ndof, v3d, rv3d); const bool has_zoom = (ndof->tvec[2] != 0.0f); /* Rotation first because dynamic offset resets offset otherwise (and disasbles panning). */ @@ -1506,7 +1516,7 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *e const wmNDOFMotionData *ndof = event->customdata; char xform_flag = 0; - const bool has_translate = NDOF_HAS_TRANSLATE; + const bool has_translate = ndof_has_translate(ndof, v3d, rv3d); const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp; /* we're panning here! so erase any leftover rotation from other operators */ -- cgit v1.2.3 From 53f27cdc205327739e81e0980c5beb356c5dd793 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 29 Nov 2019 19:12:50 +1100 Subject: UI: use popover for NDOF menu Number sliders were being used in a menu which doesn't work very well. --- .../keyconfig/keymap_data/blender_default.py | 2 +- .../keymap_data/industry_compatible_data.py | 2 +- release/scripts/startup/bl_ui/space_userpref.py | 22 ++++++++++++++-------- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 3a7a142e310..06fac16292d 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -392,7 +392,7 @@ def km_window(params): ), # NDOF settings - op_menu("USERPREF_MT_ndof_settings", {"type": 'NDOF_BUTTON_MENU', "value": 'PRESS'}), + op_panel("USERPREF_PT_ndof_settings", {"type": 'NDOF_BUTTON_MENU', "value": 'PRESS'}), ("wm.context_scale_float", {"type": 'NDOF_BUTTON_PLUS', "value": 'PRESS'}, {"properties": [("data_path", 'preferences.inputs.ndof_sensitivity'), ("value", 1.1)]}), ("wm.context_scale_float", {"type": 'NDOF_BUTTON_MINUS', "value": 'PRESS'}, diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index dc62b6bba68..6bf9a60a3d7 100644 --- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -196,7 +196,7 @@ def km_window(params): op_menu("SCREEN_MT_user_menu", {"type": 'TAB', "value": 'PRESS', "shift": True}), # NDOF settings - op_menu("USERPREF_MT_ndof_settings", {"type": 'NDOF_BUTTON_MENU', "value": 'PRESS'}), + op_panel("USERPREF_PT_ndof_settings", {"type": 'NDOF_BUTTON_MENU', "value": 'PRESS'}), ("wm.context_scale_float", {"type": 'NDOF_BUTTON_PLUS', "value": 'PRESS'}, {"properties": [("data_path", 'preferences.inputs.ndof_sensitivity'), ("value", 1.1)]}), ("wm.context_scale_float", {"type": 'NDOF_BUTTON_MINUS', "value": 'PRESS'}, diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 7c6a7ecbcee..ab4d54f039e 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1409,20 +1409,24 @@ class USERPREF_PT_saveload_file_browser(PreferencePanel, Panel): flow.prop(paths, "hide_system_bookmarks") -class USERPREF_MT_ndof_settings(Menu): - # accessed from the window key-bindings in C (only) +class USERPREF_PT_ndof_settings(Panel): bl_label = "3D Mouse Settings" + bl_space_type = 'TOPBAR' # dummy. + bl_region_type = 'HEADER' def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False # No animation. input_prefs = context.preferences.inputs is_view3d = context.space_data.type == 'VIEW_3D' - layout.prop(input_prefs, "ndof_sensitivity") - layout.prop(input_prefs, "ndof_orbit_sensitivity") - layout.prop(input_prefs, "ndof_deadzone") + col = layout.column(align=True) + col.prop(input_prefs, "ndof_sensitivity") + col.prop(input_prefs, "ndof_orbit_sensitivity") + col.prop(input_prefs, "ndof_deadzone") if is_view3d: layout.separator() @@ -1430,8 +1434,8 @@ class USERPREF_MT_ndof_settings(Menu): layout.separator() layout.label(text="Orbit Style") - layout.row().prop(input_prefs, "ndof_view_navigate_method", text="") - layout.row().prop(input_prefs, "ndof_view_rotate_method", text="") + layout.row().prop(input_prefs, "ndof_view_navigate_method", text="Navigate") + layout.row().prop(input_prefs, "ndof_view_rotate_method", text="Orbit") layout.separator() layout.label(text="Orbit Options") layout.prop(input_prefs, "ndof_rotx_invert_axis") @@ -2255,7 +2259,6 @@ classes = ( USERPREF_PT_saveload_autorun, USERPREF_PT_saveload_file_browser, - USERPREF_MT_ndof_settings, USERPREF_MT_keyconfigs, USERPREF_PT_input_keyboard, @@ -2278,6 +2281,9 @@ classes = ( USERPREF_PT_experimental_all, + # Popovers. + USERPREF_PT_ndof_settings, + # Add dynamically generated editor theme panels last, # so they show up last in the theme section. *ThemeGenericClassGenerator.generate_panel_classes_from_theme_areas(), -- cgit v1.2.3 From e7e074235bdc47af424539c38a43cc9a5511d66a Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 29 Nov 2019 09:39:28 +0100 Subject: EEVEE: Cleanup Remove redundant defines. --- source/blender/draw/engines/eevee/eevee_private.h | 8 -------- source/blender/draw/engines/eevee/eevee_renderpasses.c | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index bbe68aec190..97bde2e5f2e 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -63,14 +63,6 @@ extern struct DrawEngineType draw_engine_eevee_type; # define SHADER_IRRADIANCE "#define IRRADIANCE_HL2\n" #endif -#define EEVEE_RENDERPASSES_SUPPORTED \ - (SCE_PASS_COMBINED | SCE_PASS_Z | SCE_PASS_MIST | SCE_PASS_NORMAL | SCE_PASS_AO | \ - SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT) - -#define EEVEE_RENDERPASSES_WITH_POST_PROCESSING \ - (SCE_PASS_Z | SCE_PASS_MIST | SCE_PASS_NORMAL | SCE_PASS_AO | SCE_PASS_SUBSURFACE_COLOR | \ - SCE_PASS_SUBSURFACE_DIRECT) - /* Macro causes over indentation. */ /* clang-format off */ #define SHADER_DEFINES \ diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index 9b7bd34c9fa..927ff70a52b 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -236,7 +236,7 @@ void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - bool is_valid = (render_pass & EEVEE_RENDERPASSES_SUPPORTED) > 0; + bool is_valid = (render_pass & EEVEE_RENDERPASSES_ALL) > 0; bool needs_color_transfer = (render_pass & EEVEE_RENDERPASSES_COLOR_PASS) > 0 && DRW_state_is_opengl_render(); -- cgit v1.2.3 From 9e168b63b4a45f63f17491a0e1eba025c42d0963 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Fri, 29 Nov 2019 10:01:37 +0100 Subject: GPencil: Add missing Overlay mode The VERTEX mode was not checked in shaders and must be managed equals to MATERIAL mode. --- source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl | 4 +++- source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl | 4 +++- source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl index 0c290260b20..8285541e0b4 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl @@ -51,6 +51,7 @@ uniform float fade_ob_factor; #define V3D_SHADING_MATERIAL_COLOR 0 #define V3D_SHADING_TEXTURE_COLOR 3 +#define V3D_SHADING_VERTEX_COLOR 5 in vec4 finalColor; in vec2 texCoord_interp; @@ -210,7 +211,8 @@ void main() /* for solid override color */ if (shading_type[0] == OB_SOLID) { if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) && - (shading_type[1] != V3D_SHADING_TEXTURE_COLOR)) { + (shading_type[1] != V3D_SHADING_TEXTURE_COLOR) && + (shading_type[1] != V3D_SHADING_VERTEX_COLOR)) { fragColor = wire_color; } if (viewport_xray == 1) { diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl index 87963c66858..33d7d714231 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl @@ -26,6 +26,7 @@ out vec4 finalprev_pos; #define V3D_SHADING_MATERIAL_COLOR 0 #define V3D_SHADING_TEXTURE_COLOR 3 +#define V3D_SHADING_VERTEX_COLOR 5 float defaultpixsize = pixsize * (1000.0 / pixfactor); @@ -52,7 +53,8 @@ void main() /* for solid override color */ if (shading_type[0] == OB_SOLID) { if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) && - (shading_type[1] != V3D_SHADING_TEXTURE_COLOR)) { + (shading_type[1] != V3D_SHADING_TEXTURE_COLOR) && + (shading_type[1] != V3D_SHADING_VERTEX_COLOR)) { finalColor = wire_color; } if (viewport_xray == 1) { diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl index 582b9a7f249..8df08f0bf68 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl @@ -24,6 +24,7 @@ out vec2 finaluvdata; #define V3D_SHADING_MATERIAL_COLOR 0 #define V3D_SHADING_TEXTURE_COLOR 3 +#define V3D_SHADING_VERTEX_COLOR 5 float defaultpixsize = pixsize * (1000.0 / pixfactor); @@ -49,7 +50,8 @@ void main(void) /* for solid override color */ if (shading_type[0] == OB_SOLID) { if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) && - (shading_type[1] != V3D_SHADING_TEXTURE_COLOR)) { + (shading_type[1] != V3D_SHADING_TEXTURE_COLOR) && + (shading_type[1] != V3D_SHADING_VERTEX_COLOR)) { finalColor = wire_color; } if (viewport_xray == 1) { -- cgit v1.2.3 From ae13bba24e4a104d17478be40e714a789d062fb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 29 Nov 2019 10:35:19 +0100 Subject: Archive build script: fix compatibility with older tar on CentOS 7 On CentOS 7, `tar --use-compress-program='xz -9'` tries to run `xz -9` as executable, rather than running `xz` with `-9` as argument. Passing the `-9` option via the `XZ_OPT` environment variable, as suggested by @campbellbarton in D6138, works fine. --- build_files/package_spec/build_archive.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build_files/package_spec/build_archive.py b/build_files/package_spec/build_archive.py index 58a970bca31..754bb8cd402 100755 --- a/build_files/package_spec/build_archive.py +++ b/build_files/package_spec/build_archive.py @@ -49,11 +49,14 @@ try: if not os.path.exists(output_dir): os.mkdir(output_dir) + archive_env = os.environ.copy() + if extension == 'zip': archive_cmd = ['zip', '-9', '-r', package_archive, package_dir] elif extension == 'tar.xz': archive_cmd = ['tar', '-cf', package_archive, '--owner=0', '--group=0', - '--use-compress-program=xz -9', package_dir] + '--use-compress-program=xz', package_dir] + archive_env['XZ_OPT'] = '-9' else: sys.stderr.write('Unknown archive extension: ' + extension) sys.exit(-1) -- cgit v1.2.3 From b25bb2d7ec31ef08d67142ad655d59cd37e1d747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 29 Nov 2019 10:37:43 +0100 Subject: Archive build script: stop when creating archive fails The `subprocess.call()` function doesn't check the exit status code of the subprocess. Use `subprocess.check_call()` or `subprocess.run()` instead. --- build_files/package_spec/build_archive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_files/package_spec/build_archive.py b/build_files/package_spec/build_archive.py index 754bb8cd402..d8d3c29ea48 100755 --- a/build_files/package_spec/build_archive.py +++ b/build_files/package_spec/build_archive.py @@ -61,7 +61,7 @@ try: sys.stderr.write('Unknown archive extension: ' + extension) sys.exit(-1) - subprocess.call(archive_cmd) + subprocess.check_call(archive_cmd, env=archive_env) except Exception as ex: sys.stderr.write('Failed to create package archive: ' + str(ex) + '\n') sys.exit(1) -- cgit v1.2.3 From be1f4d875fb8001a10886a8577032e0f197827d3 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Fri, 29 Nov 2019 11:22:36 +0100 Subject: Fix T72013: Gpencil Interpolate strokes causes instant crash when material list is empty The problem was the draw function tried to use the material and gpsettings and both were NULL. Now, the default material is used. --- source/blender/blenkernel/BKE_material.h | 1 + source/blender/blenkernel/intern/material.c | 5 +++++ source/blender/editors/gpencil/drawgpencil.c | 11 +++++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 7ff9c4e6376..d7b037a8189 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -95,6 +95,7 @@ bool BKE_object_material_slot_remove(struct Main *bmain, struct Object *ob); bool BKE_object_material_slot_used(struct ID *id, short actcol); struct Material *BKE_material_gpencil_get(struct Object *ob, short act); +struct Material *BKE_material_gpencil_default_get(void); struct MaterialGPencilStyle *BKE_material_gpencil_settings_get(struct Object *ob, short act); void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma); diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 73c278a0ab6..54432c8da74 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -598,6 +598,11 @@ Material *BKE_material_gpencil_get(Object *ob, short act) } } +struct Material *BKE_material_gpencil_default_get(void) +{ + return &defgpencil_material; +} + MaterialGPencilStyle *BKE_material_gpencil_settings_get(Object *ob, short act) { Material *ma = give_current_material(ob, act); diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 80795b825b0..06e5f36637b 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -51,6 +51,7 @@ #include "BKE_context.h" #include "BKE_brush.h" #include "BKE_global.h" +#include "BKE_material.h" #include "BKE_paint.h" #include "BKE_gpencil.h" #include "BKE_image.h" @@ -427,7 +428,9 @@ static void gp_draw_stroke_fill(bGPdata *gpd, const float color[4]) { BLI_assert(gps->totpoints >= 3); - Material *ma = gpd->mat[gps->mat_nr]; + const bool use_mat = (gpd->mat != NULL); + + Material *ma = (use_mat) ? gpd->mat[gps->mat_nr] : BKE_material_gpencil_default_get(); MaterialGPencilStyle *gp_style = (ma) ? ma->gp_style : NULL; /* Calculate triangles cache for filling area (must be done only after changes) */ @@ -869,6 +872,7 @@ static void gp_draw_strokes(tGPDdraw *tgpw) short sthickness; float ink[4]; const bool is_unique = (tgpw->gps != NULL); + const bool use_mat = (tgpw->gpd->mat != NULL); GPU_program_point_size(true); @@ -880,7 +884,7 @@ static void gp_draw_strokes(tGPDdraw *tgpw) continue; } /* check if the color is visible */ - Material *ma = tgpw->gpd->mat[gps->mat_nr]; + Material *ma = (use_mat) ? tgpw->gpd->mat[gps->mat_nr] : BKE_material_gpencil_default_get(); MaterialGPencilStyle *gp_style = (ma) ? ma->gp_style : NULL; if ((gp_style == NULL) || (gp_style->flag & GP_STYLE_COLOR_HIDE) || @@ -1159,6 +1163,9 @@ void ED_gp_draw_interpolation(const bContext *C, tGPDinterpolate *tgpi, const in copy_v4_v4(tgpw.tintcolor, color); tgpw.onion = true; tgpw.custonion = true; + if (obact->totcol == 0) { + tgpw.gpd->mat = NULL; + } gp_draw_strokes(&tgpw); } -- cgit v1.2.3 From e7c7707ca9a876f123511b548a742ca9373e19b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 29 Nov 2019 14:09:16 +0100 Subject: Fix T71986: Alembic: object constraints animation no longer exported `AbcTransformWriter::hasAnimation` recently became smarter than just returning `true`, but wasn't quite smart enough yet. Constraints are now considered a source of 'animation'. --- source/blender/alembic/intern/abc_transform.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc index 9b12fe86d59..9fc52d71e23 100644 --- a/source/blender/alembic/intern/abc_transform.cc +++ b/source/blender/alembic/intern/abc_transform.cc @@ -27,6 +27,7 @@ extern "C" { #include "DNA_object_types.h" +#include "BLI_listbase.h" #include "BLI_math.h" #include "BKE_animsys.h" @@ -133,7 +134,7 @@ Imath::Box3d AbcTransformWriter::bounds() bool AbcTransformWriter::hasAnimation(Object *ob) const { - return BKE_animdata_id_is_animated(&ob->id); + return !BLI_listbase_is_empty(&ob->constraints) || BKE_animdata_id_is_animated(&ob->id); } /* ************************************************************************** */ -- cgit v1.2.3 From d9e61ce1953b5d1edc6f12ee832584e7a582beda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 29 Nov 2019 14:15:07 +0100 Subject: Alembic: changed "Visible Layers" to "Visible Objects" in export options There are no more 'layers' in Blender. I chose 'Visible Objects' rather than 'Visible Collections' to be consistent with the other '{Renderable,Selected} Objects Only' options. No functional changes. --- source/blender/alembic/ABC_alembic.h | 2 +- source/blender/alembic/intern/abc_exporter.cc | 4 ++-- source/blender/alembic/intern/abc_exporter.h | 2 +- source/blender/alembic/intern/alembic_capi.cc | 2 +- source/blender/editors/io/io_alembic.c | 10 +++++----- source/blender/makesrna/intern/rna_scene_api.c | 6 +++--- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/source/blender/alembic/ABC_alembic.h b/source/blender/alembic/ABC_alembic.h index 7c5efaf309d..878dbfc2a53 100644 --- a/source/blender/alembic/ABC_alembic.h +++ b/source/blender/alembic/ABC_alembic.h @@ -59,7 +59,7 @@ struct AlembicExportParams { bool apply_subdiv; bool curves_as_mesh; bool flatten_hierarchy; - bool visible_layers_only; + bool visible_objects_only; bool renderable_only; bool face_sets; bool use_subdiv_schema; diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc index cbc8fd769b7..d422a3c023e 100644 --- a/source/blender/alembic/intern/abc_exporter.cc +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -74,7 +74,7 @@ ExportSettings::ExportSettings() depsgraph(NULL), logger(), selected_only(false), - visible_layers_only(false), + visible_objects_only(false), renderable_only(false), frame_start(1), frame_end(1), @@ -161,7 +161,7 @@ static bool export_object(const ExportSettings *const settings, } // FIXME Sybren: handle these cleanly (maybe just remove code), // now using active scene layer instead. - if (settings->visible_layers_only && !BASE_VISIBLE(v3d, base)) { + if (settings->visible_objects_only && !BASE_VISIBLE(v3d, base)) { return false; } } diff --git a/source/blender/alembic/intern/abc_exporter.h b/source/blender/alembic/intern/abc_exporter.h index a73289fcf95..923fe0ca29f 100644 --- a/source/blender/alembic/intern/abc_exporter.h +++ b/source/blender/alembic/intern/abc_exporter.h @@ -49,7 +49,7 @@ struct ExportSettings { SimpleLogger logger; bool selected_only; - bool visible_layers_only; + bool visible_objects_only; bool renderable_only; double frame_start, frame_end; diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index 1034c5b319f..5efa8c8a446 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -365,7 +365,7 @@ bool ABC_export(Scene *scene, /* TODO(Sybren): visible_layer & renderable only is ignored for now, * to be replaced with collections later in the 2.8 dev process * (also see note above). */ - job->settings.visible_layers_only = params->visible_layers_only; + job->settings.visible_objects_only = params->visible_objects_only; job->settings.renderable_only = params->renderable_only; job->settings.use_subdiv_schema = params->use_subdiv_schema; diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 573dfcde88a..809210a58b5 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -127,7 +127,7 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) .apply_subdiv = RNA_boolean_get(op->ptr, "apply_subdiv"), .curves_as_mesh = RNA_boolean_get(op->ptr, "curves_as_mesh"), .flatten_hierarchy = RNA_boolean_get(op->ptr, "flatten"), - .visible_layers_only = RNA_boolean_get(op->ptr, "visible_layers_only"), + .visible_objects_only = RNA_boolean_get(op->ptr, "visible_objects_only"), .renderable_only = RNA_boolean_get(op->ptr, "renderable_only"), .face_sets = RNA_boolean_get(op->ptr, "face_sets"), .use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"), @@ -209,7 +209,7 @@ static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr) uiItemR(row, imfptr, "renderable_only", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); - uiItemR(row, imfptr, "visible_layers_only", 0, NULL, ICON_NONE); + uiItemR(row, imfptr, "visible_objects_only", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "flatten", 0, NULL, ICON_NONE); @@ -392,10 +392,10 @@ void WM_OT_alembic_export(wmOperatorType *ot) "Export only objects marked renderable in the outliner"); RNA_def_boolean(ot->srna, - "visible_layers_only", + "visible_objects_only", 0, - "Visible Layers Only", - "Export only objects in visible layers"); + "Visible Objects Only", + "Export only objects in visible collections"); RNA_def_boolean(ot->srna, "flatten", diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 8a06d594c1f..3562569acec 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -216,7 +216,7 @@ static void rna_Scene_alembic_export(Scene *scene, bool vcolors, bool apply_subdiv, bool flatten_hierarchy, - bool visible_layers_only, + bool visible_objects_only, bool renderable_only, bool face_sets, bool use_subdiv_schema, @@ -251,7 +251,7 @@ static void rna_Scene_alembic_export(Scene *scene, .vcolors = vcolors, .apply_subdiv = apply_subdiv, .flatten_hierarchy = flatten_hierarchy, - .visible_layers_only = visible_layers_only, + .visible_objects_only = visible_objects_only, .renderable_only = renderable_only, .face_sets = face_sets, .use_subdiv_schema = use_subdiv_schema, @@ -391,7 +391,7 @@ void RNA_api_scene(StructRNA *srna) func, "apply_subdiv", 1, "Subsurfs as meshes", "Export subdivision surfaces as meshes"); RNA_def_boolean(func, "flatten", 0, "Flatten hierarchy", "Flatten hierarchy"); RNA_def_boolean(func, - "visible_layers_only", + "visible_objects_only", 0, "Visible layers only", "Export only objects in visible layers"); -- cgit v1.2.3 From ff9d33a77cacc57c2eab2d92cd9742f9e901efe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 29 Nov 2019 14:20:15 +0100 Subject: Alembic: clarification of 'visible objects only' export option tooltip The visibility of the object is what counts, not just the visibility of the collection. --- source/blender/editors/io/io_alembic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 809210a58b5..7582ef3f41d 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -395,7 +395,7 @@ void WM_OT_alembic_export(wmOperatorType *ot) "visible_objects_only", 0, "Visible Objects Only", - "Export only objects in visible collections"); + "Export only objects that are visible"); RNA_def_boolean(ot->srna, "flatten", -- cgit v1.2.3 From fc2b966fc7235a99d73e9d40736adf70f86ce506 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 29 Nov 2019 11:42:18 +0100 Subject: Refactor: Add C++ guard code to headers C++ is used more and more, and it is becoming more and more annoying to keep track of whether header have C++ guard or not. Is easier and more clear to be consistent in all headers and have such guards in all headers. --- source/blender/blenkernel/BKE_action.h | 9 ++++----- source/blender/blenkernel/BKE_animsys.h | 8 ++++++++ source/blender/blenkernel/BKE_modifier.h | 8 ++++++++ source/blender/blenkernel/BKE_sequencer.h | 8 ++++++++ source/blender/blenkernel/BKE_sound.h | 8 ++++++++ source/blender/draw/DRW_engine.h | 8 ++++++++ source/blender/makesdna/DNA_action_types.h | 8 ++++++++ source/blender/makesdna/DNA_mesh_types.h | 8 ++++++++ source/blender/makesdna/DNA_movieclip_types.h | 8 ++++++++ source/blender/makesdna/DNA_sequence_types.h | 8 ++++++++ 10 files changed, 76 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index b7139d5bbf6..fdfea95937b 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -25,6 +25,10 @@ * \brief Blender kernel action and pose functionality. */ +#ifdef __cplusplus +extern "C" { +#endif + #include "DNA_listBase.h" /* The following structures are defined in DNA_action_types.h, and DNA_anim_types.h */ @@ -38,11 +42,6 @@ struct bPose; struct bPoseChannel; struct bPoseChannel_Runtime; -/* Kernel prototypes */ -#ifdef __cplusplus -extern "C" { -#endif - /* Action Lib Stuff ----------------- */ /* Allocate a new bAction with the given name */ diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index d0249cb2b38..cacbfe35f2b 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -24,6 +24,10 @@ * \ingroup bke */ +#ifdef __cplusplus +extern "C" { +#endif + struct AnimData; struct Depsgraph; struct FCurve; @@ -297,4 +301,8 @@ void BKE_animsys_update_driver_array(struct ID *id); /* ************************************* */ +#ifdef __cplusplus +} +#endif + #endif /* __BKE_ANIMSYS_H__*/ diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 07dee83e5ca..1e549849989 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -20,6 +20,10 @@ * \ingroup bke */ +#ifdef __cplusplus +extern "C" { +#endif + #include "DNA_modifier_types.h" /* needed for all enum typdefs */ #include "BLI_compiler_attrs.h" #include "BKE_customdata.h" @@ -461,4 +465,8 @@ void modwrap_deformVertsEM(ModifierData *md, struct Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object *ob_eval, const bool get_cage_mesh); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index c1bb60737ff..1ae1772e094 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -24,6 +24,10 @@ * \ingroup bke */ +#ifdef __cplusplus +extern "C" { +#endif + struct Depsgraph; struct Editing; struct GPUOffScreen; @@ -599,4 +603,8 @@ void BKE_sequencer_color_balance_apply(struct StripColorBalance *cb, void BKE_sequencer_all_free_anim_ibufs(struct Scene *scene, int cfra); +#ifdef __cplusplus +} +#endif + #endif /* __BKE_SEQUENCER_H__ */ diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 1567985bd53..6807d81daa3 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -23,6 +23,10 @@ * \ingroup bke */ +#ifdef __cplusplus +extern "C" { +#endif + #define SOUND_WAVE_SAMPLES_PER_SECOND 250 #if defined(WITH_AUDASPACE) @@ -190,4 +194,8 @@ struct Depsgraph; void BKE_sound_evaluate(struct Depsgraph *depsgraph, struct Main *bmain, struct bSound *sound); +#ifdef __cplusplus +} +#endif + #endif /* __BKE_SOUND_H__ */ diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 34d3ae1d207..e959d0c49ee 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -23,6 +23,10 @@ #ifndef __DRW_ENGINE_H__ #define __DRW_ENGINE_H__ +#ifdef __cplusplus +extern "C" { +#endif + #include "BLI_sys_types.h" /* for bool */ struct ARegion; @@ -166,4 +170,8 @@ void DRW_deferred_shader_remove(struct GPUMaterial *mat); struct DrawDataList *DRW_drawdatalist_from_id(struct ID *id); void DRW_drawdata_free(struct ID *id); +#ifdef __cplusplus +} +#endif + #endif /* __DRW_ENGINE_H__ */ diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index b7834e2c7e0..95e6437ae8d 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -28,6 +28,10 @@ #ifndef __DNA_ACTION_TYPES_H__ #define __DNA_ACTION_TYPES_H__ +#ifdef __cplusplus +extern "C" { +#endif + #include "DNA_listBase.h" #include "DNA_ID.h" #include "DNA_view2d_types.h" @@ -955,4 +959,8 @@ typedef enum eActionChannelFlag { ACHAN_MOVED = (1u << 31), } eActionChannelFlag; +#ifdef __cplusplus +} +#endif + #endif /* __DNA_ACTION_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index fb9e522dfa9..60e0eb2976e 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -28,6 +28,10 @@ #include "DNA_ID.h" #include "DNA_customdata_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct AnimData; struct Ipo; struct Key; @@ -277,4 +281,8 @@ enum { #define MESH_MAX_VERTS 2000000000L +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index 8de79d9ea2b..2e0c43bdb51 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -24,6 +24,10 @@ #ifndef __DNA_MOVIECLIP_TYPES_H__ #define __DNA_MOVIECLIP_TYPES_H__ +#ifdef __cplusplus +extern "C" { +#endif + #include "DNA_ID.h" #include "DNA_tracking_types.h" #include "DNA_color_types.h" /* for color management */ @@ -207,4 +211,8 @@ enum { MCLIP_PROXY_RENDER_USE_FALLBACK_RENDER = 2, }; +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 8d9dc77c49b..fb941a61ae8 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -37,6 +37,10 @@ #include "DNA_vec_types.h" #include "DNA_vfont_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct Ipo; struct MovieClip; struct Scene; @@ -680,4 +684,8 @@ enum { SEQ_CACHE_PREFETCH_ENABLE = (1 << 10), }; +#ifdef __cplusplus +} +#endif + #endif /* __DNA_SEQUENCE_TYPES_H__ */ -- cgit v1.2.3 From d1166dcf315f264d514eb48ddceb13deecf01353 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 29 Nov 2019 11:43:40 +0100 Subject: Depsgraph: Refactor, split runtime backup into smaller files It started to be a long code of all various cases in a single file, which started to be really confusing. --- source/blender/depsgraph/CMakeLists.txt | 18 + .../intern/eval/deg_eval_copy_on_write.cc | 544 +-------------------- .../intern/eval/deg_eval_runtime_backup.cc | 101 ++++ .../intern/eval/deg_eval_runtime_backup.h | 55 +++ .../eval/deg_eval_runtime_backup_modifier.cc | 49 ++ .../intern/eval/deg_eval_runtime_backup_modifier.h | 58 +++ .../eval/deg_eval_runtime_backup_movieclip.cc | 61 +++ .../eval/deg_eval_runtime_backup_movieclip.h | 48 ++ .../intern/eval/deg_eval_runtime_backup_object.cc | 182 +++++++ .../intern/eval/deg_eval_runtime_backup_object.h | 59 +++ .../intern/eval/deg_eval_runtime_backup_pose.cc | 28 ++ .../intern/eval/deg_eval_runtime_backup_pose.h | 37 ++ .../intern/eval/deg_eval_runtime_backup_scene.cc | 82 ++++ .../intern/eval/deg_eval_runtime_backup_scene.h | 58 +++ .../eval/deg_eval_runtime_backup_sequence.cc | 58 +++ .../intern/eval/deg_eval_runtime_backup_sequence.h | 47 ++ .../eval/deg_eval_runtime_backup_sequencer.cc | 72 +++ .../eval/deg_eval_runtime_backup_sequencer.h | 49 ++ .../intern/eval/deg_eval_runtime_backup_sound.cc | 64 +++ .../intern/eval/deg_eval_runtime_backup_sound.h | 47 ++ 20 files changed, 1176 insertions(+), 541 deletions(-) create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.cc create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.cc create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.h create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.cc create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.cc create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.h create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.cc create mode 100644 source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.h diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index 21ab148496c..4abeec19645 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -58,6 +58,15 @@ set(SRC intern/eval/deg_eval.cc intern/eval/deg_eval_copy_on_write.cc intern/eval/deg_eval_flush.cc + intern/eval/deg_eval_runtime_backup.cc + intern/eval/deg_eval_runtime_backup_modifier.cc + intern/eval/deg_eval_runtime_backup_movieclip.cc + intern/eval/deg_eval_runtime_backup_object.cc + intern/eval/deg_eval_runtime_backup_pose.cc + intern/eval/deg_eval_runtime_backup_scene.cc + intern/eval/deg_eval_runtime_backup_sequence.cc + intern/eval/deg_eval_runtime_backup_sequencer.cc + intern/eval/deg_eval_runtime_backup_sound.cc intern/eval/deg_eval_stats.cc intern/node/deg_node.cc intern/node/deg_node_component.cc @@ -98,6 +107,15 @@ set(SRC intern/eval/deg_eval.h intern/eval/deg_eval_copy_on_write.h intern/eval/deg_eval_flush.h + intern/eval/deg_eval_runtime_backup.h + intern/eval/deg_eval_runtime_backup_modifier.h + intern/eval/deg_eval_runtime_backup_movieclip.h + intern/eval/deg_eval_runtime_backup_object.h + intern/eval/deg_eval_runtime_backup_pose.h + intern/eval/deg_eval_runtime_backup_scene.h + intern/eval/deg_eval_runtime_backup_sequence.h + intern/eval/deg_eval_runtime_backup_sequencer.h + intern/eval/deg_eval_runtime_backup_sound.h intern/eval/deg_eval_stats.h intern/node/deg_node.h intern/node/deg_node_component.h diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index 8a33453b923..3a2cf35f4d5 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -21,7 +21,7 @@ * \ingroup depsgraph */ -/* Enable special; trickery to treat nested owned IDs (such as nodetree of +/* Enable special trickery to treat nested owned IDs (such as nodetree of * material) to be handled in same way as "real" data-blocks, even tho some * internal BKE routines doesn't treat them like that. * @@ -95,6 +95,7 @@ extern "C" { #include "intern/depsgraph.h" #include "intern/builder/deg_builder.h" #include "intern/builder/deg_builder_nodes.h" +#include "intern/eval/deg_eval_runtime_backup.h" #include "intern/node/deg_node.h" #include "intern/node/deg_node_id.h" @@ -945,545 +946,6 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph, return deg_expand_copy_on_write_datablock(depsgraph, id_node, node_builder, create_placeholders); } -namespace { - -/* Backup of sequencer strips runtime data. */ - -/* Backup of a single strip. */ -class SequenceBackup { - public: - SequenceBackup() - { - reset(); - } - - inline void reset() - { - scene_sound = NULL; - } - - void init_from_sequence(Sequence *sequence) - { - scene_sound = sequence->scene_sound; - - sequence->scene_sound = NULL; - } - - void restore_to_sequence(Sequence *sequence) - { - sequence->scene_sound = scene_sound; - reset(); - } - - inline bool isEmpty() const - { - return (scene_sound == NULL); - } - - void *scene_sound; -}; - -class SequencerBackup { - public: - SequencerBackup(); - - void init_from_scene(Scene *scene); - void restore_to_scene(Scene *scene); - - typedef map SequencesBackupMap; - SequencesBackupMap sequences_backup; -}; - -SequencerBackup::SequencerBackup() -{ -} - -void SequencerBackup::init_from_scene(Scene *scene) -{ - Sequence *sequence; - SEQ_BEGIN (scene->ed, sequence) { - SequenceBackup sequence_backup; - sequence_backup.init_from_sequence(sequence); - if (!sequence_backup.isEmpty()) { - sequences_backup.insert(make_pair(sequence->orig_sequence, sequence_backup)); - } - } - SEQ_END; -} - -void SequencerBackup::restore_to_scene(Scene *scene) -{ - Sequence *sequence; - SEQ_BEGIN (scene->ed, sequence) { - SequencesBackupMap::iterator it = sequences_backup.find(sequence->orig_sequence); - if (it == sequences_backup.end()) { - continue; - } - SequenceBackup &sequence_backup = it->second; - sequence_backup.restore_to_sequence(sequence); - } - SEQ_END; - /* Cleanup audio while the scene is still known. */ - for (SequencesBackupMap::value_type &it : sequences_backup) { - SequenceBackup &sequence_backup = it.second; - if (sequence_backup.scene_sound != NULL) { - BKE_sound_remove_scene_sound(scene, sequence_backup.scene_sound); - } - } -} - -/* Backup of scene runtime data. */ - -class SceneBackup { - public: - SceneBackup(); - - void reset(); - - void init_from_scene(Scene *scene); - void restore_to_scene(Scene *scene); - - /* Sound/audio related pointers of the scene itself. - * - * NOTE: Scene can not disappear after relations update, because otherwise the entire dependency - * graph will be gone. This means we don't need to compare original scene pointer, or worry about - * freeing those if they cant' be restored: we just copy them over to a new scene. */ - void *sound_scene; - void *playback_handle; - void *sound_scrub_handle; - void *speaker_handles; - float rigidbody_last_time; - - SequencerBackup sequencer_backup; -}; - -SceneBackup::SceneBackup() -{ - reset(); -} - -void SceneBackup::reset() -{ - sound_scene = NULL; - playback_handle = NULL; - sound_scrub_handle = NULL; - speaker_handles = NULL; - rigidbody_last_time = -1; -} - -void SceneBackup::init_from_scene(Scene *scene) -{ - sound_scene = scene->sound_scene; - playback_handle = scene->playback_handle; - sound_scrub_handle = scene->sound_scrub_handle; - speaker_handles = scene->speaker_handles; - - if (scene->rigidbody_world != NULL) { - rigidbody_last_time = scene->rigidbody_world->ltime; - } - - /* Clear pointers stored in the scene, so they are not freed when copied-on-written datablock - * is freed for re-allocation. */ - scene->sound_scene = NULL; - scene->playback_handle = NULL; - scene->sound_scrub_handle = NULL; - scene->speaker_handles = NULL; - - sequencer_backup.init_from_scene(scene); -} - -void SceneBackup::restore_to_scene(Scene *scene) -{ - scene->sound_scene = sound_scene; - scene->playback_handle = playback_handle; - scene->sound_scrub_handle = sound_scrub_handle; - scene->speaker_handles = speaker_handles; - - if (scene->rigidbody_world != NULL) { - scene->rigidbody_world->ltime = rigidbody_last_time; - } - - sequencer_backup.restore_to_scene(scene); - - reset(); -} - -/* Backup of sound datablocks runtime data. */ - -class SoundBackup { - public: - SoundBackup(); - - void reset(); - - void init_from_sound(bSound *sound); - void restore_to_sound(bSound *sound); - - void *cache; - void *waveform; - void *playback_handle; -}; - -SoundBackup::SoundBackup() -{ - reset(); -} - -void SoundBackup::reset() -{ - cache = NULL; - waveform = NULL; - playback_handle = NULL; -} - -void SoundBackup::init_from_sound(bSound *sound) -{ - cache = sound->cache; - waveform = sound->waveform; - playback_handle = sound->playback_handle; - - sound->cache = NULL; - sound->waveform = NULL; - sound->playback_handle = NULL; -} - -void SoundBackup::restore_to_sound(bSound *sound) -{ - sound->cache = cache; - sound->waveform = waveform; - sound->playback_handle = playback_handle; - - reset(); -} - -/* Identifier used to match modifiers to backup/restore their runtime data. - * Identification is happening using original modifier data pointer and the - * modifier type. - * It is not enough to only pointer, since it's possible to have a situation - * when modifier is removed and a new one added, and due to memory allocation - * policy they might have same pointer. - * By adding type into matching we are at least ensuring that modifier will not - * try to interpret runtime data created by another modifier type. */ -class ModifierDataBackupID { - public: - ModifierDataBackupID() : ModifierDataBackupID(NULL, eModifierType_None) - { - } - - ModifierDataBackupID(ModifierData *modifier_data, ModifierType type) - : modifier_data(modifier_data), type(type) - { - } - - bool operator<(const ModifierDataBackupID &other) const - { - if (modifier_data < other.modifier_data) { - return true; - } - if (modifier_data == other.modifier_data) { - return static_cast(type) < static_cast(other.type); - } - return false; - } - - ModifierData *modifier_data; - ModifierType type; -}; - -/* Storage for backed up runtime modifier data. */ -typedef map ModifierRuntimeDataBackup; - -/* Storage for backed up pose channel runtime data. */ -typedef map PoseChannelRuntimeDataBackup; - -class ObjectRuntimeBackup { - public: - ObjectRuntimeBackup() : base_flag(0), base_local_view_bits(0) - { - /* TODO(sergey): Use something like BKE_object_runtime_reset(). */ - memset(&runtime, 0, sizeof(runtime)); - } - - /* Make a backup of object's evaluation runtime data, additionally - * make object to be safe for free without invalidating backed up - * pointers. */ - void init_from_object(Object *object); - void backup_modifier_runtime_data(Object *object); - void backup_pose_channel_runtime_data(Object *object); - - /* Restore all fields to the given object. */ - void restore_to_object(Object *object); - /* NOTE: Will free all runtime data which has not been restored. */ - void restore_modifier_runtime_data(Object *object); - void restore_pose_channel_runtime_data(Object *object); - - Object_Runtime runtime; - short base_flag; - unsigned short base_local_view_bits; - ModifierRuntimeDataBackup modifier_runtime_data; - PoseChannelRuntimeDataBackup pose_channel_runtime_data; -}; - -void ObjectRuntimeBackup::init_from_object(Object *object) -{ - /* Store evaluated mesh and curve_cache, and make sure we don't free it. */ - Mesh *mesh_eval = object->runtime.mesh_eval; - runtime = object->runtime; - BKE_object_runtime_reset(object); - /* Keep bbox (for now at least). */ - object->runtime.bb = runtime.bb; - /* Object update will override actual object->data to an evaluated version. - * Need to make sure we don't have data set to evaluated one before free - * anything. */ - if (mesh_eval != NULL && object->data == mesh_eval) { - object->data = runtime.mesh_orig; - } - /* Make a backup of base flags. */ - base_flag = object->base_flag; - base_local_view_bits = object->base_local_view_bits; - /* Backup tuntime data of all modifiers. */ - backup_modifier_runtime_data(object); - /* Backup runtime data of all pose channels. */ - backup_pose_channel_runtime_data(object); -} - -inline ModifierDataBackupID create_modifier_data_id(const ModifierData *modifier_data) -{ - return ModifierDataBackupID(modifier_data->orig_modifier_data, - static_cast(modifier_data->type)); -} - -void ObjectRuntimeBackup::backup_modifier_runtime_data(Object *object) -{ - LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) { - if (modifier_data->runtime == NULL) { - continue; - } - BLI_assert(modifier_data->orig_modifier_data != NULL); - ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data); - modifier_runtime_data.insert(make_pair(modifier_data_id, modifier_data->runtime)); - modifier_data->runtime = NULL; - } -} - -void ObjectRuntimeBackup::backup_pose_channel_runtime_data(Object *object) -{ - if (object->pose != NULL) { - LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - /* This is NULL in Edit mode. */ - if (pchan->orig_pchan != NULL) { - pose_channel_runtime_data[pchan->orig_pchan] = pchan->runtime; - BKE_pose_channel_runtime_reset(&pchan->runtime); - } - } - } -} - -void ObjectRuntimeBackup::restore_to_object(Object *object) -{ - Mesh *mesh_orig = object->runtime.mesh_orig; - BoundBox *bb = object->runtime.bb; - object->runtime = runtime; - object->runtime.mesh_orig = mesh_orig; - object->runtime.bb = bb; - if (object->type == OB_MESH && object->runtime.mesh_eval != NULL) { - if (object->id.recalc & ID_RECALC_GEOMETRY) { - /* If geometry is tagged for update it means, that part of - * evaluated mesh are not valid anymore. In this case we can not - * have any "persistent" pointers to point to an invalid data. - * - * We restore object's data datablock to an original copy of - * that datablock. */ - object->data = mesh_orig; - - /* After that, immediately free the invalidated caches. */ - BKE_object_free_derived_caches(object); - } - else { - Mesh *mesh_eval = object->runtime.mesh_eval; - /* Do same thing as object update: override actual object data - * pointer with evaluated datablock. */ - object->data = mesh_eval; - /* Evaluated mesh simply copied edit_mesh pointer from - * original mesh during update, need to make sure no dead - * pointers are left behind. */ - mesh_eval->edit_mesh = mesh_orig->edit_mesh; - } - } - object->base_flag = base_flag; - object->base_local_view_bits = base_local_view_bits; - /* Restore modifier's runtime data. - * NOTE: Data of unused modifiers will be freed there. */ - restore_modifier_runtime_data(object); - restore_pose_channel_runtime_data(object); -} - -void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object) -{ - LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) { - BLI_assert(modifier_data->orig_modifier_data != NULL); - ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data); - ModifierRuntimeDataBackup::iterator runtime_data_iterator = modifier_runtime_data.find( - modifier_data_id); - if (runtime_data_iterator != modifier_runtime_data.end()) { - modifier_data->runtime = runtime_data_iterator->second; - runtime_data_iterator->second = NULL; - } - } - for (ModifierRuntimeDataBackup::value_type value : modifier_runtime_data) { - const ModifierDataBackupID modifier_data_id = value.first; - void *runtime = value.second; - if (value.second == NULL) { - continue; - } - const ModifierTypeInfo *modifier_type_info = modifierType_getInfo(modifier_data_id.type); - BLI_assert(modifier_type_info != NULL); - modifier_type_info->freeRuntimeData(runtime); - } -} - -void ObjectRuntimeBackup::restore_pose_channel_runtime_data(Object *object) -{ - if (object->pose != NULL) { - LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - /* This is NULL in Edit mode. */ - if (pchan->orig_pchan != NULL) { - PoseChannelRuntimeDataBackup::iterator runtime_data_iterator = - pose_channel_runtime_data.find(pchan->orig_pchan); - if (runtime_data_iterator != pose_channel_runtime_data.end()) { - pchan->runtime = runtime_data_iterator->second; - pose_channel_runtime_data.erase(runtime_data_iterator); - } - } - } - } - for (PoseChannelRuntimeDataBackup::value_type &value : pose_channel_runtime_data) { - BKE_pose_channel_runtime_free(&value.second); - } -} - -/* Backup of movie clip runtime data. */ - -class MovieClipBackup { - public: - MovieClipBackup(); - - void reset(); - - void init_from_movieclip(MovieClip *movieclip); - void restore_to_movieclip(MovieClip *movieclip); - - struct anim *anim; - struct MovieClipCache *cache; -}; - -MovieClipBackup::MovieClipBackup() -{ - reset(); -} - -void MovieClipBackup::reset() -{ - anim = NULL; - cache = NULL; -} - -void MovieClipBackup::init_from_movieclip(MovieClip *movieclip) -{ - anim = movieclip->anim; - cache = movieclip->cache; - /* Clear pointers stored in the movie clip, so they are not freed when copied-on-written - * datablock is freed for re-allocation. */ - movieclip->anim = NULL; - movieclip->cache = NULL; -} - -void MovieClipBackup::restore_to_movieclip(MovieClip *movieclip) -{ - movieclip->anim = anim; - movieclip->cache = cache; - - reset(); -} - -class RuntimeBackup { - public: - RuntimeBackup() : drawdata_ptr(NULL) - { - drawdata_backup.first = drawdata_backup.last = NULL; - } - - /* NOTE: Will reset all runbtime fields which has been backed up to NULL. */ - void init_from_id(ID *id); - - /* Restore fields to the given ID. */ - void restore_to_id(ID *id); - - SceneBackup scene_backup; - SoundBackup sound_backup; - ObjectRuntimeBackup object_backup; - DrawDataList drawdata_backup; - DrawDataList *drawdata_ptr; - MovieClipBackup movieclip_backup; -}; - -void RuntimeBackup::init_from_id(ID *id) -{ - if (!check_datablock_expanded(id)) { - return; - } - const ID_Type id_type = GS(id->name); - switch (id_type) { - case ID_OB: - object_backup.init_from_object(reinterpret_cast(id)); - break; - case ID_SCE: - scene_backup.init_from_scene(reinterpret_cast(id)); - break; - case ID_SO: - sound_backup.init_from_sound(reinterpret_cast(id)); - break; - case ID_MC: - movieclip_backup.init_from_movieclip(reinterpret_cast(id)); - break; - default: - break; - } - /* Note that we never free GPU draw data from here since that's not - * safe for threading and draw data is likely to be re-used. */ - drawdata_ptr = DRW_drawdatalist_from_id(id); - if (drawdata_ptr != NULL) { - drawdata_backup = *drawdata_ptr; - drawdata_ptr->first = drawdata_ptr->last = NULL; - } -} - -void RuntimeBackup::restore_to_id(ID *id) -{ - const ID_Type id_type = GS(id->name); - switch (id_type) { - case ID_OB: - object_backup.restore_to_object(reinterpret_cast(id)); - break; - case ID_SCE: - scene_backup.restore_to_scene(reinterpret_cast(id)); - break; - case ID_SO: - sound_backup.restore_to_sound(reinterpret_cast(id)); - break; - case ID_MC: - movieclip_backup.restore_to_movieclip(reinterpret_cast(id)); - break; - default: - break; - } - if (drawdata_ptr != NULL) { - *drawdata_ptr = drawdata_backup; - } -} - -} // namespace - ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode *id_node) { const ID *id_orig = id_node->id_orig; @@ -1492,7 +954,7 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode if (!deg_copy_on_write_is_needed(id_orig)) { return id_cow; } - RuntimeBackup backup; + RuntimeBackup backup(depsgraph); backup.init_from_id(id_cow); deg_free_copy_on_write_datablock(id_cow); deg_expand_copy_on_write_datablock(depsgraph, id_node); diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc new file mode 100644 index 00000000000..88390ab412f --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc @@ -0,0 +1,101 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup.h" + +#include "intern/eval/deg_eval_copy_on_write.h" + +#include "BLI_utildefines.h" + +#include "DRW_engine.h" + +namespace DEG { + +RuntimeBackup::RuntimeBackup(const Depsgraph *depsgraph) + : scene_backup(depsgraph), + sound_backup(depsgraph), + object_backup(depsgraph), + drawdata_ptr(NULL), + movieclip_backup(depsgraph) +{ + drawdata_backup.first = drawdata_backup.last = NULL; +} + +void RuntimeBackup::init_from_id(ID *id) +{ + if (!deg_copy_on_write_is_expanded(id)) { + return; + } + + const ID_Type id_type = GS(id->name); + switch (id_type) { + case ID_OB: + object_backup.init_from_object(reinterpret_cast(id)); + break; + case ID_SCE: + scene_backup.init_from_scene(reinterpret_cast(id)); + break; + case ID_SO: + sound_backup.init_from_sound(reinterpret_cast(id)); + break; + case ID_MC: + movieclip_backup.init_from_movieclip(reinterpret_cast(id)); + break; + default: + break; + } + + /* Note that we never free GPU draw data from here since that's not + * safe for threading and draw data is likely to be re-used. */ + drawdata_ptr = DRW_drawdatalist_from_id(id); + if (drawdata_ptr != NULL) { + drawdata_backup = *drawdata_ptr; + drawdata_ptr->first = drawdata_ptr->last = NULL; + } +} + +void RuntimeBackup::restore_to_id(ID *id) +{ + const ID_Type id_type = GS(id->name); + switch (id_type) { + case ID_OB: + object_backup.restore_to_object(reinterpret_cast(id)); + break; + case ID_SCE: + scene_backup.restore_to_scene(reinterpret_cast(id)); + break; + case ID_SO: + sound_backup.restore_to_sound(reinterpret_cast(id)); + break; + case ID_MC: + movieclip_backup.restore_to_movieclip(reinterpret_cast(id)); + break; + default: + break; + } + if (drawdata_ptr != NULL) { + *drawdata_ptr = drawdata_backup; + } +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h new file mode 100644 index 00000000000..31ae3164e37 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "DNA_ID.h" + +#include "intern/eval/deg_eval_runtime_backup_movieclip.h" +#include "intern/eval/deg_eval_runtime_backup_object.h" +#include "intern/eval/deg_eval_runtime_backup_scene.h" +#include "intern/eval/deg_eval_runtime_backup_sound.h" + +namespace DEG { + +struct Depsgraph; + +class RuntimeBackup { + public: + explicit RuntimeBackup(const Depsgraph *depsgraph); + + /* NOTE: Will reset all runtime fields which has been backed up to NULL. */ + void init_from_id(ID *id); + + /* Restore fields to the given ID. */ + void restore_to_id(ID *id); + + SceneBackup scene_backup; + SoundBackup sound_backup; + ObjectRuntimeBackup object_backup; + DrawDataList drawdata_backup; + DrawDataList *drawdata_ptr; + MovieClipBackup movieclip_backup; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc new file mode 100644 index 00000000000..c5744533083 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc @@ -0,0 +1,49 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_modifier.h" + +namespace DEG { + +ModifierDataBackupID::ModifierDataBackupID(const Depsgraph * /*depsgraph*/) + : ModifierDataBackupID(NULL, eModifierType_None) +{ +} + +ModifierDataBackupID::ModifierDataBackupID(ModifierData *modifier_data, ModifierType type) + : modifier_data(modifier_data), type(type) +{ +} + +bool ModifierDataBackupID::operator<(const ModifierDataBackupID &other) const +{ + if (modifier_data < other.modifier_data) { + return true; + } + if (modifier_data == other.modifier_data) { + return static_cast(type) < static_cast(other.type); + } + return false; +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h new file mode 100644 index 00000000000..4b3d46126f3 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "BKE_modifier.h" + +#include "intern/depsgraph_type.h" + +struct ModifierData; + +namespace DEG { + +struct Depsgraph; + +/* Identifier used to match modifiers to backup/restore their runtime data. + * Identification is happening using original modifier data pointer and the + * modifier type. + * It is not enough to only pointer, since it's possible to have a situation + * when modifier is removed and a new one added, and due to memory allocation + * policy they might have same pointer. + * By adding type into matching we are at least ensuring that modifier will not + * try to interpret runtime data created by another modifier type. */ +class ModifierDataBackupID { + public: + ModifierDataBackupID(const Depsgraph *depsgraph); + ModifierDataBackupID(ModifierData *modifier_data, ModifierType type); + + bool operator<(const ModifierDataBackupID &other) const; + + ModifierData *modifier_data; + ModifierType type; +}; + +/* Storage for backed up runtime modifier data. */ +typedef map ModifierRuntimeDataBackup; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.cc new file mode 100644 index 00000000000..54838475bbf --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.cc @@ -0,0 +1,61 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_movieclip.h" + +#include "DNA_movieclip_types.h" + +#include "BLI_utildefines.h" + +namespace DEG { + +MovieClipBackup::MovieClipBackup(const Depsgraph * /*depsgraph*/) +{ + reset(); +} + +void MovieClipBackup::reset() +{ + anim = NULL; + cache = NULL; +} + +void MovieClipBackup::init_from_movieclip(MovieClip *movieclip) +{ + anim = movieclip->anim; + cache = movieclip->cache; + /* Clear pointers stored in the movie clip, so they are not freed when copied-on-written + * datablock is freed for re-allocation. */ + movieclip->anim = NULL; + movieclip->cache = NULL; +} + +void MovieClipBackup::restore_to_movieclip(MovieClip *movieclip) +{ + movieclip->anim = anim; + movieclip->cache = cache; + + reset(); +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h new file mode 100644 index 00000000000..a9d528a254c --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h @@ -0,0 +1,48 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +struct anim; +struct MovieClip; +struct MovieClipCache; + +namespace DEG { + +struct Depsgraph; + +/* Backup of movie clip runtime data. */ +class MovieClipBackup { + public: + MovieClipBackup(const Depsgraph *depsgraph); + + void reset(); + + void init_from_movieclip(MovieClip *movieclip); + void restore_to_movieclip(MovieClip *movieclip); + + struct anim *anim; + struct MovieClipCache *cache; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc new file mode 100644 index 00000000000..a6a042f3e7b --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc @@ -0,0 +1,182 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_object.h" + +#include + +#include "DNA_mesh_types.h" + +#include "BLI_listbase.h" + +#include "BKE_action.h" +#include "BKE_object.h" + +namespace DEG { + +ObjectRuntimeBackup::ObjectRuntimeBackup(const Depsgraph * /*depsgraph*/) + : base_flag(0), base_local_view_bits(0) +{ + /* TODO(sergey): Use something like BKE_object_runtime_reset(). */ + memset(&runtime, 0, sizeof(runtime)); +} + +void ObjectRuntimeBackup::init_from_object(Object *object) +{ + /* Store evaluated mesh and curve_cache, and make sure we don't free it. */ + Mesh *mesh_eval = object->runtime.mesh_eval; + runtime = object->runtime; + BKE_object_runtime_reset(object); + /* Keep bbox (for now at least). */ + object->runtime.bb = runtime.bb; + /* Object update will override actual object->data to an evaluated version. + * Need to make sure we don't have data set to evaluated one before free + * anything. */ + if (mesh_eval != NULL && object->data == mesh_eval) { + object->data = runtime.mesh_orig; + } + /* Make a backup of base flags. */ + base_flag = object->base_flag; + base_local_view_bits = object->base_local_view_bits; + /* Backup tuntime data of all modifiers. */ + backup_modifier_runtime_data(object); + /* Backup runtime data of all pose channels. */ + backup_pose_channel_runtime_data(object); +} + +inline ModifierDataBackupID create_modifier_data_id(const ModifierData *modifier_data) +{ + return ModifierDataBackupID(modifier_data->orig_modifier_data, + static_cast(modifier_data->type)); +} + +void ObjectRuntimeBackup::backup_modifier_runtime_data(Object *object) +{ + LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) { + if (modifier_data->runtime == NULL) { + continue; + } + BLI_assert(modifier_data->orig_modifier_data != NULL); + ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data); + modifier_runtime_data.insert(make_pair(modifier_data_id, modifier_data->runtime)); + modifier_data->runtime = NULL; + } +} + +void ObjectRuntimeBackup::backup_pose_channel_runtime_data(Object *object) +{ + if (object->pose != NULL) { + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + /* This is NULL in Edit mode. */ + if (pchan->orig_pchan != NULL) { + pose_channel_runtime_data[pchan->orig_pchan] = pchan->runtime; + BKE_pose_channel_runtime_reset(&pchan->runtime); + } + } + } +} + +void ObjectRuntimeBackup::restore_to_object(Object *object) +{ + Mesh *mesh_orig = object->runtime.mesh_orig; + BoundBox *bb = object->runtime.bb; + object->runtime = runtime; + object->runtime.mesh_orig = mesh_orig; + object->runtime.bb = bb; + if (object->type == OB_MESH && object->runtime.mesh_eval != NULL) { + if (object->id.recalc & ID_RECALC_GEOMETRY) { + /* If geometry is tagged for update it means, that part of + * evaluated mesh are not valid anymore. In this case we can not + * have any "persistent" pointers to point to an invalid data. + * + * We restore object's data datablock to an original copy of + * that datablock. */ + object->data = mesh_orig; + + /* After that, immediately free the invalidated caches. */ + BKE_object_free_derived_caches(object); + } + else { + Mesh *mesh_eval = object->runtime.mesh_eval; + /* Do same thing as object update: override actual object data + * pointer with evaluated datablock. */ + object->data = mesh_eval; + /* Evaluated mesh simply copied edit_mesh pointer from + * original mesh during update, need to make sure no dead + * pointers are left behind. */ + mesh_eval->edit_mesh = mesh_orig->edit_mesh; + } + } + object->base_flag = base_flag; + object->base_local_view_bits = base_local_view_bits; + /* Restore modifier's runtime data. + * NOTE: Data of unused modifiers will be freed there. */ + restore_modifier_runtime_data(object); + restore_pose_channel_runtime_data(object); +} + +void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object) +{ + LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) { + BLI_assert(modifier_data->orig_modifier_data != NULL); + ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data); + ModifierRuntimeDataBackup::iterator runtime_data_iterator = modifier_runtime_data.find( + modifier_data_id); + if (runtime_data_iterator != modifier_runtime_data.end()) { + modifier_data->runtime = runtime_data_iterator->second; + runtime_data_iterator->second = NULL; + } + } + for (ModifierRuntimeDataBackup::value_type value : modifier_runtime_data) { + const ModifierDataBackupID modifier_data_id = value.first; + void *runtime = value.second; + if (value.second == NULL) { + continue; + } + const ModifierTypeInfo *modifier_type_info = modifierType_getInfo(modifier_data_id.type); + BLI_assert(modifier_type_info != NULL); + modifier_type_info->freeRuntimeData(runtime); + } +} + +void ObjectRuntimeBackup::restore_pose_channel_runtime_data(Object *object) +{ + if (object->pose != NULL) { + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + /* This is NULL in Edit mode. */ + if (pchan->orig_pchan != NULL) { + PoseChannelRuntimeDataBackup::iterator runtime_data_iterator = + pose_channel_runtime_data.find(pchan->orig_pchan); + if (runtime_data_iterator != pose_channel_runtime_data.end()) { + pchan->runtime = runtime_data_iterator->second; + pose_channel_runtime_data.erase(runtime_data_iterator); + } + } + } + } + for (PoseChannelRuntimeDataBackup::value_type &value : pose_channel_runtime_data) { + BKE_pose_channel_runtime_free(&value.second); + } +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h new file mode 100644 index 00000000000..e5c3d6a967a --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h @@ -0,0 +1,59 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "DNA_object_types.h" + +#include "intern/eval/deg_eval_runtime_backup_modifier.h" +#include "intern/eval/deg_eval_runtime_backup_pose.h" + +struct Object; + +namespace DEG { + +class ObjectRuntimeBackup { + public: + ObjectRuntimeBackup(const Depsgraph *depsgraph); + + /* Make a backup of object's evaluation runtime data, additionally + * make object to be safe for free without invalidating backed up + * pointers. */ + void init_from_object(Object *object); + void backup_modifier_runtime_data(Object *object); + void backup_pose_channel_runtime_data(Object *object); + + /* Restore all fields to the given object. */ + void restore_to_object(Object *object); + /* NOTE: Will free all runtime data which has not been restored. */ + void restore_modifier_runtime_data(Object *object); + void restore_pose_channel_runtime_data(Object *object); + + Object_Runtime runtime; + short base_flag; + unsigned short base_local_view_bits; + ModifierRuntimeDataBackup modifier_runtime_data; + PoseChannelRuntimeDataBackup pose_channel_runtime_data; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.cc new file mode 100644 index 00000000000..821cc21f359 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.cc @@ -0,0 +1,28 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_pose.h" + +namespace DEG { + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.h new file mode 100644 index 00000000000..53a2c4c0784 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.h @@ -0,0 +1,37 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "intern/depsgraph_type.h" + +#include "DNA_action_types.h" + +struct bPoseChannel; + +namespace DEG { + +/* Storage for backed up pose channel runtime data. */ +typedef map PoseChannelRuntimeDataBackup; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.cc new file mode 100644 index 00000000000..a288fb6ab92 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.cc @@ -0,0 +1,82 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_scene.h" + +#include "DNA_scene_types.h" +#include "DNA_rigidbody_types.h" + +namespace DEG { + +SceneBackup::SceneBackup(const Depsgraph *depsgraph) : sequencer_backup(depsgraph) +{ + reset(); +} + +void SceneBackup::reset() +{ + sound_scene = NULL; + playback_handle = NULL; + sound_scrub_handle = NULL; + speaker_handles = NULL; + rigidbody_last_time = -1; +} + +void SceneBackup::init_from_scene(Scene *scene) +{ + sound_scene = scene->sound_scene; + playback_handle = scene->playback_handle; + sound_scrub_handle = scene->sound_scrub_handle; + speaker_handles = scene->speaker_handles; + + if (scene->rigidbody_world != NULL) { + rigidbody_last_time = scene->rigidbody_world->ltime; + } + + /* Clear pointers stored in the scene, so they are not freed when copied-on-written datablock + * is freed for re-allocation. */ + scene->sound_scene = NULL; + scene->playback_handle = NULL; + scene->sound_scrub_handle = NULL; + scene->speaker_handles = NULL; + + sequencer_backup.init_from_scene(scene); +} + +void SceneBackup::restore_to_scene(Scene *scene) +{ + scene->sound_scene = sound_scene; + scene->playback_handle = playback_handle; + scene->sound_scrub_handle = sound_scrub_handle; + scene->speaker_handles = speaker_handles; + + if (scene->rigidbody_world != NULL) { + scene->rigidbody_world->ltime = rigidbody_last_time; + } + + sequencer_backup.restore_to_scene(scene); + + reset(); +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h new file mode 100644 index 00000000000..751bc4208d2 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "intern/eval/deg_eval_runtime_backup_sequencer.h" + +struct Scene; + +namespace DEG { + +struct Depsgraph; + +/* Backup of scene runtime data. */ +class SceneBackup { + public: + SceneBackup(const Depsgraph *depsgraph); + + void reset(); + + void init_from_scene(Scene *scene); + void restore_to_scene(Scene *scene); + + /* Sound/audio related pointers of the scene itself. + * + * NOTE: Scene can not disappear after relations update, because otherwise the entire dependency + * graph will be gone. This means we don't need to compare original scene pointer, or worry about + * freeing those if they cant' be restored: we just copy them over to a new scene. */ + void *sound_scene; + void *playback_handle; + void *sound_scrub_handle; + void *speaker_handles; + float rigidbody_last_time; + + SequencerBackup sequencer_backup; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.cc new file mode 100644 index 00000000000..0150281a4ef --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.cc @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_sequence.h" + +#include "DNA_sequence_types.h" + +namespace DEG { + +SequenceBackup::SequenceBackup(const Depsgraph * /*depsgraph*/) +{ + reset(); +} + +void SequenceBackup::reset() +{ + scene_sound = NULL; +} + +void SequenceBackup::init_from_sequence(Sequence *sequence) +{ + scene_sound = sequence->scene_sound; + + sequence->scene_sound = NULL; +} + +void SequenceBackup::restore_to_sequence(Sequence *sequence) +{ + sequence->scene_sound = scene_sound; + reset(); +} + +bool SequenceBackup::isEmpty() const +{ + return (scene_sound == NULL); +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.h new file mode 100644 index 00000000000..8a762a2785e --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.h @@ -0,0 +1,47 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +struct Sequence; + +namespace DEG { + +struct Depsgraph; + +/* Backup of a single strip. */ +class SequenceBackup { + public: + SequenceBackup(const Depsgraph *depsgraph); + + void reset(); + + void init_from_sequence(Sequence *sequence); + void restore_to_sequence(Sequence *sequence); + + bool isEmpty() const; + + void *scene_sound; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc new file mode 100644 index 00000000000..08c2697aab3 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc @@ -0,0 +1,72 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_sequencer.h" + +#include "DNA_scene_types.h" +#include "DNA_sequence_types.h" + +#include "BKE_sequencer.h" +#include "BKE_sound.h" + +namespace DEG { + +SequencerBackup::SequencerBackup(const Depsgraph *depsgraph) : depsgraph(depsgraph) +{ +} + +void SequencerBackup::init_from_scene(Scene *scene) +{ + Sequence *sequence; + SEQ_BEGIN (scene->ed, sequence) { + SequenceBackup sequence_backup(depsgraph); + sequence_backup.init_from_sequence(sequence); + if (!sequence_backup.isEmpty()) { + sequences_backup.insert(make_pair(sequence->orig_sequence, sequence_backup)); + } + } + SEQ_END; +} + +void SequencerBackup::restore_to_scene(Scene *scene) +{ + Sequence *sequence; + SEQ_BEGIN (scene->ed, sequence) { + SequencesBackupMap::iterator it = sequences_backup.find(sequence->orig_sequence); + if (it == sequences_backup.end()) { + continue; + } + SequenceBackup &sequence_backup = it->second; + sequence_backup.restore_to_sequence(sequence); + } + SEQ_END; + /* Cleanup audio while the scene is still known. */ + for (SequencesBackupMap::value_type &it : sequences_backup) { + SequenceBackup &sequence_backup = it.second; + if (sequence_backup.scene_sound != NULL) { + BKE_sound_remove_scene_sound(scene, sequence_backup.scene_sound); + } + } +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h new file mode 100644 index 00000000000..57b533a1b84 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h @@ -0,0 +1,49 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "intern/eval/deg_eval_runtime_backup_sequence.h" +#include "intern/depsgraph_type.h" + +struct Scene; + +namespace DEG { + +struct Depsgraph; + +/* Backup of sequencer strips runtime data. */ +class SequencerBackup { + public: + SequencerBackup(const Depsgraph *depsgraph); + + void init_from_scene(Scene *scene); + void restore_to_scene(Scene *scene); + + const Depsgraph *depsgraph; + + typedef map SequencesBackupMap; + SequencesBackupMap sequences_backup; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.cc new file mode 100644 index 00000000000..0c54032e32c --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.cc @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_sound.h" + +#include "BLI_utildefines.h" + +#include "DNA_sound_types.h" + +namespace DEG { + +SoundBackup::SoundBackup(const Depsgraph * /*depsgraph*/) +{ + reset(); +} + +void SoundBackup::reset() +{ + cache = NULL; + waveform = NULL; + playback_handle = NULL; +} + +void SoundBackup::init_from_sound(bSound *sound) +{ + cache = sound->cache; + waveform = sound->waveform; + playback_handle = sound->playback_handle; + + sound->cache = NULL; + sound->waveform = NULL; + sound->playback_handle = NULL; +} + +void SoundBackup::restore_to_sound(bSound *sound) +{ + sound->cache = cache; + sound->waveform = waveform; + sound->playback_handle = playback_handle; + + reset(); +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.h new file mode 100644 index 00000000000..87783146701 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.h @@ -0,0 +1,47 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +struct bSound; + +namespace DEG { + +struct Depsgraph; + +/* Backup of sound datablocks runtime data. */ +class SoundBackup { + public: + SoundBackup(const Depsgraph *depsgraph); + + void reset(); + + void init_from_sound(bSound *sound); + void restore_to_sound(bSound *sound); + + void *cache; + void *waveform; + void *playback_handle; +}; + +} // namespace DEG -- cgit v1.2.3 From 64f311289a3f6400b460d5ca8834f9ab4f17521e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 29 Nov 2019 12:11:19 +0100 Subject: Cleanup: Remove unused function --- source/blender/blenkernel/BKE_animsys.h | 3 --- source/blender/blenkernel/intern/anim_sys.c | 14 -------------- 2 files changed, 17 deletions(-) diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index cacbfe35f2b..74ef529ff6a 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -262,9 +262,6 @@ void BKE_animsys_evaluate_all_animation(struct Main *main, struct Scene *scene, float ctime); -/* TODO(sergey): This is mainly a temp public function. */ -bool BKE_animsys_execute_fcurve(struct PointerRNA *ptr, struct FCurve *fcu, float curval); - /* ------------ Specialized API --------------- */ /* There are a few special tools which require these following functions. They are NOT to be used * for standard animation evaluation UNDER ANY CIRCUMSTANCES! diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index eea71d52ab6..249f384ceee 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1845,20 +1845,6 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val return true; } -/* Simple replacement based data-setting of the FCurve using RNA */ -bool BKE_animsys_execute_fcurve(PointerRNA *ptr, FCurve *fcu, float curval) -{ - PathResolvedRNA anim_rna; - bool ok = false; - - if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { - ok = animsys_write_rna_setting(&anim_rna, curval); - } - - /* return whether we were successful */ - return ok; -} - static bool animsys_construct_orig_pointer_rna(const PointerRNA *ptr, PointerRNA *ptr_orig) { *ptr_orig = *ptr; -- cgit v1.2.3 From 4feced2f3e5a3b5a9719d6e03af49ec639ab1374 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 29 Nov 2019 12:41:33 +0100 Subject: Refactor: Make animated RNA value read/write more reusable Currently unused, but needed for coming fix. --- source/blender/blenkernel/BKE_animsys.h | 4 ++++ source/blender/blenkernel/intern/anim_sys.c | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 74ef529ff6a..963e3158d46 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -37,6 +37,7 @@ struct KeyingSet; struct ListBase; struct Main; struct NlaKeyframingContext; +struct PathResolvedRNA; struct PointerRNA; struct PropertyRNA; struct ReportList; @@ -248,6 +249,9 @@ typedef enum eAnimData_Recalc { ADT_RECALC_ALL = (ADT_RECALC_DRIVERS | ADT_RECALC_ANIM), } eAnimData_Recalc; +bool BKE_animsys_read_rna_setting(struct PathResolvedRNA *anim_rna, float *r_value); +bool BKE_animsys_write_rna_setting(struct PathResolvedRNA *anim_rna, const float value); + /* Evaluation loop for evaluating animation data */ void BKE_animsys_evaluate_animdata(struct Scene *scene, struct ID *id, diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 249f384ceee..32420e2e894 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1717,7 +1717,7 @@ static bool animsys_store_rna_setting(PointerRNA *ptr, /* less than 1.0 evaluates to false, use epsilon to avoid float error */ #define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > ((1.0f - FLT_EPSILON))) -static bool animsys_read_rna_setting(PathResolvedRNA *anim_rna, float *r_value) +bool BKE_animsys_read_rna_setting(PathResolvedRNA *anim_rna, float *r_value) { PropertyRNA *prop = anim_rna->prop; PointerRNA *ptr = &anim_rna->ptr; @@ -1780,7 +1780,7 @@ static bool animsys_read_rna_setting(PathResolvedRNA *anim_rna, float *r_value) } /* Write the given value to a setting using RNA, and return success */ -static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float value) +bool BKE_animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float value) { PropertyRNA *prop = anim_rna->prop; PointerRNA *ptr = &anim_rna->ptr; @@ -1791,7 +1791,7 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val /* Check whether value is new. Otherwise we skip all the updates. */ float old_value; - if (!animsys_read_rna_setting(anim_rna, &old_value)) { + if (!BKE_animsys_read_rna_setting(anim_rna, &old_value)) { return false; } if (old_value == value) { @@ -1881,7 +1881,7 @@ static void animsys_write_orig_anim_rna(PointerRNA *ptr, PathResolvedRNA orig_anim_rna; /* TODO(sergey): Should be possible to cache resolved path in dependency graph somehow. */ if (animsys_store_rna_setting(&ptr_orig, rna_path, array_index, &orig_anim_rna)) { - animsys_write_rna_setting(&orig_anim_rna, value); + BKE_animsys_write_rna_setting(&orig_anim_rna, value); } } @@ -1912,7 +1912,7 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, PathResolvedRNA anim_rna; if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { const float curval = calculate_fcurve(&anim_rna, fcu, ctime); - animsys_write_rna_setting(&anim_rna, curval); + BKE_animsys_write_rna_setting(&anim_rna, curval); if (flush_to_original) { animsys_write_orig_anim_rna(ptr, fcu->rna_path, fcu->array_index, curval); } @@ -1946,7 +1946,7 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime PathResolvedRNA anim_rna; if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { const float curval = calculate_fcurve(&anim_rna, fcu, ctime); - ok = animsys_write_rna_setting(&anim_rna, curval); + ok = BKE_animsys_write_rna_setting(&anim_rna, curval); } /* set error-flag if evaluation failed */ @@ -2025,7 +2025,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup * PathResolvedRNA anim_rna; if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { const float curval = calculate_fcurve(&anim_rna, fcu, ctime); - animsys_write_rna_setting(&anim_rna, curval); + BKE_animsys_write_rna_setting(&anim_rna, curval); } } } @@ -3319,7 +3319,7 @@ void nladata_flush_channels(PointerRNA *ptr, if (nec->is_array) { rna.prop_index = i; } - animsys_write_rna_setting(&rna, value); + BKE_animsys_write_rna_setting(&rna, value); if (flush_to_original) { animsys_write_orig_anim_rna(ptr, nec->rna_path, rna.prop_index, value); } @@ -3804,7 +3804,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt) for (aor = adt->overrides.first; aor; aor = aor->next) { PathResolvedRNA anim_rna; if (animsys_store_rna_setting(ptr, aor->rna_path, aor->array_index, &anim_rna)) { - animsys_write_rna_setting(&anim_rna, aor->value); + BKE_animsys_write_rna_setting(&anim_rna, aor->value); } } } @@ -4129,7 +4129,7 @@ void BKE_animsys_eval_driver(Depsgraph *depsgraph, ID *id, int driver_index, FCu /* Evaluate driver, and write results to COW-domain destination */ const float ctime = DEG_get_ctime(depsgraph); const float curval = calculate_fcurve(&anim_rna, fcu, ctime); - ok = animsys_write_rna_setting(&anim_rna, curval); + ok = BKE_animsys_write_rna_setting(&anim_rna, curval); /* Flush results & status codes to original data for UI (T59984) */ if (ok && DEG_is_active(depsgraph)) { -- cgit v1.2.3 From 846e402b08d1ec2a11454fdcaac8392446109b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 29 Nov 2019 15:36:07 +0100 Subject: Alembic: fixed unit test for exporter API change --- tests/python/alembic_tests.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/python/alembic_tests.py b/tests/python/alembic_tests.py index 09e9b8981e3..9de1bc06d84 100755 --- a/tests/python/alembic_tests.py +++ b/tests/python/alembic_tests.py @@ -170,7 +170,7 @@ class HierarchicalAndFlatExportTest(AbstractAlembicTest): def test_hierarchical_export(self, tempdir: pathlib.Path): abc = tempdir / 'cubes_hierarchical.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_layers_only=True, flatten=False)" % abc.as_posix() + "renderable_only=True, visible_objects_only=True, flatten=False)" % abc.as_posix() self.run_blender('cubes-hierarchy.blend', script) # Now check the resulting Alembic file. @@ -188,7 +188,7 @@ class HierarchicalAndFlatExportTest(AbstractAlembicTest): def test_flat_export(self, tempdir: pathlib.Path): abc = tempdir / 'cubes_flat.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_layers_only=True, flatten=True)" % abc.as_posix() + "renderable_only=True, visible_objects_only=True, flatten=True)" % abc.as_posix() self.run_blender('cubes-hierarchy.blend', script) # Now check the resulting Alembic file. @@ -209,7 +209,7 @@ class DupliGroupExportTest(AbstractAlembicTest): def test_hierarchical_export(self, tempdir: pathlib.Path): abc = tempdir / 'dupligroup_hierarchical.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_layers_only=True, flatten=False)" % abc.as_posix() + "renderable_only=True, visible_objects_only=True, flatten=False)" % abc.as_posix() self.run_blender('dupligroup-scene.blend', script) # Now check the resulting Alembic file. @@ -227,7 +227,7 @@ class DupliGroupExportTest(AbstractAlembicTest): def test_flat_export(self, tempdir: pathlib.Path): abc = tempdir / 'dupligroup_hierarchical.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_layers_only=True, flatten=True)" % abc.as_posix() + "renderable_only=True, visible_objects_only=True, flatten=True)" % abc.as_posix() self.run_blender('dupligroup-scene.blend', script) # Now check the resulting Alembic file. @@ -248,7 +248,7 @@ class CurveExportTest(AbstractAlembicTest): def test_export_single_curve(self, tempdir: pathlib.Path): abc = tempdir / 'single-curve.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_layers_only=True, flatten=False)" % abc.as_posix() + "renderable_only=True, visible_objects_only=True, flatten=False)" % abc.as_posix() self.run_blender('single-curve.blend', script) # Now check the resulting Alembic file. @@ -269,7 +269,7 @@ class HairParticlesExportTest(AbstractAlembicTest): def _do_test(self, tempdir: pathlib.Path, export_hair: bool, export_particles: bool) -> pathlib.Path: abc = tempdir / 'hair-particles.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_layers_only=True, flatten=False, " \ + "renderable_only=True, visible_objects_only=True, flatten=False, " \ "export_hair=%r, export_particles=%r, as_background_job=False)" \ % (abc.as_posix(), export_hair, export_particles) self.run_blender('hair-particles.blend', script) @@ -330,7 +330,7 @@ class LongNamesExportTest(AbstractAlembicTest): def test_export_long_names(self, tempdir: pathlib.Path): abc = tempdir / 'long-names.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=False, visible_layers_only=False, flatten=False)" % abc.as_posix() + "renderable_only=False, visible_objects_only=False, flatten=False)" % abc.as_posix() self.run_blender('long-names.blend', script) name_parts = [ -- cgit v1.2.3 From f63d65ae5ab9c85656a2f81ed4680f112029fe79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 29 Nov 2019 16:05:01 +0100 Subject: Tests: prevent failing assertion when running blendfile-loading test Loading a blendfile allocates one or more windows that need to be freed. Freeing those windows also calls `BKE_workspace_instance_hook_free()` to free workspaces. However, in the `BlendfileLoadingBaseTest` test there are no workspaces allocated. This caused an assertion failure, which was worked around by not asserting when Blender is running in background mode. Reviewed by @Severin via pair programming --- source/blender/blenkernel/intern/workspace.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c index dd2b182474e..3e449fa6b25 100644 --- a/source/blender/blenkernel/intern/workspace.c +++ b/source/blender/blenkernel/intern/workspace.c @@ -26,6 +26,7 @@ #include "BLI_string_utils.h" #include "BLI_listbase.h" +#include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_library.h" #include "BKE_main.h" @@ -202,8 +203,10 @@ WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const Main *bmain) } void BKE_workspace_instance_hook_free(const Main *bmain, WorkSpaceInstanceHook *hook) { - /* workspaces should never be freed before wm (during which we call this function) */ - BLI_assert(!BLI_listbase_is_empty(&bmain->workspaces)); + /* workspaces should never be freed before wm (during which we call this function). + * However, when running in background mode, loading a blend file may allocate windows (that need + * to be freed) without creating workspaces. This happens in BlendfileLoadingBaseTest. */ + BLI_assert(!BLI_listbase_is_empty(&bmain->workspaces) || G.background); /* Free relations for this hook */ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { -- cgit v1.2.3 From 3a5d398aaf552c5c5b8662d259bffe3287dc1992 Mon Sep 17 00:00:00 2001 From: mano-wii Date: Fri, 29 Nov 2019 12:06:02 -0300 Subject: Fix T72024: Transform Snap: Alingn Rotation distorts object Occurs in edit mode when object has no uniform scale. --- source/blender/editors/transform/transform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index f3d26f85471..74fc1406795 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -5262,12 +5262,12 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) copy_v3_v3(tvec, vec); } + mul_m3_v3(td->smtx, tvec); + if (use_rotate_offset) { add_v3_v3(tvec, rotate_offset); } - mul_m3_v3(td->smtx, tvec); - if (t->options & CTX_GPENCIL_STROKES) { /* grease pencil multiframe falloff */ bGPDstroke *gps = (bGPDstroke *)td->extra; -- cgit v1.2.3 From 1321be0af9f67b40f8c481ee6a9d42482215bbb5 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Fri, 29 Nov 2019 16:27:19 +0100 Subject: GPencil: Fix error when interpolate sequence strokes with weights When the final stroke was smaller than original stroke, the weights array must be resized, but by error the function used the original stroke pointer instead of the new stroke pointer and this corrupted the pointers. --- source/blender/editors/gpencil/gpencil_interpolate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 3c4d43b5f53..ec26006eb06 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -1052,8 +1052,8 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */ if (gps_from->totpoints > gps_to->totpoints) { /* free weights of removed points */ - if (gps_from->dvert != NULL) { - BKE_defvert_array_free_elems(gps_from->dvert + gps_to->totpoints, + if (new_stroke->dvert != NULL) { + BKE_defvert_array_free_elems(new_stroke->dvert + gps_to->totpoints, gps_from->totpoints - gps_to->totpoints); } -- cgit v1.2.3 From 9ea0eb0b950f498b2bda91f137fce7c961eb08f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 29 Nov 2019 16:30:10 +0100 Subject: Alembic export: assume that transforms are always animated This is a partial rollback of f18ad385dffe70f5e57df00ff9bbb7b42fa05be0. It turned out to be more tricky to determine animatedness of an object. This fixes T71986. --- source/blender/alembic/intern/abc_transform.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc index 9fc52d71e23..033bd33d781 100644 --- a/source/blender/alembic/intern/abc_transform.cc +++ b/source/blender/alembic/intern/abc_transform.cc @@ -134,7 +134,7 @@ Imath::Box3d AbcTransformWriter::bounds() bool AbcTransformWriter::hasAnimation(Object *ob) const { - return !BLI_listbase_is_empty(&ob->constraints) || BKE_animdata_id_is_animated(&ob->id); + return true; } /* ************************************************************************** */ -- cgit v1.2.3 From 56283464b8b4b2df9c42acf1edfd810c026796a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 29 Nov 2019 16:55:39 +0100 Subject: Cleanup: Alembic: avoid unused parameter warning --- source/blender/alembic/intern/abc_transform.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc index 033bd33d781..585d4178e41 100644 --- a/source/blender/alembic/intern/abc_transform.cc +++ b/source/blender/alembic/intern/abc_transform.cc @@ -132,7 +132,7 @@ Imath::Box3d AbcTransformWriter::bounds() return Imath::transform(bounds, m_matrix); } -bool AbcTransformWriter::hasAnimation(Object *ob) const +bool AbcTransformWriter::hasAnimation(Object * /*ob*/) const { return true; } -- cgit v1.2.3 From f478fef9d6b0609f4bb60fd98e9292b60927b80e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 30 Nov 2019 03:07:00 +1100 Subject: Fix T72000: Key shortcuts unavailable in popovers --- .../blender/editors/interface/interface_handlers.c | 7 +++-- source/blender/windowmanager/WM_api.h | 3 ++ source/blender/windowmanager/WM_types.h | 2 ++ .../blender/windowmanager/intern/wm_event_system.c | 2 +- source/blender/windowmanager/intern/wm_tooltip.c | 32 ++++++++++++++++------ 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 11106dd403f..b34188684e6 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -294,6 +294,7 @@ typedef struct uiHandleButtonMulti { typedef struct uiHandleButtonData { wmWindowManager *wm; wmWindow *window; + ScrArea *area; ARegion *region; bool interactive; @@ -7721,7 +7722,8 @@ static void button_tooltip_timer_reset(bContext *C, uiBut *but) if (!wm->drags.first) { bool is_label = UI_but_has_tooltip_label(but); double delay = is_label ? UI_TOOLTIP_DELAY_LABEL : UI_TOOLTIP_DELAY; - WM_tooltip_timer_init_ex(C, data->window, data->region, ui_but_tooltip_init, delay); + WM_tooltip_timer_init_ex( + C, data->window, data->area, data->region, ui_but_tooltip_init, delay); if (is_label) { bScreen *sc = WM_window_get_active_screen(data->window); if (sc->tool_tip) { @@ -7927,6 +7929,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA data = MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData"); data->wm = CTX_wm_manager(C); data->window = CTX_wm_window(C); + data->area = CTX_wm_area(C); BLI_assert(ar != NULL); data->region = ar; @@ -8009,7 +8012,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA /* Show a label for this button. */ bScreen *sc = WM_window_get_active_screen(data->window); if ((PIL_check_seconds_timer() - WM_tooltip_time_closed()) < 0.1) { - WM_tooltip_immediate_init(C, CTX_wm_window(C), ar, ui_but_tooltip_init); + WM_tooltip_immediate_init(C, CTX_wm_window(C), data->area, ar, ui_but_tooltip_init); if (sc->tool_tip) { sc->tool_tip->pass = 1; } diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 44fd9158934..72ccbb0fb55 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -821,15 +821,18 @@ typedef struct ARegion *(*wmTooltipInitFn)(struct bContext *C, void WM_tooltip_immediate_init(struct bContext *C, struct wmWindow *win, + struct ScrArea *sa, struct ARegion *ar, wmTooltipInitFn init); void WM_tooltip_timer_init_ex(struct bContext *C, struct wmWindow *win, + struct ScrArea *sa, struct ARegion *ar, wmTooltipInitFn init, double delay); void WM_tooltip_timer_init(struct bContext *C, struct wmWindow *win, + struct ScrArea *sa, struct ARegion *ar, wmTooltipInitFn init); void WM_tooltip_timer_clear(struct bContext *C, struct wmWindow *win); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 15ad8cbedc4..0c3a5f92113 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -894,6 +894,8 @@ typedef struct wmDropBox { typedef struct wmTooltipState { /** Create tooltip on this event. */ struct wmTimer *timer; + /** The area the tooltip is created in. */ + struct ScrArea *area_from; /** The region the tooltip is created in. */ struct ARegion *region_from; /** The tooltip region. */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index c63bc24d58e..180a518de2b 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2850,7 +2850,7 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers if (wm_gizmomap_highlight_set(gzmap, C, gz, part)) { if (gz != NULL) { if (U.flag & USER_TOOLTIPS) { - WM_tooltip_timer_init(C, CTX_wm_window(C), region, WM_gizmomap_tooltip_init); + WM_tooltip_timer_init(C, CTX_wm_window(C), area, region, WM_gizmomap_tooltip_init); } } } diff --git a/source/blender/windowmanager/intern/wm_tooltip.c b/source/blender/windowmanager/intern/wm_tooltip.c index 3a219d7a573..b192ea94010 100644 --- a/source/blender/windowmanager/intern/wm_tooltip.c +++ b/source/blender/windowmanager/intern/wm_tooltip.c @@ -42,7 +42,8 @@ double WM_tooltip_time_closed(void) return g_tooltip_time_closed; } -void WM_tooltip_immediate_init(bContext *C, wmWindow *win, ARegion *ar, wmTooltipInitFn init) +void WM_tooltip_immediate_init( + bContext *C, wmWindow *win, ScrArea *sa, ARegion *ar, wmTooltipInitFn init) { WM_tooltip_timer_clear(C, win); @@ -50,13 +51,14 @@ void WM_tooltip_immediate_init(bContext *C, wmWindow *win, ARegion *ar, wmToolti if (screen->tool_tip == NULL) { screen->tool_tip = MEM_callocN(sizeof(*screen->tool_tip), __func__); } + screen->tool_tip->area_from = sa; screen->tool_tip->region_from = ar; screen->tool_tip->init = init; WM_tooltip_init(C, win); } void WM_tooltip_timer_init_ex( - bContext *C, wmWindow *win, ARegion *ar, wmTooltipInitFn init, double delay) + bContext *C, wmWindow *win, ScrArea *sa, ARegion *ar, wmTooltipInitFn init, double delay) { WM_tooltip_timer_clear(C, win); @@ -65,14 +67,16 @@ void WM_tooltip_timer_init_ex( if (screen->tool_tip == NULL) { screen->tool_tip = MEM_callocN(sizeof(*screen->tool_tip), __func__); } + screen->tool_tip->area_from = sa; screen->tool_tip->region_from = ar; screen->tool_tip->timer = WM_event_add_timer(wm, win, TIMER, delay); screen->tool_tip->init = init; } -void WM_tooltip_timer_init(bContext *C, wmWindow *win, ARegion *ar, wmTooltipInitFn init) +void WM_tooltip_timer_init( + bContext *C, wmWindow *win, ScrArea *sa, ARegion *ar, wmTooltipInitFn init) { - WM_tooltip_timer_init_ex(C, win, ar, init, UI_TOOLTIP_DELAY); + WM_tooltip_timer_init_ex(C, win, sa, ar, init, UI_TOOLTIP_DELAY); } void WM_tooltip_timer_clear(bContext *C, wmWindow *win) @@ -112,11 +116,21 @@ void WM_tooltip_init(bContext *C, wmWindow *win) } const int pass_prev = screen->tool_tip->pass; double pass_delay = 0.0; - screen->tool_tip->region = screen->tool_tip->init(C, - screen->tool_tip->region_from, - &screen->tool_tip->pass, - &pass_delay, - &screen->tool_tip->exit_on_event); + + { + ScrArea *area_prev = CTX_wm_area(C); + ARegion *ar_prev = CTX_wm_region(C); + CTX_wm_area_set(C, screen->tool_tip->area_from); + CTX_wm_region_set(C, screen->tool_tip->region_from); + screen->tool_tip->region = screen->tool_tip->init(C, + screen->tool_tip->region_from, + &screen->tool_tip->pass, + &pass_delay, + &screen->tool_tip->exit_on_event); + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, ar_prev); + } + copy_v2_v2_int(screen->tool_tip->event_xy, &win->eventstate->x); if (pass_prev != screen->tool_tip->pass) { /* The pass changed, add timer for next pass. */ -- cgit v1.2.3 From dc87d09b8b3249898e0f0d301fa22f03cff9d6d5 Mon Sep 17 00:00:00 2001 From: Alessio Monti di Sopra Date: Sat, 30 Nov 2019 17:03:22 +1100 Subject: UI: allow to hide markers region per editor Instead of having the option to show marker lines, make the marker region optional. - Added a Show Markers entry in the View menu of the animation editors. - If the markers region is not active then the Marker menu gets hidden. - Removed marker menu from the driver editor and don't allow to use marker operators. --- release/scripts/startup/bl_ui/space_dopesheet.py | 8 +- release/scripts/startup/bl_ui/space_graph.py | 9 +- release/scripts/startup/bl_ui/space_nla.py | 8 +- release/scripts/startup/bl_ui/space_sequencer.py | 6 +- release/scripts/startup/bl_ui/space_time.py | 9 +- source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenloader/intern/versioning_280.c | 51 +++++++---- .../blenloader/intern/versioning_defaults.c | 13 +-- source/blender/editors/animation/anim_markers.c | 98 +++++++++++++--------- source/blender/editors/space_action/space_action.c | 8 +- source/blender/editors/space_graph/space_graph.c | 7 +- source/blender/editors/space_nla/space_nla.c | 7 +- .../editors/space_sequencer/sequencer_draw.c | 5 +- .../editors/space_sequencer/space_sequencer.c | 2 +- source/blender/makesdna/DNA_action_types.h | 4 +- source/blender/makesdna/DNA_space_types.h | 10 +-- source/blender/makesrna/intern/rna_space.c | 42 ++++++---- 17 files changed, 179 insertions(+), 110 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index fac8ff238c0..3b498b834bf 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -288,7 +288,8 @@ class DOPESHEET_MT_editor_menus(Menu): layout.menu("DOPESHEET_MT_view") layout.menu("DOPESHEET_MT_select") - layout.menu("DOPESHEET_MT_marker") + if st.show_markers: + layout.menu("DOPESHEET_MT_marker") if st.mode == 'DOPESHEET' or (st.mode == 'ACTION' and st.action is not None): layout.menu("DOPESHEET_MT_channel") @@ -322,9 +323,12 @@ class DOPESHEET_MT_view(Menu): layout.prop(st, "show_group_colors") layout.prop(st, "show_interpolation") layout.prop(st, "show_extremes") - layout.prop(st, "show_marker_lines") layout.prop(st, "use_auto_merge_keyframes") + layout.separator() + layout.prop(st, "show_markers") + + layout.separator() layout.prop(st, "show_seconds") layout.prop(st, "show_locked_time") diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index 15ef7b0ef82..188741956ab 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -94,10 +94,12 @@ class GRAPH_MT_editor_menus(Menu): bl_label = "" def draw(self, _context): + st = _context.space_data layout = self.layout layout.menu("GRAPH_MT_view") layout.menu("GRAPH_MT_select") - layout.menu("GRAPH_MT_marker") + if st.mode != 'DRIVERS' and st.show_markers: + layout.menu("GRAPH_MT_marker") layout.menu("GRAPH_MT_channel") layout.menu("GRAPH_MT_key") @@ -117,9 +119,12 @@ class GRAPH_MT_view(Menu): layout.prop(st, "show_cursor") layout.prop(st, "show_sliders") layout.prop(st, "show_group_colors") - layout.prop(st, "show_marker_lines") layout.prop(st, "use_auto_merge_keyframes") + if st.mode != 'DRIVERS': + layout.separator() + layout.prop(st, "show_markers") + layout.separator() layout.prop(st, "use_beauty_drawing") diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py index 825e4b41609..24d6f65d9b9 100644 --- a/release/scripts/startup/bl_ui/space_nla.py +++ b/release/scripts/startup/bl_ui/space_nla.py @@ -71,10 +71,12 @@ class NLA_MT_editor_menus(Menu): bl_label = "" def draw(self, _context): + st = _context.space_data layout = self.layout layout.menu("NLA_MT_view") layout.menu("NLA_MT_select") - layout.menu("NLA_MT_marker") + if st.show_markers: + layout.menu("NLA_MT_marker") layout.menu("NLA_MT_edit") layout.menu("NLA_MT_add") @@ -96,8 +98,10 @@ class NLA_MT_view(Menu): layout.prop(st, "show_locked_time") layout.prop(st, "show_strip_curves") + + layout.separator() + layout.prop(st, "show_markers") layout.prop(st, "show_local_markers") - layout.prop(st, "show_marker_lines") layout.separator() layout.operator("anim.previewrange_set") diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 4d9a4646f5f..b4f841d2eb8 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -134,7 +134,8 @@ class SEQUENCER_MT_editor_menus(Menu): if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}: layout.menu("SEQUENCER_MT_select") - layout.menu("SEQUENCER_MT_marker") + if st.show_markers: + layout.menu("SEQUENCER_MT_marker") layout.menu("SEQUENCER_MT_add") layout.menu("SEQUENCER_MT_strip") @@ -268,7 +269,8 @@ class SEQUENCER_MT_view(Menu): layout.prop(st, "show_seconds") layout.prop(st, "show_strip_offset") - layout.prop(st, "show_marker_lines") + layout.separator() + layout.prop(st, "show_markers") if is_preview: layout.separator() diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py index 04a904edde3..6d60c67ded0 100644 --- a/release/scripts/startup/bl_ui/space_time.py +++ b/release/scripts/startup/bl_ui/space_time.py @@ -90,6 +90,7 @@ class TIME_MT_editor_menus(Menu): def draw(self, _context): layout = self.layout horizontal = (layout.direction == 'VERTICAL') + st = _context.space_data if horizontal: row = layout.row() sub = row.row(align=True) @@ -109,7 +110,8 @@ class TIME_MT_editor_menus(Menu): sub = row.row(align=True) sub.menu("TIME_MT_view") - sub.menu("TIME_MT_marker") + if st.show_markers: + sub.menu("TIME_MT_marker") class TIME_MT_marker(Menu): @@ -135,7 +137,10 @@ class TIME_MT_view(Menu): layout.separator() - layout.prop(st, "show_marker_lines") + layout.prop(st, "show_markers") + + layout.separator() + layout.prop(scene, "show_keys_from_selected_only") layout.separator() diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index c38e6e14d70..f1c45ac0b45 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ * \note Use #STRINGIFY() rather than defining with quotes. */ #define BLENDER_VERSION 282 -#define BLENDER_SUBVERSION 2 +#define BLENDER_SUBVERSION 3 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 47e55a55ea1..6c8b14ad5c7 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -3394,19 +3394,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - if (!MAIN_VERSION_ATLEAST(bmain, 280, 45)) { - for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { - for (ScrArea *area = screen->areabase.first; area; area = area->next) { - for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) { - if (sl->spacetype == SPACE_SEQ) { - SpaceSeq *sseq = (SpaceSeq *)sl; - sseq->flag |= SEQ_SHOW_MARKER_LINES; - } - } - } - } - } - if (!MAIN_VERSION_ATLEAST(bmain, 280, 46)) { /* Add wireframe color. */ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "char", "wire_color_type")) { @@ -4222,9 +4209,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - { - /* Versioning code until next subversion bump goes here. */ - + if (!MAIN_VERSION_ATLEAST(bmain, 282, 3)) { /* Remove Unified pressure/size and pressure/alpha */ for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { ToolSettings *ts = scene->toolsettings; @@ -4249,5 +4234,39 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + /* Make markers region visible by default. */ + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + for (ScrArea *area = screen->areabase.first; area; area = area->next) { + for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) { + switch (sl->spacetype) { + case SPACE_SEQ: { + SpaceSeq *sseq = (SpaceSeq *)sl; + sseq->flag |= SEQ_SHOW_MARKERS; + break; + } + case SPACE_ACTION: { + SpaceAction *saction = (SpaceAction *)sl; + saction->flag |= SACTION_SHOW_MARKERS; + break; + } + case SPACE_GRAPH: { + SpaceGraph *sipo = (SpaceGraph *)sl; + sipo->flag |= SIPO_SHOW_MARKERS; + break; + } + case SPACE_NLA: { + SpaceNla *snla = (SpaceNla *)sl; + snla->flag |= SNLA_SHOW_MARKERS; + break; + } + } + } + } + } + } + + { + /* Versioning code until next subversion bump goes here. */ } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index f2d6db886d3..1c88f6b00af 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -150,10 +150,9 @@ static void blo_update_defaults_screen(bScreen *screen, } } else if (sa->spacetype == SPACE_ACTION) { - /* Show marker lines, hide channels and collapse summary in timelines. */ + /* Show markers region, hide channels and collapse summary in timelines. */ SpaceAction *saction = sa->spacedata.first; - saction->flag |= SACTION_SHOW_MARKER_LINES; - + saction->flag |= SACTION_SHOW_MARKERS; if (saction->mode == SACTCONT_TIMELINE) { saction->ads.flag |= ADS_FLAG_SUMMARY_COLLAPSED; @@ -166,11 +165,15 @@ static void blo_update_defaults_screen(bScreen *screen, } else if (sa->spacetype == SPACE_GRAPH) { SpaceGraph *sipo = sa->spacedata.first; - sipo->flag |= SIPO_MARKER_LINES; + sipo->flag |= SIPO_SHOW_MARKERS; } else if (sa->spacetype == SPACE_NLA) { SpaceNla *snla = sa->spacedata.first; - snla->flag |= SNLA_SHOW_MARKER_LINES; + snla->flag |= SNLA_SHOW_MARKERS; + } + else if (sa->spacetype == SPACE_SEQ) { + SpaceSeq *seq = sa->spacedata.first; + seq->flag |= SEQ_SHOW_MARKERS; } else if (sa->spacetype == SPACE_TEXT) { /* Show syntax and line numbers in Script workspace text editor. */ diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 36583ecf060..13358808a23 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -228,6 +228,47 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la *last = max; } +/** + * Function used in operator polls, checks whether the markers region is currently drawn in the + * editor in which the operator is called. + */ +static bool ED_operator_markers_region_active(bContext *C) +{ + ScrArea *sa = CTX_wm_area(C); + + switch (sa->spacetype) { + case SPACE_ACTION: { + SpaceAction *saction = sa->spacedata.first; + if (saction->flag & SACTION_SHOW_MARKERS) { + return true; + } + break; + } + case SPACE_GRAPH: { + SpaceGraph *sipo = sa->spacedata.first; + if (sipo->mode != SIPO_MODE_DRIVERS && sipo->flag & SIPO_SHOW_MARKERS) { + return true; + } + break; + } + case SPACE_NLA: { + SpaceNla *snla = sa->spacedata.first; + if (snla->flag & SNLA_SHOW_MARKERS) { + return true; + } + break; + } + case SPACE_SEQ: { + SpaceSeq *seq = sa->spacedata.first; + if (seq->flag & SEQ_SHOW_MARKERS) { + return true; + } + break; + } + } + return false; +} + static bool region_position_is_over_marker(View2D *v2d, ListBase *markers, float region_x) { if (markers == NULL || BLI_listbase_is_empty(markers)) { @@ -409,7 +450,7 @@ static void draw_marker_name(const uiFontStyle *fstyle, UI_fontstyle_draw_simple(fstyle, name_x, text_y, name, text_color); } -static void draw_marker_line(const float color[4], float x, float ymin, float ymax) +static void draw_marker_line(const float color[4], int xpos, int ymin, int ymax) { GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); @@ -426,8 +467,8 @@ static void draw_marker_line(const float color[4], float x, float ymin, float ym immUniform1f("dash_factor", 0.5f); immBegin(GPU_PRIM_LINES, 2); - immVertex2f(pos, x, ymin); - immVertex2f(pos, x, ymax); + immVertex2f(pos, xpos, ymin); + immVertex2f(pos, xpos, ymax); immEnd(); immUnbindProgram(); @@ -449,26 +490,6 @@ static int marker_get_icon_id(TimeMarker *marker, int flag) } } -static void draw_marker_line_if_necessary(TimeMarker *marker, int flag, int xpos, int height) -{ -#ifdef DURIAN_CAMERA_SWITCH - if ((marker->camera) || (flag & DRAW_MARKERS_LINES)) -#else - if (flag & DRAW_MARKERS_LINES) -#endif - { - float color[4]; - if (marker->flag & SELECT) { - copy_v4_fl4(color, 1.0f, 1.0f, 1.0f, 0.38f); - } - else { - copy_v4_fl4(color, 0.0f, 0.0f, 0.0f, 0.38f); - } - - draw_marker_line(color, xpos, UI_DPI_FAC * 20, height); - } -} - static void draw_marker( const uiFontStyle *fstyle, TimeMarker *marker, int cfra, int xpos, int flag, int region_height) { @@ -476,7 +497,15 @@ static void draw_marker( GPU_blend_set_func_separate( GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - draw_marker_line_if_necessary(marker, flag, xpos, region_height); + float color[4]; + if (marker->flag & SELECT) { + copy_v4_fl4(color, 1.0f, 1.0f, 1.0f, 0.38f); + } + else { + copy_v4_fl4(color, 0.0f, 0.0f, 0.0f, 0.38f); + } + + draw_marker_line(color, xpos, UI_DPI_FAC * 20, region_height); int icon_id = marker_get_icon_id(marker, flag); UI_icon_draw(xpos - 0.55f * UI_DPI_ICON_SIZE, UI_DPI_FAC * 18, icon_id); @@ -599,8 +628,7 @@ static bool ed_markers_poll_selected_markers(bContext *C) { ListBase *markers = ED_context_get_markers(C); - /* first things first: markers can only exist in timeline views */ - if (ED_operator_animview_active(C) == 0) { + if (!ED_operator_markers_region_active(C)) { return 0; } @@ -613,12 +641,7 @@ static bool ed_markers_poll_selected_no_locked_markers(bContext *C) ListBase *markers = ED_context_get_markers(C); ToolSettings *ts = CTX_data_tool_settings(C); - if (ts->lock_markers) { - return 0; - } - - /* first things first: markers can only exist in timeline views */ - if (ED_operator_animview_active(C) == 0) { + if (ts->lock_markers || !ED_operator_markers_region_active(C)) { return 0; } @@ -632,12 +655,7 @@ static bool ed_markers_poll_markers_exist(bContext *C) ListBase *markers = ED_context_get_markers(C); ToolSettings *ts = CTX_data_tool_settings(C); - if (ts->lock_markers) { - return 0; - } - - /* first things first: markers can only exist in timeline views */ - if (ED_operator_animview_active(C) == 0) { + if (ts->lock_markers || !ED_operator_markers_region_active(C)) { return 0; } @@ -692,7 +710,7 @@ static void MARKER_OT_add(wmOperatorType *ot) /* api callbacks */ ot->exec = ed_marker_add_exec; - ot->poll = ED_operator_animview_active; + ot->poll = ED_operator_markers_region_active; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1661,7 +1679,7 @@ static void MARKER_OT_camera_bind(wmOperatorType *ot) /* api callbacks */ ot->exec = ed_marker_camera_bind_exec; - ot->poll = ED_operator_animview_active; + ot->poll = ED_operator_markers_region_active; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 1685852dd02..901efbdf0ff 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -71,7 +71,7 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene) saction->autosnap = SACTSNAP_FRAME; saction->mode = SACTCONT_DOPESHEET; saction->mode_prev = SACTCONT_DOPESHEET; - saction->flag = SACTION_SHOW_INTERPOLATION | SACTION_SHOW_MARKER_LINES; + saction->flag = SACTION_SHOW_INTERPOLATION | SACTION_SHOW_MARKERS; saction->ads.filterflag |= ADS_FILTER_SUMMARY; @@ -215,10 +215,10 @@ static void action_main_region_draw(const bContext *C, ARegion *ar) marker_flag = ((ac.markers && (ac.markers != &ac.scene->markers)) ? DRAW_MARKERS_LOCAL : 0) | DRAW_MARKERS_MARGIN; - if (saction->flag & SACTION_SHOW_MARKER_LINES) { - marker_flag |= DRAW_MARKERS_LINES; + + if (saction->flag & SACTION_SHOW_MARKERS) { + ED_markers_draw(C, marker_flag); } - ED_markers_draw(C, marker_flag); /* caches */ if (saction->mode == SACTCONT_TIMELINE) { diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index b8d9d3b791f..eb7ba480296 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -81,7 +81,7 @@ static SpaceLink *graph_new(const ScrArea *UNUSED(sa), const Scene *scene) /* settings for making it easier by default to just see what you're interested in tweaking */ sipo->ads->filterflag |= ADS_FILTER_ONLYSEL; - sipo->flag |= SIPO_SELVHANDLESONLY | SIPO_MARKER_LINES; + sipo->flag |= SIPO_SELVHANDLESONLY | SIPO_SHOW_MARKERS; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for graphedit"); @@ -296,10 +296,9 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) if (sipo->mode != SIPO_MODE_DRIVERS) { UI_view2d_view_orthoSpecial(ar, v2d, 1); int marker_draw_flag = DRAW_MARKERS_MARGIN; - if (sipo->flag & SIPO_MARKER_LINES) { - marker_draw_flag |= DRAW_MARKERS_LINES; + if (sipo->flag & SIPO_SHOW_MARKERS) { + ED_markers_draw(C, marker_draw_flag); } - ED_markers_draw(C, marker_draw_flag); } /* preview range */ diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index f274f3c93ec..5cd2a86adf8 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -71,7 +71,7 @@ static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene) /* set auto-snapping settings */ snla->autosnap = SACTSNAP_FRAME; - snla->flag = SNLA_SHOW_MARKER_LINES; + snla->flag = SNLA_SHOW_MARKERS; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for nla"); @@ -274,10 +274,9 @@ static void nla_main_region_draw(const bContext *C, ARegion *ar) /* markers */ UI_view2d_view_orthoSpecial(ar, v2d, 1); int marker_draw_flag = DRAW_MARKERS_MARGIN; - if (snla->flag & SNLA_SHOW_MARKER_LINES) { - marker_draw_flag |= DRAW_MARKERS_LINES; + if (snla->flag & SNLA_SHOW_MARKERS) { + ED_markers_draw(C, marker_draw_flag); } - ED_markers_draw(C, marker_draw_flag); /* preview range */ UI_view2d_view_ortho(v2d); diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 5b2ea9d4793..e6f3a362487 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -2067,10 +2067,9 @@ void draw_timeline_seq(const bContext *C, ARegion *ar) /* markers */ UI_view2d_view_orthoSpecial(ar, v2d, 1); int marker_draw_flag = DRAW_MARKERS_MARGIN; - if (sseq->flag & SEQ_SHOW_MARKER_LINES) { - marker_draw_flag |= DRAW_MARKERS_LINES; + if (sseq->flag & SEQ_SHOW_MARKERS) { + ED_markers_draw(C, marker_draw_flag); } - ED_markers_draw(C, marker_draw_flag); UI_view2d_view_ortho(v2d); /* draw cache on top of markers area */ diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index e1cf6d00b90..6e1b9d62f0e 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -93,7 +93,7 @@ static SpaceLink *sequencer_new(const ScrArea *UNUSED(sa), const Scene *scene) sseq->chanshown = 0; sseq->view = SEQ_VIEW_SEQUENCE; sseq->mainb = SEQ_DRAW_IMG_IMBUF; - sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA | SEQ_SHOW_MARKER_LINES; + sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA | SEQ_SHOW_MARKERS; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for sequencer"); diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 95e6437ae8d..b95a4ca3d96 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -860,8 +860,8 @@ typedef enum eSAction_Flag { SACTION_SHOW_INTERPOLATION = (1 << 12), /* show extremes */ SACTION_SHOW_EXTREMES = (1 << 13), - /* show vertical line markers */ - SACTION_SHOW_MARKER_LINES = (1 << 14), + /* show markers region */ + SACTION_SHOW_MARKERS = (1 << 14), } eSAction_Flag; /* SpaceAction_Runtime.flag */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 1ce282a5a91..7692a4b17bb 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -466,8 +466,8 @@ typedef enum eGraphEdit_Flag { /* normalize curves on display */ SIPO_NORMALIZE = (1 << 14), SIPO_NORMALIZE_FREEZE = (1 << 15), - /* show vertical line for every marker */ - SIPO_MARKER_LINES = (1 << 16), + /* show markers region */ + SIPO_SHOW_MARKERS = (1 << 16), } eGraphEdit_Flag; /* SpaceGraph.mode (Graph Editor Mode) */ @@ -532,8 +532,8 @@ typedef enum eSpaceNla_Flag { SNLA_NOREALTIMEUPDATES = (1 << 6), /* don't show local strip marker indications */ SNLA_NOLOCALMARKERS = (1 << 7), - /* show vertical line for every marker */ - SNLA_SHOW_MARKER_LINES = (1 << 8), + /* show markers region */ + SNLA_SHOW_MARKERS = (1 << 8), } eSpaceNla_Flag; /** \} */ @@ -615,7 +615,7 @@ typedef enum eSpaceSeq_Flag { SEQ_NO_WAVEFORMS = (1 << 8), /* draw no waveforms */ SEQ_SHOW_SAFE_CENTER = (1 << 9), SEQ_SHOW_METADATA = (1 << 10), - SEQ_SHOW_MARKER_LINES = (1 << 11), + SEQ_SHOW_MARKERS = (1 << 11), /* show markers region */ } eSpaceSeq_Flag; /* SpaceSeq.view */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 9d43514f6d4..c97d19f47e5 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -4560,9 +4560,12 @@ static void rna_def_space_sequencer(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); - prop = RNA_def_property(srna, "show_marker_lines", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_MARKER_LINES); - RNA_def_property_ui_text(prop, "Show Marker Lines", "Show a vertical line for every marker"); + prop = RNA_def_property(srna, "show_markers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_MARKERS); + RNA_def_property_ui_text( + prop, + "Show Markers", + "If any exists, show markers in a separate row at the bottom of the editor"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); prop = RNA_def_property(srna, "show_annotation", PROP_BOOLEAN, PROP_NONE); @@ -4818,7 +4821,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) prop = RNA_def_property(srna, "show_pose_markers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_POSEMARKERS_SHOW); RNA_def_property_ui_text(prop, - "Show Pose Markers", + "Toggle Pose Markers", "Show markers belonging to the active action instead of Scene markers " "(Action and Shape Key Editors only)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); @@ -4847,10 +4850,13 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) "comparison with adjacent keys"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); - prop = RNA_def_property(srna, "show_marker_lines", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_SHOW_MARKER_LINES); - RNA_def_property_ui_text(prop, "Show Marker Lines", "Show a vertical line for every marker"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); + prop = RNA_def_property(srna, "show_markers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_SHOW_MARKERS); + RNA_def_property_ui_text( + prop, + "Show Markers", + "If any exists, show markers in a separate row at the bottom of the editor"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); /* editing */ prop = RNA_def_property(srna, "use_auto_merge_keyframes", PROP_BOOLEAN, PROP_NONE); @@ -5004,9 +5010,12 @@ static void rna_def_space_graph(BlenderRNA *brna) "Display groups and channels with colors matching their corresponding groups"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - prop = RNA_def_property(srna, "show_marker_lines", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_MARKER_LINES); - RNA_def_property_ui_text(prop, "Show Marker Lines", "Show a vertical line for every marker"); + prop = RNA_def_property(srna, "show_markers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_SHOW_MARKERS); + RNA_def_property_ui_text( + prop, + "Show Markers", + "If any exists, show markers in a separate row at the bottom of the editor"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); /* editing */ @@ -5115,10 +5124,13 @@ static void rna_def_space_nla(BlenderRNA *brna) "Show action-local markers on the strips, useful when synchronizing timing across strips"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL); - prop = RNA_def_property(srna, "show_marker_lines", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SNLA_SHOW_MARKER_LINES); - RNA_def_property_ui_text(prop, "Show Marker Lines", "Show a vertical line for every marker"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); + prop = RNA_def_property(srna, "show_markers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SNLA_SHOW_MARKERS); + RNA_def_property_ui_text( + prop, + "Show Markers", + "If any exists, show markers in a separate row at the bottom of the editor"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL); /* editing */ prop = RNA_def_property(srna, "use_realtime_update", PROP_BOOLEAN, PROP_NONE); -- cgit v1.2.3 From 6d79ebebc5dba38225d3817b28e1c189ce8136d5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 30 Nov 2019 18:52:32 +1100 Subject: Cleanup: remove unused NDOF icons --- release/datafiles/blender_icons.svg | 27 --------------------- .../datafiles/blender_icons16/icon16_ndof_dom.dat | Bin 1048 -> 0 bytes .../datafiles/blender_icons16/icon16_ndof_fly.dat | Bin 1048 -> 0 bytes .../blender_icons16/icon16_ndof_trans.dat | Bin 1048 -> 0 bytes .../datafiles/blender_icons16/icon16_ndof_turn.dat | Bin 1048 -> 0 bytes .../datafiles/blender_icons32/icon32_ndof_dom.dat | Bin 4120 -> 0 bytes .../datafiles/blender_icons32/icon32_ndof_fly.dat | Bin 4120 -> 0 bytes .../blender_icons32/icon32_ndof_trans.dat | Bin 4120 -> 0 bytes .../datafiles/blender_icons32/icon32_ndof_turn.dat | Bin 4120 -> 0 bytes release/scripts/startup/bl_ui/space_userpref.py | 4 +-- source/blender/editors/datafiles/CMakeLists.txt | 4 --- source/blender/editors/include/UI_icons.h | 8 +++--- source/blender/editors/space_view3d/view3d_draw.c | 7 ------ 13 files changed, 6 insertions(+), 44 deletions(-) delete mode 100644 release/datafiles/blender_icons16/icon16_ndof_dom.dat delete mode 100644 release/datafiles/blender_icons16/icon16_ndof_fly.dat delete mode 100644 release/datafiles/blender_icons16/icon16_ndof_trans.dat delete mode 100644 release/datafiles/blender_icons16/icon16_ndof_turn.dat delete mode 100644 release/datafiles/blender_icons32/icon32_ndof_dom.dat delete mode 100644 release/datafiles/blender_icons32/icon32_ndof_fly.dat delete mode 100644 release/datafiles/blender_icons32/icon32_ndof_trans.dat delete mode 100644 release/datafiles/blender_icons32/icon32_ndof_turn.dat diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg index f317b346eb8..6a87ac0adaa 100644 --- a/release/datafiles/blender_icons.svg +++ b/release/datafiles/blender_icons.svg @@ -1048,9 +1048,6 @@ - - - @@ -1065,9 +1062,6 @@ - - - @@ -1327,14 +1321,6 @@ - - - - - - - - @@ -3746,14 +3732,6 @@ - - - - - - - - @@ -3831,11 +3809,6 @@ - - - - - diff --git a/release/datafiles/blender_icons16/icon16_ndof_dom.dat b/release/datafiles/blender_icons16/icon16_ndof_dom.dat deleted file mode 100644 index e6ecd80d5a9..00000000000 Binary files a/release/datafiles/blender_icons16/icon16_ndof_dom.dat and /dev/null differ diff --git a/release/datafiles/blender_icons16/icon16_ndof_fly.dat b/release/datafiles/blender_icons16/icon16_ndof_fly.dat deleted file mode 100644 index 84b672bdf9f..00000000000 Binary files a/release/datafiles/blender_icons16/icon16_ndof_fly.dat and /dev/null differ diff --git a/release/datafiles/blender_icons16/icon16_ndof_trans.dat b/release/datafiles/blender_icons16/icon16_ndof_trans.dat deleted file mode 100644 index f74edd6f8b0..00000000000 Binary files a/release/datafiles/blender_icons16/icon16_ndof_trans.dat and /dev/null differ diff --git a/release/datafiles/blender_icons16/icon16_ndof_turn.dat b/release/datafiles/blender_icons16/icon16_ndof_turn.dat deleted file mode 100644 index 5b0cee02b49..00000000000 Binary files a/release/datafiles/blender_icons16/icon16_ndof_turn.dat and /dev/null differ diff --git a/release/datafiles/blender_icons32/icon32_ndof_dom.dat b/release/datafiles/blender_icons32/icon32_ndof_dom.dat deleted file mode 100644 index 9c7e6fdfc99..00000000000 Binary files a/release/datafiles/blender_icons32/icon32_ndof_dom.dat and /dev/null differ diff --git a/release/datafiles/blender_icons32/icon32_ndof_fly.dat b/release/datafiles/blender_icons32/icon32_ndof_fly.dat deleted file mode 100644 index a328f8dc1ca..00000000000 Binary files a/release/datafiles/blender_icons32/icon32_ndof_fly.dat and /dev/null differ diff --git a/release/datafiles/blender_icons32/icon32_ndof_trans.dat b/release/datafiles/blender_icons32/icon32_ndof_trans.dat deleted file mode 100644 index 553752dda40..00000000000 Binary files a/release/datafiles/blender_icons32/icon32_ndof_trans.dat and /dev/null differ diff --git a/release/datafiles/blender_icons32/icon32_ndof_turn.dat b/release/datafiles/blender_icons32/icon32_ndof_turn.dat deleted file mode 100644 index 3f43546cdbf..00000000000 Binary files a/release/datafiles/blender_icons32/icon32_ndof_turn.dat and /dev/null differ diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index ab4d54f039e..35aa0504cd7 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1456,8 +1456,8 @@ class USERPREF_PT_ndof_settings(Panel): if is_view3d: layout.separator() layout.label(text="Fly/Walk Options") - layout.prop(input_prefs, "ndof_fly_helicopter", icon='NDOF_FLY') - layout.prop(input_prefs, "ndof_lock_horizon", icon='NDOF_DOM') + layout.prop(input_prefs, "ndof_fly_helicopter") + layout.prop(input_prefs, "ndof_lock_horizon") class USERPREF_PT_input_keyboard(PreferencePanel, Panel): diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 680fe3a00e5..fd8fe103a2d 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -529,10 +529,6 @@ set(ICON_NAMES axis_side axis_front axis_top - ndof_dom - ndof_turn - ndof_fly - ndof_trans layer_used layer_active sortalpha diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index c15f299bca8..2bf50d3b4b8 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -739,10 +739,10 @@ DEF_ICON_BLANK(251) DEF_ICON(AXIS_SIDE) DEF_ICON(AXIS_FRONT) DEF_ICON(AXIS_TOP) -DEF_ICON(NDOF_DOM) -DEF_ICON(NDOF_TURN) -DEF_ICON(NDOF_FLY) -DEF_ICON(NDOF_TRANS) +DEF_ICON_BLANK(252) +DEF_ICON_BLANK(252a) +DEF_ICON_BLANK(252b) +DEF_ICON_BLANK(252c) DEF_ICON(LAYER_USED) DEF_ICON(LAYER_ACTIVE) /* available */ diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 831f8d77285..5f029e840d3 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1121,13 +1121,6 @@ static void draw_rotation_guide(const RegionView3D *rv3d) immEnd(); immUnbindProgram(); -# if 0 - /* find screen coordinates for rotation center, then draw pretty icon */ - mul_m4_v3(rv3d->persinv, rot_center); - UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN); - /* ^^ just playing around, does not work */ -# endif - GPU_blend(false); glDepthMask(GL_TRUE); } -- cgit v1.2.3 From e9dd2abaef72f7fafc13ed30e6f1b31d949f37f5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 30 Nov 2019 19:20:06 +1100 Subject: NDOF: invert axes by default Matches 3D Connexion's reference software. --- release/datafiles/userdef/userdef_default.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/release/datafiles/userdef/userdef_default.c b/release/datafiles/userdef/userdef_default.c index 35caf9dd6cd..3856a03b1ba 100644 --- a/release/datafiles/userdef/userdef_default.c +++ b/release/datafiles/userdef/userdef_default.c @@ -154,7 +154,12 @@ const UserDef U_default = { .ndof_orbit_sensitivity = 4.0, .ndof_deadzone = 0.1, .ndof_flag = (NDOF_MODE_ORBIT | NDOF_LOCK_HORIZON | NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM | - NDOF_SHOULD_ROTATE), + NDOF_SHOULD_ROTATE | + /* Software from the driver authors follows this convention + * so invert this by default, see: T67579. */ + NDOF_ROTX_INVERT_AXIS | NDOF_ROTY_INVERT_AXIS | NDOF_ROTZ_INVERT_AXIS | + NDOF_PANX_INVERT_AXIS | NDOF_PANY_INVERT_AXIS | NDOF_PANZ_INVERT_AXIS | + NDOF_ZOOM_INVERT), .ogl_multisamples = 0, .image_draw_method = IMAGE_DRAW_METHOD_AUTO, .glalphaclip = 0.004, -- cgit v1.2.3 From fcdf4b36c53c0f2fec8f1296b48c1a003bddf5b0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 30 Nov 2019 19:21:25 +1100 Subject: UI: group NDOF XYZ invert options --- release/scripts/startup/bl_ui/space_userpref.py | 31 ++++++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 35aa0504cd7..387acbec625 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1437,17 +1437,36 @@ class USERPREF_PT_ndof_settings(Panel): layout.row().prop(input_prefs, "ndof_view_navigate_method", text="Navigate") layout.row().prop(input_prefs, "ndof_view_rotate_method", text="Orbit") layout.separator() + layout.label(text="Orbit Options") - layout.prop(input_prefs, "ndof_rotx_invert_axis") - layout.prop(input_prefs, "ndof_roty_invert_axis") - layout.prop(input_prefs, "ndof_rotz_invert_axis") + split = layout.split(factor=0.6) + row = split.row() + row.alignment = 'RIGHT' + row.label(text="Invert Axis") + row = split.row(align=True) + for text, attr in ( + ("X", "ndof_rotx_invert_axis"), + ("Y", "ndof_roty_invert_axis"), + ("Z", "ndof_rotz_invert_axis"), + ): + row.prop(input_prefs, attr, text=text, toggle=True) # view2d use pan/zoom layout.separator() layout.label(text="Pan Options") - layout.prop(input_prefs, "ndof_panx_invert_axis") - layout.prop(input_prefs, "ndof_pany_invert_axis") - layout.prop(input_prefs, "ndof_panz_invert_axis") + + split = layout.split(factor=0.6) + row = split.row() + row.alignment = 'RIGHT' + row.label(text="Invert Axis") + row = split.row(align=True) + for text, attr in ( + ("X", "ndof_panx_invert_axis"), + ("Y", "ndof_pany_invert_axis"), + ("Z", "ndof_panz_invert_axis"), + ): + row.prop(input_prefs, attr, text=text, toggle=True) + layout.prop(input_prefs, "ndof_pan_yz_swap_axis") layout.label(text="Zoom Options") -- cgit v1.2.3 From 5c0f1e1a4e88cbbfaf90691e7c642fa053dd5cc7 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Sat, 30 Nov 2019 11:46:24 +0100 Subject: GPencil: Fix unreported thickness does not scale when layer is parented The thickness was using the object scale always, but when the layer is parented, must use the parented object scale. --- source/blender/draw/engines/gpencil/gpencil_draw_utils.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index 48912a914dc..cd96b21280f 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -1816,7 +1816,6 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data, for (int i = 0; i < cache->grp_used; i++) { elm = &cache->grp_cache[i]; array_elm = &cache_ob->shgrp_array[idx]; - const float scale = cache_ob->scale; /* Limit stencil id */ if (stencil_id > 255) { @@ -1858,6 +1857,8 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data, break; } + const float scale = (!cache_ob->is_dup_ob) ? mat4_to_scale(gpf->runtime.parent_obmat) : + cache_ob->scale; float(*obmat)[4] = (!cache_ob->is_dup_ob) ? gpf->runtime.parent_obmat : cache_ob->obmat; switch (elm->type) { case eGpencilBatchGroupType_Stroke: { -- cgit v1.2.3 From f0e7fd4ad62ec1dd5c9632050a8fde347c28656f Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Sat, 30 Nov 2019 17:05:08 +0100 Subject: GPencil: Fix unreported error when frame is zero in Time modifier When the frame was zero, the frame number was clamped by error to 1. --- source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c index 01bb0ae2b93..e3ad5a64ac3 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c @@ -71,8 +71,14 @@ static int remapTime(struct GpencilModifierData *md, const bool invpass = mmd->flag & GP_TIME_INVERT_LAYERPASS; int sfra = custom ? mmd->sfra : scene->r.sfra; int efra = custom ? mmd->efra : scene->r.efra; - CLAMP_MIN(sfra, 1); - CLAMP_MIN(efra, 1); + CLAMP_MIN(sfra, 0); + CLAMP_MIN(efra, 0); + + /* Avoid inverse ranges. */ + if (efra < sfra) { + return cfra; + } + const int time_range = efra - sfra + 1; int offset = mmd->offset; int segments = 0; -- cgit v1.2.3 From f1ac64921b49eaea8658d144754a1a532198c720 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sat, 30 Nov 2019 19:07:44 +0300 Subject: Fix T71213: Mask or Mirror before Armature breaks weight paint. This is a revert of a small fraction of commit rB5e332fd700 that introduced the issue according to bisect. Doing a break here is wrong, because BKE_crazyspace_build_sculpt assumes that processing stopped at the first deform modifier without deformMatrices, and thus skips all modifiers until it finds one like that. Thus this early loop exit makes the behavior worse, as instead of skipping just Mask and Mirror, it skips all. --- source/blender/blenkernel/intern/crazyspace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 9618ef8c78e..33f9b5b1012 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -417,12 +417,12 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, mti->deformMatrices(md, &mectx, me_eval, deformedVerts, defmats, me_eval->totvert); } else { + /* More complex handling will continue in BKE_crazyspace_build_sculpt. + * Exiting the loop on a non-deform modifier causes issues - T71213. */ + BLI_assert(crazyspace_modifier_supports_deform(md)); break; } } - else { - break; - } } for (; md; md = md->next) { -- cgit v1.2.3