Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/engines/overlay/overlay_engine.c')
-rw-r--r--source/blender/draw/engines/overlay/overlay_engine.c491
1 files changed, 491 insertions, 0 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c
new file mode 100644
index 00000000000..667172e5bb5
--- /dev/null
+++ b/source/blender/draw/engines/overlay/overlay_engine.c
@@ -0,0 +1,491 @@
+/*
+ * 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
+ *
+ * Engine for drawing a selection map where the pixels indicate the selection indices.
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "ED_view3d.h"
+
+#include "BKE_object.h"
+
+#include "overlay_engine.h"
+#include "overlay_private.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Engine Callbacks
+ * \{ */
+
+static void OVERLAY_engine_init(void *vedata)
+{
+ OVERLAY_Data *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;
+
+ if (!stl->pd) {
+ /* Alloc transient pointers */
+ stl->pd = MEM_callocN(sizeof(*stl->pd), __func__);
+ }
+
+ OVERLAY_PrivateData *pd = stl->pd;
+ View3DOverlay overlay;
+ short v3d_flag, v3d_gridflag;
+
+ 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) {
+ overlay = v3d->overlay;
+ v3d_flag = v3d->flag;
+ v3d_gridflag = v3d->gridflag;
+ }
+ else {
+ memset(&overlay, 0, sizeof(overlay));
+ v3d_flag = 0;
+ v3d_gridflag = 0;
+ 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;
+ }
+
+ if (v3d->shading.type == OB_WIRE) {
+ overlay.flag |= V3D_OVERLAY_WIREFRAMES;
+ }
+
+ /* Check if anything changed, and if so, reset AA. */
+ if (v3d_flag != pd->v3d_flag || pd->v3d_gridflag != v3d_gridflag ||
+ memcmp(&pd->overlay, &overlay, sizeof(overlay))) {
+ pd->overlay = overlay;
+ pd->v3d_flag = v3d_flag;
+ pd->v3d_gridflag = v3d_gridflag;
+ OVERLAY_antialiasing_reset(vedata);
+ }
+
+ pd->wireframe_mode = (v3d->shading.type == OB_WIRE);
+ pd->clipping_state = (rv3d->rflag & RV3D_CLIPPING) ? DRW_STATE_CLIP_PLANES : 0;
+ 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);
+
+ OVERLAY_antialiasing_init(vedata);
+
+ switch (stl->pd->ctx_mode) {
+ case CTX_MODE_EDIT_MESH:
+ OVERLAY_edit_mesh_init(vedata);
+ break;
+ default:
+ /* Nothing to do. */
+ break;
+ }
+ OVERLAY_facing_init(vedata);
+ OVERLAY_grid_init(vedata);
+ OVERLAY_image_init(vedata);
+ OVERLAY_outline_init(vedata);
+ OVERLAY_wireframe_init(vedata);
+}
+
+static void OVERLAY_cache_init(void *vedata)
+{
+ OVERLAY_Data *data = vedata;
+ OVERLAY_StorageList *stl = data->stl;
+ OVERLAY_PrivateData *pd = stl->pd;
+
+ switch (pd->ctx_mode) {
+ case CTX_MODE_EDIT_MESH:
+ OVERLAY_edit_mesh_cache_init(vedata);
+ break;
+ case CTX_MODE_EDIT_SURFACE:
+ case CTX_MODE_EDIT_CURVE:
+ OVERLAY_edit_curve_cache_init(vedata);
+ break;
+ case CTX_MODE_EDIT_TEXT:
+ OVERLAY_edit_text_cache_init(vedata);
+ break;
+ case CTX_MODE_EDIT_ARMATURE:
+ break;
+ case CTX_MODE_EDIT_METABALL:
+ break;
+ case CTX_MODE_EDIT_LATTICE:
+ OVERLAY_edit_lattice_cache_init(vedata);
+ break;
+ case CTX_MODE_PARTICLE:
+ OVERLAY_edit_particle_cache_init(vedata);
+ break;
+ case CTX_MODE_POSE:
+ case CTX_MODE_PAINT_WEIGHT:
+ case CTX_MODE_PAINT_VERTEX:
+ case CTX_MODE_PAINT_TEXTURE:
+ OVERLAY_paint_cache_init(vedata);
+ break;
+ case CTX_MODE_SCULPT:
+ OVERLAY_sculpt_cache_init(vedata);
+ break;
+ case CTX_MODE_OBJECT:
+ case CTX_MODE_PAINT_GPENCIL:
+ case CTX_MODE_EDIT_GPENCIL:
+ case CTX_MODE_SCULPT_GPENCIL:
+ case CTX_MODE_WEIGHT_GPENCIL:
+ break;
+ default:
+ BLI_assert(!"Draw mode invalid");
+ break;
+ }
+ OVERLAY_antialiasing_cache_init(vedata);
+ OVERLAY_armature_cache_init(vedata);
+ OVERLAY_extra_cache_init(vedata);
+ OVERLAY_facing_cache_init(vedata);
+ OVERLAY_grid_cache_init(vedata);
+ OVERLAY_image_cache_init(vedata);
+ OVERLAY_metaball_cache_init(vedata);
+ OVERLAY_motion_path_cache_init(vedata);
+ OVERLAY_outline_cache_init(vedata);
+ OVERLAY_particle_cache_init(vedata);
+ OVERLAY_wireframe_cache_init(vedata);
+}
+
+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_CURVE, OB_FONT)) {
+ return NULL;
+ }
+
+ if (dupli_data) {
+ if (*dupli_data == NULL) {
+ *dupli_data = MEM_callocN(sizeof(OVERLAY_DupliData), __func__);
+ *do_init = true;
+ }
+ else if ((*dupli_data)->base_flag != ob->base_flag) {
+ /* Select state might have change, reinit. */
+ *do_init = true;
+ }
+ return *dupli_data;
+ }
+ return NULL;
+}
+
+static void OVERLAY_cache_populate(void *vedata, Object *ob)
+{
+ OVERLAY_Data *data = vedata;
+ OVERLAY_PrivateData *pd = data->stl->pd;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const bool is_select = DRW_state_is_select();
+ const bool renderable = DRW_object_is_renderable(ob);
+ const bool in_pose_mode = ob->type == OB_ARMATURE && OVERLAY_armature_is_pose_mode(ob, draw_ctx);
+ const bool in_edit_mode = BKE_object_is_in_editmode(ob);
+ const bool in_particle_edit_mode = ob->mode == OB_MODE_PARTICLE_EDIT;
+ const bool in_paint_mode = (ob == draw_ctx->obact) &&
+ (draw_ctx->object_mode & OB_MODE_ALL_PAINT);
+ const bool in_sculpt_mode = (ob == draw_ctx->obact) && (ob->sculpt != NULL);
+ const bool has_surface = ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL, OB_FONT);
+ 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);
+ 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 && renderable &&
+ (pd->v3d_flag & V3D_SELECT_OUTLINE) &&
+ ((ob->base_flag & BASE_SELECTED) ||
+ (is_select && ob->type == OB_LIGHTPROBE));
+ const bool draw_bone_selection = (ob->type == OB_MESH) && pd->armature.do_pose_fade_geom &&
+ !is_select;
+ const bool draw_extras =
+ ((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_facing) {
+ OVERLAY_facing_cache_populate(vedata, ob);
+ }
+ if (draw_wires) {
+ OVERLAY_wireframe_cache_populate(vedata, ob, dupli, do_init);
+ }
+ if (draw_outlines) {
+ OVERLAY_outline_cache_populate(vedata, ob, dupli, do_init);
+ }
+ if (draw_bone_selection) {
+ OVERLAY_pose_cache_populate(vedata, ob);
+ }
+
+ if (in_edit_mode) {
+ switch (ob->type) {
+ case OB_MESH:
+ OVERLAY_edit_mesh_cache_populate(vedata, ob);
+ break;
+ case OB_ARMATURE:
+ if (draw_bones) {
+ OVERLAY_edit_armature_cache_populate(vedata, ob);
+ }
+ break;
+ case OB_CURVE:
+ OVERLAY_edit_curve_cache_populate(vedata, ob);
+ break;
+ case OB_SURF:
+ OVERLAY_edit_surf_cache_populate(vedata, ob);
+ break;
+ case OB_LATTICE:
+ OVERLAY_edit_lattice_cache_populate(vedata, ob);
+ break;
+ case OB_MBALL:
+ OVERLAY_edit_metaball_cache_populate(vedata, ob);
+ break;
+ case OB_FONT:
+ OVERLAY_edit_text_cache_populate(vedata, ob);
+ break;
+ }
+ }
+ else if (in_pose_mode && draw_bones) {
+ OVERLAY_pose_armature_cache_populate(vedata, ob);
+ }
+ else if (in_paint_mode) {
+ switch (draw_ctx->object_mode) {
+ case OB_MODE_VERTEX_PAINT:
+ OVERLAY_paint_vertex_cache_populate(vedata, ob);
+ break;
+ case OB_MODE_WEIGHT_PAINT:
+ OVERLAY_paint_weight_cache_populate(vedata, ob);
+ break;
+ case OB_MODE_TEXTURE_PAINT:
+ OVERLAY_paint_texture_cache_populate(vedata, ob);
+ break;
+ default:
+ break;
+ }
+ }
+ else if (in_particle_edit_mode) {
+ OVERLAY_edit_particle_cache_populate(vedata, ob);
+ }
+
+ if (in_sculpt_mode) {
+ OVERLAY_sculpt_cache_populate(vedata, ob);
+ }
+
+ if (draw_motion_paths) {
+ OVERLAY_motion_path_cache_populate(vedata, ob);
+ }
+
+ switch (ob->type) {
+ case OB_ARMATURE:
+ if (draw_bones && (is_select || (!in_edit_mode && !in_pose_mode))) {
+ OVERLAY_armature_cache_populate(vedata, ob);
+ }
+ break;
+ case OB_MBALL:
+ if (!in_edit_mode) {
+ OVERLAY_metaball_cache_populate(vedata, ob);
+ }
+ break;
+ case OB_GPENCIL:
+ OVERLAY_gpencil_cache_populate(vedata, ob);
+ break;
+ }
+ /* Non-Meshes */
+ if (draw_extras) {
+ switch (ob->type) {
+ case OB_EMPTY:
+ OVERLAY_empty_cache_populate(vedata, ob);
+ break;
+ case OB_LAMP:
+ OVERLAY_light_cache_populate(vedata, ob);
+ break;
+ case OB_CAMERA:
+ OVERLAY_camera_cache_populate(vedata, ob);
+ break;
+ case OB_SPEAKER:
+ OVERLAY_speaker_cache_populate(vedata, ob);
+ break;
+ case OB_LIGHTPROBE:
+ OVERLAY_lightprobe_cache_populate(vedata, ob);
+ break;
+ case OB_LATTICE:
+ OVERLAY_lattice_cache_populate(vedata, ob);
+ break;
+ }
+ }
+
+ if (!BLI_listbase_is_empty(&ob->particlesystem)) {
+ OVERLAY_particle_cache_populate(vedata, ob);
+ }
+
+ /* Relationship, object center, bounbox ... */
+ OVERLAY_extra_cache_populate(vedata, ob);
+
+ if (dupli) {
+ dupli->base_flag = ob->base_flag;
+ }
+}
+
+static void OVERLAY_cache_finish(void *vedata)
+{
+ /* TODO(fclem) Only do this when really needed. */
+ {
+ /* HACK we allocate the infront 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, 0);
+
+ GPU_framebuffer_ensure_config(
+ &dfbl->default_fb,
+ {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(dtxl->color)});
+ GPU_framebuffer_ensure_config(
+ &dfbl->in_front_fb,
+ {GPU_ATTACHMENT_TEXTURE(dtxl->depth_in_front), GPU_ATTACHMENT_TEXTURE(dtxl->color)});
+ }
+
+ OVERLAY_antialiasing_cache_finish(vedata);
+ OVERLAY_armature_cache_finish(vedata);
+ OVERLAY_image_cache_finish(vedata);
+}
+
+static void OVERLAY_draw_scene(void *vedata)
+{
+ OVERLAY_Data *data = vedata;
+ OVERLAY_PrivateData *pd = data->stl->pd;
+ OVERLAY_FramebufferList *fbl = data->fbl;
+
+ OVERLAY_antialiasing_start(vedata);
+
+ DRW_view_set_active(pd->view_default);
+
+ OVERLAY_image_draw(vedata);
+ OVERLAY_facing_draw(vedata);
+ OVERLAY_wireframe_draw(vedata);
+ OVERLAY_armature_draw(vedata);
+ OVERLAY_particle_draw(vedata);
+ OVERLAY_metaball_draw(vedata);
+ OVERLAY_extra_draw(vedata);
+
+ DRW_view_set_active(NULL);
+
+ OVERLAY_grid_draw(vedata);
+ OVERLAY_outline_draw(vedata);
+
+ DRW_view_set_active(pd->view_default);
+
+ if (DRW_state_is_fbo()) {
+ GPU_framebuffer_bind(fbl->overlay_in_front_fb);
+
+ /* If we are not in solid shading mode, we clear the depth. */
+ if (pd->clear_in_front) {
+ /* TODO(fclem) This clear should be done in a global place. */
+ GPU_framebuffer_clear_depth(fbl->overlay_in_front_fb, 1.0f);
+ }
+ }
+
+ OVERLAY_wireframe_in_front_draw(vedata);
+ OVERLAY_armature_in_front_draw(vedata);
+ OVERLAY_extra_in_front_draw(vedata);
+ OVERLAY_metaball_in_front_draw(vedata);
+ OVERLAY_image_in_front_draw(vedata);
+
+ if (DRW_state_is_fbo()) {
+ GPU_framebuffer_bind(fbl->overlay_default_fb);
+ }
+
+ OVERLAY_motion_path_draw(vedata);
+ OVERLAY_extra_centers_draw(vedata);
+
+ switch (pd->ctx_mode) {
+ case CTX_MODE_EDIT_MESH:
+ OVERLAY_edit_mesh_draw(vedata);
+ break;
+ case CTX_MODE_EDIT_SURFACE:
+ case CTX_MODE_EDIT_CURVE:
+ OVERLAY_edit_curve_draw(vedata);
+ break;
+ case CTX_MODE_EDIT_TEXT:
+ /* Text overlay need final color for color inversion. */
+ OVERLAY_antialiasing_end(vedata);
+ OVERLAY_edit_text_draw(vedata);
+ return; /* WATCH! dont do AA twice. */
+ case CTX_MODE_EDIT_LATTICE:
+ OVERLAY_edit_lattice_draw(vedata);
+ break;
+ case CTX_MODE_POSE:
+ /* Pain overlay needs final color because of multiply blend mode. */
+ OVERLAY_antialiasing_end(vedata);
+ OVERLAY_paint_draw(vedata);
+ OVERLAY_pose_draw(vedata);
+ return; /* WATCH! dont do AA twice. */
+ case CTX_MODE_PAINT_WEIGHT:
+ case CTX_MODE_PAINT_VERTEX:
+ case CTX_MODE_PAINT_TEXTURE:
+ /* Pain overlay need final color because of multiply blend mode. */
+ OVERLAY_antialiasing_end(vedata);
+ OVERLAY_paint_draw(vedata);
+ return; /* WATCH! dont do AA twice. */
+ case CTX_MODE_PARTICLE:
+ OVERLAY_edit_particle_draw(vedata);
+ break;
+ case CTX_MODE_SCULPT:
+ OVERLAY_sculpt_draw(vedata);
+ break;
+ default:
+ break;
+ }
+
+ OVERLAY_antialiasing_end(vedata);
+}
+
+static void OVERLAY_engine_free(void)
+{
+ OVERLAY_shader_free();
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Engine Type
+ * \{ */
+
+static const DrawEngineDataSize overlay_data_size = DRW_VIEWPORT_DATA_SIZE(OVERLAY_Data);
+
+DrawEngineType draw_engine_overlay_type = {
+ NULL,
+ NULL,
+ N_("Overlay"),
+ &overlay_data_size,
+ &OVERLAY_engine_init,
+ &OVERLAY_engine_free,
+ &OVERLAY_cache_init,
+ &OVERLAY_cache_populate,
+ &OVERLAY_cache_finish,
+ NULL,
+ &OVERLAY_draw_scene,
+ NULL,
+ NULL,
+ NULL,
+};
+
+/** \} */
+
+#undef SELECT_ENGINE