8b90d3285416c8198048fa425f5c7026aeefd9e7
[blender.git] / source / blender / draw / intern / draw_armature.c
1 /*
2  * Copyright 2016, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Institute
19  *
20  */
21
22 /** \file draw_armature.c
23  *  \ingroup draw
24  */
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <math.h>
29
30 #include "DNA_anim_types.h"
31 #include "DNA_armature_types.h"
32 #include "DNA_constraint_types.h"
33 #include "DNA_scene_types.h"
34 #include "DNA_screen_types.h"
35 #include "DNA_view3d_types.h"
36 #include "DNA_object_types.h"
37
38 #include "DRW_render.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_math.h"
42 #include "BLI_dlrbTree.h"
43 #include "BLI_utildefines.h"
44
45 #include "BKE_animsys.h"
46 #include "BKE_action.h"
47 #include "BKE_armature.h"
48 #include "BKE_global.h"
49 #include "BKE_modifier.h"
50 #include "BKE_nla.h"
51 #include "BKE_curve.h"
52
53 #include "BIF_gl.h"
54
55 #include "ED_armature.h"
56 #include "ED_keyframes_draw.h"
57
58 #include "GPU_select.h"
59
60 #include "UI_resources.h"
61
62 #include "draw_common.h"
63 #include "draw_manager_text.h"
64
65 #define BONE_VAR(eBone, pchan, var) ((eBone) ? (eBone->var) : (pchan->var))
66 #define BONE_FLAG(eBone, pchan) ((eBone) ? (eBone->flag) : (pchan->bone->flag))
67
68 #define PT_DEFAULT_RAD 0.05f /* radius of the point batch. */
69
70 /* For now just match 2.7x where possible. */
71 // #define USE_SOLID_COLOR
72
73 /* Reset for drawing each armature object */
74 static struct {
75         /* Current armature object */
76         Object *ob;
77         /* Reset when changing current_armature */
78         DRWShadingGroup *bone_octahedral_solid;
79         DRWShadingGroup *bone_octahedral_wire;
80         DRWShadingGroup *bone_octahedral_outline;
81         DRWShadingGroup *bone_box_solid;
82         DRWShadingGroup *bone_box_wire;
83         DRWShadingGroup *bone_box_outline;
84         DRWShadingGroup *bone_wire;
85         DRWShadingGroup *bone_stick;
86         DRWShadingGroup *bone_envelope_solid;
87         DRWShadingGroup *bone_envelope_distance;
88         DRWShadingGroup *bone_envelope_wire;
89         DRWShadingGroup *bone_point_solid;
90         DRWShadingGroup *bone_point_wire;
91         DRWShadingGroup *bone_axes;
92         DRWShadingGroup *lines_relationship;
93         DRWShadingGroup *lines_ik;
94         DRWShadingGroup *lines_ik_no_target;
95         DRWShadingGroup *lines_ik_spline;
96
97         DRWArmaturePasses passes;
98 } g_data = {NULL};
99
100
101 /**
102  * Follow `TH_*` naming except for mixed colors.
103  */
104 static struct {
105         float select_color[4];
106         float edge_select_color[4];
107         float bone_select_color[4];  /* tint */
108         float wire_color[4];
109         float wire_edit_color[4];
110         float bone_solid_color[4];
111         float bone_active_unselect_color[4];  /* mix */
112         float bone_pose_color[4];
113         float bone_pose_active_color[4];
114         float bone_pose_active_unselect_color[4];  /* mix */
115         float text_hi_color[4];
116         float text_color[4];
117         float vertex_select_color[4];
118         float vertex_color[4];
119
120         /* not a theme, this is an override */
121         const float *const_color;
122         float const_wire;
123 } g_theme;
124
125
126 /* -------------------------------------------------------------------- */
127
128 /** \name Shader Groups (DRW_shgroup)
129  * \{ */
130
131 /* Octahedral */
132 static void drw_shgroup_bone_octahedral(
133         const float (*bone_mat)[4],
134         const float bone_color[4], const float hint_color[4], const float outline_color[4])
135 {
136         if (g_data.bone_octahedral_outline == NULL) {
137                 struct GPUBatch *geom = DRW_cache_bone_octahedral_wire_get();
138                 g_data.bone_octahedral_outline = shgroup_instance_bone_shape_outline(g_data.passes.bone_outline, geom);
139         }
140         if (g_data.bone_octahedral_solid == NULL) {
141                 struct GPUBatch *geom = DRW_cache_bone_octahedral_get();
142                 g_data.bone_octahedral_solid = shgroup_instance_bone_shape_solid(g_data.passes.bone_solid, geom);
143         }
144         float final_bonemat[4][4];
145         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
146         DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_solid, final_bonemat, bone_color, hint_color);
147         if (outline_color[3] > 0.0f) {
148                 DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_outline, final_bonemat, outline_color);
149         }
150 }
151
152 /* Box / B-Bone */
153 static void drw_shgroup_bone_box(
154         const float (*bone_mat)[4],
155         const float bone_color[4], const float hint_color[4], const float outline_color[4])
156 {
157         if (g_data.bone_box_wire == NULL) {
158                 struct GPUBatch *geom = DRW_cache_bone_box_wire_get();
159                 g_data.bone_box_outline = shgroup_instance_bone_shape_outline(g_data.passes.bone_outline, geom);
160         }
161         if (g_data.bone_box_solid == NULL) {
162                 struct GPUBatch *geom = DRW_cache_bone_box_get();
163                 g_data.bone_box_solid = shgroup_instance_bone_shape_solid(g_data.passes.bone_solid, geom);
164         }
165         float final_bonemat[4][4];
166         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
167         DRW_shgroup_call_dynamic_add(g_data.bone_box_solid, final_bonemat, bone_color, hint_color);
168         if (outline_color[3] > 0.0f) {
169                 DRW_shgroup_call_dynamic_add(g_data.bone_box_outline, final_bonemat, outline_color);
170         }
171 }
172
173 /* Wire */
174 static void drw_shgroup_bone_wire(const float (*bone_mat)[4], const float color[4])
175 {
176         if (g_data.bone_wire == NULL) {
177                 g_data.bone_wire = shgroup_dynlines_flat_color(g_data.passes.bone_wire);
178         }
179         float head[3], tail[3];
180         mul_v3_m4v3(head, g_data.ob->obmat, bone_mat[3]);
181         DRW_shgroup_call_dynamic_add(g_data.bone_wire, head, color);
182
183         add_v3_v3v3(tail, bone_mat[3], bone_mat[1]);
184         mul_m4_v3(g_data.ob->obmat, tail);
185         DRW_shgroup_call_dynamic_add(g_data.bone_wire, tail, color);
186 }
187
188 /* Stick */
189 static void drw_shgroup_bone_stick(
190         const float (*bone_mat)[4],
191         const float col_wire[4], const float col_bone[4], const float col_head[4], const float col_tail[4])
192 {
193         if (g_data.bone_stick == NULL) {
194                 g_data.bone_stick = shgroup_instance_bone_stick(g_data.passes.bone_wire);
195         }
196         float final_bonemat[4][4], tail[4];
197         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
198         add_v3_v3v3(tail, final_bonemat[3], final_bonemat[1]);
199         DRW_shgroup_call_dynamic_add(g_data.bone_stick, final_bonemat[3], tail, col_wire, col_bone, col_head, col_tail);
200 }
201
202
203 /* Envelope */
204 static void drw_shgroup_bone_envelope_distance(
205         const float (*bone_mat)[4],
206         const float *radius_head, const float *radius_tail, const float *distance)
207 {
208         if (g_data.passes.bone_envelope != NULL) {
209                 if (g_data.bone_envelope_distance == NULL) {
210                         g_data.bone_envelope_distance = shgroup_instance_bone_envelope_distance(g_data.passes.bone_envelope);
211                         /* passes.bone_envelope should have the DRW_STATE_CULL_FRONT state enabled. */
212                 }
213                 float head_sphere[4] = {0.0f, 0.0f, 0.0f, 1.0f}, tail_sphere[4] = {0.0f, 1.0f, 0.0f, 1.0f};
214                 float final_bonemat[4][4];
215                 mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
216                 /* We need matrix mul because we need shear applied. */
217                 /* NOTE: could be done in shader if that becomes a bottleneck. */
218                 mul_m4_v4(final_bonemat, head_sphere);
219                 mul_m4_v4(final_bonemat, tail_sphere);
220                 head_sphere[3]  = *radius_head;
221                 head_sphere[3] += *distance;
222                 tail_sphere[3]  = *radius_tail;
223                 tail_sphere[3] += *distance;
224                 DRW_shgroup_call_dynamic_add(g_data.bone_envelope_distance, head_sphere, tail_sphere, final_bonemat[0]);
225         }
226 }
227
228 static void drw_shgroup_bone_envelope(
229         const float (*bone_mat)[4],
230         const float bone_color[4], const float hint_color[4], const float outline_color[4],
231         const float *radius_head, const float *radius_tail)
232 {
233         if (g_data.bone_point_wire == NULL) {
234                 g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.passes.bone_wire);
235         }
236         if (g_data.bone_point_solid == NULL) {
237                 g_data.bone_point_solid = shgroup_instance_bone_sphere_solid(g_data.passes.bone_solid);
238         }
239         if (g_data.bone_envelope_wire == NULL) {
240                 g_data.bone_envelope_wire = shgroup_instance_bone_envelope_outline(g_data.passes.bone_wire);
241         }
242         if (g_data.bone_envelope_solid == NULL) {
243                 g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(g_data.passes.bone_solid);
244                 /* We can have a lot of overdraw if we don't do this. Also envelope are not subject to
245                  * inverted matrix. */
246                 DRW_shgroup_state_enable(g_data.bone_envelope_solid, DRW_STATE_CULL_BACK);
247         }
248
249         float head_sphere[4] = {0.0f, 0.0f, 0.0f, 1.0f}, tail_sphere[4] = {0.0f, 1.0f, 0.0f, 1.0f};
250         float final_bonemat[4][4];
251         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
252         mul_m4_v4(final_bonemat, head_sphere);
253         mul_m4_v4(final_bonemat, tail_sphere);
254         head_sphere[3] = *radius_head;
255         tail_sphere[3] = *radius_tail;
256
257         if (head_sphere[3] < 0.0f) {
258                 /* Draw Tail only */
259                 float tmp[4][4] = {{0.0f}};
260                 tmp[0][0] = tmp[1][1] = tmp[2][2] = tail_sphere[3] / PT_DEFAULT_RAD;
261                 tmp[3][3] = 1.0f;
262                 copy_v3_v3(tmp[3], tail_sphere);
263                 DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, bone_color, hint_color);
264                 if (outline_color[3] > 0.0f) {
265                         DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, outline_color);
266                 }
267         }
268         else if (tail_sphere[3] < 0.0f) {
269                 /* Draw Head only */
270                 float tmp[4][4] = {{0.0f}};
271                 tmp[0][0] = tmp[1][1] = tmp[2][2] = head_sphere[3] / PT_DEFAULT_RAD;
272                 tmp[3][3] = 1.0f;
273                 copy_v3_v3(tmp[3], head_sphere);
274                 DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, bone_color, hint_color);
275                 if (outline_color[3] > 0.0f) {
276                         DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, outline_color);
277                 }
278         }
279         else {
280                 /* Draw Body */
281                 float tmp_sphere[4];
282                 float len = len_v3v3(tail_sphere, head_sphere);
283                 float fac_head = (len - head_sphere[3]) / len;
284                 float fac_tail = (len - tail_sphere[3]) / len;
285
286                 /* Small epsilon to avoid problem with float precison in shader. */
287                 if (len > (tail_sphere[3] + head_sphere[3]) + 1e-8f) {
288
289                         copy_v4_v4(tmp_sphere, head_sphere);
290                         interp_v4_v4v4(head_sphere, tail_sphere, head_sphere, fac_head);
291                         interp_v4_v4v4(tail_sphere, tmp_sphere,  tail_sphere, fac_tail);
292                         DRW_shgroup_call_dynamic_add(
293                                 g_data.bone_envelope_solid, head_sphere, tail_sphere, bone_color, hint_color, final_bonemat[0]);
294                         if (outline_color[3] > 0.0f) {
295                                 DRW_shgroup_call_dynamic_add(
296                                         g_data.bone_envelope_wire, head_sphere, tail_sphere, outline_color, final_bonemat[0]);
297                         }
298                 }
299                 else {
300                         float tmp[4][4] = {{0.0f}};
301                         float fac = max_ff(fac_head, 1.0f - fac_tail);
302                         interp_v4_v4v4(tmp_sphere, tail_sphere, head_sphere, clamp_f(fac, 0.0f, 1.0f));
303                         tmp[0][0] = tmp[1][1] = tmp[2][2] = tmp_sphere[3] / PT_DEFAULT_RAD;
304                         tmp[3][3] = 1.0f;
305                         copy_v3_v3(tmp[3], tmp_sphere);
306                         DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, bone_color, hint_color);
307                         if (outline_color[3] > 0.0f) {
308                                 DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, outline_color);
309                         }
310                 }
311         }
312 }
313
314 /* Custom (geometry) */
315
316 static void drw_shgroup_bone_custom_solid(
317         const float (*bone_mat)[4],
318         const float bone_color[4], const float hint_color[4], const float outline_color[4],
319         Object *custom)
320 {
321         /* grr, not re-using instances! */
322         struct GPUBatch *surf = DRW_cache_object_surface_get(custom);
323         struct GPUBatch *edges = DRW_cache_object_edge_detection_get(custom, NULL);
324         struct GPUBatch *ledges = DRW_cache_object_loose_edges_get(custom);
325         float final_bonemat[4][4];
326
327         if (surf || edges || ledges) {
328                 mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
329         }
330
331         if (surf) {
332                 DRWShadingGroup *shgrp_geom_solid = shgroup_instance_bone_shape_solid(g_data.passes.bone_solid, surf);
333                 DRW_shgroup_call_dynamic_add(shgrp_geom_solid, final_bonemat, bone_color, hint_color);
334         }
335
336         if (edges && outline_color[3] > 0.0f) {
337                 DRWShadingGroup *shgrp_geom_wire = shgroup_instance_bone_shape_outline(g_data.passes.bone_outline, edges);
338                 DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, outline_color);
339         }
340
341         if (ledges) {
342                 DRWShadingGroup *shgrp_geom_ledges = shgroup_instance_wire(g_data.passes.bone_wire, ledges);
343                 float final_color[4];
344                 copy_v3_v3(final_color, outline_color);
345                 final_color[3] = 1.0f; /* hack */
346                 DRW_shgroup_call_dynamic_add(shgrp_geom_ledges, final_bonemat, final_color);
347         }
348 }
349
350 static void drw_shgroup_bone_custom_wire(
351         const float (*bone_mat)[4],
352         const float color[4], Object *custom)
353 {
354         /* grr, not re-using instances! */
355         struct GPUBatch *geom = DRW_cache_object_wire_outline_get(custom);
356         if (geom) {
357                 DRWShadingGroup *shgrp_geom_wire = shgroup_instance_wire(g_data.passes.bone_wire, geom);
358                 float final_bonemat[4][4], final_color[4];
359                 mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
360                 copy_v3_v3(final_color, color);
361                 final_color[3] = 1.0f; /* hack */
362                 DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, final_color);
363         }
364 }
365
366 /* Head and tail sphere */
367 static void drw_shgroup_bone_point(
368         const float (*bone_mat)[4],
369         const float bone_color[4], const float hint_color[4], const float outline_color[4])
370 {
371         if (g_data.bone_point_wire == NULL) {
372                 g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.passes.bone_wire);
373         }
374         if (g_data.bone_point_solid == NULL) {
375                 g_data.bone_point_solid = shgroup_instance_bone_sphere_solid(g_data.passes.bone_solid);
376         }
377         float final_bonemat[4][4];
378         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
379         DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, final_bonemat, bone_color, hint_color);
380         if (outline_color[3] > 0.0f) {
381                 DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, final_bonemat, outline_color);
382         }
383 }
384
385 /* Axes */
386 static void drw_shgroup_bone_axes(const float (*bone_mat)[4], const float color[4])
387 {
388         if (g_data.bone_axes == NULL) {
389                 g_data.bone_axes = shgroup_instance_bone_axes(g_data.passes.bone_axes);
390         }
391         float final_bonemat[4][4];
392         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
393         DRW_shgroup_call_dynamic_add(g_data.bone_axes, final_bonemat, color);
394 }
395
396 /* Relationship lines */
397 static void drw_shgroup_bone_relationship_lines(const float start[3], const float end[3])
398 {
399         if (g_data.lines_relationship == NULL) {
400                 g_data.lines_relationship = shgroup_dynlines_dashed_uniform_color(
401                         g_data.passes.relationship_lines, g_theme.wire_color);
402         }
403         /* reverse order to have less stipple overlap */
404         float v[3];
405         mul_v3_m4v3(v, g_data.ob->obmat, end);
406         DRW_shgroup_call_dynamic_add(g_data.lines_relationship, v);
407         mul_v3_m4v3(v, g_data.ob->obmat, start);
408         DRW_shgroup_call_dynamic_add(g_data.lines_relationship, v);
409 }
410
411 static void drw_shgroup_bone_ik_lines(const float start[3], const float end[3])
412 {
413         if (g_data.lines_ik == NULL) {
414                 static float fcolor[4] = {0.8f, 0.5f, 0.0f, 1.0f};  /* add theme! */
415                 g_data.lines_ik = shgroup_dynlines_dashed_uniform_color(g_data.passes.relationship_lines, fcolor);
416         }
417         /* reverse order to have less stipple overlap */
418         float v[3];
419         mul_v3_m4v3(v, g_data.ob->obmat, end);
420         DRW_shgroup_call_dynamic_add(g_data.lines_ik, v);
421         mul_v3_m4v3(v, g_data.ob->obmat, start);
422         DRW_shgroup_call_dynamic_add(g_data.lines_ik, v);
423 }
424
425 static void drw_shgroup_bone_ik_no_target_lines(const float start[3], const float end[3])
426 {
427         if (g_data.lines_ik_no_target == NULL) {
428                 static float fcolor[4] = {0.8f, 0.8f, 0.2f, 1.0f};  /* add theme! */
429                 g_data.lines_ik_no_target = shgroup_dynlines_dashed_uniform_color(g_data.passes.relationship_lines, fcolor);
430         }
431         /* reverse order to have less stipple overlap */
432         DRW_shgroup_call_dynamic_add(g_data.lines_ik_no_target, end);
433         DRW_shgroup_call_dynamic_add(g_data.lines_ik_no_target, start);
434 }
435
436 static void drw_shgroup_bone_ik_spline_lines(const float start[3], const float end[3])
437 {
438         if (g_data.lines_ik_spline == NULL) {
439                 static float fcolor[4] = {0.8f, 0.8f, 0.2f, 1.0f};  /* add theme! */
440                 g_data.lines_ik_spline = shgroup_dynlines_dashed_uniform_color(g_data.passes.relationship_lines, fcolor);
441         }
442         /* reverse order to have less stipple overlap */
443         DRW_shgroup_call_dynamic_add(g_data.lines_ik_spline, end);
444         DRW_shgroup_call_dynamic_add(g_data.lines_ik_spline, start);
445 }
446
447 /** \} */
448
449
450 /* -------------------------------------------------------------------- */
451
452 /** \name Drawing Theme Helpers
453  *
454  * Note, this section is duplicate of code in 'drawarmature.c'.
455  *
456  * \{ */
457
458 /* global here is reset before drawing each bone */
459 struct {
460         const ThemeWireColor *bcolor;
461 } g_color;
462
463 /* values of colCode for set_pchan_color */
464 enum {
465         PCHAN_COLOR_NORMAL  = 0,        /* normal drawing */
466         PCHAN_COLOR_SOLID,              /* specific case where "solid" color is needed */
467         PCHAN_COLOR_CONSTS,             /* "constraint" colors (which may/may-not be suppressed) */
468
469         PCHAN_COLOR_SPHEREBONE_BASE,    /* for the 'stick' of sphere (envelope) bones */
470         PCHAN_COLOR_SPHEREBONE_END,     /* for the ends of sphere (envelope) bones */
471         PCHAN_COLOR_LINEBONE            /* for the middle of line-bones */
472 };
473
474 /* This function sets the color-set for coloring a certain bone */
475 static void set_pchan_colorset(Object *ob, bPoseChannel *pchan)
476 {
477         bPose *pose = (ob) ? ob->pose : NULL;
478         bArmature *arm = (ob) ? ob->data : NULL;
479         bActionGroup *grp = NULL;
480         short color_index = 0;
481
482         /* sanity check */
483         if (ELEM(NULL, ob, arm, pose, pchan)) {
484                 g_color.bcolor = NULL;
485                 return;
486         }
487
488         /* only try to set custom color if enabled for armature */
489         if (arm->flag & ARM_COL_CUSTOM) {
490                 /* currently, a bone can only use a custom color set if it's group (if it has one),
491                  * has been set to use one
492                  */
493                 if (pchan->agrp_index) {
494                         grp = (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
495                         if (grp)
496                                 color_index = grp->customCol;
497                 }
498         }
499
500         /* bcolor is a pointer to the color set to use. If NULL, then the default
501          * color set (based on the theme colors for 3d-view) is used.
502          */
503         if (color_index > 0) {
504                 bTheme *btheme = UI_GetTheme();
505                 g_color.bcolor = &btheme->tarm[(color_index - 1)];
506         }
507         else if (color_index == -1) {
508                 /* use the group's own custom color set (grp is always != NULL here) */
509                 g_color.bcolor = &grp->cs;
510         }
511         else {
512                 g_color.bcolor = NULL;
513         }
514 }
515
516 /* This function is for brightening/darkening a given color (like UI_GetThemeColorShade3ubv()) */
517 static void cp_shade_color3ub(uchar cp[3], const int offset)
518 {
519         int r, g, b;
520
521         r = offset + (int) cp[0];
522         CLAMP(r, 0, 255);
523         g = offset + (int) cp[1];
524         CLAMP(g, 0, 255);
525         b = offset + (int) cp[2];
526         CLAMP(b, 0, 255);
527
528         cp[0] = r;
529         cp[1] = g;
530         cp[2] = b;
531 }
532
533 static void cp_shade_color3f(float cp[3], const float offset)
534 {
535         add_v3_fl(cp, offset);
536         CLAMP(cp[0], 0, 255);
537         CLAMP(cp[1], 0, 255);
538         CLAMP(cp[2], 0, 255);
539 }
540
541
542 /* This function sets the gl-color for coloring a certain bone (based on bcolor) */
543 static bool set_pchan_color(short colCode, const int boneflag, const short constflag, float r_color[4])
544 {
545         float *fcolor = r_color;
546         const ThemeWireColor *bcolor = g_color.bcolor;
547
548         switch (colCode) {
549                 case PCHAN_COLOR_NORMAL:
550                 {
551                         if (bcolor) {
552                                 uchar cp[4] = {255};
553
554                                 if (boneflag & BONE_DRAW_ACTIVE) {
555                                         copy_v3_v3_char((char *)cp, bcolor->active);
556                                         if (!(boneflag & BONE_SELECTED)) {
557                                                 cp_shade_color3ub(cp, -80);
558                                         }
559                                 }
560                                 else if (boneflag & BONE_SELECTED) {
561                                         copy_v3_v3_char((char *)cp, bcolor->select);
562                                 }
563                                 else {
564                                         /* a bit darker than solid */
565                                         copy_v3_v3_char((char *)cp, bcolor->solid);
566                                         cp_shade_color3ub(cp, -50);
567                                 }
568
569                                 rgb_uchar_to_float(fcolor, cp);
570                         }
571                         else {
572                                 if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) {
573                                         UI_GetThemeColor4fv(TH_BONE_POSE_ACTIVE, fcolor);
574                                 }
575                                 else if (boneflag & BONE_DRAW_ACTIVE) {
576                                         UI_GetThemeColorBlendShade4fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, fcolor);
577                                 }
578                                 else if (boneflag & BONE_SELECTED) {
579                                         UI_GetThemeColor4fv(TH_BONE_POSE, fcolor);
580                                 }
581                                 else {
582                                         UI_GetThemeColor4fv(TH_WIRE, fcolor);
583                                 }
584                         }
585
586                         return true;
587                 }
588                 case PCHAN_COLOR_SOLID:
589                 {
590                         UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
591
592                         if (bcolor) {
593                                 float solid_bcolor[3];
594                                 rgb_uchar_to_float(solid_bcolor, (uchar *)bcolor->solid);
595                                 interp_v3_v3v3(fcolor, fcolor, solid_bcolor, 1.0f);
596                         }
597
598                         return true;
599                 }
600                 case PCHAN_COLOR_CONSTS:
601                 {
602                         if ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) {
603                                 uchar cp[4];
604                                 if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 80);
605                                 else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 80);
606                                 else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 80);
607                                 else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 80);
608                                 else {
609                                         return false;
610                                 }
611
612                                 rgba_uchar_to_float(fcolor, cp);
613
614                                 return true;
615                         }
616                         return false;
617                 }
618                 case PCHAN_COLOR_SPHEREBONE_BASE:
619                 {
620                         if (bcolor) {
621                                 uchar cp[4] = {255};
622
623                                 if (boneflag & BONE_DRAW_ACTIVE) {
624                                         copy_v3_v3_char((char *)cp, bcolor->active);
625                                 }
626                                 else if (boneflag & BONE_SELECTED) {
627                                         copy_v3_v3_char((char *)cp, bcolor->select);
628                                 }
629                                 else {
630                                         copy_v3_v3_char((char *)cp, bcolor->solid);
631                                 }
632
633                                 rgb_uchar_to_float(fcolor, cp);
634                         }
635                         else {
636                                 if (boneflag & BONE_DRAW_ACTIVE) {
637                                         UI_GetThemeColorShade4fv(TH_BONE_POSE, 40, fcolor);
638                                 }
639                                 else if (boneflag & BONE_SELECTED) {
640                                         UI_GetThemeColor4fv(TH_BONE_POSE, fcolor);
641                                 }
642                                 else {
643                                         UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
644                                 }
645                         }
646
647                         return true;
648                 }
649                 case PCHAN_COLOR_SPHEREBONE_END:
650                 {
651                         if (bcolor) {
652                                 uchar cp[4] = {255};
653
654                                 if (boneflag & BONE_DRAW_ACTIVE) {
655                                         copy_v3_v3_char((char *)cp, bcolor->active);
656                                         cp_shade_color3ub(cp, 10);
657                                 }
658                                 else if (boneflag & BONE_SELECTED) {
659                                         copy_v3_v3_char((char *)cp, bcolor->select);
660                                         cp_shade_color3ub(cp, -30);
661                                 }
662                                 else {
663                                         copy_v3_v3_char((char *)cp, bcolor->solid);
664                                         cp_shade_color3ub(cp, -30);
665                                 }
666
667                                 rgb_uchar_to_float(fcolor, cp);
668                         }
669                         else {
670                                 if (boneflag & BONE_DRAW_ACTIVE) {
671                                         UI_GetThemeColorShade4fv(TH_BONE_POSE, 10, fcolor);
672                                 }
673                                 else if (boneflag & BONE_SELECTED) {
674                                         UI_GetThemeColorShade4fv(TH_BONE_POSE, -30, fcolor);
675                                 }
676                                 else {
677                                         UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
678                                 }
679                         }
680                         break;
681                 }
682                 case PCHAN_COLOR_LINEBONE:
683                 {
684                         /* inner part in background color or constraint */
685                         if ((constflag) && ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS))) {
686                                 uchar cp[4];
687                                 if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 255);
688                                 else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 255);
689                                 else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 255);
690                                 else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 255);
691                                 else if (constflag) UI_GetThemeColor4ubv(TH_BONE_POSE, cp);  /* PCHAN_HAS_ACTION */
692
693                                 rgb_uchar_to_float(fcolor, cp);
694                         }
695                         else {
696                                 if (bcolor) {
697                                         const char *cp = bcolor->solid;
698                                         rgb_uchar_to_float(fcolor, (uchar *)cp);
699                                         fcolor[3] = 204.f / 255.f;
700                                 }
701                                 else {
702                                         UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor);
703                                 }
704                         }
705
706                         return true;
707                 }
708         }
709
710         return false;
711 }
712
713 /** \} */
714
715
716 /* -------------------------------------------------------------------- */
717
718 /** \name Drawing Color Helpers
719  * \{ */
720
721 /** See: 'set_pchan_color'*/
722 static void update_color(const Object *ob, const float const_color[4])
723 {
724         g_theme.const_color = const_color;
725         g_theme.const_wire = ((ob->base_flag & BASE_SELECTED) != 0) ? 1.5f : 0.0f;
726
727 #define NO_ALPHA(c) (((c)[3] = 1.0f), (c))
728
729         UI_GetThemeColor3fv(TH_SELECT, NO_ALPHA(g_theme.select_color));
730         UI_GetThemeColor3fv(TH_EDGE_SELECT, NO_ALPHA(g_theme.edge_select_color));
731         UI_GetThemeColorShade3fv(TH_EDGE_SELECT, -20, NO_ALPHA(g_theme.bone_select_color));
732         UI_GetThemeColor3fv(TH_WIRE, NO_ALPHA(g_theme.wire_color));
733         UI_GetThemeColor3fv(TH_WIRE_EDIT, NO_ALPHA(g_theme.wire_edit_color));
734         UI_GetThemeColor3fv(TH_BONE_SOLID, NO_ALPHA(g_theme.bone_solid_color));
735         UI_GetThemeColorBlendShade3fv(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f, 0, NO_ALPHA(g_theme.bone_active_unselect_color));
736         UI_GetThemeColor3fv(TH_BONE_POSE, NO_ALPHA(g_theme.bone_pose_color));
737         UI_GetThemeColor3fv(TH_BONE_POSE_ACTIVE, NO_ALPHA(g_theme.bone_pose_active_color));
738         UI_GetThemeColorBlendShade3fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, NO_ALPHA(g_theme.bone_pose_active_unselect_color));
739         UI_GetThemeColor3fv(TH_TEXT_HI, NO_ALPHA(g_theme.text_hi_color));
740         UI_GetThemeColor3fv(TH_TEXT, NO_ALPHA(g_theme.text_color));
741         UI_GetThemeColor3fv(TH_VERTEX_SELECT, NO_ALPHA(g_theme.vertex_select_color));
742         UI_GetThemeColor3fv(TH_VERTEX, NO_ALPHA(g_theme.vertex_color));
743
744 #undef NO_ALPHA
745 }
746
747 static const float *get_bone_solid_color(
748         const EditBone *UNUSED(eBone), const bPoseChannel *pchan, const bArmature *arm,
749         const int boneflag, const short constflag)
750 {
751         if (g_theme.const_color)
752                 return g_theme.bone_solid_color;
753
754         if (arm->flag & ARM_POSEMODE) {
755                 static float disp_color[4];
756                 copy_v4_v4(disp_color, pchan->draw_data->solid_color);
757                 set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag, disp_color);
758                 return disp_color;
759         }
760
761         return g_theme.bone_solid_color;
762 }
763
764 static const float *get_bone_solid_with_consts_color(
765         const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm,
766         const int boneflag, const short constflag)
767 {
768         if (g_theme.const_color)
769                 return g_theme.bone_solid_color;
770
771         const float *col = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag);
772
773         static float consts_color[4];
774         if (set_pchan_color(PCHAN_COLOR_CONSTS, boneflag, constflag, consts_color)) {
775                 interp_v3_v3v3(consts_color, col, consts_color, 0.5f);
776         }
777         else {
778                 copy_v4_v4(consts_color, col);
779         }
780         return consts_color;
781 }
782
783 static float get_bone_wire_thickness(int boneflag)
784 {
785         if (g_theme.const_color)
786                 return g_theme.const_wire;
787         else if (boneflag & (BONE_DRAW_ACTIVE | BONE_SELECTED))
788                 return 2.0f;
789         else
790                 return 1.0f;
791 }
792
793 static const float *get_bone_wire_color(
794         const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm,
795         const int boneflag, const short constflag)
796 {
797         static float disp_color[4];
798
799         if (g_theme.const_color) {
800                 copy_v3_v3(disp_color, g_theme.const_color);
801         }
802         else if (eBone) {
803                 if (boneflag & BONE_SELECTED) {
804                         if (boneflag & BONE_DRAW_ACTIVE) {
805                                 copy_v3_v3(disp_color, g_theme.edge_select_color);
806                         }
807                         else {
808                                 copy_v3_v3(disp_color, g_theme.bone_select_color);
809                         }
810                 }
811                 else {
812                         if (boneflag & BONE_DRAW_ACTIVE) {
813                                 copy_v3_v3(disp_color, g_theme.bone_active_unselect_color);
814                         }
815                         else {
816                                 copy_v3_v3(disp_color, g_theme.wire_edit_color);
817                         }
818                 }
819         }
820         else if (arm->flag & ARM_POSEMODE) {
821                 copy_v4_v4(disp_color, pchan->draw_data->wire_color);
822                 set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag, disp_color);
823         }
824         else {
825                 copy_v3_v3(disp_color, g_theme.vertex_color);
826         }
827
828         disp_color[3] = get_bone_wire_thickness(boneflag);
829
830         return disp_color;
831 }
832
833 #define HINT_MUL 0.5f
834 #define HINT_SHADE 0.2f
835
836 static void bone_hint_color_shade(float hint_color[4], const float color[4])
837 {
838         mul_v3_v3fl(hint_color, color, HINT_MUL);
839         cp_shade_color3f(hint_color, -HINT_SHADE);
840         hint_color[3] = 1.0f;
841 }
842
843 static const float *get_bone_hint_color(
844         const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm,
845         const int boneflag, const short constflag)
846 {
847         static float hint_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
848
849         if (g_theme.const_color) {
850                 bone_hint_color_shade(hint_color, g_theme.bone_solid_color);
851         }
852         else {
853                 const float *wire_color = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
854                 bone_hint_color_shade(hint_color, wire_color);
855         }
856
857         return hint_color;
858 }
859
860 /** \} */
861
862
863 /* -------------------------------------------------------------------- */
864
865 /** \name Helper Utils
866  * \{ */
867
868 static void pchan_draw_data_init(bPoseChannel *pchan)
869 {
870         if (pchan->draw_data != NULL) {
871                 if (pchan->draw_data->bbone_matrix_len != pchan->bone->segments) {
872                         MEM_SAFE_FREE(pchan->draw_data);
873                 }
874         }
875
876         if (pchan->draw_data == NULL) {
877                 pchan->draw_data = MEM_mallocN(sizeof(*pchan->draw_data) + sizeof(Mat4) * pchan->bone->segments, __func__);
878                 pchan->draw_data->bbone_matrix_len = pchan->bone->segments;
879         }
880 }
881
882 static void draw_bone_update_disp_matrix_default(EditBone *eBone, bPoseChannel *pchan)
883 {
884         float s[4][4], ebmat[4][4];
885         float length;
886         float (*bone_mat)[4];
887         float (*disp_mat)[4];
888         float (*disp_tail_mat)[4];
889
890         /* TODO : This should be moved to depsgraph or armature refresh
891          * and not be tight to the draw pass creation.
892          * This would refresh armature without invalidating the draw cache */
893         if (pchan) {
894                 length = pchan->bone->length;
895                 bone_mat = pchan->pose_mat;
896                 disp_mat = pchan->disp_mat;
897                 disp_tail_mat = pchan->disp_tail_mat;
898         }
899         else {
900                 eBone->length = len_v3v3(eBone->tail, eBone->head);
901                 ED_armature_ebone_to_mat4(eBone, ebmat);
902
903                 length = eBone->length;
904                 bone_mat = ebmat;
905                 disp_mat = eBone->disp_mat;
906                 disp_tail_mat = eBone->disp_tail_mat;
907         }
908
909         scale_m4_fl(s, length);
910         mul_m4_m4m4(disp_mat, bone_mat, s);
911         copy_m4_m4(disp_tail_mat, disp_mat);
912         translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f);
913 }
914
915 /* XXX Direct copy from drawarmature.c... This is ugly! */
916 /* A partial copy of b_bone_spline_setup(), with just the parts for previewing editmode curve settings
917  *
918  * This assumes that prev/next bones don't have any impact (since they should all still be in the "straight"
919  * position here anyway), and that we can simply apply the bbone settings to get the desired effect...
920  */
921 static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_SUBDIV][4][4])
922 {
923         float h1[3], h2[3], length, hlength1, hlength2, roll1 = 0.0f, roll2 = 0.0f;
924         float mat3[3][3];
925         float data[MAX_BBONE_SUBDIV + 1][4], *fp;
926         int a;
927
928         length = ebone->length;
929
930         hlength1 = ebone->ease1 * length * 0.390464f; /* 0.5f * sqrt(2) * kappa, the handle length for near-perfect circles */
931         hlength2 = ebone->ease2 * length * 0.390464f;
932
933         /* find the handle points, since this is inside bone space, the
934          * first point = (0, 0, 0)
935          * last point =  (0, length, 0)
936          *
937          * we also just apply all the "extra effects", since they're the whole reason we're doing this...
938          */
939         h1[0] = ebone->curveInX;
940         h1[1] = hlength1;
941         h1[2] = ebone->curveInY;
942         roll1 = ebone->roll1;
943
944         h2[0] = ebone->curveOutX;
945         h2[1] = -hlength2;
946         h2[2] = ebone->curveOutY;
947         roll2 = ebone->roll2;
948
949         /* make curve */
950         if (ebone->segments > MAX_BBONE_SUBDIV)
951                 ebone->segments = MAX_BBONE_SUBDIV;
952
953         BKE_curve_forward_diff_bezier(0.0f,  h1[0],                               h2[0],                               0.0f,   data[0],     MAX_BBONE_SUBDIV, 4 * sizeof(float));
954         BKE_curve_forward_diff_bezier(0.0f,  h1[1],                               length + h2[1],                      length, data[0] + 1, MAX_BBONE_SUBDIV, 4 * sizeof(float));
955         BKE_curve_forward_diff_bezier(0.0f,  h1[2],                               h2[2],                               0.0f,   data[0] + 2, MAX_BBONE_SUBDIV, 4 * sizeof(float));
956         BKE_curve_forward_diff_bezier(roll1, roll1 + 0.390464f * (roll2 - roll1), roll2 - 0.390464f * (roll2 - roll1), roll2,  data[0] + 3, MAX_BBONE_SUBDIV, 4 * sizeof(float));
957
958         equalize_bbone_bezier(data[0], ebone->segments); /* note: does stride 4! */
959
960         /* make transformation matrices for the segments for drawing */
961         for (a = 0, fp = data[0]; a < ebone->segments; a++, fp += 4) {
962                 sub_v3_v3v3(h1, fp + 4, fp);
963                 vec_roll_to_mat3(h1, fp[3], mat3); /* fp[3] is roll */
964
965                 copy_m4_m3(result_array[a], mat3);
966                 copy_v3_v3(result_array[a][3], fp);
967
968                 /* "extra" scale facs... */
969                 {
970                         const int num_segments = ebone->segments;
971
972                         const float scaleFactorIn  = 1.0f + (ebone->scaleIn  - 1.0f) * ((float)(num_segments - a) / (float)num_segments);
973                         const float scaleFactorOut = 1.0f + (ebone->scaleOut - 1.0f) * ((float)(a + 1)            / (float)num_segments);
974
975                         const float scalefac = scaleFactorIn * scaleFactorOut;
976                         float bscalemat[4][4], bscale[3];
977
978                         bscale[0] = scalefac;
979                         bscale[1] = 1.0f;
980                         bscale[2] = scalefac;
981
982                         size_to_mat4(bscalemat, bscale);
983
984                         /* Note: don't multiply by inverse scale mat here,
985                          * as it causes problems with scaling shearing and breaking segment chains */
986                         mul_m4_series(result_array[a], result_array[a], bscalemat);
987                 }
988         }
989 }
990
991 static void draw_bone_update_disp_matrix_bbone(EditBone *eBone, bPoseChannel *pchan)
992 {
993         float s[4][4], ebmat[4][4];
994         float length, xwidth, zwidth;
995         float (*bone_mat)[4];
996         short bbone_segments;
997
998         /* TODO : This should be moved to depsgraph or armature refresh
999          * and not be tight to the draw pass creation.
1000          * This would refresh armature without invalidating the draw cache */
1001         if (pchan) {
1002                 length = pchan->bone->length;
1003                 xwidth = pchan->bone->xwidth;
1004                 zwidth = pchan->bone->zwidth;
1005                 bone_mat = pchan->pose_mat;
1006                 bbone_segments = pchan->bone->segments;
1007         }
1008         else {
1009                 eBone->length = len_v3v3(eBone->tail, eBone->head);
1010                 ED_armature_ebone_to_mat4(eBone, ebmat);
1011
1012                 length = eBone->length;
1013                 xwidth = eBone->xwidth;
1014                 zwidth = eBone->zwidth;
1015                 bone_mat = ebmat;
1016                 bbone_segments = eBone->segments;
1017         }
1018
1019         size_to_mat4(s, (const float[3]){xwidth, length / bbone_segments, zwidth});
1020
1021         /* Compute BBones segment matrices... */
1022         /* Note that we need this even for one-segment bones, because box drawing need specific weirdo matrix for the box,
1023          * that we cannot use to draw end points & co. */
1024         if (pchan) {
1025                 Mat4 *bbones_mat = (Mat4 *)pchan->draw_data->bbone_matrix;
1026                 if (bbone_segments > 1) {
1027                         b_bone_spline_setup(pchan, 0, bbones_mat);
1028
1029                         for (int i = bbone_segments; i--; bbones_mat++) {
1030                                 mul_m4_m4m4(bbones_mat->mat, bbones_mat->mat, s);
1031                                 mul_m4_m4m4(bbones_mat->mat, bone_mat, bbones_mat->mat);
1032                         }
1033                 }
1034                 else {
1035                         mul_m4_m4m4(bbones_mat->mat, bone_mat, s);
1036                 }
1037         }
1038         else {
1039                 float (*bbones_mat)[4][4] = eBone->disp_bbone_mat;
1040
1041                 if (bbone_segments > 1) {
1042                         ebone_spline_preview(eBone, bbones_mat);
1043
1044                         for (int i = bbone_segments; i--; bbones_mat++) {
1045                                 mul_m4_m4m4(*bbones_mat, *bbones_mat, s);
1046                                 mul_m4_m4m4(*bbones_mat, bone_mat, *bbones_mat);
1047                         }
1048                 }
1049                 else {
1050                         mul_m4_m4m4(*bbones_mat, bone_mat, s);
1051                 }
1052         }
1053
1054         /* Grrr... We need default display matrix to draw end points, axes, etc. :( */
1055         draw_bone_update_disp_matrix_default(eBone, pchan);
1056 }
1057
1058 static void draw_bone_update_disp_matrix_custom(bPoseChannel *pchan)
1059 {
1060         float s[4][4];
1061         float length;
1062         float (*bone_mat)[4];
1063         float (*disp_mat)[4];
1064         float (*disp_tail_mat)[4];
1065
1066         /* See TODO above */
1067         length = PCHAN_CUSTOM_DRAW_SIZE(pchan);
1068         bone_mat = pchan->custom_tx ? pchan->custom_tx->pose_mat : pchan->pose_mat;
1069         disp_mat = pchan->disp_mat;
1070         disp_tail_mat = pchan->disp_tail_mat;
1071
1072         scale_m4_fl(s, length);
1073         mul_m4_m4m4(disp_mat, bone_mat, s);
1074         copy_m4_m4(disp_tail_mat, disp_mat);
1075         translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f);
1076 }
1077
1078 static void draw_axes(EditBone *eBone, bPoseChannel *pchan)
1079 {
1080         float final_col[4];
1081         const float *col = (g_theme.const_color) ? g_theme.const_color :
1082                            (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? g_theme.text_hi_color : g_theme.text_color;
1083         copy_v4_v4(final_col, col);
1084         /* Mix with axes color. */
1085         final_col[3] = (g_theme.const_color) ? 1.0 : (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? 0.3 : 0.8;
1086         drw_shgroup_bone_axes(BONE_VAR(eBone, pchan, disp_mat), final_col);
1087 }
1088
1089 static void draw_points(
1090         const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm,
1091         const int boneflag, const short constflag,
1092         const int select_id)
1093 {
1094         float col_solid_root[4], col_solid_tail[4], col_wire_root[4], col_wire_tail[4];
1095         float col_hint_root[4], col_hint_tail[4];
1096
1097         copy_v4_v4(col_solid_root, g_theme.bone_solid_color);
1098         copy_v4_v4(col_solid_tail, g_theme.bone_solid_color);
1099         copy_v4_v4(col_wire_root, (g_theme.const_color) ? g_theme.const_color : g_theme.vertex_color);
1100         copy_v4_v4(col_wire_tail, (g_theme.const_color) ? g_theme.const_color : g_theme.vertex_color);
1101
1102         const bool is_envelope_draw = (arm->drawtype == ARM_ENVELOPE);
1103         static const float envelope_ignore = -1.0f;
1104
1105         col_wire_tail[3] = col_wire_root[3] = get_bone_wire_thickness(boneflag);
1106
1107         /* Edit bone points can be selected */
1108         if (eBone) {
1109                 if (eBone->flag & BONE_ROOTSEL) {
1110                         copy_v3_v3(col_wire_root, g_theme.vertex_select_color);
1111                 }
1112                 if (eBone->flag & BONE_TIPSEL) {
1113                         copy_v3_v3(col_wire_tail, g_theme.vertex_select_color);
1114                 }
1115         }
1116         else if (arm->flag & ARM_POSEMODE) {
1117                 const float *solid_color = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag);
1118                 const float *wire_color = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
1119                 copy_v4_v4(col_wire_tail, wire_color);
1120                 copy_v4_v4(col_wire_root, wire_color);
1121                 copy_v4_v4(col_solid_tail, solid_color);
1122                 copy_v4_v4(col_solid_root, solid_color);
1123         }
1124
1125         bone_hint_color_shade(col_hint_root, (g_theme.const_color) ? col_solid_root : col_wire_root);
1126         bone_hint_color_shade(col_hint_tail, (g_theme.const_color) ? col_solid_tail : col_wire_tail);
1127
1128         /*      Draw root point if we are not connected and parent are not hidden */
1129         if ((BONE_FLAG(eBone, pchan) & BONE_CONNECTED) == 0) {
1130                 if (select_id != -1) {
1131                         DRW_select_load_id(select_id | BONESEL_ROOT);
1132                 }
1133
1134                 if (eBone) {
1135                         if (!((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent))) {
1136                                 if (is_envelope_draw) {
1137                                         drw_shgroup_bone_envelope(
1138                                                 eBone->disp_mat, col_solid_root, col_hint_root, col_wire_root,
1139                                                 &eBone->rad_head, &envelope_ignore);
1140                                 }
1141                                 else {
1142                                         drw_shgroup_bone_point(eBone->disp_mat, col_solid_root, col_hint_root, col_wire_root);
1143                                 }
1144                         }
1145                 }
1146                 else {
1147                         Bone *bone = pchan->bone;
1148                         if (!((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))) {
1149                                 if (is_envelope_draw) {
1150                                         drw_shgroup_bone_envelope(
1151                                                 pchan->disp_mat, col_solid_root, col_hint_root, col_wire_root,
1152                                                 &bone->rad_head, &envelope_ignore);
1153                                 }
1154                                 else {
1155                                         drw_shgroup_bone_point(pchan->disp_mat, col_solid_root, col_hint_root, col_wire_root);
1156                                 }
1157                         }
1158                 }
1159         }
1160
1161         /*      Draw tip point */
1162         if (select_id != -1) {
1163                 DRW_select_load_id(select_id | BONESEL_TIP);
1164         }
1165
1166         if (is_envelope_draw) {
1167                 const float *rad_tail = eBone ? &eBone->rad_tail : &pchan->bone->rad_tail;
1168                 drw_shgroup_bone_envelope(
1169                         BONE_VAR(eBone, pchan, disp_mat), col_solid_tail, col_hint_tail, col_wire_tail,
1170                         &envelope_ignore, rad_tail);
1171         }
1172         else {
1173                 drw_shgroup_bone_point(BONE_VAR(eBone, pchan, disp_tail_mat), col_solid_tail, col_hint_tail, col_wire_tail);
1174         }
1175
1176         if (select_id != -1) {
1177                 DRW_select_load_id(-1);
1178         }
1179 }
1180
1181 /** \} */
1182
1183
1184 /* -------------------------------------------------------------------- */
1185
1186 /** \name Draw Bones
1187  * \{ */
1188
1189 static void draw_bone_custom_shape(
1190         EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
1191         const int boneflag, const short constflag,
1192         const int select_id)
1193 {
1194         const float *col_solid = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag);
1195         const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
1196         const float *col_hint = get_bone_hint_color(eBone, pchan, arm, boneflag, constflag);
1197         const float (*disp_mat)[4] = pchan->disp_mat;
1198
1199         if (select_id != -1) {
1200                 DRW_select_load_id(select_id | BONESEL_BONE);
1201         }
1202
1203         if ((boneflag & BONE_DRAWWIRE) == 0) {
1204                 drw_shgroup_bone_custom_solid(disp_mat, col_solid, col_hint, col_wire, pchan->custom);
1205         }
1206         else {
1207                 drw_shgroup_bone_custom_wire(disp_mat, col_wire, pchan->custom);
1208         }
1209
1210         if (select_id != -1) {
1211                 DRW_select_load_id(-1);
1212         }
1213 }
1214
1215 static void draw_bone_envelope(
1216         EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
1217         const int boneflag, const short constflag,
1218         const int select_id)
1219 {
1220         const float *col_solid = get_bone_solid_with_consts_color(eBone, pchan, arm, boneflag, constflag);
1221         const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
1222         const float *col_hint = get_bone_hint_color(eBone, pchan, arm, boneflag, constflag);
1223
1224         float *rad_head, *rad_tail, *distance;
1225         if (eBone) {
1226                 rad_tail = &eBone->rad_tail;
1227                 distance = &eBone->dist;
1228                 rad_head = (eBone->parent && (boneflag & BONE_CONNECTED)) ? &eBone->parent->rad_tail : &eBone->rad_head;
1229         }
1230         else {
1231                 rad_tail = &pchan->bone->rad_tail;
1232                 distance = &pchan->bone->dist;
1233                 rad_head = (pchan->parent && (boneflag & BONE_CONNECTED)) ? &pchan->parent->bone->rad_tail : &pchan->bone->rad_head;
1234         }
1235
1236         if ((select_id == -1) &&
1237             (boneflag & BONE_NO_DEFORM) == 0 &&
1238             ((boneflag & BONE_SELECTED) || (eBone && (boneflag & (BONE_ROOTSEL | BONE_TIPSEL)))))
1239         {
1240                 drw_shgroup_bone_envelope_distance(BONE_VAR(eBone, pchan, disp_mat), rad_head, rad_tail, distance);
1241         }
1242
1243         if (select_id != -1) {
1244                 DRW_select_load_id(select_id | BONESEL_BONE);
1245         }
1246
1247         drw_shgroup_bone_envelope(
1248                 BONE_VAR(eBone, pchan, disp_mat), col_solid, col_hint, col_wire,
1249                 rad_head, rad_tail);
1250
1251         if (select_id != -1) {
1252                 DRW_select_load_id(-1);
1253         }
1254
1255         draw_points(eBone, pchan, arm, boneflag, constflag, select_id);
1256 }
1257
1258 static void draw_bone_line(
1259         EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
1260         const int boneflag, const short constflag, const int select_id)
1261 {
1262         const float *col_bone = get_bone_solid_with_consts_color(eBone, pchan, arm, boneflag, constflag);
1263         const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
1264         const float no_display[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1265         const float *col_head = no_display;
1266         const float *col_tail = col_bone;
1267
1268         if (eBone) {
1269                 if (eBone->flag & BONE_TIPSEL) {
1270                         col_tail = g_theme.vertex_select_color;
1271                 }
1272                 if (boneflag & BONE_SELECTED) {
1273                         col_bone = g_theme.edge_select_color;
1274                 }
1275                 col_wire = g_theme.wire_color;
1276         }
1277
1278         /*      Draw root point if we are not connected and parent are not hidden */
1279         if ((BONE_FLAG(eBone, pchan) & BONE_CONNECTED) == 0) {
1280                 if (eBone && !(eBone->parent && !EBONE_VISIBLE(arm, eBone->parent))) {
1281                         col_head = (eBone->flag & BONE_ROOTSEL) ? g_theme.vertex_select_color : col_bone;
1282                 }
1283                 else if (pchan) {
1284                         Bone *bone = pchan->bone;
1285                         if (!(bone->parent && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))) {
1286                                 col_head = col_bone;
1287                         }
1288                 }
1289         }
1290
1291         if (g_theme.const_color != NULL) {
1292                 col_wire = no_display; /* actually shrink the display. */
1293                 col_bone = col_head = col_tail = g_theme.const_color;
1294         }
1295
1296         if (select_id == -1) {
1297                 /* Not in selection mode, draw everything at once. */
1298                 drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, col_bone, col_head, col_tail);
1299         }
1300         else {
1301                 /* In selection mode, draw bone, root and tip separately. */
1302                 DRW_select_load_id(select_id | BONESEL_BONE);
1303                 drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, col_bone, no_display, no_display);
1304
1305                 if (col_head[3] > 0.0f) {
1306                         DRW_select_load_id(select_id | BONESEL_ROOT);
1307                         drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, no_display, col_head, no_display);
1308                 }
1309
1310                 DRW_select_load_id(select_id | BONESEL_TIP);
1311                 drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, no_display, no_display, col_tail);
1312
1313                 DRW_select_load_id(-1);
1314         }
1315 }
1316
1317 static void draw_bone_wire(
1318         EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
1319         const int boneflag, const short constflag,
1320         const int select_id)
1321 {
1322         const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
1323
1324         if (select_id != -1) {
1325                 DRW_select_load_id(select_id | BONESEL_BONE);
1326         }
1327
1328         if (pchan) {
1329                 Mat4 *bbones_mat = (Mat4 *)pchan->draw_data->bbone_matrix;
1330                 BLI_assert(bbones_mat != NULL);
1331
1332                 for (int i = pchan->bone->segments; i--; bbones_mat++) {
1333                         drw_shgroup_bone_wire(bbones_mat->mat, col_wire);
1334                 }
1335         }
1336         else if (eBone) {
1337                 for (int i = 0; i < eBone->segments; i++) {
1338                         drw_shgroup_bone_wire(eBone->disp_bbone_mat[i], col_wire);
1339                 }
1340         }
1341
1342         if (select_id != -1) {
1343                 DRW_select_load_id(-1);
1344         }
1345
1346         if (eBone) {
1347                 draw_points(eBone, pchan, arm, boneflag, constflag, select_id);
1348         }
1349 }
1350
1351 static void draw_bone_box(
1352         EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
1353         const int boneflag, const short constflag,
1354         const int select_id)
1355 {
1356         const float *col_solid = get_bone_solid_with_consts_color(eBone, pchan, arm, boneflag, constflag);
1357         const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
1358         const float *col_hint = get_bone_hint_color(eBone, pchan, arm, boneflag, constflag);
1359
1360         if (select_id != -1) {
1361                 DRW_select_load_id(select_id | BONESEL_BONE);
1362         }
1363
1364         if (pchan) {
1365                 Mat4 *bbones_mat = (Mat4 *)pchan->draw_data->bbone_matrix;
1366                 BLI_assert(bbones_mat != NULL);
1367
1368                 for (int i = pchan->bone->segments; i--; bbones_mat++) {
1369                         drw_shgroup_bone_box(bbones_mat->mat, col_solid, col_hint, col_wire);
1370                 }
1371         }
1372         else if (eBone) {
1373                 for (int i = 0; i < eBone->segments; i++) {
1374                         drw_shgroup_bone_box(eBone->disp_bbone_mat[i], col_solid, col_hint, col_wire);
1375                 }
1376         }
1377
1378         if (select_id != -1) {
1379                 DRW_select_load_id(-1);
1380         }
1381
1382         if (eBone) {
1383                 draw_points(eBone, pchan, arm, boneflag, constflag, select_id);
1384         }
1385 }
1386
1387 static void draw_bone_octahedral(
1388         EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
1389         const int boneflag, const short constflag,
1390         const int select_id)
1391 {
1392         const float *col_solid = get_bone_solid_with_consts_color(eBone, pchan, arm, boneflag, constflag);
1393         const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
1394         const float *col_hint = get_bone_hint_color(eBone, pchan, arm, boneflag, constflag);
1395
1396         if (select_id != -1) {
1397                 DRW_select_load_id(select_id | BONESEL_BONE);
1398         }
1399
1400         drw_shgroup_bone_octahedral(BONE_VAR(eBone, pchan, disp_mat), col_solid, col_hint, col_wire);
1401
1402         if (select_id != -1) {
1403                 DRW_select_load_id(-1);
1404         }
1405
1406         draw_points(eBone, pchan, arm, boneflag, constflag, select_id);
1407 }
1408
1409 /** \} */
1410
1411
1412 /* -------------------------------------------------------------------- */
1413
1414 /** \name Draw Relationships
1415  * \{ */
1416
1417 static void pchan_draw_ik_lines(bPoseChannel *pchan, const bool only_temp, const int constflag)
1418 {
1419         bConstraint *con;
1420         bPoseChannel *parchan;
1421         float *line_start = NULL, *line_end = NULL;
1422
1423         for (con = pchan->constraints.first; con; con = con->next) {
1424                 if (con->enforce == 0.0f)
1425                         continue;
1426
1427                 switch (con->type) {
1428                         case CONSTRAINT_TYPE_KINEMATIC:
1429                         {
1430                                 bKinematicConstraint *data = (bKinematicConstraint *)con->data;
1431                                 int segcount = 0;
1432
1433                                 /* if only_temp, only draw if it is a temporary ik-chain */
1434                                 if (only_temp && !(data->flag & CONSTRAINT_IK_TEMP))
1435                                         continue;
1436
1437                                 /* exclude tip from chain? */
1438                                 parchan = ((data->flag & CONSTRAINT_IK_TIP) == 0) ? pchan->parent : pchan;
1439                                 line_start = parchan->pose_tail;
1440
1441                                 /* Find the chain's root */
1442                                 while (parchan->parent) {
1443                                         segcount++;
1444                                         if (segcount == data->rootbone || segcount > 255) {
1445                                                 break;  /* 255 is weak */
1446                                         }
1447                                         parchan = parchan->parent;
1448                                 }
1449
1450                                 if (parchan) {
1451                                         line_end = parchan->pose_head;
1452
1453                                         if (constflag & PCHAN_HAS_TARGET)
1454                                                 drw_shgroup_bone_ik_lines(line_start, line_end);
1455                                         else
1456                                                 drw_shgroup_bone_ik_no_target_lines(line_start, line_end);
1457                                 }
1458                                 break;
1459                         }
1460                         case CONSTRAINT_TYPE_SPLINEIK:
1461                         {
1462                                 bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
1463                                 int segcount = 0;
1464
1465                                 /* don't draw if only_temp, as Spline IK chains cannot be temporary */
1466                                 if (only_temp)
1467                                         continue;
1468
1469                                 parchan = pchan;
1470                                 line_start = parchan->pose_tail;
1471
1472                                 /* Find the chain's root */
1473                                 while (parchan->parent) {
1474                                         segcount++;
1475                                         /* FIXME: revise the breaking conditions */
1476                                         if (segcount == data->chainlen || segcount > 255) break;  /* 255 is weak */
1477                                         parchan = parchan->parent;
1478                                 }
1479                                 /* Only draw line in case our chain is more than one bone long! */
1480                                 if (parchan != pchan) { /* XXX revise the breaking conditions to only stop at the tail? */
1481                                         line_end = parchan->pose_head;
1482                                         drw_shgroup_bone_ik_spline_lines(line_start, line_end);
1483                                 }
1484                                 break;
1485                         }
1486                 }
1487         }
1488 }
1489
1490 static void draw_bone_relations(
1491         EditBone *ebone, bPoseChannel *pchan, bArmature *arm,
1492         const int boneflag, const short constflag, const bool do_relations)
1493 {
1494         if (g_data.passes.relationship_lines) {
1495                 if (ebone && ebone->parent) {
1496                         if (do_relations) {
1497                                 /* Always draw for unconnected bones, regardless of selection,
1498                                  * since riggers will want to know about the links between bones
1499                                  */
1500                                 if ((boneflag & BONE_CONNECTED) == 0) {
1501                                         drw_shgroup_bone_relationship_lines(ebone->head, ebone->parent->tail);
1502                                 }
1503                         }
1504                 }
1505                 else if (pchan && pchan->parent) {
1506                         if (do_relations) {
1507                                 /* Only draw if bone or its parent is selected - reduces viewport complexity with complex rigs */
1508                                 if ((boneflag & BONE_SELECTED) ||
1509                                     (pchan->parent->bone && (pchan->parent->bone->flag & BONE_SELECTED)))
1510                                 {
1511                                         if ((boneflag & BONE_CONNECTED) == 0) {
1512                                                 drw_shgroup_bone_relationship_lines(pchan->pose_head, pchan->parent->pose_tail);
1513                                         }
1514                                 }
1515                         }
1516
1517                         /* Draw a line to IK root bone if bone is selected. */
1518                         if (arm->flag & ARM_POSEMODE) {
1519                                 if (constflag & (PCHAN_HAS_IK | PCHAN_HAS_SPLINEIK)) {
1520                                         if (boneflag & BONE_SELECTED) {
1521                                                 pchan_draw_ik_lines(pchan, !do_relations, constflag);
1522                                         }
1523                                 }
1524                         }
1525                 }
1526         }
1527 }
1528 /** \} */
1529
1530 /* -------------------------------------------------------------------- */
1531
1532 /** \name Main Draw Loops
1533  * \{ */
1534
1535 static void draw_armature_edit(Object *ob)
1536 {
1537         const DRWContextState *draw_ctx = DRW_context_state_get();
1538         EditBone *eBone;
1539         bArmature *arm = ob->data;
1540         int index;
1541         const bool is_select = DRW_state_is_select();
1542
1543         update_color(ob, NULL);
1544
1545         const bool show_text = DRW_state_show_text();
1546         const bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0);
1547
1548         for (eBone = arm->edbo->first, index = ob->select_color; eBone; eBone = eBone->next, index += 0x10000) {
1549                 if (eBone->layer & arm->layer) {
1550                         if ((eBone->flag & BONE_HIDDEN_A) == 0) {
1551                                 const int select_id = is_select ? index : (uint)-1;
1552
1553                                 const short constflag = 0;
1554
1555                                 /* catch exception for bone with hidden parent */
1556                                 int boneflag = eBone->flag;
1557                                 if ((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent)) {
1558                                         boneflag &= ~BONE_CONNECTED;
1559                                 }
1560
1561                                 /* set temporary flag for drawing bone as active, but only if selected */
1562                                 if (eBone == arm->act_edbone) {
1563                                         boneflag |= BONE_DRAW_ACTIVE;
1564                                 }
1565
1566                                 draw_bone_relations(eBone, NULL, arm, boneflag, constflag, show_relations);
1567
1568                                 if (arm->drawtype == ARM_ENVELOPE) {
1569                                         draw_bone_update_disp_matrix_default(eBone, NULL);
1570                                         draw_bone_envelope(eBone, NULL, arm, boneflag, constflag, select_id);
1571                                 }
1572                                 else if (arm->drawtype == ARM_LINE) {
1573                                         draw_bone_update_disp_matrix_default(eBone, NULL);
1574                                         draw_bone_line(eBone, NULL, arm, boneflag, constflag, select_id);
1575                                 }
1576                                 else if (arm->drawtype == ARM_WIRE) {
1577                                         draw_bone_update_disp_matrix_bbone(eBone, NULL);
1578                                         draw_bone_wire(eBone, NULL, arm, boneflag, constflag, select_id);
1579                                 }
1580                                 else if (arm->drawtype == ARM_B_BONE) {
1581                                         draw_bone_update_disp_matrix_bbone(eBone, NULL);
1582                                         draw_bone_box(eBone, NULL, arm, boneflag, constflag, select_id);
1583                                 }
1584                                 else {
1585                                         draw_bone_update_disp_matrix_default(eBone, NULL);
1586                                         draw_bone_octahedral(eBone, NULL, arm, boneflag, constflag, select_id);
1587                                 }
1588
1589                                 /* Draw names of bone */
1590                                 if (show_text && (arm->flag & ARM_DRAWNAMES)) {
1591                                         uchar color[4];
1592                                         UI_GetThemeColor4ubv((eBone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, color);
1593
1594                                         float vec[3];
1595                                         mid_v3_v3v3(vec, eBone->head, eBone->tail);
1596                                         mul_m4_v3(ob->obmat, vec);
1597
1598                                         struct DRWTextStore *dt = DRW_text_cache_ensure();
1599                                         DRW_text_cache_add(
1600                                                 dt, vec, eBone->name, strlen(eBone->name),
1601                                                 10, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color);
1602                                 }
1603
1604                                 /*      Draw additional axes */
1605                                 if (arm->flag & ARM_DRAWAXES) {
1606                                         draw_axes(eBone, NULL);
1607                                 }
1608                         }
1609                 }
1610         }
1611 }
1612
1613 /* if const_color is NULL do pose mode coloring */
1614 static void draw_armature_pose(Object *ob, const float const_color[4])
1615 {
1616         const DRWContextState *draw_ctx = DRW_context_state_get();
1617         bArmature *arm = ob->data;
1618         bPoseChannel *pchan;
1619         int index = -1;
1620         Bone *bone;
1621
1622         update_color(ob, const_color);
1623
1624         /* We can't safely draw non-updated pose, might contain NULL bone pointers... */
1625         if (ob->pose->flag & POSE_RECALC) {
1626                 BKE_pose_rebuild(NULL, ob, arm);
1627         }
1628
1629         // if (!(base->flag & OB_FROMDUPLI)) // TODO
1630         {
1631                 if ((draw_ctx->object_mode & OB_MODE_POSE) || (ob == draw_ctx->object_pose)) {
1632                         arm->flag |= ARM_POSEMODE;
1633                 }
1634
1635                 if (arm->flag & ARM_POSEMODE) {
1636                         index = ob->select_color;
1637                 }
1638         }
1639
1640         const bool is_pose_select = (arm->flag & ARM_POSEMODE) && DRW_state_is_select();
1641         const bool show_text = DRW_state_show_text();
1642         const bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0);
1643
1644         /* being set below */
1645         for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1646                 bone = pchan->bone;
1647
1648                 /* bone must be visible */
1649                 if ((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) {
1650                         if (bone->layer & arm->layer) {
1651                                 const int select_id = is_pose_select ? index : (uint)-1;
1652
1653                                 const short constflag = pchan->constflag;
1654
1655                                 pchan_draw_data_init(pchan);
1656
1657                                 if (const_color) {
1658                                         /* keep color */
1659                                 }
1660                                 else {
1661                                         /* set color-set to use */
1662                                         set_pchan_colorset(ob, pchan);
1663                                 }
1664
1665                                 int boneflag = bone->flag;
1666                                 /* catch exception for bone with hidden parent */
1667                                 boneflag = bone->flag;
1668                                 if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
1669                                         boneflag &= ~BONE_CONNECTED;
1670                                 }
1671
1672                                 /* set temporary flag for drawing bone as active, but only if selected */
1673                                 if (bone == arm->act_bone)
1674                                         boneflag |= BONE_DRAW_ACTIVE;
1675
1676                                 draw_bone_relations(NULL, pchan, arm, boneflag, constflag, show_relations);
1677
1678                                 if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) {
1679                                         draw_bone_update_disp_matrix_custom(pchan);
1680                                         draw_bone_custom_shape(NULL, pchan, arm, boneflag, constflag, select_id);
1681                                 }
1682                                 else if (arm->drawtype == ARM_ENVELOPE) {
1683                                         draw_bone_update_disp_matrix_default(NULL, pchan);
1684                                         draw_bone_envelope(NULL, pchan, arm, boneflag, constflag, select_id);
1685                                 }
1686                                 else if (arm->drawtype == ARM_LINE) {
1687                                         draw_bone_update_disp_matrix_default(NULL, pchan);
1688                                         draw_bone_line(NULL, pchan, arm, boneflag, constflag, select_id);
1689                                 }
1690                                 else if (arm->drawtype == ARM_WIRE) {
1691                                         draw_bone_update_disp_matrix_bbone(NULL, pchan);
1692                                         draw_bone_wire(NULL, pchan, arm, boneflag, constflag, select_id);
1693                                 }
1694                                 else if (arm->drawtype == ARM_B_BONE) {
1695                                         draw_bone_update_disp_matrix_bbone(NULL, pchan);
1696                                         draw_bone_box(NULL, pchan, arm, boneflag, constflag, select_id);
1697                                 }
1698                                 else {
1699                                         draw_bone_update_disp_matrix_default(NULL, pchan);
1700                                         draw_bone_octahedral(NULL, pchan, arm, boneflag, constflag, select_id);
1701                                 }
1702
1703                                 /* Draw names of bone */
1704                                 if (show_text && (arm->flag & ARM_DRAWNAMES)) {
1705                                         uchar color[4];
1706                                         UI_GetThemeColor4ubv((arm->flag & ARM_POSEMODE) &&
1707                                                              (bone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, color);
1708                                         float vec[3];
1709                                         mid_v3_v3v3(vec, pchan->pose_head, pchan->pose_tail);
1710                                         mul_m4_v3(ob->obmat, vec);
1711
1712                                         struct DRWTextStore *dt = DRW_text_cache_ensure();
1713                                         DRW_text_cache_add(
1714                                                 dt, vec, pchan->name, strlen(pchan->name),
1715                                                 10, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color);
1716                                 }
1717
1718                                 /*      Draw additional axes */
1719                                 if (arm->flag & ARM_DRAWAXES) {
1720                                         draw_axes(NULL, pchan);
1721                                 }
1722                         }
1723                 }
1724                 if (is_pose_select) {
1725                         index += 0x10000;
1726                 }
1727         }
1728
1729         arm->flag &= ~ARM_POSEMODE;
1730 }
1731
1732 /**
1733  * This function set the object space to use for all subsequent `DRW_shgroup_bone_*` calls.
1734  */
1735 static void drw_shgroup_armature(Object *ob, DRWArmaturePasses passes)
1736 {
1737         memset(&g_data, 0x0, sizeof(g_data));
1738         g_data.ob = ob;
1739         g_data.passes = passes;
1740         memset(&g_color, 0x0, sizeof(g_color));
1741 }
1742
1743 void DRW_shgroup_armature_object(Object *ob, ViewLayer *view_layer, DRWArmaturePasses passes)
1744 {
1745         float *color;
1746         DRW_object_wire_theme_get(ob, view_layer, &color);
1747         passes.bone_envelope = NULL; /* Don't do envelope distance in object mode. */
1748         drw_shgroup_armature(ob, passes);
1749         draw_armature_pose(ob, color);
1750 }
1751
1752 void DRW_shgroup_armature_pose(Object *ob, DRWArmaturePasses passes)
1753 {
1754         drw_shgroup_armature(ob, passes);
1755         draw_armature_pose(ob, NULL);
1756 }
1757
1758 void DRW_shgroup_armature_edit(Object *ob, DRWArmaturePasses passes)
1759 {
1760         drw_shgroup_armature(ob, passes);
1761         draw_armature_edit(ob);
1762 }
1763
1764 /** \} */