2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2019 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2019-07-30 17:55:20 -03:00
|
|
|
|
|
|
|
|
/** \file
|
|
|
|
|
* \ingroup draw_engine
|
|
|
|
|
*
|
|
|
|
|
* Engine for drawing a selection map where the pixels indicate the selection indices.
|
|
|
|
|
*/
|
|
|
|
|
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_editmesh.hh"
|
2023-08-02 22:14:18 +02:00
|
|
|
#include "BKE_mesh.hh"
|
2019-07-30 17:55:20 -03:00
|
|
|
|
|
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
|
|
2023-08-05 02:57:52 +02:00
|
|
|
#include "ED_view3d.hh"
|
2019-07-30 17:55:20 -03:00
|
|
|
|
2023-09-22 03:18:17 +02:00
|
|
|
#include "DEG_depsgraph_query.hh"
|
2019-07-30 17:55:20 -03:00
|
|
|
|
2023-08-03 20:04:50 -04:00
|
|
|
#include "draw_cache_impl.hh"
|
2019-07-30 17:55:20 -03:00
|
|
|
|
2023-10-04 14:32:18 -03:00
|
|
|
#include "select_private.hh"
|
2019-07-30 17:55:20 -03:00
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Draw Utilities
|
|
|
|
|
* \{ */
|
2019-08-15 10:31:54 -03:00
|
|
|
|
2019-08-01 23:00:16 -03:00
|
|
|
short select_id_get_object_select_mode(Scene *scene, Object *ob)
|
|
|
|
|
{
|
|
|
|
|
short r_select_mode = 0;
|
2019-09-12 14:14:40 +02:00
|
|
|
if (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT)) {
|
2019-09-19 13:18:52 +10:00
|
|
|
/* In order to sample flat colors for vertex weights / texture-paint / vertex-paint
|
2019-09-12 14:14:40 +02:00
|
|
|
* we need to be in SCE_SELECT_FACE mode so select_cache_init() correctly sets up
|
|
|
|
|
* a shgroup with select_id_flat.
|
2019-09-19 13:18:52 +10:00
|
|
|
* Note this is not working correctly for vertex-paint (yet), but has been discussed
|
2023-02-12 14:37:16 +11:00
|
|
|
* in #66645 and there is a solution by @mano-wii in P1032.
|
2019-09-12 14:14:40 +02:00
|
|
|
* So OB_MODE_VERTEX_PAINT is already included here [required for P1032 I guess]. */
|
2023-07-27 14:16:58 +02:00
|
|
|
Mesh *me_orig = static_cast<Mesh *>(DEG_get_original_object(ob)->data);
|
2019-09-12 14:14:40 +02:00
|
|
|
if (me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) {
|
2019-09-03 23:43:15 +10:00
|
|
|
r_select_mode = SCE_SELECT_VERTEX;
|
|
|
|
|
}
|
2019-09-12 14:14:40 +02:00
|
|
|
else {
|
2019-09-03 23:43:15 +10:00
|
|
|
r_select_mode = SCE_SELECT_FACE;
|
2019-08-01 23:00:16 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
r_select_mode = scene->toolsettings->selectmode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return r_select_mode;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-06 12:21:39 +01:00
|
|
|
static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, eDrawType dt)
|
2019-07-30 17:55:20 -03:00
|
|
|
{
|
|
|
|
|
if (select_mode & SCE_SELECT_FACE) {
|
|
|
|
|
if ((dt < OB_SOLID) || XRAY_FLAG_ENABLED(v3d)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-02 23:20:29 +01:00
|
|
|
static void draw_select_id_edit_mesh(SELECTID_Instance &inst,
|
2019-07-30 17:55:20 -03:00
|
|
|
Object *ob,
|
2024-12-02 23:20:29 +01:00
|
|
|
ResourceHandle res_handle,
|
2019-07-30 17:55:20 -03:00
|
|
|
short select_mode,
|
|
|
|
|
bool draw_facedot,
|
|
|
|
|
uint initial_offset,
|
|
|
|
|
uint *r_vert_offset,
|
|
|
|
|
uint *r_edge_offset,
|
|
|
|
|
uint *r_face_offset)
|
|
|
|
|
{
|
2024-01-05 12:20:30 -05:00
|
|
|
using namespace blender::draw;
|
2024-12-02 23:20:29 +01:00
|
|
|
using namespace blender;
|
2024-05-21 09:09:02 -04:00
|
|
|
Mesh &mesh = *static_cast<Mesh *>(ob->data);
|
|
|
|
|
BMEditMesh *em = mesh.runtime->edit_mesh.get();
|
2019-07-30 17:55:20 -03:00
|
|
|
|
|
|
|
|
BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
|
|
|
|
|
|
2019-07-30 18:26:35 -03:00
|
|
|
if (select_mode & SCE_SELECT_FACE) {
|
2024-12-02 23:20:29 +01:00
|
|
|
gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(mesh);
|
|
|
|
|
PassSimple::Sub *face_sub = inst.select_face_flat;
|
|
|
|
|
face_sub->push_constant("offset", int(initial_offset));
|
|
|
|
|
face_sub->draw(geom_faces, res_handle);
|
2019-07-30 17:55:20 -03:00
|
|
|
|
|
|
|
|
if (draw_facedot) {
|
2024-12-02 23:20:29 +01:00
|
|
|
gpu::Batch *geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(mesh);
|
|
|
|
|
face_sub->draw(geom_facedots, res_handle);
|
2019-07-30 17:55:20 -03:00
|
|
|
}
|
2024-04-16 10:21:18 -03:00
|
|
|
*r_face_offset = initial_offset + em->bm->totface;
|
2019-07-30 17:55:20 -03:00
|
|
|
}
|
|
|
|
|
else {
|
2019-08-17 18:40:08 -03:00
|
|
|
if (ob->dt >= OB_SOLID) {
|
2019-09-17 08:26:38 -03:00
|
|
|
#ifdef USE_CAGE_OCCLUSION
|
2024-12-02 23:20:29 +01:00
|
|
|
gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(mesh);
|
2019-09-17 08:26:38 -03:00
|
|
|
#else
|
2024-12-02 23:20:29 +01:00
|
|
|
gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_surface(mesh);
|
2019-09-17 08:26:38 -03:00
|
|
|
#endif
|
2024-12-02 23:20:29 +01:00
|
|
|
inst.select_face_uniform->draw(geom_faces, res_handle);
|
2019-08-17 18:40:08 -03:00
|
|
|
}
|
2019-07-30 17:55:20 -03:00
|
|
|
*r_face_offset = initial_offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Unlike faces, only draw edges if edge select mode. */
|
|
|
|
|
if (select_mode & SCE_SELECT_EDGE) {
|
2024-12-02 23:20:29 +01:00
|
|
|
gpu::Batch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(mesh);
|
|
|
|
|
inst.select_edge->push_constant("offset", int(*r_face_offset));
|
|
|
|
|
inst.select_edge->draw(geom_edges, res_handle);
|
2024-04-16 10:21:18 -03:00
|
|
|
*r_edge_offset = *r_face_offset + em->bm->totedge;
|
2019-07-30 17:55:20 -03:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Note that `r_vert_offset` is calculated from `r_edge_offset`.
|
2023-02-12 14:37:16 +11:00
|
|
|
* Otherwise the first vertex is never selected, see: #53512. */
|
2019-07-30 17:55:20 -03:00
|
|
|
*r_edge_offset = *r_face_offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Unlike faces, only verts if vert select mode. */
|
|
|
|
|
if (select_mode & SCE_SELECT_VERTEX) {
|
2024-12-02 23:20:29 +01:00
|
|
|
gpu::Batch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(mesh);
|
|
|
|
|
inst.select_vert->push_constant("offset", int(*r_edge_offset));
|
|
|
|
|
inst.select_vert->draw(geom_verts, res_handle);
|
2024-04-16 10:21:18 -03:00
|
|
|
*r_vert_offset = *r_edge_offset + em->bm->totvert;
|
2019-07-30 17:55:20 -03:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*r_vert_offset = *r_edge_offset;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-02 23:20:29 +01:00
|
|
|
static void draw_select_id_mesh(SELECTID_Instance &inst,
|
2019-07-30 18:26:35 -03:00
|
|
|
Object *ob,
|
2024-12-02 23:20:29 +01:00
|
|
|
ResourceHandle res_handle,
|
2019-07-30 18:26:35 -03:00
|
|
|
short select_mode,
|
|
|
|
|
uint initial_offset,
|
|
|
|
|
uint *r_vert_offset,
|
|
|
|
|
uint *r_edge_offset,
|
|
|
|
|
uint *r_face_offset)
|
2019-07-30 17:55:20 -03:00
|
|
|
{
|
2024-01-05 12:20:30 -05:00
|
|
|
using namespace blender::draw;
|
2024-12-02 23:20:29 +01:00
|
|
|
using namespace blender;
|
2024-05-21 09:09:02 -04:00
|
|
|
Mesh &mesh = *static_cast<Mesh *>(ob->data);
|
2019-07-30 17:55:20 -03:00
|
|
|
|
2024-12-02 23:20:29 +01:00
|
|
|
gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(mesh);
|
2019-07-30 18:26:35 -03:00
|
|
|
if (select_mode & SCE_SELECT_FACE) {
|
2024-12-02 23:20:29 +01:00
|
|
|
inst.select_face_flat->push_constant("offset", int(initial_offset));
|
|
|
|
|
inst.select_face_flat->draw(geom_faces, res_handle);
|
2024-05-21 09:09:02 -04:00
|
|
|
*r_face_offset = initial_offset + mesh.faces_num;
|
2019-07-30 18:26:35 -03:00
|
|
|
}
|
|
|
|
|
else {
|
2019-07-30 17:55:20 -03:00
|
|
|
/* Only draw faces to mask out verts, we don't want their selection ID's. */
|
2024-12-02 23:20:29 +01:00
|
|
|
inst.select_face_uniform->draw(geom_faces, res_handle);
|
2019-07-30 18:26:35 -03:00
|
|
|
*r_face_offset = initial_offset;
|
|
|
|
|
}
|
2019-07-30 17:55:20 -03:00
|
|
|
|
2019-07-30 18:26:35 -03:00
|
|
|
if (select_mode & SCE_SELECT_EDGE) {
|
2024-12-02 23:20:29 +01:00
|
|
|
gpu::Batch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(mesh);
|
|
|
|
|
inst.select_edge->push_constant("offset", int(*r_face_offset));
|
|
|
|
|
inst.select_edge->draw(geom_edges, res_handle);
|
2024-05-21 09:09:02 -04:00
|
|
|
*r_edge_offset = *r_face_offset + mesh.edges_num;
|
2019-07-30 17:55:20 -03:00
|
|
|
}
|
|
|
|
|
else {
|
2019-07-30 18:26:35 -03:00
|
|
|
*r_edge_offset = *r_face_offset;
|
|
|
|
|
}
|
2019-07-30 17:55:20 -03:00
|
|
|
|
2019-07-30 18:26:35 -03:00
|
|
|
if (select_mode & SCE_SELECT_VERTEX) {
|
2024-12-02 23:20:29 +01:00
|
|
|
gpu::Batch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(mesh);
|
|
|
|
|
inst.select_vert->push_constant("offset", int(*r_edge_offset));
|
|
|
|
|
inst.select_vert->draw(geom_verts, res_handle);
|
2024-05-21 09:09:02 -04:00
|
|
|
*r_vert_offset = *r_edge_offset + mesh.verts_num;
|
2019-07-30 17:55:20 -03:00
|
|
|
}
|
2019-08-06 17:26:52 -03:00
|
|
|
else {
|
|
|
|
|
*r_vert_offset = *r_edge_offset;
|
|
|
|
|
}
|
2019-07-30 17:55:20 -03:00
|
|
|
}
|
|
|
|
|
|
2024-12-02 23:20:29 +01:00
|
|
|
void select_id_draw_object(SELECTID_Instance &inst,
|
2019-07-30 17:55:20 -03:00
|
|
|
View3D *v3d,
|
|
|
|
|
Object *ob,
|
2024-12-02 23:20:29 +01:00
|
|
|
ResourceHandle res_handle,
|
2019-07-30 17:55:20 -03:00
|
|
|
short select_mode,
|
|
|
|
|
uint initial_offset,
|
|
|
|
|
uint *r_vert_offset,
|
|
|
|
|
uint *r_edge_offset,
|
|
|
|
|
uint *r_face_offset)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(initial_offset > 0);
|
|
|
|
|
|
|
|
|
|
switch (ob->type) {
|
2024-11-21 16:42:00 +01:00
|
|
|
case OB_MESH: {
|
|
|
|
|
const Mesh &mesh = *static_cast<const Mesh *>(ob->data);
|
|
|
|
|
if (mesh.runtime->edit_mesh) {
|
2023-07-27 14:16:58 +02:00
|
|
|
bool draw_facedot = check_ob_drawface_dot(select_mode, v3d, eDrawType(ob->dt));
|
2024-12-02 23:20:29 +01:00
|
|
|
draw_select_id_edit_mesh(inst,
|
2019-07-30 17:55:20 -03:00
|
|
|
ob,
|
2024-12-02 23:20:29 +01:00
|
|
|
res_handle,
|
2019-07-30 17:55:20 -03:00
|
|
|
select_mode,
|
|
|
|
|
draw_facedot,
|
|
|
|
|
initial_offset,
|
|
|
|
|
r_vert_offset,
|
|
|
|
|
r_edge_offset,
|
|
|
|
|
r_face_offset);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2024-12-02 23:20:29 +01:00
|
|
|
draw_select_id_mesh(inst,
|
|
|
|
|
ob,
|
|
|
|
|
res_handle,
|
|
|
|
|
select_mode,
|
|
|
|
|
initial_offset,
|
|
|
|
|
r_vert_offset,
|
|
|
|
|
r_edge_offset,
|
|
|
|
|
r_face_offset);
|
2019-07-30 17:55:20 -03:00
|
|
|
}
|
|
|
|
|
break;
|
2024-11-21 16:42:00 +01:00
|
|
|
}
|
2022-02-18 09:50:29 -06:00
|
|
|
case OB_CURVES_LEGACY:
|
2019-07-30 17:55:20 -03:00
|
|
|
case OB_SURF:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
#undef SELECT_ENGINE
|