diff options
Diffstat (limited to 'source/blender/draw/engines/overlay/overlay_engine.cc')
-rw-r--r-- | source/blender/draw/engines/overlay/overlay_engine.cc | 767 |
1 files changed, 767 insertions, 0 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_engine.cc b/source/blender/draw/engines/overlay/overlay_engine.cc new file mode 100644 index 00000000000..f1fdfe98fdc --- /dev/null +++ b/source/blender/draw/engines/overlay/overlay_engine.cc @@ -0,0 +1,767 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2019 Blender Foundation. */ + +/** \file + * \ingroup draw_engine + * + * Engine for drawing a selection map where the pixels indicate the selection indices. + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "DEG_depsgraph_query.h" + +#include "ED_view3d.h" + +#include "UI_interface.h" + +#include "BKE_duplilist.h" +#include "BKE_object.h" +#include "BKE_paint.h" + +#include "DNA_space_types.h" + +#include "overlay_engine.h" +#include "overlay_private.hh" + +/* -------------------------------------------------------------------- */ +/** \name Engine Callbacks + * \{ */ + +static void OVERLAY_engine_init(void *vedata) +{ + OVERLAY_Data *data = static_cast<OVERLAY_Data *>(vedata); + OVERLAY_StorageList *stl = data->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const RegionView3D *rv3d = draw_ctx->rv3d; + const View3D *v3d = draw_ctx->v3d; + const Scene *scene = draw_ctx->scene; + const ToolSettings *ts = scene->toolsettings; + + if (!stl->pd) { + /* Allocate transient pointers. */ + stl->pd = static_cast<OVERLAY_PrivateData *>(MEM_callocN(sizeof(*stl->pd), __func__)); + } + + /* Allocate instance. */ + if (data->instance == nullptr) { + data->instance = static_cast<OVERLAY_Instance *>( + MEM_callocN(sizeof(*data->instance), __func__)); + } + + OVERLAY_PrivateData *pd = stl->pd; + pd->space_type = v3d != nullptr ? int(SPACE_VIEW3D) : draw_ctx->space_data->spacetype; + + if (pd->space_type == SPACE_IMAGE) { + const SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + pd->hide_overlays = (sima->overlay.flag & SI_OVERLAY_SHOW_OVERLAYS) == 0; + pd->clipping_state = DRWState(0); + OVERLAY_grid_init(data); + OVERLAY_edit_uv_init(data); + return; + } + if (pd->space_type == SPACE_NODE) { + pd->hide_overlays = true; + pd->clipping_state = DRWState(0); + return; + } + + pd->hide_overlays = (v3d->flag2 & V3D_HIDE_OVERLAYS) != 0; + pd->ctx_mode = CTX_data_mode_enum_ex( + draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode); + + if (!pd->hide_overlays) { + pd->overlay = v3d->overlay; + pd->v3d_flag = v3d->flag; + pd->v3d_gridflag = v3d->gridflag; + } + else { + memset(&pd->overlay, 0, sizeof(pd->overlay)); + pd->v3d_flag = 0; + pd->v3d_gridflag = 0; + pd->overlay.flag = V3D_OVERLAY_HIDE_TEXT | V3D_OVERLAY_HIDE_MOTION_PATHS | + V3D_OVERLAY_HIDE_BONES | V3D_OVERLAY_HIDE_OBJECT_XTRAS | + V3D_OVERLAY_HIDE_OBJECT_ORIGINS; + pd->overlay.wireframe_threshold = v3d->overlay.wireframe_threshold; + pd->overlay.wireframe_opacity = v3d->overlay.wireframe_opacity; + } + + if (v3d->shading.type == OB_WIRE) { + pd->overlay.flag |= V3D_OVERLAY_WIREFRAMES; + } + + if (ts->sculpt) { + if (ts->sculpt->flags & SCULPT_HIDE_FACE_SETS) { + pd->overlay.sculpt_mode_face_sets_opacity = 0.0f; + } + if (ts->sculpt->flags & SCULPT_HIDE_MASK) { + pd->overlay.sculpt_mode_mask_opacity = 0.0f; + } + } + + pd->use_in_front = (v3d->shading.type <= OB_SOLID) || + BKE_scene_uses_blender_workbench(draw_ctx->scene); + pd->wireframe_mode = (v3d->shading.type == OB_WIRE); + pd->clipping_state = RV3D_CLIPPING_ENABLED(v3d, rv3d) ? DRW_STATE_CLIP_PLANES : DRWState(0); + pd->xray_opacity = XRAY_ALPHA(v3d); + pd->xray_enabled = XRAY_ACTIVE(v3d); + pd->xray_enabled_and_not_wire = pd->xray_enabled && v3d->shading.type > OB_WIRE; + pd->clear_in_front = (v3d->shading.type != OB_SOLID); + pd->cfra = DEG_get_ctime(draw_ctx->depsgraph); + + OVERLAY_antialiasing_init(data); + + switch (stl->pd->ctx_mode) { + case CTX_MODE_EDIT_MESH: + OVERLAY_edit_mesh_init(data); + break; + case CTX_MODE_EDIT_CURVES: + OVERLAY_edit_curves_init(data); + break; + default: + /* Nothing to do. */ + break; + } + OVERLAY_facing_init(data); + OVERLAY_grid_init(data); + OVERLAY_image_init(data); + OVERLAY_outline_init(data); + OVERLAY_wireframe_init(data); + OVERLAY_paint_init(data); +} + +static void OVERLAY_cache_init(void *vedata) +{ + OVERLAY_Data *data = static_cast<OVERLAY_Data *>(vedata); + OVERLAY_StorageList *stl = data->stl; + OVERLAY_PrivateData *pd = stl->pd; + + if (pd->space_type == SPACE_IMAGE) { + OVERLAY_background_cache_init(data); + OVERLAY_grid_cache_init(data); + OVERLAY_edit_uv_cache_init(data); + return; + } + if (pd->space_type == SPACE_NODE) { + OVERLAY_background_cache_init(data); + return; + } + + switch (pd->ctx_mode) { + case CTX_MODE_EDIT_MESH: { + OVERLAY_edit_mesh_cache_init(data); + /* `pd->edit_mesh.flag` is valid after calling `OVERLAY_edit_mesh_cache_init`. */ + const bool draw_edit_weights = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_WEIGHT); + if (draw_edit_weights) { + OVERLAY_paint_cache_init(data); + } + break; + } + case CTX_MODE_EDIT_SURFACE: + case CTX_MODE_EDIT_CURVE: + OVERLAY_edit_curve_cache_init(data); + break; + case CTX_MODE_EDIT_TEXT: + OVERLAY_edit_text_cache_init(data); + break; + case CTX_MODE_EDIT_ARMATURE: + break; + case CTX_MODE_EDIT_METABALL: + break; + case CTX_MODE_EDIT_LATTICE: + OVERLAY_edit_lattice_cache_init(data); + break; + case CTX_MODE_PARTICLE: + OVERLAY_edit_particle_cache_init(data); + break; + case CTX_MODE_POSE: + case CTX_MODE_PAINT_WEIGHT: + case CTX_MODE_PAINT_VERTEX: + case CTX_MODE_PAINT_TEXTURE: + OVERLAY_paint_cache_init(data); + break; + case CTX_MODE_SCULPT: + OVERLAY_sculpt_cache_init(data); + break; + case CTX_MODE_EDIT_GPENCIL: + case CTX_MODE_PAINT_GPENCIL: + case CTX_MODE_SCULPT_GPENCIL: + case CTX_MODE_VERTEX_GPENCIL: + case CTX_MODE_WEIGHT_GPENCIL: + OVERLAY_edit_gpencil_cache_init(data); + break; + case CTX_MODE_EDIT_CURVES: + OVERLAY_edit_curves_cache_init(data); + break; + case CTX_MODE_SCULPT_CURVES: + OVERLAY_sculpt_curves_cache_init(data); + break; + case CTX_MODE_OBJECT: + break; + default: + BLI_assert_msg(0, "Draw mode invalid"); + break; + } + OVERLAY_antialiasing_cache_init(data); + OVERLAY_armature_cache_init(data); + OVERLAY_viewer_attribute_cache_init(data); + OVERLAY_background_cache_init(data); + OVERLAY_fade_cache_init(data); + OVERLAY_mode_transfer_cache_init(data); + OVERLAY_extra_cache_init(data); + OVERLAY_facing_cache_init(data); + OVERLAY_gpencil_cache_init(data); + OVERLAY_grid_cache_init(data); + OVERLAY_image_cache_init(data); + OVERLAY_metaball_cache_init(data); + OVERLAY_motion_path_cache_init(data); + OVERLAY_outline_cache_init(data); + OVERLAY_particle_cache_init(data); + OVERLAY_wireframe_cache_init(data); + OVERLAY_volume_cache_init(data); +} + +BLI_INLINE OVERLAY_DupliData *OVERLAY_duplidata_get(Object *ob, void *vedata, bool *do_init) +{ + OVERLAY_DupliData **dupli_data = (OVERLAY_DupliData **)DRW_duplidata_get(vedata); + *do_init = false; + if (!ELEM(ob->type, OB_MESH, OB_SURF, OB_LATTICE, OB_CURVES_LEGACY, OB_FONT)) { + return nullptr; + } + + if (dupli_data) { + if (*dupli_data == nullptr) { + *dupli_data = static_cast<OVERLAY_DupliData *>( + MEM_callocN(sizeof(OVERLAY_DupliData), __func__)); + *do_init = true; + } + else if ((*dupli_data)->base_flag != ob->base_flag) { + /* Select state might have change, reinitialize. */ + *do_init = true; + } + return *dupli_data; + } + return nullptr; +} + +static bool overlay_object_is_edit_mode(const OVERLAY_PrivateData *pd, const Object *ob) +{ + if (DRW_object_is_in_edit_mode(ob)) { + /* Also check for context mode as the object mode is not 100% reliable. (see T72490) */ + switch (ob->type) { + case OB_MESH: + return pd->ctx_mode == CTX_MODE_EDIT_MESH; + case OB_ARMATURE: + return pd->ctx_mode == CTX_MODE_EDIT_ARMATURE; + case OB_CURVES_LEGACY: + return pd->ctx_mode == CTX_MODE_EDIT_CURVE; + case OB_SURF: + return pd->ctx_mode == CTX_MODE_EDIT_SURFACE; + case OB_LATTICE: + return pd->ctx_mode == CTX_MODE_EDIT_LATTICE; + case OB_MBALL: + return pd->ctx_mode == CTX_MODE_EDIT_METABALL; + case OB_FONT: + return pd->ctx_mode == CTX_MODE_EDIT_TEXT; + case OB_CURVES: + return pd->ctx_mode == CTX_MODE_EDIT_CURVES; + case OB_POINTCLOUD: + case OB_VOLUME: + /* No edit mode yet. */ + return false; + } + } + return false; +} + +static bool overlay_should_fade_object(Object *ob, Object *active_object) +{ + if (!active_object || !ob) { + return false; + } + + if (ELEM(active_object->mode, OB_MODE_OBJECT, OB_MODE_POSE)) { + return false; + } + + if ((active_object->mode & ob->mode) != 0) { + return false; + } + + return true; +} + +static void OVERLAY_cache_populate(void *vedata, Object *ob) +{ + OVERLAY_Data *data = static_cast<OVERLAY_Data *>(vedata); + OVERLAY_PrivateData *pd = data->stl->pd; + + if (pd->space_type == SPACE_IMAGE) { + return; + } + + const DRWContextState *draw_ctx = DRW_context_state_get(); + DupliObject *dupli_object = DRW_object_get_dupli(ob); + Object *dupli_parent = DRW_object_get_dupli_parent(ob); + const bool is_select = DRW_state_is_select(); + const bool renderable = DRW_object_is_renderable(ob); + const bool is_preview = dupli_object != nullptr && + dupli_object->preview_base_geometry != nullptr; + const bool in_pose_mode = ob->type == OB_ARMATURE && OVERLAY_armature_is_pose_mode(ob, draw_ctx); + const bool in_edit_mode = overlay_object_is_edit_mode(pd, ob); + const bool is_instance = (ob->base_flag & BASE_FROM_DUPLI); + const bool instance_parent_in_edit_mode = is_instance ? + overlay_object_is_edit_mode( + pd, DRW_object_get_dupli_parent(ob)) : + false; + const bool in_particle_edit_mode = (ob->mode == OB_MODE_PARTICLE_EDIT) && + (pd->ctx_mode == CTX_MODE_PARTICLE); + const bool in_paint_mode = (ob == draw_ctx->obact) && + (draw_ctx->object_mode & OB_MODE_ALL_PAINT); + const bool in_sculpt_curve_mode = (ob == draw_ctx->obact || + (is_preview && dupli_parent == draw_ctx->obact)) && + (draw_ctx->object_mode & OB_MODE_SCULPT_CURVES); + const bool in_sculpt_mode = (ob == draw_ctx->obact) && (ob->sculpt != nullptr) && + (ob->sculpt->mode_type == OB_MODE_SCULPT); + const bool in_curves_sculpt_mode = (ob == draw_ctx->obact) && + (ob->mode == OB_MODE_SCULPT_CURVES); + const bool has_surface = ELEM(ob->type, + OB_MESH, + OB_CURVES_LEGACY, + OB_SURF, + OB_FONT, + OB_GPENCIL, + OB_CURVES, + OB_POINTCLOUD, + OB_VOLUME); + const bool draw_surface = (ob->dt >= OB_WIRE) && (renderable || (ob->dt == OB_WIRE)); + const bool draw_facing = draw_surface && (pd->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) && + !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; + 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); + const bool draw_outlines = !in_edit_mode && !in_paint_mode && !in_sculpt_curve_mode && + renderable && has_surface && !instance_parent_in_edit_mode && + (pd->v3d_flag & V3D_SELECT_OUTLINE) && + (ob->base_flag & BASE_SELECTED); + const bool draw_bone_selection = (ob->type == OB_MESH) && pd->armature.do_pose_fade_geom && + !is_select; + const bool draw_edit_weights = in_edit_mode && (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_WEIGHT); + const bool draw_extras = + (!pd->hide_overlays) && + (((pd->overlay.flag & V3D_OVERLAY_HIDE_OBJECT_XTRAS) == 0) || + /* Show if this is the camera we're looking through since it's useful for selecting. */ + ((draw_ctx->rv3d->persp == RV3D_CAMOB) && ((ID *)draw_ctx->v3d->camera == ob->id.orig_id))); + + const bool draw_motion_paths = (pd->overlay.flag & V3D_OVERLAY_HIDE_MOTION_PATHS) == 0; + + bool do_init; + OVERLAY_DupliData *dupli = OVERLAY_duplidata_get(ob, vedata, &do_init); + + if (draw_fade) { + OVERLAY_fade_cache_populate(data, ob); + } + if (draw_facing) { + OVERLAY_facing_cache_populate(data, ob); + } + if (draw_mode_transfer) { + OVERLAY_mode_transfer_cache_populate(data, ob); + } + if (draw_wires) { + OVERLAY_wireframe_cache_populate(data, ob, dupli, do_init); + } + if (draw_outlines) { + OVERLAY_outline_cache_populate(data, ob, dupli, do_init); + } + if (draw_bone_selection) { + OVERLAY_pose_cache_populate(data, ob); + } + + if (pd->overlay.flag & V3D_OVERLAY_VIEWER_ATTRIBUTE) { + if (is_preview) { + OVERLAY_viewer_attribute_cache_populate(data, ob); + } + } + + if (ob->type == OB_VOLUME) { + OVERLAY_volume_cache_populate(data, ob); + } + + if (in_edit_mode && !pd->hide_overlays) { + switch (ob->type) { + case OB_MESH: + OVERLAY_edit_mesh_cache_populate(data, ob); + if (draw_edit_weights) { + OVERLAY_paint_weight_cache_populate(data, ob); + } + break; + case OB_ARMATURE: + if (draw_bones) { + OVERLAY_edit_armature_cache_populate(data, ob); + } + break; + case OB_CURVES_LEGACY: + OVERLAY_edit_curve_cache_populate(data, ob); + break; + case OB_SURF: + OVERLAY_edit_surf_cache_populate(data, ob); + break; + case OB_LATTICE: + OVERLAY_edit_lattice_cache_populate(data, ob); + break; + case OB_MBALL: + OVERLAY_edit_metaball_cache_populate(data, ob); + break; + case OB_FONT: + OVERLAY_edit_text_cache_populate(data, ob); + break; + case OB_CURVES: + OVERLAY_edit_curves_cache_populate(data, ob); + break; + } + } + else if (in_pose_mode && draw_bones) { + OVERLAY_pose_armature_cache_populate(data, ob); + } + else if (in_paint_mode && !pd->hide_overlays) { + switch (draw_ctx->object_mode) { + case OB_MODE_VERTEX_PAINT: + OVERLAY_paint_vertex_cache_populate(data, ob); + break; + case OB_MODE_WEIGHT_PAINT: + OVERLAY_paint_weight_cache_populate(data, ob); + break; + case OB_MODE_TEXTURE_PAINT: + OVERLAY_paint_texture_cache_populate(data, ob); + break; + default: + break; + } + } + else if (in_particle_edit_mode) { + OVERLAY_edit_particle_cache_populate(data, ob); + } + + if (in_sculpt_mode) { + OVERLAY_sculpt_cache_populate(data, ob); + } + else if (in_curves_sculpt_mode) { + OVERLAY_sculpt_curves_cache_populate(data, ob); + } + + if (draw_motion_paths) { + OVERLAY_motion_path_cache_populate(data, ob); + } + + if (!pd->hide_overlays) { + switch (ob->type) { + case OB_ARMATURE: + if (draw_bones && (is_select || (!in_edit_mode && !in_pose_mode))) { + OVERLAY_armature_cache_populate(data, ob); + } + break; + case OB_MBALL: + if (!in_edit_mode) { + OVERLAY_metaball_cache_populate(data, ob); + } + break; + case OB_GPENCIL: + OVERLAY_gpencil_cache_populate(data, ob); + break; + } + } + /* Non-Meshes */ + if (draw_extras) { + switch (ob->type) { + case OB_EMPTY: + OVERLAY_empty_cache_populate(data, ob); + break; + case OB_LAMP: + OVERLAY_light_cache_populate(data, ob); + break; + case OB_CAMERA: + OVERLAY_camera_cache_populate(data, ob); + break; + case OB_SPEAKER: + OVERLAY_speaker_cache_populate(data, ob); + break; + case OB_LIGHTPROBE: + OVERLAY_lightprobe_cache_populate(data, ob); + break; + case OB_LATTICE: { + /* Unlike the other types above, lattices actually have a bounding box defined, so hide the + * lattice wires if only the bounding-box is requested. */ + if (ob->dt > OB_BOUNDBOX) { + OVERLAY_lattice_cache_populate(data, ob); + } + break; + } + } + } + + if (!BLI_listbase_is_empty(&ob->particlesystem)) { + OVERLAY_particle_cache_populate(data, ob); + } + + /* Relationship, object center, bounding-box... etc. */ + if (!pd->hide_overlays) { + OVERLAY_extra_cache_populate(data, ob); + } + + if (dupli) { + dupli->base_flag = ob->base_flag; + } +} + +static void OVERLAY_cache_finish(void *vedata) +{ + OVERLAY_Data *data = static_cast<OVERLAY_Data *>(vedata); + OVERLAY_PrivateData *pd = data->stl->pd; + + if (ELEM(pd->space_type, SPACE_IMAGE)) { + OVERLAY_edit_uv_cache_finish(data); + return; + } + if (ELEM(pd->space_type, SPACE_NODE)) { + return; + } + + /* TODO(fclem): Only do this when really needed. */ + { + /* HACK we allocate the in front depth here to avoid the overhead when if is not needed. */ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + DRW_texture_ensure_fullscreen_2d( + &dtxl->depth_in_front, GPU_DEPTH24_STENCIL8, DRWTextureFlag(0)); + + GPU_framebuffer_ensure_config( + &dfbl->in_front_fb, + {GPU_ATTACHMENT_TEXTURE(dtxl->depth_in_front), GPU_ATTACHMENT_TEXTURE(dtxl->color)}); + } + + OVERLAY_mode_transfer_cache_finish(data); + OVERLAY_antialiasing_cache_finish(data); + OVERLAY_armature_cache_finish(data); + OVERLAY_image_cache_finish(data); +} + +static void OVERLAY_draw_scene(void *vedata) +{ + OVERLAY_Data *data = static_cast<OVERLAY_Data *>(vedata); + OVERLAY_PrivateData *pd = data->stl->pd; + OVERLAY_FramebufferList *fbl = data->fbl; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + + /* Needs to be done first as it modifies the scene color and depth buffer. */ + if (pd->space_type == SPACE_VIEW3D) { + OVERLAY_image_scene_background_draw(data); + } + + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(dfbl->overlay_only_fb); + /* Don't clear background for the node editor. The node editor draws the background and we + * need to mask out the image from the already drawn overlay color buffer. */ + if (pd->space_type != SPACE_NODE) { + const float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color(dfbl->overlay_only_fb, clear_col); + } + } + + if (pd->space_type == SPACE_IMAGE) { + OVERLAY_background_draw(data); + OVERLAY_grid_draw(data); + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(dfbl->overlay_fb); + } + OVERLAY_edit_uv_draw(data); + return; + } + if (pd->space_type == SPACE_NODE) { + OVERLAY_background_draw(data); + return; + } + + OVERLAY_image_background_draw(data); + OVERLAY_background_draw(data); + + OVERLAY_antialiasing_start(data); + + DRW_view_set_active(nullptr); + + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(fbl->overlay_color_only_fb); + } + + OVERLAY_outline_draw(data); + OVERLAY_xray_depth_copy(data); + + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(fbl->overlay_default_fb); + } + + OVERLAY_image_draw(data); + OVERLAY_fade_draw(data); + OVERLAY_facing_draw(data); + OVERLAY_mode_transfer_draw(data); + OVERLAY_extra_blend_draw(data); + OVERLAY_volume_draw(data); + + /* These overlays are drawn here to avoid artifacts with wire-frame opacity. */ + switch (pd->ctx_mode) { + case CTX_MODE_SCULPT: + OVERLAY_sculpt_draw(data); + break; + case CTX_MODE_SCULPT_CURVES: + OVERLAY_sculpt_curves_draw(data); + break; + case CTX_MODE_EDIT_MESH: + case CTX_MODE_POSE: + case CTX_MODE_PAINT_WEIGHT: + case CTX_MODE_PAINT_VERTEX: + case CTX_MODE_PAINT_TEXTURE: + OVERLAY_paint_draw(data); + break; + default: + break; + } + + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(fbl->overlay_line_fb); + } + + OVERLAY_wireframe_draw(data); + OVERLAY_armature_draw(data); + OVERLAY_particle_draw(data); + OVERLAY_metaball_draw(data); + OVERLAY_gpencil_draw(data); + OVERLAY_extra_draw(data); + if (pd->overlay.flag & V3D_OVERLAY_VIEWER_ATTRIBUTE) { + OVERLAY_viewer_attribute_draw(data); + } + + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(fbl->overlay_color_only_fb); + } + + OVERLAY_xray_fade_draw(data); + OVERLAY_grid_draw(data); + + OVERLAY_xray_depth_infront_copy(data); + + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(fbl->overlay_in_front_fb); + } + + OVERLAY_fade_infront_draw(data); + OVERLAY_facing_infront_draw(data); + OVERLAY_mode_transfer_infront_draw(data); + + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(fbl->overlay_line_in_front_fb); + } + + OVERLAY_wireframe_in_front_draw(data); + OVERLAY_armature_in_front_draw(data); + OVERLAY_extra_in_front_draw(data); + OVERLAY_metaball_in_front_draw(data); + + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(fbl->overlay_color_only_fb); + } + + OVERLAY_image_in_front_draw(data); + OVERLAY_motion_path_draw(data); + OVERLAY_extra_centers_draw(data); + + if (DRW_state_is_select() || DRW_state_is_depth()) { + /* Edit modes have their own selection code. */ + return; + } + + /* Functions after this point can change FBO freely. */ + + switch (pd->ctx_mode) { + case CTX_MODE_EDIT_MESH: + OVERLAY_edit_mesh_draw(data); + break; + case CTX_MODE_EDIT_SURFACE: + case CTX_MODE_EDIT_CURVE: + OVERLAY_edit_curve_draw(data); + break; + case CTX_MODE_EDIT_TEXT: + OVERLAY_edit_text_draw(data); + break; + case CTX_MODE_EDIT_LATTICE: + OVERLAY_edit_lattice_draw(data); + break; + case CTX_MODE_POSE: + OVERLAY_pose_draw(data); + break; + case CTX_MODE_PARTICLE: + OVERLAY_edit_particle_draw(data); + break; + case CTX_MODE_EDIT_GPENCIL: + case CTX_MODE_PAINT_GPENCIL: + case CTX_MODE_SCULPT_GPENCIL: + case CTX_MODE_VERTEX_GPENCIL: + case CTX_MODE_WEIGHT_GPENCIL: + OVERLAY_edit_gpencil_draw(data); + break; + case CTX_MODE_SCULPT_CURVES: + break; + case CTX_MODE_EDIT_CURVES: + OVERLAY_edit_curves_draw(data); + break; + default: + break; + } + + OVERLAY_antialiasing_end(data); +} + +static void OVERLAY_engine_free() +{ + OVERLAY_shader_free(); +} + +static void OVERLAY_instance_free(void *instance_) +{ + OVERLAY_Instance *instance = (OVERLAY_Instance *)instance_; + DRW_UBO_FREE_SAFE(instance->grid_ubo); + MEM_freeN(instance); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Engine Type + * \{ */ + +static const DrawEngineDataSize overlay_data_size = DRW_VIEWPORT_DATA_SIZE(OVERLAY_Data); + +DrawEngineType draw_engine_overlay_type = { + nullptr, + nullptr, + N_("Overlay"), + &overlay_data_size, + &OVERLAY_engine_init, + &OVERLAY_engine_free, + &OVERLAY_instance_free, + &OVERLAY_cache_init, + &OVERLAY_cache_populate, + &OVERLAY_cache_finish, + &OVERLAY_draw_scene, + nullptr, + nullptr, + nullptr, + nullptr, +}; + +/** \} */ + +#undef SELECT_ENGINE |