Blender V5.0
overlay_armature.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#pragma once
10
11#include "DNA_userdef_types.h"
12
13#include "ED_view3d.hh"
14
15#include "DRW_render.hh"
16
17#include "overlay_base.hh"
19
20namespace blender::draw::overlay {
21using namespace blender;
22
28
34 using EmptyInstanceBuf = ShapeInstanceBuf<ExtraInstanceData>;
35 using BoneInstanceBuf = ShapeInstanceBuf<BoneInstanceData>;
36 using BoneEnvelopeBuf = ShapeInstanceBuf<BoneEnvelopeData>;
37 using BoneStickBuf = ShapeInstanceBuf<BoneStickData>;
38 using DegreesOfFreedomBuf = ShapeInstanceBuf<ExtraInstanceData>;
39
40 private:
41 const SelectionType selection_type_;
42
43 PassSimple armature_ps_ = {"Armature"};
44
45 /* Force transparent drawing in X-ray mode. */
46 bool draw_transparent = false;
47 /* Force disable drawing relation is relations are off in viewport. */
48 bool show_relations = false;
49 /* Show selection state. */
50 bool show_outline = false;
51
52 struct BoneBuffers {
53 const SelectionType selection_type_;
54
55 /* Bone end points (joints). */
56 PassSimple::Sub *sphere_fill = nullptr;
57 PassSimple::Sub *sphere_outline = nullptr;
58 /* Bone shapes. */
59 PassSimple::Sub *shape_fill = nullptr;
60 PassSimple::Sub *shape_outline = nullptr;
61 /* Custom bone wire-frame. */
62 PassSimple::Sub *shape_wire = nullptr;
63 PassSimple::Sub *shape_wire_strip = nullptr;
64 /* Envelopes. */
65 PassSimple::Sub *envelope_fill = nullptr;
66 PassSimple::Sub *envelope_outline = nullptr;
67 PassSimple::Sub *envelope_distance = nullptr;
68 /* Stick bones. */
69 PassSimple::Sub *stick = nullptr;
70 /* Wire bones. */
71 PassSimple::Sub *wire = nullptr;
72
73 /* Bone axes. */
74 PassSimple::Sub *arrows = nullptr;
75 /* Degrees of freedom. */
76 PassSimple::Sub *degrees_of_freedom_fill = nullptr;
77 PassSimple::Sub *degrees_of_freedom_wire = nullptr;
78 /* Relations. */
79 PassSimple::Sub *relations = nullptr;
80
81 BoneInstanceBuf bbones_fill_buf = {selection_type_, "bbones_fill_buf"};
82 BoneInstanceBuf bbones_outline_buf = {selection_type_, "bbones_outline_buf"};
83
84 BoneInstanceBuf octahedral_fill_buf = {selection_type_, "octahedral_fill_buf"};
85 BoneInstanceBuf octahedral_outline_buf = {selection_type_, "octahedral_outline_buf"};
86
87 BoneInstanceBuf sphere_fill_buf = {selection_type_, "sphere_fill_buf"};
88 BoneInstanceBuf sphere_outline_buf = {selection_type_, "sphere_outline_buf"};
89
90 BoneEnvelopeBuf envelope_fill_buf = {selection_type_, "envelope_fill_buf"};
91 BoneEnvelopeBuf envelope_outline_buf = {selection_type_, "envelope_outline_buf"};
92 BoneEnvelopeBuf envelope_distance_buf = {selection_type_, "envelope_distance_buf"};
93
94 BoneStickBuf stick_buf = {selection_type_, "stick_buf"};
95
96 LinePrimitiveBuf wire_buf = {selection_type_, "wire_buf"};
97
98 EmptyInstanceBuf arrows_buf = {selection_type_, "arrows_buf"};
99
100 DegreesOfFreedomBuf degrees_of_freedom_fill_buf = {SelectionType::DISABLED,
101 "degrees_of_freedom_buf"};
102 DegreesOfFreedomBuf degrees_of_freedom_wire_buf = {SelectionType::DISABLED,
103 "degrees_of_freedom_buf"};
104
105 LinePrimitiveBuf relations_buf = {SelectionType::DISABLED, "relations_buf"};
106
111
112 BoneInstanceBuf &custom_shape_fill_get_buffer(gpu::Batch *geom)
113 {
114 return *custom_shape_fill.lookup_or_add_cb(geom, [this]() {
115 return std::make_unique<BoneInstanceBuf>(this->selection_type_, "CustomBoneSolid");
116 });
117 }
118
119 BoneInstanceBuf &custom_shape_outline_get_buffer(gpu::Batch *geom)
120 {
121 return *custom_shape_outline.lookup_or_add_cb(geom, [this]() {
122 return std::make_unique<BoneInstanceBuf>(this->selection_type_, "CustomBoneOutline");
123 });
124 }
125
126 BoneInstanceBuf &custom_shape_wire_get_buffer(gpu::Batch *geom)
127 {
128 if (geom->prim_type == GPU_PRIM_LINE_STRIP) {
129 return *custom_shape_wire_strip.lookup_or_add_cb(geom, [this]() {
130 return std::make_unique<BoneInstanceBuf>(this->selection_type_, "CustomBoneWireStrip");
131 });
132 }
133 return *custom_shape_wire.lookup_or_add_cb(geom, [this]() {
134 return std::make_unique<BoneInstanceBuf>(this->selection_type_, "CustomBoneWire");
135 });
136 }
137
138 BoneBuffers(const SelectionType selection_type) : selection_type_(selection_type) {};
139 };
140
141 BoneBuffers opaque_ = {selection_type_};
142 BoneBuffers transparent_ = {selection_type_};
143
144 public:
145 Armatures(const SelectionType selection_type) : selection_type_(selection_type) {};
146
147 void begin_sync(Resources &res, const State &state) final
148 {
149 enabled_ = state.is_space_v3d() && state.show_bones();
150
151 if (!enabled_) {
152 return;
153 }
154
155 draw_transparent = (state.v3d->shading.type == OB_WIRE) || XRAY_FLAG_ENABLED(state.v3d);
156 show_relations = !((state.v3d->flag & V3D_HIDE_HELPLINES) || res.is_selection());
157 show_outline = (state.v3d->flag & V3D_SELECT_OUTLINE);
158
159 const bool do_smooth_wire = U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE;
160 const float wire_alpha = state.ctx_mode == CTX_MODE_PAINT_WEIGHT ?
161 state.overlay.bone_wire_alpha :
162 1.0f;
163 /* Draw bone outlines and custom shape wire with a specific alpha. */
164 const bool use_wire_alpha = (wire_alpha < 1.0f);
165
166 gpu::Texture **depth_tex = (state.xray_enabled) ? &res.depth_tx : &res.dummy_depth_tx;
167
168 armature_ps_.init();
169 armature_ps_.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
170 armature_ps_.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
171 res.select_bind(armature_ps_);
172
173 /* Envelope distances and degrees of freedom need to be drawn first as they use additive
174 * transparent blending. */
175 {
178 {
179 auto &sub = armature_ps_.sub("opaque.envelope_distance");
180 sub.state_set(transparent_state | DRW_STATE_CULL_FRONT, state.clipping_plane_count);
181 sub.shader_set(res.shaders->armature_envelope_fill.get());
182 sub.push_constant("alpha", 1.0f);
183 sub.push_constant("is_distance", true);
184 opaque_.envelope_distance = &sub;
185 }
186 if (use_wire_alpha) {
187 auto &sub = armature_ps_.sub("transparent.envelope_distance");
188 sub.state_set(transparent_state | DRW_STATE_CULL_FRONT, state.clipping_plane_count);
189 sub.shader_set(res.shaders->armature_envelope_fill.get());
190 sub.push_constant("alpha", wire_alpha);
191 sub.push_constant("is_distance", true);
192 transparent_.envelope_distance = &sub;
193 }
194 else {
195 transparent_.envelope_distance = opaque_.envelope_distance;
196 }
197
198 {
199 auto &sub = armature_ps_.sub("opaque.degrees_of_freedom_fill");
200 sub.state_set(transparent_state, state.clipping_plane_count);
201 sub.shader_set(res.shaders->armature_degrees_of_freedom.get());
202 sub.push_constant("alpha", 1.0f);
203 opaque_.degrees_of_freedom_fill = &sub;
204 }
205 if (use_wire_alpha) {
206 auto &sub = armature_ps_.sub("transparent.degrees_of_freedom_fill");
207 sub.state_set(transparent_state, state.clipping_plane_count);
208 sub.shader_set(res.shaders->armature_degrees_of_freedom.get());
209 sub.push_constant("alpha", wire_alpha);
210 transparent_.degrees_of_freedom_fill = &sub;
211 }
212 else {
213 transparent_.degrees_of_freedom_fill = opaque_.degrees_of_freedom_fill;
214 }
215 }
216
219
220 /* Bone Shapes (Octahedral, Box, Custom Shapes, Spheres). */
221 {
222 {
223 auto &sub = armature_ps_.sub("opaque.sphere_fill");
224 sub.state_set(default_state, state.clipping_plane_count);
225 sub.shader_set(res.shaders->armature_sphere_fill.get());
226 sub.push_constant("alpha", 1.0f);
227 opaque_.sphere_fill = &sub;
228 }
229 {
230 auto &sub = armature_ps_.sub("transparent.sphere_fill");
231 sub.state_set((default_state & ~DRW_STATE_WRITE_DEPTH) | DRW_STATE_BLEND_ALPHA,
232 state.clipping_plane_count);
233 sub.shader_set(res.shaders->armature_sphere_fill.get());
234 sub.push_constant("alpha", wire_alpha * 0.4f);
235 transparent_.sphere_fill = &sub;
236 }
237
238 {
239 auto &sub = armature_ps_.sub("opaque.shape_fill");
240 sub.state_set(default_state, state.clipping_plane_count);
241 sub.shader_set(res.shaders->armature_shape_fill.get());
242 sub.push_constant("alpha", 1.0f);
243 opaque_.shape_fill = &sub;
244 }
245 {
246 auto &sub = armature_ps_.sub("transparent.shape_fill");
247 sub.state_set((default_state & ~DRW_STATE_WRITE_DEPTH) | DRW_STATE_BLEND_ALPHA,
248 state.clipping_plane_count);
249 sub.shader_set(res.shaders->armature_shape_fill.get());
250 sub.push_constant("alpha", wire_alpha * 0.6f);
251 transparent_.shape_fill = &sub;
252 }
253
254 {
255 auto &sub = armature_ps_.sub("opaque.sphere_outline");
256 sub.state_set(default_state, state.clipping_plane_count);
257 sub.shader_set(res.shaders->armature_sphere_outline.get());
258 sub.push_constant("alpha", 1.0f);
259 opaque_.sphere_outline = &sub;
260 }
261 if (use_wire_alpha) {
262 auto &sub = armature_ps_.sub("transparent.sphere_outline");
263 sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
264 sub.shader_set(res.shaders->armature_sphere_outline.get());
265 sub.push_constant("alpha", wire_alpha);
266 transparent_.sphere_outline = &sub;
267 }
268 else {
269 transparent_.sphere_outline = opaque_.sphere_outline;
270 }
271
272 {
273 auto &sub = armature_ps_.sub("opaque.shape_outline");
274 sub.state_set(default_state, state.clipping_plane_count);
275 sub.shader_set(res.shaders->armature_shape_outline.get());
276 sub.push_constant("alpha", 1.0f);
277 opaque_.shape_outline = &sub;
278 }
279 if (use_wire_alpha) {
280 auto &sub = armature_ps_.sub("transparent.shape_outline");
281 sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
282 sub.shader_set(res.shaders->armature_shape_outline.get());
283 sub.bind_texture("depth_tx", depth_tex);
284 sub.push_constant("alpha", wire_alpha * 0.6f);
285 sub.push_constant("do_smooth_wire", do_smooth_wire);
286 transparent_.shape_outline = &sub;
287 }
288 else {
289 transparent_.shape_outline = opaque_.shape_outline;
290 }
291
292 {
293 auto &sub = armature_ps_.sub("opaque.shape_wire");
294 sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
295 sub.shader_set(res.shaders->armature_shape_wire.get());
296 sub.push_constant("alpha", 1.0f);
297 sub.push_constant("do_smooth_wire", do_smooth_wire);
298 sub.push_constant("use_arrow_drawing", false);
299 opaque_.shape_wire = &sub;
300 }
301 if (use_wire_alpha) {
302 auto &sub = armature_ps_.sub("transparent.shape_wire");
303 sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
304 sub.shader_set(res.shaders->armature_shape_wire.get());
305 sub.bind_texture("depth_tx", depth_tex);
306 sub.push_constant("alpha", wire_alpha * 0.6f);
307 sub.push_constant("do_smooth_wire", do_smooth_wire);
308 sub.push_constant("use_arrow_drawing", false);
309 transparent_.shape_wire = &sub;
310 }
311 else {
312 transparent_.shape_wire = opaque_.shape_wire;
313 }
314
315 {
316 auto &sub = armature_ps_.sub("opaque.shape_wire_strip");
317 sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
318 sub.shader_set(res.shaders->armature_shape_wire_strip.get());
319 sub.push_constant("alpha", 1.0f);
320 sub.push_constant("do_smooth_wire", do_smooth_wire);
321 sub.push_constant("use_arrow_drawing", false);
322 opaque_.shape_wire_strip = &sub;
323 }
324 if (use_wire_alpha) {
325 auto &sub = armature_ps_.sub("transparent.shape_wire_strip");
326 sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
327 sub.shader_set(res.shaders->armature_shape_wire_strip.get());
328 sub.bind_texture("depth_tx", depth_tex);
329 sub.push_constant("alpha", wire_alpha * 0.6f);
330 sub.push_constant("do_smooth_wire", do_smooth_wire);
331 sub.push_constant("use_arrow_drawing", false);
332 transparent_.shape_wire_strip = &sub;
333 }
334 else {
335 transparent_.shape_wire_strip = opaque_.shape_wire_strip;
336 }
337 }
338 /* Degrees of freedom. */
339 {
340 {
341 auto &sub = armature_ps_.sub("opaque.degrees_of_freedom_wire");
342 sub.shader_set(res.shaders->armature_degrees_of_freedom.get());
343 sub.push_constant("alpha", 1.0f);
344 opaque_.degrees_of_freedom_wire = &sub;
345 }
346 if (use_wire_alpha) {
347 auto &sub = armature_ps_.sub("transparent.degrees_of_freedom_wire");
348 sub.shader_set(res.shaders->armature_degrees_of_freedom.get());
349 sub.push_constant("alpha", wire_alpha);
350 transparent_.degrees_of_freedom_wire = &sub;
351 }
352 else {
353 transparent_.degrees_of_freedom_wire = opaque_.degrees_of_freedom_wire;
354 }
355 }
356 /* Stick bones. */
357 {
358 {
359 auto &sub = armature_ps_.sub("opaque.stick");
360 sub.shader_set(res.shaders->armature_stick.get());
361 sub.push_constant("alpha", 1.0f);
362 opaque_.stick = &sub;
363 }
364 if (use_wire_alpha) {
365 auto &sub = armature_ps_.sub("transparent.stick");
366 sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
367 sub.shader_set(res.shaders->armature_stick.get());
368 sub.push_constant("alpha", wire_alpha);
369 transparent_.stick = &sub;
370 }
371 else {
372 transparent_.stick = opaque_.stick;
373 }
374 }
375 /* Envelopes. */
376 {
377 {
378 auto &sub = armature_ps_.sub("opaque.envelope_fill");
379 sub.state_set(default_state | DRW_STATE_CULL_BACK, state.clipping_plane_count);
380 sub.shader_set(res.shaders->armature_envelope_fill.get());
381 sub.push_constant("is_distance", false);
382 sub.push_constant("alpha", 1.0f);
383 opaque_.envelope_fill = &sub;
384 }
385 {
386 auto &sub = armature_ps_.sub("transparent.envelope_fill");
387 sub.state_set((default_state & ~DRW_STATE_WRITE_DEPTH) |
389 state.clipping_plane_count);
390 sub.shader_set(res.shaders->armature_envelope_fill.get());
391 sub.push_constant("alpha", wire_alpha * 0.6f);
392 transparent_.envelope_fill = &sub;
393 }
394
395 {
396 auto &sub = armature_ps_.sub("opaque.envelope_outline");
397 sub.state_set(default_state | DRW_STATE_CULL_BACK, state.clipping_plane_count);
398 sub.shader_set(res.shaders->armature_envelope_outline.get());
399 sub.push_constant("alpha", 1.0f);
400 opaque_.envelope_outline = &sub;
401 }
402 if (use_wire_alpha) {
403 auto &sub = armature_ps_.sub("transparent.envelope_outline");
404 sub.state_set((default_state & ~DRW_STATE_WRITE_DEPTH) |
406 state.clipping_plane_count);
407 sub.shader_set(res.shaders->armature_envelope_outline.get());
408 sub.push_constant("alpha", wire_alpha);
409 transparent_.envelope_outline = &sub;
410 }
411 else {
412 transparent_.envelope_outline = opaque_.envelope_outline;
413 }
414 }
415 {
416 {
417 auto &sub = armature_ps_.sub("opaque.wire");
418 sub.shader_set(res.shaders->armature_wire.get());
419 sub.push_constant("alpha", 1.0f);
420 opaque_.wire = &sub;
421 }
422 if (use_wire_alpha) {
423 auto &sub = armature_ps_.sub("transparent.wire");
424 sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
425 sub.shader_set(res.shaders->armature_wire.get());
426 sub.push_constant("alpha", wire_alpha);
427 transparent_.wire = &sub;
428 }
429 else {
430 transparent_.wire = opaque_.wire;
431 }
432 }
433
434 {
435 auto &sub = armature_ps_.sub("opaque.arrow");
436 sub.shader_set(res.shaders->extra_shape.get());
437 opaque_.arrows = &sub;
438 transparent_.arrows = opaque_.arrows;
439 }
440
441 {
442 auto &sub = armature_ps_.sub("opaque.relations");
443 sub.shader_set(res.shaders->extra_wire.get());
444 opaque_.relations = &sub;
445 transparent_.relations = opaque_.relations;
446 }
447
448 auto shape_instance_bufs_begin_sync = [](BoneBuffers &bb) {
449 bb.envelope_fill_buf.clear();
450 bb.envelope_outline_buf.clear();
451 bb.envelope_distance_buf.clear();
452 bb.bbones_fill_buf.clear();
453 bb.bbones_outline_buf.clear();
454 bb.octahedral_fill_buf.clear();
455 bb.octahedral_outline_buf.clear();
456 bb.sphere_fill_buf.clear();
457 bb.sphere_outline_buf.clear();
458 bb.stick_buf.clear();
459 bb.wire_buf.clear();
460 bb.arrows_buf.clear();
461 bb.degrees_of_freedom_fill_buf.clear();
462 bb.degrees_of_freedom_wire_buf.clear();
463 bb.relations_buf.clear();
464 /* TODO(fclem): Potentially expensive operation recreating a lot of gpu buffers.
465 * Prefer a pruning strategy. */
466 bb.custom_shape_fill.clear();
467 bb.custom_shape_outline.clear();
468 bb.custom_shape_wire.clear();
469 bb.custom_shape_wire_strip.clear();
470 };
471
472 shape_instance_bufs_begin_sync(transparent_);
473 shape_instance_bufs_begin_sync(opaque_);
474 }
475
476 struct DrawContext {
477 /* Current armature object */
478 Object *ob = nullptr;
479 const ObjectRef *ob_ref = nullptr;
480
481 /* Note: can be mutated inside `draw_armature_pose()`. */
484
485 Armatures::BoneBuffers *bone_buf = nullptr;
486 Resources *res = nullptr;
487 DRWTextStore *dt = nullptr;
488
489 /* Not a theme, this is an override. */
490 const float *const_color = nullptr;
491 /* Wire thickness. */
492 float const_wire = 0.0f;
493
494 bool do_relations = false;
495 bool transparent = false;
496 bool show_relations = false;
499 bool show_text = false;
500 /* Draw the inner part of the bones, otherwise render just outlines. */
501 bool is_filled = false;
502
503 const ThemeWireColor *bcolor = nullptr; /* Pose-channel color. */
504
505 DrawContext() = default;
506 };
507
509 Resources &res,
510 const State &state,
511 eArmatureDrawMode draw_mode)
512 {
514
515 DrawContext ctx;
516 ctx.ob = ob_ref.object;
517 ctx.ob_ref = &ob_ref;
518 ctx.res = &res;
519 ctx.dt = state.dt;
520 ctx.draw_mode = draw_mode;
522
523 const bool is_edit_or_pose_mode = draw_mode != ARM_DRAW_MODE_OBJECT;
524 const bool draw_as_wire = (ctx.ob->dt < OB_SOLID);
525 const bool is_transparent = draw_transparent || (draw_as_wire && is_edit_or_pose_mode);
526
527 ctx.bone_buf = is_transparent ? &transparent_ : &opaque_;
528
529 ctx.is_filled = (!draw_transparent && !draw_as_wire) || is_edit_or_pose_mode;
530 ctx.show_relations = show_relations;
531 ctx.do_relations = show_relations && is_edit_or_pose_mode;
532 ctx.draw_envelope_distance = is_edit_or_pose_mode;
534 ctx.show_text = state.show_text;
535 ctx.const_color = is_edit_or_pose_mode ? nullptr : &res.object_wire_color(ob_ref, state)[0];
536 ctx.const_wire = (!ctx.is_filled || is_transparent) ? 1.0f : 0.0f;
537 if ((ctx.ob->base_flag & BASE_SELECTED) && show_outline) {
538 ctx.const_wire = 1.5f;
539 }
540 return ctx;
541 }
542
543 void edit_object_sync(Manager & /*manager*/,
544 const ObjectRef &ob_ref,
545 Resources &res,
546 const State &state) final
547 {
548 if (!enabled_) {
549 return;
550 }
551
553 draw_armature_edit(&ctx);
554 }
555
556 void object_sync(Manager & /*manager*/,
557 const ObjectRef &ob_ref,
558 Resources &res,
559 const State &state) final
560 {
561 if (!enabled_ || ob_ref.object->dt == OB_BOUNDBOX) {
562 return;
563 }
564
565 eArmatureDrawMode draw_mode = is_pose_mode(ob_ref.object, state) ? ARM_DRAW_MODE_POSE :
567
568 DrawContext ctx = create_draw_context(ob_ref, res, state, draw_mode);
569 draw_armature_pose(&ctx);
570 }
571
572 void end_sync(Resources &res, const State & /*state*/) final
573 {
574 if (!enabled_) {
575 return;
576 }
577
578 auto end_sync = [&](BoneBuffers &bb) {
579 bb.sphere_fill_buf.end_sync(*bb.sphere_fill, res.shapes.bone_sphere.get());
580 bb.sphere_outline_buf.end_sync(*bb.sphere_outline, res.shapes.bone_sphere_wire.get());
581
582 bb.octahedral_fill_buf.end_sync(*bb.shape_fill, res.shapes.bone_octahedron.get());
583 bb.octahedral_outline_buf.end_sync(
584 *bb.shape_outline, res.shapes.bone_octahedron_wire.get(), GPU_PRIM_LINES, 1);
585
586 bb.bbones_fill_buf.end_sync(*bb.shape_fill, res.shapes.bone_box.get());
587 bb.bbones_outline_buf.end_sync(
588 *bb.shape_outline, res.shapes.bone_box_wire.get(), GPU_PRIM_LINES, 1);
589
590 bb.envelope_fill_buf.end_sync(*bb.envelope_fill, res.shapes.bone_envelope.get());
591 bb.envelope_outline_buf.end_sync(*bb.envelope_outline, res.shapes.bone_envelope_wire.get());
592 bb.envelope_distance_buf.end_sync(*bb.envelope_distance, res.shapes.bone_envelope.get());
593
594 bb.stick_buf.end_sync(*bb.stick, res.shapes.bone_stick.get());
595
596 bb.wire_buf.end_sync(*bb.wire);
597
598 bb.arrows_buf.end_sync(*bb.arrows, res.shapes.arrows.get());
599
600 bb.degrees_of_freedom_fill_buf.end_sync(*bb.degrees_of_freedom_fill,
601 res.shapes.bone_degrees_of_freedom.get());
602 bb.degrees_of_freedom_wire_buf.end_sync(*bb.degrees_of_freedom_wire,
603 res.shapes.bone_degrees_of_freedom_wire.get());
604
605 bb.relations_buf.end_sync(*bb.relations);
606
608
609 gpu::Batch *arrow_batch = res.shapes.arrows.get();
610 for (CustomShapeBuf item : bb.custom_shape_fill.items()) {
611 item.value->end_sync(*bb.shape_fill, item.key);
612 }
613 for (CustomShapeBuf item : bb.custom_shape_outline.items()) {
614 item.value->end_sync(*bb.shape_outline, item.key, GPU_PRIM_LINES, 1);
615 }
616 for (CustomShapeBuf item : bb.custom_shape_wire.items()) {
617 /* WORKAROUND: This shape needs a special vertex shader path that should be triggered by
618 * its `vclass` attribute. However, to avoid many changes in the primitive expansion API,
619 * we create a specific path inside the shader only for this shape batch and infer the
620 * value of the `vclass` attribute based on the vertex index. */
621 if (item.key == arrow_batch) {
622 bb.shape_wire->push_constant("use_arrow_drawing", true);
623 }
624
625 item.value->end_sync(*bb.shape_wire, item.key, GPU_PRIM_TRIS, 2);
626
627 if (item.key == arrow_batch) {
628 bb.shape_wire->push_constant("use_arrow_drawing", false);
629 }
630 }
631 for (CustomShapeBuf item : bb.custom_shape_wire_strip.items()) {
632 item.value->end_sync(*bb.shape_wire_strip, item.key, GPU_PRIM_TRIS, 2);
633 }
634 };
635
636 end_sync(transparent_);
637 end_sync(opaque_);
638 }
639
640 void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
641 {
642 if (!enabled_) {
643 return;
644 }
645
646 GPU_framebuffer_bind(framebuffer);
647 manager.submit(armature_ps_, view);
648 }
649
650 /* Public for the time of the Overlay Next port to avoid duplicated logic. */
653
654 static bool is_pose_mode(const Object *armature_ob, const State &state)
655 {
656 const Object *active_ob = state.object_active;
657
658 /* Armature is in pose mode. */
659 if (((armature_ob == active_ob) || (armature_ob->mode & OB_MODE_POSE)) &&
660 ((state.object_mode & OB_MODE_POSE) != 0))
661 {
662 return true;
663 }
664
665 /* Active object is in weight paint and the associated armature is in pose mode. */
666 if ((active_ob != nullptr) && (state.object_mode & OB_MODE_ALL_WEIGHT_PAINT)) {
667 if (armature_ob == BKE_object_pose_armature_get(const_cast<Object *>(active_ob))) {
668 return true;
669 }
670 }
671
672 return false;
673 }
674};
675
676} // namespace blender::draw::overlay
@ CTX_MODE_PAINT_WEIGHT
Object * BKE_object_pose_armature_get(Object *ob)
@ ARM_DRAW_RELATION_FROM_HEAD
eArmature_Drawtype
@ ARM_DRAW_TYPE_OCTA
@ OB_WIRE
@ OB_BOUNDBOX
@ OB_SOLID
#define OB_MODE_ALL_WEIGHT_PAINT
@ OB_MODE_POSE
#define BASE_SELECTED(v3d, base)
@ USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE
@ V3D_SELECT_OUTLINE
@ V3D_HIDE_HELPLINES
T & DRW_object_get_data_for_drawing(const Object &object)
#define XRAY_FLAG_ENABLED(v3d)
static AppView * view
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *fb)
@ GPU_PRIM_LINES
@ GPU_PRIM_LINE_STRIP
@ GPU_PRIM_TRIS
#define U
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
Definition BLI_map.hh:620
detail::PassBase< command::DrawCommandBuf > Sub
Definition draw_pass.hh:499
static bool is_pose_mode(const Object *armature_ob, const State &state)
DrawContext create_draw_context(const ObjectRef &ob_ref, Resources &res, const State &state, eArmatureDrawMode draw_mode)
static void draw_armature_pose(Armatures::DrawContext *ctx)
void begin_sync(Resources &res, const State &state) final
Armatures(const SelectionType selection_type)
void edit_object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
void end_sync(Resources &res, const State &) final
static void draw_armature_edit(Armatures::DrawContext *ctx)
#define DRW_CLIPPING_UBO_SLOT
#define OVERLAY_GLOBALS_SLOT
DRWState
Definition draw_state.hh:25
@ DRW_STATE_BLEND_ALPHA
Definition draw_state.hh:55
@ DRW_STATE_BLEND_ADD
Definition draw_state.hh:51
@ DRW_STATE_CULL_FRONT
Definition draw_state.hh:44
@ DRW_STATE_WRITE_DEPTH
Definition draw_state.hh:29
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
@ DRW_STATE_DEPTH_LESS_EQUAL
Definition draw_state.hh:38
@ DRW_STATE_CULL_BACK
Definition draw_state.hh:43
static ulong state[N]
select::SelectionType SelectionType
detail::Pass< command::DrawCommandBuf > PassSimple
short base_flag
const float4 & object_wire_color(const ObjectRef &ob_ref, ThemeColorID theme_id) const