Object Mode: Add to EvaluationContext & DRWContextState
[blender.git] / source / blender / draw / intern / draw_armature.c
1 /*
2  * Copyright 2016, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Institute
19  *
20  */
21
22 /** \file draw_armature.c
23  *  \ingroup draw
24  */
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <math.h>
29
30 #include "DNA_anim_types.h"
31 #include "DNA_armature_types.h"
32 #include "DNA_constraint_types.h"
33 #include "DNA_scene_types.h"
34 #include "DNA_screen_types.h"
35 #include "DNA_view3d_types.h"
36 #include "DNA_object_types.h"
37
38 #include "DRW_render.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_math.h"
42 #include "BLI_dlrbTree.h"
43 #include "BLI_utildefines.h"
44
45 #include "BKE_animsys.h"
46 #include "BKE_action.h"
47 #include "BKE_armature.h"
48 #include "BKE_global.h"
49 #include "BKE_modifier.h"
50 #include "BKE_nla.h"
51 #include "BKE_curve.h"
52
53 #include "BIF_gl.h"
54
55 #include "ED_armature.h"
56 #include "ED_keyframes_draw.h"
57
58 #include "GPU_select.h"
59
60 #include "UI_resources.h"
61
62 #include "draw_common.h"
63 #include "draw_manager_text.h"
64
65 #define BONE_VAR(eBone, pchan, var) ((eBone) ? (eBone->var) : (pchan->var))
66 #define BONE_FLAG(eBone, pchan) ((eBone) ? (eBone->flag) : (pchan->bone->flag))
67
68 /* For now just match 2.7x where possible. */
69 // #define USE_SOLID_COLOR
70
71 /* Reset for drawing each armature object */
72 static struct {
73         /* Current armature object */
74         Object *ob;
75         /* Reset when changing current_armature */
76         DRWShadingGroup *bone_octahedral_solid;
77         DRWShadingGroup *bone_octahedral_wire;
78         DRWShadingGroup *bone_box_solid;
79         DRWShadingGroup *bone_box_wire;
80         DRWShadingGroup *bone_wire_wire;
81         DRWShadingGroup *bone_envelope_solid;
82         DRWShadingGroup *bone_envelope_distance;
83         DRWShadingGroup *bone_envelope_wire;
84         DRWShadingGroup *bone_envelope_head_wire;
85         DRWShadingGroup *bone_point_solid;
86         DRWShadingGroup *bone_point_wire;
87         DRWShadingGroup *bone_axes;
88         DRWShadingGroup *relationship_lines;
89
90         DRWPass *pass_bone_solid;
91         DRWPass *pass_bone_wire;
92         DRWPass *pass_bone_envelope;
93 } g_data = {NULL};
94
95 /* -------------------------------------------------------------------- */
96
97 /** \name Shader Groups (DRW_shgroup)
98  * \{ */
99
100 /* Octahedral */
101 static void drw_shgroup_bone_octahedral_solid(const float (*bone_mat)[4], const float color[4])
102 {
103         if (g_data.bone_octahedral_solid == NULL) {
104                 struct Gwn_Batch *geom = DRW_cache_bone_octahedral_get();
105                 g_data.bone_octahedral_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom);
106         }
107         float final_bonemat[4][4];
108         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
109         DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_solid, final_bonemat, color);
110 }
111
112 static void drw_shgroup_bone_octahedral_wire(const float (*bone_mat)[4], const float color[4])
113 {
114         if (g_data.bone_octahedral_wire == NULL) {
115                 struct Gwn_Batch *geom = DRW_cache_bone_octahedral_wire_outline_get();
116                 g_data.bone_octahedral_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
117         }
118         float final_bonemat[4][4];
119         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
120         DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_wire, final_bonemat, color);
121 }
122
123 /* Box / B-Bone */
124 static void drw_shgroup_bone_box_solid(const float (*bone_mat)[4], const float color[4])
125 {
126         if (g_data.bone_box_solid == NULL) {
127                 struct Gwn_Batch *geom = DRW_cache_bone_box_get();
128                 g_data.bone_box_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom);
129         }
130         float final_bonemat[4][4];
131         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
132         DRW_shgroup_call_dynamic_add(g_data.bone_box_solid, final_bonemat, color);
133 }
134
135 static void drw_shgroup_bone_box_wire(const float (*bone_mat)[4], const float color[4])
136 {
137         if (g_data.bone_box_wire == NULL) {
138                 struct Gwn_Batch *geom = DRW_cache_bone_box_wire_outline_get();
139                 g_data.bone_box_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
140         }
141         float final_bonemat[4][4];
142         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
143         DRW_shgroup_call_dynamic_add(g_data.bone_box_wire, final_bonemat, color);
144 }
145
146 /* Wire */
147 static void drw_shgroup_bone_wire_wire(const float (*bone_mat)[4], const float color[4])
148 {
149         if (g_data.bone_wire_wire == NULL) {
150                 struct Gwn_Batch *geom = DRW_cache_bone_wire_wire_outline_get();
151                 g_data.bone_wire_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
152         }
153         float final_bonemat[4][4];
154         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
155         DRW_shgroup_call_dynamic_add(g_data.bone_wire_wire, final_bonemat, color);
156 }
157
158 /* Envelope */
159 static void drw_shgroup_bone_envelope_distance(
160         const float (*bone_mat)[4], const float color[4],
161         const float *radius_head, const float *radius_tail, const float *distance)
162 {
163         if (g_data.pass_bone_envelope != NULL) {
164                 if (g_data.bone_envelope_distance == NULL) {
165                         struct Gwn_Batch *geom = DRW_cache_bone_envelope_distance_outline_get();
166                         /* Note: bone_wire draw pass is not really working, think we need another one here? */
167                         g_data.bone_envelope_distance = shgroup_instance_bone_envelope_wire(g_data.pass_bone_envelope, geom);
168                 }
169                 float final_bonemat[4][4];
170                 mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
171                 DRW_shgroup_call_dynamic_add(g_data.bone_envelope_distance, final_bonemat, color, radius_head, radius_tail, distance);
172         }
173 }
174
175 static void drw_shgroup_bone_envelope_solid(
176         const float (*bone_mat)[4], const float color[4],
177         const float *radius_head, const float *radius_tail)
178 {
179         if (g_data.bone_envelope_solid == NULL) {
180                 struct Gwn_Batch *geom = DRW_cache_bone_envelope_solid_get();
181                 g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(g_data.pass_bone_solid, geom);
182         }
183         float final_bonemat[4][4];
184         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
185         DRW_shgroup_call_dynamic_add(g_data.bone_envelope_solid, final_bonemat, color, radius_head, radius_tail);
186 }
187
188 static void drw_shgroup_bone_envelope_wire(
189         const float (*bone_mat)[4], const float color[4],
190         const float *radius_head, const float *radius_tail, const float *distance)
191 {
192         if (g_data.bone_envelope_wire == NULL) {
193                 struct Gwn_Batch *geom = DRW_cache_bone_envelope_wire_outline_get();
194                 g_data.bone_envelope_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom);
195         }
196         float final_bonemat[4][4];
197         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
198         DRW_shgroup_call_dynamic_add(g_data.bone_envelope_wire, final_bonemat, color, radius_head, radius_tail, distance);
199 }
200
201 static void drw_shgroup_bone_envelope_head_wire(
202         const float (*bone_mat)[4], const float color[4],
203         const float *radius_head, const float *radius_tail, const float *distance)
204 {
205         if (g_data.bone_envelope_head_wire == NULL) {
206                 struct Gwn_Batch *geom = DRW_cache_bone_envelope_head_wire_outline_get();
207                 g_data.bone_envelope_head_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom);
208         }
209         float final_bonemat[4][4];
210         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
211         DRW_shgroup_call_dynamic_add(g_data.bone_envelope_head_wire, final_bonemat, color, radius_head, radius_tail, distance);
212 }
213
214 /* Custom (geometry) */
215
216 static void drw_shgroup_bone_custom_solid(const float (*bone_mat)[4], const float color[4], Object *custom)
217 {
218         /* grr, not re-using instances! */
219         struct Gwn_Batch *geom = DRW_cache_object_surface_get(custom);
220         if (geom) {
221                 DRWShadingGroup *shgrp_geom_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom);
222                 float final_bonemat[4][4];
223                 mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
224                 DRW_shgroup_call_dynamic_add(shgrp_geom_solid, final_bonemat, color);
225         }
226 }
227
228 static void drw_shgroup_bone_custom_wire(const float (*bone_mat)[4], const float color[4], Object *custom)
229 {
230         /* grr, not re-using instances! */
231         struct Gwn_Batch *geom = DRW_cache_object_wire_outline_get(custom);
232         if (geom) {
233                 DRWShadingGroup *shgrp_geom_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
234                 float final_bonemat[4][4];
235                 mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
236                 DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, color);
237         }
238 }
239
240 /* Head and tail sphere */
241 static void drw_shgroup_bone_point_solid(const float (*bone_mat)[4], const float color[4])
242 {
243         if (g_data.bone_point_solid == NULL) {
244                 struct Gwn_Batch *geom = DRW_cache_bone_point_get();
245                 g_data.bone_point_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom);
246         }
247         float final_bonemat[4][4];
248         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
249         DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, final_bonemat, color);
250 }
251
252 static void drw_shgroup_bone_point_wire(const float (*bone_mat)[4], const float color[4])
253 {
254         if (g_data.bone_point_wire == NULL) {
255                 struct Gwn_Batch *geom = DRW_cache_bone_point_wire_outline_get();
256                 g_data.bone_point_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
257         }
258         float final_bonemat[4][4];
259         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
260         DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, final_bonemat, color);
261 }
262
263 /* Axes */
264 static void drw_shgroup_bone_axes(const float (*bone_mat)[4], const float color[4])
265 {
266         if (g_data.bone_axes == NULL) {
267                 struct Gwn_Batch *geom = DRW_cache_bone_arrows_get();
268                 g_data.bone_axes = shgroup_instance_wire(g_data.pass_bone_wire, geom);
269         }
270         float final_bonemat[4][4];
271         mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
272         DRW_shgroup_call_dynamic_add(g_data.bone_axes, final_bonemat, color);
273 }
274
275 /* Relationship lines */
276 static void UNUSED_FUNCTION(drw_shgroup_bone_relationship_lines)(const float head[3], const float tail[3])
277 {
278         DRW_shgroup_call_dynamic_add(g_data.relationship_lines, head);
279         DRW_shgroup_call_dynamic_add(g_data.relationship_lines, tail);
280 }
281
282 /** \} */
283
284
285 /* -------------------------------------------------------------------- */
286
287 /** \name Drawing Theme Helpers
288  *
289  * Note, this section is duplicate of code in 'drawarmature.c'.
290  *
291  * \{ */
292
293 /* global here is reset before drawing each bone */
294 struct {
295         const ThemeWireColor *bcolor;
296 } g_color;
297
298 /* values of colCode for set_pchan_color */
299 enum {
300         PCHAN_COLOR_NORMAL  = 0,        /* normal drawing */
301         PCHAN_COLOR_SOLID,              /* specific case where "solid" color is needed */
302         PCHAN_COLOR_CONSTS,             /* "constraint" colors (which may/may-not be suppressed) */
303
304         PCHAN_COLOR_SPHEREBONE_BASE,    /* for the 'stick' of sphere (envelope) bones */
305         PCHAN_COLOR_SPHEREBONE_END,     /* for the ends of sphere (envelope) bones */
306         PCHAN_COLOR_LINEBONE            /* for the middle of line-bones */
307 };
308
309 /* This function sets the color-set for coloring a certain bone */
310 static void set_pchan_colorset(Object *ob, bPoseChannel *pchan)
311 {
312         bPose *pose = (ob) ? ob->pose : NULL;
313         bArmature *arm = (ob) ? ob->data : NULL;
314         bActionGroup *grp = NULL;
315         short color_index = 0;
316
317         /* sanity check */
318         if (ELEM(NULL, ob, arm, pose, pchan)) {
319                 g_color.bcolor = NULL;
320                 return;
321         }
322
323         /* only try to set custom color if enabled for armature */
324         if (arm->flag & ARM_COL_CUSTOM) {
325                 /* currently, a bone can only use a custom color set if it's group (if it has one),
326                  * has been set to use one
327                  */
328                 if (pchan->agrp_index) {
329                         grp = (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
330                         if (grp)
331                                 color_index = grp->customCol;
332                 }
333         }
334
335         /* bcolor is a pointer to the color set to use. If NULL, then the default
336          * color set (based on the theme colors for 3d-view) is used.
337          */
338         if (color_index > 0) {
339                 bTheme *btheme = UI_GetTheme();
340                 g_color.bcolor = &btheme->tarm[(color_index - 1)];
341         }
342         else if (color_index == -1) {
343                 /* use the group's own custom color set (grp is always != NULL here) */
344                 g_color.bcolor = &grp->cs;
345         }
346         else {
347                 g_color.bcolor = NULL;
348         }
349 }
350
351 /* This function is for brightening/darkening a given color (like UI_GetThemeColorShade3ubv()) */
352 static void cp_shade_color3ub(unsigned char cp[3], const int offset)
353 {
354         int r, g, b;
355
356         r = offset + (int) cp[0];
357         CLAMP(r, 0, 255);
358         g = offset + (int) cp[1];
359         CLAMP(g, 0, 255);
360         b = offset + (int) cp[2];
361         CLAMP(b, 0, 255);
362
363         cp[0] = r;
364         cp[1] = g;
365         cp[2] = b;
366 }
367
368 /* This function sets the gl-color for coloring a certain bone (based on bcolor) */
369 static bool set_pchan_color(short colCode, const int boneflag, const short constflag, float r_color[4])
370 {
371         float *fcolor = r_color;
372         const ThemeWireColor *bcolor = g_color.bcolor;
373
374         switch (colCode) {
375                 case PCHAN_COLOR_NORMAL:
376                 {
377                         if (bcolor) {
378                                 unsigned char cp[4] = {255};
379
380                                 if (boneflag & BONE_DRAW_ACTIVE) {
381                                         copy_v3_v3_char((char *)cp, bcolor->active);
382                                         if (!(boneflag & BONE_SELECTED)) {
383                                                 cp_shade_color3ub(cp, -80);
384                                         }
385                                 }
386                                 else if (boneflag & BONE_SELECTED) {
387                                         copy_v3_v3_char((char *)cp, bcolor->select);
388                                 }
389                                 else {
390                                         /* a bit darker than solid */
391                                         copy_v3_v3_char((char *)cp, bcolor->solid);
392                                         cp_shade_color3ub(cp, -50);
393                                 }
394
395                                 rgb_uchar_to_float(fcolor, cp);
396                         }
397                         else {
398                                 if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) {
399                                         UI_GetThemeColor4fv(TH_BONE_POSE_ACTIVE, fcolor);
400                                 }
401                                 else if (boneflag & BONE_DRAW_ACTIVE) {
402                                         UI_GetThemeColorBlendShade4fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, fcolor);
403                                 }
404                                 else if (boneflag & BONE_SELECTED) {
405                                         UI_GetThemeColor4fv(TH_BONE_POSE, fcolor);
406                                 }
407                                 else {
408                                         UI_GetThemeColor4fv(TH_WIRE, fcolor);
409                                 }
410                         }
411
412                         return true;
413                 }
414                 case PCHAN_COLOR_SOLID:
415                 {
416                         if (bcolor) {
417                                 rgb_uchar_to_float(fcolor, (unsigned char *)bcolor->solid);
418                         }
419                         else {
420                                 UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
421                         }
422
423                         return true;
424                 }
425                 case PCHAN_COLOR_CONSTS:
426                 {
427                         if ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) {
428                                 unsigned char cp[4];
429                                 if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 80);
430                                 else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 80);
431                                 else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 80);
432                                 else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 80);
433
434                                 rgba_uchar_to_float(fcolor, cp);
435
436                                 return true;
437                         }
438                         return false;
439                 }
440                 case PCHAN_COLOR_SPHEREBONE_BASE:
441                 {
442                         if (bcolor) {
443                                 unsigned char cp[4] = {255};
444
445                                 if (boneflag & BONE_DRAW_ACTIVE) {
446                                         copy_v3_v3_char((char *)cp, bcolor->active);
447                                 }
448                                 else if (boneflag & BONE_SELECTED) {
449                                         copy_v3_v3_char((char *)cp, bcolor->select);
450                                 }
451                                 else {
452                                         copy_v3_v3_char((char *)cp, bcolor->solid);
453                                 }
454
455                                 rgb_uchar_to_float(fcolor, cp);
456                         }
457                         else {
458                                 if (boneflag & BONE_DRAW_ACTIVE) {
459                                         UI_GetThemeColorShade4fv(TH_BONE_POSE, 40, fcolor);
460                                 }
461                                 else if (boneflag & BONE_SELECTED) {
462                                         UI_GetThemeColor4fv(TH_BONE_POSE, fcolor);
463                                 }
464                                 else {
465                                         UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
466                                 }
467                         }
468
469                         return true;
470                 }
471                 case PCHAN_COLOR_SPHEREBONE_END:
472                 {
473                         if (bcolor) {
474                                 unsigned char cp[4] = {255};
475
476                                 if (boneflag & BONE_DRAW_ACTIVE) {
477                                         copy_v3_v3_char((char *)cp, bcolor->active);
478                                         cp_shade_color3ub(cp, 10);
479                                 }
480                                 else if (boneflag & BONE_SELECTED) {
481                                         copy_v3_v3_char((char *)cp, bcolor->select);
482                                         cp_shade_color3ub(cp, -30);
483                                 }
484                                 else {
485                                         copy_v3_v3_char((char *)cp, bcolor->solid);
486                                         cp_shade_color3ub(cp, -30);
487                                 }
488
489                                 rgb_uchar_to_float(fcolor, cp);
490                         }
491                         else {
492                                 if (boneflag & BONE_DRAW_ACTIVE) {
493                                         UI_GetThemeColorShade4fv(TH_BONE_POSE, 10, fcolor);
494                                 }
495                                 else if (boneflag & BONE_SELECTED) {
496                                         UI_GetThemeColorShade4fv(TH_BONE_POSE, -30, fcolor);
497                                 }
498                                 else {
499                                         UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
500                                 }
501                         }
502                         break;
503                 }
504                 case PCHAN_COLOR_LINEBONE:
505                 {
506                         /* inner part in background color or constraint */
507                         if ((constflag) && ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS))) {
508                                 unsigned char cp[4];
509                                 if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 255);
510                                 else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 255);
511                                 else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 255);
512                                 else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 255);
513                                 else if (constflag) UI_GetThemeColor4ubv(TH_BONE_POSE, cp);  /* PCHAN_HAS_ACTION */
514
515                                 rgb_uchar_to_float(fcolor, cp);
516                         }
517                         else {
518                                 if (bcolor) {
519                                         const char *cp = bcolor->solid;
520                                         rgb_uchar_to_float(fcolor, (unsigned char *)cp);
521                                         fcolor[3] = 204.f / 255.f;
522                                 }
523                                 else {
524                                         UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor);
525                                 }
526                         }
527
528                         return true;
529                 }
530         }
531
532         return false;
533 }
534
535 /** \} */
536
537
538 /* -------------------------------------------------------------------- */
539
540 /** \name Drawing Color Helpers
541  * \{ */
542
543 /**
544  * Follow `TH_*` naming except for mixed colors.
545  */
546 static struct {
547         float select_color[4];
548         float edge_select_color[4];
549         float bone_select_color[4];  /* tint */
550         float wire_color[4];
551         float wire_edit_color[4];
552         float bone_solid_color[4];
553         float bone_active_unselect_color[4];  /* mix */
554         float bone_pose_color[4];
555         float bone_pose_active_color[4];
556         float bone_pose_active_unselect_color[4];  /* mix */
557         float text_hi_color[4];
558         float text_color[4];
559         float vertex_select_color[4];
560         float vertex_color[4];
561
562         /* not a theme, this is an override */
563         const float *const_color;
564 } g_theme;
565
566 /** See: 'set_pchan_color'*/
567 static void update_color(const float const_color[4])
568 {
569         g_theme.const_color = const_color;
570
571 #define NO_ALPHA(c) (((c)[3] = 1.0f), (c))
572
573         UI_GetThemeColor3fv(TH_SELECT, NO_ALPHA(g_theme.select_color));
574         UI_GetThemeColor3fv(TH_EDGE_SELECT, NO_ALPHA(g_theme.edge_select_color));
575         UI_GetThemeColorShade3fv(TH_EDGE_SELECT, -20, NO_ALPHA(g_theme.bone_select_color));
576         UI_GetThemeColor3fv(TH_WIRE, NO_ALPHA(g_theme.wire_color));
577         UI_GetThemeColor3fv(TH_WIRE_EDIT, NO_ALPHA(g_theme.wire_edit_color));
578         UI_GetThemeColor3fv(TH_BONE_SOLID, NO_ALPHA(g_theme.bone_solid_color));
579         UI_GetThemeColorBlendShade3fv(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f, 0, NO_ALPHA(g_theme.bone_active_unselect_color));
580         UI_GetThemeColor3fv(TH_BONE_POSE, NO_ALPHA(g_theme.bone_pose_color));
581         UI_GetThemeColor3fv(TH_BONE_POSE_ACTIVE, NO_ALPHA(g_theme.bone_pose_active_color));
582         UI_GetThemeColorBlendShade3fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, NO_ALPHA(g_theme.bone_pose_active_unselect_color));
583         UI_GetThemeColor3fv(TH_TEXT_HI, NO_ALPHA(g_theme.text_hi_color));
584         UI_GetThemeColor3fv(TH_TEXT, NO_ALPHA(g_theme.text_color));
585         UI_GetThemeColor3fv(TH_VERTEX_SELECT, NO_ALPHA(g_theme.vertex_select_color));
586         UI_GetThemeColor3fv(TH_VERTEX, NO_ALPHA(g_theme.vertex_color));
587
588 #undef NO_ALPHA
589 }
590
591 static const float *get_bone_solid_color(
592         const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm,
593         const int boneflag, const short constflag)
594 {
595         if (g_theme.const_color)
596                 return g_theme.bone_solid_color;
597
598 #ifdef USE_SOLID_COLOR
599         /* Edit Mode */
600         if (eBone) {
601                 bool is_active = (arm->act_edbone == eBone);
602                 if (eBone->flag & BONE_SELECTED) {
603                         if (is_active) {
604                                 return g_theme.edge_select_color;
605                         }
606                         else {
607                                 return g_theme.bone_select_color;
608                         }
609                 }
610         }
611         else if (arm->flag & ARM_POSEMODE) {
612                 bool is_active = (arm->act_bone == pchan->bone);
613                 if (pchan->bone->flag & BONE_SELECTED) {
614                         if (is_active) {
615                                 return g_theme.bone_pose_active_color;
616                         }
617                         else {
618                                 return g_theme.bone_pose_color;
619                         }
620                 }
621         }
622 #else
623         if (arm->drawtype == ARM_ENVELOPE) {
624                 /* Edit Mode */
625                 if (eBone) {
626                         bool is_active = (arm->act_edbone == eBone);
627                         if (eBone->flag & BONE_SELECTED) {
628                                 if (is_active) {
629                                         return g_theme.edge_select_color;
630                                 }
631                                 else {
632                                         return g_theme.bone_select_color;
633                                 }
634                         }
635                 }
636                 else if (arm->flag & ARM_POSEMODE) {
637                         bool is_active = (arm->act_bone == pchan->bone);
638                         if (pchan->bone->flag & BONE_SELECTED) {
639                                 if (is_active) {
640                                         return g_theme.bone_pose_active_color;
641                                 }
642                                 else {
643                                         return g_theme.bone_pose_color;
644                                 }
645                         }
646                 }
647         }
648 #endif
649
650         if (arm->flag & ARM_POSEMODE) {
651                 float *disp_color = pchan->draw_data->solid_color;
652                 set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag, disp_color);
653                 disp_color[3] = 1.0;
654                 return disp_color;
655         }
656
657         return g_theme.bone_solid_color;
658 }
659
660 static const float *get_bone_wire_color(
661         const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm,
662         const int boneflag, const short constflag)
663 {
664         if (g_theme.const_color)
665                 return g_theme.const_color;
666
667         if (eBone) {
668                 if (boneflag & BONE_SELECTED) {
669                         if (boneflag & BONE_DRAW_ACTIVE) {
670                                 return g_theme.edge_select_color;
671                         }
672                         else {
673                                 return g_theme.bone_select_color;
674                         }
675                 }
676                 else {
677                         if (boneflag & BONE_DRAW_ACTIVE) {
678                                 return g_theme.bone_active_unselect_color;
679                         }
680                         else {
681                                 return g_theme.wire_edit_color;
682                         }
683                 }
684         }
685         else if (arm->flag & ARM_POSEMODE) {
686                 float *disp_color = pchan->draw_data->wire_color;
687                 set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag, disp_color);
688                 disp_color[3] = 1.0;
689                 return disp_color;
690
691
692 #if 0
693                 if (boneflag & BONE_SELECTED) {
694                         if (is_active) {
695                                 return g_theme.bone_pose_active_color;
696                         }
697                         else {
698                                 return g_theme.bone_pose_color;
699                         }
700                 }
701                 else {
702                         if (is_active) {
703                                 return g_theme.bone_pose_active_unselect_color;
704                         }
705                         else {
706                                 return g_theme.wire_color;
707                         }
708                 }
709 #endif
710         }
711
712         return g_theme.vertex_color;
713 }
714
715 /** \} */
716
717
718 /* -------------------------------------------------------------------- */
719
720 /** \name Helper Utils
721  * \{ */
722
723 static void pchan_draw_data_init(bPoseChannel *pchan)
724 {
725         if (pchan->draw_data != NULL) {
726                 if (pchan->draw_data->bbone_matrix_len != pchan->bone->segments) {
727                         MEM_SAFE_FREE(pchan->draw_data);
728                 }
729         }
730
731         if (pchan->draw_data == NULL) {
732                 pchan->draw_data = MEM_mallocN(sizeof(*pchan->draw_data) + sizeof(Mat4) * pchan->bone->segments, __func__);
733                 pchan->draw_data->bbone_matrix_len = pchan->bone->segments;
734         }
735 }
736
737 static void draw_bone_update_disp_matrix_default(EditBone *eBone, bPoseChannel *pchan)
738 {
739         float s[4][4], ebmat[4][4];
740         float length;
741         float (*bone_mat)[4];
742         float (*disp_mat)[4];
743         float (*disp_tail_mat)[4];
744
745         /* TODO : This should be moved to depsgraph or armature refresh
746          * and not be tight to the draw pass creation.
747          * This would refresh armature without invalidating the draw cache */
748         if (pchan) {
749                 length = pchan->bone->length;
750                 bone_mat = pchan->pose_mat;
751                 disp_mat = pchan->disp_mat;
752                 disp_tail_mat = pchan->disp_tail_mat;
753         }
754         else {
755                 eBone->length = len_v3v3(eBone->tail, eBone->head);
756                 ED_armature_ebone_to_mat4(eBone, ebmat);
757
758                 length = eBone->length;
759                 bone_mat = ebmat;
760                 disp_mat = eBone->disp_mat;
761                 disp_tail_mat = eBone->disp_tail_mat;
762         }
763
764         scale_m4_fl(s, length);
765         mul_m4_m4m4(disp_mat, bone_mat, s);
766         copy_m4_m4(disp_tail_mat, disp_mat);
767         translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f);
768 }
769
770 /* XXX Direct copy from drawarmature.c... This is ugly! */
771 /* A partial copy of b_bone_spline_setup(), with just the parts for previewing editmode curve settings
772  *
773  * This assumes that prev/next bones don't have any impact (since they should all still be in the "straight"
774  * position here anyway), and that we can simply apply the bbone settings to get the desired effect...
775  */
776 static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_SUBDIV][4][4])
777 {
778         float h1[3], h2[3], length, hlength1, hlength2, roll1 = 0.0f, roll2 = 0.0f;
779         float mat3[3][3];
780         float data[MAX_BBONE_SUBDIV + 1][4], *fp;
781         int a;
782
783         length = ebone->length;
784
785         hlength1 = ebone->ease1 * length * 0.390464f; /* 0.5f * sqrt(2) * kappa, the handle length for near-perfect circles */
786         hlength2 = ebone->ease2 * length * 0.390464f;
787
788         /* find the handle points, since this is inside bone space, the
789          * first point = (0, 0, 0)
790          * last point =  (0, length, 0)
791          *
792          * we also just apply all the "extra effects", since they're the whole reason we're doing this...
793          */
794         h1[0] = ebone->curveInX;
795         h1[1] = hlength1;
796         h1[2] = ebone->curveInY;
797         roll1 = ebone->roll1;
798
799         h2[0] = ebone->curveOutX;
800         h2[1] = -hlength2;
801         h2[2] = ebone->curveOutY;
802         roll2 = ebone->roll2;
803
804         /* make curve */
805         if (ebone->segments > MAX_BBONE_SUBDIV)
806                 ebone->segments = MAX_BBONE_SUBDIV;
807
808         BKE_curve_forward_diff_bezier(0.0f,  h1[0],                               h2[0],                               0.0f,   data[0],     MAX_BBONE_SUBDIV, 4 * sizeof(float));
809         BKE_curve_forward_diff_bezier(0.0f,  h1[1],                               length + h2[1],                      length, data[0] + 1, MAX_BBONE_SUBDIV, 4 * sizeof(float));
810         BKE_curve_forward_diff_bezier(0.0f,  h1[2],                               h2[2],                               0.0f,   data[0] + 2, MAX_BBONE_SUBDIV, 4 * sizeof(float));
811         BKE_curve_forward_diff_bezier(roll1, roll1 + 0.390464f * (roll2 - roll1), roll2 - 0.390464f * (roll2 - roll1), roll2,  data[0] + 3, MAX_BBONE_SUBDIV, 4 * sizeof(float));
812
813         equalize_bbone_bezier(data[0], ebone->segments); /* note: does stride 4! */
814
815         /* make transformation matrices for the segments for drawing */
816         for (a = 0, fp = data[0]; a < ebone->segments; a++, fp += 4) {
817                 sub_v3_v3v3(h1, fp + 4, fp);
818                 vec_roll_to_mat3(h1, fp[3], mat3); /* fp[3] is roll */
819
820                 copy_m4_m3(result_array[a], mat3);
821                 copy_v3_v3(result_array[a][3], fp);
822
823                 /* "extra" scale facs... */
824                 {
825                         const int num_segments = ebone->segments;
826
827                         const float scaleFactorIn  = 1.0f + (ebone->scaleIn  - 1.0f) * ((float)(num_segments - a) / (float)num_segments);
828                         const float scaleFactorOut = 1.0f + (ebone->scaleOut - 1.0f) * ((float)(a + 1)            / (float)num_segments);
829
830                         const float scalefac = scaleFactorIn * scaleFactorOut;
831                         float bscalemat[4][4], bscale[3];
832
833                         bscale[0] = scalefac;
834                         bscale[1] = 1.0f;
835                         bscale[2] = scalefac;
836
837                         size_to_mat4(bscalemat, bscale);
838
839                         /* Note: don't multiply by inverse scale mat here, as it causes problems with scaling shearing and breaking segment chains */
840                         mul_m4_series(result_array[a], result_array[a], bscalemat);
841                 }
842         }
843 }
844
845 static void draw_bone_update_disp_matrix_bbone(EditBone *eBone, bPoseChannel *pchan)
846 {
847         float s[4][4], ebmat[4][4];
848         float length, xwidth, zwidth;
849         float (*bone_mat)[4];
850         short bbone_segments;
851
852         /* TODO : This should be moved to depsgraph or armature refresh
853          * and not be tight to the draw pass creation.
854          * This would refresh armature without invalidating the draw cache */
855         if (pchan) {
856                 length = pchan->bone->length;
857                 xwidth = pchan->bone->xwidth;
858                 zwidth = pchan->bone->zwidth;
859                 bone_mat = pchan->pose_mat;
860                 bbone_segments = pchan->bone->segments;
861         }
862         else {
863                 eBone->length = len_v3v3(eBone->tail, eBone->head);
864                 ED_armature_ebone_to_mat4(eBone, ebmat);
865
866                 length = eBone->length;
867                 xwidth = eBone->xwidth;
868                 zwidth = eBone->zwidth;
869                 bone_mat = ebmat;
870                 bbone_segments = eBone->segments;
871         }
872
873         size_to_mat4(s, (const float[3]){xwidth, length / bbone_segments, zwidth});
874
875         /* Compute BBones segment matrices... */
876         /* Note that we need this even for one-segment bones, because box drawing need specific weirdo matrix for the box,
877          * that we cannot use to draw end points & co. */
878         if (pchan) {
879                 Mat4 *bbones_mat = (Mat4 *)pchan->draw_data->bbone_matrix;
880                 if (bbone_segments > 1) {
881                         b_bone_spline_setup(pchan, 0, bbones_mat);
882
883                         for (int i = bbone_segments; i--; bbones_mat++) {
884                                 mul_m4_m4m4(bbones_mat->mat, bbones_mat->mat, s);
885                                 mul_m4_m4m4(bbones_mat->mat, bone_mat, bbones_mat->mat);
886                         }
887                 }
888                 else {
889                         mul_m4_m4m4(bbones_mat->mat, bone_mat, s);
890                 }
891         }
892         else {
893                 float (*bbones_mat)[4][4] = eBone->disp_bbone_mat;
894
895                 if (bbone_segments > 1) {
896                         ebone_spline_preview(eBone, bbones_mat);
897
898                         for (int i = bbone_segments; i--; bbones_mat++) {
899                                 mul_m4_m4m4(*bbones_mat, *bbones_mat, s);
900                                 mul_m4_m4m4(*bbones_mat, bone_mat, *bbones_mat);
901                         }
902                 }
903                 else {
904                         mul_m4_m4m4(*bbones_mat, bone_mat, s);
905                 }
906         }
907
908         /* Grrr... We need default display matrix to draw end points, axes, etc. :( */
909         draw_bone_update_disp_matrix_default(eBone, pchan);
910 }
911
912 static void draw_bone_update_disp_matrix_custom(bPoseChannel *pchan)
913 {
914         float s[4][4];
915         float length;
916         float (*bone_mat)[4];
917         float (*disp_mat)[4];
918         float (*disp_tail_mat)[4];
919
920         /* See TODO above */
921         length = PCHAN_CUSTOM_DRAW_SIZE(pchan);
922         bone_mat = pchan->custom_tx ? pchan->custom_tx->pose_mat : pchan->pose_mat;
923         disp_mat = pchan->disp_mat;
924         disp_tail_mat = pchan->disp_tail_mat;
925
926         scale_m4_fl(s, length);
927         mul_m4_m4m4(disp_mat, bone_mat, s);
928         copy_m4_m4(disp_tail_mat, disp_mat);
929         translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f);
930 }
931
932 static void draw_axes(EditBone *eBone, bPoseChannel *pchan)
933 {
934         const float *col = (g_theme.const_color) ? g_theme.const_color :
935                            (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? g_theme.text_hi_color : g_theme.text_color;
936
937         drw_shgroup_bone_axes(BONE_VAR(eBone, pchan, disp_mat), col);
938 }
939
940 static void draw_points(
941         const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm,
942         const int boneflag, const short constflag,
943         const int select_id)
944 {
945         const float *col_solid_root = g_theme.bone_solid_color;
946         const float *col_solid_tail = g_theme.bone_solid_color;
947         const float *col_wire_root = (g_theme.const_color) ? g_theme.const_color : g_theme.vertex_color;
948         const float *col_wire_tail = (g_theme.const_color) ? g_theme.const_color : g_theme.vertex_color;
949
950         const bool is_envelope_draw = (arm->drawtype == ARM_ENVELOPE);
951         static const float envelope_ignore = -1.0f;
952
953         /* Edit bone points can be selected */
954         if (eBone) {
955                 if (eBone->flag & BONE_ROOTSEL) {
956 #ifdef USE_SOLID_COLOR
957                         col_solid_root = g_theme.vertex_select_color;
958 #else
959                         if (is_envelope_draw) {
960                                 col_solid_root = g_theme.vertex_select_color;
961                         }
962 #endif
963                         col_wire_root = g_theme.vertex_select_color;
964                 }
965                 if (eBone->flag & BONE_TIPSEL) {
966 #ifdef USE_SOLID_COLOR
967                         col_solid_tail = g_theme.vertex_select_color;
968 #else
969                         if (is_envelope_draw) {
970                                 col_solid_tail = g_theme.vertex_select_color;
971                         }
972 #endif
973                         col_wire_tail = g_theme.vertex_select_color;
974                 }
975         }
976         else if (arm->flag & ARM_POSEMODE) {
977                 col_solid_root = col_solid_tail = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag);
978                 col_wire_root = col_wire_tail = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
979         }
980
981         /*      Draw root point if we are not connected and parent are not hidden */
982         if ((BONE_FLAG(eBone, pchan) & BONE_CONNECTED) == 0) {
983                 if (select_id != -1) {
984                         DRW_select_load_id(select_id | BONESEL_ROOT);
985                 }
986
987                 if (eBone) {
988                         if (!((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent))) {
989                                 if (is_envelope_draw) {
990                                         drw_shgroup_bone_envelope_solid(eBone->disp_mat, col_solid_root,
991                                                                         &eBone->rad_head, &envelope_ignore);
992                                         drw_shgroup_bone_envelope_head_wire(eBone->disp_mat, col_wire_root,
993                                                                             &eBone->rad_head, &envelope_ignore, &envelope_ignore);
994                                 }
995                                 else {
996                                         drw_shgroup_bone_point_solid(eBone->disp_mat, col_solid_root);
997                                         drw_shgroup_bone_point_wire(eBone->disp_mat, col_wire_root);
998                                 }
999                         }
1000                 }
1001                 else {
1002                         Bone *bone = pchan->bone;
1003                         if (!((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))) {
1004                                 if (is_envelope_draw) {
1005                                         drw_shgroup_bone_envelope_solid(pchan->disp_mat, col_solid_root,
1006                                                                         &bone->rad_head, &envelope_ignore);
1007                                         drw_shgroup_bone_envelope_head_wire(pchan->disp_mat, col_wire_root,
1008                                                                             &bone->rad_head, &envelope_ignore, &envelope_ignore);
1009                                 }
1010                                 else {
1011                                         drw_shgroup_bone_point_solid(pchan->disp_mat, col_solid_root);
1012                                         drw_shgroup_bone_point_wire(pchan->disp_mat, col_wire_root);
1013                                 }
1014                         }
1015                 }
1016         }
1017
1018         /*      Draw tip point */
1019         if (select_id != -1) {
1020                 DRW_select_load_id(select_id | BONESEL_TIP);
1021         }
1022
1023         if (is_envelope_draw) {
1024                 const float *rad_tail = eBone ? &eBone->rad_tail : &pchan->bone->rad_tail;
1025                 drw_shgroup_bone_envelope_solid(
1026                             BONE_VAR(eBone, pchan, disp_mat), col_solid_tail, &envelope_ignore, rad_tail);
1027                 drw_shgroup_bone_envelope_head_wire(
1028                             BONE_VAR(eBone, pchan, disp_mat), col_wire_tail, &envelope_ignore, rad_tail, &envelope_ignore);
1029         }
1030         else {
1031                 drw_shgroup_bone_point_solid(BONE_VAR(eBone, pchan, disp_tail_mat), col_solid_tail);
1032                 drw_shgroup_bone_point_wire(BONE_VAR(eBone, pchan, disp_tail_mat), col_wire_tail);
1033         }
1034
1035         if (select_id != -1) {
1036                 DRW_select_load_id(-1);
1037         }
1038 }
1039
1040 /** \} */
1041
1042
1043 /* -------------------------------------------------------------------- */
1044
1045 /** \name Draw Bones
1046  * \{ */
1047
1048 static void draw_bone_custom_shape(
1049         EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
1050         const int boneflag, const short constflag,
1051         const int select_id)
1052 {
1053         const float *col_solid = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag);
1054         const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
1055         const float (*disp_mat)[4] = pchan->disp_mat;
1056
1057         if (select_id != -1) {
1058                 DRW_select_load_id(select_id | BONESEL_BONE);
1059         }
1060
1061         drw_shgroup_bone_custom_solid(disp_mat, col_solid, pchan->custom);
1062         drw_shgroup_bone_custom_wire(disp_mat, col_wire, pchan->custom);
1063
1064         if (select_id != -1) {
1065                 DRW_select_load_id(-1);
1066         }
1067 }
1068
1069 static void draw_bone_envelope(
1070         EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
1071         const int boneflag, const short constflag,
1072         const int select_id)
1073 {
1074         const float *col_solid = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag);
1075         const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
1076
1077         static const float col_white[4] = {1.0f, 1.0f, 1.0f, 0.2f};
1078
1079         float *rad_head, *rad_tail, *distance;
1080         if (eBone) {
1081                 rad_tail = &eBone->rad_tail;
1082                 distance = &eBone->dist;
1083                 rad_head = (eBone->parent && (boneflag & BONE_CONNECTED)) ? &eBone->parent->rad_tail : &eBone->rad_head;
1084         }
1085         else {
1086                 rad_tail = &pchan->bone->rad_tail;
1087                 distance = &pchan->bone->dist;
1088                 rad_head = (pchan->parent && (boneflag & BONE_CONNECTED)) ? &pchan->parent->bone->rad_tail : &pchan->bone->rad_head;
1089         }
1090
1091         if ((boneflag & BONE_NO_DEFORM) == 0 &&
1092             ((boneflag & BONE_SELECTED) || (eBone && (boneflag & (BONE_ROOTSEL | BONE_TIPSEL)))))
1093         {
1094                 drw_shgroup_bone_envelope_distance(BONE_VAR(eBone, pchan, disp_mat), col_white, rad_head, rad_tail, distance);
1095         }
1096
1097         if (select_id != -1) {
1098                 DRW_select_load_id(select_id | BONESEL_BONE);
1099         }
1100
1101         drw_shgroup_bone_envelope_solid(BONE_VAR(eBone, pchan, disp_mat), col_solid, rad_head, rad_tail);
1102         drw_shgroup_bone_envelope_wire(BONE_VAR(eBone, pchan, disp_mat), col_wire, rad_head, rad_tail, distance);
1103
1104         if (select_id != -1) {
1105                 DRW_select_load_id(-1);
1106         }
1107
1108         draw_points(eBone, pchan, arm, boneflag, constflag, select_id);
1109 }
1110
1111 static void draw_bone_line(
1112         EditBone *UNUSED(eBone), bPoseChannel *UNUSED(pchan), bArmature *UNUSED(arm),
1113         const int UNUSED(boneflag), const short UNUSED(constflag),
1114         const int UNUSED(select_id))
1115 {
1116         /* work in progress  -- fclem */
1117 }
1118
1119 static void draw_bone_wire(
1120         EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
1121         const int boneflag, const short constflag,
1122         const int select_id)
1123 {
1124         const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
1125
1126         if (select_id != -1) {
1127                 DRW_select_load_id(select_id | BONESEL_BONE);
1128         }
1129
1130         if (pchan) {
1131                 Mat4 *bbones_mat = (Mat4 *)pchan->draw_data->bbone_matrix;
1132                 BLI_assert(bbones_mat != NULL);
1133
1134                 for (int i = pchan->bone->segments; i--; bbones_mat++) {
1135                         drw_shgroup_bone_wire_wire(bbones_mat->mat, col_wire);
1136                 }
1137         }
1138         else if (eBone) {
1139                 for (int i = 0; i < eBone->segments; i++) {
1140                         drw_shgroup_bone_wire_wire(eBone->disp_bbone_mat[i], col_wire);
1141                 }
1142         }
1143
1144         if (select_id != -1) {
1145                 DRW_select_load_id(-1);
1146         }
1147
1148         if (eBone) {
1149                 draw_points(eBone, pchan, arm, boneflag, constflag, select_id);
1150         }
1151 }
1152
1153 static void draw_bone_box(
1154         EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
1155         const int boneflag, const short constflag,
1156         const int select_id)
1157 {
1158         const float *col_solid = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag);
1159         const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
1160
1161         if (select_id != -1) {
1162                 DRW_select_load_id(select_id | BONESEL_BONE);
1163         }
1164
1165         if (pchan) {
1166                 Mat4 *bbones_mat = (Mat4 *)pchan->draw_data->bbone_matrix;
1167                 BLI_assert(bbones_mat != NULL);
1168
1169                 for (int i = pchan->bone->segments; i--; bbones_mat++) {
1170                         drw_shgroup_bone_box_solid(bbones_mat->mat, col_solid);
1171                         drw_shgroup_bone_box_wire(bbones_mat->mat, col_wire);
1172                 }
1173         }
1174         else if (eBone) {
1175                 for (int i = 0; i < eBone->segments; i++) {
1176                         drw_shgroup_bone_box_solid(eBone->disp_bbone_mat[i], col_solid);
1177                         drw_shgroup_bone_box_wire(eBone->disp_bbone_mat[i], col_wire);
1178                 }
1179         }
1180
1181         if (select_id != -1) {
1182                 DRW_select_load_id(-1);
1183         }
1184
1185         if (eBone) {
1186                 draw_points(eBone, pchan, arm, boneflag, constflag, select_id);
1187         }
1188 }
1189
1190 static void draw_bone_octahedral(
1191         EditBone *eBone, bPoseChannel *pchan, bArmature *arm,
1192         const int boneflag, const short constflag,
1193         const int select_id)
1194 {
1195         const float *col_solid = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag);
1196         const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag);
1197
1198         if (select_id != -1) {
1199                 DRW_select_load_id(select_id | BONESEL_BONE);
1200         }
1201
1202         drw_shgroup_bone_octahedral_solid(BONE_VAR(eBone, pchan, disp_mat), col_solid);
1203         drw_shgroup_bone_octahedral_wire(BONE_VAR(eBone, pchan, disp_mat), col_wire);
1204
1205         if (select_id != -1) {
1206                 DRW_select_load_id(-1);
1207         }
1208
1209         draw_points(eBone, pchan, arm, boneflag, constflag, select_id);
1210 }
1211
1212 /** \} */
1213
1214
1215 /* -------------------------------------------------------------------- */
1216
1217 /** \name Main Draw Loops
1218  * \{ */
1219
1220 static void draw_armature_edit(Object *ob)
1221 {
1222         EditBone *eBone;
1223         bArmature *arm = ob->data;
1224         int index;
1225         const bool is_select = DRW_state_is_select();
1226
1227         update_color(NULL);
1228
1229         const bool show_text = DRW_state_show_text();
1230
1231         for (eBone = arm->edbo->first, index = 0; eBone; eBone = eBone->next, index++) {
1232                 if (eBone->layer & arm->layer) {
1233                         if ((eBone->flag & BONE_HIDDEN_A) == 0) {
1234                                 const int select_id = is_select ? index : (unsigned int)-1;
1235
1236                                 const short constflag = 0;
1237
1238                                 /* catch exception for bone with hidden parent */
1239                                 int boneflag = eBone->flag;
1240                                 if ((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent)) {
1241                                         boneflag &= ~BONE_CONNECTED;
1242                                 }
1243
1244                                 /* set temporary flag for drawing bone as active, but only if selected */
1245                                 if (eBone == arm->act_edbone) {
1246                                         boneflag |= BONE_DRAW_ACTIVE;
1247                                 }
1248
1249                                 if (arm->drawtype == ARM_ENVELOPE) {
1250                                         draw_bone_update_disp_matrix_default(eBone, NULL);
1251                                         draw_bone_envelope(eBone, NULL, arm, boneflag, constflag, select_id);
1252                                 }
1253                                 else if (arm->drawtype == ARM_LINE) {
1254                                         draw_bone_update_disp_matrix_default(eBone, NULL);
1255                                         draw_bone_line(eBone, NULL, arm, boneflag, constflag, select_id);
1256                                 }
1257                                 else if (arm->drawtype == ARM_WIRE) {
1258                                         draw_bone_update_disp_matrix_bbone(eBone, NULL);
1259                                         draw_bone_wire(eBone, NULL, arm, boneflag, constflag, select_id);
1260                                 }
1261                                 else if (arm->drawtype == ARM_B_BONE) {
1262                                         draw_bone_update_disp_matrix_bbone(eBone, NULL);
1263                                         draw_bone_box(eBone, NULL, arm, boneflag, constflag, select_id);
1264                                 }
1265                                 else {
1266                                         draw_bone_update_disp_matrix_default(eBone, NULL);
1267                                         draw_bone_octahedral(eBone, NULL, arm, boneflag, constflag, select_id);
1268                                 }
1269
1270                                 /* Draw names of bone */
1271                                 if (show_text && (arm->flag & ARM_DRAWNAMES)) {
1272                                         unsigned char color[4];
1273                                         UI_GetThemeColor4ubv((eBone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, color);
1274
1275                                         float vec[3];
1276                                         mid_v3_v3v3(vec, eBone->head, eBone->tail);
1277                                         mul_m4_v3(ob->obmat, vec);
1278
1279                                         struct DRWTextStore *dt = DRW_text_cache_ensure();
1280                                         DRW_text_cache_add(
1281                                                 dt, vec, eBone->name, strlen(eBone->name),
1282                                                 10, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color);
1283                                 }
1284
1285                                 /*      Draw additional axes */
1286                                 if (arm->flag & ARM_DRAWAXES) {
1287                                         draw_axes(eBone, NULL);
1288                                 }
1289                         }
1290                 }
1291         }
1292 }
1293
1294 /* if const_color is NULL do pose mode coloring */
1295 static void draw_armature_pose(Object *ob, const float const_color[4])
1296 {
1297         bArmature *arm = ob->data;
1298         bPoseChannel *pchan;
1299         int index = -1;
1300         Bone *bone;
1301
1302         update_color(const_color);
1303
1304         /* We can't safely draw non-updated pose, might contain NULL bone pointers... */
1305         if (ob->pose->flag & POSE_RECALC) {
1306                 BKE_pose_rebuild(ob, arm);
1307         }
1308
1309         // if (!(base->flag & OB_FROMDUPLI)) // TODO
1310         {
1311                 const DRWContextState *draw_ctx = DRW_context_state_get();
1312
1313                 if (draw_ctx->object_mode & OB_MODE_POSE) {
1314                         arm->flag |= ARM_POSEMODE;
1315                 }
1316
1317                 if (arm->flag & ARM_POSEMODE) {
1318                         index = ob->select_color;
1319                 }
1320         }
1321
1322         const bool is_pose_select = (arm->flag & ARM_POSEMODE) && DRW_state_is_select();
1323         const bool show_text = DRW_state_show_text();
1324
1325         /* being set below */
1326         arm->layer_used = 0;
1327
1328         for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1329                 bone = pchan->bone;
1330                 arm->layer_used |= bone->layer;
1331
1332                 /* bone must be visible */
1333                 if ((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) {
1334                         if (bone->layer & arm->layer) {
1335                                 const int select_id = is_pose_select ? index : (unsigned int)-1;
1336
1337                                 const short constflag = pchan->constflag;
1338
1339                                 pchan_draw_data_init(pchan);
1340
1341                                 if (const_color) {
1342                                         /* keep color */
1343                                 }
1344                                 else {
1345                                         /* set color-set to use */
1346                                         set_pchan_colorset(ob, pchan);
1347                                 }
1348
1349                                 int boneflag = bone->flag;
1350                                 /* catch exception for bone with hidden parent */
1351                                 boneflag = bone->flag;
1352                                 if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
1353                                         boneflag &= ~BONE_CONNECTED;
1354                                 }
1355
1356                                 /* set temporary flag for drawing bone as active, but only if selected */
1357                                 if (bone == arm->act_bone)
1358                                         boneflag |= BONE_DRAW_ACTIVE;
1359
1360
1361                                 if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) {
1362                                         draw_bone_update_disp_matrix_custom(pchan);
1363                                         draw_bone_custom_shape(NULL, pchan, arm, boneflag, constflag, select_id);
1364                                 }
1365                                 else if (arm->drawtype == ARM_ENVELOPE) {
1366                                         draw_bone_update_disp_matrix_default(NULL, pchan);
1367                                         draw_bone_envelope(NULL, pchan, arm, boneflag, constflag, select_id);
1368                                 }
1369                                 else if (arm->drawtype == ARM_LINE) {
1370                                         draw_bone_update_disp_matrix_default(NULL, pchan);
1371                                         draw_bone_line(NULL, pchan, arm, boneflag, constflag, select_id);
1372                                 }
1373                                 else if (arm->drawtype == ARM_WIRE) {
1374                                         draw_bone_update_disp_matrix_bbone(NULL, pchan);
1375                                         draw_bone_wire(NULL, pchan, arm, boneflag, constflag, select_id);
1376                                 }
1377                                 else if (arm->drawtype == ARM_B_BONE) {
1378                                         draw_bone_update_disp_matrix_bbone(NULL, pchan);
1379                                         draw_bone_box(NULL, pchan, arm, boneflag, constflag, select_id);
1380                                 }
1381                                 else {
1382                                         draw_bone_update_disp_matrix_default(NULL, pchan);
1383                                         draw_bone_octahedral(NULL, pchan, arm, boneflag, constflag, select_id);
1384                                 }
1385
1386                                 /* Draw names of bone */
1387                                 if (show_text && (arm->flag & ARM_DRAWNAMES)) {
1388                                         unsigned char color[4];
1389                                         UI_GetThemeColor4ubv((arm->flag & ARM_POSEMODE) &&
1390                                                              (bone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, color);
1391                                         float vec[3];
1392                                         mid_v3_v3v3(vec, pchan->pose_head, pchan->pose_tail);
1393                                         mul_m4_v3(ob->obmat, vec);
1394
1395                                         struct DRWTextStore *dt = DRW_text_cache_ensure();
1396                                         DRW_text_cache_add(
1397                                                 dt, vec, pchan->name, strlen(pchan->name),
1398                                                 10, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color);
1399                                 }
1400
1401                                 /*      Draw additional axes */
1402                                 if (arm->flag & ARM_DRAWAXES) {
1403                                         draw_axes(NULL, pchan);
1404                                 }
1405                         }
1406                 }
1407                 if (is_pose_select) {
1408                         index += 0x10000;
1409                 }
1410         }
1411
1412         arm->flag &= ~ARM_POSEMODE;
1413 }
1414
1415 /**
1416  * This function set the object space to use for all subsequent `DRW_shgroup_bone_*` calls.
1417  */
1418 static void drw_shgroup_armature(
1419         Object *ob, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWPass *pass_bone_envelope,
1420         DRWShadingGroup *shgrp_relationship_lines)
1421 {
1422         memset(&g_data, 0x0, sizeof(g_data));
1423         g_data.ob = ob;
1424
1425         g_data.pass_bone_solid = pass_bone_solid;
1426         g_data.pass_bone_wire = pass_bone_wire;
1427         g_data.pass_bone_envelope = pass_bone_envelope;
1428         g_data.relationship_lines = shgrp_relationship_lines;
1429
1430         memset(&g_color, 0x0, sizeof(g_color));
1431 }
1432
1433 void DRW_shgroup_armature_object(
1434         Object *ob, ViewLayer *view_layer, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWPass *UNUSED(pass_bone_envelope),
1435         DRWShadingGroup *shgrp_relationship_lines)
1436 {
1437         float *color;
1438         DRW_object_wire_theme_get(ob, view_layer, &color);
1439
1440         drw_shgroup_armature(ob, pass_bone_solid, pass_bone_wire, NULL, shgrp_relationship_lines);
1441         draw_armature_pose(ob, color);
1442 }
1443
1444 void DRW_shgroup_armature_pose(
1445         Object *ob, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWPass *pass_bone_envelope,
1446         DRWShadingGroup *shgrp_relationship_lines)
1447 {
1448         drw_shgroup_armature(ob, pass_bone_solid, pass_bone_wire, pass_bone_envelope, shgrp_relationship_lines);
1449         draw_armature_pose(ob, NULL);
1450 }
1451
1452 void DRW_shgroup_armature_edit(
1453         Object *ob, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWPass *pass_bone_envelope,
1454         DRWShadingGroup *shgrp_relationship_lines)
1455 {
1456         drw_shgroup_armature(ob, pass_bone_solid, pass_bone_wire, pass_bone_envelope, shgrp_relationship_lines);
1457         draw_armature_edit(ob);
1458 }
1459
1460 /** \} */