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