diff options
author | Pablo Dobarro <pablodp606@gmail.com> | 2021-05-18 02:03:01 +0300 |
---|---|---|
committer | Pablo Dobarro <pablodp606@gmail.com> | 2021-06-03 21:17:17 +0300 |
commit | dba3fb9e091acfa7d2144468a220b2b0d577c15d (patch) | |
tree | 817e5c84a1f7319b7ef7811226dabcae615b63ea /source/blender | |
parent | 3e695a27cdfad560d0b28e742cfa069d098200d6 (diff) |
Overlay: Flash on Mode Transfer overlay
This implements T87633
This overlay renders a flash animation on the target object when
transfering the mode to it using the mode transfer operator.
This provides visual feedback when switching between objects without
extra overlays that affect the general color and lighting in the scene.
Differences with the design task:
- This uses just a fade out animation instead of a fade in/out animation.
The code is ready for fade in/out, but as the rest of the overlays
(face sets, masks...) change instantly without animation, having a fade
in/out effect gives the impression that the object flashes twice (once
for the face sets, twice for the peak alpha of the flash animation).
- The rendering uses a flat color without fresnel for now, but this can
be improved in the future to make it look more like the shader in the
prototype.
- Not enabled by default (can be enabled in the overlays panel), maybe
the defaults can change for 3.0 to disable fade inactive and enable this
instead.
Reviewed By: jbakker, JulienKaspar
Differential Revision: https://developer.blender.org/D11055
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/draw/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/draw/engines/overlay/overlay_engine.c | 8 | ||||
-rw-r--r-- | source/blender/draw/engines/overlay/overlay_mode_transfer.c | 159 | ||||
-rw-r--r-- | source/blender/draw/engines/overlay/overlay_private.h | 12 | ||||
-rw-r--r-- | source/blender/editors/object/object_modes.c | 11 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_object_types.h | 3 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_view3d_types.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_space.c | 8 |
8 files changed, 203 insertions, 0 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index d6598bf79b0..ee5b2c549a5 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -149,6 +149,7 @@ set(SRC engines/overlay/overlay_image.c engines/overlay/overlay_lattice.c engines/overlay/overlay_metaball.c + engines/overlay/overlay_mode_transfer.c engines/overlay/overlay_motion_path.c engines/overlay/overlay_outline.c engines/overlay/overlay_paint.c diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c index b8f721946f2..19f822e3f68 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.c +++ b/source/blender/draw/engines/overlay/overlay_engine.c @@ -207,6 +207,7 @@ static void OVERLAY_cache_init(void *vedata) OVERLAY_armature_cache_init(vedata); OVERLAY_background_cache_init(vedata); OVERLAY_fade_cache_init(vedata); + OVERLAY_mode_transfer_cache_init(vedata); OVERLAY_extra_cache_init(vedata); OVERLAY_facing_cache_init(vedata); OVERLAY_gpencil_cache_init(vedata); @@ -323,6 +324,7 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob) !is_select; const bool draw_fade = draw_surface && (pd->overlay.flag & V3D_OVERLAY_FADE_INACTIVE) && overlay_should_fade_object(ob, draw_ctx->obact); + const bool draw_mode_transfer = draw_surface && (pd->overlay.flag & V3D_OVERLAY_MODE_TRANSFER); const bool draw_bones = (pd->overlay.flag & V3D_OVERLAY_HIDE_BONES) == 0; const bool draw_wires = draw_surface && has_surface && (pd->wireframe_mode || !pd->hide_overlays); @@ -349,6 +351,9 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob) if (draw_facing) { OVERLAY_facing_cache_populate(vedata, ob); } + if (draw_mode_transfer) { + OVERLAY_mode_transfer_cache_populate(vedata, ob); + } if (draw_wires) { OVERLAY_wireframe_cache_populate(vedata, ob, dupli, do_init); } @@ -504,6 +509,7 @@ static void OVERLAY_cache_finish(void *vedata) {GPU_ATTACHMENT_TEXTURE(dtxl->depth_in_front), GPU_ATTACHMENT_TEXTURE(dtxl->color)}); } + OVERLAY_mode_transfer_cache_finish(vedata); OVERLAY_antialiasing_cache_finish(vedata); OVERLAY_armature_cache_finish(vedata); OVERLAY_image_cache_finish(vedata); @@ -566,6 +572,7 @@ static void OVERLAY_draw_scene(void *vedata) OVERLAY_image_draw(vedata); OVERLAY_fade_draw(vedata); OVERLAY_facing_draw(vedata); + OVERLAY_mode_transfer_draw(vedata); OVERLAY_extra_blend_draw(vedata); OVERLAY_volume_draw(vedata); @@ -605,6 +612,7 @@ static void OVERLAY_draw_scene(void *vedata) OVERLAY_fade_infront_draw(vedata); OVERLAY_facing_infront_draw(vedata); + OVERLAY_mode_transfer_infront_draw(vedata); if (DRW_state_is_fbo()) { GPU_framebuffer_bind(fbl->overlay_line_in_front_fb); diff --git a/source/blender/draw/engines/overlay/overlay_mode_transfer.c b/source/blender/draw/engines/overlay/overlay_mode_transfer.c new file mode 100644 index 00000000000..253f606b086 --- /dev/null +++ b/source/blender/draw/engines/overlay/overlay_mode_transfer.c @@ -0,0 +1,159 @@ +/* + * 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 2021, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#include "BKE_paint.h" +#include "DRW_render.h" + +#include "ED_view3d.h" + +#include "PIL_time.h" +#include "UI_resources.h" + +#include "overlay_private.h" + +void OVERLAY_mode_transfer_cache_init(OVERLAY_Data *vedata) +{ + OVERLAY_PassList *psl = vedata->psl; + OVERLAY_PrivateData *pd = vedata->stl->pd; + + pd->mode_transfer.time = PIL_check_seconds_timer(); + + for (int i = 0; i < 2; i++) { + /* Non Meshes Pass (Camera, empties, lights ...) */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA; + DRW_PASS_CREATE(psl->mode_transfer_ps[i], state | pd->clipping_state); + } +} + +#define MODE_TRANSFER_FLASH_LENGTH 0.55f +/* TODO(pablodp606): Remove this option for 3.0 if fade in/out is not used. */ +#define MODE_TRANSFER_FLASH_FADE 0.0f +#define MODE_TRANSFER_FLASH_MAX_ALPHA 0.25f + +static bool mode_transfer_is_animation_running(const float anim_time) +{ + return anim_time >= 0.0f && anim_time <= MODE_TRANSFER_FLASH_LENGTH; +} + +static float mode_transfer_alpha_for_animation_time_get(const float anim_time) +{ + if (anim_time > MODE_TRANSFER_FLASH_LENGTH) { + return 0.0f; + } + + if (anim_time < 0.0f) { + return 0.0f; + } + + if (MODE_TRANSFER_FLASH_FADE <= 0.0f) { + return (1.0f - (anim_time / MODE_TRANSFER_FLASH_LENGTH)) * MODE_TRANSFER_FLASH_MAX_ALPHA; + } + + const float flash_fade_in_time = MODE_TRANSFER_FLASH_LENGTH * MODE_TRANSFER_FLASH_FADE; + const float flash_fade_out_time = MODE_TRANSFER_FLASH_LENGTH - flash_fade_in_time; + + float alpha = 0.0f; + if (anim_time < flash_fade_in_time) { + alpha = anim_time / flash_fade_in_time; + } + else { + const float fade_out_anim_time = anim_time - flash_fade_in_time; + alpha = 1.0f - (fade_out_anim_time / flash_fade_out_time); + } + + return alpha * MODE_TRANSFER_FLASH_MAX_ALPHA; +} + +void OVERLAY_mode_transfer_cache_populate(OVERLAY_Data *vedata, Object *ob) +{ + OVERLAY_PrivateData *pd = vedata->stl->pd; + OVERLAY_PassList *psl = vedata->psl; + + if (pd->xray_enabled) { + return; + } + + const float animation_time = pd->mode_transfer.time - + ob->runtime.overlay_mode_transfer_start_time; + + if (!mode_transfer_is_animation_running(animation_time)) { + return; + } + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) && + !DRW_state_is_image_render(); + const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0; + + DRWShadingGroup *mode_transfer_grp[2]; + + for (int i = 0; i < 2; i++) { + GPUShader *sh = OVERLAY_shader_uniform_color(); + mode_transfer_grp[i] = DRW_shgroup_create(sh, psl->mode_transfer_ps[i]); + DRW_shgroup_uniform_block(mode_transfer_grp[i], "globalsBlock", G_draw.block_ubo); + + float color[4]; + UI_GetThemeColor3fv(TH_VERTEX_SELECT, color); + color[3] = mode_transfer_alpha_for_animation_time_get(animation_time); + srgb_to_linearrgb_v4(color, color); + DRW_shgroup_uniform_vec4_copy(mode_transfer_grp[i], "color", color); + } + + if (!pd->use_in_front) { + mode_transfer_grp[IN_FRONT] = mode_transfer_grp[NOT_IN_FRONT]; + } + + pd->mode_transfer.any_animated = true; + + if (use_sculpt_pbvh) { + DRW_shgroup_call_sculpt(mode_transfer_grp[is_xray], ob, false, false); + } + else { + struct GPUBatch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + DRW_shgroup_call(mode_transfer_grp[is_xray], geom, ob); + } + } +} + +void OVERLAY_mode_transfer_draw(OVERLAY_Data *vedata) +{ + OVERLAY_PassList *psl = vedata->psl; + + DRW_draw_pass(psl->mode_transfer_ps[NOT_IN_FRONT]); +} + +void OVERLAY_mode_transfer_infront_draw(OVERLAY_Data *vedata) +{ + OVERLAY_PassList *psl = vedata->psl; + + DRW_draw_pass(psl->mode_transfer_ps[IN_FRONT]); +} + +void OVERLAY_mode_transfer_cache_finish(OVERLAY_Data *vedata) +{ + OVERLAY_PrivateData *pd = vedata->stl->pd; + if (pd->mode_transfer.any_animated) { + DRW_viewport_request_redraw(); + } + pd->mode_transfer.any_animated = false; +} diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h index db43136e308..969289a3219 100644 --- a/source/blender/draw/engines/overlay/overlay_private.h +++ b/source/blender/draw/engines/overlay/overlay_private.h @@ -107,6 +107,7 @@ typedef struct OVERLAY_PassList { DRWPass *gpencil_canvas_ps; DRWPass *facing_ps[2]; DRWPass *fade_ps[2]; + DRWPass *mode_transfer_ps[2]; DRWPass *grid_ps; DRWPass *image_background_ps; DRWPass *image_background_scene_ps; @@ -282,6 +283,7 @@ typedef struct OVERLAY_PrivateData { DRWShadingGroup *extra_grid_grp; DRWShadingGroup *facing_grp[2]; DRWShadingGroup *fade_grp[2]; + DRWShadingGroup *flash_grp[2]; DRWShadingGroup *motion_path_lines_grp; DRWShadingGroup *motion_path_points_grp; DRWShadingGroup *outlines_grp; @@ -414,6 +416,10 @@ typedef struct OVERLAY_PrivateData { struct { DRWCallBuffer *handle[2]; } mball; + struct { + double time; + bool any_animated; + } mode_transfer; } OVERLAY_PrivateData; /* Transient data */ typedef struct OVERLAY_StorageList { @@ -607,6 +613,12 @@ void OVERLAY_fade_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_fade_draw(OVERLAY_Data *vedata); void OVERLAY_fade_infront_draw(OVERLAY_Data *vedata); +void OVERLAY_mode_transfer_cache_init(OVERLAY_Data *vedata); +void OVERLAY_mode_transfer_cache_populate(OVERLAY_Data *vedata, Object *ob); +void OVERLAY_mode_transfer_draw(OVERLAY_Data *vedata); +void OVERLAY_mode_transfer_infront_draw(OVERLAY_Data *vedata); +void OVERLAY_mode_transfer_cache_finish(OVERLAY_Data *vedata); + void OVERLAY_grid_init(OVERLAY_Data *vedata); void OVERLAY_grid_cache_init(OVERLAY_Data *vedata); void OVERLAY_grid_draw(OVERLAY_Data *vedata); diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c index edf9afd1fd6..3d1a5ac2d62 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -30,6 +30,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "PIL_time.h" + #include "BLT_translation.h" #include "BKE_context.h" @@ -438,6 +440,13 @@ static void object_transfer_mode_reposition_view_pivot(bContext *C, const int mv ups->last_stroke_valid = true; } +static void object_overlay_mode_transfer_animation_start(bContext *C, Object *ob_dst) +{ + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + Object *ob_dst_eval = DEG_get_evaluated_object(depsgraph, ob_dst); + ob_dst_eval->runtime.overlay_mode_transfer_start_time = PIL_check_seconds_timer(); +} + static bool object_transfer_mode_to_base(bContext *C, wmOperator *op, Base *base_dst) { Scene *scene = CTX_data_scene(C); @@ -475,6 +484,8 @@ static bool object_transfer_mode_to_base(bContext *C, wmOperator *op, Base *base ob_dst_orig = DEG_get_original_object(ob_dst); ED_object_mode_set_ex(C, last_mode, true, op->reports); + object_overlay_mode_transfer_animation_start(C, ob_dst); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_toolsystem_update_from_context_view3d(C); mode_transfered = true; diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index aa1178fb139..9951bdefbbb 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -144,6 +144,9 @@ typedef struct Object_Runtime { */ char is_data_eval_owned; + /** Start time of the mode transfer overlay animation. */ + double overlay_mode_transfer_start_time; + /** Axis aligned boundbox (in localspace). */ struct BoundBox *bb; diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 2f4e4e57b9f..9e7e30d913e 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -515,6 +515,7 @@ enum { V3D_OVERLAY_HIDE_OBJECT_ORIGINS = (1 << 10), V3D_OVERLAY_STATS = (1 << 11), V3D_OVERLAY_FADE_INACTIVE = (1 << 12), + V3D_OVERLAY_MODE_TRANSFER = (1 << 13), }; /** #View3DOverlay.edit_flag */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 0af2572a4bd..bb356e4b532 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -4129,6 +4129,14 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna) prop, "Fade Inactive Objects", "Fade inactive geometry using the viewport background color"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "show_mode_transfer", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_MODE_TRANSFER); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, + "Flash on Mode Transfer", + "Flash the target object when tranfering the active mode to it"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "fade_inactive_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "overlay.fade_alpha"); RNA_def_property_ui_text(prop, "Opacity", "Strength of the fade effect"); |