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