Blender V4.5
select_engine.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2019 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "BKE_editmesh.hh"
12#include "BKE_mesh_types.hh"
13#include "BLI_math_matrix.h"
14
15#include "BLT_translation.hh"
16
18#include "DRW_render.hh"
19#include "ED_view3d.hh"
20
21#include "RE_engine.h"
22
23#include "DRW_engine.hh"
24#include "DRW_select_buffer.hh"
25
26#include "draw_cache_impl.hh"
27#include "draw_common_c.hh"
29#include "draw_manager.hh"
30#include "draw_pass.hh"
31#include "draw_view_data.hh"
32
34
35#include "select_engine.hh"
36
38
39#define USE_CAGE_OCCLUSION
40
41struct Instance : public DrawEngine {
42 private:
43 PassSimple depth_only_ps = {"depth_only_ps"};
44 PassSimple::Sub *depth_only = nullptr;
45 PassSimple::Sub *depth_occlude = nullptr;
46
47 PassSimple select_edge_ps = {"select_id_edge_ps"};
48 PassSimple::Sub *select_edge = nullptr;
49
50 PassSimple select_id_vert_ps = {"select_id_vert_ps"};
51 PassSimple::Sub *select_vert = nullptr;
52
53 PassSimple select_face_ps = {"select_id_face_ps"};
54 PassSimple::Sub *select_face_uniform = nullptr;
55 PassSimple::Sub *select_face_flat = nullptr;
56
57 View view_faces = {"view_faces"};
58 View view_edges = {"view_edges"};
59 View view_verts = {"view_verts"};
60
61 UniformArrayBuffer<float4, 6> clip_planes_buf;
62
63 const DRWContext *draw_ctx = nullptr;
64
65 public:
66 struct StaticData {
67 GPUFrameBuffer *framebuffer_select_id;
68 GPUTexture *texture_u32;
69
70 struct Shaders {
71 /* Depth Pre Pass */
72 GPUShader *select_id_flat;
75
77
78 static StaticData &get()
79 {
80 static StaticData data = {};
81 return data;
82 }
83 };
84
86 {
87 return "SelectID";
88 }
89
90 void init() final
91 {
92 this->draw_ctx = DRW_context_get();
93 StaticData &e_data = StaticData::get();
94 eGPUShaderConfig sh_cfg = (RV3D_CLIPPING_ENABLED(draw_ctx->v3d, draw_ctx->rv3d)) ?
97
98 StaticData::Shaders *sh_data = &e_data.sh_data[sh_cfg];
99
100 /* Prepass */
101 if (!sh_data->select_id_flat) {
103 sh_cfg == GPU_SHADER_CFG_CLIPPED ? "select_id_flat_clipped" : "select_id_flat");
104 }
105 if (!sh_data->select_id_uniform) {
107 sh_cfg == GPU_SHADER_CFG_CLIPPED ? "select_id_uniform_clipped" : "select_id_uniform");
108 }
109 }
110
112 {
113 StaticData &e_data = StaticData::get();
114 eGPUShaderConfig sh_cfg = (RV3D_CLIPPING_ENABLED(draw_ctx->v3d, draw_ctx->rv3d)) ?
117
118 StaticData::Shaders *sh = &e_data.sh_data[sh_cfg];
119
120 if (e_data.context.select_mode == -1) {
121 e_data.context.select_mode = get_object_select_mode(draw_ctx->scene, draw_ctx->obact);
122 BLI_assert(e_data.context.select_mode != 0);
123 }
124
126 if (RV3D_CLIPPING_ENABLED(draw_ctx->v3d, draw_ctx->rv3d)) {
128 }
129
130 bool retopology_occlusion = RETOPOLOGY_ENABLED(draw_ctx->v3d) && !XRAY_ENABLED(draw_ctx->v3d);
131 float retopology_offset = RETOPOLOGY_OFFSET(draw_ctx->v3d);
132
133 for (int i : IndexRange(6)) {
134 clip_planes_buf[i] = float4(0);
135 }
136
137 /* Note there might be less than 6 planes, but we always compute the 6 of them for simplicity.
138 */
139 int clipping_plane_count = RV3D_CLIPPING_ENABLED(draw_ctx->v3d, draw_ctx->rv3d) ? 6 : 0;
140 int plane_len = min((RV3D_LOCK_FLAGS(draw_ctx->rv3d) & RV3D_BOXCLIP) ? 4 : 6,
141 clipping_plane_count);
142
143 for (auto i : IndexRange(plane_len)) {
144 clip_planes_buf[i] = draw_ctx->rv3d->clip[i];
145 }
146
147 clip_planes_buf.push_update();
148
149 {
150 depth_only_ps.init();
151 depth_only_ps.state_set(state, clipping_plane_count);
152 depth_only_ps.bind_ubo(DRW_CLIPPING_UBO_SLOT, clip_planes_buf);
153 depth_only = nullptr;
154 depth_occlude = nullptr;
155 {
156 auto &sub = depth_only_ps.sub("DepthOnly");
157 sub.shader_set(sh->select_id_uniform);
158 sub.push_constant("retopology_offset", retopology_offset);
159 sub.push_constant("select_id", 0);
160 depth_only = &sub;
161 }
162 if (retopology_occlusion) {
163 auto &sub = depth_only_ps.sub("Occlusion");
164 sub.shader_set(sh->select_id_uniform);
165 sub.push_constant("retopology_offset", 0.0f);
166 sub.push_constant("select_id", 0);
167 depth_occlude = &sub;
168 }
169
170 select_face_ps.init();
171 select_face_ps.state_set(state, clipping_plane_count);
172 select_face_ps.bind_ubo(DRW_CLIPPING_UBO_SLOT, clip_planes_buf);
173 select_face_uniform = nullptr;
174 select_face_flat = nullptr;
175 if (e_data.context.select_mode & SCE_SELECT_FACE) {
176 auto &sub = select_face_ps.sub("Face");
177 const float vertex_size = U.pixelsize *
179 sub.shader_set(sh->select_id_flat);
180 sub.push_constant("vertex_size", float(2 * vertex_size));
181 sub.push_constant("retopology_offset", retopology_offset);
182 select_face_flat = &sub;
183 }
184 else {
185 auto &sub = select_face_ps.sub("FaceNoSelect");
186 sub.shader_set(sh->select_id_uniform);
187 sub.push_constant("select_id", 0);
188 sub.push_constant("retopology_offset", retopology_offset);
189 select_face_uniform = &sub;
190 }
191
192 select_edge_ps.init();
193 select_edge_ps.bind_ubo(DRW_CLIPPING_UBO_SLOT, clip_planes_buf);
194 select_edge = nullptr;
195 if (e_data.context.select_mode & SCE_SELECT_EDGE) {
196 auto &sub = select_edge_ps.sub("Sub");
197 sub.state_set(state | DRW_STATE_FIRST_VERTEX_CONVENTION, clipping_plane_count);
198 sub.shader_set(sh->select_id_flat);
199 sub.push_constant("retopology_offset", retopology_offset);
200 select_edge = &sub;
201 }
202
203 select_id_vert_ps.init();
204 select_id_vert_ps.bind_ubo(DRW_CLIPPING_UBO_SLOT, clip_planes_buf);
205 select_vert = nullptr;
207 const float vertex_size = U.pixelsize *
209 auto &sub = select_id_vert_ps.sub("Sub");
210 sub.state_set(state, clipping_plane_count);
211 sub.shader_set(sh->select_id_flat);
212 sub.push_constant("vertex_size", float(2 * vertex_size));
213 sub.push_constant("retopology_offset", retopology_offset);
214 select_vert = &sub;
215 }
216 }
217
218 e_data.context.elem_ranges.clear();
219
220 e_data.context.persmat = float4x4(draw_ctx->rv3d->persmat);
221 e_data.context.max_index_drawn_len = 1;
222 framebuffer_setup();
225 }
226
228 BMEditMesh *em,
229 ResourceHandle res_handle,
230 short select_mode,
231 bool draw_facedot,
232 const uint initial_index)
233 {
234 using namespace blender::draw;
235 using namespace blender;
237
238 ElemIndexRanges ranges{};
239 ranges.total = IndexRange::from_begin_size(initial_index, 0);
240
242
243 if (select_mode & SCE_SELECT_FACE) {
244 ranges.face = alloc_range(ranges.total, em->bm->totface);
245
246 gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(mesh);
247 PassSimple::Sub *face_sub = select_face_flat;
248 face_sub->push_constant("offset", int(ranges.face.start()));
249 face_sub->draw(geom_faces, res_handle);
250
251 if (draw_facedot) {
252 gpu::Batch *geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(mesh);
253 face_sub->draw(geom_facedots, res_handle);
254 }
255 }
256 else {
257 if (ob->dt >= OB_SOLID) {
258#ifdef USE_CAGE_OCCLUSION
259 gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(mesh);
260#else
261 gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_surface(mesh);
262#endif
263 select_face_uniform->draw(geom_faces, res_handle);
264 }
265 }
266
267 /* Unlike faces, only draw edges if edge select mode. */
268 if (select_mode & SCE_SELECT_EDGE) {
269 ranges.edge = alloc_range(ranges.total, em->bm->totedge);
270
271 gpu::Batch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(mesh);
272 select_edge->push_constant("offset", int(ranges.edge.start()));
273 select_edge->draw(geom_edges, res_handle);
274 }
275
276 /* Unlike faces, only verts if vert select mode. */
277 if (select_mode & SCE_SELECT_VERTEX) {
278 ranges.vert = alloc_range(ranges.total, em->bm->totvert);
279
280 gpu::Batch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(mesh);
281 select_vert->push_constant("offset", int(ranges.vert.start()));
282 select_vert->draw(geom_verts, res_handle);
283 }
284 return ranges;
285 }
286
288 ResourceHandle res_handle,
289 short select_mode,
290 const uint initial_index)
291 {
292 using namespace blender::draw;
293 using namespace blender;
295
296 ElemIndexRanges ranges{};
297 ranges.total = IndexRange::from_begin_size(initial_index, 0);
298
299 gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(mesh);
300 if (select_mode & SCE_SELECT_FACE) {
301 ranges.face = alloc_range(ranges.total, mesh.faces_num);
302
303 select_face_flat->push_constant("offset", int(ranges.face.start()));
304 select_face_flat->draw(geom_faces, res_handle);
305 }
306 else {
307 /* Only draw faces to mask out verts, we don't want their selection ID's. */
308 select_face_uniform->draw(geom_faces, res_handle);
309 }
310
311 if (select_mode & SCE_SELECT_EDGE) {
312 ranges.edge = alloc_range(ranges.total, mesh.edges_num);
313
314 gpu::Batch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(mesh);
315 select_edge->push_constant("offset", int(ranges.edge.start()));
316 select_edge->draw(geom_edges, res_handle);
317 }
318
319 if (select_mode & SCE_SELECT_VERTEX) {
320 ranges.vert = alloc_range(ranges.total, mesh.verts_num);
321
322 gpu::Batch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(mesh);
323 select_vert->push_constant("offset", int(ranges.vert.start()));
324 select_vert->draw(geom_verts, res_handle);
325 }
326
327 return ranges;
328 }
329
331 View3D *v3d, Object *ob, ResourceHandle res_handle, short select_mode, uint index_start)
332 {
333 BLI_assert_msg(index_start > 0, "Index 0 is reserved for no selection");
334
335 switch (ob->type) {
336 case OB_MESH: {
337 const bool is_editmode = ob->mode == OB_MODE_EDIT;
338 /* NOTE: it's important to get the edit-mesh before modifiers have been applied
339 * because the evaluated mesh may not have an edit-mesh, see #138715.
340 * Match edit-mesh access from #mesh_render_data_create. */
341 const Mesh *orig_edit_mesh = is_editmode ? BKE_object_get_pre_modified_mesh(ob) : nullptr;
342 BMEditMesh *em = (orig_edit_mesh) ? orig_edit_mesh->runtime->edit_mesh.get() : nullptr;
343
344 if (em) {
345 bool draw_facedot = check_ob_drawface_dot(select_mode, v3d, eDrawType(ob->dt));
346 return edit_mesh_sync(ob, em, res_handle, select_mode, draw_facedot, index_start);
347 }
348 return mesh_sync(ob, res_handle, select_mode, index_start);
349 }
350 case OB_CURVES_LEGACY:
351 case OB_SURF:
352 break;
353 }
355 return ElemIndexRanges{};
356 }
357
358 void object_sync(ObjectRef &ob_ref, Manager &manager) final
359 {
360 Object *ob = ob_ref.object;
361 StaticData &e_data = StaticData::get();
362 SELECTID_Context &sel_ctx = e_data.context;
363
364 if (!sel_ctx.objects.contains(ob)) {
365 if (ob->dt >= OB_SOLID) {
366 /* This object is not selectable. It is here to participate in occlusion.
367 * This is the case in retopology mode. */
368 blender::gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_surface(
370
371 depth_occlude->draw(geom_faces, manager.resource_handle(ob_ref));
372 }
373 return;
374 }
375
376 /* Only sync selectable object once.
377 * This can happen in retopology mode where there is two sync loop. */
378 sel_ctx.elem_ranges.lookup_or_add_cb(ob, [&]() {
379 ResourceHandle res_handle = manager.resource_handle(ob_ref);
380 ElemIndexRanges elem_ranges = object_sync(
381 draw_ctx->v3d, ob, res_handle, sel_ctx.select_mode, sel_ctx.max_index_drawn_len);
382 sel_ctx.max_index_drawn_len = elem_ranges.total.one_after_last();
383 return elem_ranges;
384 });
385 }
386
387 void end_sync() final {}
388
389 void draw(Manager &manager) final
390 {
391 StaticData &e_data = StaticData::get();
392
394 {
395 View::OffsetData offset_data(*draw_ctx->rv3d);
396 /* Create view with depth offset */
397 const View &view = View::default_get();
398 view_faces.sync(view.viewmat(), view.winmat());
399 view_edges.sync(view.viewmat(), offset_data.winmat_polygon_offset(view.winmat(), 1.0f));
400 view_verts.sync(view.viewmat(), offset_data.winmat_polygon_offset(view.winmat(), 1.1f));
401 }
402
403 {
404 DefaultFramebufferList *dfbl = draw_ctx->viewport_framebuffer_list_get();
407 manager.submit(depth_only_ps, view_faces);
408 }
409
410 /* Setup framebuffer */
412
413 manager.submit(select_face_ps, view_faces);
414
415 if (e_data.context.select_mode & SCE_SELECT_EDGE) {
416 manager.submit(select_edge_ps, view_edges);
417 }
418
420 manager.submit(select_id_vert_ps, view_verts);
421 }
423 }
424
425 private:
426 void framebuffer_setup()
427 {
428 StaticData &e_data = StaticData::get();
430 int size[2];
431 size[0] = GPU_texture_width(dtxl->depth);
432 size[1] = GPU_texture_height(dtxl->depth);
433
434 if (e_data.framebuffer_select_id == nullptr) {
435 e_data.framebuffer_select_id = GPU_framebuffer_create("framebuffer_select_id");
436 }
437
438 if ((e_data.texture_u32 != nullptr) && ((GPU_texture_width(e_data.texture_u32) != size[0]) ||
439 (GPU_texture_height(e_data.texture_u32) != size[1])))
440 {
441 GPU_texture_free(e_data.texture_u32);
442 e_data.texture_u32 = nullptr;
443 }
444
445 /* Make sure the depth texture is attached.
446 * It may disappear when loading another Blender session. */
447 GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, dtxl->depth, 0, 0);
448
449 if (e_data.texture_u32 == nullptr) {
451 e_data.texture_u32 = GPU_texture_create_2d(
452 "select_buf_ids", size[0], size[1], 1, GPU_R32UI, usage, nullptr);
453 GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, e_data.texture_u32, 0, 0);
454
455 GPU_framebuffer_check_valid(e_data.framebuffer_select_id, nullptr);
456 }
457 }
458
459 short get_object_select_mode(Scene *scene, Object *ob)
460 {
461 short r_select_mode = 0;
463 /* In order to sample flat colors for vertex weights / texture-paint / vertex-paint
464 * we need to be in SCE_SELECT_FACE mode so select_cache_init() correctly sets up
465 * a shgroup with select_id_flat.
466 * Note this is not working correctly for vertex-paint (yet), but has been discussed
467 * in #66645 and there is a solution by @mano-wii in P1032.
468 * So OB_MODE_VERTEX_PAINT is already included here [required for P1032 I guess]. */
469 Mesh *me_orig = static_cast<Mesh *>(DEG_get_original(ob)->data);
470 if (me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) {
471 r_select_mode = SCE_SELECT_VERTEX;
472 }
473 else {
474 r_select_mode = SCE_SELECT_FACE;
475 }
476 }
477 else {
478 r_select_mode = scene->toolsettings->selectmode;
479 }
480
481 return r_select_mode;
482 }
483
484 bool check_ob_drawface_dot(short select_mode, const View3D *v3d, eDrawType dt)
485 {
486 if (select_mode & SCE_SELECT_FACE) {
487 if ((dt < OB_SOLID) || XRAY_FLAG_ENABLED(v3d)) {
488 return true;
489 }
491 return true;
492 }
493 }
494 return false;
495 }
496
497 /* Return a new range if size `n` after `total_range` and grow `total_range` by the same amount.
498 */
499 IndexRange alloc_range(IndexRange &total_range, uint size)
500 {
501 const IndexRange indices = total_range.after(size);
502 total_range = IndexRange::from_begin_size(total_range.start(), total_range.size() + size);
503 return indices;
504 }
505};
506
508{
509 return new Instance();
510}
511
513{
515 for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) {
516 Instance::StaticData::Shaders *sh_data = &e_data.sh_data[sh_data_index];
519 }
520
523}
524
525} // namespace blender::draw::edit_select
526
528
529/* -------------------------------------------------------------------- */
532
533using namespace blender::draw::edit_select;
534
540
546
548{
550 return e_data.texture_u32;
551}
552
const Mesh * BKE_object_get_pre_modified_mesh(const Object *object)
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define final(a, b, c)
Definition BLI_hash.h:19
unsigned int uint
#define ARRAY_SIZE(arr)
T * DEG_get_original(T *id)
struct Mesh Mesh
@ ME_EDIT_PAINT_VERT_SEL
eDrawType
@ OB_SOLID
@ OB_MODE_EDIT
@ OB_MODE_WEIGHT_PAINT
@ OB_MODE_TEXTURE_PAINT
@ OB_MODE_VERTEX_PAINT
@ OB_SURF
@ OB_MESH
@ OB_CURVES_LEGACY
struct Object Object
struct Scene Scene
@ SCE_SELECT_FACE
@ SCE_SELECT_VERTEX
@ SCE_SELECT_EDGE
@ RV3D_BOXCLIP
#define RV3D_LOCK_FLAGS(rv3d)
@ V3D_OVERLAY_EDIT_FACE_DOT
#define RV3D_CLIPPING_ENABLED(v3d, rv3d)
struct View3D View3D
void DRW_submission_end()
void DRW_submission_start()
#define XRAY_ENABLED(v3d)
#define RETOPOLOGY_ENABLED(v3d)
#define RETOPOLOGY_OFFSET(v3d)
#define XRAY_FLAG_ENABLED(v3d)
static AppView * view
GPUFrameBuffer * GPU_framebuffer_create(const char *name)
#define GPU_FRAMEBUFFER_FREE_SAFE(fb)
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
void GPU_framebuffer_clear_color_depth(GPUFrameBuffer *fb, const float clear_col[4], float clear_depth)
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
void GPU_framebuffer_clear_depth(GPUFrameBuffer *fb, float clear_depth)
void GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *texture, int slot, int mip)
#define GPU_SHADER_FREE_SAFE(shader)
GPUShader * GPU_shader_create_from_info_name(const char *info_name)
@ GPU_SHADER_CFG_DEFAULT
@ GPU_SHADER_CFG_CLIPPED
#define GPU_SHADER_CFG_LEN
int GPU_texture_height(const GPUTexture *texture)
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(GPUTexture *texture)
int GPU_texture_width(const GPUTexture *texture)
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
#define GPU_TEXTURE_FREE_SAFE(texture)
@ GPU_R32UI
#define U
BMesh const char void * data
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
#define BM_FACE
#define BM_EDGE
#define BM_VERT
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr int64_t size() const
constexpr IndexRange after(int64_t n) const
constexpr int64_t start() const
void clear()
Definition BLI_map.hh:1038
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
Definition BLI_map.hh:620
bool contains(const T &value) const
constexpr int64_t one_after_last() const
static constexpr IndexRange from_begin_size(const int64_t begin, const int64_t size)
constexpr int64_t start() const
static View & default_get()
Definition draw_view.cc:317
void draw(gpu::Batch *batch, uint instance_len=-1, uint vertex_len=-1, uint vertex_first=-1, ResourceHandleRange handle={0}, uint custom_id=0)
Definition draw_pass.hh:884
void push_constant(const char *name, const float &data)
detail::PassBase< command::DrawCommandBuf > Sub
Definition draw_pass.hh:490
const DRWContext * DRW_context_get()
Mesh & DRW_object_get_data_for_drawing(const Object &object)
#define DRW_CLIPPING_UBO_SLOT
DRWState
Definition draw_state.hh:25
@ DRW_STATE_CLIP_PLANES
Definition draw_state.hh:71
@ DRW_STATE_FIRST_VERTEX_CONVENTION
Definition draw_state.hh:72
#define DRW_STATE_DEFAULT
Definition draw_state.hh:79
static ushort indices[]
static ulong state[N]
blender::gpu::Batch * DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh &mesh)
detail::Pass< command::DrawCommandBuf > PassSimple
blender::gpu::Batch * DRW_mesh_batch_cache_get_surface(Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_triangles_with_select_id(Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_verts_with_select_id(Mesh &mesh)
blender::gpu::Batch * DRW_mesh_batch_cache_get_edges_with_select_id(Mesh &mesh)
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
SELECTID_Context * DRW_select_engine_context_get()
GPUFrameBuffer * DRW_engine_select_framebuffer_get()
GPUTexture * DRW_engine_select_texture_get()
#define min(a, b)
Definition sort.cc:36
int totvert
int totedge
int totface
DefaultTextureList * viewport_texture_list_get() const
GPUFrameBuffer * depth_only_fb
blender::IndexRange face
blender::IndexRange total
blender::IndexRange vert
blender::IndexRange edge
int edges_num
MeshRuntimeHandle * runtime
char editflag
int faces_num
int verts_num
blender::Map< Object *, ElemIndexRanges > elem_ranges
blender::Vector< Object * > objects
blender::float4x4 persmat
struct ToolSettings * toolsettings
View3DOverlay overlay
float4x4 winmat_polygon_offset(float4x4 winmat, float offset)
Definition draw_view.hh:197
struct blender::draw::edit_select::Instance::StaticData::Shaders sh_data[GPU_SHADER_CFG_LEN]
blender::StringRefNull name_get() final
void object_sync(ObjectRef &ob_ref, Manager &manager) final
ElemIndexRanges edit_mesh_sync(Object *ob, BMEditMesh *em, ResourceHandle res_handle, short select_mode, bool draw_facedot, const uint initial_index)
void draw(Manager &manager) final
ElemIndexRanges mesh_sync(Object *ob, ResourceHandle res_handle, short select_mode, const uint initial_index)
ElemIndexRanges object_sync(View3D *v3d, Object *ob, ResourceHandle res_handle, short select_mode, uint index_start)
i
Definition text_draw.cc:230