merging trunk 19093:19274
authorMartin Poirier <theeth@yahoo.com>
Fri, 13 Mar 2009 18:04:38 +0000 (18:04 +0000)
committerMartin Poirier <theeth@yahoo.com>
Fri, 13 Mar 2009 18:04:38 +0000 (18:04 +0000)
33 files changed:
release/scripts/scripttemplate_background_job.py [deleted file]
source/blender/blenkernel/BKE_global.h
source/blender/blenkernel/intern/object.c
source/blender/blenlib/BLI_arithb.h
source/blender/blenlib/BLI_graph.h
source/blender/blenlib/intern/arithb.c
source/blender/blenlib/intern/graph.c
source/blender/blenloader/intern/readfile.c
source/blender/include/BDR_sketch.h [new file with mode: 0644]
source/blender/include/BIF_editarmature.h
source/blender/include/BIF_generate.h [new file with mode: 0644]
source/blender/include/BIF_retarget.h [new file with mode: 0644]
source/blender/include/BIF_sketch.h [new file with mode: 0644]
source/blender/include/BIF_space.h
source/blender/include/BIF_transform.h
source/blender/include/reeb.h
source/blender/makesdna/DNA_scene_types.h
source/blender/python/api2_2x/Armature.c
source/blender/python/api2_2x/Bone.c
source/blender/src/buttons_editing.c
source/blender/src/drawview.c
source/blender/src/edit.c
source/blender/src/editarmature.c
source/blender/src/editarmature_generate.c [new file with mode: 0644]
source/blender/src/editarmature_retarget.c [moved from source/blender/src/autoarmature.c with 72% similarity]
source/blender/src/editarmature_sketch.c [new file with mode: 0644]
source/blender/src/gpencil.c
source/blender/src/header_view3d.c
source/blender/src/reeb.c
source/blender/src/space.c
source/blender/src/transform_snap.c
source/blender/src/usiblender.c
source/blender/src/view.c

diff --git a/release/scripts/scripttemplate_background_job.py b/release/scripts/scripttemplate_background_job.py
deleted file mode 100644 (file)
index 86b5899..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-#!BPY
-"""
-Name: 'Background Job Example'
-Blender: 248
-Group: 'ScriptTemplate'
-Tooltip: 'Script template for automating tasks from the command line with blender'
-"""
-
-from Blender import Window
-import bpy
-
-script_data = \
-'''# This script is an example of how you can run blender from the command line (in background mode with no interface)
-# to automate tasks, in this example it creates a text object, camera and light, then renders and/or saves it.
-# This example also shows how you can parse command line options to python scripts.
-# 
-# Example usage for this test.
-#  blender -b -P $HOME/background_job.py -- --text="Hello World" --render="/tmp/hello" --save="/tmp/hello.blend"
-# 
-# Notice all python args are after the '--' argument.
-
-import Blender
-import bpy
-
-def example_function(body_text, save_path, render_path):
-       
-       sce= bpy.data.scenes.active
-
-       txt_data= bpy.data.curves.new('MyText', 'Text3d')
-       
-       # Text Object
-       txt_ob = sce.objects.new(txt_data)                      # add the data to the scene as an object
-       txt_data.setText(body_text)                                     # set the body text to the command line arg given
-       txt_data.setAlignment(Blender.Text3d.MIDDLE)# center text
-       
-       # Camera
-       cam_data= bpy.data.cameras.new('MyCam')         # create new camera data
-       cam_ob= sce.objects.new(cam_data)                       # add the camera data to the scene (creating a new object)
-       sce.objects.camera= cam_ob                                      # set the active camera
-       cam_ob.loc= 0,0,10
-       
-       # Lamp
-       lamp_data= bpy.data.lamps.new('MyLamp')
-       lamp_ob= sce.objects.new(lamp_data)
-       lamp_ob.loc= 2,2,5
-
-       if save_path:
-               try:
-                       f= open(save_path, 'w')
-                       f.close()
-                       ok= True
-               except:
-                       print 'Cannot save to path "%s"' % save_path
-                       ok= False
-               
-               if ok:
-                       Blender.Save(save_path, 1)
-       
-       if render_path:
-               render= sce.render
-               render.extensions= True
-               render.renderPath = render_path
-               render.sFrame= 1
-               render.eFrame= 1
-               render.renderAnim()
-
-
-
-import sys             # to get command line args
-import optparse        # to parse options for us and print a nice help message
-
-script_name= 'background_job.py'
-
-def main():
-       
-       # get the args passed to blender after "--", all of which are ignored by blender specifically
-       # so python may receive its own arguments
-       argv= sys.argv
-
-       if '--' not in argv:
-               argv = [] # as if no args are passed
-       else:   
-               argv = argv[argv.index('--')+1: ] # get all args after "--"
-       
-       # When --help or no args are given, print this help
-       usage_text =  'Run blender in background mode with this script:\n'
-       usage_text += '  blender -b -P ' + script_name + ' -- [options]'
-                       
-       parser = optparse.OptionParser(usage = usage_text)
-       
-
-       # Example background utility, add some text and renders or saves it (with options)
-       # Possible types are: string, int, long, choice, float and complex.
-       parser.add_option('-t', '--text', dest='body_text', help='This text will be used to render an image', type='string')
-
-       parser.add_option('-s', '--save', dest='save_path', help='Save the generated file to the specified path', metavar='FILE')
-       parser.add_option('-r', '--render', dest='render_path', help='Render an image to the specified path', metavar='FILE')
-
-       options, args = parser.parse_args(argv) # In this example we wont use the args
-       
-       if not argv:
-               parser.print_help()
-               return
-
-       if not options.body_text:
-               print 'Error: --text="some string" argument not given, aborting.\n'
-               parser.print_help()
-               return
-       
-       # Run the example function
-       example_function(options.body_text, options.save_path, options.render_path)
-
-       print 'batch job finished, exiting'
-
-
-if __name__ == '__main__':
-       main()
-'''
-
-new_text = bpy.data.texts.new('background_job.py')
-new_text.write(script_data)
-bpy.data.texts.active = new_text
-Window.RedrawAll()
-
index e8918bcdce6ff82b9302c79cd8960607b2429ef4..eb89e1699ea3b9579b1187f5334afcf88d812437 100644 (file)
@@ -151,7 +151,6 @@ typedef struct Global {
        
        /* confusing... G.f and G.flags */
        int flags;
-
 } Global;
 
 /* **************** GLOBAL ********************* */
index a25afeafaef5fb3edd115b3ff865439c82d6cecb..0b153c3c065a9b1ec4400d492a55cfcd7c1248bc 100644 (file)
@@ -521,6 +521,7 @@ void unlink_object(Object *ob)
        while(sce) {
                if(sce->id.lib==NULL) {
                        if(sce->camera==ob) sce->camera= NULL;
+                       if(sce->toolsettings->skgen_template==ob) sce->toolsettings->skgen_template = NULL;
                }
                sce= sce->id.next;
        }
index fd58aa318da9ee8c0231091efd72928286da11fc..092ed00fbe5d6739082f7e153b5047baa068be03 100644 (file)
@@ -391,8 +391,10 @@ void tubemap(float x, float y, float z, float *u, float *v);
 void spheremap(float x, float y, float z, float *u, float *v);
 
 int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float i1[3], float i2[3]);
+int LineIntersectLineStrict(float v1[3], float v2[3], float v3[3], float v4[3], float vi[3], float *lambda);
 int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv);
 int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv);
+int RayIntersectsTriangleThreshold(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv, float threshold);
 int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint);
 int AxialLineIntersectsTriangle(int axis, float co1[3], float co2[3], float v0[3], float v1[3], float v2[3], float *lambda);
 int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3]);
index 160c2e04cf56516ee4daa5718a17fae0c3d96f0a..f4fccfcbb2c8d1a6eb386c18288564ea9f1a6a43 100644 (file)
@@ -60,6 +60,39 @@ typedef struct BArc {
        int symmetry_flag;
 } BArc;
 
+struct BArcIterator;
+
+void* IT_head(void* iter);
+void* IT_tail(void* iter);
+void* IT_peek(void* iter, int n);
+void* IT_next(void* iter);
+void* IT_nextN(void* iter, int n);
+void* IT_previous(void* iter);
+int   IT_stopped(void* iter);
+
+typedef void* (*HeadFct)(void* iter);
+typedef void* (*TailFct)(void* iter);
+typedef void* (*PeekFct)(void* iter, int n);
+typedef void* (*NextFct)(void* iter);
+typedef void* (*NextNFct)(void* iter, int n);
+typedef void* (*PreviousFct)(void* iter);
+typedef int   (*StoppedFct)(void* iter);
+
+typedef struct BArcIterator {
+       HeadFct         head;
+       TailFct         tail;
+       PeekFct         peek;
+       NextFct         next;
+       NextNFct        nextN;
+       PreviousFct     previous;
+       StoppedFct      stopped;
+       
+       float *p, *no;
+       
+       int length;
+       int index;
+} BArcIterator;
+
 /* Helper structure for radial symmetry */
 typedef struct RadialArc
 {
index 61cbf791bf1bc8538c11093db215962ffac3bcdf..ad1dc1ca12c53dfa7cbfdcbb5609c48c8a57f71e 100644 (file)
@@ -3896,6 +3896,57 @@ int RayIntersectsTriangle(float p1[3], float d[3], float v0[3], float v1[3], flo
        return 1;
 }
 
+int RayIntersectsTriangleThreshold(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv, float threshold)
+{
+       float p[3], s[3], e1[3], e2[3], q[3];
+       float a, f, u, v;
+       float du = 0, dv = 0;
+       
+       VecSubf(e1, v1, v0);
+       VecSubf(e2, v2, v0);
+       
+       Crossf(p, d, e2);
+       a = Inpf(e1, p);
+       if ((a > -0.000001) && (a < 0.000001)) return 0;
+       f = 1.0f/a;
+       
+       VecSubf(s, p1, v0);
+       
+       Crossf(q, s, e1);
+       *lambda = f * Inpf(e2, q);
+       if ((*lambda < 0.0)) return 0;
+       
+       u = f * Inpf(s, p);
+       v = f * Inpf(d, q);
+       
+       if (u < 0) du = u;
+       if (u > 1) du = u - 1;
+       if (v < 0) dv = v;
+       if (v > 1) dv = v - 1;
+       if (u > 0 && v > 0 && u + v > 1)
+       {
+               float t = u + v - 1;
+               du = u - t/2;
+               dv = v - t/2;
+       }
+
+       VecMulf(e1, du);
+       VecMulf(e2, dv);
+       
+       if (Inpf(e1, e1) + Inpf(e2, e2) > threshold * threshold)
+       {
+               return 0;
+       }
+
+       if(uv) {
+               uv[0]= u;
+               uv[1]= v;
+       }
+       
+       return 1;
+}
+
+
 /* Adapted from the paper by Kasper Fauerby */
 /* "Improved Collision detection and Response" */
 static int getLowestRoot(float a, float b, float c, float maxR, float* root)
@@ -4245,6 +4296,67 @@ int LineIntersectLine(float v1[3], float v2[3], float v3[3], float v4[3], float
        }
 } 
 
+/* Intersection point strictly between the two lines
+ * 0 when no intersection is found 
+ * */
+int LineIntersectLineStrict(float v1[3], float v2[3], float v3[3], float v4[3], float vi[3], float *lambda)
+{
+       float a[3], b[3], c[3], ab[3], cb[3], ca[3], dir1[3], dir2[3];
+       float d;
+       float d1;
+       
+       VecSubf(c, v3, v1);
+       VecSubf(a, v2, v1);
+       VecSubf(b, v4, v3);
+
+       VecCopyf(dir1, a);
+       Normalize(dir1);
+       VecCopyf(dir2, b);
+       Normalize(dir2);
+       d = Inpf(dir1, dir2);
+       if (d == 1.0f || d == -1.0f || d == 0) {
+               /* colinear or one vector is zero-length*/
+               return 0;
+       }
+       
+       d1 = d;
+
+       Crossf(ab, a, b);
+       d = Inpf(c, ab);
+
+       /* test if the two lines are coplanar */
+       if (d > -0.000001f && d < 0.000001f) {
+               float f1, f2;
+               Crossf(cb, c, b);
+               Crossf(ca, c, a);
+
+               f1 = Inpf(cb, ab) / Inpf(ab, ab);
+               f2 = Inpf(ca, ab) / Inpf(ab, ab);
+               
+               if (f1 >= 0 && f1 <= 1 &&
+                       f2 >= 0 && f2 <= 1)
+               {
+                       VecMulf(a, f1);
+                       VecAddf(vi, v1, a);
+                       
+                       if (lambda != NULL)
+                       {
+                               *lambda = f1;
+                       }
+                       
+                       return 1; /* intersection found */
+               }
+               else
+               {
+                       return 0;
+               }
+       }
+       else
+       {
+               return 0;
+       }
+} 
+
 int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3])
 {
        return (min1[0]<max2[0] && min1[1]<max2[1] && min1[2]<max2[2] &&
index bcd8a2ce7cdd97e2353a7729fb09dc6f201ad7f7..52277063a8fd0b791bebbd583b617fb2b9268abf 100644 (file)
@@ -465,8 +465,6 @@ int subtreeShape(BNode *node, BArc *rootArc, int include_root)
 
 int BLI_subtreeShape(BGraph *graph, BNode *node, BArc *rootArc, int include_root)
 {
-       BNode *test_node;
-       
        BLI_flagNodes(graph, 0);
        return subtreeShape(node, rootArc, include_root);
 }
@@ -1033,6 +1031,11 @@ void BLI_markdownSymmetry(BGraph *graph, BNode *root_node, float limit)
        BNode *node;
        BArc *arc;
        
+       if (root_node == NULL)
+       {
+               return;
+       }
+       
        if (BLI_isGraphCyclic(graph))
        {
                return;
@@ -1085,3 +1088,56 @@ void BLI_markdownSymmetry(BGraph *graph, BNode *root_node, float limit)
        }
 }
 
+void* IT_head(void* arg)
+{
+       BArcIterator *iter = (BArcIterator*)arg; 
+       return iter->head(iter);
+}
+
+void* IT_tail(void* arg)
+{
+       BArcIterator *iter = (BArcIterator*)arg; 
+       return iter->tail(iter); 
+}
+
+void* IT_peek(void* arg, int n)
+{
+       BArcIterator *iter = (BArcIterator*)arg;
+       
+       if (iter->index + n < 0)
+       {
+               return iter->head(iter);
+       }
+       else if (iter->index + n >= iter->length)
+       {
+               return iter->tail(iter);
+       }
+       else
+       {
+               return iter->peek(iter, n);
+       }
+}
+
+void* IT_next(void* arg)
+{
+       BArcIterator *iter = (BArcIterator*)arg; 
+       return iter->next(iter);
+}
+
+void* IT_nextN(void* arg, int n)
+{
+       BArcIterator *iter = (BArcIterator*)arg; 
+       return iter->nextN(iter, n);
+}
+
+void* IT_previous(void* arg)
+{
+       BArcIterator *iter = (BArcIterator*)arg; 
+       return iter->previous(iter);
+}
+
+int   IT_stopped(void* arg)
+{
+       BArcIterator *iter = (BArcIterator*)arg; 
+       return iter->stopped(iter);
+}
index dc9c97cb3f5f6181c151365e307e2fc1064d725f..7fc2a995a2f2ef7aae6aba899376d98f7e4c40af 100644 (file)
@@ -3477,6 +3477,9 @@ static void lib_link_scene(FileData *fd, Main *main)
                        sce->toolsettings->imapaint.brush=
                                newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.brush);
 
+       
+                       sce->toolsettings->skgen_template = newlibadr(fd, sce->id.lib, sce->toolsettings->skgen_template);
+
                        /* Sculptdata textures */
                        for(a=0; a<MAX_MTEX; ++a) {
                                MTex *mtex= sce->sculptdata.mtex[a];
@@ -7387,47 +7390,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                ima->flag |= IMA_DO_PREMUL;
                        }
                }
-
-               if (main->versionfile < 245 || main->subversionfile < 12)
-               {
-                       /* initialize skeleton generation toolsettings */
-                       for(sce=main->scene.first; sce; sce = sce->id.next)
-                       {
-                               sce->toolsettings->skgen_resolution = 50;
-                               sce->toolsettings->skgen_threshold_internal     = 0.01f;
-                               sce->toolsettings->skgen_threshold_external     = 0.01f;
-                               sce->toolsettings->skgen_angle_limit                    = 45.0f;
-                               sce->toolsettings->skgen_length_ratio                   = 1.3f;
-                               sce->toolsettings->skgen_length_limit                   = 1.5f;
-                               sce->toolsettings->skgen_correlation_limit              = 0.98f;
-                               sce->toolsettings->skgen_symmetry_limit                 = 0.1f;
-                               sce->toolsettings->skgen_postpro = SKGEN_SMOOTH;
-                               sce->toolsettings->skgen_postpro_passes = 1;
-                               sce->toolsettings->skgen_options = SKGEN_FILTER_INTERNAL|SKGEN_FILTER_EXTERNAL|SKGEN_SUB_CORRELATION;
-                               sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION;
-                               sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH;
-                               sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE;
-                       }
-               }
-       }
-       
-       /* sanity check for skgen
-        * */
-       {
-               Scene *sce;
-               for(sce=main->scene.first; sce; sce = sce->id.next)
-               {
-                       if (sce->toolsettings->skgen_subdivisions[0] == sce->toolsettings->skgen_subdivisions[1] ||
-                               sce->toolsettings->skgen_subdivisions[0] == sce->toolsettings->skgen_subdivisions[2] ||
-                               sce->toolsettings->skgen_subdivisions[1] == sce->toolsettings->skgen_subdivisions[2])
-                       {
-                                       sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION;
-                                       sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH;
-                                       sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE;
-                       }
-               }
        }
-       
 
        if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 2)) {
                Image *ima;
@@ -8009,17 +7972,43 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
        
-       if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 2)) {
+       if (main->versionfile < 248 || main->subversionfile < 2)
+       {
                Scene *sce;
                
-               /* Note, these will need to be added for painting */
-               for (sce= main->scene.first; sce; sce= sce->id.next) {
+               for(sce=main->scene.first; sce; sce = sce->id.next)
+               {
+                       /* Note, these will need to be added for painting */
                        sce->toolsettings->imapaint.seam_bleed = 2;
                        sce->toolsettings->imapaint.normal_angle = 80;
+
+                       /* initialize skeleton generation toolsettings */
+                       sce->toolsettings->skgen_resolution = 250;
+                       sce->toolsettings->skgen_threshold_internal     = 0.1f;
+                       sce->toolsettings->skgen_threshold_external     = 0.1f;
+                       sce->toolsettings->skgen_angle_limit                    = 30.0f;
+                       sce->toolsettings->skgen_length_ratio                   = 1.3f;
+                       sce->toolsettings->skgen_length_limit                   = 1.5f;
+                       sce->toolsettings->skgen_correlation_limit              = 0.98f;
+                       sce->toolsettings->skgen_symmetry_limit                 = 0.1f;
+                       sce->toolsettings->skgen_postpro = SKGEN_SMOOTH;
+                       sce->toolsettings->skgen_postpro_passes = 3;
+                       sce->toolsettings->skgen_options = SKGEN_FILTER_INTERNAL|SKGEN_FILTER_EXTERNAL|SKGEN_FILTER_SMART|SKGEN_SUB_CORRELATION|SKGEN_HARMONIC;
+                       sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION;
+                       sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH;
+                       sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE;
+
+                       
+                       sce->toolsettings->skgen_retarget_angle_weight = 1.0f;
+                       sce->toolsettings->skgen_retarget_length_weight = 1.0f;
+                       sce->toolsettings->skgen_retarget_distance_weight = 1.0f;
+       
+                       /* Skeleton Sketching */
+                       sce->toolsettings->bone_sketching = 0;
+                       sce->toolsettings->skgen_retarget_roll = SK_RETARGET_ROLL_VIEW;
                }
        }
-       
-       
+
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
 
diff --git a/source/blender/include/BDR_sketch.h b/source/blender/include/BDR_sketch.h
new file mode 100644 (file)
index 0000000..55d6e1d
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * $Id:  $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BDR_SKETCH_H
+#define BDR_SKETCH_H
+
+void BDR_queueDrawSketch();
+void BDR_drawSketch();
+void BDR_drawSketchNames();
+
+#endif /* BDR_SKETCH_H */
index ce275563a873a6eb46713e9f7b0b47ba259d32a1..19d64f853e8edc3408883978bca9908753797902 100644 (file)
@@ -68,6 +68,23 @@ typedef struct EditBone
 
 } EditBone;
 
+EditBone *addEditBone(char *name, struct ListBase *ebones, struct bArmature *arm);
+
+/* duplicate method */
+void preEditBoneDuplicate(struct ListBase *editbones);
+EditBone *duplicateEditBone(EditBone *curBone, char *name, struct ListBase *editbones, struct Object *ob);
+void updateDuplicateSubtarget(EditBone *dupBone, struct ListBase *editbones, struct Object *ob);
+
+/* duplicate method (cross objects */
+
+/* editbones is the target list */
+EditBone *duplicateEditBoneObjects(EditBone *curBone, char *name, struct ListBase *editbones, struct Object *src_ob, struct Object *dst_ob);
+
+/* editbones is the source list */
+void updateDuplicateSubtargetObjects(EditBone *dupBone, struct ListBase *editbones, struct Object *src_ob, struct Object *dst_ob);
+
+/* -- */
+
 float  rollBoneToVector(EditBone *bone, float new_up_axis[3]);
 
 void   make_boneList(struct ListBase *list, struct ListBase *bones, EditBone *parent);
@@ -117,7 +134,7 @@ void        selectconnected_posearmature(void);
 void   armature_select_hierarchy(short direction, short add_to_sel);
 
 void   setflag_armature(short mode);
-void    unique_editbone_name (struct ListBase *ebones, char *name);
+void   unique_editbone_name (struct ListBase *ebones, char *name, EditBone *bone); /* if bone is already in list, pass it as param to ignore it */
 
 void   auto_align_armature(short mode);
 void   switch_direction_armature(void);
@@ -152,11 +169,15 @@ void      align_selected_bones(void);
 
 #define BONESEL_NOSEL  0x80000000      /* Indicates a negative number */
 
-/* from autoarmature */
+/* from editarmature_retarget */
 void BIF_retargetArmature();
 void BIF_adjustRetarget();
 void BIF_freeRetarget();
 
+/* from editarmature_sketch */
+void BIF_freeSketch();
+void BIF_freeTemplates();
+
 struct ReebArc;
 float calcVariance(struct ReebArc *arc, int start, int end, float v0[3], float n[3]);
 float calcDistance(struct ReebArc *arc, int start, int end, float head[3], float tail[3]);
diff --git a/source/blender/include/BIF_generate.h b/source/blender/include/BIF_generate.h
new file mode 100644 (file)
index 0000000..e64edf9
--- /dev/null
@@ -0,0 +1,44 @@
+/**
+ * $Id:  $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef BIF_GENERATE_H
+#define BIF_GENERATE_H
+
+struct EditBone;
+struct BArcIterator;
+struct bArmature;
+struct ListBase;
+
+typedef int(NextSubdivisionFunc)(struct BArcIterator*, int, int, float[3], float[3]);
+float calcArcCorrelation(struct BArcIterator *iter, int start, int end, float v0[3], float n[3]);
+
+int nextFixedSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]);
+int nextLengthSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]);
+int nextAdaptativeSubdivision(struct BArcIterator *iter, int start, int end, float head[3], float p[3]);
+
+struct EditBone * subdivideArcBy(struct bArmature *arm, ListBase *editbones, struct BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion);
+
+void setBoneRollFromNormal(struct EditBone *bone, float *no, float invmat[][4], float tmat[][3]);
+
+#endif /* BIF_GENERATE_H */
diff --git a/source/blender/include/BIF_retarget.h b/source/blender/include/BIF_retarget.h
new file mode 100644 (file)
index 0000000..9de10fb
--- /dev/null
@@ -0,0 +1,154 @@
+/**
+ * $Id:  $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BIF_RETARGET_H
+#define BIF_RETARGET_H
+
+#include "DNA_listBase.h"
+
+#include "BLI_graph.h"
+#include "BLI_ghash.h"
+#include "BLI_threads.h"
+
+#include "reeb.h"
+
+struct Object;
+struct bArmature;
+
+struct EditBone;
+
+struct RigJoint;
+struct RigGraph;
+struct RigNode;
+struct RigArc;
+struct RigEdge;
+
+#define USE_THREADS
+
+typedef struct RigGraph {
+       ListBase        arcs;
+       ListBase        nodes;
+
+       float length;
+       
+       FreeArc                 free_arc;
+       FreeNode                free_node;
+       RadialSymmetry  radial_symmetry;
+       AxialSymmetry   axial_symmetry;
+       /*********************************/
+
+       ListBase        controls;
+       ListBase*       editbones;
+       
+       struct RigNode *head;
+       ReebGraph *link_mesh;
+       
+       
+       struct ThreadedWorker *worker;
+       
+       GHash *bones_map;       /* map of editbones by name */
+       GHash *controls_map;    /* map of rigcontrols by bone pointer */
+       
+       struct Object *ob;
+} RigGraph;
+
+typedef struct RigNode {
+       void *next, *prev;
+       float p[3];
+       int flag;
+
+       int degree;
+       struct BArc **arcs;
+
+       int subgraph_index;
+
+       int symmetry_level;
+       int symmetry_flag;
+       float symmetry_axis[3];
+       /*********************************/
+
+       ReebNode *link_mesh;
+} RigNode;
+
+typedef struct RigArc {
+       void *next, *prev;
+       RigNode *head, *tail;
+       int flag;
+
+       float length;
+
+       int symmetry_level;
+       int symmetry_group;
+       int symmetry_flag;
+       /*********************************/
+       
+       ListBase edges;
+       int count;
+       ReebArc *link_mesh;
+} RigArc;
+
+typedef struct RigEdge {
+       struct RigEdge *next, *prev;
+       float head[3], tail[3];
+       float length;
+       float angle; /* angle to next edge */
+       float up_angle; /* angle between up_axis and the joint normal (defined as Previous edge CrossProduct Current edge */
+       struct EditBone *bone;
+       float up_axis[3];
+} RigEdge;
+
+/* Control flags */
+#define RIG_CTRL_HEAD_DONE             1
+#define RIG_CTRL_TAIL_DONE             2
+#define RIG_CTRL_PARENT_DEFORM 4
+#define RIG_CTRL_FIT_ROOT              8
+#define RIG_CTRL_FIT_BONE              16
+
+#define RIG_CTRL_DONE  (RIG_CTRL_HEAD_DONE|RIG_CTRL_TAIL_DONE)
+
+/* Control tail flags */
+typedef enum {
+       TL_NONE = 0,
+       TL_TAIL,
+       TL_HEAD
+} LinkTailMode;
+
+typedef struct RigControl {
+       struct RigControl *next, *prev;
+       float head[3], tail[3];
+       struct EditBone *bone;
+       struct EditBone *link;
+       struct EditBone *link_tail;
+       float   up_axis[3];
+       float   offset[3];
+       float   qrot[4]; /* for dual linked bones, store the rotation of the linked bone for the finalization */
+       int             flag;
+       LinkTailMode tail_mode;
+} RigControl;
+
+void BIF_retargetArc(ReebArc *earc, RigGraph *template_rigg);
+RigGraph *RIG_graphFromArmature(struct Object *ob, struct bArmature *arm);
+int RIG_nbJoints(RigGraph *rg);
+char *RIG_nameBone(RigGraph *rg, int arc_index, int bone_index);
+void RIG_freeRigGraph(BGraph *rg);
+
+#endif /* BIF_RETARGET_H */
diff --git a/source/blender/include/BIF_sketch.h b/source/blender/include/BIF_sketch.h
new file mode 100644 (file)
index 0000000..9cd7393
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ * $Id:  $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BIF_SKETCH_H
+#define BIF_SKETCH_H
+
+int BIF_paintSketch(short mbut);
+void BIF_endStrokeSketch();
+void BIF_convertSketch();
+void BIF_deleteSketch();
+void BIF_selectAllSketch(int mode); /* -1: deselect, 0: select, 1: toggle */
+int BIF_validSketchMode();
+int BIF_fullSketchMode(); /* full sketch turned on (not Quick) */
+void BIF_cancelStrokeSketch();
+
+void  BIF_makeListTemplates();
+char *BIF_listTemplates();
+int   BIF_currentTemplate();
+void  BIF_freeTemplates();
+void  BIF_setTemplate(int);
+int   BIF_nbJointsTemplate();
+char * BIF_nameBoneTemplate();
+
+#endif /* BIF_SKETCH_H */
index c7d0f4a1ada462beaa0938206ff15e6c8e3626c4..a52b499e936cd78c009f0840198b61d4c8f88006 100644 (file)
@@ -54,6 +54,7 @@ struct SpaceOops;
 #define VIEW3D_HANDLER_MULTIRES         5
 #define VIEW3D_HANDLER_TRANSFORM       6
 #define VIEW3D_HANDLER_GREASEPENCIL 7
+#define VIEW3D_HANDLER_BONESKETCH 8
 
 /* ipo handler codes */
 #define IPO_HANDLER_PROPERTIES 20
index 0e3985fc52c107a859de338bc324ee4df45996dd..096201f86d03d317ca81a3041818e9e56f0128ff 100644 (file)
@@ -86,6 +86,7 @@ struct TransInfo;
 struct ScrArea;
 struct Base;
 struct Scene;
+struct Object;
 
 struct TransInfo * BIF_GetTransInfo(void);
 void BIF_setSingleAxisConstraint(float vec[3], char *text);
@@ -125,5 +126,32 @@ void ManipulatorTransform();
 int BIF_do_manipulator(struct ScrArea *sa);
 void BIF_draw_manipulator(struct ScrArea *sa);
 
+/* Snapping */
+
+
+typedef struct DepthPeel
+{
+       struct DepthPeel *next, *prev;
+       
+       float depth;
+       float p[3];
+       float no[3];
+       struct Object *ob;
+       int flag;
+} DepthPeel;
+
+struct ListBase;
+
+typedef enum SnapMode
+{
+       NOT_SELECTED = 0,
+       NOT_ACTIVE = 1
+} SnapMode;
+
+#define SNAP_MIN_DISTANCE 30
+
+int snapObjects(int *dist, float *loc, float *no, SnapMode mode);
+int peelObjects(struct ListBase *depth_peels, short mval[2]);
+
 #endif
 
index 57f7d1b60cf599814fb4c0f64642e18d3e2db6d6..eab0e2a8601e9d0cb3ec4703b494b65e5e4e46de 100644 (file)
@@ -28,7 +28,7 @@
 #ifndef REEB_H_
 #define REEB_H_
 
-//#define WITH_BF_REEB
+#define WITH_BF_REEB
 
 #include "DNA_listBase.h"
 
@@ -63,6 +63,7 @@ typedef struct EmbedBucket {
        float val;
        int       nv;
        float p[3];
+       float no[3]; /* if non-null, normal of the bucket */
 } EmbedBucket;
 
 typedef struct ReebNode {
@@ -79,6 +80,8 @@ typedef struct ReebNode {
        int symmetry_flag;
        float symmetry_axis[3];
        /*********************************/
+       
+       float no[3];
 
        int index;
        float weight;
@@ -117,12 +120,23 @@ typedef struct ReebArc {
 } ReebArc;
 
 typedef struct ReebArcIterator {
-       struct ReebArc  *arc;
+       HeadFct         head;
+       TailFct         tail;
+       PeekFct         peek;
+       NextFct         next;
+       NextNFct        nextN;
+       PreviousFct     previous;
+       StoppedFct      stopped;
+       
+       float *p, *no;
+       
+       int length;
        int index;
+       /*********************************/
+       struct ReebArc  *arc;
        int start;
        int end;
-       int stride; 
-       int length;
+       int stride;
 } ReebArcIterator;
 
 struct EditMesh;
@@ -139,15 +153,9 @@ void renormalizeWeight(struct EditMesh *em, float newmax);
 ReebGraph * generateReebGraph(struct EditMesh *me, int subdivisions);
 ReebGraph * newReebGraph();
 
-void initArcIterator(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head);
-void initArcIterator2(struct ReebArcIterator *iter, struct ReebArc *arc, int start, int end);
-void initArcIteratorStart(struct ReebArcIterator *iter, struct ReebArc *arc, struct ReebNode *head, int start);
-struct EmbedBucket * nextBucket(struct ReebArcIterator *iter);
-struct EmbedBucket * nextNBucket(ReebArcIterator *iter, int n);
-struct EmbedBucket * peekBucket(ReebArcIterator *iter, int n);
-struct EmbedBucket * currentBucket(struct ReebArcIterator *iter);
-struct EmbedBucket * previousBucket(struct ReebArcIterator *iter);
-int iteratorStopped(struct ReebArcIterator *iter);
+void initArcIterator(BArcIterator *iter, struct ReebArc *arc, struct ReebNode *head);
+void initArcIterator2(BArcIterator *iter, struct ReebArc *arc, int start, int end);
+void initArcIteratorStart(BArcIterator *iter, struct ReebArc *arc, struct ReebNode *head, int start);
 
 /* Filtering */
 void filterNullReebGraph(ReebGraph *rg);
@@ -185,6 +193,7 @@ ReebNode *BIF_lowestLevelNode(ReebNode *node);
 ReebGraph *BIF_graphForMultiNode(ReebGraph *rg, ReebNode *node);
 
 void REEB_freeGraph(ReebGraph *rg);
+void REEB_freeArc(BArc *barc);
 void REEB_exportGraph(ReebGraph *rg, int count);
 void REEB_draw();
 
index 09c2344d53acc6abebf6370f4f99251deeaa794c..35e086b418adb79cf64df9bfa0b76995f9508a98 100644 (file)
@@ -447,12 +447,20 @@ typedef struct ToolSettings {
        char  skgen_postpro_passes;
        char  skgen_subdivisions[3];
        char  skgen_multi_level;
-       char  skgen_optimisation_method;
        
-       char tpad[6];
+       /* Skeleton Sketching */
+       struct Object *skgen_template;
+       char bone_sketching;
+       char bone_sketching_convert;
+       char skgen_subdivision_number;
+       char skgen_retarget_options;
+       char skgen_retarget_roll;
+       char skgen_side_string[8];
+       char skgen_num_string[8];
        
        /* Alt+RMB option */
        char edge_mode;
+       char pad3[2];
 } ToolSettings;
 
 /* Used by all brushes to store their properties, which can be directly set
@@ -734,6 +742,7 @@ typedef struct Scene {
 /* scene->snap_flag */
 #define SCE_SNAP                               1
 #define SCE_SNAP_ROTATE                        2
+#define SCE_SNAP_PEEL_OBJECT   4
 /* scene->snap_target */
 #define SCE_SNAP_TARGET_CLOSEST        0
 #define SCE_SNAP_TARGET_CENTER 1
@@ -743,6 +752,7 @@ typedef struct Scene {
 #define SCE_SNAP_MODE_VERTEX   0
 #define SCE_SNAP_MODE_EDGE             1
 #define SCE_SNAP_MODE_FACE             2
+#define SCE_SNAP_MODE_VOLUME   3
 
 /* sce->selectmode */
 #define SCE_SELECT_VERTEX      1 /* for mesh */
@@ -892,6 +902,25 @@ typedef struct Scene {
 #define SKGEN_AVERAGE                  1
 #define SKGEN_SHARPEN                  2
 
+/* toolsettings->bone_sketching */
+#define BONE_SKETCHING                 1
+#define BONE_SKETCHING_QUICK   2
+#define BONE_SKETCHING_ADJUST  4
+
+/* toolsettings->bone_sketching_convert */
+#define        SK_CONVERT_CUT_FIXED                    1
+#define        SK_CONVERT_CUT_LENGTH                   2
+#define        SK_CONVERT_CUT_ADAPTATIVE               3
+#define        SK_CONVERT_RETARGET                             4
+
+/* toolsettings->skgen_retarget_options */
+#define        SK_RETARGET_AUTONAME                    1
+
+/* toolsettings->skgen_retarget_roll */
+#define        SK_RETARGET_ROLL_VIEW                   1
+#define        SK_RETARGET_ROLL_JOINT                  2
+
+
 #ifdef __cplusplus
 }
 #endif
index 99a4398ec89c3fe010d05109658cd3f5170178fc..2ef0c2b4afe71fc7f44f03d14aabd5c3d781b4ce 100644 (file)
@@ -280,7 +280,7 @@ static int BonesDict_SetItem(BPy_BonesDict *self, PyObject *key, PyObject *value
                //create a new editbone
                editbone = MEM_callocN(sizeof(EditBone), "eBone");
                BLI_strncpy(editbone->name, key_str, 32);
-               unique_editbone_name(NULL, editbone->name);
+               unique_editbone_name(NULL, editbone->name, NULL);
                editbone->dist = ((BPy_EditBone*)value)->dist;
                editbone->ease1 = ((BPy_EditBone*)value)->ease1;
                editbone->ease2 = ((BPy_EditBone*)value)->ease2;
index 948eb007803d25bb3e07ac249fe98d04f5f2ab74..cacb358434435d9c9ce43d7a545f3c569bc1ab9f 100644 (file)
@@ -832,7 +832,7 @@ static PyObject *EditBone_new(PyTypeObject *type, PyObject *args, PyObject *kwds
        //otherwise this will act as a py_object
        py_editBone->editbone = NULL;
 
-       unique_editbone_name(NULL, name);
+       unique_editbone_name(NULL, name, NULL);
        BLI_strncpy(py_editBone->name, name, 32);
        py_editBone->parent = NULL;
        py_editBone->weight= 1.0f;
index 953519416e1803d52fff634242ab0bba2fa248c3..7b564bdd7a3828d0bc1fc56b5080dba98688a096 100644 (file)
@@ -5312,7 +5312,6 @@ static void editing_panel_mesh_skgen_retarget(Object *ob, Mesh *me)
        uiDefButF(block, NUM, B_DIFF,                                                   "Ang:",                 1025, 40, 83,19, &G.scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0,              "Angle Weight");
        uiDefButF(block, NUM, B_DIFF,                                                   "Len:",                 1108, 40, 83,19, &G.scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0,             "Length Weight");
        uiDefButF(block, NUM, B_DIFF,                                                   "Dist:",                1191, 40, 84,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0,           "Distance Weight");
-       uiDefButC(block, NUM, B_DIFF,                                                   "Method:",              1025, 20, 125,19, &G.scene->toolsettings->skgen_optimisation_method, 0, 2, 1, 0,"Optimisation Method (0: brute, 1: memoize, 2: annealing max fixed");
 }
 
 static void editing_panel_mesh_skgen(Object *ob, Mesh *me)
index 44b61c816a55e94bd9d2996eda966f14cddad033..cb4fa246562569c67a5b6524a1ee4c0a62c54784 100644 (file)
 #include "BIF_resources.h"
 #include "BIF_retopo.h"
 #include "BIF_screen.h"
+#include "BIF_sketch.h"
 #include "BIF_space.h"
 
 #ifdef WITH_VERSE
 #include "BDR_vpaint.h"
 #include "BDR_sculptmode.h"
 #include "BDR_gpencil.h"
+#include "BDR_sketch.h"
 
 #include "BSE_drawview.h"
 #include "BSE_filesel.h"
@@ -2272,6 +2274,141 @@ static void view3d_panel_transform_spaces(short cntrl)
        if(yco < 0) uiNewPanelHeight(block, height-yco);
 }
 
+static void delete_sketch_armature(void *arg1, void *arg2)
+{
+       BIF_deleteSketch();
+}
+
+static void convert_sketch_armature(void *arg1, void *arg2)
+{
+       BIF_convertSketch();
+}
+
+static void assign_template_sketch_armature(void *arg1, void *arg2)
+{
+       int index = *(int*)arg1;
+       BIF_setTemplate(index);
+}
+static void view3d_panel_bonesketch_spaces(short cntrl)
+{
+       static int template_index;
+       static char joint_label[128];
+       uiBlock *block;
+       uiBut *but;
+       char *bone_name;
+       int yco = 130, height = 140;
+       int nb_joints;
+
+       /* replace with check call to sketching lib */
+       if (G.obedit && G.obedit->type == OB_ARMATURE)
+       {
+               static char subdiv_tooltip[4][64] = {
+                       "Subdivide arcs based on a fixed number of bones",
+                       "Subdivide arcs in bones of equal length",
+                       "Subdivide arcs based on correlation",
+                       "Retarget template to stroke"
+                       };
+
+               
+               block= uiNewBlock(&curarea->uiblocks, "view3d_panel_bonesketch_spaces", UI_EMBOSS, UI_HELV, curarea->win);
+               uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE  | cntrl);
+               uiSetPanelHandler(VIEW3D_HANDLER_BONESKETCH);  // for close and esc
+       
+               if(uiNewPanel(curarea, block, "Bone Sketching", "View3d", 10, 230, 250, height)==0) return;
+       
+               uiNewPanelHeight(block, height);
+       
+               uiBlockBeginAlign(block);
+               
+               /* use real flag instead of 1 */
+               uiDefButBitC(block, TOG, BONE_SKETCHING, B_REDR, "Use Bone Sketching", 10, yco, 160, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones");
+               uiDefButBitC(block, TOG, BONE_SKETCHING_ADJUST, B_REDR, "A", 170, yco, 20, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Adjust strokes by drawing near them");
+               uiDefButBitC(block, TOG, BONE_SKETCHING_QUICK, B_REDR, "Q", 190, yco, 20, 20, &G.scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Automatically convert and delete on stroke end");
+               yco -= 20;
+               
+               but = uiDefBut(block, BUT, B_REDR, "Convert", 10,yco,100,20, 0, 0, 0, 0, 0, "Convert sketch to armature");
+               uiButSetFunc(but, convert_sketch_armature, NULL, NULL);
+
+               but = uiDefBut(block, BUT, B_REDR, "Delete", 110,yco,100,20, 0, 0, 0, 0, 0, "Delete sketch");
+               uiButSetFunc(but, delete_sketch_armature, NULL, NULL);
+               yco -= 20;
+               
+               uiBlockEndAlign(block);
+
+               uiBlockBeginAlign(block);
+               
+               uiDefButC(block, MENU, B_REDR, "Subdivision Method%t|Length%x2|Adaptative%x3|Fixed%x1|Template%x4", 10,yco,60,19, &G.scene->toolsettings->bone_sketching_convert, 0, 0, 0, 0, subdiv_tooltip[(unsigned char)G.scene->toolsettings->bone_sketching_convert]);
+
+               switch(G.scene->toolsettings->bone_sketching_convert)
+               {
+               case SK_CONVERT_CUT_LENGTH:
+                       uiDefButF(block, NUM, B_REDR,                                   "Lim:",         70, yco, 140, 19, &G.scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0,           "Maximum length of the subdivided bones");
+                       yco -= 20;
+                       break;
+               case SK_CONVERT_CUT_ADAPTATIVE:
+                       uiDefButF(block, NUM, B_REDR,                                   "Thres:",                       70, yco, 140, 19, &G.scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0,    "Correlation threshold for subdivision");
+                       yco -= 20;
+                       break;
+               default:
+               case SK_CONVERT_CUT_FIXED:
+                       uiDefButC(block, NUM, B_REDR,                                   "Num:",         70, yco, 140, 19, &G.scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5,        "Number of subdivided bones");
+                       yco -= 20;
+                       break;
+               case SK_CONVERT_RETARGET:
+                       uiDefButC(block, ROW, B_DIFF, "No",                     70,  yco, 40,19, &G.scene->toolsettings->skgen_retarget_roll, 0, 0, 0, 0,                                                                       "No special roll treatment");
+                       uiDefButC(block, ROW, B_DIFF, "View",           110,  yco, 50,19, &G.scene->toolsettings->skgen_retarget_roll, 0, SK_RETARGET_ROLL_VIEW, 0, 0,                          "Roll bones perpendicular to view");
+                       uiDefButC(block, ROW, B_DIFF, "Joint",          160, yco, 50,19, &G.scene->toolsettings->skgen_retarget_roll, 0, SK_RETARGET_ROLL_JOINT, 0, 0,                          "Roll bones relative to joint bend");
+                       yco -= 30;
+
+                       uiBlockEndAlign(block);
+
+                       uiBlockBeginAlign(block);
+                       /* button here to select what to do (copy or not), template, ...*/
+
+                       BIF_makeListTemplates();
+                       template_index = BIF_currentTemplate();
+                       
+                       but = uiDefButI(block, MENU, B_REDR, BIF_listTemplates(), 10,yco,200,19, &template_index, 0, 0, 0, 0, "Template");
+                       uiButSetFunc(but, assign_template_sketch_armature, &template_index, NULL);
+                       
+                       yco -= 20;
+                       
+                       uiDefButF(block, NUM, B_DIFF,                                                   "A:",                   10, yco, 66,19, &G.scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0,               "Angle Weight");
+                       uiDefButF(block, NUM, B_DIFF,                                                   "L:",                   76, yco, 67,19, &G.scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0,              "Length Weight");
+                       uiDefButF(block, NUM, B_DIFF,                                                   "D:",           143,yco, 67,19, &G.scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0,            "Distance Weight");
+                       yco -= 20;
+                       
+                       uiDefBut(block, TEX,B_DIFF,"S:",                                                        10,  yco, 90, 20, G.scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace &S with");
+                       uiDefBut(block, TEX,B_DIFF,"N:",                                                        100, yco, 90, 20, G.scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace &N with");
+                       uiDefIconButBitC(block, TOG, SK_RETARGET_AUTONAME, B_DIFF, ICON_AUTO,190,yco,20,20, &G.scene->toolsettings->skgen_retarget_options, 0, 0, 0, 0, "Use Auto Naming");     
+                       yco -= 20;
+       
+                       /* auto renaming magic */
+                       uiBlockEndAlign(block);
+                       
+                       nb_joints = BIF_nbJointsTemplate();
+       
+                       if (nb_joints == -1)
+                       {
+                               nb_joints = G.totvertsel;
+                       }
+                       
+                       bone_name = BIF_nameBoneTemplate();
+                       
+                       BLI_snprintf(joint_label, 32, "%i joints: %s", nb_joints, bone_name);
+                       
+                       uiDefBut(block, LABEL, 1, joint_label,                                  10, yco, 200, 20, NULL, 0.0, 0.0, 0, 0, "");
+                       yco -= 20;
+                       break;
+               }
+
+               uiBlockEndAlign(block);
+               
+               uiDefButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_DIFF, "Peel Objects", 10, yco, 200, 20, &G.scene->snap_flag, 0, 0, 0, 0, "Peel whole objects as one");
+
+               if(yco < 0) uiNewPanelHeight(block, height-yco);
+       }
+}
 
 static void view3d_panel_object(short cntrl)   // VIEW3D_HANDLER_OBJECT
 {
@@ -2663,6 +2800,9 @@ static void view3d_blockhandlers(ScrArea *sa)
                case VIEW3D_HANDLER_GREASEPENCIL:
                        view3d_panel_gpencil(v3d->blockhandler[a+1]);
                        break;
+               case VIEW3D_HANDLER_BONESKETCH:
+                       view3d_panel_bonesketch_spaces(v3d->blockhandler[a+1]);
+                       break;
                }
                /* clear action value for event */
                v3d->blockhandler[a+1]= 0;
@@ -3271,6 +3411,8 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
        /* draw grease-pencil stuff */
        if (v3d->flag2 & V3D_DISPGP)
                draw_gpencil_3dview(sa, 1);
+               
+       BDR_drawSketch();
        
        persp(PERSP_WIN);  // set ortho
 
index a80e7b6c3602a34aa38410d744ca35b10a267164..f681b65925f2aeb9aecde776c82b29841e583b85 100644 (file)
@@ -99,6 +99,7 @@
 #include "BIF_space.h"
 #include "BIF_screen.h"
 #include "BIF_toolbox.h"
+#include "BIF_sketch.h"
 
 #ifdef WITH_VERSE
 #include "BIF_verse.h"
@@ -1838,7 +1839,11 @@ void mergemenu(void)
 
 void delete_context_selected(void) 
 {
-       if(G.obedit) {
+       if(BIF_fullSketchMode())
+       {
+               BIF_deleteSketch();
+       }
+       else if(G.obedit) {
                if(G.obedit->type==OB_MESH) delete_mesh();
                else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) delNurb();
                else if(G.obedit->type==OB_MBALL) delete_mball();
index ee5d56eaf43f527284944573823484cd44e5a141..ec14e2aabe2fd69997d8d5bab310fcfe1d57df44 100644 (file)
@@ -93,6 +93,7 @@
 #include "BIF_space.h"
 #include "BIF_toolbox.h"
 #include "BIF_transform.h"
+#include "BIF_generate.h"
 
 #include "BDR_editobject.h"
 #include "BDR_drawobject.h"
@@ -699,7 +700,7 @@ int join_armature(void)
                                        curbone= editbone_name_exists(&eblist, pchan->name);
                                        
                                        /* Get new name */
-                                       unique_editbone_name(&ebbase, curbone->name);
+                                       unique_editbone_name(&ebbase, curbone->name, NULL);
                                        
                                        /* Transform the bone */
                                        {
@@ -1740,6 +1741,8 @@ void make_editArmature(void)
        if (!arm) return;
        
        make_boneList(&G.edbo, &arm->bonebase,NULL);
+       
+       BIF_freeTemplates(); /* force template update when entering editmode */
 }
 
 /* put EditMode back in Object */
@@ -1994,17 +1997,14 @@ void undo_push_armature(char *name)
 /* **************** END EditMode stuff ********************** */
 /* *************** Adding stuff in editmode *************** */
 
-/* default bone add, returns it selected, but without tail set */
-static EditBone *add_editbone(char *name)
+EditBone *addEditBone(char *name, ListBase *ebones, bArmature *arm)
 {
-       bArmature *arm= G.obedit->data;
-       
        EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone");
        
        BLI_strncpy(bone->name, name, 32);
-       unique_editbone_name(&G.edbo, bone->name);
+       unique_editbone_name(ebones, bone->name, NULL);
        
-       BLI_addtail(&G.edbo, bone);
+       BLI_addtail(ebones, bone);
        
        bone->flag |= BONE_TIPSEL;
        bone->weight= 1.0F;
@@ -2021,6 +2021,14 @@ static EditBone *add_editbone(char *name)
        return bone;
 }
 
+/* default bone add, returns it selected, but without tail set */
+static EditBone *add_editbone(char *name)
+{
+       bArmature *arm= G.obedit->data;
+       
+       return addEditBone(name, &G.edbo, arm);
+}
+
 static void add_primitive_bone(Object *ob, short newob)
 {
        float           obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
@@ -2192,13 +2200,12 @@ static EditBone *add_points_bone (float head[], float tail[])
        return ebo;
 }
 
-
-static EditBone *get_named_editbone(char *name)
+static EditBone *get_named_editbone_from_list(char *name, ListBase *editbones)
 {
        EditBone  *eBone;
 
        if (name) {
-               for (eBone=G.edbo.first; eBone; eBone=eBone->next) {
+               for (eBone=editbones->first; eBone; eBone=eBone->next) {
                        if (!strcmp(name, eBone->name))
                                return eBone;
                }
@@ -2207,7 +2214,29 @@ static EditBone *get_named_editbone(char *name)
        return NULL;
 }
 
-static void update_dup_subtarget(EditBone *dupBone)
+static EditBone *get_named_editbone(char *name)
+{
+       return get_named_editbone_from_list(name, &G.edbo);
+}
+
+/* Call this before doing any duplications
+ * */
+void preEditBoneDuplicate(ListBase *editbones)
+{
+       EditBone *eBone;
+       
+       /* clear temp */
+       for (eBone = editbones->first; eBone; eBone = eBone->next)
+       {
+               eBone->temp = NULL;
+       }
+}
+
+/*
+ * Note: When duplicating cross objects, editbones here is the list of bones
+ * from the SOURCE object but ob is the DESTINATION object
+ * */
+void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Object *src_ob, Object *dst_ob)
 {
        /* If an edit bone has been duplicated, lets
         * update it's constraints if the subtarget
@@ -2218,7 +2247,7 @@ static void update_dup_subtarget(EditBone *dupBone)
        bConstraint  *curcon;
        ListBase     *conlist;
        
-       if ( (chan = verify_pose_channel(OBACT->pose, dupBone->name)) ) {
+       if ( (chan = verify_pose_channel(dst_ob->pose, dupBone->name)) ) {
                if ( (conlist = &chan->constraints) ) {
                        for (curcon = conlist->first; curcon; curcon=curcon->next) {
                                /* does this constraint have a subtarget in
@@ -2232,14 +2261,15 @@ static void update_dup_subtarget(EditBone *dupBone)
                                        cti->get_constraint_targets(curcon, &targets);
                                        
                                        for (ct= targets.first; ct; ct= ct->next) {
-                                               if ((ct->tar == G.obedit) && (ct->subtarget[0])) {
-                                                       oldtarget = get_named_editbone(ct->subtarget);
+                                               if ((ct->tar == src_ob) && (ct->subtarget[0])) {
+                                                       ct->tar = dst_ob; /* update target */
+                                                       oldtarget = get_named_editbone_from_list(ct->subtarget, editbones);
                                                        if (oldtarget) {
                                                                /* was the subtarget bone duplicated too? If
                                                                 * so, update the constraint to point at the 
                                                                 * duplicate of the old subtarget.
                                                                 */
-                                                               if (oldtarget->flag & BONE_SELECTED){
+                                                               if (oldtarget->temp){
                                                                        newtarget = (EditBone *) oldtarget->temp;
                                                                        strcpy(ct->subtarget, newtarget->name);
                                                                }
@@ -2255,6 +2285,78 @@ static void update_dup_subtarget(EditBone *dupBone)
        }
 }
 
+void updateDuplicateSubtarget(EditBone *dupBone, ListBase *editbones, Object *ob)
+{
+       updateDuplicateSubtargetObjects(dupBone, editbones, ob, ob);
+}
+
+
+EditBone *duplicateEditBoneObjects(EditBone *curBone, char *name, ListBase *editbones, Object *src_ob, Object *dst_ob)
+{
+       EditBone *eBone = MEM_callocN(sizeof(EditBone), "addup_editbone");
+       
+       /*      Copy data from old bone to new bone */
+       memcpy(eBone, curBone, sizeof(EditBone));
+       
+       curBone->temp = eBone;
+       eBone->temp = curBone;
+       
+       if (name != NULL)
+       {
+               BLI_strncpy(eBone->name, name, 32);
+       }
+
+       unique_editbone_name(editbones, eBone->name, NULL);
+       BLI_addtail(editbones, eBone);
+       
+       /* Lets duplicate the list of constraints that the
+        * current bone has.
+        */
+       if (src_ob->pose) {
+               bPoseChannel *chanold, *channew;
+               ListBase     *listold, *listnew;
+               
+               chanold = verify_pose_channel(src_ob->pose, curBone->name);
+               if (chanold) {
+                       listold = &chanold->constraints;
+                       if (listold) {
+                               /* WARNING: this creates a new posechannel, but there will not be an attached bone 
+                                *              yet as the new bones created here are still 'EditBones' not 'Bones'. 
+                                */
+                               channew = 
+                                       verify_pose_channel(dst_ob->pose, eBone->name);
+                               if (channew) {
+                                       /* copy transform locks */
+                                       channew->protectflag = chanold->protectflag;
+                                       
+                                       /* copy bone group */
+                                       channew->agrp_index= chanold->agrp_index;
+                                       
+                                       /* ik (dof) settings */
+                                       channew->ikflag = chanold->ikflag;
+                                       VECCOPY(channew->limitmin, chanold->limitmin);
+                                       VECCOPY(channew->limitmax, chanold->limitmax);
+                                       VECCOPY(channew->stiffness, chanold->stiffness);
+                                       channew->ikstretch= chanold->ikstretch;
+                                       
+                                       /* constraints */
+                                       listnew = &channew->constraints;
+                                       copy_constraints(listnew, listold);
+                                       
+                                       /* custom shape */
+                                       channew->custom= chanold->custom;
+                               }
+                       }
+               }
+       }
+       
+       return eBone;
+}
+
+EditBone *duplicateEditBone(EditBone *curBone, char *name, ListBase *editbones, Object *ob)
+{
+       return duplicateEditBoneObjects(curBone, name, editbones, ob, ob);
+}
 
 void adduplicate_armature(void)
 {
@@ -2264,6 +2366,8 @@ void adduplicate_armature(void)
        EditBone        *firstDup=NULL; /*      The beginning of the duplicated bones in the edbo list */
        
        countall(); // flushes selection!
+       
+       preEditBoneDuplicate(&G.edbo);
 
        /* Select mirrored bones */
        if (arm->flag & ARM_MIRROR_EDIT) {
@@ -2277,6 +2381,7 @@ void adduplicate_armature(void)
                        }
                }
        }
+
        
        /*      Find the selected bones and duplicate them as needed */
        for (curBone=G.edbo.first; curBone && curBone!=firstDup; curBone=curBone->next) {
@@ -2291,7 +2396,7 @@ void adduplicate_armature(void)
                                curBone->temp = eBone;
                                eBone->temp = curBone;
                                
-                               unique_editbone_name(&G.edbo, eBone->name);
+                               unique_editbone_name(&G.edbo, eBone->name, NULL);
                                BLI_addtail(&G.edbo, eBone);
                                if (!firstDup)
                                        firstDup=eBone;
@@ -2351,12 +2456,12 @@ void adduplicate_armature(void)
                                */
                                if (!curBone->parent)
                                        eBone->parent = NULL;
-                               /*      If this bone has a parent that IS selected,
+                               /*      If this bone has a parent that was duplicated,
                                        Set the duplicate->parent to the curBone->parent->duplicate
                                        */
-                               else if (curBone->parent->flag & BONE_SELECTED)
+                               else if (curBone->parent->temp)
                                        eBone->parent= (EditBone *)curBone->parent->temp;
-                               /*      If this bone has a parent that IS not selected,
+                               /*      If this bone has a parent that was not duplicated,
                                        Set the duplicate->parent to the curBone->parent
                                        */
                                else {
@@ -2366,7 +2471,7 @@ void adduplicate_armature(void)
                                
                                /* Lets try to fix any constraint subtargets that might
                                        have been duplicated */
-                               update_dup_subtarget(eBone);
+                               updateDuplicateSubtarget(eBone, &G.edbo, OBACT);
                        }
                }
        } 
@@ -3055,13 +3160,16 @@ static EditBone *editbone_name_exists (ListBase *ebones, char *name)
 }
 
 /* note: there's a unique_bone_name() too! */
-void unique_editbone_name (ListBase *ebones, char *name)
+void unique_editbone_name (ListBase *ebones, char *name, EditBone *bone)
 {
+       EditBone *dupli;
        char            tempname[64];
        int                     number;
        char            *dot;
        
-       if (editbone_name_exists(ebones, name)) {
+       dupli = editbone_name_exists(ebones, name); 
+       
+       if (dupli && bone != dupli) {
                /*      Strip off the suffix, if it's a number */
                number= strlen(name);
                if (number && isdigit(name[number-1])) {
@@ -3182,7 +3290,7 @@ void extrude_armature(int forked)
                                                        else strcat(newbone->name, "_R");
                                                }
                                        }
-                                       unique_editbone_name(&G.edbo, newbone->name);
+                                       unique_editbone_name(&G.edbo, newbone->name, NULL);
                                        
                                        /* Add the new bone to the list */
                                        BLI_addtail(&G.edbo, newbone);
@@ -3269,7 +3377,7 @@ void subdivide_armature(int numcuts)
                                                        
                                                        newbone->flag |= BONE_CONNECTED;
                                                        
-                                                       unique_editbone_name (&G.edbo, newbone->name);
+                                                       unique_editbone_name (&G.edbo, newbone->name, NULL);
                                                        
                                                        /* correct parent bones */
                                                        for (tbone = G.edbo.first; tbone; tbone=tbone->next) {
@@ -4303,7 +4411,7 @@ void armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
                        
                        eBone= editbone_name_exists(&G.edbo, oldname);
                        if (eBone) {
-                               unique_editbone_name(&G.edbo, newname);
+                               unique_editbone_name(&G.edbo, newname, NULL);
                                BLI_strncpy(eBone->name, newname, MAXBONENAME);
                        }
                        else return;
@@ -4548,9 +4656,9 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail)
        EditBone *lastBone = NULL;
        if (G.scene->toolsettings->skgen_options & SKGEN_CUT_ANGLE)
        {
-               ReebArcIterator iter;
-               EmbedBucket *current = NULL;
-               EmbedBucket *previous = NULL;
+               ReebArcIterator arc_iter;
+               BArcIterator *iter = (BArcIterator*)&arc_iter;
+               float *previous = NULL, *current = NULL;
                EditBone *child = NULL;
                EditBone *parent = NULL;
                EditBone *root = NULL;
@@ -4562,22 +4670,28 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail)
                
                root = parent;
                
-               for (initArcIterator(&iter, arc, head), previous = nextBucket(&iter), current = nextBucket(&iter);
-                       current;
-                       previous = current, current = nextBucket(&iter))
+               initArcIterator(iter, arc, head);
+               IT_next(iter);
+               previous = iter->p;
+               
+               for (IT_next(iter);
+                       IT_stopped(iter) == 0;
+                       previous = iter->p, IT_next(iter))
                {
                        float vec1[3], vec2[3];
                        float len1, len2;
+                       
+                       current = iter->p;
 
-                       VecSubf(vec1, previous->p, parent->head);
-                       VecSubf(vec2, current->p, previous->p);
+                       VecSubf(vec1, previous, parent->head);
+                       VecSubf(vec2, current, previous);
 
                        len1 = Normalize(vec1);
                        len2 = Normalize(vec2);
 
                        if (len1 > 0.0f && len2 > 0.0f && Inpf(vec1, vec2) < angleLimit)
                        {
-                               VECCOPY(parent->tail, previous->p);
+                               VECCOPY(parent->tail, previous);
 
                                child = add_editbone("Bone");
                                VECCOPY(child->head, parent->tail);
@@ -4604,179 +4718,26 @@ EditBone * subdivideByAngle(ReebArc *arc, ReebNode *head, ReebNode *tail)
        return lastBone;
 }
 
-float calcVariance(ReebArc *arc, int start, int end, float v0[3], float n[3])
-{
-       int len = 2 + abs(end - start);
-       
-       if (len > 2)
-       {
-               ReebArcIterator iter;
-               EmbedBucket *bucket = NULL;
-               float avg_t = 0.0f;
-               float s_t = 0.0f;
-               float s_xyz = 0.0f;
-               
-               /* First pass, calculate average */
-               for (initArcIterator2(&iter, arc, start, end), bucket = nextBucket(&iter);
-                       bucket;
-                       bucket = nextBucket(&iter))
-               {
-                       float v[3];
-                       
-                       VecSubf(v, bucket->p, v0);
-                       avg_t += Inpf(v, n);
-               }
-               
-               avg_t /= Inpf(n, n);
-               avg_t += 1.0f; /* adding start (0) and end (1) values */
-               avg_t /= len;
-               
-               /* Second pass, calculate s_xyz and s_t */
-               for (initArcIterator2(&iter, arc, start, end), bucket = nextBucket(&iter);
-                       bucket;
-                       bucket = nextBucket(&iter))
-               {
-                       float v[3], d[3];
-                       float dt;
-                       
-                       VecSubf(v, bucket->p, v0);
-                       Projf(d, v, n);
-                       VecSubf(v, v, d);
-                       
-                       dt = VecLength(d) - avg_t;
-                       
-                       s_t += dt * dt;
-                       s_xyz += Inpf(v, v);
-               }
-               
-               /* adding start(0) and end(1) values to s_t */
-               s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t);
-               
-               return s_xyz / s_t; 
-       }
-       else
-       {
-               return 0;
-       }
-}
-
-float calcDistance(ReebArc *arc, int start, int end, float head[3], float tail[3])
-{
-       ReebArcIterator iter;
-       EmbedBucket *bucket = NULL;
-       float max_dist = 0;
-       
-       /* calculate maximum distance */
-       for (initArcIterator2(&iter, arc, start, end), bucket = nextBucket(&iter);
-               bucket;
-               bucket = nextBucket(&iter))
-       {
-               float v1[3], v2[3], c[3];
-               float dist;
-               
-               VecSubf(v1, head, tail);
-               VecSubf(v2, bucket->p, tail);
-
-               Crossf(c, v1, v2);
-               
-               dist = Inpf(c, c) / Inpf(v1, v1);
-               
-               max_dist = dist > max_dist ? dist : max_dist;
-       }
-       
-       
-       return max_dist; 
-}
-
-EditBone * subdivideByCorrelation(ReebArc *arc, ReebNode *head, ReebNode *tail)
+EditBone * test_subdivideByCorrelation(ReebArc *arc, ReebNode *head, ReebNode *tail)
 {
-       ReebArcIterator iter;
-       float n[3];
-       float ADAPTIVE_THRESHOLD = G.scene->toolsettings->skgen_correlation_limit;
        EditBone *lastBone = NULL;
-       
-       /* init iterator to get start and end from head */
-       initArcIterator(&iter, arc, head);
-       
-       /* Calculate overall */
-       VecSubf(n, arc->buckets[iter.end].p, head->p);
-       
+
        if (G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION)
        {
-               EmbedBucket *bucket = NULL;
-               EmbedBucket *previous = NULL;
-               EditBone *child = NULL;
-               EditBone *parent = NULL;
-               float normal[3] = {0, 0, 0};
-               float avg_normal[3];
-               int total = 0;
-               int boneStart = iter.start;
+               float invmat[4][4] = {  {1, 0, 0, 0},
+                                                               {0, 1, 0, 0},
+                                                               {0, 0, 1, 0},
+                                                               {0, 0, 0, 1}};
+               float tmat[3][3] = {    {1, 0, 0},
+                                                               {0, 1, 0},
+                                                               {0, 0, 1}};
+               ReebArcIterator arc_iter;
+               BArcIterator *iter = (BArcIterator*)&arc_iter;
+               bArmature *arm= G.obedit->data;
                
-               parent = add_editbone("Bone");
-               parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
-               VECCOPY(parent->head, head->p);
+               initArcIterator(iter, arc, head);
                
-               for (previous = nextBucket(&iter), bucket = nextBucket(&iter);
-                       bucket;
-                       previous = bucket, bucket = nextBucket(&iter))
-               {
-                       float btail[3];
-                       float value = 0;
-
-                       if (G.scene->toolsettings->skgen_options & SKGEN_STICK_TO_EMBEDDING)
-                       {
-                               VECCOPY(btail, bucket->p);
-                       }
-                       else
-                       {
-                               float length;
-                               
-                               /* Calculate normal */
-                               VecSubf(n, bucket->p, parent->head);
-                               length = Normalize(n);
-                               
-                               total += 1;
-                               VecAddf(normal, normal, n);
-                               VECCOPY(avg_normal, normal);
-                               VecMulf(avg_normal, 1.0f / total);
-                                
-                               VECCOPY(btail, avg_normal);
-                               VecMulf(btail, length);
-                               VecAddf(btail, btail, parent->head);
-                       }
-
-                       if (G.scene->toolsettings->skgen_options & SKGEN_ADAPTIVE_DISTANCE)
-                       {
-                               value = calcDistance(arc, boneStart, iter.index, parent->head, btail);
-                       }
-                       else
-                       {
-                               float n[3];
-                               
-                               VecSubf(n, btail, parent->head);
-                               value = calcVariance(arc, boneStart, iter.index, parent->head, n);
-                       }
-
-                       if (value > ADAPTIVE_THRESHOLD)
-                       {
-                               VECCOPY(parent->tail, btail);
-
-                               child = add_editbone("Bone");
-                               VECCOPY(child->head, parent->tail);
-                               child->parent = parent;
-                               child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
-                               
-                               parent = child; // new child is next parent
-                               boneStart = iter.index; // start from end
-                               
-                               normal[0] = normal[1] = normal[2] = 0;
-                               total = 0;
-                       }
-               }
-
-               VECCOPY(parent->tail, tail->p);
-               
-               lastBone = parent; /* set last bone in the chain */
+               lastBone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
        }
        
        return lastBone;
@@ -4809,107 +4770,26 @@ float arcLengthRatio(ReebArc *arc)
        return embedLength / arcLength; 
 }
 
-EditBone * subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail)
+EditBone * test_subdivideByLength(ReebArc *arc, ReebNode *head, ReebNode *tail)
 {
        EditBone *lastBone = NULL;
        if ((G.scene->toolsettings->skgen_options & SKGEN_CUT_LENGTH) &&
                arcLengthRatio(arc) >= G.scene->toolsettings->skgen_length_ratio)
        {
-               ReebArcIterator iter;
-               EmbedBucket *bucket = NULL;
-               EmbedBucket *previous = NULL;
-               EditBone *child = NULL;
-               EditBone *parent = NULL;
-               float lengthLimit = G.scene->toolsettings->skgen_length_limit;
-               int same = 0;
-               
-               parent = add_editbone("Bone");
-               parent->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
-               VECCOPY(parent->head, head->p);
-
-               initArcIterator(&iter, arc, head);
-
-               bucket = nextBucket(&iter);
+               float invmat[4][4] = {  {1, 0, 0, 0},
+                                                               {0, 1, 0, 0},
+                                                               {0, 0, 1, 0},
+                                                               {0, 0, 0, 1}};
+               float tmat[3][3] = {    {1, 0, 0},
+                                                               {0, 1, 0},
+                                                               {0, 0, 1}};
+               ReebArcIterator arc_iter;
+               BArcIterator *iter = (BArcIterator*)&arc_iter;
+               bArmature *arm= G.obedit->data;
                
-               while (bucket != NULL)
-               {
-                       float *vec0 = NULL;
-                       float *vec1 = bucket->p;
-
-                       /* first bucket. Previous is head */
-                       if (previous == NULL)
-                       {
-                               vec0 = head->p;
-                       }
-                       /* Previous is a valid bucket */
-                       else
-                       {
-                               vec0 = previous->p;
-                       }
-                       
-                       /* If lengthLimit hits the current segment */
-                       if (VecLenf(vec1, parent->head) > lengthLimit)
-                       {
-                               if (same == 0)
-                               {
-                                       float dv[3], off[3];
-                                       float a, b, c, f;
-                                       
-                                       /* Solve quadratic distance equation */
-                                       VecSubf(dv, vec1, vec0);
-                                       a = Inpf(dv, dv);
-                                       
-                                       VecSubf(off, vec0, parent->head);
-                                       b = 2 * Inpf(dv, off);
-                                       
-                                       c = Inpf(off, off) - (lengthLimit * lengthLimit);
-                                       
-                                       f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a);
-                                       
-                                       //printf("a %f, b %f, c %f, f %f\n", a, b, c, f);
-                                       
-                                       if (isnan(f) == 0 && f < 1.0f)
-                                       {
-                                               VECCOPY(parent->tail, dv);
-                                               VecMulf(parent->tail, f);
-                                               VecAddf(parent->tail, parent->tail, vec0);
-                                       }
-                                       else
-                                       {
-                                               VECCOPY(parent->tail, vec1);
-                                       }
-                               }
-                               else
-                               {
-                                       float dv[3];
-                                       
-                                       VecSubf(dv, vec1, vec0);
-                                       Normalize(dv);
-                                        
-                                       VECCOPY(parent->tail, dv);
-                                       VecMulf(parent->tail, lengthLimit);
-                                       VecAddf(parent->tail, parent->tail, parent->head);
-                               }
-                               
-                               child = add_editbone("Bone");
-                               VECCOPY(child->head, parent->tail);
-                               child->parent = parent;
-                               child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
-                               
-                               parent = child; // new child is next parent
-                               
-                               same = 1; // mark as same
-                       }
-                       else
-                       {
-                               previous = bucket;
-                               bucket = nextBucket(&iter);
-                               same = 0; // Reset same
-                       }
-               }
-               VECCOPY(parent->tail, tail->p);
+               initArcIterator(iter, arc, head);
                
-               lastBone = parent; /* set last bone in the chain */
+               lastBone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextLengthSubdivision);
        }
        
        return lastBone;
@@ -5002,13 +4882,13 @@ void generateSkeletonFromReebGraph(ReebGraph *rg)
                        switch(G.scene->toolsettings->skgen_subdivisions[i])
                        {
                                case SKGEN_SUB_LENGTH:
-                                       lastBone = subdivideByLength(arc, head, tail);
+                                       lastBone = test_subdivideByLength(arc, head, tail);
                                        break;
                                case SKGEN_SUB_ANGLE:
                                        lastBone = subdivideByAngle(arc, head, tail);
                                        break;
                                case SKGEN_SUB_CORRELATION:
-                                       lastBone = subdivideByCorrelation(arc, head, tail);
+                                       lastBone = test_subdivideByCorrelation(arc, head, tail);
                                        break;
                        }
                }
diff --git a/source/blender/src/editarmature_generate.c b/source/blender/src/editarmature_generate.c
new file mode 100644 (file)
index 0000000..189a823
--- /dev/null
@@ -0,0 +1,327 @@
+/**
+ * $Id: editarmature_generate.c  $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * editarmature.c: Interface for creating and posing armature objects
+ */
+
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_scene_types.h"
+#include "DNA_armature_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_graph.h"
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+
+#include "BIF_editarmature.h"
+#include "BIF_generate.h"
+
+void setBoneRollFromNormal(EditBone *bone, float *no, float invmat[][4], float tmat[][3])
+{
+       if (no != NULL && !VecIsNull(no))
+       {
+               float tangent[3], cotangent[3], normal[3];
+
+               VECCOPY(normal, no);    
+               Mat3MulVecfl(tmat, normal);
+
+               VecSubf(tangent, bone->tail, bone->head);
+               Crossf(cotangent, tangent, normal);
+               Crossf(normal, cotangent, tangent);
+               
+               Normalize(normal);
+               
+               bone->roll = rollBoneToVector(bone, normal);
+       }
+}
+
+float calcArcCorrelation(BArcIterator *iter, int start, int end, float v0[3], float n[3])
+{
+       int len = 2 + abs(end - start);
+       
+       if (len > 2)
+       {
+               float avg_t = 0.0f;
+               float s_t = 0.0f;
+               float s_xyz = 0.0f;
+               int i;
+               
+               /* First pass, calculate average */
+               for (i = start; i <= end; i++)
+               {
+                       float v[3];
+                       
+                       IT_peek(iter, i);
+                       VecSubf(v, iter->p, v0);
+                       avg_t += Inpf(v, n);
+               }
+               
+               avg_t /= Inpf(n, n);
+               avg_t += 1.0f; /* adding start (0) and end (1) values */
+               avg_t /= len;
+               
+               /* Second pass, calculate s_xyz and s_t */
+               for (i = start; i <= end; i++)
+               {
+                       float v[3], d[3];
+                       float dt;
+                       
+                       IT_peek(iter, i);
+                       VecSubf(v, iter->p, v0);
+                       Projf(d, v, n);
+                       VecSubf(v, v, d);
+                       
+                       dt = VecLength(d) - avg_t;
+                       
+                       s_t += dt * dt;
+                       s_xyz += Inpf(v, v);
+               }
+               
+               /* adding start(0) and end(1) values to s_t */
+               s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t);
+               
+               return 1.0f - s_xyz / s_t; 
+       }
+       else
+       {
+               return 1.0f;
+       }
+}
+
+int nextFixedSubdivision(BArcIterator *iter, int start, int end, float head[3], float p[3])
+{
+       static float stroke_length = 0;
+       static float current_length;
+       static char n;
+       float *v1, *v2;
+       float length_threshold;
+       int i;
+       
+       if (stroke_length == 0)
+       {
+               current_length = 0;
+
+               IT_peek(iter, start);
+               v1 = iter->p;
+               
+               for (i = start + 1; i <= end; i++)
+               {
+                       IT_peek(iter, i);
+                       v2 = iter->p;
+
+                       stroke_length += VecLenf(v1, v2);
+                       
+                       v1 = v2;
+               }
+               
+               n = 0;
+               current_length = 0;
+       }
+       
+       n++;
+       
+       length_threshold = n * stroke_length / G.scene->toolsettings->skgen_subdivision_number;
+       
+       IT_peek(iter, start);
+       v1 = iter->p;
+
+       /* < and not <= because we don't care about end, it is P_EXACT anyway */
+       for (i = start + 1; i < end; i++)
+       {
+               IT_peek(iter, i);
+               v2 = iter->p;
+
+               current_length += VecLenf(v1, v2);
+
+               if (current_length >= length_threshold)
+               {
+                       VECCOPY(p, v2);
+                       return i;
+               }
+               
+               v1 = v2;
+       }
+       
+       stroke_length = 0;
+       
+       return -1;
+}
+int nextAdaptativeSubdivision(BArcIterator *iter, int start, int end, float head[3], float p[3])
+{
+       float correlation_threshold = G.scene->toolsettings->skgen_correlation_limit;
+       float *start_p;
+       float n[3];
+       int i;
+       
+       IT_peek(iter, start);
+       start_p = iter->p;
+
+       for (i = start + 2; i <= end; i++)
+       {
+               /* Calculate normal */
+               IT_peek(iter, i);
+               VecSubf(n, iter->p, head);
+
+               if (calcArcCorrelation(iter, start, i, start_p, n) < correlation_threshold)
+               {
+                       IT_peek(iter, i - 1);
+                       VECCOPY(p, iter->p);
+                       return i - 1;
+               }
+       }
+       
+       return -1;
+}
+
+int nextLengthSubdivision(BArcIterator *iter, int start, int end, float head[3], float p[3])
+{
+       float lengthLimit = G.scene->toolsettings->skgen_length_limit;
+       int same = 1;
+       int i;
+       
+       i = start + 1;
+       while (i <= end)
+       {
+               float *vec0;
+               float *vec1;
+               
+               IT_peek(iter, i - 1);
+               vec0 = iter->p;
+
+               IT_peek(iter, i);
+               vec1 = iter->p;
+               
+               /* If lengthLimit hits the current segment */
+               if (VecLenf(vec1, head) > lengthLimit)
+               {
+                       if (same == 0)
+                       {
+                               float dv[3], off[3];
+                               float a, b, c, f;
+                               
+                               /* Solve quadratic distance equation */
+                               VecSubf(dv, vec1, vec0);
+                               a = Inpf(dv, dv);
+                               
+                               VecSubf(off, vec0, head);
+                               b = 2 * Inpf(dv, off);
+                               
+                               c = Inpf(off, off) - (lengthLimit * lengthLimit);
+                               
+                               f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a);
+                               
+                               //printf("a %f, b %f, c %f, f %f\n", a, b, c, f);
+                               
+                               if (isnan(f) == 0 && f < 1.0f)
+                               {
+                                       VECCOPY(p, dv);
+                                       VecMulf(p, f);
+                                       VecAddf(p, p, vec0);
+                               }
+                               else
+                               {
+                                       VECCOPY(p, vec1);
+                               }
+                       }
+                       else
+                       {
+                               float dv[3];
+                               
+                               VecSubf(dv, vec1, vec0);
+                               Normalize(dv);
+                                
+                               VECCOPY(p, dv);
+                               VecMulf(p, lengthLimit);
+                               VecAddf(p, p, head);
+                       }
+                       
+                       return i - 1; /* restart at lower bound */
+               }
+               else
+               {
+                       i++;
+                       same = 0; // Reset same
+               }
+       }
+       
+       return -1;
+}
+
+EditBone * subdivideArcBy(bArmature *arm, ListBase *editbones, BArcIterator *iter, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion)
+{
+       EditBone *lastBone = NULL;
+       EditBone *child = NULL;
+       EditBone *parent = NULL;
+       int bone_start = 0;
+       int end = iter->length;
+       int index;
+       
+       IT_head(iter);
+       
+       parent = addEditBone("Bone", editbones, arm);
+       VECCOPY(parent->head, iter->p);
+       
+       index = next_subdividion(iter, bone_start, end, parent->head, parent->tail);
+       while (index != -1)
+       {
+               IT_peek(iter, index);
+
+               child = addEditBone("Bone", editbones, arm);
+               VECCOPY(child->head, parent->tail);
+               child->parent = parent;
+               child->flag |= BONE_CONNECTED;
+               
+               /* going to next bone, fix parent */
+               Mat4MulVecfl(invmat, parent->tail);
+               Mat4MulVecfl(invmat, parent->head);
+               setBoneRollFromNormal(parent, iter->no, invmat, tmat);
+
+               parent = child; // new child is next parent
+               bone_start = index; // start next bone from current index
+
+               index = next_subdividion(iter, bone_start, end, parent->head, parent->tail);
+       }
+       
+       iter->tail(iter);
+
+       VECCOPY(parent->tail, iter->p);
+
+       /* fix last bone */
+       Mat4MulVecfl(invmat, parent->tail);
+       Mat4MulVecfl(invmat, parent->head);
+       setBoneRollFromNormal(parent, iter->no, invmat, tmat);
+       lastBone = parent;
+       
+       return lastBone;
+}
similarity index 72%
rename from source/blender/src/autoarmature.c
rename to source/blender/src/editarmature_retarget.c
index b0a7a2ab5cc72a7d4ebd56822f5c3af98648d934..ad114868a69520759945021a88b18cf5d94292dd 100644 (file)
@@ -62,7 +62,9 @@
 #include "BKE_armature.h"
 
 #include "BIF_editarmature.h"
+#include "BIF_retarget.h"
 #include "BIF_space.h"
+#include "BIF_toolbox.h"
 
 #include "PIL_time.h"
 
 
 /************ RIG RETARGET DATA STRUCTURES ***************/
 
-struct RigJoint;
-struct RigGraph;
-struct RigNode;
-struct RigArc;
-struct RigEdge;
-
-//#define USE_THREADS
-
-typedef struct RigGraph {
-       ListBase        arcs;
-       ListBase        nodes;
-       
-       float length;
-       
-       FreeArc                 free_arc;
-       FreeNode                free_node;
-       RadialSymmetry  radial_symmetry;
-       AxialSymmetry   axial_symmetry;
-       /*********************************/
-
-       struct RigNode *head;
-       ReebGraph *link_mesh;
-       
-       ListBase editbones;
-       
-       ListBase controls;
-       struct ThreadedWorker *worker;
-       
-       GHash *bones_map;       /* map of editbones by name */
-       GHash *controls_map;    /* map of rigcontrols by bone pointer */
-       
-       Object *ob;
-} RigGraph;
-
-typedef struct RigNode {
-       void *next, *prev;
-       float p[3];
-       int flag;
-
-       int degree;
-       struct BArc **arcs;
-
-       int subgraph_index;
-
-       int symmetry_level;
-       int symmetry_flag;
-       float symmetry_axis[3];
-       /*********************************/
-
-       ReebNode *link_mesh;
-} RigNode;
-
-typedef struct RigArc {
-       void *next, *prev;
-       RigNode *head, *tail;
-       int flag;
-
-       float length;
-
-       int symmetry_level;
-       int symmetry_group;
-       int symmetry_flag;
-       /*********************************/
-       
-       ListBase edges;
-       int count;
-       ReebArc *link_mesh;
-} RigArc;
-
-typedef struct RigEdge {
-       struct RigEdge *next, *prev;
-       float head[3], tail[3];
-       float length;
-       float angle;
-       EditBone *bone;
-       float up_axis[3];
-} RigEdge;
-
-/* Control flags */
-#define RIG_CTRL_DONE                  1
-#define RIG_CTRL_PARENT_DEFORM 2
-#define RIG_CTRL_FIT_ROOT              4
-#define RIG_CTRL_FIT_BONE              8
-
-typedef struct RigControl {
-       struct RigControl *next, *prev;
-       float head[3], tail[3];
-       EditBone *bone;
-       EditBone *link;
-       float   up_axis[3];
-       float   offset[3];
-       int             flag;
-} RigControl;
-
 typedef struct MemoNode {
        float   weight;
        int     next;
@@ -186,8 +94,7 @@ typedef enum
 typedef enum
 {
        METHOD_BRUTE_FORCE = 0,
-       METHOD_MEMOIZE = 1,
-       METHOD_ANNEALING = 2
+       METHOD_MEMOIZE = 1
 } RetargetMethod;
 
 typedef enum
@@ -197,14 +104,14 @@ typedef enum
        ARC_USED = 2
 } ArcUsageFlags;
 
-
 RigGraph *GLOBAL_RIGG = NULL;
 
 /*******************************************************************************************************/
 
 void *exec_retargetArctoArc(void *param);
 
-static void RIG_calculateEdgeAngle(RigEdge *edge_first, RigEdge *edge_second);
+static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second);
+float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4]);
 
 /* two levels */
 #define SHAPE_LEVELS (SHAPE_RADIX * SHAPE_RADIX) 
@@ -256,30 +163,105 @@ void getEditBoneRollUpAxis(EditBone *bone, float roll, float up_axis[3])
        VECCOPY(up_axis, mat[2]);
 }
 
-float getNewBoneRoll(EditBone *bone, float old_up_axis[3], float quat[4])
+float rollBoneByQuatAligned(EditBone *bone, float old_up_axis[3], float qrot[4], float qroll[4], float aligned_axis[3])
 {
-       float mat[3][3];
-       float nor[3], up_axis[3], new_up_axis[3], vec[3];
-       float roll;
+       float nor[3], new_up_axis[3], x_axis[3], z_axis[3];
        
        VECCOPY(new_up_axis, old_up_axis);
-       QuatMulVecf(quat, new_up_axis);
-
+       QuatMulVecf(qrot, new_up_axis);
+       
        VecSubf(nor, bone->tail, bone->head);
        
-       vec_roll_to_mat3(nor, 0, mat);
-       VECCOPY(up_axis, mat[2]);
+       Crossf(x_axis, nor, aligned_axis);
+       Crossf(z_axis, x_axis, nor);
        
-       roll = NormalizedVecAngle2(new_up_axis, up_axis);
+       Normalize(new_up_axis);
+       Normalize(x_axis);
+       Normalize(z_axis);
+       
+       if (Inpf(new_up_axis, x_axis) < 0)
+       {
+               VecMulf(x_axis, -1);
+       }
        
-       Crossf(vec, up_axis, new_up_axis);
+       if (Inpf(new_up_axis, z_axis) < 0)
+       {
+               VecMulf(z_axis, -1);
+       }
        
-       if (Inpf(vec, nor) < 0)
+       if (NormalizedVecAngle2(x_axis, new_up_axis) < NormalizedVecAngle2(z_axis, new_up_axis))
+       {
+               RotationBetweenVectorsToQuat(qroll, new_up_axis, x_axis); /* set roll rotation quat */
+               return rollBoneToVector(bone, x_axis);
+       }
+       else
+       {
+               RotationBetweenVectorsToQuat(qroll, new_up_axis, z_axis); /* set roll rotation quat */
+               return rollBoneToVector(bone, z_axis);
+       }
+}
+
+float rollBoneByQuatJoint(RigEdge *edge, RigEdge *previous, float qrot[4], float qroll[4])
+{
+       if (previous == NULL)
+       {
+               QuatOne(qroll);
+               return rollBoneByQuat(edge->bone, edge->up_axis, qrot);
+       }
+       else
        {
-               roll = -roll;
+               float new_up_axis[3];
+               float vec_first[3], vec_second[3], normal[3];
+               
+               if (previous->bone)
+               {
+                       VecSubf(vec_first, previous->bone->tail, previous->bone->head);
+               } 
+               else if (previous->prev->bone)
+               {
+                       VecSubf(vec_first, edge->bone->head, previous->prev->bone->tail);
+               }
+               else
+               {
+                       /* SHOULDN'T BE HERE */
+                       QuatOne(qroll);
+                       return rollBoneByQuat(edge->bone, edge->up_axis, qrot);
+               }
+               
+               VecSubf(vec_second, edge->bone->tail, edge->bone->head);
+       
+               Normalize(vec_first);
+               Normalize(vec_second);
+               
+               Crossf(normal, vec_first, vec_second);
+               Normalize(normal);
+               
+               AxisAngleToQuat(qroll, vec_second, edge->up_angle);
+               
+               QuatMulVecf(qroll, normal);
+                       
+               VECCOPY(new_up_axis, edge->up_axis);
+               QuatMulVecf(qrot, new_up_axis);
+               
+               Normalize(new_up_axis);
+               
+               /* real qroll between normal and up_axis */
+               RotationBetweenVectorsToQuat(qroll, new_up_axis, normal);
+
+               return rollBoneToVector(edge->bone, normal);
        }
+}
+
+float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4])
+{
+       float new_up_axis[3];
+       
+       VECCOPY(new_up_axis, old_up_axis);
+       QuatMulVecf(qrot, new_up_axis);
        
-       return roll;
+       Normalize(new_up_axis);
+       
+       return rollBoneToVector(bone, new_up_axis);
 }
 
 /************************************ DESTRUCTORS ******************************************************/
@@ -291,14 +273,18 @@ void RIG_freeRigArc(BArc *arc)
 
 void RIG_freeRigGraph(BGraph *rg)
 {
+       RigGraph *rigg = (RigGraph*)rg;
        BNode *node;
        BArc *arc;
        
 #ifdef USE_THREADS
-       BLI_destroy_worker(((RigGraph*)rg)->worker);
+       BLI_destroy_worker(rigg->worker);
 #endif
        
-       REEB_freeGraph(((RigGraph*)rg)->link_mesh);
+       if (rigg->link_mesh)
+       {
+               REEB_freeGraph(rigg->link_mesh);
+       }
        
        for (arc = rg->arcs.first; arc; arc = arc->next)
        {
@@ -312,12 +298,16 @@ void RIG_freeRigGraph(BGraph *rg)
        }
        BLI_freelistN(&rg->nodes);
        
-       BLI_freelistN(&((RigGraph*)rg)->controls);
+       BLI_freelistN(&rigg->controls);
 
-       BLI_ghash_free(((RigGraph*)rg)->bones_map, NULL, NULL);
-       BLI_ghash_free(((RigGraph*)rg)->controls_map, NULL, NULL);
+       BLI_ghash_free(rigg->bones_map, NULL, NULL);
+       BLI_ghash_free(rigg->controls_map, NULL, NULL);
        
-       BLI_freelistN(&((RigGraph*)rg)->editbones);
+       if (rigg->editbones != &G.edbo)
+       {
+               BLI_freelistN(rigg->editbones);
+               MEM_freeN(rigg->editbones);
+       }
        
        MEM_freeN(rg);
 }
@@ -434,7 +424,7 @@ static void RIG_appendEdgeToArc(RigArc *arc, RigEdge *edge)
        {
                RigEdge *last_edge = edge->prev;
                VECCOPY(edge->head, last_edge->tail);
-               RIG_calculateEdgeAngle(last_edge, edge);
+               RIG_calculateEdgeAngles(last_edge, edge);
        }
        
        edge->length = VecLenf(edge->head, edge->tail);
@@ -460,10 +450,226 @@ static void RIG_addEdgeToArc(RigArc *arc, float tail[3], EditBone *bone)
        
        RIG_appendEdgeToArc(arc, edge);
 }
+/************************************** CLONING TEMPLATES **********************************************/
+
+static void renameTemplateBone(char *name, char *template_name, ListBase *editbones)
+{
+       char *side_string = G.scene->toolsettings->skgen_side_string;
+       char *num_string = G.scene->toolsettings->skgen_num_string;
+       int i, j;
+       
+       for (i = 0, j = 0; template_name[i] != '\0' && i < 31 && j < 31; i++)
+       {
+               if (template_name[i] == '&')
+               {
+                       if (template_name[i+1] == 'S' || template_name[i+1] == 's')
+                       {
+                               j += sprintf(name + j, side_string);
+                               i++;
+                       }
+                       else if (template_name[i+1] == 'N' || template_name[i+1] == 'n')
+                       {
+                               j += sprintf(name + j, num_string);
+                               i++;
+                       }
+                       else
+                       {
+                               name[j] = template_name[i];
+                               j++;
+                       }
+               }
+               else
+               {
+                       name[j] = template_name[i];
+                       j++;
+               }
+       }
+       
+       name[j] = '\0';
+       
+       unique_editbone_name(editbones, name, NULL);
+}
+
+static RigControl *cloneControl(RigGraph *rg, RigGraph *src_rg, RigControl *src_ctrl, GHash *ptr_hash)
+{
+       RigControl *ctrl;
+       char name[32];
+       
+       ctrl = newRigControl(rg);
+       
+       VECCOPY(ctrl->head, src_ctrl->head);
+       VECCOPY(ctrl->tail, src_ctrl->tail);
+       VECCOPY(ctrl->up_axis, src_ctrl->up_axis);
+       VECCOPY(ctrl->offset, src_ctrl->offset);
+       
+       ctrl->tail_mode = src_ctrl->tail_mode;
+       ctrl->flag = src_ctrl->flag;
+
+       renameTemplateBone(name, src_ctrl->bone->name, rg->editbones);
+       ctrl->bone = duplicateEditBoneObjects(src_ctrl->bone, name, rg->editbones, src_rg->ob, rg->ob);
+       ctrl->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE);
+       BLI_ghash_insert(ptr_hash, src_ctrl->bone, ctrl->bone);
+       
+       ctrl->link = src_ctrl->link;
+       ctrl->link_tail = src_ctrl->link_tail;
+       
+       return ctrl;
+}
+
+static RigArc *cloneArc(RigGraph *rg, RigGraph *src_rg, RigArc *src_arc, GHash *ptr_hash)
+{
+       RigEdge *src_edge;
+       RigArc  *arc;
+       
+       arc = newRigArc(rg);
+       
+       arc->head = BLI_ghash_lookup(ptr_hash, src_arc->head);
+       arc->tail = BLI_ghash_lookup(ptr_hash, src_arc->tail);
+       
+       arc->head->degree++;
+       arc->tail->degree++;
+       
+       arc->length = src_arc->length;
+
+       arc->count = src_arc->count;
+       
+       for (src_edge = src_arc->edges.first; src_edge; src_edge = src_edge->next)
+       {
+               RigEdge *edge;
+       
+               edge = MEM_callocN(sizeof(RigEdge), "rig edge");
+
+               VECCOPY(edge->head, src_edge->head);
+               VECCOPY(edge->tail, src_edge->tail);
+               VECCOPY(edge->up_axis, src_edge->up_axis);
+               
+               edge->length = src_edge->length;
+               edge->angle = src_edge->angle;
+               edge->up_angle = src_edge->up_angle;
+               
+               if (src_edge->bone != NULL)
+               {
+                       char name[32];
+                       renameTemplateBone(name, src_edge->bone->name, rg->editbones);
+                       edge->bone = duplicateEditBoneObjects(src_edge->bone, name, rg->editbones, src_rg->ob, rg->ob);
+                       edge->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL|BONE_ACTIVE);
+                       BLI_ghash_insert(ptr_hash, src_edge->bone, edge->bone);
+               }
+
+               BLI_addtail(&arc->edges, edge);
+       }
+       
+       return arc;
+}
+
+static RigGraph *cloneRigGraph(RigGraph *src, ListBase *editbones, Object *ob)
+{
+       GHash   *ptr_hash;      
+       RigNode *node;
+       RigArc  *arc;
+       RigControl *ctrl;
+       RigGraph *rg;
+       
+       ptr_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+       rg = newRigGraph();
+       
+       rg->ob = ob;
+       rg->editbones = editbones;
+       
+       preEditBoneDuplicate(rg->editbones); /* prime bones for duplication */
+       preEditBoneDuplicate(src->editbones); /* prime bones for duplication */
+       
+       /* Clone nodes */
+       for (node = src->nodes.first; node; node = node->next)
+       {
+               RigNode *cloned_node = newRigNode(rg, node->p);
+               BLI_ghash_insert(ptr_hash, node, cloned_node);
+       }
+       
+       rg->head = BLI_ghash_lookup(ptr_hash, src->head);
+       
+       /* Clone arcs */
+       for (arc = src->arcs.first; arc; arc = arc->next)
+       {
+               cloneArc(rg, src, arc, ptr_hash);
+       }
+       
+       /* Clone controls */
+       for (ctrl = src->controls.first; ctrl; ctrl = ctrl->next)
+       {
+               cloneControl(rg, src, ctrl, ptr_hash);
+       }
+       
+       /* Relink bones properly */
+       for (arc = rg->arcs.first; arc; arc = arc->next)
+       {
+               RigEdge *edge;
+               
+               for (edge = arc->edges.first; edge; edge = edge->next)
+               {
+                       if (edge->bone != NULL)
+                       {
+                               EditBone *bone;
+                               
+                               updateDuplicateSubtargetObjects(edge->bone, src->editbones, src->ob, rg->ob);
+
+                               if (edge->bone->parent)
+                               {                               
+                                       bone = BLI_ghash_lookup(ptr_hash, edge->bone->parent);
+               
+                                       if (bone != NULL)
+                                       {
+                                               edge->bone->parent = bone;
+                                       }
+                                       else
+                                       {
+                                               /* disconnect since parent isn't cloned
+                                                * this will only happen when cloning from selected bones 
+                                                * */
+                                               edge->bone->flag &= ~BONE_CONNECTED;
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
+       {
+               EditBone *bone;
+               
+               updateDuplicateSubtargetObjects(ctrl->bone, src->editbones, src->ob, rg->ob);
+
+               if (ctrl->bone->parent)
+               {
+                       bone = BLI_ghash_lookup(ptr_hash, ctrl->bone->parent);
+                       
+                       if (bone != NULL)
+                       {
+                               ctrl->bone->parent = bone;
+                       }
+                       else
+                       {
+                               /* disconnect since parent isn't cloned
+                                * this will only happen when cloning from selected bones 
+                                * */
+                               ctrl->bone->flag &= ~BONE_CONNECTED;
+                       }
+               }
+
+               ctrl->link = BLI_ghash_lookup(ptr_hash, ctrl->link);
+               ctrl->link_tail = BLI_ghash_lookup(ptr_hash, ctrl->link_tail);
+       }
+       
+       BLI_ghash_free(ptr_hash, NULL, NULL);
+       
+       return rg;
+}
+
 
 /*******************************************************************************************************/
 
-static void RIG_calculateEdgeAngle(RigEdge *edge_first, RigEdge *edge_second)
+static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second)
 {
        float vec_first[3], vec_second[3];
        
@@ -473,7 +679,17 @@ static void RIG_calculateEdgeAngle(RigEdge *edge_first, RigEdge *edge_second)
        Normalize(vec_first);
        Normalize(vec_second);
        
-       edge_first->angle = saacos(Inpf(vec_first, vec_second));
+       edge_first->angle = NormalizedVecAngle2(vec_first, vec_second);
+       
+       if (edge_second->bone != NULL)
+       {
+               float normal[3];
+
+               Crossf(normal, vec_first, vec_second);
+               Normalize(normal);
+
+               edge_second->up_angle = NormalizedVecAngle2(normal, edge_second->up_axis);
+       }
 }
 
 /************************************ CONTROL BONES ****************************************************/
@@ -485,6 +701,7 @@ static void RIG_addControlBone(RigGraph *rg, EditBone *bone)
        VECCOPY(ctrl->head, bone->head);
        VECCOPY(ctrl->tail, bone->tail);
        getEditBoneRollUpAxis(bone, bone->roll, ctrl->up_axis);
+       ctrl->tail_mode = TL_NONE;
        
        BLI_ghash_insert(rg->controls_map, bone->name, ctrl);
 }
@@ -588,16 +805,31 @@ static void RIG_reconnectControlBones(RigGraph *rg)
                                /* constraint targets */
                                if (cti && cti->get_constraint_targets)
                                {
+                                       int target_index;
+                                       
                                        cti->get_constraint_targets(con, &targets);
                                        
-                                       for (ct= targets.first; ct; ct= ct->next)
+                                       for (target_index = 0, ct= targets.first; ct; target_index++, ct= ct->next)
                                        {
                                                if ((ct->tar == rg->ob) && strcmp(ct->subtarget, ctrl->bone->name) == 0)
                                                {
                                                        /* SET bone link to bone corresponding to pchan */
                                                        EditBone *link = BLI_ghash_lookup(rg->bones_map, pchan->name);
                                                        
-                                                       found = RIG_parentControl(ctrl, link);
+                                                       /* Making sure bone is in this armature */
+                                                       if (link != NULL)
+                                                       {
+                                                               /* for pole targets, link to parent bone instead, if possible */
+                                                               if (con->type == CONSTRAINT_TYPE_KINEMATIC && target_index == 1)
+                                                               {
+                                                                       if (link->parent && BLI_ghash_haskey(rg->bones_map, link->parent->name))
+                                                                       {
+                                                                               link = link->parent;
+                                                                       }
+                                                               }
+                                                               
+                                                               found = RIG_parentControl(ctrl, link);
+                                                       }
                                                }
                                        }
                                        
@@ -692,8 +924,6 @@ static void RIG_reconnectControlBones(RigGraph *rg)
        {
                change = 0;
                
-               printf("-------------------------\n");
-               
                for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
                {
                        /* if control is not linked yet */
@@ -736,7 +966,6 @@ static void RIG_reconnectControlBones(RigGraph *rg)
                                                                        /* if owner is a control bone, link with it */                                                                  
                                                                        if (link && link->link)
                                                                        {
-                                                                               printf("%s -constraint- %s\n", ctrl->bone->name, link->bone->name);
                                                                                RIG_parentControl(ctrl, link->bone);
                                                                                found = 1;
                                                                                break;
@@ -755,7 +984,6 @@ static void RIG_reconnectControlBones(RigGraph *rg)
                                        /* check if parent is already linked */
                                        if (ctrl_parent && ctrl_parent->link)
                                        {
-                                               printf("%s -parent- %s\n", ctrl->bone->name, ctrl_parent->bone->name);
                                                RIG_parentControl(ctrl, ctrl_parent->bone);
                                                change = 1;
                                        }
@@ -767,7 +995,6 @@ static void RIG_reconnectControlBones(RigGraph *rg)
                                                        /* if a child is linked, link to that one */
                                                        if (ctrl_child->link && ctrl_child->bone->parent == ctrl->bone)
                                                        {
-                                                               printf("%s -child- %s\n", ctrl->bone->name, ctrl_child->bone->name);
                                                                RIG_parentControl(ctrl, ctrl_child->bone);
                                                                change = 1;
                                                                break;
@@ -777,8 +1004,48 @@ static void RIG_reconnectControlBones(RigGraph *rg)
                                }
                        }
                }
-               
        }
+       
+       /* third pass, link control tails */
+       for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
+       {
+               /* fit bone already means full match, so skip those */
+               if ((ctrl->flag & RIG_CTRL_FIT_BONE) == 0)
+               {
+                       GHashIterator ghi;
+                       
+                       /* look on deform bones first */
+                       BLI_ghashIterator_init(&ghi, rg->bones_map);
+                       
+                       for( ; !BLI_ghashIterator_isDone(&ghi); BLI_ghashIterator_step(&ghi))
+                       {
+                               EditBone *bone = (EditBone*)BLI_ghashIterator_getValue(&ghi);
+                               
+                               /* don't link with parent */
+                               if (bone->parent != ctrl->bone)
+                               {
+                                       if (VecLenf(ctrl->bone->tail, bone->head) < 0.01)
+                                       {
+                                               ctrl->tail_mode = TL_HEAD;
+                                               ctrl->link_tail = bone;
+                                               break;
+                                       }
+                                       else if (VecLenf(ctrl->bone->tail, bone->tail) < 0.01)
+                                       {
+                                               ctrl->tail_mode = TL_TAIL;
+                                               ctrl->link_tail = bone;
+                                               break;
+                                       }
+                               }
+                       }
+                       
+                       /* if we haven't found one yet, look in control bones */
+                       if (ctrl->tail_mode == TL_NONE)
+                       {
+                       }
+               }
+       }
+       
 }
 
 /*******************************************************************************************************/
@@ -1034,7 +1301,7 @@ static void RIG_removeUneededOffsets(RigGraph *rg)
        }
 }
 
-static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bone, RigNode *starting_node)
+static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bone, RigNode *starting_node, int selected)
 {
        EditBone *bone, *last_bone = root_bone;
        RigArc *arc = NULL;
@@ -1044,42 +1311,45 @@ static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bo
        {
                int nb_children;
                
-               if ((bone->flag & BONE_NO_DEFORM) == 0)
-               {
-                       BLI_ghash_insert(rg->bones_map, bone->name, bone);
-               
-                       if (arc == NULL)
+               if (selected == 0 || (bone->flag & BONE_SELECTED))
+               { 
+                       if ((bone->flag & BONE_NO_DEFORM) == 0)
                        {
-                               arc = newRigArc(rg);
+                               BLI_ghash_insert(rg->bones_map, bone->name, bone);
+                       
+                               if (arc == NULL)
+                               {
+                                       arc = newRigArc(rg);
+                                       
+                                       if (starting_node == NULL)
+                                       {
+                                               starting_node = newRigNodeHead(rg, arc, root_bone->head);
+                                       }
+                                       else
+                                       {
+                                               addRigNodeHead(rg, arc, starting_node);
+                                       }
+                               }
                                
-                               if (starting_node == NULL)
+                               if (bone->parent && (bone->flag & BONE_CONNECTED) == 0)
                                {
-                                       starting_node = newRigNodeHead(rg, arc, root_bone->head);
+                                       RIG_addEdgeToArc(arc, bone->head, NULL);
                                }
-                               else
+                               
+                               RIG_addEdgeToArc(arc, bone->tail, bone);
+                               
+                               last_bone = bone;
+                               
+                               if (strcmp(bone->name, "head") == 0)
                                {
-                                       addRigNodeHead(rg, arc, starting_node);
+                                       contain_head = 1;
                                }
                        }
-                       
-                       if (bone->parent && (bone->flag & BONE_CONNECTED) == 0)
-                       {
-                               RIG_addEdgeToArc(arc, bone->head, NULL);
-                       }
-                       
-                       RIG_addEdgeToArc(arc, bone->tail, bone);
-                       
-                       last_bone = bone;
-                       
-                       if (strcmp(bone->name, "head") == 0)
+                       else if ((bone->flag & BONE_EDITMODE_LOCKED) == 0) /* ignore locked bones */
                        {
-                               contain_head = 1;
+                               RIG_addControlBone(rg, bone);
                        }
                }
-               else if ((bone->flag & BONE_EDITMODE_LOCKED) == 0) /* ignore locked bones */
-               {
-                       RIG_addControlBone(rg, bone);
-               }
                
                nb_children = countEditBoneChildren(list, bone);
                if (nb_children > 1)
@@ -1099,7 +1369,7 @@ static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bo
                        for (i = 0; i < nb_children; i++)
                        {
                                root_bone = nextEditBoneChild(list, bone, i);
-                               RIG_arcFromBoneChain(rg, list, root_bone, end_node);
+                               RIG_arcFromBoneChain(rg, list, root_bone, end_node, selected);
                        }
                        
                        /* arc ends here, break */
@@ -1266,21 +1536,30 @@ void RIG_printGraph(RigGraph *rg)
 
 /*******************************************************************************************************/
 
-static RigGraph *armatureToGraph(Object *ob, bArmature *arm)
+RigGraph *RIG_graphFromArmature(Object *ob, bArmature *arm)
 {
        EditBone *ebone;
        RigGraph *rg;
        
        rg = newRigGraph();
        
-       make_boneList(&rg->editbones, &arm->bonebase, NULL);
+       if (G.obedit == ob)
+       {
+               rg->editbones = &G.edbo;
+       }
+       else
+       {
+               rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones");
+               make_boneList(rg->editbones, &arm->bonebase, NULL);
+       }
+       
        rg->ob = ob;
 
        /* Do the rotations */
-       for (ebone = rg->editbones.first; ebone; ebone=ebone->next){
+       for (ebone = rg->editbones->first; ebone; ebone=ebone->next){
                if (ebone->parent == NULL)
                {
-                       RIG_arcFromBoneChain(rg, &rg->editbones, ebone, NULL);
+                       RIG_arcFromBoneChain(rg, rg->editbones, ebone, NULL, 0);
                }
        }
        
@@ -1306,14 +1585,62 @@ static RigGraph *armatureToGraph(Object *ob, bArmature *arm)
        return rg;
 }
 
-/************************************ GENERATING *****************************************************/
-
-static EditBone *add_editbonetolist(char *name, ListBase *list)
+RigGraph *armatureSelectedToGraph(Object *ob, bArmature *arm)
 {
-       EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone");
-       
-       BLI_strncpy(bone->name, name, 32);
-       unique_editbone_name(list, bone->name);
+       EditBone *ebone;
+       RigGraph *rg;
+       
+       rg = newRigGraph();
+       
+       if (G.obedit == ob)
+       {
+               rg->editbones = &G.edbo;
+       }
+       else
+       {
+               rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones");
+               make_boneList(rg->editbones, &arm->bonebase, NULL);
+       }
+
+       rg->ob = ob;
+
+       /* Do the rotations */
+       for (ebone = rg->editbones->first; ebone; ebone=ebone->next){
+               if (ebone->parent == NULL)
+               {
+                       RIG_arcFromBoneChain(rg, rg->editbones, ebone, NULL, 1);
+               }
+       }
+       
+       BLI_removeDoubleNodes((BGraph*)rg, 0.001);
+       
+       RIG_removeNormalNodes(rg);
+       
+       RIG_removeUneededOffsets(rg);
+       
+       BLI_buildAdjacencyList((BGraph*)rg);
+       
+       RIG_findHead(rg);
+
+       BLI_markdownSymmetry((BGraph*)rg, (BNode*)rg->head, G.scene->toolsettings->skgen_symmetry_limit);
+       
+       RIG_reconnectControlBones(rg); /* after symmetry, because we use levels to find best match */
+       
+       if (BLI_isGraphCyclic((BGraph*)rg))
+       {
+               printf("armature cyclic\n");
+       }
+       
+       return rg;
+}
+/************************************ GENERATING *****************************************************/
+
+static EditBone *add_editbonetolist(char *name, ListBase *list)
+{
+       EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone");
+       
+       BLI_strncpy(bone->name, name, 32);
+       unique_editbone_name(list, bone->name, NULL);
        
        BLI_addtail(list, bone);
        
@@ -1332,100 +1659,6 @@ static EditBone *add_editbonetolist(char *name, ListBase *list)
        return bone;
 }
 
-EditBone * generateBonesForArc(RigGraph *rigg, ReebArc *arc, ReebNode *head, ReebNode *tail)
-{
-       ReebArcIterator iter;
-       float n[3];
-       float ADAPTIVE_THRESHOLD = G.scene->toolsettings->skgen_correlation_limit;
-       EditBone *lastBone = NULL;
-       
-       /* init iterator to get start and end from head */
-       initArcIterator(&iter, arc, head);
-       
-       /* Calculate overall */
-       VecSubf(n, arc->buckets[iter.end].p, head->p);
-       
-       if (1 /* G.scene->toolsettings->skgen_options & SKGEN_CUT_CORRELATION */ )
-       {
-               EmbedBucket *bucket = NULL;
-               EmbedBucket *previous = NULL;
-               EditBone *child = NULL;
-               EditBone *parent = NULL;
-               float normal[3] = {0, 0, 0};
-               float avg_normal[3];
-               int total = 0;
-               int boneStart = iter.start;
-               
-               parent = add_editbonetolist("Bone", &rigg->editbones);
-               parent->flag = BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
-               VECCOPY(parent->head, head->p);
-               
-               for (previous = nextBucket(&iter), bucket = nextBucket(&iter);
-                       bucket;
-                       previous = bucket, bucket = nextBucket(&iter))
-               {
-                       float btail[3];
-                       float value = 0;
-
-                       if (G.scene->toolsettings->skgen_options & SKGEN_STICK_TO_EMBEDDING)
-                       {
-                               VECCOPY(btail, bucket->p);
-                       }
-                       else
-                       {
-                               float length;
-                               
-                               /* Calculate normal */
-                               VecSubf(n, bucket->p, parent->head);
-                               length = Normalize(n);
-                               
-                               total += 1;
-                               VecAddf(normal, normal, n);
-                               VECCOPY(avg_normal, normal);
-                               VecMulf(avg_normal, 1.0f / total);
-                                
-                               VECCOPY(btail, avg_normal);
-                               VecMulf(btail, length);
-                               VecAddf(btail, btail, parent->head);
-                       }
-
-                       if (G.scene->toolsettings->skgen_options & SKGEN_ADAPTIVE_DISTANCE)
-                       {
-                               value = calcDistance(arc, boneStart, iter.index, parent->head, btail);
-                       }
-                       else
-                       {
-                               float n[3];
-                               
-                               VecSubf(n, btail, parent->head);
-                               value = calcVariance(arc, boneStart, iter.index, parent->head, n);
-                       }
-
-                       if (value > ADAPTIVE_THRESHOLD)
-                       {
-                               VECCOPY(parent->tail, btail);
-
-                               child = add_editbonetolist("Bone", &rigg->editbones);
-                               VECCOPY(child->head, parent->tail);
-                               child->parent = parent;
-                               child->flag |= BONE_CONNECTED|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
-                               
-                               parent = child; // new child is next parent
-                               boneStart = iter.index; // start from end
-                               
-                               normal[0] = normal[1] = normal[2] = 0;
-                               total = 0;
-                       }
-               }
-
-               VECCOPY(parent->tail, tail->p);
-               
-               lastBone = parent; /* set last bone in the chain */
-       }
-       
-       return lastBone;
-}
-
 void generateMissingArcsFromNode(RigGraph *rigg, ReebNode *node, int multi_level_limit)
 {
        while (node->multi_level > multi_level_limit && node->link_up)
@@ -1452,7 +1685,7 @@ void generateMissingArcsFromNode(RigGraph *rigg, ReebNode *node, int multi_level
                                
                                earc->flag = ARC_USED;
                                
-                               generateBonesForArc(rigg, earc, node, other);
+                               //generateBonesForArc(rigg, earc, node, other);
                                generateMissingArcsFromNode(rigg, other, multi_level_limit);
                        }
                }
@@ -1481,38 +1714,106 @@ void generateMissingArcs(RigGraph *rigg)
 
 /************************************ RETARGETTING *****************************************************/
 
+static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float tail[3], float qrot[4], float resize);
+
+static void repositionTailControl(RigGraph *rigg, RigControl *ctrl);
+
+static void finalizeControl(RigGraph *rigg, RigControl *ctrl, float resize)
+{
+       if ((ctrl->flag & RIG_CTRL_DONE) == RIG_CTRL_DONE)
+       {
+               RigControl *ctrl_child;
+
+#if 0          
+               printf("CTRL: %s LINK: %s", ctrl->bone->name, ctrl->link->name);
+               
+               if (ctrl->link_tail)
+               {
+                       printf(" TAIL: %s", ctrl->link_tail->name);
+               }
+               
+               printf("\n");
+#endif
+               
+               /* if there was a tail link: apply link, recalc resize factor and qrot */
+               if (ctrl->tail_mode != TL_NONE)
+               {
+                       float *tail_vec = NULL;
+                       float v1[3], v2[3], qtail[4];
+                       
+                       if (ctrl->tail_mode == TL_TAIL)
+                       {
+                               tail_vec = ctrl->link_tail->tail;
+                       }
+                       else if (ctrl->tail_mode == TL_HEAD)
+                       {
+                               tail_vec = ctrl->link_tail->head;
+                       }
+                       
+                       VecSubf(v1, ctrl->bone->tail, ctrl->bone->head);
+                       VecSubf(v2, tail_vec, ctrl->bone->head);
+                       
+                       VECCOPY(ctrl->bone->tail, tail_vec);
+                       
+                       RotationBetweenVectorsToQuat(qtail, v1, v2);
+                       QuatMul(ctrl->qrot, qtail, ctrl->qrot);
+                       
+                       resize = VecLength(v2) / VecLenf(ctrl->head, ctrl->tail);
+               }
+               
+               ctrl->bone->roll = rollBoneByQuat(ctrl->bone, ctrl->up_axis, ctrl->qrot);
+       
+               /* Cascade to connected control bones */
+               for (ctrl_child = rigg->controls.first; ctrl_child; ctrl_child = ctrl_child->next)
+               {
+                       if (ctrl_child->link == ctrl->bone)
+                       {
+                               repositionControl(rigg, ctrl_child, ctrl->bone->head, ctrl->bone->tail, ctrl->qrot, resize);
+                       }
+                       if (ctrl_child->link_tail == ctrl->bone)
+                       {
+                               repositionTailControl(rigg, ctrl_child);
+                       }
+               }
+       }       
+}
+
+static void repositionTailControl(RigGraph *rigg, RigControl *ctrl)
+{
+       ctrl->flag |= RIG_CTRL_TAIL_DONE;
+
+       finalizeControl(rigg, ctrl, 1); /* resize will be recalculated anyway so we don't need it */
+}
+
 static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float tail[3], float qrot[4], float resize)
 {
-       RigControl *ctrl_child;
        float parent_offset[3], tail_offset[3];
        
-       VecSubf(tail_offset, ctrl->tail, ctrl->head);
-       VecMulf(tail_offset, resize);
-       
        VECCOPY(parent_offset, ctrl->offset);
        VecMulf(parent_offset, resize);
-       
        QuatMulVecf(qrot, parent_offset);
-       QuatMulVecf(qrot, tail_offset);
        
        VecAddf(ctrl->bone->head, head, parent_offset); 
-       VecAddf(ctrl->bone->tail, ctrl->bone->head, tail_offset);
-       ctrl->bone->roll = getNewBoneRoll(ctrl->bone, ctrl->up_axis, qrot);
-       
-       ctrl->flag |= RIG_CTRL_DONE;
 
-       /* Cascade to connected control bones */
-       for (ctrl_child = rigg->controls.first; ctrl_child; ctrl_child = ctrl_child->next)
+       ctrl->flag |= RIG_CTRL_HEAD_DONE;
+
+       QUATCOPY(ctrl->qrot, qrot); 
+
+       if (ctrl->tail_mode == TL_NONE)
        {
-               if (ctrl_child->link == ctrl->bone)
-               {
-                       repositionControl(rigg, ctrl_child, ctrl->bone->head, ctrl->bone->tail, qrot, resize);
-               }
+               VecSubf(tail_offset, ctrl->tail, ctrl->head);
+               VecMulf(tail_offset, resize);
+               QuatMulVecf(qrot, tail_offset);
+
+               VecAddf(ctrl->bone->tail, ctrl->bone->head, tail_offset);
+               
+               ctrl->flag |= RIG_CTRL_TAIL_DONE;
        }
 
+       finalizeControl(rigg, ctrl, resize);
 }
 
-static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3])
+static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3], float up_axis[3])
 {
        EditBone *bone;
        RigControl *ctrl;
@@ -1532,17 +1833,44 @@ static void repositionBone(RigGraph *rigg, RigEdge *edge, float vec0[3], float v
        
        RotationBetweenVectorsToQuat(qrot, v1, v2);
        
+       VECCOPY(bone->head, vec0);
+       VECCOPY(bone->tail, vec1);
+       
+       if (!VecIsNull(up_axis))
+       {
+               float qroll[4];
+
+               if (G.scene->toolsettings->skgen_retarget_roll == SK_RETARGET_ROLL_VIEW)
+               {
+                       bone->roll = rollBoneByQuatAligned(bone, edge->up_axis, qrot, qroll, up_axis);
+               }
+               else if (G.scene->toolsettings->skgen_retarget_roll == SK_RETARGET_ROLL_JOINT)
+               {
+                       bone->roll = rollBoneByQuatJoint(edge, edge->next, qrot, qroll);
+               }
+               else
+               {
+                       QuatOne(qroll);
+               }
+               
+               QuatMul(qrot, qroll, qrot);
+       }
+       else
+       {
+               bone->roll = rollBoneByQuat(bone, edge->up_axis, qrot);
+       }
+
        for (ctrl = rigg->controls.first; ctrl; ctrl = ctrl->next)
        {
                if (ctrl->link == bone)
                {
                        repositionControl(rigg, ctrl, vec0, vec1, qrot, resize);
                }
+               if (ctrl->link_tail == bone)
+               {
+                       repositionTailControl(rigg, ctrl);
+               }
        }
-       
-       VECCOPY(bone->head, vec0);
-       VECCOPY(bone->tail, vec1);
-       bone->roll = getNewBoneRoll(bone, edge->up_axis, qrot);
 }
 
 static RetargetMode detectArcRetargetMode(RigArc *arc);
@@ -1603,29 +1931,6 @@ static RetargetMode detectArcRetargetMode(RigArc *iarc)
 }
 
 #ifndef USE_THREADS
-static void printCostCube(float *cost_cube, int nb_joints)
-{
-       int i;
-       
-       for (i = 0; i < nb_joints; i++)
-       {
-               printf("%0.3f ", cost_cube[3 * i]);
-       }
-       printf("\n");
-
-       for (i = 0; i < nb_joints; i++)
-       {
-               printf("%0.3f ", cost_cube[3 * i + 1]);
-       }
-       printf("\n");
-
-       for (i = 0; i < nb_joints; i++)
-       {
-               printf("%0.3f ", cost_cube[3 * i + 2]);
-       }
-       printf("\n");
-}
-
 static void printMovesNeeded(int *positions, int nb_positions)
 {
        int moves = 0;
@@ -1651,9 +1956,9 @@ static void printPositions(int *positions, int nb_positions)
 }
 #endif
 
-#define MAX_COST 100 /* FIX ME */
+#define MAX_COST FLT_MAX /* FIX ME */
 
-static float costDistance(ReebArcIterator *iter, float *vec0, float *vec1, int i0, int i1)
+static float costDistance(BArcIterator *iter, float *vec0, float *vec1, int i0, int i1)
 {
        EmbedBucket *bucket = NULL;
        float max_dist = 0;
@@ -1673,7 +1978,7 @@ static float costDistance(ReebArcIterator *iter, float *vec0, float *vec1, int i
                        {
                                float dist;
                                
-                               bucket = peekBucket(iter, j);
+                               bucket = IT_peek(iter, j);
        
                                VecSubf(v2, bucket->p, vec1);
                
@@ -1733,7 +2038,7 @@ static float costLength(float original_length, float current_length)
        }
 }
 
-static float calcCostLengthDistance(ReebArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec1, float *vec2, int i1, int i2)
+static float calcCostLengthDistance(BArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec1, float *vec2, int i1, int i2)
 {
        float vec[3];
        float length;
@@ -1744,7 +2049,7 @@ static float calcCostLengthDistance(ReebArcIterator *iter, float **vec_cache, Ri
        return costLength(edge->length, length) + costDistance(iter, vec1, vec2, i1, i2);
 }
 
-static float calcCostAngleLengthDistance(ReebArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec0, float *vec1, float *vec2, int i1, int i2)
+static float calcCostAngleLengthDistance(BArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec0, float *vec1, float *vec2, int i1, int i2)
 {
        float vec_second[3], vec_first[3];
        float length2;
@@ -1772,187 +2077,6 @@ static float calcCostAngleLengthDistance(ReebArcIterator *iter, float **vec_cach
        return new_cost;
 }
 
-static float calcCost(ReebArcIterator *iter, RigEdge *e1, RigEdge *e2, float *vec0, float *vec1, float *vec2, int i0, int i1, int i2)
-{
-       float vec_second[3], vec_first[3];
-       float length1, length2;
-       float new_cost = 0;
-
-       VecSubf(vec_second, vec2, vec1);
-       length2 = Normalize(vec_second);
-
-       VecSubf(vec_first, vec1, vec0); 
-       length1 = Normalize(vec_first);
-
-       /* Angle cost */        
-       new_cost += costAngle(e1->angle, vec_first, vec_second);
-
-       /* Length cost */
-       new_cost += costLength(e1->length, length1);
-       new_cost += costLength(e2->length, length2);
-
-       /* Distance cost */
-       new_cost += costDistance(iter, vec0, vec1, i0, i1);
-       new_cost += costDistance(iter, vec1, vec2, i1, i2);
-
-       return new_cost;
-}
-
-static void calcGradient(RigEdge *e1, RigEdge *e2, ReebArcIterator *iter, int index, int nb_joints, float *cost_cube, int *positions, float **vec_cache)
-{
-       EmbedBucket *bucket = NULL;
-       float *vec0, *vec1, *vec2;
-       float current_cost;
-       int i0, i1, i2;
-       int next_position;
-
-       vec0 = vec_cache[index];
-       vec1 = vec_cache[index + 1];
-       vec2 = vec_cache[index + 2];
-       
-       if (index == 0)
-       {
-               i0 = 0;
-       }
-       else
-       {
-               i0 = positions[index - 1];
-       }
-       
-       i1 = positions[index];
-       
-       if (index +1 == nb_joints)
-       {
-               i2 = iter->length;
-       }
-       else
-       {
-               i2 = positions[index + 1];
-       }
-
-
-       current_cost = calcCost(iter, e1, e2, vec0, vec1, vec2, i0, i1, i2);
-       cost_cube[index * 3 + 1] = current_cost;
-       
-       next_position = positions[index] + 1;
-       
-       if (index + 1 < nb_joints && next_position == positions[index + 1])
-       {
-               cost_cube[index * 3 + 2] = MAX_COST;
-       }
-       else if (next_position > iter->length) /* positions are indexed at 1, so length is last */
-       {
-               cost_cube[index * 3 + 2] = MAX_COST;
-       }
-       else
-       {
-               bucket = peekBucket(iter, next_position);
-               
-               if (bucket == NULL)
-               {
-                       cost_cube[index * 3 + 2] = MAX_COST;
-               }
-               else
-               {
-                       vec1 = bucket->p;
-                       
-                       cost_cube[index * 3 + 2] = calcCost(iter, e1, e2, vec0, vec1, vec2, i0, next_position, i2) - current_cost;
-               }
-       }
-
-       next_position = positions[index] - 1;
-       
-       if (index - 1 > -1 && next_position == positions[index - 1])
-       {
-               cost_cube[index * 3] = MAX_COST;
-       }
-       else if (next_position < 1) /* positions are indexed at 1, so 1 is first */
-       {
-               cost_cube[index * 3] = MAX_COST;
-       }
-       else
-       {
-               bucket = peekBucket(iter, next_position);
-               
-               if (bucket == NULL)
-               {
-                       cost_cube[index * 3] = MAX_COST;
-               }
-               else
-               {
-                       vec1 = bucket->p;
-                       
-                       cost_cube[index * 3] = calcCost(iter, e1, e2, vec0, vec1, vec2, i0, next_position, i2) - current_cost;
-               }
-       }
-}
-
-static float probability(float delta_cost, float temperature)
-{
-       if (delta_cost < 0)
-       {
-               return 1;
-       }
-       else
-       {
-               return (float)exp(delta_cost / temperature);
-       }
-}
-
-static int neighbour(int nb_joints, float *cost_cube, int *moving_joint, int *moving_direction)
-{
-       int total = 0;
-       int chosen = 0;
-       int i;
-       
-       for (i = 0; i < nb_joints; i++)
-       {
-               if (cost_cube[i * 3] < MAX_COST)
-               {
-                       total++;
-               }
-               
-               if (cost_cube[i * 3 + 2] < MAX_COST)
-               {
-                       total++;
-               }
-       }
-       
-       if (total == 0)
-       {
-               return 0;
-       }
-       
-       chosen = (int)(BLI_drand() * total);
-       
-       for (i = 0; i < nb_joints; i++)
-       {
-               if (cost_cube[i * 3] < MAX_COST)
-               {
-                       if (chosen == 0)
-                       {
-                               *moving_joint = i;
-                               *moving_direction = -1;
-                               break;
-                       }
-                       chosen--;
-               }
-               
-               if (cost_cube[i * 3 + 2] < MAX_COST)
-               {
-                       if (chosen == 0)
-                       {
-                               *moving_joint = i;
-                               *moving_direction = 1;
-                               break;
-                       }
-                       chosen--;
-               }
-       }
-       
-       return 1;
-}
-
 static int indexMemoNode(int nb_positions, int previous, int current, int joints_left)
 {
        return joints_left * nb_positions * nb_positions + current * nb_positions + previous;
@@ -1975,7 +2099,7 @@ static void copyMemoPositions(int *positions, MemoNode *table, int nb_positions,
        }
 }
 
-static MemoNode * solveJoints(MemoNode *table, ReebArcIterator *iter, float **vec_cache, int nb_joints, int nb_positions, int previous, int current, RigEdge *edge, int joints_left)
+static MemoNode * solveJoints(MemoNode *table, BArcIterator *iter, float **vec_cache, int nb_joints, int nb_positions, int previous, int current, RigEdge *edge, int joints_left)
 {
        MemoNode *node;
        int index = indexMemoNode(nb_positions, previous, current, joints_left);
@@ -1988,10 +2112,11 @@ static MemoNode * solveJoints(MemoNode *table, ReebArcIterator *iter, float **ve
        }
        else if (joints_left == 0)
        {
+               float *vec0 = vec_cache[previous];
                float *vec1 = vec_cache[current];
                float *vec2 = vec_cache[nb_positions + 1];
 
-               node->weight = calcCostLengthDistance(iter, vec_cache, edge, vec1, vec2, current, iter->length);
+               node->weight = calcCostAngleLengthDistance(iter, vec_cache, edge, vec0, vec1, vec2, current, iter->length);
 
                return node;
        }
@@ -2063,20 +2188,18 @@ static int testFlipArc(RigArc *iarc, RigNode *inode_start)
 
 static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
 {
-       ReebArcIterator iter;
+       ReebArcIterator arc_iter;
+       BArcIterator *iter = (BArcIterator*)&arc_iter;
        RigEdge *edge;
        EmbedBucket *bucket = NULL;
        ReebNode *node_start, *node_end;
        ReebArc *earc = iarc->link_mesh;
        float min_cost = FLT_MAX;
        float *vec0, *vec1, *vec2;
-       float **vec_cache;
-       float *cost_cache;
        int *best_positions;
-       int *positions;
        int nb_edges = BLI_countlist(&iarc->edges);
        int nb_joints = nb_edges - 1;
-       RetargetMethod method = G.scene->toolsettings->skgen_optimisation_method;
+       RetargetMethod method = METHOD_MEMOIZE;
        int i;
        
        if (nb_joints > earc->bcount)
@@ -2085,10 +2208,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
                return;
        }
 
-       positions = MEM_callocN(sizeof(int) * nb_joints, "Aggresive positions");
-       best_positions = MEM_callocN(sizeof(int) * nb_joints, "Best Aggresive positions");
-       cost_cache = MEM_callocN(sizeof(float) * nb_edges, "Cost cache");
-       vec_cache = MEM_callocN(sizeof(float*) * (nb_edges + 1), "Vec cache");
+       best_positions = MEM_callocN(sizeof(int) * nb_joints, "Best positions");
        
        if (testFlipArc(iarc, inode_start))
        {
@@ -2100,23 +2220,18 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
                node_start = earc->head;
                node_end = earc->tail;
        }
-       
-       /* init with first values */
-       for (i = 0; i < nb_joints; i++)
-       {
-               positions[i] = i + 1;
-               //positions[i] = (earc->bcount / nb_edges) * (i + 1);
-       }
-       
-       /* init cost cache */
-       for (i = 0; i < nb_edges; i++)
+
+       /* equal number of joints and potential position, just fill them in */
+       if (nb_joints == earc->bcount)
        {
-               cost_cache[i] = 0;
+               int i;
+               
+               /* init with first values */
+               for (i = 0; i < nb_joints; i++)
+               {
+                       best_positions[i] = i + 1;
+               }
        }
-       
-       vec_cache[0] = node_start->p;
-       vec_cache[nb_edges] = node_end->p;
-
        if (method == METHOD_MEMOIZE)
        {
                int nb_positions = earc->bcount;
@@ -2129,15 +2244,15 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
                positions_cache[0] = node_start->p;
                positions_cache[nb_positions + 1] = node_end->p;
                
-               initArcIterator(&iter, earc, node_start);
+               initArcIterator(iter, earc, node_start);
 
                for (i = 1; i <= nb_positions; i++)
                {
-                       EmbedBucket *bucket = peekBucket(&iter, i);
+                       EmbedBucket *bucket = IT_peek(iter, i);
                        positions_cache[i] = bucket->p;
                }
 
-               result = solveJoints(table, &iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints);
+               result = solveJoints(table, iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints);
                
                min_cost = result->weight;
                copyMemoPositions(best_positions, table, earc->bcount, nb_joints);
@@ -2148,10 +2263,32 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
        /* BRUTE FORCE */
        else if (method == METHOD_BRUTE_FORCE)
        {
+               float **vec_cache;
+               float *cost_cache;
+               int *positions;
                int last_index = 0;
                int first_pass = 1;
                int must_move = nb_joints - 1;
                
+               positions = MEM_callocN(sizeof(int) * nb_joints, "Aggresive positions");
+               cost_cache = MEM_callocN(sizeof(float) * nb_edges, "Cost cache");
+               vec_cache = MEM_callocN(sizeof(float*) * (nb_edges + 1), "Vec cache");
+       
+               /* init with first values */
+               for (i = 0; i < nb_joints; i++)
+               {
+                       positions[i] = i + 1;
+               }
+               
+               /* init cost cache */
+               for (i = 0; i < nb_edges; i++)
+               {
+                       cost_cache[i] = 0;
+               }
+               
+               vec_cache[0] = node_start->p;
+               vec_cache[nb_edges] = node_end->p;              
+               
                while(1)
                {
                        float cost = 0;
@@ -2197,7 +2334,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
                        }
                
                        /* calculating cost */
-                       initArcIterator(&iter, earc, node_start);
+                       initArcIterator(iter, earc, node_start);
                        
                        vec0 = NULL;
                        vec1 = node_start->p;
@@ -2218,13 +2355,13 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
                                        if (i < nb_joints)
                                        {
                                                i2 = positions[i];
-                                               bucket = peekBucket(&iter, positions[i]);
+                                               bucket = IT_peek(iter, positions[i]);
                                                vec2 = bucket->p;
                                                vec_cache[i + 1] = vec2; /* update cache for updated position */
                                        }
                                        else
                                        {
-                                               i2 = iter.length;
+                                               i2 = iter->length;
                                                vec2 = node_end->p;
                                        }
                                        
@@ -2260,7 +2397,7 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
                                        new_cost += costLength(edge->length, length2);
                                        
                                        /* Distance Cost */
-                                       new_cost += costDistance(&iter, vec1, vec2, i1, i2);
+                                       new_cost += costDistance(iter, vec1, vec2, i1, i2);
                                        
                                        cost_cache[i] = new_cost;
                                }
@@ -2286,118 +2423,14 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
                                memcpy(best_positions, positions, sizeof(int) * nb_joints);
                        }
                }
-       }
-       /* SIMULATED ANNEALING */
-       else if (method == METHOD_ANNEALING)
-       {
-               RigEdge *previous;
-               float *cost_cube;
-               float cost;
-               int k;
-               int kmax;
-
-               kmax = 100000;
-               
-               BLI_srand(nb_joints);
-               
-               /* [joint: index][position: -1, 0, +1] */
-               cost_cube = MEM_callocN(sizeof(float) * 3 * nb_joints, "Cost Cube");
-               
-               initArcIterator(&iter, earc, node_start);
-
-               /* init vec_cache */
-               for (i = 0; i < nb_joints; i++)
-               {
-                       bucket = peekBucket(&iter, positions[i]);
-                       vec_cache[i + 1] = bucket->p;
-               }
-               
-               cost = 0;
-
-               /* init cost cube */
-               for (previous = iarc->edges.first, edge = previous->next, i = 0;
-                        edge;
-                        previous = edge, edge = edge->next, i += 1)
-               {
-                       calcGradient(previous, edge, &iter, i, nb_joints, cost_cube, positions, vec_cache);
-                       
-                       cost += cost_cube[3 * i + 1];
-               }
-               
-#ifndef USE_THREADS
-               printf("initial cost: %f\n", cost);
-               printf("kmax: %i\n", kmax);
-#endif
-               
-               for (k = 0; k < kmax; k++)
-               {
-                       int status;
-                       int moving_joint = -1;
-                       int move_direction = -1;
-                       float delta_cost;
-                       float temperature;
-                       
-                       status = neighbour(nb_joints, cost_cube, &moving_joint, &move_direction);
-                       
-                       if (status == 0)
-                       {
-                               /* if current state is still a minimum, copy it */
-                               if (cost < min_cost)
-                               {
-                                       min_cost = cost;
-                                       memcpy(best_positions, positions, sizeof(int) * nb_joints);
-                               }
-                               break;
-                       }
-                       
-                       delta_cost = cost_cube[moving_joint * 3 + (1 + move_direction)];
-
-                       temperature = 1 - (float)k / (float)kmax;
-                       if (probability(delta_cost, temperature) > BLI_frand())
-                       {
-                               /* update position */                   
-                               positions[moving_joint] += move_direction;
-                               
-                               /* update vector cache */
-                               bucket = peekBucket(&iter, positions[moving_joint]);
-                               vec_cache[moving_joint + 1] = bucket->p;
-                               
-                               cost += delta_cost;
        
-                               /* cost optimizing */
-                               if (cost < min_cost)
-                               {
-                                       min_cost = cost;
-                                       memcpy(best_positions, positions, sizeof(int) * nb_joints);
-                               }
-
-                               /* update cost cube */                  
-                               for (previous = iarc->edges.first, edge = previous->next, i = 0;
-                                        edge;
-                                        previous = edge, edge = edge->next, i += 1)
-                               {
-                                       if (i == moving_joint - 1 ||
-                                               i == moving_joint ||
-                                               i == moving_joint + 1)
-                                       {
-                                               calcGradient(previous, edge, &iter, i, nb_joints, cost_cube, positions, vec_cache);
-                                       }
-                               }
-                       }
-               }
-
-               //min_cost = cost;
-               //memcpy(best_positions, positions, sizeof(int) * nb_joints);
-               
-//             printf("k = %i\n", k);
-               
-               
-               MEM_freeN(cost_cube);
-       }       
-
+               MEM_freeN(positions);
+               MEM_freeN(cost_cache);
+               MEM_freeN(vec_cache);
+       }
 
        vec0 = node_start->p;
-       initArcIterator(&iter, earc, node_start);
+       initArcIterator(iter, earc, node_start);
        
 #ifndef USE_THREADS
        printPositions(best_positions, nb_joints);
@@ -2411,33 +2444,34 @@ static void retargetArctoArcAggresive(RigGraph *rigg, RigArc *iarc, RigNode *ino
                 edge;
                 edge = edge->next, i++)
        {
+               float *no = NULL;
                if (i < nb_joints)
                {
-                       bucket = peekBucket(&iter, best_positions[i]);
+                       bucket = IT_peek(iter, best_positions[i]);
                        vec1 = bucket->p;
+                       no = bucket->no;
                }
                else
                {
                        vec1 = node_end->p;
+                       no = node_end->no;
                }
                
                if (edge->bone)
                {
-                       repositionBone(rigg, edge, vec0, vec1);
+                       repositionBone(rigg, edge, vec0, vec1, no);
                }
                
                vec0 = vec1;
        }
-       
-       MEM_freeN(positions);
+
        MEM_freeN(best_positions);
-       MEM_freeN(cost_cache);
-       MEM_freeN(vec_cache);
 }
 
 static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
 {
-       ReebArcIterator iter;
+       ReebArcIterator arc_iter;
+       BArcIterator *iter = (BArcIterator*)&arc_iter;
        ReebArc *earc = iarc->link_mesh;
        ReebNode *node_start, *node_end;
        RigEdge *edge;
@@ -2459,9 +2493,9 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_
                node_end = (ReebNode*)earc->tail;
        }
        
-       initArcIterator(&iter, earc, node_start);
+       initArcIterator(iter, earc, node_start);
 
-       bucket = nextBucket(&iter);
+       bucket = IT_next(iter);
        
        vec0 = node_start->p;
        
@@ -2472,15 +2506,15 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_
                embedding_length += VecLenf(vec0, vec1);
                
                vec0 = vec1;
-               bucket = nextBucket(&iter);
+               bucket = IT_next(iter);
        }
        
        embedding_length += VecLenf(node_end->p, vec1);
        
        /* fit bones */
-       initArcIterator(&iter, earc, node_start);
+       initArcIterator(iter, earc, node_start);
 
-       bucket = nextBucket(&iter);
+       bucket = IT_next(iter);
 
        vec0 = node_start->p;
        previous_vec = vec0;
@@ -2489,26 +2523,28 @@ static void retargetArctoArcLength(RigGraph *rigg, RigArc *iarc, RigNode *inode_
        for (edge = iarc->edges.first; edge; edge = edge->next)
        {
                float new_bone_length = edge->length / iarc->length * embedding_length;
-
+               float *no = NULL;
                float length = 0;
 
                while (bucket && new_bone_length > length)
                {
                        length += VecLenf(previous_vec, vec1);
-                       bucket = nextBucket(&iter);
+                       bucket = IT_next(iter);
                        previous_vec = vec1;
                        vec1 = bucket->p;
+                       no = bucket->no;
                }
                
                if (bucket == NULL)
                {
                        vec1 = node_end->p;
+                       no = node_end->no;
                }
 
                /* no need to move virtual edges (space between unconnected bones) */           
                if (edge->bone)
                {
-                       repositionBone(rigg, edge, vec0, vec1);
+                       repositionBone(rigg, edge, vec0, vec1, no);
                }
                
                vec0 = vec1;
@@ -2551,11 +2587,11 @@ void *exec_retargetArctoArc(void *param)
 
                if (testFlipArc(iarc, inode_start))
                {
-                       repositionBone(rigg, edge, earc->tail->p, earc->head->p);
+                       repositionBone(rigg, edge, earc->tail->p, earc->head->p, earc->head->no);
                }
                else
                {
-                       repositionBone(rigg, edge, earc->head->p, earc->tail->p);
+                       repositionBone(rigg, edge, earc->head->p, earc->tail->p, earc->tail->no);
                }
        }
        else
@@ -2819,6 +2855,13 @@ static void retargetSubgraph(RigGraph *rigg, RigArc *start_arc, RigNode *start_n
        }
 }
 
+static void finishRetarget(RigGraph *rigg)
+{
+#ifdef USE_THREADS
+       BLI_end_worker(rigg->worker);
+#endif
+}
+
 static void adjustGraphs(RigGraph *rigg)
 {
        RigArc *arc;
@@ -2831,12 +2874,10 @@ static void adjustGraphs(RigGraph *rigg)
                }
        }
 
-#ifdef USE_THREADS
-       BLI_end_worker(rigg->worker);
-#endif
+       finishRetarget(rigg);
 
        /* Turn the list into an armature */
-       editbones_to_armature(&rigg->editbones, rigg->ob);
+       editbones_to_armature(rigg->editbones, rigg->ob);
        
        BIF_undo_push("Retarget Skeleton");
 }
@@ -2860,14 +2901,56 @@ static void retargetGraphs(RigGraph *rigg)
        
        //generateMissingArcs(rigg);
        
-#ifdef USE_THREADS
-       BLI_end_worker(rigg->worker);
-#endif
+       finishRetarget(rigg);
 
        /* Turn the list into an armature */
-       editbones_to_armature(&rigg->editbones, rigg->ob);
+       editbones_to_armature(rigg->editbones, rigg->ob);
+}
+
+char *RIG_nameBone(RigGraph *rg, int arc_index, int bone_index)
+{
+       RigArc *arc = BLI_findlink(&rg->arcs, arc_index);
+       RigEdge *iedge;
+
+       if (arc == NULL)
+       {
+               return "None";
+       }
+       
+       if (bone_index == BLI_countlist(&arc->edges))
+       {
+               return "Last joint";
+       }
+
+       iedge = BLI_findlink(&arc->edges, bone_index);
+       
+       if (iedge == NULL)
+       {
+               return "Done";
+       }
+       
+       if (iedge->bone == NULL)
+       {
+               return "Bone offset";
+       }
+       
+       return iedge->bone->name;
 }
 
+int RIG_nbJoints(RigGraph *rg)
+{
+       RigArc *arc;
+       int total = 0;
+       
+       total += BLI_countlist(&rg->nodes);
+       
+       for (arc = rg->arcs.first; arc; arc = arc->next)
+       {
+               total += BLI_countlist(&arc->edges) - 1; /* -1 because end nodes are already counted */
+       }
+       
+       return total;
+}
 
 void BIF_retargetArmature()
 {
@@ -2905,7 +2988,7 @@ void BIF_retargetArmature()
                        
                                start_time = PIL_check_seconds_timer();
        
-                               rigg = armatureToGraph(ob, arm);
+                               rigg = RIG_graphFromArmature(ob, arm);
                                
                                end_time = PIL_check_seconds_timer();
                                rig_time = end_time - start_time;
@@ -2950,6 +3033,53 @@ void BIF_retargetArmature()
        allqueue(REDRAWVIEW3D, 0);
 }
 
+void BIF_retargetArc(ReebArc *earc, RigGraph *template_rigg)
+{
+       Object *ob;
+       RigGraph *rigg;
+       RigArc *iarc;
+       bArmature *arm;
+       
+       if (template_rigg)
+       {
+               ob = template_rigg->ob;         
+               arm = ob->data;
+       }
+       else
+       {
+               ob = G.obedit;  
+               arm = ob->data;
+               template_rigg = armatureSelectedToGraph(ob, arm);
+       }
+       
+       if (template_rigg->arcs.first == NULL)
+       {
+               error("No Template and no deforming bones selected");
+               return;
+       }
+       
+       rigg = cloneRigGraph(template_rigg, &G.edbo, G.obedit);
+       
+       iarc = rigg->arcs.first;
+       
+       iarc->link_mesh = earc;
+       iarc->head->link_mesh = earc->head;
+       iarc->tail->link_mesh = earc->tail;
+       
+       retargetArctoArc(rigg, iarc, iarc->head);
+       
+       finishRetarget(rigg);
+       
+       /* free template if it comes from the edit armature */
+       if (ob == G.obedit)
+       {
+               RIG_freeRigGraph((BGraph*)template_rigg);
+       }
+       RIG_freeRigGraph((BGraph*)rigg);
+       
+       allqueue(REDRAWVIEW3D, 0);
+}
+
 void BIF_adjustRetarget()
 {
        if (GLOBAL_RIGG)
diff --git a/source/blender/src/editarmature_sketch.c b/source/blender/src/editarmature_sketch.c
new file mode 100644 (file)
index 0000000..1452a3d
--- /dev/null
@@ -0,0 +1,3073 @@
+/**
+ * $Id: $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_scene_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_graph.h"
+#include "BLI_ghash.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_object.h"
+#include "BKE_anim.h"
+
+#include "BSE_view.h"
+
+#include "BIF_gl.h"
+#include "BIF_resources.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_mywindow.h"
+#include "BIF_editarmature.h"
+#include "BIF_sketch.h"
+#include "BIF_retarget.h"
+#include "BIF_generate.h"
+#include "BIF_interface.h"
+
+#include "BIF_transform.h"
+
+#include "blendef.h"
+#include "mydevice.h"
+#include "reeb.h"
+
+typedef enum SK_PType
+{
+       PT_CONTINUOUS,
+       PT_EXACT,
+} SK_PType;
+
+typedef enum SK_PMode
+{
+       PT_SNAP,
+       PT_PROJECT,
+} SK_PMode;
+
+typedef struct SK_Point
+{
+       float p[3];
+       float no[3];
+       SK_PType type;
+       SK_PMode mode;
+} SK_Point;
+
+typedef struct SK_Stroke
+{
+       struct SK_Stroke *next, *prev;
+
+       SK_Point *points;
+       int nb_points;
+       int buf_size;
+       int selected;
+} SK_Stroke;
+
+#define SK_OVERDRAW_LIMIT      5
+
+typedef struct SK_Overdraw
+{
+       SK_Stroke *target;
+       int     start, end;
+       int count;
+} SK_Overdraw;
+
+#define SK_Stroke_BUFFER_INIT_SIZE 20
+
+typedef struct SK_DrawData
+{
+       short mval[2];
+       short previous_mval[2];
+       SK_PType type;
+} SK_DrawData;
+
+typedef struct SK_Intersection
+{
+       struct SK_Intersection *next, *prev;
+       SK_Stroke *stroke;
+       int                     before;
+       int                     after;
+       int                     gesture_index;
+       float           p[3];
+       float           lambda; /* used for sorting intersection points */
+} SK_Intersection;
+
+typedef struct SK_Sketch
+{
+       ListBase        strokes;
+       SK_Stroke       *active_stroke;
+       SK_Stroke       *gesture;
+       SK_Point        next_point;
+       SK_Overdraw over;
+} SK_Sketch;
+
+typedef struct SK_StrokeIterator {
+       HeadFct         head;
+       TailFct         tail;
+       PeekFct         peek;
+       NextFct         next;
+       NextNFct        nextN;
+       PreviousFct     previous;
+       StoppedFct      stopped;
+       
+       float *p, *no;
+       
+       int length;
+       int index;
+       /*********************************/
+       SK_Stroke *stroke;
+       int start;
+       int end;
+       int stride;
+} SK_StrokeIterator;
+
+typedef struct SK_Gesture {
+       SK_Stroke       *stk;
+       SK_Stroke       *segments;
+
+       ListBase        intersections;
+       ListBase        self_intersections;
+
+       int                     nb_self_intersections;
+       int                     nb_intersections;
+       int                     nb_segments;
+} SK_Gesture;
+
+typedef int  (*GestureDetectFct)(SK_Gesture*, SK_Sketch *);
+typedef void (*GestureApplyFct)(SK_Gesture*, SK_Sketch *);
+
+typedef struct SK_GestureAction {
+       char name[64];
+       GestureDetectFct        detect;
+       GestureApplyFct         apply;
+} SK_GestureAction;
+
+SK_Sketch *GLOBAL_sketch = NULL;
+SK_Point boneSnap;
+int    LAST_SNAP_POINT_VALID = 0;
+float  LAST_SNAP_POINT[3];
+
+/******************** PROTOTYPES ******************************/
+
+void initStrokeIterator(BArcIterator *iter, SK_Stroke *stk, int start, int end);
+
+void sk_deleteSelectedStrokes(SK_Sketch *sketch);
+
+void sk_freeStroke(SK_Stroke *stk);
+void sk_freeSketch(SK_Sketch *sketch);
+
+SK_Point *sk_lastStrokePoint(SK_Stroke *stk);
+
+int sk_detectCutGesture(SK_Gesture *gest, SK_Sketch *sketch);
+void sk_applyCutGesture(SK_Gesture *gest, SK_Sketch *sketch);
+int sk_detectTrimGesture(SK_Gesture *gest, SK_Sketch *sketch);
+void sk_applyTrimGesture(SK_Gesture *gest, SK_Sketch *sketch);
+int sk_detectCommandGesture(SK_Gesture *gest, SK_Sketch *sketch);
+void sk_applyCommandGesture(SK_Gesture *gest, SK_Sketch *sketch);
+int sk_detectDeleteGesture(SK_Gesture *gest, SK_Sketch *sketch);
+void sk_applyDeleteGesture(SK_Gesture *gest, SK_Sketch *sketch);
+int sk_detectMergeGesture(SK_Gesture *gest, SK_Sketch *sketch);
+void sk_applyMergeGesture(SK_Gesture *gest, SK_Sketch *sketch);
+int sk_detectReverseGesture(SK_Gesture *gest, SK_Sketch *sketch);
+void sk_applyReverseGesture(SK_Gesture *gest, SK_Sketch *sketch);
+int sk_detectConvertGesture(SK_Gesture *gest, SK_Sketch *sketch);
+void sk_applyConvertGesture(SK_Gesture *gest, SK_Sketch *sketch);
+
+
+void sk_resetOverdraw(SK_Sketch *sketch);
+int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk);
+
+/******************** GESTURE ACTIONS ******************************/
+
+SK_GestureAction GESTURE_ACTIONS[] =
+       {
+               {"Cut", sk_detectCutGesture, sk_applyCutGesture},
+               {"Trim", sk_detectTrimGesture, sk_applyTrimGesture},
+               {"Command", sk_detectCommandGesture, sk_applyCommandGesture},
+               {"Delete", sk_detectDeleteGesture, sk_applyDeleteGesture},
+               {"Merge", sk_detectMergeGesture, sk_applyMergeGesture},
+               {"Reverse", sk_detectReverseGesture, sk_applyReverseGesture},
+               {"Convert", sk_detectConvertGesture, sk_applyConvertGesture},
+               {"", NULL, NULL}
+       };
+
+/******************** TEMPLATES UTILS *************************/
+
+char  *TEMPLATES_MENU = NULL;
+int    TEMPLATES_CURRENT = 0;
+GHash *TEMPLATES_HASH = NULL;
+RigGraph *TEMPLATE_RIGG = NULL;
+
+void BIF_makeListTemplates()
+{
+       Base *base;
+       int index = 0;
+
+       if (TEMPLATES_HASH != NULL)
+       {
+               BLI_ghash_free(TEMPLATES_HASH, NULL, NULL);
+       }
+       
+       TEMPLATES_HASH = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
+       TEMPLATES_CURRENT = 0;
+
+       for ( base = FIRSTBASE; base; base = base->next )
+       {
+               Object *ob = base->object;
+               
+               if (ob != G.obedit && ob->type == OB_ARMATURE)
+               {
+                       index++;
+                       BLI_ghash_insert(TEMPLATES_HASH, SET_INT_IN_POINTER(index), ob);
+                       
+                       if (ob == G.scene->toolsettings->skgen_template)
+                       {
+                               TEMPLATES_CURRENT = index;
+                       }
+               }
+       }
+}
+
+char *BIF_listTemplates()
+{
+       GHashIterator ghi;
+       char menu_header[] = "Template%t|None%x0|";
+       char *p;
+       
+       if (TEMPLATES_MENU != NULL)
+       {
+               MEM_freeN(TEMPLATES_MENU);
+       }
+       
+       TEMPLATES_MENU = MEM_callocN(sizeof(char) * (BLI_ghash_size(TEMPLATES_HASH) * 32 + 30), "skeleton template menu");
+       
+       p = TEMPLATES_MENU;
+       
+       p += sprintf(TEMPLATES_MENU, "%s", menu_header);
+       
+       BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
+       
+       while (!BLI_ghashIterator_isDone(&ghi))
+       {
+               Object *ob = BLI_ghashIterator_getValue(&ghi);
+               int key = (int)BLI_ghashIterator_getKey(&ghi);
+               
+               p += sprintf(p, "|%s%%x%i", ob->id.name+2, key);
+               
+               BLI_ghashIterator_step(&ghi);
+       }
+       
+       return TEMPLATES_MENU;
+}
+
+int   BIF_currentTemplate()
+{
+       if (TEMPLATES_CURRENT == 0 && G.scene->toolsettings->skgen_template != NULL)
+       {
+               GHashIterator ghi;
+               BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
+               
+               while (!BLI_ghashIterator_isDone(&ghi))
+               {
+                       Object *ob = BLI_ghashIterator_getValue(&ghi);
+                       int key = (int)BLI_ghashIterator_getKey(&ghi);
+                       
+                       if (ob == G.scene->toolsettings->skgen_template)
+                       {
+                               TEMPLATES_CURRENT = key;
+                               break;
+                       }
+                       
+                       BLI_ghashIterator_step(&ghi);
+               }
+       }
+       
+       return TEMPLATES_CURRENT;
+}
+
+RigGraph* sk_makeTemplateGraph(Object *ob)
+{
+       if (ob == G.obedit)
+       {
+               return NULL;
+       }
+       
+       if (ob != NULL)
+       {
+               if (TEMPLATE_RIGG && TEMPLATE_RIGG->ob != ob)
+               {
+                       RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
+                       TEMPLATE_RIGG = NULL;
+               }
+               
+               if (TEMPLATE_RIGG == NULL)
+               {
+                       bArmature *arm;
+
+                       arm = ob->data;
+                       
+                       TEMPLATE_RIGG = RIG_graphFromArmature(ob, arm);
+               }
+       }
+       
+       return TEMPLATE_RIGG;
+}
+
+int BIF_nbJointsTemplate()
+{
+       RigGraph *rg = sk_makeTemplateGraph(G.scene->toolsettings->skgen_template);
+       
+       if (rg)
+       {
+               return RIG_nbJoints(rg);
+       }
+       else
+       {
+               return -1; 
+       }
+}
+
+char * BIF_nameBoneTemplate()
+{
+       SK_Sketch *stk = GLOBAL_sketch;
+       RigGraph *rg;
+       int index = 0;
+
+       if (stk && stk->active_stroke != NULL)
+       {
+               index = stk->active_stroke->nb_points;
+       }
+       
+       rg = sk_makeTemplateGraph(G.scene->toolsettings->skgen_template);
+       
+       if (rg == NULL)
+       {
+               return "";
+       }
+
+       return RIG_nameBone(rg, 0, index);
+}
+
+void  BIF_freeTemplates()
+{
+       if (TEMPLATES_MENU != NULL)
+       {
+               MEM_freeN(TEMPLATES_MENU);
+               TEMPLATES_MENU = NULL;
+       }
+       
+       if (TEMPLATES_HASH != NULL)
+       {
+               BLI_ghash_free(TEMPLATES_HASH, NULL, NULL);
+               TEMPLATES_HASH = NULL;
+       }
+       
+       if (TEMPLATE_RIGG != NULL)
+       {
+               RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
+               TEMPLATE_RIGG = NULL;
+       }
+}
+
+void  BIF_setTemplate(int index)
+{
+       if (index > 0)
+       {
+               G.scene->toolsettings->skgen_template = BLI_ghash_lookup(TEMPLATES_HASH, SET_INT_IN_POINTER(index));
+       }
+       else
+       {
+               G.scene->toolsettings->skgen_template = NULL;
+               
+               if (TEMPLATE_RIGG != NULL)
+               {
+                       RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
+               }
+               TEMPLATE_RIGG = NULL;
+       }
+}      
+
+/*********************** CONVERSION ***************************/
+
+void sk_autoname(ReebArc *arc)
+{
+       if (G.scene->toolsettings->skgen_retarget_options & SK_RETARGET_AUTONAME)
+       {
+               if (arc == NULL)
+               {
+                       char *num = G.scene->toolsettings->skgen_num_string;
+                       int i = atoi(num);
+                       i++;
+                       BLI_snprintf(num, 8, "%i", i);
+               }
+               else
+               {
+                       char *side = G.scene->toolsettings->skgen_side_string;
+                       int valid = 0;
+                       int caps = 0;
+                       
+                       if (BLI_streq(side, ""))
+                       {
+                               valid = 1;
+                       }
+                       else if (BLI_streq(side, "R") || BLI_streq(side, "L"))
+                       {
+                               valid = 1;
+                               caps = 1;
+                       }
+                       else if (BLI_streq(side, "r") || BLI_streq(side, "l"))
+                       {
+                               valid = 1;
+                               caps = 0;
+                       }
+                       
+                       if (valid)
+                       {
+                               if (arc->head->p[0] < 0)
+                               {
+                                       BLI_snprintf(side, 8, caps?"R":"r");
+                               }
+                               else
+                               {
+                                       BLI_snprintf(side, 8, caps?"L":"l");
+                               }
+                       }
+               }
+       }
+}
+
+ReebNode *sk_pointToNode(SK_Point *pt, float imat[][4], float tmat[][3])
+{
+       ReebNode *node;
+       
+       node = MEM_callocN(sizeof(ReebNode), "reeb node");
+       VECCOPY(node->p, pt->p);
+       Mat4MulVecfl(imat, node->p);
+       
+       VECCOPY(node->no, pt->no);
+       Mat3MulVecfl(tmat, node->no);
+       
+       return node;
+}
+
+ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4], float tmat[][3])
+{
+       ReebArc *arc;
+       int i;
+       
+       arc = MEM_callocN(sizeof(ReebArc), "reeb arc");
+       arc->head = sk_pointToNode(stk->points, imat, tmat);
+       arc->tail = sk_pointToNode(sk_lastStrokePoint(stk), imat, tmat);
+       
+       arc->bcount = stk->nb_points - 2; /* first and last are nodes, don't count */
+       arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "Buckets");
+       
+       for (i = 0; i < arc->bcount; i++)
+       {
+               VECCOPY(arc->buckets[i].p, stk->points[i + 1].p);
+               Mat4MulVecfl(imat, arc->buckets[i].p);
+
+               VECCOPY(arc->buckets[i].no, stk->points[i + 1].no);
+               Mat3MulVecfl(tmat, arc->buckets[i].no);
+       }
+       
+       return arc;
+}
+
+void sk_retargetStroke(SK_Stroke *stk)
+{
+       float imat[4][4];
+       float tmat[3][3];
+       ReebArc *arc;
+       RigGraph *rg;
+       
+       Mat4Invert(imat, G.obedit->obmat);
+       
+       Mat3CpyMat4(tmat, G.obedit->obmat);
+       Mat3Transp(tmat);
+
+       arc = sk_strokeToArc(stk, imat, tmat);
+       
+       sk_autoname(arc);
+       
+       rg = sk_makeTemplateGraph(G.scene->toolsettings->skgen_template);
+
+       BIF_retargetArc(arc, rg);
+       
+       sk_autoname(NULL);
+       
+       MEM_freeN(arc->head);
+       MEM_freeN(arc->tail);
+       REEB_freeArc((BArc*)arc);
+}
+
+/**************************************************************/
+
+void sk_freeSketch(SK_Sketch *sketch)
+{
+       SK_Stroke *stk, *next;
+       
+       for (stk = sketch->strokes.first; stk; stk = next)
+       {
+               next = stk->next;
+               
+               sk_freeStroke(stk);
+       }
+       
+       MEM_freeN(sketch);
+}
+
+SK_Sketch* sk_createSketch()
+{
+       SK_Sketch *sketch;
+       
+       sketch = MEM_callocN(sizeof(SK_Sketch), "SK_Sketch");
+       
+       sketch->active_stroke = NULL;
+       sketch->gesture = NULL;
+
+       sketch->strokes.first = NULL;
+       sketch->strokes.last = NULL;
+       
+       return sketch;
+}
+
+void sk_initPoint(SK_Point *pt)
+{
+       VECCOPY(pt->no, G.vd->viewinv[2]);
+       Normalize(pt->no);
+       /* more init code here */
+}
+
+void sk_copyPoint(SK_Point *dst, SK_Point *src)
+{
+       memcpy(dst, src, sizeof(SK_Point));
+}
+
+void sk_allocStrokeBuffer(SK_Stroke *stk)
+{
+       stk->points = MEM_callocN(sizeof(SK_Point) * stk->buf_size, "SK_Point buffer");
+}
+
+void sk_freeStroke(SK_Stroke *stk)
+{
+       MEM_freeN(stk->points);
+       MEM_freeN(stk);
+}
+
+SK_Stroke* sk_createStroke()
+{
+       SK_Stroke *stk;
+       
+       stk = MEM_callocN(sizeof(SK_Stroke), "SK_Stroke");
+       
+       stk->selected = 0;
+       stk->nb_points = 0;
+       stk->buf_size = SK_Stroke_BUFFER_INIT_SIZE;
+       
+       sk_allocStrokeBuffer(stk);
+       
+       return stk;
+}
+
+void sk_shrinkStrokeBuffer(SK_Stroke *stk)
+{
+       if (stk->nb_points < stk->buf_size)
+       {
+               SK_Point *old_points = stk->points;
+               
+               stk->buf_size = stk->nb_points;
+
+               sk_allocStrokeBuffer(stk);              
+               
+               memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
+               
+               MEM_freeN(old_points);
+       }
+}
+
+void sk_growStrokeBuffer(SK_Stroke *stk)
+{
+       if (stk->nb_points == stk->buf_size)
+       {
+               SK_Point *old_points = stk->points;
+               
+               stk->buf_size *= 2;
+               
+               sk_allocStrokeBuffer(stk);
+               
+               memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
+               
+               MEM_freeN(old_points);
+       }
+}
+
+void sk_growStrokeBufferN(SK_Stroke *stk, int n)
+{
+       if (stk->nb_points + n > stk->buf_size)
+       {
+               SK_Point *old_points = stk->points;
+               
+               while (stk->nb_points + n > stk->buf_size)
+               {
+                       stk->buf_size *= 2;
+               }
+               
+               sk_allocStrokeBuffer(stk);
+               
+               memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
+               
+               MEM_freeN(old_points);
+       }
+}
+
+
+void sk_replaceStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
+{
+       memcpy(stk->points + n, pt, sizeof(SK_Point));
+}
+
+void sk_insertStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
+{
+       int size = stk->nb_points - n;
+       
+       sk_growStrokeBuffer(stk);
+       
+       memmove(stk->points + n + 1, stk->points + n, size * sizeof(SK_Point));
+       
+       memcpy(stk->points + n, pt, sizeof(SK_Point));
+       
+       stk->nb_points++;
+}
+
+void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt)
+{
+       sk_growStrokeBuffer(stk);
+       
+       memcpy(stk->points + stk->nb_points, pt, sizeof(SK_Point));
+       
+       stk->nb_points++;
+}
+
+void sk_insertStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end)
+{
+       int size = end - start + 1;
+       
+       sk_growStrokeBufferN(stk, len - size);
+       
+       if (len != size)
+       {
+               int tail_size = stk->nb_points - end + 1;
+               
+               memmove(stk->points + start + len, stk->points + end + 1, tail_size * sizeof(SK_Point));
+       }
+       
+       memcpy(stk->points + start, pts, len * sizeof(SK_Point));
+       
+       stk->nb_points += len - size;
+}
+
+void sk_trimStroke(SK_Stroke *stk, int start, int end)
+{
+       int size = end - start + 1;
+       
+       if (start > 0)
+       {
+               memmove(stk->points, stk->points + start, size * sizeof(SK_Point));
+       }
+       
+       stk->nb_points = size;
+}
+
+void sk_straightenStroke(SK_Stroke *stk, int start, int end, float p_start[3], float p_end[3])
+{
+       SK_Point pt1, pt2;
+       SK_Point *prev, *next;
+       float delta_p[3];
+       int i, total;
+       
+       total = end - start;
+
+       VecSubf(delta_p, p_end, p_start);
+       
+       prev = stk->points + start;
+       next = stk->points + end;
+       
+       VECCOPY(pt1.p, p_start);
+       VECCOPY(pt1.no, prev->no);
+       pt1.mode = prev->mode;
+       pt1.type = prev->type;
+       
+       VECCOPY(pt2.p, p_end);
+       VECCOPY(pt2.no, next->no);
+       pt2.mode = next->mode;
+       pt2.type = next->type;
+       
+       sk_insertStrokePoint(stk, &pt1, start + 1); /* insert after start */
+       sk_insertStrokePoint(stk, &pt2, end + 1); /* insert before end (since end was pushed back already) */
+       
+       for (i = 1; i < total; i++)
+       {
+               float delta = (float)i / (float)total;
+               float *p = stk->points[start + 1 + i].p;
+
+               VECCOPY(p, delta_p);
+               VecMulf(p, delta);
+               VecAddf(p, p, p_start);
+       } 
+}
+
+void sk_polygonizeStroke(SK_Stroke *stk, int start, int end)
+{
+       int offset;
+       int i;
+       
+       /* find first exact points outside of range */
+       for (;start > 0; start--)
+       {
+               if (stk->points[start].type == PT_EXACT)
+               {
+                       break;
+               }
+       }
+       
+       for (;end < stk->nb_points - 1; end++)
+       {
+               if (stk->points[end].type == PT_EXACT)
+               {
+                       break;
+               }
+       }
+       
+       offset = start + 1;
+       
+       for (i = start + 1; i < end; i++)
+       {
+               if (stk->points[i].type == PT_EXACT)
+               {
+                       if (offset != i)
+                       {
+                               memcpy(stk->points + offset, stk->points + i, sizeof(SK_Point));
+                       }
+
+                       offset++;
+               }
+       }
+       
+       /* some points were removes, move end of array */
+       if (offset < end)
+       {
+               int size = stk->nb_points - end;
+               memmove(stk->points + offset, stk->points + end, size * sizeof(SK_Point));
+               stk->nb_points = offset + size;
+       }
+}
+
+void sk_flattenStroke(SK_Stroke *stk, int start, int end)
+{
+       float normal[3], distance[3];
+       float limit;
+       int i, total;
+       
+       total = end - start + 1;
+       
+       VECCOPY(normal, stk->points[start].no);
+       
+       VecSubf(distance, stk->points[end].p, stk->points[start].p);
+       Projf(normal, distance, normal);
+       limit = Normalize(normal);
+       
+       for (i = 1; i < total - 1; i++)
+       {
+               float d = limit * i / total;
+               float offset[3];
+               float *p = stk->points[start + i].p;
+
+               VecSubf(distance, p, stk->points[start].p);
+               Projf(distance, distance, normal);
+               
+               VECCOPY(offset, normal);
+               VecMulf(offset, d);
+               
+               VecSubf(p, p, distance);
+               VecAddf(p, p, offset);
+       } 
+}
+
+void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk)
+{
+       if (sketch->active_stroke == stk)
+       {
+               sketch->active_stroke = NULL;
+       }
+       
+       BLI_remlink(&sketch->strokes, stk);
+       sk_freeStroke(stk);
+}
+
+void sk_reverseStroke(SK_Stroke *stk)
+{
+       SK_Point *old_points = stk->points;
+       int i = 0;
+       
+       sk_allocStrokeBuffer(stk);
+       
+       for (i = 0; i < stk->nb_points; i++)
+       {
+               sk_copyPoint(stk->points + i, old_points + stk->nb_points - 1 - i);
+       }
+       
+       MEM_freeN(old_points);
+}
+
+
+void sk_cancelStroke(SK_Sketch *sketch)
+{
+       if (sketch->active_stroke != NULL)
+       {
+               sk_resetOverdraw(sketch);
+               sk_removeStroke(sketch, sketch->active_stroke);
+       }
+}
+
+/* Apply reverse Chaikin filter to simplify the polyline
+ * */
+void sk_filterStroke(SK_Stroke *stk, int start, int end)
+{
+       SK_Point *old_points = stk->points;
+       int nb_points = stk->nb_points;
+       int i, j;
+       
+       return;
+       
+       if (start == -1)
+       {
+               start = 0;
+               end = stk->nb_points - 1;
+       }
+
+       sk_allocStrokeBuffer(stk);
+       stk->nb_points = 0;
+       
+       /* adding points before range */
+       for (i = 0; i < start; i++)
+       {
+               sk_appendStrokePoint(stk, old_points + i);
+       }
+       
+       for (i = start, j = start; i <= end; i++)
+       {
+               if (i - j == 3)
+               {
+                       SK_Point pt;
+                       float vec[3];
+                       
+                       sk_copyPoint(&pt, &old_points[j+1]);
+
+                       pt.p[0] = 0;
+                       pt.p[1] = 0;
+                       pt.p[2] = 0;
+                       
+                       VECCOPY(vec, old_points[j].p);
+                       VecMulf(vec, -0.25);
+                       VecAddf(pt.p, pt.p, vec);
+                       
+                       VECCOPY(vec, old_points[j+1].p);
+                       VecMulf(vec,  0.75);
+                       VecAddf(pt.p, pt.p, vec);
+
+                       VECCOPY(vec, old_points[j+2].p);
+                       VecMulf(vec,  0.75);
+                       VecAddf(pt.p, pt.p, vec);
+
+                       VECCOPY(vec, old_points[j+3].p);
+                       VecMulf(vec, -0.25);
+                       VecAddf(pt.p, pt.p, vec);
+                       
+                       sk_appendStrokePoint(stk, &pt);
+
+                       j += 2;
+               }
+               
+               /* this might be uneeded when filtering last continuous stroke */
+               if (old_points[i].type == PT_EXACT)
+               {
+                       sk_appendStrokePoint(stk, old_points + i);
+                       j = i;
+               }
+       } 
+       
+       /* adding points after range */
+       for (i = end + 1; i < nb_points; i++)
+       {
+               sk_appendStrokePoint(stk, old_points + i);
+       }
+
+       MEM_freeN(old_points);
+
+       sk_shrinkStrokeBuffer(stk);
+}
+
+void sk_filterLastContinuousStroke(SK_Stroke *stk)
+{
+       int start, end;
+       
+       end = stk->nb_points -1;
+       
+       for (start = end - 1; start > 0 && stk->points[start].type == PT_CONTINUOUS; start--)
+       {
+               /* nothing to do here*/
+       }
+       
+       if (end - start > 1)
+       {
+               sk_filterStroke(stk, start, end);
+       }
+}
+
+SK_Point *sk_lastStrokePoint(SK_Stroke *stk)
+{
+       SK_Point *pt = NULL;
+       
+       if (stk->nb_points > 0)
+       {
+               pt = stk->points + (stk->nb_points - 1);
+       }
+       
+       return pt;
+}
+
+void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int end)
+{
+       float rgb[3];
+       int i;
+       
+       if (id != -1)
+       {
+               glLoadName(id);
+               
+               glBegin(GL_LINE_STRIP);
+               
+               for (i = 0; i < stk->nb_points; i++)
+               {
+                       glVertex3fv(stk->points[i].p);
+               }
+               
+               glEnd();
+               
+       }
+       else
+       {
+               float d_rgb[3] = {1, 1, 1};
+               
+               VECCOPY(rgb, color);
+               VecSubf(d_rgb, d_rgb, rgb);
+               VecMulf(d_rgb, 1.0f / (float)stk->nb_points);
+               
+               glBegin(GL_LINE_STRIP);
+
+               for (i = 0; i < stk->nb_points; i++)
+               {
+                       if (i >= start && i <= end)
+                       {
+                               glColor3f(0.3, 0.3, 0.3);
+                       }
+                       else
+                       {
+                               glColor3fv(rgb);
+                       }
+                       glVertex3fv(stk->points[i].p);
+                       VecAddf(rgb, rgb, d_rgb);
+               }
+               
+               glEnd();
+       
+               glColor3f(0, 0, 0);
+               glBegin(GL_POINTS);
+       
+               for (i = 0; i < stk->nb_points; i++)
+               {
+                       if (stk->points[i].type == PT_EXACT)
+                       {
+                               glVertex3fv(stk->points[i].p);
+                       }
+               }
+               
+               glEnd();
+       }
+
+//     glColor3f(1, 1, 1);
+//     glBegin(GL_POINTS);
+//
+//     for (i = 0; i < stk->nb_points; i++)
+//     {
+//             if (stk->points[i].type == PT_CONTINUOUS)
+//             {
+//                     glVertex3fv(stk->points[i].p);
+//             }
+//     }
+//
+//     glEnd();
+}
+
+void drawSubdividedStrokeBy(BArcIterator *iter, NextSubdivisionFunc next_subdividion)
+{
+       float head[3], tail[3];
+       int bone_start = 0;
+       int end = iter->length;
+       int index;
+
+       iter->head(iter);
+       VECCOPY(head, iter->p);
+       
+       glColor3f(0, 1, 0);
+       glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE) * 2);
+       glBegin(GL_POINTS);
+       
+       index = next_subdividion(iter, bone_start, end, head, tail);
+       while (index != -1)
+       {
+               glVertex3fv(tail);
+               
+               VECCOPY(head, tail);
+               bone_start = index; // start next bone from current index
+
+               index = next_subdividion(iter, bone_start, end, head, tail);
+       }
+       
+       glEnd();
+       glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
+}
+
+void sk_drawStrokeSubdivision(SK_Stroke *stk)
+{
+       int head_index = -1;
+       int i;
+       
+       if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
+       {
+               return;
+       }
+
+       
+       for (i = 0; i < stk->nb_points; i++)
+       {
+               SK_Point *pt = stk->points + i;
+               
+               if (pt->type == PT_EXACT || i == stk->nb_points - 1) /* stop on exact or on last point */
+               {
+                       if (head_index == -1)
+                       {
+                               head_index = i;
+                       }
+                       else
+                       {
+                               if (i - head_index > 1)
+                               {
+                                       SK_StrokeIterator sk_iter;
+                                       BArcIterator *iter = (BArcIterator*)&sk_iter;
+                                       
+                                       initStrokeIterator(iter, stk, head_index, i);
+
+                                       if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
+                                       {
+                                               drawSubdividedStrokeBy(iter, nextAdaptativeSubdivision);
+                                       }
+                                       else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
+                                       {
+                                               drawSubdividedStrokeBy(iter, nextLengthSubdivision);
+                                       }
+                                       else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
+                                       {
+                                               drawSubdividedStrokeBy(iter, nextFixedSubdivision);
+                                       }
+                                       
+                               }
+
+                               head_index = i;
+                       }
+               }
+       }       
+}
+
+SK_Point *sk_snapPointStroke(SK_Stroke *stk, short mval[2], int *dist, int *index, int all_pts)
+{
+       SK_Point *pt = NULL;
+       int i;
+       
+       for (i = 0; i < stk->nb_points; i++)
+       {
+               if (all_pts || stk->points[i].type == PT_EXACT)
+               {
+                       short pval[2];
+                       int pdist;
+                       
+                       project_short_noclip(stk->points[i].p, pval);
+                       
+                       pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
+                       
+                       if (pdist < *dist)
+                       {
+                               *dist = pdist;
+                               pt = stk->points + i;
+                               
+                               if (index != NULL)
+                               {
+                                       *index = i;
+                               }
+                       }
+               }
+       }
+       
+       return pt;
+}
+
+SK_Point *sk_snapPointArmature(Object *ob, ListBase *ebones, short mval[2], int *dist)
+{
+       SK_Point *pt = NULL;
+       EditBone *bone;
+       
+       for (bone = ebones->first; bone; bone = bone->next)
+       {
+               float vec[3];
+               short pval[2];
+               int pdist;
+               
+               if ((bone->flag & BONE_CONNECTED) == 0)
+               {
+                       VECCOPY(vec, bone->head);
+                       Mat4MulVecfl(ob->obmat, vec);
+                       project_short_noclip(vec, pval);
+                       
+                       pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
+                       
+                       if (pdist < *dist)
+                       {
+                               *dist = pdist;
+                               pt = &boneSnap;
+                               VECCOPY(pt->p, vec);
+                               pt->type = PT_EXACT;
+                       }
+               }
+               
+               
+               VECCOPY(vec, bone->tail);
+               Mat4MulVecfl(ob->obmat, vec);
+               project_short_noclip(vec, pval);
+               
+               pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
+               
+               if (pdist < *dist)
+               {
+                       *dist = pdist;
+                       pt = &boneSnap;
+                       VECCOPY(pt->p, vec);
+                       pt->type = PT_EXACT;
+               }
+       }
+       
+       return pt;
+}
+
+void sk_resetOverdraw(SK_Sketch *sketch)
+{
+       sketch->over.target = NULL;
+       sketch->over.start = -1;
+       sketch->over.end = -1;
+       sketch->over.count = 0;
+}
+
+int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk)
+{
+       return  sketch->over.target &&
+                       sketch->over.count >= SK_OVERDRAW_LIMIT &&
+                       (sketch->over.target == stk || stk == NULL) &&
+                       (sketch->over.start != -1 || sketch->over.end != -1);
+}
+
+void sk_updateOverdraw(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
+{
+       if (sketch->over.target == NULL)
+       {
+               SK_Stroke *target;
+               int closest_index = -1;
+               int dist = SNAP_MIN_DISTANCE * 2;
+               
+               /* If snapping, don't start overdraw */
+               if (sk_lastStrokePoint(stk)->mode == PT_SNAP)
+               {
+                       return;
+               }
+               
+               for (target = sketch->strokes.first; target; target = target->next)
+               {
+                       if (target != stk)
+                       {
+                               int index;
+                               
+                               SK_Point *spt = sk_snapPointStroke(target, dd->mval, &dist, &index, 1);
+                               
+                               if (spt != NULL)
+                               {
+                                       sketch->over.target = target;
+                                       closest_index = index;
+                               }
+                       }
+               }
+               
+               if (sketch->over.target != NULL)
+               {
+                       if (closest_index > -1)
+                       {
+                               if (sk_lastStrokePoint(stk)->type == PT_EXACT)
+                               {
+                                       sketch->over.count = SK_OVERDRAW_LIMIT;
+                               }
+                               else
+                               {
+                                       sketch->over.count++;
+                               }
+                       }
+
+                       if (stk->nb_points == 1)
+                       {
+                               sketch->over.start = closest_index;
+                       }
+                       else
+                       {
+                               sketch->over.end = closest_index;
+                       }
+               }
+       }
+       else if (sketch->over.target != NULL)
+       {
+               SK_Point *closest_pt = NULL;
+               int dist = SNAP_MIN_DISTANCE * 2;
+               int index;
+
+               closest_pt = sk_snapPointStroke(sketch->over.target, dd->mval, &dist, &index, 1);
+               
+               if (closest_pt != NULL)
+               {
+                       if (sk_lastStrokePoint(stk)->type == PT_EXACT)
+                       {
+                               sketch->over.count = SK_OVERDRAW_LIMIT;
+                       }
+                       else
+                       {
+                               sketch->over.count++;
+                       }
+                       
+                       sketch->over.end = index;
+               }
+               else
+               {
+                       sketch->over.end = -1;
+               }
+       }
+}
+
+/* return 1 on reverse needed */
+int sk_adjustIndexes(SK_Sketch *sketch, int *start, int *end)
+{
+       int retval = 0;
+
+       *start = sketch->over.start;
+       *end = sketch->over.end;
+       
+       if (*start == -1)
+       {
+               *start = 0;
+       }
+       
+       if (*end == -1)
+       {
+               *end = sketch->over.target->nb_points - 1;
+       }
+       
+       if (*end < *start)
+       {
+               int tmp = *start;
+               *start = *end;
+               *end = tmp;
+               retval = 1;
+       }
+       
+       return retval;
+}
+
+void sk_endOverdraw(SK_Sketch *sketch)
+{
+       SK_Stroke *stk = sketch->active_stroke;
+       
+       if (sk_hasOverdraw(sketch, NULL))
+       {
+               int start;
+               int end;
+               
+               if (sk_adjustIndexes(sketch, &start, &end))
+               {
+                       sk_reverseStroke(stk);
+               }
+               
+               if (stk->nb_points > 1)
+               {
+                       stk->points->type = sketch->over.target->points[start].type;
+                       sk_lastStrokePoint(stk)->type = sketch->over.target->points[end].type;
+               }
+               
+               sk_insertStrokePoints(sketch->over.target, stk->points, stk->nb_points, start, end);
+               
+               sk_removeStroke(sketch, stk);
+               
+               sk_resetOverdraw(sketch);
+       }
+}
+
+
+void sk_startStroke(SK_Sketch *sketch)
+{
+       SK_Stroke *stk = sk_createStroke();
+       
+       BLI_addtail(&sketch->strokes, stk);
+       sketch->active_stroke = stk;
+
+       sk_resetOverdraw(sketch);       
+}
+
+void sk_endStroke(SK_Sketch *sketch)
+{
+       sk_shrinkStrokeBuffer(sketch->active_stroke);
+
+       if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST)
+       {
+               sk_endOverdraw(sketch);
+       }
+
+       sketch->active_stroke = NULL;
+}
+
+void sk_updateDrawData(SK_DrawData *dd)
+{
+       dd->type = PT_CONTINUOUS;
+       
+       dd->previous_mval[0] = dd->mval[0];
+       dd->previous_mval[1] = dd->mval[1];
+}
+
+float sk_distanceDepth(float p1[3], float p2[3])
+{
+       float vec[3];
+       float distance;
+       
+       VecSubf(vec, p1, p2);
+       
+       Projf(vec, vec, G.vd->viewinv[2]);
+       
+       distance = VecLength(vec);
+       
+       if (Inpf(G.vd->viewinv[2], vec) > 0)
+       {
+               distance *= -1;
+       }
+       
+       return distance; 
+}
+
+void sk_interpolateDepth(SK_Stroke *stk, int start, int end, float length, float distance)
+{
+       float progress = 0;
+       int i;
+       
+       progress = VecLenf(stk->points[start].p, stk->points[start - 1].p);
+       
+       for (i = start; i <= end; i++)
+       {
+               float ray_start[3], ray_normal[3];
+               float delta = VecLenf(stk->points[i].p, stk->points[i + 1].p);
+               short pval[2];
+               
+               project_short_noclip(stk->points[i].p, pval);
+               viewray(pval, ray_start, ray_normal);
+               
+               VecMulf(ray_normal, distance * progress / length);
+               VecAddf(stk->points[i].p, stk->points[i].p, ray_normal);
+
+               progress += delta ;
+       }
+}
+
+void sk_projectDrawPoint(float vec[3], SK_Stroke *stk, SK_DrawData *dd)
+{
+       /* copied from grease pencil, need fixing */    
+       SK_Point *last = sk_lastStrokePoint(stk);
+       short cval[2];
+       //float *fp = give_cursor();
+       float fp[3] = {0, 0, 0};
+       float dvec[3];
+       
+       if (last != NULL)
+       {
+               VECCOPY(fp, last->p);
+       }
+       
+       initgrabz(fp[0], fp[1], fp[2]);
+       
+       /* method taken from editview.c - mouse_cursor() */
+       project_short_noclip(fp, cval);
+       window_to_3d(dvec, cval[0] - dd->mval[0], cval[1] - dd->mval[1]);
+       VecSubf(vec, fp, dvec);
+}
+
+int sk_getStrokeDrawPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
+{
+       pt->type = dd->type;
+       pt->mode = PT_PROJECT;
+       sk_projectDrawPoint(pt->p, stk, dd);
+       
+       return 1;
+}
+
+int sk_addStrokeDrawPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
+{
+       SK_Point pt;
+       
+       sk_initPoint(&pt);
+       
+       sk_getStrokeDrawPoint(&pt, sketch, stk, dd);
+
+       sk_appendStrokePoint(stk, &pt);
+       
+       return 1;
+}
+
+int sk_getStrokeSnapPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
+{
+       int point_added = 0;
+
+       if (G.scene->snap_mode == SCE_SNAP_MODE_VOLUME)
+       {
+               ListBase depth_peels;
+               DepthPeel *p1, *p2;
+               float *last_p = NULL;
+               float dist = FLT_MAX;
+               float p[3];
+               
+               depth_peels.first = depth_peels.last = NULL;
+               
+               peelObjects(&depth_peels, dd->mval);
+               
+               if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS)
+               {
+                       last_p = stk->points[stk->nb_points - 1].p;
+               }
+               else if (LAST_SNAP_POINT_VALID)
+               {
+                       last_p = LAST_SNAP_POINT;
+               }
+               
+               
+               for (p1 = depth_peels.first; p1; p1 = p1->next)
+               {
+                       if (p1->flag == 0)
+                       {
+                               float vec[3];
+                               float new_dist;
+                               
+                               p2 = NULL;
+                               p1->flag = 1;
+       
+                               /* if peeling objects, take the first and last from each object */                      
+                               if (G.scene->snap_flag & SCE_SNAP_PEEL_OBJECT)
+                               {
+                                       DepthPeel *peel;
+                                       for (peel = p1->next; peel; peel = peel->next)
+                                       {
+                                               if (peel->ob == p1->ob)
+                                               {
+                                                       peel->flag = 1;
+                                                       p2 = peel;
+                                               }
+                                       }
+                               }
+                               /* otherwise, pair first with second and so on */
+                               else
+                               {
+                                       for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
+                                       {
+                                               /* nothing to do here */
+                                       }
+                               }
+                               
+                               if (p2)
+                               {
+                                       p2->flag = 1;
+                                       
+                                       VecAddf(vec, p1->p, p2->p);
+                                       VecMulf(vec, 0.5f);
+                               }
+                               else
+                               {
+                                       VECCOPY(vec, p1->p);
+                               }
+                               
+                               if (last_p == NULL)
+                               {
+                                       VECCOPY(p, vec);
+                                       dist = 0;
+                                       break;
+                               }
+                               
+                               new_dist = VecLenf(last_p, vec);
+                               
+                               if (new_dist < dist)
+                               {
+                                       VECCOPY(p, vec);
+                                       dist = new_dist;
+                               }
+                       }
+               }
+               
+               if (dist != FLT_MAX)
+               {
+                       pt->type = dd->type;
+                       pt->mode = PT_SNAP;
+                       VECCOPY(pt->p, p);
+                       
+                       point_added = 1;
+               }
+               
+               BLI_freelistN(&depth_peels);
+       }
+       else
+       {
+               SK_Stroke *snap_stk;
+               float vec[3];
+               float no[3];
+               int found = 0;
+               int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
+
+               /* snap to strokes */
+               // if (G.scene->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */
+               for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next)
+               {
+                       SK_Point *spt = NULL;
+                       if (snap_stk == stk)
+                       {
+                               spt = sk_snapPointStroke(snap_stk, dd->mval, &dist, NULL, 0);
+                       }
+                       else
+                       {
+                               spt = sk_snapPointStroke(snap_stk, dd->mval, &dist, NULL, 1);
+                       }
+                               
+                       if (spt != NULL)
+                       {
+                               VECCOPY(pt->p, spt->p);
+                               point_added = 1;
+                       }
+               }
+
+               /* try to snap to closer object */
+               found = snapObjects(&dist, vec, no, NOT_SELECTED);
+               if (found == 1)
+               {
+                       pt->type = dd->type;
+                       pt->mode = PT_SNAP;
+                       VECCOPY(pt->p, vec);
+                       
+                       point_added = 1;
+               }
+       }
+       
+       return point_added;
+}
+
+int sk_addStrokeSnapPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
+{
+       int point_added;
+       SK_Point pt;
+       
+       sk_initPoint(&pt);
+
+       point_added = sk_getStrokeSnapPoint(&pt, sketch, stk, dd);
+       
+       if (point_added)
+       {
+               float final_p[3];
+               float length, distance;
+               int total;
+               int i;
+               
+               VECCOPY(final_p, pt.p);
+               
+               sk_projectDrawPoint(pt.p, stk, dd);
+               sk_appendStrokePoint(stk, &pt);
+               
+               /* update all previous point to give smooth Z progresion */
+               total = 0;
+               length = 0;
+               for (i = stk->nb_points - 2; i > 0; i--)
+               {
+                       length += VecLenf(stk->points[i].p, stk->points[i + 1].p);
+                       total++;
+                       if (stk->points[i].mode == PT_SNAP || stk->points[i].type == PT_EXACT)
+                       {
+                               break;
+                       }
+               }
+               
+               if (total > 1)
+               {
+                       distance = sk_distanceDepth(final_p, stk->points[i].p);
+                       
+                       sk_interpolateDepth(stk, i + 1, stk->nb_points - 2, length, distance);
+               }
+               
+               VECCOPY(stk->points[stk->nb_points - 1].p, final_p);
+               
+               point_added = 1;
+       }
+       
+       return point_added;
+}
+
+void sk_addStrokePoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short qual)
+{
+       int point_added = 0;
+       
+       if (qual & LR_CTRLKEY)
+       {
+               point_added = sk_addStrokeSnapPoint(sketch, stk, dd);
+       }
+       
+       if (point_added == 0)
+       {
+               point_added = sk_addStrokeDrawPoint(sketch, stk, dd);
+       }
+       
+       if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST)
+       {
+               sk_updateOverdraw(sketch, stk, dd);
+       }
+}
+
+void sk_getStrokePoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short qual)
+{
+       int point_added = 0;
+       
+       if (qual & LR_CTRLKEY)
+       {
+               point_added = sk_getStrokeSnapPoint(pt, sketch, stk, dd);
+               LAST_SNAP_POINT_VALID = 1;
+               VECCOPY(LAST_SNAP_POINT, pt->p);
+       }
+       else
+       {
+               LAST_SNAP_POINT_VALID = 0;
+       }
+       
+       if (point_added == 0)
+       {
+               point_added = sk_getStrokeDrawPoint(pt, sketch, stk, dd);
+       }       
+}
+
+void sk_endContinuousStroke(SK_Stroke *stk)
+{
+       stk->points[stk->nb_points - 1].type = PT_EXACT;
+}
+
+void sk_updateNextPoint(SK_Sketch *sketch)
+{
+       if (sketch->active_stroke)
+       {
+               SK_Stroke *stk = sketch->active_stroke;
+               memcpy(&sketch->next_point, stk->points[stk->nb_points - 1].p, sizeof(SK_Point));
+       }
+}
+
+int sk_stroke_filtermval(SK_DrawData *dd)
+{
+       int retval = 0;
+       if (ABS(dd->mval[0] - dd->previous_mval[0]) + ABS(dd->mval[1] - dd->previous_mval[1]) > U.gp_manhattendist)
+       {
+               retval = 1;
+       }
+       
+       return retval;
+}
+
+void sk_initDrawData(SK_DrawData *dd)
+{
+       getmouseco_areawin(dd->mval);
+       dd->previous_mval[0] = -1;
+       dd->previous_mval[1] = -1;
+       dd->type = PT_EXACT;
+}
+/********************************************/
+
+static void* headPoint(void *arg);
+static void* tailPoint(void *arg);
+static void* nextPoint(void *arg);
+static void* nextNPoint(void *arg, int n);
+static void* peekPoint(void *arg, int n);
+static void* previousPoint(void *arg);
+static int   iteratorStopped(void *arg);
+
+static void initIteratorFct(SK_StrokeIterator *iter)
+{
+       iter->head = headPoint;
+       iter->tail = tailPoint;
+       iter->peek = peekPoint;
+       iter->next = nextPoint;
+       iter->nextN = nextNPoint;
+       iter->previous = previousPoint;
+       iter->stopped = iteratorStopped;        
+}
+
+static SK_Point* setIteratorValues(SK_StrokeIterator *iter, int index)
+{
+       SK_Point *pt = NULL;
+       
+       if (index >= 0 && index < iter->length)
+       {
+               pt = &(iter->stroke->points[iter->start + (iter->stride * index)]);
+               iter->p = pt->p;
+               iter->no = pt->no;
+       }
+       else
+       {
+               iter->p = NULL;
+               iter->no = NULL;
+       }
+       
+       return pt;
+}
+
+void initStrokeIterator(BArcIterator *arg, SK_Stroke *stk, int start, int end)
+{
+       SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+
+       initIteratorFct(iter);
+       iter->stroke = stk;
+       
+       if (start < end)
+       {
+               iter->start = start + 1;
+               iter->end = end - 1;
+               iter->stride = 1;
+       }
+       else
+       {
+               iter->start = start - 1;
+               iter->end = end + 1;
+               iter->stride = -1;
+       }
+       
+       iter->length = iter->stride * (iter->end - iter->start + 1);
+       
+       iter->index = -1;
+}
+
+
+static void* headPoint(void *arg)
+{
+       SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+       SK_Point *result = NULL;
+       
+       result = &(iter->stroke->points[iter->start - iter->stride]);
+       iter->p = result->p;
+       iter->no = result->no;
+       
+       return result;
+}
+
+static void* tailPoint(void *arg)
+{
+       SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+       SK_Point *result = NULL;
+       
+       result = &(iter->stroke->points[iter->end + iter->stride]);
+       iter->p = result->p;
+       iter->no = result->no;
+       
+       return result;
+}
+
+static void* nextPoint(void *arg)
+{
+       SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+       SK_Point *result = NULL;
+       
+       iter->index++;
+       if (iter->index < iter->length)
+       {
+               result = setIteratorValues(iter, iter->index);
+       }
+
+       return result;
+}
+
+static void* nextNPoint(void *arg, int n)
+{
+       SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+       SK_Point *result = NULL;
+               
+       iter->index += n;
+
+       /* check if passed end */
+       if (iter->index < iter->length)
+       {
+               result = setIteratorValues(iter, iter->index);
+       }
+
+       return result;
+}
+
+static void* peekPoint(void *arg, int n)
+{
+       SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+       SK_Point *result = NULL;
+       int index = iter->index + n;
+
+       /* check if passed end */
+       if (index < iter->length)
+       {
+               result = setIteratorValues(iter, index);
+       }
+
+       return result;
+}
+
+static void* previousPoint(void *arg)
+{
+       SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+       SK_Point *result = NULL;
+       
+       if (iter->index > 0)
+       {
+               iter->index--;
+               result = setIteratorValues(iter, iter->index);
+       }
+
+       return result;
+}
+
+static int iteratorStopped(void *arg)
+{
+       SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
+
+       if (iter->index >= iter->length)
+       {
+               return 1;
+       }
+       else
+       {
+               return 0;
+       }
+}
+
+void sk_convertStroke(SK_Stroke *stk)
+{
+       bArmature *arm = G.obedit->data;
+       SK_Point *head;
+       EditBone *parent = NULL;
+       float invmat[4][4]; /* move in caller function */
+       float tmat[3][3];
+       int head_index = 0;
+       int i;
+       
+       head = NULL;
+       
+       Mat4Invert(invmat, G.obedit->obmat);
+       
+       Mat3CpyMat4(tmat, G.obedit->obmat);
+       Mat3Transp(tmat);
+       
+       for (i = 0; i < stk->nb_points; i++)
+       {
+               SK_Point *pt = stk->points + i;
+               
+               if (pt->type == PT_EXACT)
+               {
+                       if (head == NULL)
+                       {
+                               head_index = i;
+                               head = pt;
+                       }
+                       else
+                       {
+                               EditBone *bone = NULL;
+                               EditBone *new_parent;
+                               
+                               if (i - head_index > 1)
+                               {
+                                       SK_StrokeIterator sk_iter;
+                                       BArcIterator *iter = (BArcIterator*)&sk_iter;
+
+                                       initStrokeIterator(iter, stk, head_index, i);
+                                       
+                                       if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
+                                       {
+                                               bone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
+                                       }
+                                       else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
+                                       {
+                                               bone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextLengthSubdivision);
+                                       }
+                                       else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
+                                       {
+                                               bone = subdivideArcBy(arm, &G.edbo, iter, invmat, tmat, nextFixedSubdivision);
+                                       }
+                               }
+                               
+                               if (bone == NULL)
+                               {
+                                       bone = addEditBone("Bone", &G.edbo, arm);
+                                       
+                                       VECCOPY(bone->head, head->p);
+                                       VECCOPY(bone->tail, pt->p);
+
+                                       Mat4MulVecfl(invmat, bone->head);
+                                       Mat4MulVecfl(invmat, bone->tail);
+                                       setBoneRollFromNormal(bone, pt->no, invmat, tmat);
+                               }
+                               
+                               new_parent = bone;
+                               bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
+                               
+                               /* move to end of chain */
+                               while (bone->parent != NULL)
+                               {
+                                       bone = bone->parent;
+                                       bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
+                               }
+
+                               if (parent != NULL)
+                               {
+                                       bone->parent = parent;
+                                       bone->flag |= BONE_CONNECTED;                                   
+                               }
+                               
+                               parent = new_parent;
+                               head_index = i;
+                               head = pt;
+                       }
+               }
+       }
+}
+
+void sk_convert(SK_Sketch *sketch)
+{
+       SK_Stroke *stk;
+       
+       for (stk = sketch->strokes.first; stk; stk = stk->next)
+       {
+               if (stk->selected == 1)
+               {
+                       if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
+                       {
+                               sk_retargetStroke(stk);
+                       }
+                       else
+                       {
+                               sk_convertStroke(stk);
+                       }
+                       allqueue(REDRAWBUTSEDIT, 0);
+               }
+       }
+}
+/******************* GESTURE *************************/
+
+
+/* returns the number of self intersections */
+int sk_getSelfIntersections(ListBase *list, SK_Stroke *gesture)
+{
+       int added = 0;
+       int s_i;
+
+       for (s_i = 0; s_i < gesture->nb_points - 1; s_i++)
+       {
+               float s_p1[3] = {0, 0, 0};
+               float s_p2[3] = {0, 0, 0};
+               int g_i;
+               
+               project_float(gesture->points[s_i].p, s_p1);
+               project_float(gesture->points[s_i + 1].p, s_p2);
+
+               /* start checking from second next, because two consecutive cannot intersect */
+               for (g_i = s_i + 2; g_i < gesture->nb_points - 1; g_i++)
+               {
+                       float g_p1[3] = {0, 0, 0};
+                       float g_p2[3] = {0, 0, 0};
+                       float vi[3];
+                       float lambda;
+                       
+                       project_float(gesture->points[g_i].p, g_p1);
+                       project_float(gesture->points[g_i + 1].p, g_p2);
+                       
+                       if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
+                       {
+                               SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
+                               
+                               isect->gesture_index = g_i;
+                               isect->before = s_i;
+                               isect->after = s_i + 1;
+                               isect->stroke = gesture;
+                               
+                               VecSubf(isect->p, gesture->points[s_i + 1].p, gesture->points[s_i].p);
+                               VecMulf(isect->p, lambda);
+                               VecAddf(isect->p, isect->p, gesture->points[s_i].p);
+                               
+                               BLI_addtail(list, isect);
+
+                               added++;
+                       }
+               }
+       }
+       
+       return added;
+}
+
+int cmpIntersections(void *i1, void *i2)
+{
+       SK_Intersection *isect1 = i1, *isect2 = i2;
+       
+       if (isect1->stroke == isect2->stroke)
+       {
+               if (isect1->before < isect2->before)
+               {
+                       return -1;
+               }
+               else if (isect1->before > isect2->before)
+               {
+                       return 1;
+               }
+               else
+               {
+                       if (isect1->lambda < isect2->lambda)
+                       {
+                               return -1;
+                       }
+                       else if (isect1->lambda > isect2->lambda)
+                       {
+                               return 1;
+                       }
+               }
+       }
+       
+       return 0;
+}
+
+
+/* returns the maximum number of intersections per stroke */
+int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture)
+{
+       SK_Stroke *stk;
+       int added = 0;
+
+       for (stk = sketch->strokes.first; stk; stk = stk->next)
+       {
+               int s_added = 0;
+               int s_i;
+               
+               for (s_i = 0; s_i < stk->nb_points - 1; s_i++)
+               {
+                       float s_p1[3] = {0, 0, 0};
+                       float s_p2[3] = {0, 0, 0};
+                       int g_i;
+                       
+                       project_float(stk->points[s_i].p, s_p1);
+                       project_float(stk->points[s_i + 1].p, s_p2);
+
+                       for (g_i = 0; g_i < gesture->nb_points - 1; g_i++)
+                       {
+                               float g_p1[3] = {0, 0, 0};
+                               float g_p2[3] = {0, 0, 0};
+                               float vi[3];
+                               float lambda;
+                               
+                               project_float(gesture->points[g_i].p, g_p1);
+                               project_float(gesture->points[g_i + 1].p, g_p2);
+                               
+                               if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
+                               {
+                                       SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
+                                       float ray_start[3], ray_end[3];
+                                       short mval[2];
+                                       
+                                       isect->gesture_index = g_i;
+                                       isect->before = s_i;
+                                       isect->after = s_i + 1;
+                                       isect->stroke = stk;
+                                       isect->lambda = lambda;
+                                       
+                                       mval[0] = (short)(vi[0]);
+                                       mval[1] = (short)(vi[1]);
+                                       viewline(mval, ray_start, ray_end);
+                                       
+                                       LineIntersectLine(      stk->points[s_i].p,
+                                                                               stk->points[s_i + 1].p,
+                                                                               ray_start,
+                                                                               ray_end,
+                                                                               isect->p,
+                                                                               vi);
+                                       
+                                       BLI_addtail(list, isect);
+
+                                       s_added++;
+                               }
+                       }
+               }
+               
+               added = MAX2(s_added, added);
+       }
+       
+       BLI_sortlist(list, cmpIntersections);
+       
+       return added;
+}
+
+int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture)
+{
+       SK_StrokeIterator sk_iter;
+       BArcIterator *iter = (BArcIterator*)&sk_iter;
+       
+       float CORRELATION_THRESHOLD = 0.99f;
+       float *vec;
+       int i, j;
+       
+       sk_appendStrokePoint(segments, &gesture->points[0]);
+       vec = segments->points[segments->nb_points - 1].p;
+
+       initStrokeIterator(iter, gesture, 0, gesture->nb_points - 1);
+
+       for (i = 1, j = 0; i < gesture->nb_points; i++)
+       { 
+               float n[3];
+               
+               /* Calculate normal */
+               VecSubf(n, gesture->points[i].p, vec);
+               
+               if (calcArcCorrelation(iter, j, i, vec, n) < CORRELATION_THRESHOLD)
+               {
+                       j = i - 1;
+                       sk_appendStrokePoint(segments, &gesture->points[j]);
+                       vec = segments->points[segments->nb_points - 1].p;
+                       segments->points[segments->nb_points - 1].type = PT_EXACT;
+               }
+       }
+
+       sk_appendStrokePoint(segments, &gesture->points[gesture->nb_points - 1]);
+       
+       return segments->nb_points - 1;
+}
+
+int sk_detectCutGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       if (gest->nb_segments == 1 && gest->nb_intersections == 1)
+       {
+               return 1;
+       }
+
+       return 0;
+}
+
+void sk_applyCutGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       SK_Intersection *isect;
+       
+       for (isect = gest->intersections.first; isect; isect = isect->next)
+       {
+               SK_Point pt;
+               
+               pt.type = PT_EXACT;
+               pt.mode = PT_PROJECT; /* take mode from neighbouring points */
+               VECCOPY(pt.p, isect->p);
+               
+               sk_insertStrokePoint(isect->stroke, &pt, isect->after);
+       }
+}
+
+int sk_detectTrimGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       if (gest->nb_segments == 2 && gest->nb_intersections == 1 && gest->nb_self_intersections == 0)
+       {
+               float s1[3], s2[3];
+               float angle;
+               
+               VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p);
+               VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p);
+               
+               angle = VecAngle2(s1, s2);
+       
+               if (angle > 60 && angle < 120)
+               {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+void sk_applyTrimGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       SK_Intersection *isect;
+       float trim_dir[3];
+       
+       VecSubf(trim_dir, gest->segments->points[2].p, gest->segments->points[1].p);
+       
+       for (isect = gest->intersections.first; isect; isect = isect->next)
+       {
+               SK_Point pt;
+               float stroke_dir[3];
+               
+               pt.type = PT_EXACT;
+               pt.mode = PT_PROJECT; /* take mode from neighbouring points */
+               VECCOPY(pt.p, isect->p);
+               
+               VecSubf(stroke_dir, isect->stroke->points[isect->after].p, isect->stroke->points[isect->before].p);
+               
+               /* same direction, trim end */
+               if (Inpf(stroke_dir, trim_dir) > 0)
+               {
+                       sk_replaceStrokePoint(isect->stroke, &pt, isect->after);
+                       sk_trimStroke(isect->stroke, 0, isect->after);
+               }
+               /* else, trim start */
+               else
+               {
+                       sk_replaceStrokePoint(isect->stroke, &pt, isect->before);
+                       sk_trimStroke(isect->stroke, isect->before, isect->stroke->nb_points - 1);
+               }
+       
+       }
+}
+
+int sk_detectCommandGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 1)
+       {
+               SK_Intersection *isect, *self_isect;
+               
+               /* get the the last intersection of the first pair */
+               for( isect = gest->intersections.first; isect; isect = isect->next )
+               {
+                       if (isect->stroke == isect->next->stroke)
+                       {
+                               isect = isect->next;
+                               break;
+                       }
+               }
+               
+               self_isect = gest->self_intersections.first;
+               
+               if (isect && isect->gesture_index < self_isect->gesture_index)
+               {
+                       return 1;
+               }
+       }
+       
+       return 0;
+}
+
+void sk_applyCommandGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       SK_Intersection *isect;
+       int command;
+       
+       command = pupmenu("Action %t|Flatten %x1|Straighten %x2|Polygonize %x3");
+       if(command < 1) return;
+
+       for (isect = gest->intersections.first; isect; isect = isect->next)
+       {
+               SK_Intersection *i2;
+               
+               i2 = isect->next;
+               
+               if (i2 && i2->stroke == isect->stroke)
+               {
+                       switch (command)
+                       {
+                               case 1:
+                                       sk_flattenStroke(isect->stroke, isect->before, i2->after);
+                                       break;
+                               case 2:
+                                       sk_straightenStroke(isect->stroke, isect->before, i2->after, isect->p, i2->p);
+                                       break;
+                               case 3:
+                                       sk_polygonizeStroke(isect->stroke, isect->before, i2->after);
+                                       break;
+                       }
+
+                       isect = i2;
+               }
+       }
+}
+
+int sk_detectDeleteGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       if (gest->nb_segments == 2 && gest->nb_intersections == 2)
+       {
+               float s1[3], s2[3];
+               float angle;
+               
+               VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p);
+               VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p);
+               
+               angle = VecAngle2(s1, s2);
+               
+               if (angle > 120)
+               {
+                       return 1;
+               }
+       }
+       
+       return 0;
+}
+
+void sk_applyDeleteGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       SK_Intersection *isect;
+       
+       for (isect = gest->intersections.first; isect; isect = isect->next)
+       {
+               /* only delete strokes that are crossed twice */
+               if (isect->next && isect->next->stroke == isect->stroke)
+               {
+                       isect = isect->next;
+                       
+                       sk_removeStroke(sketch, isect->stroke);
+               }
+       }
+}
+
+int sk_detectMergeGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       if (gest->nb_segments > 2 && gest->nb_intersections == 2)
+       {
+               short start_val[2], end_val[2];
+               short dist;
+               
+               project_short_noclip(gest->stk->points[0].p, start_val);
+               project_short_noclip(sk_lastStrokePoint(gest->stk)->p, end_val);
+               
+               dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1]));
+               
+               /* if gesture is a circle */
+               if ( dist <= 20 )
+               {
+                       SK_Intersection *isect;
+                       
+                       /* check if it circled around an exact point */
+                       for (isect = gest->intersections.first; isect; isect = isect->next)
+                       {
+                               /* only delete strokes that are crossed twice */
+                               if (isect->next && isect->next->stroke == isect->stroke)
+                               {
+                                       int start_index, end_index;
+                                       int i;
+                                       
+                                       start_index = MIN2(isect->after, isect->next->after);
+                                       end_index = MAX2(isect->before, isect->next->before);
+       
+                                       for (i = start_index; i <= end_index; i++)
+                                       {
+                                               if (isect->stroke->points[i].type == PT_EXACT)
+                                               {
+                                                       return 1; /* at least one exact point found, stop detect here */
+                                               }
+                                       }
+       
+                                       /* skip next */                         
+                                       isect = isect->next;
+                               }
+                       }
+               }
+       }
+                               
+       return 0;
+}
+
+void sk_applyMergeGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       SK_Intersection *isect;
+       
+       /* check if it circled around an exact point */
+       for (isect = gest->intersections.first; isect; isect = isect->next)
+       {
+               /* only merge strokes that are crossed twice */
+               if (isect->next && isect->next->stroke == isect->stroke)
+               {
+                       int start_index, end_index;
+                       int i;
+                       
+                       start_index = MIN2(isect->after, isect->next->after);
+                       end_index = MAX2(isect->before, isect->next->before);
+
+                       for (i = start_index; i <= end_index; i++)
+                       {
+                               /* if exact, switch to continuous */
+                               if (isect->stroke->points[i].type == PT_EXACT)
+                               {
+                                       isect->stroke->points[i].type = PT_CONTINUOUS;
+                               }
+                       }
+
+                       /* skip next */                         
+                       isect = isect->next;
+               }
+       }
+}
+
+int sk_detectReverseGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 0)
+       {
+               SK_Intersection *isect;
+               
+               /* check if it circled around an exact point */
+               for (isect = gest->intersections.first; isect; isect = isect->next)
+               {
+                       /* only delete strokes that are crossed twice */
+                       if (isect->next && isect->next->stroke == isect->stroke)
+                       {
+                               float start_v[3], end_v[3];
+                               float angle;
+                               
+                               if (isect->gesture_index < isect->next->gesture_index)
+                               {
+                                       VecSubf(start_v, isect->p, gest->stk->points[0].p);
+                                       VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->next->p);
+                               }
+                               else
+                               {
+                                       VecSubf(start_v, isect->next->p, gest->stk->points[0].p);
+                                       VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->p);
+                               }
+                               
+                               angle = VecAngle2(start_v, end_v);
+                               
+                               if (angle > 120)
+                               {
+                                       return 1;
+                               }
+       
+                               /* skip next */                         
+                               isect = isect->next;
+                       }
+               }
+       }
+               
+       return 0;
+}
+
+void sk_applyReverseGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       SK_Intersection *isect;
+       
+       for (isect = gest->intersections.first; isect; isect = isect->next)
+       {
+               /* only reverse strokes that are crossed twice */
+               if (isect->next && isect->next->stroke == isect->stroke)
+               {
+                       sk_reverseStroke(isect->stroke);
+
+                       /* skip next */                         
+                       isect = isect->next;
+               }
+       }
+}
+
+int sk_detectConvertGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       if (gest->nb_segments == 3 && gest->nb_self_intersections == 1)
+       {
+               return 1;
+       }
+       return 0;
+}
+
+void sk_applyConvertGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       sk_convert(sketch);
+}
+
+static void sk_initGesture(SK_Gesture *gest, SK_Sketch *sketch)
+{
+       gest->intersections.first = gest->intersections.last = NULL;
+       gest->self_intersections.first = gest->self_intersections.last = NULL;
+       
+       gest->segments = sk_createStroke();
+       gest->stk = sketch->gesture;
+
+       gest->nb_self_intersections = sk_getSelfIntersections(&gest->self_intersections, gest->stk);
+       gest->nb_intersections = sk_getIntersections(&gest->intersections, sketch, gest->stk);
+       gest->nb_segments = sk_getSegments(gest->segments, gest->stk);
+}
+
+static void sk_freeGesture(SK_Gesture *gest)
+{
+       sk_freeStroke(gest->segments);
+       BLI_freelistN(&gest->intersections);
+       BLI_freelistN(&gest->self_intersections);
+}
+
+void sk_applyGesture(SK_Sketch *sketch)
+{
+       SK_Gesture gest;
+       SK_GestureAction *act;
+       
+       sk_initGesture(&gest, sketch);
+       
+       /* detect and apply */
+       for (act = GESTURE_ACTIONS; act->apply != NULL; act++)
+       {
+               if (act->detect(&gest, sketch))
+               {
+                       act->apply(&gest, sketch);
+                       break;
+               }
+       }
+       
+       sk_freeGesture(&gest);
+}
+
+/********************************************/
+
+void sk_deleteSelectedStrokes(SK_Sketch *sketch)
+{
+       SK_Stroke *s