Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / space_view3d / drawarmature.c
index 9917486d5497348d334304882ec9f16dedf5e488..f41712218163dd90cff4426968bd459f423e87e7 100644 (file)
@@ -53,6 +53,7 @@
 #include "BKE_global.h"
 #include "BKE_modifier.h"
 #include "BKE_nla.h"
+#include "BKE_curve.h"
 
 
 #include "BIF_gl.h"
@@ -1090,20 +1091,101 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned
        glPopMatrix();
 }
 
-static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, float xwidth, float length, float zwidth)
+/* A partial copy of b_bone_spline_setup(), with just the parts for previewing editmode curve settings 
+ *
+ * This assumes that prev/next bones don't have any impact (since they should all still be in the "straight"
+ * position here anyway), and that we can simply apply the bbone settings to get the desired effect...
+ */
+static void ebone_spline_preview(EditBone *ebone, Mat4 result_array[MAX_BBONE_SUBDIV])
+{
+       float h1[3], h2[3], length, hlength1, hlength2, roll1 = 0.0f, roll2 = 0.0f;
+       float mat3[3][3];
+       float data[MAX_BBONE_SUBDIV + 1][4], *fp;
+       int a;
+       
+       length = ebone->length;
+       
+       hlength1 = ebone->ease1 * length * 0.390464f; /* 0.5f * sqrt(2) * kappa, the handle length for near-perfect circles */
+       hlength2 = ebone->ease2 * length * 0.390464f;
+       
+       /* find the handle points, since this is inside bone space, the
+        * first point = (0, 0, 0)
+        * last point =  (0, length, 0)
+        *
+        * we also just apply all the "extra effects", since they're the whole reason we're doing this...
+        */
+       h1[0] = ebone->curveInX;
+       h1[1] = hlength1;
+       h1[2] = ebone->curveInY;
+       roll1 = ebone->roll1;
+       
+       h2[0] = ebone->curveOutX;
+       h2[1] = -hlength2;
+       h2[2] = ebone->curveOutY;
+       roll2 = ebone->roll2;
+       
+       /* make curve */
+       if (ebone->segments > MAX_BBONE_SUBDIV)
+               ebone->segments = MAX_BBONE_SUBDIV;
+
+       BKE_curve_forward_diff_bezier(0.0f,  h1[0],                               h2[0],                               0.0f,   data[0],     MAX_BBONE_SUBDIV, 4 * sizeof(float));
+       BKE_curve_forward_diff_bezier(0.0f,  h1[1],                               length + h2[1],                      length, data[0] + 1, MAX_BBONE_SUBDIV, 4 * sizeof(float));
+       BKE_curve_forward_diff_bezier(0.0f,  h1[2],                               h2[2],                               0.0f,   data[0] + 2, MAX_BBONE_SUBDIV, 4 * sizeof(float));
+       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));
+
+       equalize_bbone_bezier(data[0], ebone->segments); /* note: does stride 4! */
+
+       /* make transformation matrices for the segments for drawing */
+       for (a = 0, fp = data[0]; a < ebone->segments; a++, fp += 4) {
+               sub_v3_v3v3(h1, fp + 4, fp);
+               vec_roll_to_mat3(h1, fp[3], mat3); /* fp[3] is roll */
+               
+               copy_m4_m3(result_array[a].mat, mat3);
+               copy_v3_v3(result_array[a].mat[3], fp);
+               
+               /* "extra" scale facs... */
+               {
+                       const int num_segments = ebone->segments;
+                       
+                       const float scaleFactorIn  = 1.0f + (ebone->scaleIn  - 1.0f) * ((float)(num_segments - a) / (float)num_segments);
+                       const float scaleFactorOut = 1.0f + (ebone->scaleOut - 1.0f) * ((float)(a + 1)            / (float)num_segments);
+                       
+                       const float scalefac = scaleFactorIn * scaleFactorOut;
+                       float bscalemat[4][4], bscale[3];
+                       
+                       bscale[0] = scalefac;
+                       bscale[1] = 1.0f;
+                       bscale[2] = scalefac;
+                       
+                       size_to_mat4(bscalemat, bscale);
+                       
+                       /* Note: don't multiply by inverse scale mat here, as it causes problems with scaling shearing and breaking segment chains */
+                       mul_m4_series(result_array[a].mat, result_array[a].mat, bscalemat);
+               }
+       }
+}
+
+static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, EditBone *ebone, float xwidth, float length, float zwidth)
 {
        int segments = 0;
        
        if (pchan) 
                segments = pchan->bone->segments;
+       else if (ebone)
+               segments = ebone->segments;
        
-       if ((segments > 1) && (pchan)) {
+       if (segments > 1) {
                float dlen = length / (float)segments;
                Mat4 bbone[MAX_BBONE_SUBDIV];
                int a;
-
-               b_bone_spline_setup(pchan, 0, bbone);
-
+               
+               if (pchan) {
+                       b_bone_spline_setup(pchan, 0, bbone);
+               }
+               else if (ebone) {
+                       ebone_spline_preview(ebone, bbone);
+               }
+               
                for (a = 0; a < segments; a++) {
                        glPushMatrix();
                        glMultMatrixf(bbone[a].mat);
@@ -1174,7 +1256,7 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
                else
                        UI_ThemeColor(TH_BONE_SOLID);
                
-               draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
+               draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth);
                
                /* disable solid drawing */
                GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
@@ -1187,7 +1269,7 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
                                if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
                                        glEnable(GL_BLEND);
                                        
-                                       draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
+                                       draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth);
                                        
                                        glDisable(GL_BLEND);
                                }
@@ -1197,7 +1279,7 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
                        }
                }
                
-               draw_b_bone_boxes(OB_WIRE, pchan, xwidth, length, zwidth);
+               draw_b_bone_boxes(OB_WIRE, pchan, ebone, xwidth, length, zwidth);
        }
 }
 
@@ -1887,7 +1969,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
        }
        
        /* custom bone may draw outline double-width */
-       glLineWidth(1.0f);
+       if (arm->flag & ARM_POSEMODE) {
+               glLineWidth(1.0f);
+       }
 
        /* wire draw over solid only in posemode */
        if ((dt <= OB_WIRE) || (arm->flag & ARM_POSEMODE) || ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {