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